]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALReconstructor.cxx
remove unnecessary commented line
[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   fgTriggerDigits = new TClonesArray("AliEMCALTriggerRawDigit",1000);   
139
140   //Track matching
141   fMatches = new TList();
142   fMatches->SetOwner(kTRUE);
143
144
145 //____________________________________________________________________________
146 AliEMCALReconstructor::~AliEMCALReconstructor()
147 {
148   // dtor
149
150   //AliDebug(2, "Mark.");
151
152   if(fGeom)              delete fGeom;
153   
154   //No need to delete, recovered from OCDB
155   //if(fCalibData)         delete fCalibData;
156   //if(fPedestalData)      delete fPedestalData;
157   
158   if(fgDigitsArr){
159     fgDigitsArr->Clear("C");
160     delete fgDigitsArr; 
161   }
162   
163   if(fgClustersArr){
164     fgClustersArr->Clear();
165     delete fgClustersArr; 
166   }
167   
168   if(fgTriggerDigits){
169     fgTriggerDigits->Clear();
170     delete fgTriggerDigits; 
171   }
172   
173   if(fgRawUtils)         delete fgRawUtils;
174   if(fgClusterizer)      delete fgClusterizer;
175   if(fgTriggerProcessor) delete fgTriggerProcessor;
176   
177   if(fMatches) { fMatches->Delete(); delete fMatches; fMatches = 0;}
178   
179   AliCodeTimer::Instance()->Print();
180
181
182 //____________________________________________________________________________                                  
183 void AliEMCALReconstructor::InitClusterizer() const
184 {
185   //Init the clusterizer with geometry and calibration pointers, avoid doing it twice.                          
186   Int_t clusterizerType = -1;
187   Int_t eventType = -1;
188   if(GetRecParam()) {
189     clusterizerType = GetRecParam()->GetClusterizerFlag();
190     eventType       = GetRecParam()->GetEventSpecie();
191   }
192   else{
193     AliCDBEntry *entry = (AliCDBEntry*)
194       AliCDBManager::Instance()->Get("EMCAL/Calib/RecoParam");
195     //Get The reco param for the default event specie                                                           
196     if (entry) {
197       AliEMCALRecParam *recParam  = (AliEMCALRecParam*)((TObjArray *) entry->GetObject())->At(0);
198       if(recParam) clusterizerType = recParam->GetClusterizerFlag(); 
199     }
200   }
201   
202   //Check if clusterizer previously set corresponds to what is needed for this event type                       
203   if(fgClusterizer){
204     if(eventType!=AliRecoParam::kCalib){
205       //printf("ReCreate clusterizer? Clusterizer set <%d>, Clusterizer in use <%s>\n",
206       //     clusterizerType, fgClusterizer->Version());
207       
208       if     (clusterizerType == AliEMCALRecParam::kClusterizerv1  && !strcmp(fgClusterizer->Version(),"clu-v1"))  return;
209       
210       else if(clusterizerType == AliEMCALRecParam::kClusterizerNxN && !strcmp(fgClusterizer->Version(),"clu-NxN")) return;
211       
212       else if(clusterizerType == AliEMCALRecParam::kClusterizerv2  && !strcmp(fgClusterizer->Version(),"clu-v2"))  return;
213       
214       //Need to create new clusterizer, the one set previously is not the correct one     
215       delete fgClusterizer;
216     }
217     else return;
218   }
219   
220   if      (clusterizerType  == AliEMCALRecParam::kClusterizerv1)
221     {
222       fgClusterizer = new AliEMCALClusterizerv1 (fGeom, fCalibData,fPedestalData);
223     }
224   else if (clusterizerType  == AliEMCALRecParam::kClusterizerNxN)
225     {
226       fgClusterizer = new AliEMCALClusterizerNxN(fGeom, fCalibData,fPedestalData);
227     }
228   else if (clusterizerType  == AliEMCALRecParam::kClusterizerv2)
229   {
230     fgClusterizer = new AliEMCALClusterizerv2   (fGeom, fCalibData,fPedestalData);
231   }
232   else 
233   {
234     AliFatal(Form("Unknown clusterizer %d ", clusterizerType));
235   }
236 }
237
238 //____________________________________________________________________________
239 void AliEMCALReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const
240 {
241   // method called by AliReconstruction; 
242   // Only the clusterization is performed,; the rest of the reconstruction is done in FillESD because the track
243   // segment maker needs access to the AliESD object to retrieve the tracks reconstructed by 
244   // the global tracking.
245   // Works on the current event.
246   
247   AliCodeTimerAuto("",0)
248     
249   //Get input digits and put them in fgDigitsArr, clear the list before 
250   ReadDigitsArrayFromTree(digitsTree);
251   
252   InitClusterizer();
253   
254   fgClusterizer->InitParameters();
255   fgClusterizer->SetOutput(clustersTree);
256   
257   //Skip clusterization of LED events
258   if (GetRecParam()->GetEventSpecie()!=AliRecoParam::kCalib){
259     
260     if(fgDigitsArr && fgDigitsArr->GetEntries()) {
261       
262       fgClusterizer->SetInput(digitsTree);
263       
264       //fgClusterizer->Digits2Clusters("deb all") ; //For debugging
265       fgClusterizer->Digits2Clusters("");
266       
267       fgClusterizer->Clear();
268       
269     }//digits array exists and has somethind
270   }//not a LED event
271   
272   clustersTree->Fill(); 
273
274   // Deleting the recpoints at the end of the reconstruction call
275   fgClusterizer->DeleteRecPoints();
276 }
277
278 //____________________________________________________________________________
279 void AliEMCALReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
280   
281 {
282   // Conversion from raw data to
283   // EMCAL digits.
284   // Works on a single-event basis
285   
286   rawReader->Reset() ; 
287   
288   fTriggerData->SetMode(1);     
289   
290   if(fgDigitsArr) fgDigitsArr->Clear("C");
291   
292   TClonesArray *digitsTrg = new TClonesArray("AliEMCALTriggerRawDigit", 32 * 96);
293   
294   Int_t bufsize = 32000;
295   digitsTree->Branch("EMCAL", &fgDigitsArr, bufsize);
296   digitsTree->Branch("EMTRG", &digitsTrg, bufsize);
297   
298   //Skip calibration events do the rest
299   Bool_t doFit = kTRUE;
300   if ( !(GetRecParam()->FitLEDEvents()) && GetRecParam()->GetEventSpecie()==AliRecoParam::kCalib) doFit = kFALSE;
301   if (doFit){
302     //must be done here because, in constructor, option is not yet known
303     fgRawUtils->SetOption(GetOption());
304     
305     //  fgRawUtils->SetRawFormatHighLowGainFactor(GetRecParam()->GetHighLowGainFactor());
306     
307     //   fgRawUtils->SetRawFormatOrder(GetRecParam()->GetOrderParameter());
308     //    fgRawUtils->SetRawFormatTau(GetRecParam()->GetTau());
309     fgRawUtils->SetNoiseThreshold(GetRecParam()->GetNoiseThreshold());
310     fgRawUtils->SetNPedSamples(GetRecParam()->GetNPedSamples());
311     fgRawUtils->SetRemoveBadChannels(GetRecParam()->GetRemoveBadChannels());
312     if (!fgRawUtils->GetFittingAlgorithm()) fgRawUtils->SetFittingAlgorithm(GetRecParam()->GetFittingAlgorithm());
313     fgRawUtils->SetFALTROUsage(GetRecParam()->UseFALTRO());
314     
315     //fgRawUtils->SetTimeMin(GetRecParam()->GetTimeMin());
316     //fgRawUtils->SetTimeMax(GetRecParam()->GetTimeMax());
317     
318     //  fgRawUtils->SetTimeMin(-99999 );
319     //  fgRawUtils->SetTimeMax( 99999 );
320     
321     fgRawUtils->Raw2Digits(rawReader,fgDigitsArr,fPedestalData,digitsTrg,fTriggerData);
322     
323   }//skip calibration event
324   else{
325     AliDebug(1," Calibration Event, skip!");
326   }
327   
328   digitsTree->Fill();
329   digitsTrg->Delete();
330   delete digitsTrg;
331   
332 }
333
334
335 //____________________________________________________________________________
336 void AliEMCALReconstructor::FillESD(TTree* digitsTree, TTree* clustersTree, 
337                                     AliESDEvent* esd) const
338 {
339   // Called by AliReconstruct after Reconstruct() and global tracking and vertexing 
340   // and V0 
341   // Works on the current event
342   // printf(" ## AliEMCALReconstructor::FillESD() is started ### \n ");
343   //return;
344   
345   //########################################
346   // Trigger
347   //########################################
348   
349   static int saveOnce = 0;
350   
351   Int_t v0M[2] = {0, 0};
352   
353   AliESDVZERO* esdV0 = esd->GetVZEROData();
354   
355   if (esdV0) 
356     {
357       for (Int_t i = 0; i < 32; i++)
358         {
359           v0M[0] += (Int_t)esdV0->GetAdcV0C(i);
360           v0M[1] += (Int_t)esdV0->GetAdcV0A(i);
361         }
362     }
363   else
364     {
365       AliWarning("Cannot retrieve V0 ESD! Run w/ null V0 charges");
366     }
367   
368   if (fgTriggerDigits) fgTriggerDigits->Clear();
369   
370   TBranch *branchtrg = digitsTree->GetBranch("EMTRG");
371   
372   if (!branchtrg) 
373     { 
374       AliError("Can't get the branch with the EMCAL trigger digits!");
375       return;
376     }
377   
378   branchtrg->SetAddress(&fgTriggerDigits);
379   branchtrg->GetEntry(0);
380   
381   // Note: fgTriggerProcessor reset done at the end of this method
382 //   fgTriggerProcessor->Digits2Trigger(fgTriggerDigits, v0M, fTriggerData);
383   
384   // Fill ESD
385   AliESDCaloTrigger* trgESD = esd->GetCaloTrigger("EMCAL");
386   
387   if (trgESD)
388     {
389       trgESD->Allocate(fgTriggerDigits->GetEntriesFast());
390       
391       for (Int_t i = 0; i < fgTriggerDigits->GetEntriesFast(); i++)
392         {         
393           AliEMCALTriggerRawDigit* rdig = (AliEMCALTriggerRawDigit*)fgTriggerDigits->At(i);
394           
395           Int_t px, py;
396           if (fGeom->GetPositionInEMCALFromAbsFastORIndex(rdig->GetId(), px, py))
397             {
398               Int_t a = -1, t = -1, times[10]; 
399               
400               rdig->GetMaximum(a, t);
401               rdig->GetL0Times(times);
402               
403               trgESD->Add(px, py, a, t, times, rdig->GetNL0Times(), rdig->GetL1TimeSum(), rdig->GetTriggerBits());
404             }
405         }
406       
407       trgESD->SetL1Threshold(0, fTriggerData->GetL1GammaThreshold());
408       
409       trgESD->SetL1Threshold(1, fTriggerData->GetL1JetThreshold()  );
410       
411       Int_t v0[2];
412       fTriggerData->GetL1V0(v0);
413       
414       trgESD->SetL1V0(v0);      
415       trgESD->SetL1FrameMask(fTriggerData->GetL1FrameMask());            
416       
417       if (!saveOnce && fTriggerData->GetL1DataDecoded()) 
418         {
419           int type[8] = {0};
420           fTriggerData->GetL1TriggerType(type);
421           
422           esd->SetCaloTriggerType(type);
423           
424           saveOnce = 1;
425         }
426     }
427   
428   // Resetting
429   fTriggerData->Reset();
430   
431   //########################################
432   //##############Fill CaloCells###############
433   //########################################
434   
435   //Get input digits and put them in fgDigitsArr, clear the list before 
436   ReadDigitsArrayFromTree(digitsTree);
437   
438   Int_t nDigits = fgDigitsArr->GetEntries(), idignew = 0 ;
439   AliDebug(1,Form("%d digits",nDigits));
440   AliESDCaloCells &emcCells = *(esd->GetEMCALCells());
441   emcCells.CreateContainer(nDigits);
442   emcCells.SetType(AliVCaloCells::kEMCALCell);
443   Float_t energy = 0;
444   Float_t time   = 0;
445   for (Int_t idig = 0 ; idig < nDigits ; idig++) {
446     const AliEMCALDigit * dig = (const AliEMCALDigit*)fgDigitsArr->At(idig);
447     time   = dig->GetTime();      // Time already calibrated in clusterizer
448     energy = dig->GetAmplitude(); // energy calibrated in clusterizer
449     if(energy > 0 ){
450       fgClusterizer->Calibrate(energy,time,dig->GetId()); //Digits already calibrated in clusterizers
451       if(energy > 0){ //Digits tagged as bad (dead, hot, not alive) are set to 0 in calibrate, remove them
452         emcCells.SetCell(idignew,dig->GetId(),energy, time);   
453         idignew++;
454       }
455     }
456   }
457   emcCells.SetNumberOfCells(idignew);
458   emcCells.Sort();
459   
460   //------------------------------------------------------------
461   //-----------------CLUSTERS-----------------------------
462   //------------------------------------------------------------
463   clustersTree->SetBranchStatus("*",0); //disable all branches
464   clustersTree->SetBranchStatus("EMCALECARP",1); //Enable only the branch we need
465   if(fgClustersArr) fgClustersArr->Clear();
466   TBranch *branch = clustersTree->GetBranch("EMCALECARP");
467   branch->SetAddress(&fgClustersArr);
468   branch->GetEntry(0);
469   //clustersTree->GetEvent(0);
470   
471   Int_t nClusters = fgClustersArr->GetEntries(),  nClustersNew=0;
472   AliDebug(1,Form("%d clusters",nClusters));
473
474   
475   //########################################
476   //##############Fill CaloClusters#############
477   //########################################
478   for (Int_t iClust = 0 ; iClust < nClusters ; iClust++) {
479     const AliEMCALRecPoint * clust = (const AliEMCALRecPoint*)fgClustersArr->At(iClust);
480     if(!clust) continue;
481     //if(clust->GetClusterType()== AliVCluster::kEMCALClusterv1) nRP++; else nPC++;
482     // clust->Print(); //For debugging
483     // Get information from EMCAL reconstruction points
484     Float_t xyz[3];
485     TVector3 gpos;
486     clust->GetGlobalPosition(gpos);
487     for (Int_t ixyz=0; ixyz<3; ixyz++)
488       xyz[ixyz] = gpos[ixyz];
489     Float_t elipAxis[2];
490     clust->GetElipsAxis(elipAxis);
491     //Create digits lists
492     Int_t cellMult = clust->GetMultiplicity();
493     //TArrayS digiList(digitMult);
494     Float_t *amplFloat = clust->GetEnergiesList();
495     Int_t   *digitInts = clust->GetAbsId();
496     TArrayS absIdList(cellMult);
497     TArrayD fracList(cellMult);
498     
499     Int_t newCellMult = 0;
500     for (Int_t iCell=0; iCell<cellMult; iCell++) {
501       if (amplFloat[iCell] > 0) {
502         absIdList[newCellMult] = (UShort_t)(digitInts[iCell]);
503         //Calculate Fraction
504         if(emcCells.GetCellAmplitude(digitInts[iCell])>0 && GetRecParam()->GetUnfold()){
505           fracList[newCellMult] = amplFloat[iCell]/(emcCells.GetCellAmplitude(digitInts[iCell]));//get cell calibration value 
506           
507         }
508         else{
509           fracList[newCellMult] = 0; 
510         }
511         newCellMult++;
512       }
513     }
514     
515     absIdList.Set(newCellMult);
516     fracList.Set(newCellMult);
517     
518     if(newCellMult > 0) { // accept cluster if it has some digit
519       nClustersNew++;
520       //Primaries
521       Int_t  parentMult  = 0;
522       Int_t *parentList =  clust->GetParents(parentMult);
523       // fills the ESDCaloCluster
524       AliESDCaloCluster * ec = new AliESDCaloCluster() ;
525       ec->SetType(AliVCluster::kEMCALClusterv1);
526       ec->SetPosition(xyz);
527       ec->SetE(clust->GetEnergy());
528       
529       //Distance to the nearest bad crystal
530       ec->SetDistanceToBadChannel(clust->GetDistanceToBadTower()); 
531       
532       ec->SetNCells(newCellMult);
533       //Change type of list from short to ushort
534       UShort_t *newAbsIdList  = new UShort_t[newCellMult];
535       Double_t *newFracList   = new Double_t[newCellMult];
536       for(Int_t i = 0; i < newCellMult ; i++) {
537         newAbsIdList[i]=absIdList[i];
538         newFracList[i] =fracList[i];
539       }
540       ec->SetCellsAbsId(newAbsIdList);
541       ec->SetCellsAmplitudeFraction(newFracList);
542       ec->SetDispersion(clust->GetDispersion());
543       ec->SetChi2(-1); //not yet implemented
544       ec->SetM02(elipAxis[0]*elipAxis[0]) ;
545       ec->SetM20(elipAxis[1]*elipAxis[1]) ;
546       ec->SetTOF(clust->GetTime()) ; //time-of-fligh
547       ec->SetNExMax(clust->GetNExMax());          //number of local maxima
548   
549       
550       TArrayI arrayParents(parentMult,parentList);
551       ec->AddLabels(arrayParents);
552       //
553       //Track matching
554       //
555       fMatches->Clear();
556       Int_t nTracks = esd->GetNumberOfTracks();
557       for (Int_t itrack = 0; itrack < nTracks; itrack++)
558         {
559           AliESDtrack * track = esd->GetTrack(itrack) ; // retrieve track
560           if(track->GetEMCALcluster()==iClust)
561             {
562               Float_t dEta=-999, dPhi=-999;
563               Bool_t isMatch =  CalculateResidual(track, ec, dEta, dPhi);
564               if(!isMatch) 
565                 {
566                   // AliDebug(10, "Not good");
567                   continue;
568                 }
569               AliEMCALMatch *match = new AliEMCALMatch();
570               match->SetIndexT(itrack);
571               match->SetDistance(TMath::Sqrt(dEta*dEta+dPhi*dPhi));
572               match->SetdEta(dEta);
573               match->SetdPhi(dPhi);
574               fMatches->Add(match);
575             }
576         } 
577       fMatches->Sort(kSortAscending); //Sort matched tracks from closest to furthest
578       Int_t nMatch = fMatches->GetEntries();
579       TArrayI arrayTrackMatched(nMatch);
580       for(Int_t imatch=0; imatch<nMatch; imatch++)
581         {
582           AliEMCALMatch *match = (AliEMCALMatch*)fMatches->At(imatch);
583           arrayTrackMatched[imatch] = match->GetIndexT();
584           if(imatch==0)
585             {
586               ec->SetTrackDistance(match->GetdPhi(), match->GetdEta());
587             }
588         }
589       ec->AddTracksMatched(arrayTrackMatched);
590     
591       //add the cluster to the esd object
592       esd->AddCaloCluster(ec);
593
594       delete ec;
595       delete [] newAbsIdList ;
596       delete [] newFracList ;
597     }
598   } // cycle on clusters
599
600   //
601   //Reset the index of matched cluster for tracks
602   //to the one in CaloCluster array
603   Int_t ncls = esd->GetNumberOfCaloClusters();
604   for(Int_t icl=0; icl<ncls; icl++)
605     {
606       AliESDCaloCluster *cluster = esd->GetCaloCluster(icl);
607       if(!cluster || !cluster->IsEMCAL()) continue;
608       TArrayI *trackIndex = cluster->GetTracksMatched();
609       for(Int_t itr=0; itr<trackIndex->GetSize(); itr++)
610         {
611           AliESDtrack *track = esd->GetTrack(trackIndex->At(itr));
612           track->SetEMCALcluster(cluster->GetID());
613         }
614     }
615   
616   
617   //Fill ESDCaloCluster with PID weights
618   AliEMCALPID *pid = new AliEMCALPID;
619   //pid->SetPrintInfo(kTRUE);
620   pid->SetReconstructor(kTRUE);
621   pid->RunPID(esd);
622   delete pid;
623   
624   //Store EMCAL misalignment matrixes
625   FillMisalMatrixes(esd) ;
626   
627 }
628
629 //==================================================================================
630 void AliEMCALReconstructor::FillMisalMatrixes(AliESDEvent* esd)const{
631   //Store EMCAL matrixes in ESD Header
632   
633   //Check, if matrixes was already stored
634   for(Int_t sm = 0 ; sm < fGeom->GetNumberOfSuperModules(); sm++){
635     if(esd->GetEMCALMatrix(sm)!=0)
636       return ;
637   }
638   
639   //Create and store matrixes
640   if(!gGeoManager){
641     AliError("Can not store misal. matrixes: no gGeoManager! \n") ;
642     return ;
643   }
644   //Note, that owner of copied marixes will be header
645   const Int_t bufsize = 255;
646   char path[bufsize] ;
647   TGeoHMatrix * m = 0x0;
648   for(Int_t sm = 0; sm < fGeom->GetNumberOfSuperModules(); sm++){
649     snprintf(path,bufsize,"/ALIC_1/XEN1_1/SMOD_%d",sm+1) ; //In Geometry modules numbered 1,2,.,5
650     if(sm >= 10) snprintf(path,bufsize,"/ALIC_1/XEN1_1/SM10_%d",sm-10+1) ;
651     
652     if (gGeoManager->CheckPath(path)){
653       gGeoManager->cd(path);
654       m = gGeoManager->GetCurrentMatrix() ;
655       //                        printf("================================================= \n");
656       //                        printf("AliEMCALReconstructor::FixMisalMatrixes(), sm %d, \n",sm);
657       //                        m->Print("");
658       esd->SetEMCALMatrix(new TGeoHMatrix(*m),sm) ;
659       //                        printf("================================================= \n");
660     }
661     else{
662       esd->SetEMCALMatrix(NULL,sm) ;
663     }
664   }
665 }
666
667 //__________________________________________________________________________
668 void AliEMCALReconstructor::ReadDigitsArrayFromTree(TTree *digitsTree) const
669 {
670   // Read the digits from the input tree
671   // See AliEMCALClusterizer::SetInput(TTree *digitsTree);    
672   
673   // Clear previous digits in the list
674   if(fgDigitsArr){ 
675     fgDigitsArr->Clear("C");
676   }
677   else{
678     // It should not happen, but just in case ...
679     fgDigitsArr = new TClonesArray("AliEMCALDigit",100); 
680   }
681   
682   // Read the digits from the input tree
683   TBranch *branch = digitsTree->GetBranch("EMCAL");
684   if (!branch) { 
685     AliError("can't get the branch with the EMCAL digits !");
686     return;
687   }  
688   
689   branch->SetAddress(&fgDigitsArr);
690   branch->GetEntry(0);
691 }
692
693 //==================================================================================
694 Bool_t AliEMCALReconstructor::CalculateResidual(AliESDtrack *track, AliESDCaloCluster *cluster, Float_t &dEta, Float_t &dPhi)const
695 {
696   //
697   // calculate the residual between track and cluster
698   //
699
700   // If the esdFriend is available, use the TPCOuter point as the starting point of extrapolation
701   // Otherwise use the TPCInner point
702
703   dEta = -999, dPhi = -999;
704
705   AliExternalTrackParam *trkParam = 0;
706   const AliESDfriendTrack*  friendTrack = track->GetFriendTrack();
707   if(friendTrack && friendTrack->GetTPCOut())
708     trkParam = const_cast<AliExternalTrackParam*>(friendTrack->GetTPCOut());
709   else
710     trkParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());
711   if(!trkParam) return kFALSE;
712
713   AliExternalTrackParam trkParamTmp (*trkParam);
714   if(!AliEMCALRecoUtils::ExtrapolateTrackToCluster(&trkParamTmp, cluster, track->GetMass(), GetRecParam()->GetExtrapolateStep(), dEta, dPhi)) return kFALSE;
715
716   return kTRUE;
717 }
718
719 //
720 //==================================================================================
721 //
722 AliEMCALReconstructor::AliEMCALMatch::AliEMCALMatch() 
723   : TObject(),  
724     fIndexT(-1), 
725     fDistance(-999.),
726     fdEta(-999.),
727     fdPhi(-999.)
728 {
729   //default constructor
730
731 }
732
733 //
734 //==================================================================================
735 //
736 AliEMCALReconstructor::AliEMCALMatch::AliEMCALMatch(const AliEMCALMatch& copy)
737   : TObject(),
738     fIndexT(copy.fIndexT),
739     fDistance(copy.fDistance),
740     fdEta(copy.fdEta),
741     fdPhi(copy.fdPhi)
742 {
743   //copy ctor
744 }
745
746 //
747 //==================================================================================
748 //
749 Int_t AliEMCALReconstructor::AliEMCALMatch::Compare(const TObject *obj) const 
750 {
751   //
752   // Compare wrt the residual
753   //
754         
755   AliEMCALReconstructor::AliEMCALMatch *that = (AliEMCALReconstructor::AliEMCALMatch*)obj;
756         
757   Double_t thisDist = fDistance;//fDistance;
758   Double_t thatDist = that->fDistance;//that->GetDistance();
759         
760   if (thisDist > thatDist) return 1;
761   else if (thisDist < thatDist) return -1;
762   return 0;
763 }