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"
61 #include "AliEMCALPIDUtils.h"
63 ClassImp(AliEMCALRecoUtils)
65 //______________________________________________
66 AliEMCALRecoUtils::AliEMCALRecoUtils():
67 fNonLinearityFunction (kNoCorrection), fParticleType(kPhoton),
68 fPosAlgo(kUnchanged),fW0(4.), fNonLinearThreshold(30),
69 fRecalibration(kFALSE), fEMCALRecalibrationFactors(),
70 fRemoveBadChannels(kFALSE), fRecalDistToBadChannels(kFALSE), fEMCALBadChannelMap(),
71 fNCellsFromEMCALBorder(0), fNoEMCALBorderAtEta0(kTRUE),
73 fMatchedTrackIndex(0x0), fMatchedClusterIndex(0x0),
74 fResidualEta(0x0), fResidualPhi(0x0), fCutEtaPhiSum(kTRUE), fCutEtaPhiSeparate(kFALSE), fCutR(0.1), fCutEta(0.02), fCutPhi(0.04), fMass(0.139), fStep(1),
75 fRejectExoticCluster(kFALSE),
76 fCutMinTrackPt(0), fCutMinNClusterTPC(0), fCutMinNClusterITS(0), fCutMaxChi2PerClusterTPC(0), fCutMaxChi2PerClusterITS(0),
77 fCutRequireTPCRefit(0), fCutRequireITSRefit(0), fCutAcceptKinkDaughters(0),
78 fCutMaxDCAToVertexXY(0), fCutMaxDCAToVertexZ(0),fCutDCAToVertex2D(0),fPIDUtils(),
79 fUseTimeCorrectionFactors(kFALSE), fTimeCorrectionFactorsSet(kFALSE)
83 // Initialize all constant values which have to be used
84 // during Reco algorithm execution
87 //Misalignment matrices
88 for(Int_t i = 0; i < 15 ; i++) {
89 fMisalTransShift[i] = 0.;
90 fMisalRotShift[i] = 0.;
94 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = 0.;
96 //For kBeamTestCorrected case, but default is no correction
97 fNonLinearityParams[0] = 0.99078;
98 fNonLinearityParams[1] = 0.161499;
99 fNonLinearityParams[2] = 0.655166;
100 fNonLinearityParams[3] = 0.134101;
101 fNonLinearityParams[4] = 163.282;
102 fNonLinearityParams[5] = 23.6904;
103 fNonLinearityParams[6] = 0.978;
105 //For kPi0GammaGamma case
106 //fNonLinearityParams[0] = 0.1457/0.1349766/1.038;
107 //fNonLinearityParams[1] = -0.02024/0.1349766/1.038;
108 //fNonLinearityParams[2] = 1.046;
111 fMatchedTrackIndex = new TArrayI();
112 fMatchedClusterIndex = new TArrayI();
113 fResidualPhi = new TArrayF();
114 fResidualEta = new TArrayF();
118 fPIDUtils = new AliEMCALPIDUtils();
123 //______________________________________________________________________
124 AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco)
125 : TNamed(reco), fNonLinearityFunction(reco.fNonLinearityFunction),
126 fParticleType(reco.fParticleType), fPosAlgo(reco.fPosAlgo), fW0(reco.fW0), fNonLinearThreshold(reco.fNonLinearThreshold),
127 fRecalibration(reco.fRecalibration),fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
128 fRemoveBadChannels(reco.fRemoveBadChannels),fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
129 fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
130 fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder),fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
131 fAODFilterMask(reco.fAODFilterMask),
132 fMatchedTrackIndex(reco.fMatchedTrackIndex?new TArrayI(*reco.fMatchedTrackIndex):0x0),
133 fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
134 fResidualEta(reco.fResidualEta?new TArrayF(*reco.fResidualEta):0x0),
135 fResidualPhi(reco.fResidualPhi?new TArrayF(*reco.fResidualPhi):0x0),
136 fCutEtaPhiSum(reco.fCutEtaPhiSum), fCutEtaPhiSeparate(reco.fCutEtaPhiSeparate), fCutR(reco.fCutR), fCutEta(reco.fCutEta), fCutPhi(reco.fCutPhi),
137 fMass(reco.fMass), fStep(reco.fStep),
138 fRejectExoticCluster(reco.fRejectExoticCluster),
139 fCutMinTrackPt(reco.fCutMinTrackPt), fCutMinNClusterTPC(reco.fCutMinNClusterTPC), fCutMinNClusterITS(reco.fCutMinNClusterITS),
140 fCutMaxChi2PerClusterTPC(reco.fCutMaxChi2PerClusterTPC), fCutMaxChi2PerClusterITS(reco.fCutMaxChi2PerClusterITS),
141 fCutRequireTPCRefit(reco.fCutRequireTPCRefit), fCutRequireITSRefit(reco.fCutRequireITSRefit),
142 fCutAcceptKinkDaughters(reco.fCutAcceptKinkDaughters),
143 fCutMaxDCAToVertexXY(reco.fCutMaxDCAToVertexXY), fCutMaxDCAToVertexZ(reco.fCutMaxDCAToVertexZ),fCutDCAToVertex2D(reco.fCutDCAToVertex2D),
144 fPIDUtils(reco.fPIDUtils),
145 fUseTimeCorrectionFactors(reco.fUseTimeCorrectionFactors), fTimeCorrectionFactorsSet(reco.fTimeCorrectionFactorsSet)
149 for(Int_t i = 0; i < 15 ; i++) {
150 fMisalRotShift[i] = reco.fMisalRotShift[i];
151 fMisalTransShift[i] = reco.fMisalTransShift[i];
153 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
158 //______________________________________________________________________
159 AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco)
161 //Assignment operator
163 if(this == &reco)return *this;
164 ((TNamed *)this)->operator=(reco);
166 fNonLinearityFunction = reco.fNonLinearityFunction;
167 fParticleType = reco.fParticleType;
168 fPosAlgo = reco.fPosAlgo;
170 fNonLinearThreshold = reco.fNonLinearThreshold;
171 fRecalibration = reco.fRecalibration;
172 fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
173 fRemoveBadChannels = reco.fRemoveBadChannels;
174 fRecalDistToBadChannels = reco.fRecalDistToBadChannels;
175 fEMCALBadChannelMap = reco.fEMCALBadChannelMap;
176 fNCellsFromEMCALBorder = reco.fNCellsFromEMCALBorder;
177 fNoEMCALBorderAtEta0 = reco.fNoEMCALBorderAtEta0;
180 for(Int_t i = 0; i < 15 ; i++) {fMisalTransShift[i] = reco.fMisalTransShift[i]; fMisalRotShift[i] = reco.fMisalRotShift[i];}
181 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
183 fAODFilterMask = reco.fAODFilterMask;
185 fCutEtaPhiSum = reco.fCutEtaPhiSum;
186 fCutEtaPhiSeparate = reco.fCutEtaPhiSeparate;
188 fCutEta = reco.fCutEta;
189 fCutPhi = reco.fCutPhi;
192 fRejectExoticCluster = reco.fRejectExoticCluster;
194 fCutMinTrackPt = reco.fCutMinTrackPt;
195 fCutMinNClusterTPC = reco.fCutMinNClusterTPC;
196 fCutMinNClusterITS = reco.fCutMinNClusterITS;
197 fCutMaxChi2PerClusterTPC = reco.fCutMaxChi2PerClusterTPC;
198 fCutMaxChi2PerClusterITS = reco.fCutMaxChi2PerClusterITS;
199 fCutRequireTPCRefit = reco.fCutRequireTPCRefit;
200 fCutRequireITSRefit = reco.fCutRequireITSRefit;
201 fCutAcceptKinkDaughters = reco.fCutAcceptKinkDaughters;
202 fCutMaxDCAToVertexXY = reco.fCutMaxDCAToVertexXY;
203 fCutMaxDCAToVertexZ = reco.fCutMaxDCAToVertexZ;
204 fCutDCAToVertex2D = reco.fCutDCAToVertex2D;
206 fPIDUtils = reco.fPIDUtils;
208 fUseTimeCorrectionFactors = reco.fUseTimeCorrectionFactors;
209 fTimeCorrectionFactorsSet = reco.fTimeCorrectionFactorsSet;
212 if(reco.fResidualEta){
213 // assign or copy construct
215 *fResidualEta = *reco.fResidualEta;
217 else fResidualEta = new TArrayF(*reco.fResidualEta);
220 if(fResidualEta)delete fResidualEta;
224 if(reco.fResidualPhi){
225 // assign or copy construct
227 *fResidualPhi = *reco.fResidualPhi;
229 else fResidualPhi = new TArrayF(*reco.fResidualPhi);
232 if(fResidualPhi)delete fResidualPhi;
236 if(reco.fMatchedTrackIndex){
237 // assign or copy construct
238 if(fMatchedTrackIndex){
239 *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
241 else fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
244 if(fMatchedTrackIndex)delete fMatchedTrackIndex;
245 fMatchedTrackIndex = 0;
248 if(reco.fMatchedClusterIndex){
249 // assign or copy construct
250 if(fMatchedClusterIndex){
251 *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
253 else fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
256 if(fMatchedClusterIndex)delete fMatchedClusterIndex;
257 fMatchedClusterIndex = 0;
265 //__________________________________________________
266 AliEMCALRecoUtils::~AliEMCALRecoUtils()
270 if(fEMCALRecalibrationFactors) {
271 fEMCALRecalibrationFactors->Clear();
272 delete fEMCALRecalibrationFactors;
275 if(fEMCALBadChannelMap) {
276 fEMCALBadChannelMap->Clear();
277 delete fEMCALBadChannelMap;
280 delete fMatchedTrackIndex ;
281 delete fMatchedClusterIndex ;
282 delete fResidualEta ;
283 delete fResidualPhi ;
287 //_______________________________________________________________
288 Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(AliEMCALGeometry* geom, AliVCluster* cluster, AliVCaloCells* cells)
290 // Given the list of AbsId of the cluster, get the maximum cell and
291 // check if there are fNCellsFromBorder from the calorimeter border
294 AliInfo("Cluster pointer null!");
298 //If the distance to the border is 0 or negative just exit accept all clusters
299 if(cells->GetType()==AliVCaloCells::kEMCALCell && fNCellsFromEMCALBorder <= 0 ) return kTRUE;
301 Int_t absIdMax = -1, iSM =-1, ieta = -1, iphi = -1;
302 Bool_t shared = kFALSE;
303 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSM, ieta, iphi, shared);
305 AliDebug(2,Form("Cluster Max AbsId %d, Cell Energy %2.2f, Cluster Energy %2.2f, Ncells from border %d, EMCAL eta=0 %d\n",
306 absIdMax, cells->GetCellAmplitude(absIdMax), cluster->E(), fNCellsFromEMCALBorder, fNoEMCALBorderAtEta0));
308 if(absIdMax==-1) return kFALSE;
310 //Check if the cell is close to the borders:
311 Bool_t okrow = kFALSE;
312 Bool_t okcol = kFALSE;
314 if(iSM < 0 || iphi < 0 || ieta < 0 ) {
315 AliFatal(Form("Negative value for super module: %d, or cell ieta: %d, or cell iphi: %d, check EMCAL geometry name\n",
321 if(iphi >= fNCellsFromEMCALBorder && iphi < 24-fNCellsFromEMCALBorder) okrow =kTRUE;
324 if(iphi >= fNCellsFromEMCALBorder && iphi < 12-fNCellsFromEMCALBorder) okrow =kTRUE;
328 if(!fNoEMCALBorderAtEta0){
329 if(ieta > fNCellsFromEMCALBorder && ieta < 48-fNCellsFromEMCALBorder) okcol =kTRUE;
333 if(ieta >= fNCellsFromEMCALBorder) okcol = kTRUE;
336 if(ieta < 48-fNCellsFromEMCALBorder) okcol = kTRUE;
340 AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d: column? %d, row? %d\nq",
341 fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
343 if (okcol && okrow) {
344 //printf("Accept\n");
348 //printf("Reject\n");
349 AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
356 //_________________________________________________________________________________________________________
357 Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(AliEMCALGeometry* geom, UShort_t* cellList, const Int_t nCells){
358 // Check that in the cluster cells, there is no bad channel of those stored
359 // in fEMCALBadChannelMap or fPHOSBadChannelMap
361 if(!fRemoveBadChannels) return kFALSE;
362 if(!fEMCALBadChannelMap) return kFALSE;
367 for(Int_t iCell = 0; iCell<nCells; iCell++){
369 //Get the column and row
370 Int_t iTower = -1, iIphi = -1, iIeta = -1;
371 geom->GetCellIndex(cellList[iCell],imod,iTower,iIphi,iIeta);
372 if(fEMCALBadChannelMap->GetEntries() <= imod) continue;
373 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
374 if(GetEMCALChannelStatus(imod, icol, irow)){
375 AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
379 }// cell cluster loop
385 //_________________________________________________
386 Bool_t AliEMCALRecoUtils::IsExoticCluster(AliVCluster *cluster) const {
387 // Check if the cluster has high energy but small number of cells
388 // The criteria comes from Gustavo's study
392 AliInfo("Cluster pointer null!");
396 if(cluster->GetNCells()<(1+cluster->E()/3.))
402 //__________________________________________________
403 Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster){
404 // Correct cluster energy from non linearity functions
407 AliInfo("Cluster pointer null!");
412 Float_t energy = cluster->E();
414 switch (fNonLinearityFunction) {
418 //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
419 //Double_t fNonLinearityParams[0] = 1.014;
420 //Double_t fNonLinearityParams[1] = -0.03329;
421 //Double_t fNonLinearityParams[2] = -0.3853;
422 //Double_t fNonLinearityParams[3] = 0.5423;
423 //Double_t fNonLinearityParams[4] = -0.4335;
424 energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
425 ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
426 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
432 //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
433 //Double_t fNonLinearityParams[0] = 1.04;
434 //Double_t fNonLinearityParams[1] = -0.1445;
435 //Double_t fNonLinearityParams[2] = 1.046;
436 energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
440 case kPi0GammaConversion:
442 //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
443 //fNonLinearityParams[0] = 0.139393/0.1349766;
444 //fNonLinearityParams[1] = 0.0566186;
445 //fNonLinearityParams[2] = 0.982133;
446 energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
453 //From beam test, Alexei's results, for different ZS thresholds
454 // th=30 MeV; th = 45 MeV; th = 75 MeV
455 //fNonLinearityParams[0] = 1.007; 1.003; 1.002
456 //fNonLinearityParams[1] = 0.894; 0.719; 0.797
457 //fNonLinearityParams[2] = 0.246; 0.334; 0.358
458 //Rescale the param[0] with 1.03
459 energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
464 case kBeamTestCorrected:
466 //From beam test, corrected for material between beam and EMCAL
467 //fNonLinearityParams[0] = 0.99078
468 //fNonLinearityParams[1] = 0.161499;
469 //fNonLinearityParams[2] = 0.655166;
470 //fNonLinearityParams[3] = 0.134101;
471 //fNonLinearityParams[4] = 163.282;
472 //fNonLinearityParams[5] = 23.6904;
473 //fNonLinearityParams[6] = 0.978;
474 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
480 AliDebug(2,"No correction on the energy\n");
488 //__________________________________________________
489 void AliEMCALRecoUtils::InitNonLinearityParam()
491 //Initialising Non Linearity Parameters
493 if(fNonLinearityFunction == kPi0MC)
495 fNonLinearityParams[0] = 1.014;
496 fNonLinearityParams[1] = -0.03329;
497 fNonLinearityParams[2] = -0.3853;
498 fNonLinearityParams[3] = 0.5423;
499 fNonLinearityParams[4] = -0.4335;
502 if(fNonLinearityFunction == kPi0GammaGamma)
504 fNonLinearityParams[0] = 1.04;
505 fNonLinearityParams[1] = -0.1445;
506 fNonLinearityParams[2] = 1.046;
509 if(fNonLinearityFunction == kPi0GammaConversion)
511 fNonLinearityParams[0] = 0.139393;
512 fNonLinearityParams[1] = 0.0566186;
513 fNonLinearityParams[2] = 0.982133;
516 if(fNonLinearityFunction == kBeamTest)
518 if(fNonLinearThreshold == 30)
520 fNonLinearityParams[0] = 1.007;
521 fNonLinearityParams[1] = 0.894;
522 fNonLinearityParams[2] = 0.246;
524 if(fNonLinearThreshold == 45)
526 fNonLinearityParams[0] = 1.003;
527 fNonLinearityParams[1] = 0.719;
528 fNonLinearityParams[2] = 0.334;
530 if(fNonLinearThreshold == 75)
532 fNonLinearityParams[0] = 1.002;
533 fNonLinearityParams[1] = 0.797;
534 fNonLinearityParams[2] = 0.358;
538 if(fNonLinearityFunction == kBeamTestCorrected)
540 fNonLinearityParams[0] = 0.99078;
541 fNonLinearityParams[1] = 0.161499;
542 fNonLinearityParams[2] = 0.655166;
543 fNonLinearityParams[3] = 0.134101;
544 fNonLinearityParams[4] = 163.282;
545 fNonLinearityParams[5] = 23.6904;
546 fNonLinearityParams[6] = 0.978;
550 //__________________________________________________
551 Float_t AliEMCALRecoUtils::GetDepth(const Float_t energy, const Int_t iParticle, const Int_t iSM) const
553 //Calculate shower depth for a given cluster energy and particle type
563 depth = x0 * (TMath::Log(energy*1000/ ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
567 depth = x0 * (TMath::Log(energy*1000/ ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
574 gGeoManager->cd("ALIC_1/XEN1_1");
575 TGeoNode *geoXEn1 = gGeoManager->GetCurrentNode();
576 TGeoNodeMatrix *geoSM = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
578 TGeoVolume *geoSMVol = geoSM->GetVolume();
579 TGeoShape *geoSMShape = geoSMVol->GetShape();
580 TGeoBBox *geoBox = dynamic_cast<TGeoBBox *>(geoSMShape);
581 if(geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
582 else AliFatal("Null GEANT box");
583 }else AliFatal("NULL GEANT node matrix");
586 depth = x0 * (TMath::Log(energy*1000 / ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
592 depth = x0 * (TMath::Log(energy*1000 / ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
599 //__________________________________________________
600 void AliEMCALRecoUtils::GetMaxEnergyCell(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu,
601 Int_t & absId, Int_t& iSupMod, Int_t& ieta, Int_t& iphi, Bool_t &shared)
603 //For a given CaloCluster gets the absId of the cell
604 //with maximum energy deposit.
607 Double_t eCell = -1.;
608 Float_t fraction = 1.;
609 Float_t recalFactor = 1.;
610 Int_t cellAbsId = -1 ;
618 AliInfo("Cluster pointer null!");
619 absId=-1; iSupMod0=-1, ieta = -1; iphi = -1; shared = -1;
623 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
624 cellAbsId = clu->GetCellAbsId(iDig);
625 fraction = clu->GetCellAmplitudeFraction(iDig);
626 //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
627 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
628 geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta);
629 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
630 if(iDig==0) iSupMod0=iSupMod;
631 else if(iSupMod0!=iSupMod) {
633 //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
635 if(IsRecalibrationOn()) {
636 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
638 eCell = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
639 //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
643 //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
647 //Get from the absid the supermodule, tower and eta/phi numbers
648 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
649 //Gives SuperModule and Tower numbers
650 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
651 iIphi, iIeta,iphi,ieta);
652 //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
653 //printf("Max end---\n");
657 //________________________________________________________________
658 void AliEMCALRecoUtils::InitEMCALRecalibrationFactors(){
659 //Init EMCAL recalibration factors
660 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
661 //In order to avoid rewriting the same histograms
662 Bool_t oldStatus = TH1::AddDirectoryStatus();
663 TH1::AddDirectory(kFALSE);
665 fEMCALRecalibrationFactors = new TObjArray(10);
666 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));
667 //Init the histograms with 1
668 for (Int_t sm = 0; sm < 10; sm++) {
669 for (Int_t i = 0; i < 48; i++) {
670 for (Int_t j = 0; j < 24; j++) {
671 SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
675 fEMCALRecalibrationFactors->SetOwner(kTRUE);
676 fEMCALRecalibrationFactors->Compress();
678 //In order to avoid rewriting the same histograms
679 TH1::AddDirectory(oldStatus);
683 //________________________________________________________________
684 void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap(){
685 //Init EMCAL bad channels map
686 AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
687 //In order to avoid rewriting the same histograms
688 Bool_t oldStatus = TH1::AddDirectoryStatus();
689 TH1::AddDirectory(kFALSE);
691 fEMCALBadChannelMap = new TObjArray(10);
692 //TH2F * hTemp = new TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
693 for (int i = 0; i < 10; i++) {
694 fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
699 fEMCALBadChannelMap->SetOwner(kTRUE);
700 fEMCALBadChannelMap->Compress();
702 //In order to avoid rewriting the same histograms
703 TH1::AddDirectory(oldStatus);
706 //________________________________________________________________
707 void AliEMCALRecoUtils::RecalibrateClusterEnergy(AliEMCALGeometry* geom, AliVCluster * cluster, AliVCaloCells * cells){
708 // Recalibrate the cluster energy, considering the recalibration map and the energy of the cells that compose the cluster.
711 AliInfo("Cluster pointer null!");
715 //Get the cluster number of cells and list of absId, check what kind of cluster do we have.
716 UShort_t * index = cluster->GetCellsAbsId() ;
717 Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
718 Int_t ncells = cluster->GetNCells();
720 //Initialize some used variables
723 Int_t icol = -1, irow = -1, imod=1;
724 Float_t factor = 1, frac = 0;
726 //Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
727 for(Int_t icell = 0; icell < ncells; icell++){
728 absId = index[icell];
729 frac = fraction[icell];
730 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
731 Int_t iTower = -1, iIphi = -1, iIeta = -1;
732 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
733 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
734 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
735 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
736 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
737 imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
739 energy += cells->GetCellAmplitude(absId)*factor*frac;
743 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f\n",cluster->E(),energy));
745 cluster->SetE(energy);
750 //__________________________________________________
751 void AliEMCALRecoUtils::RecalculateClusterPosition(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
753 //For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
756 AliInfo("Cluster pointer null!");
760 if (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
761 else if(fPosAlgo==kPosTowerIndex) RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
762 else AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
766 //__________________________________________________
767 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
769 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
770 // The algorithm is a copy of what is done in AliEMCALRecPoint
773 Float_t fraction = 1.;
774 Float_t recalFactor = 1.;
777 Int_t iTower = -1, iIphi = -1, iIeta = -1;
778 Int_t iSupModMax = -1, iSM=-1, iphi = -1, ieta = -1;
779 Float_t weight = 0., totalWeight=0.;
780 Float_t newPos[3] = {0,0,0};
781 Double_t pLocal[3], pGlobal[3];
782 Bool_t shared = kFALSE;
784 Float_t clEnergy = clu->E(); //Energy already recalibrated previously
785 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
786 Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
788 //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
790 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
791 absId = clu->GetCellAbsId(iDig);
792 fraction = clu->GetCellAmplitudeFraction(iDig);
793 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
794 geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta);
795 geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);
797 if(IsRecalibrationOn()) {
798 recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
800 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
802 weight = GetCellWeight(eCell,clEnergy);
803 //printf("cell energy %f, weight %f\n",eCell,weight);
804 totalWeight += weight;
805 geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
806 //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
807 geom->GetGlobal(pLocal,pGlobal,iSupModMax);
808 //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
810 for(int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
815 for(int i=0; i<3; i++ ) newPos[i] /= totalWeight;
818 //Float_t pos[]={0,0,0};
819 //clu->GetPosition(pos);
820 //printf("OldPos : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
821 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
823 if(iSupModMax > 1) {//sector 1
824 newPos[0] +=fMisalTransShift[3];//-=3.093;
825 newPos[1] +=fMisalTransShift[4];//+=6.82;
826 newPos[2] +=fMisalTransShift[5];//+=1.635;
827 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
831 newPos[0] +=fMisalTransShift[0];//+=1.134;
832 newPos[1] +=fMisalTransShift[1];//+=8.2;
833 newPos[2] +=fMisalTransShift[2];//+=1.197;
834 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
837 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
839 clu->SetPosition(newPos);
843 //__________________________________________________
844 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
846 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
847 // The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position
850 Float_t fraction = 1.;
851 Float_t recalFactor = 1.;
855 Int_t iIphi = -1, iIeta = -1;
856 Int_t iSupMod = -1, iSupModMax = -1;
857 Int_t iphi = -1, ieta =-1;
858 Bool_t shared = kFALSE;
860 Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
861 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
862 Float_t depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
864 Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
865 Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
866 Int_t startingSM = -1;
868 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
869 absId = clu->GetCellAbsId(iDig);
870 fraction = clu->GetCellAmplitudeFraction(iDig);
871 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
872 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
873 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
875 if (iDig==0) startingSM = iSupMod;
876 else if(iSupMod != startingSM) areInSameSM = kFALSE;
878 eCell = cells->GetCellAmplitude(absId);
880 if(IsRecalibrationOn()) {
881 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
883 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
885 weight = GetCellWeight(eCell,clEnergy);
886 if(weight < 0) weight = 0;
887 totalWeight += weight;
888 weightedCol += ieta*weight;
889 weightedRow += iphi*weight;
891 //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
895 Float_t xyzNew[]={0.,0.,0.};
896 if(areInSameSM == kTRUE) {
897 //printf("In Same SM\n");
898 weightedCol = weightedCol/totalWeight;
899 weightedRow = weightedRow/totalWeight;
900 geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
903 //printf("In Different SM\n");
904 geom->RecalculateTowerPosition(iphi, ieta, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
907 clu->SetPosition(xyzNew);
911 //____________________________________________________________________________
912 void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster){
914 //re-evaluate distance to bad channel with updated bad map
916 if(!fRecalDistToBadChannels) return;
919 AliInfo("Cluster pointer null!");
923 //Get channels map of the supermodule where the cluster is.
924 Int_t absIdMax = -1, iSupMod =-1, icolM = -1, irowM = -1;
925 Bool_t shared = kFALSE;
926 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSupMod, icolM, irowM, shared);
927 TH2D* hMap = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
930 Float_t minDist = 10000.;
933 //Loop on tower status map
934 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
935 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
936 //Check if tower is bad.
937 if(hMap->GetBinContent(icol,irow)==0) continue;
938 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
939 // iSupMod,icol, irow, icolM,irowM);
941 dRrow=TMath::Abs(irowM-irow);
942 dRcol=TMath::Abs(icolM-icol);
943 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
945 //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
952 //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
957 //The only possible combinations are (0,1), (2,3) ... (8,9)
958 if(iSupMod%2) iSupMod2 = iSupMod-1;
959 else iSupMod2 = iSupMod+1;
960 hMap2 = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
962 //Loop on tower status map of second super module
963 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
964 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
965 //Check if tower is bad.
966 if(hMap2->GetBinContent(icol,irow)==0) continue;
967 //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",
968 // iSupMod2,icol, irow,iSupMod,icolM,irowM);
970 dRrow=TMath::Abs(irow-irowM);
973 dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
976 dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
979 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
980 if(dist < minDist) minDist = dist;
985 }// shared cluster in 2 SuperModules
987 AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
988 cluster->SetDistanceToBadChannel(minDist);
992 //____________________________________________________________________________
993 void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster){
995 //re-evaluate identification parameters with bayesian
998 AliInfo("Cluster pointer null!");
1002 if ( cluster->GetM02() != 0)
1003 fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
1005 Float_t pidlist[AliPID::kSPECIESN+1];
1006 for(Int_t i = 0; i < AliPID::kSPECIESN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
1008 cluster->SetPID(pidlist);
1012 //____________________________________________________________________________
1013 void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster)
1015 // Calculates new center of gravity in the local EMCAL-module coordinates
1016 // and tranfers into global ALICE coordinates
1017 // Calculates Dispersion and main axis
1020 AliInfo("Cluster pointer null!");
1026 Double_t eCell = 0.;
1027 Float_t fraction = 1.;
1028 Float_t recalFactor = 1.;
1036 Double_t etai = -1.;
1037 Double_t phii = -1.;
1044 Double_t xmean = 0.;
1045 Double_t zmean = 0.;
1048 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1050 //Get from the absid the supermodule, tower and eta/phi numbers
1051 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1052 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1054 //Get the cell energy, if recalibration is on, apply factors
1055 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1056 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1057 if(IsRecalibrationOn()) {
1058 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1060 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1062 if(cluster->E() > 0 && eCell > 0){
1064 w = GetCellWeight(eCell,cluster->E());
1066 etai=(Double_t)ieta;
1067 phii=(Double_t)iphi;
1072 dxx += w * etai * etai ;
1074 dzz += w * phii * phii ;
1076 dxz += w * etai * phii ;
1080 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1083 //Normalize to the weight
1089 AliError(Form("Wrong weight %f\n", wtot));
1091 //Calculate dispersion
1092 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1094 //Get from the absid the supermodule, tower and eta/phi numbers
1095 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1096 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1098 //Get the cell energy, if recalibration is on, apply factors
1099 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1100 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1101 if(IsRecalibrationOn()) {
1102 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1104 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1106 if(cluster->E() > 0 && eCell > 0){
1108 w = GetCellWeight(eCell,cluster->E());
1110 etai=(Double_t)ieta;
1111 phii=(Double_t)iphi;
1112 if(w > 0.0) d += w*((etai-xmean)*(etai-xmean)+(phii-zmean)*(phii-zmean));
1115 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1118 //Normalize to the weigth and set shower shape parameters
1119 if (wtot > 0 && nstat > 1) {
1124 dxx -= xmean * xmean ;
1125 dzz -= zmean * zmean ;
1126 dxz -= xmean * zmean ;
1127 cluster->SetM02(0.5 * (dxx + dzz) + TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1128 cluster->SetM20(0.5 * (dxx + dzz) - TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1132 cluster->SetM20(0.) ;
1133 cluster->SetM02(0.) ;
1137 cluster->SetDispersion(TMath::Sqrt(d)) ;
1139 cluster->SetDispersion(0) ;
1142 //____________________________________________________________________________
1143 void AliEMCALRecoUtils::FindMatches(AliVEvent *event,TObjArray * clusterArr, AliEMCALGeometry *geom)
1145 //This function should be called before the cluster loop
1146 //Before call this function, please recalculate the cluster positions
1147 //Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR
1148 //Store matched cluster indexes and residuals
1150 fMatchedTrackIndex->Reset();
1151 fMatchedClusterIndex->Reset();
1152 fResidualPhi->Reset();
1153 fResidualEta->Reset();
1155 fMatchedTrackIndex->Set(500);
1156 fMatchedClusterIndex->Set(500);
1157 fResidualPhi->Set(500);
1158 fResidualEta->Set(500);
1160 AliESDEvent* esdevent = dynamic_cast<AliESDEvent*> (event);
1161 AliAODEvent* aodevent = dynamic_cast<AliAODEvent*> (event);
1165 for (Int_t i=0; i<21;i++) cv[i]=0;
1166 for(Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
1168 AliExternalTrackParam *trackParam = 0;
1170 //If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner
1173 AliESDtrack *esdTrack = esdevent->GetTrack(itr);
1174 if(!esdTrack || !IsAccepted(esdTrack)) continue;
1175 if(esdTrack->Pt()<fCutMinTrackPt) continue;
1176 const AliESDfriendTrack* friendTrack = esdTrack->GetFriendTrack();
1177 if(friendTrack && friendTrack->GetTPCOut())
1179 //Use TPC Out as starting point if it is available
1180 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
1184 //Otherwise use TPC inner
1185 trackParam = const_cast<AliExternalTrackParam*>(esdTrack->GetInnerParam());
1189 //If the input event is AOD, the starting point for extrapolation is at vertex
1190 //AOD tracks are selected according to its bit.
1193 AliAODTrack *aodTrack = aodevent->GetTrack(itr);
1194 if(!aodTrack) continue;
1195 if(!aodTrack->TestFilterMask(fAODFilterMask)) continue; //Select AOD tracks that fulfill GetStandardITSTPCTrackCuts2010()
1196 if(aodTrack->Pt()<fCutMinTrackPt) continue;
1197 Double_t pos[3],mom[3];
1198 aodTrack->GetXYZ(pos);
1199 aodTrack->GetPxPyPz(mom);
1200 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()));
1201 trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
1204 //Return if the input data is not "AOD" or "ESD"
1207 printf("Wrong input data type! Should be \"AOD\" or \"ESD\"\n");
1211 if(!trackParam) continue;
1213 Float_t dRMax = fCutR, dEtaMax=fCutEta, dPhiMax=fCutPhi;
1215 if(!clusterArr){// get clusters from event
1216 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1218 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1219 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1220 AliExternalTrackParam trkPamTmp(*trackParam);//Retrieve the starting point every time before the extrapolation
1221 Float_t tmpEta=-999, tmpPhi=-999;
1222 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1225 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1234 else if(fCutEtaPhiSeparate)
1236 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1245 printf("Error: please specify your cut criteria\n");
1246 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1247 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1248 if(aodevent && trackParam) delete trackParam;
1253 else { // external cluster array, not from ESD event
1254 for(Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
1256 AliVCluster *cluster = dynamic_cast<AliVCluster*> (clusterArr->At(icl)) ;
1258 AliInfo("Cluster not found!!!");
1261 if(!cluster->IsEMCAL()) continue;
1262 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1263 Float_t tmpEta=-999, tmpPhi=-999;
1264 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1267 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1276 else if(fCutEtaPhiSeparate)
1278 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1287 printf("Error: please specify your cut criteria\n");
1288 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1289 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1290 if(aodevent && trackParam) delete trackParam;
1294 }// external list of clusters
1298 fMatchedTrackIndex ->AddAt(itr,matched);
1299 fMatchedClusterIndex->AddAt(index,matched);
1300 fResidualEta ->AddAt(dEtaMax,matched);
1301 fResidualPhi ->AddAt(dPhiMax,matched);
1304 if(aodevent && trackParam) delete trackParam;
1307 AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
1309 fMatchedTrackIndex ->Set(matched);
1310 fMatchedClusterIndex->Set(matched);
1311 fResidualPhi ->Set(matched);
1312 fResidualEta ->Set(matched);
1315 //________________________________________________________________________________
1316 Int_t AliEMCALRecoUtils::FindMatchedCluster(AliESDtrack *track, AliVEvent *event, AliEMCALGeometry *geom)
1319 // This function returns the index of matched cluster to input track
1320 // Returns -1 if no match is found
1323 Float_t dRMax = fCutR, dEtaMax = fCutEta, dPhiMax = fCutPhi;
1326 AliExternalTrackParam *trackParam=0;
1327 const AliESDfriendTrack* friendTrack = track->GetFriendTrack();
1328 if(friendTrack && friendTrack->GetTPCOut())
1329 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
1331 trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
1333 if(!trackParam) return index;
1334 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1336 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1337 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1338 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1339 Float_t tmpEta=-999, tmpPhi=-999;
1340 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1343 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1352 else if(fCutEtaPhiSeparate)
1354 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1363 printf("Error: please specify your cut criteria\n");
1364 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1365 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1372 //________________________________________________________________________________
1373 Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, AliVCluster *cluster, Float_t &tmpEta, Float_t &tmpPhi)
1376 //Return the residual by extrapolating a track to a cluster
1378 if(!trkParam || !cluster) return kFALSE;
1381 cluster->GetPosition(clsPos); //Has been recalculated
1382 TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
1383 Double_t alpha = ((int)(vec.Phi()*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
1384 vec.RotateZ(-alpha); //Rotate the cluster to the local extrapolation coordinate system
1385 trkParam->Rotate(alpha); //Rotate the track to the same local extrapolation system
1386 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), fMass, fStep,kFALSE, 0.8, -1)) return kFALSE;
1387 trkParam->GetXYZ(trkPos); //Get the extrapolated global position
1389 TVector3 clsPosVec(clsPos[0],clsPos[1],clsPos[2]);
1390 TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
1392 Float_t clsPhi = (Float_t)clsPosVec.Phi();
1393 if(clsPhi<0) clsPhi+=2*TMath::Pi();
1394 Float_t trkPhi = (Float_t)trkPosVec.Phi();
1395 if(trkPhi<0) trkPhi+=2*TMath::Pi();
1396 tmpPhi = clsPhi-trkPhi; // track cluster matching
1397 tmpEta = clsPosVec.Eta()-trkPosVec.Eta(); // track cluster matching
1402 //________________________________________________________________________________
1403 void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex, Float_t &dEta, Float_t &dPhi)
1405 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1406 //Get the residuals dEta and dPhi for this cluster to the closest track
1407 //Works with ESDs and AODs
1409 if( FindMatchedPosForCluster(clsIndex) >= 999 )
1411 AliDebug(2,"No matched tracks found!\n");
1416 dEta = fResidualEta->At(FindMatchedPosForCluster(clsIndex));
1417 dPhi = fResidualPhi->At(FindMatchedPosForCluster(clsIndex));
1419 //________________________________________________________________________________
1420 void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dEta, Float_t &dPhi)
1422 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1423 //Get the residuals dEta and dPhi for this track to the closest cluster
1424 //Works with ESDs and AODs
1426 if( FindMatchedPosForTrack(trkIndex) >= 999 )
1428 AliDebug(2,"No matched cluster found!\n");
1433 dEta = fResidualEta->At(FindMatchedPosForTrack(trkIndex));
1434 dPhi = fResidualPhi->At(FindMatchedPosForTrack(trkIndex));
1437 //__________________________________________________________
1438 Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
1440 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1441 //Get the index of matched track to this cluster
1442 //Works with ESDs and AODs
1444 if(IsClusterMatched(clsIndex))
1445 return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
1450 //__________________________________________________________
1451 Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
1453 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1454 //Get the index of matched cluster to this track
1455 //Works with ESDs and AODs
1457 if(IsTrackMatched(trkIndex))
1458 return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
1463 //__________________________________________________
1464 Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex) const
1466 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1467 //Returns if the cluster has a match
1468 if(FindMatchedPosForCluster(clsIndex) < 999)
1474 //__________________________________________________
1475 Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex) const
1477 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1478 //Returns if the track has a match
1479 if(FindMatchedPosForTrack(trkIndex) < 999)
1485 //__________________________________________________________
1486 UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
1488 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1489 //Returns the position of the match in the fMatchedClusterIndex array
1490 Float_t tmpR = fCutR;
1493 for(Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++)
1495 if(fMatchedClusterIndex->At(i)==clsIndex)
1497 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1502 AliDebug(3,Form("Matched cluster index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedClusterIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1509 //__________________________________________________________
1510 UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
1512 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1513 //Returns the position of the match in the fMatchedTrackIndex array
1514 Float_t tmpR = fCutR;
1517 for(Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++)
1519 if(fMatchedTrackIndex->At(i)==trkIndex)
1521 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1526 AliDebug(3,Form("Matched track index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedTrackIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1533 //__________________________________________________________
1534 Bool_t AliEMCALRecoUtils::IsGoodCluster(AliVCluster *cluster, AliEMCALGeometry *geom, AliVCaloCells* cells)
1536 // check if the cluster survives some quality cut
1539 Bool_t isGood=kTRUE;
1540 if(!cluster || !cluster->IsEMCAL()) return kFALSE;
1541 if(ClusterContainsBadChannel(geom,cluster->GetCellsAbsId(),cluster->GetNCells())) return kFALSE;
1542 if(!CheckCellFiducialRegion(geom,cluster,cells)) return kFALSE;
1543 if(fRejectExoticCluster && IsExoticCluster(cluster)) return kFALSE;
1548 //__________________________________________________________
1549 Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
1551 // Given a esd track, return whether the track survive all the cuts
1553 // The different quality parameter are first
1554 // retrieved from the track. then it is found out what cuts the
1555 // track did not survive and finally the cuts are imposed.
1557 UInt_t status = esdTrack->GetStatus();
1559 Int_t nClustersITS = esdTrack->GetITSclusters(0);
1560 Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
1562 Float_t chi2PerClusterITS = -1;
1563 Float_t chi2PerClusterTPC = -1;
1564 if (nClustersITS!=0)
1565 chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
1566 if (nClustersTPC!=0)
1567 chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
1571 Float_t maxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); //This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
1572 //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
1573 SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
1578 esdTrack->GetImpactParameters(b,bCov);
1579 if (bCov[0]<=0 || bCov[2]<=0) {
1580 AliDebug(1, "Estimated b resolution lower or equal zero!");
1581 bCov[0]=0; bCov[2]=0;
1584 Float_t dcaToVertexXY = b[0];
1585 Float_t dcaToVertexZ = b[1];
1586 Float_t dcaToVertex = -1;
1588 if (fCutDCAToVertex2D)
1589 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY/fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + dcaToVertexZ*dcaToVertexZ/fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ);
1591 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
1595 Bool_t cuts[kNCuts];
1596 for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
1598 // track quality cuts
1599 if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
1601 if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
1603 if (nClustersTPC<fCutMinNClusterTPC)
1605 if (nClustersITS<fCutMinNClusterITS)
1607 if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC)
1609 if (chi2PerClusterITS>fCutMaxChi2PerClusterITS)
1611 if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
1613 if (fCutDCAToVertex2D && dcaToVertex > 1)
1615 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
1617 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ) > fCutMaxDCAToVertexZ)
1620 //Require at least one SPD point + anything else in ITS
1621 if( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
1625 for (Int_t i=0; i<kNCuts; i++)
1626 if (cuts[i]) {cut = kTRUE;}
1634 //__________________________________________________
1635 void AliEMCALRecoUtils::InitTrackCuts()
1637 //Intilize the track cut criteria
1638 //By default these cuts are set according to AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
1639 //Also you can customize the cuts using the setters
1642 SetMinNClustersTPC(70);
1643 SetMaxChi2PerClusterTPC(4);
1644 SetAcceptKinkDaughters(kFALSE);
1645 SetRequireTPCRefit(kTRUE);
1648 SetRequireITSRefit(kTRUE);
1649 SetMaxDCAToVertexZ(2);
1650 SetDCAToVertex2D(kFALSE);
1651 SetMaxChi2PerClusterITS(); //which by default sets the value to 1e10.
1652 SetMinNClustersITS();
1655 //___________________________________________________
1656 void AliEMCALRecoUtils::Print(const Option_t *) const
1660 printf("AliEMCALRecoUtils Settings: \n");
1661 printf("Misalignment shifts\n");
1662 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,
1663 fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
1664 fMisalRotShift[i*3], fMisalRotShift[i*3+1], fMisalRotShift[i*3+2] );
1665 printf("Non linearity function %d, parameters:\n", fNonLinearityFunction);
1666 for(Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
1668 printf("Position Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
1670 printf("Matching criteria: ");
1673 printf("sqrt(dEta^2+dPhi^2)<%2.2f\n",fCutR);
1675 else if(fCutEtaPhiSeparate)
1677 printf("dEta<%2.2f, dPhi<%2.2f\n",fCutEta,fCutPhi);
1682 printf("please specify your cut criteria\n");
1683 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1684 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1687 printf("Mass hypothesis = %2.3f[GeV/c^2], extrapolation step = %2.2f[cm]\n",fMass,fStep);
1689 printf("Track cuts: \n");
1690 printf("Minimum track pT: %1.2f\n",fCutMinTrackPt);
1691 printf("AOD track selection mask: %d\n",fAODFilterMask);
1692 printf("TPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
1693 printf("AcceptKinks = %d\n",fCutAcceptKinkDaughters);
1694 printf("MinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
1695 printf("MaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
1696 printf("DCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
1700 //_____________________________________________________________________
1701 void AliEMCALRecoUtils::SetTimeDependentCorrections(Int_t runnumber){
1702 //Get EMCAL time dependent corrections from file and put them in the recalibration histograms
1703 //Do it only once and only if it is requested
1705 if(!fUseTimeCorrectionFactors) return;
1706 if(fTimeCorrectionFactorsSet) return;
1708 printf("AliEMCALRecoUtils::GetTimeDependentCorrections() - Get Correction Factors for Run number %d\n",runnumber);
1710 AliEMCALCalibTimeDepCorrection *corr = new AliEMCALCalibTimeDepCorrection();
1711 corr->ReadRootInfo(Form("CorrectionFiles/Run%d_Correction.root",runnumber));
1713 SwitchOnRecalibration();
1714 for(Int_t ism = 0; ism < 4; ism++){
1715 for(Int_t icol = 0; icol < 48; icol++){
1716 for(Int_t irow = 0; irow < 24; irow++){
1717 Float_t orgRecalFactor = GetEMCALChannelRecalibrationFactors(ism)->GetBinContent(icol,irow);
1718 Float_t newRecalFactor = orgRecalFactor*corr->GetCorrection(ism, icol,irow,0);
1719 GetEMCALChannelRecalibrationFactors(ism)->SetBinContent(icol,irow,newRecalFactor);
1720 //printf("ism %d, icol %d, irow %d, corrections : org %f, time dep %f, final %f (org*time %f)\n",ism, icol, irow,
1721 // orgRecalFactor, corr->GetCorrection(ism, icol,irow,0),
1722 // (GetEMCALChannelRecalibrationFactors(ism))->GetBinContent(icol,irow),newRecalFactor);
1726 fTimeCorrectionFactorsSet = kTRUE;