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 **************************************************************************/
17 // Interface to the user task
18 // Several strategies for Electron identification implemented.
19 // In addition users can combine different detectors or use
20 // single detector PID
23 // Markus Fasel <M.Fasel@gsi.de>
27 #include <THnSparse.h>
28 #include <TIterator.h>
30 #include <TObjArray.h>
31 #include <TObjString.h>
34 #include "AliESDtrack.h"
38 #include "AliHFEpid.h"
39 #include "AliHFEpidBase.h"
40 #include "AliHFEpidITS.h"
41 #include "AliHFEpidTPC.h"
42 #include "AliHFEpidTRD.h"
43 #include "AliHFEpidTOF.h"
44 #include "AliHFEpidMC.h"
48 //____________________________________________________________
49 AliHFEpid::AliHFEpid():
56 // Default constructor
58 memset(fDetectorPID, 0, sizeof(AliHFEpidBase *) * kNdetectorPID);
61 //____________________________________________________________
62 AliHFEpid::AliHFEpid(const AliHFEpid &c):
64 fEnabledDetectors(c.fEnabledDetectors),
67 fDebugLevel(c.fDebugLevel)
72 memset(fDetectorPID, 0, sizeof(AliHFEpidBase *) * kNdetectorPID);
73 if(c.fDetectorPID[kMCpid])
74 fDetectorPID[kMCpid] = new AliHFEpidMC(*(dynamic_cast<AliHFEpidMC *>(c.fDetectorPID[kMCpid])));
75 if(c.fDetectorPID[kTPCpid])
76 fDetectorPID[kTPCpid] = new AliHFEpidTPC(*(dynamic_cast<AliHFEpidTPC *>(c.fDetectorPID[kTPCpid])));
77 if(c.fDetectorPID[kTRDpid])
78 fDetectorPID[kTRDpid] = new AliHFEpidTRD(*(dynamic_cast<AliHFEpidTRD *>(c.fDetectorPID[kTOFpid])));
79 if(c.fDetectorPID[kTOFpid])
80 fDetectorPID[kTOFpid] = new AliHFEpidTOF(*(dynamic_cast<AliHFEpidTOF *>(c.fDetectorPID[kTOFpid])));
81 if(c.IsQAOn()) SetQAOn();
82 if(c.HasMCData()) SetHasMCData(kTRUE);
83 for(Int_t idet = 0; idet < kNdetectorPID; idet++){
84 if(c.IsQAOn() && fDetectorPID[idet]) fDetectorPID[idet]->SetQAOn(fQAlist);
85 if(c.HasMCData() && fDetectorPID[idet]) fDetectorPID[idet]->SetHasMCData(kTRUE);
89 //____________________________________________________________
90 AliHFEpid& AliHFEpid::operator=(const AliHFEpid &c){
92 // Assignment operator
94 TObject::operator=(c);
97 fEnabledDetectors = c.fEnabledDetectors;
98 fPIDstrategy = c.fPIDstrategy;
100 fDebugLevel = c.fDebugLevel;
102 memset(fDetectorPID, 0, sizeof(AliHFEpidBase *) * kNdetectorPID);
103 if(c.fDetectorPID[kMCpid])
104 fDetectorPID[kMCpid] = new AliHFEpidMC(*(dynamic_cast<AliHFEpidMC *>(c.fDetectorPID[kMCpid])));
105 if(c.fDetectorPID[kTPCpid])
106 fDetectorPID[kTPCpid] = new AliHFEpidTPC(*(dynamic_cast<AliHFEpidTPC *>(c.fDetectorPID[kTPCpid])));
107 if(c.fDetectorPID[kTRDpid])
108 fDetectorPID[kTRDpid] = new AliHFEpidTRD(*(dynamic_cast<AliHFEpidTRD *>(c.fDetectorPID[kTOFpid])));
109 if(c.fDetectorPID[kTOFpid])
110 fDetectorPID[kTOFpid] = new AliHFEpidTOF(*(dynamic_cast<AliHFEpidTOF *>(c.fDetectorPID[kTOFpid])));
111 if(c.IsQAOn()) SetQAOn();
112 if(c.HasMCData()) SetHasMCData(kTRUE);
113 for(Int_t idet = 0; idet < kNdetectorPID; idet++){
114 if(c.IsQAOn() && fDetectorPID[idet]) fDetectorPID[idet]->SetQAOn(fQAlist);
115 if(c.HasMCData() && fDetectorPID[idet]) fDetectorPID[idet]->SetHasMCData();
121 //____________________________________________________________
122 AliHFEpid::~AliHFEpid(){
126 for(Int_t idet = 0; idet < kNdetectorPID; idet++){
127 if(fDetectorPID[idet])
128 delete fDetectorPID[idet];
130 if(fQAlist) delete fQAlist; fQAlist = 0x0; // Each detector has to care about its Histograms
133 //____________________________________________________________
134 Bool_t AliHFEpid::InitializePID(TString arg){
136 // Initializes PID Object:
137 // + Defines which detectors to use
138 // + Initializes Detector PID objects
141 fDetectorPID[kMCpid] = new AliHFEpidMC("Monte Carlo PID"); // Always there
142 SETBIT(fEnabledDetectors, kMCpid);
143 // Initialize detector PIDs according to PID Strategies
144 if(arg.BeginsWith("Strategy")){
145 arg.ReplaceAll("Strategy", "");
146 fPIDstrategy = arg.Atoi();
147 AliInfo(Form("PID Strategy %d enabled", fPIDstrategy));
148 Int_t strategyStatus = kTRUE;
149 switch(fPIDstrategy){
150 case 1: InitStrategy1(); break;
151 case 2: InitStrategy2(); break;
152 case 3: InitStrategy3(); break;
153 case 4: InitStrategy4(); break;
154 case 5: InitStrategy5(); break;
155 case 6: InitStrategy6(); break;
156 default: strategyStatus = kFALSE;
158 return strategyStatus;
160 // No Strategy defined, Initialize according to detectors specified
161 AliInfo(Form("Doing InitializePID for Detectors %s end", arg.Data()));
162 fDetectorPID[kITSpid] = new AliHFEpidITS("ITS development PID"); // Development version of the ITS pid, for the moment always there
163 SETBIT(fEnabledDetectors, kITSpid);
165 TObjArray *detsEnabled = arg.Tokenize(":");
166 TIterator *detIterator = detsEnabled->MakeIterator();
167 TObjString *det = 0x0;
168 while((det = dynamic_cast<TObjString *>(detIterator->Next()))){
169 if(det->String().CompareTo("TPC") == 0){
170 AliInfo("Doing TPC PID");
171 fDetectorPID[kTPCpid] = new AliHFEpidTPC("TPC PID");
172 SETBIT(fEnabledDetectors, kTPCpid);
173 } else if(det->String().CompareTo("TRD") == 0){
174 fDetectorPID[kTRDpid] = new AliHFEpidTRD("TRD PID");
175 SETBIT(fEnabledDetectors, kTRDpid);
176 } else if(det->String().CompareTo("TOF") == 0){
177 AliInfo("Doing TOF PID");
178 fDetectorPID[kTOFpid] = new AliHFEpidTOF("TOF PID");
179 SETBIT(fEnabledDetectors, kTOFpid);
181 // Here is still space for ESD PID
183 // Initialize PID Objects
184 Bool_t status = kTRUE;
185 for(Int_t idet = 0; idet < kNdetectorPID; idet++){
186 if(fDetectorPID[idet]){
187 status &= fDetectorPID[idet]->InitializePID();
188 if(IsQAOn() && status) fDetectorPID[idet]->SetQAOn(fQAlist);
189 if(HasMCData() && status) fDetectorPID[idet]->SetHasMCData();
195 //____________________________________________________________
196 Bool_t AliHFEpid::IsSelected(AliHFEpidObject *track){
198 // Steers PID decision for single detectors respectively combined
201 if(!track->fRecTrack){
203 return (TMath::Abs(fDetectorPID[kMCpid]->IsSelected(track)) == 11);
205 if(fPIDstrategy > 0 && fPIDstrategy < 7){
207 switch(fPIDstrategy){
208 case 1: pid = IdentifyStrategy1(track); break;
209 case 2: pid = IdentifyStrategy2(track); break;
210 case 3: pid = IdentifyStrategy3(track); break;
211 case 4: pid = IdentifyStrategy4(track); break;
212 case 5: pid = IdentifyStrategy5(track); break;
213 case 6: pid = IdentifyStrategy6(track); break;
218 if(TESTBIT(fEnabledDetectors, kTPCpid)){
219 if(IsQAOn() && fDebugLevel > 1){
220 AliInfo("Filling QA plots");
221 MakePlotsItsTpc(track); // First fill the QA histograms
223 if(TESTBIT(fEnabledDetectors, kTOFpid)){
225 return MakePidTpcTof(track);
226 } else if(TESTBIT(fEnabledDetectors, kTRDpid)){
227 // case TPC-TRD with low level detector Signals
228 return MakePidTpcTrd(track);
230 return (TMath::Abs(fDetectorPID[kTPCpid]->IsSelected(track)) ==11);
231 } else if(TESTBIT(fEnabledDetectors, kTRDpid)){
232 return (TMath::Abs(fDetectorPID[kTRDpid]->IsSelected(track)) ==11);
233 } else if(TESTBIT(fEnabledDetectors, kTOFpid)){
234 return (TMath::Abs(fDetectorPID[kTOFpid]->IsSelected(track)) ==11);
240 //____________________________________________________________
241 Bool_t AliHFEpid::MakePidTpcTof(AliHFEpidObject *track){
243 // Combines TPC and TOF PID decision
245 if(track->fAnalysisType != AliHFEpidObject::kESDanalysis) return kFALSE;
246 AliESDtrack *esdTrack = dynamic_cast<AliESDtrack *>(track->fRecTrack);
247 if(!esdTrack) return kFALSE;
249 AliHFEpidTOF *tofPID = dynamic_cast<AliHFEpidTOF*>(fDetectorPID[kTOFpid]);
251 AliWarning("TOF pid object is NULL");
256 AliHFEpidTPC *tpcPID = dynamic_cast<AliHFEpidTPC*>(fDetectorPID[kTPCpid]);
258 AliWarning("TPC pid object is NULL");
262 // charge of the particle
264 if(esdTrack->GetOuterParam()) charge = esdTrack->GetOuterParam()->Charge();
265 else charge = esdTrack->GetInnerParam()->Charge();
268 const Int_t cTPCsigma = 2;
269 // set the number of sigmas in the TPC
270 tpcPID->SetTPCnSigma(cTPCsigma);
271 // turn on the the dEdx line crossing for kaons and protons
272 tpcPID->AddTPCdEdxLineCrossing(3, cTPCsigma); // for kaons
273 tpcPID->AddTPCdEdxLineCrossing(4, cTPCsigma); // for protons
274 // request the tpc PID information
275 Int_t pidTPC = tpcPID->IsSelected(track);
277 // without TPC pid it makes no sense to look at the TOF pid with this detector combination
282 // is the TPC in the crossing line region? 0 - no crossing, otherwise the AliPID of the crossing
283 // particle returned - 3 for Kaon and 4 for Proton
284 Int_t crossing = tpcPID->GetCrossingType();
287 const Int_t cTOFsigma = 3;
288 tofPID->SetTOFnSigma(cTOFsigma);
289 // request TOF PID information
290 Int_t pidTOF = tofPID->IsSelected(track);
292 // case that the TOF for some reason does not deliver a PID information
293 // or the TPC is not in the crossing point region, only the TPC will be used
294 if(0 != pidTOF && 0 != crossing){
296 return (321 == pidTOF) ? kFALSE : kTRUE;
298 else if(4 == crossing){
299 return (2212 == pidTOF) ? kFALSE : kTRUE;
302 // something went wrong
303 AliError("Wrong crossing type returned from AliHFEpidTPC - check your code!!");
309 return (11 == pidTPC) ? kTRUE : kFALSE;
313 //____________________________________________________________
314 Bool_t AliHFEpid::MakePidTpcTrd(AliHFEpidObject *track){
316 // Combination of TPC and TRD PID
317 // Fills Histograms TPC Signal vs. TRD signal for different
320 if(track->fAnalysisType != AliHFEpidObject::kESDanalysis) return kFALSE; //AOD based detector PID combination not yet implemented
321 AliDebug(1, "Analysis Type OK, do PID");
322 AliESDtrack *esdTrack = dynamic_cast<AliESDtrack *>(track->fRecTrack);
323 AliHFEpidTRD *trdPid = dynamic_cast<AliHFEpidTRD *>(fDetectorPID[kTRDpid]);
324 Int_t pdg = TMath::Abs(fDetectorPID[kMCpid]->IsSelected(track));
327 case 11: pid = AliPID::kElectron; break;
328 case 13: pid = AliPID::kMuon; break;
329 case 211: pid = AliPID::kPion; break;
330 case 321: pid = AliPID::kKaon; break;
331 case 2212: pid = AliPID::kProton; break;
334 Double_t content[10];
336 content[1] = esdTrack->P();
337 content[2] = esdTrack->GetTPCsignal();
338 content[3] = trdPid->GetTRDSignalV1(esdTrack, pid);
339 if(IsQAOn() && fDebugLevel > 1){
340 content[4] = trdPid->GetTRDSignalV2(esdTrack, pid);
341 AliDebug(1, Form("Momentum: %f, TRD Signal: Method 1[%f], Method 2[%f]", content[1], content[3], content[4]));
342 (dynamic_cast<THnSparseF *>(fQAlist->At(kTRDSignal)))->Fill(content);
344 if(content[1] > 2){ // perform combined
345 AliDebug(1, "Momentum bigger 2 GeV/c, doing combined PID");
346 if(content[2] > 65 && content[3] > 500) return kTRUE;
350 AliDebug(1, "Momentum smaller 2GeV/c, doing TPC alone PID");
351 return fDetectorPID[kTPCpid]->IsSelected(track) == 11;
355 //____________________________________________________________
356 void AliHFEpid::MakePlotsItsTpc(AliHFEpidObject *track){
358 // Make a plot ITS signal - TPC signal for several momentum bins
360 if(track->fAnalysisType != AliHFEpidObject::kESDanalysis) return; //AOD based detector PID combination not yet implemented
361 AliESDtrack * esdTrack = dynamic_cast<AliESDtrack *>(track->fRecTrack);
362 // Fill My Histograms for MC PID
363 Int_t pdg = TMath::Abs(fDetectorPID[kMCpid]->IsSelected(track));
366 case 11: pid = AliPID::kElectron; break;
367 case 13: pid = AliPID::kMuon; break;
368 case 211: pid = AliPID::kPion; break;
369 case 321: pid = AliPID::kKaon; break;
370 case 2212: pid = AliPID::kProton; break;
373 if(IsQAOn() && fDebugLevel > 0){
374 Double_t content[10];
376 content[1] = esdTrack->GetTPCInnerParam() ? esdTrack->GetTPCInnerParam()->P() : esdTrack->P();
377 content[2] = (dynamic_cast<AliHFEpidITS *>(fDetectorPID[kITSpid]))->GetITSSignalV1(track->fRecTrack, pid);
378 content[3] = esdTrack->GetTPCsignal();
379 AliDebug(1, Form("Momentum %f, TPC Signal %f, ITS Signal %f", content[1], content[2], content[3]));
380 (dynamic_cast<THnSparseF *>(fQAlist->At(kITSSignal)))->Fill(content);
384 //____________________________________________________________
385 void AliHFEpid::SetQAOn(){
389 SetBit(kIsQAOn, kTRUE);
390 AliInfo("QA switched on");
393 fQAlist->SetName("PIDqa");
394 THnSparseF *histo = NULL;
396 // Prepare axis for QA histograms
397 const Int_t kMomentumBins = 41;
398 const Double_t kPtMin = 0.1;
399 const Double_t kPtMax = 10.;
400 Double_t momentumBins[kMomentumBins];
401 for(Int_t ibin = 0; ibin < kMomentumBins; ibin++)
402 momentumBins[ibin] = static_cast<Double_t>(TMath::Power(10,TMath::Log10(kPtMin) + (TMath::Log10(kPtMax)-TMath::Log10(kPtMin))/(kMomentumBins-1)*static_cast<Double_t>(ibin)));
404 // Add Histogram for combined TPC-TRD PID
406 AliDebug(1, "Adding histogram for ITS-TPC investigation");
407 const Int_t kDimensionsTRDsig = 5;
408 Int_t kNbinsTRDsig[kDimensionsTRDsig] = {AliPID::kSPECIES + 1, kMomentumBins - 1, 200, 3000, 3000};
409 Double_t binMinTRDsig[kDimensionsTRDsig] = {-1., 0.1, 0, 0, 0};
410 Double_t binMaxTRDsig[kDimensionsTRDsig] = {AliPID::kSPECIES, 10., 200., 3000., 3000.};
411 fQAlist->AddAt((histo = new THnSparseF("fCombTPCTRDpid", "Combined TPC-TRD PID", kDimensionsTRDsig, kNbinsTRDsig, binMinTRDsig, binMaxTRDsig)), kTRDSignal);
412 histo->GetAxis(1)->Set(kMomentumBins - 1, momentumBins);
413 histo->GetAxis(0)->SetTitle("Particle Species");
414 histo->GetAxis(1)->SetTitle("p / GeV/c");
415 histo->GetAxis(2)->SetTitle("TPC Signal / a.u.");
416 histo->GetAxis(3)->SetTitle("TRD Signal / a.u.");
417 histo->GetAxis(4)->SetTitle("TRD Signal / a.u.");
420 // Add Histogram for combined TPC-ITS PID
422 AliDebug(1, "Adding histogram for TPC-TRD investigation");
423 const Int_t kDimensionsITSsig = 4;
424 Int_t kNbinsITSsig[kDimensionsITSsig] = {AliPID::kSPECIES + 1, kMomentumBins - 1, 300, 3000};
425 Double_t binMinITSsig[kDimensionsITSsig] = {-1., 0.1, 0., 0.};
426 Double_t binMaxITSsig[kDimensionsITSsig] = {AliPID::kSPECIES, 10., 300., 300.};
427 fQAlist->AddAt((histo = new THnSparseF("fCombTPCITSpid", "Combined TPC-ITS PID", kDimensionsITSsig, kNbinsITSsig, binMinITSsig, binMaxITSsig)), kITSSignal);
428 histo->GetAxis(1)->Set(kMomentumBins - 1, momentumBins);
429 histo->GetAxis(0)->SetTitle("Particle Species");
430 histo->GetAxis(1)->SetTitle("p / GeV/c");
431 histo->GetAxis(2)->SetTitle("ITS Signal / a.u.");
432 histo->GetAxis(3)->SetTitle("TPC Signal / a.u.");
436 //____________________________________________________________
437 void AliHFEpid::InitStrategy1(){
439 // TPC alone, 3-sigma cut
441 AliHFEpidTPC *pid = new AliHFEpidTPC("strat1TPCpid");
442 pid->SetTPCnSigma(3);
443 Bool_t status = pid->InitializePID();
444 if(IsQAOn() && status) pid->SetQAOn(fQAlist);
445 if(HasMCData() && status) pid->SetHasMCData();
446 fDetectorPID[kTPCpid] = pid;
449 //____________________________________________________________
450 void AliHFEpid::InitStrategy2(){
452 // TPC alone, symmetric 3 sigma cut and asymmetric sigma cut in the momentum region between 2GeV/c and 10 GeV/c and sigma between -1 and 100
454 AliHFEpidTPC *pid = new AliHFEpidTPC("strat2TPCpid");
455 pid->SetTPCnSigma(3);
456 pid->SetAsymmetricTPCsigmaCut(2., 10., 0., 4.);
457 Bool_t status = pid->InitializePID();
458 if(IsQAOn() && status) pid->SetQAOn(fQAlist);
459 if(HasMCData() && status) pid->SetHasMCData();
460 fDetectorPID[kTPCpid] = pid;
463 //____________________________________________________________
464 void AliHFEpid::InitStrategy3(){
466 // TPC alone, symmetric 3 sigma cut and 2 - -100 sigma pion rejection
468 AliHFEpidTPC *pid = new AliHFEpidTPC("strat3TPCpid");
469 pid->SetTPCnSigma(3);
470 pid->SetRejectParticle(AliPID::kPion, 0., -100., 10., 1.);
471 Bool_t status = pid->InitializePID();
472 if(IsQAOn() && status) pid->SetQAOn(fQAlist);
473 if(HasMCData() && status) pid->SetHasMCData();
474 fDetectorPID[kTPCpid] = pid;
477 //____________________________________________________________
478 void AliHFEpid::InitStrategy4(){
480 // TPC and TRD combined, TPC 3 sigma cut and TRD NN 90% el efficiency level above 2 GeV/c
483 AliHFEpidTRD *trdpid = new AliHFEpidTRD("strat4TRDpid");
484 Bool_t status = trdpid->InitializePID();
485 if(IsQAOn() && status) trdpid->SetQAOn(fQAlist);
486 if(HasMCData() && status) trdpid->SetHasMCData();
487 fDetectorPID[kTRDpid] = trdpid;
490 //____________________________________________________________
491 void AliHFEpid::InitStrategy5(){
493 // TPC and TRD combined, TPC 3 sigma cut and TRD NN 90% el efficiency level above 2 GeV/c
496 AliHFEpidTRD *trdpid = new AliHFEpidTRD("strat5TRDpid");
497 Bool_t status = trdpid->InitializePID();
498 if(IsQAOn() && status) trdpid->SetQAOn(fQAlist);
499 if(HasMCData() && status) trdpid->SetHasMCData();
500 fDetectorPID[kTRDpid] = trdpid;
503 //____________________________________________________________
504 void AliHFEpid::InitStrategy6(){
506 // Combined TPC-TOF PID, combination is discribed in the funtion MakePidTpcTof
508 AliHFEpidTPC *tpcpid = new AliHFEpidTPC("strat6TPCpid");
509 AliHFEpidTOF *tofpid = new AliHFEpidTOF("strat6TOFpid");
510 Bool_t status = tpcpid->InitializePID();
512 AliError("Initialization of TPC PID failed");
513 Bool_t status1 = tofpid->InitializePID();
515 AliError("Initialization of TOF PID failed");
517 if(IsQAOn() && status){
518 tpcpid->SetQAOn(fQAlist);
519 tofpid->SetQAOn(fQAlist);
521 if(HasMCData() && status){
522 tpcpid->SetHasMCData();
523 tofpid->SetHasMCData();
525 fDetectorPID[kTPCpid] = tpcpid;
526 fDetectorPID[kTOFpid] = tofpid;
529 //____________________________________________________________
530 Bool_t AliHFEpid::IdentifyStrategy1(AliHFEpidObject *track){
531 return TMath::Abs(fDetectorPID[kTPCpid]->IsSelected(track)) == 11;
534 //____________________________________________________________
535 Bool_t AliHFEpid::IdentifyStrategy2(AliHFEpidObject *track){
536 return TMath::Abs(fDetectorPID[kTPCpid]->IsSelected(track)) == 11;
539 //____________________________________________________________
540 Bool_t AliHFEpid::IdentifyStrategy3(AliHFEpidObject *track){
541 return TMath::Abs(fDetectorPID[kTPCpid]->IsSelected(track)) == 11;
544 //____________________________________________________________
545 Bool_t AliHFEpid::IdentifyStrategy4(AliHFEpidObject *track){
546 Int_t trdpid = TMath::Abs(fDetectorPID[kTRDpid]->IsSelected(track));
547 return (trdpid == 0 || trdpid == 11) && (TMath::Abs(fDetectorPID[kTPCpid]->IsSelected(track)) == 11);
550 //____________________________________________________________
551 Bool_t AliHFEpid::IdentifyStrategy5(AliHFEpidObject *track){
552 return MakePidTpcTrd(track);
555 //____________________________________________________________
556 Bool_t AliHFEpid::IdentifyStrategy6(AliHFEpidObject *track){
557 return MakePidTpcTof(track);