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(50),
75 fRejectExoticCluster(kFALSE),
76 fTrackCutsType(kTPCOnlyCut), fCutMinTrackPt(0), fCutMinNClusterTPC(-1), fCutMinNClusterITS(-1), fCutMaxChi2PerClusterTPC(1e10), fCutMaxChi2PerClusterITS(1e10),
77 fCutRequireTPCRefit(kFALSE), fCutRequireITSRefit(kFALSE), fCutAcceptKinkDaughters(kFALSE),
78 fCutMaxDCAToVertexXY(1e10), fCutMaxDCAToVertexZ(1e10),fCutDCAToVertex2D(kFALSE),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();
117 fPIDUtils = new AliEMCALPIDUtils();
120 //______________________________________________________________________
121 AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco)
122 : TNamed(reco), fNonLinearityFunction(reco.fNonLinearityFunction),
123 fParticleType(reco.fParticleType), fPosAlgo(reco.fPosAlgo), fW0(reco.fW0), fNonLinearThreshold(reco.fNonLinearThreshold),
124 fRecalibration(reco.fRecalibration),fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
125 fRemoveBadChannels(reco.fRemoveBadChannels),fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
126 fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
127 fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder),fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
128 fAODFilterMask(reco.fAODFilterMask),
129 fMatchedTrackIndex(reco.fMatchedTrackIndex?new TArrayI(*reco.fMatchedTrackIndex):0x0),
130 fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
131 fResidualEta(reco.fResidualEta?new TArrayF(*reco.fResidualEta):0x0),
132 fResidualPhi(reco.fResidualPhi?new TArrayF(*reco.fResidualPhi):0x0),
133 fCutEtaPhiSum(reco.fCutEtaPhiSum), fCutEtaPhiSeparate(reco.fCutEtaPhiSeparate), fCutR(reco.fCutR), fCutEta(reco.fCutEta), fCutPhi(reco.fCutPhi),
134 fMass(reco.fMass), fStep(reco.fStep),
135 fRejectExoticCluster(reco.fRejectExoticCluster),
136 fTrackCutsType(reco.fTrackCutsType), fCutMinTrackPt(reco.fCutMinTrackPt), fCutMinNClusterTPC(reco.fCutMinNClusterTPC), fCutMinNClusterITS(reco.fCutMinNClusterITS),
137 fCutMaxChi2PerClusterTPC(reco.fCutMaxChi2PerClusterTPC), fCutMaxChi2PerClusterITS(reco.fCutMaxChi2PerClusterITS),
138 fCutRequireTPCRefit(reco.fCutRequireTPCRefit), fCutRequireITSRefit(reco.fCutRequireITSRefit),
139 fCutAcceptKinkDaughters(reco.fCutAcceptKinkDaughters),
140 fCutMaxDCAToVertexXY(reco.fCutMaxDCAToVertexXY), fCutMaxDCAToVertexZ(reco.fCutMaxDCAToVertexZ),fCutDCAToVertex2D(reco.fCutDCAToVertex2D),
141 fPIDUtils(reco.fPIDUtils),
142 fUseTimeCorrectionFactors(reco.fUseTimeCorrectionFactors), fTimeCorrectionFactorsSet(reco.fTimeCorrectionFactorsSet)
146 for(Int_t i = 0; i < 15 ; i++) {
147 fMisalRotShift[i] = reco.fMisalRotShift[i];
148 fMisalTransShift[i] = reco.fMisalTransShift[i];
150 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
155 //______________________________________________________________________
156 AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco)
158 //Assignment operator
160 if(this == &reco)return *this;
161 ((TNamed *)this)->operator=(reco);
163 fNonLinearityFunction = reco.fNonLinearityFunction;
164 fParticleType = reco.fParticleType;
165 fPosAlgo = reco.fPosAlgo;
167 fNonLinearThreshold = reco.fNonLinearThreshold;
168 fRecalibration = reco.fRecalibration;
169 fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
170 fRemoveBadChannels = reco.fRemoveBadChannels;
171 fRecalDistToBadChannels = reco.fRecalDistToBadChannels;
172 fEMCALBadChannelMap = reco.fEMCALBadChannelMap;
173 fNCellsFromEMCALBorder = reco.fNCellsFromEMCALBorder;
174 fNoEMCALBorderAtEta0 = reco.fNoEMCALBorderAtEta0;
177 for(Int_t i = 0; i < 15 ; i++) {fMisalTransShift[i] = reco.fMisalTransShift[i]; fMisalRotShift[i] = reco.fMisalRotShift[i];}
178 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
180 fAODFilterMask = reco.fAODFilterMask;
182 fCutEtaPhiSum = reco.fCutEtaPhiSum;
183 fCutEtaPhiSeparate = reco.fCutEtaPhiSeparate;
185 fCutEta = reco.fCutEta;
186 fCutPhi = reco.fCutPhi;
189 fRejectExoticCluster = reco.fRejectExoticCluster;
191 fTrackCutsType = reco.fTrackCutsType;
192 fCutMinTrackPt = reco.fCutMinTrackPt;
193 fCutMinNClusterTPC = reco.fCutMinNClusterTPC;
194 fCutMinNClusterITS = reco.fCutMinNClusterITS;
195 fCutMaxChi2PerClusterTPC = reco.fCutMaxChi2PerClusterTPC;
196 fCutMaxChi2PerClusterITS = reco.fCutMaxChi2PerClusterITS;
197 fCutRequireTPCRefit = reco.fCutRequireTPCRefit;
198 fCutRequireITSRefit = reco.fCutRequireITSRefit;
199 fCutAcceptKinkDaughters = reco.fCutAcceptKinkDaughters;
200 fCutMaxDCAToVertexXY = reco.fCutMaxDCAToVertexXY;
201 fCutMaxDCAToVertexZ = reco.fCutMaxDCAToVertexZ;
202 fCutDCAToVertex2D = reco.fCutDCAToVertex2D;
204 fPIDUtils = reco.fPIDUtils;
206 fUseTimeCorrectionFactors = reco.fUseTimeCorrectionFactors;
207 fTimeCorrectionFactorsSet = reco.fTimeCorrectionFactorsSet;
210 if(reco.fResidualEta){
211 // assign or copy construct
213 *fResidualEta = *reco.fResidualEta;
215 else fResidualEta = new TArrayF(*reco.fResidualEta);
218 if(fResidualEta)delete fResidualEta;
222 if(reco.fResidualPhi){
223 // assign or copy construct
225 *fResidualPhi = *reco.fResidualPhi;
227 else fResidualPhi = new TArrayF(*reco.fResidualPhi);
230 if(fResidualPhi)delete fResidualPhi;
234 if(reco.fMatchedTrackIndex){
235 // assign or copy construct
236 if(fMatchedTrackIndex){
237 *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
239 else fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
242 if(fMatchedTrackIndex)delete fMatchedTrackIndex;
243 fMatchedTrackIndex = 0;
246 if(reco.fMatchedClusterIndex){
247 // assign or copy construct
248 if(fMatchedClusterIndex){
249 *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
251 else fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
254 if(fMatchedClusterIndex)delete fMatchedClusterIndex;
255 fMatchedClusterIndex = 0;
262 //__________________________________________________
263 AliEMCALRecoUtils::~AliEMCALRecoUtils()
267 if(fEMCALRecalibrationFactors) {
268 fEMCALRecalibrationFactors->Clear();
269 delete fEMCALRecalibrationFactors;
272 if(fEMCALBadChannelMap) {
273 fEMCALBadChannelMap->Clear();
274 delete fEMCALBadChannelMap;
277 delete fMatchedTrackIndex ;
278 delete fMatchedClusterIndex ;
279 delete fResidualEta ;
280 delete fResidualPhi ;
284 //_______________________________________________________________
285 Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(AliEMCALGeometry* geom, AliVCluster* cluster, AliVCaloCells* cells)
287 // Given the list of AbsId of the cluster, get the maximum cell and
288 // check if there are fNCellsFromBorder from the calorimeter border
291 AliInfo("Cluster pointer null!");
295 //If the distance to the border is 0 or negative just exit accept all clusters
296 if(cells->GetType()==AliVCaloCells::kEMCALCell && fNCellsFromEMCALBorder <= 0 ) return kTRUE;
298 Int_t absIdMax = -1, iSM =-1, ieta = -1, iphi = -1;
299 Bool_t shared = kFALSE;
300 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSM, ieta, iphi, shared);
302 AliDebug(2,Form("Cluster Max AbsId %d, Cell Energy %2.2f, Cluster Energy %2.2f, Ncells from border %d, EMCAL eta=0 %d\n",
303 absIdMax, cells->GetCellAmplitude(absIdMax), cluster->E(), fNCellsFromEMCALBorder, fNoEMCALBorderAtEta0));
305 if(absIdMax==-1) return kFALSE;
307 //Check if the cell is close to the borders:
308 Bool_t okrow = kFALSE;
309 Bool_t okcol = kFALSE;
311 if(iSM < 0 || iphi < 0 || ieta < 0 ) {
312 AliFatal(Form("Negative value for super module: %d, or cell ieta: %d, or cell iphi: %d, check EMCAL geometry name\n",
318 if(iphi >= fNCellsFromEMCALBorder && iphi < 24-fNCellsFromEMCALBorder) okrow =kTRUE;
321 if(iphi >= fNCellsFromEMCALBorder && iphi < 12-fNCellsFromEMCALBorder) okrow =kTRUE;
325 if(!fNoEMCALBorderAtEta0){
326 if(ieta > fNCellsFromEMCALBorder && ieta < 48-fNCellsFromEMCALBorder) okcol =kTRUE;
330 if(ieta >= fNCellsFromEMCALBorder) okcol = kTRUE;
333 if(ieta < 48-fNCellsFromEMCALBorder) okcol = kTRUE;
337 AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d: column? %d, row? %d\nq",
338 fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
340 if (okcol && okrow) {
341 //printf("Accept\n");
345 //printf("Reject\n");
346 AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
353 //_________________________________________________________________________________________________________
354 Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(AliEMCALGeometry* geom, UShort_t* cellList, const Int_t nCells){
355 // Check that in the cluster cells, there is no bad channel of those stored
356 // in fEMCALBadChannelMap or fPHOSBadChannelMap
358 if(!fRemoveBadChannels) return kFALSE;
359 if(!fEMCALBadChannelMap) return kFALSE;
364 for(Int_t iCell = 0; iCell<nCells; iCell++){
366 //Get the column and row
367 Int_t iTower = -1, iIphi = -1, iIeta = -1;
368 geom->GetCellIndex(cellList[iCell],imod,iTower,iIphi,iIeta);
369 if(fEMCALBadChannelMap->GetEntries() <= imod) continue;
370 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
371 if(GetEMCALChannelStatus(imod, icol, irow)){
372 AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
376 }// cell cluster loop
382 //_________________________________________________
383 Bool_t AliEMCALRecoUtils::IsExoticCluster(AliVCluster *cluster) const {
384 // Check if the cluster has high energy but small number of cells
385 // The criteria comes from Gustavo's study
389 AliInfo("Cluster pointer null!");
393 Int_t nc = cluster->GetNCells() ;
395 if ( nc > 8 ) return kFALSE ; // Good cluster, needed for 3x3 clusterizer
396 else if ( nc < 1 + cluster->E()/3. ) return kTRUE ; // Bad cluster
397 else return kFALSE ; // Good cluster
401 //__________________________________________________
402 Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster){
403 // Correct cluster energy from non linearity functions
406 AliInfo("Cluster pointer null!");
411 Float_t energy = cluster->E();
413 switch (fNonLinearityFunction) {
417 //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
418 //Double_t fNonLinearityParams[0] = 1.014;
419 //Double_t fNonLinearityParams[1] = -0.03329;
420 //Double_t fNonLinearityParams[2] = -0.3853;
421 //Double_t fNonLinearityParams[3] = 0.5423;
422 //Double_t fNonLinearityParams[4] = -0.4335;
423 energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
424 ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
425 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
431 //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
432 //Double_t fNonLinearityParams[0] = 1.04;
433 //Double_t fNonLinearityParams[1] = -0.1445;
434 //Double_t fNonLinearityParams[2] = 1.046;
435 energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
439 case kPi0GammaConversion:
441 //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
442 //fNonLinearityParams[0] = 0.139393/0.1349766;
443 //fNonLinearityParams[1] = 0.0566186;
444 //fNonLinearityParams[2] = 0.982133;
445 energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
452 //From beam test, Alexei's results, for different ZS thresholds
453 // th=30 MeV; th = 45 MeV; th = 75 MeV
454 //fNonLinearityParams[0] = 1.007; 1.003; 1.002
455 //fNonLinearityParams[1] = 0.894; 0.719; 0.797
456 //fNonLinearityParams[2] = 0.246; 0.334; 0.358
457 //Rescale the param[0] with 1.03
458 energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
463 case kBeamTestCorrected:
465 //From beam test, corrected for material between beam and EMCAL
466 //fNonLinearityParams[0] = 0.99078
467 //fNonLinearityParams[1] = 0.161499;
468 //fNonLinearityParams[2] = 0.655166;
469 //fNonLinearityParams[3] = 0.134101;
470 //fNonLinearityParams[4] = 163.282;
471 //fNonLinearityParams[5] = 23.6904;
472 //fNonLinearityParams[6] = 0.978;
473 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
479 AliDebug(2,"No correction on the energy\n");
487 //__________________________________________________
488 void AliEMCALRecoUtils::InitNonLinearityParam()
490 //Initialising Non Linearity Parameters
492 if(fNonLinearityFunction == kPi0MC)
494 fNonLinearityParams[0] = 1.014;
495 fNonLinearityParams[1] = -0.03329;
496 fNonLinearityParams[2] = -0.3853;
497 fNonLinearityParams[3] = 0.5423;
498 fNonLinearityParams[4] = -0.4335;
501 if(fNonLinearityFunction == kPi0GammaGamma)
503 fNonLinearityParams[0] = 1.04;
504 fNonLinearityParams[1] = -0.1445;
505 fNonLinearityParams[2] = 1.046;
508 if(fNonLinearityFunction == kPi0GammaConversion)
510 fNonLinearityParams[0] = 0.139393;
511 fNonLinearityParams[1] = 0.0566186;
512 fNonLinearityParams[2] = 0.982133;
515 if(fNonLinearityFunction == kBeamTest)
517 if(fNonLinearThreshold == 30)
519 fNonLinearityParams[0] = 1.007;
520 fNonLinearityParams[1] = 0.894;
521 fNonLinearityParams[2] = 0.246;
523 if(fNonLinearThreshold == 45)
525 fNonLinearityParams[0] = 1.003;
526 fNonLinearityParams[1] = 0.719;
527 fNonLinearityParams[2] = 0.334;
529 if(fNonLinearThreshold == 75)
531 fNonLinearityParams[0] = 1.002;
532 fNonLinearityParams[1] = 0.797;
533 fNonLinearityParams[2] = 0.358;
537 if(fNonLinearityFunction == kBeamTestCorrected)
539 fNonLinearityParams[0] = 0.99078;
540 fNonLinearityParams[1] = 0.161499;
541 fNonLinearityParams[2] = 0.655166;
542 fNonLinearityParams[3] = 0.134101;
543 fNonLinearityParams[4] = 163.282;
544 fNonLinearityParams[5] = 23.6904;
545 fNonLinearityParams[6] = 0.978;
549 //__________________________________________________
550 Float_t AliEMCALRecoUtils::GetDepth(const Float_t energy, const Int_t iParticle, const Int_t iSM) const
552 //Calculate shower depth for a given cluster energy and particle type
562 depth = x0 * (TMath::Log(energy*1000/ ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
566 depth = x0 * (TMath::Log(energy*1000/ ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
573 gGeoManager->cd("ALIC_1/XEN1_1");
574 TGeoNode *geoXEn1 = gGeoManager->GetCurrentNode();
575 TGeoNodeMatrix *geoSM = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
577 TGeoVolume *geoSMVol = geoSM->GetVolume();
578 TGeoShape *geoSMShape = geoSMVol->GetShape();
579 TGeoBBox *geoBox = dynamic_cast<TGeoBBox *>(geoSMShape);
580 if(geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
581 else AliFatal("Null GEANT box");
582 }else AliFatal("NULL GEANT node matrix");
585 depth = x0 * (TMath::Log(energy*1000 / ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
591 depth = x0 * (TMath::Log(energy*1000 / ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
598 //__________________________________________________
599 void AliEMCALRecoUtils::GetMaxEnergyCell(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu,
600 Int_t & absId, Int_t& iSupMod, Int_t& ieta, Int_t& iphi, Bool_t &shared)
602 //For a given CaloCluster gets the absId of the cell
603 //with maximum energy deposit.
606 Double_t eCell = -1.;
607 Float_t fraction = 1.;
608 Float_t recalFactor = 1.;
609 Int_t cellAbsId = -1 ;
617 AliInfo("Cluster pointer null!");
618 absId=-1; iSupMod0=-1, ieta = -1; iphi = -1; shared = -1;
622 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
623 cellAbsId = clu->GetCellAbsId(iDig);
624 fraction = clu->GetCellAmplitudeFraction(iDig);
625 //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
626 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
627 geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta);
628 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
629 if(iDig==0) iSupMod0=iSupMod;
630 else if(iSupMod0!=iSupMod) {
632 //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
634 if(IsRecalibrationOn()) {
635 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
637 eCell = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
638 //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
642 //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
646 //Get from the absid the supermodule, tower and eta/phi numbers
647 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
648 //Gives SuperModule and Tower numbers
649 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
650 iIphi, iIeta,iphi,ieta);
651 //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
652 //printf("Max end---\n");
656 //________________________________________________________________
657 void AliEMCALRecoUtils::InitEMCALRecalibrationFactors(){
658 //Init EMCAL recalibration factors
659 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
660 //In order to avoid rewriting the same histograms
661 Bool_t oldStatus = TH1::AddDirectoryStatus();
662 TH1::AddDirectory(kFALSE);
664 fEMCALRecalibrationFactors = new TObjArray(10);
665 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));
666 //Init the histograms with 1
667 for (Int_t sm = 0; sm < 10; sm++) {
668 for (Int_t i = 0; i < 48; i++) {
669 for (Int_t j = 0; j < 24; j++) {
670 SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
674 fEMCALRecalibrationFactors->SetOwner(kTRUE);
675 fEMCALRecalibrationFactors->Compress();
677 //In order to avoid rewriting the same histograms
678 TH1::AddDirectory(oldStatus);
682 //________________________________________________________________
683 void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap(){
684 //Init EMCAL bad channels map
685 AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
686 //In order to avoid rewriting the same histograms
687 Bool_t oldStatus = TH1::AddDirectoryStatus();
688 TH1::AddDirectory(kFALSE);
690 fEMCALBadChannelMap = new TObjArray(10);
691 //TH2F * hTemp = new TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
692 for (int i = 0; i < 10; i++) {
693 fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
698 fEMCALBadChannelMap->SetOwner(kTRUE);
699 fEMCALBadChannelMap->Compress();
701 //In order to avoid rewriting the same histograms
702 TH1::AddDirectory(oldStatus);
705 //________________________________________________________________
706 void AliEMCALRecoUtils::RecalibrateClusterEnergy(AliEMCALGeometry* geom, AliVCluster * cluster, AliVCaloCells * cells){
707 // Recalibrate the cluster energy, considering the recalibration map and the energy of the cells that compose the cluster.
710 AliInfo("Cluster pointer null!");
714 //Get the cluster number of cells and list of absId, check what kind of cluster do we have.
715 UShort_t * index = cluster->GetCellsAbsId() ;
716 Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
717 Int_t ncells = cluster->GetNCells();
719 //Initialize some used variables
722 Int_t icol = -1, irow = -1, imod=1;
723 Float_t factor = 1, frac = 0;
725 //Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
726 for(Int_t icell = 0; icell < ncells; icell++){
727 absId = index[icell];
728 frac = fraction[icell];
729 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
730 Int_t iTower = -1, iIphi = -1, iIeta = -1;
731 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
732 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
733 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
734 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
735 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
736 imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
738 energy += cells->GetCellAmplitude(absId)*factor*frac;
742 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f\n",cluster->E(),energy));
744 cluster->SetE(energy);
749 //__________________________________________________
750 void AliEMCALRecoUtils::RecalculateClusterPosition(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
752 //For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
755 AliInfo("Cluster pointer null!");
759 if (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
760 else if(fPosAlgo==kPosTowerIndex) RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
761 else AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
765 //__________________________________________________
766 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
768 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
769 // The algorithm is a copy of what is done in AliEMCALRecPoint
772 Float_t fraction = 1.;
773 Float_t recalFactor = 1.;
776 Int_t iTower = -1, iIphi = -1, iIeta = -1;
777 Int_t iSupModMax = -1, iSM=-1, iphi = -1, ieta = -1;
778 Float_t weight = 0., totalWeight=0.;
779 Float_t newPos[3] = {0,0,0};
780 Double_t pLocal[3], pGlobal[3];
781 Bool_t shared = kFALSE;
783 Float_t clEnergy = clu->E(); //Energy already recalibrated previously
784 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
785 Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
787 //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
789 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
790 absId = clu->GetCellAbsId(iDig);
791 fraction = clu->GetCellAmplitudeFraction(iDig);
792 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
793 geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta);
794 geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);
796 if(IsRecalibrationOn()) {
797 recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
799 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
801 weight = GetCellWeight(eCell,clEnergy);
802 //printf("cell energy %f, weight %f\n",eCell,weight);
803 totalWeight += weight;
804 geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
805 //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
806 geom->GetGlobal(pLocal,pGlobal,iSupModMax);
807 //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
809 for(int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
814 for(int i=0; i<3; i++ ) newPos[i] /= totalWeight;
817 //Float_t pos[]={0,0,0};
818 //clu->GetPosition(pos);
819 //printf("OldPos : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
820 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
822 if(iSupModMax > 1) {//sector 1
823 newPos[0] +=fMisalTransShift[3];//-=3.093;
824 newPos[1] +=fMisalTransShift[4];//+=6.82;
825 newPos[2] +=fMisalTransShift[5];//+=1.635;
826 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
830 newPos[0] +=fMisalTransShift[0];//+=1.134;
831 newPos[1] +=fMisalTransShift[1];//+=8.2;
832 newPos[2] +=fMisalTransShift[2];//+=1.197;
833 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
836 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
838 clu->SetPosition(newPos);
842 //__________________________________________________
843 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
845 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
846 // The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position
849 Float_t fraction = 1.;
850 Float_t recalFactor = 1.;
854 Int_t iIphi = -1, iIeta = -1;
855 Int_t iSupMod = -1, iSupModMax = -1;
856 Int_t iphi = -1, ieta =-1;
857 Bool_t shared = kFALSE;
859 Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
860 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
861 Float_t depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
863 Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
864 Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
865 Int_t startingSM = -1;
867 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
868 absId = clu->GetCellAbsId(iDig);
869 fraction = clu->GetCellAmplitudeFraction(iDig);
870 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
871 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
872 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
874 if (iDig==0) startingSM = iSupMod;
875 else if(iSupMod != startingSM) areInSameSM = kFALSE;
877 eCell = cells->GetCellAmplitude(absId);
879 if(IsRecalibrationOn()) {
880 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
882 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
884 weight = GetCellWeight(eCell,clEnergy);
885 if(weight < 0) weight = 0;
886 totalWeight += weight;
887 weightedCol += ieta*weight;
888 weightedRow += iphi*weight;
890 //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
894 Float_t xyzNew[]={0.,0.,0.};
895 if(areInSameSM == kTRUE) {
896 //printf("In Same SM\n");
897 weightedCol = weightedCol/totalWeight;
898 weightedRow = weightedRow/totalWeight;
899 geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
902 //printf("In Different SM\n");
903 geom->RecalculateTowerPosition(iphi, ieta, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
906 clu->SetPosition(xyzNew);
910 //____________________________________________________________________________
911 void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster){
913 //re-evaluate distance to bad channel with updated bad map
915 if(!fRecalDistToBadChannels) return;
918 AliInfo("Cluster pointer null!");
922 //Get channels map of the supermodule where the cluster is.
923 Int_t absIdMax = -1, iSupMod =-1, icolM = -1, irowM = -1;
924 Bool_t shared = kFALSE;
925 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSupMod, icolM, irowM, shared);
926 TH2D* hMap = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
929 Float_t minDist = 10000.;
932 //Loop on tower status map
933 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
934 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
935 //Check if tower is bad.
936 if(hMap->GetBinContent(icol,irow)==0) continue;
937 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
938 // iSupMod,icol, irow, icolM,irowM);
940 dRrow=TMath::Abs(irowM-irow);
941 dRcol=TMath::Abs(icolM-icol);
942 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
944 //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
951 //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
956 //The only possible combinations are (0,1), (2,3) ... (8,9)
957 if(iSupMod%2) iSupMod2 = iSupMod-1;
958 else iSupMod2 = iSupMod+1;
959 hMap2 = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
961 //Loop on tower status map of second super module
962 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
963 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
964 //Check if tower is bad.
965 if(hMap2->GetBinContent(icol,irow)==0) continue;
966 //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",
967 // iSupMod2,icol, irow,iSupMod,icolM,irowM);
969 dRrow=TMath::Abs(irow-irowM);
972 dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
975 dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
978 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
979 if(dist < minDist) minDist = dist;
984 }// shared cluster in 2 SuperModules
986 AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
987 cluster->SetDistanceToBadChannel(minDist);
991 //____________________________________________________________________________
992 void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster){
994 //re-evaluate identification parameters with bayesian
997 AliInfo("Cluster pointer null!");
1001 if ( cluster->GetM02() != 0)
1002 fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
1004 Float_t pidlist[AliPID::kSPECIESN+1];
1005 for(Int_t i = 0; i < AliPID::kSPECIESN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
1007 cluster->SetPID(pidlist);
1011 //____________________________________________________________________________
1012 void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster)
1014 // Calculates new center of gravity in the local EMCAL-module coordinates
1015 // and tranfers into global ALICE coordinates
1016 // Calculates Dispersion and main axis
1019 AliInfo("Cluster pointer null!");
1025 Double_t eCell = 0.;
1026 Float_t fraction = 1.;
1027 Float_t recalFactor = 1.;
1035 Double_t etai = -1.;
1036 Double_t phii = -1.;
1043 Double_t xmean = 0.;
1044 Double_t zmean = 0.;
1047 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1049 //Get from the absid the supermodule, tower and eta/phi numbers
1050 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1051 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1053 //Get the cell energy, if recalibration is on, apply factors
1054 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1055 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1056 if(IsRecalibrationOn()) {
1057 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1059 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1061 if(cluster->E() > 0 && eCell > 0){
1063 w = GetCellWeight(eCell,cluster->E());
1065 etai=(Double_t)ieta;
1066 phii=(Double_t)iphi;
1071 dxx += w * etai * etai ;
1073 dzz += w * phii * phii ;
1075 dxz += w * etai * phii ;
1079 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1082 //Normalize to the weight
1088 AliError(Form("Wrong weight %f\n", wtot));
1090 //Calculate dispersion
1091 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1093 //Get from the absid the supermodule, tower and eta/phi numbers
1094 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1095 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1097 //Get the cell energy, if recalibration is on, apply factors
1098 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1099 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1100 if(IsRecalibrationOn()) {
1101 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1103 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1105 if(cluster->E() > 0 && eCell > 0){
1107 w = GetCellWeight(eCell,cluster->E());
1109 etai=(Double_t)ieta;
1110 phii=(Double_t)iphi;
1111 if(w > 0.0) d += w*((etai-xmean)*(etai-xmean)+(phii-zmean)*(phii-zmean));
1114 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1117 //Normalize to the weigth and set shower shape parameters
1118 if (wtot > 0 && nstat > 1) {
1123 dxx -= xmean * xmean ;
1124 dzz -= zmean * zmean ;
1125 dxz -= xmean * zmean ;
1126 cluster->SetM02(0.5 * (dxx + dzz) + TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1127 cluster->SetM20(0.5 * (dxx + dzz) - TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1131 cluster->SetM20(0.) ;
1132 cluster->SetM02(0.) ;
1136 cluster->SetDispersion(TMath::Sqrt(d)) ;
1138 cluster->SetDispersion(0) ;
1141 //____________________________________________________________________________
1142 void AliEMCALRecoUtils::FindMatches(AliVEvent *event,TObjArray * clusterArr, AliEMCALGeometry *geom)
1144 //This function should be called before the cluster loop
1145 //Before call this function, please recalculate the cluster positions
1146 //Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR
1147 //Store matched cluster indexes and residuals
1149 fMatchedTrackIndex->Reset();
1150 fMatchedClusterIndex->Reset();
1151 fResidualPhi->Reset();
1152 fResidualEta->Reset();
1154 fMatchedTrackIndex->Set(500);
1155 fMatchedClusterIndex->Set(500);
1156 fResidualPhi->Set(500);
1157 fResidualEta->Set(500);
1159 AliESDEvent* esdevent = dynamic_cast<AliESDEvent*> (event);
1160 AliAODEvent* aodevent = dynamic_cast<AliAODEvent*> (event);
1164 for (Int_t i=0; i<21;i++) cv[i]=0;
1165 for(Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
1167 AliExternalTrackParam *trackParam = 0;
1169 //If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner
1172 AliESDtrack *esdTrack = esdevent->GetTrack(itr);
1173 if(!esdTrack || !IsAccepted(esdTrack)) continue;
1174 if(esdTrack->Pt()<fCutMinTrackPt) continue;
1175 const AliESDfriendTrack* friendTrack = esdTrack->GetFriendTrack();
1176 if(friendTrack && friendTrack->GetTPCOut())
1178 //Use TPC Out as starting point if it is available
1179 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
1183 //Otherwise use TPC inner
1184 trackParam = const_cast<AliExternalTrackParam*>(esdTrack->GetInnerParam());
1188 //If the input event is AOD, the starting point for extrapolation is at vertex
1189 //AOD tracks are selected according to its bit.
1192 AliAODTrack *aodTrack = aodevent->GetTrack(itr);
1193 if(!aodTrack) continue;
1194 if(!aodTrack->TestFilterMask(fAODFilterMask)) continue; //Select AOD tracks that fulfill GetStandardITSTPCTrackCuts2010()
1195 if(aodTrack->Pt()<fCutMinTrackPt) continue;
1196 Double_t pos[3],mom[3];
1197 aodTrack->GetXYZ(pos);
1198 aodTrack->GetPxPyPz(mom);
1199 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()));
1200 trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
1203 //Return if the input data is not "AOD" or "ESD"
1206 printf("Wrong input data type! Should be \"AOD\" or \"ESD\"\n");
1210 if(!trackParam) continue;
1212 Float_t dRMax = fCutR, dEtaMax=fCutEta, dPhiMax=fCutPhi;
1214 if(!clusterArr){// get clusters from event
1215 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1217 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1218 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1219 AliExternalTrackParam trkPamTmp(*trackParam);//Retrieve the starting point every time before the extrapolation
1220 Float_t tmpEta=-999, tmpPhi=-999;
1221 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1224 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1233 else if(fCutEtaPhiSeparate)
1235 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1244 printf("Error: please specify your cut criteria\n");
1245 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1246 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1247 if(aodevent && trackParam) delete trackParam;
1252 else { // external cluster array, not from ESD event
1253 for(Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
1255 AliVCluster *cluster = dynamic_cast<AliVCluster*> (clusterArr->At(icl)) ;
1257 AliInfo("Cluster not found!!!");
1260 if(!cluster->IsEMCAL()) continue;
1261 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1262 Float_t tmpEta=-999, tmpPhi=-999;
1263 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1266 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1275 else if(fCutEtaPhiSeparate)
1277 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1286 printf("Error: please specify your cut criteria\n");
1287 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1288 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1289 if(aodevent && trackParam) delete trackParam;
1293 }// external list of clusters
1297 fMatchedTrackIndex ->AddAt(itr,matched);
1298 fMatchedClusterIndex->AddAt(index,matched);
1299 fResidualEta ->AddAt(dEtaMax,matched);
1300 fResidualPhi ->AddAt(dPhiMax,matched);
1303 if(aodevent && trackParam) delete trackParam;
1306 AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
1308 fMatchedTrackIndex ->Set(matched);
1309 fMatchedClusterIndex->Set(matched);
1310 fResidualPhi ->Set(matched);
1311 fResidualEta ->Set(matched);
1314 //________________________________________________________________________________
1315 Int_t AliEMCALRecoUtils::FindMatchedCluster(AliESDtrack *track, AliVEvent *event, AliEMCALGeometry *geom)
1318 // This function returns the index of matched cluster to input track
1319 // Returns -1 if no match is found
1322 Float_t dRMax = fCutR, dEtaMax = fCutEta, dPhiMax = fCutPhi;
1325 AliExternalTrackParam *trackParam=0;
1326 const AliESDfriendTrack* friendTrack = track->GetFriendTrack();
1327 if(friendTrack && friendTrack->GetTPCOut())
1328 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
1330 trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
1332 if(!trackParam) return index;
1333 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1335 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1336 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1337 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1338 Float_t tmpEta=-999, tmpPhi=-999;
1339 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1342 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1351 else if(fCutEtaPhiSeparate)
1353 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1362 printf("Error: please specify your cut criteria\n");
1363 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1364 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1371 //________________________________________________________________________________
1372 Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, AliVCluster *cluster, Float_t &tmpEta, Float_t &tmpPhi)
1375 //Return the residual by extrapolating a track to a cluster
1377 if(!trkParam || !cluster) return kFALSE;
1380 cluster->GetPosition(clsPos); //Has been recalculated
1381 TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
1382 Double_t alpha = ((int)(vec.Phi()*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
1383 vec.RotateZ(-alpha); //Rotate the cluster to the local extrapolation coordinate system
1384 trkParam->Rotate(alpha); //Rotate the track to the same local extrapolation system
1385 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), fMass, fStep,kFALSE, 0.8, -1)) return kFALSE;
1386 trkParam->GetXYZ(trkPos); //Get the extrapolated global position
1388 TVector3 clsPosVec(clsPos[0],clsPos[1],clsPos[2]);
1389 TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
1391 Float_t clsPhi = (Float_t)clsPosVec.Phi();
1392 if(clsPhi<0) clsPhi+=2*TMath::Pi();
1393 Float_t trkPhi = (Float_t)trkPosVec.Phi();
1394 if(trkPhi<0) trkPhi+=2*TMath::Pi();
1395 tmpPhi = clsPhi-trkPhi; // track cluster matching
1396 tmpEta = clsPosVec.Eta()-trkPosVec.Eta(); // track cluster matching
1401 //________________________________________________________________________________
1402 void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex, Float_t &dEta, Float_t &dPhi)
1404 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1405 //Get the residuals dEta and dPhi for this cluster to the closest track
1406 //Works with ESDs and AODs
1408 if( FindMatchedPosForCluster(clsIndex) >= 999 )
1410 AliDebug(2,"No matched tracks found!\n");
1415 dEta = fResidualEta->At(FindMatchedPosForCluster(clsIndex));
1416 dPhi = fResidualPhi->At(FindMatchedPosForCluster(clsIndex));
1418 //________________________________________________________________________________
1419 void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dEta, Float_t &dPhi)
1421 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1422 //Get the residuals dEta and dPhi for this track to the closest cluster
1423 //Works with ESDs and AODs
1425 if( FindMatchedPosForTrack(trkIndex) >= 999 )
1427 AliDebug(2,"No matched cluster found!\n");
1432 dEta = fResidualEta->At(FindMatchedPosForTrack(trkIndex));
1433 dPhi = fResidualPhi->At(FindMatchedPosForTrack(trkIndex));
1436 //__________________________________________________________
1437 Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
1439 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1440 //Get the index of matched track to this cluster
1441 //Works with ESDs and AODs
1443 if(IsClusterMatched(clsIndex))
1444 return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
1449 //__________________________________________________________
1450 Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
1452 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1453 //Get the index of matched cluster to this track
1454 //Works with ESDs and AODs
1456 if(IsTrackMatched(trkIndex))
1457 return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
1462 //__________________________________________________
1463 Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex) const
1465 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1466 //Returns if the cluster has a match
1467 if(FindMatchedPosForCluster(clsIndex) < 999)
1473 //__________________________________________________
1474 Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex) const
1476 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1477 //Returns if the track has a match
1478 if(FindMatchedPosForTrack(trkIndex) < 999)
1484 //__________________________________________________________
1485 UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
1487 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1488 //Returns the position of the match in the fMatchedClusterIndex array
1489 Float_t tmpR = fCutR;
1492 for(Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++)
1494 if(fMatchedClusterIndex->At(i)==clsIndex)
1496 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1501 AliDebug(3,Form("Matched cluster index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedClusterIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1508 //__________________________________________________________
1509 UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
1511 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1512 //Returns the position of the match in the fMatchedTrackIndex array
1513 Float_t tmpR = fCutR;
1516 for(Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++)
1518 if(fMatchedTrackIndex->At(i)==trkIndex)
1520 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1525 AliDebug(3,Form("Matched track index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedTrackIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1532 //__________________________________________________________
1533 Bool_t AliEMCALRecoUtils::IsGoodCluster(AliVCluster *cluster, AliEMCALGeometry *geom, AliVCaloCells* cells)
1535 // check if the cluster survives some quality cut
1538 Bool_t isGood=kTRUE;
1539 if(!cluster || !cluster->IsEMCAL()) return kFALSE;
1540 if(ClusterContainsBadChannel(geom,cluster->GetCellsAbsId(),cluster->GetNCells())) return kFALSE;
1541 if(!CheckCellFiducialRegion(geom,cluster,cells)) return kFALSE;
1542 if(fRejectExoticCluster && IsExoticCluster(cluster)) return kFALSE;
1547 //__________________________________________________________
1548 Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
1550 // Given a esd track, return whether the track survive all the cuts
1552 // The different quality parameter are first
1553 // retrieved from the track. then it is found out what cuts the
1554 // track did not survive and finally the cuts are imposed.
1556 UInt_t status = esdTrack->GetStatus();
1558 Int_t nClustersITS = esdTrack->GetITSclusters(0);
1559 Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
1561 Float_t chi2PerClusterITS = -1;
1562 Float_t chi2PerClusterTPC = -1;
1563 if (nClustersITS!=0)
1564 chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
1565 if (nClustersTPC!=0)
1566 chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
1570 Float_t maxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); //This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
1571 //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
1572 SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
1577 esdTrack->GetImpactParameters(b,bCov);
1578 if (bCov[0]<=0 || bCov[2]<=0) {
1579 AliDebug(1, "Estimated b resolution lower or equal zero!");
1580 bCov[0]=0; bCov[2]=0;
1583 Float_t dcaToVertexXY = b[0];
1584 Float_t dcaToVertexZ = b[1];
1585 Float_t dcaToVertex = -1;
1587 if (fCutDCAToVertex2D)
1588 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY/fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + dcaToVertexZ*dcaToVertexZ/fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ);
1590 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
1594 Bool_t cuts[kNCuts];
1595 for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
1597 // track quality cuts
1598 if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
1600 if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
1602 if (nClustersTPC<fCutMinNClusterTPC)
1604 if (nClustersITS<fCutMinNClusterITS)
1606 if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC)
1608 if (chi2PerClusterITS>fCutMaxChi2PerClusterITS)
1610 if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
1612 if (fCutDCAToVertex2D && dcaToVertex > 1)
1614 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
1616 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ) > fCutMaxDCAToVertexZ)
1619 //Require at least one SPD point + anything else in ITS
1620 if( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
1624 for (Int_t i=0; i<kNCuts; i++)
1625 if (cuts[i]) {cut = kTRUE;}
1633 //__________________________________________________
1634 void AliEMCALRecoUtils::InitTrackCuts()
1636 //Intilize the track cut criteria
1637 //By default these cuts are set according to AliESDtrackCuts::GetStandardTPCOnlyTrackCuts()
1638 //Also you can customize the cuts using the setters
1640 switch (fTrackCutsType)
1644 AliInfo(Form("Track cuts for matching: GetStandardTPCOnlyTrackCuts()"));
1646 SetMinNClustersTPC(70);
1647 SetMaxChi2PerClusterTPC(4);
1648 SetAcceptKinkDaughters(kFALSE);
1649 SetRequireTPCRefit(kFALSE);
1652 SetRequireITSRefit(kFALSE);
1653 SetMaxDCAToVertexZ(3.2);
1654 SetMaxDCAToVertexXY(2.4);
1655 SetDCAToVertex2D(kTRUE);
1662 AliInfo(Form("Track cuts for matching: GetStandardITSTPCTrackCuts2010(kTURE)"));
1664 SetMinNClustersTPC(70);
1665 SetMaxChi2PerClusterTPC(4);
1666 SetAcceptKinkDaughters(kFALSE);
1667 SetRequireTPCRefit(kTRUE);
1670 SetRequireITSRefit(kTRUE);
1671 SetMaxDCAToVertexZ(2);
1672 SetMaxDCAToVertexXY();
1673 SetDCAToVertex2D(kFALSE);
1680 //___________________________________________________
1681 void AliEMCALRecoUtils::Print(const Option_t *) const
1685 printf("AliEMCALRecoUtils Settings: \n");
1686 printf("Misalignment shifts\n");
1687 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,
1688 fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
1689 fMisalRotShift[i*3], fMisalRotShift[i*3+1], fMisalRotShift[i*3+2] );
1690 printf("Non linearity function %d, parameters:\n", fNonLinearityFunction);
1691 for(Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
1693 printf("Position Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
1695 printf("Matching criteria: ");
1698 printf("sqrt(dEta^2+dPhi^2)<%2.2f\n",fCutR);
1700 else if(fCutEtaPhiSeparate)
1702 printf("dEta<%2.2f, dPhi<%2.2f\n",fCutEta,fCutPhi);
1707 printf("please specify your cut criteria\n");
1708 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1709 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1712 printf("Mass hypothesis = %2.3f [GeV/c^2], extrapolation step = %2.2f[cm]\n",fMass,fStep);
1714 printf("Track cuts: \n");
1715 printf("Minimum track pT: %1.2f\n",fCutMinTrackPt);
1716 printf("AOD track selection mask: %d\n",fAODFilterMask);
1717 printf("TPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
1718 printf("AcceptKinks = %d\n",fCutAcceptKinkDaughters);
1719 printf("MinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
1720 printf("MaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
1721 printf("DCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
1725 //_____________________________________________________________________
1726 void AliEMCALRecoUtils::SetTimeDependentCorrections(Int_t runnumber){
1727 //Get EMCAL time dependent corrections from file and put them in the recalibration histograms
1728 //Do it only once and only if it is requested
1730 if(!fUseTimeCorrectionFactors) return;
1731 if(fTimeCorrectionFactorsSet) return;
1733 printf("AliEMCALRecoUtils::GetTimeDependentCorrections() - Get Correction Factors for Run number %d\n",runnumber);
1735 AliEMCALCalibTimeDepCorrection *corr = new AliEMCALCalibTimeDepCorrection();
1736 corr->ReadRootInfo(Form("CorrectionFiles/Run%d_Correction.root",runnumber));
1738 SwitchOnRecalibration();
1739 for(Int_t ism = 0; ism < 4; ism++){
1740 for(Int_t icol = 0; icol < 48; icol++){
1741 for(Int_t irow = 0; irow < 24; irow++){
1742 Float_t orgRecalFactor = GetEMCALChannelRecalibrationFactors(ism)->GetBinContent(icol,irow);
1743 Float_t newRecalFactor = orgRecalFactor*corr->GetCorrection(ism, icol,irow,0);
1744 GetEMCALChannelRecalibrationFactors(ism)->SetBinContent(icol,irow,newRecalFactor);
1745 //printf("ism %d, icol %d, irow %d, corrections : org %f, time dep %f, final %f (org*time %f)\n",ism, icol, irow,
1746 // orgRecalFactor, corr->GetCorrection(ism, icol,irow,0),
1747 // (GetEMCALChannelRecalibrationFactors(ism))->GetBinContent(icol,irow),newRecalFactor);
1751 fTimeCorrectionFactorsSet = kTRUE;