1313// / \brief Analysis task to produce impact-parameter distributions of charm hadrons
1414// /
1515// / \author Fabrizio Grosa <fabrizio.grosa@cern.ch>, CERN
16+ // / \author Antonio Palasciano <antonio.palasciano@cern.ch>, INFN Bari
1617
1718#include < vector>
19+ #include < array>
1820
21+ #include " Common/Core/RecoDecay.h"
1922#include " Framework/AnalysisTask.h"
2023#include " Framework/HistogramRegistry.h"
2124#include " Framework/runDataProcessing.h"
2225
2326#include " PWGHF/Core/HfHelper.h"
27+ #include " PWGHF/Core/CentralityEstimation.h"
2428#include " PWGHF/DataModel/CandidateReconstructionTables.h"
2529#include " PWGHF/DataModel/CandidateSelectionTables.h"
30+ #include " PWGHF/Utils/utilsEvSelHf.h"
2631
2732using namespace o2 ;
33+ using namespace o2 ::aod;
2834using namespace o2 ::analysis;
2935using namespace o2 ::constants::math;
3036using namespace o2 ::framework;
3137using namespace o2 ::framework::expressions;
38+ using namespace o2 ::hf_centrality;
39+ using namespace o2 ::hf_occupancy;
3240
3341enum Channel : uint8_t {
3442 DplusToKPiPi = 0 ,
@@ -40,6 +48,8 @@ namespace o2::aod
4048{
4149namespace hf_charm_cand_lite
4250{
51+ DECLARE_SOA_COLUMN (Centrality, centrality, float ); // ! Centrality (or multiplicity) percentile
52+ DECLARE_SOA_COLUMN (Occupancy, occupancy, float ); // ! Occupancy
4353DECLARE_SOA_COLUMN (M, m, float ); // ! Invariant mass of candidate (GeV/c2)
4454DECLARE_SOA_COLUMN (Pt, pt, float ); // ! Transverse momentum of candidate (GeV/c)
4555DECLARE_SOA_COLUMN (Y, y, float ); // ! Rapidity of candidate
@@ -48,35 +58,59 @@ DECLARE_SOA_COLUMN(ImpactParameterXY, impactParameterXY, float); //! Dca XY of c
4858DECLARE_SOA_COLUMN (MlScoreBkg, mlScoreBkg, float ); // ! ML score for background class
4959DECLARE_SOA_COLUMN (MlScorePrompt, mlScorePrompt, float ); // ! ML Prompt score for prompt class
5060DECLARE_SOA_COLUMN (MlScoreNonPrompt, mlScoreNonPrompt, float ); // ! ML Non Prompt score for non prompt class
61+ DECLARE_SOA_COLUMN (PtProng0, ptProng0, float ); // ! Pt of the 1st daughter
62+ DECLARE_SOA_COLUMN (PtProng1, ptProng1, float ); // ! Pt of the 2nd daughter
63+ DECLARE_SOA_COLUMN (PtProng2, ptProng2, float ); // ! Pt of the 3rd daughter (if present)
64+ DECLARE_SOA_COLUMN (PhiProng0, phiProng0, float ); // ! Phi of the 1st daughter
65+ DECLARE_SOA_COLUMN (PhiProng1, phiProng1, float ); // ! Phi of the 2nd daughter
66+ DECLARE_SOA_COLUMN (PhiProng2, phiProng2, float ); // ! Phi of the 3rd daughter (if present)
67+ DECLARE_SOA_COLUMN (EtaProng0, etaProng0, float ); // ! Eta of the 1st daughter
68+ DECLARE_SOA_COLUMN (EtaProng1, etaProng1, float ); // ! Eta of the 2nd daughter
69+ DECLARE_SOA_COLUMN (EtaProng2, etaProng2, float ); // ! Eta of the 3rd daughter (if present)
5170} // namespace hf_charm_cand_lite
5271
53- DECLARE_SOA_TABLE (HfCharmCandLites, " AOD" , " HFCHARMCANDLITE" , // ! Table with some B+ properties
72+ DECLARE_SOA_TABLE (HfCharmCandLites, " AOD" , " HFCHARMCANDLITE" , // ! Table with some charm hadron properties
73+ collision::BCId,
74+ collision::NumContrib,
75+ collision::PosX,
76+ collision::PosY,
77+ collision::PosZ,
78+ hf_charm_cand_lite::Centrality,
79+ hf_charm_cand_lite::Occupancy,
80+ hf_cand::XSecondaryVertex,
81+ hf_cand::YSecondaryVertex,
82+ hf_cand::ZSecondaryVertex,
5483 hf_charm_cand_lite::M,
5584 hf_charm_cand_lite::Pt,
5685 hf_charm_cand_lite::Y,
5786 hf_charm_cand_lite::Phi,
5887 hf_charm_cand_lite::ImpactParameterXY,
5988 hf_charm_cand_lite::MlScoreBkg,
6089 hf_charm_cand_lite::MlScorePrompt,
61- hf_charm_cand_lite::MlScoreNonPrompt);
90+ hf_charm_cand_lite::MlScoreNonPrompt,
91+ hf_charm_cand_lite::PtProng0,
92+ hf_charm_cand_lite::PtProng1,
93+ hf_charm_cand_lite::PtProng2,
94+ hf_charm_cand_lite::PhiProng0,
95+ hf_charm_cand_lite::PhiProng1,
96+ hf_charm_cand_lite::PhiProng2,
97+ hf_charm_cand_lite::EtaProng0,
98+ hf_charm_cand_lite::EtaProng1,
99+ hf_charm_cand_lite::EtaProng2);
62100} // namespace o2::aod
63101
64102struct HfTaskCharmHadImpactPar {
65103 Produces<aod::HfCharmCandLites> hfCharmCandLite;
66104
67105 Configurable<int > selectionFlag{" selectionFlag" , 15 , " Selection Flag for the considered charm hadron" };
68106 Configurable<int > fillLightTreeCandidate{" fillLightTreeCandidate" , 0 , " Flag to store charm hadron features" };
69- ConfigurableAxis axisPt{" axisPt" , {0 .f , 1 .f , 2 .f , 3 .f , 4 .f , 5 .f , 6 .f , 8 .f , 10 .f , 12 .f , 16 .f , 24 .f , 36 .f , 50 .f }, " axis for pT of charm hadron" };
70- ConfigurableAxis axisMass{" axisMass" , {250 , 1 .65f , 2 .15f }, " axis for mass of charm hadron" };
71- ConfigurableAxis axisPhi{" axisPhi" , {180 , 0 .f , 2 * PI}, " axis for azimuthal angle of charm hadron" };
72- ConfigurableAxis axisY{" axisY" , {20 , -1 .f , 1 .f }, " axis for rapidity of charm hadron" };
73- ConfigurableAxis axisImpPar{" axisImpPar" , {2000 , -500 .f , 500 .f }, " axis for impact-parameter of charm hadron" };
74- ConfigurableAxis axisMlScore0{" axisMlScore0" , {100 , 0 .f , 1 .f }, " axis for ML output score 0" };
75- ConfigurableAxis axisMlScore1{" axisMlScore1" , {100 , 0 .f , 1 .f }, " axis for ML output score 1" };
76- ConfigurableAxis axisMlScore2{" axisMlScore2" , {100 , 0 .f , 1 .f }, " axis for ML output score 2" };
107+ Configurable<int > centEstimator{" centEstimator" , 0 , " Centrality estimation (None: 0, FT0C: 2, FT0M: 3)" };
108+ Configurable<int > occEstimator{" occEstimator" , 0 , " Occupancy estimation (None: 0, ITS: 1, FT0C: 2)" };
77109
78110 HfHelper hfHelper;
79111
112+ using Collisions = soa::Join<aod::Collisions, aod::EvSels>;
113+ using CollisionsCent = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs>;
80114 using CandDplusData = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi>>;
81115 using CandDplusDataWithMl = soa::Filtered<soa::Join<CandDplusData, aod::HfMlDplusToPiKPi>>;
82116 using CandDzeroData = soa::Filtered<soa::Join<aod::HfCand2Prong, aod::HfSelD0>>;
@@ -85,6 +119,15 @@ struct HfTaskCharmHadImpactPar {
85119 Filter filterDplusFlag = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlag;
86120 Filter filterDzeroFlag = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag;
87121
122+ ConfigurableAxis axisPt{" axisPt" , {0 .f , 1 .f , 2 .f , 3 .f , 4 .f , 5 .f , 6 .f , 8 .f , 10 .f , 12 .f , 16 .f , 24 .f , 36 .f , 50 .f }, " axis for pT of charm hadron" };
123+ ConfigurableAxis axisMass{" axisMass" , {250 , 1 .65f , 2 .15f }, " axis for mass of charm hadron" };
124+ ConfigurableAxis axisPhi{" axisPhi" , {180 , 0 .f , TwoPI}, " axis for azimuthal angle of charm hadron" };
125+ ConfigurableAxis axisY{" axisY" , {20 , -1 .f , 1 .f }, " axis for rapidity of charm hadron" };
126+ ConfigurableAxis axisImpPar{" axisImpPar" , {2000 , -500 .f , 500 .f }, " axis for impact-parameter of charm hadron" };
127+ ConfigurableAxis axisMlScore0{" axisMlScore0" , {100 , 0 .f , 1 .f }, " axis for ML output score 0" };
128+ ConfigurableAxis axisMlScore1{" axisMlScore1" , {100 , 0 .f , 1 .f }, " axis for ML output score 1" };
129+ ConfigurableAxis axisMlScore2{" axisMlScore2" , {100 , 0 .f , 1 .f }, " axis for ML output score 2" };
130+
88131 HistogramRegistry registry{" registry" };
89132
90133 void init (InitContext&)
@@ -147,17 +190,24 @@ struct HfTaskCharmHadImpactPar {
147190 }
148191 }
149192
150- // Fill THnSparses for the ML analysis
193+ // Fill the TTree with both event and candidate properties
151194 // / \param candidate is a particle candidate
152- template <Channel channel, bool withMl, typename CCands>
153- void fillTree (const CCands& candidate)
195+ // / \param collision is the respective collision
196+ template <Channel channel, bool withMl, typename CCands, typename CollType>
197+ void fillTree (const CCands& candidate, const CollType& collision)
154198 {
155199 std::vector<float > outputMl = {-999 ., -999 ., -999 .};
156200 float invMass{-1 .f };
157201 float yCand{-999 .f };
202+ std::array<float , 3 > ptProngs = {candidate.ptProng0 (), candidate.ptProng1 (), -1 .};
203+ std::array<double , 3 > phiProngs = {RecoDecay::phi (std::array{candidate.pxProng0 (), candidate.pyProng0 ()}), RecoDecay::phi (std::array{candidate.pxProng1 (), candidate.pyProng1 ()}), 99 .};
204+ std::array<double , 3 > etaProngs = {RecoDecay::eta (std::array{candidate.pxProng0 (), candidate.pyProng0 (), candidate.pzProng0 ()}), RecoDecay::eta (std::array{candidate.pxProng1 (), candidate.pyProng1 (), candidate.pzProng1 ()}), 99 .};
158205 if constexpr (channel == Channel::DplusToKPiPi) { // D+ -> Kpipi
159206 invMass = hfHelper.invMassDplusToPiKPi (candidate);
160207 yCand = hfHelper.yDplus (candidate);
208+ ptProngs[2 ] = candidate.ptProng2 ();
209+ phiProngs[2 ] = RecoDecay::phi (candidate.pxProng2 (), candidate.pyProng2 ());
210+ etaProngs[2 ] = RecoDecay::eta (std::array{candidate.pxProng2 (), candidate.pyProng2 (), candidate.pzProng2 ()});
161211 if constexpr (withMl) {
162212 for (auto iScore{0u }; iScore < candidate.mlProbDplusToPiKPi ().size (); ++iScore) {
163213 outputMl[iScore] = candidate.mlProbDplusToPiKPi ()[iScore];
@@ -183,52 +233,83 @@ struct HfTaskCharmHadImpactPar {
183233 }
184234 }
185235 }
236+ float centrality = 0 .;
237+ float occupancy = 0 .;
238+ if (centEstimator != CentralityEstimator::None) {
239+ centrality = getCentralityColl (collision, centEstimator);
240+ }
241+ if (occEstimator != OccupancyEstimator::None) {
242+ occupancy = getOccupancyColl (collision, occEstimator);
243+ }
244+
186245 hfCharmCandLite (
187- // Charm candidate meson features
246+ // Event features
247+ collision.bcId (),
248+ collision.numContrib (),
249+ collision.posX (),
250+ collision.posY (),
251+ collision.posZ (),
252+ centrality,
253+ occupancy,
254+ // Charm candidate features
255+ candidate.xSecondaryVertex (),
256+ candidate.ySecondaryVertex (),
257+ candidate.zSecondaryVertex (),
188258 invMass,
189259 candidate.pt (),
190260 yCand,
191261 candidate.phi (),
192262 candidate.impactParameterXY (),
193263 outputMl[0 ],
194264 outputMl[1 ],
195- outputMl[2 ]);
265+ outputMl[2 ],
266+ // Daughter features
267+ ptProngs[0 ],
268+ ptProngs[1 ],
269+ ptProngs[2 ],
270+ phiProngs[0 ],
271+ phiProngs[1 ],
272+ phiProngs[2 ],
273+ etaProngs[0 ],
274+ etaProngs[1 ],
275+ etaProngs[2 ]);
196276 }
197277
198278 // / \param candidates are reconstructed candidates
199279 template <Channel channel, bool withMl, typename CCands>
200- void runAnalysis (const CCands& candidates)
280+ void runAnalysis (const CCands& candidates, CollisionsCent const & )
201281 {
202282 for (auto const & candidate : candidates) {
283+ auto collision = candidate.template collision_as <CollisionsCent>();
203284 fillSparse<channel, withMl>(candidate);
204285 if (fillLightTreeCandidate) {
205- fillTree<channel, withMl>(candidate);
286+ fillTree<channel, withMl>(candidate, collision );
206287 }
207288 }
208289 }
209290
210291 // process functions
211- void processDplus (CandDplusData const & candidates)
292+ void processDplus (CandDplusData const & candidates, CollisionsCent const & collisions )
212293 {
213- runAnalysis<Channel::DplusToKPiPi, false >(candidates);
294+ runAnalysis<Channel::DplusToKPiPi, false >(candidates, collisions );
214295 }
215296 PROCESS_SWITCH (HfTaskCharmHadImpactPar, processDplus, " Process D+ w/o ML" , false );
216297
217- void processDplusWithMl (CandDplusDataWithMl const & candidates)
298+ void processDplusWithMl (CandDplusDataWithMl const & candidates, CollisionsCent const & collisions )
218299 {
219- runAnalysis<Channel::DplusToKPiPi, true >(candidates);
300+ runAnalysis<Channel::DplusToKPiPi, true >(candidates, collisions );
220301 }
221302 PROCESS_SWITCH (HfTaskCharmHadImpactPar, processDplusWithMl, " Process D+ with ML" , true );
222303
223- void processDzero (CandDzeroData const & candidates)
304+ void processDzero (CandDzeroData const & candidates, CollisionsCent const & collisions )
224305 {
225- runAnalysis<Channel::DzeroToKPi, false >(candidates);
306+ runAnalysis<Channel::DzeroToKPi, false >(candidates, collisions );
226307 }
227308 PROCESS_SWITCH (HfTaskCharmHadImpactPar, processDzero, " Process D0 w/o ML" , false );
228309
229- void processDzeroWithMl (CandDzeroDataWithMl const & candidates)
310+ void processDzeroWithMl (CandDzeroDataWithMl const & candidates, CollisionsCent const & collisions )
230311 {
231- runAnalysis<Channel::DzeroToKPi, true >(candidates);
312+ runAnalysis<Channel::DzeroToKPi, true >(candidates, collisions );
232313 }
233314 PROCESS_SWITCH (HfTaskCharmHadImpactPar, processDzeroWithMl, " Process D0 with ML" , false );
234315};
0 commit comments