]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALReconstructor.cxx
Changes for #93916 EMCAL commit attached patch and port to the release
[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", 32 * 96);       
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                 v0M[0] = esdV0->GetTriggerChargeC();
358                 v0M[1] = esdV0->GetTriggerChargeA();
359     }
360   else
361     {
362       AliWarning("No V0 ESD! Run trigger processor w/ null V0 charges");
363     }
364   
365   if (fgTriggerDigits && fgTriggerDigits->GetEntriesFast()) fgTriggerDigits->Delete();
366   
367   TBranch *branchtrg = digitsTree->GetBranch("EMTRG");
368   
369   if (!branchtrg) 
370     { 
371       AliError("Can't get the branch with the EMCAL trigger digits!");
372       return;
373     }
374   
375   branchtrg->SetAddress(&fgTriggerDigits);
376   branchtrg->GetEntry(0);
377   
378   // Note: fgTriggerProcessor reset done at the end of this method
379   fgTriggerProcessor->Digits2Trigger(fgTriggerDigits, v0M, fTriggerData);
380   
381   // Fill ESD
382   AliESDCaloTrigger* trgESD = esd->GetCaloTrigger("EMCAL");
383   
384   if (trgESD)
385     {
386       trgESD->Allocate(fgTriggerDigits->GetEntriesFast());
387       
388       for (Int_t i = 0; i < fgTriggerDigits->GetEntriesFast(); i++)
389         {         
390           AliEMCALTriggerRawDigit* rdig = (AliEMCALTriggerRawDigit*)fgTriggerDigits->At(i);
391           if (AliDebugLevel() > 999) rdig->Print("");
392                 
393           Int_t px, py;
394           if (fGeom->GetPositionInEMCALFromAbsFastORIndex(rdig->GetId(), px, py))
395             {
396               Int_t a = -1, t = -1, times[10]; 
397               
398               rdig->GetMaximum(a, t);
399               rdig->GetL0Times(times);
400                         
401               trgESD->Add(px, py, a, t, times, rdig->GetNL0Times(), rdig->GetL1TimeSum(), rdig->GetTriggerBits());
402             }
403         }
404       
405                 for (int i = 0; i < 2; i++) {
406                         trgESD->SetL1Threshold(2 * i    , fTriggerData->GetL1JetThreshold(  i));
407                         trgESD->SetL1Threshold(2 * i + 1, fTriggerData->GetL1GammaThreshold(i));
408                 }
409       
410       Int_t v0[2];
411       fTriggerData->GetL1V0(v0);
412       
413       trgESD->SetL1V0(v0);      
414       trgESD->SetL1FrameMask(fTriggerData->GetL1FrameMask());            
415       
416       if (!saveOnce && fTriggerData->GetL1DataDecoded()) 
417         {
418           int type[15] = {0};
419           fTriggerData->GetL1TriggerType(type);
420           
421           esd->SetCaloTriggerType(type);
422           
423           saveOnce = 1;
424         }
425     }
426   
427   // Resetting
428   fTriggerData->Reset();
429   
430   //########################################
431   //##############Fill CaloCells###############
432   //########################################
433   
434   //Get input digits and put them in fgDigitsArr, clear the list before 
435   ReadDigitsArrayFromTree(digitsTree);
436   
437   Int_t nDigits = fgDigitsArr->GetEntries(), idignew = 0 ;
438   AliDebug(1,Form("%d digits",nDigits));
439   AliESDCaloCells &emcCells = *(esd->GetEMCALCells());
440   emcCells.CreateContainer(nDigits);
441   emcCells.SetType(AliVCaloCells::kEMCALCell);
442   Float_t energy = 0;
443   Float_t time   = 0;
444   for (Int_t idig = 0 ; idig < nDigits ; idig++) {
445     const AliEMCALDigit * dig = (const AliEMCALDigit*)fgDigitsArr->At(idig);
446     time   = dig->GetTime();      // Time already calibrated in clusterizer
447     energy = dig->GetAmplitude(); // energy calibrated in clusterizer
448     if(energy > 0 ){
449       fgClusterizer->Calibrate(energy,time,dig->GetId()); //Digits already calibrated in clusterizers
450       if(energy > 0){ //Digits tagged as bad (dead, hot, not alive) are set to 0 in calibrate, remove them
451         emcCells.SetCell(idignew,dig->GetId(),energy, time);   
452         idignew++;
453       }
454     }
455   }
456   emcCells.SetNumberOfCells(idignew);
457   emcCells.Sort();
458   
459   //------------------------------------------------------------
460   //-----------------CLUSTERS-----------------------------
461   //------------------------------------------------------------
462   clustersTree->SetBranchStatus("*",0); //disable all branches
463   clustersTree->SetBranchStatus("EMCALECARP",1); //Enable only the branch we need
464   if(fgClustersArr) fgClustersArr->Clear();
465   TBranch *branch = clustersTree->GetBranch("EMCALECARP");
466   branch->SetAddress(&fgClustersArr);
467   branch->GetEntry(0);
468   //clustersTree->GetEvent(0);
469   
470   Int_t nClusters = fgClustersArr->GetEntries(),  nClustersNew=0;
471   AliDebug(1,Form("%d clusters",nClusters));
472
473   
474   //########################################
475   //##############Fill CaloClusters#############
476   //########################################
477   for (Int_t iClust = 0 ; iClust < nClusters ; iClust++) {
478     const AliEMCALRecPoint * clust = (const AliEMCALRecPoint*)fgClustersArr->At(iClust);
479     if(!clust) continue;
480     //if(clust->GetClusterType()== AliVCluster::kEMCALClusterv1) nRP++; else nPC++;
481     // clust->Print(); //For debugging
482     // Get information from EMCAL reconstruction points
483     Float_t xyz[3];
484     TVector3 gpos;
485     clust->GetGlobalPosition(gpos);
486     for (Int_t ixyz=0; ixyz<3; ixyz++)
487       xyz[ixyz] = gpos[ixyz];
488     Float_t elipAxis[2];
489     clust->GetElipsAxis(elipAxis);
490     //Create digits lists
491     Int_t cellMult = clust->GetMultiplicity();
492     //TArrayS digiList(digitMult);
493     Float_t *amplFloat = clust->GetEnergiesList();
494     Int_t   *digitInts = clust->GetAbsId();
495     TArrayS absIdList(cellMult);
496     TArrayD fracList(cellMult);
497     
498     Int_t newCellMult = 0;
499     for (Int_t iCell=0; iCell<cellMult; iCell++) {
500       if (amplFloat[iCell] > 0) {
501         absIdList[newCellMult] = (UShort_t)(digitInts[iCell]);
502         //Calculate Fraction
503         if(emcCells.GetCellAmplitude(digitInts[iCell])>0 && GetRecParam()->GetUnfold()){
504           fracList[newCellMult] = amplFloat[iCell]/(emcCells.GetCellAmplitude(digitInts[iCell]));//get cell calibration value 
505           
506         }
507         else{
508           fracList[newCellMult] = 0; 
509         }
510         newCellMult++;
511       }
512     }
513     
514     absIdList.Set(newCellMult);
515     fracList.Set(newCellMult);
516     
517     if(newCellMult > 0) { // accept cluster if it has some digit
518       nClustersNew++;
519       //Primaries
520       Int_t  parentMult  = 0;
521       Int_t *parentList =  clust->GetParents(parentMult);
522       // fills the ESDCaloCluster
523       AliESDCaloCluster * ec = new AliESDCaloCluster() ;
524       ec->SetType(AliVCluster::kEMCALClusterv1);
525       ec->SetPosition(xyz);
526       ec->SetE(clust->GetEnergy());
527       
528       //Distance to the nearest bad crystal
529       ec->SetDistanceToBadChannel(clust->GetDistanceToBadTower()); 
530       
531       ec->SetNCells(newCellMult);
532       //Change type of list from short to ushort
533       UShort_t *newAbsIdList  = new UShort_t[newCellMult];
534       Double_t *newFracList   = new Double_t[newCellMult];
535       for(Int_t i = 0; i < newCellMult ; i++) {
536         newAbsIdList[i]=absIdList[i];
537         newFracList[i] =fracList[i];
538       }
539       ec->SetCellsAbsId(newAbsIdList);
540       ec->SetCellsAmplitudeFraction(newFracList);
541       ec->SetDispersion(clust->GetDispersion());
542       ec->SetChi2(-1); //not yet implemented
543       ec->SetM02(elipAxis[0]*elipAxis[0]) ;
544       ec->SetM20(elipAxis[1]*elipAxis[1]) ;
545       ec->SetTOF(clust->GetTime()) ; //time-of-fligh
546       ec->SetNExMax(clust->GetNExMax());          //number of local maxima
547   
548       
549       TArrayI arrayParents(parentMult,parentList);
550       ec->AddLabels(arrayParents);
551       //
552       //Track matching
553       //
554       fMatches->Clear();
555       Int_t nTracks = esd->GetNumberOfTracks();
556       for (Int_t itrack = 0; itrack < nTracks; itrack++)
557         {
558           AliESDtrack * track = esd->GetTrack(itrack) ; // retrieve track
559           if(track->GetEMCALcluster()==iClust)
560             {
561               Float_t dEta=-999, dPhi=-999;
562               Bool_t isMatch =  CalculateResidual(track, ec, dEta, dPhi);
563               if(!isMatch) 
564                 {
565                   // AliDebug(10, "Not good");
566                   continue;
567                 }
568               AliEMCALMatch *match = new AliEMCALMatch();
569               match->SetIndexT(itrack);
570               match->SetDistance(TMath::Sqrt(dEta*dEta+dPhi*dPhi));
571               match->SetdEta(dEta);
572               match->SetdPhi(dPhi);
573               fMatches->Add(match);
574             }
575         } 
576       fMatches->Sort(kSortAscending); //Sort matched tracks from closest to furthest
577       Int_t nMatch = fMatches->GetEntries();
578       TArrayI arrayTrackMatched(nMatch);
579       for(Int_t imatch=0; imatch<nMatch; imatch++)
580         {
581           AliEMCALMatch *match = (AliEMCALMatch*)fMatches->At(imatch);
582           arrayTrackMatched[imatch] = match->GetIndexT();
583           if(imatch==0)
584             {
585               ec->SetTrackDistance(match->GetdPhi(), match->GetdEta());
586             }
587         }
588       ec->AddTracksMatched(arrayTrackMatched);
589     
590       //add the cluster to the esd object
591       esd->AddCaloCluster(ec);
592
593       delete ec;
594       delete [] newAbsIdList ;
595       delete [] newFracList ;
596     }
597   } // cycle on clusters
598
599   //
600   //Reset the index of matched cluster for tracks
601   //to the one in CaloCluster array
602   Int_t ncls = esd->GetNumberOfCaloClusters();
603   for(Int_t icl=0; icl<ncls; icl++)
604     {
605       AliESDCaloCluster *cluster = esd->GetCaloCluster(icl);
606       if(!cluster || !cluster->IsEMCAL()) continue;
607       TArrayI *trackIndex = cluster->GetTracksMatched();
608       for(Int_t itr=0; itr<trackIndex->GetSize(); itr++)
609         {
610           AliESDtrack *track = esd->GetTrack(trackIndex->At(itr));
611           track->SetEMCALcluster(cluster->GetID());
612         }
613     }
614   
615   
616   //Fill ESDCaloCluster with PID weights
617   AliEMCALPID *pid = new AliEMCALPID;
618   //pid->SetPrintInfo(kTRUE);
619   pid->SetReconstructor(kTRUE);
620   pid->RunPID(esd);
621   delete pid;
622   
623   //Store EMCAL misalignment matrixes
624   FillMisalMatrixes(esd) ;
625   
626 }
627
628 //==================================================================================
629 void AliEMCALReconstructor::FillMisalMatrixes(AliESDEvent* esd)const{
630   //Store EMCAL matrixes in ESD Header
631   
632   //Check, if matrixes was already stored
633   for(Int_t sm = 0 ; sm < fGeom->GetNumberOfSuperModules(); sm++){
634     if(esd->GetEMCALMatrix(sm)!=0)
635       return ;
636   }
637   
638   //Create and store matrixes
639   if(!gGeoManager){
640     AliError("Can not store misal. matrixes: no gGeoManager! \n") ;
641     return ;
642   }
643   //Note, that owner of copied marixes will be header
644   const Int_t bufsize = 255;
645   char path[bufsize] ;
646   TGeoHMatrix * m = 0x0;
647   for(Int_t sm = 0; sm < fGeom->GetNumberOfSuperModules(); sm++){
648     snprintf(path,bufsize,"/ALIC_1/XEN1_1/SMOD_%d",sm+1) ; //In Geometry modules numbered 1,2,.,5
649     if(sm >= 10 && !((fGeom->GetEMCGeometry()->GetGeoName()).Contains("12SMV1"))) snprintf(path,bufsize,"/ALIC_1/XEN1_1/SM10_%d",sm-10+1) ;
650     if(sm >= 10 &&  ((fGeom->GetEMCGeometry()->GetGeoName()).Contains("12SMV1"))) snprintf(path,bufsize,"/ALIC_1/XEN1_1/SM3rd_%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(kTRUE), 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 AliEMCALReconstructor::AliEMCALMatch& AliEMCALReconstructor::AliEMCALMatch::AliEMCALMatch::operator = (const AliEMCALMatch &source)
747 { // assignment operator; use copy ctor
748   if (&source == this) return *this;
749
750   new (this) AliEMCALMatch(source);
751   return *this;
752 }
753 //
754 //==================================================================================
755 //
756 Int_t AliEMCALReconstructor::AliEMCALMatch::Compare(const TObject *obj) const 
757 {
758   //
759   // Compare wrt the residual
760   //
761         
762   AliEMCALReconstructor::AliEMCALMatch *that = (AliEMCALReconstructor::AliEMCALMatch*)obj;
763         
764   Double_t thisDist = fDistance;//fDistance;
765   Double_t thatDist = that->fDistance;//that->GetDistance();
766         
767   if (thisDist > thatDist) return 1;
768   else if (thisDist < thatDist) return -1;
769   return 0;
770 }