@@ -45,6 +45,8 @@ enum LambdaPid { kLambda = 0,
4545#define O2_DEFINE_CONFIGURABLE (NAME, TYPE, DEFAULT, HELP ) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP};
4646
4747struct Filter2Prong {
48+ SliceCache cache;
49+
4850 O2_DEFINE_CONFIGURABLE (cfgVerbosity, int , 0 , " Verbosity level (0 = major, 1 = per collision)" )
4951 O2_DEFINE_CONFIGURABLE (cfgYMax, float , -1 .0f , " Maximum candidate rapidity" )
5052 O2_DEFINE_CONFIGURABLE (cfgImPart1Mass, float , o2::constants::physics::MassKPlus, " Daughter particle 1 mass in GeV" )
@@ -146,6 +148,10 @@ struct Filter2Prong {
146148 O2_DEFINE_CONFIGURABLE (applyTOF, bool , false , " Flag for applying TOF" );
147149 } grpPhi;
148150
151+ O2_DEFINE_CONFIGURABLE (cfgNoMixedEvents, int , 5 , " Number of mixed events per event for mixed phi building" )
152+ ConfigurableAxis axisVertexMix{" axisVertexMix" , {7 , -7 , 7 }, " vertex axis for phi event mixing" };
153+ ConfigurableAxis axisMultiplicityMix{" axisMultiplicityMix" , {VARIABLE_WIDTH, 0 , 5 , 10 , 20 , 30 , 40 , 50 , 100.1 }, " multiplicity axis for phi event mixing" };
154+
149155 HfHelper hfHelper;
150156 Produces<aod::CF2ProngTracks> output2ProngTracks;
151157 Produces<aod::CF2ProngTrackmls> output2ProngTrackmls;
@@ -772,6 +778,104 @@ struct Filter2Prong {
772778 }
773779 PROCESS_SWITCH (Filter2Prong, processDataPhiV0, " Process data Phi and V0 candidates with invariant mass method" , false );
774780
781+ using DerivedCollisions = soa::Join<aod::Collisions, aod::EvSels, aod::CFMultiplicities>;
782+ void processDataPhiMixed (DerivedCollisions const & collisions, aod::CFTrackRefs const & cftracks)
783+ {
784+ auto getMultiplicity = [](auto const & col) {
785+ return col.multiplicity ();
786+ };
787+ using BinningTypeDerived = FlexibleBinningPolicy<std::tuple<decltype (getMultiplicity)>, aod::collision::PosZ, decltype (getMultiplicity)>;
788+ BinningTypeDerived configurableBinningDerived{{getMultiplicity}, {axisVertexMix, axisMultiplicityMix}, true };
789+ auto tracksTuple = std::make_tuple (cftracks, cftracks);
790+ using TA = std::tuple_element<0 , decltype (tracksTuple)>::type;
791+ using TB = std::tuple_element<std::tuple_size_v<decltype (tracksTuple)> - 1 , decltype (tracksTuple)>::type;
792+ Pair<DerivedCollisions, TA, TB, BinningTypeDerived> pairs{configurableBinningDerived, cfgNoMixedEvents, -1 , collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip
793+
794+ o2::aod::ITSResponse itsResponse;
795+
796+ for (auto it = pairs.begin (); it != pairs.end (); it++) {
797+ auto & [collision1, tracks1, collision2, tracks2] = *it;
798+
799+ if (!(collision1.sel8 () &&
800+ collision1.selection_bit (aod::evsel::kNoSameBunchPileup ) &&
801+ collision1.selection_bit (aod::evsel::kIsGoodZvtxFT0vsPV ) &&
802+ collision1.selection_bit (aod::evsel::kIsGoodITSLayersAll ))) {
803+ continue ;
804+ }
805+
806+ if (!(collision2.sel8 () &&
807+ collision2.selection_bit (aod::evsel::kNoSameBunchPileup ) &&
808+ collision2.selection_bit (aod::evsel::kIsGoodZvtxFT0vsPV ) &&
809+ collision2.selection_bit (aod::evsel::kIsGoodITSLayersAll ))) {
810+ continue ;
811+ }
812+
813+ for (const auto & cftrack1 : tracks1) {
814+ const auto & p1 = cftrack1.track_as <Filter2Prong::PIDTrack>();
815+
816+ if (p1.sign () != 1 ) {
817+ continue ;
818+ }
819+ if (!selectionTrack (p1)) {
820+ continue ;
821+ }
822+ if (grpPhi.ITSPIDSelection &&
823+ p1.p () < grpPhi.ITSPIDPthreshold .value &&
824+ !(itsResponse.nSigmaITS <o2::track::PID::Kaon>(p1) > grpPhi.lowITSPIDNsigma .value &&
825+ itsResponse.nSigmaITS <o2::track::PID::Kaon>(p1) < grpPhi.highITSPIDNsigma .value )) {
826+ continue ;
827+ }
828+ if (grpPhi.removefaketrack && isFakeTrack (p1)) {
829+ continue ;
830+ }
831+
832+ for (const auto & cftrack2 : tracks2) {
833+ const auto & p2 = cftrack2.track_as <Filter2Prong::PIDTrack>();
834+
835+ if (p2.sign () != -1 ) {
836+ continue ;
837+ }
838+ if (!selectionTrack (p2)) {
839+ continue ;
840+ }
841+ if (grpPhi.ITSPIDSelection &&
842+ p2.p () < grpPhi.ITSPIDPthreshold .value &&
843+ !(itsResponse.nSigmaITS <o2::track::PID::Kaon>(p2) > grpPhi.lowITSPIDNsigma .value &&
844+ itsResponse.nSigmaITS <o2::track::PID::Kaon>(p2) < grpPhi.highITSPIDNsigma .value )) {
845+ continue ;
846+ }
847+ if (grpPhi.removefaketrack && isFakeTrack (p2)) {
848+ continue ;
849+ }
850+ if (!selectionPair (p1, p2)) {
851+ continue ;
852+ }
853+
854+ if (selectionPID3 (p1) && selectionPID3 (p2)) {
855+ if (selectionSys (p1, false , false ) && selectionSys (p2, false , false )) {
856+ ROOT::Math::PtEtaPhiMVector vec1 (p1.pt (), p1.eta (), p1.phi (), cfgImPart1Mass);
857+ ROOT::Math::PtEtaPhiMVector vec2 (p2.pt (), p2.eta (), p2.phi (), cfgImPart2Mass);
858+ ROOT::Math::PtEtaPhiMVector s = vec1 + vec2;
859+
860+ if (s.M () < grpPhi.ImMinInvMassPhiMeson || s.M () > grpPhi.ImMaxInvMassPhiMeson ) {
861+ continue ;
862+ }
863+
864+ float phi = RecoDecay::constrainAngle (s.Phi (), 0 .0f );
865+
866+ output2ProngTracks (collision1.globalIndex (),
867+ cftrack1.globalIndex (), cftrack2.globalIndex (),
868+ s.pt (), s.eta (), phi, s.M (),
869+ aod::cf2prongtrack::PhiToKKPID3Mixed);
870+ }
871+ }
872+ }
873+ }
874+ }
875+ }
876+
877+ PROCESS_SWITCH (Filter2Prong, processDataPhiMixed, " Process mixed-event phi candidates using O2 framework" , false );
878+
775879 // Phi and V0s invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now.
776880 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)
777881 {
0 commit comments