CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 /* 
00002  *  \class PulseFitWithShape
00003  *
00004  *  $Date: 2013/04/19 22:19:23 $
00005  *  \author: Julie Malcles - CEA/Saclay
00006  */
00007 
00008 
00009 // File PulseFitWithShape.cxx
00010 
00011 #include <CalibCalorimetry/EcalLaserAnalyzer/interface/PulseFitWithShape.h>
00012 
00013 #include <iostream>
00014 #include "TMath.h"
00015 #include <cmath>
00016 
00017 //ClassImp(PulseFitWithShape)
00018 
00019 
00020 // Constructor...
00021 PulseFitWithShape::PulseFitWithShape()
00022 { 
00023  
00024   fNsamples               =  0;
00025   fNsamplesShape          =  0;
00026   fNum_samp_bef_max       =  0;
00027   fNum_samp_after_max     =  0;
00028   fNoise                  = 0.0;
00029 }
00030 
00031 // Destructor
00032 PulseFitWithShape::~PulseFitWithShape()
00033 { 
00034 }
00035 
00036 // Initialisation
00037 
00038 void PulseFitWithShape::init(int n_samples,int samplb,int sampla,int niter,int n_samplesShape, const std::vector<double>& shape, double nois)
00039 {
00040  
00041   fNsamples   = n_samples ;
00042   fNsamplesShape   = n_samplesShape ;
00043   fNb_iter = niter ;
00044   fNum_samp_bef_max = samplb ;
00045   fNum_samp_after_max = sampla  ;
00046 
00047 
00048   if( fNsamplesShape < fNum_samp_bef_max+fNum_samp_after_max+1){
00049     std::cout<<"PulseFitWithShape::init: Error! Configuration samples in fit greater than total number of samples!" << std::endl;
00050   }
00051 
00052   for(int i=0;i<fNsamplesShape;i++){
00053     pshape.push_back(shape[i]);
00054     dshape.push_back(0.0);
00055   }
00056 
00057   fNoise=nois;
00058   return ;
00059  }
00060 
00061 // Compute the amplitude using as input the Crystaldata  
00062 
00063 double PulseFitWithShape::doFit(double *adc, double *cova)
00064 {
00065 
00066   // xpar = fit paramaters
00067   //     [0] = signal amplitude
00068   //     [1] = residual pedestal
00069   //     [2] = clock phase
00070 
00071   bool useCova=true;
00072   if(cova==0) useCova=false;
00073 
00074   double xpar[3]; 
00075   double chi2;
00076 
00077   fAmp_fitted_max = 0. ;
00078   fTim_fitted_max = 0. ;
00079   
00080   // for now don't fit pedestal
00081 
00082   xpar[1]=0.0;
00083   
00084   // Sample noise. If the cova matrix is defined, use it :
00085 
00086   double noise=fNoise;
00087   //if(cova[0] > 0.) noise=1./sqrt(cova[0]);
00088   
00089   xpar[0]=0.;
00090   xpar[2]=0.;
00091 
00092 
00093   // first locate max:
00094 
00095   int imax=0;
00096   double amax=0.0;
00097   for(int i=0; i<fNsamples; i++){
00098     if (adc[i]>amax){
00099       amax=adc[i];
00100       imax=i;
00101     }
00102   }
00103   
00104   // Shift pulse shape and calculate its derivative:
00105   
00106   double qms=0.;
00107   int ims=0;
00108   
00109   // 1) search for maximum
00110   
00111   for(int is=0; is<fNsamplesShape; is++){
00112     if(pshape[is] > qms){
00113       qms=pshape[is];
00114       ims=is;
00115     }
00116 
00117   // 2) compute shape derivative :
00118     
00119     if(is < fNsamplesShape-2)
00120       dshape[is]= (pshape[is+2]-pshape[is])*12.5;
00121     else
00122       dshape[is]=dshape[is-1]; 
00123   }
00124 
00125   // 3) compute pol2 max
00126 
00127   double sq1=pshape[ims-1];
00128   double sq2=pshape[ims];
00129   double sq3=pshape[ims+1];
00130   
00131   double a2=(sq3+sq1)/2.0-sq2;
00132   double a1=sq2-sq1+a2*(1-2*ims);
00133  
00134   
00135   double t_ims=0;
00136   if(a2!=0) t_ims=-a1/(2.0*a2);
00137 
00138 
00139   // Starting point of the fit : qmax and tmax given by a
00140   // P2 fit on 3 max samples.
00141   
00142   double qm=0.;
00143   int im=0;
00144  
00145   int nsamplef=fNum_samp_bef_max + fNum_samp_after_max +1 ; // number of samples used in the fit
00146   int nsampleo=imax-fNum_samp_bef_max;  // first sample number = sample max-fNum_samp_bef_max 
00147   
00148   for(int is=0; is<nsamplef; is++){
00149 
00150     if(adc[is+nsampleo] > qm){
00151       qm=adc[is+nsampleo];
00152       im=nsampleo+is;
00153     }
00154   }
00155 
00156   double tm;
00157   if(qm > 5.*noise){
00158     if(im >= nsamplef+nsampleo) im=nsampleo+nsamplef-1;
00159     double q1=adc[im-1];
00160     double q2=adc[im];
00161     double q3=adc[im+1];
00162     double y2=(q1+q3)/2.-q2;
00163     double y1=q2-q1+y2*(1-2*im);
00164     double y0=q2-y1*(double)im-y2*(double)(im*im);
00165     tm=-y1/2./y2;
00166     xpar[0]=y0+y1*tm+y2*tm*tm;
00167     xpar[2]=(double)ims/25.-tm;
00168   }
00169 
00170   double chi2old=999999.;
00171   chi2=99999.;
00172   int nsfit=nsamplef;
00173   int iloop=0;
00174   int nloop=fNb_iter;
00175   if(qm <= 5*noise)nloop=1; // Just one iteration for very low signal
00176 
00177   double *resi;
00178   resi= new double[fNsamples];  
00179   for (int j=0;j<fNsamples;j++) resi[j]=0;
00180 
00181   while(std::fabs(chi2old-chi2) > 0.1 && iloop < nloop)
00182     {
00183       iloop++;
00184       chi2old=chi2;
00185       
00186       double c=0.;
00187       double y1=0.;
00188       double s1=0.;
00189       double s2=0.;
00190       double ys1=0.;
00191       double sp1=0.;
00192       double sp2=0.;
00193       double ssp=0.;
00194       double ysp=0.;
00195       
00196       for(int is=0; is<nsfit; is++)
00197         {
00198           int iis=is;
00199           iis=is+nsampleo;
00200           
00201           double t1=(double)iis+xpar[2];
00202           double xbin=t1*25.;
00203           int ibin1=(int)xbin;
00204           
00205           if(ibin1 < 0) ibin1=0;
00206 
00207           double amp1,amp11,amp12,der1,der11,der12;
00208 
00209           if(ibin1 <= fNsamplesShape-2){     // Interpolate shape values to get the right number :
00210             
00211             int ibin2=ibin1+1;
00212             double xfrac=xbin-ibin1;
00213             amp11=pshape[ibin1];
00214             amp12=pshape[ibin2];
00215             amp1=(1.-xfrac)*amp11+xfrac*amp12;
00216             der11=dshape[ibin1];
00217             der12=dshape[ibin2];
00218             der1=(1.-xfrac)*der11+xfrac*der12;
00219             
00220           }else{                            // Or extraoplate if we are outside the array :
00221             
00222             amp1=pshape[fNsamplesShape-1]+dshape[fNsamplesShape-1]*
00223               (xbin-double(fNsamplesShape-1))/25.;
00224             der1=dshape[fNsamplesShape-1];
00225           }
00226           
00227           if( useCova ){     // Use covariance matrix: 
00228             for(int js=0; js<nsfit; js++)
00229               {
00230                 int jjs=js;
00231                 jjs+=nsampleo;
00232                 
00233                 t1=(double)jjs+xpar[2];
00234                 xbin=t1*25.;
00235                 ibin1=(int)xbin;
00236                 if(ibin1 < 0) ibin1=0;
00237                 if(ibin1 > fNsamplesShape-2)ibin1=fNsamplesShape-2;
00238                 int ibin2=ibin1+1;
00239                 double xfrac=xbin-ibin1;
00240                 amp11=pshape[ibin1];
00241                 amp12=pshape[ibin2];
00242                 double amp2=(1.-xfrac)*amp11+xfrac*amp12;
00243                 der11=dshape[ibin1];
00244                 der12=dshape[ibin2];
00245                 double der2=(1.-xfrac)*der11+xfrac*der12;
00246                 c=c+cova[js*fNsamples+is];
00247                 y1=y1+adc[iis]*cova[js*fNsamples+is];
00248                 s1=s1+amp1*cova[js*fNsamples+is];
00249                 s2=s2+amp1*amp2*cova[js*fNsamples+is];
00250                 ys1=ys1+adc[iis]*amp2*cova[js*fNsamples+is];
00251                 sp1=sp1+der1*cova[is*fNsamples+js];
00252                 sp2=sp2+der1*der2*cova[js*fNsamples+is];
00253                 ssp=ssp+amp1*der2*cova[js*fNsamples+is];
00254                 ysp=ysp+adc[iis]*der2*cova[js*fNsamples+is];
00255               }
00256           }else { // Don't use covariance matrix: 
00257             c++;
00258             y1=y1+adc[iis];
00259             s1=s1+amp1;
00260             s2=s2+amp1*amp1;
00261             ys1=ys1+amp1*adc[iis];
00262             sp1=sp1+der1;
00263             sp2=sp2+der1*der1;
00264             ssp=ssp+der1*amp1;
00265             ysp=ysp+der1*adc[iis];
00266           }
00267         }
00268       xpar[0]=(ysp*ssp-ys1*sp2)/(ssp*ssp-s2*sp2);
00269       xpar[2]+=(ysp/xpar[0]/sp2-ssp/sp2);
00270    
00271       for(int is=0; is<nsfit; is++){
00272         int iis=is;
00273         iis=is+nsampleo;
00274         
00275         double t1=(double)iis+xpar[2];
00276         double xbin=t1*25.;
00277         int ibin1=(int)xbin;
00278         if(ibin1 < 0) ibin1=0;
00279         
00280         if(ibin1 < 0) ibin1=0;
00281         if(ibin1 > fNsamplesShape-2)ibin1=fNsamplesShape-2;
00282         int ibin2=ibin1+1;
00283         double xfrac=xbin-ibin1;
00284         double amp11=xpar[0]*pshape[ibin1];
00285         double amp12=xpar[0]*pshape[ibin2];
00286         double amp1=xpar[1]+(1.-xfrac)*amp11+xfrac*amp12;
00287         resi[iis]=adc[iis]-amp1;
00288       }
00289 
00290       chi2=0.;
00291       for(int is=0; is<nsfit; is++){
00292         int iis=is;
00293         iis+=nsampleo;
00294         
00295         if( useCova ){
00296           for(int js=0; js<nsfit; js++){
00297             int jjs=js;
00298             jjs+=nsampleo;
00299             chi2+=resi[iis]*resi[jjs]*cova[js*fNsamples+is];
00300           }
00301 
00302         }else chi2+=resi[iis]*resi[iis];
00303       }
00304     }
00305   
00306   fAmp_fitted_max = xpar[0];
00307   fTim_fitted_max = (double)t_ims/25.-xpar[2];
00308   
00309   return chi2 ;
00310 
00311 }
00312