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>
28 #include <TParticle.h>
29 #include <TDatabasePDG.h>
31 #include "THnSparse.h"
32 #include "AliMCEvent.h"
33 #include "AliESDEvent.h"
34 #include "AliMCParticle.h"
35 #include "AliESDtrack.h"
39 #include "AliHFEdisplacedElectrons.h"
41 ClassImp(AliHFEdisplacedElectrons)
43 //__________________________________________________________
44 const Float_t AliHFEdisplacedElectrons::fgkDcaMinPtIntv[13] = {
46 // define DCA low limits for single electrons cut in each Pt bin
47 // preliminary numbers
48 // these numbers should be replaced by the best numbers determined by
49 // cut efficiency study: signal/background (not used right now)
64 //__________________________________________________________
65 const Float_t AliHFEdisplacedElectrons::fgkPtIntv[14] = {
67 // define pT bins for spectra of single electrons
69 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};
71 //__________________________________________________________
72 const Char_t *AliHFEdisplacedElectrons::fgkKineVar[3] = {
75 //__________________________________________________________
76 const Char_t *AliHFEdisplacedElectrons::fgkKineVarTitle[3] ={
77 "rapidity;y;dN/dy", "azimuthal;#phi;dN/d#phi", "transverse momentum;p_{T};dN/dp_{T}",
80 //__________________________________________________________
81 AliHFEdisplacedElectrons::AliHFEdisplacedElectrons():
85 , fTHnSparseDcaMcPionInfo(NULL)
86 , fTHnSparseDcaMcEleInfo(NULL)
87 , fTHnSparseDcaDataEleInfo(NULL)
91 // default constructor
96 //__________________________________________________________
97 AliHFEdisplacedElectrons::AliHFEdisplacedElectrons(const AliHFEdisplacedElectrons &displacedElectrons):
98 TObject(displacedElectrons)
102 , fTHnSparseDcaMcPionInfo(NULL)
103 , fTHnSparseDcaMcEleInfo(NULL)
104 , fTHnSparseDcaDataEleInfo(NULL)
114 //__________________________________________________________
115 AliHFEdisplacedElectrons&AliHFEdisplacedElectrons::operator=(const AliHFEdisplacedElectrons &)
118 // Assignment operator
120 Printf("Not yet implemented.");
124 //__________________________________________________________
125 AliHFEdisplacedElectrons::~AliHFEdisplacedElectrons()
128 // default constructor
131 if(fTHnSparseDcaMcPionInfo)
132 delete fTHnSparseDcaMcPionInfo;
133 if(fTHnSparseDcaMcEleInfo)
134 delete fTHnSparseDcaMcEleInfo;
135 if(fTHnSparseDcaDataEleInfo)
136 delete fTHnSparseDcaDataEleInfo;
139 fOutputList->Clear();
144 Printf("analysis done\n");
147 //__________________________________________________________
148 void AliHFEdisplacedElectrons::InitAnalysis(){
150 // init analysis (no intialization yet)
154 Printf("initialize analysis\n");
159 //__________________________________________________________
160 void AliHFEdisplacedElectrons::CreateOutputs(TList* const displacedList){
163 // create output fOutputList
167 // 8 interested electron sources: others, photon conv, direct photon, pi0, eta, b, b->c, c
168 // 21 possible DCA cuts XY
169 // 21 possible DCA cuts Z
172 // 10 azimuthal angle phi bins
175 if(!displacedList) return;
177 fOutputList = displacedList;
178 fOutputList -> SetName("information");
182 Int_t nBinsEleSource = 8;
183 Double_t minEleSource = -1.5;
184 Double_t maxEleSource = 6.5;
185 Double_t *binLimEleSource = new Double_t[nBinsEleSource+1];
186 for(Int_t i=0; i<=nBinsEleSource; i++)
187 binLimEleSource[i] = minEleSource + i*(maxEleSource-minEleSource)/nBinsEleSource;
189 // dca bins: the same as XY and Z
190 // these should be variable bins as well
191 Int_t nBinsDca = kNDcaMin-1; // 12 bins
192 Double_t minDca = -0.5;
193 Double_t maxDca = 20.5;
194 Double_t dcaBinWidth = (maxDca-minDca)/nBinsDca;
195 Double_t *binLimDca = new Double_t[nBinsDca+1];
196 for(Int_t i=0; i<=nBinsDca; i++)
197 binLimDca[i] = minDca + i*dcaBinWidth;
201 Int_t nBinsPt = kNPtIntv-1;
202 Double_t *binLimPt = new Double_t[nBinsPt+1];
203 for(Int_t i=0; i<=nBinsPt; i++)
204 binLimPt[i] = fgkPtIntv[i]; // variable bins
208 Double_t minRap = -1.0;
209 Double_t maxRap = 1.0;
210 Double_t *binLimRap = new Double_t[nBinsRap+1];
211 for(Int_t i=0; i<=nBinsRap; i++)
212 binLimRap[i] = minRap + i*(maxRap-minRap)/nBinsRap;
214 // azumuthal phi angle
217 Double_t maxPhi = 2*TMath::Pi();
218 Double_t *binLimPhi = new Double_t[nBinsPhi+1];
219 for(Int_t i=0; i<=nBinsPhi; i++)
220 binLimPhi[i] = minPhi + i*(maxPhi-minPhi)/nBinsPhi;
225 const Int_t nVarPion = 5;
226 Int_t iBinPion[nVarPion] = {nBinsDca, nBinsDca, nBinsPt, nBinsRap, nBinsPhi};
228 THnSparseF *fTHnSparseDcaMcPionInfo = NULL; // empty for the moment
230 fTHnSparseDcaMcPionInfo = new THnSparseF("dcaMcPionInfo",
231 "MC info:;dcaXY [50 #mum];dcaZ [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];",
233 fTHnSparseDcaMcPionInfo->SetBinEdges(0, binLimDca); // dca xy cut
234 fTHnSparseDcaMcPionInfo->SetBinEdges(1, binLimDca); // dca z cut
235 fTHnSparseDcaMcPionInfo->SetBinEdges(2, binLimPt); // pt
236 fTHnSparseDcaMcPionInfo->SetBinEdges(3, binLimRap); // rapidity
237 fTHnSparseDcaMcPionInfo->SetBinEdges(4, binLimPhi); // phi
238 fTHnSparseDcaMcPionInfo->Sumw2();
240 fOutputList -> AddAt(fTHnSparseDcaMcPionInfo, kMCpion);
244 const Int_t nVar = 6;
245 Int_t iBin[nVar] = {nBinsEleSource,nBinsDca, nBinsDca, nBinsPt, nBinsRap, nBinsPhi};
247 THnSparseF *fTHnSparseDcaMcEleInfo = NULL; // empty for the moment
249 fTHnSparseDcaMcEleInfo = new THnSparseF("dcaMcElectronInfo",
250 "MC info:;ID [electron source id];dcaXY [50 #mum];dcaZ [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];",
252 fTHnSparseDcaMcEleInfo->SetBinEdges(0, binLimEleSource); // electron source
253 fTHnSparseDcaMcEleInfo->SetBinEdges(1, binLimDca); // dca xy cut
254 fTHnSparseDcaMcEleInfo->SetBinEdges(2, binLimDca); // dca z cut
255 fTHnSparseDcaMcEleInfo->SetBinEdges(3, binLimPt); // pt
256 fTHnSparseDcaMcEleInfo->SetBinEdges(4, binLimRap); // rapidity
257 fTHnSparseDcaMcEleInfo->SetBinEdges(5, binLimPhi); // phi
258 fTHnSparseDcaMcEleInfo->Sumw2();
259 fOutputList -> AddAt(fTHnSparseDcaMcEleInfo, kMCelectron);
265 THnSparseF *fTHnSparseDcaDataEleInfo = NULL; // empty for the moment
266 const Int_t nVarData = 5;
267 Int_t iBinData[nVarData] = {nBinsDca, nBinsDca, nBinsPt, nBinsRap, nBinsPhi};
269 fTHnSparseDcaDataEleInfo = new THnSparseF("dcaDataElectronInfo",
270 "Data info:;dcaXY [50 #mum];dcaZ [50 #mum];pT [GeV/c];y [rapidity];#phi [rad];",
272 fTHnSparseDcaDataEleInfo->SetBinEdges(0, binLimDca); // dca xy cut
273 fTHnSparseDcaDataEleInfo->SetBinEdges(1, binLimDca); // dca z cut
274 fTHnSparseDcaDataEleInfo->SetBinEdges(2, binLimPt); // pt
275 fTHnSparseDcaDataEleInfo->SetBinEdges(3, binLimRap); // rapidity
276 fTHnSparseDcaDataEleInfo->SetBinEdges(4, binLimPhi); // phi
277 fTHnSparseDcaDataEleInfo->Sumw2();
279 fOutputList -> AddAt(fTHnSparseDcaDataEleInfo, kData);
281 AliInfo("THnSparse histograms are created\n");
282 fOutputList->Print();
287 //__________________________________________________________
288 void AliHFEdisplacedElectrons::FillMCOutput(AliESDEvent * const fESDEvent, AliESDtrack* const esdTrack, AliStack * const stack)
292 if(!esdTrack) return;
293 AliESDtrack *track = esdTrack;
294 Double_t pt = track->Pt();
295 Double_t eta = track->Eta();
296 Double_t phi = track->Phi();
298 Int_t label = track->GetLabel();
299 if(label<0 || label>stack->GetNtrack()) return;
301 TParticle *particle = stack->Particle(label);
302 if(!particle) return;
305 // obtain impact parameters in xy and y
306 const AliESDVertex *primVtx = fESDEvent->GetPrimaryVertex();
308 Float_t magneticField = 5; // initialized as 5kG
309 magneticField = fESDEvent->GetMagneticField(); // in kG
312 Double_t dz[2]; // error of dca in cm
314 track->PropagateToDCA(primVtx,magneticField, 1000., dz, covardz);
317 Double_t dcaXY = TMath::Abs(dz[0])*1.0e4; // conv dca in cm to dca in micron
318 Double_t dcaZ = TMath::Abs(dz[1])*1.0e4;
322 if(HasMCData() && TMath::Abs(GetMCpid(stack, label))==kPDGelectron){
324 Int_t eleLabel = label;
326 const Int_t nvarMC=6;
327 Double_t var[nvarMC];
329 Int_t sourcePdg = ElectronFromSource(stack, eleLabel);
331 if(sourcePdg==kPDGgamma){ // check direct photon or not // fixme
332 if(ElePhotonDirect(stack, eleLabel)!=-1)
333 var[0] = kEleDirectPhotonConv;
335 var[0] = kElePhotonConv;
337 printf("photonconv=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
338 } // photon or direct photon -> e
340 if(sourcePdg==kPDGpi0){
342 if(fDebugLevel>=10) printf("pi0======this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
345 if(sourcePdg==kPDGeta){
348 printf("eta=====this electron %d is from %d, source id=%.1f\n", eleLabel, sourcePdg, var[0]);
351 if(TMath::Abs(sourcePdg%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
352 TMath::Abs(sourcePdg)/1000==kPDGbeauty ||
353 TMath::Abs(sourcePdg)/100==kPDGbeauty ||
354 TMath::Abs(sourcePdg)==kPDGbeauty){
357 printf("beauty======electron %d is from %d with id %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
358 } // direct beauty -> e
359 if(TMath::Abs(sourcePdg%10000)/100==kPDGcharm || // for special intermediate meson states: like 1004**
360 TMath::Abs(sourcePdg)/1000==kPDGcharm ||
361 TMath::Abs(sourcePdg)/100==kPDGcharm ||
362 TMath::Abs(sourcePdg)==kPDGcharm){
364 // electron from b->c->e
365 // electron from c->e
366 if(ElectronFromCharm(stack, eleLabel)!=-1){
367 var[0] = ElectronFromCharm(stack, eleLabel);
369 printf("charm----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
371 } // charm electrons: b->c->e or c->e
373 if(fDebugLevel>=10) printf("others----->electron %d has mother %d is from %.1f\n", eleLabel, ElectronFromSource(stack, eleLabel), var[0]);
375 if(dcaXY<1000) var[1] = Int_t(dcaXY)/50; // larger than 1mm should go to the last bin
378 if(dcaZ<1000) var[2] = Int_t(dcaZ)/50;
386 (dynamic_cast<THnSparseF *>(fOutputList->At(kMCelectron)))->Fill(var);
389 if(HasMCData() && TMath::Abs(GetMCpid(stack, label))==kPDGpion){
391 const Int_t nvarPionMC=5;
392 Double_t varPion[nvarPionMC];
394 varPion[0] = Int_t(dcaXY)/50; // dca xy
398 varPion[1] = Int_t(dcaZ)/50; // dca Z
402 // varPion[0] = TMath::Abs(dcaXY); // dca xy
403 // varPion[1] = TMath::Abs(dcaZ); // dca z
404 varPion[2] = pt; // pt
405 varPion[3] = eta; //eta
406 varPion[4] = phi; // phi
408 (dynamic_cast<THnSparseF *>(fOutputList->At(kMCpion)))->Fill(varPion);
415 //__________________________________________________________
416 void AliHFEdisplacedElectrons::FillESDOutput(AliESDEvent * const fESD, AliESDtrack* const esdTrack)
420 if(!esdTrack) return;
421 AliESDtrack *track = esdTrack;
423 Double_t pt = track->Pt();
424 Double_t eta = track->Eta();
425 Double_t phi = track->Phi();
427 // obtain impact parameters in xy and y
428 const AliESDVertex *primVtx = fESD->GetPrimaryVertex();
430 Float_t magneticField = 5; // initialized as 5kG
431 magneticField = fESD->GetMagneticField(); // in kG
432 Double_t dz[2]; // error of dca in cm
434 track->PropagateToDCA(primVtx,magneticField, 1000., dz, covardz);
435 Double_t dcaXY = TMath::Abs(dz[0]*1.0e4); // conv dca in cm to dca in micron
436 Double_t dcaZ = TMath::Abs(dz[1]*1.0e4);
439 const Int_t nvarData = 5;
440 Double_t varData[nvarData];
443 varData[0] = Int_t(dcaXY)/50; // dca xy
447 varData[1] = Int_t(dcaZ)/50; // dca Z
451 varData[2] = pt; // pt
452 varData[3] = eta; //eta
453 varData[4] = phi; // phi
455 (dynamic_cast<THnSparseF *>(fOutputList->At(kData)))->Fill(varData);
459 //__________________________________________________________
460 Int_t AliHFEdisplacedElectrons::ElectronFromSource(AliStack * const stack, Int_t label) const
464 // return electron source label via electron label
467 // kEleSource is supposed to be either photon conv, direct photon conv, pi0, eta, beauty --> 0, 1, 2, 3, 4
469 Int_t eleLabel = label;
471 if(eleLabel<0 || eleLabel>stack->GetNtrack()) return -1;
473 TParticle *particle = stack->Particle(eleLabel);
474 if(!particle) return -1;
476 Int_t motherLabel = particle->GetFirstMother();
477 if(motherLabel<0 || motherLabel>stack->GetNtrack()) return -1;
478 TParticle *motherPart = stack->Particle(motherLabel);
479 if(!motherPart) return -1;
481 Int_t pdgCode = TMath::Abs(motherPart->GetPdgCode());
483 if(pdgCode==kPDGelectron) {
484 if(fDebugLevel>=10) printf("particle label: %d...(motherLabel=%d : motherPdg=%d) grandmother's pdg code was returned...%d \n",
485 label, motherLabel, pdgCode, ElectronFromSource(stack, motherLabel));
486 return ElectronFromSource(stack, motherLabel);
493 //__________________________________________________________
494 Int_t AliHFEdisplacedElectrons::ElectronFromCharm(AliStack * const stack, Int_t label) const
497 // separate electron: kEleC from c->eX, kEleBC from b->c->eX
500 Int_t motherLabel = label;
501 TParticle *motherParticle = stack->Particle(motherLabel); // mother part
502 if(!motherParticle) return -1;
503 Int_t gMotherLabel = motherParticle->GetFirstMother(); // grand mother
504 if(gMotherLabel<0 || gMotherLabel>stack->GetNtrack()) return -1;
506 TParticle *gMotherPart = stack->Particle(gMotherLabel);
507 if(!gMotherPart) return -1;
509 Int_t pdgCode = gMotherPart->GetPdgCode();
510 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
511 TMath::Abs(pdgCode)/1000==kPDGbeauty || TMath::Abs(pdgCode)/100==kPDGbeauty || TMath::Abs(pdgCode)==kPDGbeauty) {
512 if(fDebugLevel>=10) printf("this electron label %d is from mother %d, and finally from %d\n", label, ElectronFromSource(stack, label), pdgCode);
514 } // for sure it is from BC
517 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
518 TMath::Abs(pdgCode)/1000==kPDGcharm ||
519 TMath::Abs(pdgCode)/100==kPDGcharm ||
520 TMath::Abs(pdgCode)==kPDGcharm){
522 if(CharmFromBeauty(stack, gMotherLabel)!=-1)
534 //__________________________________________________________
535 Int_t AliHFEdisplacedElectrons::CharmFromBeauty(AliStack * const stack, Int_t hfLabel) const
539 // check if charm meson/hadron is from beauty decay
540 // -1, not from beauty
541 // return the label of the mother of this charm hadron
544 Int_t charmLabel = hfLabel;
546 // AliStack *stack = fMC->Stack();
547 if(charmLabel<0 || charmLabel>stack->GetNtrack()) return -1;
548 TParticle *particle = stack->Particle(charmLabel);
549 if(!particle) return -1;
551 Int_t motherCharmLabel = particle->GetFirstMother();
552 if(motherCharmLabel<0 || motherCharmLabel>stack->GetNtrack()) return -1;
554 TParticle *motherCharmPart = stack->Particle(motherCharmLabel);
555 if(!motherCharmPart) return -1;
557 Int_t pdgCode = motherCharmPart->GetPdgCode();
559 if(TMath::Abs(pdgCode%10000)/100==kPDGbeauty || // for special intermediate meson states: like 100553
560 TMath::Abs(pdgCode)/1000==kPDGbeauty ||
561 TMath::Abs(pdgCode)/100==kPDGbeauty ||
562 TMath::Abs(pdgCode)==kPDGbeauty)
563 return motherCharmLabel;
565 if(TMath::Abs(pdgCode%10000)/100==kPDGcharm || // for special intermediate meson states: like 100443, 10443, 204*3 (*=1, 2, 3, 4)
566 TMath::Abs(pdgCode)/1000==kPDGcharm ||
567 TMath::Abs(pdgCode)/100==kPDGcharm)
568 return CharmFromBeauty(stack, motherCharmLabel); // loop over to see if charm is from beauty -- if yes, return the label of mother of the charm
574 //__________________________________________________________
575 Int_t AliHFEdisplacedElectrons::ElePhotonDirect(AliStack * const stack, Int_t label) const
578 // electron is from photon, and check if this photon is direct
581 Int_t eleLabel = label;
583 TParticle *particle = stack->Particle(eleLabel);
584 if(particle->GetFirstMother()<0 || particle->GetFirstMother()>stack->GetNtrack())
587 TParticle *photonPart = stack->Particle(particle->GetFirstMother());
590 Int_t motherPhotonLabel = photonPart->GetFirstMother();
591 if(motherPhotonLabel<0 || motherPhotonLabel>stack->GetNtrack())
594 TParticle *motherPhotonPart = stack->Particle(motherPhotonLabel);
595 if(!motherPhotonPart)
598 Int_t pdgMotherPhoton = motherPhotonPart->GetPdgCode();
599 if(TMath::Abs(pdgMotherPhoton)<=10 || TMath::Abs(pdgMotherPhoton)==21)
608 //__________________________________________________________
609 Int_t AliHFEdisplacedElectrons::GetMCpid(AliStack* const stack, Int_t partLabel) const
616 Int_t label = partLabel;
617 // AliStack* stack = fMC->Stack();
618 if((label < 0) || (label >= stack->GetNtrack())) return -1;
621 TParticle * particle = stack->Particle(label);
622 if(!particle) return -1;
623 Int_t pdg = particle->GetPdgCode();
629 //__________________________________________________________
630 Int_t AliHFEdisplacedElectrons::GetMotherLabel(AliStack *const stack, Int_t eleLabel) const
633 // Simply label of mother
637 Int_t label = eleLabel;
638 // AliStack* stack = fMC->Stack();
639 if((label < 0) || (label >= stack->GetNtrack())) return -1;
642 TParticle * particle = stack->Particle(label);
643 if(!particle) return -1;
645 return particle->GetFirstMother();
650 //__________________________________________________________
651 Float_t AliHFEdisplacedElectrons::GetRapidity(TParticle *part) const
655 Float_t rapidity = -999;
656 if((part->Energy() - part->Pz())*(part->Energy() + part->Pz())>0)
657 rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));
663 //__________________________________________________________
664 Float_t AliHFEdisplacedElectrons::GetTrackRapidity(AliESDtrack * const track) const
666 // return rapidity of electron
668 Float_t px = track->Px();
669 Float_t py = track->Py();
670 Float_t pz = track->Pz();
672 // electron mass 0.00051099906 GeV/c2
673 TParticlePDG* electron = TDatabasePDG::Instance()->GetParticle(kPDGelectron);
674 Double_t mass = electron->Mass();
676 Float_t en = TMath::Sqrt(px*px + py*py + pz*pz + mass*mass);
678 Float_t rapidity = -999;
679 if((en - pz)*(en + pz)>0)
680 rapidity = 0.5*(TMath::Log((en - pz)*(en + pz)));