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 // QA class of Heavy Flavor quark and fragmeted/decayed particles
17 // -Check kinematics of Heavy Quarks/hadrons, and decayed leptons
19 // decay lepton kinematics w/wo acceptance
20 // heavy hadron decay length, electron pT fraction carried from decay
21 // -Check yield of Heavy Quarks/hadrons
22 // Number of produced heavy quark
23 // Number of produced hadron of given pdg code
27 // MinJung Kweon <minjung@physi.uni-heidelberg.de>
33 #include <TParticle.h>
37 #include <AliGenEventHeader.h>
38 #include <AliAODMCParticle.h>
40 #include "AliHFEmcQA.h"
42 const Int_t AliHFEmcQA::fgkGluon=21;
43 const Int_t AliHFEmcQA::fgkMaxGener=10;
44 const Int_t AliHFEmcQA::fgkMaxIter=100;
45 const Int_t AliHFEmcQA::fgkqType = 7; // number of species waiting for QA done
49 //_______________________________________________________________________________________________
50 AliHFEmcQA::AliHFEmcQA() :
56 // Default constructor
60 //_______________________________________________________________________________________________
61 AliHFEmcQA::AliHFEmcQA(const AliHFEmcQA&p):
66 ,fNparents(p.fNparents)
71 //_______________________________________________________________________________________________
73 AliHFEmcQA::operator=(const AliHFEmcQA &)
75 // Assignment operator
77 AliInfo("Not yet implemented.");
81 //_______________________________________________________________________________________________
82 AliHFEmcQA::~AliHFEmcQA()
86 AliInfo("Analysis Done.");
89 //_______________________________________________________________________________________________
90 void AliHFEmcQA::PostAnalyze() const
94 //__________________________________________
95 void AliHFEmcQA::CreateHistograms(const Int_t kquark, Int_t icut, TString hnopt)
99 if (kquark != kCharm && kquark != kBeauty) {
100 AliDebug(1, "This task is only for heavy quark QA, return\n");
103 Int_t iq = kquark - kCharm;
105 TString kqTypeLabel[fgkqType];
106 if (kquark == kCharm){
107 kqTypeLabel[kQuark]="c";
108 kqTypeLabel[kantiQuark]="cbar";
109 kqTypeLabel[kHadron]="cHadron";
110 kqTypeLabel[keHadron]="ceHadron";
111 kqTypeLabel[kDeHadron]="nullHadron";
112 kqTypeLabel[kElectron]="ce";
113 kqTypeLabel[kElectron2nd]="nulle";
114 } else if (kquark == kBeauty){
115 kqTypeLabel[kQuark]="b";
116 kqTypeLabel[kantiQuark]="bbar";
117 kqTypeLabel[kHadron]="bHadron";
118 kqTypeLabel[keHadron]="beHadron";
119 kqTypeLabel[kDeHadron]="bDeHadron";
120 kqTypeLabel[kElectron]="be";
121 kqTypeLabel[kElectron2nd]="bce";
126 for (Int_t iqType = 0; iqType < fgkqType; iqType++ ){
127 if (iqType < keHadron && icut > 0) continue; // don't duplicate histogram for quark and hadron
128 hname = hnopt+"PdgCode_"+kqTypeLabel[iqType];
129 fHist[iq][iqType][icut].fPdgCode = new TH1F(hname,hname,20001,-10000.5,10000.5);
130 hname = hnopt+"Pt_"+kqTypeLabel[iqType];
131 fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",250,0,50);
132 hname = hnopt+"Y_"+kqTypeLabel[iqType];
133 fHist[iq][iqType][icut].fY = new TH1F(hname,hname,150,-7.5,7.5);
134 hname = hnopt+"Eta_"+kqTypeLabel[iqType];
135 fHist[iq][iqType][icut].fEta = new TH1F(hname,hname,150,-7.5,7.5);
139 hname = hnopt+"Nq_"+kqTypeLabel[kQuark];
140 fHistComm[iq][icut].fNq = new TH1F(hname,hname,10,-0.5,9.5);
141 hname = hnopt+"ProcessID_"+kqTypeLabel[kQuark];
142 fHistComm[iq][icut].fProcessID = new TH1F(hname,hname,21,-10.5,10.5);
144 hname = hnopt+"ePtRatio_"+kqTypeLabel[kQuark];
145 fHistComm[iq][icut].fePtRatio = new TH2F(hname,hname+";p_{T} (GeV/c);momentum fraction",100,0,30,100,0,1);
146 hname = hnopt+"DePtRatio_"+kqTypeLabel[kQuark];
147 fHistComm[iq][icut].fDePtRatio = new TH2F(hname,hname+";p_{T} (GeV/c);momentum fraction",100,0,30,100,0,1);
148 hname = hnopt+"eDistance_"+kqTypeLabel[kQuark];
149 fHistComm[iq][icut].feDistance= new TH2F(hname,hname+";p_{T} (GeV/c);distance (cm)",100,0,30,200,0,2);
150 hname = hnopt+"DeDistance_"+kqTypeLabel[kQuark];
151 fHistComm[iq][icut].fDeDistance= new TH2F(hname,hname+";p_{T} (GeV/c);distance (cm)",100,0,30,200,0,2);
155 //__________________________________________
156 void AliHFEmcQA::Init()
158 // called at begining every event
160 for (Int_t i=0; i<2; i++){
166 fParentSelect[0][0] = 411;
167 fParentSelect[0][1] = 421;
168 fParentSelect[0][2] = 431;
169 fParentSelect[0][3] = 4122;
170 fParentSelect[0][4] = 4132;
171 fParentSelect[0][5] = 4232;
172 fParentSelect[0][6] = 4332;
174 fParentSelect[1][0] = 511;
175 fParentSelect[1][1] = 521;
176 fParentSelect[1][2] = 531;
177 fParentSelect[1][3] = 5122;
178 fParentSelect[1][4] = 5132;
179 fParentSelect[1][5] = 5232;
180 fParentSelect[1][6] = 5332;
184 //__________________________________________
185 void AliHFEmcQA::GetQuarkKine(TParticle *part, Int_t iTrack, const Int_t kquark)
187 // get heavy quark kinematics
189 if (kquark != kCharm && kquark != kBeauty) {
190 AliDebug(1, "This task is only for heavy quark QA, return\n");
193 Int_t iq = kquark - kCharm;
196 AliDebug(1, "Stack label is negative, return\n");
200 //TParticle *part = fStack->Particle(iTrack);
201 Int_t partPdgcode = TMath::Abs(part->GetPdgCode());
203 // select heavy hadron or not fragmented heavy quark
204 if ( int(partPdgcode/100.)==kquark || int(partPdgcode/1000.)==kquark || (partPdgcode==kquark && (part->GetNDaughters()==0 && iTrack>5)) ){
206 TParticle *partMother;
209 if (partPdgcode == kquark){ // in case of not fragmented heavy quark
212 } else{ // in case of heavy hadron, start to search for mother heavy parton
213 iLabel = part->GetFirstMother();
214 if (iLabel>-1) { partMother = fStack->Particle(iLabel); }
216 AliDebug(1, "Stack label is negative, return\n");
221 // heavy parton selection as a mother of heavy hadron
222 // if the heavy particle comes from string which is denoted as particle status 12|12|12...12|11,[PYTHIA p.60]
223 // in this case, the mother of heavy particle can be one of the fragmented parton of the string
224 // should I make a condition that partMother should be quark or diquark? -> not necessary
225 if ( abs(partMother->GetPdgCode()) == kquark || (partMother->GetStatusCode() == 11) ){
226 //if ( abs(partMother->GetPdgCode()) == kquark || (partMother->GetStatusCode() == 11 || partMother->GetStatusCode() == 12) ){
228 if ( abs(partMother->GetPdgCode()) != kquark ){
229 // search fragmented partons in the same string
230 Bool_t isSameString = kTRUE;
231 for (Int_t i=1; i<fgkMaxIter; i++){
233 if (iLabel>-1) { partMother = fStack->Particle(iLabel); }
235 AliDebug(1, "Stack label is negative, return\n");
238 if ( abs(partMother->GetPdgCode()) == kquark ) break;
239 if ( partMother->GetStatusCode() != 12 ) isSameString = kFALSE;
240 if (!isSameString) return;
243 AliDebug(1, "Can not find heavy parton of this heavy hadron in the string, return\n");
244 if (abs(partMother->GetPdgCode()) != kquark) return;
246 if (fIsHeavy[iq] >= 50) return;
247 fHeavyQuark[fIsHeavy[iq]] = partMother;
250 // fill kinematics for heavy parton
251 if (partMother->GetPdgCode() > 0) { // quark
252 fHist[iq][kQuark][0].fPdgCode->Fill(partMother->GetPdgCode());
253 fHist[iq][kQuark][0].fPt->Fill(partMother->Pt());
254 fHist[iq][kQuark][0].fY->Fill(GetRapidity(partMother));
255 fHist[iq][kQuark][0].fEta->Fill(partMother->Eta());
257 fHist[iq][kantiQuark][0].fPdgCode->Fill(partMother->GetPdgCode());
258 fHist[iq][kantiQuark][0].fPt->Fill(partMother->Pt());
259 fHist[iq][kantiQuark][0].fY->Fill(GetRapidity(partMother));
260 fHist[iq][kantiQuark][0].fEta->Fill(partMother->Eta());
263 } // end of heavy parton slection loop
265 } // end of heavy hadron or quark selection
269 //__________________________________________
270 void AliHFEmcQA::EndOfEventAna(const Int_t kquark)
272 // end of event analysis
274 if (kquark != kCharm && kquark != kBeauty) {
275 AliDebug(1, "This task is only for heavy quark QA, return\n");
278 Int_t iq = kquark - kCharm;
281 // # of heavy quark per event
282 AliDebug(1,Form("Number of heavy quark in this event = %d \n",fIsHeavy[iq]));
283 fHistComm[iq][0].fNq->Fill(fIsHeavy[iq]);
285 Int_t motherID[fgkMaxGener];
286 Int_t motherType[fgkMaxGener];
287 Int_t motherLabel[fgkMaxGener];
288 Int_t ancestorPdg[fgkMaxGener];
289 Int_t ancestorLabel[fgkMaxGener];
291 for (Int_t i = 0; i < fgkMaxGener; i++){ // initialization
296 ancestorLabel[i] = 0;
299 // check history of found heavy quarks
300 for (Int_t i = 0; i < fIsHeavy[iq]; i++){
302 ancestorLabel[0] = i;
303 ancestorPdg[0] = fHeavyQuark[i]->GetPdgCode();
304 ancestorLabel[1] = fHeavyQuark[i]->GetFirstMother();
306 AliDebug(1,Form("pdg code= %d\n",ancestorPdg[0]));
307 AliDebug(1,Form("ancestor label= %d\n",ancestorLabel[1]));
310 while (ancestorLabel[ig] != -1){
311 // in case there is mother, get mother's pdg code and grandmother's label
312 IdentifyMother(ancestorLabel[ig], ancestorPdg[ig], ancestorLabel[ig+1]);
313 // if mother is still heavy, find again mother's ancestor
314 if (ancestorPdg[ig-1] == ancestorPdg[ig]) {
316 continue; // if it is from same heavy
318 // if the heavy's mother is not heavy, check the mother's label to know if it comes from inital or final parton shower
319 if (IsFromInitialShower(ancestorLabel[ig],motherID[i],motherType[i],motherLabel[i])) break;
320 if (IsFromFinalParton(ancestorLabel[ig],motherID[i],motherType[i],motherLabel[i])) break;
321 // if it is not the above case, something is strange
322 ReportStrangeness(motherID[i],motherType[i],motherLabel[i]);
325 if (ancestorLabel[ig] == -1){ // from hard scattering
326 HardScattering(kquark, motherID[i],motherType[i], motherLabel[i]);
329 } // end of found heavy quark loop
332 // check process type
334 for (Int_t i = 0; i < fIsHeavy[iq]; i++){
335 AliDebug(1,Form("Mother ID= %d type= %d label= %d\n",motherID[i],motherType[i],motherLabel[i]));
339 Int_t nheavypair = Int_t(fIsHeavy[iq]/2.);
340 for (Int_t ipair = 0; ipair < nheavypair; ipair++){
343 Int_t id2 = ipair*2 + 1;
345 if (motherType[id1] == 2 && motherType[id2] == 2){
346 if (motherLabel[id1] == motherLabel[id2]) processID = kGluonSplitting; // gluon spliting
349 else if (motherType[id1] == -1 && motherType[id2] == -1) {
350 if (motherLabel[id1] == -1 && motherLabel[id2] == -1) {
351 if (motherID[id1] == fgkGluon) processID = kPairCreationFromg; // gluon fusion
352 else processID = kPairCreationFromq; // q-qbar pair creation
356 else if (motherType[id1] == -1 || motherType[id2] == -1) {
357 if ((motherLabel[id1] == -1 || motherLabel[id2] == -1) && (motherLabel[id1]*motherLabel[id2] == -2 || motherLabel[id1]*motherLabel[id2] == -3)) {
358 if(motherID[id1]*motherID[id2] == kquark*fgkGluon) processID = kFlavourExitation; // flavour exitation
359 else processID = kLightQuarkShower;
363 else if (motherType[id1] == -2 || motherType[id2] == -2) {
364 if (motherLabel[id1] == motherLabel[id2]) processID = kInitialPartonShower; // initial parton shower
370 if (nheavypair >1) AliDebug(1,Form("Multi pair found : process ID = %d\n",processID));
371 else fHistComm[iq][0].fProcessID->Fill(processID);
372 AliDebug(1,Form("Process ID = %d\n",processID));
373 } // end of # heavy quark pair loop
377 //__________________________________________
378 void AliHFEmcQA::GetHadronKine(TParticle* mcpart, const Int_t kquark)
380 // decay electron kinematics
382 if (kquark != kCharm && kquark != kBeauty) {
383 AliDebug(1, "This task is only for heavy quark QA, return\n");
386 Int_t iq = kquark - kCharm;
388 //TParticle* mcpart = fStack->Particle(iTrack);
390 Int_t iLabel = mcpart->GetFirstMother();
392 AliDebug(1, "Stack label is negative, return\n");
396 TParticle *partCopy = mcpart;
397 Int_t pdgcode = mcpart->GetPdgCode();
398 Int_t pdgcodeCopy = pdgcode;
400 // if the mother is charmed hadron
401 Bool_t isDirectCharm = kFALSE;
402 if ( int(abs(pdgcode)/100.) == kCharm || int(abs(pdgcode)/1000.) == kCharm ) {
404 // iterate until you find B hadron as a mother or become top ancester
405 for (Int_t i=1; i<fgkMaxIter; i++){
407 Int_t jLabel = mcpart->GetFirstMother();
409 isDirectCharm = kTRUE;
410 break; // if there is no ancester
412 if (jLabel < 0){ // safety protection
413 AliDebug(1, "Stack label is negative, return\n");
416 // if there is an ancester
417 TParticle* mother = fStack->Particle(jLabel);
418 Int_t motherPDG = mother->GetPdgCode();
420 for (Int_t j=0; j<fNparents; j++){
421 if (abs(motherPDG)==fParentSelect[1][j]) return; // return if this hadron is originated from b
425 } // end of iteration
427 if((isDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
428 for (Int_t i=0; i<fNparents; i++){
429 if (abs(pdgcodeCopy)==fParentSelect[iq][i]){
431 // fill hadron kinematics
432 fHist[iq][kHadron][0].fPdgCode->Fill(pdgcodeCopy);
433 fHist[iq][kHadron][0].fPt->Fill(partCopy->Pt());
434 fHist[iq][kHadron][0].fY->Fill(GetRapidity(partCopy));
435 fHist[iq][kHadron][0].fEta->Fill(partCopy->Eta());
442 //__________________________________________
443 void AliHFEmcQA::GetDecayedKine(TParticle* mcpart, const Int_t kquark, Int_t kdecayed, Int_t icut)
445 // decay electron kinematics
447 if (kquark != kCharm && kquark != kBeauty) {
448 AliDebug(1, "This task is only for heavy quark QA, return\n");
451 Int_t iq = kquark - kCharm;
452 Bool_t isFinalOpenCharm = kFALSE;
456 AliDebug(1, "Stack label is negative, return\n");
461 //TParticle* mcpart = fStack->Particle(iTrack);
463 if ( abs(mcpart->GetPdgCode()) != kdecayed ) return;
465 Int_t iLabel = mcpart->GetFirstMother();
467 AliDebug(1, "Stack label is negative, return\n");
471 TParticle *partMother = fStack->Particle(iLabel);
472 TParticle *partMotherCopy = partMother;
473 Int_t maPdgcode = partMother->GetPdgCode();
474 Int_t maPdgcodeCopy = maPdgcode;
476 // get mc primary vertex
478 if(fMCHeader) fMCHeader->PrimaryVertex(mcPrimVtx);
480 // get electron production vertex
481 TLorentzVector ePoint;
482 mcpart->ProductionVertex(ePoint);
484 // calculated production vertex to primary vertex (in xy plane)
485 Float_t decayLxy = TMath::Sqrt((mcPrimVtx[0]-ePoint[0])*(mcPrimVtx[0]-ePoint[0])+(mcPrimVtx[1]-ePoint[1])*(mcPrimVtx[1]-ePoint[1]));
487 // if the mother is charmed hadron
488 Bool_t isMotherDirectCharm = kFALSE;
489 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
491 for (Int_t i=0; i<fNparents; i++){
492 if (abs(maPdgcode)==fParentSelect[0][i]){
493 isFinalOpenCharm = kTRUE;
496 if (!isFinalOpenCharm) return ;
498 // iterate until you find B hadron as a mother or become top ancester
499 for (Int_t i=1; i<fgkMaxIter; i++){
501 Int_t jLabel = partMother->GetFirstMother();
503 isMotherDirectCharm = kTRUE;
504 break; // if there is no ancester
506 if (jLabel < 0){ // safety protection
507 AliDebug(1, "Stack label is negative, return\n");
511 // if there is an ancester
512 TParticle* grandMa = fStack->Particle(jLabel);
513 Int_t grandMaPDG = grandMa->GetPdgCode();
515 for (Int_t j=0; j<fNparents; j++){
516 if (abs(grandMaPDG)==fParentSelect[1][j]){
518 if (kquark == kCharm) return;
519 // fill electron kinematics
520 fHist[iq][kElectron2nd][icut].fPdgCode->Fill(mcpart->GetPdgCode());
521 fHist[iq][kElectron2nd][icut].fPt->Fill(mcpart->Pt());
522 fHist[iq][kElectron2nd][icut].fY->Fill(GetRapidity(mcpart));
523 fHist[iq][kElectron2nd][icut].fEta->Fill(mcpart->Eta());
525 // fill mother hadron kinematics
526 fHist[iq][kDeHadron][icut].fPdgCode->Fill(grandMaPDG);
527 fHist[iq][kDeHadron][icut].fPt->Fill(grandMa->Pt());
528 fHist[iq][kDeHadron][icut].fY->Fill(GetRapidity(grandMa));
529 fHist[iq][kDeHadron][icut].fEta->Fill(grandMa->Eta());
531 // ratio between pT of electron and pT of mother B hadron
532 if(grandMa->Pt()) fHistComm[iq][icut].fDePtRatio->Fill(grandMa->Pt(),mcpart->Pt()/grandMa->Pt());
534 // distance between electron production point and primary vertex
535 fHistComm[iq][icut].fDeDistance->Fill(grandMa->Pt(),decayLxy);
540 partMother = grandMa;
541 } // end of iteration
543 if((isMotherDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
544 for (Int_t i=0; i<fNparents; i++){
545 if (abs(maPdgcodeCopy)==fParentSelect[iq][i]){
547 // fill electron kinematics
548 fHist[iq][kElectron][icut].fPdgCode->Fill(mcpart->GetPdgCode());
549 fHist[iq][kElectron][icut].fPt->Fill(mcpart->Pt());
550 fHist[iq][kElectron][icut].fY->Fill(GetRapidity(mcpart));
551 fHist[iq][kElectron][icut].fEta->Fill(mcpart->Eta());
553 // fill mother hadron kinematics
554 fHist[iq][keHadron][icut].fPdgCode->Fill(maPdgcodeCopy);
555 fHist[iq][keHadron][icut].fPt->Fill(partMotherCopy->Pt());
556 fHist[iq][keHadron][icut].fY->Fill(GetRapidity(partMotherCopy));
557 fHist[iq][keHadron][icut].fEta->Fill(partMotherCopy->Eta());
559 // ratio between pT of electron and pT of mother B hadron
560 if(partMotherCopy->Pt()) fHistComm[iq][icut].fePtRatio->Fill(partMotherCopy->Pt(),mcpart->Pt()/partMotherCopy->Pt());
562 // distance between electron production point and primary vertex
563 fHistComm[iq][icut].feDistance->Fill(partMotherCopy->Pt(),decayLxy);
569 //____________________________________________________________________
570 void AliHFEmcQA::GetDecayedKine(AliAODMCParticle *mcpart, const Int_t kquark, Int_t kdecayed, Int_t icut)
572 // decay electron kinematics
574 if (kquark != kCharm && kquark != kBeauty) {
575 AliDebug(1, "This task is only for heavy quark QA, return\n");
579 Int_t iq = kquark - kCharm;
580 Bool_t isFinalOpenCharm = kFALSE;
582 if ( abs(mcpart->GetPdgCode()) != kdecayed ) return;
585 Int_t iLabel = mcpart->GetMother();
587 AliDebug(1, "Stack label is negative, return\n");
591 AliAODMCParticle *partMother = (AliAODMCParticle*)fMCArray->At(iLabel);
592 AliAODMCParticle *partMotherCopy = partMother;
593 Int_t maPdgcode = partMother->GetPdgCode();
594 Int_t maPdgcodeCopy = maPdgcode;
596 Bool_t isMotherDirectCharm = kFALSE;
597 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
599 for (Int_t i=0; i<fNparents; i++){
600 if (abs(maPdgcode)==fParentSelect[0][i]){
601 isFinalOpenCharm = kTRUE;
604 if (!isFinalOpenCharm) return;
606 for (Int_t i=1; i<fgkMaxIter; i++){
608 Int_t jLabel = partMother->GetMother();
610 isMotherDirectCharm = kTRUE;
611 break; // if there is no ancester
613 if (jLabel < 0){ // safety protection
614 AliDebug(1, "Stack label is negative, return\n");
618 // if there is an ancester
619 AliAODMCParticle* grandMa = (AliAODMCParticle*)fMCArray->At(jLabel);
620 Int_t grandMaPDG = grandMa->GetPdgCode();
622 for (Int_t j=0; j<fNparents; j++){
623 if (abs(grandMaPDG)==fParentSelect[1][j]){
625 if (kquark == kCharm) return;
626 // fill electron kinematics
627 fHist[iq][kElectron2nd][icut].fPdgCode->Fill(mcpart->GetPdgCode());
628 fHist[iq][kElectron2nd][icut].fPt->Fill(mcpart->Pt());
629 fHist[iq][kElectron2nd][icut].fY->Fill(GetRapidity(mcpart));
630 fHist[iq][kElectron2nd][icut].fEta->Fill(mcpart->Eta());
632 // fill mother hadron kinematics
633 fHist[iq][kDeHadron][icut].fPdgCode->Fill(grandMaPDG);
634 fHist[iq][kDeHadron][icut].fPt->Fill(grandMa->Pt());
635 fHist[iq][kDeHadron][icut].fY->Fill(GetRapidity(grandMa));
636 fHist[iq][kDeHadron][icut].fEta->Fill(grandMa->Eta());
642 partMother = grandMa;
643 } // end of iteration
645 if ((isMotherDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
646 for (Int_t i=0; i<fNparents; i++){
647 if (abs(maPdgcodeCopy)==fParentSelect[iq][i]){
649 // fill electron kinematics
650 fHist[iq][kElectron][icut].fPdgCode->Fill(mcpart->GetPdgCode());
651 fHist[iq][kElectron][icut].fPt->Fill(mcpart->Pt());
652 fHist[iq][kElectron][icut].fY->Fill(GetRapidity(mcpart));
653 fHist[iq][kElectron][icut].fEta->Fill(mcpart->Eta());
655 // fill mother hadron kinematics
656 fHist[iq][keHadron][icut].fPdgCode->Fill(maPdgcodeCopy);
657 fHist[iq][keHadron][icut].fPt->Fill(partMotherCopy->Pt());
658 fHist[iq][keHadron][icut].fY->Fill(GetRapidity(partMotherCopy));
659 fHist[iq][keHadron][icut].fEta->Fill(partMotherCopy->Eta());
667 //__________________________________________
668 void AliHFEmcQA::IdentifyMother(Int_t motherlabel, Int_t &motherpdg, Int_t &grandmotherlabel)
670 // find mother pdg code and label
672 if (motherlabel < 0) {
673 AliDebug(1, "Stack label is negative, return\n");
676 TParticle *heavysMother = fStack->Particle(motherlabel);
677 motherpdg = heavysMother->GetPdgCode();
678 grandmotherlabel = heavysMother->GetFirstMother();
679 AliDebug(1,Form("ancestor pdg code= %d\n",motherpdg));
682 //__________________________________________
683 void AliHFEmcQA::HardScattering(const Int_t kquark, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
685 // mothertype -1 means this heavy quark coming from hard vertex
687 TParticle *afterinitialrad1 = fStack->Particle(4);
688 TParticle *afterinitialrad2 = fStack->Particle(5);
692 if (abs(afterinitialrad1->GetPdgCode()) == fgkGluon && abs(afterinitialrad2->GetPdgCode()) == fgkGluon){
693 AliDebug(1,"heavy from gluon gluon pair creation!\n");
697 else if (abs(afterinitialrad1->GetPdgCode()) == kquark || abs(afterinitialrad2->GetPdgCode()) == kquark){ // one from Q and the other from g
698 AliDebug(1,"heavy from flavor exitation!\n");
702 else if (abs(afterinitialrad1->GetPdgCode()) == abs(afterinitialrad2->GetPdgCode())){
703 AliDebug(1,"heavy from q-qbar pair creation!\n");
708 AliDebug(1,"something strange!\n");
715 //__________________________________________
716 Bool_t AliHFEmcQA::IsFromInitialShower(Int_t inputmotherlabel, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
718 // mothertype -2 means this heavy quark coming from initial state
720 if (inputmotherlabel==2 || inputmotherlabel==3){ // mother exist before initial state radiation
721 TParticle *heavysMother = fStack->Particle(inputmotherlabel);
722 motherID = heavysMother->GetPdgCode();
723 mothertype = -2; // there is mother before initial state radiation
724 motherlabel = inputmotherlabel;
725 AliDebug(1,"initial parton shower! \n");
733 //__________________________________________
734 Bool_t AliHFEmcQA::IsFromFinalParton(Int_t inputmotherlabel, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
736 // mothertype 2 means this heavy quark coming from final state
738 if (inputmotherlabel > 5){ // mother exist after hard scattering
739 TParticle *heavysMother = fStack->Particle(inputmotherlabel);
740 motherID = heavysMother->GetPdgCode();
742 motherlabel = inputmotherlabel;
743 AliDebug(1,Form("heavy quark from %d after hard scattering! \n",motherID));
750 //__________________________________________
751 void AliHFEmcQA::ReportStrangeness(Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
753 // mark strange behavior
758 AliDebug(1,"something strange!\n");
761 //__________________________________________
762 Float_t AliHFEmcQA::GetRapidity(TParticle *part) const
767 if(!((part->Energy() - part->Pz())*(part->Energy() + part->Pz())>0)) rapidity=-999;
768 else rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));
772 //__________________________________________
773 Float_t AliHFEmcQA::GetRapidity(AliAODMCParticle *part) const
778 if(!((part->E() - part->Pz())*(part->E() + part->Pz())>0)) rapidity=-999;
779 else rapidity = 0.5*(TMath::Log((part->E()+part->Pz()) / (part->E()-part->Pz())));
783 //__________________________________________
784 Int_t AliHFEmcQA::GetSource(AliAODMCParticle * const mcpart)
786 // decay particle's origin
788 //if ( abs(mcpart->GetPdgCode()) != AliHFEmcQA::kElectronPDG ) return -1;
791 Bool_t isFinalOpenCharm = kFALSE;
794 Int_t iLabel = mcpart->GetMother();
796 AliDebug(1, "Stack label is negative, return\n");
800 AliAODMCParticle *partMother = (AliAODMCParticle*)fMCArray->At(iLabel);
801 Int_t maPdgcode = partMother->GetPdgCode();
803 // if the mother is charmed hadron
804 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
806 for (Int_t i=0; i<fNparents; i++){
807 if (abs(maPdgcode)==fParentSelect[0][i]){
808 isFinalOpenCharm = kTRUE;
811 if (!isFinalOpenCharm) return -1;
813 // iterate until you find B hadron as a mother or become top ancester
814 for (Int_t i=1; i<fgkMaxIter; i++){
816 Int_t jLabel = partMother->GetMother();
818 origin = kDirectCharm;
821 if (jLabel < 0){ // safety protection
822 AliDebug(1, "Stack label is negative, return\n");
826 // if there is an ancester
827 AliAODMCParticle* grandMa = (AliAODMCParticle*)fMCArray->At(jLabel);
828 Int_t grandMaPDG = grandMa->GetPdgCode();
830 for (Int_t j=0; j<fNparents; j++){
831 if (abs(grandMaPDG)==fParentSelect[1][j]){
832 origin = kBeautyCharm;
837 partMother = grandMa;
838 } // end of iteration
840 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
841 for (Int_t i=0; i<fNparents; i++){
842 if (abs(maPdgcode)==fParentSelect[1][i]){
843 origin = kDirectBeauty;
848 else if ( abs(maPdgcode) == 22 ) {
852 else if ( abs(maPdgcode) == 111 ) {
860 //__________________________________________
861 Int_t AliHFEmcQA::GetSource(TParticle * const mcpart)
863 // decay particle's origin
865 //if ( abs(mcpart->GetPdgCode()) != AliHFEmcQA::kElectronPDG ) return -1;
868 Bool_t isFinalOpenCharm = kFALSE;
870 Int_t iLabel = mcpart->GetFirstMother();
872 AliDebug(1, "Stack label is negative, return\n");
876 TParticle *partMother = fStack->Particle(iLabel);
877 Int_t maPdgcode = partMother->GetPdgCode();
879 // if the mother is charmed hadron
880 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
882 for (Int_t i=0; i<fNparents; i++){
883 if (abs(maPdgcode)==fParentSelect[0][i]){
884 isFinalOpenCharm = kTRUE;
887 if (!isFinalOpenCharm) return -1;
889 // iterate until you find B hadron as a mother or become top ancester
890 for (Int_t i=1; i<fgkMaxIter; i++){
892 Int_t jLabel = partMother->GetFirstMother();
894 origin = kDirectCharm;
897 if (jLabel < 0){ // safety protection
898 AliDebug(1, "Stack label is negative, return\n");
902 // if there is an ancester
903 TParticle* grandMa = fStack->Particle(jLabel);
904 Int_t grandMaPDG = grandMa->GetPdgCode();
906 for (Int_t j=0; j<fNparents; j++){
907 if (abs(grandMaPDG)==fParentSelect[1][j]){
908 origin = kBeautyCharm;
913 partMother = grandMa;
914 } // end of iteration
916 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
917 for (Int_t i=0; i<fNparents; i++){
918 if (abs(maPdgcode)==fParentSelect[1][i]){
919 origin = kDirectBeauty;
924 else if ( abs(maPdgcode) == 22 ) {
928 else if ( abs(maPdgcode) == 111 ) {