LCOV - code coverage report
Current view: top level - EMCAL/EMCALrec - AliEMCALUnfolding.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 489 0.2 %
Date: 2016-06-14 17:26:59 Functions: 1 25 4.0 %

          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             : //_________________________________________________________________________
      17             : //  Base class for the cluster unfolding algorithm 
      18             : //*-- Author: Adam Matyja (SUBATECH)
      19             : //  Based on unfolding in clusterizerv1 done by Cynthia Hadjidakis
      20             : //-- Unfolding for eta~0: Cynthia Hadjidakis - still in AliEMCALCLusterizerv1
      21             : //-- Unfolding extension for whole EMCAL: Adam Matyja (SUBATECH & INP PAN)
      22             : //
      23             : //  unfolds the clusters having several local maxima. 
      24             : //////////////////////////////////////////////////////////////////////////////
      25             : 
      26             : // --- ROOT system ---
      27             : #include "TClonesArray.h"
      28             : #include <TMath.h> 
      29             : #include <TMinuit.h>
      30             : 
      31             : // --- Standard library ---
      32             : #include <cassert>
      33             : 
      34             : // --- AliRoot header files ---
      35             : #include "AliEMCALUnfolding.h"
      36             : #include "AliEMCALGeometry.h"
      37             : #include "AliRunLoader.h"
      38             : #include "AliRun.h"
      39             : #include "AliEMCAL.h"
      40             : #include "AliEMCALRecParam.h"
      41             : #include "AliEMCALRecPoint.h"
      42             : #include "AliEMCALDigit.h"
      43             : #include "AliEMCALReconstructor.h"
      44             : 
      45             : #include "AliLog.h"
      46             : #include "AliCDBManager.h"
      47             : class AliCDBStorage;
      48             : #include "AliCDBEntry.h"
      49             : 
      50             : Double_t AliEMCALUnfolding::fgSSPars[8]={0.9262,3.365,1.548,0.1625,-0.4195,0.,0.,2.332};
      51             : Double_t AliEMCALUnfolding::fgPar5[3]={12.31,-0.007381,-0.06936};
      52             : Double_t AliEMCALUnfolding::fgPar6[3]={0.05452,0.0001228,0.001361};
      53             : 
      54          42 : ClassImp(AliEMCALUnfolding)
      55             :   
      56             : //____________________________________________________________________________
      57           0 : AliEMCALUnfolding::AliEMCALUnfolding():
      58           0 :   fNumberOfECAClusters(0),
      59           0 :   fECALocMaxCut(0),
      60           0 :   fThreshold(0.01),//10 MeV
      61           0 :   fRejectBelowThreshold(0),//split
      62           0 :   fGeom(NULL),
      63           0 :   fRecPoints(NULL),
      64           0 :   fDigitsArr(NULL)
      65           0 : {
      66             :   // ctor with the indication of the file where header Tree and digits Tree are stored
      67           0 :   Init() ;
      68           0 : }
      69             : 
      70             : //____________________________________________________________________________
      71           0 : AliEMCALUnfolding::AliEMCALUnfolding(AliEMCALGeometry* geometry):
      72           0 :   fNumberOfECAClusters(0),
      73           0 :   fECALocMaxCut(0),
      74           0 :   fThreshold(0.01),//10 MeV
      75           0 :   fRejectBelowThreshold(0),//split
      76           0 :   fGeom(geometry),
      77           0 :   fRecPoints(NULL),
      78           0 :   fDigitsArr(NULL)
      79           0 : {
      80             :   // ctor with the indication of the file where header Tree and digits Tree are stored
      81             :   // use this contructor to avoid usage of Init() which uses runloader
      82             :   // change needed by HLT - MP
      83           0 :   if (!fGeom)
      84             :   {
      85           0 :     AliFatal("AliEMCALUnfolding: Geometry not initialized.");
      86             :   }
      87             : 
      88           0 : }
      89             : 
      90             : //____________________________________________________________________________
      91           0 : AliEMCALUnfolding::AliEMCALUnfolding(AliEMCALGeometry* geometry,Float_t ECALocMaxCut,Double_t *SSPars,Double_t *Par5,Double_t *Par6):
      92           0 :   fNumberOfECAClusters(0),
      93           0 :   fECALocMaxCut(ECALocMaxCut),
      94           0 :   fThreshold(0.01),//10 MeV
      95           0 :   fRejectBelowThreshold(0),//split
      96           0 :   fGeom(geometry),
      97           0 :   fRecPoints(NULL),
      98           0 :   fDigitsArr(NULL)
      99           0 : {
     100             :   // ctor with the indication of the file where header Tree and digits Tree are stored
     101             :   // use this contructor to avoid usage of Init() which uses runloader
     102             :   // change needed by HLT - MP
     103           0 :   if (!fGeom)
     104             :   {
     105           0 :     AliFatal("AliEMCALUnfolding: Geometry not initialized.");
     106             :   }
     107             :   Int_t i=0;
     108           0 :   for (i = 0; i < 8; i++) fgSSPars[i] = SSPars[i];
     109           0 :   for (i = 0; i < 3; i++) {
     110           0 :     fgPar5[i] = Par5[i];
     111           0 :     fgPar6[i] = Par6[i];
     112             :   }
     113             : 
     114           0 : }
     115             : 
     116             : //____________________________________________________________________________
     117             : void AliEMCALUnfolding::Init()
     118             : {
     119             :   // Make all memory allocations which can not be done in default constructor.
     120             :   // Attach the Clusterizer task to the list of EMCAL tasks
     121             : 
     122           0 :   AliRunLoader *rl = AliRunLoader::Instance();
     123           0 :   if (rl && rl->GetAliRun()){
     124           0 :     AliEMCAL* emcal = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"));
     125           0 :     if(emcal)fGeom = emcal->GetGeometry();
     126           0 :   }
     127             :   
     128           0 :   if(!fGeom)
     129           0 :     fGeom =  AliEMCALGeometry::GetInstance(AliEMCALGeometry::GetDefaultGeometryName());
     130             :   
     131           0 :   AliDebug(1,Form("geom %p",fGeom));
     132             :   
     133           0 :   if(!gMinuit) 
     134             :     //    gMinuit = new TMinuit(100) ;//the same is in FindFitV2
     135           0 :     gMinuit = new TMinuit(30) ;//the same is in FindFitV2
     136             :   
     137           0 : }
     138             : 
     139             : //____________________________________________________________________________
     140             :   AliEMCALUnfolding::~AliEMCALUnfolding()
     141           0 : {
     142             :   // dtor
     143           0 : }
     144             : 
     145             : //____________________________________________________________________________
     146             : void AliEMCALUnfolding::SetInput(Int_t numberOfECAClusters,TObjArray *recPoints,TClonesArray *digitsArr)
     147             : {
     148             :   //
     149             :   //Set input for unfolding purposes
     150             :   //
     151           0 :   SetNumberOfECAClusters(numberOfECAClusters);
     152           0 :   SetRecPoints(recPoints);
     153           0 :   SetDigitsArr(digitsArr);
     154           0 : }
     155             : 
     156             : //____________________________________________________________________________
     157             : void AliEMCALUnfolding::MakeUnfolding()
     158             : {
     159             :   // Unfolds clusters using the shape of an ElectroMagnetic shower
     160             :   // Performs unfolding of all clusters
     161             :   
     162           0 :   AliDebug(4,Form(" V1: total no of clusters %d from %d digits",fNumberOfECAClusters,fDigitsArr->GetEntriesFast()));
     163           0 :   if(fNumberOfECAClusters > 0){
     164           0 :     if (fGeom==0)
     165           0 :       AliFatal("Did not get geometry from EMCALLoader") ;
     166             :     //Int_t nModulesToUnfold = fGeom->GetNCells();
     167             :     
     168           0 :     Int_t numberOfClustersToUnfold=fNumberOfECAClusters;
     169             :     //we unfold only clusters present in the array untill now
     170             :     //fNumberOfECAClusters may change due to unfilded clusters
     171             :     //so 0 to numberOfClustersToUnfold-1: clusters before unfolding
     172             :     //numberOfClustersToUnfold to the end: new clusters from unfolding
     173             :     //of course numberOfClustersToUnfold also is decreased but we don't loop over clusters added in UF 
     174             :     Int_t index ;
     175           0 :     for(index = 0 ; index < numberOfClustersToUnfold ; index++){
     176           0 :       AliEMCALRecPoint * recPoint = dynamic_cast<AliEMCALRecPoint *>( fRecPoints->At(index) ) ;
     177           0 :       if(recPoint){
     178           0 :         Int_t nMultipl = recPoint->GetMultiplicity() ;
     179           0 :         AliEMCALDigit ** maxAt = new AliEMCALDigit*[nMultipl] ;
     180           0 :         Float_t * maxAtEnergy = new Float_t[nMultipl] ;
     181           0 :         Int_t nMax = recPoint->GetNumberOfLocalMax(maxAt, maxAtEnergy,fECALocMaxCut,fDigitsArr) ;
     182           0 :         if( nMax > 1 ) {     // if cluster is very flat (no pronounced maximum) then nMax = 0
     183           0 :           AliDebug(4,Form("  *** V1+UNFOLD *** Cluster index before UF %d",fNumberOfECAClusters));
     184           0 :           if(UnfoldClusterV2(recPoint, nMax, maxAt, maxAtEnergy) ){
     185             :             //if unfolding correct remove old recPoint
     186           0 :             fRecPoints->Remove(recPoint);
     187           0 :             fRecPoints->Compress() ;//is it really needed
     188           0 :             index-- ;
     189           0 :             fNumberOfECAClusters-- ;
     190           0 :             numberOfClustersToUnfold--;
     191           0 :           }
     192           0 :           AliDebug(4,Form("  Cluster index after UF %d",fNumberOfECAClusters));
     193             :         } else{
     194           0 :           recPoint->SetNExMax(1) ; //Only one local maximum
     195             :         }
     196             :         
     197           0 :         delete[] maxAt ;
     198           0 :         delete[] maxAtEnergy ;
     199           0 :       } else {
     200             :         //AliError("RecPoint NULL"); //end of check if recPoint exist
     201           0 :         Error("MakeUnfolding", "RecPoint NULL, index = %d, fNumberOfECAClusters = %d, numberOfClustersToUnfold = %d",index,fNumberOfECAClusters,numberOfClustersToUnfold) ;
     202             :       }
     203             :     } // rec point loop
     204           0 :   }//end of check fNumberOfECAClusters
     205             :   // End of Unfolding of clusters
     206             : 
     207           0 :   AliDebug(4,Form(" V1+UNFOLD: total no of clusters %d from %d digits",fNumberOfECAClusters,fDigitsArr->GetEntriesFast()));
     208             : //  for(Int_t i=0;i<fNumberOfECAClusters;i++){
     209             : //    AliEMCALRecPoint * recPoint = dynamic_cast<AliEMCALRecPoint *>(fRecPoints->At(i));
     210             : //    Int_t nMultipl = recPoint->GetMultiplicity() ;
     211             : //    Double_t energy=recPoint->GetEnergy();
     212             : //    Int_t absIdMaxDigit=recPoint->GetAbsIdMaxDigit();
     213             : //    Int_t sm=recPoint->GetSuperModuleNumber();
     214             : //    Double_t pointEne=recPoint->GetPointEnergy();
     215             : //    Float_t maxEne=recPoint->GetMaximalEnergy();
     216             : //    Int_t maxEneInd=recPoint->GetMaximalEnergyIndex();
     217             : //    printf("  cluster %d,ncells %d,ene %f,absIdMaxCell %d,sm %d,pointEne %f,maxEne %f,maxEneInd %d\n",i,nMultipl,energy,absIdMaxDigit,sm,pointEne,maxEne,maxEneInd);
     218             : //  }
     219             : 
     220           0 : }
     221             : 
     222             : //____________________________________________________________________________
     223             : Int_t AliEMCALUnfolding::UnfoldOneCluster(AliEMCALRecPoint * iniTower, 
     224             :                                           Int_t nMax, 
     225             :                                           AliEMCALDigit ** maxAt, 
     226             :                                           Float_t * maxAtEnergy,
     227             :                                           TObjArray *list)
     228             : {
     229             :   // Input one cluster
     230             :   // Output list of clusters
     231             :   // returns number of clusters
     232             :   // if fit failed or unfolding is not applicable returns 0 and empty list
     233             :   
     234             :   //**************************** part 1 *******************************************
     235             :   // Performs the unfolding of a cluster with nMax overlapping showers 
     236             :   
     237             :   //cout<<"unfolding check here part 1"<<endl;
     238           0 :   AliDebug(5,Form("  Original cluster E %f, nMax = %d",iniTower->GetEnergy(),nMax ));
     239             : 
     240           0 :   Int_t nPar = 3 * nMax ;
     241           0 :   Float_t * fitparameters = new Float_t[nPar] ;
     242             :   
     243           0 :   if (fGeom==0)
     244           0 :     AliFatal("Did not get geometry from EMCALLoader") ;
     245             :   
     246           0 :   Bool_t rv = FindFitV2(iniTower, maxAt, maxAtEnergy, nPar, fitparameters) ;
     247           0 :   if( !rv ) 
     248             :   {
     249             :     // Fit failed, return (and remove cluster? - why? I leave the cluster)
     250           0 :     iniTower->SetNExMax(-1) ;
     251           0 :     delete[] fitparameters ;
     252           0 :     return 0;//changed here
     253             :   }
     254             :   
     255             :   //speed up solution for clusters with 2 maxima where one maximum is below threshold fThreshold
     256           0 :   if(nMax==2){
     257           0 :     if(fitparameters[2]<fThreshold || fitparameters[5]<fThreshold){
     258           0 :       AliDebug(1,"One of fitted energy below threshold");
     259           0 :       iniTower->SetNExMax(1) ;
     260           0 :       delete[] fitparameters ;
     261           0 :       return 0;//changed here
     262             :     }
     263             :   }
     264             : 
     265             :   //**************************** part 2 *******************************************
     266             :   // create unfolded rec points and fill them with new energy lists
     267             :   // First calculate energy deposited in each sell in accordance with
     268             :   // fit (without fluctuations): efit[]
     269             :   // and later correct this number in acordance with actual energy
     270             :   // deposition
     271             :   
     272             :   //  cout<<"unfolding check here part 2"<<endl;
     273           0 :   Int_t nDigits = iniTower->GetMultiplicity() ;
     274           0 :   Float_t * efit = new Float_t[nDigits] ;//new fitted energy in cells
     275             :   Float_t xpar=0.,zpar=0.,epar=0.  ;//center of gravity in cell units
     276             :   
     277             :   AliEMCALDigit * digit = 0 ;
     278           0 :   Int_t * digitsList = iniTower->GetDigitsList() ;
     279             :   
     280           0 :   Int_t iSupMod =  0 ;
     281           0 :   Int_t iTower  =  0 ;
     282           0 :   Int_t iIphi   =  0 ;
     283           0 :   Int_t iIeta   =  0 ;
     284           0 :   Int_t iphi    =  0 ;//x direction
     285           0 :   Int_t ieta    =  0 ;//z direstion
     286             :   
     287             :   Int_t iparam = 0 ;
     288             :   Int_t iDigit = 0 ;
     289             :   
     290           0 :   for(iDigit = 0 ; iDigit < nDigits ; iDigit ++)
     291             :   {
     292           0 :     digit = dynamic_cast<AliEMCALDigit*>( fDigitsArr->At(digitsList[iDigit] ) ) ;
     293           0 :     if(digit)
     294             :     {
     295           0 :       fGeom->GetCellIndex(digit->GetId(),iSupMod,iTower,iIphi,iIeta); 
     296           0 :       fGeom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
     297           0 :                                          iIphi, iIeta,iphi,ieta);
     298           0 :       EvalParsPhiDependence(digit->GetId(),fGeom);
     299             :       
     300           0 :       efit[iDigit] = 0.;
     301             :       iparam = 0;
     302           0 :       while(iparam < nPar )
     303             :       {
     304           0 :         xpar = fitparameters[iparam] ;
     305           0 :         zpar = fitparameters[iparam+1] ;
     306           0 :         epar = fitparameters[iparam+2] ;
     307             : 
     308           0 :         efit[iDigit] += epar * ShowerShapeV2((Float_t)iphi - xpar,(Float_t)ieta - zpar) ;
     309           0 :         iparam += 3 ;
     310             :       }
     311             : 
     312           0 :     } else AliDebug(1,"Digit NULL part 2!");
     313             :     
     314             :   }//digit loop
     315             :   
     316             :   //**************************** part 3 *******************************************
     317             :   // Now create new RecPoints and fill energy lists with efit corrected to fluctuations
     318             :   // so that energy deposited in each cell is distributed between new clusters proportionally
     319             :   // to its contribution to efit
     320             :   
     321           0 :   Float_t * energiesList = iniTower->GetEnergiesList() ;
     322             :   Float_t ratio = 0. ;
     323             :   Float_t eDigit = 0. ;
     324             :   Int_t nSplittedClusters=(Int_t)nPar/3;
     325             :   
     326           0 :   Float_t * correctedEnergyList = new Float_t[nDigits*nSplittedClusters];
     327             :   //above - temporary table with energies after unfolding.
     328             :   //the order is following: 
     329             :   //first cluster <first cell - last cell>, 
     330             :   //second cluster <first cell - last cell>, etc.
     331             :   
     332             :   //**************************** sub-part 3.1 *************************************
     333             :   //If not the energy from a given cell in the cluster is divided in correct proportions 
     334             :   //in accordance to the other clusters and added to them and set to 0.
     335             :   
     336             :   //  cout<<"unfolding check here part 3.1"<<endl;
     337             : 
     338             :   iparam = 0 ;
     339           0 :   while(iparam < nPar )
     340             :   {
     341           0 :     xpar = fitparameters[iparam] ;
     342           0 :     zpar = fitparameters[iparam+1] ;
     343           0 :     epar = fitparameters[iparam+2] ;
     344             :     
     345           0 :     for(iDigit = 0 ; iDigit < nDigits ; iDigit ++)
     346             :     {
     347           0 :       digit = dynamic_cast<AliEMCALDigit*>( fDigitsArr->At( digitsList[iDigit] ) ) ;
     348           0 :       if(digit)
     349             :       {
     350           0 :         fGeom->GetCellIndex(digit->GetId(),iSupMod,iTower,iIphi,iIeta); 
     351           0 :         fGeom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
     352           0 :                                            iIphi, iIeta,iphi,ieta);
     353             :         
     354           0 :         EvalParsPhiDependence(digit->GetId(),fGeom);
     355             :        
     356           0 :         if(efit[iDigit]==0) 
     357             :         {//just for sure
     358           0 :           correctedEnergyList[iparam/3*nDigits+iDigit] = 0.;//correction here
     359           0 :           continue;
     360             :         }
     361             :         
     362           0 :         ratio = epar * ShowerShapeV2((Float_t)iphi - xpar,(Float_t)ieta - zpar) / efit[iDigit] ;
     363           0 :         eDigit = energiesList[iDigit] * ratio ;
     364             :         
     365             :         //add energy to temporary matrix
     366           0 :         correctedEnergyList[iparam/3*nDigits+iDigit] = eDigit;
     367             :         
     368           0 :       } else AliDebug(1,"NULL digit part 3");
     369             :     }//digit loop 
     370           0 :     iparam += 3 ;
     371             :   }//while
     372             :   
     373             :   //**************************** sub-part 3.2 *************************************
     374             :   //here we check if energy of the cell in the cluster after unfolding is above threshold. 
     375             :   //here we correct energy for each cell and cluster
     376             :   //  cout<<"unfolding check here part 3.2"<<endl;
     377             : 
     378             : 
     379             :   //here we have 3 possibilities
     380             :   //when after UF cell energy in cluster is below threshold:
     381             :   //1 - keep it associated to cluster - equivalent of threshold=0
     382             :   //2 - default - split (or add) energy of that cell into that cell in the other cluster(s)
     383             :   //3 - reject that cell from cluster - fraction energy in cell=0 - breaks energy conservation
     384             :   //Bool_t rejectBelowThreshold=kTRUE;//default option = 2 - split = kFALSE
     385             : 
     386           0 :   if(fThreshold > 0){//option 2 or 3
     387           0 :     if(fRejectBelowThreshold){//option 3
     388           0 :       for(iDigit = 0 ; iDigit < nDigits ; iDigit++){//digit loop
     389           0 :         for(iparam = 0 ; iparam < nPar ; iparam+=3){//param0 loop = energy loop
     390           0 :           if(correctedEnergyList[iparam/3*nDigits+iDigit] < fThreshold ) correctedEnergyList[iparam/3*nDigits+iDigit]=0.;
     391             :         }
     392             :       }
     393             :     }else{//option 2
     394             :       Float_t maximumEne=0.;
     395             :       Int_t maximumIndex=0;
     396             :       Bool_t isAnyBelowThreshold=kFALSE;
     397             :       //  Float_t Threshold=0.01;
     398           0 :       Float_t * energyFraction = new Float_t[nSplittedClusters];
     399             :       Int_t iparam2 = 0 ;
     400           0 :       for(iDigit = 0 ; iDigit < nDigits ; iDigit++){
     401             :         isAnyBelowThreshold=kFALSE;
     402             :         maximumEne=0.;
     403           0 :         for(iparam = 0 ; iparam < nPar ; iparam+=3){
     404           0 :           if(correctedEnergyList[iparam/3*nDigits+iDigit] < fThreshold ) isAnyBelowThreshold = kTRUE;
     405           0 :           if(correctedEnergyList[iparam/3*nDigits+iDigit] > maximumEne) 
     406             :             {
     407             :               maximumEne = correctedEnergyList[iparam/3*nDigits+iDigit];
     408             :               maximumIndex = iparam;
     409           0 :             }
     410             :         }//end of loop over clusters after unfolding
     411             :         
     412           0 :         if(!isAnyBelowThreshold) continue; //no cluster-cell below threshold 
     413             :         
     414           0 :         if(maximumEne < fThreshold) 
     415             :           {//add all cluster cells and put energy into max index, other set to 0
     416             :             maximumEne=0.;
     417           0 :             for(iparam = 0 ; iparam < nPar ; iparam+=3)
     418             :               {
     419           0 :                 maximumEne+=correctedEnergyList[iparam/3*nDigits+iDigit];
     420           0 :                 correctedEnergyList[iparam/3*nDigits+iDigit]=0;
     421             :               }
     422           0 :             correctedEnergyList[maximumIndex/3*nDigits+iDigit]=maximumEne;
     423           0 :             continue;
     424             :           }//end if
     425             :         
     426             :         //divide energy of cell below threshold in the correct proportion and add to other cells
     427             :         maximumEne=0.;//not used any more so use it for the energy sum 
     428           0 :         for(iparam = 0 ; iparam < nPar ; iparam+=3)
     429             :           {//calculate energy sum
     430           0 :             if(correctedEnergyList[iparam/3*nDigits+iDigit] < fThreshold) energyFraction[iparam/3]=0;
     431             :             else 
     432             :               {
     433           0 :                 energyFraction[iparam/3]=1.;
     434           0 :                 maximumEne+=correctedEnergyList[iparam/3*nDigits+iDigit];
     435             :               }
     436             :           }//end of loop over clusters after unfolding
     437           0 :         if(maximumEne>0.) {
     438           0 :           for(iparam = 0 ; iparam < nPar ; iparam+=3){//calculate fraction
     439           0 :             energyFraction[iparam/3] = energyFraction[iparam/3] * correctedEnergyList[iparam/3*nDigits+iDigit] / maximumEne;
     440             :           }
     441             :           
     442           0 :           for(iparam = 0 ; iparam < nPar ; iparam+=3)
     443             :             {//add energy from cells below threshold to others
     444           0 :               if(energyFraction[iparam/3]>0.) continue;
     445             :               else
     446             :                 {
     447           0 :                   for(iparam2 = 0 ; iparam2 < nPar ; iparam2+=3)
     448             :                     {
     449           0 :                       correctedEnergyList[iparam2/3*nDigits+iDigit] += (energyFraction[iparam2/3] * 
     450           0 :                                                                         correctedEnergyList[iparam/3*nDigits+iDigit]) ;
     451             :                     }//inner loop
     452           0 :                   correctedEnergyList[iparam/3*nDigits+iDigit] = 0.;
     453             :                 }
     454           0 :             }
     455             :         } else {
     456             :           //digit energy to be set to 0
     457           0 :           for(iparam = 0 ; iparam < nPar ; iparam+=3)
     458             :             {
     459           0 :               correctedEnergyList[iparam/3*nDigits+iDigit] = 0.;
     460             :             }
     461             :         }//correction for: is energy>0
     462             :         
     463             :       }//end of loop over digits
     464           0 :       delete[] energyFraction;
     465             :       
     466             :     }//end of option 2 or 3 
     467             :   } else {//option 1
     468             :     //do nothing
     469             :   }
     470             : 
     471             :   
     472             :   //**************************** sub-part 3.3 *************************************
     473             :   //here we add digits to recpoints with corrected energy
     474             :   //  cout<<"unfolding check here part 3.3"<<endl;
     475             : 
     476             :   Int_t newClusterIndex=0;
     477             :   iparam = 0 ;
     478           0 :   while(iparam < nPar )
     479             :   {
     480             :     AliEMCALRecPoint * recPoint = 0 ;
     481             :     
     482           0 :     if(nSplittedClusters >= list->GetSize())
     483           0 :       list->Expand(nSplittedClusters);
     484             :     
     485             :     //add recpoint
     486           0 :     (*list)[newClusterIndex] = new AliEMCALRecPoint("") ;
     487           0 :     recPoint = dynamic_cast<AliEMCALRecPoint *>( list->At(newClusterIndex) ) ;
     488             :     
     489           0 :     if(recPoint){//recPoint present -> good
     490           0 :       recPoint->SetNExMax(nSplittedClusters) ;//can be wrong number, to be corrected in outer method
     491             :       
     492           0 :       for(iDigit = 0 ; iDigit < nDigits ; iDigit ++) {
     493           0 :         digit = dynamic_cast<AliEMCALDigit*>( fDigitsArr->At( digitsList[iDigit] ) ) ;
     494           0 :         if(digit && correctedEnergyList[iparam/3*nDigits+iDigit]>0. ){
     495             :           //if(correctedEnergyList[iparam/3*nDigits+iDigit]<fThreshold) printf("Final E cell %f < %f\n",correctedEnergyList[iparam/3*nDigits+iDigit],fThreshold);
     496           0 :           recPoint->AddDigit( *digit, correctedEnergyList[iparam/3*nDigits+iDigit], kFALSE ) ; //FIXME, need to study the shared case
     497           0 :         } else {
     498           0 :           AliDebug(1,Form("NULL digit part3.3 or NULL energy=%f",correctedEnergyList[iparam/3*nDigits+iDigit]));
     499             :         }
     500             :       }//digit loop
     501             : 
     502           0 :       if(recPoint->GetMultiplicity()==0){//recpoint exists but no digits associated -> remove from list
     503           0 :         delete (*list)[newClusterIndex];
     504           0 :         list->RemoveAt(newClusterIndex);
     505           0 :         nSplittedClusters--;
     506           0 :         newClusterIndex--;//decrease cluster number
     507           0 :       }else {//recPoint exists and has digits associated -> very good increase number of clusters 
     508           0 :         AliDebug(5,Form("cluster %d, digit no %d, energy %f",iparam/3,(recPoint->GetDigitsList())[0],(recPoint->GetEnergiesList())[0]));
     509             :       }
     510             :       
     511             :     } else {//recPoint empty -> remove from list
     512           0 :       AliError("NULL RecPoint");
     513             :       //protection from recpoint with no digits
     514           0 :       delete (*list)[newClusterIndex];
     515           0 :       list->RemoveAt(newClusterIndex);
     516           0 :       nSplittedClusters--;
     517           0 :       newClusterIndex--;//decrease cluster number
     518             :     }
     519             : 
     520           0 :     iparam += 3 ;
     521           0 :     newClusterIndex++;
     522             :   }//while
     523             :   
     524           0 :   delete[] fitparameters ;
     525           0 :   delete[] efit ;
     526           0 :   delete[] correctedEnergyList ;
     527             : 
     528             : //  print 
     529           0 :   AliDebug(5,Form("  nSplittedClusters %d, fNumberOfECAClusters %d, newClusterIndex %d,list->Entries() %d\n",nSplittedClusters,fNumberOfECAClusters,newClusterIndex,list->GetEntriesFast() ));
     530             :   
     531             :   //  cout<<"end of unfolding check part 3.3"<<endl;
     532             :   return nSplittedClusters;
     533           0 : }
     534             : 
     535             : //____________________________________________________________________________
     536             : Bool_t AliEMCALUnfolding::UnfoldClusterV2(AliEMCALRecPoint * iniTower, 
     537             :                                           Int_t nMax, 
     538             :                                           AliEMCALDigit ** maxAt, 
     539             :                                           Float_t * maxAtEnergy)
     540             : {
     541             :   // Extended to whole EMCAL 
     542             :   // Performs the unfolding of a cluster with nMax overlapping showers 
     543             :   // Returns true if success (1->several clusters), otherwise false (fit failed)
     544             : 
     545           0 :   TObjArray *list =new TObjArray(2);//temporary object
     546           0 :   Int_t nUnfoldedClusters=UnfoldOneCluster(iniTower,nMax,maxAt,maxAtEnergy,list);
     547             : 
     548             :   // here we write new clusters from list to fRecPoints 
     549           0 :   AliDebug(5,Form("Number of clusters after unfolding %d",list->GetEntriesFast()));
     550             :   Int_t iDigit=0;
     551             :   AliEMCALDigit * digit = 0 ;
     552           0 :   for(Int_t i=0;i<list->GetEntriesFast();i++) {
     553             :     AliEMCALRecPoint * recPoint = 0 ;
     554             :     
     555           0 :     if(fNumberOfECAClusters >= fRecPoints->GetSize())
     556           0 :       fRecPoints->Expand(2*fNumberOfECAClusters) ;
     557             :     
     558             :     //add recpoint
     559           0 :     (*fRecPoints)[fNumberOfECAClusters] = new AliEMCALRecPoint("") ;//fNumberOfECAClusters-1 is old cluster before unfolding
     560           0 :     recPoint = dynamic_cast<AliEMCALRecPoint *>( fRecPoints->At(fNumberOfECAClusters) ) ;
     561           0 :                 AliEMCALRecPoint * rpUFOne = dynamic_cast<AliEMCALRecPoint *>(list->At(i)) ;
     562             :                 
     563           0 :     if( recPoint && rpUFOne ){//recPoint present -> good
     564             :       
     565           0 :                         recPoint->SetNExMax(list->GetEntriesFast()) ;
     566             :                         
     567           0 :       Int_t   *digitsList = rpUFOne->GetDigitsList();
     568           0 :       Float_t *energyList = rpUFOne->GetEnergiesList();
     569             : 
     570           0 :       if(!digitsList || ! energyList)
     571             :       {
     572           0 :         AliDebug(-1,"No digits index or energy available");
     573           0 :                                 delete (*fRecPoints)[fNumberOfECAClusters];
     574           0 :                                 fRecPoints->RemoveAt(fNumberOfECAClusters);
     575           0 :         continue;
     576             :       }
     577             :       
     578           0 :       AliDebug(5,Form("cluster %d, digit no %d, energy %f\n",i,digitsList[0],energyList[0]));
     579             : 
     580           0 :       for(iDigit = 0 ; iDigit < rpUFOne->GetMultiplicity(); iDigit ++) {
     581           0 :         digit = dynamic_cast<AliEMCALDigit*>( fDigitsArr->At( digitsList[iDigit] ) ) ;
     582           0 :         if(digit) recPoint->AddDigit( *digit, energyList[iDigit], kFALSE ) ; //FIXME, need to study the shared case
     583             :       }//digit loop
     584           0 :       fNumberOfECAClusters++ ; 
     585           0 :     } else {//recPoint empty -> remove from list
     586           0 :       AliError("NULL RecPoint");
     587           0 :       delete (*fRecPoints)[fNumberOfECAClusters];
     588           0 :       fRecPoints->RemoveAt(fNumberOfECAClusters);
     589             :     }
     590             : 
     591           0 :   }//loop over unfolded clusters
     592             :   
     593             :   //print energy of new unfolded clusters
     594           0 :   AliDebug(5,Form("  nUnfoldedClusters %d, fNumberOfECAClusters %d",nUnfoldedClusters,fNumberOfECAClusters ));
     595           0 :   for(Int_t inewclus=0; inewclus<nUnfoldedClusters;inewclus++){
     596           0 :                 AliEMCALRecPoint * rp = dynamic_cast<AliEMCALRecPoint *>(fRecPoints->At(fNumberOfECAClusters-1-inewclus));
     597           0 :     if(rp) AliDebug(5,Form("  Unfolded cluster %d E %f",inewclus, rp->GetEnergy() ));
     598             :   }
     599             : 
     600             :   //clear tables  
     601           0 :   list->SetOwner(kTRUE);
     602           0 :   list->Delete();
     603           0 :   delete list;
     604           0 :   if(nUnfoldedClusters>1) return kTRUE;
     605           0 :   return kFALSE;
     606           0 : }
     607             : 
     608             : 
     609             : 
     610             : //____________________________________________________________________________
     611             : Bool_t AliEMCALUnfolding::UnfoldClusterV2old(AliEMCALRecPoint * iniTower, 
     612             :                                           Int_t nMax, 
     613             :                                           AliEMCALDigit ** maxAt, 
     614             :                                           Float_t * maxAtEnergy)
     615             : {
     616             :   // Extended to whole EMCAL 
     617             :   // Performs the unfolding of a cluster with nMax overlapping showers 
     618             :   
     619           0 :   Int_t nPar = 3 * nMax ;
     620           0 :   Float_t * fitparameters = new Float_t[nPar] ;
     621             :   
     622           0 :   if (fGeom==0)
     623           0 :     AliFatal("Did not get geometry from EMCALLoader") ;
     624             :   
     625           0 :   Bool_t rv = FindFitV2(iniTower, maxAt, maxAtEnergy, nPar, fitparameters) ;
     626           0 :   if( !rv ) {
     627             :     // Fit failed, return (and remove cluster? - why? I leave the cluster)
     628           0 :     iniTower->SetNExMax(-1) ;
     629           0 :     delete[] fitparameters ;
     630           0 :     return kFALSE;
     631             :   }
     632             :   
     633             :   // create unfolded rec points and fill them with new energy lists
     634             :   // First calculate energy deposited in each sell in accordance with
     635             :   // fit (without fluctuations): efit[]
     636             :   // and later correct this number in acordance with actual energy
     637             :   // deposition
     638             :   
     639           0 :   Int_t nDigits = iniTower->GetMultiplicity() ;
     640           0 :   Float_t * efit = new Float_t[nDigits] ;//new fitted energy in cells
     641             :   Float_t xpar=0.,zpar=0.,epar=0.  ;//center of gravity in cell units
     642             :   
     643             :   AliEMCALDigit * digit = 0 ;
     644           0 :   Int_t * digitsList = iniTower->GetDigitsList() ;
     645             :   
     646           0 :   Int_t iSupMod =  0 ;
     647           0 :   Int_t iTower  =  0 ;
     648           0 :   Int_t iIphi   =  0 ;
     649           0 :   Int_t iIeta   =  0 ;
     650           0 :   Int_t iphi    =  0 ;//x direction
     651           0 :   Int_t ieta    =  0 ;//z direstion
     652             :   
     653             :   Int_t iparam = 0 ;
     654             :   Int_t iDigit = 0 ;
     655             :   
     656           0 :   for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
     657           0 :     digit = dynamic_cast<AliEMCALDigit*>( fDigitsArr->At(digitsList[iDigit] ) ) ;
     658           0 :     if(digit){
     659           0 :       fGeom->GetCellIndex(digit->GetId(),iSupMod,iTower,iIphi,iIeta); 
     660           0 :       fGeom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
     661           0 :                                          iIphi, iIeta,iphi,ieta);
     662           0 :       EvalParsPhiDependence(digit->GetId(),fGeom);
     663             :       
     664           0 :       efit[iDigit] = 0.;
     665             :       iparam = 0;
     666           0 :       while(iparam < nPar ){
     667           0 :         xpar = fitparameters[iparam] ;
     668           0 :         zpar = fitparameters[iparam+1] ;
     669           0 :         epar = fitparameters[iparam+2] ;
     670           0 :         iparam += 3 ;
     671             :         
     672           0 :         efit[iDigit] += epar * ShowerShapeV2((Float_t)iphi - xpar,(Float_t)ieta - zpar) ;
     673             :       }
     674           0 :     } else AliError("Digit NULL!");
     675             :     
     676             :   }//digit loop
     677             :   
     678             :   // Now create new RecPoints and fill energy lists with efit corrected to fluctuations
     679             :   // so that energy deposited in each cell is distributed between new clusters proportionally
     680             :   // to its contribution to efit
     681             :   
     682           0 :   Float_t * energiesList = iniTower->GetEnergiesList() ;
     683             :   Float_t ratio = 0 ;
     684             :   
     685             :   iparam = 0 ;
     686           0 :   while(iparam < nPar ){
     687           0 :     xpar = fitparameters[iparam] ;
     688           0 :     zpar = fitparameters[iparam+1] ;
     689           0 :     epar = fitparameters[iparam+2] ;
     690           0 :     iparam += 3 ;
     691             :     
     692             :     AliEMCALRecPoint * recPoint = 0 ;
     693             :     
     694           0 :     if(fNumberOfECAClusters >= fRecPoints->GetSize())
     695           0 :       fRecPoints->Expand(2*fNumberOfECAClusters) ;
     696             :     
     697             :     //add recpoint
     698           0 :     (*fRecPoints)[fNumberOfECAClusters] = new AliEMCALRecPoint("") ;
     699           0 :     recPoint = dynamic_cast<AliEMCALRecPoint *>( fRecPoints->At(fNumberOfECAClusters) ) ;
     700             :     
     701           0 :     if(recPoint){
     702             :       
     703           0 :       fNumberOfECAClusters++ ;
     704           0 :       recPoint->SetNExMax((Int_t)nPar/3) ;
     705             :       
     706             :       Float_t eDigit = 0. ;
     707           0 :       for(iDigit = 0 ; iDigit < nDigits ; iDigit ++){
     708           0 :         digit = dynamic_cast<AliEMCALDigit*>( fDigitsArr->At( digitsList[iDigit] ) ) ;
     709           0 :         if(digit){
     710           0 :           fGeom->GetCellIndex(digit->GetId(),iSupMod,iTower,iIphi,iIeta); 
     711           0 :           fGeom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
     712           0 :                                              iIphi, iIeta,iphi,ieta);
     713           0 :           EvalParsPhiDependence(digit->GetId(),fGeom);
     714           0 :           if(efit[iDigit]==0) continue;//just for sure
     715           0 :           ratio = epar * ShowerShapeV2((Float_t)iphi - xpar,(Float_t)ieta - zpar) / efit[iDigit] ;
     716           0 :           eDigit = energiesList[iDigit] * ratio ;
     717           0 :           recPoint->AddDigit( *digit, eDigit, kFALSE ) ; //FIXME, need to study the shared case
     718           0 :         } else AliError("NULL digit");
     719             :       }//digit loop 
     720           0 :     } else AliError("NULL RecPoint");
     721             :   }//while
     722             :   
     723           0 :   delete[] fitparameters ;
     724           0 :   delete[] efit ;
     725             :   
     726             :   return kTRUE;
     727           0 : }
     728             : 
     729             : 
     730             : //____________________________________________________________________________
     731             : Bool_t AliEMCALUnfolding::FindFitV2(AliEMCALRecPoint * recPoint, AliEMCALDigit ** maxAt, 
     732             :                                         const Float_t* maxAtEnergy,
     733             :                                         Int_t nPar, Float_t * fitparameters) const
     734             : {
     735             :   // Calls TMinuit to fit the energy distribution of a cluster with several maxima
     736             :   // The initial values for fitting procedure are set equal to the
     737             :   // positions of local maxima.       
     738             :   // Cluster will be fitted as a superposition of nPar/3
     739             :   // electromagnetic showers
     740             : 
     741           0 :   if (fGeom==0) AliFatal("Did not get geometry from EMCALLoader");
     742             :         
     743           0 :   if(!gMinuit){
     744             :     //    gMinuit = new TMinuit(100) ;//max 100 parameters
     745           0 :     if(nPar<30) gMinuit = new TMinuit(30);
     746           0 :     else gMinuit = new TMinuit(nPar) ;//max nPar parameters
     747             :     //
     748             :   } else {
     749           0 :     if(gMinuit->fMaxpar < nPar) {
     750           0 :       delete gMinuit;
     751           0 :       gMinuit = new TMinuit(nPar);
     752           0 :     }
     753             :   }
     754             : 
     755           0 :   gMinuit->mncler();                     // Reset Minuit's list of paramters
     756           0 :   gMinuit->SetPrintLevel(-1) ;           // No Printout
     757           0 :   gMinuit->SetFCN(AliEMCALUnfolding::UnfoldingChiSquareV2) ;
     758             :   // To set the address of the minimization function
     759           0 :   TList * toMinuit = new TList();
     760           0 :   toMinuit->AddAt(recPoint,0) ;
     761           0 :   toMinuit->AddAt(fDigitsArr,1) ;
     762           0 :   toMinuit->AddAt(fGeom,2) ;
     763             : 
     764           0 :   gMinuit->SetObjectFit(toMinuit) ;         // To tranfer pointer to UnfoldingChiSquare
     765             : 
     766             :   // filling initial values for fit parameters
     767             :   AliEMCALDigit * digit ;
     768             : 
     769           0 :   Int_t ierflg  = 0;
     770             :   Int_t index   = 0 ;
     771           0 :   Int_t nDigits = (Int_t) nPar / 3 ;
     772             : 
     773             :   Int_t iDigit ;
     774             : 
     775           0 :   Int_t iSupMod =  0 ;
     776           0 :   Int_t iTower  =  0 ;
     777           0 :   Int_t iIphi   =  0 ;
     778           0 :   Int_t iIeta   =  0 ;
     779           0 :   Int_t iphi    =  0 ;//x direction
     780           0 :   Int_t ieta    =  0 ;//z direstion
     781             : 
     782           0 :   for(iDigit = 0; iDigit < nDigits; iDigit++)
     783             :   {
     784           0 :     digit = maxAt[iDigit];
     785           0 :     if(!digit)
     786             :     {
     787           0 :       AliError("Null digit pointer");
     788           0 :       continue;
     789             :     }
     790             :     
     791           0 :     fGeom->GetCellIndex(digit->GetId(),iSupMod,iTower,iIphi,iIeta);
     792           0 :     fGeom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
     793           0 :                                        iIphi, iIeta,iphi,ieta);
     794             : 
     795           0 :     Float_t energy = maxAtEnergy[iDigit] ;
     796             : 
     797             :     //gMinuit->mnparm(index, "x",  iphi, 0.1, 0, 0, ierflg) ;//original
     798           0 :     gMinuit->mnparm(index, "x",  iphi, 0.05, 0, 0, ierflg) ;
     799           0 :     index++ ;
     800           0 :     if(ierflg != 0){
     801           0 :       Error("FindFit", "EMCAL Unfolding unable to set initial value for fit procedure: x=%d, param.id=%d, nMaxima=%d",iphi,index-1,nPar/3 ) ;
     802           0 :       toMinuit->Clear();
     803           0 :       delete toMinuit ;
     804           0 :       return kFALSE;
     805             :     }
     806             :     //gMinuit->mnparm(index, "z",  ieta, 0.1, 0, 0, ierflg) ;//original
     807           0 :     gMinuit->mnparm(index, "z",  ieta, 0.05, 0, 0, ierflg) ;
     808           0 :     index++ ;
     809           0 :     if(ierflg != 0){
     810           0 :       Error("FindFit", "EMCAL Unfolding unable to set initial value for fit procedure: z=%d, param.id=%d, nMaxima=%d", ieta, index-1,nPar/3) ;
     811           0 :       toMinuit->Clear();
     812           0 :       delete toMinuit ;
     813           0 :       return kFALSE;
     814             :     }
     815             :     //gMinuit->mnparm(index, "Energy",  energy , 0.05*energy, 0., 4.*energy, ierflg) ;//original
     816           0 :     gMinuit->mnparm(index, "Energy",  energy , 0.001*energy, 0., 5.*energy, ierflg) ;//was 0.05
     817           0 :     index++ ;
     818           0 :     if(ierflg != 0){
     819           0 :       Error("FindFit", "EMCAL Unfolding unable to set initial value for fit procedure: energy = %f, param.id=%d, nMaxima=%d", energy, index-1, nPar/3) ;
     820           0 :       toMinuit->Clear();
     821           0 :       delete toMinuit ;
     822           0 :       return kFALSE;
     823             :     }
     824           0 :   }
     825             : 
     826           0 :   Double_t p0 = 0.1 ; // "Tolerance" Evaluation stops when EDM = 0.0001*p0 ; 
     827             :                       // The number of function call slightly depends on it.
     828             :   //  Double_t p1 = 1.0 ;// par to gradient 
     829           0 :   Double_t p2 = 0.0 ;
     830             :   //  Double_t p3 = 3.0 ;
     831           0 :   gMinuit->mnexcm("SET STR", &p2, 0, ierflg) ;   // force TMinuit to reduce function calls
     832             :   //  gMinuit->mnexcm("SET GRA", &p1, 1, ierflg) ;   // force TMinuit to use my gradient
     833           0 :   gMinuit->SetMaxIterations(5);//was 5
     834           0 :   gMinuit->mnexcm("SET NOW", &p2 , 0, ierflg) ;  // No Warnings
     835             :   //gMinuit->mnexcm("SET PRI", &p3 , 3, ierflg) ;  // printouts
     836             : 
     837           0 :   gMinuit->mnexcm("MIGRAD", &p0, 0, ierflg) ;    // minimize
     838             :   //gMinuit->mnexcm("MINI", &p0, 0, ierflg) ;    // minimize
     839           0 :   if(ierflg == 4){  // Minimum not found
     840           0 :     AliDebug(1,"EMCAL Unfolding  Fit not converged, cluster abandoned " ) ;
     841           0 :     toMinuit->Clear();
     842           0 :     delete toMinuit ;
     843           0 :     return kFALSE ;
     844             :   }
     845           0 :   for(index = 0; index < nPar; index++){
     846           0 :     Double_t err = 0. ;
     847           0 :     Double_t val = 0. ;
     848           0 :     gMinuit->GetParameter(index, val, err) ;    // Returns value and error ofOA parameter index
     849           0 :     fitparameters[index] = val ;
     850           0 :   }
     851             : 
     852           0 :   toMinuit->Clear();
     853           0 :   delete toMinuit ;
     854             : 
     855           0 :   if(gMinuit->fMaxpar>30) delete gMinuit;
     856             : 
     857           0 :   return kTRUE;
     858             : 
     859           0 : }
     860             : 
     861             : //____________________________________________________________________________
     862             : Double_t  AliEMCALUnfolding::ShowerShapeV2(Double_t x, Double_t y)
     863             : { 
     864             :   // extended to whole EMCAL 
     865             :   // Shape of the shower
     866             :   // If you change this function, change also the gradient evaluation in ChiSquare()
     867             : 
     868           0 :   Double_t r = fgSSPars[7]*TMath::Sqrt(x*x+y*y);
     869           0 :   Double_t rp1  = TMath::Power(r, fgSSPars[1]) ;
     870           0 :   Double_t rp5  = TMath::Power(r, fgSSPars[5]) ;
     871           0 :   Double_t shape = fgSSPars[0]*TMath::Exp( -rp1 * (1. / (fgSSPars[2] + fgSSPars[3] * rp1) + fgSSPars[4] / (1 + fgSSPars[6] * rp5) ) ) ;
     872           0 :   return shape ;
     873             : }
     874             : 
     875             : //____________________________________________________________________________
     876             : void AliEMCALUnfolding::UnfoldingChiSquareV2(Int_t & nPar, Double_t * Grad,
     877             :                                              Double_t & fret,
     878             :                                              Double_t * x, Int_t iflag)
     879             : {
     880             :   // Calculates the Chi square for the cluster unfolding minimization
     881             :   // Number of parameters, Gradient, Chi squared, parameters, what to do
     882             :   
     883           0 :   TList * toMinuit = dynamic_cast<TList*>( gMinuit->GetObjectFit() ) ;
     884           0 :   if(toMinuit){
     885           0 :     AliEMCALRecPoint * recPoint = dynamic_cast<AliEMCALRecPoint*>( toMinuit->At(0) )  ;
     886           0 :     TClonesArray * digits = dynamic_cast<TClonesArray*>( toMinuit->At(1) )  ;
     887             :     // A bit buggy way to get an access to the geometry
     888             :     // To be revised!
     889           0 :     AliEMCALGeometry *geom = dynamic_cast<AliEMCALGeometry *>(toMinuit->At(2));
     890             :     
     891           0 :     if(recPoint && digits && geom){
     892             :       
     893           0 :       Int_t * digitsList     = recPoint->GetDigitsList() ;
     894             :       
     895           0 :       Int_t nOdigits = recPoint->GetDigitsMultiplicity() ;
     896             :       
     897           0 :       Float_t * energiesList = recPoint->GetEnergiesList() ;
     898             :       
     899           0 :       fret = 0. ;
     900             :       Int_t iparam = 0 ;
     901             :       
     902           0 :       if(iflag == 2)
     903           0 :         for(iparam = 0 ; iparam < nPar ; iparam++)
     904           0 :           Grad[iparam] = 0 ; // Will evaluate gradient
     905             :       
     906             :       Double_t efit = 0. ;
     907             :       
     908             :       AliEMCALDigit * digit ;
     909             :       Int_t iDigit ;
     910             :       
     911           0 :       Int_t iSupMod =  0 ;
     912           0 :       Int_t iTower  =  0 ;
     913           0 :       Int_t iIphi   =  0 ;
     914           0 :       Int_t iIeta   =  0 ;
     915           0 :       Int_t iphi    =  0 ;//x direction
     916           0 :       Int_t ieta    =  0 ;//z direstion
     917             :       
     918             :       
     919           0 :       for( iDigit = 0 ; iDigit < nOdigits ; iDigit++) {
     920           0 :         if(energiesList[iDigit]==0) continue;
     921             :         
     922           0 :         digit = dynamic_cast<AliEMCALDigit*>( digits->At( digitsList[iDigit] ) );
     923             :         
     924           0 :         if(digit){
     925           0 :           geom->GetCellIndex(digit->GetId(),iSupMod,iTower,iIphi,iIeta); 
     926           0 :           geom->GetCellPhiEtaIndexInSModule(iSupMod,iTower,
     927           0 :                                             iIphi, iIeta,iphi,ieta);
     928           0 :           EvalParsPhiDependence(digit->GetId(),geom);
     929             :           
     930           0 :           if(iflag == 2){  // calculate gradient
     931             :             Int_t iParam = 0 ;
     932             :             efit = 0. ;
     933           0 :             while(iParam < nPar ){
     934           0 :               Double_t dx = ((Float_t)iphi - x[iParam]) ;
     935           0 :               iParam++ ;
     936           0 :               Double_t dz = ((Float_t)ieta - x[iParam]) ;
     937           0 :               iParam++ ;
     938           0 :               efit += x[iParam] * ShowerShapeV2(dx,dz) ;
     939           0 :               iParam++ ;
     940             :             }
     941             :             
     942           0 :             Double_t sum = 2. * (efit - energiesList[iDigit]) / energiesList[iDigit] ; // Here we assume, that sigma = sqrt(E)
     943             :             iParam = 0 ;
     944           0 :             while(iParam < nPar ){
     945           0 :               Double_t xpar = x[iParam] ;
     946           0 :               Double_t zpar = x[iParam+1] ;
     947           0 :               Double_t epar = x[iParam+2] ;
     948             :               
     949           0 :               Double_t dr = fgSSPars[7]*TMath::Sqrt( ((Float_t)iphi - xpar) * ((Float_t)iphi - xpar) + ((Float_t)ieta - zpar) * ((Float_t)ieta - zpar) );
     950           0 :               Double_t shape = sum * ShowerShapeV2((Float_t)iphi - xpar,(Float_t)ieta - zpar) ;
     951           0 :               Double_t rp1  = TMath::Power(dr, fgSSPars[1]) ;
     952           0 :               Double_t rp5  = TMath::Power(dr, fgSSPars[5]) ;
     953             :               
     954           0 :               Double_t deriv = -2 * TMath::Power(dr,fgSSPars[1]-2.) * fgSSPars[7] * fgSSPars[7] * 
     955           0 :                 (fgSSPars[1] * ( 1/(fgSSPars[2]+fgSSPars[3]*rp1) + fgSSPars[4]/(1+fgSSPars[6]*rp5) ) - 
     956           0 :                  (fgSSPars[1]*fgSSPars[3]*rp1/( (fgSSPars[2]+fgSSPars[3]*rp1)*(fgSSPars[2]+fgSSPars[3]*rp1) ) + 
     957           0 :                   fgSSPars[4]*fgSSPars[5]*fgSSPars[6]*rp5/( (1+fgSSPars[6]*rp5)*(1+fgSSPars[6]*rp5) ) ) );
     958             :               
     959             :               //Double_t deriv =-1.33 * TMath::Power(dr,0.33)*dr * ( 1.57 / ( (1.57 + 0.0860 * r133) * (1.57 + 0.0860 * r133) )
     960             :               //                                                   - 0.55 / (1 + 0.000563 * r669) / ( (1 + 0.000563 * r669) * (1 + 0.000563 * r669) ) ) ;
     961             :               
     962           0 :               Grad[iParam] += epar * shape * deriv * ((Float_t)iphi - xpar) ;  // Derivative over x
     963             :               iParam++ ;
     964           0 :               Grad[iParam] += epar * shape * deriv * ((Float_t)ieta - zpar) ;  // Derivative over z
     965           0 :               iParam++ ;
     966           0 :               Grad[iParam] += shape ;                                  // Derivative over energy
     967           0 :               iParam++ ;
     968             :             }
     969           0 :           }
     970             :           efit = 0;
     971             :           iparam = 0 ;
     972             :           
     973           0 :           while(iparam < nPar ){
     974           0 :             Double_t xpar = x[iparam] ;
     975           0 :             Double_t zpar = x[iparam+1] ;
     976           0 :             Double_t epar = x[iparam+2] ;
     977           0 :             iparam += 3 ;
     978           0 :             efit += epar * ShowerShapeV2((Float_t)iphi - xpar,(Float_t)ieta - zpar) ;
     979             :           }
     980             :           
     981           0 :           fret += (efit-energiesList[iDigit])*(efit-energiesList[iDigit])/energiesList[iDigit] ;
     982             :           // Here we assume, that sigma = sqrt(E) 
     983           0 :         } else printf("AliEMCALUnfoding::UnfoldingChiSquareV2 - NULL digit!, nPar %d \n", nPar); // put nPar here to cheat coverity and rule checker
     984             :       } // digit loop
     985           0 :     } // recpoint, digits and geom not NULL
     986           0 :   }// List is not NULL
     987             :   
     988           0 : }
     989             : 
     990             : 
     991             : //____________________________________________________________________________
     992             : void AliEMCALUnfolding::SetShowerShapeParams(Double_t *pars){
     993           0 :   for(UInt_t i=0;i<7;++i)
     994           0 :     fgSSPars[i]=pars[i];
     995           0 :   if(pars[2]==0. && pars[3]==0.) fgSSPars[2]=1.;//to avoid dividing by 0
     996           0 : }
     997             : 
     998             : //____________________________________________________________________________
     999             : void AliEMCALUnfolding::SetPar5(Double_t *pars){
    1000           0 :   for(UInt_t i=0;i<3;++i)
    1001           0 :     fgPar5[i]=pars[i];
    1002           0 : }
    1003             : 
    1004             : //____________________________________________________________________________
    1005             : void AliEMCALUnfolding::SetPar6(Double_t *pars){
    1006           0 :   for(UInt_t i=0;i<3;++i)
    1007           0 :     fgPar6[i]=pars[i];
    1008           0 : }
    1009             : 
    1010             : //____________________________________________________________________________
    1011             : void AliEMCALUnfolding::EvalPar5(Double_t phi){
    1012             :   //
    1013             :   //Evaluate the 5th parameter of the shower shape function
    1014             :   //phi in degrees range (-10,10)
    1015             :   //
    1016             :   //fSSPars[5] = 12.31 - phi*0.007381 - phi*phi*0.06936;
    1017           0 :   fgSSPars[5] = fgPar5[0] + phi * fgPar5[1] + phi*phi * fgPar5[2];
    1018           0 : }
    1019             : 
    1020             : //____________________________________________________________________________
    1021             : void AliEMCALUnfolding::EvalPar6(Double_t phi){
    1022             :   //
    1023             :   //Evaluate the 6th parameter of the shower shape function
    1024             :   //phi in degrees range (-10,10)
    1025             :   //
    1026             :   //fSSPars[6] = 0.05452 + phi*0.0001228 + phi*phi*0.001361;
    1027           0 :   fgSSPars[6] = fgPar6[0] + phi * fgPar6[1] + phi*phi * fgPar6[2];
    1028           0 : }
    1029             : 
    1030             : //____________________________________________________________________________
    1031             : void AliEMCALUnfolding::EvalParsPhiDependence(Int_t absId, const AliEMCALGeometry *geom){
    1032             :   //
    1033             :   // calculate params p5 and p6 depending on the phi angle in global coordinate
    1034             :   // for the cell with given absId index
    1035             :   // output phiglob should be in range -10 to 10 degree
    1036             :   //
    1037           0 :   Double_t etaGlob = 0.;//eta in global c.s. - unused
    1038           0 :   Double_t phiGlob = 0.;//phi in global c.s. in radians
    1039           0 :   geom->EtaPhiFromIndex(absId, etaGlob, phiGlob);
    1040           0 :   if(phiGlob<0)phiGlob+=TMath::TwoPi();
    1041           0 :   phiGlob*=180./TMath::Pi();
    1042           0 :   phiGlob-=20.*(Int_t)(phiGlob/20.);
    1043           0 :   Int_t superModule=geom->GetSuperModuleNumber(absId);
    1044           0 :   if(superModule==10 || superModule==11 || superModule==18 || superModule==19) //sm 10,11,18,19 shift by 3.5 deg other 10 deg
    1045           0 :     phiGlob-=3.5;
    1046             :   else
    1047           0 :     phiGlob-=10.;
    1048             : 
    1049           0 :   EvalPar5(phiGlob);
    1050           0 :   EvalPar6(phiGlob);
    1051           0 : }
    1052             : 

Generated by: LCOV version 1.11