LCOV - code coverage report
Current view: top level - PHOS/PHOSbase - AliPHOSRawFitterv2.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 242 0.4 %
Date: 2016-06-14 17:26:59 Functions: 1 12 8.3 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 2007, ALICE Experiment at CERN, All rights reserved.      *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : /* $Id: $ */
      17             : 
      18             : // This class extracts the signal parameters (energy, time, quality)
      19             : // from ALTRO samples. Energy is in ADC counts, time is in time bin units.
      20             : // Class uses FastFitting algorithm to fit sample and extract time and Amplitude 
      21             : // and evaluate sample quality = (chi^2/NDF)/some parameterization providing 
      22             : // efficiency close to 100%
      23             : // 
      24             : // Typical use case:
      25             : //     AliPHOSRawFitter *fitter=new AliPHOSRawFitter();
      26             : //     fitter->SetChannelGeo(module,cellX,cellZ,caloFlag);
      27             : //     fitter->SetCalibData(fgCalibData) ;
      28             : //     fitter->Eval(sig,sigStart,sigLength);
      29             : //     Double_t amplitude = fitter.GetEnergy();
      30             : //     Double_t time      = fitter.GetTime();
      31             : //     Bool_t   isLowGain = fitter.GetCaloFlag()==0;
      32             : 
      33             : // Author: Dmitri Peressounko (after A.Pavlinov - see RAW/AliCaloFastAltroFitv0.cxx)
      34             : 
      35             : // --- ROOT system ---
      36             : #include "TArrayI.h"
      37             : #include "TList.h"
      38             : #include "TMath.h"
      39             : #include "TH1I.h"
      40             : #include "TF1.h"
      41             : #include "TCanvas.h"
      42             : #include "TFile.h"
      43             : #include "TROOT.h"
      44             : 
      45             : // --- AliRoot header files ---
      46             : #include "AliLog.h"
      47             : #include "AliPHOSCalibData.h"
      48             : #include "AliPHOSRawFitterv2.h"
      49             : #include "AliPHOSPulseGenerator.h"
      50             : 
      51          22 : ClassImp(AliPHOSRawFitterv2)
      52             : 
      53             : //-----------------------------------------------------------------------------
      54             : AliPHOSRawFitterv2::AliPHOSRawFitterv2():
      55           0 :   AliPHOSRawFitterv0(),
      56           0 :   fAlpha(0.1),fBeta(0.035),fMax(0) 
      57           0 : {
      58             :   //Default constructor.
      59           0 : }
      60             : 
      61             : //-----------------------------------------------------------------------------
      62             : AliPHOSRawFitterv2::~AliPHOSRawFitterv2()
      63           0 : {
      64             :   //Destructor.
      65           0 : }
      66             : 
      67             : //-----------------------------------------------------------------------------
      68             : AliPHOSRawFitterv2::AliPHOSRawFitterv2(const AliPHOSRawFitterv2 &phosFitter ):
      69           0 :   AliPHOSRawFitterv0(phosFitter),
      70           0 :   fAlpha(0.1),fBeta(0.035),fMax(0)
      71           0 : {
      72             :   //Copy constructor.
      73           0 : }
      74             : 
      75             : //-----------------------------------------------------------------------------
      76             : AliPHOSRawFitterv2& AliPHOSRawFitterv2::operator = (const AliPHOSRawFitterv2 & /*phosFitter*/)
      77             : {
      78             :   //Assignment operator.
      79           0 :   return *this;
      80             : }
      81             : 
      82             : //-----------------------------------------------------------------------------
      83             : Bool_t AliPHOSRawFitterv2::Eval(const UShort_t *signal, Int_t sigStart, Int_t sigLength)
      84             : {
      85             :   //Extract an energy deposited in the crystal,
      86             :   //crystal' position (module,column,row),
      87             :   //time and gain (high or low).
      88             :   //First collects sample, then evaluates it and if it has
      89             :   //reasonable shape, fits it with Gamma2 function and extracts 
      90             :   //energy and time.
      91             : 
      92             :   const Float_t maxEtoFit=5 ; //fit only samples above this energy, accept all samples (with good aRMS) below it
      93             :   const Float_t kBaseLine   = 1.0;
      94             :   const Int_t   kPreSamples = 10;
      95             : 
      96           0 :   fOverflow = kFALSE ;  
      97           0 :   fEnergy=0 ;
      98           0 :   if (fCaloFlag == 2 || fNBunches > 1) {
      99           0 :     fQuality = 150;
     100           0 :     return kTRUE;
     101             :   }
     102           0 :   if(fCaloFlag!=0 && fCaloFlag!=1){//Corrupted sample
     103           0 :     fQuality=200;
     104           0 :     fEnergy=0 ;
     105           0 :     return kTRUE;
     106             :   }
     107             : 
     108             :   //Evaluate pedestals 
     109             :   Float_t pedMean = 0;
     110             :   Float_t pedRMS  = 0;
     111             :   Int_t   nPed    = 0;
     112           0 :   for (Int_t i=sigLength-kPreSamples; i<sigLength; i++) {
     113           0 :     nPed++;
     114           0 :     pedMean += signal[i];
     115           0 :     pedRMS  += signal[i]*signal[i] ;
     116             :   }
     117             : 
     118           0 :   fEnergy = -111;
     119           0 :   fQuality= 999. ;
     120             :   Double_t pedestal = 0;
     121             : 
     122           0 :   if (fPedSubtract) {
     123           0 :     if (nPed > 0) {
     124           0 :       fPedestalRMS=(pedRMS - pedMean*pedMean/nPed)/nPed ;
     125           0 :       if(fPedestalRMS > 0.) 
     126           0 :         fPedestalRMS = TMath::Sqrt(fPedestalRMS) ;
     127           0 :       pedestal = (Double_t)(pedMean/nPed); // pedestal subtraction
     128             :     }
     129             :     else
     130           0 :       return kFALSE;
     131           0 :   }
     132             :   else {
     133             :     //take pedestals from DB
     134           0 :     pedestal = (Double_t) fAmpOffset ;
     135             :   }
     136             : 
     137             :   
     138             :   //calculate rough quality of the sample and check for overflow
     139             :   Int_t    maxAmp=0 ;
     140           0 :   Int_t    minAmp= signal[0] ;
     141             :   Int_t    nMax = 0 ; //number of points in plato
     142             :   Double_t aMean =0. ;
     143             :   Double_t aRMS  =0. ;
     144             :   Double_t wts   =0 ;
     145             :   Bool_t falling = kTRUE ; //Bad monotoneusly falling sample
     146             :   Bool_t rising = kTRUE ; //Bad monotoneusly riging sample
     147           0 :   for (Int_t i=0; i<sigLength; i++){
     148           0 :     if(signal[i] > pedestal){
     149           0 :       Double_t de = signal[i] - pedestal ;
     150           0 :       if(de > 1.) {
     151           0 :         aMean += de*i ;
     152           0 :         aRMS  += de*i*i ;
     153           0 :         wts   += de; 
     154           0 :       }
     155           0 :       if(signal[i] >  maxAmp){
     156             :         maxAmp = signal[i]; 
     157             :         nMax=0;
     158           0 :       }
     159           0 :       if(signal[i] == maxAmp){
     160           0 :         nMax++;
     161           0 :       }
     162           0 :       if(signal[i] <  minAmp)
     163           0 :         minAmp=signal[i] ;
     164           0 :       if(falling && i>0 && signal[i]<signal[i-1])
     165           0 :         falling=kFALSE ;
     166           0 :       if(rising && i>0 && signal[i]>signal[i-1])
     167           0 :         rising=kFALSE ;
     168           0 :     }
     169             :   }
     170             : 
     171           0 :   if(rising || falling){//bad "rising" or falling  sample
     172           0 :     fEnergy =    0. ;
     173           0 :     fTime   = 0. ; //-999. ;
     174           0 :     fQuality=  250. ;
     175           0 :     return kTRUE ;
     176             :   }
     177           0 :   if(maxAmp-minAmp<3 && maxAmp>7 && sigLength>20){ //bad flat sample
     178           0 :     fEnergy =    0. ;
     179           0 :     fTime   = 0; //-999. ;
     180           0 :     fQuality=  260. ;
     181           0 :     return kTRUE ;
     182             :   }
     183             : 
     184           0 :   fEnergy=Double_t(maxAmp)-pedestal ;
     185           0 :   if (fEnergy < kBaseLine) fEnergy = 0;
     186           0 :   fTime = sigStart-sigLength-3;
     187             : 
     188             :   //do not test quality of too soft samples
     189           0 :   if (wts > 0) {
     190           0 :     aMean /= wts; 
     191           0 :     aRMS   = aRMS/wts - aMean*aMean;
     192           0 :   }
     193           0 :   if (fEnergy <= maxEtoFit){
     194           0 :     if (aRMS < 2.) //sigle peak
     195           0 :       fQuality = 299. ;
     196             :     else
     197           0 :       fQuality =   0. ;
     198             :     //Evaluate time of signal arriving
     199           0 :     return kTRUE ;
     200             :   }
     201             : 
     202             :   //look for plato on the top of sample
     203           0 :   if (fEnergy>500 &&  //this is not fluctuation of soft sample
     204           0 :      nMax>2){ //and there is a plato
     205           0 :     fOverflow = kTRUE ;
     206           0 :   }
     207             :   
     208             : 
     209             :   //do not fit High Gain samples with overflow
     210           0 :   if(fCaloFlag==1 && fOverflow){
     211           0 :     fQuality = 99. ;
     212           0 :     return kTRUE;
     213             : 
     214             :   }
     215             : 
     216             :   //----Now fit sample with reasonable shape------
     217           0 :   TArrayD samples(sigLength); // array of sample amplitudes
     218           0 :   TArrayD times(sigLength); // array of sample time stamps
     219           0 :   for (Int_t i=0; i<sigLength; i++) {
     220           0 :     samples.AddAt(signal[i]-pedestal,sigLength-i-1);
     221           0 :     times.AddAt(double(i),i);
     222             :   }
     223             :       
     224           0 :   if(fMax==0)
     225           0 :     FindMax() ;
     226           0 :   if(!FindAmpT(samples,times)){
     227           0 :     if(AliLog::GetDebugLevel("PHOS","AliPHOSRawFitterv2")>3){
     228             :       goto plot ;
     229             :     }
     230             :     else{
     231           0 :       return kFALSE ;
     232             :     }
     233             :   }
     234           0 :   fEnergy*=fMax ;
     235           0 :   fTime += sigStart-sigLength-3;
     236             : 
     237             : 
     238             :   //Impose cut on quality
     239             : //  fQuality/=4. ;
     240           0 :   fQuality/=1.+0.005*fEnergy ;
     241             : 
     242             :   //Draw corrupted samples
     243           0 :   if(AliLog::GetDebugLevel("PHOS","AliPHOSRawFitterv2")>3){
     244           0 :     if(fEnergy > 50. ){
     245             :     plot:
     246           0 :       printf("Sample par: amp=%f,  t0=%f, Quality=%f \n",fEnergy,fTime,fQuality) ;
     247           0 :       TH1I * h = (TH1I*)gROOT->FindObjectAny("hSamples") ;
     248           0 :       if(!h) h = new TH1I("hSamples","Samples",65,0.,65.) ;
     249           0 :       h->Reset() ;
     250           0 :       for (Int_t i=0; i<sigLength; i++) {
     251           0 :         h->SetBinContent(i+1,float(samples.At(i))) ;
     252             :       }
     253             : //      TF1 * fffit = new TF1("fffit","[0]+[1]*((x-[2])/[3])^2*exp(2.-2.*(x-[2])/[3])",0.,200.) ;
     254           0 :       TF1 * fffit = new TF1("fffit","[0]*((x-[1])*(x-[1])*exp(-[2]*(x-[1]))+(x-[1])*exp(-[3]*(x-[1])))",0.,60.) ;
     255           0 :       fffit->SetParameters(fEnergy/fMax,fTime-(sigStart-sigLength-3),fAlpha,fBeta) ;
     256           0 :       fffit->SetLineColor(2) ;
     257           0 :       TCanvas * can = (TCanvas*)gROOT->FindObjectAny("cSamples") ;
     258           0 :       if(!can){
     259           0 :         can = new TCanvas("cSamples","cSamples",10,10,600,600) ;
     260           0 :         can->SetFillColor(0) ;
     261           0 :         can->SetFillStyle(0) ;
     262           0 :         can->Range(0,0,1,1);
     263           0 :         can->SetBorderSize(0);
     264             :       }
     265           0 :       can->cd() ;
     266             :   
     267           0 :       TPad * spectrum_1 = new TPad("spectrum_1", "spectrum_1",0.001,0.32,0.99,0.99);
     268           0 :       spectrum_1->Draw();
     269           0 :       spectrum_1->cd();
     270           0 :       spectrum_1->Range(0,0,1,1);
     271           0 :       spectrum_1->SetFillColor(0);
     272           0 :       spectrum_1->SetFillStyle(4000);
     273           0 :       spectrum_1->SetBorderSize(1);
     274           0 :       spectrum_1->SetBottomMargin(0.012);
     275           0 :       spectrum_1->SetTopMargin(0.03);
     276           0 :       spectrum_1->SetLeftMargin(0.10);
     277           0 :       spectrum_1->SetRightMargin(0.05);
     278             : 
     279           0 :       char title[155] ;
     280           0 :       snprintf(title,155,"Sample, mod=%d, x=%d, z=%d, Quality=%5.1f",fModule,fCellX,fCellZ,fQuality) ;
     281           0 :       h->SetTitle(title) ;
     282             : //      h->Fit(fffit,"","",0.,51.) ;
     283           0 :       h->Draw() ;
     284           0 :       fffit->Draw("same") ;
     285             : /*
     286             :       sprintf(title,"mod%d_x%d_z%d_HG_qu%4.1f",fModule,fCellX,fCellZ,fQuality) ;
     287             :       TFile fout("samples_bad.root","update") ;
     288             :       h->Write(title);
     289             :       fout.Close() ;
     290             : */
     291           0 :       can->cd() ;
     292           0 :       TPad *spectrum_2 = new TPad("spectrum_2", "spectrum_2",0.001,0.01,0.99,0.32);
     293           0 :       spectrum_2->SetFillColor(0) ;
     294           0 :       spectrum_2->SetFillStyle(0) ;
     295           0 :       spectrum_2->SetGridy() ;
     296           0 :       spectrum_2->Draw();
     297           0 :       spectrum_2->Range(0,0,1,1);
     298           0 :       spectrum_2->SetFillColor(0);
     299           0 :       spectrum_2->SetBorderSize(1);
     300           0 :       spectrum_2->SetTopMargin(0.01);
     301           0 :       spectrum_2->SetBottomMargin(0.25);
     302           0 :       spectrum_2->SetLeftMargin(0.10);
     303           0 :       spectrum_2->SetRightMargin(0.05);
     304           0 :       spectrum_2->cd() ;
     305             : 
     306           0 :       TH1I * hd = (TH1I*)gROOT->FindObjectAny("hSamplesDif") ;
     307           0 :       if(!hd) hd = new TH1I("hd","Samples",65,0.,65.) ;
     308           0 :       hd->Reset() ;
     309           0 :       for (Int_t i=0; i<sigLength; i++) {
     310           0 :         hd->SetBinContent(i+1,TMath::Max(-1023.,TMath::Min(1023.,samples.At(i)+pedestal-fffit->Eval(i)))) ;
     311             :       }
     312           0 :       hd->Draw();
     313             :  
     314           0 :       can->Update() ;
     315           0 :       printf("Press <enter> to continue\n") ;
     316           0 :       getchar();
     317             : 
     318             : 
     319           0 :       delete fffit ;
     320           0 :       delete spectrum_1 ;
     321           0 :       delete spectrum_2 ;
     322           0 :     }
     323             :   }
     324             :   
     325           0 :   return kTRUE;
     326           0 : }
     327             : //------------------------------------------------------------------
     328             : Bool_t AliPHOSRawFitterv2::FindAmpT(TArrayD samples, TArrayD times){
     329             : // makes fit
     330             : 
     331             :   const Int_t nMaxIter=50 ;   //Maximal number of iterations
     332             :   const Double_t epsdt = 1.e-3 ; //expected precision of t0 calculation
     333             : 
     334           0 :   Double_t dTime=times.At(0)-0.5 ; //Most probable Initial approximation
     335             : //printf(" start fit... \n") ;
     336             : 
     337           0 :   Int_t nPoints = samples.GetSize() ;
     338           0 :   Double_t dea=TMath::Exp(-fAlpha) ;
     339           0 :   Double_t deb=TMath::Exp(-fBeta) ;
     340             :   Double_t dt=1.,timeOld=dTime,dfOld=0. ; 
     341           0 :   for(Int_t iter=0; iter<nMaxIter; iter++){
     342             :     Double_t yy=0.;
     343             :     Double_t yf=0. ;
     344             :     Double_t ydf=0. ;
     345             :     Double_t yddf=0. ;
     346             :     Double_t ff=0. ;
     347             :     Double_t fdf=0. ;
     348             :     Double_t dfdf=0. ;
     349             :     Double_t fddf=0. ;
     350             :     Int_t nfit=0 ;
     351           0 :     Double_t aexp=TMath::Exp(-fAlpha*(times.At(0)-1.-dTime)) ;
     352           0 :     Double_t bexp=TMath::Exp(-fBeta*(times.At(0)-1.-dTime)) ;
     353           0 :     for(Int_t i=0; i<nPoints; i++){
     354           0 :       Double_t t= times.At(i)-dTime ;
     355           0 :       aexp*=dea ;
     356           0 :       bexp*=deb ;
     357           0 :       if(t<0.) continue ;
     358           0 :       Double_t y=samples.At(i) ;
     359           0 :       if(y<=fAmpThreshold)
     360           0 :         continue ;
     361           0 :       nfit++ ;
     362           0 :       Double_t at=fAlpha*t ;
     363           0 :       Double_t bt = fBeta*t ;
     364           0 :       Double_t phi=t*(t*aexp+bexp) ;
     365           0 :       Double_t dphi=t*aexp*(2.-at)+(1.-bt)*bexp ;
     366           0 :       Double_t ddphi=aexp*(2.-4.*at+at*at)+bexp*fBeta*(bt-2.) ;
     367           0 :       yy+=y*y ;
     368           0 :       yf+=y*phi ;
     369           0 :       ydf+=y*dphi ;
     370           0 :       yddf+=y*ddphi ;
     371           0 :       ff+=phi*phi ;
     372           0 :       fdf+=phi*dphi ;
     373           0 :       dfdf+=dphi*dphi ;
     374           0 :       fddf+=phi*ddphi ;
     375           0 :     }
     376             : 
     377           0 :     if(ff<1.e-09||nfit==0 ){
     378           0 :       fQuality=199 ;
     379           0 :       return kFALSE ;
     380             :     }
     381           0 :     Double_t f=ydf*ff-yf*fdf ;     //d(chi2)/dt
     382           0 :     Double_t df=yf*(dfdf+fddf)-yddf*ff-ydf*fdf;
     383           0 :     if(df<=0.){ //we are too far from the root. In the wicinity of root df>0
     384           0 :       if(iter!=0 && dfOld>0.){//If at previous step df was OK, just reduce step size
     385           0 :         dt*=0.5 ;
     386           0 :         dTime=timeOld+dt ;  
     387           0 :         continue ;
     388             :       }
     389           0 :       if(f<0){ //f<0 => dTime is too small and we still do not know root region
     390           0 :         dTime+=2. ;
     391           0 :         continue ;
     392             :       }
     393             :       else{ //dTime is too large, we are beyond the root region
     394           0 :         dTime-=2. ;
     395           0 :         continue ;
     396             :       }
     397             :     }
     398           0 :     dt=-f/df ; 
     399           0 :     if(TMath::Abs(dt)<epsdt){
     400           0 :       fQuality=(yy-yf*yf/ff)/nfit ;
     401           0 :       fEnergy=yf/ff ;  //ff!=0 already tested
     402           0 :       fTime=dTime ;
     403           0 :       return kTRUE ;
     404             :     }
     405             :     //In some cases time steps are huge (derivative ~0)
     406           0 :     if(dt>10.) dt=10. ;   //restrict step size
     407           0 :     if(dt<-10.) dt=-5.3 ; //this restriction should be asimmetric to avoid jumping from one point to another
     408             :     timeOld=dTime ;  //remember current position for the case
     409             :     dfOld=df ;       //of reduction of dt step size
     410           0 :     dTime+=dt ;
     411             : 
     412           0 :     if(dTime>100. || dTime<-30.){ //this is corrupted sample, do not spend time improving accuracy.
     413           0 :       fQuality=(yy-yf*yf/ff)/nfit ;
     414           0 :       fEnergy=yf/ff ;  //ff!=0 already tested
     415           0 :       fTime=dTime ;
     416           0 :       return kFALSE ;
     417             :     }
     418             : 
     419           0 :   }
     420             :   //failed to find a root, too many iterations
     421           0 :   fQuality=99.;
     422           0 :   fEnergy=0 ; 
     423           0 :   return kFALSE ;
     424           0 : }
     425             : //_________________________________________
     426             : void AliPHOSRawFitterv2::FindMax(){
     427             :   //Finds maxumum of currecnt parameterization
     428           0 :   Double_t t=2./fAlpha ;
     429           0 :   fMax = t*t*TMath::Exp(-fAlpha*t)+t*TMath::Exp(-fBeta*t) ;
     430             :   Double_t dt=15 ;
     431           0 :   while(dt>0.01){
     432           0 :      Double_t dfdt=(2.*t-fAlpha*t*t)*TMath::Exp(-fAlpha*t)+(1.-fBeta*t)*TMath::Exp(-fBeta*t) ;
     433           0 :      if(dfdt>0.)
     434           0 :         t+=dt ;
     435             :      else
     436           0 :        t-=dt ;
     437           0 :      Double_t maxNew = t*t*TMath::Exp(-fAlpha*t)+t*TMath::Exp(-fBeta*t) ;
     438           0 :      if(maxNew>fMax)
     439           0 :         fMax=maxNew ;
     440             :      else{
     441           0 :        dt/=2 ;
     442           0 :        if(dfdt<0.)
     443           0 :          t+=dt ;
     444             :        else
     445           0 :         t-=dt ;
     446             :      }
     447             :   }   
     448           0 : }
     449             :  

Generated by: LCOV version 1.11