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 /* $Id: AliEMCALRecoUtils.cxx 33808 2009-07-15 09:48:08Z gconesab $ */
18 ///////////////////////////////////////////////////////////////////////////////
20 // Class AliEMCALRecoUtils
21 // Some utilities to recalculate the cluster position or energy linearity
24 // Author: Gustavo Conesa (LPSC- Grenoble)
25 // Track matching part: Rongrong Ma (Yale)
27 ///////////////////////////////////////////////////////////////////////////////
30 // standard C++ includes
31 //#include <Riostream.h>
34 #include <TGeoManager.h>
35 #include <TGeoMatrix.h>
40 #include <TObjArray.h>
43 #include "AliVCluster.h"
44 #include "AliVCaloCells.h"
45 #include "AliVEvent.h"
48 #include "AliESDEvent.h"
49 #include "AliAODEvent.h"
50 #include "AliESDtrack.h"
51 #include "AliAODTrack.h"
52 #include "AliExternalTrackParam.h"
53 #include "AliESDfriendTrack.h"
54 #include "AliTrackerBase.h"
57 #include "AliEMCALRecoUtils.h"
58 #include "AliEMCALGeometry.h"
59 #include "AliEMCALTrack.h"
60 #include "AliEMCALCalibTimeDepCorrection.h" // Run dependent
61 #include "AliEMCALPIDUtils.h"
63 ClassImp(AliEMCALRecoUtils)
65 //______________________________________________
66 AliEMCALRecoUtils::AliEMCALRecoUtils():
67 fParticleType(kPhoton), fPosAlgo(kUnchanged), fW0(4.),
68 fNonLinearityFunction(kNoCorrection), fNonLinearThreshold(30),
69 fSmearClusterEnergy(kFALSE), fRandom(),
70 fCellsRecalibrated(kFALSE), fRecalibration(kFALSE), fEMCALRecalibrationFactors(),
71 fTimeRecalibration(kFALSE), fEMCALTimeRecalibrationFactors(),
72 fUseRunCorrectionFactors(kFALSE), fRunCorrectionFactorsSet(kFALSE),
73 fRemoveBadChannels(kFALSE), fRecalDistToBadChannels(kFALSE), fEMCALBadChannelMap(),
74 fNCellsFromEMCALBorder(0), fNoEMCALBorderAtEta0(kTRUE),
75 fRejectExoticCluster(kFALSE), fPIDUtils(), fAODFilterMask(32),
76 fMatchedTrackIndex(0x0), fMatchedClusterIndex(0x0),
77 fResidualEta(0x0), fResidualPhi(0x0), fCutEtaPhiSum(kTRUE), fCutEtaPhiSeparate(kFALSE),
78 fCutR(0.1), fCutEta(0.02), fCutPhi(0.04),
79 fMass(0.139), fStep(50),
80 fTrackCutsType(kTPCOnlyCut), fCutMinTrackPt(0), fCutMinNClusterTPC(-1),
81 fCutMinNClusterITS(-1), fCutMaxChi2PerClusterTPC(1e10), fCutMaxChi2PerClusterITS(1e10),
82 fCutRequireTPCRefit(kFALSE), fCutRequireITSRefit(kFALSE), fCutAcceptKinkDaughters(kFALSE),
83 fCutMaxDCAToVertexXY(1e10), fCutMaxDCAToVertexZ(1e10), fCutDCAToVertex2D(kFALSE)
87 // Initialize all constant values which have to be used
88 // during Reco algorithm execution
91 //Misalignment matrices
92 for(Int_t i = 0; i < 15 ; i++) {
93 fMisalTransShift[i] = 0.;
94 fMisalRotShift[i] = 0.;
98 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = 0.;
100 //For kBeamTestCorrected case, but default is no correction
101 fNonLinearityParams[0] = 0.99078;
102 fNonLinearityParams[1] = 0.161499;
103 fNonLinearityParams[2] = 0.655166;
104 fNonLinearityParams[3] = 0.134101;
105 fNonLinearityParams[4] = 163.282;
106 fNonLinearityParams[5] = 23.6904;
107 fNonLinearityParams[6] = 0.978;
109 //For kPi0GammaGamma case
110 //fNonLinearityParams[0] = 0.1457/0.1349766/1.038;
111 //fNonLinearityParams[1] = -0.02024/0.1349766/1.038;
112 //fNonLinearityParams[2] = 1.046;
114 //Cluster energy smearing
115 fSmearClusterEnergy = kFALSE;
116 fSmearClusterParam[0] = 0.07; // * sqrt E term
117 fSmearClusterParam[1] = 0.00; // * E term
118 fSmearClusterParam[2] = 0.00; // constant
121 fMatchedTrackIndex = new TArrayI();
122 fMatchedClusterIndex = new TArrayI();
123 fResidualPhi = new TArrayF();
124 fResidualEta = new TArrayF();
125 fPIDUtils = new AliEMCALPIDUtils();
130 //______________________________________________________________________
131 AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco)
133 fParticleType(reco.fParticleType), fPosAlgo(reco.fPosAlgo), fW0(reco.fW0),
134 fNonLinearityFunction(reco.fNonLinearityFunction), fNonLinearThreshold(reco.fNonLinearThreshold),
135 fSmearClusterEnergy(reco.fSmearClusterEnergy), fRandom(),
136 fCellsRecalibrated(reco.fCellsRecalibrated),
137 fRecalibration(reco.fRecalibration), fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
138 fTimeRecalibration(reco.fTimeRecalibration), fEMCALTimeRecalibrationFactors(reco.fEMCALTimeRecalibrationFactors),
139 fUseRunCorrectionFactors(reco.fUseRunCorrectionFactors), fRunCorrectionFactorsSet(reco.fRunCorrectionFactorsSet),
140 fRemoveBadChannels(reco.fRemoveBadChannels), fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
141 fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
142 fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder), fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
143 fRejectExoticCluster(reco.fRejectExoticCluster), fPIDUtils(reco.fPIDUtils),
144 fAODFilterMask(reco.fAODFilterMask),
145 fMatchedTrackIndex( reco.fMatchedTrackIndex? new TArrayI(*reco.fMatchedTrackIndex):0x0),
146 fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
147 fResidualEta( reco.fResidualEta? new TArrayF(*reco.fResidualEta):0x0),
148 fResidualPhi( reco.fResidualPhi? new TArrayF(*reco.fResidualPhi):0x0),
149 fCutEtaPhiSum(reco.fCutEtaPhiSum), fCutEtaPhiSeparate(reco.fCutEtaPhiSeparate),
150 fCutR(reco.fCutR), fCutEta(reco.fCutEta), fCutPhi(reco.fCutPhi),
151 fMass(reco.fMass), fStep(reco.fStep),
152 fTrackCutsType(reco.fTrackCutsType), fCutMinTrackPt(reco.fCutMinTrackPt),
153 fCutMinNClusterTPC(reco.fCutMinNClusterTPC), fCutMinNClusterITS(reco.fCutMinNClusterITS),
154 fCutMaxChi2PerClusterTPC(reco.fCutMaxChi2PerClusterTPC), fCutMaxChi2PerClusterITS(reco.fCutMaxChi2PerClusterITS),
155 fCutRequireTPCRefit(reco.fCutRequireTPCRefit), fCutRequireITSRefit(reco.fCutRequireITSRefit),
156 fCutAcceptKinkDaughters(reco.fCutAcceptKinkDaughters), fCutMaxDCAToVertexXY(reco.fCutMaxDCAToVertexXY),
157 fCutMaxDCAToVertexZ(reco.fCutMaxDCAToVertexZ), fCutDCAToVertex2D(reco.fCutDCAToVertex2D)
161 for(Int_t i = 0; i < 15 ; i++) { fMisalRotShift[i] = reco.fMisalRotShift[i] ;
162 fMisalTransShift[i] = reco.fMisalTransShift[i] ; }
163 for(Int_t i = 0; i < 7 ; i++) { fNonLinearityParams[i] = reco.fNonLinearityParams[i] ; }
164 for(Int_t i = 0; i < 3 ; i++) { fSmearClusterParam[i] = reco.fSmearClusterParam[i] ; }
169 //______________________________________________________________________
170 AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco)
172 //Assignment operator
174 if(this == &reco)return *this;
175 ((TNamed *)this)->operator=(reco);
177 for(Int_t i = 0; i < 15 ; i++) { fMisalTransShift[i] = reco.fMisalTransShift[i] ;
178 fMisalRotShift[i] = reco.fMisalRotShift[i] ; }
179 for(Int_t i = 0; i < 7 ; i++) { fNonLinearityParams[i] = reco.fNonLinearityParams[i] ; }
180 for(Int_t i = 0; i < 3 ; i++) { fSmearClusterParam[i] = reco.fSmearClusterParam[i] ; }
182 fParticleType = reco.fParticleType;
183 fPosAlgo = reco.fPosAlgo;
186 fNonLinearityFunction = reco.fNonLinearityFunction;
187 fNonLinearThreshold = reco.fNonLinearThreshold;
188 fSmearClusterEnergy = reco.fSmearClusterEnergy;
190 fCellsRecalibrated = reco.fCellsRecalibrated;
191 fRecalibration = reco.fRecalibration;
192 fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
194 fTimeRecalibration = reco.fTimeRecalibration;
195 fEMCALTimeRecalibrationFactors = reco.fEMCALTimeRecalibrationFactors;
197 fUseRunCorrectionFactors = reco.fUseRunCorrectionFactors;
198 fRunCorrectionFactorsSet = reco.fRunCorrectionFactorsSet;
200 fRemoveBadChannels = reco.fRemoveBadChannels;
201 fRecalDistToBadChannels = reco.fRecalDistToBadChannels;
202 fEMCALBadChannelMap = reco.fEMCALBadChannelMap;
204 fNCellsFromEMCALBorder = reco.fNCellsFromEMCALBorder;
205 fNoEMCALBorderAtEta0 = reco.fNoEMCALBorderAtEta0;
206 fRejectExoticCluster = reco.fRejectExoticCluster;
208 fPIDUtils = reco.fPIDUtils;
210 fAODFilterMask = reco.fAODFilterMask;
212 fCutEtaPhiSum = reco.fCutEtaPhiSum;
213 fCutEtaPhiSeparate = reco.fCutEtaPhiSeparate;
215 fCutEta = reco.fCutEta;
216 fCutPhi = reco.fCutPhi;
219 fRejectExoticCluster = reco.fRejectExoticCluster;
221 fTrackCutsType = reco.fTrackCutsType;
222 fCutMinTrackPt = reco.fCutMinTrackPt;
223 fCutMinNClusterTPC = reco.fCutMinNClusterTPC;
224 fCutMinNClusterITS = reco.fCutMinNClusterITS;
225 fCutMaxChi2PerClusterTPC = reco.fCutMaxChi2PerClusterTPC;
226 fCutMaxChi2PerClusterITS = reco.fCutMaxChi2PerClusterITS;
227 fCutRequireTPCRefit = reco.fCutRequireTPCRefit;
228 fCutRequireITSRefit = reco.fCutRequireITSRefit;
229 fCutAcceptKinkDaughters = reco.fCutAcceptKinkDaughters;
230 fCutMaxDCAToVertexXY = reco.fCutMaxDCAToVertexXY;
231 fCutMaxDCAToVertexZ = reco.fCutMaxDCAToVertexZ;
232 fCutDCAToVertex2D = reco.fCutDCAToVertex2D;
234 if(reco.fResidualEta){
235 // assign or copy construct
237 *fResidualEta = *reco.fResidualEta;
239 else fResidualEta = new TArrayF(*reco.fResidualEta);
242 if(fResidualEta)delete fResidualEta;
246 if(reco.fResidualPhi){
247 // assign or copy construct
249 *fResidualPhi = *reco.fResidualPhi;
251 else fResidualPhi = new TArrayF(*reco.fResidualPhi);
254 if(fResidualPhi)delete fResidualPhi;
258 if(reco.fMatchedTrackIndex){
259 // assign or copy construct
260 if(fMatchedTrackIndex){
261 *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
263 else fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
266 if(fMatchedTrackIndex)delete fMatchedTrackIndex;
267 fMatchedTrackIndex = 0;
270 if(reco.fMatchedClusterIndex){
271 // assign or copy construct
272 if(fMatchedClusterIndex){
273 *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
275 else fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
278 if(fMatchedClusterIndex)delete fMatchedClusterIndex;
279 fMatchedClusterIndex = 0;
286 //__________________________________________________
287 AliEMCALRecoUtils::~AliEMCALRecoUtils()
291 if(fEMCALRecalibrationFactors) {
292 fEMCALRecalibrationFactors->Clear();
293 delete fEMCALRecalibrationFactors;
296 if(fEMCALTimeRecalibrationFactors) {
297 fEMCALTimeRecalibrationFactors->Clear();
298 delete fEMCALTimeRecalibrationFactors;
301 if(fEMCALBadChannelMap) {
302 fEMCALBadChannelMap->Clear();
303 delete fEMCALBadChannelMap;
306 delete fMatchedTrackIndex ;
307 delete fMatchedClusterIndex ;
308 delete fResidualEta ;
309 delete fResidualPhi ;
315 //_______________________________________________________________
316 Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(AliEMCALGeometry* geom, AliVCluster* cluster, AliVCaloCells* cells)
318 // Given the list of AbsId of the cluster, get the maximum cell and
319 // check if there are fNCellsFromBorder from the calorimeter border
322 AliInfo("Cluster pointer null!");
326 //If the distance to the border is 0 or negative just exit accept all clusters
327 if(cells->GetType()==AliVCaloCells::kEMCALCell && fNCellsFromEMCALBorder <= 0 ) return kTRUE;
329 Int_t absIdMax = -1, iSM =-1, ieta = -1, iphi = -1;
330 Bool_t shared = kFALSE;
331 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSM, ieta, iphi, shared);
333 AliDebug(2,Form("Cluster Max AbsId %d, Cell Energy %2.2f, Cluster Energy %2.2f, Ncells from border %d, EMCAL eta=0 %d\n",
334 absIdMax, cells->GetCellAmplitude(absIdMax), cluster->E(), fNCellsFromEMCALBorder, fNoEMCALBorderAtEta0));
336 if(absIdMax==-1) return kFALSE;
338 //Check if the cell is close to the borders:
339 Bool_t okrow = kFALSE;
340 Bool_t okcol = kFALSE;
342 if(iSM < 0 || iphi < 0 || ieta < 0 ) {
343 AliFatal(Form("Negative value for super module: %d, or cell ieta: %d, or cell iphi: %d, check EMCAL geometry name\n",
349 if(iphi >= fNCellsFromEMCALBorder && iphi < 24-fNCellsFromEMCALBorder) okrow =kTRUE;
352 if(iphi >= fNCellsFromEMCALBorder && iphi < 12-fNCellsFromEMCALBorder) okrow =kTRUE;
356 if(!fNoEMCALBorderAtEta0){
357 if(ieta > fNCellsFromEMCALBorder && ieta < 48-fNCellsFromEMCALBorder) okcol =kTRUE;
361 if(ieta >= fNCellsFromEMCALBorder) okcol = kTRUE;
364 if(ieta < 48-fNCellsFromEMCALBorder) okcol = kTRUE;
368 AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d: column? %d, row? %d\nq",
369 fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
371 if (okcol && okrow) {
372 //printf("Accept\n");
376 //printf("Reject\n");
377 AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
384 //_________________________________________________________________________________________________________
385 Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(AliEMCALGeometry* geom, UShort_t* cellList, const Int_t nCells){
386 // Check that in the cluster cells, there is no bad channel of those stored
387 // in fEMCALBadChannelMap or fPHOSBadChannelMap
389 if(!fRemoveBadChannels) return kFALSE;
390 if(!fEMCALBadChannelMap) return kFALSE;
395 for(Int_t iCell = 0; iCell<nCells; iCell++){
397 //Get the column and row
398 Int_t iTower = -1, iIphi = -1, iIeta = -1;
399 geom->GetCellIndex(cellList[iCell],imod,iTower,iIphi,iIeta);
400 if(fEMCALBadChannelMap->GetEntries() <= imod) continue;
401 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
402 if(GetEMCALChannelStatus(imod, icol, irow)){
403 AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
407 }// cell cluster loop
413 //_________________________________________________
414 Bool_t AliEMCALRecoUtils::IsExoticCluster(AliVCluster *cluster) const {
415 // Check if the cluster has high energy but small number of cells
416 // The criteria comes from Gustavo's study
420 AliInfo("Cluster pointer null!");
424 Int_t nc = cluster->GetNCells() ;
426 if ( nc > 8 ) return kFALSE ; // Good cluster, needed for 3x3 clusterizer
427 else if ( nc < 1 + cluster->E()/3. ) return kTRUE ; // Bad cluster
428 else return kFALSE ; // Good cluster
432 //__________________________________________________
433 Float_t AliEMCALRecoUtils::SmearClusterEnergy(AliVCluster* cluster) {
435 //In case of MC analysis, smear energy to match resolution/calibration in real data
438 AliInfo("Cluster pointer null!");
442 Float_t energy = cluster->E() ;
443 Float_t rdmEnergy = energy ;
444 if(fSmearClusterEnergy){
445 rdmEnergy = fRandom.Gaus(energy,fSmearClusterParam[0] * TMath::Sqrt(energy) +
446 fSmearClusterParam[1] * energy +
447 fSmearClusterParam[2] );
448 AliDebug(2, Form("Energy: original %f, smeared %f\n", energy, rdmEnergy));
455 //__________________________________________________
456 Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster){
457 // Correct cluster energy from non linearity functions
460 AliInfo("Cluster pointer null!");
464 Float_t energy = cluster->E();
466 switch (fNonLinearityFunction) {
470 //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
471 //Double_t fNonLinearityParams[0] = 1.014;
472 //Double_t fNonLinearityParams[1] = -0.03329;
473 //Double_t fNonLinearityParams[2] = -0.3853;
474 //Double_t fNonLinearityParams[3] = 0.5423;
475 //Double_t fNonLinearityParams[4] = -0.4335;
476 energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
477 ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
478 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
484 //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
485 //Double_t fNonLinearityParams[0] = 1.04;
486 //Double_t fNonLinearityParams[1] = -0.1445;
487 //Double_t fNonLinearityParams[2] = 1.046;
488 energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
492 case kPi0GammaConversion:
494 //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
495 //fNonLinearityParams[0] = 0.139393/0.1349766;
496 //fNonLinearityParams[1] = 0.0566186;
497 //fNonLinearityParams[2] = 0.982133;
498 energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
505 //From beam test, Alexei's results, for different ZS thresholds
506 // th=30 MeV; th = 45 MeV; th = 75 MeV
507 //fNonLinearityParams[0] = 1.007; 1.003; 1.002
508 //fNonLinearityParams[1] = 0.894; 0.719; 0.797
509 //fNonLinearityParams[2] = 0.246; 0.334; 0.358
510 //Rescale the param[0] with 1.03
511 energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
516 case kBeamTestCorrected:
518 //From beam test, corrected for material between beam and EMCAL
519 //fNonLinearityParams[0] = 0.99078
520 //fNonLinearityParams[1] = 0.161499;
521 //fNonLinearityParams[2] = 0.655166;
522 //fNonLinearityParams[3] = 0.134101;
523 //fNonLinearityParams[4] = 163.282;
524 //fNonLinearityParams[5] = 23.6904;
525 //fNonLinearityParams[6] = 0.978;
526 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
532 AliDebug(2,"No correction on the energy\n");
540 //__________________________________________________
541 void AliEMCALRecoUtils::InitNonLinearityParam()
543 //Initialising Non Linearity Parameters
545 if(fNonLinearityFunction == kPi0MC)
547 fNonLinearityParams[0] = 1.014;
548 fNonLinearityParams[1] = -0.03329;
549 fNonLinearityParams[2] = -0.3853;
550 fNonLinearityParams[3] = 0.5423;
551 fNonLinearityParams[4] = -0.4335;
554 if(fNonLinearityFunction == kPi0GammaGamma)
556 fNonLinearityParams[0] = 1.04;
557 fNonLinearityParams[1] = -0.1445;
558 fNonLinearityParams[2] = 1.046;
561 if(fNonLinearityFunction == kPi0GammaConversion)
563 fNonLinearityParams[0] = 0.139393;
564 fNonLinearityParams[1] = 0.0566186;
565 fNonLinearityParams[2] = 0.982133;
568 if(fNonLinearityFunction == kBeamTest)
570 if(fNonLinearThreshold == 30)
572 fNonLinearityParams[0] = 1.007;
573 fNonLinearityParams[1] = 0.894;
574 fNonLinearityParams[2] = 0.246;
576 if(fNonLinearThreshold == 45)
578 fNonLinearityParams[0] = 1.003;
579 fNonLinearityParams[1] = 0.719;
580 fNonLinearityParams[2] = 0.334;
582 if(fNonLinearThreshold == 75)
584 fNonLinearityParams[0] = 1.002;
585 fNonLinearityParams[1] = 0.797;
586 fNonLinearityParams[2] = 0.358;
590 if(fNonLinearityFunction == kBeamTestCorrected)
592 fNonLinearityParams[0] = 0.99078;
593 fNonLinearityParams[1] = 0.161499;
594 fNonLinearityParams[2] = 0.655166;
595 fNonLinearityParams[3] = 0.134101;
596 fNonLinearityParams[4] = 163.282;
597 fNonLinearityParams[5] = 23.6904;
598 fNonLinearityParams[6] = 0.978;
602 //__________________________________________________
603 Float_t AliEMCALRecoUtils::GetDepth(const Float_t energy, const Int_t iParticle, const Int_t iSM) const
605 //Calculate shower depth for a given cluster energy and particle type
615 depth = x0 * (TMath::Log(energy*1000/ ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
619 depth = x0 * (TMath::Log(energy*1000/ ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
626 gGeoManager->cd("ALIC_1/XEN1_1");
627 TGeoNode *geoXEn1 = gGeoManager->GetCurrentNode();
628 TGeoNodeMatrix *geoSM = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
630 TGeoVolume *geoSMVol = geoSM->GetVolume();
631 TGeoShape *geoSMShape = geoSMVol->GetShape();
632 TGeoBBox *geoBox = dynamic_cast<TGeoBBox *>(geoSMShape);
633 if(geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
634 else AliFatal("Null GEANT box");
635 }else AliFatal("NULL GEANT node matrix");
638 depth = x0 * (TMath::Log(energy*1000 / ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
644 depth = x0 * (TMath::Log(energy*1000 / ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
651 //__________________________________________________
652 void AliEMCALRecoUtils::GetMaxEnergyCell(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu,
653 Int_t & absId, Int_t& iSupMod, Int_t& ieta, Int_t& iphi, Bool_t &shared)
655 //For a given CaloCluster gets the absId of the cell
656 //with maximum energy deposit.
659 Double_t eCell = -1.;
660 Float_t fraction = 1.;
661 Float_t recalFactor = 1.;
662 Int_t cellAbsId = -1 ;
670 AliInfo("Cluster pointer null!");
671 absId=-1; iSupMod0=-1, ieta = -1; iphi = -1; shared = -1;
675 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
676 cellAbsId = clu->GetCellAbsId(iDig);
677 fraction = clu->GetCellAmplitudeFraction(iDig);
678 //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
679 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
680 geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta);
681 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
682 if(iDig==0) iSupMod0=iSupMod;
683 else if(iSupMod0!=iSupMod) {
685 //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
687 if(IsRecalibrationOn()) {
688 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
690 eCell = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
691 //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
695 //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
699 //Get from the absid the supermodule, tower and eta/phi numbers
700 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
701 //Gives SuperModule and Tower numbers
702 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
703 iIphi, iIeta,iphi,ieta);
704 //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
705 //printf("Max end---\n");
709 //________________________________________________________________
710 void AliEMCALRecoUtils::InitEMCALRecalibrationFactors(){
711 //Init EMCAL recalibration factors
712 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
713 //In order to avoid rewriting the same histograms
714 Bool_t oldStatus = TH1::AddDirectoryStatus();
715 TH1::AddDirectory(kFALSE);
717 fEMCALRecalibrationFactors = new TObjArray(10);
718 for (int i = 0; i < 10; i++) fEMCALRecalibrationFactors->Add(new TH2F(Form("EMCALRecalFactors_SM%d",i),Form("EMCALRecalFactors_SM%d",i), 48, 0, 48, 24, 0, 24));
719 //Init the histograms with 1
720 for (Int_t sm = 0; sm < 10; sm++) {
721 for (Int_t i = 0; i < 48; i++) {
722 for (Int_t j = 0; j < 24; j++) {
723 SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
727 fEMCALRecalibrationFactors->SetOwner(kTRUE);
728 fEMCALRecalibrationFactors->Compress();
730 //In order to avoid rewriting the same histograms
731 TH1::AddDirectory(oldStatus);
734 //________________________________________________________________
735 void AliEMCALRecoUtils::InitEMCALTimeRecalibrationFactors(){
736 //Init EMCAL recalibration factors
737 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
738 //In order to avoid rewriting the same histograms
739 Bool_t oldStatus = TH1::AddDirectoryStatus();
740 TH1::AddDirectory(kFALSE);
742 fEMCALTimeRecalibrationFactors = new TObjArray(4);
743 for (int i = 0; i < 4; i++)
744 fEMCALTimeRecalibrationFactors->Add(new TH1F(Form("hAllTimeAvBC%d",i),
745 Form("hAllTimeAvBC%d",i),
746 48*24*10,0.,48*24*10) );
747 //Init the histograms with 1
748 for (Int_t bc = 0; bc < 4; bc++) {
749 for (Int_t i = 0; i < 48*24*10; i++)
750 SetEMCALChannelTimeRecalibrationFactor(bc,i,0.);
753 fEMCALTimeRecalibrationFactors->SetOwner(kTRUE);
754 fEMCALTimeRecalibrationFactors->Compress();
756 //In order to avoid rewriting the same histograms
757 TH1::AddDirectory(oldStatus);
760 //________________________________________________________________
761 void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap(){
762 //Init EMCAL bad channels map
763 AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
764 //In order to avoid rewriting the same histograms
765 Bool_t oldStatus = TH1::AddDirectoryStatus();
766 TH1::AddDirectory(kFALSE);
768 fEMCALBadChannelMap = new TObjArray(10);
769 //TH2F * hTemp = new TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
770 for (int i = 0; i < 10; i++) {
771 fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
774 fEMCALBadChannelMap->SetOwner(kTRUE);
775 fEMCALBadChannelMap->Compress();
777 //In order to avoid rewriting the same histograms
778 TH1::AddDirectory(oldStatus);
781 //________________________________________________________________
782 void AliEMCALRecoUtils::RecalibrateClusterEnergy(AliEMCALGeometry* geom, AliVCluster * cluster, AliVCaloCells * cells, const Int_t bc){
783 // Recalibrate the cluster energy and Time, considering the recalibration map
784 // and the energy of the cells and time that compose the cluster.
785 // bc= bunch crossing number returned by esdevent->GetBunchCrossNumber();
788 AliInfo("Cluster pointer null!");
792 //Get the cluster number of cells and list of absId, check what kind of cluster do we have.
793 UShort_t * index = cluster->GetCellsAbsId() ;
794 Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
795 Int_t ncells = cluster->GetNCells();
797 //Initialize some used variables
800 Int_t icol =-1, irow =-1, imod=1;
801 Float_t factor = 1, frac = 0;
805 //Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
806 for(Int_t icell = 0; icell < ncells; icell++){
807 absId = index[icell];
808 frac = fraction[icell];
809 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
811 if(!fCellsRecalibrated && IsRecalibrationOn()){
814 Int_t iTower = -1, iIphi = -1, iIeta = -1;
815 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
816 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
817 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
818 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
820 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
821 imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
825 energy += cells->GetCellAmplitude(absId)*factor*frac;
827 if(emax < cells->GetCellAmplitude(absId)*factor*frac){
828 emax = cells->GetCellAmplitude(absId)*factor*frac;
834 cluster->SetE(energy);
836 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f\n",cluster->E(),energy));
838 // Recalculate time of cluster only for ESDs
839 if(!strcmp("AliESDCaloCluster",Form("%s",cluster->ClassName()))){
842 Double_t weightedTime = 0;
844 Double_t weightTot = 0;
845 Double_t maxcellTime = 0;
846 for(Int_t icell = 0; icell < ncells; icell++){
847 absId = index[icell];
848 frac = fraction[icell];
849 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
851 Double_t celltime = cells->GetCellTime(absId);
852 RecalibrateCellTime(absId, bc, celltime);
853 if(absId == absIdMax) maxcellTime = celltime;
855 if(!fCellsRecalibrated){
857 Int_t iTower = -1, iIphi = -1, iIeta = -1;
858 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
859 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
860 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
861 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
863 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
864 imod,icol,irow,frac,factor,cells->GetCellTime(absId)));
868 weight = GetCellWeight(cells->GetCellAmplitude(absId)*factor*frac , energy );
870 weightedTime += celltime * weight;
875 cluster->SetTOF(weightedTime/weightTot);
877 cluster->SetTOF(maxcellTime);
882 //________________________________________________________________
883 void AliEMCALRecoUtils::RecalibrateCells(AliEMCALGeometry* geom, AliVCaloCells * cells, Int_t bc){
884 // Recalibrate the cells time and energy, considering the recalibration map and the energy
885 // of the cells that compose the cluster.
886 // bc= bunch crossing number returned by esdevent->GetBunchCrossNumber();
888 if(!IsRecalibrationOn()) return;
891 AliInfo("Cells pointer null!");
895 fCellsRecalibrated = kTRUE;
898 Int_t icol =-1, irow =-1, imod = 1;
899 Int_t iTower =-1, iIeta =-1, iIphi =-1;
901 Int_t nEMcell = cells->GetNumberOfCells() ;
903 for (Int_t iCell = 0; iCell < nEMcell; iCell++) {
905 absId = cells->GetCellNumber(iCell);
909 if(IsRecalibrationOn()){
910 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
911 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
912 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
913 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
916 Float_t cellE = cells->GetAmplitude(iCell) * factor ;
919 Double_t celltime = cells->GetCellTime(absId);
920 RecalibrateCellTime(absId, bc, celltime);
923 cells->SetCell(iCell,cells->GetCellNumber(iCell),cellE, celltime);
929 //________________________________________________________________
930 void AliEMCALRecoUtils::RecalibrateCellTime(const Int_t absId, const Int_t bc, Double_t & celltime){
931 // Recalibrate time of cell with absID considering the recalibration map
932 // bc= bunch crossing number returned by esdevent->GetBunchCrossNumber();
934 if(!fCellsRecalibrated && IsTimeRecalibrationOn()){
935 // printf("cell time org %g, ",celltime);
937 Double_t timeBCoffset = 0.;
938 if( bc%4 ==0 || bc%4==1) timeBCoffset = 100.*1.e-9; //in ns
940 Double_t celloffset = GetEMCALChannelTimeRecalibrationFactor(bc%4,absId)*1.e-9;
942 // printf("absId %d, time %f bc %d-%d: bc0 %f, bc1 %f, bc2 %f, bc3 %f \n", absId, celltime*1.e9,bc, bc%4,
943 // GetEMCALChannelTimeRecalibrationFactor(0,absId),GetEMCALChannelTimeRecalibrationFactor(1,absId),
944 // GetEMCALChannelTimeRecalibrationFactor(2,absId),GetEMCALChannelTimeRecalibrationFactor(3,absId));
946 celltime -= timeBCoffset ;
947 celltime -= celloffset ;
948 // printf("new %g\n",celltime);
953 //__________________________________________________
954 void AliEMCALRecoUtils::RecalculateClusterPosition(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
956 //For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
959 AliInfo("Cluster pointer null!");
963 if (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
964 else if(fPosAlgo==kPosTowerIndex) RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
965 else AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
969 //__________________________________________________
970 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
972 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
973 // The algorithm is a copy of what is done in AliEMCALRecPoint
976 Float_t fraction = 1.;
977 Float_t recalFactor = 1.;
980 Int_t iTower = -1, iIphi = -1, iIeta = -1;
981 Int_t iSupModMax = -1, iSM=-1, iphi = -1, ieta = -1;
982 Float_t weight = 0., totalWeight=0.;
983 Float_t newPos[3] = {0,0,0};
984 Double_t pLocal[3], pGlobal[3];
985 Bool_t shared = kFALSE;
987 Float_t clEnergy = clu->E(); //Energy already recalibrated previously
988 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
989 Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
991 //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
993 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
995 absId = clu->GetCellAbsId(iDig);
996 fraction = clu->GetCellAmplitudeFraction(iDig);
997 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
999 if(!fCellsRecalibrated){
1001 geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta);
1002 geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);
1004 if(IsRecalibrationOn()) {
1005 recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
1009 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
1011 weight = GetCellWeight(eCell,clEnergy);
1012 totalWeight += weight;
1014 geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
1015 //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
1016 geom->GetGlobal(pLocal,pGlobal,iSupModMax);
1017 //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
1019 for(int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
1024 for(int i=0; i<3; i++ ) newPos[i] /= totalWeight;
1027 //Float_t pos[]={0,0,0};
1028 //clu->GetPosition(pos);
1029 //printf("OldPos : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
1030 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
1032 if(iSupModMax > 1) {//sector 1
1033 newPos[0] +=fMisalTransShift[3];//-=3.093;
1034 newPos[1] +=fMisalTransShift[4];//+=6.82;
1035 newPos[2] +=fMisalTransShift[5];//+=1.635;
1036 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
1040 newPos[0] +=fMisalTransShift[0];//+=1.134;
1041 newPos[1] +=fMisalTransShift[1];//+=8.2;
1042 newPos[2] +=fMisalTransShift[2];//+=1.197;
1043 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
1046 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
1048 clu->SetPosition(newPos);
1052 //__________________________________________________
1053 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
1055 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
1056 // The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position
1058 Double_t eCell = 1.;
1059 Float_t fraction = 1.;
1060 Float_t recalFactor = 1.;
1064 Int_t iIphi = -1, iIeta = -1;
1065 Int_t iSupMod = -1, iSupModMax = -1;
1066 Int_t iphi = -1, ieta =-1;
1067 Bool_t shared = kFALSE;
1069 Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
1070 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
1071 Float_t depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
1073 Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
1074 Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
1075 Int_t startingSM = -1;
1077 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
1078 absId = clu->GetCellAbsId(iDig);
1079 fraction = clu->GetCellAmplitudeFraction(iDig);
1080 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1082 if (iDig==0) startingSM = iSupMod;
1083 else if(iSupMod != startingSM) areInSameSM = kFALSE;
1085 eCell = cells->GetCellAmplitude(absId);
1087 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
1088 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
1090 if(!fCellsRecalibrated){
1092 if(IsRecalibrationOn()) {
1094 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1099 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
1101 weight = GetCellWeight(eCell,clEnergy);
1102 if(weight < 0) weight = 0;
1103 totalWeight += weight;
1104 weightedCol += ieta*weight;
1105 weightedRow += iphi*weight;
1107 //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
1111 Float_t xyzNew[]={0.,0.,0.};
1112 if(areInSameSM == kTRUE) {
1113 //printf("In Same SM\n");
1114 weightedCol = weightedCol/totalWeight;
1115 weightedRow = weightedRow/totalWeight;
1116 geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
1119 //printf("In Different SM\n");
1120 geom->RecalculateTowerPosition(iphi, ieta, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
1123 clu->SetPosition(xyzNew);
1127 //____________________________________________________________________________
1128 void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster){
1130 //re-evaluate distance to bad channel with updated bad map
1132 if(!fRecalDistToBadChannels) return;
1135 AliInfo("Cluster pointer null!");
1139 //Get channels map of the supermodule where the cluster is.
1140 Int_t absIdMax = -1, iSupMod =-1, icolM = -1, irowM = -1;
1141 Bool_t shared = kFALSE;
1142 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSupMod, icolM, irowM, shared);
1143 TH2D* hMap = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
1146 Float_t minDist = 10000.;
1149 //Loop on tower status map
1150 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
1151 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
1152 //Check if tower is bad.
1153 if(hMap->GetBinContent(icol,irow)==0) continue;
1154 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
1155 // iSupMod,icol, irow, icolM,irowM);
1157 dRrow=TMath::Abs(irowM-irow);
1158 dRcol=TMath::Abs(icolM-icol);
1159 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
1161 //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
1168 //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
1171 Int_t iSupMod2 = -1;
1173 //The only possible combinations are (0,1), (2,3) ... (8,9)
1174 if(iSupMod%2) iSupMod2 = iSupMod-1;
1175 else iSupMod2 = iSupMod+1;
1176 hMap2 = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
1178 //Loop on tower status map of second super module
1179 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
1180 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
1181 //Check if tower is bad.
1182 if(hMap2->GetBinContent(icol,irow)==0) continue;
1183 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels(shared) - \n \t Bad channel in SM %d, col %d, row %d \n \t Cluster max in SM %d, col %d, row %d\n",
1184 // iSupMod2,icol, irow,iSupMod,icolM,irowM);
1186 dRrow=TMath::Abs(irow-irowM);
1189 dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
1192 dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
1195 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
1196 if(dist < minDist) minDist = dist;
1201 }// shared cluster in 2 SuperModules
1203 AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
1204 cluster->SetDistanceToBadChannel(minDist);
1208 //____________________________________________________________________________
1209 void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster){
1211 //re-evaluate identification parameters with bayesian
1214 AliInfo("Cluster pointer null!");
1218 if ( cluster->GetM02() != 0)
1219 fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
1221 Float_t pidlist[AliPID::kSPECIESN+1];
1222 for(Int_t i = 0; i < AliPID::kSPECIESN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
1224 cluster->SetPID(pidlist);
1228 //____________________________________________________________________________
1229 void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster)
1231 // Calculates new center of gravity in the local EMCAL-module coordinates
1232 // and tranfers into global ALICE coordinates
1233 // Calculates Dispersion and main axis
1236 AliInfo("Cluster pointer null!");
1242 Double_t eCell = 0.;
1243 Float_t fraction = 1.;
1244 Float_t recalFactor = 1.;
1252 Double_t etai = -1.;
1253 Double_t phii = -1.;
1260 Double_t xmean = 0.;
1261 Double_t zmean = 0.;
1264 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1266 //Get from the absid the supermodule, tower and eta/phi numbers
1267 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1268 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1270 //Get the cell energy, if recalibration is on, apply factors
1271 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1272 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1274 if(!fCellsRecalibrated){
1276 if(IsRecalibrationOn()) {
1277 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1282 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1284 if(cluster->E() > 0 && eCell > 0){
1286 w = GetCellWeight(eCell,cluster->E());
1288 etai=(Double_t)ieta;
1289 phii=(Double_t)iphi;
1294 dxx += w * etai * etai ;
1296 dzz += w * phii * phii ;
1298 dxz += w * etai * phii ;
1302 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1305 //Normalize to the weight
1311 AliError(Form("Wrong weight %f\n", wtot));
1313 //Calculate dispersion
1314 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1316 //Get from the absid the supermodule, tower and eta/phi numbers
1317 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1318 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1320 //Get the cell energy, if recalibration is on, apply factors
1321 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1322 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1323 if(IsRecalibrationOn()) {
1324 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1326 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1328 if(cluster->E() > 0 && eCell > 0){
1330 w = GetCellWeight(eCell,cluster->E());
1332 etai=(Double_t)ieta;
1333 phii=(Double_t)iphi;
1334 if(w > 0.0) d += w*((etai-xmean)*(etai-xmean)+(phii-zmean)*(phii-zmean));
1337 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1340 //Normalize to the weigth and set shower shape parameters
1341 if (wtot > 0 && nstat > 1) {
1346 dxx -= xmean * xmean ;
1347 dzz -= zmean * zmean ;
1348 dxz -= xmean * zmean ;
1349 cluster->SetM02(0.5 * (dxx + dzz) + TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1350 cluster->SetM20(0.5 * (dxx + dzz) - TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1354 cluster->SetM20(0.) ;
1355 cluster->SetM02(0.) ;
1359 cluster->SetDispersion(TMath::Sqrt(d)) ;
1361 cluster->SetDispersion(0) ;
1364 //____________________________________________________________________________
1365 void AliEMCALRecoUtils::FindMatches(AliVEvent *event,TObjArray * clusterArr, AliEMCALGeometry *geom)
1367 //This function should be called before the cluster loop
1368 //Before call this function, please recalculate the cluster positions
1369 //Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR
1370 //Store matched cluster indexes and residuals
1372 fMatchedTrackIndex->Reset();
1373 fMatchedClusterIndex->Reset();
1374 fResidualPhi->Reset();
1375 fResidualEta->Reset();
1377 fMatchedTrackIndex->Set(500);
1378 fMatchedClusterIndex->Set(500);
1379 fResidualPhi->Set(500);
1380 fResidualEta->Set(500);
1382 AliESDEvent* esdevent = dynamic_cast<AliESDEvent*> (event);
1383 AliAODEvent* aodevent = dynamic_cast<AliAODEvent*> (event);
1387 for (Int_t i=0; i<21;i++) cv[i]=0;
1388 for(Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
1390 AliExternalTrackParam *trackParam = 0;
1392 //If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner
1395 AliESDtrack *esdTrack = esdevent->GetTrack(itr);
1396 if(!esdTrack || !IsAccepted(esdTrack)) continue;
1397 if(esdTrack->Pt()<fCutMinTrackPt) continue;
1398 trackParam = const_cast<AliExternalTrackParam*>(esdTrack->GetInnerParam());
1401 //If the input event is AOD, the starting point for extrapolation is at vertex
1402 //AOD tracks are selected according to its bit.
1405 AliAODTrack *aodTrack = aodevent->GetTrack(itr);
1406 if(!aodTrack) continue;
1407 if(!aodTrack->TestFilterMask(fAODFilterMask)) continue; //Select AOD tracks that fulfill GetStandardITSTPCTrackCuts2010()
1408 if(aodTrack->Pt()<fCutMinTrackPt) continue;
1409 Double_t pos[3],mom[3];
1410 aodTrack->GetXYZ(pos);
1411 aodTrack->GetPxPyPz(mom);
1412 AliDebug(5,Form("aod track: i=%d | pos=(%5.4f,%5.4f,%5.4f) | mom=(%5.4f,%5.4f,%5.4f) | charge=%d\n",itr,pos[0],pos[1],pos[2],mom[0],mom[1],mom[2],aodTrack->Charge()));
1413 trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
1416 //Return if the input data is not "AOD" or "ESD"
1419 printf("Wrong input data type! Should be \"AOD\" or \"ESD\"\n");
1423 if(!trackParam) continue;
1425 Float_t dRMax = fCutR, dEtaMax=fCutEta, dPhiMax=fCutPhi;
1427 if(!clusterArr){// get clusters from event
1428 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1430 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1431 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1432 AliExternalTrackParam trkPamTmp(*trackParam);//Retrieve the starting point every time before the extrapolation
1433 Float_t tmpEta=-999, tmpPhi=-999;
1434 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1437 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1446 else if(fCutEtaPhiSeparate)
1448 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1457 printf("Error: please specify your cut criteria\n");
1458 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1459 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1460 if(aodevent && trackParam) delete trackParam;
1465 else { // external cluster array, not from ESD event
1466 for(Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
1468 AliVCluster *cluster = dynamic_cast<AliVCluster*> (clusterArr->At(icl)) ;
1470 AliInfo("Cluster not found!!!");
1473 if(!cluster->IsEMCAL()) continue;
1474 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1475 Float_t tmpEta=-999, tmpPhi=-999;
1476 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1479 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1488 else if(fCutEtaPhiSeparate)
1490 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1499 printf("Error: please specify your cut criteria\n");
1500 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1501 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1502 if(aodevent && trackParam) delete trackParam;
1506 }// external list of clusters
1510 fMatchedTrackIndex ->AddAt(itr,matched);
1511 fMatchedClusterIndex->AddAt(index,matched);
1512 fResidualEta ->AddAt(dEtaMax,matched);
1513 fResidualPhi ->AddAt(dPhiMax,matched);
1516 if(aodevent && trackParam) delete trackParam;
1519 AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
1521 fMatchedTrackIndex ->Set(matched);
1522 fMatchedClusterIndex->Set(matched);
1523 fResidualPhi ->Set(matched);
1524 fResidualEta ->Set(matched);
1527 //________________________________________________________________________________
1528 Int_t AliEMCALRecoUtils::FindMatchedCluster(AliESDtrack *track, AliVEvent *event, AliEMCALGeometry *geom)
1531 // This function returns the index of matched cluster to input track
1532 // Returns -1 if no match is found
1535 Float_t dRMax = fCutR, dEtaMax = fCutEta, dPhiMax = fCutPhi;
1538 AliExternalTrackParam *trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
1540 if(!trackParam) return index;
1541 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1543 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1544 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1545 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1546 Float_t tmpEta=-999, tmpPhi=-999;
1547 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1550 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1559 else if(fCutEtaPhiSeparate)
1561 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1570 printf("Error: please specify your cut criteria\n");
1571 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1572 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1579 //________________________________________________________________________________
1580 Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, AliVCluster *cluster, Float_t &tmpEta, Float_t &tmpPhi)
1583 //Return the residual by extrapolating a track to a cluster
1585 if(!trkParam || !cluster) return kFALSE;
1588 cluster->GetPosition(clsPos); //Has been recalculated
1589 TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
1590 Double_t alpha = ((int)(vec.Phi()*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
1591 vec.RotateZ(-alpha); //Rotate the cluster to the local extrapolation coordinate system
1592 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), fMass, fStep,kTRUE, 0.8, -1)) return kFALSE;
1593 trkParam->GetXYZ(trkPos); //Get the extrapolated global position
1595 TVector3 clsPosVec(clsPos[0],clsPos[1],clsPos[2]);
1596 TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
1598 // track cluster matching
1599 tmpPhi = clsPosVec.DeltaPhi(trkPosVec); // tmpPhi is between -pi and pi
1600 tmpEta = clsPosVec.Eta()-trkPosVec.Eta(); // track cluster matching
1605 //________________________________________________________________________________
1606 void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex, Float_t &dEta, Float_t &dPhi)
1608 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1609 //Get the residuals dEta and dPhi for this cluster to the closest track
1610 //Works with ESDs and AODs
1612 if( FindMatchedPosForCluster(clsIndex) >= 999 )
1614 AliDebug(2,"No matched tracks found!\n");
1619 dEta = fResidualEta->At(FindMatchedPosForCluster(clsIndex));
1620 dPhi = fResidualPhi->At(FindMatchedPosForCluster(clsIndex));
1622 //________________________________________________________________________________
1623 void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dEta, Float_t &dPhi)
1625 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1626 //Get the residuals dEta and dPhi for this track to the closest cluster
1627 //Works with ESDs and AODs
1629 if( FindMatchedPosForTrack(trkIndex) >= 999 )
1631 AliDebug(2,"No matched cluster found!\n");
1636 dEta = fResidualEta->At(FindMatchedPosForTrack(trkIndex));
1637 dPhi = fResidualPhi->At(FindMatchedPosForTrack(trkIndex));
1640 //__________________________________________________________
1641 Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
1643 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1644 //Get the index of matched track to this cluster
1645 //Works with ESDs and AODs
1647 if(IsClusterMatched(clsIndex))
1648 return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
1653 //__________________________________________________________
1654 Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
1656 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1657 //Get the index of matched cluster to this track
1658 //Works with ESDs and AODs
1660 if(IsTrackMatched(trkIndex))
1661 return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
1666 //__________________________________________________
1667 Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex) const
1669 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1670 //Returns if the cluster has a match
1671 if(FindMatchedPosForCluster(clsIndex) < 999)
1677 //__________________________________________________
1678 Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex) const
1680 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1681 //Returns if the track has a match
1682 if(FindMatchedPosForTrack(trkIndex) < 999)
1688 //__________________________________________________________
1689 UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
1691 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1692 //Returns the position of the match in the fMatchedClusterIndex array
1693 Float_t tmpR = fCutR;
1696 for(Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++)
1698 if(fMatchedClusterIndex->At(i)==clsIndex)
1700 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1705 AliDebug(3,Form("Matched cluster index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedClusterIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1712 //__________________________________________________________
1713 UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
1715 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1716 //Returns the position of the match in the fMatchedTrackIndex array
1717 Float_t tmpR = fCutR;
1720 for(Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++)
1722 if(fMatchedTrackIndex->At(i)==trkIndex)
1724 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1729 AliDebug(3,Form("Matched track index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedTrackIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1736 //__________________________________________________________
1737 Bool_t AliEMCALRecoUtils::IsGoodCluster(AliVCluster *cluster, AliEMCALGeometry *geom, AliVCaloCells* cells)
1739 // check if the cluster survives some quality cut
1742 Bool_t isGood=kTRUE;
1743 if(!cluster || !cluster->IsEMCAL()) return kFALSE;
1744 if(ClusterContainsBadChannel(geom,cluster->GetCellsAbsId(),cluster->GetNCells())) return kFALSE;
1745 if(!CheckCellFiducialRegion(geom,cluster,cells)) return kFALSE;
1746 if(fRejectExoticCluster && IsExoticCluster(cluster)) return kFALSE;
1751 //__________________________________________________________
1752 Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
1754 // Given a esd track, return whether the track survive all the cuts
1756 // The different quality parameter are first
1757 // retrieved from the track. then it is found out what cuts the
1758 // track did not survive and finally the cuts are imposed.
1760 UInt_t status = esdTrack->GetStatus();
1762 Int_t nClustersITS = esdTrack->GetITSclusters(0);
1763 Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
1765 Float_t chi2PerClusterITS = -1;
1766 Float_t chi2PerClusterTPC = -1;
1767 if (nClustersITS!=0)
1768 chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
1769 if (nClustersTPC!=0)
1770 chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
1774 Float_t maxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); //This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
1775 //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
1776 SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
1781 esdTrack->GetImpactParameters(b,bCov);
1782 if (bCov[0]<=0 || bCov[2]<=0) {
1783 AliDebug(1, "Estimated b resolution lower or equal zero!");
1784 bCov[0]=0; bCov[2]=0;
1787 Float_t dcaToVertexXY = b[0];
1788 Float_t dcaToVertexZ = b[1];
1789 Float_t dcaToVertex = -1;
1791 if (fCutDCAToVertex2D)
1792 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY/fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + dcaToVertexZ*dcaToVertexZ/fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ);
1794 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
1798 Bool_t cuts[kNCuts];
1799 for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
1801 // track quality cuts
1802 if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
1804 if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
1806 if (nClustersTPC<fCutMinNClusterTPC)
1808 if (nClustersITS<fCutMinNClusterITS)
1810 if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC)
1812 if (chi2PerClusterITS>fCutMaxChi2PerClusterITS)
1814 if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
1816 if (fCutDCAToVertex2D && dcaToVertex > 1)
1818 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
1820 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ) > fCutMaxDCAToVertexZ)
1823 //Require at least one SPD point + anything else in ITS
1824 if( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
1828 for (Int_t i=0; i<kNCuts; i++)
1829 if (cuts[i]) {cut = kTRUE;}
1837 //__________________________________________________
1838 void AliEMCALRecoUtils::InitTrackCuts()
1840 //Intilize the track cut criteria
1841 //By default these cuts are set according to AliESDtrackCuts::GetStandardTPCOnlyTrackCuts()
1842 //Also you can customize the cuts using the setters
1844 switch (fTrackCutsType)
1848 AliInfo(Form("Track cuts for matching: GetStandardTPCOnlyTrackCuts()"));
1850 SetMinNClustersTPC(70);
1851 SetMaxChi2PerClusterTPC(4);
1852 SetAcceptKinkDaughters(kFALSE);
1853 SetRequireTPCRefit(kFALSE);
1856 SetRequireITSRefit(kFALSE);
1857 SetMaxDCAToVertexZ(3.2);
1858 SetMaxDCAToVertexXY(2.4);
1859 SetDCAToVertex2D(kTRUE);
1866 AliInfo(Form("Track cuts for matching: GetStandardITSTPCTrackCuts2010(kTURE)"));
1868 SetMinNClustersTPC(70);
1869 SetMaxChi2PerClusterTPC(4);
1870 SetAcceptKinkDaughters(kFALSE);
1871 SetRequireTPCRefit(kTRUE);
1874 SetRequireITSRefit(kTRUE);
1875 SetMaxDCAToVertexZ(2);
1876 SetMaxDCAToVertexXY();
1877 SetDCAToVertex2D(kFALSE);
1884 AliInfo(Form("Track cuts for matching: Loose cut w/o DCA cut"));
1885 SetMinNClustersTPC(50);
1886 SetAcceptKinkDaughters(kTRUE);
1893 //___________________________________________________
1894 void AliEMCALRecoUtils::Print(const Option_t *) const
1898 printf("AliEMCALRecoUtils Settings: \n");
1899 printf("Misalignment shifts\n");
1900 for(Int_t i=0; i<5; i++) printf("\t sector %d, traslation (x,y,z)=(%f,%f,%f), rotation (x,y,z)=(%f,%f,%f)\n",i,
1901 fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
1902 fMisalRotShift[i*3], fMisalRotShift[i*3+1], fMisalRotShift[i*3+2] );
1903 printf("Non linearity function %d, parameters:\n", fNonLinearityFunction);
1904 for(Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
1906 printf("Position Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
1908 printf("Matching criteria: ");
1911 printf("sqrt(dEta^2+dPhi^2)<%2.2f\n",fCutR);
1913 else if(fCutEtaPhiSeparate)
1915 printf("dEta<%2.2f, dPhi<%2.2f\n",fCutEta,fCutPhi);
1920 printf("please specify your cut criteria\n");
1921 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1922 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1925 printf("Mass hypothesis = %2.3f [GeV/c^2], extrapolation step = %2.2f[cm]\n",fMass,fStep);
1927 printf("Track cuts: \n");
1928 printf("Minimum track pT: %1.2f\n",fCutMinTrackPt);
1929 printf("AOD track selection mask: %d\n",fAODFilterMask);
1930 printf("TPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
1931 printf("AcceptKinks = %d\n",fCutAcceptKinkDaughters);
1932 printf("MinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
1933 printf("MaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
1934 printf("DCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
1938 //_____________________________________________________________________
1939 void AliEMCALRecoUtils::SetRunDependentCorrections(Int_t runnumber){
1940 //Get EMCAL time dependent corrections from file and put them in the recalibration histograms
1941 //Do it only once and only if it is requested
1943 if(!fUseRunCorrectionFactors) return;
1944 if(fRunCorrectionFactorsSet) return;
1946 AliInfo(Form("AliEMCALRecoUtils::GetRunDependentCorrections() - Get Correction Factors for Run number %d\n",runnumber));
1948 AliEMCALCalibTimeDepCorrection *corr = new AliEMCALCalibTimeDepCorrection();
1949 corr->ReadRootInfo(Form("CorrectionFiles/Run%d_Correction.root",runnumber));
1951 SwitchOnRecalibration();
1952 for(Int_t ism = 0; ism < 4; ism++){
1953 for(Int_t icol = 0; icol < 48; icol++){
1954 for(Int_t irow = 0; irow < 24; irow++){
1955 Float_t orgRecalFactor = GetEMCALChannelRecalibrationFactors(ism)->GetBinContent(icol,irow);
1956 Float_t newRecalFactor = orgRecalFactor*corr->GetCorrection(ism, icol,irow,0);
1957 GetEMCALChannelRecalibrationFactors(ism)->SetBinContent(icol,irow,newRecalFactor);
1958 //printf("ism %d, icol %d, irow %d, corrections : org %f, time dep %f, final %f (org*time %f)\n",ism, icol, irow,
1959 // orgRecalFactor, corr->GetCorrection(ism, icol,irow,0),
1960 // (GetEMCALChannelRecalibrationFactors(ism))->GetBinContent(icol,irow),newRecalFactor);
1964 fRunCorrectionFactorsSet = kTRUE;