From 73a4a22fc25e9365eabe549be1864a4acd0f1360 Mon Sep 17 00:00:00 2001 From: Prottay Das Date: Fri, 10 Apr 2026 12:33:18 +0200 Subject: [PATCH 1/3] added a process function to construct mixed event combinatorial bkg for phi --- PWGCF/DataModel/CorrelationsDerived.h | 3 +- PWGCF/TableProducer/filter2Prong.cxx | 117 ++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index 8af9d7fef71..38d8e02ed0e 100644 --- a/PWGCF/DataModel/CorrelationsDerived.h +++ b/PWGCF/DataModel/CorrelationsDerived.h @@ -157,7 +157,8 @@ enum ParticleDecay { LambdaToPPiTight, AntiLambdaToPiPLoose, AntiLambdaToPiPTight, - D0barToKPiExclusive + D0barToKPiExclusive, + PhiToKKPID3Mixed }; } // namespace cf2prongtrack DECLARE_SOA_TABLE(CF2ProngTracks, "AOD", "CF2PRONGTRACK", //! Reduced track table diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index c57427a92c5..f402c64a827 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -44,7 +44,20 @@ enum LambdaPid { kLambda = 0, // #define FLOAT_PRECISION 0xFFFFFFF0 #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; +namespace o2::aod +{ +namespace cfmultiplicity +{ +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); +} +DECLARE_SOA_TABLE(CFMultiplicities, "AOD", "CFMULTIPLICITY", cfmultiplicity::Multiplicity); + +using CFMultiplicity = CFMultiplicities::iterator; +} // namespace o2::aod + struct Filter2Prong { + SliceCache cache; + O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 0, "Verbosity level (0 = major, 1 = per collision)") O2_DEFINE_CONFIGURABLE(cfgYMax, float, -1.0f, "Maximum candidate rapidity") O2_DEFINE_CONFIGURABLE(cfgImPart1Mass, float, o2::constants::physics::MassKPlus, "Daughter particle 1 mass in GeV") @@ -146,6 +159,10 @@ struct Filter2Prong { O2_DEFINE_CONFIGURABLE(applyTOF, bool, false, "Flag for applying TOF"); } grpPhi; + O2_DEFINE_CONFIGURABLE(cfgNoMixedEvents, int, 5, "Number of mixed events per event for mixed phi building") + ConfigurableAxis axisVertexMix{"axisVertexMix", {7, -7, 7}, "vertex axis for phi event mixing"}; + ConfigurableAxis axisMultiplicityMix{"axisMultiplicityMix", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity axis for phi event mixing"}; + HfHelper hfHelper; Produces output2ProngTracks; Produces output2ProngTrackmls; @@ -772,6 +789,106 @@ struct Filter2Prong { } PROCESS_SWITCH(Filter2Prong, processDataPhiV0, "Process data Phi and V0 candidates with invariant mass method", false); + using DerivedCollisions = soa::Join; + void processDataPhiMixed(DerivedCollisions const& collisions, Filter2Prong::PIDTrack const& tracksP, aod::CFTrackRefs const& cftracks) + { + auto getMultiplicity = [](auto const& col) { + return col.multiplicity(); + }; + using BinningTypeDerived = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getMultiplicity)>; + BinningTypeDerived configurableBinningDerived{{getMultiplicity}, {axisVertexMix, axisMultiplicityMix}, true}; + auto tracksTuple = std::make_tuple(cftracks, cftracks); + 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 + + o2::aod::ITSResponse itsResponse; + + 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(); + if (!(collision1.sel8() && + collision1.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision1.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + + if (!(collision2.sel8() && + collision2.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision2.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + + for (const auto& cftrack1 : tracks1) { + const auto& p1 = tracksP.iteratorAt(cftrack1.trackId() - tracksP.begin().globalIndex()); + + if (p1.sign() != 1) { + continue; + } + if (!selectionTrack(p1)) { + continue; + } + if (grpPhi.ITSPIDSelection && + p1.p() < grpPhi.ITSPIDPthreshold.value && + !(itsResponse.nSigmaITS(p1) > grpPhi.lowITSPIDNsigma.value && + itsResponse.nSigmaITS(p1) < grpPhi.highITSPIDNsigma.value)) { + continue; + } + if (grpPhi.removefaketrack && isFakeTrack(p1)) { + continue; + } + + for (const auto& cftrack2 : tracks2) { + const auto& p2 = tracksP.iteratorAt(cftrack2.trackId() - tracksP.begin().globalIndex()); + + if (p2.sign() != -1) { + continue; + } + if (!selectionTrack(p2)) { + continue; + } + if (grpPhi.ITSPIDSelection && + p2.p() < grpPhi.ITSPIDPthreshold.value && + !(itsResponse.nSigmaITS(p2) > grpPhi.lowITSPIDNsigma.value && + itsResponse.nSigmaITS(p2) < grpPhi.highITSPIDNsigma.value)) { + continue; + } + if (grpPhi.removefaketrack && isFakeTrack(p2)) { + continue; + } + if (!selectionPair(p1, p2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector vec1(p1.pt(), p1.eta(), p1.phi(), cfgImPart1Mass); + ROOT::Math::PtEtaPhiMVector vec2(p2.pt(), p2.eta(), p2.phi(), cfgImPart2Mass); + ROOT::Math::PtEtaPhiMVector s = vec1 + vec2; + + if (s.M() < grpPhi.ImMinInvMassPhiMeson || s.M() > grpPhi.ImMaxInvMassPhiMeson) { + continue; + } + + float phi = RecoDecay::constrainAngle(s.Phi(), 0.0f); + + if (selectionPID3(p1) && selectionPID3(p2)) { + if (selectionSys(p1, false, false) && selectionSys(p2, false, false)) { + output2ProngTracks(collision1.globalIndex(), + cftrack1.globalIndex(), cftrack2.globalIndex(), + s.pt(), s.eta(), phi, s.M(), + aod::cf2prongtrack::PhiToKKPID3Mixed); + } + } + } + } + } + } + + PROCESS_SWITCH(Filter2Prong, processDataPhiMixed, "Process mixed-event phi candidates using O2 framework", false); + // Phi and V0s invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now. void processDataV0(aod::Collisions::iterator const& collision, aod::BCsWithTimestamps const&, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, Filter2Prong::PIDTrack const&, aod::V0Datas const& V0s) { From 0704315793bdb26d68dcaaf25c061f4abd768fe2 Mon Sep 17 00:00:00 2001 From: Prottay Das Date: Fri, 10 Apr 2026 16:43:54 +0200 Subject: [PATCH 2/3] updated with few modifications --- PWGCF/DataModel/CorrelationsDerived.h | 8 ++++++++ PWGCF/TableProducer/filter2Prong.cxx | 15 +-------------- PWGCF/TableProducer/filterCorrelations.cxx | 15 ++------------- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index 38d8e02ed0e..dbe807c165d 100644 --- a/PWGCF/DataModel/CorrelationsDerived.h +++ b/PWGCF/DataModel/CorrelationsDerived.h @@ -46,6 +46,14 @@ DECLARE_SOA_TABLE(CFMcParticles, "AOD", "CFMCPARTICLE", //! Reduced MC particle mcparticle::IsPhysicalPrimary); using CFMcParticle = CFMcParticles::iterator; +namespace cfmultiplicity +{ +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); +} +DECLARE_SOA_TABLE(CFMultiplicities, "AOD", "CFMULTIPLICITY", cfmultiplicity::Multiplicity); + +using CFMultiplicity = CFMultiplicities::iterator; + namespace cfcollision { DECLARE_SOA_INDEX_COLUMN(CFMcCollision, cfMcCollision); //! Index to reduced MC collision diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index f402c64a827..df7cecdcef0 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -44,17 +44,6 @@ enum LambdaPid { kLambda = 0, // #define FLOAT_PRECISION 0xFFFFFFF0 #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; -namespace o2::aod -{ -namespace cfmultiplicity -{ -DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); -} -DECLARE_SOA_TABLE(CFMultiplicities, "AOD", "CFMULTIPLICITY", cfmultiplicity::Multiplicity); - -using CFMultiplicity = CFMultiplicities::iterator; -} // namespace o2::aod - struct Filter2Prong { SliceCache cache; @@ -806,9 +795,7 @@ struct Filter2Prong { 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(); + if (!(collision1.sel8() && collision1.selection_bit(aod::evsel::kNoSameBunchPileup) && collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && diff --git a/PWGCF/TableProducer/filterCorrelations.cxx b/PWGCF/TableProducer/filterCorrelations.cxx index 6ceaaa6c815..79dd72d4e67 100644 --- a/PWGCF/TableProducer/filterCorrelations.cxx +++ b/PWGCF/TableProducer/filterCorrelations.cxx @@ -42,17 +42,6 @@ using namespace o2::math_utils::detail; #define FLOAT_PRECISION 0xFFFFFFF0 #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; -namespace o2::aod -{ -namespace cfmultiplicity -{ -DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); //! Centrality/multiplicity value -} // namespace cfmultiplicity -DECLARE_SOA_TABLE(CFMultiplicities, "AOD", "CFMULTIPLICITY", cfmultiplicity::Multiplicity); //! Transient multiplicity table - -using CFMultiplicity = CFMultiplicities::iterator; -} // namespace o2::aod - struct FilterCF { Service pdg; @@ -106,7 +95,7 @@ struct FilterCF { // TODO how to have this in the second task? For now they are copied Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt); - Filter trackSelection = (requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true); + Filter trackSelection = (requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true); Filter mcCollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; @@ -570,7 +559,7 @@ struct MultiplicitySelector { O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt); - Filter trackSelection = (requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true); + Filter trackSelection = (requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true); void init(InitContext&) { From 97c3568a01e50d739e94ce9941cbb206fed86809 Mon Sep 17 00:00:00 2001 From: Prottay Das Date: Fri, 10 Apr 2026 16:46:37 +0200 Subject: [PATCH 3/3] updated2 --- PWGCF/TableProducer/filter2Prong.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index df7cecdcef0..0baf4e31279 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -851,18 +851,18 @@ struct Filter2Prong { continue; } - ROOT::Math::PtEtaPhiMVector vec1(p1.pt(), p1.eta(), p1.phi(), cfgImPart1Mass); - ROOT::Math::PtEtaPhiMVector vec2(p2.pt(), p2.eta(), p2.phi(), cfgImPart2Mass); - ROOT::Math::PtEtaPhiMVector s = vec1 + vec2; + if (selectionPID3(p1) && selectionPID3(p2)) { + if (selectionSys(p1, false, false) && selectionSys(p2, false, false)) { + ROOT::Math::PtEtaPhiMVector vec1(p1.pt(), p1.eta(), p1.phi(), cfgImPart1Mass); + ROOT::Math::PtEtaPhiMVector vec2(p2.pt(), p2.eta(), p2.phi(), cfgImPart2Mass); + ROOT::Math::PtEtaPhiMVector s = vec1 + vec2; - if (s.M() < grpPhi.ImMinInvMassPhiMeson || s.M() > grpPhi.ImMaxInvMassPhiMeson) { - continue; - } + if (s.M() < grpPhi.ImMinInvMassPhiMeson || s.M() > grpPhi.ImMaxInvMassPhiMeson) { + continue; + } - float phi = RecoDecay::constrainAngle(s.Phi(), 0.0f); + float phi = RecoDecay::constrainAngle(s.Phi(), 0.0f); - if (selectionPID3(p1) && selectionPID3(p2)) { - if (selectionSys(p1, false, false) && selectionSys(p2, false, false)) { output2ProngTracks(collision1.globalIndex(), cftrack1.globalIndex(), cftrack2.globalIndex(), s.pt(), s.eta(), phi, s.M(),