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 = 8.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;
251 Double_t *binLimR = new Double_t[nBinsR+1];
252 for(Int_t i=0; i<=nBinsR; i++)
253 binLimR[i] = minR + i*(maxR-minR)/nBinsR;
256 Int_t nBinsStat = 11;
257 Double_t minStat = 0;
258 Double_t maxStat = 11;
259 Double_t *binLimStat = new Double_t[nBinsStat+1];
260 for(Int_t i=0; i<=nBinsStat; i++)
261 binLimStat[i] = minStat + i*(maxStat-minStat)/nBinsStat;
263 fTHnSparseDcaMcEleInfo = 0x0;
264 fTHnSparseDcaEsdEleInfo = 0x0;
265 fTHnSparseDcaDataEleInfo = 0x0;
267 // for MC only: MC electron ID
268 const Int_t nVarMc = 8;
269 Int_t iBinMc[nVarMc] = {nBinsEleSource, nBinsDcaXY, nBinsDcaZ, nBinsPt, nBinsRap, nBinsPhi, nBinsR, nBinsStat};
271 fTHnSparseDcaMcEleInfo = new THnSparseF("dcaMcElectronInfo",
272 "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",
275 fTHnSparseDcaMcEleInfo->SetBinEdges(0, binLimEleSource); // electron source
276 fTHnSparseDcaMcEleInfo->SetBinEdges(1, binLimDcaXY); // dca xy cut
277 fTHnSparseDcaMcEleInfo->SetBinEdges(2, binLimDcaZ); // dca z cut
278 fTHnSparseDcaMcEleInfo->SetBinEdges(3, binLimPt); // pt
279 fTHnSparseDcaMcEleInfo->SetBinEdges(4, binLimRap); // rapidity
280 fTHnSparseDcaMcEleInfo->SetBinEdges(5, binLimPhi); // phi
281 fTHnSparseDcaMcEleInfo->SetBinEdges(6, binLimR);
282 fTHnSparseDcaMcEleInfo->SetBinEdges(7, binLimStat);
283 fTHnSparseDcaMcEleInfo->Sumw2();
285 // for ESD with MC: HFE pid and MC pid
286 const Int_t nVarEsd = 9;
287 Int_t iBin[nVarEsd] = {nBinsEleSource,nBinsDcaXY, nBinsDcaZ, nBinsDcaXY, nBinsPt, nBinsRap, nBinsPhi, nBinsR, nBinsStat};
289 fTHnSparseDcaEsdEleInfo
290 = new THnSparseF("dcaEsdElectronInfo",
291 "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",
294 fTHnSparseDcaEsdEleInfo->SetBinEdges(0, binLimEleSource); // electron source
295 fTHnSparseDcaEsdEleInfo->SetBinEdges(1, binLimDcaXY); // dca xy without current track
296 fTHnSparseDcaEsdEleInfo->SetBinEdges(2, binLimDcaZ); // dca z without current track
297 fTHnSparseDcaEsdEleInfo->SetBinEdges(3, binLimDcaXY); // dca xy kf without current track
298 fTHnSparseDcaEsdEleInfo->SetBinEdges(4, binLimPt); // pt esd
299 fTHnSparseDcaEsdEleInfo->SetBinEdges(5, binLimRap); // rapidity esd
300 fTHnSparseDcaEsdEleInfo->SetBinEdges(6, binLimPhi); // phi esd
301 fTHnSparseDcaEsdEleInfo->SetBinEdges(7, binLimR);
302 fTHnSparseDcaEsdEleInfo->SetBinEdges(8, binLimStat);
303 fTHnSparseDcaEsdEleInfo->Sumw2();
306 // for ESD data: HFE pid
307 const Int_t nVarData = 6;
308 Int_t iBinData[nVarData] = {nBinsDcaXY, nBinsDcaZ, nBinsDcaXY, nBinsPt, nBinsRap, nBinsPhi};
310 fTHnSparseDcaDataEleInfo
311 = new THnSparseF("dcaDataElectronInfo",
312 "Data electrons;dcaXY [50 #mum];dcaZ [100 #mum];dcaXYkf [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];",
314 fTHnSparseDcaDataEleInfo->SetBinEdges(0, binLimDcaXY); // dca xy cut w/o
315 fTHnSparseDcaDataEleInfo->SetBinEdges(1, binLimDcaZ); // dca z cut w/o
316 fTHnSparseDcaDataEleInfo->SetBinEdges(2, binLimDcaXY); // dca xy kf cut
317 fTHnSparseDcaDataEleInfo->SetBinEdges(3, binLimPt); // pt
318 fTHnSparseDcaDataEleInfo->SetBinEdges(4, binLimRap); // rapidity
319 fTHnSparseDcaDataEleInfo->SetBinEdges(5, binLimPhi); // phi
320 fTHnSparseDcaDataEleInfo->Sumw2();
322 fDeOutputList -> AddAt(fTHnSparseDcaMcEleInfo, kMcElectron);
323 fDeOutputList -> AddAt(fTHnSparseDcaEsdEleInfo, kEsdElectron);
324 fDeOutputList -> AddAt(fTHnSparseDcaDataEleInfo, kDataElectron);
326 AliInfo("THnSparse histograms are created\n");
327 fDeOutputList->Print();
332 //__________________________________________________________
333 void AliHFEdisplacedElectrons::FillMcOutput(const AliESDEvent *const fESD, AliMCEvent* const fMC, const AliMCParticle* const mctrack)
337 //0. after mc event cut
338 //1. after checking stack, mcpart etc are valid
340 //3. after event and track selection
342 AliStack *stack = fMC->Stack();
343 TParticle *part = mctrack->Particle();
345 // obtain impact parameters in xy and z
346 AliMCVertex *mcPrimVtx = (AliMCVertex *)fMC->GetPrimaryVertex();
348 mcPrimV[0] = mcPrimVtx->GetX();
349 mcPrimV[1] = mcPrimVtx->GetY();
350 mcPrimV[2] = mcPrimVtx->GetZ();
352 Double_t mcVtxXY = TMath::Abs(mcPrimV[0]*mcPrimV[0] + mcPrimV[1]*mcPrimV[1]);
354 Float_t vx = part->Vx(); // in cm
355 Float_t vy = part->Vy(); // in cm
356 Float_t vz = part->Vz(); // in cm
358 Float_t vxy = TMath::Sqrt(vx*vx+vy*vy);
360 Float_t mcpx = part->Px();
361 Float_t mcpy = part->Py();
362 Float_t mcpt = TMath::Sqrt(mcpx*mcpx+mcpy*mcpy);
363 Float_t mceta = part->Eta();
364 Float_t mcphi = part->Phi();
367 Double_t mcR = part->R();
368 Int_t mcStatus = part->GetStatusCode();
371 Int_t pdg = part->GetPdgCode();
374 if(pdg==kPDGelectron || pdg==-kPDGpion) charge = -1;
376 // calculate mcDca ------------------------------------------------------------------
377 const Float_t conv[2] = {1.783/1.6, 2.99792458};
378 Float_t magneticField = 0; // initialized as 5kG
379 magneticField = fESD->GetMagneticField(); // in kG
380 Float_t radiusMc = mcpt/(TMath::Abs(magneticField)/10.)*conv[0]*conv[1]; // pt in GeV/c, magnetic field in Tesla, radius in meter
383 radius = TMath::Abs(radiusMc);
384 Float_t nx = mcpx/mcpt;
385 Float_t ny = mcpy/mcpt;
386 Double_t dxy = vxy - mcVtxXY; // in cm
387 Double_t dvx = vx - mcPrimV[0]; // in cm
388 Double_t dvy = vy - mcPrimV[1]; // in cm
389 Float_t mcDcaXYm = (radius - TMath::Sqrt(dxy*dxy/100./100. + radius*radius + 2*radius*charge*(dvx*ny-dvy*nx)/100.)) ; // in meters
390 Double_t mcDca[2] = {mcDcaXYm*100, vz}; // in cm
391 Double_t mcDcaXY = mcDca[0]*1.0e4; // conv dca in cm to dca in micron
392 Double_t mcDcaZ = mcDca[1]*1.0e4;
394 const Int_t nvarMC=8;
395 Double_t var[nvarMC];
398 if(TMath::Abs(pdg)==kPDGelectron) {
400 Int_t eleLabel = mctrack->GetLabel();
401 Int_t sourcePdg = ElectronFromSource(stack, eleLabel);
403 if(sourcePdg==kPDGgamma){ // check direct photon or not
404 if(ElePhotonDirect(stack, eleLabel)!=-1)
405 var[0] = kEleDirectPhotonConv;
407 var[0] = kElePhotonConv;
408 if(fDeDebugLevel>=10)
409 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
410 } // photon or direct photon -> e
412 if(sourcePdg==kPDGpi0){
414 if(fDeDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
417 if(sourcePdg==kPDGeta){
419 if(fDeDebugLevel>=10)
420 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
423 if(TMath::Abs(sourcePdg%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
424 TMath::Abs(sourcePdg)/1000==kPDGbeauty ||
425 TMath::Abs(sourcePdg)/100==kPDGbeauty ||
426 TMath::Abs(sourcePdg)==kPDGbeauty){
428 if(fDeDebugLevel>=10)
429 printf("beauty======electron %d is from %d with id %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
430 } // direct beauty -> e
431 if(TMath::Abs(sourcePdg%10000)/100==kPDGcharm || // for special intermediate meson states: like 1004**
432 TMath::Abs(sourcePdg)/1000==kPDGcharm ||
433 TMath::Abs(sourcePdg)/100==kPDGcharm ||
434 TMath::Abs(sourcePdg)==kPDGcharm){
436 // electron from b->c->e
437 // electron from c->e
438 if(ElectronFromCharm(stack, eleLabel)!=-1){
439 var[0] = ElectronFromCharm(stack, eleLabel);
440 if(fDeDebugLevel>=10)
441 printf("charm----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
443 } // charm electrons: b->c->e or c->e
445 if(fDeDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
446 } // electron source endif
449 if(TMath::Abs(pdg)==kPDGpion)
452 if(TMath::Abs(mcDcaXY)<1000) var[1] = Int_t(mcDcaXY)/50; // larger than 1mm should go to the last bin
454 var[1] = ((mcDcaXY>0)?1:-1)*20;
456 if(TMath::Abs(mcDcaZ)<1000) var[2] = Int_t(mcDcaZ)/100;
458 var[2] = ((mcDcaZ>0)?1:-1)*10;
461 var[4] = mceta; // eta
462 var[5] = mcphi; // phi
463 var[6] = mcR; // production radius
464 var[7] = mcStatus; // internal status
467 (static_cast<THnSparseF *>(fDeOutputList->At(kMcElectron)))->Fill(var);
472 //__________________________________________________________
473 void AliHFEdisplacedElectrons::FillEsdOutput(const AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack, AliStack * const stack)
475 // after esd event selection, esd track cuts, and hfe pid
476 // this is the case for ESD tracks, with MC information
478 AliESDtrack *track = esdTrack;
479 Double_t pt = track->Pt();
480 Double_t eta = track->Eta();
481 Double_t phi = track->Phi();
483 Int_t eleLabel = track->GetLabel();
484 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return;
486 TParticle *particle = stack->Particle(eleLabel);
487 if(!particle) return;
490 Double_t mcR = particle->R();
491 Int_t mcStatus = particle->GetStatusCode();
494 // obtain impact parameters in xy and z
495 Float_t magneticField = 5; // initialized as 5kG
496 magneticField = fESDEvent->GetMagneticField(); // in kG
497 Double_t beampiperadius=3.;
498 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
501 const Int_t nvarESD = 9;
502 Double_t var[nvarESD];
505 Int_t sourcePdg = -1;
507 if(TMath::Abs(particle->GetPdgCode())==kPDGelectron){
509 sourcePdg = ElectronFromSource(stack, eleLabel);
511 if(sourcePdg==kPDGgamma){ // check direct photon or not
512 if(ElePhotonDirect(stack, eleLabel)!=-1)
513 var[0] = kEleDirectPhotonConv;
515 var[0] = kElePhotonConv;
516 if(fDeDebugLevel>=10)
517 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
518 } else if(sourcePdg==kPDGpi0){ // check dalitz
520 if(fDeDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
521 } else if(sourcePdg==kPDGeta){ // check eta
523 if(fDeDebugLevel>=10)
524 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
525 } else if(IsB(sourcePdg)) var[0] = kEleB; // check beauty
526 else if(IsC(sourcePdg)) var[0] = CheckCharm(stack,eleLabel); // check charm
528 } else if(TMath::Abs(particle->GetPdgCode())==kPDGpion) var[0] = kEleMissIDpion;
529 else var[0] = kEleMissID;
533 // excluding current track
534 // ---- beginning --- method from Andrea D 28.05.2010
535 AliVertexerTracks *vertexer = new AliVertexerTracks(magneticField);
536 vertexer->SetITSMode();
537 vertexer->SetMinClusters(fNclustersITS);
539 skipped[0] = (Int_t)track->GetID();
540 vertexer->SetSkipTracks(1,skipped);
541 AliESDVertex *vtxESDSkip = (AliESDVertex*)vertexer->FindPrimaryVertex(fESDEvent);
542 delete vertexer; vertexer = NULL;
543 if(vtxESDSkip->GetNContributors()<fMinNprimVtxContributor) return;
544 // -- ending --- method from Andrea D 28.05.2010
546 Double_t dz[2]; // error of dca in cm
548 if(!track->PropagateToDCA(vtxESDSkip,magneticField, beampiperadius, dz, covardz)) return; // protection
550 Double_t dcaXY = dz[0]*1.0e4; // conv dca in cm to dca in micron
551 Double_t dcaZ = dz[1]*1.0e4;
553 if(fDeDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
555 if(TMath::Abs(dcaXY)<1000) var[1] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
557 var[1] = ((dcaXY>0)?1:-1)*20;
559 if(TMath::Abs(dcaZ)<1000) var[2] = Int_t(dcaZ)/100;
561 var[2] = ((dcaZ>0)?1:-1)*10;
563 // calculate dca using AliKFParticle class------------------------------------------------------------------
565 Int_t trkID = track->GetID();
566 AliKFParticle::SetField(magneticField);
567 AliKFParticle kfParticle(*track, particle->GetPdgCode());
568 // prepare kfprimary vertex
569 AliKFVertex kfESDprimary;
570 // Reconstruct Primary Vertex (with ESD tracks)
571 Int_t n=primVtx->GetNIndices();
572 if (n>0 && primVtx->GetStatus()){
573 kfESDprimary = AliKFVertex(*primVtx);
574 UShort_t *priIndex = primVtx->GetIndices();
575 for (Int_t i=0;i<n;i++){
576 Int_t idx = Int_t(priIndex[i]);
578 kfESDprimary -= kfParticle;
579 kfDcaXY = kfParticle.GetDistanceFromVertexXY(kfESDprimary)*1e4;
580 } // remove current track from this calculation
581 } // loop over all primary vertex contributors
585 if(TMath::Abs(kfDcaXY)<1000)
586 var[3] = Int_t(kfDcaXY)/50;
588 var[3] = (kfDcaXY>0?1:-1)*20;
596 (static_cast<THnSparseF *>(fDeOutputList->At(kEsdElectron)))->Fill(var);
600 //__________________________________________________________
601 void AliHFEdisplacedElectrons::FillDataOutput(const AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack)
604 // this is pure data, without MC information at all
605 // fill output: with HFE pid selection of electrons after all track quality cuts
607 if(!esdTrack) return;
608 AliESDtrack *track = esdTrack;
610 Double_t pt = track->Pt();
611 Double_t eta = track->Eta();
612 Double_t phi = track->Phi();
614 // obtain impact parameters in xy and y
615 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
617 Float_t magneticField = 5; // initialized as 5kG
618 magneticField = fESDEvent->GetMagneticField(); // in kG
619 Double_t beampiperadius=3.;
622 const Int_t nvarData = 6;
623 Double_t varData[nvarData];
626 // excluding current track
629 //------ beginning --- method from Andrea D 28.05.2010
630 AliVertexerTracks *vertexer = new AliVertexerTracks(fESDEvent->GetMagneticField());
631 vertexer->SetITSMode();
632 vertexer->SetMinClusters(fNclustersITS);
634 skipped[0] = (Int_t)track->GetID();
635 vertexer->SetSkipTracks(1,skipped);
636 AliESDVertex *vtxESDSkip = (AliESDVertex*)vertexer->FindPrimaryVertex(fESDEvent);
637 delete vertexer; vertexer = NULL;
638 if(vtxESDSkip->GetNContributors()<fMinNprimVtxContributor) return;
639 //------ ending --- method from Andrea D 28.05.2010
641 Double_t dz[2]; // error of dca in cm
644 if(!track->PropagateToDCA(vtxESDSkip,magneticField, beampiperadius, dz, covardz)) return; // protection
646 Double_t dcaXY = dz[0]*1.0e4; // conv dca in cm to dca in micron
647 Double_t dcaZ = dz[1]*1.0e4;
649 if(TMath::Abs(dcaXY)<1000) varData[0] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
651 varData[0] = (dcaXY>0?1:-1)*20;
652 if(TMath::Abs(dcaZ)<1000) varData[1] = Int_t(dcaZ)/100;
654 varData[1] = (dcaZ>0?1:-1)*10;
657 // calculate dca using AliKFParticle class------------------------------------------------------------------
659 Int_t trkID = track->GetID();
660 AliKFParticle::SetField(magneticField);
661 AliKFParticle kfParticle(*track, -11*track->Charge());
662 // prepare kfprimary vertex
663 AliKFVertex kfESDprimary;
664 // Reconstruct Primary Vertex (with ESD tracks)
665 Int_t n=primVtx->GetNIndices();
666 if (n>0 && primVtx->GetStatus()){
667 kfESDprimary = AliKFVertex(*primVtx);
668 UShort_t *priIndex = primVtx->GetIndices();
669 for (Int_t i=0;i<n;i++){
670 Int_t idx = Int_t(priIndex[i]);
672 kfESDprimary -= kfParticle;
673 kfDcaXY = kfParticle.GetDistanceFromVertexXY(kfESDprimary)*1e4;
674 } // remove current track from this calculation
675 } // loop over all primary vertex contributors
677 if(TMath::Abs(kfDcaXY)<1000)
678 varData[2] = Int_t(kfDcaXY)/50;
680 varData[2] = ((kfDcaXY)>0?1:-1)*20;
683 varData[3] = pt; // pt
684 varData[4] = eta; //eta
685 varData[5] = phi; // phi
687 (static_cast<THnSparseF *>(fDeOutputList->At(kDataElectron)))->Fill(varData);
691 //__________________________________________________________
692 Int_t AliHFEdisplacedElectrons::ElectronFromSource(AliStack * const stack, Int_t label) const
696 // return electron source label via electron label
699 // kEleSource is supposed to be either photon conv, direct photon conv, pi0, eta, beauty --> 0, 1, 2, 3, 4
701 Int_t eleLabel = label;
703 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return -1;
705 TParticle *particle = stack->Particle(eleLabel);
706 if(!particle) return -1;
708 Int_t motherLabel = particle->GetFirstMother();
709 if(motherLabel<0 || motherLabel>stack->GetNtrack()) return -1;
710 TParticle *motherPart = stack->Particle(motherLabel);
711 if(!motherPart) return -1;
713 Int_t pdgCode = TMath::Abs(motherPart->GetPdgCode());
715 if(pdgCode==kPDGelectron) {
716 if(fDeDebugLevel>=10) printf("particle label: %d...(motherLabel=%d : motherPdg=%d) grandmother's pdg code was returned...%d \n",
717 label, motherLabel, pdgCode, ElectronFromSource(stack, motherLabel));
718 return ElectronFromSource(stack, motherLabel);
725 //__________________________________________________________
726 Int_t AliHFEdisplacedElectrons::ElectronFromCharm(AliStack * const stack, Int_t label) const
729 // separate electron: kEleC from c->eX, kEleBC from b->c->eX
732 Int_t motherLabel = label;
733 TParticle *motherParticle = stack->Particle(motherLabel); // mother part
734 if(!motherParticle) return -1;
735 Int_t gMotherLabel = motherParticle->GetFirstMother(); // grand mother
736 if(gMotherLabel<0 || gMotherLabel>stack->GetNtrack()) return -1;
738 TParticle *gMotherPart = stack->Particle(gMotherLabel);
739 if(!gMotherPart) return -1;
741 Int_t pdgCode = gMotherPart->GetPdgCode();
742 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
743 TMath::Abs(pdgCode)/1000==kPDGbeauty || TMath::Abs(pdgCode)/100==kPDGbeauty || TMath::Abs(pdgCode)==kPDGbeauty) {
744 if(fDeDebugLevel>=10) printf("this electron label %d is from mother %d, and finally from %d\n", label, ElectronFromSource(stack, label), pdgCode);
746 } // for sure it is from BC
749 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
750 TMath::Abs(pdgCode)/1000==kPDGcharm ||
751 TMath::Abs(pdgCode)/100==kPDGcharm ||
752 TMath::Abs(pdgCode)==kPDGcharm){
754 if(CharmFromBeauty(stack, gMotherLabel)!=-1) return kEleBC;
764 //__________________________________________________________
765 Int_t AliHFEdisplacedElectrons::CharmFromBeauty(AliStack * const stack, Int_t hfLabel) const
769 // check if charm meson/hadron is from beauty decay
770 // -1, not from beauty
771 // return the label of the mother of this charm hadron
774 Int_t charmLabel = hfLabel;
776 // AliStack *stack = fMC->Stack();
777 if(charmLabel<0 || charmLabel>stack->GetNtrack()) return -1;
778 TParticle *particle = stack->Particle(charmLabel);
779 if(!particle) return -1;
781 Int_t motherCharmLabel = particle->GetFirstMother();
782 if(motherCharmLabel<0 || motherCharmLabel>stack->GetNtrack()) return -1;
784 TParticle *motherCharmPart = stack->Particle(motherCharmLabel);
785 if(!motherCharmPart) return -1;
787 Int_t pdgCode = motherCharmPart->GetPdgCode();
789 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
790 TMath::Abs(pdgCode)/1000==kPDGbeauty ||
791 TMath::Abs(pdgCode)/100==kPDGbeauty ||
792 TMath::Abs(pdgCode)==kPDGbeauty)
793 return motherCharmLabel;
795 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
796 TMath::Abs(pdgCode)/1000==kPDGcharm ||
797 TMath::Abs(pdgCode)/100==kPDGcharm)
798 return CharmFromBeauty(stack, motherCharmLabel); // loop over to see if charm is from beauty -- if yes, return the label of mother of the charm
804 //__________________________________________________________
805 Int_t AliHFEdisplacedElectrons::ElePhotonDirect(AliStack * const stack, Int_t label) const
808 // electron is from photon, and check if this photon is direct
811 Int_t eleLabel = label;
813 TParticle *particle = stack->Particle(eleLabel);
814 if(particle->GetFirstMother()<0 || particle->GetFirstMother()>stack->GetNtrack())
817 TParticle *photonPart = stack->Particle(particle->GetFirstMother());
820 Int_t motherPhotonLabel = photonPart->GetFirstMother();
821 if(motherPhotonLabel<0 || motherPhotonLabel>stack->GetNtrack())
824 TParticle *motherPhotonPart = stack->Particle(motherPhotonLabel);
825 if(!motherPhotonPart)
828 Int_t pdgMotherPhoton = motherPhotonPart->GetPdgCode();
829 if(TMath::Abs(pdgMotherPhoton)<=10 || TMath::Abs(pdgMotherPhoton)==21)
838 //__________________________________________________________
839 Int_t AliHFEdisplacedElectrons::GetMCpid(AliStack* const stack, Int_t partLabel) const
846 Int_t label = partLabel;
847 // AliStack* stack = fMC->Stack();
848 if((label < 0) || (label >= stack->GetNtrack())) return -1;
851 TParticle * particle = stack->Particle(label);
852 if(!particle) return -1;
853 Int_t pdg = particle->GetPdgCode();
859 //__________________________________________________________
860 Int_t AliHFEdisplacedElectrons::GetMotherLabel(AliStack *const stack, Int_t eleLabel) const
863 // Simply label of mother
867 Int_t label = eleLabel;
868 // AliStack* stack = fMC->Stack();
869 if((label < 0) || (label >= stack->GetNtrack())) return -1;
872 TParticle * particle = stack->Particle(label);
873 if(!particle) return -1;
875 return particle->GetFirstMother();
880 //__________________________________________________________
881 Float_t AliHFEdisplacedElectrons::GetRapidity(TParticle *part) const
885 Float_t rapidity = -999;
886 if((part->Energy() - part->Pz())*(part->Energy() + part->Pz())>0)
887 rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));
893 //__________________________________________________________
894 Float_t AliHFEdisplacedElectrons::GetTrackRapidity(AliESDtrack * const track) const
896 // return rapidity of electron
898 Float_t px = track->Px();
899 Float_t py = track->Py();
900 Float_t pz = track->Pz();
902 // electron mass 0.00051099906 GeV/c2
903 TParticlePDG* electron = TDatabasePDG::Instance()->GetParticle(kPDGelectron);
904 Double_t mass = electron->Mass();
906 Float_t en = TMath::Sqrt(px*px + py*py + pz*pz + mass*mass);
908 Float_t rapidity = -999;
909 if((en - pz)*(en + pz)>0)
910 rapidity = 0.5*(TMath::Log((en - pz)*(en + pz)));
915 //__________________________________________________________
916 Int_t AliHFEdisplacedElectrons::CheckCharm(AliStack * const stack, Int_t eleLabel)
918 // checks the genealogy of the ele from charm for a beauty
919 // this method needs the stack and the label of the electron
920 // warning: it assumes that the ele comes from a charm
922 TParticle *particle = stack->Particle(eleLabel);
923 Int_t label = particle->GetFirstMother();
925 while(label>0 && label<(stack->GetNtrack())){
926 particle = stack->Particle(label);
927 if(IsB(TMath::Abs(particle->GetPdgCode()))) return kEleBC;
928 label = particle->GetFirstMother();
934 //__________________________________________________________
935 Bool_t AliHFEdisplacedElectrons::IsB(Int_t pdg) const
937 // check if the pdg is that of a beauty particle
939 if((TMath::Abs(pdg)%10000)/100==kPDGbeauty ||
940 TMath::Abs(pdg)/1000==kPDGbeauty ||
941 TMath::Abs(pdg)/100==kPDGbeauty ||
942 TMath::Abs(pdg)==kPDGbeauty) return kTRUE;
946 //__________________________________________________________
947 Bool_t AliHFEdisplacedElectrons::IsC(Int_t pdg) const
949 // check if the pdg is that of a charmed particle
951 if((TMath::Abs(pdg)%10000)/100==kPDGcharm ||
952 TMath::Abs(pdg)/1000==kPDGcharm ||
953 TMath::Abs(pdg)/100==kPDGcharm ||
954 TMath::Abs(pdg)==kPDGcharm) return kTRUE;