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 **************************************************************************/
16 //_________________________________________________________________________
17 // Class for PID selection with calorimeters
18 // The Output of the main method GetIdentifiedParticleType is a PDG number identifying the cluster,
19 // being kPhoton, kElectron, kPi0 ... as defined in the header file
20 // - GetIdentifiedParticleType(const AliVCluster * cluster)
21 // Assignes a PID tag to the cluster, right now there is the possibility to : use bayesian weights from reco,
22 // recalculate them (EMCAL) or use other procedures not used in reco.
23 // In order to recalculate Bayesian, it is necessary to load the EMCALUtils library
24 // and do SwitchOnBayesianRecalculation().
25 // To change the PID parameters from Low to High like the ones by default, use the constructor
27 // where flux is AliCaloPID::kLow or AliCaloPID::kHigh
28 // If it is necessary to change the parameters use the constructor
29 // AliCaloPID(AliEMCALPIDUtils *utils) and set the parameters before.
31 // - GetGetIdentifiedParticleTypeFromBayesian(const Double_t * pid, const Float_t energy)
32 // Reads the PID weights array of the ESDs and depending on its magnitude identifies the particle,
33 // executed when bayesian is ON by GetIdentifiedParticleType(const AliVCluster * cluster)
34 // - SetPIDBits: Simple PID, depending on the thresholds fLOCut fTOFCut and even the
35 // result of the PID bayesian a different PID bit is set.
37 // - IsTrackMatched(): Independent method that needs to be combined with GetIdentifiedParticleType to know if the cluster was matched
39 //*-- Author: Gustavo Conesa (INFN-LNF)
40 //////////////////////////////////////////////////////////////////////////////
43 // --- ROOT system ---
48 // ---- ANALYSIS system ----
49 #include "AliCaloPID.h"
50 #include "AliAODCaloCluster.h"
51 #include "AliVCaloCells.h"
52 #include "AliVTrack.h"
53 #include "AliAODPWG4Particle.h"
54 #include "AliCalorimeterUtils.h"
55 #include "AliVEvent.h"
58 #include "AliEMCALPIDUtils.h"
63 //________________________
64 AliCaloPID::AliCaloPID() :
65 TObject(), fDebug(-1), fParticleFlux(kLow),
67 fEMCALPIDUtils(), fUseBayesianWeights(kFALSE), fRecalculateBayesian(kFALSE),
68 fEMCALPhotonWeight(0.), fEMCALPi0Weight(0.),
69 fEMCALElectronWeight(0.), fEMCALChargeWeight(0.), fEMCALNeutralWeight(0.),
70 fPHOSPhotonWeight(0.), fPHOSPi0Weight(0.),
71 fPHOSElectronWeight(0.), fPHOSChargeWeight(0.) , fPHOSNeutralWeight(0.),
72 fPHOSWeightFormula(0), fPHOSPhotonWeightFormula(0), fPHOSPi0WeightFormula(0),
73 fPHOSPhotonWeightFormulaExpression(""),
74 fPHOSPi0WeightFormulaExpression(""),
76 fEMCALL0CutMax(100.), fEMCALL0CutMin(0),
77 fEMCALDEtaCut(2000.), fEMCALDPhiCut(2000.),
79 fPHOSDispersionCut(1000), fPHOSRCut(1000),
81 fDoClusterSplitting(kFALSE),
82 fUseSimpleMassCut(kFALSE),
83 fUseSimpleM02Cut(kFALSE),
84 fUseSplitAsyCut(kFALSE),
85 fUseSplitSSCut(kTRUE),
86 fSplitM02MaxCut(0), fSplitM02MinCut(0), fSplitMinNCells(0),
87 fMassEtaMin(0), fMassEtaMax(0),
88 fMassPi0Min(0), fMassPi0Max(0),
89 fMassPhoMin(0), fMassPhoMax(0),
90 fM02MaxParamShiftNLMN(0),
91 fSplitWidthSigma(0), fMassShiftHighECell(0)
95 //Initialize parameters
99 //________________________________________
100 AliCaloPID::AliCaloPID(const Int_t flux) :
101 TObject(), fDebug(-1), fParticleFlux(flux),
103 fEMCALPIDUtils(), fUseBayesianWeights(kFALSE), fRecalculateBayesian(kFALSE),
104 fEMCALPhotonWeight(0.), fEMCALPi0Weight(0.),
105 fEMCALElectronWeight(0.), fEMCALChargeWeight(0.), fEMCALNeutralWeight(0.),
106 fPHOSPhotonWeight(0.), fPHOSPi0Weight(0.),
107 fPHOSElectronWeight(0.), fPHOSChargeWeight(0.) , fPHOSNeutralWeight(0.),
108 fPHOSWeightFormula(0), fPHOSPhotonWeightFormula(0), fPHOSPi0WeightFormula(0),
109 fPHOSPhotonWeightFormulaExpression(""),
110 fPHOSPi0WeightFormulaExpression(""),
112 fEMCALL0CutMax(100.), fEMCALL0CutMin(0),
113 fEMCALDEtaCut(2000.), fEMCALDPhiCut(2000.),
115 fPHOSDispersionCut(1000), fPHOSRCut(1000),
117 fDoClusterSplitting(kFALSE),
118 fUseSimpleMassCut(kFALSE),
119 fUseSimpleM02Cut(kFALSE),
120 fUseSplitAsyCut(kFALSE),
121 fUseSplitSSCut(kTRUE),
122 fSplitM02MaxCut(0), fSplitM02MinCut(0), fSplitMinNCells(0),
123 fMassEtaMin(0), fMassEtaMax(0),
124 fMassPi0Min(0), fMassPi0Max(0),
125 fMassPhoMin(0), fMassPhoMax(0),
126 fM02MaxParamShiftNLMN(0),
127 fSplitWidthSigma(0), fMassShiftHighECell(0)
131 //Initialize parameters
136 //_______________________________________________
137 AliCaloPID::AliCaloPID(const TNamed * emcalpid) :
138 TObject(), fDebug(-1), fParticleFlux(kLow),
140 fEMCALPIDUtils((AliEMCALPIDUtils*)emcalpid),
141 fUseBayesianWeights(kFALSE), fRecalculateBayesian(kFALSE),
142 fEMCALPhotonWeight(0.), fEMCALPi0Weight(0.),
143 fEMCALElectronWeight(0.), fEMCALChargeWeight(0.), fEMCALNeutralWeight(0.),
144 fPHOSPhotonWeight(0.), fPHOSPi0Weight(0.),
145 fPHOSElectronWeight(0.), fPHOSChargeWeight(0.) , fPHOSNeutralWeight(0.),
146 fPHOSWeightFormula(0), fPHOSPhotonWeightFormula(0), fPHOSPi0WeightFormula(0),
147 fPHOSPhotonWeightFormulaExpression(""),
148 fPHOSPi0WeightFormulaExpression(""),
150 fEMCALL0CutMax(100.), fEMCALL0CutMin(0),
151 fEMCALDEtaCut(2000.), fEMCALDPhiCut(2000.),
153 fPHOSDispersionCut(1000), fPHOSRCut(1000),
155 fDoClusterSplitting(kFALSE),
156 fUseSimpleMassCut(kFALSE),
157 fUseSimpleM02Cut(kFALSE),
158 fUseSplitAsyCut(kFALSE),
159 fUseSplitSSCut(kTRUE),
160 fSplitM02MaxCut(0), fSplitM02MinCut(0), fSplitMinNCells(0),
161 fMassEtaMin(0), fMassEtaMax(0),
162 fMassPi0Min(0), fMassPi0Max(0),
163 fMassPhoMin(0), fMassPhoMax(0),
164 fM02MaxParamShiftNLMN(0),
165 fSplitWidthSigma(0), fMassShiftHighECell(0)
170 //Initialize parameters
174 //_______________________
175 AliCaloPID::~AliCaloPID()
179 delete fPHOSPhotonWeightFormula ;
180 delete fPHOSPi0WeightFormula ;
181 delete fEMCALPIDUtils ;
185 //_______________________________
186 void AliCaloPID::InitParameters()
188 //Initialize the parameters of the PID.
191 fEMCALPhotonWeight = 0.6 ;
192 fEMCALPi0Weight = 0.6 ;
193 fEMCALElectronWeight = 0.6 ;
194 fEMCALChargeWeight = 0.6 ;
195 fEMCALNeutralWeight = 0.6 ;
197 fPHOSPhotonWeight = 0.6 ;
198 fPHOSPi0Weight = 0.6 ;
199 fPHOSElectronWeight = 0.6 ;
200 fPHOSChargeWeight = 0.6 ;
201 fPHOSNeutralWeight = 0.6 ;
203 //Formula to set the PID weight threshold for photon or pi0
204 fPHOSWeightFormula = kFALSE;
205 fPHOSPhotonWeightFormulaExpression = "0.98*(x<40)+ 0.68*(x>=100)+(x>=40 && x<100)*(0.98+x*(6e-3)-x*x*(2e-04)+x*x*x*(1.1e-06))";
206 fPHOSPi0WeightFormulaExpression = "0.98*(x<65)+ 0.915*(x>=100)+(x>=65 && x-x*(1.95e-3)-x*x*(4.31e-05)+x*x*x*(3.61e-07))" ;
208 if(fRecalculateBayesian){
209 if(fParticleFlux == kLow){
210 printf("AliCaloPID::Init() - SetLOWFluxParam\n");
211 fEMCALPIDUtils->SetLowFluxParam() ;
213 else if (fParticleFlux == kHigh){
214 printf("AliCaloPID::Init() - SetHIGHFluxParam\n");
215 fEMCALPIDUtils->SetHighFluxParam() ;
219 //PID recalculation, not bayesian
222 fEMCALL0CutMax = 0.3 ;
223 fEMCALL0CutMin = 0.01;
225 fEMCALDPhiCut = 0.05; // Same cut as in AliEMCALRecoUtils
226 fEMCALDEtaCut = 0.025;// Same cut as in AliEMCALRecoUtils
228 // PHOS / EMCAL, not used
233 fPHOSDispersionCut = 2.5;
237 fSplitM02MinCut = 0.3 ;
238 fSplitM02MaxCut = 5 ;
239 fSplitMinNCells = 4 ;
250 fMassPi0Param[0][0] = 0 ; // Constant term on mass dependence
251 fMassPi0Param[0][1] = 0 ; // slope term on mass dependence
252 fMassPi0Param[0][2] = 0 ; // E function change
253 fMassPi0Param[0][3] = 0.044 ; // constant term on mass dependence
254 fMassPi0Param[0][4] = 0.0049; // slope term on mass dependence
255 fMassPi0Param[0][5] = 0.070 ; // Absolute low mass cut
257 fMassPi0Param[1][0] = 0.115 ; // Constant term below 21 GeV
258 fMassPi0Param[1][1] = 0.00096; // slope term below 21 GeV
259 fMassPi0Param[1][2] = 21 ; // E function change
260 fMassPi0Param[1][3] = 0.10 ; // constant term on mass dependence
261 fMassPi0Param[1][4] = 0.0017; // slope term on mass dependence
262 fMassPi0Param[1][5] = 0.070 ; // Absolute low mass cut
264 fWidthPi0Param[0][0] = 0.012 ; // Constant term on width dependence
265 fWidthPi0Param[0][1] = 0.0 ; // Slope term on width dependence
266 fWidthPi0Param[0][2] = 19 ; // E function change
267 fWidthPi0Param[0][3] = 0.0012; // Constant term on width dependence
268 fWidthPi0Param[0][4] = 0.0006; // Slope term on width dependence
269 fWidthPi0Param[0][5] = 0.0 ; // xx term
271 fWidthPi0Param[1][0] = 0.009 ; // Constant term on width dependence
272 fWidthPi0Param[1][1] = 0.000 ; // Slope term on width dependence
273 fWidthPi0Param[1][2] = 10 ; // E function change
274 fWidthPi0Param[1][3] = 0.0023 ; // Constant term on width dependence
275 fWidthPi0Param[1][4] = 0.00067; // Slope term on width dependence
276 fWidthPi0Param[1][5] = 0.000 ;// xx term
278 fMassShiftHighECell = 0; // Shift of cuts in case of higher energy threshold in cells, 5 MeV when Ecell>150 MeV
280 //TF1 *lM02MinNLM1 = new TF1("M02MinNLM1","exp(2.135-0.245*x)",6,13.6);
281 fM02MinParam[0][0] = 2.135 ;
282 fM02MinParam[0][1] =-0.245 ;
283 fM02MinParam[0][2] = 0.0 ;
284 fM02MinParam[0][3] = 0.0 ;
285 fM02MinParam[0][4] = 0.0 ;
287 // Same as NLM=1 for NLM=2
288 fM02MinParam[1][0] = 2.135 ;
289 fM02MinParam[1][1] =-0.245 ;
290 fM02MinParam[1][2] = 0.0 ;
291 fM02MinParam[1][3] = 0.0 ;
292 fM02MinParam[1][4] = 0.0 ;
294 //TF1 *lM02MaxNLM1 = new TF1("M02MaxNLM1","exp(0.0662-0.0201*x)-0.0955+0.00186*x[0]+9.91/x[0]",6,100);
295 fM02MaxParam[0][0] = 0.0662 ;
296 fM02MaxParam[0][1] =-0.0201 ;
297 fM02MaxParam[0][2] =-0.0955 ;
298 fM02MaxParam[0][3] = 0.00186;
299 fM02MaxParam[0][4] = 9.91 ;
301 //TF1 *lM02MaxNLM2 = new TF1("M02MaxNLM2","exp(0.353-0.0264*x)-0.524+0.00559*x[0]+21.9/x[0]",6,100);
302 fM02MaxParam[1][0] = 0.353 ;
303 fM02MaxParam[1][1] =-0.0264 ;
304 fM02MaxParam[1][2] =-0.524 ;
305 fM02MaxParam[1][3] = 0.00559;
306 fM02MaxParam[1][4] = 21.9 ;
308 fM02MaxParamShiftNLMN = 0.75;
310 //TF1 *lAsyNLM1 = new TF1("lAsyNLM1","0.96-879/(x*x*x)",5,100);
311 fAsyMinParam[0][0] = 0.96 ;
312 fAsyMinParam[0][1] = 0 ;
313 fAsyMinParam[0][2] =-879 ;
314 fAsyMinParam[0][3] = 0.96 ; // Absolute max
316 //TF1 *lAsyNLM2 = new TF1("lAsyNLM2","0.95+0.0015*x-233/(x*x*x)",5,100);
317 fAsyMinParam[1][0] = 0.95 ;
318 fAsyMinParam[1][1] = 0.0015;
319 fAsyMinParam[1][2] =-233 ;
320 fAsyMinParam[1][3] = 1.0 ; // Absolute max
322 fSplitEFracMin[0] = 0.0 ; // 0.96
323 fSplitEFracMin[1] = 0.0 ; // 0.96
324 fSplitEFracMin[2] = 0.0 ; // 0.7
326 fSubClusterEMin[0] = 0.0; // 3 GeV
327 fSubClusterEMin[1] = 0.0; // 1 GeV
328 fSubClusterEMin[2] = 0.0; // 1 GeV
331 fSplitWidthSigma = 3. ;
336 //_____________________________________________________________________________________________________
337 Bool_t AliCaloPID::IsInPi0SplitAsymmetryRange(const Float_t energy, const Float_t asy, const Int_t nlm)
339 // Select the appropriate mass range for pi0 selection in splitting method
340 // No used yet in splitting ID decision
342 if(!fUseSplitAsyCut) return kTRUE ;
344 Float_t abasy = TMath::Abs(asy);
347 if(nlm > 2) inlm=1; // only 2 cases defined nlm=1 and nlm>=2
349 // Get the parametrized min cut of asymmetry for NLM=2 up to 11 GeV
351 Float_t cut = fAsyMinParam[inlm][0] + fAsyMinParam[inlm][1]*energy + fAsyMinParam[inlm][2]/energy/energy/energy ;
353 // In any case and beyond validity energy range of the function,
354 // the parameter cannot be smaller than 1
355 if( cut > fAsyMinParam[inlm][3] ) cut = fAsyMinParam[inlm][3];
357 //printf("energy %2.2f - nlm: %d (%d)- p0 %f, p1 %f, p2 %f, p3 %f ; cut: %2.2f\n",energy,nlm,inlm,
358 // fAsyMinParam[inlm][0],fAsyMinParam[inlm][1],fAsyMinParam[inlm][2],fAsyMinParam[inlm][3],cut);
360 if(abasy < cut) return kTRUE;
365 //_________________________________________________________________________________________________
366 Bool_t AliCaloPID::IsInPi0SplitMassRange(const Float_t energy, const Float_t mass, const Int_t nlm)
368 // Select the appropriate mass range for pi0 selection in splitting method
370 if(fUseSimpleMassCut)
372 if(mass < fMassPi0Max && mass > fMassPi0Min) return kTRUE;
376 // Get the selected mean value as reference for the mass
378 if(nlm > 2) inlm=1; // only 2 cases defined nlm=1 and nlm>=2
380 Float_t meanMass = energy * fMassPi0Param[inlm][1] + fMassPi0Param[inlm][0];
381 if(energy > fMassPi0Param[inlm][2]) meanMass = energy * fMassPi0Param[inlm][4] + fMassPi0Param[inlm][3];
383 // In case of higher energy cell cut than 50 MeV, smaller mean mass 0-5 MeV, not really necessary
384 meanMass -= fMassShiftHighECell;
386 // Get the parametrized width of the mass
387 Float_t width = 0.009;
388 if (energy > 8 && energy < fWidthPi0Param[inlm][2])
389 width = energy * fWidthPi0Param[inlm][1] + fWidthPi0Param[inlm][0];
390 else if( energy > fWidthPi0Param[inlm][2])
391 width = energy * energy * fWidthPi0Param[inlm][5] + energy * fWidthPi0Param[inlm][4] + fWidthPi0Param[inlm][3];
393 // Calculate the 2 sigma cut
394 Float_t minMass = meanMass-fSplitWidthSigma*width;
395 Float_t maxMass = meanMass+fSplitWidthSigma*width;
397 // In case of low energy, hard cut to avoid conversions
398 if(energy < 10 && minMass < fMassPi0Param[inlm][5] ) minMass = fMassPi0Param[inlm][5];
400 //printf("E %2.2f, mass %1.1f, nlm %d: sigma %1.1f width %3.1f, mean Mass %3.0f, minMass %3.0f, maxMass %3.0f\n ",
401 // energy,mass *1000, inlm, fSplitWidthSigma, width*1000, meanMass*1000,minMass*1000,maxMass*1000);
403 if(mass < maxMass && mass > minMass) return kTRUE;
408 //________________________________________________
409 Bool_t AliCaloPID::IsInM02Range(const Float_t m02)
411 // Select the appropriate m02 range, fix cut, not E dependent
413 Float_t minCut = fSplitM02MinCut;
414 Float_t maxCut = fSplitM02MaxCut;
416 if(m02 < maxCut && m02 > minCut) return kTRUE;
421 //___________________________________________________________________________________________
422 Bool_t AliCaloPID::IsInPi0M02Range(const Float_t energy, const Float_t m02, const Int_t nlm)
424 // Select the appropriate m02 range in splitting method for pi0
426 if(!fUseSplitSSCut) return kTRUE ;
428 //First check the absolute minimum and maximum
429 if(!IsInM02Range(m02)) return kFALSE ;
431 //If requested, check the E dependent cuts
432 else if(!fUseSimpleM02Cut)
435 if(nlm > 2) inlm=1; // only 2 cases defined nlm=1 and nlm>=2
437 Float_t minCut = fSplitM02MinCut;
438 Float_t maxCut = fSplitM02MaxCut;
440 //e^{a+bx} + c + dx + e/x
441 if(energy > 1) minCut = TMath::Exp( fM02MinParam[inlm][0] + fM02MinParam[inlm][1]*energy ) +
442 fM02MinParam[inlm][2] + fM02MinParam[inlm][3]*energy + fM02MinParam[inlm][4]/energy;
444 if(energy > 1) maxCut = TMath::Exp( fM02MaxParam[inlm][0] + fM02MaxParam[inlm][1]*energy ) +
445 fM02MaxParam[inlm][2] + fM02MaxParam[inlm][3]*energy + fM02MaxParam[inlm][4]/energy;
447 // In any case and beyond validity energy range of the function,
448 // the parameter cannot be smaller than 0.3 or larger than 4-5
449 if( minCut < fSplitM02MinCut) minCut = fSplitM02MinCut;
450 if( maxCut > fSplitM02MaxCut) maxCut = fSplitM02MaxCut;
451 if( nlm > 2 ) maxCut+=fM02MaxParamShiftNLMN;
453 //if(energy > 7) printf("\t \t E %2.2f, nlm %d, m02 %2.2f, minM02 %2.2f, maxM02 %2.2f\n",energy, nlm, m02,minCut,maxCut);
455 if(m02 < maxCut && m02 > minCut) return kTRUE;
465 //_____________________________________________________________________________________________
466 Bool_t AliCaloPID::IsInEtaM02Range(const Float_t energy, const Float_t m02, const Int_t nlm)
468 // Select the appropriate m02 range in splitting method to select eta's
469 // Use same parametrization as pi0, just shift the distributions (to be tuned)
471 if(!fUseSplitSSCut) return kTRUE ;
473 //First check the absolute minimum and maximum
474 if(!IsInM02Range(m02)) return kFALSE ;
476 //DO NOT USE, study parametrization
478 //If requested, check the E dependent cuts
479 else if(!fUseSimpleM02Cut)
482 if(nlm > 2) inlm=1; // only 2 cases defined nlm=1 and nlm>=2
484 Float_t minCut = fSplitM02MinCut;
485 Float_t maxCut = fSplitM02MaxCut;
487 Float_t shiftE = energy-20; // to be tuned
488 if(nlm==1) shiftE=energy-28;
490 //e^{a+bx} + c + dx + e/x
491 if(shiftE > 1) minCut = TMath::Exp( fM02MinParam[inlm][0] + fM02MinParam[inlm][1]*shiftE ) +
492 fM02MinParam[inlm][2] + fM02MinParam[inlm][3]*shiftE + fM02MinParam[inlm][4]/shiftE;
494 // In any case the parameter cannot be smaller than 0.3
495 if( minCut < fSplitM02MinCut) minCut = fSplitM02MinCut;
497 shiftE = energy+20; // to be tuned
499 if(shiftE > 1) maxCut = 1 + TMath::Exp( fM02MaxParam[inlm][0] + fM02MaxParam[inlm][1]*shiftE ) +
500 fM02MaxParam[inlm][2] + fM02MaxParam[inlm][3]*shiftE + fM02MaxParam[inlm][4]/shiftE;
502 // In any case the parameter cannot be smaller than 4-5
503 if( maxCut > fSplitM02MaxCut) maxCut = fSplitM02MaxCut;
504 if( nlm > 2 ) maxCut+=fM02MaxParamShiftNLMN;
506 //if(energy>6)printf("\t \t E %2.2f, nlm %d, m02 %2.2f, minM02 %2.2f, maxM02 %2.2f\n",energy, nlm, m02,minCut,maxCut);
508 if(m02 < maxCut && m02 > minCut) return kTRUE;
517 //_____________________________________________________________________________________________
518 Bool_t AliCaloPID::IsInConM02Range(const Float_t energy, const Float_t m02, const Int_t nlm)
520 // Select the appropriate m02 range in splitting method for converted photons
521 // Just min limit for pi0s is max for conversion.
523 if(!fUseSplitSSCut) return kTRUE ;
525 Float_t minCut = 0.1;
526 Float_t maxCut = fSplitM02MinCut;
528 if(!fUseSimpleM02Cut)
531 if(nlm > 2) inlm=1; // only 2 cases defined nlm=1 and nlm>=2
533 //e^{a+bx} + c + dx + e/x
534 if(energy > 1) maxCut = TMath::Exp( fM02MinParam[inlm][0] + fM02MinParam[inlm][1]*energy ) +
535 fM02MinParam[inlm][2] + fM02MinParam[inlm][3]*energy + fM02MinParam[inlm][4]/energy;
537 if( maxCut < fSplitM02MinCut) maxCut = fSplitM02MinCut;
540 if(m02 < maxCut && m02 > minCut) return kTRUE;
545 //______________________________________________
546 AliEMCALPIDUtils *AliCaloPID::GetEMCALPIDUtils()
548 // return pointer to AliEMCALPIDUtils, create it if needed
550 if(!fEMCALPIDUtils) fEMCALPIDUtils = new AliEMCALPIDUtils ;
551 return fEMCALPIDUtils ;
556 //______________________________________________________________________
557 Int_t AliCaloPID::GetIdentifiedParticleType(const AliVCluster * cluster)
559 // Returns a PDG number corresponding to the likely ID of the cluster
561 Float_t energy = cluster->E();
562 Float_t lambda0 = cluster->GetM02();
563 Float_t lambda1 = cluster->GetM20();
565 // ---------------------
566 // Use bayesian approach
567 // ---------------------
569 if(fUseBayesianWeights)
571 Double_t weights[AliPID::kSPECIESCN];
573 if(cluster->IsEMCAL() && fRecalculateBayesian)
575 fEMCALPIDUtils->ComputePID(energy, lambda0);
576 for(Int_t i = 0; i < AliPID::kSPECIESCN; i++) weights[i] = fEMCALPIDUtils->GetPIDFinal(i);
580 for(Int_t i = 0; i < AliPID::kSPECIESCN; i++) weights[i] = cluster->GetPID()[i];
583 if(fDebug > 0) PrintClusterPIDWeights(weights);
585 return GetIdentifiedParticleTypeFromBayesWeights(cluster->IsEMCAL(), weights, energy);
588 // -------------------------------------------------------
589 // Calculate PID SS from data, do not use bayesian weights
590 // -------------------------------------------------------
592 if(fDebug > 0) printf("AliCaloPID::GetIdentifiedParticleType: EMCAL %d?, E %3.2f, l0 %3.2f, l1 %3.2f, disp %3.2f, tof %1.11f, distCPV %3.2f, distToBC %1.1f, NMax %d\n",
593 cluster->IsEMCAL(),energy,lambda0,cluster->GetM20(),cluster->GetDispersion(),cluster->GetTOF(),
594 cluster->GetEmcCpvDistance(), cluster->GetDistanceToBadChannel(),cluster->GetNExMax());
596 if(cluster->IsEMCAL())
598 if(fDebug > 0) printf("AliCaloPID::GetIdentifiedParticleType() - EMCAL SS %f <%f < %f?\n",fEMCALL0CutMin, lambda0, fEMCALL0CutMax);
600 if(lambda0 < fEMCALL0CutMax && lambda0 > fEMCALL0CutMin) return kPhoton ;
601 else return kNeutralUnknown ;
605 if(TestPHOSDispersion(energy,lambda0,lambda1) < fPHOSDispersionCut) return kPhoton;
606 else return kNeutralUnknown;
611 //_______________________________________________________________________________
612 Int_t AliCaloPID::GetIdentifiedParticleTypeFromBayesWeights(const Bool_t isEMCAL,
613 const Double_t * pid,
614 const Float_t energy)
616 //Return most probable identity of the particle after bayesian weights calculated in reconstruction
620 AliFatal("pid pointer not initialized!!!");
621 return kNeutralUnknown; // not needed, added to content coverity
624 Float_t wPh = fPHOSPhotonWeight ;
625 Float_t wPi0 = fPHOSPi0Weight ;
626 Float_t wE = fPHOSElectronWeight ;
627 Float_t wCh = fPHOSChargeWeight ;
628 Float_t wNe = fPHOSNeutralWeight ;
630 if(!isEMCAL && fPHOSWeightFormula){
631 wPh = GetPHOSPhotonWeightFormula()->Eval(energy) ;
632 wPi0 = GetPHOSPi0WeightFormula() ->Eval(energy);
636 wPh = fEMCALPhotonWeight ;
637 wPi0 = fEMCALPi0Weight ;
638 wE = fEMCALElectronWeight ;
639 wCh = fEMCALChargeWeight ;
640 wNe = fEMCALNeutralWeight ;
643 if(fDebug > 0) PrintClusterPIDWeights(pid);
645 Int_t pdg = kNeutralUnknown ;
646 Float_t chargedHadronWeight = pid[AliVCluster::kProton]+pid[AliVCluster::kKaon]+
647 pid[AliVCluster::kPion]+pid[AliVCluster::kMuon];
648 Float_t neutralHadronWeight = pid[AliVCluster::kNeutron]+pid[AliVCluster::kKaon0];
649 Float_t allChargedWeight = pid[AliVCluster::kElectron]+pid[AliVCluster::kEleCon]+ chargedHadronWeight;
650 Float_t allNeutralWeight = pid[AliVCluster::kPhoton]+pid[AliVCluster::kPi0]+ neutralHadronWeight;
652 //Select most probable ID
655 if(pid[AliVCluster::kPhoton] > wPh) pdg = kPhoton ;
656 else if(pid[AliVCluster::kPi0] > wPi0) pdg = kPi0 ;
657 else if(pid[AliVCluster::kElectron] > wE) pdg = kElectron ;
658 else if(pid[AliVCluster::kEleCon] > wE) pdg = kEleCon ;
659 else if(chargedHadronWeight > wCh) pdg = kChargedHadron ;
660 else if(neutralHadronWeight > wNe) pdg = kNeutralHadron ;
661 else if(allChargedWeight > allNeutralWeight)
662 pdg = kChargedUnknown ;
664 pdg = kNeutralUnknown ;
668 if(pid[AliVCluster::kPhoton] > wPh) pdg = kPhoton ;
669 else if(pid[AliVCluster::kElectron] > wE) pdg = kElectron ;
670 else if(pid[AliVCluster::kPhoton]+pid[AliVCluster::kElectron] > wPh) pdg = kPhoton ; //temporal sollution until track matching for electrons is considered
671 else if(pid[AliVCluster::kPi0] > wPi0) pdg = kPi0 ;
672 else if(chargedHadronWeight + neutralHadronWeight > wCh) pdg = kChargedHadron ;
673 else if(neutralHadronWeight + chargedHadronWeight > wNe) pdg = kNeutralHadron ;
674 else pdg = kNeutralUnknown ;
677 if(fDebug > 0)printf("AliCaloPID::GetIdentifiedParticleType:Final Pdg: %d, cluster energy %2.2f \n", pdg,energy);
683 //____________________________________________________________________________________________________
684 Int_t AliCaloPID::GetIdentifiedParticleTypeFromClusterSplitting(AliVCluster* cluster,
685 AliVCaloCells* cells,
686 AliCalorimeterUtils * caloutils,
689 Double_t & mass, Double_t & angle,
690 TLorentzVector & l1, TLorentzVector & l2,
691 Int_t & absId1, Int_t & absId2,
692 Float_t & distbad1, Float_t & distbad2,
693 Bool_t & fidcut1, Bool_t & fidcut2 )
695 // Split the cluster in 2, do invariant mass, get the mass and decide
696 // if this is a photon, pi0, eta, ...
698 Float_t eClus = cluster->E();
699 Float_t m02 = cluster->GetM02();
700 const Int_t nc = cluster->GetNCells();
702 Float_t maxEList [nc];
707 //If too low number of cells, skip it
708 if ( nc < fSplitMinNCells) return kNeutralUnknown ;
710 if(fDebug > 0) printf("\t pass nCells cut\n");
712 // Get Number of local maxima
713 nMax = caloutils->GetNumberOfLocalMaxima(cluster, cells, absIdList, maxEList) ;
715 if(fDebug > 0) printf("AliCaloPID::GetIdentifiedParticleTypeFromClusterSplitting() - Cluster : E %1.1f, M02 %1.2f, NLM %d, N Cells %d\n",
718 //---------------------------------------------------------------------
719 // Get the 2 max indeces and do inv mass
720 //---------------------------------------------------------------------
722 TString calorimeter = "EMCAL";
723 if(cluster->IsPHOS()) calorimeter = "PHOS";
727 absId1 = absIdList[0];
728 absId2 = absIdList[1];
731 Float_t en1 = cells->GetCellAmplitude(absId1);
732 caloutils->RecalibrateCellAmplitude(en1,calorimeter,absId1);
733 Float_t en2 = cells->GetCellAmplitude(absId2);
734 caloutils->RecalibrateCellAmplitude(en2,calorimeter,absId2);
737 absId2 = absIdList[0];
738 absId1 = absIdList[1];
744 absId1 = absIdList[0];
746 //Find second highest energy cell
749 for(Int_t iDigit = 0 ; iDigit < cluster->GetNCells() ; iDigit++)
751 Int_t absId = cluster->GetCellsAbsId()[iDigit];
752 if( absId == absId1 ) continue ;
753 Float_t endig = cells->GetCellAmplitude(absId);
754 caloutils->RecalibrateCellAmplitude(endig,calorimeter,absId);
764 // loop on maxima, find 2 highest
768 for(Int_t iDigit = 0 ; iDigit < nMax ; iDigit++)
770 Float_t endig = maxEList[iDigit];
774 absId1 = absIdList[iDigit];
776 }// first maxima loop
780 for(Int_t iDigit = 0 ; iDigit < nMax ; iDigit++)
782 if(absIdList[iDigit]==absId1) continue;
783 Float_t endig = maxEList[iDigit];
787 absId2 = absIdList[iDigit];
789 }// second maxima loop
791 } // n local maxima > 2
793 if(absId2<0 || absId1<0)
795 if(fDebug > 0) printf("AliCaloPID::GetIdentifiedParticleTypeFromClusterSplitting() - Bad index for local maxima : N max %d, i1 %d, i2 %d, cluster E %2.2f, ncells %d, m02 %2.2f\n",
796 nMax,absId1,absId2,eClus,nc,m02);
797 return kNeutralUnknown ;
800 //---------------------------------------------------------------------
801 // Split the cluster energy in 2, around the highest 2 local maxima
802 //---------------------------------------------------------------------
804 AliAODCaloCluster cluster1(0, 0,NULL,0.,NULL,NULL,1,0);
805 AliAODCaloCluster cluster2(1, 0,NULL,0.,NULL,NULL,1,0);
807 caloutils->SplitEnergy(absId1,absId2,cluster, cells, &cluster1, &cluster2,nMax); /*absIdList, maxEList,*/
809 fidcut1 = caloutils->GetEMCALRecoUtils()->CheckCellFiducialRegion(caloutils->GetEMCALGeometry(), &cluster1,cells);
810 fidcut2 = caloutils->GetEMCALRecoUtils()->CheckCellFiducialRegion(caloutils->GetEMCALGeometry(), &cluster2,cells);
812 caloutils->GetEMCALRecoUtils()->RecalculateClusterDistanceToBadChannel(caloutils->GetEMCALGeometry(),cells,&cluster1);
813 caloutils->GetEMCALRecoUtils()->RecalculateClusterDistanceToBadChannel(caloutils->GetEMCALGeometry(),cells,&cluster2);
815 distbad1 = cluster1.GetDistanceToBadChannel();
816 distbad2 = cluster2.GetDistanceToBadChannel();
817 // if(!fidcut2 || !fidcut1 || distbad1 < 2 || distbad2 < 2)
818 // printf("*** Dist to bad channel cl %f, cl1 %f, cl2 %f; fid cut cl %d, cl1 %d, cl2 %d \n",
819 // cluster->GetDistanceToBadChannel(),distbad1,distbad2,
820 // caloutils->GetEMCALRecoUtils()->CheckCellFiducialRegion(caloutils->GetEMCALGeometry(), cluster,cells),fidcut1,fidcut2);
822 cluster1.GetMomentum(l1,vertex);
823 cluster2.GetMomentum(l2,vertex);
826 angle = l2.Angle(l1.Vect());
827 Float_t e1 = cluster1.E();
828 Float_t e2 = cluster2.E();
830 // Consider clusters with splitted energy not too different to original cluster energy
831 Float_t splitFracCut = 0;
832 if(nMax < 3) splitFracCut = fSplitEFracMin[nMax-1];
833 else splitFracCut = fSplitEFracMin[2];
834 if((e1+e2)/eClus < splitFracCut) return kNeutralUnknown ;
836 if(fDebug > 0) printf("\t pass Split E frac cut\n");
838 // Consider sub-clusters with minimum energy
839 Float_t minECut = fSubClusterEMin[2];
840 if (nMax == 2) minECut = fSubClusterEMin[1];
841 else if(nMax == 1) minECut = fSubClusterEMin[0];
842 if(e1 < minECut || e2 < minECut)
844 //printf("Reject: e1 %2.1f, e2 %2.1f, cut %2.1f\n",e1,e2,minECut);
845 return kNeutralUnknown ;
848 if(fDebug > 0) printf("\t pass min sub-cluster E cut\n");
850 // Asymmetry of cluster
852 if(e1+e2 > 0) asy = (e1-e2) / (e1+e2);
854 if( !IsInPi0SplitAsymmetryRange(eClus,asy,nMax) ) return kNeutralUnknown ;
857 if (fDebug>0) printf("\t pass asymmetry cut\n");
859 Bool_t pi0OK = kFALSE;
860 Bool_t etaOK = kFALSE;
861 Bool_t conOK = kFALSE;
863 //If too small or big M02, skip it
864 if (IsInPi0M02Range(eClus,m02,nMax)) pi0OK = kTRUE;
865 else if(IsInEtaM02Range(eClus,m02,nMax)) etaOK = kTRUE;
866 else if(IsInConM02Range(eClus,m02,nMax)) conOK = kTRUE;
868 Float_t energy = eClus;
869 if(nMax > 2) energy = e1+e2; // In case of NLM>2 use mass cut for NLM=2 but for the split sum not the cluster energy that is not the pi0 E.
871 // Check the mass, and set an ID to the splitted cluster
872 if ( conOK && mass < fMassPhoMax && mass > fMassPhoMin ) { if(fDebug > 0) printf("\t Split Conv \n"); return kPhoton ; }
873 else if( etaOK && mass < fMassEtaMax && mass > fMassEtaMin ) { if(fDebug > 0) printf("\t Split Eta \n"); return kEta ; }
874 else if( pi0OK && IsInPi0SplitMassRange(energy,mass,nMax)) { if(fDebug > 0) printf("\t Split Pi0 \n"); return kPi0 ; }
875 else return kNeutralUnknown ;
879 //_________________________________________
880 TString AliCaloPID::GetPIDParametersList()
882 //Put data member values in string to keep in output container
884 TString parList ; //this will be list of parameters used for this analysis.
885 const Int_t buffersize = 255;
886 char onePar[buffersize] ;
887 snprintf(onePar,buffersize,"--- AliCaloPID ---\n") ;
889 if(fUseBayesianWeights){
890 snprintf(onePar,buffersize,"fEMCALPhotonWeight =%2.2f (EMCAL bayesian weight for photons)\n",fEMCALPhotonWeight) ;
892 snprintf(onePar,buffersize,"fEMCALPi0Weight =%2.2f (EMCAL bayesian weight for pi0)\n",fEMCALPi0Weight) ;
894 snprintf(onePar,buffersize,"fEMCALElectronWeight =%2.2f(EMCAL bayesian weight for electrons)\n",fEMCALElectronWeight) ;
896 snprintf(onePar,buffersize,"fEMCALChargeWeight =%2.2f (EMCAL bayesian weight for charged hadrons)\n",fEMCALChargeWeight) ;
898 snprintf(onePar,buffersize,"fEMCALNeutralWeight =%2.2f (EMCAL bayesian weight for neutral hadrons)\n",fEMCALNeutralWeight) ;
900 snprintf(onePar,buffersize,"fPHOSPhotonWeight =%2.2f (PHOS bayesian weight for photons)\n",fPHOSPhotonWeight) ;
902 snprintf(onePar,buffersize,"fPHOSPi0Weight =%2.2f (PHOS bayesian weight for pi0)\n",fPHOSPi0Weight) ;
904 snprintf(onePar,buffersize,"fPHOSElectronWeight =%2.2f(PHOS bayesian weight for electrons)\n",fPHOSElectronWeight) ;
906 snprintf(onePar,buffersize,"fPHOSChargeWeight =%2.2f (PHOS bayesian weight for charged hadrons)\n",fPHOSChargeWeight) ;
908 snprintf(onePar,buffersize,"fPHOSNeutralWeight =%2.2f (PHOS bayesian weight for neutral hadrons)\n",fPHOSNeutralWeight) ;
911 if(fPHOSWeightFormula){
912 snprintf(onePar,buffersize,"PHOS Photon Weight Formula: %s\n",fPHOSPhotonWeightFormulaExpression.Data() ) ;
914 snprintf(onePar,buffersize,"PHOS Pi0 Weight Formula: %s\n",fPHOSPi0WeightFormulaExpression.Data() ) ;
919 snprintf(onePar,buffersize,"EMCAL: fEMCALL0CutMin =%2.2f, fEMCALL0CutMax =%2.2f (Cut on Shower Shape) \n",fEMCALL0CutMin, fEMCALL0CutMax) ;
921 snprintf(onePar,buffersize,"EMCAL: fEMCALDEtaCut =%2.2f, fEMCALDPhiCut =%2.2f (Cut on track matching) \n",fEMCALDEtaCut, fEMCALDPhiCut) ;
923 snprintf(onePar,buffersize,"fTOFCut =%e (Cut on TOF, used in PID evaluation) \n",fTOFCut) ;
925 snprintf(onePar,buffersize,"fPHOSRCut =%2.2f, fPHOSDispersionCut =%2.2f (Cut on Shower Shape and CPV) \n",fPHOSRCut,fPHOSDispersionCut) ;
930 if(fDoClusterSplitting)
932 snprintf(onePar,buffersize,"%2.2f< M02 < %2.2f \n", fSplitM02MinCut, fSplitM02MaxCut) ;
934 snprintf(onePar,buffersize,"fMinNCells =%d \n", fSplitMinNCells) ;
936 snprintf(onePar,buffersize,"pi0 : %2.1f < m <%2.1f\n", fMassPi0Min,fMassPi0Max);
938 snprintf(onePar,buffersize,"eta : %2.1f < m <%2.1f\n", fMassEtaMin,fMassEtaMax);
940 snprintf(onePar,buffersize,"conv: %2.1f < m <%2.1f\n", fMassPhoMin,fMassPhoMax);
948 //________________________________________________
949 void AliCaloPID::Print(const Option_t * opt) const
952 //Print some relevant parameters set for the analysis
956 printf("***** Print: %s %s ******\n", GetName(), GetTitle() ) ;
958 if(fUseBayesianWeights)
960 printf("PHOS PID weight , photon %0.2f, pi0 %0.2f, e %0.2f, charge %0.2f, neutral %0.2f \n",
961 fPHOSPhotonWeight, fPHOSPi0Weight,
962 fPHOSElectronWeight, fPHOSChargeWeight, fPHOSNeutralWeight) ;
963 printf("EMCAL PID weight, photon %0.2f, pi0 %0.2f, e %0.2f, charge %0.2f, neutral %0.2f\n",
964 fEMCALPhotonWeight, fEMCALPi0Weight,
965 fEMCALElectronWeight, fEMCALChargeWeight, fEMCALNeutralWeight) ;
967 printf("PHOS Parametrized weight on? = %d\n", fPHOSWeightFormula) ;
968 if(fPHOSWeightFormula)
970 printf("Photon weight formula = %s\n", fPHOSPhotonWeightFormulaExpression.Data());
971 printf("Pi0 weight formula = %s\n", fPHOSPi0WeightFormulaExpression .Data());
973 if(fRecalculateBayesian) printf(" Recalculate bayesian with Particle Flux? = %d\n",fParticleFlux);
977 printf("TOF cut = %e\n", fTOFCut);
978 printf("EMCAL Lambda0 cut min = %2.2f; max = %2.2f\n", fEMCALL0CutMin,fEMCALL0CutMax);
979 printf("EMCAL cluster-track dEta < %2.3f; dPhi < %2.3f\n", fEMCALDEtaCut, fEMCALDPhiCut);
980 printf("PHOS Treac matching cut =%2.2f, Dispersion Cut =%2.2f \n",fPHOSRCut, fPHOSDispersionCut) ;
984 if(fDoClusterSplitting)
986 printf("Min. N Cells =%d \n", fSplitMinNCells) ;
987 printf("%2.2f < lambda_0^2 <%2.2f \n",fSplitM02MinCut,fSplitM02MaxCut);
988 printf("pi0 : %2.2f<m<%2.2f \n", fMassPi0Min,fMassPi0Max);
989 printf("eta : %2.2f<m<%2.2f \n", fMassEtaMin,fMassEtaMax);
990 printf("phot: %2.2f<m<%2.2f \n", fMassPhoMin,fMassPhoMax);
997 //_________________________________________________________________
998 void AliCaloPID::PrintClusterPIDWeights(const Double_t * pid) const
1000 // print PID of cluster, (AliVCluster*)cluster->GetPID()
1002 printf("AliCaloPID::PrintClusterPIDWeights() \n \t ph %0.2f, pi0 %0.2f, el %0.2f, conv el %0.2f, \n \t \
1003 pion %0.2f, kaon %0.2f, proton %0.2f , neutron %0.2f, kaon %0.2f \n",
1004 pid[AliVCluster::kPhoton], pid[AliVCluster::kPi0],
1005 pid[AliVCluster::kElectron], pid[AliVCluster::kEleCon],
1006 pid[AliVCluster::kPion], pid[AliVCluster::kKaon],
1007 pid[AliVCluster::kProton],
1008 pid[AliVCluster::kNeutron], pid[AliVCluster::kKaon0]);
1012 //___________________________________________________________________________
1013 void AliCaloPID::SetPIDBits(AliVCluster * cluster,
1014 AliAODPWG4Particle * ph, AliCalorimeterUtils* cu,
1017 //Set Bits for PID selection
1019 //Dispersion/lambdas
1020 //Double_t disp= cluster->GetDispersion() ;
1021 Double_t l1 = cluster->GetM20() ;
1022 Double_t l0 = cluster->GetM02() ;
1023 Bool_t isDispOK = kTRUE ;
1024 if(cluster->IsPHOS()){
1025 if(TestPHOSDispersion(ph->Pt(),l0,l1) < fPHOSDispersionCut) isDispOK = kTRUE;
1026 else isDispOK = kFALSE;
1030 if(l0 > fEMCALL0CutMin && l0 < fEMCALL0CutMax) isDispOK = kTRUE;
1034 ph->SetDispBit(isDispOK) ;
1037 Double_t tof=cluster->GetTOF() ;
1038 ph->SetTOFBit(TMath::Abs(tof)<fTOFCut) ;
1041 Bool_t isNeutral = IsTrackMatched(cluster,cu,event);
1043 ph->SetChargedBit(isNeutral);
1046 ph->SetIdentifiedParticleType(GetIdentifiedParticleType(cluster));
1050 printf("AliCaloPID::SetPIDBits: TOF %e, Lambda0 %2.2f, Lambda1 %2.2f\n",tof , l0, l1);
1051 printf("AliCaloPID::SetPIDBits: pdg %d, bits: TOF %d, Dispersion %d, Charge %d\n",
1052 ph->GetIdentifiedParticleType(), ph->GetTOFBit() , ph->GetDispBit() , ph->GetChargedBit());
1056 //_________________________________________________________
1057 Bool_t AliCaloPID::IsTrackMatched(AliVCluster* cluster,
1058 AliCalorimeterUtils * cu,
1059 AliVEvent* event) const
1061 //Check if there is any track attached to this cluster
1063 Int_t nMatches = cluster->GetNTracksMatched();
1064 AliVTrack * track = 0;
1069 //In case of ESDs, by default without match one entry with negative index, no match, reject.
1070 if(!strcmp("AliESDCaloCluster",Form("%s",cluster->ClassName())))
1072 Int_t iESDtrack = cluster->GetTrackMatchedIndex();
1073 if(iESDtrack >= 0) track = dynamic_cast<AliVTrack*> (event->GetTrack(iESDtrack));
1078 if(fDebug > 0) printf("AliCaloPID::IsTrackMatched() - Null matched track in ESD when index is OK!\n");
1083 track = dynamic_cast<AliVTrack*> (cluster->GetTrackMatched(0));
1086 if(fDebug > 0) printf("AliCaloPID::IsTrackMatched() - Null matched track in AOD!\n");
1091 Float_t dZ = cluster->GetTrackDz();
1092 Float_t dR = cluster->GetTrackDx();
1094 // if track matching was recalculated
1095 if(cluster->IsEMCAL() && cu && cu->IsRecalculationOfClusterTrackMatchingOn())
1097 dR = 2000., dZ = 2000.;
1098 cu->GetEMCALRecoUtils()->GetMatchedResiduals(cluster->GetID(),dZ,dR);
1101 if(cluster->IsPHOS())
1103 track->GetPxPyPz(p) ;
1104 TLorentzVector trackmom(p[0],p[1],p[2],0);
1105 Int_t charge = track->Charge();
1106 Double_t mf = event->GetMagneticField();
1107 if(TestPHOSChargedVeto(dR, dZ, trackmom.Pt(), charge, mf ) < fPHOSRCut) return kTRUE;
1114 printf("AliCaloPID::IsTrackMatched - EMCAL dR %f < %f, dZ %f < %f \n",dR, fEMCALDPhiCut, dZ, fEMCALDEtaCut);
1116 if(TMath::Abs(dR) < fEMCALDPhiCut &&
1117 TMath::Abs(dZ) < fEMCALDEtaCut) return kTRUE;
1123 } // more than 1 match, at least one track in array
1128 //___________________________________________________________________________________________________
1129 Float_t AliCaloPID::TestPHOSDispersion(const Double_t pt, const Double_t l1, const Double_t l2) const
1131 //Check if cluster photon-like. Uses photon cluster parameterization in real pp data
1132 //Returns distance in sigmas. Recommended cut 2.5
1134 Double_t l2Mean = 1.53126+9.50835e+06/(1.+1.08728e+07*pt+1.73420e+06*pt*pt) ;
1135 Double_t l1Mean = 1.12365+0.123770*TMath::Exp(-pt*0.246551)+5.30000e-03*pt ;
1136 Double_t l2Sigma = 6.48260e-02+7.60261e+10/(1.+1.53012e+11*pt+5.01265e+05*pt*pt)+9.00000e-03*pt;
1137 Double_t l1Sigma = 4.44719e-04+6.99839e-01/(1.+1.22497e+00*pt+6.78604e-07*pt*pt)+9.00000e-03*pt;
1138 Double_t c =-0.35-0.550*TMath::Exp(-0.390730*pt) ;
1139 Double_t r2 = 0.5* (l1-l1Mean)*(l1-l1Mean)/l1Sigma/l1Sigma +
1140 0.5* (l2-l2Mean)*(l2-l2Mean)/l2Sigma/l2Sigma +
1141 0.5*c*(l1-l1Mean)*(l2-l2Mean)/l1Sigma/l2Sigma ;
1143 if(fDebug > 0) printf("AliCaloPID::TestPHOSDispersion() - PHOS SS R %f < %f?\n", TMath::Sqrt(r2), fPHOSDispersionCut);
1145 return TMath::Sqrt(r2) ;
1149 //_______________________________________________________________________________________________
1150 Float_t AliCaloPID::TestPHOSChargedVeto(const Double_t dx, const Double_t dz, const Double_t pt,
1151 const Int_t charge, const Double_t mf) const
1153 //Checks distance to the closest track. Takes into account
1154 //non-perpendicular incidence of tracks.
1155 //returns distance in sigmas. Recommended cut: 2.
1156 //Requires (sign) of magnetic filed. onc can find it for example as following
1158 // AliESDEvent *event = dynamic_cast<AliESDEvent*>(InputEvent());
1160 // mf = event->GetMagneticField(); //Positive for ++ and negative for --
1163 Double_t meanX = 0.;
1164 Double_t meanZ = 0.;
1165 Double_t sx = TMath::Min(5.4,2.59719e+02*TMath::Exp(-pt/1.02053e-01)+
1166 6.58365e-01*5.91917e-01*5.91917e-01/((pt-9.61306e-01)*(pt-9.61306e-01)+5.91917e-01*5.91917e-01)+
1168 Double_t sz = TMath::Min(2.75,4.90341e+02*1.91456e-02*1.91456e-02/(pt*pt+1.91456e-02*1.91456e-02)+
1171 if(mf<0.){ //field --
1174 meanX = TMath::Min(7.3, 3.89994*1.20679 *1.20679 /(pt*pt+1.20679*1.20679)+
1175 0.249029+2.49088e+07*TMath::Exp(-pt*3.33650e+01)) ;
1177 meanX =-TMath::Min(7.7, 3.86040*0.912499*0.912499/(pt*pt+0.912499*0.912499)+
1178 1.23114 +4.48277e+05*TMath::Exp(-pt*2.57070e+01)) ;
1183 meanX =-TMath::Min(8.0,3.86040*1.31357*1.31357/(pt*pt+1.31357*1.31357)+
1184 0.880579+7.56199e+06*TMath::Exp(-pt*3.08451e+01)) ;
1186 meanX = TMath::Min(6.85, 3.89994*1.16240*1.16240/(pt*pt+1.16240*1.16240)-
1187 0.120787+2.20275e+05*TMath::Exp(-pt*2.40913e+01)) ;
1190 Double_t rz = (dz-meanZ)/sz ;
1191 Double_t rx = (dx-meanX)/sx ;
1194 printf("AliCaloPID::TestPHOSDispersion() - PHOS Matching R %f < %f\n",TMath::Sqrt(rx*rx+rz*rz), fPHOSRCut);
1196 return TMath::Sqrt(rx*rx+rz*rz) ;