]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALRecPoint.cxx
remove static from variables which are initialized
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALRecPoint.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 /* $Id$ */
16 //_________________________________________________________________________
17 //  Reconstructed Points for the EMCAL
18 //  A RecPoint is a cluster of digits
19 //  
20 //  
21 //*-- Author: Yves Schutz (SUBATECH)
22 //*-- Author: Dmitri Peressounko (RRC KI & SUBATECH)
23 //*-- Author: Heather Gray (LBL) merged AliEMCALRecPoint and AliEMCALTowerRecPoint 02/04
24
25 // --- ROOT system ---
26 #include "TPad.h"
27 #include "TGraph.h"
28 #include "TPaveText.h"
29 #include "TClonesArray.h"
30 #include "TMath.h"
31 #include "TGeoMatrix.h"
32 #include "TGeoManager.h"
33 #include "TGeoPhysicalNode.h"
34 #include "TRandom.h"
35
36 // --- Standard library ---
37 #include <Riostream.h>
38
39 // --- AliRoot header files ---
40 //#include "AliGenerator.h"
41 class AliGenerator;
42 class AliEMCAL;
43 #include "AliLog.h"
44 #include "AliGeomManager.h"
45 #include "AliEMCALGeometry.h"
46 #include "AliEMCALHit.h"
47 #include "AliEMCALDigit.h"
48 #include "AliEMCALRecPoint.h"
49 #include "AliCaloCalibPedestal.h"
50 #include "AliEMCALGeoParams.h"
51
52 ClassImp(AliEMCALRecPoint)
53
54 //____________________________________________________________________________
55 AliEMCALRecPoint::AliEMCALRecPoint()
56   : AliCluster(), fGeomPtr(0),
57     fAmp(0), fIndexInList(-1), //to be set when the point is already stored
58     fGlobPos(0,0,0),fLocPos(0,0,0), 
59     fMaxDigit(100), fMulDigit(0), fMaxTrack(200),
60     fMulTrack(0), fDigitsList(0), fTracksList(0),
61     fClusterType(-1), fCoreEnergy(0), fDispersion(0),
62     fEnergyList(0), fTimeList(0), fAbsIdList(0),
63     fTime(0.), fNExMax(0), fCoreRadius(10),  //HG check this 
64     fDETracksList(0), fMulParent(0), fMaxParent(0),
65     fParentsList(0), fDEParentsList(0), fSuperModuleNumber(0),
66     fDigitIndMax(-1), fDistToBadTower(-1), fSharedCluster(kFALSE)
67 {
68   // ctor
69   fGeomPtr = AliEMCALGeometry::GetInstance();
70   
71   fLambda[0] = 0;
72   fLambda[1] = 0;
73
74 }
75
76 //____________________________________________________________________________
77 AliEMCALRecPoint::AliEMCALRecPoint(const char *) 
78   : AliCluster(), fGeomPtr(0),
79     fAmp(0), fIndexInList(-1), //to be set when the point is already stored
80     fGlobPos(0,0,0), fLocPos(0,0,0),
81     fMaxDigit(100), fMulDigit(0), fMaxTrack(1000), fMulTrack(0),
82     fDigitsList(new Int_t[fMaxDigit]), fTracksList(new Int_t[fMaxTrack]),
83     fClusterType(-1), fCoreEnergy(0), fDispersion(0),
84     fEnergyList(new Float_t[fMaxDigit]), fTimeList(new Float_t[fMaxDigit]), 
85     fAbsIdList(new Int_t[fMaxDigit]), fTime(-1.), fNExMax(0), fCoreRadius(10),
86     fDETracksList(new Float_t[fMaxTrack]), fMulParent(0), fMaxParent(1000),
87     fParentsList(new Int_t[fMaxParent]), fDEParentsList(new Float_t[fMaxParent]),
88     fSuperModuleNumber(0), fDigitIndMax(-1), fDistToBadTower(-1),fSharedCluster(kFALSE)
89 {
90   // ctor
91   for (Int_t i = 0; i < fMaxTrack; i++)
92     fDETracksList[i] = 0;
93   for (Int_t i = 0; i < fMaxParent; i++) {
94     fParentsList[i] = -1;
95     fDEParentsList[i] = 0;
96   }
97
98   fGeomPtr = AliEMCALGeometry::GetInstance();
99   fLambda[0] = 0;
100   fLambda[1] = 0;
101 }
102
103 //____________________________________________________________________________
104 AliEMCALRecPoint::AliEMCALRecPoint(const AliEMCALRecPoint & rp) 
105   : AliCluster(rp), fGeomPtr(rp.fGeomPtr),
106     fAmp(rp.fAmp), fIndexInList(rp.fIndexInList),
107     fGlobPos(rp.fGlobPos),fLocPos(rp.fLocPos),
108     fMaxDigit(rp.fMaxDigit), fMulDigit(rp.fMulDigit),
109     fMaxTrack(rp.fMaxTrack), fMulTrack(rp.fMaxTrack),
110     fDigitsList(new Int_t[rp.fMaxDigit]), fTracksList(new Int_t[rp.fMaxTrack]),
111     fClusterType(rp.fClusterType), fCoreEnergy(rp.fCoreEnergy), 
112     fDispersion(rp.fDispersion),
113     fEnergyList(new Float_t[rp.fMaxDigit]), fTimeList(new Float_t[rp.fMaxDigit]), 
114     fAbsIdList(new Int_t[rp.fMaxDigit]), fTime(rp.fTime), fNExMax(rp.fNExMax),fCoreRadius(rp.fCoreRadius),
115     fDETracksList(new Float_t[rp.fMaxTrack]), fMulParent(rp.fMulParent), 
116     fMaxParent(rp.fMaxParent), fParentsList(new Int_t[rp.fMaxParent]), 
117     fDEParentsList(new Float_t[rp.fMaxParent]),
118     fSuperModuleNumber(rp.fSuperModuleNumber), fDigitIndMax(rp.fDigitIndMax), 
119     fDistToBadTower(rp.fDistToBadTower), fSharedCluster(rp.fSharedCluster)
120 {
121   //copy ctor
122   fLambda[0] = rp.fLambda[0];
123   fLambda[1] = rp.fLambda[1];
124
125   for(Int_t i = 0; i < rp.fMulDigit; i++) {
126     fEnergyList[i] = rp.fEnergyList[i];
127     fTimeList[i] = rp.fTimeList[i];
128     fAbsIdList[i] = rp.fAbsIdList[i];
129   }
130
131   for(Int_t i = 0; i < rp.fMulTrack; i++) fDETracksList[i] = rp.fDETracksList[i];
132
133   for(Int_t i = 0; i < rp.fMulParent; i++) {
134     fParentsList[i] = rp.fParentsList[i];
135     fDEParentsList[i] = rp.fDEParentsList[i];
136   }
137
138 }
139 //____________________________________________________________________________
140 AliEMCALRecPoint::~AliEMCALRecPoint()
141 {
142   // dtor
143   if ( fEnergyList )
144     delete[] fEnergyList ; 
145   if ( fTimeList )
146     delete[] fTimeList ; 
147   if ( fAbsIdList )
148     delete[] fAbsIdList ; 
149    if ( fDETracksList)
150     delete[] fDETracksList;
151    if ( fParentsList)
152     delete[] fParentsList;
153    if ( fDEParentsList)
154     delete[] fDEParentsList;
155         
156    delete [] fDigitsList ;
157    delete [] fTracksList ;
158 }
159
160 //____________________________________________________________________________
161 AliEMCALRecPoint& AliEMCALRecPoint::operator= (const AliEMCALRecPoint &rp)
162 {
163   // assignment operator
164
165   if(&rp == this) return *this;
166
167   fGeomPtr = rp.fGeomPtr;
168   fAmp = rp.fAmp;
169   fIndexInList = rp.fIndexInList;
170   fGlobPos = rp.fGlobPos;
171   fLocPos  = rp.fLocPos;
172   fMaxDigit = rp.fMaxDigit;
173   fMulDigit = rp.fMulDigit;
174   fMaxTrack = rp.fMaxTrack;
175   fMulTrack = rp.fMaxTrack;
176   for(Int_t i = 0; i<fMaxDigit; i++) fDigitsList[i] = rp.fDigitsList[i];
177   for(Int_t i = 0; i<fMaxTrack; i++) fTracksList[i] = rp.fTracksList[i];
178   fClusterType = rp.fClusterType;
179   fCoreEnergy = rp.fCoreEnergy; 
180   fDispersion = rp.fDispersion;
181   for(Int_t i = 0; i<fMaxDigit; i++) {
182     fEnergyList[i] = rp.fEnergyList[i];
183     fTimeList[i] = rp.fTimeList[i]; 
184     fAbsIdList[i] = rp.fAbsIdList[i];
185   }
186   fTime = rp.fTime;
187   fNExMax = rp.fNExMax;
188   fCoreRadius = rp.fCoreRadius;
189   for(Int_t i = 0; i < fMaxTrack; i++) fDETracksList[i] = rp.fDETracksList[i];
190   fMulParent = rp.fMulParent;
191   fMaxParent = rp.fMaxParent;
192   for(Int_t i = 0; i < fMaxParent; i++) {
193     fParentsList[i] = rp.fParentsList[i]; 
194     fDEParentsList[i] = rp.fDEParentsList[i];
195   }
196   fSuperModuleNumber = rp.fSuperModuleNumber;
197   fDigitIndMax = rp.fDigitIndMax;
198
199   fLambda[0] = rp.fLambda[0];
200   fLambda[1] = rp.fLambda[1];
201         
202   fDistToBadTower = rp.fDistToBadTower;
203   fSharedCluster  = rp.fSharedCluster;
204         
205   return *this;
206
207 }
208
209 //____________________________________________________________________________
210 void AliEMCALRecPoint::AddDigit(AliEMCALDigit & digit, Float_t Energy, Bool_t shared)
211 {
212   // Adds a digit to the RecPoint
213   // and accumulates the total amplitude and the multiplicity 
214   
215   if(fEnergyList == 0)
216     fEnergyList =  new Float_t[fMaxDigit]; 
217   if(fTimeList == 0)
218     fTimeList =  new Float_t[fMaxDigit]; 
219   if(fAbsIdList == 0) {
220     fAbsIdList =  new Int_t[fMaxDigit];
221   }
222
223   if ( fMulDigit >= fMaxDigit ) { // increase the size of the lists 
224     fMaxDigit*=2 ; 
225     Int_t * tempo = new Int_t[fMaxDigit]; 
226     Float_t * tempoE =  new Float_t[fMaxDigit];
227     Float_t * tempoT =  new Float_t[fMaxDigit];
228     Int_t * tempoId = new Int_t[fMaxDigit]; 
229
230     Int_t index ;     
231     for ( index = 0 ; index < fMulDigit ; index++ ){
232       tempo[index]   = fDigitsList[index] ;
233       tempoE[index]  = fEnergyList[index] ; 
234       tempoT[index]  = fTimeList[index] ; 
235       tempoId[index] = fAbsIdList[index] ; 
236     }
237     
238     delete [] fDigitsList ;
239     delete [] fEnergyList ;
240     delete [] fTimeList ;
241     delete [] fAbsIdList ;
242
243     fDigitsList = tempo;
244     fEnergyList = tempoE; 
245     fTimeList = tempoT;
246     fAbsIdList = tempoId;
247   } // if
248   
249   fDigitsList[fMulDigit]   = digit.GetIndexInList()  ; 
250   fEnergyList[fMulDigit]   = Energy ;
251   fTimeList[fMulDigit]     = digit.GetTimeR() ;
252   fAbsIdList[fMulDigit]    = digit.GetId();
253   fMulDigit++ ; 
254   fAmp += Energy ; 
255         
256   if(shared) fSharedCluster = kTRUE;
257         
258   //GCB, May-2010, setting moved to EvalAll method, set the super module number for the largest energy digit position. 
259   //JLK 10-Oct-2007 this hasn't been filled before because it was in
260   //the wrong place in previous versions.
261   //Now we evaluate it only if the supermodulenumber for this recpoint
262   //has not yet been set (or is the 0th one)
263   //if(fSuperModuleNumber == 0)
264     //fSuperModuleNumber = fGeomPtr->GetSuperModuleNumber(digit.GetId());
265
266 }
267 //____________________________________________________________________________
268 Bool_t AliEMCALRecPoint::AreNeighbours(AliEMCALDigit * digit1, AliEMCALDigit * digit2 ) const
269 {
270   // Tells if (true) or not (false) two digits are neighbours
271   // A neighbour is defined as being two digits which share a corner
272   // ONLY USED IN CASE OF UNFOLDING 
273         
274   Bool_t areNeighbours = kFALSE ;
275   Int_t nSupMod=0, nModule=0, nIphi=0, nIeta=0;
276   Int_t nSupMod1=0, nModule1=0, nIphi1=0, nIeta1=0;
277   Int_t relid1[2] , relid2[2] ; // ieta, iphi
278   Int_t rowdiff=0, coldiff=0;
279
280   areNeighbours = kFALSE ;
281
282   fGeomPtr->GetCellIndex(digit1->GetId(), nSupMod,nModule,nIphi,nIeta);
283   fGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, relid1[0],relid1[1]);
284
285   fGeomPtr->GetCellIndex(digit2->GetId(), nSupMod1,nModule1,nIphi1,nIeta1);
286   fGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod1,nModule1,nIphi1,nIeta1, relid2[0],relid2[1]);
287   
288   // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2-1
289   // C Side impair SM, nSupMod%2=1; A side pair SM nSupMod%2=0
290   if(fSharedCluster){
291     if(nSupMod1%2) relid1[1]+=AliEMCALGeoParams::fgkEMCALCols;
292     else           relid2[1]+=AliEMCALGeoParams::fgkEMCALCols;
293   }
294         
295   rowdiff = TMath::Abs( relid1[0] - relid2[0] ) ;  
296   coldiff = TMath::Abs( relid1[1] - relid2[1] ) ;  
297
298   if (( coldiff <= 1 )  && ( rowdiff <= 1 ) && (coldiff + rowdiff > 0)) 
299   areNeighbours = kTRUE ;
300   
301   return areNeighbours;
302 }
303
304 //____________________________________________________________________________
305 Int_t AliEMCALRecPoint::Compare(const TObject * obj) const
306 {
307   // Compares two RecPoints according to their position in the EMCAL modules
308
309   Float_t delta = 1 ; //Width of "Sorting row". 
310         
311   Int_t rv = 2 ; 
312
313   AliEMCALRecPoint * clu = (AliEMCALRecPoint *)obj ; 
314
315   TVector3 locpos1; 
316   GetLocalPosition(locpos1);
317   TVector3 locpos2;  
318   clu->GetLocalPosition(locpos2);  
319
320   Int_t rowdif = (Int_t)(TMath::Ceil(locpos1.X()/delta)-TMath::Ceil(locpos2.X()/delta)) ;
321   if (rowdif> 0) 
322     rv = 1 ;
323   else if(rowdif < 0) 
324     rv = -1 ;
325   else if(locpos1.Y()>locpos2.Y()) 
326     rv = -1 ;
327   else 
328     rv = 1 ; 
329
330   return rv ; 
331 }
332
333 // GCB, May-2010, Method not used, just comment it but remove?
334 //____________________________________________________________________________
335 //Int_t AliEMCALRecPoint::DistancetoPrimitive(Int_t px, Int_t py)
336 //{
337 //  // Compute distance from point px,py to  a AliEMCALRecPoint considered as a Tmarker
338 //  // Compute the closest distance of approach from point px,py to this marker.
339 //  // The distance is computed in pixels units.
340 //  // HG Still need to update -> Not sure what this should achieve
341 //
342 //  TVector3 pos(0.,0.,0.) ;
343 //  GetLocalPosition(pos) ;
344 //  Float_t x =  pos.X() ;
345 //  Float_t y =  pos.Y() ;
346 //  const Int_t kMaxDiff = 10;
347 //  Int_t pxm  = gPad->XtoAbsPixel(x);
348 //  Int_t pym  = gPad->YtoAbsPixel(y);
349 //  Int_t dist = (px-pxm)*(px-pxm) + (py-pym)*(py-pym);
350 //  
351 //  if (dist > kMaxDiff) return 9999;
352 //  return dist;
353 //}
354
355 //___________________________________________________________________________
356  void AliEMCALRecPoint::Draw(Option_t *option)
357  {
358    // Draw this AliEMCALRecPoint with its current attributes
359    
360    AppendPad(option);
361  }
362
363 // GCB, May-2010, Method not used, just comment it but remove?
364 //______________________________________________________________________________
365 //void AliEMCALRecPoint::ExecuteEvent(Int_t /*event*/, Int_t, Int_t)
366 //{
367 //  // Execute action corresponding to one event
368 //  // This member function is called when a AliEMCALRecPoint is clicked with the locator
369 //  //
370 //  // If Left button is clicked on AliEMCALRecPoint, the digits are switched on    
371 //  // and switched off when the mouse button is released.
372 //
373 //  //  static Int_t pxold, pyold;
374 //
375 //  /*  static TGraph *  digitgraph = 0 ;
376 //  static TPaveText* clustertext = 0 ;
377 //  
378 //  if (!gPad->IsEditable()) return;
379 //  
380 //  switch (event) {
381 //    
382 //    
383 //  case kButton1Down:{
384 //    AliEMCALDigit * digit ;
385 //
386 //    Int_t iDigit;
387 //    Int_t relid[2] ;
388 //  
389 //    const Int_t kMulDigit=AliEMCALRecPoint::GetDigitsMultiplicity() ;
390 //    Float_t * xi = new Float_t [kMulDigit] ; 
391 //    Float_t * zi = new Float_t [kMulDigit] ;
392 //    
393 //    for(iDigit = 0; iDigit < kMulDigit; iDigit++) {
394 //      Fatal("AliEMCALRecPoint::ExecuteEvent", " -> Something wrong with the code"); 
395 //      digit = 0 ; //dynamic_cast<AliEMCALDigit *>((fDigitsList)[iDigit]);
396 //      fGeomPtr->AbsToRelNumbering(digit->GetId(), relid) ;
397 //      fGeomPtr->PosInAlice(relid, xi[iDigit], zi[iDigit]) ;
398 //    }
399 //    
400 //    if (!digitgraph) {
401 //      digitgraph = new TGraph(fMulDigit,xi,zi);
402 //      digitgraph-> SetMarkerStyle(5) ; 
403 //      digitgraph-> SetMarkerSize(1.) ;
404 //      digitgraph-> SetMarkerColor(1) ;
405 //      digitgraph-> Draw("P") ;
406 //    }
407 //    if (!clustertext) {
408 //      
409 //      TVector3 pos(0.,0.,0.) ;
410 //      GetLocalPosition(pos) ;
411 //      clustertext = new TPaveText(pos.X()-10,pos.Z()+10,pos.X()+50,pos.Z()+35,"") ;
412 //      Text_t  line1[40] ;
413 //      Text_t  line2[40] ;
414 //      sprintf(line1,"Energy=%1.2f GeV",GetEnergy()) ;
415 //      sprintf(line2,"%d Digits",GetDigitsMultiplicity()) ;
416 //      clustertext ->AddText(line1) ;
417 //      clustertext ->AddText(line2) ;
418 //      clustertext ->Draw("");
419 //    }
420 //    gPad->Update() ; 
421 //    Print("") ;
422 //    delete[] xi ; 
423 //    delete[] zi ; 
424 //   }
425 //  
426 //break;
427 //  
428 //  case kButton1Up:
429 //    if (digitgraph) {
430 //      delete digitgraph  ;
431 //      digitgraph = 0 ;
432 //    }
433 //    if (clustertext) {
434 //      delete clustertext ;
435 //      clustertext = 0 ;
436 //    }
437 //    
438 //    break;
439 //    
440 //    }*/
441 //}
442
443 //____________________________________________________________________________
444 void AliEMCALRecPoint::EvalAll(Float_t logWeight,TClonesArray * digits) 
445 {
446   // Evaluates cluster parameters
447         
448   // First calculate the index of digit with maximum amplitude and get 
449   // the supermodule number where it sits.
450   fDigitIndMax       = GetMaximalEnergyIndex();
451   fSuperModuleNumber = fGeomPtr->GetSuperModuleNumber(GetAbsIdMaxDigit());
452   
453   //Evaluate global and local position
454   EvalGlobalPosition(logWeight, digits) ;
455   EvalLocalPosition(logWeight, digits) ;
456         
457   //Evaluate shower parameters
458   EvalElipsAxis(logWeight, digits) ;
459   EvalDispersion(logWeight, digits) ;
460
461   //EvalCoreEnergy(logWeight, digits);
462   EvalTime(digits) ;
463   EvalPrimaries(digits) ;
464   EvalParents(digits);
465         
466   //Called last because it sets the global position of the cluster?
467   EvalLocal2TrackingCSTransform();
468
469 }
470
471 //____________________________________________________________________________
472 void  AliEMCALRecPoint::EvalDispersion(Float_t logWeight, TClonesArray * digits)
473 {
474   // Calculates the dispersion of the shower at the origin of the RecPoint
475   // in cell units - Nov 16,2006
476
477   Double_t d = 0., wtot = 0., w = 0.;
478   Int_t iDigit=0, nstat=0;
479   AliEMCALDigit * digit=0;
480         
481   // Calculates the dispersion in cell units 
482   Double_t etai, phii, etaMean=0.0, phiMean=0.0; 
483   int nSupMod=0, nModule=0, nIphi=0, nIeta=0;
484   int iphi=0, ieta=0;
485   // Calculate mean values
486   for(iDigit=0; iDigit < fMulDigit; iDigit++) {
487     digit = (AliEMCALDigit *) digits->At(fDigitsList[iDigit])  ;
488
489     if (fAmp>0 && fEnergyList[iDigit]>0) {
490       fGeomPtr->GetCellIndex(digit->GetId(), nSupMod,nModule,nIphi,nIeta);
491       fGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
492         
493       // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
494       // C Side impair SM, nSupMod%2=1; A side pair SM nSupMod%2=0
495       if(fSharedCluster && nSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
496                 
497       etai=(Double_t)ieta;
498       phii=(Double_t)iphi;
499       w = TMath::Max(0.,logWeight+TMath::Log(fEnergyList[iDigit]/fAmp ) ) ;
500
501       if(w>0.0) {
502         phiMean += phii*w;
503         etaMean += etai*w;
504         wtot    += w;
505       }
506     }
507   }
508   if (wtot>0) {
509     phiMean /= wtot ;
510     etaMean /= wtot ;
511   } else AliError(Form("Wrong weight %f\n", wtot));
512
513   // Calculate dispersion
514   for(iDigit=0; iDigit < fMulDigit; iDigit++) {
515     digit = (AliEMCALDigit *) digits->At(fDigitsList[iDigit])  ;
516
517     if (fAmp>0 && fEnergyList[iDigit]>0) {
518       fGeomPtr->GetCellIndex(digit->GetId(), nSupMod,nModule,nIphi,nIeta);
519       fGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
520                 
521       // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
522       // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
523       if(fSharedCluster && nSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
524       
525       etai=(Double_t)ieta;
526       phii=(Double_t)iphi;
527       w = TMath::Max(0.,logWeight+TMath::Log(fEnergyList[iDigit]/fAmp ) ) ;
528
529       if(w>0.0) {
530         nstat++;
531         d += w*((etai-etaMean)*(etai-etaMean)+(phii-phiMean)*(phii-phiMean));
532       }
533     }
534   }
535   
536   if ( wtot > 0 && nstat>1) d /= wtot ;
537   else                      d = 0. ; 
538
539   fDispersion = TMath::Sqrt(d) ;
540   //printf("AliEMCALRecPoint::EvalDispersion() : Dispersion %f \n",fDispersion);
541 }
542
543 //____________________________________________________________________________
544 void AliEMCALRecPoint::EvalDistanceToBadChannels(AliCaloCalibPedestal* caloped)
545 {
546         //For each EMC rec. point set the distance to the nearest bad channel.
547         //AliInfo(Form("%d bad channel(s) found.\n", caloped->GetDeadTowerCount()));
548   //It is done in cell units and not in global or local position as before (Sept 2010)
549         
550         if(!caloped->GetDeadTowerCount()) return;
551                 
552         //Get channels map of the supermodule where the cluster is.
553         TH2D* hMap  = caloped->GetDeadMap(fSuperModuleNumber);
554         
555   Int_t dRrow, dReta;   
556         Float_t  minDist = 10000.;
557         Float_t  dist    = 0.;
558   Int_t nSupMod, nModule;
559   Int_t nIphi, nIeta;
560   Int_t iphi, ieta;
561   fDigitIndMax  = GetMaximalEnergyIndex();
562   fGeomPtr->GetCellIndex(fAbsIdList[fDigitIndMax], nSupMod,nModule,nIphi,nIeta);
563   fGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
564
565   //    TVector3 dR;    
566   //    TVector3 cellpos;
567   //    Float_t  minDist = 100000;
568   //    Float_t  dist    = 0;
569   //    Int_t    absId   = -1;  
570   
571   //Loop on tower status map 
572         for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
573                 for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
574                         //Check if tower is bad.
575                         if(hMap->GetBinContent(icol,irow)==AliCaloCalibPedestal::kAlive) continue;
576       //printf("AliEMCALRecPoint::EvalDistanceToBadChannels() - Bad channel in SM %d, col %d, row %d\n",iSM,icol, irow);
577
578       dRrow=TMath::Abs(irow-iphi);
579       dReta=TMath::Abs(icol-ieta);
580       dist=TMath::Sqrt(dRrow*dRrow+dReta*dReta);
581                         if(dist < minDist) minDist = dist;
582       
583       //                        //Tower is bad, get the absId of the index.
584       //                        absId = fGeomPtr->GetAbsCellIdFromCellIndexes(fSuperModuleNumber, irow, icol); 
585       //                        
586       //                        //Get the position of this tower.
587       //                        
588       //                        //Calculate the distance in local coordinates
589       //                        //fGeomPtr->RelPosCellInSModule(absId,cellpos);
590       //                        //Calculate distance between this tower and cluster, set if is smaller than previous.
591       //                        //dR = cellpos-fLocPos;
592       //                        
593       //                        //Calculate the distance in global coordinates
594       //                        fGeomPtr->GetGlobal(absId,cellpos);
595       //                        //Calculate distance between this tower and cluster, set if it is smaller than previous.
596       //                        dR = cellpos-fGlobPos;
597       //                        
598       //                        dist = dR.Mag();
599       //                        if(dist < minDist) minDist = dist;
600       
601                 }
602         }
603   
604         //In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
605         if (fSharedCluster) {
606                 TH2D* hMap2 = 0;
607                 Int_t nSupMod2 = -1;
608         
609                 //The only possible combinations are (0,1), (2,3) ... (10,11)
610                 if(fSuperModuleNumber%2) nSupMod2 = fSuperModuleNumber-1;
611                 else                     nSupMod2 = fSuperModuleNumber+1;
612                 hMap2  = caloped->GetDeadMap(nSupMod2);
613     
614                 //Loop on tower status map of second super module
615                 for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){
616                         for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){
617                                 //Check if tower is bad.
618                                 if(hMap2->GetBinContent(icol,irow)==AliCaloCalibPedestal::kAlive) continue;
619                                 //printf("AliEMCALRecPoint::EvalDistanceToBadChannels() - Bad channel in SM %d, col %d, row %d\n",iSM,icol, irow);
620         
621         dRrow=TMath::Abs(irow-iphi);
622
623         if(fSuperModuleNumber%2) {
624                                   dReta=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+ieta));
625                                 }
626         else {
627           dReta=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-ieta);
628                                 }                    
629         
630                                 dist=TMath::Sqrt(dRrow*dRrow+dReta*dReta);
631         if(dist < minDist) minDist = dist;        
632         
633 //                              
634 //                              //Tower is bad, get the absId of the index.
635 //                              absId = fGeomPtr->GetAbsCellIdFromCellIndexes(nSupMod2, irow, icol); 
636 //                              
637 //                              //Get the position of this tower.
638 //                              
639 //                              //Calculate the distance in global coordinates
640 //                              fGeomPtr->GetGlobal(absId,cellpos);
641 //                              //Calculate distance between this tower and cluster, set if it is smaller than previous.
642 //                              dR = cellpos-fGlobPos;
643 //                              
644 //                              dist = dR.Mag();
645 //                              if(dist < minDist) minDist = dist;
646                         }
647                 }
648         
649         }// shared cluster in 2 SuperModules
650                 
651         fDistToBadTower = minDist;
652         //printf("AliEMCALRecPoint::EvalDistanceToBadChannel() - Distance to Bad is %f cm, shared cluster? %d \n",fDistToBadTower,fSharedCluster);
653 }
654
655
656 //____________________________________________________________________________
657 void AliEMCALRecPoint::EvalLocalPosition(Float_t logWeight, TClonesArray * digits)
658 {
659         // Calculates the center of gravity in the local EMCAL-module coordinates 
660         //  Info("Print", " logWeight %f : cluster energy %f ", logWeight, fAmp); // for testing
661                 
662         AliEMCALDigit * digit=0;
663         Int_t i=0, nstat=0;
664         
665         Double_t dist  = TmaxInCm(Double_t(fAmp));
666         //Int_t idMax = GetAbsIdMaxDigit();// idMax is not used at all in RelPosCellInSModule, why use it?
667         
668         Double_t clXYZ[3]={0.,0.,0.}, clRmsXYZ[3]={0.,0.,0.}, xyzi[3], wtot=0., w=0.;
669         
670         //printf(" dist : %f  e : %f \n", dist, fAmp);
671         for(Int_t iDigit=0; iDigit<fMulDigit; iDigit++) {
672                 digit = dynamic_cast<AliEMCALDigit *>(digits->At(fDigitsList[iDigit])) ;
673
674     if(!digit) {
675       AliError("No Digit!!");
676       continue;
677     }
678     
679                 //fGeomPtr->RelPosCellInSModule(digit->GetId(), idMax, dist, xyzi[0], xyzi[1], xyzi[2]);
680                 fGeomPtr->RelPosCellInSModule(digit->GetId(), dist, xyzi[0], xyzi[1], xyzi[2]);
681                 
682                 //Temporal patch, due to mapping problem, need to swap "y" in one of the 2 SM, although no effect in position calculation. GCB 05/2010
683                 if(fSharedCluster && fSuperModuleNumber != fGeomPtr->GetSuperModuleNumber(digit->GetId())) xyzi[1]*=-1;
684                 
685                 //printf("EvalLocalPosition Cell:  Id %i, SM %i : dist %f Local x,y,z %f %f %f \n", 
686                 //              digit->GetId(), fGeomPtr->GetSuperModuleNumber(digit->GetId()), dist, xyzi[0], xyzi[1], xyzi[2]);
687                 
688                 if(logWeight > 0.0)  w = TMath::Max( 0., logWeight + TMath::Log( fEnergyList[iDigit] / fAmp ));
689                 else  w = fEnergyList[iDigit]; // just energy
690                 
691                 if(w>0.0) {
692                         wtot += w ;
693                         nstat++;
694                         for(i=0; i<3; i++ ) {
695                                 clXYZ[i]    += (w*xyzi[i]);
696                                 clRmsXYZ[i] += (w*xyzi[i]*xyzi[i]);
697                         }
698                 }
699         }
700         //  cout << " wtot " << wtot << endl;
701         if ( wtot > 0 ) { 
702                 //    xRMS   = TMath::Sqrt(x2m - xMean*xMean);
703                 for(i=0; i<3; i++ ) {
704                         clXYZ[i] /= wtot;
705                         if(nstat>1) {
706                                 clRmsXYZ[i] /= (wtot*wtot);  
707                                 clRmsXYZ[i]  =  clRmsXYZ[i] - clXYZ[i]*clXYZ[i];
708                                 if(clRmsXYZ[i] > 0.0) {
709                                         clRmsXYZ[i] =  TMath::Sqrt(clRmsXYZ[i]);
710                                 } else      clRmsXYZ[i] = 0;
711                         } else        clRmsXYZ[i] = 0;
712                 }    
713         } else {
714                 for(i=0; i<3; i++ ) {
715                         clXYZ[i] = clRmsXYZ[i] = -1.;
716                 }
717         }
718         // clRmsXYZ[i] ??
719         
720 //      // Cluster of one single digit, smear the position to avoid discrete position
721 //      // smear x and z with +- 3 cm to uniform (avoid discrete effects). Tower size is approx 6 cm.
722 //      // Rndm generates a number in ]0,1]
723 //      if (fMulDigit==1) { 
724 //        clXYZ[0] += fGeomPtr->GetPhiTileSize()*(0.5 - gRandom->Rndm()); 
725 //        clXYZ[2] += fGeomPtr->GetEtaTileSize()*(0.5 - gRandom->Rndm()); 
726 //      }
727         
728         //Set position in local vector
729         fLocPos.SetX(clXYZ[0]);
730         fLocPos.SetY(clXYZ[1]);
731         fLocPos.SetZ(clXYZ[2]);
732                 
733         if (gDebug==2)
734                 printf("EvalLocalPosition Cluster: Local (x,y,z) = (%f,%f,%f) \n", fLocPos.X(), fLocPos.Y(), fLocPos.Z()) ; 
735
736 }
737
738
739 //____________________________________________________________________________
740 void AliEMCALRecPoint::EvalGlobalPosition(Float_t logWeight, TClonesArray * digits)
741 {
742   // Calculates the center of gravity in the global ALICE coordinates 
743   //  Info("Print", " logWeight %f : cluster energy %f ", logWeight, fAmp); // for testing
744   
745   AliEMCALDigit * digit=0;
746   Int_t i=0, nstat=0;
747         
748   Double_t dist  = TmaxInCm(Double_t(fAmp));
749   //Int_t       idMax = GetAbsIdMaxDigit();// idMax is not used at all in RelPosCellInSModule, why use it?
750         
751   Double_t clXYZ[3]={0.,0.,0.}, clRmsXYZ[3]={0.,0.,0.}, lxyzi[3], xyzi[3], wtot=0., w=0.;
752
753   //printf(" dist : %f  e : %f \n", dist, fAmp);
754   for(Int_t iDigit=0; iDigit<fMulDigit; iDigit++) {
755     digit = dynamic_cast<AliEMCALDigit *>(digits->At(fDigitsList[iDigit])) ;
756
757     if(!digit) {
758       AliError("No Digit!!");
759       continue;
760     }    
761     
762     //Get the local coordinates of the cell
763     //fGeomPtr->RelPosCellInSModule(digit->GetId(), idMax, dist, lxyzi[0], lxyzi[1], lxyzi[2]);
764     fGeomPtr->RelPosCellInSModule(digit->GetId(), dist, lxyzi[0], lxyzi[1], lxyzi[2]);
765     
766     //Now get the global coordinate
767     fGeomPtr->GetGlobal(lxyzi,xyzi, fGeomPtr->GetSuperModuleNumber(digit->GetId()));
768     //TVector3 pos(xyzi[0], xyzi[1], xyzi[2]);
769     //printf("EvalGlobalPosition Cell:  Id %i, SM %i : dist %f Local (x,y,z) = (%f %f %f), eta %f, phi%f \n", 
770     //     digit->GetId(), fGeomPtr->GetSuperModuleNumber(digit->GetId()),dist, xyzi[0], xyzi[1], xyzi[2],pos.Eta(),pos.Phi()*TMath::RadToDeg());
771           
772     if(logWeight > 0.0)  w = TMath::Max( 0., logWeight + TMath::Log( fEnergyList[iDigit] / fAmp ));
773     else  w = fEnergyList[iDigit]; // just energy
774
775     if(w>0.0) {
776       wtot += w ;
777       nstat++;
778       for(i=0; i<3; i++ ) {
779         clXYZ[i]    += (w*xyzi[i]);
780         clRmsXYZ[i] += (w*xyzi[i]*xyzi[i]);
781       }
782     }
783   }
784   //  cout << " wtot " << wtot << endl;
785   if ( wtot > 0 ) { 
786     //    xRMS   = TMath::Sqrt(x2m - xMean*xMean);
787     for(i=0; i<3; i++ ) {
788       clXYZ[i] /= wtot;
789       if(nstat>1) {
790         clRmsXYZ[i] /= (wtot*wtot);  
791         clRmsXYZ[i]  =  clRmsXYZ[i] - clXYZ[i]*clXYZ[i];
792         if(clRmsXYZ[i] > 0.0) {
793           clRmsXYZ[i] =  TMath::Sqrt(clRmsXYZ[i]);
794         } else      clRmsXYZ[i] = 0;
795       } else        clRmsXYZ[i] = 0;
796     }    
797   } else {
798     for(i=0; i<3; i++ ) {
799       clXYZ[i] = clRmsXYZ[i] = -1.;
800     }
801   }
802   // clRmsXYZ[i] ??
803
804 //  // Cluster of one single digit, smear the position to avoid discrete position
805 //  // smear x and z with +- 3 cm to uniform (avoid discrete effects). Tower size is approx 6 cm.
806 //  // Rndm generates a number in ]0,1]
807 //  if (fMulDigit==1) { 
808 //    clXYZ[0] += fGeomPtr->GetPhiTileSize()*(0.5 - gRandom->Rndm()); 
809 //    clXYZ[2] += fGeomPtr->GetEtaTileSize()*(0.5 - gRandom->Rndm());   
810 //  }
811         
812   //Set position in global vector
813   fGlobPos.SetX(clXYZ[0]);
814   fGlobPos.SetY(clXYZ[1]);
815   fGlobPos.SetZ(clXYZ[2]);
816                 
817   if (gDebug==2)
818         printf("EvalGlobalPosition Cluster: (x ,y ,z) = (%f,%f,%f), eta %f,phi %f\n", 
819                    fGlobPos.X(), fGlobPos.Y(), fGlobPos.Z(),fGlobPos.Eta(),fGlobPos.Phi()*TMath::RadToDeg()) ; 
820 }
821
822 //____________________________________________________________________________
823 void AliEMCALRecPoint::EvalLocalPositionFit(Double_t deff, Double_t logWeight, 
824 Double_t phiSlope, TClonesArray * digits)
825 {
826   // Evaluates local position of clusters in SM
827   
828   Double_t ycorr=0;
829   AliEMCALDigit *digit=0;
830   Int_t i=0, nstat=0;
831   Double_t clXYZ[3]={0.,0.,0.}, clRmsXYZ[3]={0.,0.,0.}, xyzi[3], wtot=0., w=0.; 
832
833   Double_t dist  = TmaxInCm(Double_t(fAmp));
834   //Int_t       idMax = GetAbsIdMaxDigit();// idMax is not used at all in RelPosCellInSModule, why use it?
835         
836   for(Int_t iDigit=0; iDigit<digits->GetEntries(); iDigit++) {
837     digit = dynamic_cast<AliEMCALDigit *>(digits->At(fDigitsList[iDigit])) ;
838  
839     dist = deff;
840     //fGeomPtr->RelPosCellInSModule(digit->GetId(), idMax, dist, xyzi[0], xyzi[1], xyzi[2]);
841     fGeomPtr->RelPosCellInSModule(digit->GetId(), dist, xyzi[0], xyzi[1], xyzi[2]);
842     
843     if(logWeight > 0.0)  w = TMath::Max( 0., logWeight + TMath::Log( fEnergyList[iDigit] / fAmp ));
844     else                 w = fEnergyList[iDigit]; // just energy
845     
846     if(w>0.0) {
847       wtot += w ;
848       nstat++;
849       for(i=0; i<3; i++ ) {
850         clXYZ[i]    += (w*xyzi[i]);
851         clRmsXYZ[i] += (w*xyzi[i]*xyzi[i]);
852       }
853     }
854   }
855   //  cout << " wtot " << wtot << endl;
856   if ( wtot > 0 ) { 
857     //    xRMS   = TMath::Sqrt(x2m - xMean*xMean);
858     for(i=0; i<3; i++ ) {
859       clXYZ[i] /= wtot;
860       if(nstat>1) {
861         clRmsXYZ[i] /= (wtot*wtot);  
862         clRmsXYZ[i]  =  clRmsXYZ[i] - clXYZ[i]*clXYZ[i];
863         if(clRmsXYZ[i] > 0.0) {
864           clRmsXYZ[i] =  TMath::Sqrt(clRmsXYZ[i]);
865         } else      clRmsXYZ[i] = 0;
866       } else        clRmsXYZ[i] = 0;
867     }    
868   } else {
869     for(i=0; i<3; i++ ) {
870       clXYZ[i] = clRmsXYZ[i] = -1.;
871     }
872   }
873   // clRmsXYZ[i] ??
874   if(phiSlope != 0.0 && logWeight > 0.0 && wtot) { 
875     // Correction in phi direction (y - coords here); Aug 16;
876     // May be put to global level or seperate method
877     ycorr = clXYZ[1] * (1. + phiSlope);
878     //printf(" y %f : ycorr %f : slope %f \n", clXYZ[1], ycorr, phiSlope); 
879     clXYZ[1] = ycorr;
880   }
881         
882   fLocPos.SetX(clXYZ[0]);
883   fLocPos.SetY(clXYZ[1]);
884   fLocPos.SetZ(clXYZ[2]);
885     
886 //  if (gDebug==2)
887 //    printf("EvalLocalPosition: eta,phi,r = %f,%f,%f", fLocPos.X(), fLocPos.Y(), fLocPos.Z()) ; 
888 }
889
890 //_____________________________________________________________________________
891 Bool_t AliEMCALRecPoint::EvalLocalPosition2(TClonesArray * digits, TArrayD &ed)
892 {
893   // Evaluated local position of rec.point using digits 
894   // and parametrisation of w0 and deff
895   //printf(" <I> AliEMCALRecPoint::EvalLocalPosition2() \n"); 
896   return AliEMCALRecPoint::EvalLocalPositionFromDigits(digits, ed, fLocPos);
897 }
898
899 //_____________________________________________________________________________
900 Bool_t AliEMCALRecPoint::EvalLocalPositionFromDigits(TClonesArray *digits, TArrayD &ed, TVector3 &locPos)
901 {
902   // Used when digits should be recalibrated
903   Double_t deff=0, w0=0, esum=0;
904   Int_t iDigit=0;
905   //  AliEMCALDigit *digit;
906
907   if(ed.GetSize() && (digits->GetEntries()!=ed.GetSize())) return kFALSE;
908
909   // Calculate sum energy of digits
910   esum = 0.0;
911   for(iDigit=0; iDigit<ed.GetSize(); iDigit++) esum += ed[iDigit];
912
913   GetDeffW0(esum, deff, w0);
914   
915   return EvalLocalPositionFromDigits(esum, deff, w0, digits, ed, locPos); 
916 }
917
918 //_____________________________________________________________________________
919 Bool_t AliEMCALRecPoint::EvalLocalPositionFromDigits(const Double_t esum, const Double_t deff, const Double_t w0, TClonesArray *digits, TArrayD &ed, TVector3 &locPos)
920 {
921   //Evaluate position of digits in supermodule.
922   AliEMCALDigit *digit=0;
923
924   Int_t i=0, nstat=0;
925   Double_t clXYZ[3]={0.,0.,0.}, xyzi[3], wtot=0., w=0.; 
926   //Int_t       idMax = GetAbsIdMaxDigit();// idMax is not used at all in RelPosCellInSModule, why use it?
927         
928   // Get pointer to EMCAL geometry
929   // (can't use fGeomPtr in static method)
930   AliEMCALGeometry* geo = AliEMCALGeometry::GetInstance(); 
931
932   for(Int_t iDigit=0; iDigit<digits->GetEntries(); iDigit++) {
933     digit = dynamic_cast<AliEMCALDigit *>(digits->At(iDigit));
934
935     //geo->RelPosCellInSModule(digit->GetId(), idMax, deff, xyzi[0], xyzi[1], xyzi[2]);
936     geo->RelPosCellInSModule(digit->GetId(), deff, xyzi[0], xyzi[1], xyzi[2]);
937
938     if(w0 > 0.0)  w = TMath::Max( 0., w0 + TMath::Log(ed[iDigit] / esum));
939     else          w = ed[iDigit]; // just energy
940
941     if(w>0.0) {
942       wtot += w ;
943       nstat++;
944       for(i=0; i<3; i++ ) {
945         clXYZ[i] += (w*xyzi[i]);
946       }
947     }
948   }
949   //  cout << " wtot " << wtot << endl;
950   if (wtot > 0) { 
951     for(i=0; i<3; i++ ) {
952       clXYZ[i] /= wtot;
953     }
954     locPos.SetX(clXYZ[0]);
955     locPos.SetY(clXYZ[1]);
956     locPos.SetZ(clXYZ[2]);
957     return kTRUE;
958   } else {
959     return kFALSE;
960   }
961
962 }
963
964 //_____________________________________________________________________________
965 void AliEMCALRecPoint::GetDeffW0(const Double_t esum , Double_t &deff,  Double_t &w0)
966 {
967   //
968   // Aug 31, 2001 
969   // Applied for simulation data with threshold 3 adc
970   // Calculate efective distance (deff) and weigh parameter (w0) 
971   // for coordinate calculation; 0.5 GeV < esum <100 GeV.
972   // Look to:  http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/CALIB/GEOMCORR/deffandW0VaEgamma_2.gif
973   //
974   Double_t e=0.0;
975   const  Double_t kdp0=9.25147, kdp1=1.16700; // Hard coded now
976   const  Double_t kwp0=4.83713, kwp1=-2.77970e-01, kwp2 = 4.41116;
977
978   // No extrapolation here
979   e = esum<0.5?0.5:esum;
980   e = e>100.?100.:e;
981
982   deff = kdp0 + kdp1*TMath::Log(e);
983   w0   = kwp0 / (1. + TMath::Exp(kwp1*(e+kwp2)));
984   //printf("<I> AliEMCALRecPoint::GetDeffW0 esum %5.2f : deff %5.2f : w0 %5.2f \n", esum, deff, w0); 
985 }
986
987 //______________________________________________________________________________
988 void AliEMCALRecPoint::EvalCoreEnergy(Float_t logWeight, TClonesArray * digits)
989 {
990   // This function calculates energy in the core, 
991   // i.e. within a radius rad = fCoreEnergy around the center. Beyond this radius
992   // in accordance with shower profile the energy deposition 
993   // should be less than 2%
994   // Unfinished - Nov 15,2006
995   // Distance is calculate in (phi,eta) units
996
997   AliEMCALDigit * digit = 0 ;
998
999   Int_t iDigit=0;
1000
1001   if (!fLocPos.Mag()) {
1002     EvalLocalPosition(logWeight, digits);
1003   }
1004   
1005   Double_t phiPoint = fLocPos.Phi(), etaPoint = fLocPos.Eta();
1006   Double_t eta, phi, distance;
1007   for(iDigit=0; iDigit < fMulDigit; iDigit++) {
1008     digit = (AliEMCALDigit *) ( digits->At(fDigitsList[iDigit]) ) ;
1009     
1010     eta = phi = 0.0;
1011     fGeomPtr->EtaPhiFromIndex(digit->GetId(),eta, phi) ;
1012     phi = phi * TMath::DegToRad();
1013   
1014     distance = TMath::Sqrt((eta-etaPoint)*(eta-etaPoint)+(phi-phiPoint)*(phi-phiPoint));
1015     if(distance < fCoreRadius)
1016       fCoreEnergy += fEnergyList[iDigit] ;
1017   }
1018   
1019 }
1020 //____________________________________________________________________________
1021 void  AliEMCALRecPoint::EvalElipsAxis(Float_t logWeight,TClonesArray * digits)
1022 {
1023   // Calculates the axis of the shower ellipsoid in eta and phi
1024   // in cell units
1025
1026   TString gn(fGeomPtr->GetName());
1027
1028   Double_t wtot = 0.;
1029   Double_t x    = 0.;
1030   Double_t z    = 0.;
1031   Double_t dxx  = 0.;
1032   Double_t dzz  = 0.;
1033   Double_t dxz  = 0.;
1034
1035   AliEMCALDigit * digit = 0;
1036         
1037   Double_t etai =0, phii=0, w=0; 
1038   int nSupMod=0, nModule=0, nIphi=0, nIeta=0;
1039   int iphi=0, ieta=0;
1040   for(Int_t iDigit=0; iDigit<fMulDigit; iDigit++) {
1041     digit = (AliEMCALDigit *) digits->At(fDigitsList[iDigit])  ;
1042     etai = phii = 0.; 
1043     // Nov 15,2006 - use cell numbers as coordinates
1044     // Copied for shish-kebab geometry, ieta,iphi is cast as double as eta,phi
1045     // We can use the eta,phi(or coordinates) of cell
1046     nSupMod = nModule = nIphi = nIeta = iphi = ieta = 0;
1047
1048     fGeomPtr->GetCellIndex(digit->GetId(), nSupMod,nModule,nIphi,nIeta);
1049     fGeomPtr->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
1050           
1051     // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
1052     // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
1053     if(fSharedCluster && nSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
1054     
1055     etai=(Double_t)ieta;
1056     phii=(Double_t)iphi;
1057           
1058     w = TMath::Max(0.,logWeight+TMath::Log(fEnergyList[iDigit]/fAmp ) ) ;
1059     // fAmp summed amplitude of digits, i.e. energy of recpoint 
1060     // Gives smaller value of lambda than log weight  
1061     // w = fEnergyList[iDigit] / fAmp; // Nov 16, 2006 - try just energy
1062
1063     dxx  += w * etai * etai ;
1064     x    += w * etai ;
1065     dzz  += w * phii * phii ;
1066     z    += w * phii ; 
1067
1068     dxz  += w * etai * phii ; 
1069
1070     wtot += w ;
1071   }
1072
1073   if ( wtot > 0 ) { 
1074     dxx /= wtot ;
1075     x   /= wtot ;
1076     dxx -= x * x ;
1077     dzz /= wtot ;
1078     z   /= wtot ;
1079     dzz -= z * z ;
1080     dxz /= wtot ;
1081     dxz -= x * z ;
1082
1083     fLambda[0] =  0.5 * (dxx + dzz) + TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz )  ;
1084     if(fLambda[0] > 0)
1085       fLambda[0] = TMath::Sqrt(fLambda[0]) ;
1086     else
1087       fLambda[0] = 0;
1088     
1089     fLambda[1] =  0.5 * (dxx + dzz) - TMath::Sqrt( 0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz )  ;
1090
1091     if(fLambda[1] > 0) //To avoid exception if numerical errors lead to negative lambda.
1092       fLambda[1] = TMath::Sqrt(fLambda[1]) ;
1093     else
1094       fLambda[1]= 0. ;
1095   } else { 
1096     fLambda[0]= 0. ;
1097     fLambda[1]= 0. ;
1098   }
1099
1100   //printf("AliEMCALRecPoint::EvalElipsAxis() lambdas  = %f,%f \n", fLambda[0],fLambda[1]) ; 
1101
1102 }
1103
1104 //______________________________________________________________________________
1105 void  AliEMCALRecPoint::EvalPrimaries(TClonesArray * digits)
1106 {
1107   // Constructs the list of primary particles (tracks) which 
1108   // have contributed to this RecPoint and calculate deposited energy 
1109   // for each track
1110   
1111   AliEMCALDigit * digit =0;
1112   Int_t * primArray = new Int_t[fMaxTrack] ;
1113   memset(primArray,-1,sizeof(Int_t)*fMaxTrack);
1114   Float_t * dEPrimArray = new Float_t[fMaxTrack] ;
1115   memset(dEPrimArray,-1,sizeof(Int_t)*fMaxTrack);
1116   
1117   Int_t index ;  
1118   for ( index = 0 ; index < GetDigitsMultiplicity() ; index++ ) { // all digits
1119     digit = dynamic_cast<AliEMCALDigit *>(digits->At( fDigitsList[index] )) ; 
1120     if(!digit) {
1121       AliError("No Digit!!");
1122       continue;
1123     }
1124     
1125     Int_t nprimaries = digit->GetNprimary() ;
1126     if ( nprimaries == 0 ) continue ;
1127     Int_t jndex ;
1128     for ( jndex = 0 ; jndex < nprimaries ; jndex++ ) { // all primaries in digit
1129       if ( fMulTrack > fMaxTrack ) {
1130         fMulTrack = fMaxTrack ;
1131         Error("EvalPrimaries", "increase fMaxTrack ")  ;
1132         break ;
1133       }
1134       Int_t newPrimary = digit->GetPrimary(jndex+1);
1135       Float_t dEPrimary = digit->GetDEPrimary(jndex+1);
1136       Int_t kndex ;
1137       Bool_t already = kFALSE ;
1138       for ( kndex = 0 ; kndex < fMulTrack ; kndex++ ) { //check if not already stored
1139         if ( newPrimary == primArray[kndex] ){
1140           already = kTRUE ;
1141           dEPrimArray[kndex] += dEPrimary; 
1142           break ;
1143         }
1144       } // end of check
1145       if ( !already && (fMulTrack < fMaxTrack)) { // store it
1146         primArray[fMulTrack] = newPrimary ; 
1147         dEPrimArray[fMulTrack] = dEPrimary ; 
1148         fMulTrack++ ;
1149       } // store it
1150     } // all primaries in digit
1151   } // all digits
1152   
1153   Int_t *sortIdx = new Int_t[fMulTrack];
1154   TMath::Sort(fMulTrack,dEPrimArray,sortIdx); 
1155   for(index = 0; index < fMulTrack; index++) {
1156     fTracksList[index] = primArray[sortIdx[index]] ;    
1157     fDETracksList[index] = dEPrimArray[sortIdx[index]] ;
1158   }
1159   delete [] sortIdx;
1160   delete [] primArray ;
1161   delete [] dEPrimArray ;
1162   
1163 }
1164
1165 //______________________________________________________________________________
1166 void  AliEMCALRecPoint::EvalParents(TClonesArray * digits)
1167 {
1168   // Constructs the list of parent particles (tracks) which have contributed to this RecPoint
1169   
1170   AliEMCALDigit * digit=0 ;
1171   Int_t * parentArray = new Int_t[fMaxTrack] ;
1172   memset(parentArray,-1,sizeof(Int_t)*fMaxTrack);
1173   Float_t * dEParentArray = new Float_t[fMaxTrack] ;
1174   memset(dEParentArray,-1,sizeof(Int_t)*fMaxTrack);
1175   
1176   Int_t index ;  
1177   for ( index = 0 ; index < GetDigitsMultiplicity() ; index++ ) { // all digits
1178     if (fDigitsList[index] >= digits->GetEntries() || fDigitsList[index] < 0)
1179       AliError(Form("Trying to get invalid digit %d (idx in WriteRecPoint %d)",fDigitsList[index],index));
1180     digit = dynamic_cast<AliEMCALDigit *>(digits->At( fDigitsList[index] )) ; 
1181     if(!digit) {
1182       AliError("No Digit!!");
1183       continue;
1184     }
1185     
1186     Int_t nparents = digit->GetNiparent() ;
1187     if ( nparents == 0 ) continue ;
1188     
1189     Int_t jndex ;
1190     for ( jndex = 0 ; jndex < nparents ; jndex++ ) { // all primaries in digit
1191       if ( fMulParent > fMaxParent ) {
1192         fMulTrack = - 1 ;
1193         Error("EvalParents", "increase fMaxParent")  ;
1194         break ;
1195       }
1196       Int_t newParent = digit->GetIparent(jndex+1) ;
1197       Float_t newdEParent = digit->GetDEParent(jndex+1) ;
1198       Int_t kndex ;
1199       Bool_t already = kFALSE ;
1200       for ( kndex = 0 ; kndex < fMulParent ; kndex++ ) { //check if not already stored
1201         if ( newParent == parentArray[kndex] ){
1202           dEParentArray[kndex] += newdEParent;
1203           already = kTRUE ;
1204           break ;
1205         }
1206       } // end of check
1207       if ( !already && (fMulParent < fMaxParent)) { // store it
1208         parentArray[fMulParent] = newParent ; 
1209         dEParentArray[fMulParent] = newdEParent ; 
1210         fMulParent++ ;
1211       } // store it
1212     } // all parents in digit
1213   } // all digits
1214   
1215   if (fMulParent>0) {
1216     Int_t *sortIdx = new Int_t[fMulParent];
1217     TMath::Sort(fMulParent,dEParentArray,sortIdx); 
1218     for(index = 0; index < fMulParent; index++) {
1219       fParentsList[index] = parentArray[sortIdx[index]] ;      
1220       fDEParentsList[index] = dEParentArray[sortIdx[index]] ;
1221     }
1222     delete [] sortIdx;
1223   }
1224   
1225   delete [] parentArray;
1226   delete [] dEParentArray;
1227 }
1228
1229 //____________________________________________________________________________
1230 void AliEMCALRecPoint::GetLocalPosition(TVector3 & lpos) const
1231 {
1232   // returns the position of the cluster in the local reference system
1233   // of the sub-detector
1234   
1235   lpos = fLocPos;
1236 }
1237
1238 //____________________________________________________________________________
1239 void AliEMCALRecPoint::GetGlobalPosition(TVector3 & gpos) const
1240 {
1241   // returns the position of the cluster in the global reference system of ALICE
1242   // These are now the Cartesian X, Y and Z
1243   //  cout<<" geom "<<geom<<endl;
1244   // fGeomPtr->GetGlobal(fLocPos, gpos, fSuperModuleNumber);
1245   gpos = fGlobPos;
1246         
1247 }
1248
1249 //____________________________________________________________________________
1250 //void AliEMCALRecPoint::GetGlobalPosition(TVector3 & gpos, TMatrixF & gmat) const
1251 //{
1252 //  // returns the position of the cluster in the global reference system of ALICE
1253 //  // These are now the Cartesian X, Y and Z
1254 //  //  cout<<" geom "<<geom<<endl;
1255 //
1256 //  //To be implemented
1257 //  fGeomPtr->GetGlobalEMCAL(this, gpos, gmat);
1258 //
1259 //}
1260
1261 //_____________________________________________________________________________
1262 void AliEMCALRecPoint::EvalLocal2TrackingCSTransform()
1263 {
1264   //Evaluates local to "tracking" c.s. transformation (B.P.).
1265   //All evaluations should be completed before calling for this
1266   //function.                           
1267   //See ALICE PPR Chapter 5 p.18 for "tracking" c.s. definition,
1268   //or just ask Jouri Belikov. :) 
1269
1270   SetVolumeId(AliGeomManager::LayerToVolUID(AliGeomManager::kEMCAL,GetSuperModuleNumber()));
1271
1272   const TGeoHMatrix* tr2loc = GetTracking2LocalMatrix();
1273   if(!tr2loc) AliFatal(Form("No Tracking2LocalMatrix found."));
1274
1275   Double_t lxyz[3] = {fLocPos.X(),fLocPos.Y(),fLocPos.Z()};
1276   Double_t txyz[3] = {0,0,0};
1277
1278   tr2loc->MasterToLocal(lxyz,txyz);
1279   SetX(txyz[0]); SetY(txyz[1]); SetZ(txyz[2]);
1280
1281   if(AliLog::GetGlobalDebugLevel()>0) {
1282         TVector3 gpos; //TMatrixF gmat;
1283     //GetGlobalPosition(gpos,gmat); //Not doing anythin special, replace by next line.  
1284         fGeomPtr->GetGlobal(fLocPos, gpos, GetSuperModuleNumber());
1285           
1286     Float_t gxyz[3];
1287     GetGlobalXYZ(gxyz);
1288     AliInfo(Form("lCS-->(%.3f,%.3f,%.3f), tCS-->(%.3f,%.3f,%.3f), gCS-->(%.3f,%.3f,%.3f),  gCScalc-\
1289 ->(%.3f,%.3f,%.3f), supermodule %d",
1290                  fLocPos.X(),fLocPos.Y(),fLocPos.Z(),
1291                  GetX(),GetY(),GetZ(),
1292                  gpos.X(),gpos.Y(),gpos.Z(),
1293                  gxyz[0],gxyz[1],gxyz[2],GetSuperModuleNumber()));
1294   }
1295
1296 }
1297
1298 //____________________________________________________________________________
1299 Float_t AliEMCALRecPoint::GetMaximalEnergy(void) const
1300 {
1301   // Finds the maximum energy in the cluster
1302   
1303   Float_t menergy = 0. ;
1304
1305   Int_t iDigit;
1306   for(iDigit=0; iDigit<fMulDigit; iDigit++) {
1307  
1308     if(fEnergyList[iDigit] > menergy) 
1309       menergy = fEnergyList[iDigit] ;
1310   }
1311   return menergy ;
1312 }
1313
1314 //____________________________________________________________________________
1315 Int_t AliEMCALRecPoint::GetMaximalEnergyIndex(void) const
1316 {
1317   // Finds the maximum energy in the cluster
1318   
1319   Float_t menergy = 0. ;
1320   Int_t mid       = 0  ;
1321   Int_t iDigit;
1322   
1323   for(iDigit=0; iDigit<fMulDigit; iDigit++) {
1324     
1325     if(fEnergyList[iDigit] > menergy){ 
1326       menergy = fEnergyList[iDigit] ;
1327       mid     = iDigit ;
1328     }
1329   }//loop on cluster digits
1330   
1331   return mid ;
1332 }
1333
1334
1335 //____________________________________________________________________________
1336 Int_t AliEMCALRecPoint::GetMultiplicityAtLevel(Float_t H) const
1337 {
1338   // Calculates the multiplicity of digits with energy larger than H*energy 
1339   
1340   Int_t multipl   = 0 ;
1341   Int_t iDigit ;
1342   for(iDigit=0; iDigit<fMulDigit; iDigit++) {
1343
1344     if(fEnergyList[iDigit] > H * fAmp) 
1345       multipl++ ;
1346   }
1347   return multipl ;
1348 }
1349
1350 //____________________________________________________________________________
1351 Int_t  AliEMCALRecPoint::GetNumberOfLocalMax(AliEMCALDigit **  maxAt, Float_t * maxAtEnergy,
1352                                                Float_t locMaxCut,TClonesArray * digits) const
1353
1354   // Calculates the number of local maxima in the cluster using fLocalMaxCut as the minimum
1355   // energy difference between two local maxima
1356
1357   AliEMCALDigit * digit  = 0;
1358   AliEMCALDigit * digitN = 0;
1359   
1360   Int_t iDigitN = 0 ;
1361   Int_t iDigit  = 0 ;
1362
1363   for(iDigit = 0; iDigit < fMulDigit; iDigit++)
1364     maxAt[iDigit] = (AliEMCALDigit*) digits->At(fDigitsList[iDigit])  ;
1365   
1366   for(iDigit = 0 ; iDigit < fMulDigit; iDigit++) {   
1367     if(maxAt[iDigit]) {
1368       digit = maxAt[iDigit] ;
1369           
1370       for(iDigitN = 0; iDigitN < fMulDigit; iDigitN++) {        
1371         digitN = (AliEMCALDigit *) digits->At(fDigitsList[iDigitN]) ; 
1372         
1373         if ( AreNeighbours(digit, digitN) ) {
1374           if (fEnergyList[iDigit] > fEnergyList[iDigitN] ) {    
1375             maxAt[iDigitN] = 0 ;
1376             // but may be digit too is not local max ?
1377             if(fEnergyList[iDigit] < fEnergyList[iDigitN] + locMaxCut) 
1378               maxAt[iDigit] = 0 ;
1379           }
1380           else {
1381             maxAt[iDigit] = 0 ;
1382             // but may be digitN too is not local max ?
1383             if(fEnergyList[iDigit] > fEnergyList[iDigitN] - locMaxCut) 
1384               maxAt[iDigitN] = 0 ; 
1385           } 
1386         } // if Areneighbours
1387       } // while digitN
1388     } // slot not empty
1389   } // while digit
1390   
1391   iDigitN = 0 ;
1392   for(iDigit = 0; iDigit < fMulDigit; iDigit++) { 
1393     if(maxAt[iDigit] ){
1394       maxAt[iDigitN] = maxAt[iDigit] ;
1395       maxAtEnergy[iDigitN] = fEnergyList[iDigit] ;
1396       iDigitN++ ; 
1397     }
1398   }
1399   return iDigitN ;
1400 }
1401
1402 //____________________________________________________________________________
1403 Int_t AliEMCALRecPoint::GetPrimaryIndex() const  
1404 {
1405   // Get the primary track index in TreeK which deposits the most energy 
1406   // in Digits which forms RecPoint. 
1407
1408   if (fMulTrack)
1409     return fTracksList[0];
1410   return -12345;
1411 }
1412
1413 //____________________________________________________________________________
1414 void AliEMCALRecPoint::EvalTime(TClonesArray * digits){
1415   // time is set to the time of the digit with the maximum energy
1416
1417   Float_t maxE  = 0;
1418   Int_t   maxAt = 0;
1419   for(Int_t idig=0; idig < fMulDigit; idig++){
1420     if(fEnergyList[idig] > maxE){
1421       maxE  = fEnergyList[idig] ;
1422       maxAt = idig;
1423     }
1424   }
1425   fTime = ((AliEMCALDigit*) digits->At(fDigitsList[maxAt]))->GetTime() ;
1426   
1427 }
1428
1429 //______________________________________________________________________________
1430 void AliEMCALRecPoint::Paint(Option_t *)
1431 {
1432   // Paint this ALiRecPoint as a TMarker  with its current attributes
1433   
1434   TVector3 pos(0.,0.,0.)  ;
1435   GetLocalPosition(pos)   ;
1436   Coord_t x = pos.X()     ;
1437   Coord_t y = pos.Z()     ;
1438   Color_t markercolor = 1 ;
1439   Size_t  markersize  = 1.;
1440   Style_t markerstyle = 5 ;
1441   
1442   if (!gPad->IsBatch()) {
1443     gVirtualX->SetMarkerColor(markercolor) ;
1444     gVirtualX->SetMarkerSize (markersize)  ;
1445     gVirtualX->SetMarkerStyle(markerstyle) ;
1446   }
1447   gPad->SetAttMarkerPS(markercolor,markerstyle,markersize) ;
1448   gPad->PaintPolyMarker(1,&x,&y,"") ;
1449 }
1450
1451 //_____________________________________________________________________
1452 Double_t AliEMCALRecPoint::TmaxInCm(const Double_t e , const Int_t key)
1453
1454   // e energy in GeV)
1455   // key  =  0(gamma, default)
1456   //     !=  0(electron)
1457   const Double_t ca   = 4.82;  // shower max parameter - first guess; ca=TMath::Log(1000./8.07)
1458   const Double_t x0   = 1.23;  // radiation lenght (cm)
1459   Double_t tmax = 0.;    // position of electromagnetic shower max in cm
1460
1461   if(e>0.1) {
1462     tmax = TMath::Log(e) + ca;
1463     if      (key==0) tmax += 0.5; 
1464     else             tmax -= 0.5;
1465     tmax *= x0; // convert to cm
1466   }
1467   return tmax;
1468 }
1469
1470 //______________________________________________________________________________
1471 Float_t AliEMCALRecPoint::EtaToTheta(Float_t arg) const
1472 {
1473   //Converts Theta (Radians) to Eta(Radians)
1474   return (2.*TMath::ATan(TMath::Exp(-arg)));
1475 }
1476
1477 //______________________________________________________________________________
1478 Float_t AliEMCALRecPoint::ThetaToEta(Float_t arg) const
1479 {
1480   //Converts Eta (Radians) to Theta(Radians)
1481   return (-1 * TMath::Log(TMath::Tan(0.5 * arg)));
1482 }
1483
1484 //____________________________________________________________________________
1485 void AliEMCALRecPoint::Print(Option_t *opt) const
1486 {
1487   // Print the list of digits belonging to the cluster
1488   if(strlen(opt)==0) return;
1489   TString message ; 
1490   message  = "AliEMCALRecPoint:\n" ;
1491   message +=  " digits # = " ; 
1492   Info("Print", message.Data()) ; 
1493
1494   Int_t iDigit;
1495   for(iDigit=0; iDigit<fMulDigit; iDigit++)
1496     printf(" %d ", fDigitsList[iDigit] ) ;  
1497   printf("\n");
1498
1499   Info("Print", " Energies = ") ;
1500   for(iDigit=0; iDigit<fMulDigit; iDigit++) 
1501     printf(" %f ", fEnergyList[iDigit] ) ;
1502   printf("\n");
1503
1504   Info("Print", "\n Abs Ids = ") ;
1505   for(iDigit=0; iDigit<fMulDigit; iDigit++) 
1506     printf(" %i ", fAbsIdList[iDigit] ) ;
1507   printf("\n");
1508
1509   Info("Print", " Primaries  ") ;
1510   for(iDigit = 0;iDigit < fMulTrack; iDigit++)
1511     printf(" %d ", fTracksList[iDigit]) ;
1512
1513   printf("\n Local x %6.2f y %7.2f z %7.1f \n", fLocPos[0], fLocPos[1], fLocPos[2]);
1514
1515   message  = "       ClusterType     = %d" ;
1516   message += "       Multiplicity    = %d" ;
1517   message += "       Cluster Energy  = %f" ; 
1518   message += "       Core energy     = %f" ; 
1519   message += "       Core radius     = %f" ; 
1520   message += "       Number of primaries %d" ; 
1521   message += "       Stored at position %d" ; 
1522   Info("Print", message.Data(), fClusterType, fMulDigit, fAmp, fCoreEnergy, fCoreRadius, fMulTrack, GetIndexInList() ) ;  
1523 }
1524
1525 //___________________________________________________________
1526 Double_t  AliEMCALRecPoint::GetPointEnergy() const
1527 {
1528   //Returns energy ....
1529   Double_t e=0.0;
1530   for(int ic=0; ic<GetMultiplicity(); ic++) e += double(fEnergyList[ic]);
1531   return e;
1532 }