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 //-------------------------------------------------------------------------
18 // -------------------
19 // Simple collection of reconstructed tracks
20 // selected from an ESD event
21 // to be used for analysis.
22 // .........................................
24 // author: A. Pulvirenti (email: alberto.pulvirenti@ct.infn.it)
25 //-------------------------------------------------------------------------
29 #include <TClonesArray.h>
30 #include <TDatabasePDG.h>
33 #include "AliRsnMCInfo.h"
34 #include "AliRsnDaughter.h"
35 #include "AliRsnEvent.h"
37 #include "AliRsnPID.h"
41 const char* AliRsnPID::fgkParticleNameLong[AliRsnPID::kSpecies + 1] =
51 const char* AliRsnPID::fgkParticleNameShort[AliRsnPID::kSpecies + 1] =
61 const char* AliRsnPID::fgkParticleNameLatex[AliRsnPID::kSpecies + 1] =
71 const Int_t AliRsnPID::fgkParticlePDG[AliRsnPID::kSpecies + 1] =
81 //_____________________________________________________________________________
82 AliRsnPID::AliRsnPID() :
88 // Default constructor
89 // Sets a default setup:
91 // - no lower limit for probability
92 // - upper limit of 10 GeV for Pt
93 // - suitable values for prior probabilities
96 fPrior[kElectron] = 0.20;
97 fPrior[kMuon ] = 0.20;
98 fPrior[kPion ] = 0.83;
99 fPrior[kKaon ] = 0.07;
100 fPrior[kProton ] = 0.06;
103 //_____________________________________________________________________________
104 AliRsnPID::AliRsnPID(const AliRsnPID &event) :
105 TObject((TObject)event),
106 fMethod(event.fMethod),
107 fMaxPt(event.fMaxPt),
108 fMinProb(event.fMinProb)
112 // Implemented to manage the array safely.
116 for (i = 0; i < kSpecies; i++) fPrior[i] = event.fPrior[i];
119 //_____________________________________________________________________________
120 AliRsnPID& AliRsnPID::operator=(const AliRsnPID &event)
123 // Assignment operator.
124 // Implemented to manage the array safely.
127 fMethod = event.fMethod;
128 fMaxPt = event.fMaxPt;
129 fMinProb = event.fMinProb;
132 for (i = 0; i < kSpecies; i++) fPrior[i] = event.fPrior[i];
134 // return the newly created object
138 //_____________________________________________________________________________
139 AliRsnPID::EType AliRsnPID::InternalType(Int_t pdg)
141 // Return the internal enum value corresponding to the PDG
142 // code passed as argument, if possible.
143 // Otherwise, returns 'kUnknown' by default.
147 Int_t absPDG = TMath::Abs(pdg);
172 //_____________________________________________________________________________
173 Int_t AliRsnPID::PDGCode(EType type)
176 // Returns the PDG code of the particle type
177 // specified as argument (w.r. to the internal enum)
180 if (type >= kElectron && type <= kUnknown) {
181 return fgkParticlePDG[type];
188 //_____________________________________________________________________________
189 const char* AliRsnPID::ParticleName(EType type, Bool_t shortName)
192 // Returns the name of the particle type
193 // specified as argument (w.r. to the internal enum)
196 if (type >= kElectron && type <= kUnknown) {
197 return shortName ? fgkParticleNameShort[type] : fgkParticleNameLong[type];
200 return shortName ? "unk" : "unknown";
204 //_____________________________________________________________________________
205 const char* AliRsnPID::ParticleNameLatex(EType type)
208 // Returns the name of the particle type
209 // specified as argument (w.r. to the internal enum)
212 if (type >= kElectron && type <= kUnknown) {
213 return fgkParticleNameLatex[type];
220 //_____________________________________________________________________________
221 Double_t AliRsnPID::ParticleMass(EType type)
224 // Returns the mass corresponding to the particle type
225 // specified as argument (w.r. to the internal enum)
227 TDatabasePDG *db = TDatabasePDG::Instance();
228 Int_t pdg = PDGCode(type);
229 return db->GetParticle(pdg)->Mass();
232 //_____________________________________________________________________________
233 Bool_t AliRsnPID::IdentifyRealistic(AliRsnDaughter *daughter)
236 // Uses the Bayesian combination of prior probabilities
237 // with the PID weights of the passed object to compute
238 // the overall PID probabilities for each particle type.
240 // Once this computation is done, the argument is assigned
241 // the PID corresponding to the largest probability,
242 // and its data members are updated accordingly.
243 // If the track Pt is larger than the cut defined (fMaxPt)
244 // or the probability is smaller than the cut defined (fMinProb),
245 // the track is considered unidentified.
247 // If the identification procedure encounters errors,
248 // the return value will be "FALSE", otherwise it is "TRUE".
251 // reset all PID probabilities to 0.0
252 Unidentify(daughter, 0.0);
254 // check the transverse momentum:
255 // if it is larger than the cut, the particle is unidentified
256 // setting all its probabilities to 1.0
257 if (daughter->Pt() > fMaxPt) {
258 Unidentify(daughter, 1.0);
262 // 0 - retrieve PID weights from argument
265 Double_t *prob = new Double_t[kSpecies];
266 Double_t *weight = new Double_t[kSpecies];
267 for (i = 0; i < kSpecies; i++) weight[i] = (daughter->PID())[i];
269 // step 1 - compute the normalization factor
270 for (i = 0; i < kSpecies; i++) {
271 prob[i] = fPrior[i] * weight[i];
274 if (sum <= (Double_t)0.) {
275 AliError(Form("Sum of weights = %f < 0", sum));
279 // step 2 - normalize PID weights and update daughter data-member
280 for (i = 0; i < kSpecies; i++) {
282 daughter->SetPIDProb(i, prob[i]);
285 // step 3 - find the maximum probability and update daughter data members
287 Double_t pmax = prob[0];
288 for (i = 1; i < kSpecies; i++) {
289 if (prob[i] > pmax) {
294 EType type = (EType)imax;
295 if (pmax >= fMinProb) {
296 daughter->SetPIDType(type);
297 daughter->SetM(ParticleMass(type));
300 daughter->SetPIDType(kUnknown);
306 //_____________________________________________________________________________
307 Bool_t AliRsnPID::IdentifyPerfect(AliRsnDaughter *daughter)
310 // Uses the true PDG code to make a perfect identification.
311 // If the true PDG code does not correspond to any
312 // of the expected PID types, gives a warning, sets the
313 // PID to 'unknown' and returns kFALSE.
314 // Otherwise, returns kTRUE.
317 // reset all PID probabilities to 0.0
318 Unidentify(daughter, 0.0);
320 // if the MCInfo is not present, the particle cannot be identified perfectly
321 // in this case, to notice the error, the probs are maintained all to 0.0
322 AliRsnMCInfo *particle = daughter->GetMCInfo();
324 AliWarning("Particle object not initialized: impossible to do perfect PID");
328 // convert the PDG into the internal enum
329 Int_t pdgCode = particle->PDG();
330 EType type = InternalType(pdgCode);
332 // if the type is one of the available ones in the PID enum
334 // the corresponding probability is set to 1, and the other remain 0
335 if (type >= 0 && type < kSpecies) {
336 daughter->SetPIDType(type);
337 daughter->SetPIDProb(type, 1.0);
338 daughter->SetM(ParticleMass(type));
345 //_____________________________________________________________________________
346 Bool_t AliRsnPID::Unidentify(AliRsnDaughter *daughter, Double_t value)
349 // Sets the PID to 'unknown' to every track.
353 for (i = 0; i < kSpecies; i++) daughter->SetPIDProb(i, value);
354 daughter->SetPIDType(kUnknown);
358 //_____________________________________________________________________________
359 Bool_t AliRsnPID::Identify(AliRsnDaughter *daughter)
362 // Recalls one of the above methods, according to the one
363 // defined in the related data member.
364 // If the method is not recognized, returns kFALSE and
365 // gives an alert. Otherwise, returns kTRUE.
370 Unidentify(daughter);
373 IdentifyRealistic(daughter);
376 IdentifyPerfect(daughter);
379 AliError(Form("PID method '%d' unrecognized. Nothing done.", fMethod));
384 //_____________________________________________________________________________
385 Bool_t AliRsnPID::IdentifiedAs(AliRsnDaughter *d, EType type, Short_t charge)
388 // Tells if a particle has been identified to be of a given tipe and charge.
389 // If the charge is zero, the check is done only on the PID type, otherwise
390 // both charge and PID type are required to match
393 return (d->PIDType() == type);
395 else if (charge > 0) {
396 return (d->PIDType() == type && d->Charge() > 0);
399 return (d->PIDType() == type && d->Charge() < 0);
403 //_____________________________________________________________________________
404 Bool_t AliRsnPID::Identify(AliRsnEvent *event)
407 // Performs identification for all tracks in a given event.
408 // Returns the logical AND of all PID operations.
411 Bool_t check = kTRUE;
412 if (!event) return check;
413 if (!event->GetTracks()) return check;
414 if (event->GetTracks()->IsEmpty()) return check;
416 AliRsnDaughter *daughter = 0;
417 TObjArrayIter iter(event->GetTracks());
418 while ( (daughter = (AliRsnDaughter*)iter.Next()) ) {
419 check = check && Identify(daughter);
421 event->FillPIDArrays();
427 //_____________________________________________________________________________
428 void AliRsnPID::SetPriorProbability(EType type, Double_t p)
431 // Sets the prior probability for Realistic PID, for a
432 // given particle species.
435 if (type >= kElectron && type < kSpecies) {