]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALClusterizerNxN.cxx
AddInfo additions - needed for normal Preprocessor operations
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALClusterizerNxN.cxx
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 // This class derives from AliEMCALClustrerizer but also keeps the API of AliEMCALClusterizerv1
17 // Algorithm:
18 // 1. peek the most energetic cell
19 // 2. assign it as a center of the cluster and add cells surrounding it: 3x3, 5x5...
20 // 3. remove the cells contributing to the cluster
21 // 4. start from 1 for the remaining clusters
22 // 5. cluster splitting (not implemented yet) - use the shape analysis to resolve the energy sharing
23 // - for high energy clusters check the surrounding of the 3x3 clusters for extra energy 
24 // (merge 3x3 clusters and resolve the internal energy sharing - case for 2 clusters merged)
25 // Use Case:
26 //  root [0] AliEMCALClusterizerNxN * cl = new AliEMCALClusterizerNxN("galice.root")  
27 //  Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
28 //               //reads gAlice from header file "..."                      
29 //  root [1] cl->ExecuteTask()  
30 //               //finds RecPoints in all events stored in galice.root
31 //  root [2] cl->SetDigitsBranch("digits2") 
32 //               //sets another title for Digitis (input) branch
33 //  root [3] cl->SetRecPointsBranch("recp2")  
34 //               //sets another title four output branches
35 //  root [4] cl->SetTowerLocalMaxCut(0.03)  
36 //               //set clusterization parameters
37 //  root [5] cl->ExecuteTask("deb all time")  
38 //               //once more finds RecPoints options are 
39 //               // deb - print number of found rec points
40 //               // deb all - print number of found RecPoints and some their characteristics 
41 //               // time - print benchmarking results
42
43 // --- ROOT system ---
44 #include <TMath.h> 
45 #include <TMinuit.h>
46 #include <TTree.h> 
47 #include <TBenchmark.h>
48 #include <TBrowser.h>
49 #include <TROOT.h>
50 #include <TClonesArray.h>
51
52 // --- Standard library ---
53 #include <cassert>
54
55 // --- AliRoot header files ---
56 #include "AliLog.h"
57 #include "AliEMCALClusterizerNxN.h"
58 #include "AliEMCALRecPoint.h"
59 #include "AliEMCALDigit.h"
60 #include "AliEMCALGeometry.h"
61 #include "AliCaloCalibPedestal.h"
62 #include "AliEMCALCalibData.h"
63 #include "AliESDCaloCluster.h"
64 #include "AliEMCALUnfolding.h"
65
66 ClassImp(AliEMCALClusterizerNxN)
67
68 //____________________________________________________________________________
69 AliEMCALClusterizerNxN::AliEMCALClusterizerNxN()
70 : AliEMCALClusterizer(), fNRowDiff(1), fNColDiff(1)
71 {
72   // ctor with the indication of the file where header Tree and digits Tree are stored
73 }
74
75 //____________________________________________________________________________
76 AliEMCALClusterizerNxN::AliEMCALClusterizerNxN(AliEMCALGeometry* geometry)
77   : AliEMCALClusterizer(geometry), fNRowDiff(1), fNColDiff(1)
78 {
79   // ctor with the indication of the file where header Tree and digits Tree are stored
80   // use this contructor to avoid usage of Init() which uses runloader
81   // change needed by HLT - MP
82
83 }
84
85 //____________________________________________________________________________
86 AliEMCALClusterizerNxN::AliEMCALClusterizerNxN(AliEMCALGeometry* geometry, AliEMCALCalibData * calib, AliCaloCalibPedestal * caloped)
87 : AliEMCALClusterizer(geometry, calib, caloped), fNRowDiff(1), fNColDiff(1)
88 {
89   // ctor, geometry and calibration are initialized elsewhere.
90 }
91
92 //____________________________________________________________________________
93 AliEMCALClusterizerNxN::~AliEMCALClusterizerNxN()
94 {
95   // dtor
96 }
97
98 //____________________________________________________________________________
99 void AliEMCALClusterizerNxN::Digits2Clusters(Option_t * option)
100 {
101   // Steering method to perform clusterization for the current event 
102   // in AliEMCALLoader
103   
104   if(strstr(option,"tim"))
105     gBenchmark->Start("EMCALClusterizer"); 
106   
107   if(strstr(option,"print"))
108     Print("") ; 
109   
110   //Get calibration parameters from file or digitizer default values.
111   GetCalibrationParameters() ;
112   
113   //Get dead channel map from file or digitizer default values.
114   GetCaloCalibPedestal() ;
115         
116   fNumberOfECAClusters = 0;
117   
118   MakeClusters() ;  //only the real clusters
119   
120   if(fToUnfold){
121     fClusterUnfolding->SetInput(fNumberOfECAClusters,fRecPoints,fDigitsArr);
122     fClusterUnfolding->MakeUnfolding();
123   }
124   
125   //Evaluate position, dispersion and other RecPoint properties for EC section 
126   Int_t index ;
127   for(index = 0; index < fRecPoints->GetEntries(); index++) 
128   { 
129     AliEMCALRecPoint * rp = dynamic_cast<AliEMCALRecPoint *>(fRecPoints->At(index));
130     if(rp){
131       rp->EvalAll(fECAW0,fDigitsArr,fgkIsInputCalibrated) ;
132       AliDebug(5, Form("MAX INDEX %d ", rp->GetMaximalEnergyIndex()));
133       //For each rec.point set the distance to the nearest bad crystal
134       rp->EvalDistanceToBadChannels(fCaloPed);
135     }
136   }
137   
138   fRecPoints->Sort() ;
139   
140   for(index = 0; index < fRecPoints->GetEntries(); index++) 
141   {
142     AliEMCALRecPoint * rp = dynamic_cast<AliEMCALRecPoint *>(fRecPoints->At(index));
143     if(rp){
144       rp->SetIndexInList(index) ;
145       rp->Print();
146     }
147     else AliFatal("RecPoint NULL!!");
148   }
149   
150   fTreeR->Fill();
151   
152   if(strstr(option,"deb") || strstr(option,"all"))  
153     PrintRecPoints(option) ;
154   
155   AliDebug(1,Form("EMCAL Clusterizer found %d Rec Points",fRecPoints->GetEntriesFast()));
156   
157   fRecPoints->Delete();
158   
159   if(strstr(option,"tim")){
160     gBenchmark->Stop("EMCALClusterizer");
161     printf("Exec took %f seconds for Clusterizing", 
162            gBenchmark->GetCpuTime("EMCALClusterizer"));
163   }    
164 }
165
166 //____________________________________________________________________________
167 Int_t AliEMCALClusterizerNxN::AreNeighbours(AliEMCALDigit * d1, AliEMCALDigit * d2, Bool_t & shared) const
168 {
169   // Gives the neighbourness of two digits = 0 are not neighbour ; continue searching 
170   //                                       = 1 are neighbour
171   //                                       = 2 is in different SM; continue searching 
172   // In case it is in different SM, but same phi rack, check if neigbours at eta=0
173   // neighbours are defined as digits having at least a common side 
174   // The order of d1 and d2 is important: first (d1) should be a digit already in a cluster 
175   //                                      which is compared to a digit (d2)  not yet in a cluster  
176   
177   static Int_t nSupMod1=0, nModule1=0, nIphi1=0, nIeta1=0, iphi1=0, ieta1=0;
178   static Int_t nSupMod2=0, nModule2=0, nIphi2=0, nIeta2=0, iphi2=0, ieta2=0;
179   static Int_t rowdiff=0, coldiff=0;
180   
181   shared = kFALSE;
182   
183   fGeom->GetCellIndex(d1->GetId(), nSupMod1,nModule1,nIphi1,nIeta1);
184   fGeom->GetCellIndex(d2->GetId(), nSupMod2,nModule2,nIphi2,nIeta2);
185   fGeom->GetCellPhiEtaIndexInSModule(nSupMod1,nModule1,nIphi1,nIeta1, iphi1,ieta1);
186   fGeom->GetCellPhiEtaIndexInSModule(nSupMod2,nModule2,nIphi2,nIeta2, iphi2,ieta2);
187   
188   //If different SM, check if they are in the same phi, then consider cells close to eta=0 as neighbours; May 2010
189   if(nSupMod1 != nSupMod2 ) 
190     {
191       //Check if the 2 SM are in the same PHI position (0,1), (2,3), ...
192       Float_t smPhi1 = fGeom->GetEMCGeometry()->GetPhiCenterOfSM(nSupMod1);
193       Float_t smPhi2 = fGeom->GetEMCGeometry()->GetPhiCenterOfSM(nSupMod2);
194       
195       if(!TMath::AreEqualAbs(smPhi1, smPhi2, 1e-3)) return 2; //Not phi rack equal, not neighbours
196       
197       // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
198       // C Side impair SM, nSupMod%2=1; A side pair SM nSupMod%2=0
199       if(nSupMod1%2) ieta1+=AliEMCALGeoParams::fgkEMCALCols;
200       else           ieta2+=AliEMCALGeoParams::fgkEMCALCols;
201       
202       shared = kTRUE; // maybe a shared cluster, we know this later, set it for the moment.
203       
204     }//Different SM, same phi
205   
206   rowdiff = TMath::Abs(iphi1 - iphi2);  
207   coldiff = TMath::Abs(ieta1 - ieta2) ;  
208   
209   // neighbours +-1 in col and row
210   if ( TMath::Abs(coldiff) <= fNColDiff && TMath::Abs(rowdiff) <= fNRowDiff)
211     {
212       
213       AliDebug(9, Form("AliEMCALClusterizerNxN::AreNeighbours(): id1=%d, (row %d, col %d) ; id2=%d, (row %d, col %d), shared %d \n",
214                        d1->GetId(), iphi1,ieta1, d2->GetId(), iphi2,ieta2, shared));
215       
216       return 1;
217     }//Neighbours
218   else 
219     {
220       AliDebug(9, Form("NOT AliEMCALClusterizerNxN::AreNeighbours(): id1=%d, (row %d, col %d) ; id2=%d, (row %d, col %d), shared %d \n",
221                        d1->GetId(), iphi1,ieta1, d2->GetId(), iphi2,ieta2, shared));
222       shared = kFALSE;
223       return 2 ; 
224     }//Not neighbours
225 }
226
227 //____________________________________________________________________________
228 void AliEMCALClusterizerNxN::MakeClusters()
229 {
230   // Make clusters
231   
232   if (fGeom==0) 
233     AliFatal("Did not get geometry from EMCALLoader");
234   
235   fRecPoints->Clear();
236   
237   // Set up TObjArray with pointers to digits to work on 
238   TObjArray digitsC;
239   TIter nextdigit(fDigitsArr);
240   AliEMCALDigit *digit = 0;
241   while ( (digit = dynamic_cast<AliEMCALDigit*>(nextdigit())) ) {
242     Float_t dEnergyCalibrated = Calibrate(digit->GetAmplitude(), digit->GetTime(),digit->GetId());
243     digit->SetCalibAmp(dEnergyCalibrated);
244     digitsC.AddLast(digit);
245   }
246   
247   TIter nextdigitC(&digitsC);
248   
249   AliDebug(1,Form("MakeClusters: Number of digits %d  -> (e %f)\n",
250                   fDigitsArr->GetEntries(),fMinECut));
251   
252   Bool_t bDone = kFALSE;
253   while ( bDone != kTRUE )
254   {
255     //first sort the digits:
256     Int_t iMaxEnergyDigit = -1;
257     Float_t dMaxEnergyDigit = -1;
258     AliEMCALDigit *pMaxEnergyDigit = 0;
259     nextdigitC.Reset();
260     while ( (digit = static_cast<AliEMCALDigit *>(nextdigitC())) ) 
261     { // scan over the list of digitsC
262       Float_t dEnergyCalibrated = digit->GetCalibAmp();
263
264       if(fGeom->CheckAbsCellId(digit->GetId()) && dEnergyCalibrated > 0.0) // no threshold!
265       {
266         if (dEnergyCalibrated > dMaxEnergyDigit) 
267         {
268           dMaxEnergyDigit = dEnergyCalibrated;
269           iMaxEnergyDigit = digit->GetId();
270           pMaxEnergyDigit = digit;
271         }
272       }
273     }
274     if (iMaxEnergyDigit < 0 || digitsC.GetEntries() <= 0) 
275     {
276       bDone = kTRUE;
277       continue;
278     }
279     
280     AliDebug (2, Form("Max digit found: %1.5f AbsId: %d", dMaxEnergyDigit, iMaxEnergyDigit));
281     
282     // keep the candidate digits in a list
283     TList clusterDigitList;
284     clusterDigitList.SetOwner(kFALSE);
285     clusterDigitList.AddLast(pMaxEnergyDigit);   
286     
287     Double_t clusterCandidateEnergy = dMaxEnergyDigit;
288     
289     // now loop over the rest of the digits and cluster into NxN cluster 
290     // we do not actually cluster yet: we keep them in the list clusterDigitList
291     nextdigitC.Reset();
292     while ( (digit = dynamic_cast<AliEMCALDigit *>(nextdigitC())) ) 
293     { // scan over the list of digitsC
294       if (digit == pMaxEnergyDigit) continue;
295       Float_t dEnergyCalibrated = digit->GetCalibAmp();
296       AliDebug(5, Form("-> Digit ENERGY: %1.5f", dEnergyCalibrated));
297       if(fGeom->CheckAbsCellId(digit->GetId()) && dEnergyCalibrated > 0.0  )
298       {
299         Float_t time = pMaxEnergyDigit->GetTime(); //Time or TimeR?
300         if(TMath::Abs(time - digit->GetTime()) > fTimeCut ) continue; //Time or TimeR?
301         Bool_t shared = kFALSE; //cluster shared by 2 SuperModules?
302         if (AreNeighbours(pMaxEnergyDigit, digit, shared) == 1) // call (digit,digitN) in THAT order !!!!! 
303         {      
304           clusterDigitList.AddLast(digit) ;
305           clusterCandidateEnergy += dEnergyCalibrated;
306         }
307       }
308     }// loop over the next digits
309     
310     // start a cluster here only if a cluster energy is larger than clustering threshold
311     AliDebug(5, Form("Clusterization threshold is %f MeV", fECAClusteringThreshold));
312     if (clusterCandidateEnergy > fECAClusteringThreshold)
313     {
314       if(fNumberOfECAClusters >= fRecPoints->GetSize()) 
315         fRecPoints->Expand(2*fNumberOfECAClusters+1) ;
316       
317       AliEMCALRecPoint *recPoint = new  AliEMCALRecPoint("") ; 
318       fRecPoints->AddAt(recPoint, fNumberOfECAClusters) ;
319       recPoint = dynamic_cast<AliEMCALRecPoint *>(fRecPoints->At(fNumberOfECAClusters)) ; 
320       if(recPoint){
321         fNumberOfECAClusters++ ;       
322         recPoint->SetClusterType(AliVCluster::kEMCALClusterv1);
323         
324         AliDebug(9, Form("Number of cells per cluster (max is 9!): %d", clusterDigitList.GetEntries()));
325         for (Int_t idig = 0; idig < clusterDigitList.GetEntries(); idig++)
326         {
327           digit = (AliEMCALDigit*)clusterDigitList.At(idig);
328           Float_t dEnergyCalibrated = digit->GetCalibAmp();
329           AliDebug(5, Form(" Adding digit %d", digit->GetId()));
330           // note: this way the sharing info is lost!
331           recPoint->AddDigit(*digit, dEnergyCalibrated, kFALSE) ; //Time or TimeR?
332           digitsC.Remove(digit);                  
333         }
334       }// recpoint
335     }
336     else
337     {
338       // we do not want to start clustering in the same spot!
339       // but in this case we may NOT reuse this seed for another cluster!
340       // need a better bookeeping?
341       digitsC.Remove(pMaxEnergyDigit);
342     }
343     
344     AliDebug (2, Form("Number of digits left: %d", digitsC.GetEntries()));      
345   } // while ! done 
346   
347   AliDebug(1,Form("total no of clusters %d from %d digits",fNumberOfECAClusters,fDigitsArr->GetEntriesFast())); 
348 }
349