1 /**************************************************************************
\r
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
\r
4 * Author: The ALICE Off-line Project. *
\r
5 * Contributors are mentioned in the code where appropriate. *
\r
7 * Permission to use, copy, modify and distribute this software and its *
\r
8 * documentation strictly for non-commercial purposes is hereby granted *
\r
9 * without fee, provided that the above copyright notice appears in all *
\r
10 * copies and that both the copyright notice and this permission notice *
\r
11 * appear in the supporting documentation. The authors make no claims *
\r
12 * about the suitability of this software for any purpose. It is *
\r
13 * provided "as is" without express or implied warranty. *
\r
14 **************************************************************************/
\r
15 /* $Id: AliMCAnalysisUtils.cxx 21839 2007-10-29 13:49:42Z gustavo $ */
\r
17 //_________________________________________________________________________
\r
18 // Class for analysis utils for MC data
\r
19 // stored in stack or event header.
\r
21 // - method to check the origin of a given track/cluster
\r
22 // - method to obtain the generated jets
\r
24 //*-- Author: Gustavo Conesa (LNF-INFN)
\r
25 //////////////////////////////////////////////////////////////////////////////
\r
28 // --- ROOT system ---
\r
32 //---- ANALYSIS system ----
\r
33 #include "AliMCAnalysisUtils.h"
\r
34 #include "AliStack.h"
\r
35 #include "TParticle.h"
\r
36 #include "AliGenPythiaEventHeader.h"
\r
38 ClassImp(AliMCAnalysisUtils)
\r
40 //________________________________________________
\r
41 AliMCAnalysisUtils::AliMCAnalysisUtils() :
\r
42 TObject(), fCurrentEvent(-1), fDebug(-1),
\r
43 fJetsList(new TList), fMCGenerator("PYTHIA"), fpTHardpTJetFactor(7)
\r
48 //____________________________________________________________________________
\r
49 AliMCAnalysisUtils::AliMCAnalysisUtils(const AliMCAnalysisUtils & mcutils) :
\r
50 TObject(mcutils), fCurrentEvent(mcutils.fCurrentEvent), fDebug(mcutils.fDebug),
\r
51 fJetsList(mcutils.fJetsList), fMCGenerator(mcutils.fMCGenerator), fpTHardpTJetFactor(mcutils.fpTHardpTJetFactor)
\r
57 //_________________________________________________________________________
\r
58 AliMCAnalysisUtils & AliMCAnalysisUtils::operator = (const AliMCAnalysisUtils & mcutils)
\r
60 // assignment operator
\r
62 if(&mcutils == this) return *this;
\r
63 fCurrentEvent = mcutils.fCurrentEvent ;
\r
64 fDebug = mcutils.fDebug;
\r
65 fJetsList = mcutils.fJetsList;
\r
66 fMCGenerator = mcutils.fMCGenerator;
\r
67 fpTHardpTJetFactor = mcutils.fpTHardpTJetFactor;
\r
72 //____________________________________________________________________________
\r
73 AliMCAnalysisUtils::~AliMCAnalysisUtils()
\r
75 // Remove all pointers.
\r
83 //_________________________________________________________________________
\r
84 Int_t AliMCAnalysisUtils::CheckOrigin(const Int_t label, AliStack * stack) const {
\r
85 //Play with the MC stack if available
\r
86 //Check origin of the candidates, good for PYTHIA
\r
89 printf("AliMCAnalysisUtils::CheckOrigin() - Stack is not available, check analysis settings in configuration file, STOP!!\n");
\r
92 // printf("label %d, ntrack %d, nprim %d\n",label, stack->GetNtrack(), stack->GetNprimary());
\r
93 // for(Int_t i = 0; i< stack->GetNprimary(); i++){
\r
94 // TParticle *particle = stack->Particle(i);
\r
95 // //particle->Print();
\r
97 if(label >= 0 && label < stack->GetNtrack()){
\r
99 TParticle * mom = stack->Particle(label);
\r
100 Int_t mPdg = TMath::Abs(mom->GetPdgCode());
\r
101 Int_t mStatus = mom->GetStatusCode() ;
\r
102 Int_t iParent = mom->GetFirstMother() ;
\r
103 if(fDebug > 0 && label < 8 ) printf("AliMCAnalysisUtils::CheckOrigin: Mother is parton %d\n",iParent);
\r
106 TParticle * parent = new TParticle ;
\r
110 parent = stack->Particle(iParent);
\r
111 pPdg = TMath::Abs(parent->GetPdgCode());
\r
112 pStatus = parent->GetStatusCode();
\r
114 else if(fDebug > 0 ) printf("AliMCAnalysisUtils::CheckOrigin: Parent with label %d\n",iParent);
\r
117 if(mPdg == 22){ //photon
\r
118 if(mStatus == 1){ //undecayed particle
\r
119 if(fMCGenerator == "PYTHIA"){
\r
120 if(iParent < 8 && iParent > 5) {//outgoing partons
\r
121 if(pPdg == 22) return kMCPrompt;
\r
122 else return kMCFragmentation;
\r
123 }//Outgoing partons
\r
124 else if(pStatus == 11){//Decay
\r
125 if(pPdg == 111) return kMCPi0Decay ;
\r
126 else if (pPdg == 221) return kMCEtaDecay ;
\r
127 else return kMCOtherDecay ;
\r
129 else return kMCISR; //Initial state radiation
\r
132 else if(fMCGenerator == "HERWIG"){
\r
133 if(pStatus < 197){//Not decay
\r
135 if(parent->GetFirstMother()<=5) break;
\r
136 iParent = parent->GetFirstMother();
\r
137 parent=stack->Particle(iParent);
\r
138 pStatus= parent->GetStatusCode();
\r
139 pPdg = parent->GetPdgCode();
\r
140 }//Look for the parton
\r
142 if(iParent < 8 && iParent > 5) {
\r
143 if(pPdg == 22) return kMCPrompt;
\r
144 else return kMCFragmentation;
\r
146 return kMCISR;//Initial state radiation
\r
149 if(pPdg == 111) return kMCPi0Decay ;
\r
150 else if (pPdg == 221) return kMCEtaDecay ;
\r
151 else return kMCOtherDecay ;
\r
154 else return kMCUnknown;
\r
155 }//Status 1 : Pythia generated
\r
156 else if(mStatus == 0){
\r
157 if(pPdg ==22 || pPdg ==11|| pPdg == 2112 || pPdg == 211 ||
\r
158 pPdg == 321 || pPdg == 2212 || pPdg == 130 || pPdg == 13 )
\r
159 return kMCConversion ;
\r
160 if(pPdg == 111) return kMCPi0Decay ;
\r
161 else if (pPdg == 221) return kMCEtaDecay ;
\r
162 else return kMCOtherDecay ;
\r
163 }//status 0 : geant generated
\r
165 else if(mPdg == 111) return kMCPi0 ;
\r
166 else if(mPdg == 221) return kMCEta ;
\r
168 //cluster's mother is an electron. Where did that electron come from?
\r
169 else if(mPdg == 11){ //electron
\r
171 if(fDebug > 0) printf("AliMCAnalysisUtils::CheckOrigin: Checking ancestors of electrons");
\r
173 //check first for B and C ancestry, then other possibilities.
\r
174 //An electron from a photon parent could have other particles in
\r
175 //its history and we would want to know that, right?
\r
177 if(mStatus == 1) { //electron from event generator
\r
178 if (pPdg == -1) return kMCElectron; //no parent
\r
179 else if (pPdg == 23) return kMCZDecay; //parent is Z-boson
\r
180 else if (pPdg == 24) return kMCWDecay; //parent is W-boson
\r
181 else { //check the electron's ancestors for B/C contribution
\r
182 Bool_t bAncestor = kFALSE;
\r
183 Bool_t cAncestor = kFALSE;
\r
184 TParticle * ancestors = stack->Particle(label);
\r
185 Int_t aPdg = TMath::Abs(ancestors->GetPdgCode());
\r
186 //Int_t aStatus = ancestors->GetStatusCode();
\r
187 Int_t iAncestors = ancestors->GetFirstMother();
\r
188 if(fDebug > 0) printf("AliMCAnalysisUtils::CheckOrigin: Scaning the decay chain for bottom/charm generated electron");
\r
189 while(ancestors->IsPrimary()){//searching for ancestors
\r
190 if((499 < aPdg && aPdg < 600)||(4999 < aPdg && aPdg < 6000)) bAncestor = kTRUE;
\r
191 if((399 < aPdg && aPdg < 500)||(3999 < aPdg && aPdg < 5000)) cAncestor = kTRUE;
\r
192 if(bAncestor && cAncestor) break;
\r
193 iAncestors = ancestors->GetFirstMother();
\r
194 ancestors = stack->Particle(iAncestors);
\r
195 aPdg = ancestors->GetPdgCode();
\r
196 }//searching for ancestors
\r
197 if(bAncestor && cAncestor) return kMCEFromCFromB;//Decay chain has both B and C
\r
198 else if(bAncestor && !cAncestor) return kMCEFromB;//Decay chain has only B
\r
199 else if(!bAncestor && cAncestor) return kMCEFromC;//Decay chain has only C
\r
201 //if it is not from W,Z or B/C ancestor, where is it from?
\r
202 if (pPdg == 111) return kMCPi0Decay;//Pi0 Dalitz decay
\r
203 else if(pPdg == 221) return kMCEtaDecay;//Eta Dalitz decay
\r
204 else return kMCOtherDecay;
\r
206 } else if (mStatus == 0) { //electron from GEANT
\r
208 //Rewind ancestry and check for electron with status == 1
\r
209 //if we find one, we'll assume that this object is from an
\r
210 //electron but that it may have gone through some showering in
\r
211 //material before the detector
\r
213 //Not a double-counting problem because we are only accessing
\r
214 //these histories for MC labels connected to a reco object.
\r
215 //If you wanted to use this to sort through the kine stack
\r
216 //directly, might it be a problem?
\r
217 Bool_t eleFromEvGen = kFALSE;
\r
218 Bool_t bAncestor = kFALSE;
\r
219 Bool_t cAncestor = kFALSE;
\r
221 TParticle * ancestors = stack->Particle(label);
\r
222 Int_t aPdg = TMath::Abs(ancestors->GetPdgCode());
\r
223 Int_t aStatus = ancestors->GetStatusCode();
\r
224 Int_t iAncestors = ancestors->GetFirstMother();
\r
225 if(fDebug > 0) printf("AliMCAnalysisUtils::CheckOrigin: Scaning the decay chain for bottom/charm electrons");
\r
226 while(ancestors->IsPrimary()){//searching for ancestors
\r
227 if(aStatus == 1 && aPdg == 11) eleFromEvGen = kTRUE;
\r
228 if(eleFromEvGen && aPdg == 23) return kMCZDecay;
\r
229 if(eleFromEvGen && aPdg == 24) return kMCWDecay;
\r
230 if(eleFromEvGen && ((499 < aPdg && aPdg < 600)||(4999 < aPdg && aPdg < 6000))) bAncestor = kTRUE;
\r
231 if(eleFromEvGen && ((399 < aPdg && aPdg < 500)||(3999 < aPdg && aPdg < 5000))) cAncestor = kTRUE;
\r
232 if(bAncestor && cAncestor) break;
\r
233 iAncestors = ancestors->GetFirstMother();
\r
234 ancestors = stack->Particle(iAncestors);
\r
235 aPdg = ancestors->GetPdgCode();
\r
236 }//searching for ancestors
\r
237 if(bAncestor && cAncestor) return kMCEFromCFromB;//Decay chain has both B and C
\r
238 else if(bAncestor && !cAncestor) return kMCEFromB;//Decay chain has only B
\r
239 else if(!bAncestor && cAncestor) return kMCEFromC;//Decay chain has only C
\r
240 if(pPdg ==22 || pPdg ==11|| pPdg == 2112 || pPdg == 211 ||
\r
241 pPdg == 321 || pPdg == 2212 || pPdg == 130 || pPdg == 13 )
\r
242 return kMCConversion ;
\r
243 if(pPdg == 111) return kMCPi0Decay ;
\r
244 else if (pPdg == 221) return kMCEtaDecay ;
\r
245 else return kMCOtherDecay ;
\r
248 else return kMCUnknown;
\r
249 }//Good label value
\r
251 if(label < 0 ) printf("AliMCAnalysisUtils::CheckOrigin: *** bad label or no stack ***: label %d \n", label);
\r
252 if(label >= stack->GetNtrack()) printf("AliMCAnalysisUtils::CheckOrigin: *** large label ***: label %d, n tracks %d \n", label, stack->GetNtrack());
\r
260 //_________________________________________________________________________
\r
261 TList * AliMCAnalysisUtils::GetJets(const Int_t iEvent, AliStack * stack, const AliGenEventHeader * geh) {
\r
262 //Return list of jets (TParticles) and index of most likely parton that originated it.
\r
264 if(fCurrentEvent!=iEvent){
\r
265 fCurrentEvent = iEvent;
\r
266 fJetsList = new TList;
\r
267 Int_t nTriggerJets = 0;
\r
268 Float_t tmpjet[]={0,0,0,0};
\r
270 //printf("Event %d %d\n",fCurrentEvent,iEvent);
\r
271 //Get outgoing partons
\r
272 if(stack->GetNtrack() < 8) return fJetsList;
\r
273 TParticle * parton1 = stack->Particle(6);
\r
274 TParticle * parton2 = stack->Particle(7);
\r
276 printf("AliMCAnalysisUtils::GetJets() - parton 6 : %s, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",
\r
277 parton1->GetName(),parton1->Pt(),parton1->Energy(),parton1->Phi()*TMath::RadToDeg(),parton1->Eta());
\r
278 printf("AliMCAnalysisUtils::GetJets() - parton 7 : %s, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",
\r
279 parton2->GetName(),parton2->Pt(),parton2->Energy(),parton2->Phi()*TMath::RadToDeg(),parton2->Eta());
\r
281 // //Trace the jet from the mother parton
\r
283 // Float_t pt1 = 0;
\r
284 // Float_t pt2 = 0;
\r
288 // TParticle * tmptmp = new TParticle;
\r
289 // for(Int_t i = 0; i< stack->GetNprimary(); i++){
\r
290 // tmptmp = stack->Particle(i);
\r
292 // if(tmptmp->GetStatusCode() == 1){
\r
293 // pt = tmptmp->Pt();
\r
294 // e = tmptmp->Energy();
\r
295 // Int_t imom = tmptmp->GetFirstMother();
\r
296 // Int_t imom1 = 0;
\r
297 // //printf("1st imom %d\n",imom);
\r
298 // while(imom > 5){
\r
300 // tmptmp = stack->Particle(imom);
\r
301 // imom = tmptmp->GetFirstMother();
\r
302 // //printf("imom %d \n",imom);
\r
304 // //printf("Last imom %d %d\n",imom1, imom);
\r
305 // if(imom1 == 6) {
\r
309 // else if (imom1 == 7){
\r
316 // printf("JET 1, pt %2.2f, e %2.2f; JET 2, pt %2.2f, e %2.2f \n",pt1,e1,pt2,e2);
\r
318 //Get the jet, different way for different generator
\r
320 if(fMCGenerator == "PYTHIA"){
\r
321 TParticle * jet = new TParticle;
\r
322 AliGenPythiaEventHeader* pygeh= (AliGenPythiaEventHeader*) geh;
\r
323 nTriggerJets = pygeh->NTriggerJets();
\r
325 printf("AliMCAnalysisUtils::GetJets() - PythiaEventHeader: Njets: %d\n",nTriggerJets);
\r
327 Int_t iparton = -1;
\r
328 for(Int_t i = 0; i< nTriggerJets; i++){
\r
330 pygeh->TriggerJet(i, tmpjet);
\r
331 jet = new TParticle(94, 21, -1, -1, -1, -1, tmpjet[0],tmpjet[1],tmpjet[2],tmpjet[3], 0,0,0,0);
\r
332 //Assign an outgoing parton as mother
\r
333 Float_t phidiff1 = TMath::Abs(jet->Phi()-parton1->Phi());
\r
334 Float_t phidiff2 = TMath::Abs(jet->Phi()-parton2->Phi());
\r
335 if(phidiff1 > phidiff2) jet->SetFirstMother(7);
\r
336 else jet->SetFirstMother(6);
\r
339 printf("AliMCAnalysisUtils::GetJets() - PYTHIA Jet %d: mother %d, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",
\r
340 i, jet->GetFirstMother(),jet->Pt(),jet->Energy(),jet->Phi()*TMath::RadToDeg(),jet->Eta());
\r
341 fJetsList->Add(jet);
\r
343 }//Pythia triggered jets
\r
345 else if (fMCGenerator=="HERWIG"){
\r
348 TParticle * tmp = parton1;
\r
349 if(parton1->GetPdgCode()!=22){
\r
351 if(tmp->GetFirstDaughter()==-1) return fJetsList;
\r
352 tmp = stack->Particle(tmp->GetFirstDaughter());
\r
353 pdg = tmp->GetPdgCode();
\r
356 //Add found jet to list
\r
357 TParticle *jet1 = new TParticle(*tmp);
\r
358 jet1->SetFirstMother(6);
\r
359 fJetsList->Add(jet1);
\r
360 //printf("jet 1: first daughter %d, last daughter %d\n", tmp->GetFirstDaughter(), tmp->GetLastDaughter());
\r
361 //tmp = stack->Particle(tmp->GetFirstDaughter());
\r
365 printf("AliMCAnalysisUtils::GetJets() - HERWIG Jet 1: mother %d, status %d, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",
\r
366 jet1->GetFirstMother(),jet1->GetStatusCode(),jet1->Pt(),jet1->Energy(),jet1->Phi()*TMath::RadToDeg(),jet1->Eta());
\r
373 if(parton2->GetPdgCode()!=22){
\r
375 if(tmp->GetFirstDaughter()==-1) return fJetsList;
\r
376 i = tmp->GetFirstDaughter();
\r
377 tmp = stack->Particle(tmp->GetFirstDaughter());
\r
378 pdg = tmp->GetPdgCode();
\r
380 //Add found jet to list
\r
381 TParticle *jet2 = new TParticle(*tmp);
\r
382 jet2->SetFirstMother(7);
\r
383 fJetsList->Add(jet2);
\r
386 printf("AliMCAnalysisUtils::GetJets() - HERWIG Jet 2: mother %d, status %d, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",
\r
387 jet2->GetFirstMother(),jet2->GetStatusCode(),jet2->Pt(),jet2->Energy(),jet2->Phi()*TMath::RadToDeg(),jet2->Eta());
\r
388 //Int_t first = tmp->GetFirstDaughter();
\r
389 //Int_t last = tmp->GetLastDaughter();
\r
390 //printf("jet 2: first daughter %d, last daughter %d, pdg %d\n",first, last, tmp->GetPdgCode());
\r
391 // for(Int_t d = first ; d < last+1; d++){
\r
392 // tmp = stack->Particle(d);
\r
393 // if(i == tmp->GetFirstMother())
\r
394 // printf("Daughter n %d, Mother %d, name %s, status %d, pT %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",
\r
395 // d,tmp->GetFirstMother(), tmp->GetName(), tmp->GetStatusCode(),tmp->Pt(),tmp->Energy(),tmp->Phi()*TMath::RadToDeg(),tmp->Eta());
\r
399 }//Herwig generated jets
\r
406 //_________________________________________________________________________
\r
407 Bool_t AliMCAnalysisUtils::ComparePtHardAndJetPt(const AliGenEventHeader * geh){
\r
408 // Check the event, if the requested ptHard is much larger than the jet pT, then there is a problem.
\r
409 // Only for PYTHIA.
\r
411 if(fMCGenerator == "PYTHIA"){
\r
412 TParticle * jet = new TParticle;
\r
413 AliGenPythiaEventHeader* pygeh= (AliGenPythiaEventHeader*) geh;
\r
414 Int_t nTriggerJets = pygeh->NTriggerJets();
\r
415 Float_t ptHard = pygeh->GetPtHard();
\r
417 //if(fDebug > 1) printf("AliMCAnalysisUtils::PythiaEventHeader: Njets: %d, pT Hard %f\n",nTriggerJets, ptHard);
\r
418 Float_t tmpjet[]={0,0,0,0};
\r
419 for(Int_t ijet = 0; ijet< nTriggerJets; ijet++){
\r
420 pygeh->TriggerJet(ijet, tmpjet);
\r
421 jet = new TParticle(94, 21, -1, -1, -1, -1, tmpjet[0],tmpjet[1],tmpjet[2],tmpjet[3], 0,0,0,0);
\r
422 //Compare jet pT and pt Hard
\r
423 //if(fDebug > 1) printf("AliMCAnalysisUtils:: %d pycell jet pT %f\n",ijet, jet->Pt());
\r
424 if(jet->Pt() > fpTHardpTJetFactor * ptHard) {
\r
425 printf("AliMCAnalysisUtils::PythiaEventHeader: Njets: %d, pT Hard %2.2f, pycell jet pT %2.2f, rejection factor %1.1f\n",
\r
426 nTriggerJets, ptHard, jet->Pt(), fpTHardpTJetFactor);
\r
436 //________________________________________________________________
\r
437 void AliMCAnalysisUtils::Print(const Option_t * opt) const
\r
439 //Print some relevant parameters set for the analysis
\r
444 printf("***** Print: %s %s ******\n", GetName(), GetTitle() ) ;
\r
446 printf("Debug level = %d\n",fDebug);
\r
447 printf("MC Generator = %s\n",fMCGenerator.Data());
\r
448 printf("fpTHardpTJetFactor = %2.2f",fpTHardpTJetFactor);
\r