]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALReconstructor.cxx
9d3dc7239c166d0076c101d38dd2c6f495e0b02e
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALReconstructor.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 /* $Id$ */
17
18 //_________________________________________________________________________
19 //--
20 //-- Yves Schutz (SUBATECH) 
21 // Reconstruction class. Redesigned from the old AliReconstructionner class and 
22 // derived from STEER/AliReconstructor. 
23 // 
24
25
26 // --- ROOT system ---
27 #include <TClonesArray.h>
28 #include "TGeoManager.h"
29 #include "TGeoMatrix.h"
30
31 // --- Standard library ---
32
33 // --- AliRoot header files ---
34 #include "AliEMCALReconstructor.h"
35
36 #include "AliCodeTimer.h"
37 #include "AliCaloCalibPedestal.h"
38 #include "AliEMCALCalibData.h"
39 #include "AliESDEvent.h"
40 #include "AliESDCaloCluster.h"
41 #include "AliESDCaloCells.h"
42 #include "AliESDtrack.h"
43 #include "AliEMCALLoader.h"
44 #include "AliEMCALRawUtils.h"
45 #include "AliEMCALDigit.h"
46 #include "AliEMCALClusterizerv1.h"
47 #include "AliEMCALClusterizerv2.h"
48 #include "AliEMCALClusterizerNxN.h"
49 #include "AliEMCALRecPoint.h"
50 #include "AliEMCALPID.h"
51 #include "AliEMCALRecoUtils.h"
52 #include "AliRawReader.h"
53 #include "AliCDBEntry.h"
54 #include "AliCDBManager.h"
55 #include "AliEMCALGeometry.h"
56 #include "AliEMCAL.h"
57 #include "AliESDVZERO.h"
58 #include "AliCDBManager.h"
59 #include "AliRunLoader.h"
60 #include "AliRun.h"
61 #include "AliEMCALTriggerData.h"
62 #include "AliEMCALTriggerElectronics.h"
63 #include "AliEMCALTriggerDCSConfigDB.h"
64 #include "AliEMCALTriggerDCSConfig.h"
65 #include "AliEMCALTriggerData.h"
66 #include "AliEMCALTriggerRawDigit.h"
67 #include "AliEMCALTriggerPatch.h"
68 #include "AliEMCALTriggerTypes.h"
69
70 ClassImp(AliEMCALReconstructor) 
71   
72 const AliEMCALRecParam*     AliEMCALReconstructor::fgkRecParam        = 0;   // EMCAL rec. parameters
73 AliEMCALRawUtils*           AliEMCALReconstructor::fgRawUtils         = 0;   // EMCAL raw utilities class
74 AliEMCALClusterizer*        AliEMCALReconstructor::fgClusterizer      = 0;   // EMCAL clusterizer class
75 TClonesArray*               AliEMCALReconstructor::fgDigitsArr        = 0;   // list of digits, to be used multiple times
76 TObjArray*                  AliEMCALReconstructor::fgClustersArr      = 0;   // list of clusters, to be used multiple times
77 TClonesArray*               AliEMCALReconstructor::fgTriggerDigits    = 0;   // list of trigger digits, to be used multiple times
78 AliEMCALTriggerElectronics* AliEMCALReconstructor::fgTriggerProcessor = 0x0;
79 //____________________________________________________________________________
80 AliEMCALReconstructor::AliEMCALReconstructor() 
81   : fGeom(0),fCalibData(0),fPedestalData(0),fTriggerData(0x0), fMatches(0x0)
82 {
83   // ctor
84
85   // AliDebug(2, "Mark.");  
86
87   fgRawUtils = new AliEMCALRawUtils;
88   
89   //To make sure we match with the geometry in a simulation file,
90   //let's try to get it first.  If not, take the default geometry
91   AliRunLoader *rl = AliRunLoader::Instance();
92   if (rl->GetAliRun()){
93     AliEMCAL * emcal = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"));
94     if(emcal) fGeom = emcal->GetGeometry();
95   }
96   
97   if(!fGeom) {
98     AliInfo(Form("Using default geometry in reconstruction"));
99     fGeom =  AliEMCALGeometry::GetInstance(AliEMCALGeometry::GetDefaultGeometryName());
100   }
101   
102   //Get calibration parameters  
103   if(!fCalibData)
104     {
105       AliCDBEntry *entry = (AliCDBEntry*) 
106       AliCDBManager::Instance()->Get("EMCAL/Calib/Data");
107       if (entry) fCalibData =  (AliEMCALCalibData*) entry->GetObject();
108     }
109   
110   if(!fCalibData)
111     AliFatal("Calibration parameters not found in CDB!");
112   
113   //Get calibration parameters  
114   if(!fPedestalData)
115     {
116       AliCDBEntry *entry = (AliCDBEntry*) 
117       AliCDBManager::Instance()->Get("EMCAL/Calib/Pedestals");
118       if (entry) fPedestalData =  (AliCaloCalibPedestal*) entry->GetObject();
119     }
120   
121   if(!fPedestalData)
122     AliFatal("Dead map not found in CDB!");
123   
124   if(!fGeom) AliFatal(Form("Could not get geometry!"));
125   
126   AliEMCALTriggerDCSConfigDB* dcsConfigDB = AliEMCALTriggerDCSConfigDB::Instance();
127   
128   const AliEMCALTriggerDCSConfig* dcsConfig = dcsConfigDB->GetTriggerDCSConfig();
129   
130   if (!dcsConfig) AliFatal("No Trigger DCS Configuration from OCDB!");
131   fgTriggerProcessor = new AliEMCALTriggerElectronics( dcsConfig );
132   
133   fTriggerData = new AliEMCALTriggerData();
134   
135   //Init temporary list of digits
136   fgDigitsArr     = new TClonesArray("AliEMCALDigit",1000);
137   fgClustersArr   = new TObjArray(1000);
138
139   const int kNTRU = fGeom->GetNTotalTRU();
140   fgTriggerDigits = new TClonesArray("AliEMCALTriggerRawDigit", kNTRU * 96);    
141         
142   //Track matching
143   fMatches = new TList();
144   fMatches->SetOwner(kTRUE);
145
146
147 //____________________________________________________________________________
148 AliEMCALReconstructor::~AliEMCALReconstructor()
149 {
150   // dtor
151
152   //AliDebug(2, "Mark.");
153
154   ////RS  if(fGeom)              delete fGeom;
155   
156   //No need to delete, recovered from OCDB
157   //if(fCalibData)         delete fCalibData;
158   //if(fPedestalData)      delete fPedestalData;
159   
160   if(fgDigitsArr) fgDigitsArr->Clear("C");
161   delete fgDigitsArr; 
162   fgDigitsArr = 0;
163   
164   if(fgClustersArr) fgClustersArr->Clear();
165   delete fgClustersArr; 
166   fgClustersArr = 0;
167   
168   if(fgTriggerDigits) fgTriggerDigits->Clear();
169   delete fgTriggerDigits; 
170   fgTriggerDigits = 0;
171   
172   delete fgRawUtils;
173   fgRawUtils = 0;
174   delete fgClusterizer;
175   fgClusterizer = 0;
176   
177   delete fgTriggerProcessor;
178   fgTriggerProcessor = 0;
179   
180   if(fMatches) { fMatches->Delete(); delete fMatches; fMatches = 0;}
181   
182   AliCodeTimer::Instance()->Print();
183
184
185 //____________________________________________________________________________                                  
186 void AliEMCALReconstructor::InitClusterizer() const
187 {
188   //Init the clusterizer with geometry and calibration pointers, avoid doing it twice.                          
189   Int_t clusterizerType = -1;
190   Int_t eventType = -1;
191   if(GetRecParam()) {
192     clusterizerType = GetRecParam()->GetClusterizerFlag();
193     eventType       = GetRecParam()->GetEventSpecie();
194   }
195   else{
196     AliCDBEntry *entry = (AliCDBEntry*)
197       AliCDBManager::Instance()->Get("EMCAL/Calib/RecoParam");
198     //Get The reco param for the default event specie                                                           
199     if (entry) {
200       AliEMCALRecParam *recParam  = (AliEMCALRecParam*)((TObjArray *) entry->GetObject())->At(0);
201       if(recParam) clusterizerType = recParam->GetClusterizerFlag(); 
202     }
203   }
204   
205   //Check if clusterizer previously set corresponds to what is needed for this event type                       
206   if(fgClusterizer){
207     if(eventType!=AliRecoParam::kCalib){
208       //printf("ReCreate clusterizer? Clusterizer set <%d>, Clusterizer in use <%s>\n",
209       //     clusterizerType, fgClusterizer->Version());
210       
211       if     (clusterizerType == AliEMCALRecParam::kClusterizerv1  && !strcmp(fgClusterizer->Version(),"clu-v1"))  return;
212       
213       else if(clusterizerType == AliEMCALRecParam::kClusterizerNxN && !strcmp(fgClusterizer->Version(),"clu-NxN")) return;
214       
215       else if(clusterizerType == AliEMCALRecParam::kClusterizerv2  && !strcmp(fgClusterizer->Version(),"clu-v2"))  return;
216       
217       //Need to create new clusterizer, the one set previously is not the correct one     
218       delete fgClusterizer;
219     }
220     else return;
221   }
222   
223   if      (clusterizerType  == AliEMCALRecParam::kClusterizerv1)
224     {
225       fgClusterizer = new AliEMCALClusterizerv1 (fGeom, fCalibData,fPedestalData);
226     }
227   else if (clusterizerType  == AliEMCALRecParam::kClusterizerNxN)
228     {
229       fgClusterizer = new AliEMCALClusterizerNxN(fGeom, fCalibData,fPedestalData);
230     }
231   else if (clusterizerType  == AliEMCALRecParam::kClusterizerv2)
232   {
233     fgClusterizer = new AliEMCALClusterizerv2   (fGeom, fCalibData,fPedestalData);
234   }
235   else 
236   {
237     AliFatal(Form("Unknown clusterizer %d ", clusterizerType));
238   }
239 }
240
241 //____________________________________________________________________________
242 void AliEMCALReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const
243 {
244   // method called by AliReconstruction; 
245   // Only the clusterization is performed,; the rest of the reconstruction is done in FillESD because the track
246   // segment maker needs access to the AliESD object to retrieve the tracks reconstructed by 
247   // the global tracking.
248   // Works on the current event.
249   
250   AliCodeTimerAuto("",0)
251     
252   //Get input digits and put them in fgDigitsArr, clear the list before 
253   ReadDigitsArrayFromTree(digitsTree);
254   
255   InitClusterizer();
256   
257   fgClusterizer->InitParameters();
258   fgClusterizer->SetOutput(clustersTree);
259   
260   //Skip clusterization of LED events
261   if (GetRecParam()->GetEventSpecie()!=AliRecoParam::kCalib){
262     
263     if(fgDigitsArr && fgDigitsArr->GetEntries()) {
264       
265       fgClusterizer->SetInput(digitsTree);
266       
267       //fgClusterizer->Digits2Clusters("deb all") ; //For debugging
268       fgClusterizer->Digits2Clusters("");
269       
270       fgClusterizer->Clear();
271       
272     }//digits array exists and has somethind
273   }//not a LED event
274   
275   clustersTree->Fill(); 
276
277   // Deleting the recpoints at the end of the reconstruction call
278   fgClusterizer->DeleteRecPoints();
279 }
280
281 //____________________________________________________________________________
282 void AliEMCALReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
283   
284 {
285   // Conversion from raw data to
286   // EMCAL digits.
287   // Works on a single-event basis
288   
289   rawReader->Reset() ; 
290   
291   fTriggerData->SetMode(1);     
292   
293   if(fgDigitsArr) fgDigitsArr->Clear("C");
294   
295   const int kNTRU = fGeom->GetNTotalTRU();
296   TClonesArray *digitsTrg = new TClonesArray("AliEMCALTriggerRawDigit", kNTRU * 96);
297   
298   Int_t bufsize = 32000;
299   digitsTree->Branch("EMCAL", &fgDigitsArr, bufsize);
300   digitsTree->Branch("EMTRG", &digitsTrg, bufsize);
301   
302   //Skip calibration events do the rest
303   Bool_t doFit = kTRUE;
304   if ( !(GetRecParam()->FitLEDEvents()) && GetRecParam()->GetEventSpecie()==AliRecoParam::kCalib) doFit = kFALSE;
305   if (doFit){
306     //must be done here because, in constructor, option is not yet known
307     fgRawUtils->SetOption(GetOption());
308     
309     //  fgRawUtils->SetRawFormatHighLowGainFactor(GetRecParam()->GetHighLowGainFactor());
310     
311     //   fgRawUtils->SetRawFormatOrder(GetRecParam()->GetOrderParameter());
312     //    fgRawUtils->SetRawFormatTau(GetRecParam()->GetTau());
313     fgRawUtils->SetNoiseThreshold(GetRecParam()->GetNoiseThreshold());
314     fgRawUtils->SetNPedSamples(GetRecParam()->GetNPedSamples());
315     fgRawUtils->SetRemoveBadChannels(GetRecParam()->GetRemoveBadChannels());
316     if (!fgRawUtils->GetFittingAlgorithm()) fgRawUtils->SetFittingAlgorithm(GetRecParam()->GetFittingAlgorithm());
317     fgRawUtils->SetFALTROUsage(GetRecParam()->UseFALTRO());
318     //  fgRawUtils->SetFALTROUsage(0);
319  
320     //fgRawUtils->SetTimeMin(GetRecParam()->GetTimeMin());
321     //fgRawUtils->SetTimeMax(GetRecParam()->GetTimeMax());
322     
323     //  fgRawUtils->SetTimeMin(-99999 );
324     //  fgRawUtils->SetTimeMax( 99999 );
325     
326     fgRawUtils->Raw2Digits(rawReader,fgDigitsArr,fPedestalData,digitsTrg,fTriggerData);
327     
328   }//skip calibration event
329   else{
330     AliDebug(1," Calibration Event, skip!");
331   }
332   
333   digitsTree->Fill();
334   digitsTrg->Delete();
335   delete digitsTrg;
336   
337 }
338
339
340 //____________________________________________________________________________
341 void AliEMCALReconstructor::FillESD(TTree* digitsTree, TTree* clustersTree, 
342                                     AliESDEvent* esd) const
343 {
344   // Called by AliReconstruct after Reconstruct() and global tracking and vertexing 
345   // and V0 
346   // Works on the current event
347   // printf(" ## AliEMCALReconstructor::FillESD() is started ### \n ");
348   //return;
349   
350   //########################################
351   // Trigger
352   //########################################
353   
354   static int saveOnce = 0;
355   
356   Int_t v0M[2] = {0, 0};
357   
358   AliESDVZERO* esdV0 = esd->GetVZEROData();
359   
360   if (esdV0) 
361     {
362                 v0M[0] = esdV0->GetTriggerChargeC();
363                 v0M[1] = esdV0->GetTriggerChargeA();
364     }
365   else
366     {
367       AliWarning("No V0 ESD! Run trigger processor w/ null V0 charges");
368     }
369   
370   if (fgTriggerDigits && fgTriggerDigits->GetEntriesFast()) fgTriggerDigits->Delete();
371   
372   TBranch *branchtrg = digitsTree->GetBranch("EMTRG");
373   
374   if (!branchtrg) 
375     { 
376       AliError("Can't get the branch with the EMCAL trigger digits!");
377       return;
378     }
379   
380   branchtrg->SetAddress(&fgTriggerDigits);
381   branchtrg->GetEntry(0);
382   
383   // Note: fgTriggerProcessor reset done at the end of this method
384   fgTriggerProcessor->Digits2Trigger(fgTriggerDigits, v0M, fTriggerData);
385   
386   // Fill ESD
387   AliESDCaloTrigger* trgESD = esd->GetCaloTrigger("EMCAL");
388   
389   if (trgESD)
390     {
391       trgESD->Allocate(fgTriggerDigits->GetEntriesFast());
392       
393       for (Int_t i = 0; i < fgTriggerDigits->GetEntriesFast(); i++)
394         {         
395           AliEMCALTriggerRawDigit* rdig = (AliEMCALTriggerRawDigit*)fgTriggerDigits->At(i);
396           if (AliDebugLevel() > 999) rdig->Print("");
397                 
398           Int_t px, py;
399           if (fGeom->GetPositionInEMCALFromAbsFastORIndex(rdig->GetId(), px, py))
400             {
401               Int_t a = -1, t = -1, times[10]; 
402               
403               rdig->GetMaximum(a, t);
404               rdig->GetL0Times(times);
405                         
406               trgESD->Add(px, py, a, t, times, rdig->GetNL0Times(), rdig->GetL1TimeSum(), rdig->GetTriggerBits());
407             }
408         }
409       
410                 for (int i = 0; i < 2; i++) {
411                         trgESD->SetL1Threshold(2 * i    , fTriggerData->GetL1JetThreshold(  i));
412                         trgESD->SetL1Threshold(2 * i + 1, fTriggerData->GetL1GammaThreshold(i));
413                 }
414       
415       Int_t v0[2];
416       fTriggerData->GetL1V0(v0);
417       
418       trgESD->SetL1V0(v0);      
419       trgESD->SetL1FrameMask(fTriggerData->GetL1FrameMask());            
420       
421       if (!saveOnce && fTriggerData->GetL1DataDecoded()) 
422         {
423           int type[15] = {0};
424           fTriggerData->GetL1TriggerType(type);
425           
426           esd->SetCaloTriggerType(type);
427           
428           saveOnce = 1;
429         }
430     }
431   
432   // Resetting
433   fTriggerData->Reset();
434   
435   //########################################
436   //##############Fill CaloCells###############
437   //########################################
438   
439   //Get input digits and put them in fgDigitsArr, clear the list before 
440   ReadDigitsArrayFromTree(digitsTree);
441   
442   Int_t nDigits = fgDigitsArr->GetEntries(), idignew = 0 ;
443   AliDebug(1,Form("%d digits",nDigits));
444   
445   AliESDCaloCells &emcCells = *(esd->GetEMCALCells());
446   emcCells.CreateContainer(nDigits);
447   emcCells.SetType(AliVCaloCells::kEMCALCell);
448   
449   Float_t energy = 0;
450   Float_t time   = 0;
451   for (Int_t idig = 0 ; idig < nDigits ; idig++) 
452   {
453     const AliEMCALDigit * dig = (const AliEMCALDigit*)fgDigitsArr->At(idig);
454     time   = dig->GetTime();      // Time already calibrated in clusterizer
455     energy = dig->GetAmplitude(); // energy calibrated in clusterizer
456     
457     if(energy > 0 )
458     {
459       fgClusterizer->Calibrate(energy,time,dig->GetId()); //Digits already calibrated in clusterizers
460       
461       if(energy > 0) //Digits tagged as bad (dead, hot, not alive) are set to 0 in calibrate, remove them
462       { 
463         // Only for MC
464         // Get the label of the primary particle that generated the cell
465         // Assign the particle that deposited more energy
466         Int_t   nprimaries = dig->GetNprimary() ;
467         Int_t   digLabel   =-1 ;
468         Float_t edep       =-1.;
469         if ( nprimaries > 0 )
470         {
471           Int_t jndex ;
472           for ( jndex = 0 ; jndex < nprimaries ; jndex++ ) { // all primaries in digit
473  
474             if(edep < dig->GetDEParent(jndex+1))
475             {
476               digLabel = dig->GetIparent (jndex+1);
477               edep     = dig->GetDEParent(jndex+1);
478             }
479                    
480           } // all primaries in digit      
481         } // select primary label
482         
483         Bool_t highGain = kFALSE;
484         if( dig->GetType() == AliEMCALDigit::kHG ) highGain = kTRUE;
485         
486         emcCells.SetCell(idignew,dig->GetId(),energy, time,digLabel,0.,highGain);
487         idignew++;
488       }
489     }
490   }
491   
492   emcCells.SetNumberOfCells(idignew);
493   emcCells.Sort();
494   
495   //------------------------------------------------------------
496   //-----------------CLUSTERS-----------------------------
497   //------------------------------------------------------------
498   clustersTree->SetBranchStatus("*",0); //disable all branches
499   clustersTree->SetBranchStatus("EMCALECARP",1); //Enable only the branch we need
500   if(fgClustersArr) fgClustersArr->Clear();
501   TBranch *branch = clustersTree->GetBranch("EMCALECARP");
502   branch->SetAddress(&fgClustersArr);
503   branch->GetEntry(0);
504   //clustersTree->GetEvent(0);
505   
506   Int_t nClusters = fgClustersArr->GetEntries(),  nClustersNew=0;
507   AliDebug(1,Form("%d clusters",nClusters));
508
509   
510   //########################################
511   //##############Fill CaloClusters#############
512   //########################################
513   for (Int_t iClust = 0 ; iClust < nClusters ; iClust++) {
514     const AliEMCALRecPoint * clust = (const AliEMCALRecPoint*)fgClustersArr->At(iClust);
515     if(!clust) continue;
516     //if(clust->GetClusterType()== AliVCluster::kEMCALClusterv1) nRP++; else nPC++;
517     // clust->Print(); //For debugging
518     // Get information from EMCAL reconstruction points
519     Float_t xyz[3];
520     TVector3 gpos;
521     clust->GetGlobalPosition(gpos);
522     for (Int_t ixyz=0; ixyz<3; ixyz++)
523       xyz[ixyz] = gpos[ixyz];
524     Float_t elipAxis[2];
525     clust->GetElipsAxis(elipAxis);
526     //Create digits lists
527     Int_t cellMult = clust->GetMultiplicity();
528     //TArrayS digiList(digitMult);
529     Float_t *amplFloat = clust->GetEnergiesList();
530     Int_t   *digitInts = clust->GetAbsId();
531     TArrayS absIdList(cellMult);
532     TArrayD fracList(cellMult);
533     
534     Int_t newCellMult = 0;
535     for (Int_t iCell=0; iCell<cellMult; iCell++) {
536       if (amplFloat[iCell] > 0) {
537         absIdList[newCellMult] = (UShort_t)(digitInts[iCell]);
538         //Calculate Fraction
539         if(emcCells.GetCellAmplitude(digitInts[iCell])>0 && GetRecParam()->GetUnfold()){
540           fracList[newCellMult] = amplFloat[iCell]/(emcCells.GetCellAmplitude(digitInts[iCell]));//get cell calibration value 
541           
542         }
543         else{
544           fracList[newCellMult] = 0; 
545         }
546         newCellMult++;
547       }
548     }
549     
550     absIdList.Set(newCellMult);
551     fracList.Set(newCellMult);
552     
553     if(newCellMult > 0) { // accept cluster if it has some digit
554       nClustersNew++;
555       //Primaries
556       Int_t  parentMult  = 0;
557       Int_t *parentList =  clust->GetParents(parentMult);
558       // fills the ESDCaloCluster
559       AliESDCaloCluster * ec = new AliESDCaloCluster() ;
560       ec->SetType(AliVCluster::kEMCALClusterv1);
561       ec->SetPosition(xyz);
562       ec->SetE(clust->GetEnergy());
563       
564       //Distance to the nearest bad crystal
565       ec->SetDistanceToBadChannel(clust->GetDistanceToBadTower()); 
566       
567       ec->SetNCells(newCellMult);
568       //Change type of list from short to ushort
569       UShort_t *newAbsIdList  = new UShort_t[newCellMult];
570       Double_t *newFracList   = new Double_t[newCellMult];
571       for(Int_t i = 0; i < newCellMult ; i++) {
572         newAbsIdList[i]=absIdList[i];
573         newFracList[i] =fracList[i];
574       }
575       ec->SetCellsAbsId(newAbsIdList);
576       ec->SetCellsAmplitudeFraction(newFracList);
577       ec->SetDispersion(clust->GetDispersion());
578       ec->SetChi2(-1); //not yet implemented
579       ec->SetM02(elipAxis[0]*elipAxis[0]) ;
580       ec->SetM20(elipAxis[1]*elipAxis[1]) ;
581       ec->SetTOF(clust->GetTime()) ; //time-of-fligh
582       ec->SetNExMax(clust->GetNExMax());          //number of local maxima
583   
584       
585       TArrayI arrayParents(parentMult,parentList);
586       ec->AddLabels(arrayParents);
587       //
588       //Track matching
589       //
590       fMatches->Clear();
591       Int_t nTracks = esd->GetNumberOfTracks();
592       for (Int_t itrack = 0; itrack < nTracks; itrack++)
593         {
594           AliESDtrack * track = esd->GetTrack(itrack) ; // retrieve track
595           if(track->GetEMCALcluster()==iClust)
596             {
597               Float_t dEta=-999, dPhi=-999;
598               Bool_t isMatch =  CalculateResidual(track, ec, dEta, dPhi);
599               if(!isMatch) 
600                 {
601                   // AliDebug(10, "Not good");
602                   continue;
603                 }
604               AliEMCALMatch *match = new AliEMCALMatch();
605               match->SetIndexT(itrack);
606               match->SetDistance(TMath::Sqrt(dEta*dEta+dPhi*dPhi));
607               match->SetdEta(dEta);
608               match->SetdPhi(dPhi);
609               fMatches->Add(match);
610             }
611         } 
612       fMatches->Sort(kSortAscending); //Sort matched tracks from closest to furthest
613       Int_t nMatch = fMatches->GetEntries();
614       TArrayI arrayTrackMatched(nMatch);
615       for(Int_t imatch=0; imatch<nMatch; imatch++)
616         {
617           AliEMCALMatch *match = (AliEMCALMatch*)fMatches->At(imatch);
618           arrayTrackMatched[imatch] = match->GetIndexT();
619           if(imatch==0)
620             {
621               ec->SetTrackDistance(match->GetdPhi(), match->GetdEta());
622             }
623         }
624       ec->AddTracksMatched(arrayTrackMatched);
625     
626       //add the cluster to the esd object
627       esd->AddCaloCluster(ec);
628
629       delete ec;
630       delete [] newAbsIdList ;
631       delete [] newFracList ;
632     }
633   } // cycle on clusters
634
635   //
636   //Reset the index of matched cluster for tracks
637   //to the one in CaloCluster array
638   Int_t ncls = esd->GetNumberOfCaloClusters();
639   for(Int_t icl=0; icl<ncls; icl++)
640     {
641       AliESDCaloCluster *cluster = esd->GetCaloCluster(icl);
642       if(!cluster || !cluster->IsEMCAL()) continue;
643       TArrayI *trackIndex = cluster->GetTracksMatched();
644       for(Int_t itr=0; itr<trackIndex->GetSize(); itr++)
645         {
646           AliESDtrack *track = esd->GetTrack(trackIndex->At(itr));
647           track->SetEMCALcluster(cluster->GetID());
648         }
649     }
650   
651   
652   //Fill ESDCaloCluster with PID weights
653   AliEMCALPID *pid = new AliEMCALPID;
654   //pid->SetPrintInfo(kTRUE);
655   pid->SetReconstructor(kTRUE);
656   pid->RunPID(esd);
657   delete pid;
658   
659   //Store EMCAL misalignment matrixes
660   FillMisalMatrixes(esd) ;
661   
662 }
663
664 //==================================================================================
665 void AliEMCALReconstructor::FillMisalMatrixes(AliESDEvent* esd)const{
666   //Store EMCAL matrixes in ESD Header
667   
668   //Check, if matrixes was already stored
669   for(Int_t sm = 0 ; sm < fGeom->GetNumberOfSuperModules(); sm++){
670     if(esd->GetEMCALMatrix(sm)!=0)
671       return ;
672   }
673   
674   //Create and store matrixes
675   if(!gGeoManager){
676     AliError("Can not store misal. matrixes: no gGeoManager! \n") ;
677     return ;
678   }
679   //Note, that owner of copied marixes will be header
680   const Int_t bufsize = 255;
681   char path[bufsize] ;
682   TGeoHMatrix * m = 0x0;
683   Int_t tmpType = -1;
684   Int_t SMOrder = 0;
685   TString SMName;
686   for(Int_t sm = 0; sm < fGeom->GetNumberOfSuperModules(); sm++){
687     if(fGeom->GetSMType(sm) == AliEMCALGeometry::kEMCAL_Standard )      SMName = "SMOD";
688     else if(fGeom->GetSMType(sm) == AliEMCALGeometry::kEMCAL_Half )     SMName = "SM10";
689     else if(fGeom->GetSMType(sm) == AliEMCALGeometry::kEMCAL_3rd )      SMName = "SM3rd";
690     else if( fGeom->GetSMType(sm) == AliEMCALGeometry::kDCAL_Standard ) SMName = "DCSM";
691     else if( fGeom->GetSMType(sm) == AliEMCALGeometry::kDCAL_Ext )      SMName = "DCEXT";
692     else AliError("Unkown SM Type!!");
693
694     if(fGeom->GetSMType(sm) == tmpType) {
695       SMOrder++;
696     } else {
697       tmpType = fGeom->GetSMType(sm);
698       SMOrder = 1;
699     }
700     snprintf(path,bufsize,"/ALIC_1/XEN1_1/%s_%d", SMName.Data(), SMOrder) ;
701
702     if (gGeoManager->CheckPath(path)){
703       gGeoManager->cd(path);
704       m = gGeoManager->GetCurrentMatrix() ;
705       //                        printf("================================================= \n");
706       //                        printf("AliEMCALReconstructor::FixMisalMatrixes(), sm %d, \n",sm);
707       //                        m->Print("");
708       esd->SetEMCALMatrix(new TGeoHMatrix(*m),sm) ;
709       //                        printf("================================================= \n");
710     }
711     else{
712       esd->SetEMCALMatrix(NULL,sm) ;
713     }
714   }
715 }
716
717 //__________________________________________________________________________
718 void AliEMCALReconstructor::ReadDigitsArrayFromTree(TTree *digitsTree) const
719 {
720   // Read the digits from the input tree
721   // See AliEMCALClusterizer::SetInput(TTree *digitsTree);    
722   
723   // Clear previous digits in the list
724   if(fgDigitsArr){ 
725     fgDigitsArr->Clear("C");
726   }
727   else{
728     // It should not happen, but just in case ...
729     fgDigitsArr = new TClonesArray("AliEMCALDigit",100); 
730   }
731   
732   // Read the digits from the input tree
733   TBranch *branch = digitsTree->GetBranch("EMCAL");
734   if (!branch) { 
735     AliError("can't get the branch with the EMCAL digits !");
736     return;
737   }  
738   
739   branch->SetAddress(&fgDigitsArr);
740   branch->GetEntry(0);
741 }
742
743 //==================================================================================
744 Bool_t AliEMCALReconstructor::CalculateResidual(AliESDtrack *track, AliESDCaloCluster *cluster, Float_t &dEta, Float_t &dPhi)const
745 {
746   //
747   // calculate the residual between track and cluster
748   //
749
750   // If the esdFriend is available, use the TPCOuter point as the starting point of extrapolation
751   // Otherwise use the TPCInner point
752
753   dEta = -999, dPhi = -999;
754   Bool_t ITSTrackSA = 0;
755
756   AliExternalTrackParam *trkParam = 0;
757   
758   const AliESDfriendTrack*  friendTrack = track->GetFriendTrack();
759   if(friendTrack && friendTrack->GetTPCOut())
760     trkParam = const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
761   else if(track->GetInnerParam())
762     trkParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
763   else{
764     trkParam = new AliExternalTrackParam(*track); //If there is ITSSa track 
765     ITSTrackSA = 1;     
766   }
767   if(!trkParam) return kFALSE;
768   
769   AliExternalTrackParam trkParamTmp (*trkParam);
770   if(!AliEMCALRecoUtils::ExtrapolateTrackToCluster(&trkParamTmp, cluster, track->GetMass(kTRUE), GetRecParam()->GetExtrapolateStep(), dEta, dPhi)){
771         if(ITSTrackSA) delete trkParam;
772         return kFALSE;
773   }
774
775   if(ITSTrackSA) delete trkParam;
776   return kTRUE;
777 }
778
779 //
780 //==================================================================================
781 //
782 AliEMCALReconstructor::AliEMCALMatch::AliEMCALMatch() 
783   : TObject(),  
784     fIndexT(-1), 
785     fDistance(-999.),
786     fdEta(-999.),
787     fdPhi(-999.)
788 {
789   //default constructor
790
791 }
792
793 //
794 //==================================================================================
795 //
796 AliEMCALReconstructor::AliEMCALMatch::AliEMCALMatch(const AliEMCALMatch& copy)
797   : TObject(),
798     fIndexT(copy.fIndexT),
799     fDistance(copy.fDistance),
800     fdEta(copy.fdEta),
801     fdPhi(copy.fdPhi)
802 {
803   //copy ctor
804 }
805 //_____________________________________________________________________
806 AliEMCALReconstructor::AliEMCALMatch& AliEMCALReconstructor::AliEMCALMatch::AliEMCALMatch::operator = (const AliEMCALMatch &source)
807 { // assignment operator; use copy ctor
808   if (&source == this) return *this;
809
810   new (this) AliEMCALMatch(source);
811   return *this;
812 }
813 //
814 //==================================================================================
815 //
816 Int_t AliEMCALReconstructor::AliEMCALMatch::Compare(const TObject *obj) const 
817 {
818   //
819   // Compare wrt the residual
820   //
821         
822   AliEMCALReconstructor::AliEMCALMatch *that = (AliEMCALReconstructor::AliEMCALMatch*)obj;
823         
824   Double_t thisDist = fDistance;//fDistance;
825   Double_t thatDist = that->fDistance;//that->GetDistance();
826         
827   if (thisDist > thatDist) return 1;
828   else if (thisDist < thatDist) return -1;
829   return 0;
830 }