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>
31 #include "AliTPCdEdxInfo.h"
32 #include "AliAODPid.h"
33 #include "AliAODTrack.h"
34 #include "AliAODMCParticle.h"
35 #include "AliESDtrack.h"
36 #include "AliExternalTrackParam.h"
38 #include "AliMCParticle.h"
40 #include "AliPIDResponse.h"
42 #include "AliHFEpidTPC.h"
43 #include "AliHFEpidQAmanager.h"
45 ClassImp(AliHFEpidTPC)
47 //___________________________________________________________________
48 AliHFEpidTPC::AliHFEpidTPC() :
51 , fLineCrossingsEnabled(0)
52 , fkEtaCorrection(NULL)
53 , fkCentralityCorrection(NULL)
54 , fHasCutModel(kFALSE)
55 , fUseOnlyOROC(kFALSE)
57 , fRejectionEnabled(0)
60 // default constructor
63 memset(fkUpperSigmaCut, 0, sizeof(const TF1 *) * 12);
64 memset(fkLowerSigmaCut, 0, sizeof(const TF1 *) * 12);
66 memset(fRejection, 0, sizeof(Float_t) * 4 * AliPID::kSPECIES);
67 memset(fLineCrossingSigma, 0, sizeof(Double_t) * AliPID::kSPECIES);
68 memset(fPAsigCut, 0, sizeof(Float_t) * 2);
69 memset(fNAsigmaTPC, 0, sizeof(Float_t) * 2);
73 //___________________________________________________________________
74 AliHFEpidTPC::AliHFEpidTPC(const char* name) :
77 , fLineCrossingsEnabled(0)
78 , fkEtaCorrection(NULL)
79 , fkCentralityCorrection(NULL)
80 , fHasCutModel(kFALSE)
81 , fUseOnlyOROC(kFALSE)
83 , fRejectionEnabled(0)
86 // default constructor
89 memset(fkUpperSigmaCut, 0, sizeof(const TF1 *) * 12);
90 memset(fkLowerSigmaCut, 0, sizeof(const TF1 *) * 12);
92 memset(fRejection, 0, sizeof(Float_t) * 4 * AliPID::kSPECIES);
93 memset(fLineCrossingSigma, 0, sizeof(Double_t) * AliPID::kSPECIES);
94 memset(fPAsigCut, 0, sizeof(Float_t) * 2);
95 memset(fNAsigmaTPC, 0, sizeof(Float_t) * 2);
98 //___________________________________________________________________
99 AliHFEpidTPC::AliHFEpidTPC(const AliHFEpidTPC &ref) :
101 , fLineCrossingsEnabled(0)
102 , fkEtaCorrection(NULL)
103 , fkCentralityCorrection(NULL)
104 , fHasCutModel(ref.fHasCutModel)
105 , fUseOnlyOROC(ref.fUseOnlyOROC)
107 , fRejectionEnabled(0)
115 //___________________________________________________________________
116 AliHFEpidTPC &AliHFEpidTPC::operator=(const AliHFEpidTPC &ref){
118 // Assignment operator
125 //___________________________________________________________________
126 void AliHFEpidTPC::Copy(TObject &o) const{
129 // called in copy constructor and assigment operator
131 AliHFEpidTPC &target = dynamic_cast<AliHFEpidTPC &>(o);
133 target.fkEtaCorrection = fkEtaCorrection;
134 target.fkCentralityCorrection = fkCentralityCorrection;
135 target.fLineCrossingsEnabled = fLineCrossingsEnabled;
136 target.fHasCutModel = fHasCutModel;
137 target.fUseOnlyOROC = fUseOnlyOROC;
138 target.fNsigmaTPC = fNsigmaTPC;
139 target.fRejectionEnabled = fRejectionEnabled;
141 memcpy(target.fkUpperSigmaCut, fkUpperSigmaCut, sizeof(const TF1 *) * 12);
142 memcpy(target.fkLowerSigmaCut, fkLowerSigmaCut, sizeof(const TF1 *) * 12);
144 memcpy(target.fLineCrossingSigma, fLineCrossingSigma, sizeof(Double_t) * AliPID::kSPECIES);
145 memcpy(target.fPAsigCut, fPAsigCut, sizeof(Float_t) * 2);
146 memcpy(target.fNAsigmaTPC, fNAsigmaTPC, sizeof(Float_t) * 2);
148 AliHFEpidBase::Copy(target);
151 //___________________________________________________________________
152 AliHFEpidTPC::~AliHFEpidTPC(){
158 //___________________________________________________________________
159 Bool_t AliHFEpidTPC::InitializePID(Int_t /*run*/){
161 // Add TPC dE/dx Line crossings
163 //AddTPCdEdxLineCrossing(AliPID::kKaon, 0.3, 0.018);
164 //AddTPCdEdxLineCrossing(AliPID::kProton, 0.9, 0.054);
168 //___________________________________________________________________
169 Int_t AliHFEpidTPC::IsSelected(const AliHFEpidObject *track, AliHFEpidQAmanager *pidqa) const
172 // For the TPC pid we use the 2-sigma band around the bethe bloch curve
174 // exclusion of the crossing points
177 if(!fkPIDResponse) return 0;
179 AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis : AliHFEpidObject::kAODanalysis;
181 // Make clone track in order to be able to apply correction
182 const AliVTrack *rectrack;
183 AliESDtrack esdtrack;
184 AliAODTrack aodtrack;
185 /*if(fUseOnlyOROC && !(fkEtaCorrection || fkCentralityCorrection)) {
186 if(track->IsESDanalysis()){
187 esdtrack.~AliESDtrack();
188 new(&esdtrack) AliESDtrack(*(static_cast<const AliESDtrack *>(track->GetRecTrack())));
189 UseOROC(&esdtrack, anatype);
190 rectrack = &esdtrack;
192 aodtrack.~AliAODTrack();
193 new(&aodtrack) AliAODTrack(*(static_cast<const AliAODTrack *>(track->GetRecTrack())));
194 UseOROC(&aodtrack, anatype);
195 rectrack = &aodtrack;
198 else if(fkEtaCorrection || fkCentralityCorrection){*/
199 if(fkEtaCorrection || fkCentralityCorrection){
200 // Correction available
202 if(track->IsESDanalysis()){
203 esdtrack.~AliESDtrack();
204 new(&esdtrack) AliESDtrack(*(static_cast<const AliESDtrack *>(track->GetRecTrack())));
205 if(track->IsPbPb() && HasCentralityCorrection())
206 ApplyCentralityCorrection(&esdtrack, track->GetMultiplicity(), anatype);
207 if(HasEtaCorrection())
208 ApplyEtaCorrection(&esdtrack, anatype);
209 rectrack = &esdtrack;
211 aodtrack.~AliAODTrack();
212 new(&aodtrack) AliAODTrack(*(static_cast<const AliAODTrack *>(track->GetRecTrack())));
213 if(track->IsPbPb() && HasCentralityCorrection())
214 ApplyCentralityCorrection(&aodtrack, track->GetMultiplicity(), anatype);
215 if(HasEtaCorrection())
216 ApplyEtaCorrection(&aodtrack, anatype);
217 rectrack = &aodtrack;
220 // Correction not available - no need to copy
221 rectrack = track->GetRecTrack();
223 AliHFEpidObject tpctrack(*track);
224 tpctrack.SetRecTrack(rectrack);
226 // QA before selection (after correction)
227 if(pidqa) pidqa->ProcessTrack(&tpctrack, AliHFEpid::kTPCpid, AliHFEdetPIDqa::kBeforePID);
228 AliDebug(1, "Doing TPC PID based on n-Sigma cut approach");
230 // make copy of the track in order to allow for applying the correction
231 Float_t nsigma = fkPIDResponse->NumberOfSigmasTPC(rectrack, AliPID::kElectron);
232 AliDebug(1, Form("TPC NSigma: %f", nsigma));
233 // exclude crossing points:
234 // Determine the bethe values for each particle species
235 Bool_t isLineCrossing = kFALSE;
236 for(Int_t ispecies = 0; ispecies < AliPID::kSPECIES; ispecies++){
237 if(ispecies == AliPID::kElectron) continue;
238 if(!(fLineCrossingsEnabled & 1 << ispecies)) continue;
239 if(TMath::Abs(fkPIDResponse->NumberOfSigmasTPC(rectrack, (AliPID::EParticleType)ispecies)) < fLineCrossingSigma[ispecies] && TMath::Abs(nsigma) < fNsigmaTPC){
240 // Point in a line crossing region, no PID possible, but !PID still possible ;-)
241 isLineCrossing = kTRUE;
245 if(isLineCrossing) return 0;
247 // Check particle rejection
248 if(HasParticleRejection()){
249 Int_t reject = Reject(rectrack, anatype);
250 if(reject != 0) return reject;
253 // Check if we have an asymmetric sigma model set
256 pdg = CutSigmaModel(&tpctrack) ? 11 : 0;
258 // Perform Asymmetric n-sigma cut if required, else perform symmetric TPC sigma cut
259 Float_t p = rectrack->P();
260 if(HasAsymmetricSigmaCut()) {
262 //printf("p %f, fPAsigCut[0] %f, fPAsigCut[1] %f\n",p,fPAsigCut[0],fPAsigCut[1]);
263 if(p >= fPAsigCut[0] && p <= fPAsigCut[1]) {
264 if(nsigma >= fNAsigmaTPC[0] && nsigma <= fNAsigmaTPC[1]) pdg = 11;
271 if(TMath::Abs(nsigma) < fNsigmaTPC ) pdg = 11;
274 if(pidqa && pdg != 0) pidqa->ProcessTrack(&tpctrack, AliHFEpid::kTPCpid, AliHFEdetPIDqa::kAfterPID);
279 //___________________________________________________________________
280 Bool_t AliHFEpidTPC::CutSigmaModel(const AliHFEpidObject * const track) const {
282 // N SigmaCut using parametrization of the cuts
284 Bool_t isSelected = kTRUE;
285 AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis : AliHFEpidObject::kAODanalysis;
286 Float_t nsigma = fkPIDResponse->NumberOfSigmasTPC(track->GetRecTrack(), AliPID::kElectron);
287 Double_t p = GetP(track->GetRecTrack(), anatype);
288 Int_t centrality = track->IsPbPb() ? track->GetCentrality() + 1 : 0;
289 AliDebug(2, Form("Centrality: %d\n", centrality));
290 if(centrality > 11) return kFALSE;
291 const TF1 *cutfunction;
292 if((cutfunction = fkUpperSigmaCut[centrality]) && nsigma > cutfunction->Eval(p)) isSelected = kFALSE;
293 if((cutfunction = fkLowerSigmaCut[centrality]) && nsigma < cutfunction->Eval(p)) isSelected = kFALSE;
297 //___________________________________________________________________
298 Int_t AliHFEpidTPC::Reject(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anaType) const{
300 // reject particles based on asymmetric sigma cut
302 Int_t pdc[AliPID::kSPECIES] = {11,13,211,321,2212};
303 Double_t p = GetP(track, anaType);
304 for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){
305 if(!TESTBIT(fRejectionEnabled, ispec)) continue;
306 // Particle rejection enabled
307 if(p < fRejection[4*ispec] || p > fRejection[4*ispec+2]) continue;
308 Double_t sigma = fkPIDResponse->NumberOfSigmasTPC(track, static_cast<AliPID::EParticleType>(ispec));
309 if(sigma >= fRejection[4*ispec+1] && sigma <= fRejection[4*ispec+3]) return pdc[ispec] * track->Charge();
314 //___________________________________________________________________
315 void AliHFEpidTPC::ApplyEtaCorrection(AliVTrack *track, AliHFEpidObject::AnalysisType_t anatype) const{
317 // Apply correction for the eta dependence
318 // N.B. This correction has to be applied on a copy track
320 AliDebug(1, Form("Applying correction function %s\n", fkEtaCorrection->GetName()));
321 Double_t original = track->GetTPCsignal(),
323 if(anatype == AliHFEpidObject::kESDanalysis){
324 AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
325 if(fkEtaCorrection->Eval(eta)>0.0) esdtrack->SetTPCsignal(original/fkEtaCorrection->Eval(eta), esdtrack->GetTPCsignalSigma(), esdtrack->GetTPCsignalN());
327 AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
328 AliAODPid *pid = aodtrack->GetDetPid();
329 if(pid && fkEtaCorrection->Eval(eta)>0.0) pid->SetTPCsignal(original/fkEtaCorrection->Eval(eta));
333 //___________________________________________________________________
334 void AliHFEpidTPC::ApplyCentralityCorrection(AliVTrack *track, Double_t centralityEstimator, AliHFEpidObject::AnalysisType_t anatype) const{
336 // Apply correction for the eta dependence
337 // N.B. This correction has to be applied on a copy track
339 AliDebug(1, Form("Applying correction function %s\n", fkCentralityCorrection->GetName()));
340 Double_t original = track->GetTPCsignal();
341 if(anatype == AliHFEpidObject::kESDanalysis){
342 AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
343 if(fkCentralityCorrection->Eval(centralityEstimator)>0.0) esdtrack->SetTPCsignal(original/fkCentralityCorrection->Eval(centralityEstimator), esdtrack->GetTPCsignalSigma(), esdtrack->GetTPCsignalN());
345 AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
346 AliAODPid *pid = aodtrack->GetDetPid();
347 if(pid && fkCentralityCorrection->Eval(centralityEstimator)>0.0) pid->SetTPCsignal(original/fkCentralityCorrection->Eval(centralityEstimator));
351 //___________________________________________________________________
352 void AliHFEpidTPC::UseOROC(AliVTrack *track, AliHFEpidObject::AnalysisType_t anatype) const{
354 // Use TPC signal from the OROC
355 // N.B. This correction has to be applied on a copy track
357 //Double_t original = track->GetTPCsignal();
359 if(anatype == AliHFEpidObject::kESDanalysis){
360 AliESDtrack *esdtrack = static_cast<AliESDtrack *>(track);
361 AliTPCdEdxInfo *dEdxInfo = track->GetTPCdEdxInfo();
362 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)
363 Char_t TPCsignalNRegion[3]; // number of clusters above threshold used in the dEdx calculation
364 Char_t TPCsignalNRowRegion[3]; // number of crosed rows used in the dEdx calculation - signal below threshold included
365 dEdxInfo->GetTPCSignalRegionInfo(TPCsignalRegion,TPCsignalNRegion,TPCsignalNRowRegion);
366 esdtrack->SetTPCsignal(TPCsignalRegion[3],esdtrack->GetTPCsignalSigma(),(TPCsignalNRegion[1]+TPCsignalNRegion[2])); // the two last are not ok
368 AliAODTrack *aodtrack = static_cast<AliAODTrack *>(track);
369 AliTPCdEdxInfo *dEdxInfo = track->GetTPCdEdxInfo();
370 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)
371 Char_t TPCsignalNRegion[3]; // number of clusters above threshold used in the dEdx calculation
372 Char_t TPCsignalNRowRegion[3]; // number of crosed rows used in the dEdx calculation - signal below threshold included
373 dEdxInfo->GetTPCSignalRegionInfo(TPCsignalRegion,TPCsignalNRegion,TPCsignalNRowRegion);
374 AliAODPid *pid = aodtrack->GetDetPid();
375 if(pid) pid->SetTPCsignal(TPCsignalRegion[3]);
376 if(pid) pid->SetTPCsignalN((TPCsignalNRegion[1]+TPCsignalNRegion[2]));
380 //___________________________________________________________________
381 void AliHFEpidTPC::AddTPCdEdxLineCrossing(Int_t species, Double_t sigma){
383 // Add exclusion point for the TPC PID where a dEdx line crosses the electron line
384 // Stores line center and line sigma
386 if(species >= AliPID::kSPECIES){
387 AliError("Species doesn't exist");
390 fLineCrossingsEnabled |= 1 << species;
391 fLineCrossingSigma[species] = sigma;
394 //___________________________________________________________________
395 Double_t AliHFEpidTPC::GetP(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anatype) const {
397 // Get the momentum at the inner wall of the TPC
400 if(anatype == AliHFEpidObject::kESDanalysis){
401 // ESD analysis: Use Inner Params for the momentum estimate
402 const AliESDtrack *esdtrack = dynamic_cast<const AliESDtrack *>(track);
403 if(esdtrack) p = esdtrack->GetInnerParam() ? esdtrack->GetInnerParam()->GetP() : esdtrack->P();
405 // AOD analysis: Use TPC momentum stored in the AliAODpid object
406 const AliAODTrack *aodtrack = dynamic_cast<const AliAODTrack *>(track);
407 if(aodtrack) p = aodtrack->GetDetPid() ? aodtrack->GetDetPid()->GetTPCmomentum() : aodtrack->P();