]> git.uio.no Git - u/mrichter/AliRoot.git/blame - EMCAL/AliEMCALRecoUtils.cxx
cast histogram content to int to avoid compilation warning
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALRecoUtils.cxx
CommitLineData
d9b3567c 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
15
16/* $Id: AliEMCALRecoUtils.cxx 33808 2009-07-15 09:48:08Z gconesab $ */
17
18///////////////////////////////////////////////////////////////////////////////
19//
20// Class AliEMCALRecoUtils
21// Some utilities to recalculate the cluster position or energy linearity
22//
23//
24// Author: Gustavo Conesa (LPSC- Grenoble)
b540d03f 25// Track matching part: Rongrong Ma (Yale)
26
d9b3567c 27///////////////////////////////////////////////////////////////////////////////
d9b3567c 28// --- standard c ---
29
30// standard C++ includes
31//#include <Riostream.h>
32
33// ROOT includes
094786cc 34#include <TGeoManager.h>
35#include <TGeoMatrix.h>
36#include <TGeoBBox.h>
7cdec71f 37#include <TH2F.h>
38#include <TArrayI.h>
39#include <TArrayF.h>
40#include "TObjArray.h"
d9b3567c 41
42// STEER includes
d9b3567c 43#include "AliVCluster.h"
44#include "AliVCaloCells.h"
bd8c7aef 45#include "AliVEvent.h"
d9b3567c 46#include "AliLog.h"
83bfd77a 47#include "AliPID.h"
bd8c7aef 48#include "AliESDEvent.h"
bb6f5f0b 49#include "AliAODEvent.h"
bd8c7aef 50#include "AliESDtrack.h"
bb6f5f0b 51#include "AliAODTrack.h"
52#include "AliExternalTrackParam.h"
53#include "AliESDfriendTrack.h"
54#include "AliTrackerBase.h"
b540d03f 55
56// EMCAL includes
57#include "AliEMCALRecoUtils.h"
58#include "AliEMCALGeometry.h"
bd8c7aef 59#include "AliEMCALTrack.h"
96957075 60#include "AliEMCALCalibTimeDepCorrection.h"
b540d03f 61#include "AliEMCALPIDUtils.h"
d9b3567c 62
63ClassImp(AliEMCALRecoUtils)
64
65//______________________________________________
66AliEMCALRecoUtils::AliEMCALRecoUtils():
fd6df01c 67 fNonLinearityFunction (kNoCorrection), fParticleType(kPhoton),
7e0ecb89 68 fPosAlgo(kUnchanged),fW0(4.), fNonLinearThreshold(30),
fd6df01c 69 fRecalibration(kFALSE), fEMCALRecalibrationFactors(),
78467229 70 fRemoveBadChannels(kFALSE), fRecalDistToBadChannels(kFALSE), fEMCALBadChannelMap(),
bd8c7aef 71 fNCellsFromEMCALBorder(0), fNoEMCALBorderAtEta0(kTRUE),
bb6f5f0b 72 fAODFilterMask(32),
b540d03f 73 fMatchedTrackIndex(0x0), fMatchedClusterIndex(0x0),
5f7714ad 74 fResidualEta(0x0), fResidualPhi(0x0), fCutEtaPhiSum(kTRUE), fCutEtaPhiSeparate(kFALSE), fCutR(0.1), fCutEta(0.02), fCutPhi(0.04), fMass(0.139), fStep(50),
b5078f5d 75 fRejectExoticCluster(kFALSE),
5f7714ad 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(),
96957075 79 fUseTimeCorrectionFactors(kFALSE), fTimeCorrectionFactorsSet(kFALSE)
d9b3567c 80{
81//
82 // Constructor.
83 // Initialize all constant values which have to be used
84 // during Reco algorithm execution
85 //
86
b540d03f 87 //Misalignment matrices
fd6df01c 88 for(Int_t i = 0; i < 15 ; i++) {
89 fMisalTransShift[i] = 0.;
b540d03f 90 fMisalRotShift[i] = 0.;
fd6df01c 91 }
b540d03f 92
93 //Non linearity
dff9e2e3 94 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = 0.;
95
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;
104
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;
bd8c7aef 109
b540d03f 110 //Track matching
7cdec71f 111 fMatchedTrackIndex = new TArrayI();
112 fMatchedClusterIndex = new TArrayI();
bd36717e 113 fResidualPhi = new TArrayF();
114 fResidualEta = new TArrayF();
d9b3567c 115
bd8c7aef 116 InitTrackCuts();
7cdec71f 117 fPIDUtils = new AliEMCALPIDUtils();
d9b3567c 118}
119
120//______________________________________________________________________
121AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco)
094786cc 122: TNamed(reco), fNonLinearityFunction(reco.fNonLinearityFunction),
7e0ecb89 123 fParticleType(reco.fParticleType), fPosAlgo(reco.fPosAlgo), fW0(reco.fW0), fNonLinearThreshold(reco.fNonLinearThreshold),
fd6df01c 124 fRecalibration(reco.fRecalibration),fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
78467229 125 fRemoveBadChannels(reco.fRemoveBadChannels),fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
126 fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
83bfd77a 127 fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder),fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
bb6f5f0b 128 fAODFilterMask(reco.fAODFilterMask),
b540d03f 129 fMatchedTrackIndex(reco.fMatchedTrackIndex?new TArrayI(*reco.fMatchedTrackIndex):0x0),
bd8c7aef 130 fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
fa4287a2 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),
b5078f5d 135 fRejectExoticCluster(reco.fRejectExoticCluster),
5f7714ad 136 fTrackCutsType(reco.fTrackCutsType), fCutMinTrackPt(reco.fCutMinTrackPt), fCutMinNClusterTPC(reco.fCutMinNClusterTPC), fCutMinNClusterITS(reco.fCutMinNClusterITS),
bd8c7aef 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),
96957075 141 fPIDUtils(reco.fPIDUtils),
142 fUseTimeCorrectionFactors(reco.fUseTimeCorrectionFactors), fTimeCorrectionFactorsSet(reco.fTimeCorrectionFactorsSet)
d9b3567c 143{
144 //Copy ctor
145
fd6df01c 146 for(Int_t i = 0; i < 15 ; i++) {
147 fMisalRotShift[i] = reco.fMisalRotShift[i];
148 fMisalTransShift[i] = reco.fMisalTransShift[i];
149 }
dff9e2e3 150 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
bd8c7aef 151
d9b3567c 152}
153
154
155//______________________________________________________________________
156AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco)
157{
158 //Assignment operator
159
160 if(this == &reco)return *this;
161 ((TNamed *)this)->operator=(reco);
162
96957075 163 fNonLinearityFunction = reco.fNonLinearityFunction;
164 fParticleType = reco.fParticleType;
165 fPosAlgo = reco.fPosAlgo;
166 fW0 = reco.fW0;
7e0ecb89 167 fNonLinearThreshold = reco.fNonLinearThreshold;
96957075 168 fRecalibration = reco.fRecalibration;
094786cc 169 fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
96957075 170 fRemoveBadChannels = reco.fRemoveBadChannels;
171 fRecalDistToBadChannels = reco.fRecalDistToBadChannels;
172 fEMCALBadChannelMap = reco.fEMCALBadChannelMap;
173 fNCellsFromEMCALBorder = reco.fNCellsFromEMCALBorder;
174 fNoEMCALBorderAtEta0 = reco.fNoEMCALBorderAtEta0;
bd8c7aef 175
83bfd77a 176
2a71e873 177 for(Int_t i = 0; i < 15 ; i++) {fMisalTransShift[i] = reco.fMisalTransShift[i]; fMisalRotShift[i] = reco.fMisalRotShift[i];}
dff9e2e3 178 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = reco.fNonLinearityParams[i];
bb6f5f0b 179
180 fAODFilterMask = reco.fAODFilterMask;
d9b3567c 181
fa4287a2 182 fCutEtaPhiSum = reco.fCutEtaPhiSum;
183 fCutEtaPhiSeparate = reco.fCutEtaPhiSeparate;
96957075 184 fCutR = reco.fCutR;
fa4287a2 185 fCutEta = reco.fCutEta;
186 fCutPhi = reco.fCutPhi;
bb6f5f0b 187 fMass = reco.fMass;
188 fStep = reco.fStep;
b5078f5d 189 fRejectExoticCluster = reco.fRejectExoticCluster;
bd8c7aef 190
5f7714ad 191 fTrackCutsType = reco.fTrackCutsType;
fa4287a2 192 fCutMinTrackPt = reco.fCutMinTrackPt;
96957075 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;
bd8c7aef 203
96957075 204 fPIDUtils = reco.fPIDUtils;
bd8c7aef 205
96957075 206 fUseTimeCorrectionFactors = reco.fUseTimeCorrectionFactors;
207 fTimeCorrectionFactorsSet = reco.fTimeCorrectionFactorsSet;
208
bd8c7aef 209
fa4287a2 210 if(reco.fResidualEta){
bd8c7aef 211 // assign or copy construct
fa4287a2 212 if(fResidualEta){
213 *fResidualEta = *reco.fResidualEta;
bd8c7aef 214 }
fa4287a2 215 else fResidualEta = new TArrayF(*reco.fResidualEta);
bd8c7aef 216 }
217 else{
fa4287a2 218 if(fResidualEta)delete fResidualEta;
219 fResidualEta = 0;
bd8c7aef 220 }
221
fa4287a2 222 if(reco.fResidualPhi){
bd8c7aef 223 // assign or copy construct
fa4287a2 224 if(fResidualPhi){
225 *fResidualPhi = *reco.fResidualPhi;
bd8c7aef 226 }
fa4287a2 227 else fResidualPhi = new TArrayF(*reco.fResidualPhi);
bd8c7aef 228 }
229 else{
fa4287a2 230 if(fResidualPhi)delete fResidualPhi;
231 fResidualPhi = 0;
bd8c7aef 232 }
233
b540d03f 234 if(reco.fMatchedTrackIndex){
235 // assign or copy construct
236 if(fMatchedTrackIndex){
237 *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
238 }
239 else fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
240 }
241 else{
242 if(fMatchedTrackIndex)delete fMatchedTrackIndex;
243 fMatchedTrackIndex = 0;
244 }
bd8c7aef 245
246 if(reco.fMatchedClusterIndex){
247 // assign or copy construct
248 if(fMatchedClusterIndex){
249 *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
250 }
251 else fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
252 }
253 else{
254 if(fMatchedClusterIndex)delete fMatchedClusterIndex;
255 fMatchedClusterIndex = 0;
256 }
5f7714ad 257
d9b3567c 258 return *this;
259}
260
261
094786cc 262//__________________________________________________
263AliEMCALRecoUtils::~AliEMCALRecoUtils()
264{
265 //Destructor.
266
267 if(fEMCALRecalibrationFactors) {
268 fEMCALRecalibrationFactors->Clear();
269 delete fEMCALRecalibrationFactors;
270 }
fd6df01c 271
272 if(fEMCALBadChannelMap) {
273 fEMCALBadChannelMap->Clear();
274 delete fEMCALBadChannelMap;
275 }
bd8c7aef 276
7cdec71f 277 delete fMatchedTrackIndex ;
278 delete fMatchedClusterIndex ;
279 delete fResidualEta ;
280 delete fResidualPhi ;
bd8c7aef 281
094786cc 282}
283
fd6df01c 284//_______________________________________________________________
285Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(AliEMCALGeometry* geom, AliVCluster* cluster, AliVCaloCells* cells)
286{
287 // Given the list of AbsId of the cluster, get the maximum cell and
288 // check if there are fNCellsFromBorder from the calorimeter border
289
2aeb4226 290 if(!cluster){
291 AliInfo("Cluster pointer null!");
292 return kFALSE;
293 }
294
fd6df01c 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;
297
cb231979 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);
fd6df01c 301
83bfd77a 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));
fd6df01c 304
305 if(absIdMax==-1) return kFALSE;
306
307 //Check if the cell is close to the borders:
308 Bool_t okrow = kFALSE;
309 Bool_t okcol = kFALSE;
310
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",
313 iSM,ieta,iphi));
314 }
315
316 //Check rows/phi
317 if(iSM < 10){
318 if(iphi >= fNCellsFromEMCALBorder && iphi < 24-fNCellsFromEMCALBorder) okrow =kTRUE;
319 }
320 else{
321 if(iphi >= fNCellsFromEMCALBorder && iphi < 12-fNCellsFromEMCALBorder) okrow =kTRUE;
322 }
323
324 //Check columns/eta
325 if(!fNoEMCALBorderAtEta0){
326 if(ieta > fNCellsFromEMCALBorder && ieta < 48-fNCellsFromEMCALBorder) okcol =kTRUE;
327 }
328 else{
329 if(iSM%2==0){
330 if(ieta >= fNCellsFromEMCALBorder) okcol = kTRUE;
331 }
332 else {
333 if(ieta < 48-fNCellsFromEMCALBorder) okcol = kTRUE;
334 }
335 }//eta 0 not checked
336
83bfd77a 337 AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d: column? %d, row? %d\nq",
fd6df01c 338 fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
339
83bfd77a 340 if (okcol && okrow) {
341 //printf("Accept\n");
342 return kTRUE;
343 }
344 else {
345 //printf("Reject\n");
346 AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
347 return kFALSE;
348 }
fd6df01c 349
350}
351
352
353//_________________________________________________________________________________________________________
7cdec71f 354Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(AliEMCALGeometry* geom, UShort_t* cellList, const Int_t nCells){
fd6df01c 355 // Check that in the cluster cells, there is no bad channel of those stored
356 // in fEMCALBadChannelMap or fPHOSBadChannelMap
357
358 if(!fRemoveBadChannels) return kFALSE;
359 if(!fEMCALBadChannelMap) return kFALSE;
360
361 Int_t icol = -1;
362 Int_t irow = -1;
363 Int_t imod = -1;
364 for(Int_t iCell = 0; iCell<nCells; iCell++){
365
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);
83bfd77a 371 if(GetEMCALChannelStatus(imod, icol, irow)){
372 AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
373 return kTRUE;
374 }
fd6df01c 375
376 }// cell cluster loop
377
378 return kFALSE;
379
380}
094786cc 381
b5078f5d 382//_________________________________________________
7cdec71f 383Bool_t AliEMCALRecoUtils::IsExoticCluster(AliVCluster *cluster) const {
b5078f5d 384 // Check if the cluster has high energy but small number of cells
385 // The criteria comes from Gustavo's study
386 //
2aeb4226 387
388 if(!cluster){
389 AliInfo("Cluster pointer null!");
390 return kFALSE;
391 }
b5078f5d 392
393 if(cluster->GetNCells()<(1+cluster->E()/3.))
394 return kTRUE;
395 else
396 return kFALSE;
397}
398
d9b3567c 399//__________________________________________________
400Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster){
401// Correct cluster energy from non linearity functions
2aeb4226 402
403 if(!cluster){
404 AliInfo("Cluster pointer null!");
405 return 0;
406 }
407
408
d9b3567c 409 Float_t energy = cluster->E();
410
411 switch (fNonLinearityFunction) {
412
413 case kPi0MC:
871aee7a 414 {
d9b3567c 415 //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
dff9e2e3 416 //Double_t fNonLinearityParams[0] = 1.014;
417 //Double_t fNonLinearityParams[1] = -0.03329;
418 //Double_t fNonLinearityParams[2] = -0.3853;
419 //Double_t fNonLinearityParams[3] = 0.5423;
420 //Double_t fNonLinearityParams[4] = -0.4335;
8cdd1f1f 421 energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
d9b3567c 422 ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
423 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
424 break;
871aee7a 425 }
dff9e2e3 426
d9b3567c 427 case kPi0GammaGamma:
871aee7a 428 {
d9b3567c 429 //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
96957075 430 //Double_t fNonLinearityParams[0] = 1.04;
431 //Double_t fNonLinearityParams[1] = -0.1445;
871aee7a 432 //Double_t fNonLinearityParams[2] = 1.046;
d9b3567c 433 energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
434 break;
871aee7a 435 }
d9b3567c 436
437 case kPi0GammaConversion:
871aee7a 438 {
d9b3567c 439 //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
871aee7a 440 //fNonLinearityParams[0] = 0.139393/0.1349766;
441 //fNonLinearityParams[1] = 0.0566186;
442 //fNonLinearityParams[2] = 0.982133;
d9b3567c 443 energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
444
445 break;
871aee7a 446 }
447
448 case kBeamTest:
449 {
450 //From beam test, Alexei's results, for different ZS thresholds
451 // th=30 MeV; th = 45 MeV; th = 75 MeV
96957075 452 //fNonLinearityParams[0] = 1.007; 1.003; 1.002
871aee7a 453 //fNonLinearityParams[1] = 0.894; 0.719; 0.797
454 //fNonLinearityParams[2] = 0.246; 0.334; 0.358
96957075 455 //Rescale the param[0] with 1.03
871aee7a 456 energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
457
458 break;
459 }
dff9e2e3 460
4b58ac4f 461 case kBeamTestCorrected:
462 {
463 //From beam test, corrected for material between beam and EMCAL
dff9e2e3 464 //fNonLinearityParams[0] = 0.99078
465 //fNonLinearityParams[1] = 0.161499;
466 //fNonLinearityParams[2] = 0.655166;
467 //fNonLinearityParams[3] = 0.134101;
468 //fNonLinearityParams[4] = 163.282;
469 //fNonLinearityParams[5] = 23.6904;
470 //fNonLinearityParams[6] = 0.978;
471 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
472
4b58ac4f 473 break;
474 }
d9b3567c 475
476 case kNoCorrection:
477 AliDebug(2,"No correction on the energy\n");
478 break;
479
480 }
481
482 return energy;
483
484}
7e0ecb89 485//__________________________________________________
486void AliEMCALRecoUtils::InitNonLinearityParam()
487{
488 //Initialising Non Linearity Parameters
489
490 if(fNonLinearityFunction == kPi0MC)
491 {
492 fNonLinearityParams[0] = 1.014;
493 fNonLinearityParams[1] = -0.03329;
494 fNonLinearityParams[2] = -0.3853;
495 fNonLinearityParams[3] = 0.5423;
496 fNonLinearityParams[4] = -0.4335;
497 }
498
499 if(fNonLinearityFunction == kPi0GammaGamma)
500 {
501 fNonLinearityParams[0] = 1.04;
502 fNonLinearityParams[1] = -0.1445;
503 fNonLinearityParams[2] = 1.046;
504 }
505
506 if(fNonLinearityFunction == kPi0GammaConversion)
507 {
508 fNonLinearityParams[0] = 0.139393;
509 fNonLinearityParams[1] = 0.0566186;
510 fNonLinearityParams[2] = 0.982133;
511 }
512
513 if(fNonLinearityFunction == kBeamTest)
514 {
515 if(fNonLinearThreshold == 30)
516 {
517 fNonLinearityParams[0] = 1.007;
518 fNonLinearityParams[1] = 0.894;
519 fNonLinearityParams[2] = 0.246;
520 }
521 if(fNonLinearThreshold == 45)
522 {
523 fNonLinearityParams[0] = 1.003;
524 fNonLinearityParams[1] = 0.719;
525 fNonLinearityParams[2] = 0.334;
526 }
527 if(fNonLinearThreshold == 75)
528 {
529 fNonLinearityParams[0] = 1.002;
530 fNonLinearityParams[1] = 0.797;
531 fNonLinearityParams[2] = 0.358;
532 }
533 }
534
535 if(fNonLinearityFunction == kBeamTestCorrected)
536 {
537 fNonLinearityParams[0] = 0.99078;
538 fNonLinearityParams[1] = 0.161499;
539 fNonLinearityParams[2] = 0.655166;
540 fNonLinearityParams[3] = 0.134101;
541 fNonLinearityParams[4] = 163.282;
542 fNonLinearityParams[5] = 23.6904;
543 fNonLinearityParams[6] = 0.978;
544 }
545}
546
d9b3567c 547//__________________________________________________
094786cc 548Float_t AliEMCALRecoUtils::GetDepth(const Float_t energy, const Int_t iParticle, const Int_t iSM) const
549{
550 //Calculate shower depth for a given cluster energy and particle type
551
552 // parameters
cb231979 553 Float_t x0 = 1.31;
094786cc 554 Float_t ecr = 8;
555 Float_t depth = 0;
556
557 switch ( iParticle )
558 {
559 case kPhoton:
fd6df01c 560 depth = x0 * (TMath::Log(energy*1000/ ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
094786cc 561 break;
562
563 case kElectron:
fd6df01c 564 depth = x0 * (TMath::Log(energy*1000/ ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
094786cc 565 break;
566
567 case kHadron:
568 // hadron
569 // boxes anc. here
570 if(gGeoManager){
571 gGeoManager->cd("ALIC_1/XEN1_1");
572 TGeoNode *geoXEn1 = gGeoManager->GetCurrentNode();
573 TGeoNodeMatrix *geoSM = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
fd6df01c 574 if(geoSM){
575 TGeoVolume *geoSMVol = geoSM->GetVolume();
576 TGeoShape *geoSMShape = geoSMVol->GetShape();
577 TGeoBBox *geoBox = dynamic_cast<TGeoBBox *>(geoSMShape);
578 if(geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
579 else AliFatal("Null GEANT box");
580 }else AliFatal("NULL GEANT node matrix");
094786cc 581 }
582 else{//electron
fd6df01c 583 depth = x0 * (TMath::Log(energy*1000 / ecr) - 0.5); //Multiply energy by 1000 to transform to MeV
094786cc 584 }
585
586 break;
587
588 default://photon
fd6df01c 589 depth = x0 * (TMath::Log(energy*1000 / ecr) + 0.5); //Multiply energy by 1000 to transform to MeV
094786cc 590 }
591
592 return depth;
593
594}
595
596//__________________________________________________
cb231979 597void AliEMCALRecoUtils::GetMaxEnergyCell(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu,
598 Int_t & absId, Int_t& iSupMod, Int_t& ieta, Int_t& iphi, Bool_t &shared)
d9b3567c 599{
600 //For a given CaloCluster gets the absId of the cell
601 //with maximum energy deposit.
602
603 Double_t eMax = -1.;
604 Double_t eCell = -1.;
094786cc 605 Float_t fraction = 1.;
606 Float_t recalFactor = 1.;
d9b3567c 607 Int_t cellAbsId = -1 ;
094786cc 608
d9b3567c 609 Int_t iTower = -1;
610 Int_t iIphi = -1;
611 Int_t iIeta = -1;
cb231979 612 Int_t iSupMod0= -1;
2aeb4226 613
614 if(!clu){
615 AliInfo("Cluster pointer null!");
616 absId=-1; iSupMod0=-1, ieta = -1; iphi = -1; shared = -1;
617 return;
618 }
619
d9b3567c 620 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
094786cc 621 cellAbsId = clu->GetCellAbsId(iDig);
622 fraction = clu->GetCellAmplitudeFraction(iDig);
83bfd77a 623 //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
094786cc 624 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
cb231979 625 geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta);
626 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
627 if(iDig==0) iSupMod0=iSupMod;
628 else if(iSupMod0!=iSupMod) {
629 shared = kTRUE;
630 //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
631 }
094786cc 632 if(IsRecalibrationOn()) {
094786cc 633 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
634 }
635 eCell = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
83bfd77a 636 //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
094786cc 637 if(eCell > eMax) {
d9b3567c 638 eMax = eCell;
639 absId = cellAbsId;
640 //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
641 }
642 }// cell loop
643
644 //Get from the absid the supermodule, tower and eta/phi numbers
645 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
646 //Gives SuperModule and Tower numbers
647 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
83bfd77a 648 iIphi, iIeta,iphi,ieta);
649 //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
650 //printf("Max end---\n");
d9b3567c 651
652}
653
094786cc 654//________________________________________________________________
655void AliEMCALRecoUtils::InitEMCALRecalibrationFactors(){
656 //Init EMCAL recalibration factors
657 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
658 //In order to avoid rewriting the same histograms
659 Bool_t oldStatus = TH1::AddDirectoryStatus();
660 TH1::AddDirectory(kFALSE);
661
cb231979 662 fEMCALRecalibrationFactors = new TObjArray(10);
d7194a80 663 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));
094786cc 664 //Init the histograms with 1
d7194a80 665 for (Int_t sm = 0; sm < 10; sm++) {
094786cc 666 for (Int_t i = 0; i < 48; i++) {
667 for (Int_t j = 0; j < 24; j++) {
668 SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
669 }
670 }
671 }
672 fEMCALRecalibrationFactors->SetOwner(kTRUE);
673 fEMCALRecalibrationFactors->Compress();
674
675 //In order to avoid rewriting the same histograms
676 TH1::AddDirectory(oldStatus);
677}
678
679
fd6df01c 680//________________________________________________________________
681void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap(){
682 //Init EMCAL bad channels map
683 AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
684 //In order to avoid rewriting the same histograms
685 Bool_t oldStatus = TH1::AddDirectoryStatus();
686 TH1::AddDirectory(kFALSE);
687
cb231979 688 fEMCALBadChannelMap = new TObjArray(10);
fd6df01c 689 //TH2F * hTemp = new TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
6fe0e6d0 690 for (int i = 0; i < 10; i++) {
fd6df01c 691 fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
692 }
693
694 //delete hTemp;
695
696 fEMCALBadChannelMap->SetOwner(kTRUE);
697 fEMCALBadChannelMap->Compress();
698
699 //In order to avoid rewriting the same histograms
700 TH1::AddDirectory(oldStatus);
701}
702
094786cc 703//________________________________________________________________
704void AliEMCALRecoUtils::RecalibrateClusterEnergy(AliEMCALGeometry* geom, AliVCluster * cluster, AliVCaloCells * cells){
705 // Recalibrate the cluster energy, considering the recalibration map and the energy of the cells that compose the cluster.
706
2aeb4226 707 if(!cluster){
708 AliInfo("Cluster pointer null!");
709 return;
710 }
711
094786cc 712 //Get the cluster number of cells and list of absId, check what kind of cluster do we have.
713 UShort_t * index = cluster->GetCellsAbsId() ;
714 Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
715 Int_t ncells = cluster->GetNCells();
716
717 //Initialize some used variables
718 Float_t energy = 0;
719 Int_t absId = -1;
720 Int_t icol = -1, irow = -1, imod=1;
721 Float_t factor = 1, frac = 0;
722
723 //Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
724 for(Int_t icell = 0; icell < ncells; icell++){
725 absId = index[icell];
726 frac = fraction[icell];
727 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
728 Int_t iTower = -1, iIphi = -1, iIeta = -1;
729 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
730 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
731 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
732 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
733 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
734 imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
735
736 energy += cells->GetCellAmplitude(absId)*factor*frac;
737 }
738
739
740 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f\n",cluster->E(),energy));
741
742 cluster->SetE(energy);
743
744}
745
746
d9b3567c 747//__________________________________________________
094786cc 748void AliEMCALRecoUtils::RecalculateClusterPosition(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
d9b3567c 749{
750 //For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
751
2aeb4226 752 if(!clu){
753 AliInfo("Cluster pointer null!");
754 return;
755 }
756
094786cc 757 if (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
758 else if(fPosAlgo==kPosTowerIndex) RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
fd6df01c 759 else AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
094786cc 760
761}
762
763//__________________________________________________
764void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
765{
766 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
767 // The algorithm is a copy of what is done in AliEMCALRecPoint
768
769 Double_t eCell = 0.;
770 Float_t fraction = 1.;
771 Float_t recalFactor = 1.;
772
773 Int_t absId = -1;
774 Int_t iTower = -1, iIphi = -1, iIeta = -1;
775 Int_t iSupModMax = -1, iSM=-1, iphi = -1, ieta = -1;
776 Float_t weight = 0., totalWeight=0.;
777 Float_t newPos[3] = {0,0,0};
778 Double_t pLocal[3], pGlobal[3];
cb231979 779 Bool_t shared = kFALSE;
780
094786cc 781 Float_t clEnergy = clu->E(); //Energy already recalibrated previously
cb231979 782 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
094786cc 783 Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
784
83bfd77a 785 //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
786
094786cc 787 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
788 absId = clu->GetCellAbsId(iDig);
789 fraction = clu->GetCellAmplitudeFraction(iDig);
790 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
791 geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta);
792 geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);
793
794 if(IsRecalibrationOn()) {
795 recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
796 }
797 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
798
799 weight = GetCellWeight(eCell,clEnergy);
83bfd77a 800 //printf("cell energy %f, weight %f\n",eCell,weight);
094786cc 801 totalWeight += weight;
802 geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
83bfd77a 803 //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
094786cc 804 geom->GetGlobal(pLocal,pGlobal,iSupModMax);
83bfd77a 805 //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
806
094786cc 807 for(int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
808
809 }// cell loop
810
811 if(totalWeight>0){
812 for(int i=0; i<3; i++ ) newPos[i] /= totalWeight;
813 }
814
094786cc 815 //Float_t pos[]={0,0,0};
816 //clu->GetPosition(pos);
817 //printf("OldPos : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
83bfd77a 818 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
094786cc 819
820 if(iSupModMax > 1) {//sector 1
821 newPos[0] +=fMisalTransShift[3];//-=3.093;
822 newPos[1] +=fMisalTransShift[4];//+=6.82;
823 newPos[2] +=fMisalTransShift[5];//+=1.635;
83bfd77a 824 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
825
094786cc 826 }
827 else {//sector 0
828 newPos[0] +=fMisalTransShift[0];//+=1.134;
829 newPos[1] +=fMisalTransShift[1];//+=8.2;
830 newPos[2] +=fMisalTransShift[2];//+=1.197;
83bfd77a 831 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
832
094786cc 833 }
83bfd77a 834 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
835
094786cc 836 clu->SetPosition(newPos);
837
094786cc 838}
839
840//__________________________________________________
841void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(AliEMCALGeometry *geom, AliVCaloCells* cells, AliVCluster* clu)
842{
843 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
844 // The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position
845
846 Double_t eCell = 1.;
847 Float_t fraction = 1.;
848 Float_t recalFactor = 1.;
849
850 Int_t absId = -1;
d9b3567c 851 Int_t iTower = -1;
094786cc 852 Int_t iIphi = -1, iIeta = -1;
853 Int_t iSupMod = -1, iSupModMax = -1;
d9b3567c 854 Int_t iphi = -1, ieta =-1;
cb231979 855 Bool_t shared = kFALSE;
856
d9b3567c 857 Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
cb231979 858 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
094786cc 859 Float_t depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
860
d9b3567c 861 Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
094786cc 862 Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
863 Int_t startingSM = -1;
d9b3567c 864
865 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) {
094786cc 866 absId = clu->GetCellAbsId(iDig);
867 fraction = clu->GetCellAmplitudeFraction(iDig);
868 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
869 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
d9b3567c 870 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
094786cc 871
d9b3567c 872 if (iDig==0) startingSM = iSupMod;
873 else if(iSupMod != startingSM) areInSameSM = kFALSE;
094786cc 874
875 eCell = cells->GetCellAmplitude(absId);
d9b3567c 876
094786cc 877 if(IsRecalibrationOn()) {
878 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
879 }
880 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
d9b3567c 881
094786cc 882 weight = GetCellWeight(eCell,clEnergy);
d9b3567c 883 if(weight < 0) weight = 0;
884 totalWeight += weight;
885 weightedCol += ieta*weight;
886 weightedRow += iphi*weight;
887
888 //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
889
094786cc 890 }// cell loop
891
d9b3567c 892 Float_t xyzNew[]={0.,0.,0.};
893 if(areInSameSM == kTRUE) {
894 //printf("In Same SM\n");
895 weightedCol = weightedCol/totalWeight;
896 weightedRow = weightedRow/totalWeight;
094786cc 897 geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
d9b3567c 898 }
899 else {
900 //printf("In Different SM\n");
094786cc 901 geom->RecalculateTowerPosition(iphi, ieta, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
d9b3567c 902 }
d9b3567c 903
094786cc 904 clu->SetPosition(xyzNew);
d9b3567c 905
906}
907
cb231979 908//____________________________________________________________________________
909void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster){
910
911 //re-evaluate distance to bad channel with updated bad map
912
78467229 913 if(!fRecalDistToBadChannels) return;
cb231979 914
2aeb4226 915 if(!cluster){
916 AliInfo("Cluster pointer null!");
917 return;
918 }
919
cb231979 920 //Get channels map of the supermodule where the cluster is.
cb231979 921 Int_t absIdMax = -1, iSupMod =-1, icolM = -1, irowM = -1;
922 Bool_t shared = kFALSE;
923 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSupMod, icolM, irowM, shared);
924 TH2D* hMap = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
925
926 Int_t dRrow, dRcol;
927 Float_t minDist = 10000.;
928 Float_t dist = 0.;
929
930 //Loop on tower status map
931 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
932 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
933 //Check if tower is bad.
934 if(hMap->GetBinContent(icol,irow)==0) continue;
935 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
6fe0e6d0 936 // iSupMod,icol, irow, icolM,irowM);
cb231979 937
938 dRrow=TMath::Abs(irowM-irow);
939 dRcol=TMath::Abs(icolM-icol);
940 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
941 if(dist < minDist){
942 //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
943 minDist = dist;
944 }
945
946 }
947 }
948
949 //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
950 if (shared) {
951 TH2D* hMap2 = 0;
952 Int_t iSupMod2 = -1;
953
954 //The only possible combinations are (0,1), (2,3) ... (8,9)
955 if(iSupMod%2) iSupMod2 = iSupMod-1;
956 else iSupMod2 = iSupMod+1;
957 hMap2 = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
958
959 //Loop on tower status map of second super module
960 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
961 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
962 //Check if tower is bad.
963 if(hMap2->GetBinContent(icol,irow)==0) continue;
964 //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",
965 // iSupMod2,icol, irow,iSupMod,icolM,irowM);
966
967 dRrow=TMath::Abs(irow-irowM);
968
969 if(iSupMod%2) {
970 dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
971 }
972 else {
973 dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
974 }
975
976 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
977 if(dist < minDist) minDist = dist;
978
979 }
980 }
981
982 }// shared cluster in 2 SuperModules
78467229 983
6fe0e6d0 984 AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
985 cluster->SetDistanceToBadChannel(minDist);
cb231979 986
987}
988
83bfd77a 989//____________________________________________________________________________
990void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster){
991
992 //re-evaluate identification parameters with bayesian
2aeb4226 993
994 if(!cluster){
995 AliInfo("Cluster pointer null!");
996 return;
997 }
998
83bfd77a 999 if ( cluster->GetM02() != 0)
1000 fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
1001
1002 Float_t pidlist[AliPID::kSPECIESN+1];
1003 for(Int_t i = 0; i < AliPID::kSPECIESN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
1004
1005 cluster->SetPID(pidlist);
1006
1007}
1008
1009//____________________________________________________________________________
1010void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(AliEMCALGeometry * geom, AliVCaloCells* cells, AliVCluster * cluster)
1011{
1012 // Calculates new center of gravity in the local EMCAL-module coordinates
1013 // and tranfers into global ALICE coordinates
1014 // Calculates Dispersion and main axis
1015
2aeb4226 1016 if(!cluster){
1017 AliInfo("Cluster pointer null!");
1018 return;
1019 }
1020
83bfd77a 1021 Int_t nstat = 0;
1022 Float_t wtot = 0. ;
1023 Double_t eCell = 0.;
1024 Float_t fraction = 1.;
1025 Float_t recalFactor = 1.;
1026
1027 Int_t iSupMod = -1;
1028 Int_t iTower = -1;
1029 Int_t iIphi = -1;
1030 Int_t iIeta = -1;
1031 Int_t iphi = -1;
1032 Int_t ieta = -1;
1033 Double_t etai = -1.;
1034 Double_t phii = -1.;
1035
1036 Double_t w = 0.;
1037 Double_t d = 0.;
1038 Double_t dxx = 0.;
1039 Double_t dzz = 0.;
1040 Double_t dxz = 0.;
1041 Double_t xmean = 0.;
1042 Double_t zmean = 0.;
1043
1044 //Loop on cells
1045 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1046
1047 //Get from the absid the supermodule, tower and eta/phi numbers
1048 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1049 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1050
1051 //Get the cell energy, if recalibration is on, apply factors
1052 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1053 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1054 if(IsRecalibrationOn()) {
1055 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1056 }
1057 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1058
1059 if(cluster->E() > 0 && eCell > 0){
1060
1061 w = GetCellWeight(eCell,cluster->E());
1062
1063 etai=(Double_t)ieta;
1064 phii=(Double_t)iphi;
1065 if(w > 0.0) {
1066 wtot += w ;
1067 nstat++;
1068 //Shower shape
1069 dxx += w * etai * etai ;
1070 xmean+= w * etai ;
1071 dzz += w * phii * phii ;
1072 zmean+= w * phii ;
1073 dxz += w * etai * phii ;
1074 }
1075 }
1076 else
1077 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1078 }//cell loop
1079
1080 //Normalize to the weight
1081 if (wtot > 0) {
1082 xmean /= wtot ;
1083 zmean /= wtot ;
1084 }
1085 else
1086 AliError(Form("Wrong weight %f\n", wtot));
1087
1088 //Calculate dispersion
1089 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) {
1090
1091 //Get from the absid the supermodule, tower and eta/phi numbers
1092 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1093 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1094
1095 //Get the cell energy, if recalibration is on, apply factors
1096 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1097 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1098 if(IsRecalibrationOn()) {
1099 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1100 }
1101 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1102
1103 if(cluster->E() > 0 && eCell > 0){
1104
1105 w = GetCellWeight(eCell,cluster->E());
1106
1107 etai=(Double_t)ieta;
1108 phii=(Double_t)iphi;
1109 if(w > 0.0) d += w*((etai-xmean)*(etai-xmean)+(phii-zmean)*(phii-zmean));
1110 }
1111 else
1112 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1113 }// cell loop
1114
1115 //Normalize to the weigth and set shower shape parameters
1116 if (wtot > 0 && nstat > 1) {
1117 d /= wtot ;
1118 dxx /= wtot ;
1119 dzz /= wtot ;
1120 dxz /= wtot ;
1121 dxx -= xmean * xmean ;
1122 dzz -= zmean * zmean ;
1123 dxz -= xmean * zmean ;
1124 cluster->SetM02(0.5 * (dxx + dzz) + TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1125 cluster->SetM20(0.5 * (dxx + dzz) - TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz ));
1126 }
1127 else{
1128 d=0. ;
1129 cluster->SetM20(0.) ;
1130 cluster->SetM02(0.) ;
1131 }
1132
1133 if (d>=0)
1134 cluster->SetDispersion(TMath::Sqrt(d)) ;
1135 else
1136 cluster->SetDispersion(0) ;
83bfd77a 1137}
1138
b540d03f 1139//____________________________________________________________________________
b5078f5d 1140void AliEMCALRecoUtils::FindMatches(AliVEvent *event,TObjArray * clusterArr, AliEMCALGeometry *geom)
bd8c7aef 1141{
1142 //This function should be called before the cluster loop
1143 //Before call this function, please recalculate the cluster positions
1144 //Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR
1145 //Store matched cluster indexes and residuals
61160f1f 1146
fa4287a2 1147 fMatchedTrackIndex->Reset();
bd8c7aef 1148 fMatchedClusterIndex->Reset();
fa4287a2 1149 fResidualPhi->Reset();
1150 fResidualEta->Reset();
bd8c7aef 1151
fa4287a2 1152 fMatchedTrackIndex->Set(500);
67241b7e 1153 fMatchedClusterIndex->Set(500);
fa4287a2 1154 fResidualPhi->Set(500);
1155 fResidualEta->Set(500);
bd8c7aef 1156
1c7a2bf4 1157 AliESDEvent* esdevent = dynamic_cast<AliESDEvent*> (event);
1158 AliAODEvent* aodevent = dynamic_cast<AliAODEvent*> (event);
61160f1f 1159
bd8c7aef 1160 Int_t matched=0;
bb6f5f0b 1161 Double_t cv[21];
1162 for (Int_t i=0; i<21;i++) cv[i]=0;
bd8c7aef 1163 for(Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
1164 {
456126ad 1165 AliExternalTrackParam *trackParam = 0;
61160f1f 1166
bb6f5f0b 1167 //If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner
1c7a2bf4 1168 if(esdevent)
61160f1f 1169 {
1170 AliESDtrack *esdTrack = esdevent->GetTrack(itr);
1171 if(!esdTrack || !IsAccepted(esdTrack)) continue;
1172 if(esdTrack->Pt()<fCutMinTrackPt) continue;
1173 const AliESDfriendTrack* friendTrack = esdTrack->GetFriendTrack();
1174 if(friendTrack && friendTrack->GetTPCOut())
bb6f5f0b 1175 {
61160f1f 1176 //Use TPC Out as starting point if it is available
1177 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
bb6f5f0b 1178 }
61160f1f 1179 else
1180 {
1181 //Otherwise use TPC inner
1182 trackParam = const_cast<AliExternalTrackParam*>(esdTrack->GetInnerParam());
1183 }
1184 }
bb6f5f0b 1185
1186 //If the input event is AOD, the starting point for extrapolation is at vertex
1187 //AOD tracks are selected according to its bit.
1c7a2bf4 1188 else if(aodevent)
61160f1f 1189 {
1190 AliAODTrack *aodTrack = aodevent->GetTrack(itr);
1191 if(!aodTrack) continue;
1192 if(!aodTrack->TestFilterMask(fAODFilterMask)) continue; //Select AOD tracks that fulfill GetStandardITSTPCTrackCuts2010()
1193 if(aodTrack->Pt()<fCutMinTrackPt) continue;
1194 Double_t pos[3],mom[3];
1195 aodTrack->GetXYZ(pos);
1196 aodTrack->GetPxPyPz(mom);
1197 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()));
1198 trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
1199 }
bd8c7aef 1200
bb6f5f0b 1201 //Return if the input data is not "AOD" or "ESD"
1202 else
61160f1f 1203 {
1204 printf("Wrong input data type! Should be \"AOD\" or \"ESD\"\n");
1205 return;
1206 }
1207
bb6f5f0b 1208 if(!trackParam) continue;
61160f1f 1209
fa4287a2 1210 Float_t dRMax = fCutR, dEtaMax=fCutEta, dPhiMax=fCutPhi;
bd8c7aef 1211 Int_t index = -1;
b540d03f 1212 if(!clusterArr){// get clusters from event
1213 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
61160f1f 1214 {
1215 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1216 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1217 AliExternalTrackParam trkPamTmp(*trackParam);//Retrieve the starting point every time before the extrapolation
1218 Float_t tmpEta=-999, tmpPhi=-999;
1219 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1220 if(fCutEtaPhiSum)
1221 {
1222 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1223 if(tmpR<dRMax)
1224 {
1225 dRMax=tmpR;
1226 dEtaMax=tmpEta;
1227 dPhiMax=tmpPhi;
1228 index=icl;
1229 }
1230 }
1231 else if(fCutEtaPhiSeparate)
1232 {
1233 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1234 {
1235 dEtaMax = tmpEta;
1236 dPhiMax = tmpPhi;
1237 index=icl;
1238 }
1239 }
1240 else
1241 {
1242 printf("Error: please specify your cut criteria\n");
1243 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1244 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1245 if(aodevent && trackParam) delete trackParam;
1246 return;
1247 }
1248 }//cluster loop
1249 }
1250 else { // external cluster array, not from ESD event
b540d03f 1251 for(Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
61160f1f 1252 {
1253 AliVCluster *cluster = dynamic_cast<AliVCluster*> (clusterArr->At(icl)) ;
1254 if(!cluster){
1255 AliInfo("Cluster not found!!!");
1256 continue;
1257 }
1258 if(!cluster->IsEMCAL()) continue;
1259 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1260 Float_t tmpEta=-999, tmpPhi=-999;
1261 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1262 if(fCutEtaPhiSum)
1263 {
1264 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1265 if(tmpR<dRMax)
1266 {
1267 dRMax=tmpR;
1268 dEtaMax=tmpEta;
1269 dPhiMax=tmpPhi;
1270 index=icl;
1271 }
1272 }
1273 else if(fCutEtaPhiSeparate)
1274 {
1275 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
1276 {
1277 dEtaMax = tmpEta;
1278 dPhiMax = tmpPhi;
1279 index=icl;
1280 }
1281 }
1282 else
1283 {
1284 printf("Error: please specify your cut criteria\n");
1285 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1286 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1287 if(aodevent && trackParam) delete trackParam;
1288 return;
1289 }
b540d03f 1290 }//cluster loop
1291 }// external list of clusters
61160f1f 1292
bd8c7aef 1293 if(index>-1)
1294 {
b540d03f 1295 fMatchedTrackIndex ->AddAt(itr,matched);
bd8c7aef 1296 fMatchedClusterIndex->AddAt(index,matched);
fa4287a2 1297 fResidualEta ->AddAt(dEtaMax,matched);
1298 fResidualPhi ->AddAt(dPhiMax,matched);
bd8c7aef 1299 matched++;
1300 }
456126ad 1301 if(aodevent && trackParam) delete trackParam;
bd8c7aef 1302 }//track loop
b540d03f 1303
1304 AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
1305
1306 fMatchedTrackIndex ->Set(matched);
bd8c7aef 1307 fMatchedClusterIndex->Set(matched);
fa4287a2 1308 fResidualPhi ->Set(matched);
1309 fResidualEta ->Set(matched);
bd8c7aef 1310}
1311
b540d03f 1312//________________________________________________________________________________
b5078f5d 1313Int_t AliEMCALRecoUtils::FindMatchedCluster(AliESDtrack *track, AliVEvent *event, AliEMCALGeometry *geom)
bb6f5f0b 1314{
1315 //
1316 // This function returns the index of matched cluster to input track
fa4287a2 1317 // Returns -1 if no match is found
61160f1f 1318
1319
fa4287a2 1320 Float_t dRMax = fCutR, dEtaMax = fCutEta, dPhiMax = fCutPhi;
bb6f5f0b 1321 Int_t index = -1;
61160f1f 1322
bb6f5f0b 1323 AliExternalTrackParam *trackParam=0;
1324 const AliESDfriendTrack* friendTrack = track->GetFriendTrack();
1325 if(friendTrack && friendTrack->GetTPCOut())
1326 trackParam= const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
1327 else
1328 trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
61160f1f 1329
bb6f5f0b 1330 if(!trackParam) return index;
1331 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
61160f1f 1332 {
1333 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1334 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1335 AliExternalTrackParam trkPamTmp (*trackParam);//Retrieve the starting point every time before the extrapolation
1336 Float_t tmpEta=-999, tmpPhi=-999;
1337 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, tmpEta, tmpPhi)) continue;
1338 if(fCutEtaPhiSum)
bb6f5f0b 1339 {
61160f1f 1340 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
1341 if(tmpR<dRMax)
fa4287a2 1342 {
1343 dRMax=tmpR;
1344 dEtaMax=tmpEta;
1345 dPhiMax=tmpPhi;
1346 index=icl;
1347 }
61160f1f 1348 }
1349 else if(fCutEtaPhiSeparate)
1350 {
1351 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
fa4287a2 1352 {
1353 dEtaMax = tmpEta;
1354 dPhiMax = tmpPhi;
1355 index=icl;
1356 }
61160f1f 1357 }
1358 else
1359 {
1360 printf("Error: please specify your cut criteria\n");
1361 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1362 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1363 return -1;
1364 }
1365 }//cluster loop
bb6f5f0b 1366 return index;
1367}
1368
1369//________________________________________________________________________________
fa4287a2 1370Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, AliVCluster *cluster, Float_t &tmpEta, Float_t &tmpPhi)
bb6f5f0b 1371{
1372 //
1373 //Return the residual by extrapolating a track to a cluster
1374 //
1375 if(!trkParam || !cluster) return kFALSE;
1376 Float_t clsPos[3];
1377 Double_t trkPos[3];
1378 cluster->GetPosition(clsPos); //Has been recalculated
1379 TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
1380 Double_t alpha = ((int)(vec.Phi()*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
1381 vec.RotateZ(-alpha); //Rotate the cluster to the local extrapolation coordinate system
1382 trkParam->Rotate(alpha); //Rotate the track to the same local extrapolation system
bd36717e 1383 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), fMass, fStep,kFALSE, 0.8, -1)) return kFALSE;
bb6f5f0b 1384 trkParam->GetXYZ(trkPos); //Get the extrapolated global position
fa4287a2 1385
1386 TVector3 clsPosVec(clsPos[0],clsPos[1],clsPos[2]);
1387 TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
1388
1389 Float_t clsPhi = (Float_t)clsPosVec.Phi();
1390 if(clsPhi<0) clsPhi+=2*TMath::Pi();
1391 Float_t trkPhi = (Float_t)trkPosVec.Phi();
1392 if(trkPhi<0) trkPhi+=2*TMath::Pi();
1393 tmpPhi = clsPhi-trkPhi; // track cluster matching
1394 tmpEta = clsPosVec.Eta()-trkPosVec.Eta(); // track cluster matching
1395
bb6f5f0b 1396 return kTRUE;
1397}
1398
1399//________________________________________________________________________________
fa4287a2 1400void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex, Float_t &dEta, Float_t &dPhi)
bd8c7aef 1401{
bb6f5f0b 1402 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
fa4287a2 1403 //Get the residuals dEta and dPhi for this cluster to the closest track
bb6f5f0b 1404 //Works with ESDs and AODs
bd8c7aef 1405
bb6f5f0b 1406 if( FindMatchedPosForCluster(clsIndex) >= 999 )
bd8c7aef 1407 {
1408 AliDebug(2,"No matched tracks found!\n");
fa4287a2 1409 dEta=999.;
1410 dPhi=999.;
bd8c7aef 1411 return;
1412 }
fa4287a2 1413 dEta = fResidualEta->At(FindMatchedPosForCluster(clsIndex));
1414 dPhi = fResidualPhi->At(FindMatchedPosForCluster(clsIndex));
bb6f5f0b 1415}
1416//________________________________________________________________________________
fa4287a2 1417void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dEta, Float_t &dPhi)
bb6f5f0b 1418{
1419 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
fa4287a2 1420 //Get the residuals dEta and dPhi for this track to the closest cluster
bb6f5f0b 1421 //Works with ESDs and AODs
1422
1423 if( FindMatchedPosForTrack(trkIndex) >= 999 )
1424 {
1425 AliDebug(2,"No matched cluster found!\n");
fa4287a2 1426 dEta=999.;
1427 dPhi=999.;
bb6f5f0b 1428 return;
1429 }
fa4287a2 1430 dEta = fResidualEta->At(FindMatchedPosForTrack(trkIndex));
1431 dPhi = fResidualPhi->At(FindMatchedPosForTrack(trkIndex));
bb6f5f0b 1432}
1433
1434//__________________________________________________________
1435Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
1436{
1437 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1438 //Get the index of matched track to this cluster
1439 //Works with ESDs and AODs
1440
1441 if(IsClusterMatched(clsIndex))
1442 return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
1443 else
1444 return -1;
bd8c7aef 1445}
1446
b540d03f 1447//__________________________________________________________
bb6f5f0b 1448Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
b540d03f 1449{
bb6f5f0b 1450 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1451 //Get the index of matched cluster to this track
1452 //Works with ESDs and AODs
b540d03f 1453
bb6f5f0b 1454 if(IsTrackMatched(trkIndex))
1455 return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
b540d03f 1456 else
1457 return -1;
1458}
1459
bb6f5f0b 1460//__________________________________________________
7cdec71f 1461Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex) const
bb6f5f0b 1462{
1463 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
1464 //Returns if the cluster has a match
1465 if(FindMatchedPosForCluster(clsIndex) < 999)
1466 return kTRUE;
1467 else
1468 return kFALSE;
1469}
b540d03f 1470
bd8c7aef 1471//__________________________________________________
7cdec71f 1472Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex) const
bd8c7aef 1473{
bb6f5f0b 1474 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1475 //Returns if the track has a match
1476 if(FindMatchedPosForTrack(trkIndex) < 999)
82d09e74 1477 return kTRUE;
bd8c7aef 1478 else
1479 return kFALSE;
1480}
bb6f5f0b 1481
b540d03f 1482//__________________________________________________________
bb6f5f0b 1483UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
bd8c7aef 1484{
bb6f5f0b 1485 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
bd8c7aef 1486 //Returns the position of the match in the fMatchedClusterIndex array
1487 Float_t tmpR = fCutR;
81efb149 1488 UInt_t pos = 999;
b540d03f 1489
bd8c7aef 1490 for(Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++)
b540d03f 1491 {
fa4287a2 1492 if(fMatchedClusterIndex->At(i)==clsIndex)
1493 {
1494 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1495 if(r<tmpR)
1496 {
1497 pos=i;
1498 tmpR=r;
1499 AliDebug(3,Form("Matched cluster index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedClusterIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1500 }
1501 }
bb6f5f0b 1502 }
1503 return pos;
1504}
1505
1506//__________________________________________________________
1507UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
1508{
1509 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
1510 //Returns the position of the match in the fMatchedTrackIndex array
1511 Float_t tmpR = fCutR;
1512 UInt_t pos = 999;
1513
1514 for(Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++)
1515 {
fa4287a2 1516 if(fMatchedTrackIndex->At(i)==trkIndex)
1517 {
1518 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
1519 if(r<tmpR)
1520 {
1521 pos=i;
1522 tmpR=r;
1523 AliDebug(3,Form("Matched track index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",fMatchedTrackIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
1524 }
1525 }
b540d03f 1526 }
bd8c7aef 1527 return pos;
1528}
1529
b5078f5d 1530//__________________________________________________________
1531Bool_t AliEMCALRecoUtils::IsGoodCluster(AliVCluster *cluster, AliEMCALGeometry *geom, AliVCaloCells* cells)
1532{
1533 // check if the cluster survives some quality cut
1534 //
1535 //
1536 Bool_t isGood=kTRUE;
08ff636b 1537 if(!cluster || !cluster->IsEMCAL()) return kFALSE;
fa4287a2 1538 if(ClusterContainsBadChannel(geom,cluster->GetCellsAbsId(),cluster->GetNCells())) return kFALSE;
1539 if(!CheckCellFiducialRegion(geom,cluster,cells)) return kFALSE;
1540 if(fRejectExoticCluster && IsExoticCluster(cluster)) return kFALSE;
b5078f5d 1541
1542 return isGood;
1543}
1544
b540d03f 1545//__________________________________________________________
bd8c7aef 1546Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
1547{
1548 // Given a esd track, return whether the track survive all the cuts
1549
1550 // The different quality parameter are first
1551 // retrieved from the track. then it is found out what cuts the
1552 // track did not survive and finally the cuts are imposed.
1553
1554 UInt_t status = esdTrack->GetStatus();
1555
1556 Int_t nClustersITS = esdTrack->GetITSclusters(0);
1557 Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
1558
1559 Float_t chi2PerClusterITS = -1;
1560 Float_t chi2PerClusterTPC = -1;
1561 if (nClustersITS!=0)
1562 chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
1563 if (nClustersTPC!=0)
1564 chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
82d09e74 1565
1566
1567 //DCA cuts
7cdec71f 1568 Float_t maxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); //This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
82d09e74 1569 //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
7cdec71f 1570 SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
82d09e74 1571
1572
bd8c7aef 1573 Float_t b[2];
1574 Float_t bCov[3];
1575 esdTrack->GetImpactParameters(b,bCov);
1576 if (bCov[0]<=0 || bCov[2]<=0) {
1577 AliDebug(1, "Estimated b resolution lower or equal zero!");
1578 bCov[0]=0; bCov[2]=0;
1579 }
1580
1581 Float_t dcaToVertexXY = b[0];
1582 Float_t dcaToVertexZ = b[1];
1583 Float_t dcaToVertex = -1;
1584
1585 if (fCutDCAToVertex2D)
1586 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY/fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + dcaToVertexZ*dcaToVertexZ/fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ);
1587 else
1588 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
1589
1590 // cut the track?
1591
1592 Bool_t cuts[kNCuts];
1593 for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
1594
1595 // track quality cuts
1596 if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
1597 cuts[0]=kTRUE;
1598 if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
1599 cuts[1]=kTRUE;
1600 if (nClustersTPC<fCutMinNClusterTPC)
1601 cuts[2]=kTRUE;
1602 if (nClustersITS<fCutMinNClusterITS)
1603 cuts[3]=kTRUE;
1604 if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC)
1605 cuts[4]=kTRUE;
1606 if (chi2PerClusterITS>fCutMaxChi2PerClusterITS)
1607 cuts[5]=kTRUE;
1608 if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
1609 cuts[6]=kTRUE;
1610 if (fCutDCAToVertex2D && dcaToVertex > 1)
1611 cuts[7] = kTRUE;
1612 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
1613 cuts[8] = kTRUE;
1614 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ) > fCutMaxDCAToVertexZ)
1615 cuts[9] = kTRUE;
1616
82d09e74 1617 //Require at least one SPD point + anything else in ITS
1618 if( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
1619 cuts[10] = kTRUE;
1620
bd8c7aef 1621 Bool_t cut=kFALSE;
1622 for (Int_t i=0; i<kNCuts; i++)
1623 if (cuts[i]) {cut = kTRUE;}
1624
1625 // cut the track
1626 if (cut)
1627 return kFALSE;
1628 else
1629 return kTRUE;
1630}
1631//__________________________________________________
1632void AliEMCALRecoUtils::InitTrackCuts()
1633{
1634 //Intilize the track cut criteria
5f7714ad 1635 //By default these cuts are set according to AliESDtrackCuts::GetStandardTPCOnlyTrackCuts()
bd8c7aef 1636 //Also you can customize the cuts using the setters
82d09e74 1637
5f7714ad 1638 switch (fTrackCutsType)
1639 {
1640 case kTPCOnlyCut:
1641 {
1642 AliInfo(Form("Track cuts for matching: GetStandardTPCOnlyTrackCuts()\n"));
1643 //TPC
1644 SetMinNClustersTPC(70);
1645 SetMaxChi2PerClusterTPC(4);
1646 SetAcceptKinkDaughters(kFALSE);
1647 SetRequireTPCRefit(kFALSE);
1648
1649 //ITS
1650 SetRequireITSRefit(kFALSE);
1651 SetMaxDCAToVertexZ(3.2);
1652 SetMaxDCAToVertexXY(2.4);
1653 SetDCAToVertex2D(kTRUE);
1654
1655 break;
1656 }
1657
1658 case kGlobalCut:
1659 {
1660 AliInfo(Form("Track cuts for matching: GetStandardITSTPCTrackCuts2010(kTURE)\n"));
1661 //TPC
1662 SetMinNClustersTPC(70);
1663 SetMaxChi2PerClusterTPC(4);
1664 SetAcceptKinkDaughters(kFALSE);
1665 SetRequireTPCRefit(kTRUE);
1666
1667 //ITS
1668 SetRequireITSRefit(kTRUE);
1669 SetMaxDCAToVertexZ(2);
1670 SetMaxDCAToVertexXY();
1671 SetDCAToVertex2D(kFALSE);
1672
1673 break;
1674 }
1675 }
bd8c7aef 1676}
83bfd77a 1677
b540d03f 1678//___________________________________________________
d9b3567c 1679void AliEMCALRecoUtils::Print(const Option_t *) const
1680{
1681 // Print Parameters
1682
1683 printf("AliEMCALRecoUtils Settings: \n");
1684 printf("Misalignment shifts\n");
2a71e873 1685 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,
1686 fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
1687 fMisalRotShift[i*3], fMisalRotShift[i*3+1], fMisalRotShift[i*3+2] );
d9b3567c 1688 printf("Non linearity function %d, parameters:\n", fNonLinearityFunction);
1689 for(Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
094786cc 1690
1691 printf("Position Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
bd8c7aef 1692
fa4287a2 1693 printf("Matching criteria: ");
1694 if(fCutEtaPhiSum)
1695 {
1696 printf("sqrt(dEta^2+dPhi^2)<%2.2f\n",fCutR);
1697 }
1698 else if(fCutEtaPhiSeparate)
1699 {
1700 printf("dEta<%2.2f, dPhi<%2.2f\n",fCutEta,fCutPhi);
1701 }
1702 else
1703 {
1704 printf("Error\n");
1705 printf("please specify your cut criteria\n");
1706 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
1707 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
1708 }
1709
5f7714ad 1710 printf("Mass hypothesis = %2.3f [GeV/c^2], extrapolation step = %2.2f[cm]\n",fMass,fStep);
bd8c7aef 1711
1712 printf("Track cuts: \n");
fa4287a2 1713 printf("Minimum track pT: %1.2f\n",fCutMinTrackPt);
bb6f5f0b 1714 printf("AOD track selection mask: %d\n",fAODFilterMask);
bd8c7aef 1715 printf("TPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
1716 printf("AcceptKinks = %d\n",fCutAcceptKinkDaughters);
1717 printf("MinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
1718 printf("MaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
1719 printf("DCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
1720
d9b3567c 1721}
96957075 1722
b540d03f 1723//_____________________________________________________________________
96957075 1724void AliEMCALRecoUtils::SetTimeDependentCorrections(Int_t runnumber){
1725 //Get EMCAL time dependent corrections from file and put them in the recalibration histograms
1726 //Do it only once and only if it is requested
1727
1728 if(!fUseTimeCorrectionFactors) return;
1729 if(fTimeCorrectionFactorsSet) return;
1730
1731 printf("AliEMCALRecoUtils::GetTimeDependentCorrections() - Get Correction Factors for Run number %d\n",runnumber);
1732
1733 AliEMCALCalibTimeDepCorrection *corr = new AliEMCALCalibTimeDepCorrection();
1734 corr->ReadRootInfo(Form("CorrectionFiles/Run%d_Correction.root",runnumber));
1735
1736 SwitchOnRecalibration();
1737 for(Int_t ism = 0; ism < 4; ism++){
1738 for(Int_t icol = 0; icol < 48; icol++){
1739 for(Int_t irow = 0; irow < 24; irow++){
1740 Float_t orgRecalFactor = GetEMCALChannelRecalibrationFactors(ism)->GetBinContent(icol,irow);
1741 Float_t newRecalFactor = orgRecalFactor*corr->GetCorrection(ism, icol,irow,0);
1742 GetEMCALChannelRecalibrationFactors(ism)->SetBinContent(icol,irow,newRecalFactor);
1743 //printf("ism %d, icol %d, irow %d, corrections : org %f, time dep %f, final %f (org*time %f)\n",ism, icol, irow,
1744 // orgRecalFactor, corr->GetCorrection(ism, icol,irow,0),
1745 // (GetEMCALChannelRecalibrationFactors(ism))->GetBinContent(icol,irow),newRecalFactor);
1746 }
1747 }
1748 }
1749 fTimeCorrectionFactorsSet = kTRUE;
1750}
1751