@@ -27,6 +27,44 @@ using namespace o2::constants::math;
2727using namespace o2 ::framework;
2828using namespace o2 ::framework::expressions;
2929
30+ enum PdgCode {
31+ kEta = 221 ,
32+ kOmega = 223 ,
33+ kPhi = 333 ,
34+ kEtaPrime = 331
35+ };
36+
37+ enum SourceType {
38+ NotElec = 0 , // not electron
39+ DirectCharm = 1 , // electrons from prompt charm hadrons
40+ DirectBeauty = 2 , // electrons from primary beauty hadrons
41+ BeautyCharm = 3 , // electrons from non-prompt charm hadrons
42+ DirectGamma = 4 , // electrons from direct photon
43+ GammaPi0 = 5 ,
44+ GammaEta = 6 ,
45+ GammaOmega = 7 ,
46+ GammaPhi = 8 ,
47+ GammaEtaPrime = 9 ,
48+ GammaRho0 = 10 ,
49+ GammaK0s = 11 ,
50+ GammaK0l = 12 ,
51+ GammaKe3 = 13 ,
52+ GammaLambda0 = 14 ,
53+ GammaSigma = 15 ,
54+ Pi0 = 16 ,
55+ Eta = 17 ,
56+ Omega = 18 ,
57+ Phi = 19 ,
58+ EtaPrime = 20 ,
59+ Rho0 = 21 ,
60+ K0s = 22 ,
61+ K0l = 23 ,
62+ Ke3 = 24 ,
63+ Lambda0 = 25 ,
64+ Sigma = 26 ,
65+ Else = 27
66+ };
67+
3068struct HfTaskSingleElectron {
3169
3270 // Produces
@@ -55,6 +93,7 @@ struct HfTaskSingleElectron {
5593 // using declarations
5694 using MyCollisions = soa::Join<aod::Collisions, aod::EvSels>;
5795 using TracksEl = soa::Join<aod::Tracks, aod::TrackExtra, aod::TracksDCA, aod::pidTOFFullEl, aod::pidTPCFullEl>;
96+ using McTracksEl = soa::Join<aod::Tracks, aod::TrackExtra, aod::TracksDCA, aod::pidTOFFullEl, aod::pidTPCFullEl, aod::McTrackLabels>;
5897
5998 // Filter
6099 Filter collZFilter = nabs(aod::collision::posZ) < posZMax;
@@ -79,7 +118,6 @@ struct HfTaskSingleElectron {
79118 void init (InitContext const &)
80119 {
81120 // create histograms
82- histos.add (" hEventCounter" , " hEventCounter" , kTH1F , {axisEvt});
83121 histos.add (" nEvents" , " Number of events" , kTH1F , {{1 , 0 ., 1 .}});
84122 histos.add (" VtxZ" , " VtxZ; cm; entries" , kTH1F , {axisPosZ});
85123 histos.add (" etaTrack" , " etaTrack; #eta; entries" , kTH1F , {axisEta});
@@ -102,6 +140,16 @@ struct HfTaskSingleElectron {
102140
103141 // track impact parameter
104142 histos.add (" dcaTrack" , " " , kTH2F , {{axisPtEl}, {axisTrackIp}});
143+ histos.add (" dcaBeauty" , " " , kTH2F , {{axisPtEl}, {axisTrackIp}});
144+ histos.add (" dcaCharm" , " " , kTH2F , {{axisPtEl}, {axisTrackIp}});
145+ histos.add (" dcaDalitz" , " " , kTH2F , {{axisPtEl}, {axisTrackIp}});
146+ histos.add (" dcaConv" , " " , kTH2F , {{axisPtEl}, {axisTrackIp}});
147+
148+ // QA plots for MC
149+ histos.add (" hPdgC" , " " , kTH1F , {{10001 , -0.5 , 10000.5 }});
150+ histos.add (" hPdgB" , " " , kTH1F , {{10001 , -0.5 , 10000.5 }});
151+ histos.add (" hPdgDa" , " " , kTH1F , {{10001 , -0.5 , 10000.5 }});
152+ histos.add (" hPdgCo" , " " , kTH1F , {{10001 , -0.5 , 10000.5 }});
105153 }
106154
107155 template <typename TrackType>
@@ -138,24 +186,267 @@ struct HfTaskSingleElectron {
138186 return true ;
139187 }
140188
141- void process (soa::Filtered<MyCollisions>::iterator const & collision,
142- TracksEl const & tracks)
189+ template <typename TrackType>
190+ int getElecSource (const TrackType& track, double & mpt, int & mpdg)
191+ {
192+ auto mcpart = track.mcParticle ();
193+ if (std::abs (mcpart.pdgCode ()) != kElectron ) {
194+ return NotElec;
195+ }
196+
197+ int motherPdg = -999 ;
198+ int grmotherPdg = -999 ;
199+ int ggrmotherPdg = -999 ; // mother, grand mother, grand grand mother pdg
200+ int motherPt = -999 .;
201+ int grmotherPt = -999 ;
202+ int ggrmotherPt = -999 .; // mother, grand mother, grand grand mother pt
203+
204+ auto partMother = mcpart.template mothers_as <aod::McParticles>(); // first mother particle of electron
205+ auto partMotherCopy = partMother; // copy of the first mother
206+ auto mctrack = partMother; // will change all the time
207+
208+ motherPt = partMother.front ().pt (); // first mother pt
209+ motherPdg = std::abs (partMother.front ().pdgCode ()); // first mother pdg
210+ mpt = motherPt; // copy of first mother pt
211+ mpdg = motherPdg; // copy of first mother pdg
212+
213+ // check if electron from charm hadrons
214+ if ((static_cast <int >(motherPdg / 100 .) % 10 ) == kCharm || (static_cast <int >(motherPdg / 1000 .) % 10 ) == kCharm ) {
215+
216+ // iterate until B hadron is found as an ancestor
217+ while (partMother.size ()) {
218+ mctrack = partMother.front ().template mothers_as <aod::McParticles>();
219+ if (mctrack.size ()) {
220+ auto const & grmothersIdsVec = mctrack.front ().mothersIds ();
221+
222+ if (grmothersIdsVec.empty ()) {
223+ return DirectCharm;
224+ } else {
225+ grmotherPt = mctrack.front ().pt ();
226+ grmotherPdg = std::abs (mctrack.front ().pdgCode ());
227+ if ((static_cast <int >(grmotherPdg / 100 .) % 10 ) == kBottom || (static_cast <int >(grmotherPdg / 1000 .) % 10 ) == kBottom ) {
228+ mpt = grmotherPt;
229+ mpdg = grmotherPdg;
230+ return BeautyCharm;
231+ }
232+ }
233+ }
234+ partMother = mctrack;
235+ }
236+ } else if ((static_cast <int >(motherPdg / 100 .) % 10 ) == kBottom || (static_cast <int >(motherPdg / 1000 .) % 10 ) == kBottom ) { // check if electron from beauty hadrons
237+ return DirectBeauty;
238+ } else if (motherPdg == kGamma ) { // check if electron from photon conversion
239+ mctrack = partMother.front ().template mothers_as <aod::McParticles>();
240+ if (mctrack.size ()) {
241+ auto const & grmothersIdsVec = mctrack.front ().mothersIds ();
242+ if (grmothersIdsVec.empty ()) {
243+ return DirectGamma;
244+ } else {
245+ grmotherPdg = std::abs (mctrack.front ().pdgCode ());
246+ mpdg = grmotherPdg;
247+ mpt = mctrack.front ().pt ();
248+
249+ partMother = mctrack;
250+ mctrack = partMother.front ().template mothers_as <aod::McParticles>();
251+ if (mctrack.size ()) {
252+ auto const & ggrmothersIdsVec = mctrack.front ().mothersIds ();
253+ if (ggrmothersIdsVec.empty ()) {
254+ if (grmotherPdg == kPi0 ) {
255+ return GammaPi0;
256+ } else if (grmotherPdg == kEta ) {
257+ return GammaEta;
258+ } else if (grmotherPdg == kOmega ) {
259+ return GammaOmega;
260+ } else if (grmotherPdg == kPhi ) {
261+ return GammaPhi;
262+ } else if (grmotherPdg == kEtaPrime ) {
263+ return GammaEtaPrime;
264+ } else if (grmotherPdg == kRho770_0 ) {
265+ return GammaRho0;
266+ } else {
267+ return Else;
268+ }
269+ } else {
270+ ggrmotherPdg = mctrack.front ().pdgCode ();
271+ ggrmotherPt = mctrack.front ().pt ();
272+ mpdg = ggrmotherPdg;
273+ mpt = ggrmotherPt;
274+ if (grmotherPdg == kPi0 ) {
275+ if (ggrmotherPdg == kK0Short ) {
276+ return GammaK0s;
277+ } else if (ggrmotherPdg == kK0Long ) {
278+ return GammaK0l;
279+ } else if (ggrmotherPdg == kKPlus ) {
280+ return GammaKe3;
281+ } else if (ggrmotherPdg == kLambda0 ) {
282+ return GammaLambda0;
283+ } else if (ggrmotherPdg == kSigmaPlus ) {
284+ return GammaSigma;
285+ } else {
286+ mpdg = grmotherPdg;
287+ mpt = grmotherPt;
288+ return GammaPi0;
289+ }
290+ } else if (grmotherPdg == kEta ) {
291+ mpdg = grmotherPdg;
292+ mpt = grmotherPt;
293+ return GammaEta;
294+ } else if (grmotherPdg == kOmega ) {
295+ mpdg = grmotherPdg;
296+ mpt = grmotherPt;
297+ return GammaOmega;
298+ } else if (grmotherPdg == kPhi ) {
299+ mpdg = grmotherPdg;
300+ mpt = grmotherPt;
301+ return GammaPhi;
302+ } else if (grmotherPdg == kEtaPrime ) {
303+ mpdg = grmotherPdg;
304+ mpt = grmotherPt;
305+ return GammaEtaPrime;
306+ } else if (grmotherPdg == kRho770_0 ) {
307+ mpdg = grmotherPdg;
308+ mpt = grmotherPt;
309+ return GammaRho0;
310+ } else {
311+ return Else;
312+ }
313+ }
314+ }
315+ }
316+ }
317+ } else { // check if electron from Dalitz decays
318+ mctrack = partMother.front ().template mothers_as <aod::McParticles>();
319+ if (mctrack.size ()) {
320+ auto const & grmothersIdsVec = mctrack.front ().mothersIds ();
321+ if (grmothersIdsVec.empty ()) {
322+ if (motherPdg == kPi0 ) {
323+ return Pi0;
324+ } else if (motherPdg == kEta ) {
325+ return Eta;
326+ } else if (motherPdg == kOmega ) {
327+ return Omega;
328+ } else if (motherPdg == kPhi ) {
329+ return Phi;
330+ } else if (motherPdg == kEtaPrime ) {
331+ return EtaPrime;
332+ } else if (motherPdg == kRho770_0 ) {
333+ return Rho0;
334+ } else if (motherPdg == kKPlus ) {
335+ return Ke3;
336+ } else if (motherPdg == kK0Long ) {
337+ return K0l;
338+ } else {
339+ return Else;
340+ }
341+ } else {
342+ if (motherPdg == kPi0 ) {
343+ grmotherPt = mctrack.front ().pt ();
344+ grmotherPdg = mctrack.front ().pdgCode ();
345+ mpt = grmotherPt;
346+ mpdg = grmotherPdg;
347+ if (grmotherPdg == kK0Short ) {
348+ return K0s;
349+ } else if (grmotherPdg == kK0Long ) {
350+ return K0l;
351+ } else if (grmotherPdg == kKPlus ) {
352+ return Ke3;
353+ } else if (grmotherPdg == kLambda0 ) {
354+ return Lambda0;
355+ } else if (grmotherPdg == kSigmaPlus ) {
356+ return Sigma;
357+ } else {
358+ mpt = motherPt;
359+ mpdg = motherPdg;
360+ return Pi0;
361+ }
362+ } else if (motherPdg == kEta ) {
363+ return Eta;
364+ } else if (motherPdg == kOmega ) {
365+ return Omega;
366+ } else if (motherPdg == kPhi ) {
367+ return Phi;
368+ } else if (motherPdg == kEtaPrime ) {
369+ return EtaPrime;
370+ } else if (motherPdg == kRho770_0 ) {
371+ return Rho0;
372+ } else if (motherPdg == kKPlus ) {
373+ return Ke3;
374+ } else if (motherPdg == kK0Long ) {
375+ return K0l;
376+ } else {
377+ return Else;
378+ }
379+ }
380+ }
381+ }
382+
383+ return Else;
384+ }
385+
386+ void processData (soa::Filtered<MyCollisions>::iterator const & collision,
387+ TracksEl const & tracks)
388+ {
389+ float flagAnalysedEvt = 0.5 ;
390+
391+ if (!collision.sel8 ()) {
392+ return ;
393+ }
394+
395+ if (collision.numContrib () < nContribMin) {
396+ return ;
397+ }
398+
399+ histos.fill (HIST (" VtxZ" ), collision.posZ ());
400+ histos.fill (HIST (" nEvents" ), flagAnalysedEvt);
401+
402+ for (const auto & track : tracks) {
403+
404+ if (!trackSel (track)) {
405+ continue ;
406+ }
407+
408+ histos.fill (HIST (" etaTrack" ), track.eta ());
409+ histos.fill (HIST (" ptTrack" ), track.pt ());
410+
411+ histos.fill (HIST (" tpcNClsTrack" ), track.tpcNClsCrossedRows ());
412+ histos.fill (HIST (" tpcFoundFindableTrack" ), track.tpcCrossedRowsOverFindableCls ());
413+ histos.fill (HIST (" tpcChi2Track" ), track.tpcChi2NCl ());
414+ histos.fill (HIST (" itsIBClsTrack" ), track.itsNClsInnerBarrel ());
415+ histos.fill (HIST (" dcaXYTrack" ), track.dcaXY ());
416+ histos.fill (HIST (" dcaZTrack" ), track.dcaZ ());
417+
418+ histos.fill (HIST (" tofNSigPt" ), track.pt (), track.tofNSigmaEl ());
419+ histos.fill (HIST (" tpcNSigPt" ), track.pt (), track.tpcNSigmaEl ());
420+
421+ if (std::abs (track.tofNSigmaEl ()) > tofNSigmaMax) {
422+ continue ;
423+ }
424+ histos.fill (HIST (" tofNSigPtQA" ), track.pt (), track.tofNSigmaEl ());
425+ histos.fill (HIST (" tpcNSigPtAfterTofCut" ), track.pt (), track.tpcNSigmaEl ());
426+
427+ if (track.tpcNSigmaEl () < tpcNSigmaMin || track.tpcNSigmaEl () > tpcNSigmaMax) {
428+ continue ;
429+ }
430+ histos.fill (HIST (" tpcNSigPtQA" ), track.pt (), track.tpcNSigmaEl ());
431+
432+ histos.fill (HIST (" dcaTrack" ), track.pt (), track.dcaXY ());
433+ }
434+ }
435+ PROCESS_SWITCH (HfTaskSingleElectron, processData, " For real data" , true );
436+
437+ void processMc (soa::Filtered<MyCollisions>::iterator const & collision,
438+ McTracksEl const & tracks,
439+ aod::McParticles const &)
143440 {
144- float flagEventFill = 0.5 ;
145441 float flagAnalysedEvt = 0.5 ;
146- histos.fill (HIST (" hEventCounter" ), flagEventFill);
147442
148443 if (!collision.sel8 ()) {
149444 return ;
150445 }
151- flagEventFill += 1 .;
152- histos.fill (HIST (" hEventCounter" ), flagEventFill);
153446
154447 if (collision.numContrib () < nContribMin) {
155448 return ;
156449 }
157- flagEventFill += 1 .;
158- histos.fill (HIST (" hEventCounter" ), flagEventFill);
159450
160451 histos.fill (HIST (" VtxZ" ), collision.posZ ());
161452 histos.fill (HIST (" nEvents" ), flagAnalysedEvt);
@@ -179,6 +470,30 @@ struct HfTaskSingleElectron {
179470 histos.fill (HIST (" tofNSigPt" ), track.pt (), track.tofNSigmaEl ());
180471 histos.fill (HIST (" tpcNSigPt" ), track.pt (), track.tpcNSigmaEl ());
181472
473+ int mpdg; // electron source pdg code
474+ double mpt; // electron source pt
475+ int source = getElecSource (track, mpt, mpdg);
476+
477+ if (source == DirectBeauty || source == BeautyCharm) {
478+ histos.fill (HIST (" hPdgB" ), mpdg);
479+ histos.fill (HIST (" dcaBeauty" ), track.pt (), track.dcaXY ());
480+ }
481+
482+ if (source == DirectCharm) {
483+ histos.fill (HIST (" hPdgC" ), mpdg);
484+ histos.fill (HIST (" dcaCharm" ), track.pt (), track.dcaXY ());
485+ }
486+
487+ if (source >= GammaPi0 && source <= GammaSigma) {
488+ histos.fill (HIST (" hPdgCo" ), mpdg);
489+ histos.fill (HIST (" dcaConv" ), track.pt (), track.dcaXY ());
490+ }
491+
492+ if (source >= Pi0 && source <= Sigma) {
493+ histos.fill (HIST (" hPdgDa" ), mpdg);
494+ histos.fill (HIST (" dcaDalitz" ), track.pt (), track.dcaXY ());
495+ }
496+
182497 if (std::abs (track.tofNSigmaEl ()) > tofNSigmaMax) {
183498 continue ;
184499 }
@@ -193,6 +508,7 @@ struct HfTaskSingleElectron {
193508 histos.fill (HIST (" dcaTrack" ), track.pt (), track.dcaXY ());
194509 }
195510 }
511+ PROCESS_SWITCH (HfTaskSingleElectron, processMc, " For real data" , false );
196512};
197513
198514WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
0 commit comments