1 /*************************************************************************
2 * Copyright(c) 1998-2009, 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 //#####################################################
18 //# Class AliDielectronMC #
19 //# Cut Class for Jpsi->e+e- analysis #
21 //# by WooJin J. Park, GSI / W.J.Park@gsi.de #
23 //#####################################################
25 #include <AliAnalysisManager.h>
26 #include <AliAODHandler.h>
27 #include <AliESDInputHandler.h>
28 #include <AliAODInputHandler.h>
29 #include <AliMCEventHandler.h>
30 #include <AliMCEvent.h>
31 #include <AliMCParticle.h>
32 #include <AliAODMCParticle.h>
34 #include <AliESDEvent.h>
35 #include <AliAODEvent.h>
36 #include <AliESDtrack.h>
37 #include <AliAODTrack.h>
40 #include <TClonesArray.h>
41 #include <TParticle.h>
43 #include "AliDielectronSignalMC.h"
44 #include "AliDielectronMC.h"
46 AliDielectronMC* AliDielectronMC::fgInstance=0x0;
48 //____________________________________________________________
49 AliDielectronMC* AliDielectronMC::Instance()
52 // return pointer to singleton implementation
54 if (fgInstance) return fgInstance;
56 AnalysisType type=kUNSET;
58 if (AliAnalysisManager::GetAnalysisManager()){
59 if (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()->IsA()==AliESDInputHandler::Class()) type=kESD;
60 else if (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()->IsA()==AliAODInputHandler::Class()) type=kAOD;
62 AliMCEventHandler* mcHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
63 if(type == kESD) hasMC=mcHandler!=0x0;
66 fgInstance=new AliDielectronMC(type);
68 fgInstance->SetHasMC(hasMC);
73 //____________________________________________________________
74 AliDielectronMC::AliDielectronMC(AnalysisType type):
82 // default constructor
87 //____________________________________________________________
88 AliDielectronMC::~AliDielectronMC()
96 //____________________________________________________________
97 void AliDielectronMC::Initialize()
100 // initialize MC class
102 if (!ConnectMCEvent()) AliError("Initialization of MC object failed!");
105 //____________________________________________________________
106 Int_t AliDielectronMC::GetNMCTracks()
109 // return the number of generated tracks from MC event
111 if(fAnaType == kESD){
112 if (!fMCEvent){ AliError("No fMCEvent"); return 0; }
113 return fMCEvent->GetNumberOfTracks();}
114 else if(fAnaType == kAOD){
115 if(!fMcArray) { AliError("No fMcArray"); return 0; }
116 return fMcArray->GetEntriesFast();
121 //____________________________________________________________
122 Int_t AliDielectronMC::GetNMCTracksFromStack()
125 // return the number of generated tracks from stack
127 if (!fStack){ AliError("No fStack"); return -999; }
128 return fStack->GetNtrack();
131 //____________________________________________________________
132 Int_t AliDielectronMC::GetNPrimary() const
135 // return the number of primary track from MC event
137 if (!fMCEvent){ AliError("No fMCEvent"); return 0; }
138 return fMCEvent->GetNumberOfPrimaries();
141 //____________________________________________________________
142 Int_t AliDielectronMC::GetNPrimaryFromStack()
145 // return the number of primary track from stack
147 if (!fStack){ AliError("No fStack"); return -999; }
148 return fStack->GetNprimary();
151 //____________________________________________________________
152 AliVParticle* AliDielectronMC::GetMCTrackFromMCEvent(Int_t itrk) const
155 // return MC track directly from MC event
157 if (itrk<0) return NULL;
158 AliVParticle * track=0x0;
159 if(fAnaType == kESD){
160 if (!fMCEvent){ AliError("No fMCEvent"); return NULL;}
161 track = fMCEvent->GetTrack(itrk); // tracks from MC event (ESD)
162 } else if(fAnaType == kAOD) {
163 if (!fMcArray){ AliError("No fMcArray"); return NULL;}
164 if (itrk>fMcArray->GetEntriesFast()) { AliWarning(Form("track %d out of array size %d",itrk,fMcArray->GetEntriesFast())); return NULL;}
165 track = (AliVParticle*)fMcArray->At(itrk); // tracks from MC event (AOD)
170 //____________________________________________________________
171 Bool_t AliDielectronMC::ConnectMCEvent()
174 // connect stack object from the mc handler
176 if(fAnaType == kESD){
178 AliMCEventHandler* mcHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
179 if (!mcHandler){ /*AliError("Could not retrive MC event handler!");*/ return kFALSE; }
180 if (!mcHandler->InitOk() ) return kFALSE;
181 if (!mcHandler->TreeK() ) return kFALSE;
182 if (!mcHandler->TreeTR() ) return kFALSE;
184 AliMCEvent* mcEvent = mcHandler->MCEvent();
185 if (!mcEvent){ /*AliError("Could not retrieve MC event!");*/ return kFALSE; }
188 if (!UpdateStack()) return kFALSE;
190 else if(fAnaType == kAOD)
193 AliAODEvent *aod=((AliAODInputHandler*)((AliAnalysisManager::GetAnalysisManager())->GetInputEventHandler()))->GetEvent();
194 fMcArray = dynamic_cast<TClonesArray*>(aod->FindListObject(AliAODMCParticle::StdBranchName()));
195 if (!fMcArray){ /*AliError("Could not retrieve MC array!");*/ return kFALSE; }
201 //____________________________________________________________
202 Bool_t AliDielectronMC::UpdateStack()
205 // update stack with new event
207 if (!fMCEvent){ AliError("No fMCEvent"); return kFALSE;}
208 AliStack* stack = fMCEvent->Stack();
209 if (!stack){ AliError("Could not retrive stack!"); return kFALSE; }
214 //____________________________________________________________
215 AliMCParticle* AliDielectronMC::GetMCTrack( const AliESDtrack* _track)
220 if (!fMCEvent){ AliError("No fMCEvent"); return NULL;}
222 Int_t nStack = fMCEvent->GetNumberOfTracks();
223 Int_t label = TMath::Abs(_track->GetLabel());
224 if(label>nStack)return NULL;
226 AliMCParticle *mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(label));
231 //____________________________________________________________
232 AliAODMCParticle* AliDielectronMC::GetMCTrack( const AliAODTrack* _track)
237 if(!fMcArray) { AliError("No fMcArray"); return NULL;}
238 Int_t label = _track->GetLabel();
239 if(label < 0 || label > fMcArray->GetEntriesFast()) return NULL;
240 AliAODMCParticle *mctrack = (AliAODMCParticle*)fMcArray->At(label);
244 //____________________________________________________________
245 TParticle* AliDielectronMC::GetMCTrackFromStack(const AliESDtrack* _track)
248 // return MC track from stack
250 Int_t label = TMath::Abs(_track->GetLabel());
251 if (!fStack) AliWarning("fStack is not available. Update stack first.");
252 TParticle* mcpart = fStack->Particle(label);
253 if (!mcpart) return NULL;
257 //____________________________________________________________
258 AliMCParticle* AliDielectronMC::GetMCTrackMother(const AliESDtrack* _track)
261 // return MC track mother
263 AliMCParticle* mcpart = GetMCTrack(_track);
264 if (!mcpart) return NULL;
265 AliMCParticle* mcmother = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(mcpart->GetMother()));
266 if (!mcmother) return NULL;
270 //______________________________________________________________
271 AliAODMCParticle* AliDielectronMC::GetMCTrackMother(const AliAODTrack* _track)
274 // return MC track mother
276 AliAODMCParticle* mcpart = GetMCTrack(_track);
277 if (!mcpart) return NULL;
278 if(mcpart->GetMother() < 0) return NULL;
279 AliAODMCParticle* mcmother = dynamic_cast<AliAODMCParticle *>(fMcArray->At(mcpart->GetMother()));
280 if (!mcmother) return NULL;
283 //____________________________________________________________
284 AliMCParticle* AliDielectronMC::GetMCTrackMother(const AliMCParticle* _particle){
286 // return MC track mother
288 AliMCParticle* mcmother = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(_particle->GetMother()));
292 //____________________________________________________________
293 AliAODMCParticle* AliDielectronMC::GetMCTrackMother(const AliAODMCParticle* _particle){
295 // return MC track mother
297 if( _particle->GetMother() < 0) return NULL;
298 AliAODMCParticle* mcmother = dynamic_cast<AliAODMCParticle *>(fMcArray->At(_particle->GetMother()));
302 //____________________________________________________________
303 TParticle* AliDielectronMC::GetMCTrackMotherFromStack(const AliESDtrack* _track)
306 // return MC track mother from stack
308 TParticle* mcpart = GetMCTrackFromStack(_track);
309 if ( !mcpart || mcpart->GetFirstMother()<=0 ) return NULL;
310 TParticle* mcmother = fStack->Particle(mcpart->GetFirstMother());
311 if (!mcmother) return NULL;
315 //____________________________________________________________
316 Int_t AliDielectronMC::GetMCPID(const AliESDtrack* _track)
319 // return PDG code of the track from the MC truth info
321 AliMCParticle* mcpart = GetMCTrack(_track);
322 if (!mcpart) return -999;
323 return mcpart->PdgCode();
326 //__________________________________________________________
327 Int_t AliDielectronMC::GetMCPID(const AliAODTrack* _track)
330 // return PDG code of the track from the MC truth info
332 AliAODMCParticle* mcpart = GetMCTrack(_track);
333 if (!mcpart) return -999;
334 return mcpart->PdgCode();
337 //____________________________________________________________
338 Int_t AliDielectronMC::GetMCPIDFromStack(const AliESDtrack* _track)
341 // return MC PDG code from stack
343 TParticle* mcpart = GetMCTrackFromStack(_track);
344 if (!mcpart) return -999;
345 return mcpart->GetPdgCode();
348 //____________________________________________________________
349 Int_t AliDielectronMC::GetMotherPDG( const AliESDtrack* _track)
352 // return PDG code of the mother track from the MC truth info
354 AliMCParticle* mcmother = GetMCTrackMother(_track);
355 if (!mcmother) return -999;
356 return mcmother->PdgCode();
359 //________________________________________________________
360 Int_t AliDielectronMC::GetMotherPDG( const AliAODTrack* _track)
363 // return PDG code of the mother track from the MC truth info
365 AliAODMCParticle* mcmother = GetMCTrackMother(_track);
366 if (!mcmother) return -999;
367 return mcmother->PdgCode();
370 //____________________________________________________________
371 Int_t AliDielectronMC::GetMotherPDGFromStack(const AliESDtrack* _track)
374 // return PDG code of the mother track from stack
376 TParticle* mcmother = GetMCTrackMotherFromStack(_track);
377 if (!mcmother) return -999;
378 return mcmother->GetPdgCode();
381 //____________________________________________________________
382 Int_t AliDielectronMC::GetMCProcess(const AliESDtrack* _track)
385 // return process number of the track
387 AliMCParticle* mcpart = GetMCTrack(_track);
388 if (!mcpart) return -999;
392 //____________________________________________________________
393 Int_t AliDielectronMC::GetMCProcessFromStack(const AliESDtrack* _track)
396 // return process number of the track
398 TParticle* mcpart = GetMCTrackFromStack(_track);
399 if (!mcpart) return -999;
400 return mcpart->GetUniqueID();
403 //____________________________________________________________
404 Int_t AliDielectronMC::NumberOfDaughters(const AliESDtrack* track)
407 // returns the number of daughters
409 AliMCParticle *mcmother=GetMCTrackMother(track);
410 if(!mcmother||!mcmother->Particle()) return -999;
411 // return mcmother->GetFirstDaughter()>0?mcmother->GetLastDaughter()-mcmother->GetFirstDaughter()+1:0;
412 return mcmother->Particle()->GetNDaughters();
415 //_________________________________________________________
416 Int_t AliDielectronMC::NumberOfDaughters(const AliAODTrack* track)
419 // returns the number of daughters
421 AliAODMCParticle *mcmother=GetMCTrackMother(track);
422 if(!mcmother) return -999;
423 return NumberOfDaughters(mcmother);
427 //____________________________________________________________
428 Int_t AliDielectronMC::NumberOfDaughters(const AliMCParticle* particle)
431 // returns the number of daughters
433 AliMCParticle *mcmother=GetMCTrackMother(particle);
434 if(!mcmother||!mcmother->Particle()) return -999;
435 //return mcmother->GetFirstDaughter()>0?mcmother->GetLastDaughter()-mcmother->GetFirstDaughter()+1:0;
436 return mcmother->Particle()->GetNDaughters();
439 //____________________________________________________________
440 Int_t AliDielectronMC::NumberOfDaughters(const AliAODMCParticle* particle)
443 // returns the number of daughters
445 AliAODMCParticle *mcmother=GetMCTrackMother(particle);
446 if(!mcmother) return -999;
447 return mcmother->GetNDaughters();
450 //____________________________________________________________
451 Int_t AliDielectronMC::GetMCProcessMother(const AliESDtrack* _track)
454 // return process number of the mother of the track
456 AliMCParticle* mcmother = GetMCTrackMother(_track);
457 if (!mcmother) return -999;
461 //____________________________________________________________
462 Int_t AliDielectronMC::GetMCProcessMotherFromStack(const AliESDtrack* _track)
465 // return process number of the mother of the track
467 TParticle* mcmother = GetMCTrackMotherFromStack(_track);
468 if (!mcmother) return -999;
469 return mcmother->GetUniqueID();
472 //____________________________________________________________
473 Bool_t AliDielectronMC::IsMCMotherToEE(const AliVParticle *particle, Int_t pdgMother)
476 // Check if the Mother 'particle' is of type pdgMother and decays to e+e-
478 if (fAnaType==kESD && !fMCEvent) return kFALSE;
479 if (fAnaType==kAOD && !fMcArray) return kFALSE;
480 if (!particle) return kFALSE;
482 if (particle->IsA()==AliMCParticle::Class()){
483 return IsMCMotherToEEesd(static_cast<const AliMCParticle*>(particle),pdgMother);
484 } else if (particle->IsA()==AliAODMCParticle::Class()){
485 return IsMCMotherToEEaod(static_cast<const AliAODMCParticle*>(particle),pdgMother);
487 AliError("Unknown particle type");
492 //____________________________________________________________
493 Bool_t AliDielectronMC::IsMCMotherToEEesd(const AliMCParticle *particle, Int_t pdgMother)
496 // Check if the Mother 'particle' is of type pdgMother and decays to e+e-
501 if (particle->PdgCode()!=pdgMother) return kFALSE;
502 Int_t ifirst = particle->GetFirstDaughter();
503 Int_t ilast = particle->GetLastDaughter();
505 //check number of daughters
506 if ((ilast-ifirst)!=1) return kFALSE;
507 AliMCParticle *firstD=static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(ifirst));
508 AliMCParticle *secondD=static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(ilast));
510 //TODO: check how you can get rid of the hardcoded numbers. One should make use of the PdgCodes set in AliDielectron!!!
511 if (firstD->Charge()>0){
512 if (firstD->PdgCode()!=-11) return kFALSE;
513 if (secondD->PdgCode()!=11) return kFALSE;
515 if (firstD->PdgCode()!=11) return kFALSE;
516 if (secondD->PdgCode()!=-11) return kFALSE;
522 //____________________________________________________________
523 Bool_t AliDielectronMC::IsMCMotherToEEaod(const AliAODMCParticle *particle, Int_t pdgMother)
526 // Check if the Mother 'particle' is of type pdgMother and decays to e+e-
530 if (particle->GetPdgCode()!=pdgMother) return kFALSE;
531 if (particle->GetNDaughters()!=2) return kFALSE;
533 Int_t ifirst = particle->GetDaughter(0);
534 Int_t ilast = particle->GetDaughter(1);
536 //check number of daughters
537 if ((ilast-ifirst)!=1) return kFALSE;
539 AliAODMCParticle *firstD=static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(ifirst));
540 AliAODMCParticle *secondD=static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(ilast));
542 //TODO: check how you can get rid of the hardcoded numbers. One should make use of the PdgCodes set in AliDielectron!!!
544 if (firstD->Charge()>0){
545 if (firstD->GetPdgCode()!=-11) return kFALSE;
546 if (secondD->GetPdgCode()!=11) return kFALSE;
548 if (firstD->GetPdgCode()!=11) return kFALSE;
549 if (secondD->GetPdgCode()!=-11) return kFALSE;
554 //____________________________________________________________
555 Int_t AliDielectronMC::GetLabelMotherWithPdg(const AliVParticle *particle1, const AliVParticle *particle2, Int_t pdgMother)
558 // test if mother of particle 1 and 2 has pdgCode pdgMother and is the same;
561 if (!fMCEvent) return -1;
562 return GetLabelMotherWithPdgESD(particle1, particle2, pdgMother);
564 else if (fAnaType==kAOD)
566 if (!fMcArray) return -1;
567 return GetLabelMotherWithPdgAOD(particle1, particle2, pdgMother);
573 //____________________________________________________________
574 Int_t AliDielectronMC::GetLabelMotherWithPdgESD(const AliVParticle *particle1, const AliVParticle *particle2, Int_t pdgMother)
577 // test if mother of particle 1 and 2 has pdgCode +-11 (electron),
578 // have the same mother and the mother had pdg code pdgMother
580 //TODO: check how you can get rid of the hardcoded numbers. One should make use of the PdgCodes set in AliDielectron!!!
583 AliMCParticle *mcPart1=static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(particle1->GetLabel()));
584 AliMCParticle *mcPart2=static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(particle2->GetLabel()));
586 if (!mcPart1||!mcPart2) return -1;
588 Int_t lblMother1=mcPart1->GetMother();
589 Int_t lblMother2=mcPart2->GetMother();
591 AliMCParticle *mcMother1=static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(lblMother1));
592 if (!mcMother1) return -1;
593 if (lblMother1!=lblMother2) return -1;
594 if (TMath::Abs(mcPart1->PdgCode())!=11) return -1;
595 if (mcPart1->PdgCode()!=-mcPart2->PdgCode()) return -1;
596 if (mcMother1->PdgCode()!=pdgMother) return -1;
601 //____________________________________________________________
602 Int_t AliDielectronMC::GetLabelMotherWithPdgAOD(const AliVParticle *particle1, const AliVParticle *particle2, Int_t pdgMother)
605 // test if mother of particle 1 and 2 has pdgCode +-11 (electron),
606 // have the same mother and the mother had pdg code pdgMother
608 //TODO: check how you can get rid of the hardcoded numbers. One should make use of the PdgCodes set in AliDielectron!!!
610 AliAODMCParticle *mcPart1=static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(particle1->GetLabel()));
611 AliAODMCParticle *mcPart2=static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(particle2->GetLabel()));
613 if (!mcPart1||!mcPart2) return -1;
615 Int_t lblMother1=mcPart1->GetMother();
616 Int_t lblMother2=mcPart2->GetMother();
618 AliAODMCParticle *mcMother1=static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(lblMother1));
620 if (!mcMother1) return -1;
621 if (lblMother1!=lblMother2) return -1;
622 if (TMath::Abs(mcPart1->GetPdgCode())!=11) return -1;
623 if (mcPart1->GetPdgCode()!=-mcPart2->GetPdgCode()) return -1;
624 if (mcMother1->GetPdgCode()!=pdgMother) return -1;
629 //____________________________________________________________
630 void AliDielectronMC::GetDaughters(const TObject *mother, AliVParticle* &d1, AliVParticle* &d2)
633 // Get First two daughters of the mother
640 if(!fMcArray) return;
641 const AliAODMCParticle *aodMother=static_cast<const AliAODMCParticle*>(mother);
642 lblD1=aodMother->GetDaughter(0);
643 lblD2=aodMother->GetDaughter(1);
644 d1 = (AliVParticle*)fMcArray->At(lblD1);
645 d2 = (AliVParticle*)fMcArray->At(lblD2);
646 } else if (fAnaType==kESD){
647 if (!fMCEvent) return;
648 const AliMCParticle *aodMother=static_cast<const AliMCParticle*>(mother);
649 lblD1=aodMother->GetFirstDaughter();
650 lblD2=aodMother->GetLastDaughter();
651 d1=fMCEvent->GetTrack(lblD1);
652 d2=fMCEvent->GetTrack(lblD2);
657 //________________________________________________________________________________
658 Int_t AliDielectronMC::GetMothersLabel(Int_t daughterLabel) const {
660 // Get the label of the mother for particle with label daughterLabel
662 if(daughterLabel<0) return -1;
663 if (fAnaType==kAOD) {
664 if(!fMcArray) return -1;
665 return (static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(daughterLabel)))->GetMother();
666 } else if(fAnaType==kESD) {
667 if (!fMCEvent) return -1;
668 return (static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(daughterLabel)))->GetMother();
674 //________________________________________________________________________________
675 Int_t AliDielectronMC::GetPdgFromLabel(Int_t label) const {
677 // Get particle code using the label from stack
679 if(label<0) return 0;
681 if(!fMcArray) return 0;
682 return (static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(label)))->PdgCode();
683 } else if(fAnaType==kESD) {
684 if (!fMCEvent) return 0;
685 return (static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(label)))->PdgCode();
691 //________________________________________________________________________________
692 Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t pdgExclusion, Bool_t checkBothCharges) const {
694 // Test the PDG codes of particles with the required ones
696 Bool_t result = kTRUE;
697 Int_t absRequiredPDG = TMath::Abs(requiredPDG);
699 switch(absRequiredPDG) {
701 result = kTRUE; // PDG not required (any code will do fine)
703 case 100: // light flavoured mesons
705 result = TMath::Abs(particlePDG)>=100 && TMath::Abs(particlePDG)<=199;
707 if(requiredPDG>0) result = particlePDG>=100 && particlePDG<=199;
708 if(requiredPDG<0) result = particlePDG>=-199 && particlePDG<=-100;
711 case 1000: // light flavoured baryons
713 result = TMath::Abs(particlePDG)>=1000 && TMath::Abs(particlePDG)<=1999;
715 if(requiredPDG>0) result = particlePDG>=1000 && particlePDG<=1999;
716 if(requiredPDG<0) result = particlePDG>=-1999 && particlePDG<=-1000;
719 case 200: // light flavoured mesons
721 result = TMath::Abs(particlePDG)>=200 && TMath::Abs(particlePDG)<=299;
723 if(requiredPDG>0)result = particlePDG>=200 && particlePDG<=299;
724 if(requiredPDG<0)result = particlePDG>=-299 && particlePDG<=-200;
727 case 2000: // light flavoured baryons
729 result = TMath::Abs(particlePDG)>=2000 && TMath::Abs(particlePDG)<=2999;
731 if(requiredPDG>0) result = particlePDG>=2000 && particlePDG<=2999;
732 if(requiredPDG<0) result = particlePDG>=-2999 && particlePDG<=-2000;
735 case 300: // all strange mesons
737 result = TMath::Abs(particlePDG)>=300 && TMath::Abs(particlePDG)<=399;
739 if(requiredPDG>0) result = particlePDG>=300 && particlePDG<=399;
740 if(requiredPDG<0) result = particlePDG>=-399 && particlePDG<=-300;
743 case 3000: // all strange baryons
745 result = TMath::Abs(particlePDG)>=3000 && TMath::Abs(particlePDG)<=3999;
747 if(requiredPDG>0) result = particlePDG>=3000 && particlePDG<=3999;
748 if(requiredPDG<0) result = particlePDG>=-3999 && particlePDG<=-3000;
751 case 400: // all charmed mesons
753 result = TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=499;
755 if(requiredPDG>0) result = particlePDG>=400 && particlePDG<=499;
756 if(requiredPDG<0) result = particlePDG>=-499 && particlePDG<=-400;
759 case 401: // open charm mesons
761 result = TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=439;
763 if(requiredPDG>0) result = particlePDG>=400 && particlePDG<=439;
764 if(requiredPDG<0) result = particlePDG>=-439 && particlePDG<=-400;
767 case 402: // open charm mesons and baryons together
769 result = (TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=439) ||
770 (TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4399);
772 if(requiredPDG>0) result = (particlePDG>=400 && particlePDG<=439) ||
773 (particlePDG>=4000 && particlePDG<=4399);
774 if(requiredPDG<0) result = (particlePDG>=-439 && particlePDG<=-400) ||
775 (particlePDG>=-4399 && particlePDG<=-4000);
778 case 403: // all charm hadrons
780 result = (TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=499) ||
781 (TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4999);
783 if(requiredPDG>0) result = (particlePDG>=400 && particlePDG<=499) ||
784 (particlePDG>=4000 && particlePDG<=4999);
785 if(requiredPDG<0) result = (particlePDG>=-499 && particlePDG<=-400) ||
786 (particlePDG>=-4999 && particlePDG<=-4000);
789 case 4000: // all charmed baryons
791 result = TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4999;
793 if(requiredPDG>0) result = particlePDG>=4000 && particlePDG<=4999;
794 if(requiredPDG<0) result = particlePDG>=-4999 && particlePDG<=-4000;
797 case 4001: // open charm baryons
799 result = TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4399;
801 if(requiredPDG>0) result = particlePDG>=4000 && particlePDG<=4399;
802 if(requiredPDG<0) result = particlePDG>=-4399 && particlePDG<=-4000;
805 case 500: // all beauty mesons
807 result = TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=599;
809 if(requiredPDG>0) result = particlePDG>=500 && particlePDG<=599;
810 if(requiredPDG<0) result = particlePDG>=-599 && particlePDG<=-500;
813 case 501: // open beauty mesons
815 result = TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=549;
817 if(requiredPDG>0) result = particlePDG>=500 && particlePDG<=549;
818 if(requiredPDG<0) result = particlePDG>=-549 && particlePDG<=-500;
821 case 502: // open beauty mesons and baryons
823 result = (TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=549) ||
824 (TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5499);
826 if(requiredPDG>0) result = (particlePDG>=500 && particlePDG<=549) ||
827 (particlePDG>=5000 && particlePDG<=5499);
828 if(requiredPDG<0) result = (particlePDG>=-549 && particlePDG<=-500) ||
829 (particlePDG>=-5499 && particlePDG<=-5000);
832 case 503: // all beauty hadrons
834 result = (TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=599) ||
835 (TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5999);
837 if(requiredPDG>0) result = (particlePDG>=500 && particlePDG<=599) ||
838 (particlePDG>=5000 && particlePDG<=5999);
839 if(requiredPDG<0) result = (particlePDG>=-599 && particlePDG<=-500) ||
840 (particlePDG>=-5999 && particlePDG<=-5000);
843 case 5000: // all beauty baryons
845 result = TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5999;
847 if(requiredPDG>0) result = particlePDG>=5000 && particlePDG<=5999;
848 if(requiredPDG<0) result = particlePDG>=-5999 && particlePDG<=-5000;
851 case 5001: // open beauty baryons
853 result = TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5499;
855 if(requiredPDG>0) result = particlePDG>=5000 && particlePDG<=5499;
856 if(requiredPDG<0) result = particlePDG>=-5499 && particlePDG<=-5000;
859 default: // all specific cases
861 result = (absRequiredPDG==TMath::Abs(particlePDG));
863 result = (requiredPDG==particlePDG);
866 if(absRequiredPDG!=0 && pdgExclusion) result = !result;
871 //________________________________________________________________________________
872 Bool_t AliDielectronMC::IsPhysicalPrimary(Int_t label) const {
874 // Check if the particle with label "label" is a physical primary according to the
875 // definition in AliStack::IsPhysicalPrimary(Int_t label)
876 // Convention for being physical primary:
877 // 1.) particles produced in the collision
878 // 2.) stable particles with respect to strong and electromagnetic interactions
879 // 3.) excludes initial state particles
880 // 4.) includes products of directly produced Sigma0 hyperon decay
881 // 5.) includes products of directly produced pi0 decays
882 // 6.) includes products of directly produced beauty hadron decays
884 if(label<0) return kFALSE;
886 if(!fMcArray) return kFALSE;
887 return (static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(label)))->IsPhysicalPrimary();
888 } else if(fAnaType==kESD) {
889 if (!fMCEvent) return kFALSE;
890 return fStack->IsPhysicalPrimary(label);
896 //________________________________________________________________________________
897 Bool_t AliDielectronMC::CheckParticleSource(Int_t label, AliDielectronSignalMC::ESource source) const {
899 // Check the source for the particle
903 case AliDielectronSignalMC::kDontCare :
906 case AliDielectronSignalMC::kPrimary :
907 // true if label is in the list of particles from physics generator
908 // NOTE: This includes all physics event history (initial state particles,
909 // exchange bosons, quarks, di-quarks, strings, un-stable particles, final state particles)
910 // Only the final state particles make it to the detector!!
911 return (label>=0 && label<=GetNPrimary());
913 case AliDielectronSignalMC::kFinalState :
914 // primary particles created in the collision which reach the detectors
916 // 1.) particles produced in the collision
917 // 2.) stable particles with respect to strong and electromagnetic interactions
918 // 3.) excludes initial state particles
919 // 4.) includes products of directly produced Sigma0 hyperon decay
920 // 5.) includes products of directly produced pi0 decays
921 // 6.) includes products of directly produced beauty hadron decays
922 return IsPhysicalPrimary(label);
924 case AliDielectronSignalMC::kDirect :
925 // Primary particles which do not have any mother
926 // This is the case for:
927 // 1.) Initial state particles (the 2 protons in Pythia pp collisions)
928 // 2.) In some codes, with sudden freeze-out, all particles generated from the fireball are direct.
929 // There is no history for these particles.
930 // 3.) Certain particles added via MC generator cocktails (e.g. J/psi added to pythia MB events)
931 return (label>=0 && GetMothersLabel(label)<0);
933 case AliDielectronSignalMC::kSecondary :
934 // particles which are created by the interaction of final state primaries with the detector
935 // or particles from strange weakly decaying particles (e.g. lambda, kaons, etc.)
936 return (label>=GetNPrimary() && !IsPhysicalPrimary(label));
945 //________________________________________________________________________________
946 Bool_t AliDielectronMC::IsMCTruth(Int_t label, AliDielectronSignalMC* signalMC, Int_t branch) {
948 // Check if the particle corresponds to the MC truth in signalMC in the branch specified
951 // NOTE: Some particles have the sign of the label flipped. It is related to the quality of matching
952 // between the ESD and the MC track. The negative labels indicate a poor matching quality
953 //if(label<0) return kFALSE;
954 if(label<0) label *= -1;
956 AliVParticle* part = GetMCTrackFromMCEvent(label);
958 AliError(Form("Could not find MC particle with label %d",label));
963 if(!ComparePDG(part->PdgCode(),signalMC->GetLegPDG(branch),signalMC->GetLegPDGexclude(branch),signalMC->GetCheckBothChargesLegs(branch))) return kFALSE;
964 if(!CheckParticleSource(label, signalMC->GetLegSource(branch))) return kFALSE;
967 AliVParticle* mcMother=0x0;
969 if(signalMC->GetMotherPDG(branch)!=0 || signalMC->GetMotherSource(branch)!=AliDielectronSignalMC::kDontCare) {
971 mLabel = GetMothersLabel(label);
972 mcMother = GetMCTrackFromMCEvent(mLabel);
974 if(!mcMother && !signalMC->GetMotherPDGexclude(branch)) return kFALSE;
976 if(!ComparePDG((mcMother ? mcMother->PdgCode() : 0),signalMC->GetMotherPDG(branch),signalMC->GetMotherPDGexclude(branch),signalMC->GetCheckBothChargesMothers(branch))) return kFALSE;
977 if(!CheckParticleSource(mLabel, signalMC->GetMotherSource(branch))) return kFALSE;
980 // check the grandmother
981 AliVParticle* mcGrandMother=0x0;
982 if(signalMC->GetGrandMotherPDG(branch)!=0 || signalMC->GetGrandMotherSource(branch)!=AliDielectronSignalMC::kDontCare) {
985 gmLabel = GetMothersLabel(mLabel);
986 mcGrandMother = static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(gmLabel));
988 if(!mcGrandMother && !signalMC->GetGrandMotherPDGexclude(branch)) return kFALSE;
990 if(!ComparePDG((mcGrandMother ? mcGrandMother->PdgCode() : 0),signalMC->GetGrandMotherPDG(branch),signalMC->GetGrandMotherPDGexclude(branch),signalMC->GetCheckBothChargesGrandMothers(branch))) return kFALSE;
991 if(!CheckParticleSource(gmLabel, signalMC->GetGrandMotherSource(branch))) return kFALSE;
999 //________________________________________________________________________________
1000 Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielectronSignalMC* signalMC) const {
1002 // Check if the pair corresponds to the MC truth in signalMC
1006 const AliVParticle * mcD1 = pair->GetFirstDaughter();
1007 const AliVParticle * mcD2 = pair->GetSecondDaughter();
1008 Int_t labelD1 = (mcD1 ? mcD1->GetLabel() : -1);
1009 Int_t labelD2 = (mcD2 ? mcD2->GetLabel() : -1);
1010 if(labelD1<0) labelD1 *= -1;
1011 if(labelD2<0) labelD2 *= -1;
1014 d1Pdg=GetPdgFromLabel(labelD1);
1015 d2Pdg=GetPdgFromLabel(labelD2);
1018 AliVParticle* mcM1=0x0;
1019 AliVParticle* mcM2=0x0;
1022 AliVParticle* mcG1 = 0x0;
1023 AliVParticle* mcG2 = 0x0;
1025 // make direct(1-1 and 2-2) and cross(1-2 and 2-1) comparisons for the whole branch
1026 Bool_t directTerm = kTRUE;
1028 directTerm = directTerm && mcD1 && ComparePDG(d1Pdg,signalMC->GetLegPDG(1),signalMC->GetLegPDGexclude(1),signalMC->GetCheckBothChargesLegs(1))
1029 && CheckParticleSource(labelD1, signalMC->GetLegSource(1));
1031 directTerm = directTerm && mcD2 && ComparePDG(d2Pdg,signalMC->GetLegPDG(2),signalMC->GetLegPDGexclude(2),signalMC->GetCheckBothChargesLegs(2))
1032 && CheckParticleSource(labelD2, signalMC->GetLegSource(2));
1036 if(signalMC->GetMotherPDG(1)!=0 || signalMC->GetMotherSource(1)!=AliDielectronSignalMC::kDontCare) {
1037 labelM1 = GetMothersLabel(labelD1);
1038 if(labelD1>-1 && labelM1>-1) mcM1 = GetMCTrackFromMCEvent(labelM1);
1039 directTerm = directTerm && (mcM1 || signalMC->GetMotherPDGexclude(1))
1040 && ComparePDG((mcM1 ? mcM1->PdgCode() : 0),signalMC->GetMotherPDG(1),signalMC->GetMotherPDGexclude(1),signalMC->GetCheckBothChargesMothers(1))
1041 && CheckParticleSource(labelM1, signalMC->GetMotherSource(1));
1045 if(signalMC->GetMotherPDG(2)!=0 || signalMC->GetMotherSource(2)!=AliDielectronSignalMC::kDontCare) {
1046 labelM2 = GetMothersLabel(labelD2);
1047 if(labelD2>-1 && labelM2>-1) mcM2 = GetMCTrackFromMCEvent(labelM2);
1048 directTerm = directTerm && (mcM2 || signalMC->GetMotherPDGexclude(2))
1049 && ComparePDG((mcM2 ? mcM2->PdgCode() : 0),signalMC->GetMotherPDG(2),signalMC->GetMotherPDGexclude(2),signalMC->GetCheckBothChargesMothers(2))
1050 && CheckParticleSource(labelM2, signalMC->GetMotherSource(2));
1055 if(signalMC->GetGrandMotherPDG(1)!=0 || signalMC->GetGrandMotherSource(1)!=AliDielectronSignalMC::kDontCare) {
1056 labelG1 = GetMothersLabel(labelM1);
1057 if(mcM1 && labelG1>-1) mcG1 = GetMCTrackFromMCEvent(labelG1);
1058 directTerm = directTerm && (mcG1 || signalMC->GetGrandMotherPDGexclude(1))
1059 && ComparePDG((mcG1 ? mcG1->PdgCode() : 0),signalMC->GetGrandMotherPDG(1),signalMC->GetGrandMotherPDGexclude(1),signalMC->GetCheckBothChargesGrandMothers(1))
1060 && CheckParticleSource(labelG1, signalMC->GetGrandMotherSource(1));
1064 if(signalMC->GetGrandMotherPDG(2)!=0 || signalMC->GetGrandMotherSource(2)!=AliDielectronSignalMC::kDontCare) {
1065 labelG2 = GetMothersLabel(labelM2);
1066 if(mcM2 && labelG2>-1) mcG2 = GetMCTrackFromMCEvent(labelG2);
1067 directTerm = directTerm && (mcG2 || signalMC->GetGrandMotherPDGexclude(2))
1068 && ComparePDG((mcG2 ? mcG2->PdgCode() : 0),signalMC->GetGrandMotherPDG(2),signalMC->GetGrandMotherPDGexclude(2),signalMC->GetCheckBothChargesGrandMothers(2))
1069 && CheckParticleSource(labelG2, signalMC->GetGrandMotherSource(2));
1073 Bool_t crossTerm = kTRUE;
1075 crossTerm = crossTerm && mcD2
1076 && ComparePDG(d2Pdg,signalMC->GetLegPDG(1),signalMC->GetLegPDGexclude(1),signalMC->GetCheckBothChargesLegs(1))
1077 && CheckParticleSource(labelD2, signalMC->GetLegSource(1));
1079 crossTerm = crossTerm && mcD1
1080 && ComparePDG(d1Pdg,signalMC->GetLegPDG(2),signalMC->GetLegPDGexclude(2),signalMC->GetCheckBothChargesLegs(2))
1081 && CheckParticleSource(labelD1, signalMC->GetLegSource(2));
1084 if(signalMC->GetMotherPDG(1)!=0 || signalMC->GetMotherSource(1)!=AliDielectronSignalMC::kDontCare) {
1085 if(!mcM2 && labelD2>-1) {
1086 labelM2 = GetMothersLabel(labelD2);
1087 if(labelM2>-1) mcM2 = GetMCTrackFromMCEvent(labelM2);
1089 crossTerm = crossTerm && (mcM2 || signalMC->GetMotherPDGexclude(1))
1090 && ComparePDG((mcM2 ? mcM2->PdgCode() : 0),signalMC->GetMotherPDG(1),signalMC->GetMotherPDGexclude(1),signalMC->GetCheckBothChargesMothers(1))
1091 && CheckParticleSource(labelM2, signalMC->GetMotherSource(1));
1094 if(signalMC->GetMotherPDG(2)!=0 || signalMC->GetMotherSource(2)!=AliDielectronSignalMC::kDontCare) {
1095 if(!mcM1 && labelD1>-1) {
1096 labelM1 = GetMothersLabel(labelD1);
1097 if(labelM1>-1) mcM1 = GetMCTrackFromMCEvent(labelM1);
1099 crossTerm = crossTerm && (mcM1 || signalMC->GetMotherPDGexclude(2))
1100 && ComparePDG((mcM1 ? mcM1->PdgCode() : 0),signalMC->GetMotherPDG(2),signalMC->GetMotherPDGexclude(2),signalMC->GetCheckBothChargesMothers(2))
1101 && CheckParticleSource(labelM1, signalMC->GetMotherSource(2));
1105 if(signalMC->GetGrandMotherPDG(1)!=0 || signalMC->GetGrandMotherSource(1)!=AliDielectronSignalMC::kDontCare) {
1107 labelG2 = GetMothersLabel(labelM2);
1108 if(labelG2>-1) mcG2 = GetMCTrackFromMCEvent(labelG2);
1110 crossTerm = crossTerm && (mcG2 || signalMC->GetGrandMotherPDGexclude(1))
1111 && ComparePDG((mcG2 ? mcG2->PdgCode() : 0),signalMC->GetGrandMotherPDG(1),signalMC->GetGrandMotherPDGexclude(1),signalMC->GetCheckBothChargesGrandMothers(1))
1112 && CheckParticleSource(labelG2, signalMC->GetGrandMotherSource(1));
1115 if(signalMC->GetGrandMotherPDG(2)!=0 || signalMC->GetGrandMotherSource(2)!=AliDielectronSignalMC::kDontCare) {
1117 labelG1 = GetMothersLabel(labelM1);
1118 if(labelG2>-1) mcG1 = GetMCTrackFromMCEvent(labelG1);
1120 crossTerm = crossTerm && (mcG1 || signalMC->GetGrandMotherPDGexclude(2))
1121 && ComparePDG((mcG1 ? mcG1->PdgCode() : 0),signalMC->GetGrandMotherPDG(2),signalMC->GetGrandMotherPDGexclude(2),signalMC->GetCheckBothChargesGrandMothers(2))
1122 && CheckParticleSource(labelG1, signalMC->GetGrandMotherSource(2));
1125 Bool_t motherRelation = kTRUE;
1126 if(signalMC->GetMothersRelation()==AliDielectronSignalMC::kSame) {
1127 motherRelation = motherRelation && HaveSameMother(pair);
1129 if(signalMC->GetMothersRelation()==AliDielectronSignalMC::kDifferent) {
1130 motherRelation = motherRelation && !HaveSameMother(pair);
1133 return ((directTerm || crossTerm) && motherRelation);
1138 //____________________________________________________________
1139 Bool_t AliDielectronMC::HaveSameMother(const AliDielectronPair * pair) const
1142 // Check whether two particles have the same mother
1145 const AliVParticle * daughter1 = pair->GetFirstDaughter();
1146 const AliVParticle * daughter2 = pair->GetSecondDaughter();
1147 if (!daughter1 || !daughter2) return 0;
1149 AliVParticle *mcDaughter1=GetMCTrackFromMCEvent(daughter1->GetLabel());
1150 AliVParticle *mcDaughter2=GetMCTrackFromMCEvent(daughter2->GetLabel());
1151 if (!mcDaughter1 || !mcDaughter2) return 0;
1153 Int_t labelMother1=-1;
1154 Int_t labelMother2=-1;
1156 if (mcDaughter1->IsA()==AliMCParticle::Class()){
1157 labelMother1=(static_cast<AliMCParticle*>(mcDaughter1))->GetMother();
1158 labelMother2=(static_cast<AliMCParticle*>(mcDaughter2))->GetMother();
1159 } else if (mcDaughter1->IsA()==AliAODMCParticle::Class()) {
1160 labelMother1=(static_cast<AliAODMCParticle*>(mcDaughter1))->GetMother();
1161 labelMother2=(static_cast<AliAODMCParticle*>(mcDaughter2))->GetMother();
1164 Bool_t sameMother=(labelMother1>-1)&&(labelMother2>-1)&&(labelMother1==labelMother2);
1169 //________________________________________________________________
1170 Int_t AliDielectronMC::IsJpsiPrimary(const AliDielectronPair * pair)
1172 // return: "0" for primary jpsi
1173 // "1" for secondary jpsi (from beauty)
1174 // "2" for background
1175 if(!HaveSameMother(pair)) return 2;
1176 AliVParticle *mcDaughter1=GetMCTrackFromMCEvent((pair->GetFirstDaughter())->GetLabel());
1177 Int_t labelMother=-1;
1179 if (mcDaughter1->IsA()==AliMCParticle::Class()){
1180 labelMother=(static_cast<AliMCParticle*>(mcDaughter1))->GetMother();
1181 } else if (mcDaughter1->IsA()==AliAODMCParticle::Class()) {
1182 labelMother=(static_cast<AliAODMCParticle*>(mcDaughter1))->GetMother();
1185 AliVParticle* mcMother=GetMCTrackFromMCEvent(labelMother);
1186 if(!IsMCMotherToEE(mcMother,443)) return 2;
1187 return IsJpsiPrimary(mcMother);
1190 //______________________________________________________________
1191 Int_t AliDielectronMC::IsJpsiPrimary(const AliVParticle * particle)
1193 // return: "0" for primary jpsi
1194 // "1" for secondary jpsi (come from B decay)
1198 if (particle->IsA()==AliMCParticle::Class()){
1199 labelMoth = (static_cast<const AliMCParticle*>(particle))->GetMother();
1201 particle = GetMCTrackFromMCEvent(labelMoth);
1202 pdgCode = TMath::Abs((static_cast<const AliMCParticle*>(particle))->PdgCode());
1203 if((pdgCode>500 && pdgCode<600) || (pdgCode>5000 && pdgCode<6000)) return 1;
1204 labelMoth = (static_cast<const AliMCParticle*>(particle))->GetMother();
1207 else if (particle->IsA()==AliAODMCParticle::Class()){
1208 labelMoth = (static_cast<const AliAODMCParticle*>(particle))->GetMother();
1210 particle = GetMCTrackFromMCEvent(labelMoth);
1211 pdgCode = TMath::Abs((static_cast<const AliAODMCParticle*>(particle))->PdgCode());
1212 if((pdgCode>500 && pdgCode<600) || (pdgCode>5000 && pdgCode<6000)) return 1;
1213 labelMoth = (static_cast<const AliAODMCParticle*>(particle))->GetMother();