1010// or submit itself to any jurisdiction.
1111#include < experimental/type_traits>
1212#include < vector>
13+ #include < string>
14+ #include < memory>
1315
1416#include " Framework/runDataProcessing.h"
1517#include " Framework/AnalysisTask.h"
2426#include " PWGHF/DataModel/CandidateReconstructionTables.h"
2527#include " PWGHF/DataModel/CandidateSelectionTables.h"
2628
29+ #include < TFormula.h>
30+
2731using namespace o2 ;
2832using namespace o2 ::framework;
2933using namespace o2 ::framework::expressions;
@@ -35,6 +39,15 @@ using namespace o2::math_utils::detail;
3539struct Filter2Prong {
3640 O2_DEFINE_CONFIGURABLE (cfgVerbosity, int , 0 , " Verbosity level (0 = major, 1 = per collision)" )
3741 O2_DEFINE_CONFIGURABLE (cfgYMax, float , -1 .0f , " Maximum candidate rapidity" )
42+ //
43+ O2_DEFINE_CONFIGURABLE (cfgImPart1Mass, float , o2::constants::physics::MassKPlus, " Daughter particle 1 mass in GeV" )
44+ O2_DEFINE_CONFIGURABLE (cfgImPart2Mass, float , o2::constants::physics::MassKMinus, " Daughter particle 2 mass in GeV" )
45+ O2_DEFINE_CONFIGURABLE (cfgImPart1PID, float , o2::track::PID::Kaon, " PID of daughter particle 1 (O2 PID ID)" )
46+ O2_DEFINE_CONFIGURABLE (cfgImPart2PID, float , o2::track::PID::Kaon, " PID of daughter particle 1 (O2 PID ID)" )
47+ O2_DEFINE_CONFIGURABLE (cfgImCutPt, float , 0 .2f , " Minimal pT for candidates" )
48+ O2_DEFINE_CONFIGURABLE (cfgImMinInvMass, float , 0 .95f , " Minimum invariant mass (GeV)" )
49+ O2_DEFINE_CONFIGURABLE (cfgImMaxInvMass, float , 1 .07f , " Maximum invariant mass (GeV)" )
50+ O2_DEFINE_CONFIGURABLE (cfgImSigmaFormula, std::string, " (z < 0.5 && x < 3.0) || (z >= 0.5 && x < 2.5 && y < 3.0)" , " pT dependent daughter track sigma pass condition (x = TPC sigma, y = TOF sigma, z = pT)" )
3851
3952 HfHelper hfHelper;
4053 Produces<aod::CF2ProngTracks> output2ProngTracks;
@@ -51,6 +64,14 @@ struct Filter2Prong {
5164 template <class T >
5265 using HasMLProb = decltype (std::declval<T&>().mlProbD0());
5366
67+ std::unique_ptr<TFormula> sigmaFormula;
68+
69+ void init (InitContext&)
70+ {
71+ if (doprocessDataInvMass)
72+ sigmaFormula = std::make_unique<TFormula>(" sigmaFormula" , cfgImSigmaFormula.value .c_str ());
73+ }
74+
5475 template <class HFCandidatesType >
5576 void processDataT (aod::Collisions::iterator const &, aod::BCsWithTimestamps const &, aod::CFCollRefs const & cfcollisions, aod::CFTrackRefs const & cftracks, HFCandidatesType const & candidates)
5677 {
@@ -142,6 +163,40 @@ struct Filter2Prong {
142163 }
143164 }
144165 PROCESS_SWITCH (Filter2Prong, processMC, " Process MC 2-prong daughters" , false );
166+
167+ // Generic 2-prong invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now.
168+ using PIDTrack = soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCPr>;
169+ void processDataInvMass (aod::Collisions::iterator const &, aod::BCsWithTimestamps const &, aod::CFCollRefs const & cfcollisions, aod::CFTrackRefs const & cftracks, PIDTrack const & tracks)
170+ {
171+ if (cfcollisions.size () <= 0 || cftracks.size () <= 0 )
172+ return ; // rejected collision
173+ for (auto & cftrack1 : cftracks) {
174+ auto p1 = tracks.iteratorAt (cftrack1.trackId ());
175+ if (p1.sign () != 1 )
176+ continue ;
177+ if (sigmaFormula->Eval (o2::aod::pidutils::tpcNSigma (cfgImPart1PID, p1), o2::aod::pidutils::tofNSigma (cfgImPart1PID, p1)) <= 0 .0f )
178+ continue ;
179+ for (auto & cftrack2 : cftracks) {
180+ if (cftrack2.globalIndex () == cftrack1.globalIndex ())
181+ continue ;
182+ auto p2 = tracks.iteratorAt (cftrack2.trackId ());
183+ if (p2.sign () != -1 )
184+ continue ;
185+ if (sigmaFormula->Eval (o2::aod::pidutils::tpcNSigma (cfgImPart2PID, p2), o2::aod::pidutils::tofNSigma (cfgImPart2PID, p2)) <= 0 .0f )
186+ continue ;
187+ ROOT::Math::PtEtaPhiMVector vec1 (p1.pt (), p1.eta (), p1.phi (), cfgImPart1Mass);
188+ ROOT::Math::PtEtaPhiMVector vec2 (p2.pt (), p2.eta (), p2.phi (), cfgImPart2Mass);
189+ ROOT::Math::PtEtaPhiMVector s = vec1 + vec2;
190+ if (s.pt () < cfgImCutPt || s.M () < cfgImMinInvMass || s.M () > cfgImMaxInvMass)
191+ continue ;
192+
193+ float phi = RecoDecay::constrainAngle (s.Phi (), 0 .0f );
194+ output2ProngTracks (cfcollisions.begin ().globalIndex (),
195+ cftrack1.globalIndex (), cftrack2.globalIndex (), s.pt (), s.eta (), phi, s.M (), aod::cf2prongtrack::Generic2Prong);
196+ }
197+ }
198+ }
199+ PROCESS_SWITCH (Filter2Prong, processDataInvMass, " Process data generic 2-prong candidates with invariant mass method" , false );
145200}; // struct
146201
147202WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
0 commit comments