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
18 // Make PID does the PID decision
19 // Class further contains TRD specific cuts and QA histograms
22 // Markus Fasel <M.Fasel@gsi.de>
26 #include <THnSparse.h>
30 #include "AliAODPid.h"
31 #include "AliAODTrack.h"
32 #include "AliAODMCParticle.h"
33 #include "AliESDtrack.h"
35 #include "AliMCParticle.h"
36 #include "AliOADBContainer.h"
38 #include "AliPIDResponse.h"
40 #include "AliHFEOADBThresholdsTRD.h"
41 #include "AliHFEpidQAmanager.h"
42 #include "AliHFEpidTRD.h"
44 ClassImp(AliHFEpidTRD)
46 //___________________________________________________________________
47 AliHFEpidTRD::AliHFEpidTRD() :
49 , fOADBThresholds(NULL)
54 , fElectronEfficiency(0.90)
55 , fTotalChargeInSlice0(kFALSE)
59 // default constructor
61 memset(fThreshParams, 0, sizeof(Double_t) * kThreshParams);
64 //___________________________________________________________________
65 AliHFEpidTRD::AliHFEpidTRD(const char* name) :
67 , fOADBThresholds(NULL)
72 , fElectronEfficiency(0.91)
73 , fTotalChargeInSlice0(kFALSE)
77 // default constructor
79 memset(fThreshParams, 0, sizeof(Double_t) * kThreshParams);
82 //___________________________________________________________________
83 AliHFEpidTRD::AliHFEpidTRD(const AliHFEpidTRD &ref):
85 , fOADBThresholds(NULL)
87 , fNTracklets(ref.fNTracklets)
88 , fCutNTracklets(ref.fCutNTracklets)
89 , fRunNumber(ref.fRunNumber)
90 , fElectronEfficiency(ref.fElectronEfficiency)
91 , fTotalChargeInSlice0(ref.fTotalChargeInSlice0)
92 , fTRD2DPID(ref.fTRD2DPID)
97 memset(fThreshParams, 0, sizeof(Double_t) * kThreshParams);
101 //___________________________________________________________________
102 AliHFEpidTRD &AliHFEpidTRD::operator=(const AliHFEpidTRD &ref){
104 // Assignment operator
112 //___________________________________________________________________
113 void AliHFEpidTRD::Copy(TObject &ref) const {
115 // Performs the copying of the object
117 AliHFEpidTRD &target = dynamic_cast<AliHFEpidTRD &>(ref);
119 target.fMinP = fMinP;
120 target.fNTracklets = fNTracklets;
121 target.fCutNTracklets = fCutNTracklets;
122 target.fRunNumber = fRunNumber;
123 target.fTotalChargeInSlice0 = fTotalChargeInSlice0;
124 target.fTRD2DPID = fTRD2DPID;
125 target.fElectronEfficiency = fElectronEfficiency;
126 memcpy(target.fThreshParams, fThreshParams, sizeof(Double_t) * kThreshParams);
127 AliHFEpidBase::Copy(ref);
130 //___________________________________________________________________
131 AliHFEpidTRD::~AliHFEpidTRD(){
137 //______________________________________________________
138 Bool_t AliHFEpidTRD::InitializePID(Int_t run){
140 // InitializePID call different init function depending on TRD PID method
144 //if(fTRD2DPID) return Initialize2D(run);
145 if(fTRD2DPID) return kTRUE;
146 else return Initialize1D(run);
152 //______________________________________________________
153 Bool_t AliHFEpidTRD::Initialize1D(Int_t run){
155 // InitializePID: Load TRD thresholds and create the electron efficiency axis
158 AliDebug(1, Form("Initializing TRD PID for run %d", run));
159 if(InitParamsFromOADB(run)){
160 SetBit(kThresholdsInitialized);
163 AliDebug(1, Form("Threshold Parameters for %d tracklets and an electron efficiency %f loaded:", fNTracklets, fElectronEfficiency));
164 AliDebug(1, Form("Params: [%f|%f|%f|%f]", fThreshParams[0], fThreshParams[1], fThreshParams[2], fThreshParams[3]));
170 //______________________________________________________
171 Bool_t AliHFEpidTRD::Initialize2D(Int_t run){
182 //______________________________________________________
183 Int_t AliHFEpidTRD::IsSelected(const AliHFEpidObject *track, AliHFEpidQAmanager *pidqa) const {
185 // Does PID for TRD alone:
186 // PID algorithm selected according to flag
190 if(fTRD2DPID) return IsSelected2D(track, pidqa);
191 else return IsSelected1D(track, pidqa);
196 //______________________________________________________
197 Int_t AliHFEpidTRD::IsSelected1D(const AliHFEpidObject *track, AliHFEpidQAmanager *pidqa) const {
199 // Does PID for TRD alone:
200 // PID thresholds based on 90% Electron Efficiency level approximated by a linear
203 if(!TestBit(kThresholdsInitialized)) {
204 AliDebug(1,"Threshold Parameters not available");
207 AliDebug(2, "Applying TRD PID");
209 AliDebug(2, "Cannot process track");
215 const AliESDtrack *esdt = dynamic_cast<const AliESDtrack *>(track->GetRecTrack());
216 printf("checking IdentifiedAsElectronTRD, number of Tracklets: %d\n", esdt->GetTRDntrackletsPID());
217 if(fkPIDResponse->IdentifiedAsElectronTRD(dynamic_cast<const AliVTrack *>(track->GetRecTrack()), 0.8)) printf("Track identified as electron\n");
218 else printf("Track rejected\n");
220 AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis: AliHFEpidObject::kAODanalysis;
221 Double_t p = GetP(track->GetRecTrack(), anatype);
223 AliDebug(2, Form("Track momentum below %f", fMinP));
227 if(pidqa) pidqa->ProcessTrack(track, AliHFEpid::kTRDpid, AliHFEdetPIDqa::kBeforePID);
229 if(fCutNTracklets > 0){
230 AliDebug(1, Form("Number of tracklets cut applied: %d\n", fCutNTracklets));
231 Int_t ntracklets = track->GetRecTrack() ? track->GetRecTrack()->GetTRDntrackletsPID() : 0;
232 if(TestBit(kExactTrackletCut)){
233 AliDebug(1, Form("Exact cut applied: %d tracklets found\n", ntracklets));
234 if(ntracklets != fCutNTracklets) return 0;
236 AliDebug(1, Form("Greater Equal cut applied: %d tracklets found\n", ntracklets));
237 if(ntracklets < fCutNTracklets) return 0;
240 AliDebug(1,"Track selected\n");
242 Double_t electronLike = GetElectronLikelihood(track->GetRecTrack(), anatype);
244 if(TestBit(kSelectCutOnTheFly)){
245 threshold = GetTRDthresholds(p, track->GetRecTrack()->GetTRDntrackletsPID());
247 threshold = GetTRDthresholds(p);
249 AliDebug(2, Form("Threshold: %f\n", threshold));
250 if(electronLike > threshold){
251 if(pidqa) pidqa->ProcessTrack(track, AliHFEpid::kTRDpid, AliHFEdetPIDqa::kAfterPID);
258 //______________________________________________________
259 Int_t AliHFEpidTRD::IsSelected2D(const AliHFEpidObject *track, AliHFEpidQAmanager *pidqa) const {
265 AliDebug(2, "Applying TRD PID");
267 AliDebug(2, "Cannot process track");
271 AliHFEpidObject::AnalysisType_t anatype = track->IsESDanalysis() ? AliHFEpidObject::kESDanalysis: AliHFEpidObject::kAODanalysis;
272 Double_t p = GetP(track->GetRecTrack(), anatype);
274 AliDebug(2, Form("Track momentum below %f", fMinP));
278 if(pidqa) pidqa->ProcessTrack(track, AliHFEpid::kTRDpid, AliHFEdetPIDqa::kBeforePID);
280 if(fCutNTracklets > 0){
281 AliDebug(1, Form("Number of tracklets cut applied: %d\n", fCutNTracklets));
282 Int_t ntracklets = track->GetRecTrack() ? track->GetRecTrack()->GetTRDntrackletsPID() : 0;
283 if(TestBit(kExactTrackletCut)){
284 AliDebug(1, Form("Exact cut applied: %d tracklets found\n", ntracklets));
285 if(ntracklets != fCutNTracklets) return 0;
287 AliDebug(1, Form("Greater Equal cut applied: %d tracklets found\n", ntracklets));
288 if(ntracklets < fCutNTracklets) return 0;
291 AliDebug(1,"Track selected\n");
293 Int_t centralitybin = track->IsPbPb() ? track->GetCentrality() : -2;
294 Float_t fCentralityLimitsdefault[12]= {0.,5.,10., 20., 30., 40., 50., 60.,70.,80., 90., 100.};
295 Float_t centrality=-1;
296 if(centralitybin>=0) centrality=fCentralityLimitsdefault[centralitybin]+1;
298 if(fkPIDResponse->IdentifiedAsElectronTRD(track->GetRecTrack(),fElectronEfficiency,centrality,AliTRDPIDResponse::kLQ2D)){
299 AliDebug(2, Form("Electron effi: %f %i %i %f\n", fElectronEfficiency,track->GetCentrality(),centralitybin,centrality));
300 if(pidqa) pidqa->ProcessTrack(track, AliHFEpid::kTRDpid, AliHFEdetPIDqa::kAfterPID);
308 //___________________________________________________________________
309 Double_t AliHFEpidTRD::GetTRDthresholds(Double_t p, UInt_t nTracklets) const {
311 // Return momentum dependent and electron efficiency dependent TRD thresholds
312 // Determine threshold based on the number of tracklets on the fly, electron efficiency not modified
314 Double_t threshParams[4];
315 AliDebug(1, Form("Select cut for %d tracklets\n", nTracklets));
316 // Get threshold paramters for the given number of tracklets from OADB container
317 AliHFEOADBThresholdsTRD *thresholds = dynamic_cast<AliHFEOADBThresholdsTRD *>(fOADBThresholds->GetObject(fRunNumber));
319 AliDebug(1, Form("Thresholds for run %d not in the OADB", fRunNumber));
322 if(!thresholds->GetThresholdParameters(nTracklets, fElectronEfficiency, threshParams)){
323 AliDebug(1, "loading thresholds failed\n");
326 Double_t threshold = 1. - threshParams[0] - threshParams[1] * p - threshParams[2] * TMath::Exp(-threshParams[3] * p);
327 return TMath::Max(TMath::Min(threshold, 0.99), 0.2); // truncate the threshold upperwards to 0.999 and lowerwards to 0.2 and exclude unphysical values
330 //___________________________________________________________________
331 Double_t AliHFEpidTRD::GetTRDthresholds(Double_t p) const {
333 // Return momentum dependent and electron efficiency dependent TRD thresholds
335 Double_t threshold = 1. - fThreshParams[0] - fThreshParams[1] * p - fThreshParams[2] * TMath::Exp(-fThreshParams[3] * p);
336 return TMath::Max(TMath::Min(threshold, 0.99), 0.2); // truncate the threshold upperwards to 0.999 and lowerwards to 0.2 and exclude unphysical values
340 //___________________________________________________________________
341 Bool_t AliHFEpidTRD::InitParamsFromOADB(Int_t run){
343 // The name of the function says it all
345 AliHFEOADBThresholdsTRD *thresholds = dynamic_cast<AliHFEOADBThresholdsTRD *>(fOADBThresholds->GetObject(run));
347 AliDebug(1, Form("Thresholds for run %d not in the OADB", run));
350 return thresholds->GetThresholdParameters(fNTracklets, fElectronEfficiency, fThreshParams);
353 //___________________________________________________________________
354 void AliHFEpidTRD::RenormalizeElPi(const Double_t * const likein, Double_t * const likeout) const {
356 // Renormalize likelihoods for electrons and pions neglecting the
357 // likelihoods for protons, kaons and muons
359 memset(likeout, 0, sizeof(Double_t) * AliPID::kSPECIES);
360 Double_t norm = likein[AliPID::kElectron] + likein[AliPID::kPion];
361 if(norm == 0.) norm = 1.; // Safety
362 likeout[AliPID::kElectron] = likein[AliPID::kElectron] / norm;
363 likeout[AliPID::kPion] = likein[AliPID::kPion] / norm;
366 //___________________________________________________________________
367 Double_t AliHFEpidTRD::GetElectronLikelihood(const AliVTrack *track, AliHFEpidObject::AnalysisType_t anaType) const {
369 // Get TRD likelihoods for ESD respectively AOD tracks
371 Double_t pidProbs[AliPID::kSPECIES]; memset(pidProbs, 0, sizeof(Double_t) * AliPID::kSPECIES);
372 if(anaType == AliHFEpidObject::kESDanalysis){
373 const AliESDtrack *esdtrack = dynamic_cast<const AliESDtrack *>(track);
374 if(esdtrack) esdtrack->GetTRDpid(pidProbs);
376 if(fTRD2DPID) fkPIDResponse->ComputeTRDProbability(track, AliPID::kSPECIES, pidProbs,AliTRDPIDResponse::kLQ2D);
377 else fkPIDResponse->ComputeTRDProbability(track, AliPID::kSPECIES, pidProbs,AliTRDPIDResponse::kLQ1D);
379 if(!IsRenormalizeElPi()) return pidProbs[AliPID::kElectron];
380 Double_t probsNew[AliPID::kSPECIES];
381 RenormalizeElPi(pidProbs, probsNew);
382 return probsNew[AliPID::kElectron];
385 //___________________________________________________________________
386 Double_t AliHFEpidTRD::GetP(const AliVParticle *track, AliHFEpidObject::AnalysisType_t anaType) const {
388 // Get the Momentum in the TRD
391 if(anaType == AliHFEpidObject::kESDanalysis){
392 const AliESDtrack *esdtrack = dynamic_cast<const AliESDtrack *>(track);
393 if(esdtrack) p = esdtrack->GetOuterParam() ? esdtrack->GetOuterParam()->P() : esdtrack->P();
395 const AliAODTrack *aodtrack = dynamic_cast<const AliAODTrack *>(track);
396 if(aodtrack) p = aodtrack->P();
401 //___________________________________________________________________
402 Double_t AliHFEpidTRD::GetChargeLayer(const AliVParticle *track, UInt_t layer, AliHFEpidObject::AnalysisType_t anaType) const {
404 // Get the Charge in a single TRD layer
406 if(layer >= 6) return 0.;
407 Double_t charge = 0.;
408 if(anaType == AliHFEpidObject::kESDanalysis){
409 const AliESDtrack *esdtrack = dynamic_cast<const AliESDtrack *>(track);
411 // Distinction between old and new reconstruction: in the new reconstruction, the total charge is stored in slice 0, slices 1 to 8 are used for the slices for
412 // the neural network.
413 if(fTotalChargeInSlice0)
414 charge = esdtrack->GetTRDslice(static_cast<UInt_t>(layer), 0);
416 for(Int_t islice = 0; islice < esdtrack->GetNumberOfTRDslices(); islice++) charge += esdtrack->GetTRDslice(static_cast<UInt_t>(layer), islice);
419 const AliAODTrack *aodtrack = dynamic_cast<const AliAODTrack *>(track);
420 AliAODPid *aoddetpid = aodtrack ? aodtrack->GetDetPid() : NULL;
422 if(fTotalChargeInSlice0)
423 charge = aoddetpid->GetTRDslices()[layer * aoddetpid->GetTRDnSlices()];
425 for(Int_t islice = 0; islice < aoddetpid->GetTRDnSlices(); islice++) charge += aoddetpid->GetTRDslices()[layer * aoddetpid->GetTRDnSlices() + islice];
431 //___________________________________________________________________
432 void AliHFEpidTRD::GetTRDmomenta(const AliVTrack *track, Double_t *mom) const {
434 // Fill Array with momentum information at the TRD tracklet
436 for(Int_t itl = 0; itl < 6; itl++)
437 mom[itl] = track->GetTRDmomentum(itl);
440 //___________________________________________________________________
441 Double_t AliHFEpidTRD::GetTRDSignalV1(const AliESDtrack *track, Float_t truncation) const {
443 // Calculation of the TRD Signal via truncated mean
444 // Method 1: Take all Slices available
446 // Order them in increasing order
447 // Cut out the upper third
448 // Calculate mean over the last 2/3 slices
450 const Int_t kNSlices = 48;
451 const Int_t kLastSlice = 6; // Slice 7 is taken out from the truncated mean calculation
452 const Double_t kVerySmall = 1e-12;
453 // Weight the slice to equalize the MPV of the dQ/dl-distribution per slice to the one in the first slice
454 // Pions are used as reference for the equalization
455 const Double_t kWeightSlice[8] = {1., 2.122, 1.8, 1.635, 1.595, 1.614, 1.16, 7.0};
456 const Double_t kWeightSliceNo0[8] = {1., 1., 1.271, 1.451, 1.531, 1.543, 1.553, 2.163}; // Weighting factors in case slice 0 stores the total charge
457 const Double_t *kWeightFactor = fTotalChargeInSlice0 ? kWeightSliceNo0 : kWeightSlice;
458 AliDebug(3, Form("Number of Tracklets: %d\n", track->GetTRDntrackletsPID()));
459 Double_t trdSlices[kNSlices], tmp[kNSlices];
462 for(Int_t idet = 0; idet < 6; idet++)
463 for(Int_t islice = fTotalChargeInSlice0 ? 1 : 0 ; islice <= kLastSlice; islice++){
464 AliDebug(2, Form("Chamber[%d], Slice[%d]: TRDSlice = %f", idet, islice, track->GetTRDslice(idet, islice)));
465 if(TMath::Abs(track->GetTRDslice(idet, islice)) < kVerySmall) continue;;
466 trdSlices[icnt++] = track->GetTRDslice(idet, islice) * kWeightFactor[islice];
468 AliDebug(1, Form("Number of Slices: %d\n", icnt));
469 if(icnt < 6) return 0.; // We need at least 6 Slices for the truncated mean
470 TMath::Sort(icnt, trdSlices, indices, kFALSE);
471 memcpy(tmp, trdSlices, sizeof(Double_t) * icnt);
472 for(Int_t ien = 0; ien < icnt; ien++)
473 trdSlices[ien] = tmp[indices[ien]];
474 Double_t trdSignal = TMath::Mean(static_cast<Int_t>(static_cast<Float_t>(icnt) * truncation), trdSlices);
475 Double_t mom = track->GetOuterParam() ? track->GetOuterParam()->P() : -1;
476 AliDebug(3, Form("PID Meth. 1: p[%f], TRDSignal[%f]", mom, trdSignal));
480 //___________________________________________________________________
481 Double_t AliHFEpidTRD::GetTRDSignalV2(const AliESDtrack *track, Float_t truncation) const {
483 // Calculation of the TRD Signal via truncated mean
484 // Method 2: Take only first 5 slices per chamber
485 // Order them in increasing order
486 // Cut out upper half
487 // Now do mean with the reamining 3 slices per chamber
489 const Double_t kWeightSlice[8] = {1., 2.122, 1.8, 1.635, 1.595, 1.614, 1.16, 7.0};
490 const Int_t kLayers = 6;
491 const Int_t kSlicesLow = 6;
492 const Int_t kSlicesHigh = 1;
493 const Double_t kVerySmall = 1e-12;
494 Double_t trdSlicesLowTime[kLayers*kSlicesLow], trdSlicesRemaining[kLayers*(kSlicesHigh + kSlicesLow)];
495 Int_t indices[kLayers*kSlicesLow];
496 Int_t cntLowTime=0, cntRemaining = 0;
497 for(Int_t idet = 0; idet < 6; idet++)
498 for(Int_t islice = fTotalChargeInSlice0 ? 1 : 0; islice < kSlicesLow+kSlicesHigh; islice++){
499 if(TMath::Abs(track->GetTRDslice(idet, islice)) < kVerySmall) continue;;
500 if(islice < kSlicesLow){
501 AliDebug(3, Form("Part 1, Det[%d], Slice[%d], TRDSlice: %f", idet, islice, track->GetTRDslice(idet, islice)));
502 trdSlicesLowTime[cntLowTime++] = track->GetTRDslice(idet, islice) * kWeightSlice[islice];
504 AliDebug(3, Form("Part 1, Det[%d], Slice[%d], TRDSlice: %f", idet, islice, track->GetTRDslice(idet, islice)));
505 trdSlicesRemaining[cntRemaining++] = track->GetTRDslice(idet, islice) * kWeightSlice[islice];
508 if(cntLowTime < 4 || cntRemaining < 2) return 0.; // Min. Number of Slices at high time is 2 (matches with 1 layer), for the truncated mean we need at least 4 Slices
509 TMath::Sort(cntLowTime, trdSlicesLowTime, indices, kFALSE);
510 // Fill the second array with the lower half of the first time bins
511 for(Int_t ien = 0; ien < static_cast<Int_t>(static_cast<Float_t>(cntLowTime) * truncation); ien++)
512 trdSlicesRemaining[cntRemaining++] = trdSlicesLowTime[indices[ien]];
513 Double_t trdSignal = TMath::Mean(cntRemaining, trdSlicesRemaining);
514 Double_t mom = track->GetOuterParam() ? track->GetOuterParam()->P() : -1;
515 AliDebug(3, Form("PID Meth. 2: p[%f], TRDSignal[%f]", mom, trdSignal));