1 /*************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
19 // Class for electrons from beauty study
20 // Counting electrons from beauty
21 // by DCA cuts, background subtraction
24 // Hongyan Yang <hongyan@physi.uni-heidelberg.de>
25 // Carlo Bombonati <Carlo.Bombonati@cern.ch>
32 #include <TParticle.h>
33 #include <TDatabasePDG.h>
34 #include "THnSparse.h"
36 #include "AliMCEvent.h"
37 #include "AliMCVertex.h"
38 #include "AliMCParticle.h"
41 #include "AliESDEvent.h"
42 #include "AliESDtrack.h"
44 #include "AliKFParticle.h"
45 #include "AliKFVertex.h"
47 #include "AliVertexerTracks.h"
50 #include "AliHFEdisplacedElectrons.h"
52 ClassImp(AliHFEdisplacedElectrons)
54 //__________________________________________________________
55 const Float_t AliHFEdisplacedElectrons::fgkDcaMinPtIntv[13] = {
57 // define DCA low limits for single electrons cut in each Pt bin
58 // preliminary numbers
59 // these numbers should be replaced by the best numbers determined by
60 // cut efficiency study: signal/background (not used right now)
75 //__________________________________________________________
76 const Float_t AliHFEdisplacedElectrons::fgkPtIntv[14] = {
78 // define pT bins for spectra of single electrons
80 0.0,0.5,1.0,1.5,2.0,2.5,3.0,4.0,5.0,7.0,9.0,12.0,16.0,20.0};
82 //__________________________________________________________
83 const Char_t *AliHFEdisplacedElectrons::fgkKineVar[3] = {
86 //__________________________________________________________
87 const Char_t *AliHFEdisplacedElectrons::fgkKineVarTitle[3] ={
88 "rapidity;y;dN/dy", "azimuthal;#phi;dN/d#phi", "transverse momentum;p_{T};dN/dp_{T}",
91 //__________________________________________________________
92 AliHFEdisplacedElectrons::AliHFEdisplacedElectrons():
95 , fMinNprimVtxContributor(1)
96 , fTHnSparseDcaMcEleInfo(NULL)
97 , fTHnSparseDcaEsdEleInfo(NULL)
98 , fTHnSparseDcaDataEleInfo(NULL)
102 // default constructor
107 //__________________________________________________________
108 AliHFEdisplacedElectrons::AliHFEdisplacedElectrons(const AliHFEdisplacedElectrons &ref):
110 , fDeDebugLevel(ref.fDeDebugLevel)
111 , fNclustersITS(ref.fNclustersITS)
112 , fMinNprimVtxContributor(ref.fMinNprimVtxContributor)
113 , fTHnSparseDcaMcEleInfo(ref.fTHnSparseDcaMcEleInfo)
114 , fTHnSparseDcaEsdEleInfo(ref.fTHnSparseDcaEsdEleInfo)
115 , fTHnSparseDcaDataEleInfo(ref.fTHnSparseDcaDataEleInfo)
116 , fDeOutputList(ref.fDeOutputList)
125 //__________________________________________________________
126 AliHFEdisplacedElectrons&AliHFEdisplacedElectrons::operator=(const AliHFEdisplacedElectrons &ref)
129 // Assignment operator
132 if(this == &ref) return *this;
133 AliHFEdisplacedElectrons::operator=(ref);
135 fDeDebugLevel = ref.fDeDebugLevel;
136 fNclustersITS = ref.fNclustersITS;
137 fMinNprimVtxContributor = ref.fMinNprimVtxContributor;
138 fTHnSparseDcaMcEleInfo = ref.fTHnSparseDcaMcEleInfo;
139 fTHnSparseDcaEsdEleInfo = ref.fTHnSparseDcaEsdEleInfo;
140 fTHnSparseDcaDataEleInfo = ref.fTHnSparseDcaDataEleInfo;
141 fDeOutputList = ref.fDeOutputList;
146 //__________________________________________________________
147 AliHFEdisplacedElectrons::~AliHFEdisplacedElectrons()
150 // default constructor
153 if(fTHnSparseDcaMcEleInfo)
154 delete fTHnSparseDcaMcEleInfo;
155 if(fTHnSparseDcaEsdEleInfo)
156 delete fTHnSparseDcaEsdEleInfo;
157 if(fTHnSparseDcaDataEleInfo)
158 delete fTHnSparseDcaDataEleInfo;
161 fDeOutputList->Clear();
162 delete fDeOutputList;
166 Printf("analysis done\n");
169 //__________________________________________________________
170 void AliHFEdisplacedElectrons::InitAnalysis(){
172 // init analysis (no intialization yet)
176 Printf("initialize analysis\n");
181 //__________________________________________________________
182 void AliHFEdisplacedElectrons::CreateOutputs(TList* const displacedList){
185 // create output fDeOutputList
189 // 8+? interested electron sources: others, photon conv, direct photon, pi0, eta, b, b->c, c + pion or missid, and missid pion
190 // 41 possible DCA cuts XY:
193 // 10 azimuthal angle phi bins
196 if(!displacedList) return;
198 fDeOutputList = displacedList;
199 fDeOutputList -> SetName("displacedElectrons");
202 Int_t nBinsEleSource = 10;
203 Double_t minEleSource = -1.5;
204 Double_t maxEleSource = 8.5;
205 Double_t *binLimEleSource = new Double_t[nBinsEleSource+1];
206 for(Int_t i=0; i<=nBinsEleSource; i++)
207 binLimEleSource[i] = minEleSource + i*(maxEleSource-minEleSource)/nBinsEleSource;
210 Int_t nBinsDcaXY = kNDcaMin-1; // 41 bins
211 Double_t minDcaXY = -20.5;
212 Double_t maxDcaXY = 20.5;
213 Double_t dcaXYBinWidth = (maxDcaXY-minDcaXY)/nBinsDcaXY;
214 Double_t *binLimDcaXY = new Double_t[nBinsDcaXY+1];
215 for(Int_t i=0; i<=nBinsDcaXY; i++)
216 binLimDcaXY[i] = minDcaXY + i*dcaXYBinWidth;
220 Int_t nBinsDcaZ = kNDcaMin/2; // 21 bins
221 Double_t minDcaZ = -10.5;
222 Double_t maxDcaZ = 10.5;
223 Double_t dcaZBinWidth = (maxDcaZ-minDcaZ)/nBinsDcaZ;
224 Double_t *binLimDcaZ = new Double_t[nBinsDcaZ+1];
225 for(Int_t i=0; i<=nBinsDcaZ; i++)
226 binLimDcaZ[i] = minDcaZ + i*dcaZBinWidth;
229 Int_t nBinsPt = kNPtIntv-1;
230 Double_t *binLimPt = new Double_t[nBinsPt+1];
231 for(Int_t i=0; i<=nBinsPt; i++)
232 binLimPt[i] = fgkPtIntv[i]; // variable bins
236 Double_t minRap = -1.0;
237 Double_t maxRap = 1.0;
238 Double_t *binLimRap = new Double_t[nBinsRap+1];
239 for(Int_t i=0; i<=nBinsRap; i++)
240 binLimRap[i] = minRap + i*(maxRap-minRap)/nBinsRap;
242 // azumuthal phi angle
245 Double_t maxPhi = 2*TMath::Pi();
246 Double_t *binLimPhi = new Double_t[nBinsPhi+1];
247 for(Int_t i=0; i<=nBinsPhi; i++)
248 binLimPhi[i] = minPhi + i*(maxPhi-minPhi)/nBinsPhi;
254 Double_t *binLimR = new Double_t[nBinsR+1];
255 for(Int_t i=0; i<=nBinsR; i++)
256 binLimR[i] = minR + i*(maxR-minR)/nBinsR;
259 Int_t nBinsStat = 11;
260 Double_t minStat = 0;
261 Double_t maxStat = 11;
262 Double_t *binLimStat = new Double_t[nBinsStat+1];
263 for(Int_t i=0; i<=nBinsStat; i++)
264 binLimStat[i] = minStat + i*(maxStat-minStat)/nBinsStat;
266 fTHnSparseDcaMcEleInfo = 0x0;
267 fTHnSparseDcaEsdEleInfo = 0x0;
268 fTHnSparseDcaDataEleInfo = 0x0;
270 // for MC only: MC electron ID
271 const Int_t nVarMc = 8;
272 Int_t iBinMc[nVarMc] = {nBinsEleSource, nBinsDcaXY, nBinsDcaZ, nBinsPt, nBinsRap, nBinsPhi, nBinsR, nBinsStat};
274 fTHnSparseDcaMcEleInfo = new THnSparseF("dcaMcElectronInfo",
275 "MC electrons;electron source ID;mc dcaXY [50 #mum];mc dcaZ [100 #mum];mc pT [GeV/c];mc y [rapidity];mc #phi [rad];mc R [cm];Status Code",
278 fTHnSparseDcaMcEleInfo->SetBinEdges(0, binLimEleSource); // electron source
279 fTHnSparseDcaMcEleInfo->SetBinEdges(1, binLimDcaXY); // dca xy cut
280 fTHnSparseDcaMcEleInfo->SetBinEdges(2, binLimDcaZ); // dca z cut
281 fTHnSparseDcaMcEleInfo->SetBinEdges(3, binLimPt); // pt
282 fTHnSparseDcaMcEleInfo->SetBinEdges(4, binLimRap); // rapidity
283 fTHnSparseDcaMcEleInfo->SetBinEdges(5, binLimPhi); // phi
284 fTHnSparseDcaMcEleInfo->SetBinEdges(6, binLimR);
285 fTHnSparseDcaMcEleInfo->SetBinEdges(7, binLimStat);
286 fTHnSparseDcaMcEleInfo->Sumw2();
288 // for ESD with MC: HFE pid and MC pid
289 const Int_t nVarEsd = 9;
290 Int_t iBin[nVarEsd] = {nBinsEleSource,nBinsDcaXY, nBinsDcaZ, nBinsDcaXY, nBinsPt, nBinsRap, nBinsPhi, nBinsR, nBinsStat};
292 fTHnSparseDcaEsdEleInfo
293 = new THnSparseF("dcaEsdElectronInfo",
294 "ESD electrons;electron source ID;esd dcaXY [50 #mum];esd dcaZ [100 #mum];esd dcaXY KF [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];R [cm];Status Code",
297 fTHnSparseDcaEsdEleInfo->SetBinEdges(0, binLimEleSource); // electron source
298 fTHnSparseDcaEsdEleInfo->SetBinEdges(1, binLimDcaXY); // dca xy without current track
299 fTHnSparseDcaEsdEleInfo->SetBinEdges(2, binLimDcaZ); // dca z without current track
300 fTHnSparseDcaEsdEleInfo->SetBinEdges(3, binLimDcaXY); // dca xy kf without current track
301 fTHnSparseDcaEsdEleInfo->SetBinEdges(4, binLimPt); // pt esd
302 fTHnSparseDcaEsdEleInfo->SetBinEdges(5, binLimRap); // rapidity esd
303 fTHnSparseDcaEsdEleInfo->SetBinEdges(6, binLimPhi); // phi esd
304 fTHnSparseDcaEsdEleInfo->SetBinEdges(7, binLimR);
305 fTHnSparseDcaEsdEleInfo->SetBinEdges(8, binLimStat);
306 fTHnSparseDcaEsdEleInfo->Sumw2();
309 // for ESD data: HFE pid
310 const Int_t nVarData = 6;
311 Int_t iBinData[nVarData] = {nBinsDcaXY, nBinsDcaZ, nBinsDcaXY, nBinsPt, nBinsRap, nBinsPhi};
313 fTHnSparseDcaDataEleInfo
314 = new THnSparseF("dcaDataElectronInfo",
315 "Data electrons;dcaXY [50 #mum];dcaZ [100 #mum];dcaXYkf [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];",
317 fTHnSparseDcaDataEleInfo->SetBinEdges(0, binLimDcaXY); // dca xy cut w/o
318 fTHnSparseDcaDataEleInfo->SetBinEdges(1, binLimDcaZ); // dca z cut w/o
319 fTHnSparseDcaDataEleInfo->SetBinEdges(2, binLimDcaXY); // dca xy kf cut
320 fTHnSparseDcaDataEleInfo->SetBinEdges(3, binLimPt); // pt
321 fTHnSparseDcaDataEleInfo->SetBinEdges(4, binLimRap); // rapidity
322 fTHnSparseDcaDataEleInfo->SetBinEdges(5, binLimPhi); // phi
323 fTHnSparseDcaDataEleInfo->Sumw2();
325 fDeOutputList -> AddAt(fTHnSparseDcaMcEleInfo, kMcElectron);
326 fDeOutputList -> AddAt(fTHnSparseDcaEsdEleInfo, kEsdElectron);
327 fDeOutputList -> AddAt(fTHnSparseDcaDataEleInfo, kDataElectron);
329 AliInfo("THnSparse histograms are created\n");
330 fDeOutputList->Print();
335 //__________________________________________________________
336 void AliHFEdisplacedElectrons::FillMcOutput(AliESDEvent *const fESD, AliMCEvent* const fMC, AliMCParticle* const mctrack)
340 //0. after mc event cut
341 //1. after checking stack, mcpart etc are valid
343 //3. after event and track selection
345 AliStack *stack = fMC->Stack();
346 TParticle *part = mctrack->Particle();
348 // obtain impact parameters in xy and z
349 AliMCVertex *mcPrimVtx = (AliMCVertex *)fMC->GetPrimaryVertex();
351 mcPrimV[0] = mcPrimVtx->GetX();
352 mcPrimV[1] = mcPrimVtx->GetY();
353 mcPrimV[2] = mcPrimVtx->GetZ();
355 Double_t mcVtxXY = TMath::Abs(mcPrimV[0]*mcPrimV[0] + mcPrimV[1]*mcPrimV[1]);
357 Float_t vx = part->Vx(); // in cm
358 Float_t vy = part->Vy(); // in cm
359 Float_t vz = part->Vz(); // in cm
361 Float_t vxy = TMath::Sqrt(vx*vx+vy*vy);
363 Float_t mcpx = part->Px();
364 Float_t mcpy = part->Py();
365 Float_t mcpt = TMath::Sqrt(mcpx*mcpx+mcpy*mcpy);
366 Float_t mceta = part->Eta();
367 Float_t mcphi = part->Phi();
370 Double_t mcR = part->R();
371 Int_t mcStatus = part->GetStatusCode();
374 Int_t pdg = part->GetPdgCode();
377 if(pdg==kPDGelectron || pdg==-kPDGpion) charge = -1;
379 // calculate mcDca ------------------------------------------------------------------
380 const Float_t conv[2] = {1.783/1.6, 2.99792458};
381 Float_t magneticField = 0; // initialized as 5kG
382 magneticField = fESD->GetMagneticField(); // in kG
383 Float_t radiusMc = mcpt/(TMath::Abs(magneticField)/10.)*conv[0]*conv[1]; // pt in GeV/c, magnetic field in Tesla, radius in meter
386 radius = TMath::Abs(radiusMc);
387 Float_t nx = mcpx/mcpt;
388 Float_t ny = mcpy/mcpt;
389 Double_t dxy = vxy - mcVtxXY; // in cm
390 Double_t dvx = vx - mcPrimV[0]; // in cm
391 Double_t dvy = vy - mcPrimV[1]; // in cm
392 Float_t mcDcaXYm = (radius - TMath::Sqrt(dxy*dxy/100./100. + radius*radius + 2*radius*charge*(dvx*ny-dvy*nx)/100.)) ; // in meters
393 Double_t mcDca[2] = {mcDcaXYm*100, vz}; // in cm
394 Double_t mcDcaXY = mcDca[0]*1.0e4; // conv dca in cm to dca in micron
395 Double_t mcDcaZ = mcDca[1]*1.0e4;
397 const Int_t nvarMC=8;
398 Double_t var[nvarMC];
401 if(TMath::Abs(pdg)==kPDGelectron) {
403 Int_t eleLabel = mctrack->GetLabel();
404 Int_t sourcePdg = ElectronFromSource(stack, eleLabel);
406 if(sourcePdg==kPDGgamma){ // check direct photon or not
407 if(ElePhotonDirect(stack, eleLabel)!=-1)
408 var[0] = kEleDirectPhotonConv;
410 var[0] = kElePhotonConv;
411 if(fDeDebugLevel>=10)
412 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
413 } // photon or direct photon -> e
415 if(sourcePdg==kPDGpi0){
417 if(fDeDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
420 if(sourcePdg==kPDGeta){
422 if(fDeDebugLevel>=10)
423 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
426 if(TMath::Abs(sourcePdg%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
427 TMath::Abs(sourcePdg)/1000==kPDGbeauty ||
428 TMath::Abs(sourcePdg)/100==kPDGbeauty ||
429 TMath::Abs(sourcePdg)==kPDGbeauty){
431 if(fDeDebugLevel>=10)
432 printf("beauty======electron %d is from %d with id %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
433 } // direct beauty -> e
434 if(TMath::Abs(sourcePdg%10000)/100==kPDGcharm || // for special intermediate meson states: like 1004**
435 TMath::Abs(sourcePdg)/1000==kPDGcharm ||
436 TMath::Abs(sourcePdg)/100==kPDGcharm ||
437 TMath::Abs(sourcePdg)==kPDGcharm){
439 // electron from b->c->e
440 // electron from c->e
441 if(ElectronFromCharm(stack, eleLabel)!=-1){
442 var[0] = ElectronFromCharm(stack, eleLabel);
443 if(fDeDebugLevel>=10)
444 printf("charm----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
446 } // charm electrons: b->c->e or c->e
448 if(fDeDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
449 } // electron source endif
452 if(TMath::Abs(pdg)==kPDGpion)
455 if(TMath::Abs(mcDcaXY)<1000) var[1] = Int_t(mcDcaXY)/50; // larger than 1mm should go to the last bin
457 var[1] = ((mcDcaXY>0)?1:-1)*20;
459 if(TMath::Abs(mcDcaZ)<1000) var[2] = Int_t(mcDcaZ)/100;
461 var[2] = ((mcDcaZ>0)?1:-1)*10;
464 var[4] = mceta; // eta
465 var[5] = mcphi; // phi
466 var[6] = mcR; // production radius
467 var[7] = mcStatus; // internal status
470 (static_cast<THnSparseF *>(fDeOutputList->At(kMcElectron)))->Fill(var);
475 //__________________________________________________________
476 void AliHFEdisplacedElectrons::FillEsdOutput(AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack, AliStack * const stack)
478 // after esd event selection, esd track cuts, and hfe pid
479 // this is the case for ESD tracks, with MC information
481 AliESDtrack *track = esdTrack;
482 Double_t pt = track->Pt();
483 Double_t eta = track->Eta();
484 Double_t phi = track->Phi();
486 Int_t eleLabel = track->GetLabel();
487 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return;
489 TParticle *particle = stack->Particle(eleLabel);
490 if(!particle) return;
493 Double_t mcR = particle->R();
494 Int_t mcStatus = particle->GetStatusCode();
497 // obtain impact parameters in xy and z
498 Float_t magneticField = 5; // initialized as 5kG
499 magneticField = fESDEvent->GetMagneticField(); // in kG
500 Double_t beampiperadius=3.;
501 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
504 const Int_t nvarESD = 9;
505 Double_t var[nvarESD];
508 Int_t sourcePdg = -1;
510 if(TMath::Abs(particle->GetPdgCode())==kPDGelectron){
512 sourcePdg = ElectronFromSource(stack, eleLabel);
514 if(sourcePdg==kPDGgamma){ // check direct photon or not
515 if(ElePhotonDirect(stack, eleLabel)!=-1)
516 var[0] = kEleDirectPhotonConv;
518 var[0] = kElePhotonConv;
519 if(fDeDebugLevel>=10)
520 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
521 } else if(sourcePdg==kPDGpi0){ // check dalitz
523 if(fDeDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
524 } else if(sourcePdg==kPDGeta){ // check eta
526 if(fDeDebugLevel>=10)
527 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
528 } else if(IsB(sourcePdg)) var[0] = kEleB; // check beauty
529 else if(IsC(sourcePdg)) var[0] = CheckCharm(stack,eleLabel); // check charm
531 } else if(TMath::Abs(particle->GetPdgCode())==kPDGpion) var[0] = kEleMissIDpion;
532 else var[0] = kEleMissID;
536 // excluding current track
537 // ---- beginning --- method from Andrea D 28.05.2010
538 AliVertexerTracks *vertexer = new AliVertexerTracks(magneticField);
539 vertexer->SetITSMode();
540 vertexer->SetMinClusters(fNclustersITS);
542 skipped[0] = (Int_t)track->GetID();
543 vertexer->SetSkipTracks(1,skipped);
544 AliESDVertex *vtxESDSkip = (AliESDVertex*)vertexer->FindPrimaryVertex(fESDEvent);
545 delete vertexer; vertexer = NULL;
546 if(vtxESDSkip->GetNContributors()<fMinNprimVtxContributor) return;
547 // -- ending --- method from Andrea D 28.05.2010
549 Double_t dz[2]; // error of dca in cm
551 if(!track->PropagateToDCA(vtxESDSkip,magneticField, beampiperadius, dz, covardz)) return; // protection
553 Double_t dcaXY = dz[0]*1.0e4; // conv dca in cm to dca in micron
554 Double_t dcaZ = dz[1]*1.0e4;
556 if(fDeDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
558 if(TMath::Abs(dcaXY)<1000) var[1] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
560 var[1] = ((dcaXY>0)?1:-1)*20;
562 if(TMath::Abs(dcaZ)<1000) var[2] = Int_t(dcaZ)/100;
564 var[2] = ((dcaZ>0)?1:-1)*10;
566 // calculate dca using AliKFParticle class------------------------------------------------------------------
568 Int_t trkID = track->GetID();
569 AliKFParticle::SetField(magneticField);
570 AliKFParticle kfParticle(*track, particle->GetPdgCode());
571 // prepare kfprimary vertex
572 AliKFVertex kfESDprimary;
573 // Reconstruct Primary Vertex (with ESD tracks)
574 Int_t n=primVtx->GetNIndices();
575 if (n>0 && primVtx->GetStatus()){
576 kfESDprimary = AliKFVertex(*primVtx);
577 UShort_t *priIndex = primVtx->GetIndices();
578 for (Int_t i=0;i<n;i++){
579 Int_t idx = Int_t(priIndex[i]);
581 kfESDprimary -= kfParticle;
582 kfDcaXY = kfParticle.GetDistanceFromVertexXY(kfESDprimary)*1e4;
583 } // remove current track from this calculation
584 } // loop over all primary vertex contributors
588 if(TMath::Abs(kfDcaXY)<1000)
589 var[3] = Int_t(kfDcaXY)/50;
591 var[3] = (kfDcaXY>0?1:-1)*20;
599 (static_cast<THnSparseF *>(fDeOutputList->At(kEsdElectron)))->Fill(var);
603 //__________________________________________________________
604 void AliHFEdisplacedElectrons::FillDataOutput(AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack)
607 // this is pure data, without MC information at all
608 // fill output: with HFE pid selection of electrons after all track quality cuts
610 if(!esdTrack) return;
611 AliESDtrack *track = esdTrack;
613 Double_t pt = track->Pt();
614 Double_t eta = track->Eta();
615 Double_t phi = track->Phi();
617 // obtain impact parameters in xy and y
618 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
620 Float_t magneticField = 5; // initialized as 5kG
621 magneticField = fESDEvent->GetMagneticField(); // in kG
622 Double_t beampiperadius=3.;
625 const Int_t nvarData = 6;
626 Double_t varData[nvarData];
629 // excluding current track
632 //------ beginning --- method from Andrea D 28.05.2010
633 AliVertexerTracks *vertexer = new AliVertexerTracks(fESDEvent->GetMagneticField());
634 vertexer->SetITSMode();
635 vertexer->SetMinClusters(fNclustersITS);
637 skipped[0] = (Int_t)track->GetID();
638 vertexer->SetSkipTracks(1,skipped);
639 AliESDVertex *vtxESDSkip = (AliESDVertex*)vertexer->FindPrimaryVertex(fESDEvent);
640 delete vertexer; vertexer = NULL;
641 if(vtxESDSkip->GetNContributors()<fMinNprimVtxContributor) return;
642 //------ ending --- method from Andrea D 28.05.2010
644 Double_t dz[2]; // error of dca in cm
647 if(!track->PropagateToDCA(vtxESDSkip,magneticField, beampiperadius, dz, covardz)) return; // protection
649 Double_t dcaXY = dz[0]*1.0e4; // conv dca in cm to dca in micron
650 Double_t dcaZ = dz[1]*1.0e4;
652 if(TMath::Abs(dcaXY)<1000) varData[0] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
654 varData[0] = (dcaXY>0?1:-1)*20;
655 if(TMath::Abs(dcaZ)<1000) varData[1] = Int_t(dcaZ)/100;
657 varData[1] = (dcaZ>0?1:-1)*10;
660 // calculate dca using AliKFParticle class------------------------------------------------------------------
662 Int_t trkID = track->GetID();
663 AliKFParticle::SetField(magneticField);
664 AliKFParticle kfParticle(*track, -11*track->Charge());
665 // prepare kfprimary vertex
666 AliKFVertex kfESDprimary;
667 // Reconstruct Primary Vertex (with ESD tracks)
668 Int_t n=primVtx->GetNIndices();
669 if (n>0 && primVtx->GetStatus()){
670 kfESDprimary = AliKFVertex(*primVtx);
671 UShort_t *priIndex = primVtx->GetIndices();
672 for (Int_t i=0;i<n;i++){
673 Int_t idx = Int_t(priIndex[i]);
675 kfESDprimary -= kfParticle;
676 kfDcaXY = kfParticle.GetDistanceFromVertexXY(kfESDprimary)*1e4;
677 } // remove current track from this calculation
678 } // loop over all primary vertex contributors
680 if(TMath::Abs(kfDcaXY)<1000)
681 varData[2] = Int_t(kfDcaXY)/50;
683 varData[2] = ((kfDcaXY)>0?1:-1)*20;
686 varData[3] = pt; // pt
687 varData[4] = eta; //eta
688 varData[5] = phi; // phi
690 (static_cast<THnSparseF *>(fDeOutputList->At(kDataElectron)))->Fill(varData);
694 //__________________________________________________________
695 Int_t AliHFEdisplacedElectrons::ElectronFromSource(AliStack * const stack, Int_t label) const
699 // return electron source label via electron label
702 // kEleSource is supposed to be either photon conv, direct photon conv, pi0, eta, beauty --> 0, 1, 2, 3, 4
704 Int_t eleLabel = label;
706 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return -1;
708 TParticle *particle = stack->Particle(eleLabel);
709 if(!particle) return -1;
711 Int_t motherLabel = particle->GetFirstMother();
712 if(motherLabel<0 || motherLabel>stack->GetNtrack()) return -1;
713 TParticle *motherPart = stack->Particle(motherLabel);
714 if(!motherPart) return -1;
716 Int_t pdgCode = TMath::Abs(motherPart->GetPdgCode());
718 if(pdgCode==kPDGelectron) {
719 if(fDeDebugLevel>=10) printf("particle label: %d...(motherLabel=%d : motherPdg=%d) grandmother's pdg code was returned...%d \n",
720 label, motherLabel, pdgCode, ElectronFromSource(stack, motherLabel));
721 return ElectronFromSource(stack, motherLabel);
728 //__________________________________________________________
729 Int_t AliHFEdisplacedElectrons::ElectronFromCharm(AliStack * const stack, Int_t label) const
732 // separate electron: kEleC from c->eX, kEleBC from b->c->eX
735 Int_t motherLabel = label;
736 TParticle *motherParticle = stack->Particle(motherLabel); // mother part
737 if(!motherParticle) return -1;
738 Int_t gMotherLabel = motherParticle->GetFirstMother(); // grand mother
739 if(gMotherLabel<0 || gMotherLabel>stack->GetNtrack()) return -1;
741 TParticle *gMotherPart = stack->Particle(gMotherLabel);
742 if(!gMotherPart) return -1;
744 Int_t pdgCode = gMotherPart->GetPdgCode();
745 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
746 TMath::Abs(pdgCode)/1000==kPDGbeauty || TMath::Abs(pdgCode)/100==kPDGbeauty || TMath::Abs(pdgCode)==kPDGbeauty) {
747 if(fDeDebugLevel>=10) printf("this electron label %d is from mother %d, and finally from %d\n", label, ElectronFromSource(stack, label), pdgCode);
749 } // for sure it is from BC
752 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
753 TMath::Abs(pdgCode)/1000==kPDGcharm ||
754 TMath::Abs(pdgCode)/100==kPDGcharm ||
755 TMath::Abs(pdgCode)==kPDGcharm){
757 if(CharmFromBeauty(stack, gMotherLabel)!=-1) return kEleBC;
767 //__________________________________________________________
768 Int_t AliHFEdisplacedElectrons::CharmFromBeauty(AliStack * const stack, Int_t hfLabel) const
772 // check if charm meson/hadron is from beauty decay
773 // -1, not from beauty
774 // return the label of the mother of this charm hadron
777 Int_t charmLabel = hfLabel;
779 // AliStack *stack = fMC->Stack();
780 if(charmLabel<0 || charmLabel>stack->GetNtrack()) return -1;
781 TParticle *particle = stack->Particle(charmLabel);
782 if(!particle) return -1;
784 Int_t motherCharmLabel = particle->GetFirstMother();
785 if(motherCharmLabel<0 || motherCharmLabel>stack->GetNtrack()) return -1;
787 TParticle *motherCharmPart = stack->Particle(motherCharmLabel);
788 if(!motherCharmPart) return -1;
790 Int_t pdgCode = motherCharmPart->GetPdgCode();
792 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
793 TMath::Abs(pdgCode)/1000==kPDGbeauty ||
794 TMath::Abs(pdgCode)/100==kPDGbeauty ||
795 TMath::Abs(pdgCode)==kPDGbeauty)
796 return motherCharmLabel;
798 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
799 TMath::Abs(pdgCode)/1000==kPDGcharm ||
800 TMath::Abs(pdgCode)/100==kPDGcharm)
801 return CharmFromBeauty(stack, motherCharmLabel); // loop over to see if charm is from beauty -- if yes, return the label of mother of the charm
807 //__________________________________________________________
808 Int_t AliHFEdisplacedElectrons::ElePhotonDirect(AliStack * const stack, Int_t label) const
811 // electron is from photon, and check if this photon is direct
814 Int_t eleLabel = label;
816 TParticle *particle = stack->Particle(eleLabel);
817 if(particle->GetFirstMother()<0 || particle->GetFirstMother()>stack->GetNtrack())
820 TParticle *photonPart = stack->Particle(particle->GetFirstMother());
823 Int_t motherPhotonLabel = photonPart->GetFirstMother();
824 if(motherPhotonLabel<0 || motherPhotonLabel>stack->GetNtrack())
827 TParticle *motherPhotonPart = stack->Particle(motherPhotonLabel);
828 if(!motherPhotonPart)
831 Int_t pdgMotherPhoton = motherPhotonPart->GetPdgCode();
832 if(TMath::Abs(pdgMotherPhoton)<=10 || TMath::Abs(pdgMotherPhoton)==21)
841 //__________________________________________________________
842 Int_t AliHFEdisplacedElectrons::GetMCpid(AliStack* const stack, Int_t partLabel) const
849 Int_t label = partLabel;
850 // AliStack* stack = fMC->Stack();
851 if((label < 0) || (label >= stack->GetNtrack())) return -1;
854 TParticle * particle = stack->Particle(label);
855 if(!particle) return -1;
856 Int_t pdg = particle->GetPdgCode();
862 //__________________________________________________________
863 Int_t AliHFEdisplacedElectrons::GetMotherLabel(AliStack *const stack, Int_t eleLabel) const
866 // Simply label of mother
870 Int_t label = eleLabel;
871 // AliStack* stack = fMC->Stack();
872 if((label < 0) || (label >= stack->GetNtrack())) return -1;
875 TParticle * particle = stack->Particle(label);
876 if(!particle) return -1;
878 return particle->GetFirstMother();
883 //__________________________________________________________
884 Float_t AliHFEdisplacedElectrons::GetRapidity(TParticle *part) const
888 Float_t rapidity = -999;
889 if((part->Energy() - part->Pz())*(part->Energy() + part->Pz())>0)
890 rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));
896 //__________________________________________________________
897 Float_t AliHFEdisplacedElectrons::GetTrackRapidity(AliESDtrack * const track) const
899 // return rapidity of electron
901 Float_t px = track->Px();
902 Float_t py = track->Py();
903 Float_t pz = track->Pz();
905 // electron mass 0.00051099906 GeV/c2
906 TParticlePDG* electron = TDatabasePDG::Instance()->GetParticle(kPDGelectron);
907 Double_t mass = electron->Mass();
909 Float_t en = TMath::Sqrt(px*px + py*py + pz*pz + mass*mass);
911 Float_t rapidity = -999;
912 if((en - pz)*(en + pz)>0)
913 rapidity = 0.5*(TMath::Log((en - pz)*(en + pz)));
918 //__________________________________________________________
919 Int_t AliHFEdisplacedElectrons::CheckCharm(AliStack * const stack, Int_t eleLabel)
921 // checks the genealogy of the ele from charm for a beauty
922 // this method needs the stack and the label of the electron
923 // warning: it assumes that the ele comes from a charm
925 TParticle *particle = stack->Particle(eleLabel);
926 Int_t label = particle->GetFirstMother();
928 while(label>0 && label<(stack->GetNtrack())){
929 particle = stack->Particle(label);
930 if(IsB(TMath::Abs(particle->GetPdgCode()))) return kEleBC;
931 label = particle->GetFirstMother();
937 //__________________________________________________________
938 Bool_t AliHFEdisplacedElectrons::IsB(Int_t pdg) const
940 // check if the pdg is that of a beauty particle
942 if((TMath::Abs(pdg)%10000)/100==kPDGbeauty ||
943 TMath::Abs(pdg)/1000==kPDGbeauty ||
944 TMath::Abs(pdg)/100==kPDGbeauty ||
945 TMath::Abs(pdg)==kPDGbeauty) return kTRUE;
949 //__________________________________________________________
950 Bool_t AliHFEdisplacedElectrons::IsC(Int_t pdg) const
952 // check if the pdg is that of a charmed particle
954 if((TMath::Abs(pdg)%10000)/100==kPDGcharm ||
955 TMath::Abs(pdg)/1000==kPDGcharm ||
956 TMath::Abs(pdg)/100==kPDGcharm ||
957 TMath::Abs(pdg)==kPDGcharm) return kTRUE;