AliRoot Core  3dc7879 (3dc7879)
AliEMCALClusterizerv3.cxx
Go to the documentation of this file.
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 // --- ROOT system ---
17 #include <TFile.h>
18 #include <TMath.h>
19 #include <TMinuit.h>
20 #include <TTree.h>
21 #include <TBenchmark.h>
22 #include <TBrowser.h>
23 #include <TROOT.h>
24 #include <TList.h>
25 #include <TClonesArray.h>
26 
27 // --- Standard library ---
28 #include <cstring>
29 #include <cassert>
30 
31 // --- AliRoot header files ---
32 #include "AliLog.h"
33 #include "AliEMCALClusterizerv3.h"
34 #include "AliEMCALRecPoint.h"
35 #include "AliEMCALDigit.h"
36 #include "AliEMCALGeometry.h"
37 #include "AliCaloCalibPedestal.h"
38 #include "AliEMCALCalibData.h"
39 #include "AliEMCALCalibTime.h"
40 #include "AliESDCaloCluster.h"
41 #include "AliEMCALUnfolding.h"
42 
44 ClassImp(AliEMCALClusterFinder);
46 
47 
50 //____________________________________________________________________________
51 AliEMCALClusterFinder::AliEMCALClusterFinder(TObjArray* outputArray, AliEMCALGeometry* geometry, Double_t timeCut, Double_t timeMin, Double_t timeMax, Double_t gradientCut, Bool_t doEnergyGradientCut, Double_t thresholdSeedE, Double_t thresholdCellE) :
52  fEMCALGeometry(geometry), fSeedList(), fDigitMap(), fCellMask(),
53  fFoundClusters(outputArray), fNumFoundClusters(0), fTimeCut(timeCut), fTimeMin(timeMin), fTimeMax(timeMax), fGradientCut(gradientCut), fDoEnergyGradientCut(doEnergyGradientCut), fThresholdSeedEnergy(thresholdSeedE),fThresholdCellEnergy(thresholdCellE)
54 {
55 }
56 
59 //____________________________________________________________________________
61 {
62  if(fFoundClusters) fFoundClusters->Delete();
63 }
64 
67 //____________________________________________________________________________
69 {
70  // Cluster/recpoint is already initialized with seed digit
71  Bool_t shared = kFALSE;
72 
73  // Recursion 0
74  if(!recPoint)
75  {
76  recPoint = new AliEMCALRecPoint("");
78  recPoint->AddDigit(*fDigitMap[row][column], fDigitMap[row][column]->GetCalibAmp(), kFALSE);
79  }
80  Int_t currentSM = fEMCALGeometry->GetSuperModuleNumber(fDigitMap[row][column]->GetId());
81 
82  // Mark the current cell as clustered
83  fCellMask[row][column] = kTRUE;
84 
85  // Now go recursively to the next 4 neighbours and add them to the cluster if they fulfill the conditions
86  for(Int_t dir=0; dir<4; dir++)
87  {
88  Int_t rowDiff = 0;
89  Int_t colDiff = 0;
90  if(dir==0) {rowDiff = -1; colDiff = 0;}
91  else if(dir==1) {rowDiff = 0; colDiff = -1;}
92  else if(dir==2) {rowDiff = 0; colDiff = +1;}
93  else if(dir==3) {rowDiff = +1; colDiff = 0;}
94 
95  if( (row+rowDiff < 0) || (row+rowDiff >= EMCALClusterFinder::kNrows) ) continue;
96  if( (column+colDiff < 0) || (column+colDiff >= EMCALClusterFinder::kNcolumns) ) continue;
97 
98  if(fDigitMap[row+rowDiff][column+colDiff])
99  if(!fCellMask[row+rowDiff][column+colDiff])
100  if (fDoEnergyGradientCut && not (fDigitMap[row+rowDiff][column+colDiff]->GetCalibAmp()>fDigitMap[row][column]->GetCalibAmp()+fGradientCut))
101  if (not (TMath::Abs(fDigitMap[row+rowDiff][column+colDiff]->GetTime() - fDigitMap[row][column]->GetTime()) > fTimeCut))
102  {
103  // Check if cluster extends over two SMs (= shared cluster)
104  shared = (currentSM != fEMCALGeometry->GetSuperModuleNumber(fDigitMap[row+rowDiff][column+colDiff]->GetId()));
105  (void) GetClusterFromNeighbours(recPoint, row+rowDiff, column+colDiff);
106  // Add the digit to the current cluster -- if we end up here, the selected cluster fulfills the condition
107  recPoint->AddDigit(*fDigitMap[row+rowDiff][column+colDiff], fDigitMap[row+rowDiff][column+colDiff]->GetCalibAmp(), shared);
108  // Mask the cell as already used for clustering
109  }
110  }
111  return recPoint;
112 }
113 
114 
118 //____________________________________________________________________________
119 void AliEMCALClusterFinder::GetTopologicalRowColumn(AliEMCALDigit* digit, Int_t& row, Int_t& column)
120 {
121  Int_t nSupMod=0, nModule=0, nIphi=0, nIeta=0;
122  row=0;
123  column=0;
124  // Get SM number and relative row/column for SM
125  fEMCALGeometry->GetCellIndex(digit->GetId(), nSupMod,nModule,nIphi,nIeta);
126  fEMCALGeometry->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, row,column);
127 
128  // Add shifts wrt. supermodule and type of calorimeter
129  // NOTE:
130  // * Rows (phi) are arranged that one space is left empty between supermodules in phi
131  // This is due to the physical gap that forbids clustering
132  // * For DCAL, there is an additional empty column between two supermodules in eta
133  // Again, this is to account for the gap in DCAL
134 
135  row += nSupMod/2 * (24+1);
136  // In DCAL, leave a gap between two SMs with same phi
137  if(!fEMCALGeometry->IsDCALSM(nSupMod)) // EMCAL
138  column += nSupMod%2 * 48;
139  else
140  column += nSupMod%2 * (48+1);
141 }
142 
143 
146 //____________________________________________________________________________
147 Int_t AliEMCALClusterFinder::FindClusters(TClonesArray* digitArray)
148 {
149  fFoundClusters->Delete();
150 
151  // Algorithm
152  // - Fill digits in 2D topological map
153  // - Fill struct arrays (energy,x,y) (to get mapping energy -> (x,y))
154  // - Create 2D bitmap (digit is already clustered or not)
155  // - Sort struct arrays with descending energy
156  //
157  // - Loop over arrays:
158  // --> Check 2D bitmap (don't use digit which are already clustered)
159  // --> Take valid digit with highest energy as seed (they are already sorted)
160  // --> Recursive to neighboughs and create cluster
161  // --> Seed cell and all neighbours belonging to cluster will be put in 2D bitmap
162 
163  // Reset digit maps and cell masks
164  std::memset(fCellMask, 0, sizeof(Bool_t) * EMCALClusterFinder::kNrows*EMCALClusterFinder::kNcolumns);
165  std::memset(fDigitMap, 0, sizeof(AliEMCALDigit*) * EMCALClusterFinder::kNrows*EMCALClusterFinder::kNcolumns);
166 
167  // Calibrate digits and fill the maps/arrays
168  Int_t nCells = 0;
169  Double_t ehs = 0.0;
170  AliEMCALDigit *digit = 0;
171  TIter nextdigit(digitArray);
172  while ( (digit = static_cast<AliEMCALDigit*>(nextdigit())) )
173  {
174  Float_t dEnergyCalibrated = digit->GetAmplitude();
175  Float_t time = digit->GetTime();
176 
177  if (dEnergyCalibrated < fThresholdCellEnergy || time > fTimeMax || time < fTimeMin)
178  continue;
179  if (!fEMCALGeometry->CheckAbsCellId(digit->GetId()))
180  continue;
181 
182  ehs += dEnergyCalibrated;
183 
184  // Put digit to 2D map
185  Int_t row = 0, column = 0;
186  GetTopologicalRowColumn(digit, row, column);
187  fDigitMap[row][column] = digit;
188  fSeedList[nCells].energy = dEnergyCalibrated;
189  fSeedList[nCells].row = row;
190  fSeedList[nCells].column = column;
191  nCells++;
192  }
193 
194  // Sort struct arrays with ascending energy
195  std::sort(fSeedList, fSeedList+nCells);
196 
197  // Take next valid digit in calorimeter as seed (in descending energy order)
198  fNumFoundClusters = 0;
199  for(Int_t i=nCells-1; i>=0; i--)
200  {
201  Int_t row = fSeedList[i].row, column = fSeedList[i].column;
202  // Continue if the cell is already masked (i.e. was already clustered)
203  if(fCellMask[row][column])
204  continue;
205  // Continue if energy constraints are not fulfilled
206  if (fSeedList[i].energy<=fThresholdSeedEnergy)
207  continue;
208 
209  // Seed is found, form cluster recursively
210  if (fNumFoundClusters>=fFoundClusters->GetSize())
211  fFoundClusters->Expand(2*fNumFoundClusters+1);
212 
213  AliEMCALRecPoint* recPoint = GetClusterFromNeighbours(0, row, column);
214  fFoundClusters->AddAt(recPoint, fNumFoundClusters++);
215  }
216 
217  AliDebug(1,Form("%d clusters found from %d digits (total=%d)-> ehs %f (minE %f)\n",fNumFoundClusters,nCells,digitArray->GetEntriesFast(), ehs,fThresholdCellEnergy));
218  return fNumFoundClusters;
219 }
220 
221 
222 
224 ClassImp(AliEMCALClusterizerv3) ;
226 
227 
230 //____________________________________________________________________________
232  : AliEMCALClusterizerv1(), fDoEnGradCut(1), fClusterFinder(0)
233 { }
234 
239 //____________________________________________________________________________
242 { }
243 
251 //____________________________________________________________________________
253  AliEMCALCalibData* calib,
254  AliEMCALCalibTime* calibt,
255  AliCaloCalibPedestal* caloped)
256  : AliEMCALClusterizerv1(geometry, calib, calibt, caloped), fDoEnGradCut(1), fClusterFinder(0)
257 { }
258 
261 //____________________________________________________________________________
263 {
264  if(fClusterFinder) delete fClusterFinder;
265 }
266 
269 //____________________________________________________________________________
271 {
272  if(fGeom==0)
273  AliFatal("AliEMCALGeometry object not properly loaded.");
274 
275  // Create cluster finder only once, at execution time (cannot be done in constructor, because settings could change afterwards)
276  // fRecPoints is the TObjArray we will write to
277  if(!fClusterFinder)
279 
280  // Do calibration of cells and sort out some cells already
281  AliEMCALDigit *digit = 0;
282  TIter nextdigit(fDigitsArr);
283  while ( (digit = static_cast<AliEMCALDigit*>(nextdigit())) )
284  {
285  Float_t dEnergyCalibrated = digit->GetAmplitude();
286  Float_t time = digit->GetTime();
287  Calibrate(dEnergyCalibrated, time, digit->GetId());
288 
289  digit->SetCalibAmp(dEnergyCalibrated);
290  digit->SetTime(time);
291  }
292 
293  // Perform cluster finding. Output is written to fRecPoints
295 }
296 
Bool_t CheckAbsCellId(Int_t absId) const
Int_t fNumberOfECAClusters
number of clusters found in EC section
Double_t fTimeCut
maximum time difference between the digits inside EMC cluster
Bool_t fDoEnGradCut
cut on energy gradient
virtual void Calibrate(Float_t &amp, Float_t &time, const Int_t cellId)
Int_t fNumFoundClusters
number of found clusters in FindClusters()
#define TObjArray
Float_t GetTime(void) const
Definition: AliEMCALDigit.h:64
TObjArray * fRecPoints
array with EMCAL clusters
void SetCalibAmp(Float_t amp)
cellWithE fSeedList[EMCALClusterFinder::kNrows *EMCALClusterFinder::kNcolumns]
! seed array
virtual void MakeClusters()
Make list of clusters. Use AliEMCALClusterFinder class.
AliEMCALDigit * fDigitMap[EMCALClusterFinder::kNrows][EMCALClusterFinder::kNcolumns]
! topology arrays
Double_t fGradientCut
minimum energy difference to distinguish local maxima in a cluster
Double_t fThresholdCellEnergy
minimum energy for a digit to be a member of a cluster
Float_t fECALocMaxCut
minimum energy difference to distinguish local maxima in a cluster
Cell energy calibration factors container class.
EMCal digits object.
Definition: AliEMCALDigit.h:30
Meta class for recursive clusterizer.
AliEMCALClusterFinder(TObjArray *outputArray, AliEMCALGeometry *geometry, Double_t timeCut, Double_t timeMin, Double_t timeMax, Double_t gradientCut, Bool_t doEnergyGradientCut, Double_t thresholdSeedE, Double_t thresholdCellE)
Constructor.
Clusterize neighbour cells, split if several maxima.
void GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta, Int_t &iphi, Int_t &ieta) const
void SetTime(Float_t time)
Definition: AliEMCALDigit.h:74
Float_t fTimeCut
maximum time difference between the digits inside EMC cluster
TObjArray * fFoundClusters
! Pointer to found cluster object array
Bool_t GetCellIndex(Int_t absId, Int_t &nSupMod, Int_t &nModule, Int_t &nIphi, Int_t &nIeta) const
virtual void AddDigit(AliEMCALDigit &digit, const Float_t energy, const Bool_t shared)
virtual ~AliEMCALClusterizerv3()
Destructtor.
Float_t fTimeMin
minimum time of physical signal in a cell/digit
EMCal rec_points object.
AliEMCALGeometry * fGeom
! pointer to geometry for utilities
AliEMCALRecPoint * GetClusterFromNeighbours(AliEMCALRecPoint *recPoint, Int_t row, Int_t column)
Recursively search for neighbours (EMCAL)
void GetTopologicalRowColumn(AliEMCALDigit *digit, Int_t &row, Int_t &column)
Bool_t fCellMask[EMCALClusterFinder::kNrows][EMCALClusterFinder::kNcolumns]
! topology arrays
Cell time shifts container class.
Clusterize neighbour cells, no split, unfolding possible.
pedestal/bad map monitoring and calibration tools
Float_t fTimeMax
maximum time of physical signal in a cell/digit
Double_t fThresholdSeedEnergy
minimum energy to seed a EC digit in a cluster
#define AliFatal(message)
Definition: AliLog.h:640
Int_t GetSuperModuleNumber(Int_t absId) const
AliEMCALClusterFinder * fClusterFinder
! Cluster finder
TClonesArray * fDigitsArr
array with EMCAL digits
#define AliDebug(logLevel, message)
Definition: AliLog.h:300
Double_t fTimeMin
minimum time of physical signal in a cell/digit
Int_t GetId() const
Definition: AliDigitNew.h:23
Bool_t fDoEnergyGradientCut
cut on energy gradient
Double_t fTimeMax
maximum time of physical signal in a cell/digit
AliEMCALClusterizerv3()
Default constructor.
Float_t fECAClusteringThreshold
minimum energy to seed a EC digit in a cluster
Bool_t IsDCALSM(Int_t nSupMod) const
AliEMCALGeometry * fEMCALGeometry
! pointer to geometry for utilities
virtual void SetClusterType(Int_t ver)
Float_t GetAmplitude() const
Definition: AliEMCALDigit.h:55
EMCal geometry, singleton.
Int_t FindClusters(TClonesArray *digits)
Return number of found clusters. Start clustering from highest energy cell.
Float_t fMinECut
minimum energy for a digit to be a member of a cluster