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 ///////////////////////////////////////////////////////////////////////////////
31 // standard C++ includes
32 //#include <Riostream.h>
35 #include <TGeoManager.h>
36 #include <TGeoMatrix.h>
40 #include "AliVCluster.h"
41 #include "AliVCaloCells.h"
42 #include "AliVEvent.h"
45 #include "AliESDEvent.h"
46 #include "AliAODEvent.h"
47 #include "AliESDtrack.h"
48 #include "AliAODTrack.h"
49 #include "AliExternalTrackParam.h"
50 #include "AliESDfriendTrack.h"
51 #include "AliTrackerBase.h"
54 #include "AliEMCALRecoUtils.h"
55 #include "AliEMCALGeometry.h"
56 #include "AliEMCALTrack.h"
57 #include "AliEMCALCalibTimeDepCorrection.h"
58 #include "AliEMCALPIDUtils.h"
60 ClassImp(AliEMCALRecoUtils)
62 //______________________________________________
63 AliEMCALRecoUtils::AliEMCALRecoUtils():
64 fNonLinearityFunction (kNoCorrection), fParticleType(kPhoton),
65 fPosAlgo(kUnchanged),fW0(4.),
66 fRecalibration(kFALSE), fEMCALRecalibrationFactors(),
67 fRemoveBadChannels(kFALSE), fRecalDistToBadChannels(kFALSE), fEMCALBadChannelMap(),
68 fNCellsFromEMCALBorder(0), fNoEMCALBorderAtEta0(kTRUE),
70 fMatchedTrackIndex(0x0), fMatchedClusterIndex(0x0),
71 fResidualZ(0x0), fResidualR(0x0), fCutR(10), fCutZ(10), fMass(0.139), fStep(1),
72 fCutMinNClusterTPC(0), fCutMinNClusterITS(0), fCutMaxChi2PerClusterTPC(0), fCutMaxChi2PerClusterITS(0),
73 fCutRequireTPCRefit(0), fCutRequireITSRefit(0), fCutAcceptKinkDaughters(0),
74 fCutMaxDCAToVertexXY(0), fCutMaxDCAToVertexZ(0),fCutDCAToVertex2D(0),fPIDUtils(),
75 fUseTimeCorrectionFactors(kFALSE), fTimeCorrectionFactorsSet(kFALSE)
79 // Initialize all constant values which have to be used
80 // during Reco algorithm execution
83 //Misalignment matrices
84 for(Int_t i = 0; i < 15 ; i++) {
85 fMisalTransShift[i] = 0.;
86 fMisalRotShift[i] = 0.;
90 for(Int_t i = 0; i < 6 ; i++) fNonLinearityParams[i] = 0.;
91 //For kPi0GammaGamma case, but default is no correction
92 fNonLinearityParams[0] = 0.1457/0.1349766/1.038;
93 fNonLinearityParams[1] = -0.02024/0.1349766/1.038;
94 fNonLinearityParams[2] = 1.046;
97 fMatchedTrackIndex = new TArrayI();
98 fMatchedClusterIndex = new TArrayI();
99 fResidualZ = new TArrayF();
100 fResidualR = new TArrayF();
104 fPIDUtils = new AliEMCALPIDUtils();
109 //______________________________________________________________________
110 AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco)
111 : TNamed(reco), fNonLinearityFunction(reco.fNonLinearityFunction),
112 fParticleType(reco.fParticleType), fPosAlgo(reco.fPosAlgo), fW0(reco.fW0),
113 fRecalibration(reco.fRecalibration),fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
114 fRemoveBadChannels(reco.fRemoveBadChannels),fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
115 fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
116 fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder),fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
117 fAODFilterMask(reco.fAODFilterMask),
118 fMatchedTrackIndex(reco.fMatchedTrackIndex?new TArrayI(*reco.fMatchedTrackIndex):0x0),
119 fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
120 fResidualZ(reco.fResidualZ?new TArrayF(*reco.fResidualZ):0x0),
121 fResidualR(reco.fResidualR?new TArrayF(*reco.fResidualR):0x0),
122 fCutR(reco.fCutR),fCutZ(reco.fCutZ),fMass(reco.fMass), fStep(reco.fStep),
123 fCutMinNClusterTPC(reco.fCutMinNClusterTPC), fCutMinNClusterITS(reco.fCutMinNClusterITS),
124 fCutMaxChi2PerClusterTPC(reco.fCutMaxChi2PerClusterTPC), fCutMaxChi2PerClusterITS(reco.fCutMaxChi2PerClusterITS),
125 fCutRequireTPCRefit(reco.fCutRequireTPCRefit), fCutRequireITSRefit(reco.fCutRequireITSRefit),
126 fCutAcceptKinkDaughters(reco.fCutAcceptKinkDaughters),
127 fCutMaxDCAToVertexXY(reco.fCutMaxDCAToVertexXY), fCutMaxDCAToVertexZ(reco.fCutMaxDCAToVertexZ),fCutDCAToVertex2D(reco.fCutDCAToVertex2D),
128 fPIDUtils(reco.fPIDUtils),
129 fUseTimeCorrectionFactors(reco.fUseTimeCorrectionFactors), fTimeCorrectionFactorsSet(reco.fTimeCorrectionFactorsSet)
133 for(Int_t i = 0; i < 15 ; i++) {
134 fMisalRotShift[i] = reco.fMisalRotShift[i];
135 fMisalTransShift[i] = reco.fMisalTransShift[i];
137 for(Int_t i = 0; i < 6 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
142 //______________________________________________________________________
143 AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco)
145 //Assignment operator
147 if(this == &reco)return *this;
148 ((TNamed *)this)->operator=(reco);
150 fNonLinearityFunction = reco.fNonLinearityFunction;
151 fParticleType = reco.fParticleType;
152 fPosAlgo = reco.fPosAlgo;
154 fRecalibration = reco.fRecalibration;
155 fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
156 fRemoveBadChannels = reco.fRemoveBadChannels;
157 fRecalDistToBadChannels = reco.fRecalDistToBadChannels;
158 fEMCALBadChannelMap = reco.fEMCALBadChannelMap;
159 fNCellsFromEMCALBorder = reco.fNCellsFromEMCALBorder;
160 fNoEMCALBorderAtEta0 = reco.fNoEMCALBorderAtEta0;
163 for(Int_t i = 0; i < 15 ; i++) {fMisalTransShift[i] = reco.fMisalTransShift[i]; fMisalRotShift[i] = reco.fMisalRotShift[i];}
164 for(Int_t i = 0; i < 6 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
166 fAODFilterMask = reco.fAODFilterMask;
173 fCutMinNClusterTPC = reco.fCutMinNClusterTPC;
174 fCutMinNClusterITS = reco.fCutMinNClusterITS;
175 fCutMaxChi2PerClusterTPC = reco.fCutMaxChi2PerClusterTPC;
176 fCutMaxChi2PerClusterITS = reco.fCutMaxChi2PerClusterITS;
177 fCutRequireTPCRefit = reco.fCutRequireTPCRefit;
178 fCutRequireITSRefit = reco.fCutRequireITSRefit;
179 fCutAcceptKinkDaughters = reco.fCutAcceptKinkDaughters;
180 fCutMaxDCAToVertexXY = reco.fCutMaxDCAToVertexXY;
181 fCutMaxDCAToVertexZ = reco.fCutMaxDCAToVertexZ;
182 fCutDCAToVertex2D = reco.fCutDCAToVertex2D;
184 fPIDUtils = reco.fPIDUtils;
186 fUseTimeCorrectionFactors = reco.fUseTimeCorrectionFactors;
187 fTimeCorrectionFactorsSet = reco.fTimeCorrectionFactorsSet;
191 // assign or copy construct
193 *fResidualR = *reco.fResidualR;
195 else fResidualR = new TArrayF(*reco.fResidualR);
198 if(fResidualR)delete fResidualR;
203 // assign or copy construct
205 *fResidualZ = *reco.fResidualZ;
207 else fResidualZ = new TArrayF(*reco.fResidualZ);
210 if(fResidualZ)delete fResidualZ;
214 if(reco.fMatchedTrackIndex){
215 // assign or copy construct
216 if(fMatchedTrackIndex){
217 *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
219 else fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
222 if(fMatchedTrackIndex)delete fMatchedTrackIndex;
223 fMatchedTrackIndex = 0;
226 if(reco.fMatchedClusterIndex){
227 // assign or copy construct
228 if(fMatchedClusterIndex){
229 *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
231 else fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
234 if(fMatchedClusterIndex)delete fMatchedClusterIndex;
235 fMatchedClusterIndex = 0;
243 //__________________________________________________
244 AliEMCALRecoUtils::~AliEMCALRecoUtils()
248 if(fEMCALRecalibrationFactors) {
249 fEMCALRecalibrationFactors->Clear();
250 delete fEMCALRecalibrationFactors;
253 if(fEMCALBadChannelMap) {
254 fEMCALBadChannelMap->Clear();
255 delete fEMCALBadChannelMap;
258 if(fMatchedTrackIndex) {delete fMatchedTrackIndex; fMatchedTrackIndex=0;}
259 if(fMatchedClusterIndex) {delete fMatchedClusterIndex; fMatchedClusterIndex=0;}
260 if(fResidualR) {delete fResidualR; fResidualR=0;}
261 if(fResidualZ) {delete fResidualZ; fResidualZ=0;}
265 //_______________________________________________________________
266 Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(AliEMCALGeometry* geom, AliVCluster* cluster, AliVCaloCells* cells)
268 // Given the list of AbsId of the cluster, get the maximum cell and
269 // check if there are fNCellsFromBorder from the calorimeter border
271 //If the distance to the border is 0 or negative just exit accept all clusters
272 if(cells->GetType()==AliVCaloCells::kEMCALCell && fNCellsFromEMCALBorder <= 0 ) return kTRUE;
274 Int_t absIdMax = -1, iSM =-1, ieta = -1, iphi = -1;
275 Bool_t shared = kFALSE;
276 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSM, ieta, iphi, shared);
278 AliDebug(2,Form("Cluster Max AbsId %d, Cell Energy %2.2f, Cluster Energy %2.2f, Ncells from border %d, EMCAL eta=0 %d\n",
279 absIdMax, cells->GetCellAmplitude(absIdMax), cluster->E(), fNCellsFromEMCALBorder, fNoEMCALBorderAtEta0));
281 if(absIdMax==-1) return kFALSE;
283 //Check if the cell is close to the borders:
284 Bool_t okrow = kFALSE;
285 Bool_t okcol = kFALSE;
287 if(iSM < 0 || iphi < 0 || ieta < 0 ) {
288 AliFatal(Form("Negative value for super module: %d, or cell ieta: %d, or cell iphi: %d, check EMCAL geometry name\n",
294 if(iphi >= fNCellsFromEMCALBorder && iphi < 24-fNCellsFromEMCALBorder) okrow =kTRUE;
297 if(iphi >= fNCellsFromEMCALBorder && iphi < 12-fNCellsFromEMCALBorder) okrow =kTRUE;
301 if(!fNoEMCALBorderAtEta0){
302 if(ieta > fNCellsFromEMCALBorder && ieta < 48-fNCellsFromEMCALBorder) okcol =kTRUE;
306 if(ieta >= fNCellsFromEMCALBorder) okcol = kTRUE;
309 if(ieta < 48-fNCellsFromEMCALBorder) okcol = kTRUE;
313 AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d: column? %d, row? %d\nq",
314 fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
316 if (okcol && okrow) {
317 //printf("Accept\n");
321 //printf("Reject\n");
322 AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
329 //_________________________________________________________________________________________________________
330 Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(AliEMCALGeometry* geom, UShort_t* cellList, Int_t nCells){
331 // Check that in the cluster cells, there is no bad channel of those stored
332 // in fEMCALBadChannelMap or fPHOSBadChannelMap
334 if(!fRemoveBadChannels) return kFALSE;
335 if(!fEMCALBadChannelMap) return kFALSE;
340 for(Int_t iCell = 0; iCell<nCells; iCell++){
342 //Get the column and row
343 Int_t iTower = -1, iIphi = -1, iIeta = -1;
344 geom->GetCellIndex(cellList[iCell],imod,iTower,iIphi,iIeta);
345 if(fEMCALBadChannelMap->GetEntries() <= imod) continue;
346 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
347 if(GetEMCALChannelStatus(imod, icol, irow)){
348 AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
352 }// cell cluster loop
358 //__________________________________________________
359 Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster){
360 // Correct cluster energy from non linearity functions
361 Float_t energy = cluster->E();
363 switch (fNonLinearityFunction) {
367 //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
368 //Double_t fNonLinearityParams[0] = 1.001;
369 //Double_t fNonLinearityParams[1] = -0.01264;
370 //Double_t fNonLinearityParams[2] = -0.03632;
371 //Double_t fNonLinearityParams[3] = 0.1798;
372 //Double_t fNonLinearityParams[4] = -0.522;
373 energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
374 ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
375 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
381 //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
382 //Double_t fNonLinearityParams[0] = 1.04;
383 //Double_t fNonLinearityParams[1] = -0.1445;
384 //Double_t fNonLinearityParams[2] = 1.046;
385 energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
389 case kPi0GammaConversion:
391 //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
392 //fNonLinearityParams[0] = 0.139393/0.1349766;
393 //fNonLinearityParams[1] = 0.0566186;
394 //fNonLinearityParams[2] = 0.982133;
395 energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
402 //From beam test, Alexei's results, for different ZS thresholds
403 // th=30 MeV; th = 45 MeV; th = 75 MeV
404 //fNonLinearityParams[0] = 1.007; 1.003; 1.002
405 //fNonLinearityParams[1] = 0.894; 0.719; 0.797
406 //fNonLinearityParams[2] = 0.246; 0.334; 0.358
407 //Rescale the param[0] with 1.03
408 energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
412 case kBeamTestCorrected:
414 //From beam test, corrected for material between beam and EMCAL
415 //fNonLinearityParams[0] = 0.983
416 //fNonLinearityParams[1] = 9.83529e-01;
417 //fNonLinearityParams[2] = -1.84235e+02;
418 //fNonLinearityParams[3] = -2.05019e+00;
419 //fNonLinearityParams[4] = -5.89423e+00;
420 energy *= fNonLinearityParams[0]*( ( fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]) ) +
421 ( (fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())) *
422 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3])) ) );
428 AliDebug(2,"No correction on the energy\n");
437 //__________________________________________________
438 Float_t AliEMCALRecoUtils::GetDepth(const Float_t energy, const Int_t iParticle, const Int_t iSM) const
440 //Calculate shower depth for a given cluster energy and particle type
450 depth = x0 * (TMath::Log(energy*1000/ ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
454 depth = x0 * (TMath::Log(energy*1000/ ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
461 gGeoManager->cd("ALIC_1/XEN1_1");
462 TGeoNode *geoXEn1 = gGeoManager->GetCurrentNode();
463 TGeoNodeMatrix *geoSM = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
465 TGeoVolume *geoSMVol = geoSM->GetVolume();
466 TGeoShape *geoSMShape = geoSMVol->GetShape();
467 TGeoBBox *geoBox = dynamic_cast<TGeoBBox *>(geoSMShape);
468 if(geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
469 else AliFatal("Null GEANT box");
470 }else AliFatal("NULL GEANT node matrix");
473 depth = x0 * (TMath::Log(energy*1000 / ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
479 depth = x0 * (TMath::Log(energy*1000 / ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
486 //__________________________________________________
487 void AliEMCALRecoUtils::GetMaxEnergyCell(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu,
488 Int_t & absId, Int_t& iSupMod, Int_t& ieta, Int_t& iphi, Bool_t &shared)
490 //For a given CaloCluster gets the absId of the cell
491 //with maximum energy deposit.
494 Double_t eCell = -1.;
495 Float_t fraction = 1.;
496 Float_t recalFactor = 1.;
497 Int_t cellAbsId = -1 ;
503 //printf("---Max?\n");
504 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
505 cellAbsId = clu->GetCellAbsId(iDig);
506 fraction = clu->GetCellAmplitudeFraction(iDig);
507 //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
508 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
509 geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta);
510 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
511 if(iDig==0) iSupMod0=iSupMod;
512 else if(iSupMod0!=iSupMod) {
514 //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
516 if(IsRecalibrationOn()) {
517 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
519 eCell = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
520 //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
524 //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
528 //Get from the absid the supermodule, tower and eta/phi numbers
529 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
530 //Gives SuperModule and Tower numbers
531 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
532 iIphi, iIeta,iphi,ieta);
533 //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
534 //printf("Max end---\n");
538 //________________________________________________________________
539 void AliEMCALRecoUtils::InitEMCALRecalibrationFactors(){
540 //Init EMCAL recalibration factors
541 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
542 //In order to avoid rewriting the same histograms
543 Bool_t oldStatus = TH1::AddDirectoryStatus();
544 TH1::AddDirectory(kFALSE);
546 fEMCALRecalibrationFactors = new TObjArray(10);
547 for (int i = 0; i < 12; i++) fEMCALRecalibrationFactors->Add(new TH2F(Form("EMCALRecalFactors_SM%d",i),Form("EMCALRecalFactors_SM%d",i), 48, 0, 48, 24, 0, 24));
548 //Init the histograms with 1
549 for (Int_t sm = 0; sm < 12; sm++) {
550 for (Int_t i = 0; i < 48; i++) {
551 for (Int_t j = 0; j < 24; j++) {
552 SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
556 fEMCALRecalibrationFactors->SetOwner(kTRUE);
557 fEMCALRecalibrationFactors->Compress();
559 //In order to avoid rewriting the same histograms
560 TH1::AddDirectory(oldStatus);
564 //________________________________________________________________
565 void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap(){
566 //Init EMCAL bad channels map
567 AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
568 //In order to avoid rewriting the same histograms
569 Bool_t oldStatus = TH1::AddDirectoryStatus();
570 TH1::AddDirectory(kFALSE);
572 fEMCALBadChannelMap = new TObjArray(10);
573 //TH2F * hTemp = new TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
574 for (int i = 0; i < 10; i++) {
575 fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
580 fEMCALBadChannelMap->SetOwner(kTRUE);
581 fEMCALBadChannelMap->Compress();
583 //In order to avoid rewriting the same histograms
584 TH1::AddDirectory(oldStatus);
587 //________________________________________________________________
588 void AliEMCALRecoUtils::RecalibrateClusterEnergy(AliEMCALGeometry* geom, AliVCluster * cluster, AliVCaloCells * cells){
589 // Recalibrate the cluster energy, considering the recalibration map and the energy of the cells that compose the cluster.
591 //Get the cluster number of cells and list of absId, check what kind of cluster do we have.
592 UShort_t * index = cluster->GetCellsAbsId() ;
593 Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
594 Int_t ncells = cluster->GetNCells();
596 //Initialize some used variables
599 Int_t icol = -1, irow = -1, imod=1;
600 Float_t factor = 1, frac = 0;
602 //Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
603 for(Int_t icell = 0; icell < ncells; icell++){
604 absId = index[icell];
605 frac = fraction[icell];
606 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
607 Int_t iTower = -1, iIphi = -1, iIeta = -1;
608 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
609 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
610 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
611 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
612 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
613 imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
615 energy += cells->GetCellAmplitude(absId)*factor*frac;
619 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f\n",cluster->E(),energy));
621 cluster->SetE(energy);
626 //__________________________________________________
627 void AliEMCALRecoUtils::RecalculateClusterPosition(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
629 //For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
631 if (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
632 else if(fPosAlgo==kPosTowerIndex) RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
633 else AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
637 //__________________________________________________
638 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
640 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
641 // The algorithm is a copy of what is done in AliEMCALRecPoint
644 Float_t fraction = 1.;
645 Float_t recalFactor = 1.;
648 Int_t iTower = -1, iIphi = -1, iIeta = -1;
649 Int_t iSupModMax = -1, iSM=-1, iphi = -1, ieta = -1;
650 Float_t weight = 0., totalWeight=0.;
651 Float_t newPos[3] = {0,0,0};
652 Double_t pLocal[3], pGlobal[3];
653 Bool_t shared = kFALSE;
655 Float_t clEnergy = clu->E(); //Energy already recalibrated previously
656 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
657 Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
659 //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
661 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
662 absId = clu->GetCellAbsId(iDig);
663 fraction = clu->GetCellAmplitudeFraction(iDig);
664 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
665 geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta);
666 geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);
668 if(IsRecalibrationOn()) {
669 recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
671 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
673 weight = GetCellWeight(eCell,clEnergy);
674 //printf("cell energy %f, weight %f\n",eCell,weight);
675 totalWeight += weight;
676 geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
677 //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
678 geom->GetGlobal(pLocal,pGlobal,iSupModMax);
679 //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
681 for(int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
686 for(int i=0; i<3; i++ ) newPos[i] /= totalWeight;
689 //Float_t pos[]={0,0,0};
690 //clu->GetPosition(pos);
691 //printf("OldPos : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
692 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
694 if(iSupModMax > 1) {//sector 1
695 newPos[0] +=fMisalTransShift[3];//-=3.093;
696 newPos[1] +=fMisalTransShift[4];//+=6.82;
697 newPos[2] +=fMisalTransShift[5];//+=1.635;
698 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
702 newPos[0] +=fMisalTransShift[0];//+=1.134;
703 newPos[1] +=fMisalTransShift[1];//+=8.2;
704 newPos[2] +=fMisalTransShift[2];//+=1.197;
705 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
708 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
710 clu->SetPosition(newPos);
714 //__________________________________________________
715 void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
717 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
718 // The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position
721 Float_t fraction = 1.;
722 Float_t recalFactor = 1.;
726 Int_t iIphi = -1, iIeta = -1;
727 Int_t iSupMod = -1, iSupModMax = -1;
728 Int_t iphi = -1, ieta =-1;
729 Bool_t shared = kFALSE;
731 Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
732 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
733 Float_t depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
735 Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
736 Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
737 Int_t startingSM = -1;
739 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
740 absId = clu->GetCellAbsId(iDig);
741 fraction = clu->GetCellAmplitudeFraction(iDig);
742 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
743 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
744 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
746 if (iDig==0) startingSM = iSupMod;
747 else if(iSupMod != startingSM) areInSameSM = kFALSE;
749 eCell = cells->GetCellAmplitude(absId);
751 if(IsRecalibrationOn()) {
752 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
754 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
756 weight = GetCellWeight(eCell,clEnergy);
757 if(weight < 0) weight = 0;
758 totalWeight += weight;
759 weightedCol += ieta*weight;
760 weightedRow += iphi*weight;
762 //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
766 Float_t xyzNew[]={0.,0.,0.};
767 if(areInSameSM == kTRUE) {
768 //printf("In Same SM\n");
769 weightedCol = weightedCol/totalWeight;
770 weightedRow = weightedRow/totalWeight;
771 geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
774 //printf("In Different SM\n");
775 geom->RecalculateTowerPosition(iphi, ieta, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
778 clu->SetPosition(xyzNew);
782 //____________________________________________________________________________
783 void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster){
785 //re-evaluate distance to bad channel with updated bad map
787 if(!fRecalDistToBadChannels) return;
789 //Get channels map of the supermodule where the cluster is.
790 Int_t absIdMax = -1, iSupMod =-1, icolM = -1, irowM = -1;
791 Bool_t shared = kFALSE;
792 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSupMod, icolM, irowM, shared);
793 TH2D* hMap = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
796 Float_t minDist = 10000.;
799 //Loop on tower status map
800 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
801 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
802 //Check if tower is bad.
803 if(hMap->GetBinContent(icol,irow)==0) continue;
804 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
805 // iSupMod,icol, irow, icolM,irowM);
807 dRrow=TMath::Abs(irowM-irow);
808 dRcol=TMath::Abs(icolM-icol);
809 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
811 //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
818 //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
823 //The only possible combinations are (0,1), (2,3) ... (8,9)
824 if(iSupMod%2) iSupMod2 = iSupMod-1;
825 else iSupMod2 = iSupMod+1;
826 hMap2 = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
828 //Loop on tower status map of second super module
829 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
830 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
831 //Check if tower is bad.
832 if(hMap2->GetBinContent(icol,irow)==0) continue;
833 //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",
834 // iSupMod2,icol, irow,iSupMod,icolM,irowM);
836 dRrow=TMath::Abs(irow-irowM);
839 dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
842 dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
845 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
846 if(dist < minDist) minDist = dist;
851 }// shared cluster in 2 SuperModules
853 AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
854 cluster->SetDistanceToBadChannel(minDist);
858 //____________________________________________________________________________
859 void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster){
861 //re-evaluate identification parameters with bayesian
863 if ( cluster->GetM02() != 0)
864 fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
866 Float_t pidlist[AliPID::kSPECIESN+1];
867 for(Int_t i = 0; i < AliPID::kSPECIESN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
869 cluster->SetPID(pidlist);
873 //____________________________________________________________________________
874 void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster)
876 // Calculates new center of gravity in the local EMCAL-module coordinates
877 // and tranfers into global ALICE coordinates
878 // Calculates Dispersion and main axis
883 Float_t fraction = 1.;
884 Float_t recalFactor = 1.;
904 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
906 //Get from the absid the supermodule, tower and eta/phi numbers
907 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
908 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
910 //Get the cell energy, if recalibration is on, apply factors
911 fraction = cluster->GetCellAmplitudeFraction(iDigit);
912 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
913 if(IsRecalibrationOn()) {
914 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
916 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
918 if(cluster->E() > 0 && eCell > 0){
920 w = GetCellWeight(eCell,cluster->E());
928 dxx += w * etai * etai ;
930 dzz += w * phii * phii ;
932 dxz += w * etai * phii ;
936 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
939 //Normalize to the weight
945 AliError(Form("Wrong weight %f\n", wtot));
947 //Calculate dispersion
948 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
950 //Get from the absid the supermodule, tower and eta/phi numbers
951 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
952 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
954 //Get the cell energy, if recalibration is on, apply factors
955 fraction = cluster->GetCellAmplitudeFraction(iDigit);
956 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
957 if(IsRecalibrationOn()) {
958 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
960 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
962 if(cluster->E() > 0 && eCell > 0){
964 w = GetCellWeight(eCell,cluster->E());
968 if(w > 0.0) d += w*((etai-xmean)*(etai-xmean)+(phii-zmean)*(phii-zmean));
971 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
974 //Normalize to the weigth and set shower shape parameters
975 if (wtot > 0 && nstat > 1) {
980 dxx -= xmean * xmean ;
981 dzz -= zmean * zmean ;
982 dxz -= xmean * zmean ;
983 cluster->SetM02(0.5 * (dxx + dzz) + TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
984 cluster->SetM20(0.5 * (dxx + dzz) - TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
988 cluster->SetM20(0.) ;
989 cluster->SetM02(0.) ;
993 cluster->SetDispersion(TMath::Sqrt(d)) ;
995 cluster->SetDispersion(0) ;
998 //____________________________________________________________________________
999 void AliEMCALRecoUtils::FindMatches(AliVEvent *event, TObjArray * clusterArr, TString dataType)
1001 //Use dataType to indicate the input event is AOD or ESD
1002 //This function should be called before the cluster loop
1003 //Before call this function, please recalculate the cluster positions
1004 //Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR
1005 //Store matched cluster indexes and residuals
1007 fMatchedTrackIndex ->Reset();
1008 fMatchedClusterIndex->Reset();
1009 fResidualZ ->Reset();
1010 fResidualR ->Reset();
1012 fMatchedTrackIndex ->Set(500);
1013 fMatchedClusterIndex->Set(500);
1014 fResidualZ ->Set(500);
1015 fResidualR ->Set(500);
1019 for (Int_t i=0; i<21;i++) cv[i]=0;
1020 for(Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
1022 AliExternalTrackParam *trackParam=0;
1024 //If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner
1025 if(dataType.Contains("ESD"))
1027 AliESDtrack *esdTrack = ((AliESDEvent*)event)->GetTrack(itr);
1028 if(!esdTrack || !IsAccepted(esdTrack)) continue;
1029 const AliESDfriendTrack* friendTrack = esdTrack->GetFriendTrack();
1030 if(friendTrack && friendTrack->GetTPCOut())
1032 //Use TPC Out as starting point if it is available
1033 trackParam= new AliExternalTrackParam(*friendTrack->GetTPCOut());
1037 //Otherwise use TPC inner
1038 trackParam = new AliExternalTrackParam(*esdTrack->GetInnerParam());
1042 //If the input event is AOD, the starting point for extrapolation is at vertex
1043 //AOD tracks are selected according to its bit.
1044 else if(dataType.Contains("AOD"))
1046 AliAODTrack *aodTrack = ((AliAODEvent*)event)->GetTrack(itr);
1047 if(!aodTrack) continue;
1048 if(!aodTrack->TestFilterMask(fAODFilterMask)) continue; //Select AOD tracks that fulfill GetStandardITSTPCTrackCuts2010()
1049 Double_t pos[3],mom[3];
1050 aodTrack->GetXYZ(pos);
1051 aodTrack->GetPxPyPz(mom);
1052 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()));
1053 trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
1056 //Return if the input data is not "AOD" or "ESD"
1059 printf("Wrong input data type %s! Should be \"AOD\" or \"ESD\"\n",dataType.Data());
1063 if(!trackParam) continue;
1065 Float_t dRMax = fCutR, dZMax=fCutZ;
1067 if(!clusterArr){// get clusters from event
1068 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1070 AliExternalTrackParam *trkPamTmp = new AliExternalTrackParam(*trackParam);//Retrieve the starting point every time before the extrapolation
1071 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1072 if(!cluster->IsEMCAL()) continue;
1073 Float_t tmpR=-1, tmpZ=-1;
1074 if(!ExtrapolateTrackToCluster(trkPamTmp, cluster, tmpR, tmpZ)) continue;
1083 } else { // external cluster array, not from ESD event
1084 for(Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
1086 AliExternalTrackParam *trkPamTmp = new AliExternalTrackParam(*trackParam);//Retrieve the starting point every time before the extrapolation
1087 AliVCluster *cluster = (AliVCluster*) clusterArr->At(icl);
1088 if(!cluster->IsEMCAL()) continue;
1089 Float_t tmpR=-1, tmpZ=-1;
1090 if(!ExtrapolateTrackToCluster(trkPamTmp, cluster, tmpR, tmpZ)) continue;
1099 }// external list of clusters
1103 fMatchedTrackIndex ->AddAt(itr,matched);
1104 fMatchedClusterIndex->AddAt(index,matched);
1105 fResidualZ ->AddAt(dZMax,matched);
1106 fResidualR ->AddAt(dRMax,matched);
1112 AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
1114 fMatchedTrackIndex ->Set(matched);
1115 fMatchedClusterIndex->Set(matched);
1116 fResidualZ ->Set(matched);
1117 fResidualR ->Set(matched);
1120 //________________________________________________________________________________
1121 Int_t AliEMCALRecoUtils::FindMatchedCluster(AliESDtrack *track, AliVEvent *event)
1124 // This function returns the index of matched cluster to input track
1125 // Cut on match is dR<10cm by default. Returns -1 if no match is found
1128 Float_t dRMax = fCutR;
1131 AliExternalTrackParam *trackParam=0;
1132 const AliESDfriendTrack* friendTrack = track->GetFriendTrack();
1133 if(friendTrack && friendTrack->GetTPCOut())
1134 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
1136 trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
1138 if(!trackParam) return index;
1139 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1141 AliExternalTrackParam *trkPamTmp = new AliExternalTrackParam(*trackParam);//Retrieve the starting point every time before the extrapolation
1142 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1143 if(!cluster->IsEMCAL()) continue;
1144 Float_t tmpR=-1, tmpZ=-1;
1145 if(!ExtrapolateTrackToCluster(trkPamTmp, cluster, tmpR, tmpZ)) continue;
1146 if(tmpR>-1 && tmpR<dRMax)
1156 //________________________________________________________________________________
1157 Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, AliVCluster *cluster, Float_t &tmpR, Float_t &tmpZ)
1160 //Return the residual by extrapolating a track to a cluster
1162 if(!trkParam || !cluster) return kFALSE;
1165 cluster->GetPosition(clsPos); //Has been recalculated
1166 TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
1167 Double_t alpha = ((int)(vec.Phi()*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
1168 vec.RotateZ(-alpha); //Rotate the cluster to the local extrapolation coordinate system
1169 trkParam->Rotate(alpha); //Rotate the track to the same local extrapolation system
1170 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), fMass, fStep,kFALSE)) return kFALSE;
1171 trkParam->GetXYZ(trkPos); //Get the extrapolated global position
1172 tmpR = TMath::Sqrt( TMath::Power(clsPos[0]-trkPos[0],2)+TMath::Power(clsPos[1]-trkPos[1],2)+TMath::Power(clsPos[2]-trkPos[2],2) );
1173 tmpZ = clsPos[2]-trkPos[2];
1177 //________________________________________________________________________________
1178 void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex, Float_t &dR, Float_t &dZ)
1180 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1181 //Get the residuals dR and dZ for this cluster to the closest track
1182 //Works with ESDs and AODs
1184 if( FindMatchedPosForCluster(clsIndex) >= 999 )
1186 AliDebug(2,"No matched tracks found!\n");
1191 dR = fResidualR->At(FindMatchedPosForCluster(clsIndex));
1192 dZ = fResidualZ->At(FindMatchedPosForCluster(clsIndex));
1194 //________________________________________________________________________________
1195 void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dR, Float_t &dZ)
1197 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1198 //Get the residuals dR and dZ for this track to the closest cluster
1199 //Works with ESDs and AODs
1201 if( FindMatchedPosForTrack(trkIndex) >= 999 )
1203 AliDebug(2,"No matched cluster found!\n");
1208 dR = fResidualR->At(FindMatchedPosForTrack(trkIndex));
1209 dZ = fResidualZ->At(FindMatchedPosForTrack(trkIndex));
1212 //__________________________________________________________
1213 Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
1215 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1216 //Get the index of matched track to this cluster
1217 //Works with ESDs and AODs
1219 if(IsClusterMatched(clsIndex))
1220 return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
1225 //__________________________________________________________
1226 Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
1228 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1229 //Get the index of matched cluster to this track
1230 //Works with ESDs and AODs
1232 if(IsTrackMatched(trkIndex))
1233 return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
1238 //__________________________________________________
1239 Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex)
1241 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1242 //Returns if the cluster has a match
1243 if(FindMatchedPosForCluster(clsIndex) < 999)
1249 //__________________________________________________
1250 Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex)
1252 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1253 //Returns if the track has a match
1254 if(FindMatchedPosForTrack(trkIndex) < 999)
1260 //__________________________________________________________
1261 UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
1263 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1264 //Returns the position of the match in the fMatchedClusterIndex array
1265 Float_t tmpR = fCutR;
1268 for(Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++)
1270 if(fMatchedClusterIndex->At(i)==clsIndex && fResidualR->At(i)<tmpR)
1273 tmpR=fResidualR->At(i);
1274 AliDebug(3,Form("Matched cluster index: index: %d, dR: %2.4f, dZ: %2.4f.\n",fMatchedClusterIndex->At(i),fResidualR->At(i),fResidualZ->At(i)));
1280 //__________________________________________________________
1281 UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
1283 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1284 //Returns the position of the match in the fMatchedTrackIndex array
1285 Float_t tmpR = fCutR;
1288 for(Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++)
1290 if(fMatchedTrackIndex->At(i)==trkIndex && fResidualR->At(i)<tmpR)
1293 tmpR=fResidualR->At(i);
1294 AliDebug(3,Form("Matched track index: index: %d, dR: %2.4f, dZ: %2.4f.\n",fMatchedTrackIndex->At(i),fResidualR->At(i),fResidualZ->At(i)));
1300 //__________________________________________________________
1301 Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
1303 // Given a esd track, return whether the track survive all the cuts
1305 // The different quality parameter are first
1306 // retrieved from the track. then it is found out what cuts the
1307 // track did not survive and finally the cuts are imposed.
1309 UInt_t status = esdTrack->GetStatus();
1311 Int_t nClustersITS = esdTrack->GetITSclusters(0);
1312 Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
1314 Float_t chi2PerClusterITS = -1;
1315 Float_t chi2PerClusterTPC = -1;
1316 if (nClustersITS!=0)
1317 chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
1318 if (nClustersTPC!=0)
1319 chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
1323 Float_t MaxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); //This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
1324 //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
1325 SetMaxDCAToVertexXY(MaxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
1330 esdTrack->GetImpactParameters(b,bCov);
1331 if (bCov[0]<=0 || bCov[2]<=0) {
1332 AliDebug(1, "Estimated b resolution lower or equal zero!");
1333 bCov[0]=0; bCov[2]=0;
1336 Float_t dcaToVertexXY = b[0];
1337 Float_t dcaToVertexZ = b[1];
1338 Float_t dcaToVertex = -1;
1340 if (fCutDCAToVertex2D)
1341 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY/fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + dcaToVertexZ*dcaToVertexZ/fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ);
1343 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
1347 Bool_t cuts[kNCuts];
1348 for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
1350 // track quality cuts
1351 if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
1353 if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
1355 if (nClustersTPC<fCutMinNClusterTPC)
1357 if (nClustersITS<fCutMinNClusterITS)
1359 if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC)
1361 if (chi2PerClusterITS>fCutMaxChi2PerClusterITS)
1363 if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
1365 if (fCutDCAToVertex2D && dcaToVertex > 1)
1367 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
1369 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ) > fCutMaxDCAToVertexZ)
1372 //Require at least one SPD point + anything else in ITS
1373 if( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
1377 for (Int_t i=0; i<kNCuts; i++)
1378 if (cuts[i]) {cut = kTRUE;}
1386 //__________________________________________________
1387 void AliEMCALRecoUtils::InitTrackCuts()
1389 //Intilize the track cut criteria
1390 //By default these cuts are set according to AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
1391 //Also you can customize the cuts using the setters
1394 SetMinNClustersTPC(70);
1395 SetMaxChi2PerClusterTPC(4);
1396 SetAcceptKinkDaughters(kFALSE);
1397 SetRequireTPCRefit(kTRUE);
1400 SetRequireITSRefit(kTRUE);
1401 SetMaxDCAToVertexZ(2);
1402 SetDCAToVertex2D(kFALSE);
1403 SetMaxChi2PerClusterITS(); //which by default sets the value to 1e10.
1404 SetMinNClustersITS();
1407 //___________________________________________________
1408 void AliEMCALRecoUtils::Print(const Option_t *) const
1412 printf("AliEMCALRecoUtils Settings: \n");
1413 printf("Misalignment shifts\n");
1414 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,
1415 fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
1416 fMisalRotShift[i*3], fMisalRotShift[i*3+1], fMisalRotShift[i*3+2] );
1417 printf("Non linearity function %d, parameters:\n", fNonLinearityFunction);
1418 for(Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
1420 printf("Position Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
1422 printf("Matching criteria: dR < %2.2f[cm], dZ < %2.2f[cm]\n",fCutR,fCutZ);
1423 printf("Mass hypothesis = %2.3f[GeV/c^2], extrapolation step = %2.2f[cm]\n",fMass,fStep);
1425 printf("Track cuts: \n");
1426 printf("AOD track selection mask: %d\n",fAODFilterMask);
1427 printf("TPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
1428 printf("AcceptKinks = %d\n",fCutAcceptKinkDaughters);
1429 printf("MinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
1430 printf("MaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
1431 printf("DCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
1435 //_____________________________________________________________________
1436 void AliEMCALRecoUtils::SetTimeDependentCorrections(Int_t runnumber){
1437 //Get EMCAL time dependent corrections from file and put them in the recalibration histograms
1438 //Do it only once and only if it is requested
1440 if(!fUseTimeCorrectionFactors) return;
1441 if(fTimeCorrectionFactorsSet) return;
1443 printf("AliEMCALRecoUtils::GetTimeDependentCorrections() - Get Correction Factors for Run number %d\n",runnumber);
1445 AliEMCALCalibTimeDepCorrection *corr = new AliEMCALCalibTimeDepCorrection();
1446 corr->ReadRootInfo(Form("CorrectionFiles/Run%d_Correction.root",runnumber));
1448 SwitchOnRecalibration();
1449 for(Int_t ism = 0; ism < 4; ism++){
1450 for(Int_t icol = 0; icol < 48; icol++){
1451 for(Int_t irow = 0; irow < 24; irow++){
1452 Float_t orgRecalFactor = GetEMCALChannelRecalibrationFactors(ism)->GetBinContent(icol,irow);
1453 Float_t newRecalFactor = orgRecalFactor*corr->GetCorrection(ism, icol,irow,0);
1454 GetEMCALChannelRecalibrationFactors(ism)->SetBinContent(icol,irow,newRecalFactor);
1455 //printf("ism %d, icol %d, irow %d, corrections : org %f, time dep %f, final %f (org*time %f)\n",ism, icol, irow,
1456 // orgRecalFactor, corr->GetCorrection(ism, icol,irow,0),
1457 // (GetEMCALChannelRecalibrationFactors(ism))->GetBinContent(icol,irow),newRecalFactor);
1461 fTimeCorrectionFactorsSet = kTRUE;