3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* Hege Erdal <hege.erdal@gmail.com> *
10 //* Permission to use, copy, modify and distribute this software and its *
11 //* documentation strictly for non-commercial purposes is hereby granted *
12 //* without fee, provided that the above copyright notice appears in all *
13 //* copies and that both the copyright notice and this permission notice *
14 //* appear in the supporting documentation. The authors make no claims *
15 //* about the suitability of this software for any purpose. It is *
16 //* provided "as is" without express or implied warranty. *
17 //**************************************************************************
19 /// @file AliDxHFEToolsMC.cxx
20 /// @author Hege Erdal, Matthias Richter
22 /// @brief Common Tools for MC particle selection
25 #include "AliDxHFEToolsMC.h"
26 #include "AliAODMCParticle.h"
27 #include "AliVEvent.h"
28 #include "AliVParticle.h"
30 #include "TObjArray.h"
39 /// ROOT macro for the implementation of ROOT specific class methods
40 ClassImp(AliDxHFEToolsMC)
42 AliDxHFEToolsMC::AliDxHFEToolsMC(const char* option)
48 , fHistPDGMother(NULL)
49 , fOriginMother(kOriginNone)
61 const char* AliDxHFEToolsMC::fgkPDGBinLabels[]={
75 const char* AliDxHFEToolsMC::fgkPDGMotherBinLabels[]={
89 const char* AliDxHFEToolsMC::fgkStatisticsBinLabels[]={
90 "all", // all MC particles
91 "found", // selected particles with correct MC
92 "fake" // selected particles without corresponding MC
95 AliDxHFEToolsMC::~AliDxHFEToolsMC()
98 if (fHistPDG) delete fHistPDG;
100 if (fHistPDGMother) delete fHistPDGMother;
104 int AliDxHFEToolsMC::Init(const char* option)
106 // initialize according to options
107 TString strOption(option);
108 bool bControlHist=true;
109 std::auto_ptr<TObjArray> tokens(strOption.Tokenize(" "));
110 if (tokens.get() && tokens->GetEntriesFast()>0) {
111 for (int itoken=0; itoken<tokens->GetEntriesFast(); itoken++) {
112 if (tokens->At(itoken)==NULL) continue;
113 TString arg=tokens->At(itoken)->GetName();
116 if (arg.BeginsWith(key)) {
117 arg.ReplaceAll(key, "");
118 fPDGs.push_back(arg.Atoi());
121 if (arg.BeginsWith(key)) {
122 arg.ReplaceAll(key, "");
123 fMotherPDGs.push_back(arg.Atoi());
126 if (arg.BeginsWith(key)) {
127 arg.ReplaceAll(key, "");
128 bControlHist=arg.CompareTo("off")!=0;
131 if (arg.BeginsWith(key)) {
135 if (arg.BeginsWith(key)) {
142 fHistPDG=CreateControlHistogram("histPDG",
143 "pdg code of selected particle",
144 sizeof(fgkPDGBinLabels)/sizeof(const char*),
146 fHistPDGMother=CreateControlHistogram("histPDGMother",
147 "pdg code of first mother of selected particle",
148 sizeof(fgkPDGMotherBinLabels)/sizeof(fgkPDGMotherBinLabels[0]),
149 fgkPDGMotherBinLabels);
154 int AliDxHFEToolsMC::InitMCParticles(const AliVEvent* pEvent)
157 // init MC info from event object
158 if (!pEvent) return -EINVAL;
160 // TODO: choose branch name depending on VEvent type; configurable?
161 TString branchname(AliAODMCParticle::StdBranchName());
162 TObject* o=pEvent->FindListObject(branchname);
164 AliWarningClass(Form("can not find MC info '%s' in event of type '%s'", branchname.Data(), pEvent->ClassName()));
167 fMCParticles = dynamic_cast<TObjArray*>(o);
169 AliWarningClass(Form("ignoring MC info '%s' of wrong type '%s', expecting TObjArray", branchname.Data(), o->ClassName()));
172 fNrMCParticles=fMCParticles->GetEntriesFast();
176 bool AliDxHFEToolsMC::RejectByPDG(int pdg, const vector<int> &list) const
178 // check if pdg should be rejected, particle is not rejected
179 // if it is in the list, returns always false if list is empty
180 if (list.size()==0) return false;
181 for (vector<int>::const_iterator i=list.begin();
182 i!=list.end(); i++) {
183 if (*i==pdg) return false;
188 bool AliDxHFEToolsMC::RejectByPDG(AliVParticle* p, bool doStatistics, int* pdgParticleResult)
190 // check if pdg should be rejected
191 // always false if not pdg list is initialized
192 if (!p) return false;
193 Int_t MClabel = p->GetLabel();
194 if(MClabel<0) return 0;
197 // TODO: there might be more types of particles to be checked
198 AliAODMCParticle* aodmcp=0;
199 aodmcp=dynamic_cast<AliAODMCParticle*>(fMCParticles->At(MClabel));
201 pdgPart=TMath::Abs(aodmcp->GetPdgCode());
202 if (pdgPart<0) return 0;
204 if (pdgParticleResult)
205 *pdgParticleResult=pdgPart;
207 bool bReject=RejectByPDG(pdgPart, fPDGs);
208 if (doStatistics && fHistPDG) {
209 // TODO: think about histogramming mode, e.g. histogramming of rejected particles?
211 fHistPDG->Fill(MapPDGLabel(p->PdgCode()));
217 bool AliDxHFEToolsMC::RejectByMotherPDG(AliVParticle* p, bool doStatistics)
219 // check if pdg should be rejected by mother
220 // always false if not mother pdg list is initialized
221 // H: think maybe this is particle specific, and should be moved to PartSelMCEl
222 if (!p) return false;
223 int motherpdg=FindPdgOriginMother(p);
224 // TODO: This should be tweaked. Want to
225 bool bReject=RejectByPDG(motherpdg, fMotherPDGs);
226 if (doStatistics && fHistPDGMother) {
227 // TODO: think about histogramming mode, e.g. histogramming of rejected particles?
229 fHistPDGMother->Fill(MapPDGMotherLabel(p->PdgCode()));
235 int AliDxHFEToolsMC::FindMotherPDG(AliVParticle* p, bool bReturnFirstMother)
237 // Will find and return pdg of the mother, either first or loop down to the
240 // To reset fOriginMother.
241 fOriginMother=kOriginNone;
243 if (!p) return false;
244 int motherpdg=FindPdgOriginMother(p, bReturnFirstMother);
250 TH1* AliDxHFEToolsMC::CreateControlHistogram(const char* name,
253 const char** binLabels) const
255 /// create control histogram
256 std::auto_ptr<TH1> h(new TH1D(name, title, nBins, -0.5, nBins-0.5));
257 if (!h.get()) return NULL;
258 for (int iLabel=0; iLabel<nBins; iLabel++) {
259 h->GetXaxis()->SetBinLabel(iLabel+1, binLabels[iLabel]);
265 int AliDxHFEToolsMC::MapPDGLabel(int pdg) const
267 /// mapping of pdg code to enum
269 case kPDGelectron : return kPDGLabelElectron;
270 case -kPDGelectron : return kPDGLabelPositron;
271 case kPDGmuon : return kPDGLabelMuPlus;
272 case -kPDGmuon : return kPDGLabelMuMinus;
273 case kPDGpion : return kPDGLabelPiPlus;
274 case -kPDGpion : return kPDGLabelPiMinus;
275 case kPDGkaon : return kPDGLabelKPlus;
276 case -kPDGkaon : return kPDGLabelKMinus;
277 case kPDGproton : return kPDGLabelProton;
278 case -kPDGproton : return kPDGLabelAntiproton;
280 return kPDGLabelOthers;
284 int AliDxHFEToolsMC::MapPDGMotherLabel(int pdg) const
286 /// mapping of pdg code to enum
288 case kPDGd : return kPDGMotherLabelD;
289 case kPDGu : return kPDGMotherLabelU;
290 case kPDGs : return kPDGMotherLabelS;
291 case kPDGc : return kPDGMotherLabelC;
292 case kPDGb : return kPDGMotherLabelB;
293 case kPDGgluon : return kPDGMotherLabelGluon;
294 case kPDGgamma : return kPDGMotherLabelGamma;
295 case kPDGpi0 : return kPDGMotherLabelPi0;
296 case kPDGeta : return kPDGMotherLabelEta;
297 case kPDGproton: return kPDGMotherLabelProton;
299 return kPDGLabelOthers;
303 int AliDxHFEToolsMC::FindPdgOriginMother(AliVParticle* p, bool bReturnFirstMother)
305 // Return the pgd of original mother particle
306 // TODO: need also to have specific for D0, electron etc
307 // for instance to mark when you have gluon, charm or beauty
308 // among the mothers. Or maybe this will be the same anyway?
309 // TODO: implement tests on origin, if charm/beauty quark and if
310 // they came from gluon. use booleans to set this which can be accessed from
311 // outside? Something like fSequence.
313 if (!p) return kPDGnone;
318 // Either using MClabel set from outside (needed for Dmesons), or find it
320 MClabel = p->GetLabel();
325 else MClabel=fMClabel;
327 // try different classes, unfortunately there is no common base class
328 AliAODMCParticle* aodmcp=0;
329 aodmcp=dynamic_cast<AliAODMCParticle*>(fMCParticles->At(MClabel));
333 imother = aodmcp->GetMother();
335 // Absolute or +/- on pgd ???
336 Int_t pdg=TMath::Abs(aodmcp->GetPdgCode());
339 // also check this particle
340 CheckOriginMother(pdg);
344 if (!fMCParticles->At(imother)) {
345 AliErrorClass(Form("no mc particle with label %d", imother));
349 AliAODMCParticle * mother=dynamic_cast<AliAODMCParticle*>(fMCParticles->At(imother));
351 AliErrorClass(Form("mc mother particle of wrong class type %s", fMCParticles->At(imother)->ClassName()));
355 if(bReturnFirstMother){
356 return mother->GetPdgCode();
359 CheckOriginMother(pdg);
361 if (mother->GetPdgCode()==kPDGproton){
362 // why? - H: This is the proton, can't get further back
363 // To be discussed whether to do this a different way
367 //Reset fMClabel to find pdg of mother if looping on D
369 pdg=FindPdgOriginMother(mother);
374 void AliDxHFEToolsMC::CheckOriginMother(int pdg)
377 // Checking if the particle is a quark or gluon and setting fOriginMother accordingly.
378 // Right now only check on quark. Need also check on whether it comes from D or B meson?
382 fOriginMother = kOriginCharm; break;
384 fOriginMother = kOriginBeauty; break;
386 if(fOriginMother==kOriginCharm) fOriginMother=kOriginGluonCharm;
387 else if(fOriginMother==kOriginBeauty) fOriginMother=kOriginGluonBeauty;
388 else fOriginMother=kOriginGluon;
391 if(!TestIfHFquark(fOriginMother))
392 fOriginMother=kOriginDown;
395 if(!TestIfHFquark(fOriginMother))
396 fOriginMother=kOriginUp;
399 if(!TestIfHFquark(fOriginMother))
400 fOriginMother=kOriginStrange;
405 Bool_t AliDxHFEToolsMC::TestIfHFquark(int origin)
408 // Checking if particle has been marked as charm/beauty quark
416 case(kOriginGluonCharm):
418 case(kOriginGluonBeauty):
424 void AliDxHFEToolsMC::Clear(const char* /*option*/)
426 // clear internal memory