]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGHF/hfe/AliHFEpidTPC.cxx
TPC PID 2011 Pb-Pb
[u/mrichter/AliRoot.git] / PWGHF / hfe / AliHFEpidTPC.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
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 **************************************************************************/
15 //
16 // Class for TPC PID
17 // Implements the abstract base class AliHFEpidBase
18 // 
19 // Class contains TPC specific cuts and QA histograms
20 // Two selection strategies are offered: Selection of certain value
21 // regions in the TPC dE/dx (by IsSelected), and likelihoods
22 //
23 // Authors: 
24 //
25 //   Markus Fasel <M.Fasel@gsi.de> 
26 //   Markus Heide <mheide@uni-muenster.de> 
27 //  
28 #include <TF1.h>
29 #include <TMath.h>
30
31 #include "AliTPCdEdxInfo.h"
32 #include "AliAODPid.h"
33 #include "AliAODTrack.h"
34 #include "AliAODMCParticle.h"
35 #include "AliESDtrack.h"
36 #include "AliExternalTrackParam.h"
37 #include "AliLog.h"
38 #include "AliMCParticle.h"
39 #include "AliPID.h"
40 #include "AliPIDResponse.h"
41
42 #include "AliHFEpidTPC.h"
43 #include "AliHFEpidQAmanager.h"
44
45 ClassImp(AliHFEpidTPC)
46
47 //___________________________________________________________________
48 AliHFEpidTPC::AliHFEpidTPC() :
49   // add a list here
50   AliHFEpidBase()
51   , fLineCrossingsEnabled(0)
52   , fkEtaCorrection(NULL)
53   , fkCentralityCorrection(NULL)
54   , fkEtaMeanCorrection(NULL)
55   , fkEtaWidthCorrection(NULL)
56   , fkCentralityMeanCorrection(NULL)
57   , fkCentralityWidthCorrection(NULL)
58   , fHasCutModel(kFALSE)
59   , fUseOnlyOROC(kFALSE)
60   , fNsigmaTPC(3)
61   , fRejectionEnabled(0)
62   , fUsedEdx(kFALSE)
63 {
64   //
65   // default  constructor
66   // 
67
68   memset(fkUpperSigmaCut, 0, sizeof(const TF1 *) * 12);
69   memset(fkLowerSigmaCut, 0, sizeof(const TF1 *) * 12);
70
71   memset(fRejection, 0, sizeof(Float_t) * 4 * AliPID::kSPECIES);
72   memset(fLineCrossingSigma, 0, sizeof(Double_t) * AliPID::kSPECIES);
73   memset(fPAsigCut, 0, sizeof(Float_t) * 2);
74   memset(fNAsigmaTPC, 0, sizeof(Float_t) * 2);
75
76 }
77
78 //___________________________________________________________________
79 AliHFEpidTPC::AliHFEpidTPC(const char* name) :
80   // add a list here
81   AliHFEpidBase(name)
82   , fLineCrossingsEnabled(0)
83   , fkEtaCorrection(NULL)
84   , fkCentralityCorrection(NULL)
85   , fkEtaMeanCorrection(NULL)
86   , fkEtaWidthCorrection(NULL)
87   , fkCentralityMeanCorrection(NULL)
88   , fkCentralityWidthCorrection(NULL)
89   , fHasCutModel(kFALSE)
90   , fUseOnlyOROC(kFALSE)
91   , fNsigmaTPC(3)
92   , fRejectionEnabled(0)
93   , fUsedEdx(kFALSE)
94 {
95   //
96   // default  constructor
97   // 
98   //
99   memset(fkUpperSigmaCut, 0, sizeof(const TF1 *) * 12);
100   memset(fkLowerSigmaCut, 0, sizeof(const TF1 *) * 12);
101
102   memset(fRejection, 0, sizeof(Float_t) * 4 * AliPID::kSPECIES);
103   memset(fLineCrossingSigma, 0, sizeof(Double_t) * AliPID::kSPECIES);
104   memset(fPAsigCut, 0, sizeof(Float_t) * 2);
105   memset(fNAsigmaTPC, 0, sizeof(Float_t) * 2);
106 }
107
108 //___________________________________________________________________
109 AliHFEpidTPC::AliHFEpidTPC(const AliHFEpidTPC &ref) :
110   AliHFEpidBase("")
111   , fLineCrossingsEnabled(0)
112   , fkEtaCorrection(NULL)
113   , fkCentralityCorrection(NULL)
114   , fkEtaMeanCorrection(NULL)
115   , fkEtaWidthCorrection(NULL)
116   , fkCentralityMeanCorrection(NULL)
117   , fkCentralityWidthCorrection(NULL)
118   , fHasCutModel(ref.fHasCutModel)
119   , fUseOnlyOROC(ref.fUseOnlyOROC)
120   , fNsigmaTPC(2)
121   , fRejectionEnabled(0)
122   , fUsedEdx(kFALSE)
123 {
124   //
125   // Copy constructor
126   //
127   ref.Copy(*this);
128 }
129
130 //___________________________________________________________________
131 AliHFEpidTPC &AliHFEpidTPC::operator=(const AliHFEpidTPC &ref){
132   //
133   // Assignment operator
134   //
135   if(this != &ref){
136     ref.Copy(*this);
137   } 
138   return *this;
139 }
140 //___________________________________________________________________
141 void AliHFEpidTPC::Copy(TObject &o) const{
142   //
143   // Copy function 
144   // called in copy constructor and assigment operator
145   //
146   AliHFEpidTPC &target = dynamic_cast<AliHFEpidTPC &>(o);
147
148   target.fkEtaCorrection = fkEtaCorrection;
149   target.fkCentralityCorrection = fkCentralityCorrection;
150   target.fkEtaMeanCorrection = fkEtaMeanCorrection;
151   target.fkEtaWidthCorrection = fkEtaWidthCorrection;
152   target.fkCentralityMeanCorrection = fkCentralityMeanCorrection;
153   target.fkCentralityWidthCorrection = fkCentralityWidthCorrection;
154   target.fLineCrossingsEnabled = fLineCrossingsEnabled;
155   target.fHasCutModel = fHasCutModel;
156   target.fUseOnlyOROC = fUseOnlyOROC;
157   target.fNsigmaTPC = fNsigmaTPC;
158   target.fRejectionEnabled = fRejectionEnabled;
159
160   memcpy(target.fkUpperSigmaCut, fkUpperSigmaCut, sizeof(const TF1 *) * 12);
161   memcpy(target.fkLowerSigmaCut, fkLowerSigmaCut, sizeof(const TF1 *) * 12);
162
163   memcpy(target.fLineCrossingSigma, fLineCrossingSigma, sizeof(Double_t) * AliPID::kSPECIES);
164   memcpy(target.fPAsigCut, fPAsigCut, sizeof(Float_t) * 2);
165   memcpy(target.fNAsigmaTPC, fNAsigmaTPC, sizeof(Float_t) * 2);
166  
167   AliHFEpidBase::Copy(target);
168 }
169
170 //___________________________________________________________________
171 AliHFEpidTPC::~AliHFEpidTPC(){
172   //
173   // Destructor
174   //
175 }
176
177 //___________________________________________________________________
178 Bool_t AliHFEpidTPC::InitializePID(Int_t /*run*/){
179   //
180   // Add TPC dE/dx Line crossings
181   //
182   //AddTPCdEdxLineCrossing(AliPID::kKaon, 0.3, 0.018);
183   //AddTPCdEdxLineCrossing(AliPID::kProton, 0.9, 0.054);
184   return kTRUE;
185 }
186
187 //___________________________________________________________________
188 Int_t AliHFEpidTPC::IsSelected(const AliHFEpidObject *track, AliHFEpidQAmanager *pidqa) const
189 {
190   //
191   // For the TPC pid we use the 2-sigma band around the bethe bloch curve
192   // for electrons
193   // exclusion of the crossing points
194   //
195
196   if(!fkPIDResponse) return 0;
197
198   AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis : AliHFEpidObject::kAODanalysis;
199
200   // Make clone track in order to be able to apply correction
201   const AliVTrack *rectrack;
202   AliESDtrack esdtrack;
203   AliAODTrack aodtrack;
204   /*if(fUseOnlyOROC && !(fkEtaCorrection || fkCentralityCorrection)) {
205     if(track->IsESDanalysis()){
206       esdtrack.~AliESDtrack();
207       new(&esdtrack) AliESDtrack(*(static_cast<const AliESDtrack *>(track->GetRecTrack())));
208       UseOROC(&esdtrack, anatype);
209       rectrack = &esdtrack;
210     } else {
211       aodtrack.~AliAODTrack();
212       new(&aodtrack) AliAODTrack(*(static_cast<const AliAODTrack *>(track->GetRecTrack())));
213       UseOROC(&aodtrack, anatype);
214       rectrack = &aodtrack;
215     }
216   }
217   else if(fkEtaCorrection || fkCentralityCorrection){*/
218   Double_t correctedTPCnSigma=0.;
219   Bool_t TPCnSigmaCorrected=kFALSE;
220   if((fkEtaMeanCorrection&&fkEtaWidthCorrection)||
221      (fkCentralityMeanCorrection&&fkCentralityWidthCorrection)){
222     TPCnSigmaCorrected=kTRUE;
223     correctedTPCnSigma=GetCorrectedTPCnSigma(track->GetRecTrack()->Eta(), track->GetMultiplicity(), fkPIDResponse->NumberOfSigmasTPC(track->GetRecTrack(), AliPID::kElectron));
224   }
225   if(fkEtaCorrection || fkCentralityCorrection){
226     // Correction available
227     // apply it on copy
228     if(track->IsESDanalysis()){
229       esdtrack.~AliESDtrack();
230       new(&esdtrack) AliESDtrack(*(static_cast<const AliESDtrack *>(track->GetRecTrack())));
231       if(track->IsPbPb() && HasCentralityCorrection())
232         ApplyCentralityCorrection(&esdtrack, track->GetMultiplicity(), anatype);
233       if(HasEtaCorrection())
234         ApplyEtaCorrection(&esdtrack, anatype);
235       rectrack = &esdtrack;
236     } else {
237       aodtrack.~AliAODTrack();
238       new(&aodtrack) AliAODTrack(*(static_cast<const AliAODTrack *>(track->GetRecTrack())));
239       if(track->IsPbPb() && HasCentralityCorrection())
240         ApplyCentralityCorrection(&aodtrack, track->GetMultiplicity(), anatype);
241       if(HasEtaCorrection())
242         ApplyEtaCorrection(&aodtrack, anatype);
243       rectrack = &aodtrack;
244     }
245   } else {
246     // Correction not available - no need to copy
247     rectrack = track->GetRecTrack();
248   }
249   AliHFEpidObject tpctrack(*track);
250   tpctrack.SetRecTrack(rectrack);
251   if(TPCnSigmaCorrected)tpctrack.SetCorrectedTPCnSigma(correctedTPCnSigma);
252   
253   // QA before selection (after correction)
254   if(pidqa) pidqa->ProcessTrack(&tpctrack, AliHFEpid::kTPCpid, AliHFEdetPIDqa::kBeforePID);
255   AliDebug(1, "Doing TPC PID based on n-Sigma cut approach");
256   
257   // make copy of the track in order to allow for applying the correction 
258   Float_t nsigma=correctedTPCnSigma;
259   if(!TPCnSigmaCorrected)
260     nsigma = fUsedEdx ? rectrack->GetTPCsignal() : fkPIDResponse->NumberOfSigmasTPC(rectrack, AliPID::kElectron);
261   AliDebug(1, Form("TPC NSigma: %f", nsigma));
262   // exclude crossing points:
263   // Determine the bethe values for each particle species
264   Bool_t isLineCrossing = kFALSE;
265   for(Int_t ispecies = 0; ispecies < AliPID::kSPECIES; ispecies++){
266     if(ispecies == AliPID::kElectron) continue;
267     if(!(fLineCrossingsEnabled & 1 << ispecies)) continue;
268     if(TMath::Abs(fkPIDResponse->NumberOfSigmasTPC(rectrack, (AliPID::EParticleType)ispecies)) < fLineCrossingSigma[ispecies] && TMath::Abs(nsigma) < fNsigmaTPC){
269       // Point in a line crossing region, no PID possible, but !PID still possible ;-)
270       isLineCrossing = kTRUE;      
271       break;
272     }
273   }
274   if(isLineCrossing) return 0;
275
276   // Check particle rejection
277   if(HasParticleRejection()){
278     Int_t reject = Reject(rectrack, anatype);
279     if(reject != 0) return reject;
280   }
281
282   // Check if we have an asymmetric sigma model set
283   Int_t pdg = 0;
284   if(fHasCutModel){
285     pdg = CutSigmaModel(&tpctrack) ? 11 : 0;
286   } else { 
287     // Perform Asymmetric n-sigma cut if required, else perform symmetric TPC sigma cut
288     Float_t p = rectrack->P();
289     if(HasAsymmetricSigmaCut()) {
290       
291       //printf("p %f, fPAsigCut[0] %f, fPAsigCut[1] %f\n",p,fPAsigCut[0],fPAsigCut[1]);
292       if(p >= fPAsigCut[0] && p <= fPAsigCut[1]) { 
293               if(nsigma >= fNAsigmaTPC[0] && nsigma <= fNAsigmaTPC[1]) pdg = 11; 
294                 else pdg = 0;
295       }
296       else pdg = 0;
297     
298     }
299     else {
300       if(TMath::Abs(nsigma) < fNsigmaTPC ) pdg = 11;
301     }
302   }
303   if(pidqa && pdg != 0) pidqa->ProcessTrack(&tpctrack, AliHFEpid::kTPCpid, AliHFEdetPIDqa::kAfterPID);
304   return pdg;
305
306 }
307
308 //___________________________________________________________________
309 Bool_t AliHFEpidTPC::CutSigmaModel(const AliHFEpidObject * const track) const {
310   //
311   // N SigmaCut using parametrization of the cuts
312   //
313   Bool_t isSelected = kTRUE;
314   AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis : AliHFEpidObject::kAODanalysis;
315   Float_t nsigma = fUsedEdx ? track->GetRecTrack()->GetTPCsignal() : fkPIDResponse->NumberOfSigmasTPC(track->GetRecTrack(), AliPID::kElectron);
316   Double_t p = GetP(track->GetRecTrack(), anatype);
317   Int_t centrality = track->IsPbPb() ? track->GetCentrality() + 1 : 0;
318   AliDebug(2, Form("Centrality: %d\n", centrality));
319   if(centrality > 11) return kFALSE;
320   const TF1 *cutfunction;
321   if((cutfunction = fkUpperSigmaCut[centrality]) && nsigma > cutfunction->Eval(p)) isSelected = kFALSE;
322   if((cutfunction = fkLowerSigmaCut[centrality]) && nsigma < cutfunction->Eval(p)) isSelected = kFALSE;
323   return isSelected;
324 }
325
326 //___________________________________________________________________
327 Int_t AliHFEpidTPC::Reject(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anaType) const{
328   //
329   // reject particles based on asymmetric sigma cut
330   //
331   Int_t pdc[AliPID::kSPECIES] = {11,13,211,321,2212};
332   Double_t p = GetP(track, anaType);
333   for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){
334     if(!TESTBIT(fRejectionEnabled, ispec)) continue;
335     // Particle rejection enabled
336     if(p < fRejection[4*ispec] || p > fRejection[4*ispec+2]) continue;
337     Double_t sigma = fkPIDResponse->NumberOfSigmasTPC(track, static_cast<AliPID::EParticleType>(ispec));
338     if(sigma >= fRejection[4*ispec+1] && sigma <= fRejection[4*ispec+3]) return pdc[ispec] * track->Charge();
339   }
340   return 0;
341 }
342
343 //___________________________________________________________________
344 void AliHFEpidTPC::ApplyEtaCorrection(AliVTrack *track, AliHFEpidObject::AnalysisType_t anatype) const{
345   //
346   // Apply correction for the eta dependence
347   // N.B. This correction has to be applied on a copy track
348   //
349   AliDebug(1, Form("Applying correction function %s\n", fkEtaCorrection->GetName()));
350   Double_t original = track->GetTPCsignal(),
351            eta = track->Eta();
352   if(anatype == AliHFEpidObject::kESDanalysis){
353     AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
354     if(fkEtaCorrection->Eval(eta)>0.0) esdtrack->SetTPCsignal(original/fkEtaCorrection->Eval(eta), esdtrack->GetTPCsignalSigma(), esdtrack->GetTPCsignalN());
355   } else {
356     AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
357     AliAODPid *pid = aodtrack->GetDetPid();
358     if(pid && fkEtaCorrection->Eval(eta)>0.0) pid->SetTPCsignal(original/fkEtaCorrection->Eval(eta));
359   }
360 }
361
362 //___________________________________________________________________
363 void AliHFEpidTPC::ApplyCentralityCorrection(AliVTrack *track, Double_t centralityEstimator, AliHFEpidObject::AnalysisType_t anatype) const{
364   //
365   // Apply correction for the eta dependence
366   // N.B. This correction has to be applied on a copy track
367   //
368   AliDebug(1, Form("Applying correction function %s\n", fkCentralityCorrection->GetName()));
369   Double_t original = track->GetTPCsignal();
370   if(anatype == AliHFEpidObject::kESDanalysis){
371     AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
372     if(fkCentralityCorrection->Eval(centralityEstimator)>0.0) esdtrack->SetTPCsignal(original/fkCentralityCorrection->Eval(centralityEstimator), esdtrack->GetTPCsignalSigma(), esdtrack->GetTPCsignalN());
373   } else {
374     AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
375     AliAODPid *pid = aodtrack->GetDetPid();
376     if(pid && fkCentralityCorrection->Eval(centralityEstimator)>0.0) pid->SetTPCsignal(original/fkCentralityCorrection->Eval(centralityEstimator));
377   }
378 }
379
380 //___________________________________________________________________
381 Double_t AliHFEpidTPC::GetCorrectedTPCnSigma(Double_t eta, Double_t centralityEstimator, Double_t tpcNsigma) const{
382   //
383   // Apply correction for the eta dependence
384   // N.B. This correction has to be applied on a copy track
385   //
386   Double_t corrtpcNsigma = tpcNsigma;
387   AliDebug(1, Form("Applying correction function %s\n", fkEtaCorrection->GetName()));
388   if(fkEtaMeanCorrection&&fkEtaWidthCorrection){
389     if(TMath::Abs(fkEtaWidthCorrection->Eval(eta))>0.0000001) corrtpcNsigma=(corrtpcNsigma-fkEtaMeanCorrection->Eval(eta))/fkEtaWidthCorrection->Eval(eta);
390   }
391   if(fkCentralityMeanCorrection&&fkCentralityWidthCorrection) {
392     if(TMath::Abs(fkCentralityWidthCorrection->Eval(centralityEstimator))>0.0000001) corrtpcNsigma=(corrtpcNsigma-fkCentralityMeanCorrection->Eval(centralityEstimator))/fkCentralityWidthCorrection->Eval(centralityEstimator);
393   }
394   return corrtpcNsigma;
395 }
396
397 //___________________________________________________________________
398 void AliHFEpidTPC::UseOROC(AliVTrack *track, AliHFEpidObject::AnalysisType_t anatype) const{
399   //
400   // Use TPC signal from the OROC
401   // N.B. This correction has to be applied on a copy track
402   //
403   //Double_t original = track->GetTPCsignal();
404   
405   if(anatype == AliHFEpidObject::kESDanalysis){
406     AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
407     AliTPCdEdxInfo *dEdxInfo = track->GetTPCdEdxInfo();
408     Double32_t  TPCsignalRegion[4]; // TPC dEdx signal in 4 different regions - 0 - IROC, 1- OROC medium, 2 - OROC long, 3- OROC all, (default truncation used)
409     Char_t      TPCsignalNRegion[3]; // number of clusters above threshold used in the dEdx calculation
410     Char_t      TPCsignalNRowRegion[3]; // number of crosed rows used in the dEdx calculation - signal below threshold included
411     dEdxInfo->GetTPCSignalRegionInfo(TPCsignalRegion,TPCsignalNRegion,TPCsignalNRowRegion);
412     esdtrack->SetTPCsignal(TPCsignalRegion[3],esdtrack->GetTPCsignalSigma(),(TPCsignalNRegion[1]+TPCsignalNRegion[2])); // the two last are not ok
413   } else {
414     AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
415     AliTPCdEdxInfo *dEdxInfo = track->GetTPCdEdxInfo();
416     Double32_t  TPCsignalRegion[4]; // TPC dEdx signal in 4 different regions - 0 - IROC, 1- OROC medium, 2 - OROC long, 3- OROC all, (default truncation used)
417     Char_t      TPCsignalNRegion[3]; // number of clusters above threshold used in the dEdx calculation
418     Char_t      TPCsignalNRowRegion[3]; // number of crosed rows used in the dEdx calculation - signal below threshold included
419     dEdxInfo->GetTPCSignalRegionInfo(TPCsignalRegion,TPCsignalNRegion,TPCsignalNRowRegion);
420     AliAODPid *pid = aodtrack->GetDetPid();
421     if(pid) pid->SetTPCsignal(TPCsignalRegion[3]);
422     if(pid) pid->SetTPCsignalN((TPCsignalNRegion[1]+TPCsignalNRegion[2]));
423   }
424
425 }
426 //___________________________________________________________________
427 void AliHFEpidTPC::AddTPCdEdxLineCrossing(Int_t species, Double_t sigma){
428   //
429   // Add exclusion point for the TPC PID where a dEdx line crosses the electron line
430   // Stores line center and line sigma
431   //
432   if(species >= AliPID::kSPECIES){
433     AliError("Species doesn't exist");
434     return;
435   }
436   fLineCrossingsEnabled |= 1 << species;
437   fLineCrossingSigma[species] = sigma;
438 }
439
440 //___________________________________________________________________
441 Double_t AliHFEpidTPC::GetP(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anatype) const {
442   //
443   // Get the momentum at the inner wall of the TPC
444   //
445   Double_t p = -1;
446   if(anatype == AliHFEpidObject::kESDanalysis){
447     // ESD analysis: Use Inner Params for the momentum estimate
448     const AliESDtrack *esdtrack = dynamic_cast<const AliESDtrack *>(track);
449     if(esdtrack) p = esdtrack->GetInnerParam() ? esdtrack->GetInnerParam()->GetP() : esdtrack->P();
450   }
451
452   if(anatype == AliHFEpidObject::kAODanalysis)
453   {
454     // AOD analysis: Use TPC momentum stored in the AliAODpid object
455     const AliAODTrack *aodtrack = dynamic_cast<const AliAODTrack *>(track);
456     if(aodtrack) p = aodtrack->GetDetPid() ? aodtrack->GetDetPid()->GetTPCmomentum() : aodtrack->P();
457   }
458   return p;
459 }