]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/STEERBase/AliTRDPIDResponse.cxx
Commit message
[u/mrichter/AliRoot.git] / STEER / STEERBase / AliTRDPIDResponse.cxx
CommitLineData
ffb1ee30 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// PID Response class for the TRD detector
17// Based on 1D Likelihood approach
18// Calculation of probabilities using Bayesian approach
19// Attention: This method is only used to separate electrons from pions
20//
21// Authors:
22// Markus Fasel <M.Fasel@gsi.de>
23// Anton Andronic <A.Andronic@gsi.de>
24//
ffb1ee30 25#include <TAxis.h>
ea235c90 26#include <TClass.h>
27#include <TDirectory.h>
ffb1ee30 28#include <TFile.h>
29#include <TH1.h>
ce5d6908 30#include <TKey.h>
ea235c90 31#include <TMath.h>
ffb1ee30 32#include <TObjArray.h>
ce5d6908 33#include <TROOT.h>
ea235c90 34#include <TString.h>
ffb1ee30 35#include <TSystem.h>
36
37#include "AliLog.h"
5cd0300d 38
39#include "AliVTrack.h"
ffb1ee30 40
db0e2c5f 41#include "AliTRDPIDResponseObject.h"
ffb1ee30 42#include "AliTRDPIDResponse.h"
239fe91c 43//#include "AliTRDTKDInterpolator.h"
44#include "AliTRDNDFast.h"
9c499471 45#include "AliTRDdEdxParams.h"
ffb1ee30 46
47ClassImp(AliTRDPIDResponse)
48
ffb1ee30 49//____________________________________________________________
e0de37e9 50AliTRDPIDResponse::AliTRDPIDResponse():
51 TObject()
db0e2c5f 52 ,fkPIDResponseObject(NULL)
9c499471 53 ,fkTRDdEdxParams(NULL)
e0de37e9 54 ,fGainNormalisationFactor(1.)
ffb1ee30 55{
e0de37e9 56 //
57 // Default constructor
58 //
ffb1ee30 59}
60
61//____________________________________________________________
62AliTRDPIDResponse::AliTRDPIDResponse(const AliTRDPIDResponse &ref):
e0de37e9 63 TObject(ref)
db0e2c5f 64 ,fkPIDResponseObject(NULL)
9c499471 65 ,fkTRDdEdxParams(NULL)
e0de37e9 66 ,fGainNormalisationFactor(ref.fGainNormalisationFactor)
ffb1ee30 67{
e0de37e9 68 //
69 // Copy constructor
e0de37e9 70 //
ffb1ee30 71}
72
73//____________________________________________________________
74AliTRDPIDResponse &AliTRDPIDResponse::operator=(const AliTRDPIDResponse &ref){
e0de37e9 75 //
76 // Assignment operator
e0de37e9 77 //
78 if(this == &ref) return *this;
79
80 // Make copy
81 TObject::operator=(ref);
51a0ce25 82 fGainNormalisationFactor = ref.fGainNormalisationFactor;
db0e2c5f 83 fkPIDResponseObject = ref.fkPIDResponseObject;
9c499471 84 fkTRDdEdxParams = ref.fkTRDdEdxParams;
85
e0de37e9 86 return *this;
ffb1ee30 87}
88
89//____________________________________________________________
90AliTRDPIDResponse::~AliTRDPIDResponse(){
e0de37e9 91 //
92 // Destructor
93 //
9c499471 94 if(IsOwner()) {
95 delete fkPIDResponseObject;
96 delete fkTRDdEdxParams;
97 }
ffb1ee30 98}
99
100//____________________________________________________________
db0e2c5f 101Bool_t AliTRDPIDResponse::Load(const Char_t * filename){
e0de37e9 102 //
103 // Load References into the toolkit
104 //
105 AliDebug(1, "Loading reference histos from root file");
2ad33025 106 TDirectory *owd = gDirectory;// store old working directory
e0de37e9 107
108 if(!filename)
109 filename = Form("%s/STEER/LQ1dRef_v1.root",gSystem->ExpandPathName("$ALICE_ROOT"));
110 TFile *in = TFile::Open(filename);
111 if(!in){
112 AliError("Ref file not available.");
113 return kFALSE;
114 }
115
116 gROOT->cd();
db0e2c5f 117 fkPIDResponseObject = dynamic_cast<const AliTRDPIDResponseObject *>(in->Get("TRDPIDResponse")->Clone());
51a0ce25 118 in->Close(); delete in;
e0de37e9 119 owd->cd();
e0de37e9 120 SetBit(kIsOwner, kTRUE);
db0e2c5f 121 AliDebug(2, Form("Successfully loaded References for %d Momentum bins", fkPIDResponseObject->GetNumberOfMomentumBins()));
e0de37e9 122 return kTRUE;
ffb1ee30 123}
124
5cd0300d 125
126
127//____________________________________________________________
128Double_t AliTRDPIDResponse::GetNumberOfSigmas(const AliVTrack *track, AliPID::EParticleType type) const
129{
130 //
131 //calculate the TRD nSigma
132 //
133
134 const Double_t badval = -9999;
135 Double_t info[5]; for(int i=0; i<5; i++){info[i]=badval;}
136
137 const Double_t delta = GetSignalDelta(track, type, kFALSE, info);
138
139 const Double_t mean = info[0];
140 const Double_t res = info[1];
141 if(res<0){
142 return badval;
143 }
144
145 const Double_t sigma = mean*res;
bebe75fc 146 const Double_t eps = 1e-12;
147 return delta/(sigma + eps);
5cd0300d 148}
149
150//____________________________________________________________
151Double_t AliTRDPIDResponse::GetSignalDelta( const AliVTrack* track, AliPID::EParticleType type, Bool_t ratio/*=kFALSE*/, Double_t *info/*=0x0*/) const
152{
153 //
154 //calculate the TRD signal difference w.r.t. the expected
155 //output other information in info[]
156 //
157
9c499471 158 const Double_t badval = -9999;
5cd0300d 159
160 //cut on number of chambers
161 const Double_t cutch = 6;
162
163 //cut on mean number of clusters per chamber
164 const Double_t cutclsperch = 18;
5cd0300d 165
166 const Double_t nch = track->GetTRDNchamberdEdx();
167 if(nch < cutch){
168 return badval;
169 }
170
171 const Double_t ncls = track->GetTRDNclusterdEdx();
172 if( ncls/nch < cutclsperch){
173 return badval;
174 }
175
176 Double_t pTRD = -999;
177 for(Int_t ich=0; ich<6; ich++){
178 pTRD = track->GetTRDmomentum(ich);
179 if(pTRD>0)
180 break;
181 }
182 if(pTRD<0){
183 return badval;
184 }
185
9c499471 186 if(!fkTRDdEdxParams){
2ddf4abb 187 AliError("fkTRDdEdxParams null");
9c499471 188 return -99999;
189 }
190
2ddf4abb 191 const Float_t *meanpar = (fkTRDdEdxParams->GetMeanParameter(type)).GetMatrixArray();
192 const Float_t *respar = (fkTRDdEdxParams->GetSigmaParameter(type)).GetMatrixArray();
9c499471 193
194 //============================================================================================<<<<<<<<<<<<<
195
5cd0300d 196 const Double_t bg = pTRD/AliPID::ParticleMass(type);
9c499471 197 const Double_t expsig = MeandEdxTR(&bg, meanpar);
5cd0300d 198
199 if(info){
200 info[0]= expsig;
9c499471 201 info[1]= ResolutiondEdxTR(&ncls, respar);
5cd0300d 202 }
203
bebe75fc 204 const Double_t eps = 1e-10;
205
5cd0300d 206 if(ratio){
bebe75fc 207 return track->GetTRDsignal()/(expsig + eps);
5cd0300d 208 }
209 else{
210 return track->GetTRDsignal() - expsig;
211 }
212}
213
214
2ddf4abb 215Double_t AliTRDPIDResponse::ResolutiondEdxTR(const Double_t * xx, const Float_t * par)
5cd0300d 216{
217 //
218 //resolution
219 //npar=3
220 //
221
222 const Double_t ncls = xx[0];
223
224 return par[0]+par[1]*TMath::Power(ncls, par[2]);
225}
226
2ddf4abb 227Double_t AliTRDPIDResponse::MeandEdxTR(const Double_t * xx, const Float_t * pin)
5cd0300d 228{
229 //
230 //ALEPH+LOGISTIC parametrization for dEdx+TR, in unit of MIP
231 //npar = 8 = 3+5
232 //
233
2ddf4abb 234 Float_t ptr[4]={0};
5cd0300d 235 for(int ii=0; ii<3; ii++){
236 ptr[ii+1]=pin[ii];
237 }
238 return MeanTR(xx,ptr) + MeandEdx(xx,&(pin[3]));
239}
240
2ddf4abb 241Double_t AliTRDPIDResponse::MeanTR(const Double_t * xx, const Float_t * par)
5cd0300d 242{
243 //
244 //LOGISTIC parametrization for TR, in unit of MIP
245 //npar = 4
246 //
247
248 const Double_t bg = xx[0];
249 const Double_t gamma = sqrt(1+bg*bg);
250
251 const Double_t p0 = TMath::Abs(par[1]);
252 const Double_t p1 = TMath::Abs(par[2]);
253 const Double_t p2 = TMath::Abs(par[3]);
254
255 const Double_t zz = TMath::Log(gamma);
256 const Double_t tryield = p0/( 1 + TMath::Exp(-p1*(zz-p2)) );
257
258 return par[0]+tryield;
259}
260
2ddf4abb 261Double_t AliTRDPIDResponse::MeandEdx(const Double_t * xx, const Float_t * par)
5cd0300d 262{
263 //
264 //ALEPH parametrization for dEdx
265 //npar = 5
266 //
267
268 const Double_t bg = xx[0];
269 const Double_t beta = bg/TMath::Sqrt(1.+ bg*bg);
270
271 const Double_t p0 = TMath::Abs(par[0]);
272 const Double_t p1 = TMath::Abs(par[1]);
273
274 const Double_t p2 = TMath::Abs(par[2]);
275
276 const Double_t p3 = TMath::Abs(par[3]);
277 const Double_t p4 = TMath::Abs(par[4]);
278
279 const Double_t aa = TMath::Power(beta, p3);
280
281 const Double_t bb = TMath::Log( p2 + TMath::Power(1./bg, p4) );
282
283 return (p1-aa-bb)*p0/aa;
284
285}
286
287
ffb1ee30 288//____________________________________________________________
239fe91c 289Int_t AliTRDPIDResponse::GetResponse(Int_t n, const Double_t * const dedx, const Float_t * const p, Double_t prob[AliPID::kSPECIES],ETRDPIDMethod PIDmethod,Bool_t kNorm) const
ffb1ee30 290{
e0de37e9 291 //
292 // Calculate TRD likelihood values for the track based on dedx and
293 // momentum values. The likelihoods are calculated by query the
294 // reference data depending on the PID method selected
295 //
296 // Input parameter :
297 // n - number of dedx slices/chamber
298 // dedx - array of dedx slices organized layer wise
299 // p - array of momentum measurements organized layer wise
300 //
301 // Return parameters
302 // prob - probabilities allocated by TRD for particle specis
303 // kNorm - switch to normalize probabilities to 1. By default true. If false return not normalized prob.
304 //
305 // Return value
239fe91c 306 // number of tracklets used for PID, 0 if no PID
bd58d4b9 307 //
308 AliDebug(3,Form(" Response for PID method: %d",PIDmethod));
309
ffb1ee30 310
db0e2c5f 311 if(!fkPIDResponseObject){
31746593 312 AliDebug(3,"Missing reference data. PID calculation not possible.");
239fe91c 313 return 0;
db0e2c5f 314 }
ffb1ee30 315
db0e2c5f 316 for(Int_t is(AliPID::kSPECIES); is--;) prob[is]=.2;
317 Double_t prLayer[AliPID::kSPECIES];
318 Double_t dE[10], s(0.);
239fe91c 319 Int_t ntrackletsPID=0;
db0e2c5f 320 for(Int_t il(kNlayer); il--;){
321 memset(prLayer, 0, AliPID::kSPECIES*sizeof(Double_t));
bd58d4b9 322 if(!CookdEdx(n, &dedx[il*n], &dE[0],PIDmethod)) continue;
239fe91c 323 s=0.;
db0e2c5f 324 Bool_t filled=kTRUE;
325 for(Int_t is(AliPID::kSPECIES); is--;){
239fe91c 326 //if((PIDmethod==kLQ2D)&&(!(is==0||is==2)))continue;
bd58d4b9 327 if((dE[0] > 0.) && (p[il] > 0.)) prLayer[is] = GetProbabilitySingleLayer(is, p[il], &dE[0],PIDmethod);
f2762b1c 328 AliDebug(3, Form("Probability for Species %d in Layer %d: %e", is, il, prLayer[is]));
db0e2c5f 329 if(prLayer[is]<1.e-30){
330 AliDebug(2, Form("Null for species %d species prob layer[%d].",is,il));
331 filled=kFALSE;
332 break;
333 }
334 s+=prLayer[is];
335 }
336 if(!filled){
337 continue;
338 }
339 if(s<1.e-30){
340 AliDebug(2, Form("Null all species prob layer[%d].", il));
341 continue;
342 }
343 for(Int_t is(AliPID::kSPECIES); is--;){
344 if(kNorm) prLayer[is] /= s;
345 prob[is] *= prLayer[is];
346 }
239fe91c 347 ntrackletsPID++;
e0de37e9 348 }
239fe91c 349 if(!kNorm) return ntrackletsPID;
db0e2c5f 350
351 s=0.;
352 for(Int_t is(AliPID::kSPECIES); is--;) s+=prob[is];
e0de37e9 353 if(s<1.e-30){
db0e2c5f 354 AliDebug(2, "Null total prob.");
239fe91c 355 return 0;
e0de37e9 356 }
db0e2c5f 357 for(Int_t is(AliPID::kSPECIES); is--;) prob[is]/=s;
239fe91c 358 return ntrackletsPID;
ffb1ee30 359}
360
ffb1ee30 361//____________________________________________________________
bd58d4b9 362Double_t AliTRDPIDResponse::GetProbabilitySingleLayer(Int_t species, Double_t plocal, Double_t *dEdx,ETRDPIDMethod PIDmethod) const {
e0de37e9 363 //
364 // Get the non-normalized probability for a certain particle species as coming
365 // from the reference histogram
366 // Interpolation between momentum bins
367 //
368 AliDebug(1, Form("Make Probability for Species %d with Momentum %f", species, plocal));
db0e2c5f 369
51a0ce25 370 Double_t probLayer = 0.;
239fe91c 371
db0e2c5f 372 Float_t pLower, pUpper;
373
239fe91c 374 AliTRDNDFast *refUpper = dynamic_cast<AliTRDNDFast *>(fkPIDResponseObject->GetUpperReference((AliPID::EParticleType)species, plocal, pUpper,PIDmethod)),
375 *refLower = dynamic_cast<AliTRDNDFast *>(fkPIDResponseObject->GetLowerReference((AliPID::EParticleType)species, plocal, pLower,PIDmethod));
376
377 // Do Interpolation exept for underflow and overflow
378 if(refLower && refUpper){
379 Double_t probLower = refLower->Eval(dEdx);
380 Double_t probUpper = refUpper->Eval(dEdx);
381
382 probLayer = probLower + (probUpper - probLower)/(pUpper-pLower) * (plocal - pLower);
383 } else if(refLower){
384 // underflow
385 probLayer = refLower->Eval(dEdx);
386 } else if(refUpper){
387 // overflow
388 probLayer = refUpper->Eval(dEdx);
389 } else {
390 AliError("No references available");
391 }
392 AliDebug(1, Form("Eval 1D dEdx %f Probability %e", dEdx[0],probLayer));
393
394 return probLayer;
395
396/* old implementation
397
398switch(PIDmethod){
399case kNN: // NN
db0e2c5f 400 break;
401 case kLQ2D: // 2D LQ
402 {
f2762b1c 403 if(species==0||species==2){ // references only for electrons and pions
2285168d 404 Double_t error = 0.;
f2762b1c 405 Double_t point[kNslicesLQ2D];
406 for(Int_t idim=0;idim<kNslicesLQ2D;idim++){point[idim]=dEdx[idim];}
db0e2c5f 407
239fe91c 408 AliTRDTKDInterpolator *refUpper = dynamic_cast<AliTRDTKDInterpolator *>(fkPIDResponseObject->GetUpperReference((AliPID::EParticleType)species, plocal, pUpper,kLQ2D)),
409 *refLower = dynamic_cast<AliTRDTKDInterpolator *>(fkPIDResponseObject->GetLowerReference((AliPID::EParticleType)species, plocal, pLower,kLQ2D));
410 // Do Interpolation exept for underflow and overflow
411 if(refLower && refUpper){
412 Double_t probLower=0,probUpper=0;
413 refLower->Eval(point,probLower,error);
414 refUpper->Eval(point,probUpper,error);
415 probLayer = probLower + (probUpper - probLower)/(pUpper-pLower) * (plocal - pLower);
416 } else if(refLower){
417 // underflow
f2762b1c 418 refLower->Eval(point,probLayer,error);
239fe91c 419 } else if(refUpper){
420 // overflow
421 refUpper->Eval(point,probLayer,error);
422 } else {
f2762b1c 423 AliError("No references available");
424 }
425 AliDebug(2,Form("Eval 2D Q0 %f Q1 %f P %e Err %e",point[0],point[1],probLayer,error));
db0e2c5f 426 }
427 }
428 break;
429 case kLQ1D: // 1D LQ
430 {
431 TH1 *refUpper = dynamic_cast<TH1 *>(fkPIDResponseObject->GetUpperReference((AliPID::EParticleType)species, plocal, pUpper,kLQ1D)),
432 *refLower = dynamic_cast<TH1 *>(fkPIDResponseObject->GetLowerReference((AliPID::EParticleType)species, plocal, pLower,kLQ1D));
433 // Do Interpolation exept for underflow and overflow
434 if(refLower && refUpper){
435 Double_t probLower = refLower->GetBinContent(refLower->GetXaxis()->FindBin(dEdx[0]));
436 Double_t probUpper = refUpper->GetBinContent(refUpper->GetXaxis()->FindBin(dEdx[0]));
437
438 probLayer = probLower + (probUpper - probLower)/(pUpper-pLower) * (plocal - pLower);
439 } else if(refLower){
440 // underflow
441 probLayer = refLower->GetBinContent(refLower->GetXaxis()->FindBin(dEdx[0]));
442 } else if(refUpper){
443 // overflow
444 probLayer = refUpper->GetBinContent(refUpper->GetXaxis()->FindBin(dEdx[0]));
445 } else {
446 AliError("No references available");
447 }
f2762b1c 448 AliDebug(1, Form("Eval 1D dEdx %f Probability %e", dEdx[0],probLayer));
db0e2c5f 449 }
450 break;
451 default:
452 break;
239fe91c 453 }
454 return probLayer;
455 */
456
ffb1ee30 457}
458
459//____________________________________________________________
460void AliTRDPIDResponse::SetOwner(){
e0de37e9 461 //
462 // Make Deep Copy of the Reference Histograms
463 //
db0e2c5f 464 if(!fkPIDResponseObject || IsOwner()) return;
465 const AliTRDPIDResponseObject *tmp = fkPIDResponseObject;
466 fkPIDResponseObject = dynamic_cast<const AliTRDPIDResponseObject *>(tmp->Clone());
467 SetBit(kIsOwner, kTRUE);
ffb1ee30 468}
469
470//____________________________________________________________
bd58d4b9 471Bool_t AliTRDPIDResponse::CookdEdx(Int_t nSlice, const Double_t * const in, Double_t *out,ETRDPIDMethod PIDmethod) const
ffb1ee30 472{
f2762b1c 473 //
474 // Recalculate dE/dx
475 //
bd58d4b9 476 switch(PIDmethod){
e0de37e9 477 case kNN: // NN
db0e2c5f 478 break;
479 case kLQ2D: // 2D LQ
480 out[0]=0;
481 out[1]=0;
482 for(Int_t islice = 0; islice < nSlice; islice++){
239fe91c 483 if(in[islice]<=0){out[0]=0;out[1]=0;return kFALSE;} // Require that all slices are filled
db0e2c5f 484 if(islice<fkPIDResponseObject->GetNSlicesQ0())out[0]+= in[islice];
485 else out[1]+= in[islice];
486 }
239fe91c 487 // normalize signal to number of slices
488 out[0]*=1./Double_t(fkPIDResponseObject->GetNSlicesQ0());
489 out[1]*=1./Double_t(nSlice-fkPIDResponseObject->GetNSlicesQ0());
f2762b1c 490 if(out[0] < 1e-6) return kFALSE;
491 AliDebug(3,Form("CookdEdx Q0 %f Q1 %f",out[0],out[1]));
db0e2c5f 492 break;
493 case kLQ1D: // 1D LQ
494 out[0]= 0.;
495 for(Int_t islice = 0; islice < nSlice; islice++)
496 if(in[islice] > 0) out[0] += in[islice] * fGainNormalisationFactor; // Protect against negative values for slices having no dE/dx information
239fe91c 497 out[0]*=1./Double_t(nSlice);
db0e2c5f 498 if(out[0] < 1e-6) return kFALSE;
f2762b1c 499 AliDebug(3,Form("CookdEdx dEdx %f",out[0]));
db0e2c5f 500 break;
501
e0de37e9 502 default:
db0e2c5f 503 return kFALSE;
e0de37e9 504 }
505 return kTRUE;
ffb1ee30 506}
507
ea235c90 508//____________________________________________________________
bd58d4b9 509Bool_t AliTRDPIDResponse::IdentifiedAsElectron(Int_t nTracklets, const Double_t *like, Double_t p, Double_t level,Double_t centrality,ETRDPIDMethod PIDmethod) const {
db0e2c5f 510 //
511 // Check whether particle is identified as electron assuming a certain electron efficiency level
512 // Only electron and pion hypothesis is taken into account
513 //
514 // Inputs:
515 // Number of tracklets
516 // Likelihood values
517 // Momentum
518 // Electron efficiency level
519 //
520 // If the function fails when the params are not accessible, the function returns true
521 //
522 if(!fkPIDResponseObject){
31746593 523 AliDebug(3,"No PID Param object available");
ea235c90 524 return kTRUE;
525 }
526 Double_t probEle = like[AliPID::kElectron]/(like[AliPID::kElectron] + like[AliPID::kPion]);
ce487a7f 527 Double_t params[4];
bd58d4b9 528 if(!fkPIDResponseObject->GetThresholdParameters(nTracklets, level, params,centrality,PIDmethod)){
ea235c90 529 AliError("No Params found for the given configuration");
530 return kTRUE;
531 }
ce487a7f 532 Double_t threshold = 1. - params[0] - params[1] * p - params[2] * TMath::Exp(-params[3] * p);
ea235c90 533 if(probEle > TMath::Max(TMath::Min(threshold, 0.99), 0.2)) return kTRUE; // truncate the threshold upperwards to 0.999 and lowerwards to 0.2 and exclude unphysical values
534 return kFALSE;
535}
536
f2762b1c 537//____________________________________________________________
538Bool_t AliTRDPIDResponse::SetPIDResponseObject(const AliTRDPIDResponseObject * obj){
539
540 fkPIDResponseObject = obj;
541 if((AliLog::GetDebugLevel("",IsA()->GetName()))>0)fkPIDResponseObject->Print("");
542 return kTRUE;
543}
9c499471 544
545
546//____________________________________________________________
547Bool_t AliTRDPIDResponse::SetdEdxParams(const AliTRDdEdxParams * par)
548{
549 fkTRDdEdxParams = par;
550 return kTRUE;
551}