LCOV - code coverage report
Current view: top level - EMCAL/EMCALUtils - AliEMCALRecoUtils.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 67 1492 4.5 %
Date: 2016-06-14 17:26:59 Functions: 5 60 8.3 %

          Line data    Source code
       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             : // ROOT includes
      17             : #include <TGeoManager.h>
      18             : #include <TGeoMatrix.h>
      19             : #include <TGeoBBox.h>
      20             : #include <TH2F.h>
      21             : #include <TArrayI.h>
      22             : #include <TArrayF.h>
      23             : #include <TObjArray.h>
      24             : 
      25             : // STEER includes
      26             : #include "AliVCluster.h"
      27             : #include "AliVCaloCells.h"
      28             : #include "AliLog.h"
      29             : #include "AliPID.h"
      30             : #include "AliESDEvent.h"
      31             : #include "AliAODEvent.h"
      32             : #include "AliESDtrack.h"
      33             : #include "AliAODTrack.h"
      34             : #include "AliExternalTrackParam.h"
      35             : #include "AliESDfriendTrack.h"
      36             : #include "AliTrackerBase.h"
      37             : 
      38             : // EMCAL includes
      39             : #include "AliEMCALRecoUtils.h"
      40             : #include "AliEMCALGeometry.h"
      41             : #include "AliTrackerBase.h"
      42             : #include "AliEMCALPIDUtils.h"
      43             : 
      44             : /// \cond CLASSIMP
      45          72 : ClassImp(AliEMCALRecoUtils) ;
      46             : /// \endcond
      47             : 
      48             : ///
      49             : /// Constructor.
      50             : /// Initialize all constant values which have to be used
      51             : /// during Reco algorithm execution
      52             : ///
      53             : //_____________________________________
      54           0 : AliEMCALRecoUtils::AliEMCALRecoUtils():
      55           0 :   fParticleType(0),                       fPosAlgo(0),                            fW0(0), 
      56           0 :   fNonLinearityFunction(0),               fNonLinearThreshold(0),
      57           0 :   fSmearClusterEnergy(kFALSE),            fRandom(),
      58           0 :   fCellsRecalibrated(kFALSE),             fRecalibration(kFALSE),                 fEMCALRecalibrationFactors(),
      59           0 :   fConstantTimeShift(0),                  fTimeRecalibration(kFALSE),             fEMCALTimeRecalibrationFactors(),       fLowGain(kFALSE),
      60           0 :   fUseL1PhaseInTimeRecalibration(kFALSE), fEMCALL1PhaseInTimeRecalibration(),
      61           0 :   fUseRunCorrectionFactors(kFALSE),       
      62           0 :   fRemoveBadChannels(kFALSE),             fRecalDistToBadChannels(kFALSE),        fEMCALBadChannelMap(),
      63           0 :   fNCellsFromEMCALBorder(0),              fNoEMCALBorderAtEta0(kTRUE),
      64           0 :   fRejectExoticCluster(kFALSE),           fRejectExoticCells(kFALSE), 
      65           0 :   fExoticCellFraction(0),                 fExoticCellDiffTime(0),                 fExoticCellMinAmplitude(0),
      66           0 :   fPIDUtils(),                            fAODFilterMask(0),
      67           0 :   fAODHybridTracks(0),                    fAODTPCOnlyTracks(0),
      68           0 :   fMatchedTrackIndex(0x0),                fMatchedClusterIndex(0x0), 
      69           0 :   fResidualEta(0x0), fResidualPhi(0x0),   fCutEtaPhiSum(kFALSE),                  fCutEtaPhiSeparate(kFALSE), 
      70           0 :   fCutR(0),                               fCutEta(0),                             fCutPhi(0),
      71           0 :   fClusterWindow(0),                      fMass(0),                           
      72           0 :   fStepSurface(0),                        fStepCluster(0),
      73           0 :   fITSTrackSA(kFALSE),                    fEMCalSurfaceDistance(440.),
      74           0 :   fTrackCutsType(0),                      fCutMinTrackPt(0),                      fCutMinNClusterTPC(0), 
      75           0 :   fCutMinNClusterITS(0),                  fCutMaxChi2PerClusterTPC(0),            fCutMaxChi2PerClusterITS(0),
      76           0 :   fCutRequireTPCRefit(kFALSE),            fCutRequireITSRefit(kFALSE),            fCutAcceptKinkDaughters(kFALSE),
      77           0 :   fCutMaxDCAToVertexXY(0),                fCutMaxDCAToVertexZ(0),                 fCutDCAToVertex2D(kFALSE),
      78           0 :   fCutRequireITSStandAlone(kFALSE),       fCutRequireITSpureSA(kFALSE)
      79           0 : {
      80             :   // Init parameters
      81           0 :   InitParameters();
      82             :   
      83             :   // Track matching arrays init
      84           0 :   fMatchedTrackIndex     = new TArrayI();
      85           0 :   fMatchedClusterIndex   = new TArrayI();
      86           0 :   fResidualPhi           = new TArrayF();
      87           0 :   fResidualEta           = new TArrayF();
      88           0 :   fPIDUtils              = new AliEMCALPIDUtils();
      89           0 : }
      90             : 
      91             : //
      92             : // Copy constructor.
      93             : //
      94             : //______________________________________________________________________
      95             : AliEMCALRecoUtils::AliEMCALRecoUtils(const AliEMCALRecoUtils & reco) 
      96           0 : : TNamed(reco), 
      97           0 :   fParticleType(reco.fParticleType),                         fPosAlgo(reco.fPosAlgo),     fW0(reco.fW0),
      98           0 :   fNonLinearityFunction(reco.fNonLinearityFunction),         fNonLinearThreshold(reco.fNonLinearThreshold),
      99           0 :   fSmearClusterEnergy(reco.fSmearClusterEnergy),             fRandom(),
     100           0 :   fCellsRecalibrated(reco.fCellsRecalibrated),
     101           0 :   fRecalibration(reco.fRecalibration),                       fEMCALRecalibrationFactors(reco.fEMCALRecalibrationFactors),
     102           0 :   fConstantTimeShift(reco.fConstantTimeShift),  
     103           0 :   fTimeRecalibration(reco.fTimeRecalibration),               fEMCALTimeRecalibrationFactors(reco.fEMCALTimeRecalibrationFactors),
     104           0 :   fLowGain(reco.fLowGain),
     105           0 :   fUseL1PhaseInTimeRecalibration(reco.fUseL1PhaseInTimeRecalibration), 
     106           0 :   fEMCALL1PhaseInTimeRecalibration(reco.fEMCALL1PhaseInTimeRecalibration),
     107           0 :   fUseRunCorrectionFactors(reco.fUseRunCorrectionFactors),   
     108           0 :   fRemoveBadChannels(reco.fRemoveBadChannels),               fRecalDistToBadChannels(reco.fRecalDistToBadChannels),
     109           0 :   fEMCALBadChannelMap(reco.fEMCALBadChannelMap),
     110           0 :   fNCellsFromEMCALBorder(reco.fNCellsFromEMCALBorder),       fNoEMCALBorderAtEta0(reco.fNoEMCALBorderAtEta0),
     111           0 :   fRejectExoticCluster(reco.fRejectExoticCluster),           fRejectExoticCells(reco.fRejectExoticCells), 
     112           0 :   fExoticCellFraction(reco.fExoticCellFraction),             fExoticCellDiffTime(reco.fExoticCellDiffTime),               
     113           0 :   fExoticCellMinAmplitude(reco.fExoticCellMinAmplitude),
     114           0 :   fPIDUtils(reco.fPIDUtils),                                 fAODFilterMask(reco.fAODFilterMask),
     115           0 :   fAODHybridTracks(reco.fAODHybridTracks),                   fAODTPCOnlyTracks(reco.fAODTPCOnlyTracks),
     116           0 :   fMatchedTrackIndex(  reco.fMatchedTrackIndex?  new TArrayI(*reco.fMatchedTrackIndex):0x0),
     117           0 :   fMatchedClusterIndex(reco.fMatchedClusterIndex?new TArrayI(*reco.fMatchedClusterIndex):0x0),
     118           0 :   fResidualEta(        reco.fResidualEta?        new TArrayF(*reco.fResidualEta):0x0),
     119           0 :   fResidualPhi(        reco.fResidualPhi?        new TArrayF(*reco.fResidualPhi):0x0),
     120           0 :   fCutEtaPhiSum(reco.fCutEtaPhiSum),                         fCutEtaPhiSeparate(reco.fCutEtaPhiSeparate), 
     121           0 :   fCutR(reco.fCutR),        fCutEta(reco.fCutEta),           fCutPhi(reco.fCutPhi),
     122           0 :   fClusterWindow(reco.fClusterWindow),
     123           0 :   fMass(reco.fMass),        fStepSurface(reco.fStepSurface), fStepCluster(reco.fStepCluster),
     124           0 :   fITSTrackSA(reco.fITSTrackSA),                             fEMCalSurfaceDistance(440.),
     125           0 :   fTrackCutsType(reco.fTrackCutsType),                       fCutMinTrackPt(reco.fCutMinTrackPt), 
     126           0 :   fCutMinNClusterTPC(reco.fCutMinNClusterTPC),               fCutMinNClusterITS(reco.fCutMinNClusterITS), 
     127           0 :   fCutMaxChi2PerClusterTPC(reco.fCutMaxChi2PerClusterTPC),   fCutMaxChi2PerClusterITS(reco.fCutMaxChi2PerClusterITS),
     128           0 :   fCutRequireTPCRefit(reco.fCutRequireTPCRefit),             fCutRequireITSRefit(reco.fCutRequireITSRefit),
     129           0 :   fCutAcceptKinkDaughters(reco.fCutAcceptKinkDaughters),     fCutMaxDCAToVertexXY(reco.fCutMaxDCAToVertexXY),    
     130           0 :   fCutMaxDCAToVertexZ(reco.fCutMaxDCAToVertexZ),             fCutDCAToVertex2D(reco.fCutDCAToVertex2D),
     131           0 :   fCutRequireITSStandAlone(reco.fCutRequireITSStandAlone),   fCutRequireITSpureSA(reco.fCutRequireITSpureSA)
     132           0 : {  
     133           0 :   for (Int_t i = 0; i < 15 ; i++) { fMisalRotShift[i]      = reco.fMisalRotShift[i]      ; 
     134           0 :                                     fMisalTransShift[i]    = reco.fMisalTransShift[i]    ; }
     135           0 :   for (Int_t i = 0; i < 7  ; i++) { fNonLinearityParams[i] = reco.fNonLinearityParams[i] ; }
     136           0 :   for (Int_t i = 0; i < 3  ; i++) { fSmearClusterParam[i]  = reco.fSmearClusterParam[i]  ; }
     137           0 : }
     138             : 
     139             : ///
     140             : /// Assignment operator.
     141             : ///
     142             : //______________________________________________________________________
     143             : AliEMCALRecoUtils & AliEMCALRecoUtils::operator = (const AliEMCALRecoUtils & reco) 
     144             : {  
     145           0 :   if (this == &reco)return *this;
     146           0 :   ((TNamed *)this)->operator=(reco);
     147             :   
     148           0 :   for (Int_t i = 0; i < 15 ; i++) { fMisalTransShift[i]    = reco.fMisalTransShift[i]    ; 
     149           0 :     fMisalRotShift[i]      = reco.fMisalRotShift[i]      ; }
     150           0 :   for (Int_t i = 0; i < 7  ; i++) { fNonLinearityParams[i] = reco.fNonLinearityParams[i] ; }
     151           0 :   for (Int_t i = 0; i < 3  ; i++) { fSmearClusterParam[i]  = reco.fSmearClusterParam[i]  ; }   
     152             :   
     153           0 :   fParticleType              = reco.fParticleType;
     154           0 :   fPosAlgo                   = reco.fPosAlgo; 
     155           0 :   fW0                        = reco.fW0;
     156             :   
     157           0 :   fNonLinearityFunction      = reco.fNonLinearityFunction;
     158           0 :   fNonLinearThreshold        = reco.fNonLinearThreshold;
     159           0 :   fSmearClusterEnergy        = reco.fSmearClusterEnergy;
     160             :   
     161           0 :   fCellsRecalibrated         = reco.fCellsRecalibrated;
     162           0 :   fRecalibration             = reco.fRecalibration;
     163           0 :   fEMCALRecalibrationFactors = reco.fEMCALRecalibrationFactors;
     164             :   
     165           0 :   fConstantTimeShift         = reco.fConstantTimeShift;
     166           0 :   fTimeRecalibration         = reco.fTimeRecalibration;
     167           0 :   fEMCALTimeRecalibrationFactors = reco.fEMCALTimeRecalibrationFactors;
     168           0 :   fLowGain                   = reco.fLowGain;
     169             : 
     170           0 :   fUseL1PhaseInTimeRecalibration   = reco.fUseL1PhaseInTimeRecalibration;
     171           0 :   fEMCALL1PhaseInTimeRecalibration = reco.fEMCALL1PhaseInTimeRecalibration;
     172             :   
     173           0 :   fUseRunCorrectionFactors   = reco.fUseRunCorrectionFactors;
     174             :   
     175           0 :   fRemoveBadChannels         = reco.fRemoveBadChannels;
     176           0 :   fRecalDistToBadChannels    = reco.fRecalDistToBadChannels;
     177           0 :   fEMCALBadChannelMap        = reco.fEMCALBadChannelMap;
     178             :   
     179           0 :   fNCellsFromEMCALBorder     = reco.fNCellsFromEMCALBorder;
     180           0 :   fNoEMCALBorderAtEta0       = reco.fNoEMCALBorderAtEta0;
     181             :   
     182           0 :   fRejectExoticCluster       = reco.fRejectExoticCluster;           
     183           0 :   fRejectExoticCells         = reco.fRejectExoticCells; 
     184           0 :   fExoticCellFraction        = reco.fExoticCellFraction;
     185           0 :   fExoticCellDiffTime        = reco.fExoticCellDiffTime;              
     186           0 :   fExoticCellMinAmplitude    = reco.fExoticCellMinAmplitude;
     187             :   
     188           0 :   fPIDUtils                  = reco.fPIDUtils;
     189             :   
     190           0 :   fAODFilterMask             = reco.fAODFilterMask;
     191           0 :   fAODHybridTracks           = reco.fAODHybridTracks;
     192           0 :   fAODTPCOnlyTracks          = reco.fAODTPCOnlyTracks;
     193             :   
     194           0 :   fCutEtaPhiSum              = reco.fCutEtaPhiSum;
     195           0 :   fCutEtaPhiSeparate         = reco.fCutEtaPhiSeparate;
     196           0 :   fCutR                      = reco.fCutR;
     197           0 :   fCutEta                    = reco.fCutEta;
     198           0 :   fCutPhi                    = reco.fCutPhi;
     199           0 :   fClusterWindow             = reco.fClusterWindow;
     200           0 :   fMass                      = reco.fMass;
     201           0 :   fStepSurface               = reco.fStepSurface;
     202           0 :   fStepCluster               = reco.fStepCluster;
     203           0 :   fITSTrackSA                = reco.fITSTrackSA;
     204           0 :   fEMCalSurfaceDistance      = reco.fEMCalSurfaceDistance;
     205             :   
     206           0 :   fTrackCutsType             = reco.fTrackCutsType;
     207           0 :   fCutMinTrackPt             = reco.fCutMinTrackPt;
     208           0 :   fCutMinNClusterTPC         = reco.fCutMinNClusterTPC;
     209           0 :   fCutMinNClusterITS         = reco.fCutMinNClusterITS; 
     210           0 :   fCutMaxChi2PerClusterTPC   = reco.fCutMaxChi2PerClusterTPC;
     211           0 :   fCutMaxChi2PerClusterITS   = reco.fCutMaxChi2PerClusterITS;
     212           0 :   fCutRequireTPCRefit        = reco.fCutRequireTPCRefit;
     213           0 :   fCutRequireITSRefit        = reco.fCutRequireITSRefit;
     214           0 :   fCutAcceptKinkDaughters    = reco.fCutAcceptKinkDaughters;
     215           0 :   fCutMaxDCAToVertexXY       = reco.fCutMaxDCAToVertexXY;
     216           0 :   fCutMaxDCAToVertexZ        = reco.fCutMaxDCAToVertexZ;
     217           0 :   fCutDCAToVertex2D          = reco.fCutDCAToVertex2D;
     218           0 :   fCutRequireITSStandAlone   = reco.fCutRequireITSStandAlone; 
     219           0 :   fCutRequireITSpureSA       = reco.fCutRequireITSpureSA;
     220             : 
     221             :   //
     222             :   // Assign or copy construct the different TArrays
     223             :   //
     224           0 :   if (reco.fResidualEta) 
     225             :   {
     226           0 :     if (fResidualEta) 
     227           0 :       *fResidualEta = *reco.fResidualEta;
     228             :     else 
     229           0 :       fResidualEta = new TArrayF(*reco.fResidualEta);
     230             :   } 
     231             :   else 
     232             :   {
     233           0 :     if (fResidualEta) delete fResidualEta;
     234           0 :     fResidualEta = 0;
     235             :   }
     236             :   
     237           0 :   if (reco.fResidualPhi) 
     238             :   {
     239           0 :     if (fResidualPhi)  
     240           0 :       *fResidualPhi = *reco.fResidualPhi;
     241             :     else 
     242           0 :       fResidualPhi = new TArrayF(*reco.fResidualPhi);
     243             :   } 
     244             :   else 
     245             :   {
     246           0 :     if (fResidualPhi) delete fResidualPhi;
     247           0 :     fResidualPhi = 0;
     248             :   }
     249             :   
     250           0 :   if (reco.fMatchedTrackIndex) 
     251             :   {
     252           0 :     if (fMatchedTrackIndex)  
     253           0 :       *fMatchedTrackIndex = *reco.fMatchedTrackIndex;
     254             :     else  
     255           0 :       fMatchedTrackIndex = new TArrayI(*reco.fMatchedTrackIndex);
     256             :   } 
     257             :   else 
     258             :   {
     259           0 :     if (fMatchedTrackIndex) delete fMatchedTrackIndex;
     260           0 :     fMatchedTrackIndex = 0;
     261             :   }  
     262             :   
     263           0 :   if (reco.fMatchedClusterIndex)
     264             :   {
     265           0 :     if (fMatchedClusterIndex)  
     266           0 :       *fMatchedClusterIndex = *reco.fMatchedClusterIndex;
     267             :     else 
     268           0 :       fMatchedClusterIndex = new TArrayI(*reco.fMatchedClusterIndex);
     269             :   } 
     270             :   else 
     271             :   {
     272           0 :     if (fMatchedClusterIndex) delete fMatchedClusterIndex;
     273           0 :     fMatchedClusterIndex = 0;
     274             :   }
     275             :   
     276           0 :   return *this;
     277           0 : }
     278             : 
     279             : ///
     280             : /// Destructor.
     281             : ///
     282             : //_____________________________________
     283             : AliEMCALRecoUtils::~AliEMCALRecoUtils()
     284           0 : {  
     285           0 :   if (fEMCALRecalibrationFactors) 
     286             :   { 
     287           0 :     fEMCALRecalibrationFactors->Clear();
     288           0 :     delete fEMCALRecalibrationFactors;
     289             :   }  
     290             :   
     291           0 :   if (fEMCALTimeRecalibrationFactors) 
     292             :   { 
     293           0 :     fEMCALTimeRecalibrationFactors->Clear();
     294           0 :     delete fEMCALTimeRecalibrationFactors;
     295             :   }  
     296             : 
     297           0 :   if(fEMCALL1PhaseInTimeRecalibration) 
     298             :   {  
     299           0 :     fEMCALL1PhaseInTimeRecalibration->Clear();
     300           0 :     delete fEMCALL1PhaseInTimeRecalibration;
     301             :   }
     302             : 
     303           0 :   if (fEMCALBadChannelMap) 
     304             :   { 
     305           0 :     fEMCALBadChannelMap->Clear();
     306           0 :     delete fEMCALBadChannelMap;
     307             :   }
     308             :  
     309           0 :   delete fMatchedTrackIndex   ; 
     310           0 :   delete fMatchedClusterIndex ; 
     311           0 :   delete fResidualEta         ; 
     312           0 :   delete fResidualPhi         ; 
     313           0 :   delete fPIDUtils            ;
     314             : 
     315           0 :   InitTrackCuts();
     316           0 : }
     317             : 
     318             : ///
     319             : /// Reject cell if acceptance criteria not passed (correct cell number, is it bad channel) 
     320             : /// and calibrate it in energy and time.
     321             : ///
     322             : /// \param absID: absolute cell ID number
     323             : /// \param bc: bunch crossing number
     324             : /// \param amp: input cell energy amplitude, output calibrated amplitude
     325             : /// \param time: input cell time, output calibrated time
     326             : /// \param cells: list of cells
     327             : ///
     328             : /// \return bool quality of cell, exists or not 
     329             : ///
     330             : //_______________________________________________________________________________
     331             : Bool_t AliEMCALRecoUtils::AcceptCalibrateCell(Int_t absID, Int_t bc,
     332             :                                               Float_t  & amp,    Double_t & time, 
     333             :                                               AliVCaloCells* cells) 
     334             : {  
     335           0 :   AliEMCALGeometry* geom = AliEMCALGeometry::GetInstance();
     336             :   
     337           0 :   if(!geom)
     338             :   {
     339           0 :     AliError("No instance of the geometry is available");
     340           0 :     return kFALSE;
     341             :   }
     342             : 
     343           0 :   if ( absID < 0 || absID >= 24*48*geom->GetNumberOfSuperModules() ) 
     344           0 :     return kFALSE;
     345             :   
     346           0 :   Int_t imod = -1, iphi =-1, ieta=-1,iTower = -1, iIphi = -1, iIeta = -1; 
     347             :   
     348           0 :   if (!geom->GetCellIndex(absID,imod,iTower,iIphi,iIeta)) 
     349             :   {
     350             :     // cell absID does not exist
     351           0 :     amp=0; time = 1.e9;
     352           0 :     return kFALSE; 
     353             :   }
     354             :   
     355           0 :   geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,iphi,ieta);  
     356             : 
     357             :   // Do not include bad channels found in analysis,
     358           0 :   if (IsBadChannelsRemovalSwitchedOn() && GetEMCALChannelStatus(imod, ieta, iphi)) 
     359           0 :     return kFALSE;
     360             :   
     361             :   //Recalibrate energy
     362           0 :   amp  = cells->GetCellAmplitude(absID);
     363           0 :   if (!fCellsRecalibrated && IsRecalibrationOn())
     364           0 :     amp *= GetEMCALChannelRecalibrationFactor(imod,ieta,iphi);
     365             :   
     366             :   // Recalibrate time
     367           0 :   time = cells->GetCellTime(absID);
     368           0 :   time-=fConstantTimeShift*1e-9; // only in case of old Run1 simulation
     369           0 :   Bool_t isLowGain = !(cells->GetCellHighGain(absID));//HG = false -> LG = true
     370             : 
     371           0 :   RecalibrateCellTime(absID,bc,time,isLowGain);
     372             :   
     373             :   //Recalibrate time with L1 phase 
     374           0 :   RecalibrateCellTimeL1Phase(imod, bc, time);
     375             : 
     376             :   return kTRUE;
     377           0 : }
     378             : 
     379             : ///
     380             : /// Given the list of AbsId cells of the cluster, get the maximum cell and 
     381             : /// check if there are fNCellsFromBorder from the calorimeter border.
     382             : ///
     383             : /// \param geom: AliEMCALGeometry pointer
     384             : /// \param cluster: AliVCluster pointer
     385             : /// \param cells: list of cells
     386             : ///
     387             : /// \return bool, true if cluster in defined fiducial region
     388             : //_____________________________________________________________________________
     389             : Bool_t AliEMCALRecoUtils::CheckCellFiducialRegion(const AliEMCALGeometry* geom, 
     390             :                                                   const AliVCluster* cluster, 
     391             :                                                   AliVCaloCells* cells) 
     392             : {  
     393           0 :   if (!cluster)
     394             :   {
     395           0 :     AliInfo("Cluster pointer null!");
     396           0 :     return kFALSE;
     397             :   }
     398             :   
     399             :   //If the distance to the border is 0 or negative just exit accept all clusters
     400           0 :   if (cells->GetType()==AliVCaloCells::kEMCALCell && fNCellsFromEMCALBorder <= 0 ) 
     401           0 :     return kTRUE;
     402             :   
     403           0 :   Int_t absIdMax  = -1, iSM =-1, ieta = -1, iphi = -1;
     404           0 :   Bool_t shared = kFALSE;
     405           0 :   GetMaxEnergyCell(geom, cells, cluster, absIdMax,  iSM, ieta, iphi, shared);
     406             :   
     407           0 :   AliDebug(2,Form("Cluster Max AbsId %d, Cell Energy %2.2f, Cluster Energy %2.2f, Ncells from border %d, EMCAL eta=0 %d\n", 
     408             :                   absIdMax, cells->GetCellAmplitude(absIdMax), cluster->E(), fNCellsFromEMCALBorder, fNoEMCALBorderAtEta0));
     409             :   
     410           0 :   if (absIdMax==-1) return kFALSE;
     411             :   
     412             :   //Check if the cell is close to the borders:
     413             :   Bool_t okrow = kFALSE;
     414             :   Bool_t okcol = kFALSE;
     415             :   
     416           0 :   if (iSM < 0 || iphi < 0 || ieta < 0 ) {
     417           0 :     AliFatal(Form("Negative value for super module: %d, or cell ieta: %d, or cell iphi: %d, check EMCAL geometry name\n",
     418             :                   iSM,ieta,iphi));
     419           0 :     return kFALSE; // trick coverity
     420             :   }
     421             :   
     422             :   //Check rows/phi
     423             :   Int_t iPhiLast = 24;
     424           0 :    if( geom->GetSMType(iSM) == AliEMCALGeometry::kEMCAL_Half ) iPhiLast /= 2;
     425           0 :    else if (  geom->GetSMType(iSM) == AliEMCALGeometry::kEMCAL_3rd ) iPhiLast /= 3;// 1/3 sm case
     426             :   
     427           0 :   if(iphi >= fNCellsFromEMCALBorder && iphi < iPhiLast - fNCellsFromEMCALBorder) okrow = kTRUE; 
     428             : 
     429             :   //Check columns/eta
     430             :   Int_t iEtaLast = 48;
     431           0 :   if(!fNoEMCALBorderAtEta0 || geom->IsDCALSM(iSM)) {// conside inner border
     432           0 :      if(  geom->GetSMType(iSM) == AliEMCALGeometry::kDCAL_Standard )  iEtaLast = iEtaLast*2/3;        
     433           0 :      if(ieta  > fNCellsFromEMCALBorder && ieta < iEtaLast-fNCellsFromEMCALBorder) okcol = kTRUE;  
     434             :   } else {
     435           0 :     if (iSM%2==0) {
     436           0 :      if (ieta >= fNCellsFromEMCALBorder)     okcol = kTRUE;  
     437             :     } else {
     438           0 :      if(ieta <  iEtaLast-fNCellsFromEMCALBorder)  okcol = kTRUE; 
     439             :     }
     440             :   }//eta 0 not checked
     441             :   
     442           0 :   AliDebug(2,Form("EMCAL Cluster in %d cells fiducial volume: ieta %d, iphi %d, SM %d:  column? %d, row? %d\nq",
     443             :                   fNCellsFromEMCALBorder, ieta, iphi, iSM, okcol, okrow));
     444             :   
     445           0 :   if (okcol && okrow) {
     446             :     //printf("Accept\n");
     447           0 :     return kTRUE;
     448             :   } else  {
     449             :     //printf("Reject\n");
     450           0 :     AliDebug(2,Form("Reject cluster in border, max cell : ieta %d, iphi %d, SM %d\n",ieta, iphi, iSM));
     451           0 :     return kFALSE;
     452             :   }
     453           0 : }  
     454             : 
     455             : ///
     456             : /// Check that in the cluster cells, there is no bad channel of those stored 
     457             : /// in fEMCALBadChannelMap 
     458             : ///
     459             : /// \param geom: AliEMCALGeometry pointer
     460             : /// \param cellsList: list of cells absolute ID in cluster
     461             : /// \param nCells: number of cells in cluster
     462             : ///
     463             : /// \return bool, true if cluster contains a bad channel
     464             : ///
     465             : //_______________________________________________________________________________
     466             : Bool_t AliEMCALRecoUtils::ClusterContainsBadChannel(const AliEMCALGeometry* geom, 
     467             :                                                     const UShort_t* cellList, 
     468             :                                                     Int_t nCells)
     469             : {  
     470           0 :   if (!fRemoveBadChannels)  return kFALSE;
     471           0 :   if (!fEMCALBadChannelMap) return kFALSE;
     472             :   
     473           0 :   Int_t icol = -1;
     474           0 :   Int_t irow = -1;
     475           0 :   Int_t imod = -1;
     476           0 :   for (Int_t iCell = 0; iCell<nCells; iCell++) 
     477             :   {
     478             :     //Get the column and row
     479           0 :     Int_t iTower = -1, iIphi = -1, iIeta = -1; 
     480           0 :     geom->GetCellIndex(cellList[iCell],imod,iTower,iIphi,iIeta); 
     481             :   
     482           0 :     if (fEMCALBadChannelMap->GetEntries() <= imod) continue;
     483             :     
     484           0 :     geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);      
     485             :     
     486           0 :     if (GetEMCALChannelStatus(imod, icol, irow)) 
     487             :     {
     488           0 :       AliDebug(2,Form("Cluster with bad channel: SM %d, col %d, row %d\n",imod, icol, irow));
     489           0 :       return kTRUE;
     490             :     }
     491           0 :   }// cell cluster loop
     492             : 
     493           0 :   return kFALSE;
     494           0 : }
     495             : 
     496             : ///
     497             : /// Calculate the energy in the cross around the energy of a given cell.
     498             : /// Used in exotic clusters/cells rejection.
     499             : ///
     500             : /// \param absID: controlled cell absolute ID number
     501             : /// \param tcell: time of cell under control
     502             : /// \param cells: full list of cells
     503             : /// \param bc: bunch crossing number
     504             : ///
     505             : /// \return float E_cross
     506             : ///
     507             : //___________________________________________________________________________
     508             : Float_t AliEMCALRecoUtils::GetECross(Int_t absID, Double_t tcell,
     509             :                                      AliVCaloCells* cells, Int_t bc)
     510             : {  
     511           0 :   AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
     512             :   
     513           0 :   if(!geom)
     514             :   {
     515           0 :     AliError("No instance of the geometry is available");
     516           0 :     return -1;
     517             :   }
     518             : 
     519           0 :   Int_t imod = -1, iphi =-1, ieta=-1,iTower = -1, iIphi = -1, iIeta = -1; 
     520           0 :   geom->GetCellIndex(absID,imod,iTower,iIphi,iIeta); 
     521           0 :   geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,iphi,ieta);  
     522             :   
     523             :   // Get close cells index, energy and time, not in corners
     524             :   
     525             :   Int_t absID1 = -1;
     526             :   Int_t absID2 = -1;
     527             :   
     528           0 :   if ( iphi < AliEMCALGeoParams::fgkEMCALRows-1) absID1 = geom->GetAbsCellIdFromCellIndexes(imod, iphi+1, ieta);
     529           0 :   if ( iphi > 0 )                                absID2 = geom->GetAbsCellIdFromCellIndexes(imod, iphi-1, ieta);
     530             :   
     531             :   // In case of cell in eta = 0 border, depending on SM shift the cross cell index
     532             :   
     533             :   Int_t absID3 = -1;
     534             :   Int_t absID4 = -1;
     535             :   
     536           0 :   if ( ieta == AliEMCALGeoParams::fgkEMCALCols-1 && !(imod%2) ) 
     537             :   {
     538           0 :     absID3 = geom-> GetAbsCellIdFromCellIndexes(imod+1, iphi, 0);
     539           0 :     absID4 = geom-> GetAbsCellIdFromCellIndexes(imod,   iphi, ieta-1); 
     540           0 :   } 
     541           0 :   else if ( ieta == 0 && imod%2 ) 
     542             :   {
     543           0 :     absID3 = geom-> GetAbsCellIdFromCellIndexes(imod,   iphi, ieta+1);
     544           0 :     absID4 = geom-> GetAbsCellIdFromCellIndexes(imod-1, iphi, AliEMCALGeoParams::fgkEMCALCols-1); 
     545           0 :   } 
     546             :   else 
     547             :   {
     548           0 :     if ( ieta < AliEMCALGeoParams::fgkEMCALCols-1 ) 
     549           0 :       absID3 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi, ieta+1);
     550           0 :     if ( ieta > 0 )                                 
     551           0 :       absID4 = geom-> GetAbsCellIdFromCellIndexes(imod, iphi, ieta-1); 
     552             :   }
     553             :   
     554             :   //printf("IMOD %d, AbsId %d, a %d, b %d, c %d e %d \n",imod,absID,absID1,absID2,absID3,absID4);
     555             :   
     556           0 :   Float_t  ecell1  = 0, ecell2  = 0, ecell3  = 0, ecell4  = 0;
     557           0 :   Double_t tcell1  = 0, tcell2  = 0, tcell3  = 0, tcell4  = 0;
     558             : 
     559           0 :   AcceptCalibrateCell(absID1,bc, ecell1,tcell1,cells); 
     560           0 :   AcceptCalibrateCell(absID2,bc, ecell2,tcell2,cells); 
     561           0 :   AcceptCalibrateCell(absID3,bc, ecell3,tcell3,cells); 
     562           0 :   AcceptCalibrateCell(absID4,bc, ecell4,tcell4,cells); 
     563             :   
     564           0 :   if (TMath::Abs(tcell-tcell1)*1.e9 > fExoticCellDiffTime) ecell1 = 0 ;
     565           0 :   if (TMath::Abs(tcell-tcell2)*1.e9 > fExoticCellDiffTime) ecell2 = 0 ;
     566           0 :   if (TMath::Abs(tcell-tcell3)*1.e9 > fExoticCellDiffTime) ecell3 = 0 ;
     567           0 :   if (TMath::Abs(tcell-tcell4)*1.e9 > fExoticCellDiffTime) ecell4 = 0 ;
     568             :   
     569           0 :   return ecell1+ecell2+ecell3+ecell4;
     570           0 : }
     571             : 
     572             : ///
     573             : /// Look to cell neighbourhood and reject if it seems exotic
     574             : /// Do before recalibrating the cells.
     575             : ///
     576             : /// \param absID: controlled cell absolute ID number
     577             : /// \param tcell: time of cell under control
     578             : /// \param cells: full list of cells
     579             : /// \param bc: bunch crossing number
     580             : ///
     581             : /// \return bool true if cell is found exotic
     582             : ///
     583             : //_____________________________________________________________________________________________
     584             : Bool_t AliEMCALRecoUtils::IsExoticCell(Int_t absID, AliVCaloCells* cells, Int_t bc)
     585             : {
     586           0 :   if (!fRejectExoticCells) return kFALSE;
     587             :   
     588           0 :   Float_t  ecell  = 0;
     589           0 :   Double_t tcell  = 0;
     590           0 :   Bool_t   accept = AcceptCalibrateCell(absID, bc, ecell ,tcell ,cells); 
     591             :   
     592           0 :   if (!accept) return kTRUE; // reject this cell
     593             :   
     594           0 :   if (ecell < fExoticCellMinAmplitude) return kFALSE; // do not reject low energy cells
     595             : 
     596           0 :   Float_t eCross = GetECross(absID,tcell,cells,bc);
     597             :   
     598           0 :   if (1-eCross/ecell > fExoticCellFraction) 
     599             :   {
     600           0 :     AliDebug(2,Form("AliEMCALRecoUtils::IsExoticCell() - EXOTIC CELL id %d, eCell %f, eCross %f, 1-eCross/eCell %f\n",
     601             :                     absID,ecell,eCross,1-eCross/ecell));
     602           0 :     return kTRUE;
     603             :   }
     604             : 
     605           0 :   return kFALSE;
     606           0 : }
     607             : 
     608             : ///
     609             : /// Check if the cluster highest energy tower is exotic.
     610             : ///
     611             : /// \param cluster: pointer to AliVCluster
     612             : /// \param cells: full list of cells
     613             : /// \param bc: bunch crossing number
     614             : ///
     615             : /// \param cluster:  pointer to AliVCluster
     616             : ///
     617             : //___________________________________________________________________
     618             : Bool_t AliEMCALRecoUtils::IsExoticCluster(const AliVCluster *cluster, 
     619             :                                           AliVCaloCells *cells, 
     620             :                                           Int_t bc) 
     621             : {  
     622           0 :   if (!cluster) 
     623             :   {
     624           0 :     AliInfo("Cluster pointer null!");
     625           0 :     return kFALSE;
     626             :   }
     627             :   
     628           0 :   if (!fRejectExoticCluster) return kFALSE;
     629             :   
     630             :   // Get highest energy tower
     631           0 :   AliEMCALGeometry* geom = AliEMCALGeometry::GetInstance();
     632             :   
     633           0 :   if(!geom)
     634             :   {
     635           0 :     AliError("No instance of the geometry is available");
     636           0 :     return kFALSE;
     637             :   }
     638             : 
     639           0 :   Int_t iSupMod = -1, absId = -1, ieta = -1, iphi = -1;
     640           0 :   Bool_t shared = kFALSE;
     641           0 :   GetMaxEnergyCell(geom, cells, cluster, absId, iSupMod, ieta, iphi, shared);
     642             :   
     643           0 :   return IsExoticCell(absId,cells,bc);
     644           0 : }
     645             : 
     646             : ///
     647             : /// In case of MC analysis, smear energy to match resolution/calibration in real data 
     648             : /// (old, in principle not needed anymore).
     649             : ///
     650             : /// \param cluster: pointer to AliVCluster
     651             : ///
     652             : /// \return float with smeared energy
     653             : ///
     654             : //_______________________________________________________________________
     655             : Float_t AliEMCALRecoUtils::SmearClusterEnergy(const AliVCluster* cluster) 
     656             : {  
     657           0 :   if (!cluster) 
     658             :   {
     659           0 :     AliInfo("Cluster pointer null!");
     660           0 :     return 0;
     661             :   }
     662             :   
     663           0 :   Float_t energy    = cluster->E() ;
     664             :   Float_t rdmEnergy = energy ;
     665             :   
     666           0 :   if (fSmearClusterEnergy) 
     667             :   {
     668           0 :     rdmEnergy = fRandom.Gaus(energy,fSmearClusterParam[0] * TMath::Sqrt(energy) +
     669           0 :                                     fSmearClusterParam[1] * energy +
     670           0 :                                     fSmearClusterParam[2] );
     671           0 :     AliDebug(2, Form("Energy: original %f, smeared %f\n", energy, rdmEnergy));
     672             :   }
     673             :   
     674             :   return rdmEnergy;
     675           0 : }
     676             : 
     677             : ///
     678             : /// Correct cluster energy from non linearity functions, defined in enum NonlinearityFunctions
     679             : /// Recomended for data kBeamTestCorrectedv3 and for simulation kPi0MCv3
     680             : ///
     681             : /// \param cluster: pointer to AliVCluster
     682             : ///
     683             : /// \return float with corrected cluster energy
     684             : ///
     685             : //____________________________________________________________________________
     686             : Float_t AliEMCALRecoUtils::CorrectClusterEnergyLinearity(AliVCluster* cluster)
     687             : {  
     688           0 :   if (!cluster) 
     689             :   {
     690           0 :     AliInfo("Cluster pointer null!");
     691           0 :     return 0;
     692             :   }
     693             :   
     694           0 :   Float_t energy = cluster->E();
     695           0 :   if (energy < 0.100) 
     696             :   {
     697             :     // Clusters with less than 100 MeV or negative are not possible
     698           0 :     AliInfo(Form("Too low cluster energy!, E = %f < 0.100 GeV",energy));
     699           0 :     return 0;
     700             :   }
     701           0 :   else if(energy > 300.)
     702             :   {
     703           0 :     AliInfo(Form("Too high cluster energy!, E = %f GeV, do not apply non linearity",energy));
     704           0 :     return energy;
     705             :   }
     706             :   
     707           0 :   switch (fNonLinearityFunction) 
     708             :   {
     709             :     case kPi0MC:
     710             :     {
     711             :       //Non-Linearity correction (from MC with function ([0]*exp(-[1]/E))+(([2]/([3]*2.*TMath::Pi())*exp(-(E-[4])^2/(2.*[3]^2)))))
     712             :       //fNonLinearityParams[0] = 1.014;
     713             :       //fNonLinearityParams[1] =-0.03329;
     714             :       //fNonLinearityParams[2] =-0.3853;
     715             :       //fNonLinearityParams[3] = 0.5423;
     716             :       //fNonLinearityParams[4] =-0.4335;
     717           0 :        energy *= (fNonLinearityParams[0]*exp(-fNonLinearityParams[1]/energy))+
     718           0 :                   ((fNonLinearityParams[2]/(fNonLinearityParams[3]*2.*TMath::Pi())*
     719           0 :                     exp(-(energy-fNonLinearityParams[4])*(energy-fNonLinearityParams[4])/(2.*fNonLinearityParams[3]*fNonLinearityParams[3]))));
     720           0 :       break;
     721             :     }
     722             :      
     723             :     case kPi0MCv2:
     724             :     {
     725             :       //Non-Linearity correction (from MC with function [0]/((x+[1])^[2]))+1;
     726             :       //fNonLinearityParams[0] = 3.11111e-02;
     727             :       //fNonLinearityParams[1] =-5.71666e-02; 
     728             :       //fNonLinearityParams[2] = 5.67995e-01;      
     729             :       
     730           0 :       energy *= fNonLinearityParams[0]/TMath::Power(energy+fNonLinearityParams[1],fNonLinearityParams[2])+1;
     731           0 :       break;
     732             :     }
     733             :     
     734             :     case kPi0MCv3:
     735             :     {
     736             :       //Same as beam test corrected, change parameters
     737             :       //fNonLinearityParams[0] =  9.81039e-01
     738             :       //fNonLinearityParams[1] =  1.13508e-01;
     739             :       //fNonLinearityParams[2] =  1.00173e+00; 
     740             :       //fNonLinearityParams[3] =  9.67998e-02;
     741             :       //fNonLinearityParams[4] =  2.19381e+02;
     742             :       //fNonLinearityParams[5] =  6.31604e+01;
     743             :       //fNonLinearityParams[6] =  1;
     744           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     745             :       
     746           0 :       break;
     747             :     }
     748             :       
     749             :       
     750             :     case kPi0GammaGamma:
     751             :     {
     752             :       //Non-Linearity correction (from Olga Data with function p0+p1*exp(-p2*E))
     753             :       //fNonLinearityParams[0] = 1.04;
     754             :       //fNonLinearityParams[1] = -0.1445;
     755             :       //fNonLinearityParams[2] = 1.046;
     756           0 :       energy /= (fNonLinearityParams[0]+fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy)); //Olga function
     757           0 :       break;
     758             :     }
     759             :       
     760             :     case kPi0GammaConversion:
     761             :     {
     762             :       //Non-Linearity correction (Nicolas from Dimitri Data with function C*[1-a*exp(-b*E)])
     763             :       //fNonLinearityParams[0] = 0.139393/0.1349766;
     764             :       //fNonLinearityParams[1] = 0.0566186;
     765             :       //fNonLinearityParams[2] = 0.982133;
     766           0 :       energy /= fNonLinearityParams[0]*(1-fNonLinearityParams[1]*exp(-fNonLinearityParams[2]*energy));
     767             :       
     768           0 :       break;
     769             :     }
     770             :       
     771             :     case kBeamTest:
     772             :     {
     773             :       //From beam test, Alexei's results, for different ZS thresholds
     774             :       //                        th=30 MeV; th = 45 MeV; th = 75 MeV
     775             :       //fNonLinearityParams[0] = 1.007;      1.003;      1.002 
     776             :       //fNonLinearityParams[1] = 0.894;      0.719;      0.797 
     777             :       //fNonLinearityParams[2] = 0.246;      0.334;      0.358 
     778             :       //Rescale the param[0] with 1.03
     779           0 :       energy /= fNonLinearityParams[0]/(1+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]));
     780             :       
     781           0 :       break;
     782             :     }
     783             :       
     784             :     case kBeamTestCorrected:
     785             :     {
     786             :       // From beam test, corrected for material between beam and EMCAL
     787             :       //fNonLinearityParams[0] =  0.99078
     788             :       //fNonLinearityParams[1] =  0.161499;
     789             :       //fNonLinearityParams[2] =  0.655166; 
     790             :       //fNonLinearityParams[3] =  0.134101;
     791             :       //fNonLinearityParams[4] =  163.282;
     792             :       //fNonLinearityParams[5] =  23.6904;
     793             :       //fNonLinearityParams[6] =  0.978;
     794           0 :         energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     795             : 
     796           0 :       break;
     797             :     }
     798             :      
     799             :     case kBeamTestCorrectedv2:
     800             :     {
     801             :       // From beam test, corrected for material between beam and EMCAL
     802             :       // Different function to kBeamTestCorrected
     803             :       //fNonLinearityParams[0] =  0.983504;
     804             :       //fNonLinearityParams[1] =  0.210106;
     805             :       //fNonLinearityParams[2] =  0.897274;
     806             :       //fNonLinearityParams[3] =  0.0829064;
     807             :       //fNonLinearityParams[4] =  152.299;
     808             :       //fNonLinearityParams[5] =  31.5028;
     809             :       //fNonLinearityParams[6] =  0.968;
     810           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     811             :       
     812           0 :       break;
     813             :     }
     814             :       
     815             :     case kBeamTestCorrectedv3:
     816             :     {
     817             :       // Same function as kBeamTestCorrectedv2, different default parametrization.
     818             :       //fNonLinearityParams[0] =  0.976941;
     819             :       //fNonLinearityParams[1] =  0.162310;
     820             :       //fNonLinearityParams[2] =  1.08689;
     821             :       //fNonLinearityParams[3] =  0.0819592;
     822             :       //fNonLinearityParams[4] =  152.338;
     823             :       //fNonLinearityParams[5] =  30.9594;
     824             :       //fNonLinearityParams[6] =  0.9615;
     825           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     826             :       
     827           0 :       break;
     828             :     }
     829             :       
     830             :     case kSDMv5:
     831             :     {
     832             :       //Based on fit to the MC/data using kNoCorrection on the data - utilizes symmetric decay method and kPi0MCv5(MC) - 28 Oct 2013
     833             :       //fNonLinearityParams[0] =  1.0;
     834             :       //fNonLinearityParams[1] =  6.64778e-02;
     835             :       //fNonLinearityParams[2] =  1.570;
     836             :       //fNonLinearityParams[3] =  9.67998e-02;
     837             :       //fNonLinearityParams[4] =  2.19381e+02;
     838             :       //fNonLinearityParams[5] =  6.31604e+01;
     839             :       //fNonLinearityParams[6] =  1.01286;
     840           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5])))) * (0.964 + exp(-3.132-0.435*energy*2.0));
     841             :       
     842           0 :       break;
     843             :     }
     844             :       
     845             :     case kPi0MCv5:
     846             :     {
     847             :       //Based on comparing MC truth information to the reconstructed energy of clusters. 
     848             :       //fNonLinearityParams[0] =  1.0;
     849             :       //fNonLinearityParams[1] =  6.64778e-02;
     850             :       //fNonLinearityParams[2] =  1.570;
     851             :       //fNonLinearityParams[3] =  9.67998e-02;
     852             :       //fNonLinearityParams[4] =  2.19381e+02;
     853             :       //fNonLinearityParams[5] =  6.31604e+01;
     854             :       //fNonLinearityParams[6] =  1.01286;
     855           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     856             :       
     857           0 :       break;
     858             :     }
     859             :       
     860             :     case kSDMv6:
     861             :     {
     862             :       //Based on fit to the MC/data using kNoCorrection on the data 
     863             :       //  - utilizes symmetric decay method and kPi0MCv6(MC) - 09 Dec 2014
     864             :       //  - parameters constrained by the test beam data as well
     865             :       // described in the note: https://aliceinfo.cern.ch/Notes/node/211 - Sec 3.1.2 (Test Beam Constrained SDM).
     866             :       //fNonLinearityParams[0] =  1.0;
     867             :       //fNonLinearityParams[1] =  0.237767;
     868             :       //fNonLinearityParams[2] =  0.651203;
     869             :       //fNonLinearityParams[3] =  0.183741;
     870             :       //fNonLinearityParams[4] =  155.427;
     871             :       //fNonLinearityParams[5] =  17.0335;
     872             :       //fNonLinearityParams[6] =  0.987054;
     873           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     874             :       
     875           0 :       break;
     876             :     }
     877             :       
     878             :     case kPi0MCv6:
     879             :     {
     880             :       //Based on comparing MC truth information to the reconstructed energy of clusters.
     881             :       // described in the note: https://aliceinfo.cern.ch/Notes/node/211 - Sec 3.1.2 (Test Beam Constrained SDM).
     882             :       //fNonLinearityParams[0] =  1.0;
     883             :       //fNonLinearityParams[1] =  0.0797873;
     884             :       //fNonLinearityParams[2] =  1.68322;
     885             :       //fNonLinearityParams[3] =  0.0806098;
     886             :       //fNonLinearityParams[4] =  244.586;
     887             :       //fNonLinearityParams[5] =  116.938;
     888             :       //fNonLinearityParams[6] =  1.00437;
     889           0 :       energy *= fNonLinearityParams[6]/(fNonLinearityParams[0]*(1./(1.+fNonLinearityParams[1]*exp(-energy/fNonLinearityParams[2]))*1./(1.+fNonLinearityParams[3]*exp((energy-fNonLinearityParams[4])/fNonLinearityParams[5]))));
     890             :       
     891           0 :       break;
     892             :     }
     893             :       
     894             :     case kNoCorrection:
     895           0 :       AliDebug(2,"No correction on the energy\n");
     896             :       break;
     897             :       
     898             :   }
     899             :   
     900           0 :   return energy;
     901           0 : }
     902             : 
     903             : ///
     904             : /// Initialising non Linearity Parameters for the different
     905             : /// parametrizations available, defined in enum NonlinearityFunctions
     906             : ///
     907             : //__________________________________________________
     908             : void AliEMCALRecoUtils::InitNonLinearityParam()
     909             : {
     910           0 :   if (fNonLinearityFunction == kPi0MC) {
     911           0 :     fNonLinearityParams[0] = 1.014;
     912           0 :     fNonLinearityParams[1] = -0.03329;
     913           0 :     fNonLinearityParams[2] = -0.3853;
     914           0 :     fNonLinearityParams[3] = 0.5423;
     915           0 :     fNonLinearityParams[4] = -0.4335;
     916           0 :   }
     917             :   
     918           0 :   if (fNonLinearityFunction == kPi0MCv2) {
     919           0 :     fNonLinearityParams[0] = 3.11111e-02;
     920           0 :     fNonLinearityParams[1] =-5.71666e-02; 
     921           0 :     fNonLinearityParams[2] = 5.67995e-01;      
     922           0 :   }
     923             :   
     924           0 :   if (fNonLinearityFunction == kPi0MCv3) {
     925           0 :     fNonLinearityParams[0] =  9.81039e-01;
     926           0 :     fNonLinearityParams[1] =  1.13508e-01;
     927           0 :     fNonLinearityParams[2] =  1.00173e+00; 
     928           0 :     fNonLinearityParams[3] =  9.67998e-02;
     929           0 :     fNonLinearityParams[4] =  2.19381e+02;
     930           0 :     fNonLinearityParams[5] =  6.31604e+01;
     931           0 :     fNonLinearityParams[6] =  1;
     932           0 :   }
     933             :   
     934           0 :   if (fNonLinearityFunction == kPi0GammaGamma) {
     935           0 :     fNonLinearityParams[0] = 1.04;
     936           0 :     fNonLinearityParams[1] = -0.1445;
     937           0 :     fNonLinearityParams[2] = 1.046;
     938           0 :   }  
     939             : 
     940           0 :   if (fNonLinearityFunction == kPi0GammaConversion) {
     941           0 :     fNonLinearityParams[0] = 0.139393;
     942           0 :     fNonLinearityParams[1] = 0.0566186;
     943           0 :     fNonLinearityParams[2] = 0.982133;
     944           0 :   }  
     945             : 
     946           0 :   if (fNonLinearityFunction == kBeamTest) {
     947           0 :     if (fNonLinearThreshold == 30) {
     948           0 :       fNonLinearityParams[0] = 1.007; 
     949           0 :       fNonLinearityParams[1] = 0.894; 
     950           0 :       fNonLinearityParams[2] = 0.246; 
     951           0 :     }
     952           0 :     if (fNonLinearThreshold == 45) {
     953           0 :       fNonLinearityParams[0] = 1.003; 
     954           0 :       fNonLinearityParams[1] = 0.719; 
     955           0 :       fNonLinearityParams[2] = 0.334; 
     956           0 :     }
     957           0 :     if (fNonLinearThreshold == 75) {
     958           0 :       fNonLinearityParams[0] = 1.002; 
     959           0 :       fNonLinearityParams[1] = 0.797; 
     960           0 :       fNonLinearityParams[2] = 0.358; 
     961           0 :     }
     962             :   }
     963             : 
     964           0 :   if (fNonLinearityFunction == kBeamTestCorrected) {
     965           0 :     fNonLinearityParams[0] =  0.99078;
     966           0 :     fNonLinearityParams[1] =  0.161499;
     967           0 :     fNonLinearityParams[2] =  0.655166; 
     968           0 :     fNonLinearityParams[3] =  0.134101;
     969           0 :     fNonLinearityParams[4] =  163.282;
     970           0 :     fNonLinearityParams[5] =  23.6904;
     971           0 :     fNonLinearityParams[6] =  0.978;
     972           0 :   }
     973             :   
     974           0 :   if (fNonLinearityFunction == kBeamTestCorrectedv2) {
     975             :     // Parameters until November 2015, use now kBeamTestCorrectedv3
     976           0 :     fNonLinearityParams[0] =  0.983504;
     977           0 :     fNonLinearityParams[1] =  0.210106;
     978           0 :     fNonLinearityParams[2] =  0.897274;
     979           0 :     fNonLinearityParams[3] =  0.0829064;
     980           0 :     fNonLinearityParams[4] =  152.299;
     981           0 :     fNonLinearityParams[5] =  31.5028;
     982           0 :     fNonLinearityParams[6] =  0.968;    
     983           0 :   }
     984             : 
     985           0 :   if (fNonLinearityFunction == kBeamTestCorrectedv3) {
     986             :     
     987             :     // New parametrization of kBeamTestCorrectedv2
     988             :     // excluding point at 0.5 GeV from Beam Test Data
     989             :     // https://indico.cern.ch/event/438805/contribution/1/attachments/1145354/1641875/emcalPi027August2015.pdf
     990             :     
     991           0 :     fNonLinearityParams[0] =  0.976941;
     992           0 :     fNonLinearityParams[1] =  0.162310;
     993           0 :     fNonLinearityParams[2] =  1.08689;
     994           0 :     fNonLinearityParams[3] =  0.0819592;
     995           0 :     fNonLinearityParams[4] =  152.338;
     996           0 :     fNonLinearityParams[5] =  30.9594;
     997           0 :     fNonLinearityParams[6] =  0.9615;
     998           0 :   }
     999             : 
    1000           0 :   if (fNonLinearityFunction == kSDMv5) {
    1001           0 :     fNonLinearityParams[0] =  1.0;
    1002           0 :     fNonLinearityParams[1] =  6.64778e-02;
    1003           0 :     fNonLinearityParams[2] =  1.570;
    1004           0 :     fNonLinearityParams[3] =  9.67998e-02;
    1005           0 :     fNonLinearityParams[4] =  2.19381e+02;
    1006           0 :     fNonLinearityParams[5] =  6.31604e+01;
    1007           0 :     fNonLinearityParams[6] =  1.01286;
    1008           0 :   }
    1009             : 
    1010           0 :   if (fNonLinearityFunction == kPi0MCv5) {
    1011           0 :     fNonLinearityParams[0] =  1.0;
    1012           0 :     fNonLinearityParams[1] =  6.64778e-02;
    1013           0 :     fNonLinearityParams[2] =  1.570;
    1014           0 :     fNonLinearityParams[3] =  9.67998e-02;
    1015           0 :     fNonLinearityParams[4] =  2.19381e+02;
    1016           0 :     fNonLinearityParams[5] =  6.31604e+01;
    1017           0 :     fNonLinearityParams[6] =  1.01286;
    1018           0 :   }
    1019             : 
    1020           0 :   if (fNonLinearityFunction == kSDMv6) {
    1021           0 :     fNonLinearityParams[0] = 1.0;      
    1022           0 :     fNonLinearityParams[1] = 0.237767; 
    1023           0 :     fNonLinearityParams[2] = 0.651203; 
    1024           0 :     fNonLinearityParams[3] = 0.183741; 
    1025           0 :     fNonLinearityParams[4] = 155.427;  
    1026           0 :     fNonLinearityParams[5] = 17.0335;  
    1027           0 :     fNonLinearityParams[6] = 0.987054; 
    1028           0 :   }
    1029             : 
    1030           0 :   if (fNonLinearityFunction == kPi0MCv6) {
    1031           0 :     fNonLinearityParams[0] = 1.0;       
    1032           0 :     fNonLinearityParams[1] = 0.0797873; 
    1033           0 :     fNonLinearityParams[2] = 1.68322;   
    1034           0 :     fNonLinearityParams[3] = 0.0806098; 
    1035           0 :     fNonLinearityParams[4] = 244.586;   
    1036           0 :     fNonLinearityParams[5] = 116.938;   
    1037           0 :     fNonLinearityParams[6] = 1.00437;   
    1038           0 :   }
    1039           0 : }
    1040             : 
    1041             : ///
    1042             : /// Calculate shower depth for a given cluster energy and particle type.
    1043             : /// Needed to calculate cluster position.
    1044             : ///
    1045             : /// \param energy: cluster energy
    1046             : /// \param iParticle: particle assumption defined in enum ParticleType
    1047             : /// \param iSM: supermodule number
    1048             : ///
    1049             : //_________________________________________________________
    1050             : Float_t  AliEMCALRecoUtils::GetDepth(Float_t energy, 
    1051             :                                      Int_t iParticle, 
    1052             :                                      Int_t iSM) const 
    1053             : {
    1054             :   // parameters 
    1055             :   Float_t x0    = 1.31;
    1056             :   Float_t ecr   = 8;
    1057             :   Float_t depth = 0;
    1058           0 :   Float_t arg   = energy*1000/ ecr; //Multiply energy by 1000 to transform to MeV
    1059             :   
    1060           0 :   switch ( iParticle )
    1061             :   {
    1062             :     case kPhoton:
    1063           0 :       if (arg < 1) 
    1064           0 :         depth = 0;
    1065             :       else
    1066           0 :         depth = x0 * (TMath::Log(arg) + 0.5); 
    1067             :       break;
    1068             :       
    1069             :     case kElectron:
    1070           0 :       if (arg < 1) 
    1071           0 :         depth = 0;
    1072             :       else
    1073           0 :         depth = x0 * (TMath::Log(arg) - 0.5); 
    1074             :       break;
    1075             :       
    1076             :     case kHadron:
    1077             :       // hadron 
    1078             :       // boxes anc. here
    1079           0 :       if (gGeoManager) 
    1080             :       {
    1081           0 :         gGeoManager->cd("ALIC_1/XEN1_1");
    1082           0 :         TGeoNode        *geoXEn1    = gGeoManager->GetCurrentNode();
    1083           0 :         TGeoNodeMatrix  *geoSM      = dynamic_cast<TGeoNodeMatrix *>(geoXEn1->GetDaughter(iSM));
    1084           0 :         if (geoSM) 
    1085             :         {
    1086           0 :           TGeoVolume      *geoSMVol   = geoSM->GetVolume(); 
    1087           0 :           TGeoShape       *geoSMShape = geoSMVol->GetShape();
    1088           0 :           TGeoBBox        *geoBox     = dynamic_cast<TGeoBBox *>(geoSMShape);
    1089           0 :           if (geoBox) depth = 0.5 * geoBox->GetDX()*2 ;
    1090           0 :           else AliFatal("Null GEANT box");
    1091           0 :         }
    1092           0 :         else AliFatal("NULL  GEANT node matrix");
    1093           0 :       }
    1094             :       else
    1095             :       {//electron
    1096           0 :         if (arg < 1) 
    1097           0 :           depth = 0;
    1098             :         else
    1099           0 :           depth = x0 * (TMath::Log(arg) - 0.5); 
    1100             :       }
    1101             :       
    1102             :       break;
    1103             :       
    1104             :     default://photon
    1105           0 :       if (arg < 1) 
    1106           0 :         depth = 0;
    1107             :       else
    1108           0 :         depth = x0 * (TMath::Log(arg) + 0.5);
    1109             :   }  
    1110             :   
    1111           0 :   return depth;
    1112             : }
    1113             : 
    1114             : ///
    1115             : /// For a given CaloCluster gets the absId of the cell 
    1116             : /// with maximum energy deposit.
    1117             : ///
    1118             : /// \param geom: AliEMCALGeometry pointer
    1119             : /// \param cells: full list of cells
    1120             : /// \param clu: pointer to AliVCluster
    1121             : /// \param absId: absolute id number of cell with highest energy in cluster
    1122             : /// \param iSupmod: supermodule number of cell with highest energy in cluster
    1123             : /// \param ieta: column number of cell with highest energy in cluster
    1124             : /// \param iphi: row number of cell with highest energy in cluster
    1125             : /// \param shared: cluster is shared between 2 supermodules
    1126             : ///
    1127             : //____________________________________________________________________
    1128             : void AliEMCALRecoUtils::GetMaxEnergyCell(const AliEMCALGeometry *geom, 
    1129             :                                          AliVCaloCells* cells, 
    1130             :                                          const AliVCluster* clu, 
    1131             :                                          Int_t  & absId,  
    1132             :                                          Int_t  & iSupMod, 
    1133             :                                          Int_t  & ieta, 
    1134             :                                          Int_t  & iphi, 
    1135             :                                          Bool_t & shared)
    1136             : {  
    1137             :   Double_t eMax        = -1.;
    1138             :   Double_t eCell       = -1.;
    1139             :   Float_t  fraction    = 1.;
    1140             :   Float_t  recalFactor = 1.;
    1141             :   Int_t    cellAbsId   = -1 ;
    1142             : 
    1143           0 :   Int_t iTower  = -1;
    1144           0 :   Int_t iIphi   = -1;
    1145           0 :   Int_t iIeta   = -1;
    1146             :   Int_t iSupMod0= -1;
    1147             : 
    1148           0 :   if (!clu) 
    1149             :   {
    1150           0 :     AliInfo("Cluster pointer null!");
    1151           0 :     absId=-1; iSupMod0=-1, ieta = -1; iphi = -1; shared = -1;
    1152           0 :     return;
    1153             :   }
    1154             :   
    1155           0 :   for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) 
    1156             :   {
    1157           0 :     cellAbsId = clu->GetCellAbsId(iDig);
    1158           0 :     fraction  = clu->GetCellAmplitudeFraction(iDig);
    1159             :     //printf("a Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,cells->GetCellAmplitude(cellAbsId),fraction);
    1160           0 :     if (fraction < 1e-4) fraction = 1.; // in case unfolding is off
    1161             :     
    1162           0 :     geom->GetCellIndex(cellAbsId,iSupMod,iTower,iIphi,iIeta); 
    1163           0 :     geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);
    1164             :     
    1165           0 :     if (iDig==0) 
    1166             :     {
    1167           0 :       iSupMod0=iSupMod;
    1168           0 :     } else if (iSupMod0!=iSupMod)  
    1169             :     {
    1170           0 :       shared = kTRUE;
    1171             :       //printf("AliEMCALRecoUtils::GetMaxEnergyCell() - SHARED CLUSTER\n");
    1172           0 :     }
    1173             : 
    1174           0 :     if (!fCellsRecalibrated && IsRecalibrationOn()) 
    1175           0 :       recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
    1176             :     
    1177           0 :     eCell  = cells->GetCellAmplitude(cellAbsId)*fraction*recalFactor;
    1178             :     //printf("b Cell %d, id, %d, amp %f, fraction %f\n",iDig,cellAbsId,eCell,fraction);
    1179           0 :     if (eCell > eMax) 
    1180             :     { 
    1181             :       eMax  = eCell; 
    1182           0 :       absId = cellAbsId;
    1183             :       //printf("\t new max: cell %d, e %f, ecell %f\n",maxId, eMax,eCell);
    1184           0 :     }
    1185             :   }// cell loop
    1186             :   
    1187             :   //Get from the absid the supermodule, tower and eta/phi numbers
    1188           0 :   geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta); 
    1189             :   //Gives SuperModule and Tower numbers
    1190           0 :   geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta); 
    1191             :   //printf("Max id %d, iSM %d, col %d, row %d\n",absId,iSupMod,ieta,iphi);
    1192             :   //printf("Max end---\n");
    1193           0 : }
    1194             : 
    1195             : ///
    1196             : /// Initialize data members with default values
    1197             : ///
    1198             : //______________________________________
    1199             : void AliEMCALRecoUtils::InitParameters()
    1200             : {  
    1201           0 :   fParticleType = kPhoton;
    1202           0 :   fPosAlgo      = kUnchanged;
    1203           0 :   fW0           = 4.5;
    1204             :   
    1205           0 :   fNonLinearityFunction = kNoCorrection;
    1206           0 :   fNonLinearThreshold   = 30;
    1207             :   
    1208           0 :   fExoticCellFraction     = 0.97;
    1209           0 :   fExoticCellDiffTime     = 1e6;
    1210           0 :   fExoticCellMinAmplitude = 4.0;
    1211             :   
    1212           0 :   fAODFilterMask    = 128;
    1213           0 :   fAODHybridTracks  = kFALSE;
    1214           0 :   fAODTPCOnlyTracks = kTRUE;
    1215             :   
    1216           0 :   fCutEtaPhiSum      = kTRUE;
    1217           0 :   fCutEtaPhiSeparate = kFALSE;
    1218             :   
    1219           0 :   fCutR   = 0.05; 
    1220           0 :   fCutEta = 0.025; 
    1221           0 :   fCutPhi = 0.05;
    1222             :   
    1223           0 :   fClusterWindow = 100;
    1224           0 :   fMass          = 0.139;
    1225             :   
    1226           0 :   fStepSurface   = 20.;                      
    1227           0 :   fStepCluster   = 5.;
    1228           0 :   fTrackCutsType = kLooseCut;
    1229             :   
    1230           0 :   fCutMinTrackPt     = 0;
    1231           0 :   fCutMinNClusterTPC = -1;
    1232           0 :   fCutMinNClusterITS = -1;
    1233             :   
    1234           0 :   fCutMaxChi2PerClusterTPC  = 1e10;
    1235           0 :   fCutMaxChi2PerClusterITS  = 1e10;
    1236             :   
    1237           0 :   fCutRequireTPCRefit     = kFALSE;
    1238           0 :   fCutRequireITSRefit     = kFALSE;
    1239           0 :   fCutAcceptKinkDaughters = kFALSE;
    1240             :   
    1241           0 :   fCutMaxDCAToVertexXY = 1e10;             
    1242           0 :   fCutMaxDCAToVertexZ  = 1e10;              
    1243           0 :   fCutDCAToVertex2D    = kFALSE;
    1244             :   
    1245           0 :   fCutRequireITSStandAlone = kFALSE; //MARCEL
    1246           0 :   fCutRequireITSpureSA     = kFALSE; //Marcel
    1247             :   
    1248             :   // Misalignment matrices
    1249           0 :   for (Int_t i = 0; i < 15 ; i++) 
    1250             :   {
    1251           0 :     fMisalTransShift[i] = 0.; 
    1252           0 :     fMisalRotShift[i]   = 0.; 
    1253             :   }
    1254             :   
    1255             :   // Non linearity
    1256           0 :   for (Int_t i = 0; i < 7  ; i++) fNonLinearityParams[i] = 0.; 
    1257             :   
    1258             :   // For kBeamTestCorrectedv2 case, but default is no correction
    1259           0 :   fNonLinearityParams[0] =  0.983504;
    1260           0 :   fNonLinearityParams[1] =  0.210106;
    1261           0 :   fNonLinearityParams[2] =  0.897274;
    1262           0 :   fNonLinearityParams[3] =  0.0829064;
    1263           0 :   fNonLinearityParams[4] =  152.299;
    1264           0 :   fNonLinearityParams[5] =  31.5028;
    1265           0 :   fNonLinearityParams[6] =  0.968;
    1266             :   
    1267             :   // Cluster energy smearing
    1268           0 :   fSmearClusterEnergy   = kFALSE;
    1269           0 :   fSmearClusterParam[0] = 0.07; // * sqrt E term
    1270           0 :   fSmearClusterParam[1] = 0.00; // * E term
    1271           0 :   fSmearClusterParam[2] = 0.00; // constant
    1272           0 : }
    1273             : 
    1274             : ///
    1275             : /// Init EMCAL energy calibration factors container
    1276             : ///
    1277             : //_____________________________________________________
    1278             : void AliEMCALRecoUtils::InitEMCALRecalibrationFactors()
    1279             : {
    1280           0 :   AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
    1281             :   
    1282             :   // In order to avoid rewriting the same histograms
    1283           0 :   Bool_t oldStatus = TH1::AddDirectoryStatus();
    1284           0 :   TH1::AddDirectory(kFALSE);
    1285             :   
    1286           0 :   fEMCALRecalibrationFactors = new TObjArray(22);
    1287           0 :   for (int i = 0; i < 22; i++) 
    1288           0 :     fEMCALRecalibrationFactors->Add(new TH2F(Form("EMCALRecalFactors_SM%d",i),
    1289           0 :                                              Form("EMCALRecalFactors_SM%d",i),  48, 0, 48, 24, 0, 24));
    1290             :   //Init the histograms with 1
    1291           0 :   for (Int_t sm = 0; sm < 22; sm++) 
    1292             :   {
    1293           0 :     for (Int_t i = 0; i < 48; i++) 
    1294             :     {
    1295           0 :       for (Int_t j = 0; j < 24; j++) 
    1296             :       {
    1297           0 :         SetEMCALChannelRecalibrationFactor(sm,i,j,1.);
    1298             :       }
    1299             :     }
    1300             :   }
    1301             :   
    1302           0 :   fEMCALRecalibrationFactors->SetOwner(kTRUE);
    1303           0 :   fEMCALRecalibrationFactors->Compress();
    1304             :   
    1305             :   // In order to avoid rewriting the same histograms
    1306           0 :   TH1::AddDirectory(oldStatus);    
    1307           0 : }
    1308             : 
    1309             : ///
    1310             : /// Init EMCAL time calibration shifts container
    1311             : ///
    1312             : //_________________________________________________________
    1313             : void AliEMCALRecoUtils::InitEMCALTimeRecalibrationFactors()
    1314             : {
    1315           0 :   AliDebug(2,"AliCalorimeterUtils::InitEMCALRecalibrationFactors()");
    1316             : 
    1317             :   // In order to avoid rewriting the same histograms
    1318           0 :   Bool_t oldStatus = TH1::AddDirectoryStatus();
    1319           0 :   TH1::AddDirectory(kFALSE);
    1320             :   
    1321           0 :   if(fLowGain) fEMCALTimeRecalibrationFactors = new TObjArray(8);
    1322           0 :   else fEMCALTimeRecalibrationFactors = new TObjArray(4);
    1323             : 
    1324           0 :   for (int i = 0; i < 4; i++) 
    1325           0 :     fEMCALTimeRecalibrationFactors->Add(new TH1F(Form("hAllTimeAvBC%d",i),
    1326           0 :                                                  Form("hAllTimeAvBC%d",i),  
    1327             :                                                  48*24*22,0.,48*24*22)          );
    1328             :   // Init the histograms with 0
    1329           0 :   for (Int_t iBC = 0; iBC < 4; iBC++) 
    1330             :   {
    1331           0 :     for (Int_t iCh = 0; iCh < 48*24*22; iCh++) 
    1332           0 :       SetEMCALChannelTimeRecalibrationFactor(iBC,iCh,0.,kFALSE);
    1333             :   }
    1334             : 
    1335           0 :   if(fLowGain) {
    1336           0 :     for (int iBC = 0; iBC < 4; iBC++) {
    1337           0 :       fEMCALTimeRecalibrationFactors->Add(new TH1F(Form("hAllTimeAvLGBC%d",iBC),
    1338           0 :                                                    Form("hAllTimeAvLGBC%d",iBC),  
    1339             :                                                    48*24*22,0.,48*24*22)        );
    1340           0 :       for (Int_t iCh = 0; iCh < 48*24*22; iCh++) 
    1341           0 :         SetEMCALChannelTimeRecalibrationFactor(iBC,iCh,0.,kTRUE);
    1342             :     }
    1343           0 :   }
    1344             : 
    1345             : 
    1346             :   
    1347           0 :   fEMCALTimeRecalibrationFactors->SetOwner(kTRUE);
    1348           0 :   fEMCALTimeRecalibrationFactors->Compress();
    1349             :   
    1350             :   // In order to avoid rewriting the same histograms
    1351           0 :   TH1::AddDirectory(oldStatus);    
    1352           0 : }
    1353             : 
    1354             : ///
    1355             : /// Init EMCAL bad channels map container
    1356             : ///
    1357             : //____________________________________________________
    1358             : void AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()
    1359             : {
    1360           0 :   AliDebug(2,"AliEMCALRecoUtils::InitEMCALBadChannelStatusMap()");
    1361             : 
    1362             :   // In order to avoid rewriting the same histograms
    1363           0 :   Bool_t oldStatus = TH1::AddDirectoryStatus();
    1364           0 :   TH1::AddDirectory(kFALSE);
    1365             :   
    1366           0 :   fEMCALBadChannelMap = new TObjArray(22);
    1367             :   //TH2F * hTemp = new  TH2I("EMCALBadChannelMap","EMCAL SuperModule bad channel map", 48, 0, 48, 24, 0, 24);
    1368             :   
    1369           0 :   for (int i = 0; i < 22; i++) 
    1370           0 :     fEMCALBadChannelMap->Add(new TH2I(Form("EMCALBadChannelMap_Mod%d",i),Form("EMCALBadChannelMap_Mod%d",i), 48, 0, 48, 24, 0, 24));
    1371             :   
    1372           0 :   fEMCALBadChannelMap->SetOwner(kTRUE);
    1373           0 :   fEMCALBadChannelMap->Compress();
    1374             :   
    1375             :   // In order to avoid rewriting the same histograms
    1376           0 :   TH1::AddDirectory(oldStatus);    
    1377           0 : }
    1378             : 
    1379             : ///
    1380             : /// Init EMCAL L1 phase shifts container
    1381             : ///
    1382             : //___________________________________________________________
    1383             : void AliEMCALRecoUtils::InitEMCALL1PhaseInTimeRecalibration()
    1384             : {
    1385           0 :   AliDebug(2,"AliEMCALRecoUtils::InitEMCALL1PhaseInTimeRecalibrationFactors()");
    1386             :  
    1387             :   // In order to avoid rewriting the same histograms
    1388           0 :   Bool_t oldStatus = TH1::AddDirectoryStatus();
    1389           0 :   TH1::AddDirectory(kFALSE);
    1390             :   
    1391           0 :   fEMCALL1PhaseInTimeRecalibration = new TObjArray(1);
    1392             : 
    1393           0 :   fEMCALL1PhaseInTimeRecalibration->Add(new TH1C("h0","EMCALL1phaseForSM", 22, 0, 22));
    1394             :   
    1395           0 :   for (Int_t i = 0; i < 22; i++) //loop over SMs, default value = 0
    1396           0 :     SetEMCALL1PhaseInTimeRecalibrationForSM(i,0);
    1397             :   
    1398           0 :   fEMCALL1PhaseInTimeRecalibration->SetOwner(kTRUE);
    1399           0 :   fEMCALL1PhaseInTimeRecalibration->Compress();
    1400             :   
    1401             :   // In order to avoid rewriting the same histograms
    1402           0 :   TH1::AddDirectory(oldStatus);    
    1403           0 : }
    1404             : 
    1405             : ///
    1406             : /// Recalibrate the cluster energy and time, considering the recalibration map 
    1407             : /// and the time and energy of the cells that compose the cluster.
    1408             : ///
    1409             : /// \param geom: pointer to geometry
    1410             : /// \param cluster: pointer to cluster
    1411             : /// \param cells: list of cells
    1412             : /// \param bc: bunch crossing number returned by esdevent->GetBunchCrossNumber()
    1413             : ///
    1414             : //____________________________________________________________________________
    1415             : void AliEMCALRecoUtils::RecalibrateClusterEnergy(const AliEMCALGeometry* geom, 
    1416             :                                                  AliVCluster * cluster, 
    1417             :                                                  AliVCaloCells * cells, 
    1418             :                                                  Int_t bc)
    1419             : {  
    1420           0 :   if (!cluster) 
    1421             :   {
    1422           0 :     AliInfo("Cluster pointer null!");
    1423           0 :     return;
    1424             :   }  
    1425             :   
    1426             :   // Get the cluster number of cells and list of absId, check what kind of cluster do we have.
    1427           0 :   UShort_t * index    = cluster->GetCellsAbsId() ;
    1428           0 :   Double_t * fraction = cluster->GetCellsAmplitudeFraction() ;
    1429           0 :   Int_t ncells = cluster->GetNCells();
    1430             :   
    1431             :   // Initialize some used variables
    1432             :   Float_t energy = 0;
    1433             :   Int_t   absId  =-1;
    1434           0 :   Int_t   icol   =-1, irow =-1, imod=1;
    1435             :   Float_t factor = 1, frac = 0;
    1436             :   Int_t   absIdMax = -1;
    1437             :   Float_t emax     = 0;
    1438             :   
    1439             :   // Loop on the cells, get the cell amplitude and recalibration factor, multiply and and to the new energy
    1440           0 :   for (Int_t icell = 0; icell < ncells; icell++)
    1441             :   {
    1442           0 :     absId = index[icell];
    1443           0 :     frac =  fraction[icell];
    1444           0 :     if (frac < 1e-5) frac = 1; //in case of EMCAL, this is set as 0 since unfolding is off
    1445             :     
    1446           0 :     if (!fCellsRecalibrated && IsRecalibrationOn()) 
    1447             :     {
    1448             :       // Energy  
    1449           0 :       Int_t iTower = -1, iIphi = -1, iIeta = -1; 
    1450           0 :       geom->GetCellIndex(absId,imod,iTower,iIphi,iIeta); 
    1451           0 :       if (fEMCALRecalibrationFactors->GetEntries() <= imod) 
    1452           0 :         continue;
    1453           0 :       geom->GetCellPhiEtaIndexInSModule(imod,iTower,iIphi, iIeta,irow,icol);      
    1454           0 :       factor = GetEMCALChannelRecalibrationFactor(imod,icol,irow);
    1455             :       
    1456           0 :       AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - recalibrate cell: module %d, col %d, row %d, cell fraction %f,recalibration factor %f, cell energy %f\n",
    1457             :                       imod,icol,irow,frac,factor,cells->GetCellAmplitude(absId)));
    1458             :       
    1459           0 :     } 
    1460             :     
    1461           0 :     energy += cells->GetCellAmplitude(absId)*factor*frac;
    1462             :     
    1463           0 :     if (emax < cells->GetCellAmplitude(absId)*factor*frac) 
    1464             :     {
    1465           0 :       emax     = cells->GetCellAmplitude(absId)*factor*frac;
    1466             :       absIdMax = absId;
    1467           0 :     }
    1468             :   }
    1469             :   
    1470           0 :   AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Energy before %f, after %f \n",cluster->E(),energy));
    1471             :   
    1472           0 :   cluster->SetE(energy);
    1473             :   
    1474             :   // Recalculate time of cluster
    1475           0 :   Double_t timeorg = cluster->GetTOF();
    1476           0 :   Bool_t isLowGain = !(cells->GetCellHighGain(absIdMax));//HG = false -> LG = true
    1477             : 
    1478           0 :   Double_t time = cells->GetCellTime(absIdMax);
    1479           0 :   if (!fCellsRecalibrated && IsTimeRecalibrationOn())
    1480           0 :     RecalibrateCellTime(absIdMax,bc,time,isLowGain);
    1481           0 :   time-=fConstantTimeShift*1e-9; // only in case of Run1 old simulations
    1482             :   
    1483             :   // Recalibrate time with L1 phase 
    1484           0 :   if (!fCellsRecalibrated && IsL1PhaseInTimeRecalibrationOn())
    1485           0 :     RecalibrateCellTimeL1Phase(imod, bc, time);
    1486             :   
    1487           0 :   cluster->SetTOF(time);
    1488             :   
    1489           0 :   AliDebug(2,Form("AliEMCALRecoUtils::RecalibrateClusterEnergy - Time before %f, after %f \n",timeorg,cluster->GetTOF()));
    1490           0 : }
    1491             : 
    1492             : ///
    1493             : /// Recalibrate all the cells time and energy, considering the recalibration map and 
    1494             : /// the energy and time of each cell.
    1495             : ///
    1496             : /// \param cells: list of cells
    1497             : /// \param bc: bunch crossing number returned by esdevent->GetBunchCrossNumber()
    1498             : ///
    1499             : //_______________________________________________________________________
    1500             : void AliEMCALRecoUtils::RecalibrateCells(AliVCaloCells * cells, Int_t bc)
    1501             : {
    1502           0 :   if (!IsRecalibrationOn() && !IsTimeRecalibrationOn() && !IsBadChannelsRemovalSwitchedOn()) 
    1503             :     return;
    1504             :   
    1505           0 :   if (!cells) 
    1506             :   {
    1507           0 :     AliInfo("Cells pointer null!");
    1508           0 :     return;
    1509             :   }  
    1510             :   
    1511           0 :   Short_t  absId  =-1;
    1512             :   Bool_t   accept = kFALSE;
    1513           0 :   Float_t  ecell  = 0;
    1514           0 :   Double_t tcell  = 0;
    1515           0 :   Double_t ecellin = 0;
    1516           0 :   Double_t tcellin = 0;
    1517           0 :   Int_t  mclabel = -1;
    1518           0 :   Double_t efrac = 0;
    1519             :   
    1520           0 :   Int_t nEMcell  = cells->GetNumberOfCells() ;  
    1521           0 :   for (Int_t iCell = 0; iCell < nEMcell; iCell++) 
    1522             :   { 
    1523           0 :     cells->GetCell( iCell, absId, ecellin, tcellin, mclabel, efrac );
    1524             :     
    1525           0 :     accept = AcceptCalibrateCell(absId, bc, ecell ,tcell ,cells); 
    1526           0 :     if (!accept)
    1527             :     {
    1528           0 :       ecell = 0;
    1529           0 :       tcell = -1;
    1530           0 :     }
    1531             :     
    1532             :     // Set new values
    1533           0 :     cells->SetCell(iCell,absId,ecell, tcell, mclabel, efrac);
    1534             :   }
    1535             : 
    1536           0 :   fCellsRecalibrated = kTRUE;
    1537           0 : }
    1538             : 
    1539             : ///
    1540             : /// Recalibrate time of cell from AbsID number considering cell calibration map 
    1541             : ///
    1542             : /// \param absID: cell absolute ID number
    1543             : /// \param bc: bunch crossing number returned by esdevent->GetBunchCrossNumber()
    1544             : /// \param celltime: cell time to be returned calibrated
    1545             : ///
    1546             : //_______________________________________________________________________________________________________
    1547             : void AliEMCALRecoUtils::RecalibrateCellTime(Int_t absId, Int_t bc, Double_t & celltime, Bool_t isLGon) const
    1548             : {  
    1549           0 :   if (!fCellsRecalibrated && IsTimeRecalibrationOn() && bc >= 0) {
    1550           0 :     if(fLowGain)
    1551           0 :       celltime -= GetEMCALChannelTimeRecalibrationFactor(bc%4,absId,isLGon)*1.e-9;
    1552             :     else
    1553           0 :       celltime -= GetEMCALChannelTimeRecalibrationFactor(bc%4,absId,kFALSE)*1.e-9;
    1554             :   }
    1555           0 : }
    1556             : 
    1557             : ///
    1558             : /// Recalibrate time of cell from SM number considering the L1 phase shift 
    1559             : ///
    1560             : /// \param iSM: supermodule number
    1561             : /// \param bc: bunch crossing number returned by esdevent->GetBunchCrossNumber()
    1562             : /// \param celltime: cell time to be returned calibrated
    1563             : ///
    1564             : //_______________________________________________________________________________________________________
    1565             : void AliEMCALRecoUtils::RecalibrateCellTimeL1Phase(Int_t iSM, Int_t bc, Double_t & celltime) const
    1566             : {
    1567           0 :   if (!fCellsRecalibrated && IsL1PhaseInTimeRecalibrationOn() && bc >= 0) 
    1568             :   {
    1569           0 :     bc=bc%4;
    1570             : 
    1571             :     Float_t offsetPerSM=0.;
    1572           0 :     Int_t l1PhaseShift = GetEMCALL1PhaseInTimeRecalibrationForSM(iSM);
    1573           0 :     Int_t l1Phase=l1PhaseShift & 3; //bit operation
    1574             : 
    1575           0 :     if(bc >= l1Phase)
    1576           0 :       offsetPerSM = (bc - l1Phase)*25;
    1577             :     else
    1578           0 :       offsetPerSM = (bc - l1Phase + 4)*25;
    1579             : 
    1580           0 :     Int_t l1shiftOffset=l1PhaseShift>>2; //bit operation
    1581           0 :     l1shiftOffset*=25;
    1582             :    
    1583           0 :     celltime -= offsetPerSM*1.e-9;
    1584           0 :     celltime -= l1shiftOffset*1.e-9;
    1585           0 :   }
    1586           0 : }
    1587             : 
    1588             : ///
    1589             : /// For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
    1590             : ///
    1591             : /// \param geom: EMCal geometry pointer
    1592             : /// \param cells: list of EMCal cells with signal
    1593             : /// \param cluster: EMCal cluster subject to position recalculation
    1594             : ///
    1595             : //______________________________________________________________________________
    1596             : void AliEMCALRecoUtils::RecalculateClusterPosition(const AliEMCALGeometry *geom, 
    1597             :                                                    AliVCaloCells* cells, 
    1598             :                                                    AliVCluster* clu)
    1599             : {  
    1600           0 :   if (!clu)
    1601             :   {
    1602           0 :     AliInfo("Cluster pointer null!");
    1603           0 :     return;
    1604             :   }
    1605             :     
    1606           0 :   if      (fPosAlgo==kPosTowerGlobal) RecalculateClusterPositionFromTowerGlobal( geom, cells, clu);
    1607           0 :   else if (fPosAlgo==kPosTowerIndex)  RecalculateClusterPositionFromTowerIndex ( geom, cells, clu);
    1608           0 :   else    AliDebug(2,"Algorithm to recalculate position not selected, do nothing.");
    1609           0 : }  
    1610             : 
    1611             : ///
    1612             : /// For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
    1613             : /// The algorithm is a copy of what is done in AliEMCALRecPoint.
    1614             : ///
    1615             : /// \param geom: EMCal geometry pointer
    1616             : /// \param cells: list of EMCal cells with signal
    1617             : /// \param cluster: EMCal cluster subject to position recalculation
    1618             : ///
    1619             : //_____________________________________________________________________________________________
    1620             : void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerGlobal(const AliEMCALGeometry *geom, 
    1621             :                                                                   AliVCaloCells* cells, 
    1622             :                                                                   AliVCluster* clu)
    1623             : {  
    1624             :   Double_t eCell       = 0.;
    1625             :   Float_t  fraction    = 1.;
    1626             :   Float_t  recalFactor = 1.;
    1627             :   
    1628           0 :   Int_t    absId   = -1;
    1629           0 :   Int_t    iTower  = -1, iIphi  = -1, iIeta  = -1;
    1630           0 :   Int_t    iSupModMax = -1, iSM=-1, iphi   = -1, ieta   = -1;
    1631             :   Float_t  weight = 0.,  totalWeight=0.;
    1632           0 :   Float_t  newPos[3] = {-1.,-1.,-1.};
    1633           0 :   Double_t pLocal[3], pGlobal[3];
    1634           0 :   Bool_t shared = kFALSE;
    1635             : 
    1636           0 :   Float_t  clEnergy = clu->E(); //Energy already recalibrated previously
    1637           0 :   if (clEnergy <= 0) return;
    1638             :   
    1639           0 :   GetMaxEnergyCell(geom, cells, clu, absId,  iSupModMax, ieta, iphi,shared);
    1640           0 :   Double_t depth = GetDepth(clEnergy,fParticleType,iSupModMax) ;
    1641             :   
    1642             :   //printf("** Cluster energy %f, ncells %d, depth %f\n",clEnergy,clu->GetNCells(),depth);
    1643             :   
    1644           0 :   for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) 
    1645             :   {
    1646           0 :     absId = clu->GetCellAbsId(iDig);
    1647           0 :     fraction  = clu->GetCellAmplitudeFraction(iDig);
    1648           0 :     if (fraction < 1e-4) fraction = 1.; // in case unfolding is off
    1649             :     
    1650           0 :     if (!fCellsRecalibrated) 
    1651             :     {
    1652           0 :       geom->GetCellIndex(absId,iSM,iTower,iIphi,iIeta); 
    1653           0 :       geom->GetCellPhiEtaIndexInSModule(iSM,iTower,iIphi, iIeta,iphi,ieta);      
    1654           0 :       if (IsRecalibrationOn()) {
    1655           0 :         recalFactor = GetEMCALChannelRecalibrationFactor(iSM,ieta,iphi);
    1656           0 :       }
    1657             :     }
    1658             :     
    1659           0 :     eCell  = cells->GetCellAmplitude(absId)*fraction*recalFactor;
    1660             :     
    1661           0 :     weight = GetCellWeight(eCell,clEnergy);
    1662           0 :     totalWeight += weight;
    1663             :     
    1664           0 :     geom->RelPosCellInSModule(absId,depth,pLocal[0],pLocal[1],pLocal[2]);
    1665             :     //printf("pLocal (%f,%f,%f), SM %d, absId %d\n",pLocal[0],pLocal[1],pLocal[2],iSupModMax,absId);
    1666           0 :     geom->GetGlobal(pLocal,pGlobal,iSupModMax);
    1667             :     //printf("pLocal (%f,%f,%f)\n",pGlobal[0],pGlobal[1],pGlobal[2]);
    1668             : 
    1669           0 :     for (int i=0; i<3; i++ ) newPos[i] += (weight*pGlobal[i]);
    1670             :   }// cell loop
    1671             :   
    1672           0 :   if (totalWeight>0) 
    1673             :   {
    1674           0 :     for (int i=0; i<3; i++ )    newPos[i] /= totalWeight;
    1675           0 :   }
    1676             :     
    1677             :   //Float_t pos[]={0,0,0};
    1678             :   //clu->GetPosition(pos);
    1679             :   //printf("OldPos  : %2.3f,%2.3f,%2.3f\n",pos[0],pos[1],pos[2]);
    1680             :   //printf("NewPos  : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
    1681             :   
    1682           0 :   if (iSupModMax > 1) { //sector 1
    1683           0 :     newPos[0] +=fMisalTransShift[3];//-=3.093; 
    1684           0 :     newPos[1] +=fMisalTransShift[4];//+=6.82;
    1685           0 :     newPos[2] +=fMisalTransShift[5];//+=1.635;
    1686             :     //printf("   +    : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[3],fMisalTransShift[4],fMisalTransShift[5]);
    1687           0 :   } else { //sector 0
    1688           0 :     newPos[0] +=fMisalTransShift[0];//+=1.134;
    1689           0 :     newPos[1] +=fMisalTransShift[1];//+=8.2;
    1690           0 :     newPos[2] +=fMisalTransShift[2];//+=1.197;
    1691             :     //printf("   +    : %2.3f,%2.3f,%2.3f\n",fMisalTransShift[0],fMisalTransShift[1],fMisalTransShift[2]);
    1692             :   }
    1693             :   //printf("NewPos : %2.3f,%2.3f,%2.3f\n",newPos[0],newPos[1],newPos[2]);
    1694             : 
    1695           0 :   clu->SetPosition(newPos);
    1696           0 : }  
    1697             : 
    1698             : ///
    1699             : /// For a given CaloCluster recalculates the position for a given set of misalignment shifts and puts it again in the CaloCluster.
    1700             : /// The algorithm works with the tower indeces, averages the indeces and from them it calculates the global position.
    1701             : ///
    1702             : /// \param geom: EMCal geometry pointer
    1703             : /// \param cells: list of EMCal cells with signal
    1704             : /// \param cluster: EMCal cluster subject to position recalculation
    1705             : ///
    1706             : //____________________________________________________________________________________________
    1707             : void AliEMCALRecoUtils::RecalculateClusterPositionFromTowerIndex(const AliEMCALGeometry *geom, 
    1708             :                                                                  AliVCaloCells* cells, 
    1709             :                                                                  AliVCluster* clu)
    1710             : {
    1711             :   Double_t eCell       = 1.;
    1712             :   Float_t  fraction    = 1.;
    1713             :   Float_t  recalFactor = 1.;
    1714             :   
    1715           0 :   Int_t absId   = -1;
    1716           0 :   Int_t iTower  = -1;
    1717           0 :   Int_t iIphi   = -1, iIeta   = -1;
    1718           0 :   Int_t iSupMod = -1, iSupModMax = -1;
    1719           0 :   Int_t iphi = -1, ieta =-1;
    1720           0 :   Bool_t shared = kFALSE;
    1721             : 
    1722           0 :   Float_t clEnergy = clu->E(); //Energy already recalibrated previously.
    1723             :   
    1724           0 :   if (clEnergy <= 0)
    1725           0 :     return;
    1726           0 :   GetMaxEnergyCell(geom, cells, clu, absId,  iSupModMax, ieta, iphi,shared);
    1727           0 :   Float_t  depth = GetDepth(clEnergy,fParticleType,iSupMod) ;
    1728             : 
    1729             :   Float_t weight = 0., weightedCol = 0., weightedRow = 0., totalWeight=0.;
    1730             :   Bool_t areInSameSM = kTRUE; //exclude clusters with cells in different SMs for now
    1731             :   Int_t startingSM = -1;
    1732             :   
    1733           0 :   for (Int_t iDig=0; iDig< clu->GetNCells(); iDig++) 
    1734             :   {
    1735           0 :     absId = clu->GetCellAbsId(iDig);
    1736           0 :     fraction  = clu->GetCellAmplitudeFraction(iDig);
    1737           0 :     if (fraction < 1e-4) fraction = 1.; // in case unfolding is off
    1738             : 
    1739           0 :     if      (iDig==0)  startingSM = iSupMod;
    1740           0 :     else if (iSupMod != startingSM) areInSameSM = kFALSE;
    1741             : 
    1742           0 :     eCell  = cells->GetCellAmplitude(absId);
    1743             :     
    1744           0 :     geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta); 
    1745           0 :     geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi, iIeta,iphi,ieta);    
    1746             :     
    1747           0 :     if (!fCellsRecalibrated)
    1748             :     {
    1749           0 :       if (IsRecalibrationOn()) {
    1750           0 :         recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
    1751           0 :       }
    1752             :     }
    1753             :     
    1754           0 :     eCell  = cells->GetCellAmplitude(absId)*fraction*recalFactor;
    1755             :     
    1756           0 :     weight = GetCellWeight(eCell,clEnergy);
    1757           0 :     if (weight < 0) weight = 0;
    1758           0 :     totalWeight += weight;
    1759           0 :     weightedCol += ieta*weight;
    1760           0 :     weightedRow += iphi*weight;
    1761             :     
    1762             :     //printf("Max cell? cell %d, amplitude org %f, fraction %f, recalibration %f, amplitude new %f \n",cellAbsId, cells->GetCellAmplitude(cellAbsId), fraction, recalFactor, eCell) ;
    1763             :   }// cell loop
    1764             :     
    1765           0 :   Float_t xyzNew[]={-1.,-1.,-1.};
    1766           0 :   if (areInSameSM == kTRUE) 
    1767             :   {
    1768             :     //printf("In Same SM\n");
    1769           0 :     weightedCol = weightedCol/totalWeight;
    1770           0 :     weightedRow = weightedRow/totalWeight;
    1771           0 :     geom->RecalculateTowerPosition(weightedRow, weightedCol, iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew); 
    1772           0 :   } 
    1773             :   else 
    1774             :   {
    1775             :     //printf("In Different SM\n");
    1776           0 :     geom->RecalculateTowerPosition(iphi,        ieta,        iSupModMax, depth, fMisalTransShift, fMisalRotShift, xyzNew); 
    1777             :   }
    1778             :   
    1779           0 :   clu->SetPosition(xyzNew);
    1780           0 : }
    1781             : 
    1782             : ///
    1783             : /// Re-evaluate distance to bad channel with updated bad map
    1784             : ///
    1785             : /// \param geom: EMCal geometry pointer
    1786             : /// \param cells: list of EMCal cells with signal
    1787             : /// \param cluster: EMCal cluster subject to distance to bad channel recalculation
    1788             : ///
    1789             : //___________________________________________________________________________________________
    1790             : void AliEMCALRecoUtils::RecalculateClusterDistanceToBadChannel(const AliEMCALGeometry * geom, 
    1791             :                                                                AliVCaloCells* cells, 
    1792             :                                                                AliVCluster * cluster)
    1793             : {             
    1794           0 :   if (!fRecalDistToBadChannels) return;
    1795             :   
    1796           0 :   if (!cluster)
    1797             :   {
    1798           0 :     AliInfo("Cluster pointer null!");
    1799           0 :     return;
    1800             :   }  
    1801             :   
    1802             :   // Get channels map of the supermodule where the cluster is.
    1803           0 :   Int_t absIdMax  = -1, iSupMod =-1, icolM = -1, irowM = -1;
    1804           0 :   Bool_t shared = kFALSE;
    1805           0 :   GetMaxEnergyCell(geom, cells, cluster, absIdMax,  iSupMod, icolM, irowM, shared);
    1806           0 :   TH2D* hMap  = (TH2D*)fEMCALBadChannelMap->At(iSupMod);
    1807             : 
    1808             :   Int_t dRrow, dRcol;  
    1809             :   Float_t  minDist = 10000.;
    1810             :   Float_t  dist    = 0.;
    1811             :   
    1812             :   // Loop on tower status map 
    1813           0 :   for (Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++)
    1814             :   {
    1815           0 :     for (Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++)
    1816             :     {
    1817             :       // Check if tower is bad.
    1818           0 :       if (hMap->GetBinContent(icol,irow)==0) continue;
    1819             :       //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels() - \n \t Bad channel in SM %d, col %d, row %d, \n \t Cluster max in col %d, row %d\n",
    1820             :       //       iSupMod,icol, irow, icolM,irowM);
    1821             :       
    1822           0 :       dRrow=TMath::Abs(irowM-irow);
    1823           0 :       dRcol=TMath::Abs(icolM-icol);
    1824           0 :       dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
    1825           0 :       if (dist < minDist)
    1826             :       {
    1827             :         //printf("MIN DISTANCE TO BAD %2.2f\n",dist);
    1828             :         minDist = dist;
    1829           0 :       }
    1830             :     }
    1831             :   }
    1832             :   
    1833             :   // In case the cluster is shared by 2 SuperModules, need to check the map of the second Super Module
    1834           0 :   if (shared) 
    1835             :   {
    1836             :     TH2D* hMap2 = 0;
    1837             :     Int_t iSupMod2 = -1;
    1838             :     
    1839             :     // The only possible combinations are (0,1), (2,3) ... (8,9)
    1840           0 :     if (iSupMod%2) iSupMod2 = iSupMod-1;
    1841           0 :     else           iSupMod2 = iSupMod+1;
    1842           0 :     hMap2  = (TH2D*)fEMCALBadChannelMap->At(iSupMod2);
    1843             :     
    1844             :     // Loop on tower status map of second super module
    1845           0 :     for (Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++)
    1846             :     {
    1847           0 :       for (Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++)
    1848             :       {
    1849             :         // Check if tower is bad.
    1850           0 :         if (hMap2->GetBinContent(icol,irow)==0)  continue;
    1851             :         
    1852             :         //printf("AliEMCALRecoUtils::RecalculateDistanceToBadChannels(shared) - \n \t Bad channel in SM %d, col %d, row %d \n \t Cluster max in SM %d, col %d, row %d\n",
    1853             :         //     iSupMod2,icol, irow,iSupMod,icolM,irowM);
    1854           0 :         dRrow=TMath::Abs(irow-irowM);
    1855             :         
    1856           0 :         if (iSupMod%2) 
    1857           0 :           dRcol=TMath::Abs(icol-(AliEMCALGeoParams::fgkEMCALCols+icolM));
    1858             :         else 
    1859           0 :           dRcol=TMath::Abs(AliEMCALGeoParams::fgkEMCALCols+icol-icolM);
    1860             :         
    1861           0 :         dist=TMath::Sqrt(dRrow*dRrow+dRcol*dRcol);
    1862           0 :         if (dist < minDist) minDist = dist;        
    1863             :       }
    1864             :     }
    1865           0 :   }// shared cluster in 2 SuperModules
    1866             :   
    1867           0 :   AliDebug(2,Form("Max cluster cell (SM,col,row)=(%d %d %d) - Distance to Bad Channel %2.2f",iSupMod, icolM, irowM, minDist));
    1868           0 :   cluster->SetDistanceToBadChannel(minDist);
    1869           0 : }
    1870             : 
    1871             : ///
    1872             : /// Re-evaluate identification parameters with bayesian
    1873             : ///
    1874             : /// \param cluster: EMCal cluster subject to PID recalculation
    1875             : ///
    1876             : ///
    1877             : //__________________________________________________________________
    1878             : void AliEMCALRecoUtils::RecalculateClusterPID(AliVCluster * cluster)
    1879             : {             
    1880           0 :   if (!cluster)
    1881             :   {
    1882           0 :     AliInfo("Cluster pointer null!");
    1883           0 :     return;
    1884             :   }
    1885             :   
    1886           0 :   if (cluster->GetM02() != 0)
    1887           0 :     fPIDUtils->ComputePID(cluster->E(),cluster->GetM02());
    1888             :   
    1889           0 :   Float_t pidlist[AliPID::kSPECIESCN+1];
    1890           0 :   for (Int_t i = 0; i < AliPID::kSPECIESCN+1; i++) pidlist[i] = fPIDUtils->GetPIDFinal(i);
    1891             :         
    1892           0 :   cluster->SetPID(pidlist);
    1893           0 : }
    1894             : 
    1895             : ///
    1896             : /// Calculates different types of shower shape parameters, dispersion, shower shape eigenvalues and other.
    1897             : /// 
    1898             : /// \param geom: EMCal geometry pointer
    1899             : /// \param cells: list of EMCal cells with signal
    1900             : /// \param cluster: EMCal cluster subject to shower shape recalculation
    1901             : /// \param cellEcut: minimum cell energy to be considered in the shower shape recalculation
    1902             : /// \param cellTimeCut: time window of cells to be considered in shower recalculation
    1903             : /// \param bc: event bunch crossing number
    1904             : /// \param enAfterCuts: cluster energy when applying the cell cuts cellEcut and cellTime cut
    1905             : /// \param l0: main shower shape eigen value
    1906             : /// \param l1: second eigenvalue of shower shape
    1907             : /// \param disp: dispersion
    1908             : /// \param dEta: dispersion in eta (cols) direction
    1909             : /// \param dPhi: disperion in phi (rows) direction
    1910             : /// \param sEta: shower shape in eta  (cols) direction
    1911             : /// \param sPhi: shower shape in phi (rows) direction
    1912             : /// \param sEtaPhi: shower shape on phi / eta directions term
    1913             : ///
    1914             : ///
    1915             : //___________________________________________________________________________________________________________________
    1916             : void AliEMCALRecoUtils::RecalculateClusterShowerShapeParametersWithCellCuts(const AliEMCALGeometry * geom, 
    1917             :                                                                             AliVCaloCells* cells, AliVCluster * cluster,
    1918             :                                                                             Float_t cellEcut, Float_t cellTimeCut, Int_t bc, 
    1919             :                                                                             Float_t & enAfterCuts, Float_t & l0,   Float_t & l1,   
    1920             :                                                                             Float_t & disp, Float_t & dEta, Float_t & dPhi,
    1921             :                                                                             Float_t & sEta, Float_t & sPhi, Float_t & sEtaPhi)
    1922             : {  
    1923           0 :   if (!cluster) 
    1924             :   {
    1925           0 :     AliInfo("Cluster pointer null!");
    1926           0 :     return;
    1927             :   }
    1928             :     
    1929             :   Double_t eCell       = 0.;
    1930           0 :   Double_t tCell       = 0.;
    1931             :   Float_t  fraction    = 1.;
    1932             :   Float_t  recalFactor = 1.;
    1933             :   Bool_t   isLowGain   = kFALSE;
    1934             : 
    1935           0 :   Int_t    iSupMod = -1;
    1936           0 :   Int_t    iTower  = -1;
    1937           0 :   Int_t    iIphi   = -1;
    1938           0 :   Int_t    iIeta   = -1;
    1939           0 :   Int_t    iphi    = -1;
    1940           0 :   Int_t    ieta    = -1;
    1941             :   Double_t etai    = -1.;
    1942             :   Double_t phii    = -1.;
    1943             :   
    1944             :   Int_t    nstat   = 0 ;
    1945             :   Float_t  wtot    = 0.;
    1946             :   Double_t w       = 0.;
    1947             :   Double_t etaMean = 0.;
    1948             :   Double_t phiMean = 0.;
    1949             :   
    1950             :   // Loop on cells, calculate the cluster energy, in case a cut on cell energy is added,
    1951             :   // or the non linearity correction was applied
    1952             :   // and to check if the cluster is between 2 SM in eta
    1953             :   Int_t   iSM0   = -1;
    1954             :   Bool_t  shared = kFALSE;
    1955             :   Float_t energy = 0;
    1956           0 :   enAfterCuts = 0;
    1957             :   
    1958           0 :   for (Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++)
    1959             :   {
    1960             :     // Get from the absid the supermodule, tower and eta/phi numbers
    1961             :     
    1962           0 :     Int_t absId = cluster->GetCellAbsId(iDigit);
    1963             : 
    1964           0 :     geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta);
    1965           0 :     geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
    1966             :     
    1967             :     // Check if there are cells of different SM
    1968           0 :     if      (iDigit == 0   ) iSM0 = iSupMod;
    1969           0 :     else if (iSupMod!= iSM0) shared = kTRUE;
    1970             :     
    1971             :     // Get the cell energy, if recalibration is on, apply factors
    1972           0 :     fraction  = cluster->GetCellAmplitudeFraction(iDigit);
    1973           0 :     if (fraction < 1e-4) fraction = 1.; // in case unfolding is off
    1974             :     
    1975           0 :     if (IsRecalibrationOn()) 
    1976           0 :       recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
    1977             :     
    1978             :     
    1979           0 :     eCell  = cells->GetCellAmplitude(absId)*fraction*recalFactor;
    1980           0 :     tCell  = cells->GetCellTime     (absId);
    1981           0 :     isLowGain = !(cells->GetCellHighGain(absId));//HG = false -> LG = true
    1982             : 
    1983           0 :     RecalibrateCellTime(absId, bc, tCell,isLowGain);
    1984           0 :     tCell*=1e9;
    1985           0 :     tCell-=fConstantTimeShift;
    1986             : 
    1987           0 :     if(eCell > 0.05) // at least a minimum 50 MeV cut
    1988           0 :       energy += eCell;
    1989             : 
    1990           0 :     if(eCell > cellEcut && TMath::Abs(tCell) < cellTimeCut)
    1991           0 :       enAfterCuts += eCell;
    1992             :   } // cell loop
    1993             :   
    1994             :   // Loop on cells to calculate weights and shower shape terms parameters
    1995           0 :   for (Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) 
    1996             :   {
    1997             :     // Get from the absid the supermodule, tower and eta/phi numbers
    1998           0 :     Int_t absId = cluster->GetCellAbsId(iDigit);
    1999             : 
    2000           0 :     geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta); 
    2001           0 :     geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);        
    2002             :     
    2003             :     //Get the cell energy, if recalibration is on, apply factors
    2004           0 :     fraction  = cluster->GetCellAmplitudeFraction(iDigit);
    2005           0 :     if (fraction < 1e-4) fraction = 1.; // in case unfolding is off
    2006             :     
    2007           0 :     if (!fCellsRecalibrated && IsRecalibrationOn()) 
    2008           0 :         recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
    2009             :     
    2010           0 :     eCell  = cells->GetCellAmplitude(absId)*fraction*recalFactor;
    2011           0 :     tCell  = cells->GetCellTime     (absId);
    2012           0 :     isLowGain = !(cells->GetCellHighGain(absId));//HG = false -> LG = true
    2013             : 
    2014           0 :     RecalibrateCellTime(absId, bc, tCell,isLowGain);
    2015           0 :     tCell*=1e9;
    2016           0 :     tCell-=fConstantTimeShift;
    2017             :     
    2018             :     // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
    2019             :     // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
    2020           0 :     if (shared && iSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
    2021             :     
    2022           0 :     if ( energy > 0 && eCell > cellEcut && TMath::Abs(tCell) < cellTimeCut ) 
    2023             :     {
    2024           0 :       w  = GetCellWeight(eCell, energy);
    2025             :       
    2026           0 :       etai=(Double_t)ieta;
    2027           0 :       phii=(Double_t)iphi;  
    2028             :       
    2029           0 :       if (w > 0.0) 
    2030             :       {
    2031           0 :         wtot += w ;
    2032           0 :         nstat++;   
    2033             :         
    2034             :         // Shower shape
    2035           0 :         sEta     += w * etai * etai ;
    2036           0 :         etaMean  += w * etai ;
    2037           0 :         sPhi     += w * phii * phii ;
    2038           0 :         phiMean  += w * phii ; 
    2039           0 :         sEtaPhi  += w * etai * phii ; 
    2040           0 :       }
    2041             :     } 
    2042           0 :     else if(eCell > 0.05)
    2043           0 :       AliDebug(2,Form("Wrong energy in cell %f and/or cluster %f\n", eCell, cluster->E()));
    2044             :   } // cell loop
    2045             :   
    2046             :   // Normalize to the weight  
    2047           0 :   if (wtot > 0) 
    2048             :   {
    2049           0 :     etaMean /= wtot ;
    2050           0 :     phiMean /= wtot ;
    2051           0 :   } 
    2052             :   else
    2053           0 :     AliDebug(2,Form("Wrong weight %f\n", wtot));
    2054             :   
    2055             :   // Loop on cells to calculate dispersion  
    2056           0 :   for (Int_t iDigit=0; iDigit < cluster->GetNCells(); iDigit++) 
    2057             :   {
    2058             :     // Get from the absid the supermodule, tower and eta/phi numbers
    2059           0 :     Int_t absId = cluster->GetCellAbsId(iDigit);
    2060             : 
    2061           0 :     geom->GetCellIndex(absId,iSupMod,iTower,iIphi,iIeta); 
    2062           0 :     geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,iIphi,iIeta, iphi,ieta);
    2063             :     
    2064             :     //Get the cell energy, if recalibration is on, apply factors
    2065           0 :     fraction  = cluster->GetCellAmplitudeFraction(iDigit);
    2066           0 :     if (fraction < 1e-4) fraction = 1.; // in case unfolding is off
    2067           0 :     if (IsRecalibrationOn()) 
    2068           0 :       recalFactor = GetEMCALChannelRecalibrationFactor(iSupMod,ieta,iphi);
    2069             :     
    2070           0 :     eCell  = cells->GetCellAmplitude(absId)*fraction*recalFactor;
    2071           0 :     tCell  = cells->GetCellTime     (absId);
    2072           0 :     isLowGain = !(cells->GetCellHighGain(absId));//HG = false -> LG = true
    2073             : 
    2074           0 :     RecalibrateCellTime(absId, bc, tCell,isLowGain);
    2075           0 :     tCell*=1e9;
    2076           0 :     tCell-=fConstantTimeShift;
    2077             : 
    2078             :     // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2
    2079             :     // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0
    2080           0 :     if (shared && iSupMod%2) ieta+=AliEMCALGeoParams::fgkEMCALCols;
    2081             :     
    2082           0 :     if ( energy > 0 && eCell > cellEcut && TMath::Abs(tCell) < cellTimeCut ) 
    2083             :     {
    2084           0 :       w  = GetCellWeight(eCell,cluster->E());
    2085             :       
    2086           0 :       etai=(Double_t)ieta;
    2087           0 :       phii=(Double_t)iphi;    
    2088           0 :       if (w > 0.0) 
    2089             :       { 
    2090           0 :         disp +=  w *((etai-etaMean)*(etai-etaMean)+(phii-phiMean)*(phii-phiMean)); 
    2091           0 :         dEta +=  w * (etai-etaMean)*(etai-etaMean) ; 
    2092           0 :         dPhi +=  w * (phii-phiMean)*(phii-phiMean) ; 
    2093           0 :       }
    2094             :     } 
    2095             :     else
    2096           0 :       AliDebug(2,Form("Wrong energy in cell %f and/or cluster %f\n", eCell, cluster->E()));
    2097             :   }// cell loop
    2098             :   
    2099             :   // Normalize to the weigth and set shower shape parameters
    2100           0 :   if (wtot > 0 && nstat > 1)
    2101             :   {
    2102           0 :     disp    /= wtot ;
    2103           0 :     dEta    /= wtot ;
    2104           0 :     dPhi    /= wtot ;
    2105           0 :     sEta    /= wtot ;
    2106           0 :     sPhi    /= wtot ;
    2107           0 :     sEtaPhi /= wtot ;
    2108             :     
    2109           0 :     sEta    -= etaMean * etaMean ;
    2110           0 :     sPhi    -= phiMean * phiMean ;
    2111           0 :     sEtaPhi -= etaMean * phiMean ;
    2112             :     
    2113           0 :     l0 = (0.5 * (sEta + sPhi) + TMath::Sqrt( 0.25 * (sEta - sPhi) * (sEta - sPhi) + sEtaPhi * sEtaPhi ));
    2114           0 :     l1 = (0.5 * (sEta + sPhi) - TMath::Sqrt( 0.25 * (sEta - sPhi) * (sEta - sPhi) + sEtaPhi * sEtaPhi ));
    2115           0 :   } 
    2116             :   else 
    2117             :   {
    2118           0 :     l0   = 0. ;
    2119           0 :     l1   = 0. ;
    2120           0 :     dEta = 0. ; dPhi = 0. ; disp    = 0. ;
    2121           0 :     sEta = 0. ; sPhi = 0. ; sEtaPhi = 0. ;
    2122             :   }  
    2123           0 : }
    2124             : 
    2125             : ///
    2126             : /// Calculates different types of shower shape parameters, dispersion, shower shape eigenvalues and other.
    2127             : /// Call to AliEMCALRecoUtils::RecalculateClusterShowerShapeParametersWithCellCuts 
    2128             : /// with default cell cuts (50 MeV minimum cell energy and not cut on time)
    2129             : /// 
    2130             : /// \param geom: EMCal geometry pointer
    2131             : /// \param cells: list of EMCal cells with signal
    2132             : /// \param cluster: EMCal cluster subject to shower shape recalculation
    2133             : /// \param l0: main shower shape eigen value
    2134             : /// \param l1: second eigenvalue of shower shape
    2135             : /// \param disp: dispersion
    2136             : /// \param dEta: dispersion in eta (cols) direction
    2137             : /// \param dPhi: disperion in phi (rows) direction
    2138             : /// \param sEta: shower shape in eta  (cols) direction
    2139             : /// \param sPhi: shower shape in phi (rows) direction
    2140             : /// \param sEtaPhi: shower shape on phi / eta directions term
    2141             : ///
    2142             : ///
    2143             : //___________________________________________________________________________________________________________________
    2144             : void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(const AliEMCALGeometry * geom, 
    2145             :                                                                 AliVCaloCells* cells, AliVCluster * cluster,
    2146             :                                                                 Float_t & l0,   Float_t & l1,   
    2147             :                                                                 Float_t & disp, Float_t & dEta, Float_t & dPhi,
    2148             :                                                                 Float_t & sEta, Float_t & sPhi, Float_t & sEtaPhi)
    2149             : {
    2150           0 :   Float_t newEnergy      = 0;
    2151             :   Float_t cellEmin       = 0.05; // 50 MeV
    2152             :   Float_t cellTimeWindow = 1000; // open cut
    2153             :   Int_t   bc             = 0; 
    2154           0 :   AliEMCALRecoUtils::RecalculateClusterShowerShapeParametersWithCellCuts(geom, cells, cluster,
    2155             :                                                                          cellEmin, cellTimeWindow, bc,
    2156             :                                                                          newEnergy, l0, l1, disp,
    2157             :                                                                          dEta, dPhi, sEta, sPhi, sEtaPhi);
    2158           0 : }
    2159             : 
    2160             : ///
    2161             : /// Calculates Dispersion and main axis and puts them into the cluster
    2162             : /// Call to method RecalculateClusterShowerShapeParameters
    2163             : ///
    2164             : /// \param geom: EMCal geometry pointer
    2165             : /// \param cells: list of EMCal cells with signal
    2166             : /// \param cluster: EMCal cluster subject to shower shape recalculation
    2167             : ///
    2168             : //____________________________________________________________________________________________
    2169             : void AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(const AliEMCALGeometry * geom, 
    2170             :                                                                 AliVCaloCells* cells, 
    2171             :                                                                 AliVCluster * cluster)
    2172             : {  
    2173           0 :   Float_t l0   = 0., l1   = 0.;
    2174           0 :   Float_t disp = 0., dEta = 0., dPhi    = 0.; 
    2175           0 :   Float_t sEta = 0., sPhi = 0., sEtaPhi = 0.;
    2176             :   
    2177           0 :   AliEMCALRecoUtils::RecalculateClusterShowerShapeParameters(geom,cells,cluster,l0,l1,disp,
    2178             :                                                              dEta, dPhi, sEta, sPhi, sEtaPhi);
    2179             :   
    2180           0 :   cluster->SetM02(l0);
    2181           0 :   cluster->SetM20(l1);
    2182           0 :   if (disp > 0. ) cluster->SetDispersion(TMath::Sqrt(disp)) ;
    2183             :   
    2184           0 : } 
    2185             : 
    2186             : ///
    2187             : /// Calculates Dispersion and main axis and puts them into the cluster.
    2188             : /// Possibility to restrict the cell Energy and time window in the calculations
    2189             : /// 
    2190             : /// \param geom: EMCal geometry pointer
    2191             : /// \param cells: list of EMCal cells with signal
    2192             : /// \param cluster: EMCal cluster subject to shower shape recalculation
    2193             : /// \param cellEcut: minimum cell energy to be considered in the shower shape recalculation
    2194             : /// \param cellTimeCut: time window of cells to be considered in shower recalculation
    2195             : /// \param bc: event bunch crossing number
    2196             : /// \param enAfterCuts: cluster energy when applying the cell cuts cellEcut and cellTime cut
    2197             : ///
    2198             : //____________________________________________________________________________________________
    2199             : void AliEMCALRecoUtils::RecalculateClusterShowerShapeParametersWithCellCuts(const AliEMCALGeometry * geom, 
    2200             :                                                                             AliVCaloCells* cells, AliVCluster * cluster,
    2201             :                                                                             Float_t cellEcut, Float_t cellTimeCut, Int_t bc,
    2202             :                                                                             Float_t & enAfterCuts)
    2203             : {  
    2204           0 :   Float_t l0   = 0., l1   = 0.;
    2205           0 :   Float_t disp = 0., dEta = 0., dPhi    = 0.; 
    2206           0 :   Float_t sEta = 0., sPhi = 0., sEtaPhi = 0.;
    2207             :   
    2208           0 :   AliEMCALRecoUtils::RecalculateClusterShowerShapeParametersWithCellCuts(geom, cells, cluster,
    2209             :                                                                          cellEcut, cellTimeCut, bc,
    2210             :                                                                          enAfterCuts, l0, l1, disp,
    2211             :                                                                          dEta, dPhi, sEta, sPhi, sEtaPhi);
    2212             :   
    2213           0 :   cluster->SetM02(l0);
    2214           0 :   cluster->SetM20(l1);
    2215           0 :   if (disp > 0. ) cluster->SetDispersion(TMath::Sqrt(disp)) ;
    2216             :   
    2217           0 : } 
    2218             : 
    2219             : ///
    2220             : /// Find the candidate cluster-track matchs.
    2221             : ///
    2222             : /// This function should be called before the cluster loop.
    2223             : /// Before call this function, please recalculate the cluster positions.
    2224             : /// Given the input event, loop over all the tracks, select the closest cluster as matched with fCutR.
    2225             : /// Store matched cluster indexes and residuals.
    2226             : ///
    2227             : /// \param event: event pointer
    2228             : /// \param clusterArr: list of clusters
    2229             : /// \param geom: AliEMCALGeometry pointer
    2230             : ///
    2231             : //____________________________________________________________________________
    2232             : void AliEMCALRecoUtils::FindMatches(AliVEvent *event,
    2233             :                                     TObjArray * clusterArr,  
    2234             :                                     const AliEMCALGeometry *geom)
    2235             : {  
    2236           0 :   fMatchedTrackIndex  ->Reset();
    2237           0 :   fMatchedClusterIndex->Reset();
    2238           0 :   fResidualPhi->Reset();
    2239           0 :   fResidualEta->Reset();
    2240             :   
    2241           0 :   fMatchedTrackIndex  ->Set(1000);
    2242           0 :   fMatchedClusterIndex->Set(1000);
    2243           0 :   fResidualPhi->Set(1000);
    2244           0 :   fResidualEta->Set(1000);
    2245             :   
    2246           0 :   AliESDEvent* esdevent = dynamic_cast<AliESDEvent*> (event);
    2247           0 :   AliAODEvent* aodevent = dynamic_cast<AliAODEvent*> (event);
    2248             :   
    2249             :   // Init the magnetic field if not already on
    2250           0 :   if (!TGeoGlobalMagField::Instance()->GetField()) 
    2251             :   {
    2252           0 :     if (!event->InitMagneticField())
    2253             :     {
    2254           0 :       AliInfo("Mag Field not initialized, null esd/aod evetn pointers");
    2255           0 :     }
    2256             :   } // Init mag field
    2257             :   
    2258           0 :   if (esdevent) 
    2259             :   {
    2260           0 :     UInt_t mask1 = esdevent->GetESDRun()->GetDetectorsInDAQ();
    2261           0 :     UInt_t mask2 = esdevent->GetESDRun()->GetDetectorsInReco();
    2262           0 :     Bool_t desc1 = (mask1 >> 3) & 0x1;
    2263           0 :     Bool_t desc2 = (mask2 >> 3) & 0x1;
    2264           0 :     if (desc1==0 || desc2==0) { 
    2265             :       //       AliError(Form("TPC not in DAQ/RECO: %u (%u)/%u (%u)", 
    2266             :       //       mask1, esdevent->GetESDRun()->GetDetectorsInReco(),
    2267             :       //       mask2, esdevent->GetESDRun()->GetDetectorsInDAQ()));
    2268           0 :       fITSTrackSA=kTRUE;
    2269           0 :     }
    2270           0 :   }
    2271             :   
    2272             :   TObjArray *clusterArray = 0x0;
    2273           0 :   if (!clusterArr) 
    2274             :   {
    2275           0 :     clusterArray = new TObjArray(event->GetNumberOfCaloClusters());
    2276           0 :     for (Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++) 
    2277             :     {
    2278           0 :       AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
    2279           0 :       if (!IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) 
    2280           0 :         continue;
    2281           0 :       clusterArray->AddAt(cluster,icl);
    2282           0 :     }
    2283           0 :   }
    2284             :   
    2285             :   Int_t    matched=0;
    2286           0 :   Double_t cv[21];
    2287           0 :   for (Int_t i=0; i<21;i++) cv[i]=0;
    2288           0 :   for (Int_t itr=0; itr<event->GetNumberOfTracks(); itr++)
    2289             :   {
    2290             :     AliExternalTrackParam *trackParam = 0;
    2291             :     
    2292             :     // If the input event is ESD, the starting point for extrapolation is TPCOut, if available, or TPCInner 
    2293             :     AliESDtrack *esdTrack = 0;
    2294             :     AliAODTrack *aodTrack = 0;
    2295           0 :     if (esdevent) 
    2296             :     {
    2297           0 :       esdTrack = esdevent->GetTrack(itr);
    2298           0 :       if (!esdTrack) continue;
    2299           0 :       if (!IsAccepted(esdTrack)) continue;
    2300           0 :       if (esdTrack->Pt()<fCutMinTrackPt) continue;
    2301             :       
    2302           0 :       if ( TMath::Abs(esdTrack->Eta()) > 0.9 ) continue;
    2303             :       
    2304             :       // Save some time and memory in case of no DCal present
    2305           0 :       if( geom->GetNumberOfSuperModules() < 13 ) // Run1 10 (12, 2 not active but present)
    2306             :       {
    2307           0 :         Double_t phi = esdTrack->Phi()*TMath::RadToDeg();
    2308           0 :         if ( phi <= 10 || phi >= 250 ) continue;
    2309           0 :       }
    2310             :       
    2311           0 :       if (!fITSTrackSA)
    2312           0 :         trackParam =  const_cast<AliExternalTrackParam*>(esdTrack->GetInnerParam());  // if TPC Available
    2313             :       else
    2314           0 :         trackParam =  new AliExternalTrackParam(*esdTrack); // If ITS Track Standing alone              
    2315             :     }
    2316             :     
    2317             :     // If the input event is AOD, the starting point for extrapolation is at vertex
    2318             :     // AOD tracks are selected according to its filterbit.
    2319           0 :     else if (aodevent) 
    2320             :     {
    2321           0 :       aodTrack = dynamic_cast<AliAODTrack*>(aodevent->GetTrack(itr));
    2322             :       
    2323           0 :       if (!aodTrack) AliFatal("Not a standard AOD");
    2324             :      
    2325           0 :       if (!aodTrack) continue;
    2326             :       
    2327           0 :       if (fAODTPCOnlyTracks) 
    2328             :       { // Match with TPC only tracks, default from May 2013, before filter bit 32
    2329             :         //printf("Match with TPC only tracks, accept? %d, test bit 128 <%d> \n", aodTrack->IsTPCOnly(), aodTrack->TestFilterMask(128));
    2330           0 :         if (!aodTrack->IsTPCConstrained()) continue ;
    2331             :       } 
    2332           0 :       else if (fAODHybridTracks) 
    2333             :       { // Match with hybrid tracks
    2334             :         //printf("Match with Hybrid tracks, accept? %d \n", aodTrack->IsHybridGlobalConstrainedGlobal());
    2335           0 :         if (!aodTrack->IsHybridGlobalConstrainedGlobal()) continue ;
    2336             :       } else 
    2337             :       { // Match with tracks on a mask
    2338             :         //printf("Match with tracks having filter bit mask %d, accept? %d \n",fAODFilterMask,aodTrack->TestFilterMask(fAODFilterMask));
    2339           0 :         if (!aodTrack->TestFilterMask(fAODFilterMask) ) continue; //Select AOD tracks
    2340             :       }
    2341             :       
    2342           0 :       if (aodTrack->Pt() < fCutMinTrackPt) continue;
    2343             :       
    2344           0 :       if ( TMath::Abs(aodTrack->Eta()) > 0.9 ) continue;
    2345             :       
    2346             :       // Save some time and memory in case of no DCal present
    2347           0 :       if( geom->GetNumberOfSuperModules() < 13 ) // Run1 10 (12, 2 not active but present)
    2348             :       {
    2349           0 :         Double_t phi = aodTrack->Phi()*TMath::RadToDeg();
    2350           0 :         if ( phi <= 10 || phi >= 250 ) continue;
    2351           0 :       }
    2352             :       
    2353           0 :       Double_t pos[3],mom[3];
    2354           0 :       aodTrack->GetXYZ(pos);
    2355           0 :       aodTrack->GetPxPyPz(mom);
    2356           0 :       AliDebug(5,Form("aod track: i=%d | pos=(%5.4f,%5.4f,%5.4f) | mom=(%5.4f,%5.4f,%5.4f) | charge=%d\n",
    2357             :                       itr,pos[0],pos[1],pos[2],mom[0],mom[1],mom[2],aodTrack->Charge()));
    2358             :       
    2359           0 :       trackParam= new AliExternalTrackParam(pos,mom,cv,aodTrack->Charge());
    2360           0 :     }
    2361             :     
    2362             :     //Return if the input data is not "AOD" or "ESD"
    2363             :     else
    2364             :     {
    2365           0 :       printf("Wrong input data type! Should be \"AOD\" or \"ESD\"\n");
    2366           0 :       if (clusterArray) 
    2367             :       {
    2368           0 :         clusterArray->Clear();
    2369           0 :         delete clusterArray;
    2370             :       }
    2371           0 :       return;
    2372             :     }
    2373             :     
    2374           0 :     if (!trackParam) continue;
    2375             :     
    2376             :     // Extrapolate the track to EMCal surface
    2377           0 :     AliExternalTrackParam emcalParam(*trackParam);
    2378           0 :     Float_t eta, phi, pt;
    2379           0 :     if (!ExtrapolateTrackToEMCalSurface(&emcalParam, fEMCalSurfaceDistance, fMass, fStepSurface, eta, phi, pt)) 
    2380             :     {
    2381           0 :       if (aodevent    && trackParam) delete trackParam;
    2382           0 :       if (fITSTrackSA && trackParam) delete trackParam;
    2383           0 :       continue;
    2384             :     }
    2385             :     
    2386           0 :     if ( TMath::Abs(eta) > 0.75 ) 
    2387             :     {
    2388           0 :       if ( trackParam && (aodevent || fITSTrackSA) )   delete trackParam;
    2389           0 :       continue;
    2390             :     }
    2391             :     
    2392             :     // Save some time and memory in case of no DCal present
    2393           0 :     if ( geom->GetNumberOfSuperModules() < 13 &&  // Run1 10 (12, 2 not active but present)
    2394           0 :         ( phi < 70*TMath::DegToRad() || phi > 190*TMath::DegToRad())) 
    2395             :     {
    2396           0 :       if ( trackParam && (aodevent || fITSTrackSA) )   delete trackParam;
    2397           0 :       continue;
    2398             :     }
    2399             :     
    2400             :     //Find matched clusters
    2401             :     Int_t index = -1;
    2402           0 :     Float_t dEta = -999, dPhi = -999;
    2403           0 :     if (!clusterArr) 
    2404           0 :       index = FindMatchedClusterInClusterArr(&emcalParam, &emcalParam, clusterArray, dEta, dPhi);  
    2405             :     else 
    2406           0 :       index = FindMatchedClusterInClusterArr(&emcalParam, &emcalParam, clusterArr  , dEta, dPhi);  
    2407             :     
    2408             :     
    2409           0 :     if (index>-1) 
    2410             :     {
    2411           0 :       fMatchedTrackIndex   ->AddAt(itr,matched);
    2412           0 :       fMatchedClusterIndex ->AddAt(index,matched);
    2413           0 :       fResidualEta         ->AddAt(dEta,matched);
    2414           0 :       fResidualPhi         ->AddAt(dPhi,matched);
    2415           0 :       matched++;
    2416           0 :     }
    2417             :     
    2418           0 :     if (aodevent && trackParam) delete trackParam;
    2419           0 :     if (fITSTrackSA && trackParam) delete trackParam;
    2420           0 :   }//track loop
    2421             :   
    2422           0 :   if (clusterArray) 
    2423             :   {
    2424           0 :     clusterArray->Clear();
    2425           0 :     delete clusterArray;
    2426             :   }
    2427             :   
    2428           0 :   AliDebug(2,Form("Number of matched pairs = %d !\n",matched));
    2429             :   
    2430           0 :   fMatchedTrackIndex   ->Set(matched);
    2431           0 :   fMatchedClusterIndex ->Set(matched);
    2432           0 :   fResidualPhi         ->Set(matched);
    2433           0 :   fResidualEta         ->Set(matched);
    2434           0 : }
    2435             : 
    2436             : ///
    2437             : /// Find matched cluster in event. See Find MatchedClusterInClusterArr().
    2438             : ///
    2439             : /// \param track: track pointer
    2440             : /// \param event: event pointer
    2441             : /// \param geom: AliEMCALGeometry pointer
    2442             : /// \param dEta: found track-cluster match residual in eta direction
    2443             : /// \param dPhi: found track-cluster match residual in phi direction
    2444             : ///
    2445             : /// \return  the index of matched cluster to input track, returns -1 if no match is found
    2446             : ///
    2447             : //________________________________________________________________________________
    2448             : Int_t AliEMCALRecoUtils::FindMatchedClusterInEvent(const AliESDtrack *track, 
    2449             :                                                    const AliVEvent *event, 
    2450             :                                                    const AliEMCALGeometry *geom, 
    2451             :                                                    Float_t &dEta, Float_t &dPhi)
    2452             : {
    2453             :   Int_t index = -1;
    2454             :   
    2455           0 :   if ( TMath::Abs(track->Eta()) > 0.9 ) return index;
    2456             :   
    2457             :   // Save some time and memory in case of no DCal present
    2458           0 :   if( geom->GetNumberOfSuperModules() < 13 ) // Run1 10 (12, 2 not active but present)
    2459             :   {
    2460           0 :     Double_t phiV = track->Phi()*TMath::RadToDeg();
    2461           0 :     if ( phiV <= 10 || phiV >= 250 ) return index;
    2462           0 :   }
    2463             :   
    2464             :   AliExternalTrackParam *trackParam = 0;
    2465           0 :   if (!fITSTrackSA)
    2466           0 :     trackParam = const_cast<AliExternalTrackParam*>(track->GetInnerParam());  // If TPC
    2467             :   else
    2468           0 :     trackParam = new AliExternalTrackParam(*track);
    2469             :   
    2470           0 :   if (!trackParam) return index;
    2471           0 :   AliExternalTrackParam emcalParam(*trackParam);
    2472           0 :   Float_t eta, phi, pt;
    2473             :   
    2474           0 :   if (!ExtrapolateTrackToEMCalSurface(&emcalParam, fEMCalSurfaceDistance, fMass, fStepSurface, eta, phi, pt))       
    2475             :   {
    2476           0 :     if (fITSTrackSA) delete trackParam;
    2477           0 :     return index;
    2478             :   }
    2479             :   
    2480           0 :   if ( TMath::Abs(eta) > 0.75 ) 
    2481             :   {
    2482           0 :     if (fITSTrackSA) delete trackParam;
    2483           0 :     return index;
    2484             :   }
    2485             :   
    2486             :   // Save some time and memory in case of no DCal present
    2487           0 :   if ( geom->GetNumberOfSuperModules() < 13 &&  // Run1 10 (12, 2 not active but present)
    2488           0 :       ( phi < 70*TMath::DegToRad() || phi > 190*TMath::DegToRad())) 
    2489             :   {
    2490           0 :     if (fITSTrackSA) delete trackParam;
    2491           0 :     return index;    
    2492             :   }
    2493             :   
    2494           0 :   TObjArray *clusterArr = new TObjArray(event->GetNumberOfCaloClusters());
    2495             :   
    2496           0 :   for (Int_t icl=0; icl<event->GetNumberOfCaloClusters(); icl++)
    2497             :   {
    2498           0 :     AliVCluster *cluster = (AliVCluster*) event->GetCaloCluster(icl);
    2499           0 :     if (!IsGoodCluster(cluster,geom,(AliVCaloCells*)event->GetEMCALCells())) continue;
    2500           0 :     clusterArr->AddAt(cluster,icl);
    2501           0 :   }
    2502             :   
    2503           0 :   index = FindMatchedClusterInClusterArr(&emcalParam, &emcalParam, clusterArr, dEta, dPhi);  
    2504           0 :   clusterArr->Clear();
    2505           0 :   delete clusterArr;
    2506           0 :   if (fITSTrackSA) delete trackParam;
    2507             :   
    2508             :   return index;
    2509           0 : }
    2510             : 
    2511             : ///
    2512             : /// Find matched cluster in input array of clusters.
    2513             : /// 
    2514             : /// \param emcalParam: emcal track parameters container?
    2515             : /// \param trkParam: track parameters container?
    2516             : /// \param clusterArr: input array of clusters
    2517             : /// \param dEta: found track-cluster match residual in eta direction
    2518             : /// \param dPhi: found track-cluster match residual in phi direction
    2519             : ///
    2520             : /// \return  the index of matched cluster to input track.
    2521             : //_______________________________________________________________________________________________
    2522             : Int_t  AliEMCALRecoUtils::FindMatchedClusterInClusterArr(const AliExternalTrackParam *emcalParam, 
    2523             :                                                          AliExternalTrackParam *trkParam, 
    2524             :                                                          const TObjArray * clusterArr, 
    2525             :                                                          Float_t &dEta, Float_t &dPhi)
    2526             : {  
    2527           0 :   dEta=-999, dPhi=-999;
    2528           0 :   Float_t dRMax = fCutR, dEtaMax=fCutEta, dPhiMax=fCutPhi;
    2529             :   Int_t index = -1;
    2530           0 :   Float_t tmpEta=-999, tmpPhi=-999;
    2531             : 
    2532           0 :   Double_t exPos[3] = {0.,0.,0.};
    2533           0 :   if (!emcalParam->GetXYZ(exPos)) return index;
    2534             : 
    2535           0 :   Float_t clsPos[3] = {0.,0.,0.};
    2536           0 :   for (Int_t icl=0; icl<clusterArr->GetEntriesFast(); icl++)
    2537             :   {
    2538           0 :     AliVCluster *cluster = dynamic_cast<AliVCluster*> (clusterArr->At(icl)) ;
    2539             :     
    2540           0 :     if (!cluster || !cluster->IsEMCAL()) continue;
    2541             :     
    2542           0 :     cluster->GetPosition(clsPos);
    2543             :     
    2544           0 :     Double_t dR = TMath::Sqrt(TMath::Power(exPos[0]-clsPos[0],2)+TMath::Power(exPos[1]-clsPos[1],2)+TMath::Power(exPos[2]-clsPos[2],2));
    2545           0 :     if (dR > fClusterWindow) continue;
    2546             :     
    2547           0 :     AliExternalTrackParam trkPamTmp (*trkParam);//Retrieve the starting point every time before the extrapolation
    2548             :     
    2549           0 :     if (!ExtrapolateTrackToCluster(&trkPamTmp, cluster, fMass, fStepCluster, tmpEta, tmpPhi)) continue;
    2550             :     
    2551           0 :     if (fCutEtaPhiSum) 
    2552             :     {
    2553           0 :       Float_t tmpR=TMath::Sqrt(tmpEta*tmpEta + tmpPhi*tmpPhi);
    2554           0 :       if (tmpR<dRMax) 
    2555             :       {
    2556             :         dRMax=tmpR;
    2557           0 :         dEtaMax=tmpEta;
    2558           0 :         dPhiMax=tmpPhi;
    2559             :         index=icl;
    2560           0 :       }
    2561           0 :     } 
    2562           0 :     else if (fCutEtaPhiSeparate) 
    2563             :     {
    2564           0 :       if (TMath::Abs(tmpEta)<TMath::Abs(dEtaMax) && TMath::Abs(tmpPhi)<TMath::Abs(dPhiMax)) 
    2565             :       {
    2566           0 :         dEtaMax = tmpEta;
    2567           0 :         dPhiMax = tmpPhi;
    2568             :         index=icl;
    2569           0 :       }
    2570             :     } 
    2571             :     else 
    2572             :     {
    2573           0 :       printf("Error: please specify your cut criteria\n");
    2574           0 :       printf("To cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
    2575           0 :       printf("To cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
    2576           0 :       return index;
    2577             :     }
    2578           0 :   }
    2579             : 
    2580           0 :   dEta=dEtaMax;
    2581           0 :   dPhi=dPhiMax;
    2582             : 
    2583           0 :   return index;
    2584           0 : }
    2585             : 
    2586             : ///
    2587             : /// Extrapolate track to EMCAL surface.
    2588             : ///
    2589             : /// \param track: pointer to track
    2590             : /// \param emcalR: distance
    2591             : /// \param mass: mass hypothesis
    2592             : /// \param step: ...
    2593             : /// \param minpt: minimum track pT for matching
    2594             : /// \param useMassForTracking: switch to use the mass hypothesis
    2595             : ///
    2596             : /// \return bool true if track could be extrapolated
    2597             : ///
    2598             : //------------------------------------------------------------------------------------
    2599             : Bool_t AliEMCALRecoUtils::ExtrapolateTrackToEMCalSurface(AliVTrack *track,
    2600             :                                                          Double_t emcalR, Double_t mass,
    2601             :                                                          Double_t step, Double_t minpt,
    2602             :                                                          Bool_t useMassForTracking)
    2603             : { 
    2604         142 :   track->SetTrackPhiEtaPtOnEMCal(-999, -999, -999);
    2605             :   
    2606         142 :   if ( track->Pt() < minpt )
    2607          24 :     return kFALSE;
    2608             :   
    2609         118 :   if ( TMath::Abs(track->Eta()) > 0.9 ) return kFALSE;
    2610             :   
    2611             :   // Save some time and memory in case of no DCal present
    2612         118 :   AliEMCALGeometry* geom = AliEMCALGeometry::GetInstance();
    2613             :   
    2614             :   Int_t       nSupMod = AliEMCALGeoParams::fgkEMCALModules;
    2615         236 :   if ( geom ) nSupMod = geom->GetNumberOfSuperModules();
    2616             :   
    2617         118 :   if ( nSupMod < 13 ) // Run1 10 (12, 2 not active but present)
    2618             :   {
    2619         118 :     Double_t phi = track->Phi()*TMath::RadToDeg();
    2620         138 :     if ( phi <= 10 || phi >= 250 ) return kFALSE;
    2621          98 :   }
    2622             :   
    2623         294 :   AliESDtrack *esdt = dynamic_cast<AliESDtrack*>(track);
    2624             :   AliAODTrack *aodt = 0;
    2625          98 :   if (!esdt) 
    2626             :   {
    2627           0 :     aodt = dynamic_cast<AliAODTrack*>(track);
    2628             :     
    2629           0 :     if (!aodt)
    2630           0 :       return kFALSE;
    2631             :   }
    2632             :   
    2633             :   // Select the mass hypothesis
    2634          98 :   if ( mass < 0 )
    2635             :   {
    2636             :     Bool_t onlyTPC = kFALSE;
    2637           0 :     if ( mass == -99 ) onlyTPC=kTRUE;
    2638             :     
    2639           0 :     if (esdt)
    2640             :     {
    2641           0 :       if ( useMassForTracking ) mass = esdt->GetMassForTracking();
    2642           0 :       else                      mass = esdt->GetMass(onlyTPC);
    2643             :     }
    2644             :     else
    2645             :     {
    2646           0 :       if ( useMassForTracking ) mass = aodt->GetMassForTracking();
    2647           0 :       else                      mass = aodt->M();
    2648             :     }
    2649           0 :   }
    2650             :   
    2651             :   AliExternalTrackParam *trackParam = 0;
    2652          98 :   if (esdt) 
    2653             :   {
    2654          98 :     const AliExternalTrackParam *in = esdt->GetInnerParam();
    2655             :     
    2656          98 :     if (!in)
    2657          14 :       return kFALSE;
    2658             :     
    2659          84 :     trackParam = new AliExternalTrackParam(*in);
    2660          84 :   } 
    2661             :   else 
    2662             :   {
    2663           0 :     Double_t xyz[3] = {0}, pxpypz[3] = {0}, cv[21] = {0};
    2664           0 :     aodt->PxPyPz(pxpypz);  
    2665           0 :     aodt->XvYvZv(xyz);
    2666           0 :     aodt->GetCovarianceXYZPxPyPz(cv);  
    2667           0 :     trackParam = new AliExternalTrackParam(xyz,pxpypz,cv,aodt->Charge());
    2668           0 :   }
    2669             :   
    2670          84 :   if (!trackParam)
    2671           0 :     return kFALSE;
    2672             :   
    2673          84 :   Float_t etaout=-999, phiout=-999, ptout=-999;
    2674          84 :   Bool_t ret = ExtrapolateTrackToEMCalSurface(trackParam, 
    2675             :                                               emcalR,
    2676             :                                               mass,
    2677             :                                               step,
    2678             :                                               etaout, 
    2679             :                                               phiout,
    2680             :                                               ptout);
    2681             :   
    2682         168 :   delete trackParam;
    2683             :   
    2684          86 :   if (!ret) return kFALSE;
    2685             :   
    2686          82 :   if ( TMath::Abs(etaout) > 0.75 ) return kFALSE;
    2687             :   
    2688             :   // Save some time and memory in case of no DCal present
    2689          82 :   if ( nSupMod < 13 ) // Run1 10 (12, 2 not active but present)
    2690             :   {
    2691         170 :     if ( (phiout < 70*TMath::DegToRad()) || (phiout > 190*TMath::DegToRad()) )  return kFALSE;
    2692             :   }
    2693             :   
    2694          26 :   track->SetTrackPhiEtaPtOnEMCal(phiout, etaout, ptout);
    2695             :   
    2696          26 :   return kTRUE;
    2697         226 : }
    2698             : 
    2699             : 
    2700             : ///
    2701             : /// Extrapolate track to EMCAL surface.
    2702             : ///
    2703             : /// \param trkParam: pointer to external track param
    2704             : /// \param emcalR: distance
    2705             : /// \param mass: mass hypothesis
    2706             : /// \param step: ...
    2707             : /// \param eta: track extrapolated eta
    2708             : /// \param phi: track extrapolated phi
    2709             : /// \param pt: track extrapolated pt
    2710             : ///
    2711             : /// \return bool true if track could be extrapolated
    2712             : ///
    2713             : //---------------------------------------------------------------------------------------
    2714             : Bool_t AliEMCALRecoUtils::ExtrapolateTrackToEMCalSurface(AliExternalTrackParam *trkParam, 
    2715             :                                                          Double_t emcalR,
    2716             :                                                          Double_t mass, 
    2717             :                                                          Double_t step, 
    2718             :                                                          Float_t &eta, 
    2719             :                                                          Float_t &phi,
    2720             :                                                          Float_t &pt)
    2721             : {
    2722         380 :   eta = -999, phi = -999, pt = -999;
    2723             :  
    2724         190 :   if (!trkParam) return kFALSE;
    2725             :   
    2726         217 :   if (!AliTrackerBase::PropagateTrackToBxByBz(trkParam, emcalR, mass, step, kTRUE, 0.8, -1)) return kFALSE;
    2727             :   
    2728         163 :   Double_t trkPos[3] = {0.,0.,0.};
    2729             :   
    2730         163 :   if (!trkParam->GetXYZ(trkPos)) return kFALSE;
    2731             :   
    2732         163 :   TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
    2733             :   
    2734         326 :   eta = trkPosVec.Eta();
    2735         326 :   phi = trkPosVec.Phi();
    2736         326 :   pt  = trkParam->Pt();
    2737             :   
    2738         163 :   if ( phi < 0 )
    2739          19 :     phi += TMath::TwoPi();
    2740             : 
    2741             :   return kTRUE;
    2742         516 : }
    2743             : 
    2744             : ///
    2745             : /// Return the residual by extrapolating a track param to a global position.
    2746             : ///
    2747             : /// \param trkParam: pointer to external track param
    2748             : /// \param clsPos: cluster position array xyz
    2749             : /// \param mass: mass hypothesis
    2750             : /// \param step: ...
    2751             : /// \param tmpEta: residual eta
    2752             : /// \param tmpPhi: residual phi
    2753             : ///
    2754             : /// \return bool true if track could be extrapolated
    2755             : //-----------------------------------------------------------------------------------
    2756             : Bool_t AliEMCALRecoUtils::ExtrapolateTrackToPosition(AliExternalTrackParam *trkParam, 
    2757             :                                                      const Float_t *clsPos, 
    2758             :                                                      Double_t mass, 
    2759             :                                                      Double_t step, 
    2760             :                                                      Float_t &tmpEta, 
    2761             :                                                      Float_t &tmpPhi)
    2762             : {
    2763         112 :   tmpEta = -999;
    2764          56 :   tmpPhi = -999;
    2765             :   
    2766          56 :   if (!trkParam) return kFALSE;
    2767             :   
    2768          56 :   Double_t trkPos[3] = {0.,0.,0.};
    2769          56 :   TVector3 vec(clsPos[0],clsPos[1],clsPos[2]);
    2770             :   
    2771         112 :   Float_t phi = vec.Phi();
    2772             :   
    2773          56 :   if ( phi < 0 )
    2774           0 :     phi += TMath::TwoPi();
    2775             :   
    2776             :   // Rotate the cluster to the local extrapolation coordinate system
    2777          56 :   Double_t alpha = ((int)(phi*TMath::RadToDeg()/20)+0.5)*20*TMath::DegToRad();
    2778             :   
    2779          56 :   vec.RotateZ(-alpha); 
    2780             :   
    2781         112 :   if (!AliTrackerBase::PropagateTrackToBxByBz(trkParam, vec.X(), mass, step,kTRUE, 0.8, -1)) 
    2782           2 :     return kFALSE;
    2783             :   
    2784         108 :   if (!trkParam->GetXYZ(trkPos)) 
    2785           0 :     return kFALSE; // Get the extrapolated global position
    2786             : 
    2787          54 :   TVector3 clsPosVec(clsPos[0],clsPos[1],clsPos[2]);
    2788          54 :   TVector3 trkPosVec(trkPos[0],trkPos[1],trkPos[2]);
    2789             : 
    2790             :   // Track cluster matching
    2791         108 :   tmpPhi = clsPosVec.DeltaPhi(trkPosVec);    // tmpPhi is between -pi and pi
    2792         162 :   tmpEta = clsPosVec.Eta()-trkPosVec.Eta();
    2793             : 
    2794             :   return kTRUE;
    2795         166 : }
    2796             : 
    2797             : ///
    2798             : /// Return the residual by extrapolating a track param to a cluster.
    2799             : ///
    2800             : /// \param trkParam: pointer to external track param
    2801             : /// \param cluster: pointer to AliVCluster
    2802             : /// \param mass: mass hypothesis
    2803             : /// \param step: ...
    2804             : /// \param tmpEta: residual eta
    2805             : /// \param tmpPhi: residual phi
    2806             : ///
    2807             : /// \return bool true if track could be extrapolated
    2808             : ///
    2809             : //----------------------------------------------------------------------------------
    2810             : Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, 
    2811             :                                                     const AliVCluster *cluster, 
    2812             :                                                     Double_t mass, 
    2813             :                                                     Double_t step, 
    2814             :                                                     Float_t &tmpEta, 
    2815             :                                                     Float_t &tmpPhi)
    2816             : {
    2817          36 :   tmpEta = -999;
    2818          18 :   tmpPhi = -999;
    2819             :   
    2820          18 :   if (!cluster || !trkParam) 
    2821           0 :     return kFALSE;
    2822             : 
    2823          18 :   Float_t clsPos[3] = {0.,0.,0.};
    2824          18 :   cluster->GetPosition(clsPos);
    2825             : 
    2826          18 :   return ExtrapolateTrackToPosition(trkParam, clsPos, mass, step, tmpEta, tmpPhi);
    2827          36 : }
    2828             : 
    2829             : ///
    2830             : ///
    2831             : /// Return the residual by extrapolating a track param to a cluster.
    2832             : /// Mass and step hypothesis are set via data members fSteCluster and fMass and
    2833             : /// not passed like in method avobe.
    2834             : ///
    2835             : /// \param trkParam: pointer to external track param
    2836             : /// \param cluster: pointer to AliVCluster
    2837             : /// \param tmpEta: residual eta
    2838             : /// \param tmpPhi: residual phi
    2839             : ///
    2840             : /// \return bool true if track could be extrapolated
    2841             : ///
    2842             : //---------------------------------------------------------------------------------
    2843             : Bool_t AliEMCALRecoUtils::ExtrapolateTrackToCluster(AliExternalTrackParam *trkParam, 
    2844             :                                                     const AliVCluster *cluster, 
    2845             :                                                     Float_t &tmpEta, 
    2846             :                                                     Float_t &tmpPhi)
    2847             : {
    2848           0 :   return ExtrapolateTrackToCluster(trkParam, cluster, fMass, fStepCluster, tmpEta, tmpPhi);
    2849             : }
    2850             : 
    2851             : ///
    2852             : /// Given a cluster index, get the residuals dEta and dPhi for this cluster 
    2853             : /// to the closest track.
    2854             : /// It works with ESDs and AODs.
    2855             : ///
    2856             : /// \param clsIndex: cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
    2857             : /// \param dEta: residual eta
    2858             : /// \param dPhi: residual phi
    2859             : ///
    2860             : //_______________________________________________________________________
    2861             : void AliEMCALRecoUtils::GetMatchedResiduals(Int_t clsIndex, 
    2862             :                                             Float_t &dEta, Float_t &dPhi)
    2863             : {
    2864           0 :   if (FindMatchedPosForCluster(clsIndex) >= 999) 
    2865             :   {
    2866           0 :     AliDebug(2,"No matched tracks found!\n");
    2867           0 :     dEta=999.;
    2868           0 :     dPhi=999.;
    2869           0 :     return;
    2870             :   }
    2871             :   
    2872           0 :   dEta = fResidualEta->At(FindMatchedPosForCluster(clsIndex));
    2873           0 :   dPhi = fResidualPhi->At(FindMatchedPosForCluster(clsIndex));
    2874           0 : }
    2875             : 
    2876             : ///
    2877             : /// Given a track index, get the residuals dEta and dPhi for this track 
    2878             : /// to the closest cluster.
    2879             : /// It works with ESDs and AODs.
    2880             : ///
    2881             : /// \param trkIndex: cluster index as in AliESDEvent::GetTrack(trkIndex)
    2882             : /// \param dEta: residual eta
    2883             : /// \param dPhi: residual phi
    2884             : ///
    2885             : //______________________________________________________________________________________________
    2886             : void AliEMCALRecoUtils::GetMatchedClusterResiduals(Int_t trkIndex, Float_t &dEta, Float_t &dPhi)
    2887             : {
    2888           0 :   if (FindMatchedPosForTrack(trkIndex) >= 999) 
    2889             :   {
    2890           0 :     AliDebug(2,"No matched cluster found!\n");
    2891           0 :     dEta=999.;
    2892           0 :     dPhi=999.;
    2893           0 :     return;
    2894             :   }
    2895             :   
    2896           0 :   dEta = fResidualEta->At(FindMatchedPosForTrack(trkIndex));
    2897           0 :   dPhi = fResidualPhi->At(FindMatchedPosForTrack(trkIndex));
    2898           0 : }
    2899             : 
    2900             : ///
    2901             : /// Given a cluster index , get the index of matched track to this cluster.
    2902             : /// It works with ESDs and AODs.
    2903             : ///
    2904             : /// \param clsIndex: cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
    2905             : ///
    2906             : //__________________________________________________________
    2907             : Int_t AliEMCALRecoUtils::GetMatchedTrackIndex(Int_t clsIndex)
    2908             : {
    2909           0 :   if (IsClusterMatched(clsIndex))
    2910           0 :     return fMatchedTrackIndex->At(FindMatchedPosForCluster(clsIndex));
    2911             :   else 
    2912           0 :     return -1; 
    2913           0 : }
    2914             : 
    2915             : ///
    2916             : /// Given a track index, get the index of matched cluster to this track.
    2917             : /// It works with ESDs and AODs.
    2918             : ///
    2919             : /// \param trkIndex: cluster index as in AliESDEvent::GetTrack(trkIndex)
    2920             : ///
    2921             : //__________________________________________________________
    2922             : Int_t AliEMCALRecoUtils::GetMatchedClusterIndex(Int_t trkIndex)
    2923             : {  
    2924           0 :   if (IsTrackMatched(trkIndex))
    2925           0 :     return fMatchedClusterIndex->At(FindMatchedPosForTrack(trkIndex));
    2926             :   else 
    2927           0 :     return -1; 
    2928           0 : }
    2929             : 
    2930             : ///
    2931             : /// Given a cluster index, it returns if the cluster has a match.
    2932             : ///
    2933             : /// \param trkIndex: cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
    2934             : ///
    2935             : /// \return bool true if cluster is matched
    2936             : ///
    2937             : //______________________________________________________________
    2938             : Bool_t AliEMCALRecoUtils::IsClusterMatched(Int_t clsIndex) const
    2939             : {
    2940           0 :   if (FindMatchedPosForCluster(clsIndex) < 999) 
    2941           0 :     return kTRUE;
    2942             :   else
    2943           0 :     return kFALSE;
    2944           0 : }
    2945             : 
    2946             : ///
    2947             : /// Given a track index, it returns if the track has a match.
    2948             : ///
    2949             : /// \param clsIndex: cluster index as in AliESDEvent::GetTrack(trkIndex)
    2950             : ///
    2951             : /// \return bool true if cluster is matched
    2952             : ///
    2953             : //____________________________________________________________
    2954             : Bool_t AliEMCALRecoUtils::IsTrackMatched(Int_t trkIndex) const 
    2955             : {
    2956           0 :   if (FindMatchedPosForTrack(trkIndex) < 999) 
    2957           0 :     return kTRUE;
    2958             :   else
    2959           0 :     return kFALSE;
    2960           0 : }
    2961             : 
    2962             : ///
    2963             : /// Given a cluster index, it returns the position of the match in the fMatchedClusterIndex array
    2964             : ///
    2965             : /// \param clsIndex: cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
    2966             : ///
    2967             : /// \return cluster position index
    2968             : ///
    2969             : //______________________________________________________________________
    2970             : UInt_t AliEMCALRecoUtils::FindMatchedPosForCluster(Int_t clsIndex) const
    2971             : {
    2972           0 :   Float_t tmpR = fCutR;
    2973             :   UInt_t pos = 999;
    2974             :   
    2975           0 :   for (Int_t i=0; i<fMatchedClusterIndex->GetSize(); i++) 
    2976             :   {
    2977           0 :     if (fMatchedClusterIndex->At(i)==clsIndex) 
    2978             :     {
    2979           0 :       Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
    2980           0 :       if (r<tmpR) 
    2981             :       {
    2982             :         pos=i;
    2983             :         tmpR=r;
    2984           0 :         AliDebug(3,Form("Matched cluster index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",
    2985             :                         fMatchedClusterIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
    2986             :       }
    2987           0 :     }
    2988             :   }
    2989           0 :   return pos;
    2990             : }
    2991             : 
    2992             : ///
    2993             : /// Given a cluster index, it returns the position of the match in the fMatchedTrackIndex  array
    2994             : ///
    2995             : /// \param trkIndex: cluster index as in AliESDEvent::GetCaloCluster(clsIndex)
    2996             : ///
    2997             : /// \return track position index
    2998             : ///
    2999             : //____________________________________________________________________
    3000             : UInt_t AliEMCALRecoUtils::FindMatchedPosForTrack(Int_t trkIndex) const
    3001             : {
    3002           0 :   Float_t tmpR = fCutR;
    3003             :   UInt_t pos = 999;
    3004             :   
    3005           0 :   for (Int_t i=0; i<fMatchedTrackIndex->GetSize(); i++) 
    3006             :   {
    3007           0 :     if (fMatchedTrackIndex->At(i)==trkIndex) 
    3008             :     {
    3009           0 :       Float_t r = TMath::Sqrt(fResidualEta->At(i)*fResidualEta->At(i) + fResidualPhi->At(i)*fResidualPhi->At(i));
    3010           0 :       if (r<tmpR) 
    3011             :       {
    3012             :         pos=i;
    3013             :         tmpR=r;
    3014           0 :         AliDebug(3,Form("Matched track index: index: %d, dEta: %2.4f, dPhi: %2.4f.\n",
    3015             :                         fMatchedTrackIndex->At(i),fResidualEta->At(i),fResidualPhi->At(i)));
    3016             :       }
    3017           0 :     }
    3018             :   }
    3019           0 :   return pos;
    3020             : }
    3021             : 
    3022             : ///
    3023             : /// Check if the cluster survives the following quality cuts:
    3024             : ///   * Cluster pointer is non null and is EMCal (or DCal)
    3025             : ///   * There is no bad channel cell inside
    3026             : ///   * The cluster is not too close to a fiducial border
    3027             : ///   * The cluster is not exotic
    3028             : ///
    3029             : /// \param cluster: pointer to AliVCluster
    3030             : /// \param geom: pointer to AliEMCALGeometry
    3031             : /// \param cells: full list of cells
    3032             : /// \param bc: event bunch crossing number
    3033             : ///
    3034             : /// \return true if cluster passes all selection criteria
    3035             : ///
    3036             : //__________________________________________________________________________
    3037             : Bool_t AliEMCALRecoUtils::IsGoodCluster(AliVCluster *cluster, 
    3038             :                                         const AliEMCALGeometry *geom, 
    3039             :                                         AliVCaloCells* cells, Int_t bc)
    3040             : {
    3041             :   Bool_t isGood=kTRUE;
    3042             : 
    3043           0 :   if (!cluster || !cluster->IsEMCAL())              return kFALSE;
    3044           0 :   if (ClusterContainsBadChannel(geom,cluster->GetCellsAbsId(),cluster->GetNCells())) return kFALSE;
    3045           0 :   if (!CheckCellFiducialRegion(geom,cluster,cells)) return kFALSE;
    3046           0 :   if (IsExoticCluster(cluster, cells,bc))           return kFALSE;
    3047             : 
    3048           0 :   return isGood;
    3049           0 : }
    3050             : 
    3051             : ///
    3052             : /// Given a esd track, return whether the track survive all the cuts.
    3053             : ///
    3054             : /// The different quality parameter are first.
    3055             : /// retrieved from the track. then it is found out what cuts the
    3056             : /// track did not survive and finally the cuts are imposed.
    3057             : ///
    3058             : /// \param esdTrack: pointer to ESD track
    3059             : ///
    3060             : /// \return true if track passes all selection criteria
    3061             : //__________________________________________________________
    3062             : Bool_t AliEMCALRecoUtils::IsAccepted(AliESDtrack *esdTrack)
    3063             : {
    3064           0 :   UInt_t status = esdTrack->GetStatus();
    3065             : 
    3066           0 :   Int_t nClustersITS = esdTrack->GetITSclusters(0);
    3067           0 :   Int_t nClustersTPC = esdTrack->GetTPCclusters(0);
    3068             : 
    3069             :   Float_t chi2PerClusterITS = -1;
    3070             :   Float_t chi2PerClusterTPC = -1;
    3071           0 :   if (nClustersITS!=0)
    3072           0 :     chi2PerClusterITS = esdTrack->GetITSchi2()/Float_t(nClustersITS);
    3073           0 :   if (nClustersTPC!=0) 
    3074           0 :     chi2PerClusterTPC = esdTrack->GetTPCchi2()/Float_t(nClustersTPC);
    3075             : 
    3076             :   //
    3077             :   // DCA cuts
    3078             :   // Only to be used for primary
    3079             :   //
    3080           0 :   if ( fTrackCutsType == kGlobalCut ) 
    3081             :   {
    3082           0 :     Float_t maxDCAToVertexXYPtDep = 0.0182 + 0.0350/TMath::Power(esdTrack->Pt(),1.01); 
    3083             :     // This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2010()
    3084             :     
    3085             :     //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
    3086             :     
    3087           0 :     SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
    3088           0 :   } 
    3089           0 :   else if( fTrackCutsType == kGlobalCut2011 )
    3090             :   {
    3091           0 :     Float_t maxDCAToVertexXYPtDep = 0.0105 + 0.0350/TMath::Power(esdTrack->Pt(),1.1); 
    3092             :     // This expression comes from AliESDtrackCuts::GetStandardITSTPCTrackCuts2011()
    3093             :     
    3094             :      //AliDebug(3,Form("Track pT = %f, DCAtoVertexXY = %f",esdTrack->Pt(),MaxDCAToVertexXYPtDep));
    3095             :     
    3096           0 :     SetMaxDCAToVertexXY(maxDCAToVertexXYPtDep); //Set pT dependent DCA cut to vertex in x-y plane
    3097           0 :   }
    3098             : 
    3099           0 :   Float_t b[2];
    3100           0 :   Float_t bCov[3];
    3101           0 :   esdTrack->GetImpactParameters(b,bCov);
    3102           0 :   if (bCov[0]<=0 || bCov[2]<=0) 
    3103             :   {
    3104           0 :     AliDebug(1, "Estimated b resolution lower or equal zero!");
    3105           0 :     bCov[0]=0; bCov[2]=0;
    3106           0 :   }
    3107             : 
    3108           0 :   Float_t dcaToVertexXY = b[0];
    3109           0 :   Float_t dcaToVertexZ = b[1];
    3110             :   Float_t dcaToVertex = -1;
    3111             : 
    3112           0 :   if (fCutDCAToVertex2D)
    3113           0 :     dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY / fCutMaxDCAToVertexXY/fCutMaxDCAToVertexXY + 
    3114           0 :                               dcaToVertexZ*dcaToVertexZ   / fCutMaxDCAToVertexZ/fCutMaxDCAToVertexZ     );
    3115             :   else
    3116           0 :     dcaToVertex = TMath::Sqrt(dcaToVertexXY*dcaToVertexXY + dcaToVertexZ*dcaToVertexZ);
    3117             :     
    3118             :   // cut the track?
    3119             :   
    3120           0 :   Bool_t cuts[kNCuts];
    3121           0 :   for (Int_t i=0; i<kNCuts; i++) cuts[i]=kFALSE;
    3122             :   
    3123             :   // track quality cuts
    3124           0 :   if (fCutRequireTPCRefit && (status&AliESDtrack::kTPCrefit)==0)
    3125           0 :     cuts[0]=kTRUE;
    3126           0 :   if (fCutRequireITSRefit && (status&AliESDtrack::kITSrefit)==0)
    3127           0 :     cuts[1]=kTRUE;
    3128           0 :   if (nClustersTPC<fCutMinNClusterTPC)
    3129           0 :     cuts[2]=kTRUE;
    3130           0 :   if (nClustersITS<fCutMinNClusterITS) 
    3131           0 :     cuts[3]=kTRUE;
    3132           0 :   if (chi2PerClusterTPC>fCutMaxChi2PerClusterTPC) 
    3133           0 :     cuts[4]=kTRUE; 
    3134           0 :   if (chi2PerClusterITS>fCutMaxChi2PerClusterITS) 
    3135           0 :     cuts[5]=kTRUE;  
    3136           0 :   if (!fCutAcceptKinkDaughters && esdTrack->GetKinkIndex(0)>0)
    3137           0 :     cuts[6]=kTRUE;
    3138           0 :   if (fCutDCAToVertex2D && dcaToVertex > 1)
    3139           0 :     cuts[7] = kTRUE;
    3140           0 :   if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexXY) > fCutMaxDCAToVertexXY)
    3141           0 :     cuts[8] = kTRUE;
    3142           0 :   if (!fCutDCAToVertex2D && TMath::Abs(dcaToVertexZ)  > fCutMaxDCAToVertexZ)
    3143           0 :     cuts[9] = kTRUE;
    3144             : 
    3145           0 :   if (fTrackCutsType == kGlobalCut || fTrackCutsType == kGlobalCut2011) 
    3146             :   {
    3147             :     //Require at least one SPD point + anything else in ITS
    3148           0 :     if ( (esdTrack->HasPointOnITSLayer(0) || esdTrack->HasPointOnITSLayer(1)) == kFALSE)
    3149           0 :       cuts[10] = kTRUE;
    3150             :   }
    3151             : 
    3152             :   // ITS
    3153           0 :   if (fCutRequireITSStandAlone || fCutRequireITSpureSA) 
    3154             :   {
    3155           0 :     if ((status & AliESDtrack::kITSin) == 0 || (status & AliESDtrack::kTPCin)) 
    3156             :     {
    3157             :       // TPC tracks
    3158           0 :       cuts[11] = kTRUE; 
    3159           0 :     } 
    3160             :     else 
    3161             :     {
    3162             :       // ITS standalone tracks
    3163           0 :       if (fCutRequireITSStandAlone && !fCutRequireITSpureSA) 
    3164             :       {
    3165           0 :         if (status & AliESDtrack::kITSpureSA)    cuts[11] = kTRUE;
    3166             :       } 
    3167           0 :       else if (fCutRequireITSpureSA) 
    3168             :       {
    3169           0 :         if (!(status & AliESDtrack::kITSpureSA)) cuts[11] = kTRUE;
    3170             :       }
    3171             :     }
    3172             :   }
    3173             :   
    3174             :   Bool_t cut=kFALSE;
    3175           0 :   for (Int_t i=0; i<kNCuts; i++)
    3176           0 :     if (cuts[i]) { cut = kTRUE ; }
    3177             : 
    3178             :   // cut the track
    3179           0 :   if (cut) 
    3180           0 :     return kFALSE;
    3181             :   else 
    3182           0 :     return kTRUE;
    3183           0 : }
    3184             : 
    3185             : ///
    3186             : /// Initialize the track cut criteria.
    3187             : /// By default these cuts are set according to AliESDtrackCuts::GetStandardTPCOnlyTrackCuts().
    3188             : /// Also, you can customize the cuts using the setters.
    3189             : ///
    3190             : //_____________________________________
    3191             : void AliEMCALRecoUtils::InitTrackCuts()
    3192             : {  
    3193           0 :   switch (fTrackCutsType)
    3194             :   {
    3195             :     case kTPCOnlyCut:
    3196             :     {
    3197           0 :       AliInfo(Form("Track cuts for matching: AliESDtrackCuts::GetStandardTPCOnlyTrackCuts()"));
    3198             :       //TPC
    3199           0 :       SetMinNClustersTPC(70);
    3200           0 :       SetMaxChi2PerClusterTPC(4);
    3201           0 :       SetAcceptKinkDaughters(kFALSE);
    3202           0 :       SetRequireTPCRefit(kFALSE);
    3203             :       
    3204             :       //ITS
    3205           0 :       SetRequireITSRefit(kFALSE);
    3206           0 :       SetMaxDCAToVertexZ(3.2);
    3207           0 :       SetMaxDCAToVertexXY(2.4);
    3208           0 :       SetDCAToVertex2D(kTRUE);
    3209             :       
    3210           0 :       break;
    3211             :     }
    3212             :       
    3213             :     case kGlobalCut:
    3214             :     {
    3215           0 :       AliInfo(Form("Track cuts for matching: AliESDtrackCuts::GetStandardITSTPCTrackCuts2010(kTRUE)"));
    3216             :       //TPC
    3217           0 :       SetMinNClustersTPC(70);
    3218           0 :       SetMaxChi2PerClusterTPC(4);
    3219           0 :       SetAcceptKinkDaughters(kFALSE);
    3220           0 :       SetRequireTPCRefit(kTRUE);
    3221             :       
    3222             :       //ITS
    3223           0 :       SetRequireITSRefit(kTRUE);
    3224           0 :       SetMaxDCAToVertexZ(2);
    3225           0 :       SetMaxDCAToVertexXY();
    3226           0 :       SetDCAToVertex2D(kFALSE);
    3227             :       
    3228           0 :       break;
    3229             :     }
    3230             :       
    3231             :     case kLooseCut:
    3232             :     {
    3233           0 :       AliInfo(Form("Track cuts for matching: Loose cut w/o DCA cut"));
    3234           0 :       SetMinNClustersTPC(50);
    3235           0 :       SetAcceptKinkDaughters(kTRUE);
    3236             :       
    3237           0 :       break;
    3238             :     }
    3239             :       
    3240             :     case kITSStandAlone:
    3241             :     {
    3242           0 :       AliInfo(Form("Track cuts for matching: ITS Stand Alone tracks cut w/o DCA cut"));
    3243           0 :       SetRequireITSRefit(kTRUE);
    3244           0 :       SetRequireITSStandAlone(kTRUE);
    3245           0 :       SetITSTrackSA(kTRUE);
    3246           0 :       break;
    3247             :     }
    3248             :     
    3249             :     case kGlobalCut2011:
    3250             :     {
    3251           0 :       AliInfo(Form("Track cuts for matching: AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kTRUE)"));
    3252             :       //TPC
    3253           0 :       SetMinNClustersTPC(50);
    3254           0 :       SetMaxChi2PerClusterTPC(4);
    3255           0 :       SetAcceptKinkDaughters(kFALSE);
    3256           0 :       SetRequireTPCRefit(kTRUE);
    3257             :       
    3258             :       //ITS
    3259           0 :       SetRequireITSRefit(kTRUE);
    3260           0 :       SetMaxDCAToVertexZ(2);
    3261           0 :       SetMaxDCAToVertexXY();
    3262           0 :       SetDCAToVertex2D(kFALSE);
    3263             :       
    3264           0 :       break;
    3265             :     }  
    3266             :      
    3267             :     case kLooseCutWithITSrefit:
    3268             :     {
    3269           0 :       AliInfo(Form("Track cuts for matching: Loose cut w/o DCA cut plus ITSrefit"));
    3270           0 :       SetMinNClustersTPC(50);
    3271           0 :       SetAcceptKinkDaughters(kTRUE);
    3272           0 :       SetRequireITSRefit(kTRUE);
    3273             : 
    3274           0 :       break;
    3275             :     }
    3276             :   }
    3277           0 : }
    3278             : 
    3279             : ///
    3280             : /// Check if tracks are matched to EMC clusters and set the matched EMCAL cluster index to ESD track. 
    3281             : ///
    3282             : /// \param event: pointer to event
    3283             : ///
    3284             : //________________________________________________________________________
    3285             : void AliEMCALRecoUtils::SetClusterMatchedToTrack(const AliVEvent *event)
    3286             : {
    3287           0 :   Int_t nTracks = event->GetNumberOfTracks();
    3288           0 :   for (Int_t iTrack = 0; iTrack < nTracks; ++iTrack) 
    3289             :   {
    3290           0 :     AliVTrack* track = dynamic_cast<AliVTrack*>(event->GetTrack(iTrack));
    3291           0 :     if (!track) 
    3292             :     {
    3293           0 :       AliWarning(Form("Could not receive track %d", iTrack));
    3294           0 :       continue;
    3295             :     }
    3296             :     
    3297           0 :     Int_t matchClusIndex = GetMatchedClusterIndex(iTrack);       
    3298           0 :     track->SetEMCALcluster(matchClusIndex); //sets -1 if track not matched within residual
    3299             :     
    3300             :     /*the following can be done better if AliVTrack::SetStatus will be there. Patch pending with Andreas/Peter*/
    3301           0 :     AliESDtrack* esdtrack = dynamic_cast<AliESDtrack*>(track);
    3302           0 :     if (esdtrack) 
    3303             :     { 
    3304           0 :       if (matchClusIndex != -1) 
    3305           0 :         esdtrack->SetStatus(AliESDtrack::kEMCALmatch);
    3306             :       else
    3307           0 :         esdtrack->ResetStatus(AliESDtrack::kEMCALmatch);
    3308             :     } 
    3309             :     else 
    3310             :     {
    3311           0 :       AliAODTrack* aodtrack = dynamic_cast<AliAODTrack*>(track);
    3312           0 :       if (matchClusIndex != -1) 
    3313           0 :         aodtrack->SetStatus(AliESDtrack::kEMCALmatch);
    3314             :       else
    3315           0 :         aodtrack->ResetStatus(AliESDtrack::kEMCALmatch);
    3316             :     }
    3317           0 :   }
    3318           0 :   AliDebug(2,"Track matched to closest cluster");  
    3319           0 : }
    3320             : 
    3321             : ///
    3322             : /// Checks if EMC clusters are matched to ESD track.
    3323             : /// Adds track indexes of all the tracks matched to a cluster within residuals in AliVCluster.
    3324             : ///
    3325             : /// \param event: pointer to event
    3326             : ///
    3327             : //_________________________________________________________________________
    3328             : void AliEMCALRecoUtils::SetTracksMatchedToCluster(const AliVEvent *event)
    3329             : {
    3330           0 :   for (Int_t iClus=0; iClus < event->GetNumberOfCaloClusters(); ++iClus) 
    3331             :   {
    3332           0 :     AliVCluster *cluster = event->GetCaloCluster(iClus);
    3333           0 :     if (!cluster->IsEMCAL()) 
    3334           0 :       continue;
    3335             :     
    3336             :     //
    3337             :     // Remove old matches in cluster
    3338             :     //
    3339           0 :     if(cluster->GetNTracksMatched() > 0)
    3340             :     {
    3341           0 :       if(!strcmp("AliESDCaloCluster",Form("%s",cluster->ClassName())))
    3342             :       {
    3343           0 :         TArrayI arrayTrackMatched(0);
    3344           0 :         ((AliESDCaloCluster*)cluster)->AddTracksMatched(arrayTrackMatched);
    3345           0 :       }
    3346             :       else
    3347             :       {
    3348           0 :         for(Int_t iTrack = 0; iTrack < cluster->GetNTracksMatched(); iTrack++)
    3349             :         {
    3350           0 :           ((AliAODCaloCluster*)cluster)->RemoveTrackMatched((TObject*)((AliAODCaloCluster*)cluster)->GetTrackMatched(iTrack));
    3351             :         }
    3352             :       }
    3353             :     }
    3354             :     
    3355             :     //
    3356             :     // Find new matches and put them in the cluster
    3357             :     //
    3358           0 :     Int_t nTracks = event->GetNumberOfTracks();
    3359           0 :     TArrayI arrayTrackMatched(nTracks);
    3360             :     
    3361             :     // Get the closest track matched to the cluster
    3362             :     Int_t nMatched = 0;
    3363           0 :     Int_t matchTrackIndex = GetMatchedTrackIndex(iClus);
    3364           0 :     if (matchTrackIndex != -1) 
    3365             :     {
    3366           0 :       arrayTrackMatched[nMatched] = matchTrackIndex;
    3367             :       nMatched++;
    3368           0 :     }
    3369             :     
    3370             :     // Get all other tracks matched to the cluster
    3371           0 :     for (Int_t iTrk=0; iTrk<nTracks; ++iTrk) 
    3372             :     {
    3373           0 :       AliVTrack* track = dynamic_cast<AliVTrack*>(event->GetTrack(iTrk));
    3374             :       
    3375           0 :       if( !track ) continue;
    3376             :       
    3377           0 :       if ( iTrk == matchTrackIndex ) continue;
    3378             :       
    3379           0 :       if ( track->GetEMCALcluster() == iClus )
    3380             :       {
    3381           0 :         arrayTrackMatched[nMatched] = iTrk;
    3382           0 :         ++nMatched;
    3383           0 :       }
    3384           0 :     }
    3385             :     
    3386           0 :     AliDebug(2,Form("cluster E %f, N matches %d, first match %d\n",cluster->E(),nMatched,arrayTrackMatched[0]));
    3387             :     
    3388           0 :     arrayTrackMatched.Set(nMatched);
    3389           0 :     AliESDCaloCluster *esdcluster = dynamic_cast<AliESDCaloCluster*>(cluster);
    3390           0 :     if (esdcluster) 
    3391           0 :       esdcluster->AddTracksMatched(arrayTrackMatched);
    3392           0 :     else if ( nMatched > 0 ) 
    3393             :     {
    3394           0 :       AliAODCaloCluster *aodcluster = dynamic_cast<AliAODCaloCluster*>(cluster);
    3395           0 :       if (aodcluster)
    3396             :       {
    3397           0 :         aodcluster->AddTrackMatched(event->GetTrack(arrayTrackMatched.At(0)));
    3398             :         //AliAODTrack *aodtrack=dynamic_cast<AliAODTrack*>(event->GetTrack(arrayTrackMatched.At(0)));
    3399             :         //printf("Is the closest matching track with ID %d a 128? %d what's its full filter map? %u\n",aodtrack->GetID(), aodtrack->TestFilterBit(128),aodtrack->GetFilterMap());
    3400             :         //printf("With specs: pt %.4f, eta %.4f, phi %.4f\n",aodtrack->Pt(),aodtrack->Eta(), aodtrack->Phi());
    3401             :       }
    3402           0 :     }
    3403             :     
    3404           0 :     Float_t eta= -999, phi = -999;
    3405           0 :     if (matchTrackIndex != -1) 
    3406           0 :       GetMatchedResiduals(iClus, eta, phi);
    3407             :     
    3408           0 :     cluster->SetTrackDistance(phi, eta);
    3409           0 :   }
    3410             :   
    3411           0 :   AliDebug(2,"Cluster matched to tracks");  
    3412           0 : }
    3413             : 
    3414             : ///
    3415             : /// Print Parameters.
    3416             : ///
    3417             : //___________________________________________________
    3418             : void AliEMCALRecoUtils::Print(const Option_t *) const 
    3419             : { 
    3420           0 :   printf("-------------------------------------------------------------------------------------------------------------------------------------- \n");
    3421           0 :   printf("AliEMCALRecoUtils Settings: \n");
    3422           0 :   printf("\tMisalignment shifts\n");
    3423           0 :   for (Int_t i=0; i<5; i++) printf("\t\t sector %d, traslation (x,y,z)=(%f,%f,%f), rotation (x,y,z)=(%f,%f,%f)\n",i, 
    3424           0 :                                   fMisalTransShift[i*3],fMisalTransShift[i*3+1],fMisalTransShift[i*3+2],
    3425           0 :                                   fMisalRotShift[i*3],  fMisalRotShift[i*3+1],  fMisalRotShift[i*3+2]   );
    3426           0 :   printf("\tNon linearity function %d, parameters:\n", fNonLinearityFunction);
    3427           0 :   if (fNonLinearityFunction != 3) // print only if not kNoCorrection
    3428           0 :     for (Int_t i=0; i<6; i++) printf("param[%d]=%f\n",i, fNonLinearityParams[i]);
    3429             :   
    3430           0 :   printf("\tPosition Recalculation option %d, Particle Type %d, fW0 %2.2f, Recalibrate Data %d \n",fPosAlgo,fParticleType,fW0, fRecalibration);
    3431             : 
    3432           0 :   printf("\tMatching criteria: ");
    3433           0 :   if (fCutEtaPhiSum) {
    3434           0 :     printf("\t\tsqrt(dEta^2+dPhi^2)<%4.3f\n",fCutR);
    3435           0 :   } else if (fCutEtaPhiSeparate) {
    3436           0 :     printf("\t\tdEta<%4.3f, dPhi<%4.3f\n",fCutEta,fCutPhi);
    3437           0 :   } else {
    3438           0 :     printf("\t\tError\n");
    3439           0 :     printf("\t\tplease specify your cut criteria\n");
    3440           0 :     printf("\t\tTo cut on sqrt(dEta^2+dPhi^2), use: SwitchOnCutEtaPhiSum()\n");
    3441           0 :     printf("\t\tTo cut on dEta and dPhi separately, use: SwitchOnCutEtaPhiSeparate()\n");
    3442             :   }
    3443             : 
    3444           0 :   printf("\tMass hypothesis = %2.3f [GeV/c^2], extrapolation step to surface = %2.2f[cm], step to cluster = %2.2f[cm]\n",fMass,fStepSurface, fStepCluster);
    3445           0 :   printf("\tCluster selection window: dR < %2.0f\n",fClusterWindow);
    3446             : 
    3447           0 :   printf("\tTrack cuts: \n");
    3448           0 :   printf("\t\tMinimum track pT: %1.2f\n",fCutMinTrackPt);
    3449           0 :   printf("\t\tAOD track selection: tpc only %d, or hybrid %d, or mask: %d\n",fAODTPCOnlyTracks,fAODHybridTracks, fAODFilterMask);
    3450           0 :   printf("\t\tTPCRefit = %d, ITSRefit = %d\n",fCutRequireTPCRefit,fCutRequireITSRefit);
    3451           0 :   printf("\t\tAcceptKinks = %d\n",fCutAcceptKinkDaughters);
    3452           0 :   printf("\t\tMinNCulsterTPC = %d, MinNClusterITS = %d\n",fCutMinNClusterTPC,fCutMinNClusterITS);
    3453           0 :   printf("\t\tMaxChi2TPC = %2.2f, MaxChi2ITS = %2.2f\n",fCutMaxChi2PerClusterTPC,fCutMaxChi2PerClusterITS);
    3454           0 :   printf("\t\tDCSToVertex2D = %d, MaxDCAToVertexXY = %2.2f, MaxDCAToVertexZ = %2.2f\n",fCutDCAToVertex2D,fCutMaxDCAToVertexXY,fCutMaxDCAToVertexZ);
    3455           0 :   printf("-------------------------------------------------------------------------------------------------------------------------------------- \n");
    3456           0 : }

Generated by: LCOV version 1.11