1414// /
1515// / \author S. Politanò, INFN Torino, Italy
1616// / \author Wu Chuntai, CUG, China
17+ // / \author Ran Tu, Fudan University, China
1718
1819#include < string>
1920#include < vector>
@@ -48,7 +49,8 @@ enum DecayChannel { DplusToPiKPi = 0,
4849 LcToPKPi,
4950 LcToPiKP,
5051 XicToPKPi,
51- XicToPiKP
52+ XicToPiKP,
53+ Xic0ToXiPi
5254};
5355
5456enum QvecEstimator { FV0A = 0 ,
@@ -75,25 +77,11 @@ struct HfTaskFlowCharmHadrons {
7577 Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
7678 Configurable<std::vector<int >> classMl{" classMl" , {0 , 2 }, " Indexes of BDT scores to be stored. Two indexes max." };
7779
78- ConfigurableAxis thnConfigAxisInvMass{" thnConfigAxisInvMass" , {100 , 1.78 , 2.05 }, " " };
79- ConfigurableAxis thnConfigAxisPt{" thnConfigAxisPt" , {10 , 0 ., 10 .}, " " };
80- ConfigurableAxis thnConfigAxisCent{" thnConfigAxisCent" , {10000 , 0 ., 100 .}, " " };
81- ConfigurableAxis thnConfigAxisCosNPhi{" thnConfigAxisCosNPhi" , {100 , -1 ., 1 .}, " " };
82- ConfigurableAxis thnConfigAxisPsi{" thnConfigAxisPsi" , {6000 , 2 . * TMath::Pi (), 2 . * TMath::Pi ()}, " " };
83- ConfigurableAxis thnConfigAxisCosDeltaPhi{" thnConfigAxisCosDeltaPhi" , {100 , -1 ., 1 .}, " " };
84- ConfigurableAxis thnConfigAxisScalarProd{" thnConfigAxisScalarProd" , {100 , 0 ., 1 .}, " " };
85- ConfigurableAxis thnConfigAxisMlOne{" thnConfigAxisMlOne" , {1000 , 0 ., 1 .}, " " };
86- ConfigurableAxis thnConfigAxisMlTwo{" thnConfigAxisMlTwo" , {1000 , 0 ., 1 .}, " " };
87- ConfigurableAxis thnConfigAxisOccupancyITS{" thnConfigAxisOccupancyITS" , {14 , 0 , 14000 }, " " };
88- ConfigurableAxis thnConfigAxisOccupancyFT0C{" thnConfigAxisOccupancyFT0C" , {14 , 0 , 140000 }, " " };
89- ConfigurableAxis thnConfigAxisNoSameBunchPileup{" thnConfigAxisNoSameBunchPileup" , {2 , 0 , 2 }, " " };
90- ConfigurableAxis thnConfigAxisOccupancy{" thnConfigAxisOccupancy" , {2 , 0 , 2 }, " " };
91- ConfigurableAxis thnConfigAxisNoCollInTimeRangeNarrow{" thnConfigAxisNoCollInTimeRangeNarrow" , {2 , 0 , 2 }, " " };
92- ConfigurableAxis thnConfigAxisNoCollInTimeRangeStandard{" thnConfigAxisNoCollInTimeRangeStandard" , {2 , 0 , 2 }, " " };
93- ConfigurableAxis thnConfigAxisNoCollInRofStandard{" thnConfigAxisNoCollInRofStandard" , {2 , 0 , 2 }, " " };
94- ConfigurableAxis thnConfigAxisResoFT0cFV0a{" thnConfigAxisResoFT0cFV0a" , {160 , -8 , 8 }, " " };
95- ConfigurableAxis thnConfigAxisResoFT0cTPCtot{" thnConfigAxisResoFT0cTPCtot" , {160 , -8 , 8 }, " " };
96- ConfigurableAxis thnConfigAxisResoFV0aTPCtot{" thnConfigAxisResoFV0aTPCtot" , {160 , -8 , 8 }, " " };
80+ HfHelper hfHelper;
81+ EventPlaneHelper epHelper;
82+ HfEventSelection hfEvSel; // event selection and monitoring
83+ o2::framework::Service<o2::ccdb::BasicCCDBManager> ccdb;
84+ SliceCache cache;
9785
9886 using CandDsDataWMl = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDsToKKPi, aod::HfMlDsToKKPi>>;
9987 using CandDsData = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDsToKKPi>>;
@@ -103,6 +91,8 @@ struct HfTaskFlowCharmHadrons {
10391 using CandLcDataWMl = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelLc, aod::HfMlLcToPKPi>>;
10492 using CandXicData = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelXicToPKPi>>;
10593 using CandXicDataWMl = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelXicToPKPi, aod::HfMlXicToPKPi>>;
94+ using CandXic0Data = soa::Filtered<soa::Join<aod::HfCandToXiPiKf, aod::HfSelToXiPiKf>>;
95+ using CandXic0DataWMl = soa::Filtered<soa::Join<aod::HfCandToXiPiKf, aod::HfSelToXiPiKf, aod::HfMlToXiPiKf>>;
10696 using CandD0DataWMl = soa::Filtered<soa::Join<aod::HfCand2Prong, aod::HfSelD0, aod::HfMlD0>>;
10797 using CandD0Data = soa::Filtered<soa::Join<aod::HfCand2Prong, aod::HfSelD0>>;
10898 using CollsWithQvecs = soa::Join<aod::Collisions, aod::EvSels, aod::QvectorFT0Cs, aod::QvectorFT0As, aod::QvectorFT0Ms, aod::QvectorFV0As, aod::QvectorBPoss, aod::QvectorBNegs, aod::QvectorBTots, aod::CentFV0As, aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs>;
@@ -112,6 +102,7 @@ struct HfTaskFlowCharmHadrons {
112102 Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag;
113103 Filter filterSelectLcCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlag;
114104 Filter filterSelectXicCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag;
105+ Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections >= selectionFlag;
115106
116107 Partition<CandDsData> selectedDsToKKPi = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag;
117108 Partition<CandDsData> selectedDsToPiKK = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag;
@@ -129,12 +120,28 @@ struct HfTaskFlowCharmHadrons {
129120 Partition<CandXicData> selectedXicToPiKP = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag;
130121 Partition<CandXicDataWMl> selectedXicToPKPiWMl = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag;
131122 Partition<CandXicDataWMl> selectedXicToPiKPWMl = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag;
123+ Partition<CandXic0Data> selectedXic0 = aod::hf_sel_toxipi::resultSelections >= selectionFlag;
124+ Partition<CandXic0DataWMl> selectedXic0WMl = aod::hf_sel_toxipi::resultSelections >= selectionFlag;
132125
133- SliceCache cache;
134- HfHelper hfHelper;
135- EventPlaneHelper epHelper;
136- HfEventSelection hfEvSel; // event selection and monitoring
137- o2::framework::Service<o2::ccdb::BasicCCDBManager> ccdb;
126+ ConfigurableAxis thnConfigAxisInvMass{" thnConfigAxisInvMass" , {100 , 1.78 , 2.05 }, " " };
127+ ConfigurableAxis thnConfigAxisPt{" thnConfigAxisPt" , {10 , 0 ., 10 .}, " " };
128+ ConfigurableAxis thnConfigAxisCent{" thnConfigAxisCent" , {10000 , 0 ., 100 .}, " " };
129+ ConfigurableAxis thnConfigAxisCosNPhi{" thnConfigAxisCosNPhi" , {100 , -1 ., 1 .}, " " };
130+ ConfigurableAxis thnConfigAxisPsi{" thnConfigAxisPsi" , {6000 , 0 , constants::math::TwoPI}, " " };
131+ ConfigurableAxis thnConfigAxisCosDeltaPhi{" thnConfigAxisCosDeltaPhi" , {100 , -1 ., 1 .}, " " };
132+ ConfigurableAxis thnConfigAxisScalarProd{" thnConfigAxisScalarProd" , {100 , 0 ., 1 .}, " " };
133+ ConfigurableAxis thnConfigAxisMlOne{" thnConfigAxisMlOne" , {1000 , 0 ., 1 .}, " " };
134+ ConfigurableAxis thnConfigAxisMlTwo{" thnConfigAxisMlTwo" , {1000 , 0 ., 1 .}, " " };
135+ ConfigurableAxis thnConfigAxisOccupancyITS{" thnConfigAxisOccupancyITS" , {14 , 0 , 14000 }, " " };
136+ ConfigurableAxis thnConfigAxisOccupancyFT0C{" thnConfigAxisOccupancyFT0C" , {14 , 0 , 140000 }, " " };
137+ ConfigurableAxis thnConfigAxisNoSameBunchPileup{" thnConfigAxisNoSameBunchPileup" , {2 , 0 , 2 }, " " };
138+ ConfigurableAxis thnConfigAxisOccupancy{" thnConfigAxisOccupancy" , {2 , 0 , 2 }, " " };
139+ ConfigurableAxis thnConfigAxisNoCollInTimeRangeNarrow{" thnConfigAxisNoCollInTimeRangeNarrow" , {2 , 0 , 2 }, " " };
140+ ConfigurableAxis thnConfigAxisNoCollInTimeRangeStandard{" thnConfigAxisNoCollInTimeRangeStandard" , {2 , 0 , 2 }, " " };
141+ ConfigurableAxis thnConfigAxisNoCollInRofStandard{" thnConfigAxisNoCollInRofStandard" , {2 , 0 , 2 }, " " };
142+ ConfigurableAxis thnConfigAxisResoFT0cFV0a{" thnConfigAxisResoFT0cFV0a" , {160 , -8 , 8 }, " " };
143+ ConfigurableAxis thnConfigAxisResoFT0cTPCtot{" thnConfigAxisResoFT0cTPCtot" , {160 , -8 , 8 }, " " };
144+ ConfigurableAxis thnConfigAxisResoFV0aTPCtot{" thnConfigAxisResoFV0aTPCtot" , {160 , -8 , 8 }, " " };
138145
139146 HistogramRegistry registry{" registry" , {}};
140147
@@ -231,15 +238,15 @@ struct HfTaskFlowCharmHadrons {
231238 }
232239
233240 if (storeResoOccu) {
234- std::vector<AxisSpec> axes_reso = {thnAxisCent, thnAxisResoFT0cFV0a, thnAxisResoFT0cTPCtot, thnAxisResoFV0aTPCtot};
241+ std::vector<AxisSpec> axesReso = {thnAxisCent, thnAxisResoFT0cFV0a, thnAxisResoFT0cTPCtot, thnAxisResoFV0aTPCtot};
235242 if (occEstimator == 1 ) {
236- axes_reso .insert (axes_reso .end (), {thnAxisOccupancyITS, thnAxisNoSameBunchPileup, thnAxisOccupancy,
237- thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard});
243+ axesReso .insert (axesReso .end (), {thnAxisOccupancyITS, thnAxisNoSameBunchPileup, thnAxisOccupancy,
244+ thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard});
238245 } else {
239- axes_reso .insert (axes_reso .end (), {thnAxisOccupancyFT0C, thnAxisNoSameBunchPileup, thnAxisOccupancy,
240- thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard});
246+ axesReso .insert (axesReso .end (), {thnAxisOccupancyFT0C, thnAxisNoSameBunchPileup, thnAxisOccupancy,
247+ thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard});
241248 }
242- registry.add (" spReso/hSparseReso" , " THn for resolution with occupancy" , HistType::kTHnSparseF , axes_reso );
249+ registry.add (" spReso/hSparseReso" , " THn for resolution with occupancy" , HistType::kTHnSparseF , axesReso );
243250 }
244251
245252 hfEvSel.addHistograms (registry); // collision monitoring
@@ -285,19 +292,52 @@ struct HfTaskFlowCharmHadrons {
285292 }
286293 }
287294
295+ // / Compute the Q vector for the candidate's tracks
296+ // / \param cand is the candidate
297+ // / \param tracksQx is the X component of the Q vector for the tracks
298+ // / \param tracksQy is the Y component of the Q vector for the tracks
299+ // / \param channel is the decay channel
300+ template <typename T1>
301+ void getQvecXic0Tracks (const T1& cand,
302+ std::vector<float >& tracksQx,
303+ std::vector<float >& tracksQy,
304+ float ampl)
305+ {
306+ // add possibility to consider different weights for the tracks, at the moment only pT is considered;
307+ float pXTrack0 = cand.pxPosV0Dau ();
308+ float pYTrack0 = cand.pyPosV0Dau ();
309+ float pTTrack0 = std::hypot (pXTrack0, pYTrack0);
310+ float phiTrack0 = std::atan2 (pXTrack0, pYTrack0);
311+ float pXTrack1 = cand.pxNegV0Dau ();
312+ float pYTrack1 = cand.pyNegV0Dau ();
313+ float pTTrack1 = std::hypot (pXTrack1, pYTrack1);
314+ float phiTrack1 = std::atan2 (pXTrack1, pYTrack1);
315+ float pYTrack2 = cand.pxBachFromCasc ();
316+ float pXTrack2 = cand.pyBachFromCasc ();
317+ float pTTrack2 = std::hypot (pXTrack2, pYTrack2);
318+ float phiTrack2 = std::atan2 (pXTrack2, pYTrack2);
319+ float pXTrack3 = cand.pxBachFromCharmBaryon ();
320+ float pYTrack3 = cand.pyBachFromCharmBaryon ();
321+ float pTTrack3 = std::hypot (pXTrack3, pYTrack3);
322+ float phiTrack3 = std::atan2 (pXTrack3, pYTrack3);
323+
324+ tracksQx.push_back (std::cos (harmonic * phiTrack0) * pTTrack0 / ampl);
325+ tracksQy.push_back (std::sin (harmonic * phiTrack0) * pTTrack0 / ampl);
326+ tracksQx.push_back (std::cos (harmonic * phiTrack1) * pTTrack1 / ampl);
327+ tracksQy.push_back (std::sin (harmonic * phiTrack1) * pTTrack1 / ampl);
328+ tracksQx.push_back (std::cos (harmonic * phiTrack2) * pTTrack2 / ampl);
329+ tracksQy.push_back (std::sin (harmonic * phiTrack2) * pTTrack2 / ampl);
330+ tracksQx.push_back (std::cos (harmonic * phiTrack3) * pTTrack3 / ampl);
331+ tracksQy.push_back (std::sin (harmonic * phiTrack3) * pTTrack3 / ampl);
332+ }
288333 // / Compute the delta psi in the range [0, pi/harmonic]
289334 // / \param psi1 is the first angle
290335 // / \param psi2 is the second angle
291336 // / \note Ported from AliAnalysisTaskSECharmHadronvn::GetDeltaPsiSubInRange
292337 float getDeltaPsiInRange (float psi1, float psi2)
293338 {
294339 float deltaPsi = psi1 - psi2;
295- if (std::abs (deltaPsi) > constants::math::PI / harmonic) {
296- if (deltaPsi > 0 .)
297- deltaPsi -= constants::math::TwoPI / harmonic;
298- else
299- deltaPsi += constants::math::TwoPI / harmonic;
300- }
340+ deltaPsi = RecoDecay::constrainAngle (deltaPsi, -o2::constants::math::PI / harmonic, harmonic);
301341 return deltaPsi;
302342 }
303343
@@ -552,18 +592,36 @@ struct HfTaskFlowCharmHadrons {
552592 default :
553593 break ;
554594 }
595+ } else if constexpr (std::is_same_v<T1, CandXic0Data> || std::is_same_v<T1, CandXic0DataWMl>) {
596+ massCand = candidate.invMassCharmBaryon ();
597+ if constexpr (std::is_same_v<T1, CandXic0DataWMl>) {
598+ for (unsigned int iclass = 0 ; iclass < classMl->size (); iclass++)
599+ outputMl[iclass] = candidate.mlProbToXiPi ()[classMl->at (iclass)];
600+ }
555601 }
556602
557- float ptCand = candidate.pt ();
558- float phiCand = candidate.phi ();
603+ float ptCand = 0 .;
604+ float phiCand = 0 .;
605+
606+ if constexpr (std::is_same_v<T1, CandXic0Data> || std::is_same_v<T1, CandXic0DataWMl>) {
607+ ptCand = candidate.kfptXic ();
608+ phiCand = std::atan2 (candidate.pxCharmBaryon (), candidate.pyCharmBaryon ());
609+ } else {
610+ ptCand = candidate.pt ();
611+ phiCand = candidate.phi ();
612+ }
559613
560614 // If TPC is used for the SP estimation, the tracks of the hadron candidate must be removed from the TPC Q vector to avoid double counting
561615 if (qvecDetector == QvecEstimator::TPCNeg || qvecDetector == QvecEstimator::TPCPos) {
562616 float ampl = amplQVec - static_cast <float >(nProngs);
563617 std::vector<float > tracksQx = {};
564618 std::vector<float > tracksQy = {};
565-
566- getQvecDtracks<channel>(candidate, tracksQx, tracksQy, ampl);
619+ if constexpr (std::is_same_v<T1, CandXic0Data> || std::is_same_v<T1, CandXic0DataWMl>) {
620+ // std::cout<<candidate.pxProng0()<<std::endl;
621+ getQvecXic0Tracks (candidate, tracksQx, tracksQy, ampl);
622+ } else {
623+ getQvecDtracks<channel>(candidate, tracksQx, tracksQy, ampl);
624+ }
567625 for (auto iTrack{0u }; iTrack < tracksQx.size (); ++iTrack) {
568626 xQVec -= tracksQx[iTrack];
569627 yQVec -= tracksQy[iTrack];
@@ -683,6 +741,24 @@ struct HfTaskFlowCharmHadrons {
683741 }
684742 PROCESS_SWITCH (HfTaskFlowCharmHadrons, processXic, " Process Xic candidates" , false );
685743
744+ // Xic0 with ML
745+ void processXic0Ml (CollsWithQvecs::iterator const & collision,
746+ CandXic0DataWMl const &)
747+ {
748+ auto candsXic0WMl = selectedXic0WMl->sliceByCached (aod::hf_cand::collisionId, collision.globalIndex (), cache);
749+ runFlowAnalysis<DecayChannel::Xic0ToXiPi>(collision, candsXic0WMl);
750+ }
751+ PROCESS_SWITCH (HfTaskFlowCharmHadrons, processXic0Ml, " Process Xic0 candidates with ML" , false );
752+
753+ // Xic0
754+ void processXic0 (CollsWithQvecs::iterator const & collision,
755+ CandXic0Data const &)
756+ {
757+ auto candsXic0 = selectedXic0->sliceByCached (aod::hf_cand::collisionId, collision.globalIndex (), cache);
758+ runFlowAnalysis<DecayChannel::Xic0ToXiPi>(collision, candsXic0);
759+ }
760+ PROCESS_SWITCH (HfTaskFlowCharmHadrons, processXic0, " Process Xic0 candidates" , false );
761+
686762 // Resolution
687763 void processResolution (CollsWithQvecs::iterator const & collision,
688764 aod::BCsWithTimestamps const & bcs)
0 commit comments