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 **************************************************************************/
16 // Class for electrons from beauty study
17 // Counting electrons from beauty
18 // by DCA cuts, background subtraction
21 // Hongyan Yang <hongyan@physi.uni-heidelberg.de>
22 // Carlo Bombonati <Carlo.Bombonati@cern.ch>
29 #include <TParticle.h>
30 #include <TDatabasePDG.h>
31 #include "THnSparse.h"
33 #include "AliMCEvent.h"
34 #include "AliMCVertex.h"
35 #include "AliMCParticle.h"
38 #include "AliESDEvent.h"
39 #include "AliESDtrack.h"
41 #include "AliKFParticle.h"
42 #include "AliKFVertex.h"
44 #include "AliVertexerTracks.h"
47 #include "AliHFEdisplacedElectrons.h"
49 ClassImp(AliHFEdisplacedElectrons)
51 //__________________________________________________________
52 const Float_t AliHFEdisplacedElectrons::fgkDcaMinPtIntv[13] = {
54 // define DCA low limits for single electrons cut in each Pt bin
55 // preliminary numbers
56 // these numbers should be replaced by the best numbers determined by
57 // cut efficiency study: signal/background (not used right now)
72 //__________________________________________________________
73 const Float_t AliHFEdisplacedElectrons::fgkPtIntv[14] = {
75 // define pT bins for spectra of single electrons
77 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};
79 //__________________________________________________________
80 const Char_t *AliHFEdisplacedElectrons::fgkKineVar[3] = {
83 //__________________________________________________________
84 const Char_t *AliHFEdisplacedElectrons::fgkKineVarTitle[3] ={
85 "rapidity;y;dN/dy", "azimuthal;#phi;dN/d#phi", "transverse momentum;p_{T};dN/dp_{T}",
88 //__________________________________________________________
89 AliHFEdisplacedElectrons::AliHFEdisplacedElectrons():
92 , fMinNprimVtxContributor(1)
93 , fTHnSparseDcaMcEleInfo(NULL)
94 , fTHnSparseDcaEsdEleInfo(NULL)
95 , fTHnSparseDcaDataEleInfo(NULL)
99 // default constructor
104 //__________________________________________________________
105 AliHFEdisplacedElectrons::AliHFEdisplacedElectrons(const AliHFEdisplacedElectrons &ref):
107 , fDeDebugLevel(ref.fDeDebugLevel)
108 , fNclustersITS(ref.fNclustersITS)
109 , fMinNprimVtxContributor(ref.fMinNprimVtxContributor)
110 , fTHnSparseDcaMcEleInfo(ref.fTHnSparseDcaMcEleInfo)
111 , fTHnSparseDcaEsdEleInfo(ref.fTHnSparseDcaEsdEleInfo)
112 , fTHnSparseDcaDataEleInfo(ref.fTHnSparseDcaDataEleInfo)
113 , fDeOutputList(ref.fDeOutputList)
122 //__________________________________________________________
123 AliHFEdisplacedElectrons&AliHFEdisplacedElectrons::operator=(const AliHFEdisplacedElectrons &ref)
126 // Assignment operator
129 if(this == &ref) return *this;
130 AliHFEdisplacedElectrons::operator=(ref);
132 fDeDebugLevel = ref.fDeDebugLevel;
133 fNclustersITS = ref.fNclustersITS;
134 fMinNprimVtxContributor = ref.fMinNprimVtxContributor;
135 fTHnSparseDcaMcEleInfo = ref.fTHnSparseDcaMcEleInfo;
136 fTHnSparseDcaEsdEleInfo = ref.fTHnSparseDcaEsdEleInfo;
137 fTHnSparseDcaDataEleInfo = ref.fTHnSparseDcaDataEleInfo;
138 fDeOutputList = ref.fDeOutputList;
143 //__________________________________________________________
144 AliHFEdisplacedElectrons::~AliHFEdisplacedElectrons()
147 // default constructor
150 if(fTHnSparseDcaMcEleInfo)
151 delete fTHnSparseDcaMcEleInfo;
152 if(fTHnSparseDcaEsdEleInfo)
153 delete fTHnSparseDcaEsdEleInfo;
154 if(fTHnSparseDcaDataEleInfo)
155 delete fTHnSparseDcaDataEleInfo;
158 fDeOutputList->Clear();
159 delete fDeOutputList;
163 Printf("analysis done\n");
166 //__________________________________________________________
167 void AliHFEdisplacedElectrons::InitAnalysis(){
169 // init analysis (no intialization yet)
173 Printf("initialize analysis\n");
178 //__________________________________________________________
179 void AliHFEdisplacedElectrons::CreateOutputs(TList* const displacedList){
182 // create output fDeOutputList
186 // 8+? interested electron sources: others, photon conv, direct photon, pi0, eta, b, b->c, c + pion or missid, and missid pion
187 // 41 possible DCA cuts XY:
190 // 10 azimuthal angle phi bins
193 if(!displacedList) return;
195 fDeOutputList = displacedList;
196 fDeOutputList -> SetName("displacedElectrons");
199 Int_t nBinsEleSource = 10;
200 Double_t minEleSource = -1.5;
201 Double_t maxEleSource = 9.5;
202 Double_t *binLimEleSource = new Double_t[nBinsEleSource+1];
203 for(Int_t i=0; i<=nBinsEleSource; i++)
204 binLimEleSource[i] = minEleSource + i*(maxEleSource-minEleSource)/nBinsEleSource;
207 Int_t nBinsDcaXY = kNDcaMin-1; // 41 bins
208 Double_t minDcaXY = -20.5;
209 Double_t maxDcaXY = 20.5;
210 Double_t dcaXYBinWidth = (maxDcaXY-minDcaXY)/nBinsDcaXY;
211 Double_t *binLimDcaXY = new Double_t[nBinsDcaXY+1];
212 for(Int_t i=0; i<=nBinsDcaXY; i++)
213 binLimDcaXY[i] = minDcaXY + i*dcaXYBinWidth;
217 Int_t nBinsDcaZ = kNDcaMin/2; // 21 bins
218 Double_t minDcaZ = -10.5;
219 Double_t maxDcaZ = 10.5;
220 Double_t dcaZBinWidth = (maxDcaZ-minDcaZ)/nBinsDcaZ;
221 Double_t *binLimDcaZ = new Double_t[nBinsDcaZ+1];
222 for(Int_t i=0; i<=nBinsDcaZ; i++)
223 binLimDcaZ[i] = minDcaZ + i*dcaZBinWidth;
226 Int_t nBinsPt = kNPtIntv-1;
227 Double_t *binLimPt = new Double_t[nBinsPt+1];
228 for(Int_t i=0; i<=nBinsPt; i++)
229 binLimPt[i] = fgkPtIntv[i]; // variable bins
233 Double_t minRap = -1.0;
234 Double_t maxRap = 1.0;
235 Double_t *binLimRap = new Double_t[nBinsRap+1];
236 for(Int_t i=0; i<=nBinsRap; i++)
237 binLimRap[i] = minRap + i*(maxRap-minRap)/nBinsRap;
239 // azumuthal phi angle
242 Double_t maxPhi = 2*TMath::Pi();
243 Double_t *binLimPhi = new Double_t[nBinsPhi+1];
244 for(Int_t i=0; i<=nBinsPhi; i++)
245 binLimPhi[i] = minPhi + i*(maxPhi-minPhi)/nBinsPhi;
248 fTHnSparseDcaMcEleInfo = 0x0;
249 fTHnSparseDcaEsdEleInfo = 0x0;
250 fTHnSparseDcaDataEleInfo = 0x0;
252 // for MC only: MC electron ID
253 const Int_t nVarMc = 6;
254 Int_t iBinMc[nVarMc] = {nBinsEleSource, nBinsDcaXY, nBinsDcaZ, nBinsPt, nBinsRap, nBinsPhi};
256 fTHnSparseDcaMcEleInfo = new THnSparseF("dcaMcElectronInfo",
257 "MC electrons;electron source ID;mc dcaXY [50 #mum];mc dcaZ [100 #mum];mc pT [GeV/c];mc y [rapidity];mc #phi [rad];",
259 fTHnSparseDcaMcEleInfo->SetBinEdges(0, binLimEleSource); // electron source
260 fTHnSparseDcaMcEleInfo->SetBinEdges(1, binLimDcaXY); // dca xy cut
261 fTHnSparseDcaMcEleInfo->SetBinEdges(2, binLimDcaZ); // dca z cut
262 fTHnSparseDcaMcEleInfo->SetBinEdges(3, binLimPt); // pt
263 fTHnSparseDcaMcEleInfo->SetBinEdges(4, binLimRap); // rapidity
264 fTHnSparseDcaMcEleInfo->SetBinEdges(5, binLimPhi); // phi
265 fTHnSparseDcaMcEleInfo->Sumw2();
267 // for ESD with MC: HFE pid and MC pid
268 const Int_t nVarEsd = 7;
269 Int_t iBin[nVarEsd] = {nBinsEleSource,nBinsDcaXY, nBinsDcaZ, nBinsDcaXY, nBinsPt, nBinsRap, nBinsPhi};
271 fTHnSparseDcaEsdEleInfo
272 = new THnSparseF("dcaEsdElectronInfo",
273 "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];",
276 fTHnSparseDcaEsdEleInfo->SetBinEdges(0, binLimEleSource); // electron source
277 fTHnSparseDcaEsdEleInfo->SetBinEdges(1, binLimDcaXY); // dca xy without current track
278 fTHnSparseDcaEsdEleInfo->SetBinEdges(2, binLimDcaZ); // dca z without current track
279 fTHnSparseDcaEsdEleInfo->SetBinEdges(3, binLimDcaXY); // dca xy kf without current track
280 fTHnSparseDcaEsdEleInfo->SetBinEdges(4, binLimPt); // pt esd
281 fTHnSparseDcaEsdEleInfo->SetBinEdges(5, binLimRap); // rapidity esd
282 fTHnSparseDcaEsdEleInfo->SetBinEdges(6, binLimPhi); // phi esd
283 fTHnSparseDcaEsdEleInfo->Sumw2();
285 // for ESD data: HFE pid
286 const Int_t nVarData = 6;
287 Int_t iBinData[nVarData] = {nBinsDcaXY, nBinsDcaZ, nBinsDcaXY, nBinsPt, nBinsRap, nBinsPhi};
289 fTHnSparseDcaDataEleInfo
290 = new THnSparseF("dcaDataElectronInfo",
291 "Data electrons;dcaXY [50 #mum];dcaZ [100 #mum];dcaXYkf [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];",
293 fTHnSparseDcaDataEleInfo->SetBinEdges(0, binLimDcaXY); // dca xy cut w/o
294 fTHnSparseDcaDataEleInfo->SetBinEdges(1, binLimDcaZ); // dca z cut w/o
295 fTHnSparseDcaDataEleInfo->SetBinEdges(2, binLimDcaXY); // dca xy kf cut
296 fTHnSparseDcaDataEleInfo->SetBinEdges(3, binLimPt); // pt
297 fTHnSparseDcaDataEleInfo->SetBinEdges(4, binLimRap); // rapidity
298 fTHnSparseDcaDataEleInfo->SetBinEdges(5, binLimPhi); // phi
299 fTHnSparseDcaDataEleInfo->Sumw2();
301 fDeOutputList -> AddAt(fTHnSparseDcaMcEleInfo, kMcElectron);
302 fDeOutputList -> AddAt(fTHnSparseDcaEsdEleInfo, kEsdElectron);
303 fDeOutputList -> AddAt(fTHnSparseDcaDataEleInfo, kDataElectron);
305 AliInfo("THnSparse histograms are created\n");
306 fDeOutputList->Print();
311 //__________________________________________________________
312 void AliHFEdisplacedElectrons::FillMcOutput(AliESDEvent *const fESD, AliMCEvent* const fMC, AliMCParticle* const mctrack)
316 //0. after mc event cut
317 //1. after checking stack, mcpart etc are valid
319 //3. after event and track selection
321 AliStack *stack = fMC->Stack();
322 TParticle *part = mctrack->Particle();
324 // obtain impact parameters in xy and z
325 AliMCVertex *mcPrimVtx = (AliMCVertex *)fMC->GetPrimaryVertex();
327 mcPrimV[0] = mcPrimVtx->GetX();
328 mcPrimV[1] = mcPrimVtx->GetY();
329 mcPrimV[2] = mcPrimVtx->GetZ();
331 Double_t mcVtxXY = TMath::Abs(mcPrimV[0]*mcPrimV[0] + mcPrimV[1]*mcPrimV[1]);
333 Float_t vx = part->Vx(); // in cm
334 Float_t vy = part->Vy(); // in cm
335 Float_t vz = part->Vz(); // in cm
337 Float_t vxy = TMath::Sqrt(vx*vx+vy*vy);
339 Float_t mcpx = part->Px();
340 Float_t mcpy = part->Py();
341 Float_t mcpt = TMath::Sqrt(mcpx*mcpx+mcpy*mcpy);
342 Float_t mceta = part->Eta();
343 Float_t mcphi = part->Phi();
345 Int_t pdg = part->GetPdgCode();
348 if(pdg==kPDGelectron || pdg==-kPDGpion) charge = -1;
350 // calculate mcDca ------------------------------------------------------------------
351 const Float_t conv[2] = {1.783/1.6, 2.99792458};
352 Float_t magneticField = 0; // initialized as 5kG
353 magneticField = fESD->GetMagneticField(); // in kG
354 Float_t radiusMc = mcpt/(TMath::Abs(magneticField)/10.)*conv[0]*conv[1]; // pt in GeV/c, magnetic field in Tesla, radius in meter
357 radius = TMath::Abs(radiusMc);
358 Float_t nx = mcpx/mcpt;
359 Float_t ny = mcpy/mcpt;
360 Double_t dxy = vxy - mcVtxXY; // in cm
361 Double_t dvx = vx - mcPrimV[0]; // in cm
362 Double_t dvy = vy - mcPrimV[1]; // in cm
363 Float_t mcDcaXYm = (radius - TMath::Sqrt(dxy*dxy/100./100. + radius*radius + 2*radius*charge*(dvx*ny-dvy*nx)/100.)) ; // in meters
364 Double_t mcDca[2] = {mcDcaXYm*100, vz}; // in cm
365 Double_t mcDcaXY = mcDca[0]*1.0e4; // conv dca in cm to dca in micron
366 Double_t mcDcaZ = mcDca[1]*1.0e4;
368 const Int_t nvarMC=6;
369 Double_t var[nvarMC];
372 if(TMath::Abs(pdg)==kPDGelectron) {
374 Int_t eleLabel = mctrack->GetLabel();
375 Int_t sourcePdg = ElectronFromSource(stack, eleLabel);
377 if(sourcePdg==kPDGgamma){ // check direct photon or not
378 if(ElePhotonDirect(stack, eleLabel)!=-1)
379 var[0] = kEleDirectPhotonConv;
381 var[0] = kElePhotonConv;
382 if(fDeDebugLevel>=10)
383 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
384 } // photon or direct photon -> e
386 if(sourcePdg==kPDGpi0){
388 if(fDeDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
391 if(sourcePdg==kPDGeta){
393 if(fDeDebugLevel>=10)
394 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
397 if(TMath::Abs(sourcePdg%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
398 TMath::Abs(sourcePdg)/1000==kPDGbeauty ||
399 TMath::Abs(sourcePdg)/100==kPDGbeauty ||
400 TMath::Abs(sourcePdg)==kPDGbeauty){
402 if(fDeDebugLevel>=10)
403 printf("beauty======electron %d is from %d with id %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
404 } // direct beauty -> e
405 if(TMath::Abs(sourcePdg%10000)/100==kPDGcharm || // for special intermediate meson states: like 1004**
406 TMath::Abs(sourcePdg)/1000==kPDGcharm ||
407 TMath::Abs(sourcePdg)/100==kPDGcharm ||
408 TMath::Abs(sourcePdg)==kPDGcharm){
410 // electron from b->c->e
411 // electron from c->e
412 if(ElectronFromCharm(stack, eleLabel)!=-1){
413 var[0] = ElectronFromCharm(stack, eleLabel);
414 if(fDeDebugLevel>=10)
415 printf("charm----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
417 } // charm electrons: b->c->e or c->e
419 if(fDeDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
420 } // electron source endif
423 if(TMath::Abs(pdg)==kPDGpion)
426 if(TMath::Abs(mcDcaXY)<1000) var[1] = Int_t(mcDcaXY)/50; // larger than 1mm should go to the last bin
428 var[1] = ((mcDcaXY>0)?1:-1)*20;
430 if(TMath::Abs(mcDcaZ)<1000) var[2] = Int_t(mcDcaZ)/100;
432 var[2] = ((mcDcaZ>0)?1:-1)*10;
435 var[4] = mceta; // eta
436 var[5] = mcphi; // phi
438 (dynamic_cast<THnSparseF *>(fDeOutputList->At(kMcElectron)))->Fill(var);
443 //__________________________________________________________
444 void AliHFEdisplacedElectrons::FillEsdOutput(AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack, AliStack * const stack)
446 // after esd event selection, esd track cuts, and hfe pid
447 // this is the case for ESD tracks, with MC information
449 AliESDtrack *track = esdTrack;
450 Double_t pt = track->Pt();
451 Double_t eta = track->Eta();
452 Double_t phi = track->Phi();
454 Int_t eleLabel = track->GetLabel();
455 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return;
457 TParticle *particle = stack->Particle(eleLabel);
458 if(!particle) return;
460 // obtain impact parameters in xy and z
462 Float_t magneticField = 5; // initialized as 5kG
463 magneticField = fESDEvent->GetMagneticField(); // in kG
464 Double_t beampiperadius=3.;
465 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
468 const Int_t nvarESD = 7;
469 Double_t var[nvarESD];
472 Int_t sourcePdg = -1;
474 if(TMath::Abs(particle->GetPdgCode())!=kPDGelectron)
475 if(TMath::Abs(particle->GetPdgCode())!=kPDGpion)
478 var[0] = kEleMissIDpion;
481 sourcePdg = ElectronFromSource(stack, eleLabel);
483 if(sourcePdg==kPDGgamma){ // check direct photon or not
484 if(ElePhotonDirect(stack, eleLabel)!=-1)
485 var[0] = kEleDirectPhotonConv;
487 var[0] = kElePhotonConv;
488 if(fDeDebugLevel>=10)
489 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
490 } // photon or direct photon -> e
492 if(sourcePdg==kPDGpi0){
494 if(fDeDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
497 if(sourcePdg==kPDGeta){
499 if(fDeDebugLevel>=10)
500 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
503 if(TMath::Abs(sourcePdg%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
504 TMath::Abs(sourcePdg)/1000==kPDGbeauty ||
505 TMath::Abs(sourcePdg)/100==kPDGbeauty ||
506 TMath::Abs(sourcePdg)==kPDGbeauty){
508 if(fDeDebugLevel>=10)
509 printf("beauty======electron %d is from %d with id %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
510 } // direct beauty -> e
511 if(TMath::Abs(sourcePdg%10000)/100==kPDGcharm || // for special intermediate meson states: like 1004**
512 TMath::Abs(sourcePdg)/1000==kPDGcharm ||
513 TMath::Abs(sourcePdg)/100==kPDGcharm ||
514 TMath::Abs(sourcePdg)==kPDGcharm){
516 // electron from b->c->e
517 // electron from c->e
518 if(ElectronFromCharm(stack, eleLabel)!=-1){
519 var[0] = ElectronFromCharm(stack, eleLabel);
520 if(fDeDebugLevel>=10)
521 printf("charm----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
523 } // charm electrons: b->c->e or c->e
526 // excluding current track
527 // ---- beginning --- method from Andrea D 28.05.2010
528 AliVertexerTracks *vertexer = new AliVertexerTracks(magneticField);
529 vertexer->SetITSMode();
530 vertexer->SetMinClusters(fNclustersITS);
532 skipped[0] = (Int_t)track->GetID();
533 vertexer->SetSkipTracks(1,skipped);
534 AliESDVertex *vtxESDSkip = (AliESDVertex*)vertexer->FindPrimaryVertex(fESDEvent);
535 delete vertexer; vertexer = NULL;
536 if(vtxESDSkip->GetNContributors()<fMinNprimVtxContributor) return;
537 // -- ending --- method from Andrea D 28.05.2010
539 Double_t dz[2]; // error of dca in cm
541 if(!track->PropagateToDCA(vtxESDSkip,magneticField, beampiperadius, dz, covardz)) return; // protection
543 Double_t dcaXY = dz[0]*1.0e4; // conv dca in cm to dca in micron
544 Double_t dcaZ = dz[1]*1.0e4;
546 if(fDeDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
548 if(TMath::Abs(dcaXY)<1000) var[1] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
550 var[1] = ((dcaXY>0)?1:-1)*20;
552 if(TMath::Abs(dcaZ)<1000) var[2] = Int_t(dcaZ)/100;
554 var[2] = ((dcaZ>0)?1:-1)*10;
556 // calculate dca using AliKFParticle class------------------------------------------------------------------
558 Int_t trkID = track->GetID();
559 AliKFParticle::SetField(magneticField);
560 AliKFParticle kfParticle(*track, particle->GetPdgCode());
561 // prepare kfprimary vertex
562 AliKFVertex kfESDprimary;
563 // Reconstruct Primary Vertex (with ESD tracks)
564 Int_t n=primVtx->GetNIndices();
565 if (n>0 && primVtx->GetStatus()){
566 kfESDprimary = AliKFVertex(*primVtx);
567 UShort_t *priIndex = primVtx->GetIndices();
568 for (Int_t i=0;i<n;i++){
569 Int_t idx = Int_t(priIndex[i]);
571 kfESDprimary -= kfParticle;
572 kfDcaXY = kfParticle.GetDistanceFromVertexXY(kfESDprimary)*1e4;
573 } // remove current track from this calculation
574 } // loop over all primary vertex contributors
578 if(TMath::Abs(kfDcaXY)<1000)
579 var[3] = Int_t(kfDcaXY)/50;
581 var[3] = (kfDcaXY>0?1:-1)*20;
587 (dynamic_cast<THnSparseF *>(fDeOutputList->At(kEsdElectron)))->Fill(var);
591 //__________________________________________________________
592 void AliHFEdisplacedElectrons::FillDataOutput(AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack)
595 // this is pure data, without MC information at all
596 // fill output: with HFE pid selection of electrons after all track quality cuts
598 if(!esdTrack) return;
599 AliESDtrack *track = esdTrack;
601 Double_t pt = track->Pt();
602 Double_t eta = track->Eta();
603 Double_t phi = track->Phi();
605 // obtain impact parameters in xy and y
606 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
608 Float_t magneticField = 5; // initialized as 5kG
609 magneticField = fESDEvent->GetMagneticField(); // in kG
610 Double_t beampiperadius=3.;
613 const Int_t nvarData = 6;
614 Double_t varData[nvarData];
617 // excluding current track
620 //------ beginning --- method from Andrea D 28.05.2010
621 AliVertexerTracks *vertexer = new AliVertexerTracks(fESDEvent->GetMagneticField());
622 vertexer->SetITSMode();
623 vertexer->SetMinClusters(fNclustersITS);
625 skipped[0] = (Int_t)track->GetID();
626 vertexer->SetSkipTracks(1,skipped);
627 AliESDVertex *vtxESDSkip = (AliESDVertex*)vertexer->FindPrimaryVertex(fESDEvent);
628 delete vertexer; vertexer = NULL;
629 if(vtxESDSkip->GetNContributors()<fMinNprimVtxContributor) return;
630 //------ ending --- method from Andrea D 28.05.2010
632 Double_t dz[2]; // error of dca in cm
635 if(!track->PropagateToDCA(vtxESDSkip,magneticField, beampiperadius, dz, covardz)) return; // protection
637 Double_t dcaXY = dz[0]*1.0e4; // conv dca in cm to dca in micron
638 Double_t dcaZ = dz[1]*1.0e4;
640 if(TMath::Abs(dcaXY)<1000) varData[0] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
642 varData[0] = (dcaXY>0?1:-1)*20;
643 if(TMath::Abs(dcaZ)<1000) varData[1] = Int_t(dcaZ)/100;
645 varData[1] = (dcaZ>0?1:-1)*10;
648 // calculate dca using AliKFParticle class------------------------------------------------------------------
650 Int_t trkID = track->GetID();
651 AliKFParticle::SetField(magneticField);
652 AliKFParticle kfParticle(*track, -11*track->Charge());
653 // prepare kfprimary vertex
654 AliKFVertex kfESDprimary;
655 // Reconstruct Primary Vertex (with ESD tracks)
656 Int_t n=primVtx->GetNIndices();
657 if (n>0 && primVtx->GetStatus()){
658 kfESDprimary = AliKFVertex(*primVtx);
659 UShort_t *priIndex = primVtx->GetIndices();
660 for (Int_t i=0;i<n;i++){
661 Int_t idx = Int_t(priIndex[i]);
663 kfESDprimary -= kfParticle;
664 kfDcaXY = kfParticle.GetDistanceFromVertexXY(kfESDprimary)*1e4;
665 } // remove current track from this calculation
666 } // loop over all primary vertex contributors
668 if(TMath::Abs(kfDcaXY)<1000)
669 varData[2] = Int_t(kfDcaXY)/50;
671 varData[2] = ((kfDcaXY)>0?1:-1)*20;
674 varData[3] = pt; // pt
675 varData[4] = eta; //eta
676 varData[5] = phi; // phi
678 (dynamic_cast<THnSparseF *>(fDeOutputList->At(kDataElectron)))->Fill(varData);
682 //__________________________________________________________
683 Int_t AliHFEdisplacedElectrons::ElectronFromSource(AliStack * const stack, Int_t label) const
687 // return electron source label via electron label
690 // kEleSource is supposed to be either photon conv, direct photon conv, pi0, eta, beauty --> 0, 1, 2, 3, 4
692 Int_t eleLabel = label;
694 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return -1;
696 TParticle *particle = stack->Particle(eleLabel);
697 if(!particle) return -1;
699 Int_t motherLabel = particle->GetFirstMother();
700 if(motherLabel<0 || motherLabel>stack->GetNtrack()) return -1;
701 TParticle *motherPart = stack->Particle(motherLabel);
702 if(!motherPart) return -1;
704 Int_t pdgCode = TMath::Abs(motherPart->GetPdgCode());
706 if(pdgCode==kPDGelectron) {
707 if(fDeDebugLevel>=10) printf("particle label: %d...(motherLabel=%d : motherPdg=%d) grandmother's pdg code was returned...%d \n",
708 label, motherLabel, pdgCode, ElectronFromSource(stack, motherLabel));
709 return ElectronFromSource(stack, motherLabel);
716 //__________________________________________________________
717 Int_t AliHFEdisplacedElectrons::ElectronFromCharm(AliStack * const stack, Int_t label) const
720 // separate electron: kEleC from c->eX, kEleBC from b->c->eX
723 Int_t motherLabel = label;
724 TParticle *motherParticle = stack->Particle(motherLabel); // mother part
725 if(!motherParticle) return -1;
726 Int_t gMotherLabel = motherParticle->GetFirstMother(); // grand mother
727 if(gMotherLabel<0 || gMotherLabel>stack->GetNtrack()) return -1;
729 TParticle *gMotherPart = stack->Particle(gMotherLabel);
730 if(!gMotherPart) return -1;
732 Int_t pdgCode = gMotherPart->GetPdgCode();
733 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
734 TMath::Abs(pdgCode)/1000==kPDGbeauty || TMath::Abs(pdgCode)/100==kPDGbeauty || TMath::Abs(pdgCode)==kPDGbeauty) {
735 if(fDeDebugLevel>=10) printf("this electron label %d is from mother %d, and finally from %d\n", label, ElectronFromSource(stack, label), pdgCode);
737 } // for sure it is from BC
740 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
741 TMath::Abs(pdgCode)/1000==kPDGcharm ||
742 TMath::Abs(pdgCode)/100==kPDGcharm ||
743 TMath::Abs(pdgCode)==kPDGcharm){
745 if(CharmFromBeauty(stack, gMotherLabel)!=-1)
757 //__________________________________________________________
758 Int_t AliHFEdisplacedElectrons::CharmFromBeauty(AliStack * const stack, Int_t hfLabel) const
762 // check if charm meson/hadron is from beauty decay
763 // -1, not from beauty
764 // return the label of the mother of this charm hadron
767 Int_t charmLabel = hfLabel;
769 // AliStack *stack = fMC->Stack();
770 if(charmLabel<0 || charmLabel>stack->GetNtrack()) return -1;
771 TParticle *particle = stack->Particle(charmLabel);
772 if(!particle) return -1;
774 Int_t motherCharmLabel = particle->GetFirstMother();
775 if(motherCharmLabel<0 || motherCharmLabel>stack->GetNtrack()) return -1;
777 TParticle *motherCharmPart = stack->Particle(motherCharmLabel);
778 if(!motherCharmPart) return -1;
780 Int_t pdgCode = motherCharmPart->GetPdgCode();
782 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
783 TMath::Abs(pdgCode)/1000==kPDGbeauty ||
784 TMath::Abs(pdgCode)/100==kPDGbeauty ||
785 TMath::Abs(pdgCode)==kPDGbeauty)
786 return motherCharmLabel;
788 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
789 TMath::Abs(pdgCode)/1000==kPDGcharm ||
790 TMath::Abs(pdgCode)/100==kPDGcharm)
791 return CharmFromBeauty(stack, motherCharmLabel); // loop over to see if charm is from beauty -- if yes, return the label of mother of the charm
797 //__________________________________________________________
798 Int_t AliHFEdisplacedElectrons::ElePhotonDirect(AliStack * const stack, Int_t label) const
801 // electron is from photon, and check if this photon is direct
804 Int_t eleLabel = label;
806 TParticle *particle = stack->Particle(eleLabel);
807 if(particle->GetFirstMother()<0 || particle->GetFirstMother()>stack->GetNtrack())
810 TParticle *photonPart = stack->Particle(particle->GetFirstMother());
813 Int_t motherPhotonLabel = photonPart->GetFirstMother();
814 if(motherPhotonLabel<0 || motherPhotonLabel>stack->GetNtrack())
817 TParticle *motherPhotonPart = stack->Particle(motherPhotonLabel);
818 if(!motherPhotonPart)
821 Int_t pdgMotherPhoton = motherPhotonPart->GetPdgCode();
822 if(TMath::Abs(pdgMotherPhoton)<=10 || TMath::Abs(pdgMotherPhoton)==21)
831 //__________________________________________________________
832 Int_t AliHFEdisplacedElectrons::GetMCpid(AliStack* const stack, Int_t partLabel) const
839 Int_t label = partLabel;
840 // AliStack* stack = fMC->Stack();
841 if((label < 0) || (label >= stack->GetNtrack())) return -1;
844 TParticle * particle = stack->Particle(label);
845 if(!particle) return -1;
846 Int_t pdg = particle->GetPdgCode();
852 //__________________________________________________________
853 Int_t AliHFEdisplacedElectrons::GetMotherLabel(AliStack *const stack, Int_t eleLabel) const
856 // Simply label of mother
860 Int_t label = eleLabel;
861 // AliStack* stack = fMC->Stack();
862 if((label < 0) || (label >= stack->GetNtrack())) return -1;
865 TParticle * particle = stack->Particle(label);
866 if(!particle) return -1;
868 return particle->GetFirstMother();
873 //__________________________________________________________
874 Float_t AliHFEdisplacedElectrons::GetRapidity(TParticle *part) const
878 Float_t rapidity = -999;
879 if((part->Energy() - part->Pz())*(part->Energy() + part->Pz())>0)
880 rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));
886 //__________________________________________________________
887 Float_t AliHFEdisplacedElectrons::GetTrackRapidity(AliESDtrack * const track) const
889 // return rapidity of electron
891 Float_t px = track->Px();
892 Float_t py = track->Py();
893 Float_t pz = track->Pz();
895 // electron mass 0.00051099906 GeV/c2
896 TParticlePDG* electron = TDatabasePDG::Instance()->GetParticle(kPDGelectron);
897 Double_t mass = electron->Mass();
899 Float_t en = TMath::Sqrt(px*px + py*py + pz*pz + mass*mass);
901 Float_t rapidity = -999;
902 if((en - pz)*(en + pz)>0)
903 rapidity = 0.5*(TMath::Log((en - pz)*(en + pz)));