diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index 8af9d7fef71..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 @@ -157,7 +165,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..0baf4e31279 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -45,6 +45,8 @@ enum LambdaPid { kLambda = 0, #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; 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 +148,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 +778,104 @@ 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; + + 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; + } + + 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; + } + + float phi = RecoDecay::constrainAngle(s.Phi(), 0.0f); + + 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) { 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&) {