CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CalibCalorimetry/EcalLaserAnalyzer/src/PulseFitWithFunction.cc

Go to the documentation of this file.
00001 /* 
00002  *  \class PulseFitWithFunction
00003  *
00004  *  $Date: 2012/02/09 10:08:09 $
00005  *  \author: Patrick Jarry - CEA/Saclay
00006  */
00007 
00008 
00009 // File PulseFitWithFunction.cxx
00010 // ===========================================================
00011 // ==                                                       ==
00012 // ==     Class for a function fit method                   ==
00013 // ==                                                       ==
00014 // ==  Date:   July 17th 2003                               ==
00015 // ==  Author: Patrick Jarry                                ==
00016 // ==                                                       ==
00017 // ==                                                       ==
00018 // ===========================================================
00019 
00020 #include <CalibCalorimetry/EcalLaserAnalyzer/interface/PulseFitWithFunction.h>
00021 
00022 #include <iostream>
00023 #include "TMath.h"
00024 
00025 //ClassImp(PulseFitWithFunction)
00026 
00027 
00028 // Constructor...
00029 PulseFitWithFunction::PulseFitWithFunction()
00030 { 
00031  
00032   fNsamples               =  0;
00033   fNum_samp_bef_max       =  0;
00034   fNum_samp_after_max     =  0;
00035 }
00036 
00037 // Destructor
00038 PulseFitWithFunction::~PulseFitWithFunction()
00039 { 
00040 }
00041 
00042 // Initialisation
00043 
00044 void PulseFitWithFunction::init(int n_samples,int samplb,int sampla,int niter,double alfa,double beta)
00045 {
00046   //printf("\n");
00047   //printf(" =========================================================\n");
00048   //printf(" ==     Initialising the function fit method            ==\n");
00049   //printf(" ==          PulseFitWithFunction::init                 ==\n");
00050   //printf(" ==                                                     ==\n");
00051 
00052   
00053   fNsamples   = n_samples ;
00054   fAlpha_laser = alfa;
00055   fBeta_laser = beta ;
00056   fAlpha_beam = 0.98 ;
00057   fBeta_beam = 2.04 ;
00058   fNb_iter = niter ;
00059   fNum_samp_bef_max = samplb ;
00060   fNum_samp_after_max = sampla  ;
00061   //printf(" ==  # samples used = %3d                               ==\n",fNsamples);
00062   //printf(" ==  #sample before max= %1d and #sample after maximum= %1d ==\n",fNum_samp_bef_max,fNum_samp_after_max);
00063   //printf(" ==           alpha= %5.4f       beta= %5.4f          ==\n",fAlpha_laser,fBeta_laser);
00064   //printf(" =========================================================\n\n");
00065   return ;
00066  }
00067 
00068 // Compute the amplitude using as input the Crystaldata  
00069 double PulseFitWithFunction::doFit(double *adc)
00070 {
00071   double parout[4]; // amp_max ;
00072     //double amp_parab , tim_parab ;
00073   double chi2;
00074   //int imax ;
00075 //
00076 // first  one has to get starting point first with parabolic fun// //  
00077   Fit_parab(&adc[0],3,fNsamples,parout) ;
00078   amp_parab = parout[0] ;
00079   tim_parab = parout[1] ;
00080   imax = (int)parout[2] ;
00081   amp_max = parout[3] ;
00082   //printf("amp_parab= %f tim_parab=%f amp_max=%f imax=%d\n",amp_parab,tim_parab,amp_max,imax); 
00083   fNumber_samp_max=imax ;
00084 //
00085   
00086   if(amp_parab < 1.) {
00087      tim_parab = (double)imax ;
00088       amp_parab = amp_max ;
00089   }
00090 //
00091   fValue_tim_max= tim_parab ;
00092   fFunc_max= amp_parab ;
00093   fTim_max=tim_parab ;
00094 
00095 //  here to fit maximum amplitude and time of arrival ...
00096 
00097   chi2 = Fit_electronic(0,&adc[0],8.) ;
00098                                    // adc is an array to be filled with samples
00099                                    // 0 is for Laser (1 for electron)  
00100                                    // 8 is for sigma of pedestals 
00101                                    // which (can be computed)
00102 
00103 
00104   //  double amplitude = fAmp_fitted_max ; // amplitude fitted 
00105   // double time = fTim_fitted_max ; // time fitted
00106 
00107  
00108 
00109   return chi2 ; // return amplitude fitted
00110 
00111 }
00112 
00113 //-----------------------------------------------------------------------
00114 //----------------------------------------------------------------------
00115 
00116 /*************************************************/
00117 double PulseFitWithFunction::Fit_electronic(int data , double* adc_to_fit , double sigmas_sample) {
00118   // fit electronic function from simulation
00119   // parameters fAlpha and fBeta are fixed and fit is providing
00120   // the maximum amplitude ( fAmp_fitted_max ) and the time of
00121   // the maximum amplitude ( fTim_fitted_max) 
00122   // initialization of parameters
00123   double chi2=0;
00124   double d_alpha, d_beta ;
00125   // first initialize parameters fAlpha and fBeta ( depending of beam or laser)
00126   fAlpha = fAlpha_laser ;
00127   fBeta = fBeta_laser ;
00128   if(data == 1) { 
00129     fAlpha = fAlpha_beam ;
00130     fBeta = fBeta_beam ;
00131   }
00132   //
00133   fAmp_fitted_max = 0. ;
00134   fTim_fitted_max = 0. ;
00135   double un_sur_sigma = 1./fSigma_ped ;
00136   double variation_func_max = 0. ;
00137   double variation_tim_max = 0. ;
00138   //
00139   if(fValue_tim_max > 20. || fValue_tim_max  < 3.) {
00140           fValue_tim_max = fNumber_samp_max ;
00141   }
00142   int num_fit_min =(int)(fValue_tim_max - fNum_samp_bef_max) ;
00143   int num_fit_max =(int)(fValue_tim_max + fNum_samp_after_max) ;
00144   //
00145 
00146   if( sigmas_sample > 0. ) un_sur_sigma = 1./sigmas_sample;
00147   else un_sur_sigma = 1.;
00148 
00149   double func,delta ;
00150   //          Loop on iterations        
00151   for (int iter=0 ; iter < fNb_iter ; iter ++) {
00152    
00153     //          initialization inside iteration loop !
00154     chi2 = 0. ;
00155     double d11 = 0. ;
00156     double d12 = 0. ;
00157     double d22 = 0. ;
00158     double z1 = 0. ;
00159     double z2 = 0. ;
00160     fFunc_max += variation_func_max ;
00161     fTim_max += variation_tim_max ;
00162     int nsamp_used = 0 ;
00163     //
00164    
00165     // Then we loop on samples to be fitted
00166 
00167 
00168     for( int i = num_fit_min ; i < num_fit_max+1 ; i++) {
00169       // calculate function to be fitted
00170      
00171       func = Electronic_shape( (double)i  ) ;
00172       
00173       // then calculate derivatives of function to be fitted
00174       double dt =(double)i - fTim_max ;
00175       double alpha_beta = fAlpha*fBeta  ;
00176      
00177      if(dt > -alpha_beta)  {      
00178       double dt_sur_beta = dt/fBeta ;
00179          
00180       double variable = (double)1. + dt/alpha_beta ;
00181           double expo = TMath::Exp(-dt_sur_beta) ;       
00182          
00183           double puissance = TMath::Power(variable,fAlpha) ;
00184       d_alpha=un_sur_sigma*puissance*expo ;
00185       d_beta=fFunc_max*d_alpha*dt_sur_beta/(alpha_beta*variable) ;
00186      }
00187       else {
00188         continue ;
00189      }
00190      
00191       nsamp_used ++ ; // number of samples used inside the fit
00192       // compute matrix elements D (symetric --> d12 = d21 )
00193       d11 += d_alpha*d_alpha ;
00194       d12 += d_alpha*d_beta ;
00195       d22 += d_beta*d_beta ;
00196       // compute delta
00197       delta = (adc_to_fit[i]-func)*un_sur_sigma ;
00198       // compute vector elements Z
00199       z1 += delta*d_alpha ;
00200       z2 += delta*d_beta ;
00201       chi2 += delta * delta ;
00202     } //             end of loop on samples  
00203     double denom = d11*d22-d12*d12 ;
00204     if(denom == 0.) {
00205       //printf( "attention denom = 0 signal pas fitte \n") ;
00206       return 101 ;
00207     }
00208     if(nsamp_used < 3) {
00209       //printf( "Attention nsamp = %d ---> no function fit provided \n",nsamp_used) ;
00210       return 102 ;
00211     }
00212     // compute variations of parameters fAmp_max and fTim_max 
00213     variation_func_max = (z1*d22-z2*d12)/denom ;
00214     variation_tim_max = (-z1*d12+z2*d11)/denom ;
00215     chi2 = chi2/((double)nsamp_used - 2.) ;
00216   } //      end of loop on iterations       
00217   // results of the fit are calculated 
00218   fAmp_fitted_max = fFunc_max + variation_func_max ;
00219   fTim_fitted_max = fTim_max + variation_tim_max ;
00220   //
00221   return chi2 ;
00222 }
00223 
00224 //-----------------------------------------------------------------------
00225 //----------------------------------------------------------------------
00226 
00227 double  PulseFitWithFunction::Electronic_shape(double tim)
00228 {
00229   // electronic function (from simulation) to fit ECAL pulse shape
00230   double func_electronic,dtsbeta,variable,puiss;
00231   double albet = fAlpha*fBeta ;
00232   if( albet <= 0 ) return( (Double_t)0. );
00233   double dt = tim-fTim_max ;
00234   if(dt > -albet)  {
00235     dtsbeta=dt/fBeta ;
00236     variable=1.+dt/albet ;
00237         puiss=TMath::Power(variable,fAlpha);
00238         func_electronic=fFunc_max*puiss*TMath::Exp(-dtsbeta);
00239   }
00240   else func_electronic = 0. ;
00241   //
00242   return func_electronic ;
00243 }
00244 void PulseFitWithFunction::Fit_parab(Double_t *ampl,Int_t nmin,Int_t nmax,Double_t *parout)
00245 {
00246 /* Now we calculate the parabolic adjustement in order to get        */
00247 /*    maximum and time max                                           */
00248  
00249   double denom,dt,amp1,amp2,amp3 ;
00250   double ampmax = 0. ;                          
00251   int imax = 0 ;
00252   int k ;
00253 /*
00254                                                                    */     
00255   for ( k = nmin ; k < nmax ; k++) {
00256     //printf("ampl[%d]=%f\n",k,ampl[k]);
00257     if (ampl[k] > ampmax ) {
00258       ampmax = ampl[k] ;
00259       imax = k ;
00260     }
00261   }
00262         amp1 = ampl[imax-1] ;
00263         amp2 = ampl[imax] ;
00264         amp3 = ampl[imax+1] ;
00265         denom=2.*amp2-amp1-amp3  ;
00266 /*                                                           */       
00267         if(denom>0.){
00268           dt =0.5*(amp3-amp1)/denom  ;
00269         }
00270         else {
00271           //printf("denom =%f\n",denom)  ;
00272           dt=0.5  ;
00273         }
00274 /*                                                                   */        
00275 /* ampmax correspond au maximum d'amplitude parabolique et dt        */
00276 /* decalage en temps par rapport au sample maximum soit k + dt       */
00277                 
00278         parout[0] =amp2+(amp3-amp1)*dt*0.25 ;
00279         parout[1] = (double)imax + dt ;
00280         parout[2] = (double)imax ;
00281         parout[3] = ampmax ;
00282 return ;
00283 }