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 // Implements the abstract base class AliHFEpidBase
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
25 // Markus Fasel <M.Fasel@gsi.de>
26 // Markus Heide <mheide@uni-muenster.de>
32 #include "AliTPCdEdxInfo.h"
33 #include "AliAODPid.h"
34 #include "AliAODTrack.h"
35 #include "AliAODMCParticle.h"
36 #include "AliESDtrack.h"
37 #include "AliExternalTrackParam.h"
39 #include "AliMCParticle.h"
41 #include "AliPIDResponse.h"
43 #include "AliHFEpidTPC.h"
44 #include "AliHFEpidQAmanager.h"
46 ClassImp(AliHFEpidTPC)
48 //___________________________________________________________________
49 AliHFEpidTPC::AliHFEpidTPC() :
52 , fLineCrossingsEnabled(0)
53 , fkEtaCorrection(NULL)
54 , fkCentralityCorrection(NULL)
55 , fkEtaMeanCorrection(NULL)
56 , fkEtaWidthCorrection(NULL)
57 , fkCentralityMeanCorrection(NULL)
58 , fkCentralityWidthCorrection(NULL)
59 , fkCentralityEtaCorrectionMeanJpsi(NULL)
60 , fkCentralityEtaCorrectionWidthJpsi(NULL)
61 , fHasCutModel(kFALSE)
62 , fUseOnlyOROC(kFALSE)
64 , fRejectionEnabled(0)
68 // default constructor
71 memset(fkUpperSigmaCut, 0, sizeof(const TF1 *) * 12);
72 memset(fkLowerSigmaCut, 0, sizeof(const TF1 *) * 12);
74 memset(fRejection, 0, sizeof(Float_t) * 4 * AliPID::kSPECIES);
75 memset(fLineCrossingSigma, 0, sizeof(Double_t) * AliPID::kSPECIES);
76 memset(fPAsigCut, 0, sizeof(Float_t) * 2);
77 memset(fNAsigmaTPC, 0, sizeof(Float_t) * 2);
81 //___________________________________________________________________
82 AliHFEpidTPC::AliHFEpidTPC(const char* name) :
85 , fLineCrossingsEnabled(0)
86 , fkEtaCorrection(NULL)
87 , fkCentralityCorrection(NULL)
88 , fkEtaMeanCorrection(NULL)
89 , fkEtaWidthCorrection(NULL)
90 , fkCentralityMeanCorrection(NULL)
91 , fkCentralityWidthCorrection(NULL)
92 , fkCentralityEtaCorrectionMeanJpsi(NULL)
93 , fkCentralityEtaCorrectionWidthJpsi(NULL)
94 , fHasCutModel(kFALSE)
95 , fUseOnlyOROC(kFALSE)
97 , fRejectionEnabled(0)
101 // default constructor
104 memset(fkUpperSigmaCut, 0, sizeof(const TF1 *) * 12);
105 memset(fkLowerSigmaCut, 0, sizeof(const TF1 *) * 12);
107 memset(fRejection, 0, sizeof(Float_t) * 4 * AliPID::kSPECIES);
108 memset(fLineCrossingSigma, 0, sizeof(Double_t) * AliPID::kSPECIES);
109 memset(fPAsigCut, 0, sizeof(Float_t) * 2);
110 memset(fNAsigmaTPC, 0, sizeof(Float_t) * 2);
113 //___________________________________________________________________
114 AliHFEpidTPC::AliHFEpidTPC(const AliHFEpidTPC &ref) :
116 , fLineCrossingsEnabled(0)
117 , fkEtaCorrection(NULL)
118 , fkCentralityCorrection(NULL)
119 , fkEtaMeanCorrection(NULL)
120 , fkEtaWidthCorrection(NULL)
121 , fkCentralityMeanCorrection(NULL)
122 , fkCentralityWidthCorrection(NULL)
123 , fkCentralityEtaCorrectionMeanJpsi(NULL)
124 , fkCentralityEtaCorrectionWidthJpsi(NULL)
125 , fHasCutModel(ref.fHasCutModel)
126 , fUseOnlyOROC(ref.fUseOnlyOROC)
128 , fRejectionEnabled(0)
137 //___________________________________________________________________
138 AliHFEpidTPC &AliHFEpidTPC::operator=(const AliHFEpidTPC &ref){
140 // Assignment operator
147 //___________________________________________________________________
148 void AliHFEpidTPC::Copy(TObject &o) const{
151 // called in copy constructor and assigment operator
153 AliHFEpidTPC &target = dynamic_cast<AliHFEpidTPC &>(o);
155 target.fkEtaCorrection = fkEtaCorrection;
156 target.fkCentralityCorrection = fkCentralityCorrection;
157 target.fkEtaMeanCorrection = fkEtaMeanCorrection;
158 target.fkEtaWidthCorrection = fkEtaWidthCorrection;
159 target.fkCentralityMeanCorrection = fkCentralityMeanCorrection;
160 target.fkCentralityWidthCorrection = fkCentralityWidthCorrection;
161 target.fLineCrossingsEnabled = fLineCrossingsEnabled;
162 target.fHasCutModel = fHasCutModel;
163 target.fUseOnlyOROC = fUseOnlyOROC;
164 target.fNsigmaTPC = fNsigmaTPC;
165 target.fRejectionEnabled = fRejectionEnabled;
167 memcpy(target.fkUpperSigmaCut, fkUpperSigmaCut, sizeof(const TF1 *) * 12);
168 memcpy(target.fkLowerSigmaCut, fkLowerSigmaCut, sizeof(const TF1 *) * 12);
170 memcpy(target.fLineCrossingSigma, fLineCrossingSigma, sizeof(Double_t) * AliPID::kSPECIES);
171 memcpy(target.fPAsigCut, fPAsigCut, sizeof(Float_t) * 2);
172 memcpy(target.fNAsigmaTPC, fNAsigmaTPC, sizeof(Float_t) * 2);
174 AliHFEpidBase::Copy(target);
177 //___________________________________________________________________
178 AliHFEpidTPC::~AliHFEpidTPC(){
184 //___________________________________________________________________
185 Bool_t AliHFEpidTPC::InitializePID(Int_t /*run*/){
187 // Add TPC dE/dx Line crossings
189 //AddTPCdEdxLineCrossing(AliPID::kKaon, 0.3, 0.018);
190 //AddTPCdEdxLineCrossing(AliPID::kProton, 0.9, 0.054);
194 //___________________________________________________________________
195 Int_t AliHFEpidTPC::IsSelected(const AliHFEpidObject *track, AliHFEpidQAmanager *pidqa) const
198 // For the TPC pid we use the 2-sigma band around the bethe bloch curve
200 // exclusion of the crossing points
203 if(!fkPIDResponse) return 0;
205 AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis : AliHFEpidObject::kAODanalysis;
207 // Make clone track in order to be able to apply correction
208 const AliVTrack *rectrack;
209 AliESDtrack esdtrack;
210 AliAODTrack aodtrack;
211 Double_t correctedTPCnSigma=0.;
212 Bool_t TPCnSigmaCorrected=kFALSE;
213 if((fkEtaMeanCorrection&&fkEtaWidthCorrection)||
214 (fkCentralityMeanCorrection&&fkCentralityWidthCorrection)){
215 TPCnSigmaCorrected=kTRUE;
216 correctedTPCnSigma=GetCorrectedTPCnSigma(track->GetRecTrack()->Eta(), track->GetMultiplicity(), fkPIDResponse->NumberOfSigmasTPC(track->GetRecTrack(), AliPID::kElectron));
219 if((fkCentralityEtaCorrectionMeanJpsi)&&
220 (fkCentralityEtaCorrectionWidthJpsi)){
221 TPCnSigmaCorrected=kTRUE;
222 correctedTPCnSigma=GetCorrectedTPCnSigmaJpsi(track->GetRecTrack()->Eta(), track->GetMultiplicity(), fkPIDResponse->NumberOfSigmasTPC(track->GetRecTrack(), AliPID::kElectron));
224 if(fkEtaCorrection || fkCentralityCorrection){
225 // Correction available
227 if(track->IsESDanalysis()){
228 esdtrack.~AliESDtrack();
229 new(&esdtrack) AliESDtrack(*(static_cast<const AliESDtrack *>(track->GetRecTrack())));
230 if(track->IsPbPb() && HasCentralityCorrection())
231 ApplyCentralityCorrection(&esdtrack, track->GetMultiplicity(), anatype);
232 if(HasEtaCorrection())
233 ApplyEtaCorrection(&esdtrack, anatype);
234 rectrack = &esdtrack;
236 aodtrack.~AliAODTrack();
237 new(&aodtrack) AliAODTrack(*(static_cast<const AliAODTrack *>(track->GetRecTrack())));
238 if(track->IsPbPb() && HasCentralityCorrection())
239 ApplyCentralityCorrection(&aodtrack, track->GetMultiplicity(), anatype);
240 if(HasEtaCorrection())
241 ApplyEtaCorrection(&aodtrack, anatype);
242 rectrack = &aodtrack;
245 // Correction not available - no need to copy
246 rectrack = track->GetRecTrack();
248 AliHFEpidObject tpctrack(*track);
249 tpctrack.SetRecTrack(rectrack);
250 if(TPCnSigmaCorrected)tpctrack.SetCorrectedTPCnSigma(correctedTPCnSigma);
252 // QA before selection (after correction)
253 if(pidqa) pidqa->ProcessTrack(&tpctrack, AliHFEpid::kTPCpid, AliHFEdetPIDqa::kBeforePID);
254 AliDebug(1, "Doing TPC PID based on n-Sigma cut approach");
256 // make copy of the track in order to allow for applying the correction
257 Float_t nsigma=correctedTPCnSigma;
258 if(!TPCnSigmaCorrected)
259 nsigma = fUsedEdx ? rectrack->GetTPCsignal() : fkPIDResponse->NumberOfSigmasTPC(rectrack, AliPID::kElectron);
260 AliDebug(1, Form("TPC NSigma: %f", nsigma));
261 // exclude crossing points:
262 // Determine the bethe values for each particle species
263 Bool_t isLineCrossing = kFALSE;
264 for(Int_t ispecies = 0; ispecies < AliPID::kSPECIES; ispecies++){
265 if(ispecies == AliPID::kElectron) continue;
266 if(!(fLineCrossingsEnabled & 1 << ispecies)) continue;
267 if(TMath::Abs(fkPIDResponse->NumberOfSigmasTPC(rectrack, (AliPID::EParticleType)ispecies)) < fLineCrossingSigma[ispecies] && TMath::Abs(nsigma) < fNsigmaTPC){
268 // Point in a line crossing region, no PID possible, but !PID still possible ;-)
269 isLineCrossing = kTRUE;
273 if(isLineCrossing) return 0;
275 // Check particle rejection
276 if(HasParticleRejection()){
277 Int_t reject = Reject(rectrack, anatype);
278 if(reject != 0) return reject;
281 // Check if we have an asymmetric sigma model set
284 pdg = CutSigmaModel(&tpctrack) ? 11 : 0;
286 // Perform Asymmetric n-sigma cut if required, else perform symmetric TPC sigma cut
287 Float_t p = rectrack->P();
288 if(HasAsymmetricSigmaCut()) {
290 //printf("p %f, fPAsigCut[0] %f, fPAsigCut[1] %f\n",p,fPAsigCut[0],fPAsigCut[1]);
291 if(p >= fPAsigCut[0] && p <= fPAsigCut[1]) {
292 if(nsigma >= fNAsigmaTPC[0] && nsigma <= fNAsigmaTPC[1]) pdg = 11;
299 if(TMath::Abs(nsigma) < fNsigmaTPC ) pdg = 11;
302 if(pidqa && pdg != 0) pidqa->ProcessTrack(&tpctrack, AliHFEpid::kTPCpid, AliHFEdetPIDqa::kAfterPID);
307 //___________________________________________________________________
308 Bool_t AliHFEpidTPC::CutSigmaModel(const AliHFEpidObject * const track) const {
310 // N SigmaCut using parametrization of the cuts
312 Bool_t isSelected = kTRUE;
313 AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis : AliHFEpidObject::kAODanalysis;
314 Float_t nsigma = fUsedEdx ? track->GetRecTrack()->GetTPCsignal() : fkPIDResponse->NumberOfSigmasTPC(track->GetRecTrack(), AliPID::kElectron);
315 Double_t p = GetP(track->GetRecTrack(), anatype);
316 Int_t centrality = track->IsPbPb() ? track->GetCentrality() + 1 : 0;
317 AliDebug(2, Form("Centrality: %d\n", centrality));
318 if(centrality > 11) return kFALSE;
319 const TF1 *cutfunction;
320 if((cutfunction = fkUpperSigmaCut[centrality]) && nsigma > cutfunction->Eval(p)) isSelected = kFALSE;
321 if((cutfunction = fkLowerSigmaCut[centrality]) && nsigma < cutfunction->Eval(p)) isSelected = kFALSE;
325 //___________________________________________________________________
326 Int_t AliHFEpidTPC::Reject(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anaType) const{
328 // reject particles based on asymmetric sigma cut
330 Int_t pdc[AliPID::kSPECIES] = {11,13,211,321,2212};
331 Double_t p = GetP(track, anaType);
332 for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){
333 if(!TESTBIT(fRejectionEnabled, ispec)) continue;
334 // Particle rejection enabled
335 if(p < fRejection[4*ispec] || p > fRejection[4*ispec+2]) continue;
336 Double_t sigma = fkPIDResponse->NumberOfSigmasTPC(track, static_cast<AliPID::EParticleType>(ispec));
337 if(sigma >= fRejection[4*ispec+1] && sigma <= fRejection[4*ispec+3]) return pdc[ispec] * track->Charge();
342 //___________________________________________________________________
343 void AliHFEpidTPC::ApplyEtaCorrection(AliVTrack *track, AliHFEpidObject::AnalysisType_t anatype) const{
345 // Apply correction for the eta dependence
346 // N.B. This correction has to be applied on a copy track
348 AliDebug(1, Form("Applying correction function %s\n", fkEtaCorrection->GetName()));
349 Double_t original = track->GetTPCsignal(),
351 if(anatype == AliHFEpidObject::kESDanalysis){
352 AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
353 if(fkEtaCorrection->Eval(eta)>0.0) esdtrack->SetTPCsignal(original/fkEtaCorrection->Eval(eta), esdtrack->GetTPCsignalSigma(), esdtrack->GetTPCsignalN());
355 AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
356 AliAODPid *pid = aodtrack->GetDetPid();
357 if(pid && fkEtaCorrection->Eval(eta)>0.0) pid->SetTPCsignal(original/fkEtaCorrection->Eval(eta));
361 //___________________________________________________________________
362 void AliHFEpidTPC::ApplyCentralityCorrection(AliVTrack *track, Double_t centralityEstimator, AliHFEpidObject::AnalysisType_t anatype) const{
364 // Apply correction for the eta dependence
365 // N.B. This correction has to be applied on a copy track
367 AliDebug(1, Form("Applying correction function %s\n", fkCentralityCorrection->GetName()));
368 Double_t original = track->GetTPCsignal();
369 if(anatype == AliHFEpidObject::kESDanalysis){
370 AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
371 if(fkCentralityCorrection->Eval(centralityEstimator)>0.0) esdtrack->SetTPCsignal(original/fkCentralityCorrection->Eval(centralityEstimator), esdtrack->GetTPCsignalSigma(), esdtrack->GetTPCsignalN());
373 AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
374 AliAODPid *pid = aodtrack->GetDetPid();
375 if(pid && fkCentralityCorrection->Eval(centralityEstimator)>0.0) pid->SetTPCsignal(original/fkCentralityCorrection->Eval(centralityEstimator));
379 //___________________________________________________________________
380 Double_t AliHFEpidTPC::GetCorrectedTPCnSigma(Double_t eta, Double_t centralityEstimator, Double_t tpcNsigma) const{
382 // Apply correction for the eta dependence
383 // N.B. This correction has to be applied on a copy track
385 Double_t corrtpcNsigma = tpcNsigma;
386 if(fkEtaMeanCorrection&&fkEtaWidthCorrection){
387 if(TMath::Abs(fkEtaWidthCorrection->Eval(eta))>0.0000001) corrtpcNsigma=(corrtpcNsigma-fkEtaMeanCorrection->Eval(eta))/fkEtaWidthCorrection->Eval(eta);
389 if(fkCentralityMeanCorrection&&fkCentralityWidthCorrection) {
390 if(TMath::Abs(fkCentralityWidthCorrection->Eval(centralityEstimator))>0.0000001) corrtpcNsigma=(corrtpcNsigma-fkCentralityMeanCorrection->Eval(centralityEstimator))/fkCentralityWidthCorrection->Eval(centralityEstimator);
392 return corrtpcNsigma;
395 //___________________________________________________________________
396 Double_t AliHFEpidTPC::GetCorrectedTPCnSigmaJpsi(Double_t eta, Double_t centralityEstimator, Double_t tpcNsigma) const{
398 // Apply correction for the eta dependence
399 // N.B. This correction has to be applied on a copy track
401 Double_t corrtpcNsigma = tpcNsigma;
402 if(fkCentralityEtaCorrectionMeanJpsi&&fkCentralityEtaCorrectionWidthJpsi){
403 const TAxis *caxis = fkCentralityEtaCorrectionMeanJpsi->GetXaxis();
404 const TAxis *eaxis = fkCentralityEtaCorrectionMeanJpsi->GetYaxis();
405 Int_t cbin = caxis->FindFixBin(centralityEstimator);
406 Int_t ebin = eaxis->FindFixBin(eta);
407 //Double_t cbinlowedge = caxis->GetBinLowEdge(cbin);
408 //Double_t cbinupedge = caxis->GetBinUpEdge(cbin);
409 //Double_t ebinlowedge = eaxis->GetBinLowEdge(ebin);
410 //Double_t ebinupedge = eaxis->GetBinUpEdge(ebin);
411 Double_t center = fkCentralityEtaCorrectionMeanJpsi->GetBinContent(cbin,ebin);
412 Double_t width = fkCentralityEtaCorrectionWidthJpsi->GetBinContent(cbin,ebin);
413 //printf("cbin %d, cbinlowe %f, cbinupe %f, centrality %f\n",cbin,cbinlowedge,cbinupedge,centralityEstimator);
414 //printf("ebin %d, ebinlowe %f, ebinupe %f, eta %f\n",ebin,ebinlowedge,ebinupedge,eta);
415 //printf("mean %f, width %f\n",center,width);
416 if(TMath::Abs(width)>0.0000001) corrtpcNsigma=(corrtpcNsigma-center)/width;
418 return corrtpcNsigma;
421 //___________________________________________________________________
422 void AliHFEpidTPC::UseOROC(AliVTrack *track, AliHFEpidObject::AnalysisType_t anatype) const{
424 // Use TPC signal from the OROC
425 // N.B. This correction has to be applied on a copy track
427 //Double_t original = track->GetTPCsignal();
429 if(anatype == AliHFEpidObject::kESDanalysis){
430 AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
431 AliTPCdEdxInfo *dEdxInfo = track->GetTPCdEdxInfo();
432 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)
433 Char_t TPCsignalNRegion[3]; // number of clusters above threshold used in the dEdx calculation
434 Char_t TPCsignalNRowRegion[3]; // number of crosed rows used in the dEdx calculation - signal below threshold included
435 dEdxInfo->GetTPCSignalRegionInfo(TPCsignalRegion,TPCsignalNRegion,TPCsignalNRowRegion);
436 esdtrack->SetTPCsignal(TPCsignalRegion[3],esdtrack->GetTPCsignalSigma(),(TPCsignalNRegion[1]+TPCsignalNRegion[2])); // the two last are not ok
438 AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
439 AliTPCdEdxInfo *dEdxInfo = track->GetTPCdEdxInfo();
440 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)
441 Char_t TPCsignalNRegion[3]; // number of clusters above threshold used in the dEdx calculation
442 Char_t TPCsignalNRowRegion[3]; // number of crosed rows used in the dEdx calculation - signal below threshold included
443 dEdxInfo->GetTPCSignalRegionInfo(TPCsignalRegion,TPCsignalNRegion,TPCsignalNRowRegion);
444 AliAODPid *pid = aodtrack->GetDetPid();
445 if(pid) pid->SetTPCsignal(TPCsignalRegion[3]);
446 if(pid) pid->SetTPCsignalN((TPCsignalNRegion[1]+TPCsignalNRegion[2]));
450 //___________________________________________________________________
451 void AliHFEpidTPC::AddTPCdEdxLineCrossing(Int_t species, Double_t sigma){
453 // Add exclusion point for the TPC PID where a dEdx line crosses the electron line
454 // Stores line center and line sigma
456 if(species >= AliPID::kSPECIES){
457 AliError("Species doesn't exist");
460 fLineCrossingsEnabled |= 1 << species;
461 fLineCrossingSigma[species] = sigma;
464 //___________________________________________________________________
465 Double_t AliHFEpidTPC::GetP(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anatype) const {
467 // Get the momentum at the inner wall of the TPC
470 if(anatype == AliHFEpidObject::kESDanalysis){
471 // ESD analysis: Use Inner Params for the momentum estimate
472 const AliESDtrack *esdtrack = dynamic_cast<const AliESDtrack *>(track);
473 if(esdtrack) p = esdtrack->GetInnerParam() ? esdtrack->GetInnerParam()->GetP() : esdtrack->P();
476 if(anatype == AliHFEpidObject::kAODanalysis)
478 // AOD analysis: Use TPC momentum stored in the AliAODpid object
479 const AliAODTrack *aodtrack = dynamic_cast<const AliAODTrack *>(track);
480 if(aodtrack) p = aodtrack->GetDetPid() ? aodtrack->GetDetPid()->GetTPCmomentum() : aodtrack->P();