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>
34 #include <TParticle.h>
37 #include <AliMCEvent.h>
38 #include <AliGenEventHeader.h>
39 #include <AliAODMCParticle.h>
42 #include "AliHFEmcQA.h"
43 #include "AliHFEtools.h"
44 #include "AliHFEcollection.h"
48 //_______________________________________________________________________________________________
49 AliHFEmcQA::AliHFEmcQA() :
54 ,fMCQACollection(NULL)
58 ,fIsppMultiBin(kFALSE)
60 // Default constructor
61 for(Int_t mom = 0; mom < 9; mom++){
64 for(Int_t mom = 0; mom < 50; mom++){
65 fHeavyQuark[mom] = NULL;
67 for(Int_t mom = 0; mom < 2; mom++){
70 memset(fElecBackgroundFactor, 0, sizeof(Double_t) * kElecBgSpecies * kBgPtBins * kCentBins * kBgLevels);
71 memset(fBinLimit, 0, sizeof(Double_t) * (kBgPtBins+1));
74 //_______________________________________________________________________________________________
75 AliHFEmcQA::AliHFEmcQA(const AliHFEmcQA&p):
80 ,fQAhistos(p.fQAhistos)
81 ,fMCQACollection(p.fMCQACollection)
82 ,fNparents(p.fNparents)
85 ,fIsppMultiBin(kFALSE)
88 for(Int_t mom = 0; mom < 9; mom++){
91 for(Int_t mom = 0; mom < 50; mom++){
92 fHeavyQuark[mom] = NULL;
94 for(Int_t mom = 0; mom < 2; mom++){
97 memset(fElecBackgroundFactor, 0, sizeof(Double_t) * kElecBgSpecies * kBgPtBins * kCentBins * kBgLevels);
98 memset(fBinLimit, 0, sizeof(Double_t) * (kBgPtBins+1));
101 //_______________________________________________________________________________________________
103 AliHFEmcQA::operator=(const AliHFEmcQA &)
105 // Assignment operator
107 AliInfo("Not yet implemented.");
111 //_______________________________________________________________________________________________
112 AliHFEmcQA::~AliHFEmcQA()
116 AliInfo("Analysis Done.");
119 //_______________________________________________________________________________________________
120 void AliHFEmcQA::PostAnalyze() const
127 //_______________________________________________________________________________________________
128 void AliHFEmcQA::SetBackgroundWeightFactor(Double_t *elecBackgroundFactor, Double_t *binLimit)
131 // copy background weighting factors into data member
134 memcpy(fElecBackgroundFactor,elecBackgroundFactor,sizeof(Double_t) * kElecBgSpecies * kBgPtBins * kCentBins * kBgLevels);
135 memcpy(fBinLimit,binLimit,sizeof(Double_t) * (kBgPtBins+1));
138 //__________________________________________
139 void AliHFEmcQA::CreatDefaultHistograms(TList * const qaList)
142 // make default histograms
148 fQAhistos->SetName("MCqa");
150 CreateHistograms(AliHFEmcQA::kCharm,0,"mcqa_"); // create histograms for charm
151 CreateHistograms(AliHFEmcQA::kBeauty,0,"mcqa_"); // create histograms for beauty
152 CreateHistograms(AliHFEmcQA::kOthers,0,"mcqa_"); // create histograms for beauty
153 CreateHistograms(AliHFEmcQA::kCharm,1,"mcqa_barrel_"); // create histograms for charm
154 CreateHistograms(AliHFEmcQA::kBeauty,1,"mcqa_barrel_"); // create histograms for beauty
155 CreateHistograms(AliHFEmcQA::kOthers,1,"mcqa_barrel_"); // create histograms for beauty
156 CreateHistograms(AliHFEmcQA::kCharm,2,"mcqa_unitY_"); // create histograms for charm
157 CreateHistograms(AliHFEmcQA::kBeauty,2,"mcqa_unitY_"); // create histograms for beauty
158 CreateHistograms(AliHFEmcQA::kOthers,2,"mcqa_unitY_"); // create histograms for beauty
160 // prepare 2D(pt vs Y) histogram for D spectra, we consider following 9 particles
161 const Int_t nbspecies = 9;
162 TString kDspecies[nbspecies];
163 kDspecies[0]="411"; //D+
164 kDspecies[1]="421"; //D0
165 kDspecies[2]="431"; //Ds+
166 kDspecies[3]="4122"; //Lambdac+
167 kDspecies[4]="4132"; //Ksic0
168 kDspecies[5]="4232"; //Ksic+
169 kDspecies[6]="4332"; //OmegaC0
170 kDspecies[7]="413"; //D*(2010)+
171 kDspecies[8]="423"; //D*(2007)0
173 const Double_t kPtbound[2] = {0.1, 20.}; //bin taken for considering inclusive e analysis binning
175 iBin[0] = 44; // bins in pt for log binning
176 iBin[1] = 23; // bins in pt for pi0 measurement binning
177 Double_t* binEdges[1];
178 binEdges[0] = AliHFEtools::MakeLogarithmicBinning(iBin[0], kPtbound[0], kPtbound[1]);
180 // bin size is chosen to consider ALICE D measurement
181 const Int_t nptbins = 15;
182 const Int_t nybins = 9;
183 Double_t xbins[nptbins+1]={0,0.5,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,12,16,24,32,40,50}; //pt binning for the final 7 TeV D measurement
184 Double_t ybins[nybins+1]={-7.5,-1.0,-0.9,-0.8,-0.5,0.5,0.8,0.9,1.0,7.5}; // y binning
186 for (Int_t iDmeson=0; iDmeson<nbspecies; iDmeson++){
187 hname = "Dmeson"+kDspecies[iDmeson];
188 fhD[iDmeson] = new TH2F(hname,hname+";p_{T} (GeV/c)",nptbins,xbins,nybins,ybins);
189 if(fQAhistos) fQAhistos->Add(fhD[iDmeson]);
192 const Double_t kPtRange[24] = {0.,0.3,0.4,0.5,0.6,0.8,1.,1.2,1.4,1.6,1.8,2.,2.2,2.4,2.6,2.8,3.,3.5,4.,5.,6.,7.,20.,30.}; // to cope with Ana's bin
195 if(fIsPbPb) kNcent=11;
198 if(fIsppMultiBin) kNcent=8;
202 fMCQACollection = new AliHFEcollection("TaskMCQA", "MC QA histos for meason pt spectra");
204 for(Int_t centbin=0; centbin<kNcent; centbin++)
206 fMCQACollection->CreateTH1Farray(Form("pionspectra_centrbin%i",centbin), "pion yields: MC p_{t} ", iBin[1],kPtRange);
207 fMCQACollection->CreateTH1Farray(Form("etaspectra_centrbin%i",centbin), "eta yields: MC p_{t} ", iBin[1],kPtRange);
208 fMCQACollection->CreateTH1Farray(Form("omegaspectra_centrbin%i",centbin), "omega yields: MC p_{t} ", iBin[1],kPtRange);
209 fMCQACollection->CreateTH1Farray(Form("phispectra_centrbin%i",centbin), "phi yields: MC p_{t} ", iBin[1],kPtRange);
210 fMCQACollection->CreateTH1Farray(Form("etapspectra_centrbin%i",centbin), "etap yields: MC p_{t} ", iBin[1],kPtRange);
211 fMCQACollection->CreateTH1Farray(Form("rhospectra_centrbin%i",centbin), "rho yields: MC p_{t} ", iBin[1],kPtRange);
213 fMCQACollection->CreateTH1F(Form("pionspectraLog_centrbin%i",centbin), "pion yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
214 fMCQACollection->CreateTH1F(Form("etaspectraLog_centrbin%i",centbin), "eta yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
215 fMCQACollection->CreateTH1F(Form("omegaspectraLog_centrbin%i",centbin), "omega yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
216 fMCQACollection->CreateTH1F(Form("phispectraLog_centrbin%i",centbin), "phi yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
217 fMCQACollection->CreateTH1F(Form("etapspectraLog_centrbin%i",centbin), "etap yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
218 fMCQACollection->CreateTH1F(Form("rhospectraLog_centrbin%i",centbin), "rho yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
219 fMCQACollection->CreateTH1F(Form("kaonspectraLog_centrbin%i",centbin), "kaon yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
220 fMCQACollection->CreateTH1F(Form("k0LspectraLog_centrbin%i",centbin), "k0L yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
222 fMCQACollection->CreateTH1F(Form("piondaughters_centrbin%i",centbin), "pion yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
223 fMCQACollection->CreateTH1F(Form("etadaughters_centrbin%i",centbin), "eta yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
224 fMCQACollection->CreateTH1F(Form("omegadaughters_centrbin%i",centbin), "omega yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
225 fMCQACollection->CreateTH1F(Form("phidaughters_centrbin%i",centbin), "phi yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
226 fMCQACollection->CreateTH1F(Form("etapdaughters_centrbin%i",centbin), "etap yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
227 fMCQACollection->CreateTH1F(Form("rhodaughters_centrbin%i",centbin), "rho yields: MC p_{t} ", iBin[0],kPtbound[0], kPtbound[1], 1);
230 fQAhistos->Add(fMCQACollection->GetList());
234 //__________________________________________
235 void AliHFEmcQA::CreateHistograms(const Int_t kquark, Int_t icut, TString hnopt)
239 if (!(kquark == kCharm || kquark == kBeauty || kquark == kOthers)) {
240 AliDebug(1, "This task is only for heavy quark QA, return\n");
243 Int_t iq = kquark - kCharm;
245 TString kqTypeLabel[fgkqType];
246 if (kquark == kCharm){
247 kqTypeLabel[kQuark]="c";
248 kqTypeLabel[kantiQuark]="cbar";
249 kqTypeLabel[kHadron]="cHadron";
250 kqTypeLabel[keHadron]="ceHadron";
251 kqTypeLabel[kDeHadron]="nullHadron";
252 kqTypeLabel[kElectron]="ce";
253 kqTypeLabel[kElectron2nd]="nulle";
254 } else if (kquark == kBeauty){
255 kqTypeLabel[kQuark]="b";
256 kqTypeLabel[kantiQuark]="bbar";
257 kqTypeLabel[kHadron]="bHadron";
258 kqTypeLabel[keHadron]="beHadron";
259 kqTypeLabel[kDeHadron]="bDeHadron";
260 kqTypeLabel[kElectron]="be";
261 kqTypeLabel[kElectron2nd]="bce";
262 } else if (kquark == kOthers){
263 kqTypeLabel[kGamma-4]="gammae";
264 kqTypeLabel[kPi0-4]="pi0e";
265 kqTypeLabel[kElse-4]="elsee";
266 kqTypeLabel[kMisID-4]="miside";
269 const Double_t kPtbound[2] = {0.1, 20.}; //bin taken for considering inclusive e analysis binning
270 const Int_t nptbinning1 = 35;
272 iBin[0] = 44; // bins in pt
273 iBin[1] = nptbinning1; // bins in pt
274 Double_t* binEdges[1];
275 binEdges[0] = AliHFEtools::MakeLogarithmicBinning(iBin[0], kPtbound[0], kPtbound[1]);
277 // new binning for final electron analysis
278 const Double_t kPtbinning1[nptbinning1+1] = {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1., 1.1, 1.2, 1.3, 1.4, 1.5, 1.75, 2., 2.25, 2.5, 2.75, 3., 3.5, 4., 4.5, 5., 5.5, 6., 7., 8., 10., 12., 14., 16., 18., 20.};
280 const Int_t ndptbins = 500;
281 Double_t xcorrbin[ndptbins+1];
282 for (int icorrbin = 0; icorrbin< ndptbins+1; icorrbin++){
283 xcorrbin[icorrbin]=icorrbin*0.1;
287 if(kquark == kOthers){
288 for (Int_t iqType = 0; iqType < 4; iqType++ ){
289 hname = hnopt+"Pt_"+kqTypeLabel[iqType];
290 //fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",iBin[0],binEdges[0]); //mj to compare with FONLL
291 fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",60,0.25,30.25);
292 hname = hnopt+"Y_"+kqTypeLabel[iqType];
293 fHist[iq][iqType][icut].fY = new TH1F(hname,hname,150,-7.5,7.5);
294 hname = hnopt+"Eta_"+kqTypeLabel[iqType];
295 fHist[iq][iqType][icut].fEta = new TH1F(hname,hname,150,-7.5,7.5);
297 if(fQAhistos) fHist[iq][iqType][icut].FillList(fQAhistos);
301 for (Int_t iqType = 0; iqType < fgkqType; iqType++ ){
302 if (iqType < keHadron && icut > 0) continue; // don't duplicate histogram for quark and hadron
303 hname = hnopt+"PdgCode_"+kqTypeLabel[iqType];
304 fHist[iq][iqType][icut].fPdgCode = new TH1F(hname,hname,20001,-10000.5,10000.5);
305 hname = hnopt+"Pt_"+kqTypeLabel[iqType];
306 fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",iBin[1],kPtbinning1); // new binning
307 //fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",iBin[0],binEdges[0]); // old log binning
308 //fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",60,0.,30.); // mj to compare with FONLL
309 //fHist[iq][iqType][icut].fPt = new TH1F(hname,hname+";p_{T} (GeV/c)",60,0.25,30.25); // mj to compare with FONLL
310 hname = hnopt+"Y_"+kqTypeLabel[iqType];
311 fHist[iq][iqType][icut].fY = new TH1F(hname,hname,150,-7.5,7.5);
312 hname = hnopt+"Eta_"+kqTypeLabel[iqType];
313 fHist[iq][iqType][icut].fEta = new TH1F(hname,hname,150,-7.5,7.5);
315 if(fQAhistos) fHist[iq][iqType][icut].FillList(fQAhistos);
319 hname = hnopt+"Nq_"+kqTypeLabel[kQuark];
320 fHistComm[iq][icut].fNq = new TH1F(hname,hname,50,-0.5,49.5);
321 hname = hnopt+"ProcessID_"+kqTypeLabel[kQuark];
322 fHistComm[iq][icut].fProcessID = new TH1F(hname,hname,21,-10.5,10.5);
324 hname = hnopt+"PtCorr_"+kqTypeLabel[kQuark];
325 fHistComm[iq][icut].fPtCorr = new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[1],kPtbinning1); // new binning
326 //fHistComm[iq][icut].fPtCorr = new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[0],binEdges[0]);
327 hname = hnopt+"PtCorrDp_"+kqTypeLabel[kQuark];
328 fHistComm[iq][icut].fPtCorrDp= new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[1],kPtbinning1); // new binning
329 //fHistComm[iq][icut].fPtCorrDp= new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[0],binEdges[0]);
330 hname = hnopt+"PtCorrD0_"+kqTypeLabel[kQuark];
331 fHistComm[iq][icut].fPtCorrD0 = new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[1],kPtbinning1); // new binning
332 //fHistComm[iq][icut].fPtCorrD0 = new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[0],binEdges[0]);
333 hname = hnopt+"PtCorrDrest_"+kqTypeLabel[kQuark];
334 fHistComm[iq][icut].fPtCorrDrest = new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[1],kPtbinning1); // new binning
335 //fHistComm[iq][icut].fPtCorrDrest = new TH2F(hname,hname+";D p_{T} (GeV/c);e p_{T} (GeV/c)",ndptbins,xcorrbin,iBin[0],binEdges[0]);
337 hname = hnopt+"ePtRatio_"+kqTypeLabel[kQuark];
338 fHistComm[iq][icut].fePtRatio = new TH2F(hname,hname+";p_{T} (GeV/c);momentum fraction",200,0,20,100,0,1);
339 hname = hnopt+"DePtRatio_"+kqTypeLabel[kQuark];
340 fHistComm[iq][icut].fDePtRatio = new TH2F(hname,hname+";p_{T} (GeV/c);momentum fraction",100,0,20,100,0,1);
341 hname = hnopt+"eDistance_"+kqTypeLabel[kQuark];
342 fHistComm[iq][icut].feDistance= new TH2F(hname,hname+";p_{T} (GeV/c);distance (cm)",100,0,20,200,0,2);
343 hname = hnopt+"DeDistance_"+kqTypeLabel[kQuark];
344 fHistComm[iq][icut].fDeDistance= new TH2F(hname,hname+";p_{T} (GeV/c);distance (cm)",100,0,20,200,0,2);
345 if(fQAhistos) fHistComm[iq][icut].FillList(fQAhistos);
348 //__________________________________________
349 void AliHFEmcQA::Init()
351 // called at begining every event
353 for (Int_t i=0; i<2; i++){
359 fParentSelect[0][0] = 411; //D+
360 fParentSelect[0][1] = 421; //D0
361 fParentSelect[0][2] = 431; //Ds+
362 fParentSelect[0][3] = 4122; //Lambdac+
363 fParentSelect[0][4] = 4132; //Ksic0
364 fParentSelect[0][5] = 4232; //Ksic+
365 fParentSelect[0][6] = 4332; //OmegaC0
367 fParentSelect[1][0] = 511; //B0
368 fParentSelect[1][1] = 521; //B+
369 fParentSelect[1][2] = 531; //Bs0
370 fParentSelect[1][3] = 5122; //Lambdab0
371 fParentSelect[1][4] = 5132; //Ksib-
372 fParentSelect[1][5] = 5232; //Ksib0
373 fParentSelect[1][6] = 5332; //Omegab-
377 //__________________________________________
378 void AliHFEmcQA::GetMesonKine()
381 // get meson pt spectra
384 AliVParticle *mctrack2 = NULL;
385 AliMCParticle *mctrack0 = NULL;
386 AliVParticle *mctrackdaugt= NULL;
387 AliMCParticle *mctrackd= NULL;
391 if(fCentrality>11) printf("warning centrality out of histogram array limits \n");
394 for(Int_t imc = 0; imc <fMCEvent->GetNumberOfPrimaries(); imc++){
395 if(!(mctrack2 = fMCEvent->GetTrack(imc))) continue;
396 TParticle* mcpart0 = fMCEvent->Stack()->Particle(imc);
397 if(!mcpart0) continue;
398 mctrack0 = dynamic_cast<AliMCParticle *>(mctrack2);
399 if(!mctrack0) continue;
401 if(!fIsPbPb&&!fIsppMultiBin) fCentrality=0;
403 if(abs(mctrack0->PdgCode()) == 111) // pi0
405 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
406 fMCQACollection->Fill(Form("pionspectra_centrbin%i",fCentrality),mctrack0->Pt());
407 fMCQACollection->Fill(Form("pionspectraLog_centrbin%i",fCentrality),mctrack0->Pt());
409 id1=mctrack0->GetFirstDaughter();
410 id2=mctrack0->GetLastDaughter();
411 if(!((id2-id1)==2)) continue;
412 for(int idx=id1; idx<=id2; idx++){
413 if(!(mctrackdaugt = fMCEvent->GetTrack(idx))) continue;
414 if(!(mctrackd = dynamic_cast<AliMCParticle *>(mctrackdaugt))) continue;
415 if(abs(mctrackd->PdgCode()) == 11 && TMath::Abs(mctrackd->Eta())<0.8)
416 fMCQACollection->Fill(Form("piondaughters_centrbin%i",fCentrality),mctrackd->Pt());
419 else if(abs(mctrack0->PdgCode()) == 221) // eta
421 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
422 fMCQACollection->Fill(Form("etaspectra_centrbin%i",fCentrality),mctrack0->Pt());
423 fMCQACollection->Fill(Form("etaspectraLog_centrbin%i",fCentrality),mctrack0->Pt());
425 id1=mctrack0->GetFirstDaughter();
426 id2=mctrack0->GetLastDaughter();
427 if(!((id2-id1)==2||(id2-id1)==3)) continue;
428 for(int idx=id1; idx<=id2; idx++){
429 if(!(mctrackdaugt = fMCEvent->GetTrack(idx))) continue;
430 if(!(mctrackd = dynamic_cast<AliMCParticle *>(mctrackdaugt))) continue;
431 if(abs(mctrackd->PdgCode()) == 11 && TMath::Abs(mctrackd->Eta())<0.8)
432 fMCQACollection->Fill(Form("etadaughters_centrbin%i",fCentrality),mctrackd->Pt());
435 else if(abs(mctrack0->PdgCode()) == 223) // omega
437 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
438 fMCQACollection->Fill(Form("omegaspectra_centrbin%i",fCentrality),mctrack0->Pt());
439 fMCQACollection->Fill(Form("omegaspectraLog_centrbin%i",fCentrality),mctrack0->Pt());
441 id1=mctrack0->GetFirstDaughter();
442 id2=mctrack0->GetLastDaughter();
443 if(!((id2-id1)==1||(id2-id1)==2)) continue;
444 for(int idx=id1; idx<=id2; idx++){
445 if(!(mctrackdaugt = fMCEvent->GetTrack(idx))) continue;
446 if(!(mctrackd = dynamic_cast<AliMCParticle *>(mctrackdaugt))) continue;
447 if(abs(mctrackd->PdgCode()) == 11 && TMath::Abs(mctrackd->Eta())<0.8)
448 fMCQACollection->Fill(Form("omegadaughters_centrbin%i",fCentrality),mctrackd->Pt());
451 else if(abs(mctrack0->PdgCode()) == 333) // phi
453 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
454 fMCQACollection->Fill(Form("phispectra_centrbin%i",fCentrality),mctrack0->Pt());
455 fMCQACollection->Fill(Form("phispectraLog_centrbin%i",fCentrality),mctrack0->Pt());
457 id1=mctrack0->GetFirstDaughter();
458 id2=mctrack0->GetLastDaughter();
459 if(!((id2-id1)==1)) continue;
460 for(int idx=id1; idx<=id2; idx++){
461 if(!(mctrackdaugt = fMCEvent->GetTrack(idx))) continue;
462 if(!(mctrackd = dynamic_cast<AliMCParticle *>(mctrackdaugt))) continue;
463 if(abs(mctrackd->PdgCode()) == 11 && TMath::Abs(mctrackd->Eta())<0.8)
464 fMCQACollection->Fill(Form("phidaughters_centrbin%i",fCentrality),mctrackd->Pt());
467 else if(abs(mctrack0->PdgCode()) == 331) // eta prime
469 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
470 fMCQACollection->Fill(Form("etapspectra_centrbin%i",fCentrality),mctrack0->Pt());
471 fMCQACollection->Fill(Form("etapspectraLog_centrbin%i",fCentrality),mctrack0->Pt());
473 id1=mctrack0->GetFirstDaughter();
474 id2=mctrack0->GetLastDaughter();
475 if(!((id2-id1)==2||(id2-id1)==3)) continue;
476 for(int idx=id1; idx<=id2; idx++){
477 if(!(mctrackdaugt = fMCEvent->GetTrack(idx))) continue;
478 if(!(mctrackd = dynamic_cast<AliMCParticle *>(mctrackdaugt))) continue;
479 if(abs(mctrackd->PdgCode()) == 11 && TMath::Abs(mctrackd->Eta())<0.8)
480 fMCQACollection->Fill(Form("etapdaughters_centrbin%i",fCentrality),mctrackd->Pt());
483 else if(abs(mctrack0->PdgCode()) == 113) // rho
485 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
486 fMCQACollection->Fill(Form("rhospectra_centrbin%i",fCentrality),mctrack0->Pt());
487 fMCQACollection->Fill(Form("rhospectraLog_centrbin%i",fCentrality),mctrack0->Pt());
489 id1=mctrack0->GetFirstDaughter();
490 id2=mctrack0->GetLastDaughter();
491 if(!((id2-id1)==1)) continue;
492 for(int idx=id1; idx<=id2; idx++){
493 if(!(mctrackdaugt = fMCEvent->GetTrack(idx))) continue;
494 if(!(mctrackd = dynamic_cast<AliMCParticle *>(mctrackdaugt))) continue;
495 if(abs(mctrackd->PdgCode()) == 11 && TMath::Abs(mctrackd->Eta())<0.8)
496 fMCQACollection->Fill(Form("rhodaughters_centrbin%i",fCentrality),mctrackd->Pt());
499 else if(abs(mctrack0->PdgCode()) == 321) // kaon+-
501 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
502 fMCQACollection->Fill(Form("kaonspectraLog_centrbin%i",fCentrality),mctrack0->Pt());
505 else if(abs(mctrack0->PdgCode()) == 130) // k0L
507 if(TMath::Abs(AliHFEtools::GetRapidity(mcpart0))<0.8) {
508 fMCQACollection->Fill(Form("k0LspectraLog_centrbin%i",fCentrality),mctrack0->Pt());
514 //__________________________________________
515 void AliHFEmcQA::GetQuarkKine(TParticle *part, Int_t iTrack, const Int_t kquark)
517 // get heavy quark kinematics
519 if (kquark != kCharm && kquark != kBeauty) {
520 AliDebug(1, "This task is only for heavy quark QA, return\n");
523 Int_t iq = kquark - kCharm;
525 if (iTrack < 0 || !part) {
526 AliDebug(1, "Stack label is negative or no mcparticle, return\n");
530 AliMCParticle *mctrack = NULL;
531 Int_t partPdgcode = TMath::Abs(part->GetPdgCode());
533 // select heavy hadron or not fragmented heavy quark
534 if ( int(partPdgcode/100.)==kquark || int(partPdgcode/1000.)==kquark || (partPdgcode==kquark && (part->GetNDaughters()==0 && iTrack>5)) ){
536 TParticle *partMother;
539 if (partPdgcode == kquark){ // in case of not fragmented heavy quark
542 } else{ // in case of heavy hadron, start to search for mother heavy parton
543 iLabel = part->GetFirstMother();
544 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return;
545 if (iLabel>-1) { partMother = mctrack->Particle(); }
547 AliDebug(1, "Stack label is negative, return\n");
552 // heavy parton selection as a mother of heavy hadron
553 // if the heavy particle comes from string which is denoted as particle status 12|12|12...12|11,[PYTHIA p.60]
554 // in this case, the mother of heavy particle can be one of the fragmented parton of the string
555 // should I make a condition that partMother should be quark or diquark? -> not necessary
556 if ( abs(partMother->GetPdgCode()) == kquark || (partMother->GetStatusCode() == 11) ){
557 //if ( abs(partMother->GetPdgCode()) == kquark || (partMother->GetStatusCode() == 11 || partMother->GetStatusCode() == 12) ){
559 if ( abs(partMother->GetPdgCode()) != kquark ){
560 // search fragmented partons in the same string
561 Bool_t isSameString = kTRUE;
562 for (Int_t i=1; i<fgkMaxIter; i++){
564 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return;
565 if (iLabel>-1) { partMother = mctrack->Particle(); }
567 AliDebug(1, "Stack label is negative, return\n");
570 if ( abs(partMother->GetPdgCode()) == kquark ) break;
571 if ( partMother->GetStatusCode() != 12 ) isSameString = kFALSE;
572 if (!isSameString) return;
575 AliDebug(1, "Can not find heavy parton of this heavy hadron in the string, return\n");
576 if (abs(partMother->GetPdgCode()) != kquark) return;
578 if (fIsHeavy[iq] >= 50) return;
579 fHeavyQuark[fIsHeavy[iq]] = partMother;
582 // fill kinematics for heavy parton
583 if (partMother->GetPdgCode() > 0) { // quark
584 fHist[iq][kQuark][0].fPdgCode->Fill(partMother->GetPdgCode());
585 fHist[iq][kQuark][0].fPt->Fill(partMother->Pt());
586 fHist[iq][kQuark][0].fY->Fill(AliHFEtools::GetRapidity(partMother));
587 fHist[iq][kQuark][0].fEta->Fill(partMother->Eta());
589 fHist[iq][kantiQuark][0].fPdgCode->Fill(partMother->GetPdgCode());
590 fHist[iq][kantiQuark][0].fPt->Fill(partMother->Pt());
591 fHist[iq][kantiQuark][0].fY->Fill(AliHFEtools::GetRapidity(partMother));
592 fHist[iq][kantiQuark][0].fEta->Fill(partMother->Eta());
595 } // end of heavy parton slection loop
597 } // end of heavy hadron or quark selection
601 //__________________________________________
602 void AliHFEmcQA::EndOfEventAna(const Int_t kquark)
604 // end of event analysis
606 if (kquark != kCharm && kquark != kBeauty) {
607 AliDebug(1, "This task is only for heavy quark QA, return\n");
610 Int_t iq = kquark - kCharm;
613 // # of heavy quark per event
614 AliDebug(1,Form("Number of heavy quark in this event = %d \n",fIsHeavy[iq]));
615 fHistComm[iq][0].fNq->Fill(fIsHeavy[iq]);
617 Int_t motherID[fgkMaxGener];
618 Int_t motherType[fgkMaxGener];
619 Int_t motherLabel[fgkMaxGener];
620 Int_t ancestorPdg[fgkMaxGener];
621 Int_t ancestorLabel[fgkMaxGener];
623 for (Int_t i = 0; i < fgkMaxGener; i++){ // initialization
628 ancestorLabel[i] = 0;
632 // check history of found heavy quarks
633 for (Int_t i = 0; i < fIsHeavy[iq]; i++){
635 if(!fHeavyQuark[i]) return;
637 ancestorLabel[0] = i;
638 ancestorPdg[0] = fHeavyQuark[i]->GetPdgCode();
639 ancestorLabel[1] = fHeavyQuark[i]->GetFirstMother();
641 AliDebug(1,Form("pdg code= %d\n",ancestorPdg[0]));
642 AliDebug(1,Form("ancestor label= %d\n",ancestorLabel[1]));
645 while (ancestorLabel[ig] != -1){
646 // in case there is mother, get mother's pdg code and grandmother's label
647 IdentifyMother(ancestorLabel[ig], ancestorPdg[ig], ancestorLabel[ig+1]);
648 // if mother is still heavy, find again mother's ancestor
649 if (ancestorPdg[ig-1] == ancestorPdg[ig]) {
651 continue; // if it is from same heavy
653 // if the heavy's mother is not heavy, check the mother's label to know if it comes from inital or final parton shower
654 if (IsFromInitialShower(ancestorLabel[ig],motherID[i],motherType[i],motherLabel[i])) break;
655 if (IsFromFinalParton(ancestorLabel[ig],motherID[i],motherType[i],motherLabel[i])) break;
656 // if it is not the above case, something is strange
657 ReportStrangeness(motherID[i],motherType[i],motherLabel[i]);
660 if (ancestorLabel[ig] == -1){ // from hard scattering
661 HardScattering(kquark, motherID[i],motherType[i], motherLabel[i]);
664 } // end of found heavy quark loop
667 // check process type
669 for (Int_t i = 0; i < fIsHeavy[iq]; i++){
670 AliDebug(1,Form("Mother ID= %d type= %d label= %d\n",motherID[i],motherType[i],motherLabel[i]));
674 Int_t nheavypair = Int_t(fIsHeavy[iq]/2.);
675 for (Int_t ipair = 0; ipair < nheavypair; ipair++){
678 Int_t id2 = ipair*2 + 1;
680 if (motherType[id1] == 2 && motherType[id2] == 2){
681 if (motherLabel[id1] == motherLabel[id2]) processID = kGluonSplitting; // gluon spliting
684 else if (motherType[id1] == -1 && motherType[id2] == -1) {
685 if (motherLabel[id1] == -1 && motherLabel[id2] == -1) {
686 if (motherID[id1] == fgkGluon) processID = kPairCreationFromg; // gluon fusion
687 else processID = kPairCreationFromq; // q-qbar pair creation
691 else if (motherType[id1] == -1 || motherType[id2] == -1) {
692 if ((motherLabel[id1] == -1 || motherLabel[id2] == -1) && (motherLabel[id1]*motherLabel[id2] == -2 || motherLabel[id1]*motherLabel[id2] == -3)) {
693 if(motherID[id1]*motherID[id2] == kquark*fgkGluon) processID = kFlavourExitation; // flavour exitation
694 else processID = kLightQuarkShower;
698 else if (motherType[id1] == -2 || motherType[id2] == -2) {
699 if (motherLabel[id1] == motherLabel[id2]) processID = kInitialPartonShower; // initial parton shower
705 if (nheavypair >1) AliDebug(1,Form("Multi pair found : process ID = %d\n",processID));
706 else fHistComm[iq][0].fProcessID->Fill(processID);
707 AliDebug(1,Form("Process ID = %d\n",processID));
708 } // end of # heavy quark pair loop
712 //__________________________________________
713 void AliHFEmcQA::GetHadronKine(TParticle* mcpart, const Int_t kquark)
715 // decay electron kinematics
717 if (kquark != kCharm && kquark != kBeauty) {
718 AliDebug(1, "This task is only for heavy quark QA, return\n");
721 Int_t iq = kquark - kCharm;
724 AliDebug(1, "no mc particle, return\n");
728 Int_t iLabel = mcpart->GetFirstMother();
730 AliDebug(1, "Stack label is negative, return\n");
734 TParticle *partCopy = mcpart;
735 Int_t pdgcode = mcpart->GetPdgCode();
736 Int_t pdgcodeCopy = pdgcode;
738 AliMCParticle *mctrack = NULL;
740 // if the mother is charmed hadron
741 Bool_t isDirectCharm = kFALSE;
742 if ( int(abs(pdgcode)/100.) == kCharm || int(abs(pdgcode)/1000.) == kCharm ) {
744 // iterate until you find B hadron as a mother or become top ancester
745 for (Int_t i=1; i<fgkMaxIter; i++){
747 Int_t jLabel = mcpart->GetFirstMother();
749 isDirectCharm = kTRUE;
750 break; // if there is no ancester
752 if (jLabel < 0){ // safety protection
753 AliDebug(1, "Stack label is negative, return\n");
756 // if there is an ancester
757 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return;
758 TParticle* mother = mctrack->Particle();
759 Int_t motherPDG = mother->GetPdgCode();
761 for (Int_t j=0; j<fNparents; j++){
762 if (abs(motherPDG)==fParentSelect[1][j]) return; // return if this hadron is originated from b
766 } // end of iteration
768 if((isDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
769 for (Int_t i=0; i<fNparents; i++){
770 if (abs(pdgcodeCopy)==fParentSelect[iq][i]){
772 // fill hadron kinematics
773 fHist[iq][kHadron][0].fPdgCode->Fill(pdgcodeCopy);
774 fHist[iq][kHadron][0].fPt->Fill(partCopy->Pt());
775 fHist[iq][kHadron][0].fY->Fill(AliHFEtools::GetRapidity(partCopy));
776 fHist[iq][kHadron][0].fEta->Fill(partCopy->Eta());
779 fhD[i]->Fill(partCopy->Pt(),AliHFEtools::GetRapidity(partCopy));
783 // I also want to store D* info to compare with D* measurement
784 if (abs(pdgcodeCopy)==413 && iq==0) { //D*+
785 fhD[7]->Fill(partCopy->Pt(),AliHFEtools::GetRapidity(partCopy));
787 if (abs(pdgcodeCopy)==423 && iq==0) { //D*0
788 fhD[8]->Fill(partCopy->Pt(),AliHFEtools::GetRapidity(partCopy));
793 //__________________________________________
794 void AliHFEmcQA::GetDecayedKine(TParticle* mcpart, const Int_t kquark, Int_t kdecayed, Int_t icut)
796 // decay electron kinematics
798 if (!(kquark == kCharm || kquark == kBeauty || kquark == kOthers)){
799 AliDebug(1, "This task is only for heavy quark QA, return\n");
802 Int_t iq = kquark - kCharm;
803 Bool_t isFinalOpenCharm = kFALSE;
806 AliDebug(1, "no mcparticle, return\n");
812 if ( abs(mcpart->GetPdgCode()) != kdecayed ) esource = kMisID-4;
813 else esource =GetSource(mcpart)-4; // return for the cases kGamma=4, kPi0=5, kElse=6
814 if(esource==0|| esource==1 || esource==2 || esource==3){
815 fHist[iq][esource][icut].fPt->Fill(mcpart->Pt());
816 fHist[iq][esource][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart));
817 fHist[iq][esource][icut].fEta->Fill(mcpart->Eta());
821 AliDebug(1, "e source is out of defined ranges, return\n");
826 if ( abs(mcpart->GetPdgCode()) != kdecayed ) return;
828 Int_t iLabel = mcpart->GetFirstMother();
830 AliDebug(1, "Stack label is negative, return\n");
834 AliMCParticle *mctrack = NULL;
835 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return;
836 TParticle *partMother = mctrack->Particle();
837 TParticle *partMotherCopy = partMother;
838 Int_t maPdgcode = partMother->GetPdgCode();
839 Int_t maPdgcodeCopy = maPdgcode;
841 // get mc primary vertex
844 if(fMCHeader) fMCHeader->PrimaryVertex(mcPrimVtx);
846 // get electron production vertex
847 TLorentzVector ePoint;
848 mcpart->ProductionVertex(ePoint);
850 // calculated production vertex to primary vertex (in xy plane)
851 Float_t decayLxy = TMath::Sqrt((mcPrimVtx[0]-ePoint[0])*(mcPrimVtx[0]-ePoint[0])+(mcPrimVtx[1]-ePoint[1])*(mcPrimVtx[1]-ePoint[1]));
853 Float_t decayLxy = 0;
855 // if the mother is charmed hadron
856 Bool_t isMotherDirectCharm = kFALSE;
857 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
859 for (Int_t i=0; i<fNparents; i++){
860 if (abs(maPdgcode)==fParentSelect[0][i]){
861 isFinalOpenCharm = kTRUE;
864 if (!isFinalOpenCharm) return ;
866 // iterate until you find B hadron as a mother or become top ancester
867 for (Int_t i=1; i<fgkMaxIter; i++){
869 Int_t jLabel = partMother->GetFirstMother();
871 isMotherDirectCharm = kTRUE;
872 break; // if there is no ancester
874 if (jLabel < 0){ // safety protection
875 AliDebug(1, "Stack label is negative, return\n");
879 // if there is an ancester
880 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return;
881 TParticle* grandMa = mctrack->Particle();
882 Int_t grandMaPDG = grandMa->GetPdgCode();
884 for (Int_t j=0; j<fNparents; j++){
885 if (abs(grandMaPDG)==fParentSelect[1][j]){
887 if (kquark == kCharm) return;
888 // fill electron kinematics
889 fHist[iq][kElectron2nd][icut].fPdgCode->Fill(mcpart->GetPdgCode());
890 fHist[iq][kElectron2nd][icut].fPt->Fill(mcpart->Pt());
891 fHist[iq][kElectron2nd][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart));
892 fHist[iq][kElectron2nd][icut].fEta->Fill(mcpart->Eta());
894 // fill mother hadron kinematics
895 fHist[iq][kDeHadron][icut].fPdgCode->Fill(grandMaPDG);
896 fHist[iq][kDeHadron][icut].fPt->Fill(grandMa->Pt());
897 fHist[iq][kDeHadron][icut].fY->Fill(AliHFEtools::GetRapidity(grandMa));
898 fHist[iq][kDeHadron][icut].fEta->Fill(grandMa->Eta());
900 // ratio between pT of electron and pT of mother B hadron
901 if(grandMa->Pt()) fHistComm[iq][icut].fDePtRatio->Fill(grandMa->Pt(),mcpart->Pt()/grandMa->Pt());
903 // distance between electron production point and primary vertex
904 fHistComm[iq][icut].fDeDistance->Fill(grandMa->Pt(),decayLxy);
909 partMother = grandMa;
910 } // end of iteration
912 if((isMotherDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
913 for (Int_t i=0; i<fNparents; i++){
914 if (abs(maPdgcodeCopy)==fParentSelect[iq][i]){
916 //mj weighting to consider measured spectra!!!
917 Double_t mpt=partMotherCopy->Pt();
918 Double_t wfactor=2*(703.681*mpt/TMath::Power((1+TMath::Power(mpt/1.73926,2)),2.34821))/(368.608*mpt/TMath::Power((1+TMath::Power(mpt/2.74868,2)),2.34225)); // 2* considering in pythia I used particle + antiparticle differently from the measurement
919 //Double_t wfactor=(703.681*mpt/TMath::Power((1+TMath::Power(mpt/1.73926,2)),2.34821))/(368.608*mpt/TMath::Power((1+TMath::Power(mpt/2.74868,2)),2.34225));
920 // fill electron kinematics
922 fHist[iq][kElectron2nd][icut].fPdgCode->Fill(mcpart->GetPdgCode(),wfactor);
923 fHist[iq][kElectron2nd][icut].fPt->Fill(mcpart->Pt(),wfactor);
924 fHist[iq][kElectron2nd][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart),wfactor);
925 fHist[iq][kElectron2nd][icut].fEta->Fill(mcpart->Eta(),wfactor);
927 fHist[iq][kElectron][icut].fPdgCode->Fill(mcpart->GetPdgCode());
928 fHist[iq][kElectron][icut].fPt->Fill(mcpart->Pt());
929 fHist[iq][kElectron][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart));
930 fHist[iq][kElectron][icut].fEta->Fill(mcpart->Eta());
933 fHist[iq][kElectron][icut].fPdgCode->Fill(mcpart->GetPdgCode());
934 fHist[iq][kElectron][icut].fPt->Fill(mcpart->Pt());
935 fHist[iq][kElectron][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart));
936 fHist[iq][kElectron][icut].fEta->Fill(mcpart->Eta());
939 // fill mother hadron kinematics
940 fHist[iq][keHadron][icut].fPdgCode->Fill(maPdgcodeCopy);
941 fHist[iq][keHadron][icut].fPt->Fill(partMotherCopy->Pt());
942 fHist[iq][keHadron][icut].fY->Fill(AliHFEtools::GetRapidity(partMotherCopy));
943 fHist[iq][keHadron][icut].fEta->Fill(partMotherCopy->Eta());
945 // ratio between pT of electron and pT of mother B or direct D hadron
946 if(partMotherCopy->Pt()) fHistComm[iq][icut].fePtRatio->Fill(partMotherCopy->Pt(),mcpart->Pt()/partMotherCopy->Pt());
947 fHistComm[iq][icut].fPtCorr->Fill(partMotherCopy->Pt(),mcpart->Pt());
948 if(TMath::Abs(partMotherCopy->GetPdgCode())==411) fHistComm[iq][icut].fPtCorrDp->Fill(partMotherCopy->Pt(),mcpart->Pt());
949 else if(TMath::Abs(partMotherCopy->GetPdgCode())==421) fHistComm[iq][icut].fPtCorrD0->Fill(partMotherCopy->Pt(),mcpart->Pt());
950 else fHistComm[iq][icut].fPtCorrDrest->Fill(partMotherCopy->Pt(),mcpart->Pt());
952 // distance between electron production point and primary vertex
953 fHistComm[iq][icut].feDistance->Fill(partMotherCopy->Pt(),decayLxy);
959 //____________________________________________________________________
960 void AliHFEmcQA::GetDecayedKine(AliAODMCParticle *mcpart, const Int_t kquark, Int_t kdecayed, Int_t icut)
962 // decay electron kinematics
964 if (kquark != kCharm && kquark != kBeauty) {
965 AliDebug(1, "This task is only for heavy quark QA, return\n");
969 Int_t iq = kquark - kCharm;
970 Bool_t isFinalOpenCharm = kFALSE;
973 AliDebug(1, "no mcparticle, return\n");
977 if ( abs(mcpart->GetPdgCode()) != kdecayed ) return;
980 Int_t iLabel = mcpart->GetMother();
982 AliDebug(1, "Stack label is negative, return\n");
986 AliAODMCParticle *partMother = (AliAODMCParticle*)fMCArray->At(iLabel);
987 AliAODMCParticle *partMotherCopy = partMother;
988 Int_t maPdgcode = partMother->GetPdgCode();
989 Int_t maPdgcodeCopy = maPdgcode;
991 Bool_t isMotherDirectCharm = kFALSE;
992 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
994 for (Int_t i=0; i<fNparents; i++){
995 if (abs(maPdgcode)==fParentSelect[0][i]){
996 isFinalOpenCharm = kTRUE;
999 if (!isFinalOpenCharm) return;
1001 for (Int_t i=1; i<fgkMaxIter; i++){
1003 Int_t jLabel = partMother->GetMother();
1005 isMotherDirectCharm = kTRUE;
1006 break; // if there is no ancester
1008 if (jLabel < 0){ // safety protection
1009 AliDebug(1, "Stack label is negative, return\n");
1013 // if there is an ancester
1014 AliAODMCParticle* grandMa = (AliAODMCParticle*)fMCArray->At(jLabel);
1015 Int_t grandMaPDG = grandMa->GetPdgCode();
1017 for (Int_t j=0; j<fNparents; j++){
1018 if (abs(grandMaPDG)==fParentSelect[1][j]){
1020 if (kquark == kCharm) return;
1021 // fill electron kinematics
1022 fHist[iq][kElectron2nd][icut].fPdgCode->Fill(mcpart->GetPdgCode());
1023 fHist[iq][kElectron2nd][icut].fPt->Fill(mcpart->Pt());
1024 fHist[iq][kElectron2nd][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart));
1025 fHist[iq][kElectron2nd][icut].fEta->Fill(mcpart->Eta());
1027 // fill mother hadron kinematics
1028 fHist[iq][kDeHadron][icut].fPdgCode->Fill(grandMaPDG);
1029 fHist[iq][kDeHadron][icut].fPt->Fill(grandMa->Pt());
1030 fHist[iq][kDeHadron][icut].fY->Fill(AliHFEtools::GetRapidity(grandMa));
1031 fHist[iq][kDeHadron][icut].fEta->Fill(grandMa->Eta());
1037 partMother = grandMa;
1038 } // end of iteration
1040 if ((isMotherDirectCharm == kTRUE && kquark == kCharm) || kquark == kBeauty) {
1041 for (Int_t i=0; i<fNparents; i++){
1042 if (abs(maPdgcodeCopy)==fParentSelect[iq][i]){
1044 // fill electron kinematics
1045 fHist[iq][kElectron][icut].fPdgCode->Fill(mcpart->GetPdgCode());
1046 fHist[iq][kElectron][icut].fPt->Fill(mcpart->Pt());
1047 fHist[iq][kElectron][icut].fY->Fill(AliHFEtools::GetRapidity(mcpart));
1048 fHist[iq][kElectron][icut].fEta->Fill(mcpart->Eta());
1050 // fill mother hadron kinematics
1051 fHist[iq][keHadron][icut].fPdgCode->Fill(maPdgcodeCopy);
1052 fHist[iq][keHadron][icut].fPt->Fill(partMotherCopy->Pt());
1053 fHist[iq][keHadron][icut].fY->Fill(AliHFEtools::GetRapidity(partMotherCopy));
1054 fHist[iq][keHadron][icut].fEta->Fill(partMotherCopy->Eta());
1062 //__________________________________________
1063 void AliHFEmcQA::IdentifyMother(Int_t motherlabel, Int_t &motherpdg, Int_t &grandmotherlabel)
1065 // find mother pdg code and label
1067 if (motherlabel < 0) {
1068 AliDebug(1, "Stack label is negative, return\n");
1071 AliMCParticle *mctrack = NULL;
1072 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(motherlabel))))) return;
1073 TParticle *heavysMother = mctrack->Particle();
1074 motherpdg = heavysMother->GetPdgCode();
1075 grandmotherlabel = heavysMother->GetFirstMother();
1076 AliDebug(1,Form("ancestor pdg code= %d\n",motherpdg));
1079 //__________________________________________
1080 void AliHFEmcQA::HardScattering(const Int_t kquark, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
1082 // mothertype -1 means this heavy quark coming from hard vertex
1084 AliMCParticle *mctrack1 = NULL;
1085 AliMCParticle *mctrack2 = NULL;
1086 if(!(mctrack1 = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(4))))) return;
1087 if(!(mctrack2 = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(5))))) return;
1088 TParticle *afterinitialrad1 = mctrack1->Particle();
1089 TParticle *afterinitialrad2 = mctrack2->Particle();
1093 if (abs(afterinitialrad1->GetPdgCode()) == fgkGluon && abs(afterinitialrad2->GetPdgCode()) == fgkGluon){
1094 AliDebug(1,"heavy from gluon gluon pair creation!\n");
1096 motherID = fgkGluon;
1098 else if (abs(afterinitialrad1->GetPdgCode()) == kquark || abs(afterinitialrad2->GetPdgCode()) == kquark){ // one from Q and the other from g
1099 AliDebug(1,"heavy from flavor exitation!\n");
1103 else if (abs(afterinitialrad1->GetPdgCode()) == abs(afterinitialrad2->GetPdgCode())){
1104 AliDebug(1,"heavy from q-qbar pair creation!\n");
1109 AliDebug(1,"something strange!\n");
1116 //__________________________________________
1117 Bool_t AliHFEmcQA::IsFromInitialShower(Int_t inputmotherlabel, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
1119 // mothertype -2 means this heavy quark coming from initial state
1121 AliMCParticle *mctrack = NULL;
1122 if (inputmotherlabel==2 || inputmotherlabel==3){ // mother exist before initial state radiation
1123 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(inputmotherlabel))))) return kFALSE;
1124 TParticle *heavysMother = mctrack->Particle();
1125 motherID = heavysMother->GetPdgCode();
1126 mothertype = -2; // there is mother before initial state radiation
1127 motherlabel = inputmotherlabel;
1128 AliDebug(1,"initial parton shower! \n");
1136 //__________________________________________
1137 Bool_t AliHFEmcQA::IsFromFinalParton(Int_t inputmotherlabel, Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
1139 // mothertype 2 means this heavy quark coming from final state
1141 AliMCParticle *mctrack = NULL;
1142 if (inputmotherlabel > 5){ // mother exist after hard scattering
1143 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(inputmotherlabel))))) return kFALSE;
1144 TParticle *heavysMother = mctrack->Particle();
1145 motherID = heavysMother->GetPdgCode();
1147 motherlabel = inputmotherlabel;
1148 AliDebug(1,Form("heavy quark from %d after hard scattering! \n",motherID));
1155 //__________________________________________
1156 void AliHFEmcQA::ReportStrangeness(Int_t &motherID, Int_t &mothertype, Int_t &motherlabel)
1158 // mark strange behavior
1163 AliDebug(1,"something strange!\n");
1166 //__________________________________________
1167 Int_t AliHFEmcQA::GetSource(const AliAODMCParticle * const mcpart)
1169 // decay particle's origin
1171 //if ( abs(mcpart->GetPdgCode()) != AliHFEmcQA::kElectronPDG ) return -1;
1174 Bool_t isFinalOpenCharm = kFALSE;
1177 AliDebug(1, "Stack label is negative or no mcparticle, return\n");
1182 Int_t iLabel = mcpart->GetMother();
1184 AliDebug(1, "Stack label is negative, return\n");
1188 AliAODMCParticle *partMother = (AliAODMCParticle*)fMCArray->At(iLabel);
1189 Int_t maPdgcode = partMother->GetPdgCode();
1191 // if the mother is charmed hadron
1192 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
1194 for (Int_t i=0; i<fNparents; i++){
1195 if (abs(maPdgcode)==fParentSelect[0][i]){
1196 isFinalOpenCharm = kTRUE;
1199 if (!isFinalOpenCharm) return -1;
1201 // iterate until you find B hadron as a mother or become top ancester
1202 for (Int_t i=1; i<fgkMaxIter; i++){
1204 Int_t jLabel = partMother->GetMother();
1206 origin = kDirectCharm;
1209 if (jLabel < 0){ // safety protection
1210 AliDebug(1, "Stack label is negative, return\n");
1214 // if there is an ancester
1215 AliAODMCParticle* grandMa = (AliAODMCParticle*)fMCArray->At(jLabel);
1216 Int_t grandMaPDG = grandMa->GetPdgCode();
1218 for (Int_t j=0; j<fNparents; j++){
1219 if (abs(grandMaPDG)==fParentSelect[1][j]){
1220 origin = kBeautyCharm;
1225 partMother = grandMa;
1226 } // end of iteration
1228 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
1229 for (Int_t i=0; i<fNparents; i++){
1230 if (abs(maPdgcode)==fParentSelect[1][i]){
1231 origin = kDirectBeauty;
1236 else if ( abs(maPdgcode) == 22 ) {
1240 else if ( abs(maPdgcode) == 111 ) {
1248 //__________________________________________
1249 Int_t AliHFEmcQA::GetSource(const TParticle * const mcpart)
1251 // decay particle's origin
1253 //if ( abs(mcpart->GetPdgCode()) != AliHFEmcQA::kElectronPDG ) return -1;
1256 Bool_t isFinalOpenCharm = kFALSE;
1259 AliDebug(1, "no mcparticle, return\n");
1263 Int_t iLabel = mcpart->GetFirstMother();
1265 AliDebug(1, "Stack label is negative, return\n");
1269 AliMCParticle *mctrack = NULL;
1270 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return -1;
1271 TParticle *partMother = mctrack->Particle();
1272 Int_t maPdgcode = partMother->GetPdgCode();
1274 // if the mother is charmed hadron
1275 if ( int(abs(maPdgcode)/100.) == kCharm || int(abs(maPdgcode)/1000.) == kCharm ) {
1277 for (Int_t i=0; i<fNparents; i++){
1278 if (abs(maPdgcode)==fParentSelect[0][i]){
1279 isFinalOpenCharm = kTRUE;
1282 if (!isFinalOpenCharm) return -1;
1284 // iterate until you find B hadron as a mother or become top ancester
1285 for (Int_t i=1; i<fgkMaxIter; i++){
1287 Int_t jLabel = partMother->GetFirstMother();
1289 origin = kDirectCharm;
1292 if (jLabel < 0){ // safety protection
1293 AliDebug(1, "Stack label is negative, return\n");
1297 // if there is an ancester
1298 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1299 TParticle* grandMa = mctrack->Particle();
1300 Int_t grandMaPDG = grandMa->GetPdgCode();
1302 for (Int_t j=0; j<fNparents; j++){
1303 if (abs(grandMaPDG)==fParentSelect[1][j]){
1304 origin = kBeautyCharm;
1309 partMother = grandMa;
1310 } // end of iteration
1312 else if ( int(abs(maPdgcode)/100.) == kBeauty || int(abs(maPdgcode)/1000.) == kBeauty ) {
1313 for (Int_t i=0; i<fNparents; i++){
1314 if (abs(maPdgcode)==fParentSelect[1][i]){
1315 origin = kDirectBeauty;
1320 else if ( abs(maPdgcode) == 22 ) {
1324 else if ( abs(maPdgcode) == 111 ) {
1328 else origin = kElse;
1333 //__________________________________________
1334 Int_t AliHFEmcQA::GetElecSource(TParticle * const mcpart)
1336 // decay particle's origin
1339 AliDebug(1, "no mcparticle, return\n");
1343 if ( abs(mcpart->GetPdgCode()) != AliHFEmcQA::kElectronPDG ) return kMisID;
1346 Bool_t isFinalOpenCharm = kFALSE;
1348 Int_t iLabel = mcpart->GetFirstMother();
1350 AliDebug(1, "Stack label is negative, return\n");
1354 AliMCParticle *mctrack = NULL;
1355 Int_t tmpMomLabel=0;
1356 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(iLabel))))) return -1;
1357 TParticle *partMother = mctrack->Particle();
1358 TParticle *partMotherCopy = mctrack->Particle();
1359 Int_t maPdgcode = partMother->GetPdgCode();
1361 // if the mother is charmed hadron
1362 if ( (int(abs(maPdgcode)/100.)%10) == kCharm || (int(abs(maPdgcode)/1000.)%10) == kCharm ) {
1364 for (Int_t i=0; i<fNparents; i++){
1365 if (abs(maPdgcode)==fParentSelect[0][i]){
1366 isFinalOpenCharm = kTRUE;
1369 if (!isFinalOpenCharm) return -1;
1371 // iterate until you find B hadron as a mother or become top ancester
1372 for (Int_t i=1; i<fgkMaxIter; i++){
1374 Int_t jLabel = partMother->GetFirstMother();
1376 origin = kDirectCharm;
1379 if (jLabel < 0){ // safety protection
1380 AliDebug(1, "Stack label is negative, return\n");
1384 // if there is an ancester
1385 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(jLabel))))) return -1;
1386 TParticle* grandMa = mctrack->Particle();
1387 Int_t grandMaPDG = grandMa->GetPdgCode();
1389 for (Int_t j=0; j<fNparents; j++){
1390 if (abs(grandMaPDG)==fParentSelect[1][j]){
1391 origin = kBeautyCharm;
1396 partMother = grandMa;
1397 } // end of iteration
1399 else if ( (int(abs(maPdgcode)/100.)%10) == kBeauty || (int(abs(maPdgcode)/1000.)%10) == kBeauty ) {
1400 for (Int_t i=0; i<fNparents; i++){
1401 if (abs(maPdgcode)==fParentSelect[1][i]){
1402 origin = kDirectBeauty;
1407 else if ( abs(maPdgcode) == 22 ) { //conversion
1409 tmpMomLabel = partMotherCopy->GetFirstMother();
1410 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(tmpMomLabel))))) return -1;
1411 partMother = mctrack->Particle();
1412 maPdgcode = partMother->GetPdgCode();
1413 if ( abs(maPdgcode) == 111 ) {
1417 else if ( abs(maPdgcode) == 221 ) {
1421 else if ( abs(maPdgcode) == 223 ) {
1422 origin = kGammaOmega;
1425 else if ( abs(maPdgcode) == 333 ) {
1429 else if ( abs(maPdgcode) == 331 ) {
1430 origin = kGammaEtaPrime;
1433 else if ( abs(maPdgcode) == 113 ) {
1434 origin = kGammaRho0;
1437 else origin = kElse;
1438 //origin = kGamma; // finer category above
1442 else if ( abs(maPdgcode) == 111 ) {
1446 else if ( abs(maPdgcode) == 221 ) {
1450 else if ( abs(maPdgcode) == 223 ) {
1454 else if ( abs(maPdgcode) == 333 ) {
1458 else if ( abs(maPdgcode) == 331 ) {
1462 else if ( abs(maPdgcode) == 113 ) {
1471 //__________________________________________
1472 Double_t AliHFEmcQA::GetWeightFactor(AliMCParticle *mctrack, const Int_t iBgLevel){
1474 // Get weighting factor for the realistic background estimation, for three possible background yield levels, indicated by the argument "iLevel": the best estimate (0), the lower uncertainty level (1), and the upper uncertainty level (2)
1476 AliMCParticle *mctrackmother = NULL;
1477 Double_t weightElecBg = 0.;
1478 Double_t mesonPt = 0.;
1479 Double_t bgcategory = 0.;
1481 Int_t mesonID = GetElecSource(mctrack->Particle());
1482 if(mesonID==kGammaPi0 || mesonID==kPi0) mArr=0; //pion
1483 else if(mesonID==kGammaEta || mesonID==kEta) mArr=1; //eta
1484 else if(mesonID==kGammaOmega || mesonID==kOmega) mArr=2; //omega
1485 else if(mesonID==kGammaPhi || mesonID==kPhi) mArr=3; //phi
1486 else if(mesonID==kGammaEtaPrime || mesonID==kEtaPrime) mArr=4; //etaprime
1487 else if(mesonID==kGammaRho0 || mesonID==kRho0) mArr=5; //rho
1490 if(mesonID>=kGammaPi0) { // conversion electron, be careful with the enum odering
1491 Int_t glabel=TMath::Abs(mctrack->GetMother()); // gamma label
1492 if((mctrackmother = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(glabel)))){
1493 glabel=TMath::Abs(mctrackmother->GetMother()); // gamma's mother's label
1494 if((mctrackmother = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(glabel)))){
1495 mesonPt = mctrackmother->Pt(); //meson pt
1500 else{ // nonHFE except for the conversion electron
1501 Int_t glabel=TMath::Abs(mctrack->GetMother());
1502 if((mctrackmother = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(glabel)))){
1503 mesonPt=mctrackmother->Pt(); //meson pt
1509 if(fCentrality < 0)return 0.;
1510 weightElecBg=fElecBackgroundFactor[iBgLevel][fCentrality][mArr][kBgPtBins-1];
1511 for(int ii=0; ii<kBgPtBins; ii++){
1512 if((mesonPt > fBinLimit[ii]) && (mesonPt < fBinLimit[ii+1])){
1513 weightElecBg = fElecBackgroundFactor[iBgLevel][fCentrality][mArr][ii];
1519 weightElecBg=fElecBackgroundFactor[iBgLevel][0][mArr][kBgPtBins-1];
1520 for(int ii=0; ii<kBgPtBins; ii++){
1521 if((mesonPt > fBinLimit[ii]) && (mesonPt < fBinLimit[ii+1])){
1522 weightElecBg = fElecBackgroundFactor[iBgLevel][0][mArr][ii];
1528 return bgcategory*weightElecBg;
1531 //__________________________________________
1532 void AliHFEmcQA::AliHists::FillList(TList *l) const {
1534 // Fill Histos into a list for output
1536 if(fPdgCode) l->Add(fPdgCode);
1537 if(fPt) l->Add(fPt);
1539 if(fEta) l->Add(fEta);
1542 //__________________________________________
1543 void AliHFEmcQA::AliHistsComm::FillList(TList *l) const {
1545 // Fill Histos into a list for output
1547 if(fNq) l->Add(fNq);
1548 if(fProcessID) l->Add(fProcessID);
1549 if(fePtRatio) l->Add(fePtRatio);
1550 if(fPtCorr) l->Add(fPtCorr);
1551 if(fPtCorrDp) l->Add(fPtCorrDp);
1552 if(fPtCorrD0) l->Add(fPtCorrD0);
1553 if(fPtCorrDrest) l->Add(fPtCorrDrest);
1554 if(fDePtRatio) l->Add(fDePtRatio);
1555 if(feDistance) l->Add(feDistance);
1556 if(fDeDistance) l->Add(fDeDistance);