]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - EMCAL/AliEMCALRecoUtils.cxx
new dielectron tasks from Remi
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALRecoUtils.cxx
... / ...
CommitLineData
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 | Sun Dec 8 06:56:48 2013 +0100 | Constantin Loizides $ */
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)
25// Track matching part: Rongrong Ma (Yale)
26
27///////////////////////////////////////////////////////////////////////////////
28// --- standard c ---
29
30// standard C++ includes
31//#include <Riostream.h>
32
33// ROOT includes
34#include <TGeoManager.h>
35#include <TGeoMatrix.h>
36#include <TGeoBBox.h>
37#include <TH2F.h>
38#include <TArrayI.h>
39#include <TArrayF.h>
40#include <TObjArray.h>
41
42// STEER includes
43#include "AliVCluster.h"
44#include "AliVCaloCells.h"
45#include "AliLog.h"
46#include "AliPID.h"
47#include "AliESDEvent.h"
48#include "AliAODEvent.h"
49#include "AliESDtrack.h"
50#include "AliAODTrack.h"
51#include "AliExternalTrackParam.h"
52#include "AliESDfriendTrack.h"
53#include "AliTrackerBase.h"
54
55// EMCAL includes
56#include "AliEMCALRecoUtils.h"
57#include "AliEMCALGeometry.h"
58#include "AliTrackerBase.h"
59#include "AliEMCALPIDUtils.h"
60
61ClassImp(AliEMCALRecoUtils)
62
63//_____________________________________
64AliEMCALRecoUtils::AliEMCALRecoUtils():
65 fParticleType(0), fPosAlgo(0), fW0(0),
66 fNonLinearityFunction(0), fNonLinearThreshold(0),
67 fSmearClusterEnergy(kFALSE), fRandom(),
68 fCellsRecalibrated(kFALSE), fRecalibration(kFALSE), fEMCALRecalibrationFactors(),
69 fTimeRecalibration(kFALSE), fEMCALTimeRecalibrationFactors(), fUseRunCorrectionFactors(kFALSE),
70 fRemoveBadChannels(kFALSE), fRecalDistToBadChannels(kFALSE), fEMCALBadChannelMap(),
71 fNCellsFromEMCALBorder(0), fNoEMCALBorderAtEta0(kTRUE),
72 fRejectExoticCluster(kFALSE), fRejectExoticCells(kFALSE),
73 fExoticCellFraction(0), fExoticCellDiffTime(0), fExoticCellMinAmplitude(0),
74 fPIDUtils(), fAODFilterMask(0),
75 fAODHybridTracks(0), fAODTPCOnlyTracks(0),
76 fMatchedTrackIndex(0x0), fMatchedClusterIndex(0x0),
77 fResidualEta(0x0), fResidualPhi(0x0), fCutEtaPhiSum(kFALSE), fCutEtaPhiSeparate(kFALSE),
78 fCutR(0), fCutEta(0), fCutPhi(0),
79 fClusterWindow(0), fMass(0),
80 fStepSurface(0), fStepCluster(0),
81 fITSTrackSA(kFALSE), fEMCalSurfaceDistance(430.),
82 fTrackCutsType(0), fCutMinTrackPt(0), fCutMinNClusterTPC(0),
83 fCutMinNClusterITS(0), fCutMaxChi2PerClusterTPC(0), fCutMaxChi2PerClusterITS(0),
84 fCutRequireTPCRefit(kFALSE), fCutRequireITSRefit(kFALSE), fCutAcceptKinkDaughters(kFALSE),
85 fCutMaxDCAToVertexXY(0), fCutMaxDCAToVertexZ(0), fCutDCAToVertex2D(kFALSE),
86 fCutRequireITSStandAlone(kFALSE), fCutRequireITSpureSA(kFALSE)
87{
88//
89 // Constructor.
90 // Initialize all constant values which have to be used
91 // during Reco algorithm execution
92 //
93
94 // Init parameters
95 InitParameters();
96
97 //Track matching
98 fMatchedTrackIndex = new TArrayI();
99 fMatchedClusterIndex = new TArrayI();
100 fResidualPhi = new TArrayF();
101 fResidualEta = new TArrayF();
102 fPIDUtils = new AliEMCALPIDUtils();
103
104}
105
106//______________________________________________________________________
107AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco)
108: TNamed(reco),
109 fParticleType(reco.fParticleType), fPosAlgo(reco.fPosAlgo), fW0(reco.fW0),
110 fNonLinearityFunction(reco.fNonLinearityFunction), fNonLinearThreshold(reco.fNonLinearThreshold),
111 fSmearClusterEnergy(reco.fSmearClusterEnergy), fRandom(),
112 fCellsRecalibrated(reco.fCellsRecalibrated),
113 fRecalibration(reco.fRecalibration), fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
114 fTimeRecalibration(reco.fTimeRecalibration), fEMCALTimeRecalibrationFactors(reco.fEMCALTimeRecalibrationFactors),
115 fUseRunCorrectionFactors(reco.fUseRunCorrectionFactors),
116 fRemoveBadChannels(reco.fRemoveBadChannels), fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
117 fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
118 fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder), fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
119 fRejectExoticCluster(reco.fRejectExoticCluster), fRejectExoticCells(reco.fRejectExoticCells),
120 fExoticCellFraction(reco.fExoticCellFraction), fExoticCellDiffTime(reco.fExoticCellDiffTime),
121 fExoticCellMinAmplitude(reco.fExoticCellMinAmplitude),
122 fPIDUtils(reco.fPIDUtils), fAODFilterMask(reco.fAODFilterMask),
123 fAODHybridTracks(reco.fAODHybridTracks), fAODTPCOnlyTracks(reco.fAODTPCOnlyTracks),
124 fMatchedTrackIndex( reco.fMatchedTrackIndex? new TArrayI(*reco.fMatchedTrackIndex):0x0),
125 fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
126 fResidualEta( reco.fResidualEta? new TArrayF(*reco.fResidualEta):0x0),
127 fResidualPhi( reco.fResidualPhi? new TArrayF(*reco.fResidualPhi):0x0),
128 fCutEtaPhiSum(reco.fCutEtaPhiSum), fCutEtaPhiSeparate(reco.fCutEtaPhiSeparate),
129 fCutR(reco.fCutR), fCutEta(reco.fCutEta), fCutPhi(reco.fCutPhi),
130 fClusterWindow(reco.fClusterWindow),
131 fMass(reco.fMass), fStepSurface(reco.fStepSurface), fStepCluster(reco.fStepCluster),
132 fITSTrackSA(reco.fITSTrackSA), fEMCalSurfaceDistance(430.),
133 fTrackCutsType(reco.fTrackCutsType), fCutMinTrackPt(reco.fCutMinTrackPt),
134 fCutMinNClusterTPC(reco.fCutMinNClusterTPC), fCutMinNClusterITS(reco.fCutMinNClusterITS),
135 fCutMaxChi2PerClusterTPC(reco.fCutMaxChi2PerClusterTPC), fCutMaxChi2PerClusterITS(reco.fCutMaxChi2PerClusterITS),
136 fCutRequireTPCRefit(reco.fCutRequireTPCRefit), fCutRequireITSRefit(reco.fCutRequireITSRefit),
137 fCutAcceptKinkDaughters(reco.fCutAcceptKinkDaughters), fCutMaxDCAToVertexXY(reco.fCutMaxDCAToVertexXY),
138 fCutMaxDCAToVertexZ(reco.fCutMaxDCAToVertexZ), fCutDCAToVertex2D(reco.fCutDCAToVertex2D),
139 fCutRequireITSStandAlone(reco.fCutRequireITSStandAlone), fCutRequireITSpureSA(reco.fCutRequireITSpureSA)
140{
141 //Copy ctor
142
143 for(Int_t i = 0; i < 15 ; i++) { fMisalRotShift[i] = reco.fMisalRotShift[i] ;
144 fMisalTransShift[i] = reco.fMisalTransShift[i] ; }
145 for(Int_t i = 0; i < 7 ; i++) { fNonLinearityParams[i] = reco.fNonLinearityParams[i] ; }
146 for(Int_t i = 0; i < 3 ; i++) { fSmearClusterParam[i] = reco.fSmearClusterParam[i] ; }
147
148}
149
150
151//______________________________________________________________________
152AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco)
153{
154 //Assignment operator
155
156 if(this == &reco)return *this;
157 ((TNamed *)this)->operator=(reco);
158
159 for(Int_t i = 0; i < 15 ; i++) { fMisalTransShift[i] = reco.fMisalTransShift[i] ;
160 fMisalRotShift[i] = reco.fMisalRotShift[i] ; }
161 for(Int_t i = 0; i < 7 ; i++) { fNonLinearityParams[i] = reco.fNonLinearityParams[i] ; }
162 for(Int_t i = 0; i < 3 ; i++) { fSmearClusterParam[i] = reco.fSmearClusterParam[i] ; }
163
164 fParticleType = reco.fParticleType;
165 fPosAlgo = reco.fPosAlgo;
166 fW0 = reco.fW0;
167
168 fNonLinearityFunction = reco.fNonLinearityFunction;
169 fNonLinearThreshold = reco.fNonLinearThreshold;
170 fSmearClusterEnergy = reco.fSmearClusterEnergy;
171
172 fCellsRecalibrated = reco.fCellsRecalibrated;
173 fRecalibration = reco.fRecalibration;
174 fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
175
176 fTimeRecalibration = reco.fTimeRecalibration;
177 fEMCALTimeRecalibrationFactors = reco.fEMCALTimeRecalibrationFactors;
178
179 fUseRunCorrectionFactors = reco.fUseRunCorrectionFactors;
180
181 fRemoveBadChannels = reco.fRemoveBadChannels;
182 fRecalDistToBadChannels = reco.fRecalDistToBadChannels;
183 fEMCALBadChannelMap = reco.fEMCALBadChannelMap;
184
185 fNCellsFromEMCALBorder = reco.fNCellsFromEMCALBorder;
186 fNoEMCALBorderAtEta0 = reco.fNoEMCALBorderAtEta0;
187
188 fRejectExoticCluster = reco.fRejectExoticCluster;
189 fRejectExoticCells = reco.fRejectExoticCells;
190 fExoticCellFraction = reco.fExoticCellFraction;
191 fExoticCellDiffTime = reco.fExoticCellDiffTime;
192 fExoticCellMinAmplitude = reco.fExoticCellMinAmplitude;
193
194 fPIDUtils = reco.fPIDUtils;
195
196 fAODFilterMask = reco.fAODFilterMask;
197 fAODHybridTracks = reco.fAODHybridTracks;
198 fAODTPCOnlyTracks = reco.fAODTPCOnlyTracks;
199
200 fCutEtaPhiSum = reco.fCutEtaPhiSum;
201 fCutEtaPhiSeparate = reco.fCutEtaPhiSeparate;
202 fCutR = reco.fCutR;
203 fCutEta = reco.fCutEta;
204 fCutPhi = reco.fCutPhi;
205 fClusterWindow = reco.fClusterWindow;
206 fMass = reco.fMass;
207 fStepSurface = reco.fStepSurface;
208 fStepCluster = reco.fStepCluster;
209 fITSTrackSA = reco.fITSTrackSA;
210 fEMCalSurfaceDistance = reco.fEMCalSurfaceDistance;
211
212 fTrackCutsType = reco.fTrackCutsType;
213 fCutMinTrackPt = reco.fCutMinTrackPt;
214 fCutMinNClusterTPC = reco.fCutMinNClusterTPC;
215 fCutMinNClusterITS = reco.fCutMinNClusterITS;
216 fCutMaxChi2PerClusterTPC = reco.fCutMaxChi2PerClusterTPC;
217 fCutMaxChi2PerClusterITS = reco.fCutMaxChi2PerClusterITS;
218 fCutRequireTPCRefit = reco.fCutRequireTPCRefit;
219 fCutRequireITSRefit = reco.fCutRequireITSRefit;
220 fCutAcceptKinkDaughters = reco.fCutAcceptKinkDaughters;
221 fCutMaxDCAToVertexXY = reco.fCutMaxDCAToVertexXY;
222 fCutMaxDCAToVertexZ = reco.fCutMaxDCAToVertexZ;
223 fCutDCAToVertex2D = reco.fCutDCAToVertex2D;
224 fCutRequireITSStandAlone = reco.fCutRequireITSStandAlone;
225 fCutRequireITSpureSA = reco.fCutRequireITSpureSA;
226 if(reco.fResidualEta)
227 {
228 // assign or copy construct
229 if(fResidualEta)
230 {
231 *fResidualEta = *reco.fResidualEta;
232 }
233 else
234 {
235 fResidualEta = new TArrayF(*reco.fResidualEta);
236 }
237 }
238 else
239 {
240 if(fResidualEta)delete fResidualEta;
241 fResidualEta = 0;
242 }
243
244 if(reco.fResidualPhi)
245 {
246 // assign or copy construct
247 if(fResidualPhi)
248 {
249 *fResidualPhi = *reco.fResidualPhi;
250 }
251 else
252 {
253 fResidualPhi = new TArrayF(*reco.fResidualPhi);
254 }
255 }
256 else
257 {
258 if(fResidualPhi)delete fResidualPhi;
259 fResidualPhi = 0;
260 }
261
262 if(reco.fMatchedTrackIndex)
263 {
264 // assign or copy construct
265 if(fMatchedTrackIndex)
266 {
267 *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
268 }
269 else
270 {
271 fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
272 }
273 }
274 else
275 {
276 if(fMatchedTrackIndex)delete fMatchedTrackIndex;
277 fMatchedTrackIndex = 0;
278 }
279
280 if(reco.fMatchedClusterIndex)
281 {
282 // assign or copy construct
283 if(fMatchedClusterIndex)
284 {
285 *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
286 }
287 else
288 {
289 fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
290 }
291 }
292 else
293 {
294 if(fMatchedClusterIndex)delete fMatchedClusterIndex;
295 fMatchedClusterIndex = 0;
296 }
297
298 return *this;
299}
300
301
302//_____________________________________
303AliEMCALRecoUtils::~AliEMCALRecoUtils()
304{
305 //Destructor.
306
307 if(fEMCALRecalibrationFactors)
308 {
309 fEMCALRecalibrationFactors->Clear();
310 delete fEMCALRecalibrationFactors;
311 }
312
313 if(fEMCALTimeRecalibrationFactors)
314 {
315 fEMCALTimeRecalibrationFactors->Clear();
316 delete fEMCALTimeRecalibrationFactors;
317 }
318
319 if(fEMCALBadChannelMap)
320 {
321 fEMCALBadChannelMap->Clear();
322 delete fEMCALBadChannelMap;
323 }
324
325 delete fMatchedTrackIndex ;
326 delete fMatchedClusterIndex ;
327 delete fResidualEta ;
328 delete fResidualPhi ;
329 delete fPIDUtils ;
330
331 InitTrackCuts();
332}
333
334//_______________________________________________________________________________
335Bool_t AliEMCALRecoUtils::AcceptCalibrateCell(Int_t absID, Int_t bc,
336 Float_t & amp, Double_t & time,
337 AliVCaloCells* cells)
338{
339 // Reject cell if criteria not passed and calibrate it
340
341 AliEMCALGeometry* geom = AliEMCALGeometry::GetInstance();
342
343 if(absID < 0 || absID >= 24*48*geom->GetNumberOfSuperModules()) return kFALSE;
344
345 Int_t imod = -1, iphi =-1, ieta=-1,iTower = -1, iIphi = -1, iIeta = -1;
346
347 if(!geom->GetCellIndex(absID,imod,iTower,iIphi,iIeta))
348 {
349 // cell absID does not exist
350 amp=0; time = 1.e9;
351 return kFALSE;
352 }
353
354 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,iphi,ieta);
355
356 // Do not include bad channels found in analysis,
357 if( IsBadChannelsRemovalSwitchedOn() && GetEMCALChannelStatus(imod, ieta, iphi))
358 {
359 return kFALSE;
360 }
361
362 //Recalibrate energy
363 amp = cells->GetCellAmplitude(absID);
364 if(!fCellsRecalibrated && IsRecalibrationOn())
365 amp *= GetEMCALChannelRecalibrationFactor(imod,ieta,iphi);
366
367
368 // Recalibrate time
369 time = cells->GetCellTime(absID);
370
371 RecalibrateCellTime(absID,bc,time);
372
373 return kTRUE;
374}
375
376//_____________________________________________________________________________
377Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(const AliEMCALGeometry* geom,
378 const AliVCluster* cluster,
379 AliVCaloCells* cells)
380{
381 // Given the list of AbsId of the cluster, get the maximum cell and
382 // check if there are fNCellsFromBorder from the calorimeter border
383
384 if(!cluster)
385 {
386 AliInfo("Cluster pointer null!");
387 return kFALSE;
388 }
389
390 //If the distance to the border is 0 or negative just exit accept all clusters
391 if(cells->GetType()==AliVCaloCells::kEMCALCell && fNCellsFromEMCALBorder <= 0 ) return kTRUE;
392
393 Int_t absIdMax = -1, iSM =-1, ieta = -1, iphi = -1;
394 Bool_t shared = kFALSE;
395 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSM, ieta, iphi, shared);
396
397 AliDebug(2,Form("Cluster Max AbsId %d, Cell Energy %2.2f, Cluster Energy %2.2f, Ncells from border %d, EMCAL eta=0 %d\n",
398 absIdMax, cells->GetCellAmplitude(absIdMax), cluster->E(), fNCellsFromEMCALBorder, fNoEMCALBorderAtEta0));
399
400 if(absIdMax==-1) return kFALSE;
401
402 //Check if the cell is close to the borders:
403 Bool_t okrow = kFALSE;
404 Bool_t okcol = kFALSE;
405
406 if(iSM < 0 || iphi < 0 || ieta < 0 )
407 {
408 AliFatal(Form("Negative value for super module: %d, or cell ieta: %d, or cell iphi: %d, check EMCAL geometry name\n",
409 iSM,ieta,iphi));
410 }
411
412 //Check rows/phi
413 if(iSM < 10)
414 {
415 if(iphi >= fNCellsFromEMCALBorder && iphi < 24-fNCellsFromEMCALBorder) okrow =kTRUE;
416 }
417 else if (iSM >=10 && ( ( geom->GetEMCGeometry()->GetGeoName()).Contains("12SMV1")))
418 {
419 if(iphi >= fNCellsFromEMCALBorder && iphi < 8-fNCellsFromEMCALBorder) okrow =kTRUE; //1/3 sm case
420 }
421 else
422 {
423 if(iphi >= fNCellsFromEMCALBorder && iphi < 12-fNCellsFromEMCALBorder) okrow =kTRUE; // half SM case
424 }
425
426 //Check columns/eta
427 if(!fNoEMCALBorderAtEta0)
428 {
429 if(ieta > fNCellsFromEMCALBorder && ieta < 48-fNCellsFromEMCALBorder) okcol =kTRUE;
430 }
431 else
432 {
433 if(iSM%2==0)
434 {
435 if(ieta >= fNCellsFromEMCALBorder) okcol = kTRUE;
436 }
437 else
438 {
439 if(ieta < 48-fNCellsFromEMCALBorder) okcol = kTRUE;
440 }
441 }//eta 0 not checked
442
443 AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d: column? %d, row? %d\nq",
444 fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
445
446 if (okcol && okrow)
447 {
448 //printf("Accept\n");
449 return kTRUE;
450 }
451 else
452 {
453 //printf("Reject\n");
454 AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
455 return kFALSE;
456 }
457
458}
459
460
461//_______________________________________________________________________________
462Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(const AliEMCALGeometry* geom,
463 const UShort_t* cellList,
464 Int_t nCells)
465{
466 // Check that in the cluster cells, there is no bad channel of those stored
467 // in fEMCALBadChannelMap or fPHOSBadChannelMap
468
469 if(!fRemoveBadChannels) return kFALSE;
470 if(!fEMCALBadChannelMap) return kFALSE;
471
472 Int_t icol = -1;
473 Int_t irow = -1;
474 Int_t imod = -1;
475 for(Int_t iCell = 0; iCell<nCells; iCell++)
476 {
477 //Get the column and row
478 Int_t iTower = -1, iIphi = -1, iIeta = -1;
479 geom->GetCellIndex(cellList[iCell],imod,iTower,iIphi,iIeta);
480 if(fEMCALBadChannelMap->GetEntries() <= imod) continue;
481 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
482 if(GetEMCALChannelStatus(imod, icol, irow))
483 {
484 AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
485 return kTRUE;
486 }
487
488 }// cell cluster loop
489
490 return kFALSE;
491}
492
493
494//___________________________________________________________________________
495Float_t AliEMCALRecoUtils::GetECross(Int_t absID, Double_t tcell,
496 AliVCaloCells* cells, Int_t bc)
497{
498 //Calculate the energy in the cross around the energy given cell
499
500 AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
501
502 Int_t imod = -1, iphi =-1, ieta=-1,iTower = -1, iIphi = -1, iIeta = -1;
503 geom->GetCellIndex(absID,imod,iTower,iIphi,iIeta);
504 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,iphi,ieta);
505
506 //Get close cells index, energy and time, not in corners
507
508 Int_t absID1 = -1;
509 Int_t absID2 = -1;
510
511 if( iphi < AliEMCALGeoParams::fgkEMCALRows-1) absID1 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi+1, ieta);
512 if( iphi > 0 ) absID2 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi-1, ieta);
513
514 // In case of cell in eta = 0 border, depending on SM shift the cross cell index
515
516 Int_t absID3 = -1;
517 Int_t absID4 = -1;
518
519 if ( ieta == AliEMCALGeoParams::fgkEMCALCols-1 && !(imod%2) )
520 {
521 absID3 = geom-> GetAbsCellIdFromCellIndexes(imod+1, iphi, 0);
522 absID4 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi, ieta-1);
523 }
524 else if( ieta == 0 && imod%2 )
525 {
526 absID3 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi, ieta+1);
527 absID4 = geom-> GetAbsCellIdFromCellIndexes(imod-1, iphi, AliEMCALGeoParams::fgkEMCALCols-1);
528 }
529 else
530 {
531 if( ieta < AliEMCALGeoParams::fgkEMCALCols-1 )
532 absID3 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi, ieta+1);
533 if( ieta > 0 )
534 absID4 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi, ieta-1);
535 }
536
537 //printf("IMOD %d, AbsId %d, a %d, b %d, c %d e %d \n",imod,absID,absID1,absID2,absID3,absID4);
538
539 Float_t ecell1 = 0, ecell2 = 0, ecell3 = 0, ecell4 = 0;
540 Double_t tcell1 = 0, tcell2 = 0, tcell3 = 0, tcell4 = 0;
541 Bool_t accept1 = 0, accept2 = 0, accept3 = 0, accept4 = 0;
542
543 accept1 = AcceptCalibrateCell(absID1,bc, ecell1,tcell1,cells);
544 accept2 = AcceptCalibrateCell(absID2,bc, ecell2,tcell2,cells);
545 accept3 = AcceptCalibrateCell(absID3,bc, ecell3,tcell3,cells);
546 accept4 = AcceptCalibrateCell(absID4,bc, ecell4,tcell4,cells);
547
548 /*
549 printf("Cell absID %d \n",absID);
550 printf("\t accept1 %d, accept2 %d, accept3 %d, accept4 %d\n",
551 accept1,accept2,accept3,accept4);
552 printf("\t id %d: id1 %d, id2 %d, id3 %d, id4 %d\n",
553 absID,absID1,absID2,absID3,absID4);
554 printf("\t e %f: e1 %f, e2 %f, e3 %f, e4 %f\n",
555 ecell,ecell1,ecell2,ecell3,ecell4);
556 printf("\t t %f: t1 %f, t2 %f, t3 %f, t4 %f;\n dt1 %f, dt2 %f, dt3 %f, dt4 %f\n",
557 tcell*1.e9,tcell1*1.e9,tcell2*1.e9,tcell3*1.e9,tcell4*1.e9,
558 TMath::Abs(tcell-tcell1)*1.e9, TMath::Abs(tcell-tcell2)*1.e9, TMath::Abs(tcell-tcell3)*1.e9, TMath::Abs(tcell-tcell4)*1.e9);
559 */
560
561 if(TMath::Abs(tcell-tcell1)*1.e9 > fExoticCellDiffTime) ecell1 = 0 ;
562 if(TMath::Abs(tcell-tcell2)*1.e9 > fExoticCellDiffTime) ecell2 = 0 ;
563 if(TMath::Abs(tcell-tcell3)*1.e9 > fExoticCellDiffTime) ecell3 = 0 ;
564 if(TMath::Abs(tcell-tcell4)*1.e9 > fExoticCellDiffTime) ecell4 = 0 ;
565
566 return ecell1+ecell2+ecell3+ecell4;
567
568}
569
570//_____________________________________________________________________________________________
571Bool_t AliEMCALRecoUtils::IsExoticCell(Int_t absID, AliVCaloCells* cells, Int_t bc)
572{
573 // Look to cell neighbourhood and reject if it seems exotic
574 // Do before recalibrating the cells
575
576 if(!fRejectExoticCells) return kFALSE;
577
578 Float_t ecell = 0;
579 Double_t tcell = 0;
580 Bool_t accept = AcceptCalibrateCell(absID, bc, ecell ,tcell ,cells);
581
582 if(!accept) return kTRUE; // reject this cell
583
584 if(ecell < fExoticCellMinAmplitude) return kFALSE; // do not reject low energy cells
585
586 Float_t eCross = GetECross(absID,tcell,cells,bc);
587
588 if(1-eCross/ecell > fExoticCellFraction)
589 {
590 AliDebug(2,Form("AliEMCALRecoUtils::IsExoticCell() - EXOTIC CELL id %d, eCell %f, eCross %f, 1-eCross/eCell %f\n",
591 absID,ecell,eCross,1-eCross/ecell));
592 return kTRUE;
593 }
594
595 return kFALSE;
596}
597
598//___________________________________________________________________
599Bool_t AliEMCALRecoUtils::IsExoticCluster(const AliVCluster *cluster,
600 AliVCaloCells *cells,
601 Int_t bc)
602{
603 // Check if the cluster highest energy tower is exotic
604
605 if(!cluster)
606 {
607 AliInfo("Cluster pointer null!");
608 return kFALSE;
609 }
610
611 if(!fRejectExoticCluster) return kFALSE;
612
613 // Get highest energy tower
614 AliEMCALGeometry* geom = AliEMCALGeometry::GetInstance();
615 Int_t iSupMod = -1, absId = -1, ieta = -1, iphi = -1;
616 Bool_t shared = kFALSE;
617 GetMaxEnergyCell(geom, cells, cluster, absId, iSupMod, ieta, iphi, shared);
618
619 return IsExoticCell(absId,cells,bc);
620
621}
622
623//_______________________________________________________________________
624Float_t AliEMCALRecoUtils::SmearClusterEnergy(const AliVCluster* cluster)
625{
626 //In case of MC analysis, smear energy to match resolution/calibration in real data
627
628 if(!cluster)
629 {
630 AliInfo("Cluster pointer null!");
631 return 0;
632 }
633
634 Float_t energy = cluster->E() ;
635 Float_t rdmEnergy = energy ;
636 if(fSmearClusterEnergy)
637 {
638 rdmEnergy = fRandom.Gaus(energy,fSmearClusterParam[0] * TMath::Sqrt(energy) +
639 fSmearClusterParam[1] * energy +
640 fSmearClusterParam[2] );
641 AliDebug(2, Form("Energy: original %f, smeared %f\n", energy, rdmEnergy));
642 }
643
644 return rdmEnergy;
645}
646
647//____________________________________________________________________________
648Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster)
649{
650 // Correct cluster energy from non linearity functions
651
652 if(!cluster)
653 {
654 AliInfo("Cluster pointer null!");
655 return 0;
656 }
657
658 Float_t energy = cluster->E();
659
660 if(energy < 0.05)
661 {
662 // Clusters with less than 50 MeV or negative are not possible
663 AliInfo(Form("Too Low Cluster energy!, E = %f < 0.05 GeV",energy));
664 return 0;
665 }
666
667 switch (fNonLinearityFunction)
668 {
669
670 case kPi0MC:
671 {
672 //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
673 //fNonLinearityParams[0] = 1.014;
674 //fNonLinearityParams[1] =-0.03329;
675 //fNonLinearityParams[2] =-0.3853;
676 //fNonLinearityParams[3] = 0.5423;
677 //fNonLinearityParams[4] =-0.4335;
678 energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
679 ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
680 exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
681 break;
682 }
683
684 case kPi0MCv2:
685 {
686 //Non-Linearity correction (from MC with function [0]/((x+[1])^[2]))+1;
687 //fNonLinearityParams[0] = 3.11111e-02;
688 //fNonLinearityParams[1] =-5.71666e-02;
689 //fNonLinearityParams[2] = 5.67995e-01;
690
691 energy *= fNonLinearityParams[0]/TMath::Power(energy+fNonLinearityParams[1],fNonLinearityParams[2])+1;
692 break;
693 }
694
695 case kPi0MCv3:
696 {
697 //Same as beam test corrected, change parameters
698 //fNonLinearityParams[0] = 9.81039e-01
699 //fNonLinearityParams[1] = 1.13508e-01;
700 //fNonLinearityParams[2] = 1.00173e+00;
701 //fNonLinearityParams[3] = 9.67998e-02;
702 //fNonLinearityParams[4] = 2.19381e+02;
703 //fNonLinearityParams[5] = 6.31604e+01;
704 //fNonLinearityParams[6] = 1;
705 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
706
707 break;
708 }
709
710
711 case kPi0GammaGamma:
712 {
713 //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
714 //fNonLinearityParams[0] = 1.04;
715 //fNonLinearityParams[1] = -0.1445;
716 //fNonLinearityParams[2] = 1.046;
717 energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
718 break;
719 }
720
721 case kPi0GammaConversion:
722 {
723 //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
724 //fNonLinearityParams[0] = 0.139393/0.1349766;
725 //fNonLinearityParams[1] = 0.0566186;
726 //fNonLinearityParams[2] = 0.982133;
727 energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
728
729 break;
730 }
731
732 case kBeamTest:
733 {
734 //From beam test, Alexei's results, for different ZS thresholds
735 // th=30 MeV; th = 45 MeV; th = 75 MeV
736 //fNonLinearityParams[0] = 1.007; 1.003; 1.002
737 //fNonLinearityParams[1] = 0.894; 0.719; 0.797
738 //fNonLinearityParams[2] = 0.246; 0.334; 0.358
739 //Rescale the param[0] with 1.03
740 energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
741
742 break;
743 }
744
745 case kBeamTestCorrected:
746 {
747 //From beam test, corrected for material between beam and EMCAL
748 //fNonLinearityParams[0] = 0.99078
749 //fNonLinearityParams[1] = 0.161499;
750 //fNonLinearityParams[2] = 0.655166;
751 //fNonLinearityParams[3] = 0.134101;
752 //fNonLinearityParams[4] = 163.282;
753 //fNonLinearityParams[5] = 23.6904;
754 //fNonLinearityParams[6] = 0.978;
755 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
756
757 break;
758 }
759
760 case kBeamTestCorrectedv2:
761 {
762 //From beam test, corrected for material between beam and EMCAL
763 //fNonLinearityParams[0] = 0.983504;
764 //fNonLinearityParams[1] = 0.210106;
765 //fNonLinearityParams[2] = 0.897274;
766 //fNonLinearityParams[3] = 0.0829064;
767 //fNonLinearityParams[4] = 152.299;
768 //fNonLinearityParams[5] = 31.5028;
769 //fNonLinearityParams[6] = 0.968;
770 energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
771
772 break;
773 }
774
775 case kNoCorrection:
776 AliDebug(2,"No correction on the energy\n");
777 break;
778
779 }
780
781 return energy;
782}
783
784//__________________________________________________
785void AliEMCALRecoUtils::InitNonLinearityParam()
786{
787 //Initialising Non Linearity Parameters
788
789 if(fNonLinearityFunction == kPi0MC)
790 {
791 fNonLinearityParams[0] = 1.014;
792 fNonLinearityParams[1] = -0.03329;
793 fNonLinearityParams[2] = -0.3853;
794 fNonLinearityParams[3] = 0.5423;
795 fNonLinearityParams[4] = -0.4335;
796 }
797
798 if(fNonLinearityFunction == kPi0MCv2)
799 {
800 fNonLinearityParams[0] = 3.11111e-02;
801 fNonLinearityParams[1] =-5.71666e-02;
802 fNonLinearityParams[2] = 5.67995e-01;
803 }
804
805 if(fNonLinearityFunction == kPi0MCv3)
806 {
807 fNonLinearityParams[0] = 9.81039e-01;
808 fNonLinearityParams[1] = 1.13508e-01;
809 fNonLinearityParams[2] = 1.00173e+00;
810 fNonLinearityParams[3] = 9.67998e-02;
811 fNonLinearityParams[4] = 2.19381e+02;
812 fNonLinearityParams[5] = 6.31604e+01;
813 fNonLinearityParams[6] = 1;
814 }
815
816 if(fNonLinearityFunction == kPi0GammaGamma)
817 {
818 fNonLinearityParams[0] = 1.04;
819 fNonLinearityParams[1] = -0.1445;
820 fNonLinearityParams[2] = 1.046;
821 }
822
823 if(fNonLinearityFunction == kPi0GammaConversion)
824 {
825 fNonLinearityParams[0] = 0.139393;
826 fNonLinearityParams[1] = 0.0566186;
827 fNonLinearityParams[2] = 0.982133;
828 }
829
830 if(fNonLinearityFunction == kBeamTest)
831 {
832 if(fNonLinearThreshold == 30)
833 {
834 fNonLinearityParams[0] = 1.007;
835 fNonLinearityParams[1] = 0.894;
836 fNonLinearityParams[2] = 0.246;
837 }
838 if(fNonLinearThreshold == 45)
839 {
840 fNonLinearityParams[0] = 1.003;
841 fNonLinearityParams[1] = 0.719;
842 fNonLinearityParams[2] = 0.334;
843 }
844 if(fNonLinearThreshold == 75)
845 {
846 fNonLinearityParams[0] = 1.002;
847 fNonLinearityParams[1] = 0.797;
848 fNonLinearityParams[2] = 0.358;
849 }
850 }
851
852 if(fNonLinearityFunction == kBeamTestCorrected)
853 {
854 fNonLinearityParams[0] = 0.99078;
855 fNonLinearityParams[1] = 0.161499;
856 fNonLinearityParams[2] = 0.655166;
857 fNonLinearityParams[3] = 0.134101;
858 fNonLinearityParams[4] = 163.282;
859 fNonLinearityParams[5] = 23.6904;
860 fNonLinearityParams[6] = 0.978;
861 }
862
863 if(fNonLinearityFunction == kBeamTestCorrectedv2)
864 {
865 fNonLinearityParams[0] = 0.983504;
866 fNonLinearityParams[1] = 0.210106;
867 fNonLinearityParams[2] = 0.897274;
868 fNonLinearityParams[3] = 0.0829064;
869 fNonLinearityParams[4] = 152.299;
870 fNonLinearityParams[5] = 31.5028;
871 fNonLinearityParams[6] = 0.968;
872 }
873}
874
875//_________________________________________________________
876Float_t AliEMCALRecoUtils::GetDepth(Float_t energy,
877 Int_t iParticle,
878 Int_t iSM) const
879{
880 //Calculate shower depth for a given cluster energy and particle type
881
882 // parameters
883 Float_t x0 = 1.31;
884 Float_t ecr = 8;
885 Float_t depth = 0;
886 Float_t arg = energy*1000/ ecr; //Multiply energy by 1000 to transform to MeV
887
888 switch ( iParticle )
889 {
890 case kPhoton:
891 if (arg < 1)
892 depth = 0;
893 else
894 depth = x0 * (TMath::Log(arg) + 0.5);
895 break;
896
897 case kElectron:
898 if (arg < 1)
899 depth = 0;
900 else
901 depth = x0 * (TMath::Log(arg) - 0.5);
902 break;
903
904 case kHadron:
905 // hadron
906 // boxes anc. here
907 if(gGeoManager)
908 {
909 gGeoManager->cd("ALIC_1/XEN1_1");
910 TGeoNode *geoXEn1 = gGeoManager->GetCurrentNode();
911 TGeoNodeMatrix *geoSM = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
912 if(geoSM)
913 {
914 TGeoVolume *geoSMVol = geoSM->GetVolume();
915 TGeoShape *geoSMShape = geoSMVol->GetShape();
916 TGeoBBox *geoBox = dynamic_cast<TGeoBBox *>(geoSMShape);
917 if(geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
918 else AliFatal("Null GEANT box");
919 }
920 else AliFatal("NULL GEANT node matrix");
921 }
922 else
923 {//electron
924 if (arg < 1)
925 depth = 0;
926 else
927 depth = x0 * (TMath::Log(arg) - 0.5);
928 }
929
930 break;
931
932 default://photon
933 if (arg < 1)
934 depth = 0;
935 else
936 depth = x0 * (TMath::Log(arg) + 0.5);
937 }
938
939 return depth;
940}
941
942//____________________________________________________________________
943void AliEMCALRecoUtils::GetMaxEnergyCell(const AliEMCALGeometry *geom,
944 AliVCaloCells* cells,
945 const AliVCluster* clu,
946 Int_t & absId,
947 Int_t & iSupMod,
948 Int_t & ieta,
949 Int_t & iphi,
950 Bool_t & shared)
951{
952 //For a given CaloCluster gets the absId of the cell
953 //with maximum energy deposit.
954
955 Double_t eMax = -1.;
956 Double_t eCell = -1.;
957 Float_t fraction = 1.;
958 Float_t recalFactor = 1.;
959 Int_t cellAbsId = -1 ;
960
961 Int_t iTower = -1;
962 Int_t iIphi = -1;
963 Int_t iIeta = -1;
964 Int_t iSupMod0= -1;
965
966 if(!clu)
967 {
968 AliInfo("Cluster pointer null!");
969 absId=-1; iSupMod0=-1, ieta = -1; iphi = -1; shared = -1;
970 return;
971 }
972
973 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++)
974 {
975 cellAbsId = clu->GetCellAbsId(iDig);
976 fraction = clu->GetCellAmplitudeFraction(iDig);
977 //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
978 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
979 geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta);
980 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
981 if (iDig==0)
982 {
983 iSupMod0=iSupMod;
984 }
985 else if(iSupMod0!=iSupMod)
986 {
987 shared = kTRUE;
988 //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
989 }
990 if(!fCellsRecalibrated && IsRecalibrationOn())
991 {
992 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
993 }
994 eCell = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
995 //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
996 if(eCell > eMax)
997 {
998 eMax = eCell;
999 absId = cellAbsId;
1000 //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
1001 }
1002 }// cell loop
1003
1004 //Get from the absid the supermodule, tower and eta/phi numbers
1005 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
1006 //Gives SuperModule and Tower numbers
1007 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
1008 iIphi, iIeta,iphi,ieta);
1009 //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
1010 //printf("Max end---\n");
1011}
1012
1013//______________________________________
1014void AliEMCALRecoUtils::InitParameters()
1015{
1016 // Initialize data members with default values
1017
1018 fParticleType = kPhoton;
1019 fPosAlgo = kUnchanged;
1020 fW0 = 4.5;
1021
1022 fNonLinearityFunction = kNoCorrection;
1023 fNonLinearThreshold = 30;
1024
1025 fExoticCellFraction = 0.97;
1026 fExoticCellDiffTime = 1e6;
1027 fExoticCellMinAmplitude = 0.5;
1028
1029 fAODFilterMask = 128;
1030 fAODHybridTracks = kFALSE;
1031 fAODTPCOnlyTracks = kTRUE;
1032
1033 fCutEtaPhiSum = kTRUE;
1034 fCutEtaPhiSeparate = kFALSE;
1035
1036 fCutR = 0.05;
1037 fCutEta = 0.025;
1038 fCutPhi = 0.05;
1039
1040 fClusterWindow = 100;
1041 fMass = 0.139;
1042
1043 fStepSurface = 20.;
1044 fStepCluster = 5.;
1045 fTrackCutsType = kLooseCut;
1046
1047 fCutMinTrackPt = 0;
1048 fCutMinNClusterTPC = -1;
1049 fCutMinNClusterITS = -1;
1050
1051 fCutMaxChi2PerClusterTPC = 1e10;
1052 fCutMaxChi2PerClusterITS = 1e10;
1053
1054 fCutRequireTPCRefit = kFALSE;
1055 fCutRequireITSRefit = kFALSE;
1056 fCutAcceptKinkDaughters = kFALSE;
1057
1058 fCutMaxDCAToVertexXY = 1e10;
1059 fCutMaxDCAToVertexZ = 1e10;
1060 fCutDCAToVertex2D = kFALSE;
1061
1062 fCutRequireITSStandAlone = kFALSE; //MARCEL
1063 fCutRequireITSpureSA = kFALSE; //Marcel
1064
1065 //Misalignment matrices
1066 for(Int_t i = 0; i < 15 ; i++)
1067 {
1068 fMisalTransShift[i] = 0.;
1069 fMisalRotShift[i] = 0.;
1070 }
1071
1072 //Non linearity
1073 for(Int_t i = 0; i < 7 ; i++) fNonLinearityParams[i] = 0.;
1074
1075 //For kBeamTestCorrectedv2 case, but default is no correction
1076 fNonLinearityParams[0] = 0.983504;
1077 fNonLinearityParams[1] = 0.210106;
1078 fNonLinearityParams[2] = 0.897274;
1079 fNonLinearityParams[3] = 0.0829064;
1080 fNonLinearityParams[4] = 152.299;
1081 fNonLinearityParams[5] = 31.5028;
1082 fNonLinearityParams[6] = 0.968;
1083
1084 //Cluster energy smearing
1085 fSmearClusterEnergy = kFALSE;
1086 fSmearClusterParam[0] = 0.07; // * sqrt E term
1087 fSmearClusterParam[1] = 0.00; // * E term
1088 fSmearClusterParam[2] = 0.00; // constant
1089}
1090
1091//_____________________________________________________
1092void AliEMCALRecoUtils::InitEMCALRecalibrationFactors()
1093{
1094 //Init EMCAL recalibration factors
1095 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
1096 //In order to avoid rewriting the same histograms
1097 Bool_t oldStatus = TH1::AddDirectoryStatus();
1098 TH1::AddDirectory(kFALSE);
1099
1100 fEMCALRecalibrationFactors = new TObjArray(12);
1101 for (int i = 0; i < 12; i++)
1102 fEMCALRecalibrationFactors->Add(new TH2F(Form("EMCALRecalFactors_SM%d",i),
1103 Form("EMCALRecalFactors_SM%d",i), 48, 0, 48, 24, 0, 24));
1104 //Init the histograms with 1
1105 for (Int_t sm = 0; sm < 12; sm++)
1106 {
1107 for (Int_t i = 0; i < 48; i++)
1108 {
1109 for (Int_t j = 0; j < 24; j++)
1110 {
1111 SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
1112 }
1113 }
1114 }
1115
1116 fEMCALRecalibrationFactors->SetOwner(kTRUE);
1117 fEMCALRecalibrationFactors->Compress();
1118
1119 //In order to avoid rewriting the same histograms
1120 TH1::AddDirectory(oldStatus);
1121}
1122
1123//_________________________________________________________
1124void AliEMCALRecoUtils::InitEMCALTimeRecalibrationFactors()
1125{
1126 //Init EMCAL recalibration factors
1127 AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
1128 //In order to avoid rewriting the same histograms
1129 Bool_t oldStatus = TH1::AddDirectoryStatus();
1130 TH1::AddDirectory(kFALSE);
1131
1132 fEMCALTimeRecalibrationFactors = new TObjArray(4);
1133 for (int i = 0; i < 4; i++)
1134 fEMCALTimeRecalibrationFactors->Add(new TH1F(Form("hAllTimeAvBC%d",i),
1135 Form("hAllTimeAvBC%d",i),
1136 48*24*12,0.,48*24*12) );
1137 //Init the histograms with 1
1138 for (Int_t bc = 0; bc < 4; bc++)
1139 {
1140 for (Int_t i = 0; i < 48*24*12; i++)
1141 SetEMCALChannelTimeRecalibrationFactor(bc,i,0.);
1142 }
1143
1144 fEMCALTimeRecalibrationFactors->SetOwner(kTRUE);
1145 fEMCALTimeRecalibrationFactors->Compress();
1146
1147 //In order to avoid rewriting the same histograms
1148 TH1::AddDirectory(oldStatus);
1149}
1150
1151//____________________________________________________
1152void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()
1153{
1154 //Init EMCAL bad channels map
1155 AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
1156 //In order to avoid rewriting the same histograms
1157 Bool_t oldStatus = TH1::AddDirectoryStatus();
1158 TH1::AddDirectory(kFALSE);
1159
1160 fEMCALBadChannelMap = new TObjArray(12);
1161 //TH2F * hTemp = new TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
1162 for (int i = 0; i < 12; i++)
1163 {
1164 fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
1165 }
1166
1167 fEMCALBadChannelMap->SetOwner(kTRUE);
1168 fEMCALBadChannelMap->Compress();
1169
1170 //In order to avoid rewriting the same histograms
1171 TH1::AddDirectory(oldStatus);
1172}
1173
1174//____________________________________________________________________________
1175void AliEMCALRecoUtils::RecalibrateClusterEnergy(const AliEMCALGeometry* geom,
1176 AliVCluster * cluster,
1177 AliVCaloCells * cells,
1178 Int_t bc)
1179{
1180 // Recalibrate the cluster energy and Time, considering the recalibration map
1181 // and the energy of the cells and time that compose the cluster.
1182 // bc= bunch crossing number returned by esdevent->GetBunchCrossNumber();
1183
1184 if(!cluster)
1185 {
1186 AliInfo("Cluster pointer null!");
1187 return;
1188 }
1189
1190 //Get the cluster number of cells and list of absId, check what kind of cluster do we have.
1191 UShort_t * index = cluster->GetCellsAbsId() ;
1192 Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
1193 Int_t ncells = cluster->GetNCells();
1194
1195 //Initialize some used variables
1196 Float_t energy = 0;
1197 Int_t absId =-1;
1198 Int_t icol =-1, irow =-1, imod=1;
1199 Float_t factor = 1, frac = 0;
1200 Int_t absIdMax = -1;
1201 Float_t emax = 0;
1202
1203 //Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
1204 for(Int_t icell = 0; icell < ncells; icell++)
1205 {
1206 absId = index[icell];
1207 frac = fraction[icell];
1208 if(frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
1209
1210 if(!fCellsRecalibrated && IsRecalibrationOn())
1211 {
1212 // Energy
1213 Int_t iTower = -1, iIphi = -1, iIeta = -1;
1214 geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta);
1215 if(fEMCALRecalibrationFactors->GetEntries() <= imod) continue;
1216 geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);
1217 factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
1218
1219 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
1220 imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
1221
1222 }
1223
1224 energy += cells->GetCellAmplitude(absId)*factor*frac;
1225
1226 if(emax < cells->GetCellAmplitude(absId)*factor*frac)
1227 {
1228 emax = cells->GetCellAmplitude(absId)*factor*frac;
1229 absIdMax = absId;
1230 }
1231 }
1232
1233 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f \n",cluster->E(),energy));
1234
1235 cluster->SetE(energy);
1236
1237 // Recalculate time of cluster
1238 Double_t timeorg = cluster->GetTOF();
1239
1240 Double_t time = cells->GetCellTime(absIdMax);
1241 if(!fCellsRecalibrated && IsTimeRecalibrationOn())
1242 RecalibrateCellTime(absIdMax,bc,time);
1243
1244 cluster->SetTOF(time);
1245
1246 AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Time before %f, after %f \n",timeorg,cluster->GetTOF()));
1247}
1248
1249//_____________________________________________________________
1250void AliEMCALRecoUtils::RecalibrateCells(AliVCaloCells * cells,
1251 Int_t bc)
1252{
1253 // Recalibrate the cells time and energy, considering the recalibration map and the energy
1254 // of the cells that compose the cluster.
1255 // bc= bunch crossing number returned by esdevent->GetBunchCrossNumber();
1256
1257 if(!IsRecalibrationOn() && !IsTimeRecalibrationOn() && !IsBadChannelsRemovalSwitchedOn()) return;
1258
1259 if(!cells)
1260 {
1261 AliInfo("Cells pointer null!");
1262 return;
1263 }
1264
1265 Short_t absId =-1;
1266 Bool_t accept = kFALSE;
1267 Float_t ecell = 0;
1268 Double_t tcell = 0;
1269 Double_t ecellin = 0;
1270 Double_t tcellin = 0;
1271 Int_t mclabel = -1;
1272 Double_t efrac = 0;
1273
1274 Int_t nEMcell = cells->GetNumberOfCells() ;
1275 for (Int_t iCell = 0; iCell < nEMcell; iCell++)
1276 {
1277 cells->GetCell( iCell, absId, ecellin, tcellin, mclabel, efrac );
1278
1279 accept = AcceptCalibrateCell(absId, bc, ecell ,tcell ,cells);
1280 if(!accept)
1281 {
1282 ecell = 0;
1283 tcell = -1;
1284 }
1285
1286 //Set new values
1287 cells->SetCell(iCell,absId,ecell, tcell, mclabel, efrac);
1288 }
1289
1290 fCellsRecalibrated = kTRUE;
1291}
1292
1293//_______________________________________________________________________________________________________
1294void AliEMCALRecoUtils::RecalibrateCellTime(Int_t absId, Int_t bc, Double_t & celltime) const
1295{
1296 // Recalibrate time of cell with absID considering the recalibration map
1297 // bc= bunch crossing number returned by esdevent->GetBunchCrossNumber();
1298
1299 if(!fCellsRecalibrated && IsTimeRecalibrationOn() && bc >= 0)
1300 {
1301 celltime -= GetEMCALChannelTimeRecalibrationFactor(bc%4,absId)*1.e-9; ;
1302 }
1303}
1304
1305//______________________________________________________________________________
1306void AliEMCALRecoUtils::RecalculateClusterPosition(const AliEMCALGeometry *geom,
1307 AliVCaloCells* cells,
1308 AliVCluster* clu)
1309{
1310 //For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
1311
1312 if(!clu)
1313 {
1314 AliInfo("Cluster pointer null!");
1315 return;
1316 }
1317
1318 if (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
1319 else if(fPosAlgo==kPosTowerIndex) RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
1320 else AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
1321}
1322
1323//_____________________________________________________________________________________________
1324void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(const AliEMCALGeometry *geom,
1325 AliVCaloCells* cells,
1326 AliVCluster* clu)
1327{
1328 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
1329 // The algorithm is a copy of what is done in AliEMCALRecPoint
1330
1331 Double_t eCell = 0.;
1332 Float_t fraction = 1.;
1333 Float_t recalFactor = 1.;
1334
1335 Int_t absId = -1;
1336 Int_t iTower = -1, iIphi = -1, iIeta = -1;
1337 Int_t iSupModMax = -1, iSM=-1, iphi = -1, ieta = -1;
1338 Float_t weight = 0., totalWeight=0.;
1339 Float_t newPos[3] = {0,0,0};
1340 Double_t pLocal[3], pGlobal[3];
1341 Bool_t shared = kFALSE;
1342
1343 Float_t clEnergy = clu->E(); //Energy already recalibrated previously
1344 if (clEnergy <= 0)
1345 return;
1346 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
1347 Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
1348
1349 //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
1350
1351 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++)
1352 {
1353 absId = clu->GetCellAbsId(iDig);
1354 fraction = clu->GetCellAmplitudeFraction(iDig);
1355 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1356
1357 if (!fCellsRecalibrated)
1358 {
1359 geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta);
1360 geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);
1361
1362 if(IsRecalibrationOn())
1363 {
1364 recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
1365 }
1366 }
1367
1368 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
1369
1370 weight = GetCellWeight(eCell,clEnergy);
1371 totalWeight += weight;
1372
1373 geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
1374 //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
1375 geom->GetGlobal(pLocal,pGlobal,iSupModMax);
1376 //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
1377
1378 for(int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
1379 }// cell loop
1380
1381 if(totalWeight>0)
1382 {
1383 for(int i=0; i<3; i++ ) newPos[i] /= totalWeight;
1384 }
1385
1386 //Float_t pos[]={0,0,0};
1387 //clu->GetPosition(pos);
1388 //printf("OldPos : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
1389 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
1390
1391 if(iSupModMax > 1) //sector 1
1392 {
1393 newPos[0] +=fMisalTransShift[3];//-=3.093;
1394 newPos[1] +=fMisalTransShift[4];//+=6.82;
1395 newPos[2] +=fMisalTransShift[5];//+=1.635;
1396 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
1397 } else //sector 0
1398 {
1399 newPos[0] +=fMisalTransShift[0];//+=1.134;
1400 newPos[1] +=fMisalTransShift[1];//+=8.2;
1401 newPos[2] +=fMisalTransShift[2];//+=1.197;
1402 //printf(" + : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
1403 }
1404 //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
1405
1406 clu->SetPosition(newPos);
1407}
1408
1409//____________________________________________________________________________________________
1410void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(const AliEMCALGeometry *geom,
1411 AliVCaloCells* cells,
1412 AliVCluster* clu)
1413{
1414 // For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
1415 // The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position
1416
1417 Double_t eCell = 1.;
1418 Float_t fraction = 1.;
1419 Float_t recalFactor = 1.;
1420
1421 Int_t absId = -1;
1422 Int_t iTower = -1;
1423 Int_t iIphi = -1, iIeta = -1;
1424 Int_t iSupMod = -1, iSupModMax = -1;
1425 Int_t iphi = -1, ieta =-1;
1426 Bool_t shared = kFALSE;
1427
1428 Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
1429
1430 if (clEnergy <= 0)
1431 return;
1432 GetMaxEnergyCell(geom, cells, clu, absId, iSupModMax, ieta, iphi,shared);
1433 Float_t depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
1434
1435 Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
1436 Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
1437 Int_t startingSM = -1;
1438
1439 for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++)
1440 {
1441 absId = clu->GetCellAbsId(iDig);
1442 fraction = clu->GetCellAmplitudeFraction(iDig);
1443 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1444
1445 if (iDig==0) startingSM = iSupMod;
1446 else if(iSupMod != startingSM) areInSameSM = kFALSE;
1447
1448 eCell = cells->GetCellAmplitude(absId);
1449
1450 geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
1451 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
1452
1453 if (!fCellsRecalibrated)
1454 {
1455 if(IsRecalibrationOn())
1456 {
1457 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1458 }
1459 }
1460
1461 eCell = cells->GetCellAmplitude(absId)*fraction*recalFactor;
1462
1463 weight = GetCellWeight(eCell,clEnergy);
1464 if(weight < 0) weight = 0;
1465 totalWeight += weight;
1466 weightedCol += ieta*weight;
1467 weightedRow += iphi*weight;
1468
1469 //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
1470 }// cell loop
1471
1472 Float_t xyzNew[]={0.,0.,0.};
1473 if(areInSameSM == kTRUE)
1474 {
1475 //printf("In Same SM\n");
1476 weightedCol = weightedCol/totalWeight;
1477 weightedRow = weightedRow/totalWeight;
1478 geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
1479 }
1480 else
1481 {
1482 //printf("In Different SM\n");
1483 geom->RecalculateTowerPosition(iphi, ieta, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew);
1484 }
1485
1486 clu->SetPosition(xyzNew);
1487}
1488
1489//___________________________________________________________________________________________
1490void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(const AliEMCALGeometry * geom,
1491 AliVCaloCells* cells,
1492 AliVCluster * cluster)
1493{
1494 //re-evaluate distance to bad channel with updated bad map
1495
1496 if(!fRecalDistToBadChannels) return;
1497
1498 if(!cluster)
1499 {
1500 AliInfo("Cluster pointer null!");
1501 return;
1502 }
1503
1504 //Get channels map of the supermodule where the cluster is.
1505 Int_t absIdMax = -1, iSupMod =-1, icolM = -1, irowM = -1;
1506 Bool_t shared = kFALSE;
1507 GetMaxEnergyCell(geom, cells, cluster, absIdMax, iSupMod, icolM, irowM, shared);
1508 TH2D* hMap = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
1509
1510 Int_t dRrow, dRcol;
1511 Float_t minDist = 10000.;
1512 Float_t dist = 0.;
1513
1514 //Loop on tower status map
1515 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++)
1516 {
1517 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++)
1518 {
1519 //Check if tower is bad.
1520 if(hMap->GetBinContent(icol,irow)==0) continue;
1521 //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
1522 // iSupMod,icol, irow, icolM,irowM);
1523
1524 dRrow=TMath::Abs(irowM-irow);
1525 dRcol=TMath::Abs(icolM-icol);
1526 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
1527 if(dist < minDist)
1528 {
1529 //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
1530 minDist = dist;
1531 }
1532 }
1533 }
1534
1535 //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
1536 if (shared)
1537 {
1538 TH2D* hMap2 = 0;
1539 Int_t iSupMod2 = -1;
1540
1541 //The only possible combinations are (0,1), (2,3) ... (8,9)
1542 if(iSupMod%2) iSupMod2 = iSupMod-1;
1543 else iSupMod2 = iSupMod+1;
1544 hMap2 = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
1545
1546 //Loop on tower status map of second super module
1547 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++)
1548 {
1549 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++)
1550 {
1551 //Check if tower is bad.
1552 if(hMap2->GetBinContent(icol,irow)==0) continue;
1553 //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",
1554 // iSupMod2,icol, irow,iSupMod,icolM,irowM);
1555 dRrow=TMath::Abs(irow-irowM);
1556
1557 if(iSupMod%2)
1558 {
1559 dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
1560 } else
1561 {
1562 dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
1563 }
1564
1565 dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
1566 if(dist < minDist) minDist = dist;
1567 }
1568 }
1569 }// shared cluster in 2 SuperModules
1570
1571 AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
1572 cluster->SetDistanceToBadChannel(minDist);
1573}
1574
1575//__________________________________________________________________
1576void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster)
1577{
1578 //re-evaluate identification parameters with bayesian
1579
1580 if(!cluster)
1581 {
1582 AliInfo("Cluster pointer null!");
1583 return;
1584 }
1585
1586 if ( cluster->GetM02() != 0)
1587 fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
1588
1589 Float_t pidlist[AliPID::kSPECIESCN+1];
1590 for(Int_t i = 0; i < AliPID::kSPECIESCN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
1591
1592 cluster->SetPID(pidlist);
1593}
1594
1595//___________________________________________________________________________________________________________________
1596void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(const AliEMCALGeometry * geom,
1597 AliVCaloCells* cells,
1598 AliVCluster * cluster,
1599 Float_t & l0, Float_t & l1,
1600 Float_t & disp, Float_t & dEta, Float_t & dPhi,
1601 Float_t & sEta, Float_t & sPhi, Float_t & sEtaPhi)
1602{
1603 // Calculates new center of gravity in the local EMCAL-module coordinates
1604 // and tranfers into global ALICE coordinates
1605 // Calculates Dispersion and main axis
1606
1607 if(!cluster)
1608 {
1609 AliInfo("Cluster pointer null!");
1610 return;
1611 }
1612
1613 Double_t eCell = 0.;
1614 Float_t fraction = 1.;
1615 Float_t recalFactor = 1.;
1616
1617 Int_t iSupMod = -1;
1618 Int_t iTower = -1;
1619 Int_t iIphi = -1;
1620 Int_t iIeta = -1;
1621 Int_t iphi = -1;
1622 Int_t ieta = -1;
1623 Double_t etai = -1.;
1624 Double_t phii = -1.;
1625
1626 Int_t nstat = 0 ;
1627 Float_t wtot = 0.;
1628 Double_t w = 0.;
1629 Double_t etaMean = 0.;
1630 Double_t phiMean = 0.;
1631
1632 //Loop on cells, calculate the cluster energy, in case a cut on cell energy is added
1633 // and to check if the cluster is between 2 SM in eta
1634 Int_t iSM0 = -1;
1635 Bool_t shared = kFALSE;
1636 Float_t energy = 0;
1637
1638 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++)
1639 {
1640 //Get from the absid the supermodule, tower and eta/phi numbers
1641 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1642 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1643
1644 //Check if there are cells of different SM
1645 if (iDigit == 0 ) iSM0 = iSupMod;
1646 else if(iSupMod!= iSM0) shared = kTRUE;
1647
1648 //Get the cell energy, if recalibration is on, apply factors
1649 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1650 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1651
1652 if(IsRecalibrationOn())
1653 {
1654 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1655 }
1656
1657 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1658
1659 energy += eCell;
1660
1661 }//cell loop
1662
1663 //Loop on cells
1664 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++)
1665 {
1666 //Get from the absid the supermodule, tower and eta/phi numbers
1667 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1668 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1669
1670 //Get the cell energy, if recalibration is on, apply factors
1671 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1672 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1673
1674 if (!fCellsRecalibrated)
1675 {
1676 if(IsRecalibrationOn())
1677 {
1678 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1679 }
1680 }
1681
1682 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1683
1684 // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
1685 // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
1686 if(shared && iSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
1687
1688 if(cluster->E() > 0 && eCell > 0)
1689 {
1690 w = GetCellWeight(eCell,cluster->E());
1691
1692 etai=(Double_t)ieta;
1693 phii=(Double_t)iphi;
1694
1695 if(w > 0.0)
1696 {
1697 wtot += w ;
1698 nstat++;
1699 //Shower shape
1700 sEta += w * etai * etai ;
1701 etaMean += w * etai ;
1702 sPhi += w * phii * phii ;
1703 phiMean += w * phii ;
1704 sEtaPhi += w * etai * phii ;
1705 }
1706 }
1707 else
1708 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1709 }//cell loop
1710
1711 //Normalize to the weight
1712 if (wtot > 0)
1713 {
1714 etaMean /= wtot ;
1715 phiMean /= wtot ;
1716 }
1717 else
1718 AliError(Form("Wrong weight %f\n", wtot));
1719
1720 //Calculate dispersion
1721 for(Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++)
1722 {
1723 //Get from the absid the supermodule, tower and eta/phi numbers
1724 geom->GetCellIndex(cluster->GetCellAbsId(iDigit),iSupMod,iTower,iIphi,iIeta);
1725 geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
1726
1727 //Get the cell energy, if recalibration is on, apply factors
1728 fraction = cluster->GetCellAmplitudeFraction(iDigit);
1729 if(fraction < 1e-4) fraction = 1.; // in case unfolding is off
1730 if (IsRecalibrationOn())
1731 {
1732 recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
1733 }
1734 eCell = cells->GetCellAmplitude(cluster->GetCellAbsId(iDigit))*fraction*recalFactor;
1735
1736 // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
1737 // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
1738 if(shared && iSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
1739
1740 if(cluster->E() > 0 && eCell > 0)
1741 {
1742 w = GetCellWeight(eCell,cluster->E());
1743
1744 etai=(Double_t)ieta;
1745 phii=(Double_t)iphi;
1746 if(w > 0.0)
1747 {
1748 disp += w *((etai-etaMean)*(etai-etaMean)+(phii-phiMean)*(phii-phiMean));
1749 dEta += w * (etai-etaMean)*(etai-etaMean) ;
1750 dPhi += w * (phii-phiMean)*(phii-phiMean) ;
1751 }
1752 }
1753 else
1754 AliError(Form("Wrong energy %f and/or amplitude %f\n", eCell, cluster->E()));
1755 }// cell loop
1756
1757 //Normalize to the weigth and set shower shape parameters
1758 if (wtot > 0 && nstat > 1)
1759 {
1760 disp /= wtot ;
1761 dEta /= wtot ;
1762 dPhi /= wtot ;
1763 sEta /= wtot ;
1764 sPhi /= wtot ;
1765 sEtaPhi /= wtot ;
1766
1767 sEta -= etaMean * etaMean ;
1768 sPhi -= phiMean * phiMean ;
1769 sEtaPhi -= etaMean * phiMean ;
1770
1771 l0 = (0.5 * (sEta + sPhi) + TMath::Sqrt( 0.25 * (sEta - sPhi) * (sEta - sPhi) + sEtaPhi * sEtaPhi ));
1772 l1 = (0.5 * (sEta + sPhi) - TMath::Sqrt( 0.25 * (sEta - sPhi) * (sEta - sPhi) + sEtaPhi * sEtaPhi ));
1773 }
1774 else
1775 {
1776 l0 = 0. ;
1777 l1 = 0. ;
1778 dEta = 0. ; dPhi = 0. ; disp = 0. ;
1779 sEta = 0. ; sPhi = 0. ; sEtaPhi = 0. ;
1780 }
1781
1782}
1783
1784//____________________________________________________________________________________________
1785void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(const AliEMCALGeometry * geom,
1786 AliVCaloCells* cells,
1787 AliVCluster * cluster)
1788{
1789 // Calculates new center of gravity in the local EMCAL-module coordinates
1790 // and tranfers into global ALICE coordinates
1791 // Calculates Dispersion and main axis and puts them into the cluster
1792
1793 Float_t l0 = 0., l1 = 0.;
1794 Float_t disp = 0., dEta = 0., dPhi = 0.;
1795 Float_t sEta = 0., sPhi = 0., sEtaPhi = 0.;
1796
1797 AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(geom,cells,cluster,l0,l1,disp,
1798 dEta, dPhi, sEta, sPhi, sEtaPhi);
1799
1800 cluster->SetM02(l0);
1801 cluster->SetM20(l1);
1802 if(disp > 0. ) cluster->SetDispersion(TMath::Sqrt(disp)) ;
1803
1804}
1805
1806//____________________________________________________________________________
1807void AliEMCALRecoUtils::FindMatches(AliVEvent *event,
1808 TObjArray * clusterArr,
1809 const AliEMCALGeometry *geom)
1810{
1811 //This function should be called before the cluster loop
1812 //Before call this function, please recalculate the cluster positions
1813 //Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR
1814 //Store matched cluster indexes and residuals
1815
1816 fMatchedTrackIndex ->Reset();
1817 fMatchedClusterIndex->Reset();
1818 fResidualPhi->Reset();
1819 fResidualEta->Reset();
1820
1821 fMatchedTrackIndex ->Set(1000);
1822 fMatchedClusterIndex->Set(1000);
1823 fResidualPhi->Set(1000);
1824 fResidualEta->Set(1000);
1825
1826 AliESDEvent* esdevent = dynamic_cast<AliESDEvent*> (event);
1827 AliAODEvent* aodevent = dynamic_cast<AliAODEvent*> (event);
1828
1829 // init the magnetic field if not already on
1830 if(!TGeoGlobalMagField::Instance()->GetField())
1831 {
1832 if (!event->InitMagneticField())
1833 {
1834 AliInfo("Mag Field not initialized, null esd/aod evetn pointers");
1835 }
1836
1837 } // Init mag field
1838
1839 if (esdevent) {
1840 UInt_t mask1 = esdevent->GetESDRun()->GetDetectorsInDAQ();
1841 UInt_t mask2 = esdevent->GetESDRun()->GetDetectorsInReco();
1842 Bool_t desc1 = (mask1 >> 3) & 0x1;
1843 Bool_t desc2 = (mask2 >> 3) & 0x1;
1844 if (desc1==0 || desc2==0) {
1845// AliError(Form("TPC not in DAQ/RECO: %u (%u)/%u (%u)",
1846// mask1, esdevent->GetESDRun()->GetDetectorsInReco(),
1847// mask2, esdevent->GetESDRun()->GetDetectorsInDAQ()));
1848 fITSTrackSA=kTRUE;
1849 }
1850 }
1851
1852 TObjArray *clusterArray = 0x0;
1853 if(!clusterArr)
1854 {
1855 clusterArray = new TObjArray(event->GetNumberOfCaloClusters());
1856 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
1857 {
1858 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
1859 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
1860 clusterArray->AddAt(cluster,icl);
1861 }
1862 }
1863
1864 Int_t matched=0;
1865 Double_t cv[21];
1866 for (Int_t i=0; i<21;i++) cv[i]=0;
1867 for(Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
1868 {
1869 AliExternalTrackParam *trackParam = 0;
1870
1871 //If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner
1872 AliESDtrack *esdTrack = 0;
1873 AliAODTrack *aodTrack = 0;
1874 if(esdevent)
1875 {
1876 esdTrack = esdevent->GetTrack(itr);
1877 if(!esdTrack) continue;
1878 if(!IsAccepted(esdTrack)) continue;
1879 if(esdTrack->Pt()<fCutMinTrackPt) continue;
1880 Double_t phi = esdTrack->Phi()*TMath::RadToDeg();
1881 if(TMath::Abs(esdTrack->Eta())>0.8 || phi <= 20 || phi >= 240 ) continue;
1882 if(!fITSTrackSA)
1883 trackParam = const_cast<AliExternalTrackParam*>(esdTrack->GetInnerParam()); // if TPC Available
1884 else
1885 trackParam = new AliExternalTrackParam(*esdTrack); // If ITS Track Standing alone
1886 }
1887
1888 //If the input event is AOD, the starting point for extrapolation is at vertex
1889 //AOD tracks are selected according to its filterbit.
1890 else if(aodevent)
1891 {
1892 aodTrack = aodevent->GetTrack(itr);
1893 if(!aodTrack) continue;
1894
1895 if(fAODTPCOnlyTracks) // Match with TPC only tracks, default from May 2013, before filter bit 32
1896 {
1897 //printf("Match with TPC only tracks, accept? %d, test bit 128 <%d> \n", aodTrack->IsTPCOnly(), aodTrack->TestFilterMask(128));
1898 if(!aodTrack->IsTPCOnly()) continue ;
1899 }
1900 else if(fAODHybridTracks) // Match with hybrid tracks
1901 {
1902 //printf("Match with Hybrid tracks, accept? %d \n", aodTrack->IsHybridGlobalConstrainedGlobal());
1903 if(!aodTrack->IsHybridGlobalConstrainedGlobal()) continue ;
1904 }
1905 else // Match with tracks on a mask
1906 {
1907 //printf("Match with tracks having filter bit mask %d, accept? %d \n",fAODFilterMask,aodTrack->TestFilterMask(fAODFilterMask));
1908 if(!aodTrack->TestFilterMask(fAODFilterMask) ) continue; //Select AOD tracks
1909 }
1910
1911 if(aodTrack->Pt()<fCutMinTrackPt) continue;
1912
1913 Double_t phi = aodTrack->Phi()*TMath::RadToDeg();
1914 if(TMath::Abs(aodTrack->Eta())>0.8 || phi <= 20 || phi >= 240 ) continue;
1915 Double_t pos[3],mom[3];
1916 aodTrack->GetXYZ(pos);
1917 aodTrack->GetPxPyPz(mom);
1918 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()));
1919
1920 trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
1921 }
1922
1923 //Return if the input data is not "AOD" or "ESD"
1924 else
1925 {
1926 printf("Wrong input data type! Should be \"AOD\" or \"ESD\"\n");
1927 if(clusterArray)
1928 {
1929 clusterArray->Clear();
1930 delete clusterArray;
1931 }
1932 return;
1933 }
1934
1935 if(!trackParam) continue;
1936
1937 //Extrapolate the track to EMCal surface
1938 AliExternalTrackParam emcalParam(*trackParam);
1939 Float_t eta, phi, pt;
1940 if(!ExtrapolateTrackToEMCalSurface(&emcalParam, fEMCalSurfaceDistance, fMass, fStepSurface, eta, phi, pt))
1941 {
1942 if(aodevent && trackParam) delete trackParam;
1943 if(fITSTrackSA && trackParam) delete trackParam;
1944 continue;
1945 }
1946
1947 if(TMath::Abs(eta)>0.75 || (phi) < 70*TMath::DegToRad() || (phi) > 190*TMath::DegToRad())
1948 {
1949 if(aodevent && trackParam) delete trackParam;
1950 if(fITSTrackSA && trackParam) delete trackParam;
1951 continue;
1952 }
1953
1954 //Find matched clusters
1955 Int_t index = -1;
1956 Float_t dEta = -999, dPhi = -999;
1957 if(!clusterArr)
1958 {
1959 index = FindMatchedClusterInClusterArr(&emcalParam, &emcalParam, clusterArray, dEta, dPhi);
1960 }
1961 else
1962 {
1963 index = FindMatchedClusterInClusterArr(&emcalParam, &emcalParam, clusterArr, dEta, dPhi);
1964 }
1965
1966 if(index>-1)
1967 {
1968 fMatchedTrackIndex ->AddAt(itr,matched);
1969 fMatchedClusterIndex ->AddAt(index,matched);
1970 fResidualEta ->AddAt(dEta,matched);
1971 fResidualPhi ->AddAt(dPhi,matched);
1972 matched++;
1973 }
1974 if(aodevent && trackParam) delete trackParam;
1975 if(fITSTrackSA && trackParam) delete trackParam;
1976 }//track loop
1977
1978 if(clusterArray)
1979 {
1980 clusterArray->Clear();
1981 delete clusterArray;
1982 }
1983
1984 AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
1985
1986 fMatchedTrackIndex ->Set(matched);
1987 fMatchedClusterIndex ->Set(matched);
1988 fResidualPhi ->Set(matched);
1989 fResidualEta ->Set(matched);
1990}
1991
1992//________________________________________________________________________________
1993Int_t AliEMCALRecoUtils::FindMatchedClusterInEvent(const AliESDtrack *track,
1994 const AliVEvent *event,
1995 const AliEMCALGeometry *geom,
1996 Float_t &dEta, Float_t &dPhi)
1997{
1998 //
1999 // This function returns the index of matched cluster to input track
2000 // Returns -1 if no match is found
2001 Int_t index = -1;
2002 Double_t phiV = track->Phi()*TMath::RadToDeg();
2003 if(TMath::Abs(track->Eta())>0.8 || phiV <= 20 || phiV >= 240 ) return index;
2004 AliExternalTrackParam *trackParam = 0;
2005 if(!fITSTrackSA)
2006 trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam()); // If TPC
2007 else
2008 trackParam = new AliExternalTrackParam(*track);
2009
2010 if(!trackParam) return index;
2011 AliExternalTrackParam emcalParam(*trackParam);
2012 Float_t eta, phi, pt;
2013
2014 if(!ExtrapolateTrackToEMCalSurface(&emcalParam, fEMCalSurfaceDistance, fMass, fStepSurface, eta, phi, pt)) {
2015 if(fITSTrackSA) delete trackParam;
2016 return index;
2017 }
2018 if(TMath::Abs(eta)>0.75 || (phi) < 70*TMath::DegToRad() || (phi) > 190*TMath::DegToRad()){
2019 if(fITSTrackSA) delete trackParam;
2020 return index;
2021 }
2022
2023 TObjArray *clusterArr = new TObjArray(event->GetNumberOfCaloClusters());
2024
2025 for(Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
2026 {
2027 AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
2028 if(geom && !IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
2029 clusterArr->AddAt(cluster,icl);
2030 }
2031
2032 index = FindMatchedClusterInClusterArr(&emcalParam, &emcalParam, clusterArr, dEta, dPhi);
2033 clusterArr->Clear();
2034 delete clusterArr;
2035 if(fITSTrackSA) delete trackParam;
2036
2037 return index;
2038}
2039
2040//_______________________________________________________________________________________________
2041Int_t AliEMCALRecoUtils::FindMatchedClusterInClusterArr(const AliExternalTrackParam *emcalParam,
2042 AliExternalTrackParam *trkParam,
2043 const TObjArray * clusterArr,
2044 Float_t &dEta, Float_t &dPhi)
2045{
2046 // Find matched cluster in array
2047
2048 dEta=-999, dPhi=-999;
2049 Float_t dRMax = fCutR, dEtaMax=fCutEta, dPhiMax=fCutPhi;
2050 Int_t index = -1;
2051 Float_t tmpEta=-999, tmpPhi=-999;
2052
2053 Double_t exPos[3] = {0.,0.,0.};
2054 if(!emcalParam->GetXYZ(exPos)) return index;
2055
2056 Float_t clsPos[3] = {0.,0.,0.};
2057 for(Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
2058 {
2059 AliVCluster *cluster = dynamic_cast<AliVCluster*> (clusterArr->At(icl)) ;
2060 if(!cluster || !cluster->IsEMCAL()) continue;
2061 cluster->GetPosition(clsPos);
2062 Double_t dR = TMath::Sqrt(TMath::Power(exPos[0]-clsPos[0],2)+TMath::Power(exPos[1]-clsPos[1],2)+TMath::Power(exPos[2]-clsPos[2],2));
2063 if(dR > fClusterWindow) continue;
2064
2065 AliExternalTrackParam trkPamTmp (*trkParam);//Retrieve the starting point every time before the extrapolation
2066 if(!ExtrapolateTrackToCluster(&trkPamTmp, cluster, fMass, fStepCluster, tmpEta, tmpPhi)) continue;
2067 if(fCutEtaPhiSum)
2068 {
2069 Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
2070 if(tmpR<dRMax)
2071 {
2072 dRMax=tmpR;
2073 dEtaMax=tmpEta;
2074 dPhiMax=tmpPhi;
2075 index=icl;
2076 }
2077 }
2078 else if(fCutEtaPhiSeparate)
2079 {
2080 if(TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax))
2081 {
2082 dEtaMax = tmpEta;
2083 dPhiMax = tmpPhi;
2084 index=icl;
2085 }
2086 }
2087 else
2088 {
2089 printf("Error: please specify your cut criteria\n");
2090 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
2091 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
2092 return index;
2093 }
2094 }
2095
2096 dEta=dEtaMax;
2097 dPhi=dPhiMax;
2098
2099 return index;
2100}
2101
2102//------------------------------------------------------------------------------------
2103Bool_t AliEMCALRecoUtils::ExtrapolateTrackToEMCalSurface(AliVTrack *track,
2104 Double_t emcalR, Double_t mass, Double_t step)
2105{
2106 // Extrpolate track to EMCAL surface
2107
2108 track->SetTrackPhiEtaPtOnEMCal(-999, -999, -999);
2109
2110 if (track->Pt()<0.350)
2111 return kFALSE;
2112
2113 Double_t phi = track->Phi()*TMath::RadToDeg();
2114 if (TMath::Abs(track->Eta())>0.9 || phi <= 10 || phi >= 250)
2115 return kFALSE;
2116
2117 AliESDtrack *esdt = dynamic_cast<AliESDtrack*>(track);
2118 AliAODTrack *aodt = 0;
2119 if (!esdt) {
2120 aodt = dynamic_cast<AliAODTrack*>(track);
2121 if (!aodt)
2122 return kFALSE;
2123 }
2124
2125 if (mass<0) {
2126 Bool_t onlyTPC = kFALSE;
2127 if (mass==-99)
2128 onlyTPC=kTRUE;
2129 if (esdt)
2130 mass = esdt->GetMass(onlyTPC);
2131 else
2132 mass = aodt->M();
2133 }
2134
2135 AliExternalTrackParam *trackParam = 0;
2136 if (esdt) {
2137 const AliExternalTrackParam *in = esdt->GetInnerParam();
2138 if (!in)
2139 return kFALSE;
2140 trackParam = new AliExternalTrackParam(*in);
2141 } else {
2142 Double_t xyz[3] = {0}, pxpypz[3] = {0}, cv[21] = {0};
2143 aodt->PxPyPz(pxpypz);
2144 aodt->XvYvZv(xyz);
2145 aodt->GetCovarianceXYZPxPyPz(cv);
2146 trackParam = new AliExternalTrackParam(xyz,pxpypz,cv,aodt->Charge());
2147 }
2148 if (!trackParam)
2149 return kFALSE;
2150
2151 Float_t etaout=-999, phiout=-999, ptout=-999;
2152 Bool_t ret = ExtrapolateTrackToEMCalSurface(trackParam,
2153 emcalR,
2154 mass,
2155 step,
2156 etaout,
2157 phiout,
2158 ptout);
2159 delete trackParam;
2160 if (!ret)
2161 return kFALSE;
2162 if (TMath::Abs(etaout)>0.75 || (phiout<70*TMath::DegToRad()) || (phiout>190*TMath::DegToRad()))
2163 return kFALSE;
2164 track->SetTrackPhiEtaPtOnEMCal(phiout, etaout, ptout);
2165 return kTRUE;
2166}
2167
2168
2169//------------------------------------------------------------------------------------
2170Bool_t AliEMCALRecoUtils::ExtrapolateTrackToEMCalSurface(AliExternalTrackParam *trkParam,
2171 Double_t emcalR,
2172 Double_t mass,
2173 Double_t step,
2174 Float_t &eta,
2175 Float_t &phi,
2176 Float_t &pt)
2177{
2178 //Extrapolate track to EMCAL surface
2179
2180 eta = -999, phi = -999, pt = -999;
2181 if(!trkParam) return kFALSE;
2182 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, emcalR, mass, step, kTRUE, 0.8, -1)) return kFALSE;
2183 Double_t trkPos[3] = {0.,0.,0.};
2184 if(!trkParam->GetXYZ(trkPos)) return kFALSE;
2185 TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
2186 eta = trkPosVec.Eta();
2187 phi = trkPosVec.Phi();
2188 pt = trkParam->Pt();
2189 if(phi<0)
2190 phi += 2*TMath::Pi();
2191
2192 return kTRUE;
2193}
2194
2195//-----------------------------------------------------------------------------------
2196Bool_t AliEMCALRecoUtils::ExtrapolateTrackToPosition(AliExternalTrackParam *trkParam,
2197 const Float_t *clsPos,
2198 Double_t mass,
2199 Double_t step,
2200 Float_t &tmpEta,
2201 Float_t &tmpPhi)
2202{
2203 //
2204 //Return the residual by extrapolating a track param to a global position
2205 //
2206 tmpEta = -999;
2207 tmpPhi = -999;
2208 if(!trkParam) return kFALSE;
2209 Double_t trkPos[3] = {0.,0.,0.};
2210 TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
2211 Double_t alpha = ((int)(vec.Phi()*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
2212 vec.RotateZ(-alpha); //Rotate the cluster to the local extrapolation coordinate system
2213 if(!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), mass, step,kTRUE, 0.8, -1)) return kFALSE;
2214 if(!trkParam->GetXYZ(trkPos)) return kFALSE; //Get the extrapolated global position
2215
2216 TVector3 clsPosVec(clsPos[0],clsPos[1],clsPos[2]);
2217 TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
2218
2219 // track cluster matching
2220 tmpPhi = clsPosVec.DeltaPhi(trkPosVec); // tmpPhi is between -pi and pi
2221 tmpEta = clsPosVec.Eta()-trkPosVec.Eta();
2222
2223 return kTRUE;
2224}
2225
2226//----------------------------------------------------------------------------------
2227Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam,
2228 const AliVCluster *cluster,
2229 Double_t mass,
2230 Double_t step,
2231 Float_t &tmpEta,
2232 Float_t &tmpPhi)
2233{
2234 //
2235 //Return the residual by extrapolating a track param to a cluster
2236 //
2237 tmpEta = -999;
2238 tmpPhi = -999;
2239 if(!cluster || !trkParam) return kFALSE;
2240
2241 Float_t clsPos[3] = {0.,0.,0.};
2242 cluster->GetPosition(clsPos);
2243
2244 return ExtrapolateTrackToPosition(trkParam, clsPos, mass, step, tmpEta, tmpPhi);
2245}
2246
2247//---------------------------------------------------------------------------------
2248Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam,
2249 const AliVCluster *cluster,
2250 Float_t &tmpEta,
2251 Float_t &tmpPhi)
2252{
2253 //
2254 //Return the residual by extrapolating a track param to a clusterfStepCluster
2255 //
2256
2257 return ExtrapolateTrackToCluster(trkParam, cluster, fMass, fStepCluster, tmpEta, tmpPhi);
2258}
2259
2260//_______________________________________________________________________
2261void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex,
2262 Float_t &dEta, Float_t &dPhi)
2263{
2264 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
2265 //Get the residuals dEta and dPhi for this cluster to the closest track
2266 //Works with ESDs and AODs
2267
2268 if( FindMatchedPosForCluster(clsIndex) >= 999 )
2269 {
2270 AliDebug(2,"No matched tracks found!\n");
2271 dEta=999.;
2272 dPhi=999.;
2273 return;
2274 }
2275 dEta = fResidualEta->At(FindMatchedPosForCluster(clsIndex));
2276 dPhi = fResidualPhi->At(FindMatchedPosForCluster(clsIndex));
2277}
2278
2279//______________________________________________________________________________________________
2280void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dEta, Float_t &dPhi)
2281{
2282 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
2283 //Get the residuals dEta and dPhi for this track to the closest cluster
2284 //Works with ESDs and AODs
2285
2286 if( FindMatchedPosForTrack(trkIndex) >= 999 )
2287 {
2288 AliDebug(2,"No matched cluster found!\n");
2289 dEta=999.;
2290 dPhi=999.;
2291 return;
2292 }
2293 dEta = fResidualEta->At(FindMatchedPosForTrack(trkIndex));
2294 dPhi = fResidualPhi->At(FindMatchedPosForTrack(trkIndex));
2295}
2296
2297//__________________________________________________________
2298Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
2299{
2300 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
2301 //Get the index of matched track to this cluster
2302 //Works with ESDs and AODs
2303
2304 if(IsClusterMatched(clsIndex))
2305 return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
2306 else
2307 return -1;
2308}
2309
2310//__________________________________________________________
2311Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
2312{
2313 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
2314 //Get the index of matched cluster to this track
2315 //Works with ESDs and AODs
2316
2317 if(IsTrackMatched(trkIndex))
2318 return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
2319 else
2320 return -1;
2321}
2322
2323//______________________________________________________________
2324Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex) const
2325{
2326 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
2327 //Returns if the cluster has a match
2328 if(FindMatchedPosForCluster(clsIndex) < 999)
2329 return kTRUE;
2330 else
2331 return kFALSE;
2332}
2333
2334//____________________________________________________________
2335Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex) const
2336{
2337 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
2338 //Returns if the track has a match
2339 if(FindMatchedPosForTrack(trkIndex) < 999)
2340 return kTRUE;
2341 else
2342 return kFALSE;
2343}
2344
2345//______________________________________________________________________
2346UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
2347{
2348 //Given a cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
2349 //Returns the position of the match in the fMatchedClusterIndex array
2350 Float_t tmpR = fCutR;
2351 UInt_t pos = 999;
2352
2353 for(Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++)
2354 {
2355 if(fMatchedClusterIndex->At(i)==clsIndex)
2356 {
2357 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
2358 if(r<tmpR)
2359 {
2360 pos=i;
2361 tmpR=r;
2362 AliDebug(3,Form("Matched cluster index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",
2363 fMatchedClusterIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
2364 }
2365 }
2366 }
2367 return pos;
2368}
2369
2370//____________________________________________________________________
2371UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
2372{
2373 //Given a track index as in AliESDEvent::GetTrack(trkIndex)
2374 //Returns the position of the match in the fMatchedTrackIndex array
2375 Float_t tmpR = fCutR;
2376 UInt_t pos = 999;
2377
2378 for(Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++)
2379 {
2380 if(fMatchedTrackIndex->At(i)==trkIndex)
2381 {
2382 Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
2383 if(r<tmpR)
2384 {
2385 pos=i;
2386 tmpR=r;
2387 AliDebug(3,Form("Matched track index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",
2388 fMatchedTrackIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
2389 }
2390 }
2391 }
2392 return pos;
2393}
2394
2395//__________________________________________________________________________
2396Bool_t AliEMCALRecoUtils::IsGoodCluster(AliVCluster *cluster,
2397 const AliEMCALGeometry *geom,
2398 AliVCaloCells* cells, Int_t bc)
2399{
2400 // check if the cluster survives some quality cut
2401 //
2402 //
2403 Bool_t isGood=kTRUE;
2404
2405 if(!cluster || !cluster->IsEMCAL()) return kFALSE;
2406
2407 if(ClusterContainsBadChannel(geom,cluster->GetCellsAbsId(),cluster->GetNCells())) return kFALSE;
2408
2409 if(!CheckCellFiducialRegion(geom,cluster,cells)) return kFALSE;
2410
2411 if(IsExoticCluster(cluster, cells,bc)) return kFALSE;
2412
2413 return isGood;
2414}
2415
2416//__________________________________________________________
2417Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
2418{
2419 // Given a esd track, return whether the track survive all the cuts
2420
2421 // The different quality parameter are first
2422 // retrieved from the track. then it is found out what cuts the
2423 // track did not survive and finally the cuts are imposed.
2424
2425 UInt_t status = esdTrack->GetStatus();
2426
2427 Int_t nClustersITS = esdTrack->GetITSclusters(0);
2428 Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
2429
2430 Float_t chi2PerClusterITS = -1;
2431 Float_t chi2PerClusterTPC = -1;
2432 if (nClustersITS!=0)
2433 chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
2434 if (nClustersTPC!=0)
2435 chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
2436
2437
2438 //DCA cuts
2439 if(fTrackCutsType==kGlobalCut)
2440 {
2441 Float_t maxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); //This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
2442 //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
2443 SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
2444 }
2445
2446
2447 Float_t b[2];
2448 Float_t bCov[3];
2449 esdTrack->GetImpactParameters(b,bCov);
2450 if (bCov[0]<=0 || bCov[2]<=0)
2451 {
2452 AliDebug(1, "Estimated b resolution lower or equal zero!");
2453 bCov[0]=0; bCov[2]=0;
2454 }
2455
2456 Float_t dcaToVertexXY = b[0];
2457 Float_t dcaToVertexZ = b[1];
2458 Float_t dcaToVertex = -1;
2459
2460 if (fCutDCAToVertex2D)
2461 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY/fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + dcaToVertexZ*dcaToVertexZ/fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ);
2462 else
2463 dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
2464
2465 // cut the track?
2466
2467 Bool_t cuts[kNCuts];
2468 for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
2469
2470 // track quality cuts
2471 if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
2472 cuts[0]=kTRUE;
2473 if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
2474 cuts[1]=kTRUE;
2475 if (nClustersTPC<fCutMinNClusterTPC)
2476 cuts[2]=kTRUE;
2477 if (nClustersITS<fCutMinNClusterITS)
2478 cuts[3]=kTRUE;
2479 if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC)
2480 cuts[4]=kTRUE;
2481 if (chi2PerClusterITS>fCutMaxChi2PerClusterITS)
2482 cuts[5]=kTRUE;
2483 if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
2484 cuts[6]=kTRUE;
2485 if (fCutDCAToVertex2D && dcaToVertex > 1)
2486 cuts[7] = kTRUE;
2487 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
2488 cuts[8] = kTRUE;
2489 if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ) > fCutMaxDCAToVertexZ)
2490 cuts[9] = kTRUE;
2491
2492 if(fTrackCutsType==kGlobalCut)
2493 {
2494 //Require at least one SPD point + anything else in ITS
2495 if( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
2496 cuts[10] = kTRUE;
2497 }
2498
2499 // ITS
2500 if(fCutRequireITSStandAlone || fCutRequireITSpureSA){
2501 if ((status & AliESDtrack::kITSin) == 0 || (status & AliESDtrack::kTPCin)){
2502 // TPC tracks
2503 cuts[11] = kTRUE;
2504 }else{
2505 // ITS standalone tracks
2506 if(fCutRequireITSStandAlone && !fCutRequireITSpureSA){
2507 if(status & AliESDtrack::kITSpureSA) cuts[11] = kTRUE;
2508 }else if(fCutRequireITSpureSA){
2509 if(!(status & AliESDtrack::kITSpureSA)) cuts[11] = kTRUE;
2510 }
2511 }
2512 }
2513
2514 Bool_t cut=kFALSE;
2515 for (Int_t i=0; i<kNCuts; i++)
2516 if (cuts[i]) { cut = kTRUE ; }
2517
2518 // cut the track
2519 if (cut)
2520 return kFALSE;
2521 else
2522 return kTRUE;
2523}
2524
2525//_____________________________________
2526void AliEMCALRecoUtils::InitTrackCuts()
2527{
2528 //Intilize the track cut criteria
2529 //By default these cuts are set according to AliESDtrackCuts::GetStandardTPCOnlyTrackCuts()
2530 //Also you can customize the cuts using the setters
2531
2532 switch (fTrackCutsType)
2533 {
2534 case kTPCOnlyCut:
2535 {
2536 AliInfo(Form("Track cuts for matching: GetStandardTPCOnlyTrackCuts()"));
2537 //TPC
2538 SetMinNClustersTPC(70);
2539 SetMaxChi2PerClusterTPC(4);
2540 SetAcceptKinkDaughters(kFALSE);
2541 SetRequireTPCRefit(kFALSE);
2542
2543 //ITS
2544 SetRequireITSRefit(kFALSE);
2545 SetMaxDCAToVertexZ(3.2);
2546 SetMaxDCAToVertexXY(2.4);
2547 SetDCAToVertex2D(kTRUE);
2548
2549 break;
2550 }
2551
2552 case kGlobalCut:
2553 {
2554 AliInfo(Form("Track cuts for matching: GetStandardITSTPCTrackCuts2010(kTURE)"));
2555 //TPC
2556 SetMinNClustersTPC(70);
2557 SetMaxChi2PerClusterTPC(4);
2558 SetAcceptKinkDaughters(kFALSE);
2559 SetRequireTPCRefit(kTRUE);
2560
2561 //ITS
2562 SetRequireITSRefit(kTRUE);
2563 SetMaxDCAToVertexZ(2);
2564 SetMaxDCAToVertexXY();
2565 SetDCAToVertex2D(kFALSE);
2566
2567 break;
2568 }
2569
2570 case kLooseCut:
2571 {
2572 AliInfo(Form("Track cuts for matching: Loose cut w/o DCA cut"));
2573 SetMinNClustersTPC(50);
2574 SetAcceptKinkDaughters(kTRUE);
2575
2576 break;
2577 }
2578
2579 case kITSStandAlone:
2580 {
2581 AliInfo(Form("Track cuts for matching: ITS Stand Alone tracks cut w/o DCA cut"));
2582 SetRequireITSRefit(kTRUE);
2583 SetRequireITSStandAlone(kTRUE);
2584 SetITSTrackSA(kTRUE);
2585 break;
2586 }
2587
2588 }
2589}
2590
2591
2592//________________________________________________________________________
2593void AliEMCALRecoUtils::SetClusterMatchedToTrack(const AliVEvent *event)
2594{
2595 // Checks if tracks are matched to EMC clusters and set the matched EMCAL cluster index to ESD track.
2596
2597 Int_t nTracks = event->GetNumberOfTracks();
2598 for (Int_t iTrack = 0; iTrack < nTracks; ++iTrack)
2599 {
2600 AliVTrack* track = dynamic_cast<AliVTrack*>(event->GetTrack(iTrack));
2601 if (!track)
2602 {
2603 AliWarning(Form("Could not receive track %d", iTrack));
2604 continue;
2605 }
2606
2607 Int_t matchClusIndex = GetMatchedClusterIndex(iTrack);
2608 track->SetEMCALcluster(matchClusIndex); //sets -1 if track not matched within residual
2609 /*the following can be done better if AliVTrack::SetStatus will be there. Patch pending with Andreas/Peter*/
2610 AliESDtrack* esdtrack = dynamic_cast<AliESDtrack*>(track);
2611 if (esdtrack) {
2612 if(matchClusIndex != -1)
2613 esdtrack->SetStatus(AliESDtrack::kEMCALmatch);
2614 else
2615 esdtrack->ResetStatus(AliESDtrack::kEMCALmatch);
2616 } else {
2617 AliAODTrack* aodtrack = dynamic_cast<AliAODTrack*>(track);
2618 if(matchClusIndex != -1)
2619 aodtrack->SetStatus(AliESDtrack::kEMCALmatch);
2620 else
2621 aodtrack->ResetStatus(AliESDtrack::kEMCALmatch);
2622 }
2623
2624 }
2625 AliDebug(2,"Track matched to closest cluster");
2626}
2627
2628//_________________________________________________________________________
2629void AliEMCALRecoUtils::SetTracksMatchedToCluster(const AliVEvent *event)
2630{
2631 // Checks if EMC clusters are matched to ESD track.
2632 // Adds track indexes of all the tracks matched to a cluster withing residuals in ESDCalocluster.
2633
2634 for (Int_t iClus=0; iClus < event->GetNumberOfCaloClusters(); ++iClus)
2635 {
2636 AliVCluster *cluster = event->GetCaloCluster(iClus);
2637 if (!cluster->IsEMCAL())
2638 continue;
2639
2640 Int_t nTracks = event->GetNumberOfTracks();
2641 TArrayI arrayTrackMatched(nTracks);
2642
2643 // Get the closest track matched to the cluster
2644 Int_t nMatched = 0;
2645 Int_t matchTrackIndex = GetMatchedTrackIndex(iClus);
2646 if (matchTrackIndex != -1)
2647 {
2648 arrayTrackMatched[nMatched] = matchTrackIndex;
2649 nMatched++;
2650 }
2651
2652 // Get all other tracks matched to the cluster
2653 for(Int_t iTrk=0; iTrk<nTracks; ++iTrk)
2654 {
2655 AliVTrack* track = dynamic_cast<AliVTrack*>(event->GetTrack(iTrk));
2656 if(iTrk == matchTrackIndex) continue;
2657 if(track->GetEMCALcluster() == iClus)
2658 {
2659 arrayTrackMatched[nMatched] = iTrk;
2660 ++nMatched;
2661 }
2662 }
2663
2664 //printf("Tender::SetTracksMatchedToCluster - cluster E %f, N matches %d, first match %d\n",cluster->E(),nMatched,arrayTrackMatched[0]);
2665
2666 arrayTrackMatched.Set(nMatched);
2667 AliESDCaloCluster *esdcluster = dynamic_cast<AliESDCaloCluster*>(cluster);
2668 if (esdcluster)
2669 esdcluster->AddTracksMatched(arrayTrackMatched);
2670 else if (nMatched>0) {
2671 AliAODCaloCluster *aodcluster = dynamic_cast<AliAODCaloCluster*>(cluster);
2672 if (aodcluster)
2673 aodcluster->AddTrackMatched(event->GetTrack(arrayTrackMatched.At(0)));
2674 }
2675
2676 Float_t eta= -999, phi = -999;
2677 if (matchTrackIndex != -1)
2678 GetMatchedResiduals(iClus, eta, phi);
2679 cluster->SetTrackDistance(phi, eta);
2680 }
2681
2682 AliDebug(2,"Cluster matched to tracks");
2683}
2684
2685//___________________________________________________
2686void AliEMCALRecoUtils::Print(const Option_t *) const
2687{
2688 // Print Parameters
2689
2690 printf("AliEMCALRecoUtils Settings: \n");
2691 printf("Misalignment shifts\n");
2692 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,
2693 fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
2694 fMisalRotShift[i*3], fMisalRotShift[i*3+1], fMisalRotShift[i*3+2] );
2695 printf("Non linearity function %d, parameters:\n", fNonLinearityFunction);
2696 for(Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
2697
2698 printf("Position Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
2699
2700 printf("Matching criteria: ");
2701 if(fCutEtaPhiSum)
2702 {
2703 printf("sqrt(dEta^2+dPhi^2)<%4.3f\n",fCutR);
2704 }
2705 else if(fCutEtaPhiSeparate)
2706 {
2707 printf("dEta<%4.3f, dPhi<%4.3f\n",fCutEta,fCutPhi);
2708 }
2709 else
2710 {
2711 printf("Error\n");
2712 printf("please specify your cut criteria\n");
2713 printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
2714 printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
2715 }
2716
2717 printf("Mass hypothesis = %2.3f [GeV/c^2], extrapolation step to surface = %2.2f[cm], step to cluster = %2.2f[cm]\n",fMass,fStepSurface, fStepCluster);
2718 printf("Cluster selection window: dR < %2.0f\n",fClusterWindow);
2719
2720 printf("Track cuts: \n");
2721 printf("Minimum track pT: %1.2f\n",fCutMinTrackPt);
2722 printf("AOD track selection: tpc only %d, or hybrid %d, or mask: %d\n",fAODTPCOnlyTracks,fAODHybridTracks, fAODFilterMask);
2723 printf("TPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
2724 printf("AcceptKinks = %d\n",fCutAcceptKinkDaughters);
2725 printf("MinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
2726 printf("MaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
2727 printf("DCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
2728}
2729