CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/CalibCalorimetry/EcalLaserAnalyzer/src/TSFit.cc

Go to the documentation of this file.
00001 /* 
00002  *  \class TSFit
00003  *
00004  *  $Date: 2012/02/09 10:08:10 $
00005  *  \author: Jean-Pierre Pansart - CEA/Saclay
00006  */
00007 
00008 #include <CalibCalorimetry/EcalLaserAnalyzer/interface/TSFit.h>
00009 
00010 #include <cstdio>
00011 #include <cmath>
00012 #include <cstring>
00013 
00014 //ClassImp(TSFit)
00015 
00016 //------------------------------------------------------------------------
00017 // TSFit provide fitting methods of pulses with third degree polynomial
00018 //
00019 
00020 TSFit::TSFit( int size, int size_sh ) {
00021   sdim = size;
00022   plshdim = size_sh;
00023   // sample_flag = new int[size];
00024 //   t = new double[sdim];
00025 //   z = new double[sdim];
00026 //   f = new double[sdim];
00027 //   acc = new double[sdim];
00028 //   adfmx = new double[sdim];
00029 //   adcp = new double[sdim];
00030 //   maskp3 = new double[sdim];
00031 //   corel = new double[sdim];
00032 //   nbcor = new double[sdim];
00033 //   int k;
00034 //   ff = new double *[sdim];
00035 //   for(k=0;k<sdim;k++)ff[k] = new double[4];
00036 //   der = new double *[sdim];
00037 //   for(k=0;k<sdim;k++)der[k] = new double[5];
00038    
00039 
00040 }
00041 
00042 void TSFit::set_params( int n_samples, int niter, int n_presmpl,
00043                    int sample_min, int sample_max,
00044                    double time_of_max, double chi2_max,
00045                    int nsbm, int nsam ){
00046   // parameters initialisation of the fit package
00047   // nsbm  n_samples_bef_max, nsam n_samples_aft_max
00048 
00049   nbs          = n_samples;
00050   nbr_iter_fit = niter;
00051   n_presamples = n_presmpl;
00052   iinf         = sample_min;
00053   isup         = sample_max;
00054   avtm         = time_of_max;
00055   xki2_max     = chi2_max;
00056   n_samples_bef_max = nsbm;
00057   n_samples_aft_max = nsam;
00058 
00059   norme        = 0.;
00060   alpha_th     = 2.20;
00061   beta_th      = 1.11;
00062 
00063   int k;
00064 
00065   for(k=0;k<=nbs;k++){
00066     sample_flag[k] = 0;
00067   }
00068 
00069   for(k=sample_min;k<=sample_max;k++){
00070     sample_flag[k] = 1;
00071   }
00072   /*
00073   int lim1 = ( iinf > n_presamples ) ? n_presamples : iinf;
00074   for(int k=lim1;k<=sample_max;k++){
00075     sample_flag[k] = 2;
00076   }
00077   */
00078  //  printf( "sample_fag : " );
00079 //   for(k=0;k<=nbs;k++){
00080 //     printf( "%1d ", sample_flag[k] );
00081 //   }
00082 //   printf( "\n" );
00083 
00084 }
00085 
00086 void TSFit::init_errmat( double noise_initialvalue){
00087   //  Input:  noise_initial value  noise (in adc channels) as read in the 
00088   //  data base.
00089 /*------------------------------------------------------------------------*/
00090 
00091   int i, j;
00092   //double one_over_noisesq;
00093 
00094   //one_over_noisesq = 1. / ( noise_initialvalue * noise_initialvalue );
00095   for(i=0;i<sdim;i++ ){
00096     for(j=0;j<sdim;j++){
00097       errmat[i][j] = noise_initialvalue;
00098       //errmat[i][j] = 0.;
00099     }
00100     //errmat[i][i] = one_over_noisesq;
00101   }
00102 }
00103 
00104 double TSFit::fpol3dg ( int nmxul,
00105                         double *parom,
00106                         double *mask,
00107                         double *adc){
00108   // fit third degree polynomial
00109   // nmxul   array adc[] length
00110   // parom   return parameters (a0,a1,a2,a3,pos max,height)
00111   // fplo3dg uses only the diagonal terms of errmat[][]
00112   // errmat  inverse of the error matrix
00113 
00114   int i, k, l;
00115   double  h, t2, tm, delta, tmp;
00116   double xki2, dif, difmx, deglib;
00117   double bv[4], s;
00118 
00119   deglib=(double)nmxul - 4.;
00120   for(i=0;i<nmxul;i++){
00121     t[i]=i;
00122     ff[i][0]=1.;
00123     ff[i][1]=t[i];
00124     ff[i][2]=t[i]*t[i];
00125     ff[i][3]=ff[i][2]*t[i];
00126   }
00127   /*   computation of covariance matrix     */
00128   for(k=0;k<4;k++){
00129     for(l=0;l<4;l++){
00130       s=0.;
00131       for(i=0;i<nmxul;i++){
00132         s=s+ff[i][k]*ff[i][l]*errmat[i][i]*mask[i];
00133       }
00134       cov[k][l]=s;
00135     }
00136     s=0.;
00137     for(i=0;i<nmxul;i++){
00138       s=s+ff[i][k]*adc[i]*errmat[i][i]*mask[i];
00139     }
00140     bv[k]=s;
00141   }
00142   /*     parameters                          */
00143   inverms( 4, cov, invcov );
00144   for(k=0;k<4;k++){
00145     s=0.;
00146     for(l=0;l<4;l++){
00147       s=s+bv[l]*invcov[l][k];
00148     }
00149     parom[k]=s;
00150   }
00151 
00152   if( parom[3] == 0. ){
00153     parom[4] = -1000.;
00154     parom[5] = -1000.;
00155     parom[6] = -1000.;
00156     return 1000000.;
00157   }
00158   /*    worst hit and ki2                    */
00159   xki2=0.;
00160   difmx=0.;
00161   for(i=0;i<nmxul;i++ ){
00162     t2=t[i]*t[i];
00163     h= parom[0]+parom[1]*t[i]+parom[2]*t2+parom[3]*t2*t[i];
00164     dif=(adc[i]-h)*mask[i];
00165     xki2=xki2+dif*dif*errmat[i][i];
00166     if(dif > difmx) {
00167       difmx=dif;
00168     }
00169   }
00170   if(deglib > 0.5) xki2=xki2/deglib;
00171   /*     amplitude and maximum position                    */
00172   delta=parom[2]*parom[2]-3.*parom[3]*parom[1];
00173   if(delta > 0.){
00174     delta=sqrt(delta);
00175     tm=-(delta+parom[2])/(3.*parom[3]);
00176     tmp=(delta-parom[2])/(3.*parom[3]);
00177   }
00178   else{
00179     parom[4] = -1000.;
00180     parom[5] = -1000.;
00181     parom[6] = -1000.;
00182     return xki2;
00183   }
00184   parom[4]=tm;
00185   parom[5]= parom[0]+parom[1]*tm+parom[2]*tm*tm+parom[3]*tm*tm*tm;
00186   parom[6]=tmp;
00187   return xki2;
00188 }
00189 double TSFit::inverms( int n, double g[matdim][matdim], double ginv[matdim][matdim] ){
00190   // inversion of a positive definite symetric matrix of size n
00191 
00192   int i, j, k, jj;
00193   double r,  s;
00194   double deter=0;
00195 
00196   /*   initialisation  */
00197 
00198   if( n > matdim ){
00199     printf(
00200     "ERROR : trying to use TSFit::inverms with size %d( max allowed %d\n",
00201     n, matdim );
00202     return -999.;
00203   }
00204 
00205   int zero = 0;
00206   memset( (char *)al, zero, 8*n*n );
00207   memset( (char *)be, zero, 8*n*n );
00208   /*
00209   for(i=0;i<n;i++){
00210     for(j=0;j<n;j++){
00211       al[i][j] = 0.;
00212       be[i][j] = 0.;
00213     }
00214   }
00215   */
00216   /*  decomposition en vecteurs sur une base orthonormee  */
00217   al[0][0] =  sqrt( g[0][0] );
00218   for(i=1;i<n;i++){
00219     al[i][0] = g[0][i] / al[0][0];
00220     for(j=1;j<=i;j++){
00221       s=0.;
00222       for(k=0;k<=j-1;k++){
00223         s = s + al[i][k] * al[j][k];
00224       }
00225       r= g[i][j] - s;
00226       if( j < i )  al[i][j] = r / al[j][j];
00227       if( j == i ) al[i][j] = sqrt( r );
00228     }
00229   }
00230   /*  inversion de la matrice al   */
00231   be[0][0] = 1./al[0][0];
00232   for(i=1;i<n;i++){
00233     be[i][i] = 1. / al[i][i];
00234     for(j=0;j<i;j++){
00235       jj=i-j-1;
00236       s=0.;
00237       for(k=jj+1;k<=i;k++){
00238         s=s+ be[i][k] * al[k][jj];
00239       }
00240       be[i][jj]=-s/al[jj][jj];
00241     }
00242   }
00243   /*   calcul de la matrice ginv   */
00244   for(i=0;i<n;i++){
00245     for(j=0;j<n;j++){
00246       s=0.;
00247       for(k=0;k<n;k++){
00248         s=s+ be[k][i] * be[k][j];
00249       }
00250       ginv[i][j]=s;
00251     }
00252   }
00253 
00254   return deter;
00255 }
00256 
00257 double TSFit::fit_third_degree_polynomial(
00258                        double *bdc,
00259                        double *ret_dat ){
00260   //  third degree polynomial fit of the pulse summit. 
00261   //  samples are contained in array bdc and must be pedestal
00262   //  substracted.
00263   //  only samples having sample_flag >= 1 are used.
00264   //  the unit of time is one clock unit, that is to say 25 ns.
00265   //  output: ret_dat[0] = pulse height
00266   //          ret_dat[1]   position of maximum in the sample frame in clock units
00267   //          ret_dat[2]   adc value of the highest sample
00268   //          ret_dat[3]   number of the highest sample
00269   //          ret_dat[4]   lower sample number used for fitting
00270   //          ret_dat[5]   upper sample number used for fitting
00271   // errmat  inverse of the error matrix
00272 
00273   int i;
00274   int nus;
00275   double xki2;
00276   double tm, tmp, amp;
00277 
00278   static double nevt;
00279 
00280   ret_dat[0] = -999.;
00281   ret_dat[1] = -999.;
00282 
00283   //    search the maximum
00284   double val_max = 0.;
00285   int imax = 0;
00286   for(i=0;i<nbs;i++){
00287     if( sample_flag[i] == 0 )continue;
00288     if( bdc[i] > val_max ){
00289       val_max = bdc[i];
00290       imax = i;
00291     }
00292   }
00293 
00294   if( (val_max*val_max) * errmat[imax][imax] < 16. )return -118;
00295 
00296   //  if( imax != 9 )printf( "imax : %d !!!!!!!!!!!!!!!!!!!!!!!!!!!\n", imax );
00297 
00298   if( norme == 0. )norme = val_max;
00299 
00300   // look for samples above 1/3 of maximum before and 1/2 after
00301   double val2 = val_max / 2.;
00302   double val3 = val_max / 2.;
00303   int ilow = iinf;
00304   int ihig = 0;
00305 
00306   for(i=iinf;i<=isup;i++){
00307     if( sample_flag[i] >= 1 ){
00308       if( ( bdc[i] < val3 ) && ( i < imax ) )ilow = i;
00309       if( bdc[i] > val2 )ihig = i;
00310     }
00311   }
00312 
00313   ilow++;
00314   
00315   //ilow = imax - 1;
00316 
00317   /*  le test suivant, apparemment idiot, est mis a cause des sequences 0. 2048. qui apparaissent dans certains mauvais evts     JPP 11/09/00 */
00318  
00319   if( ihig == ilow)return -105;
00320   if( ilow == imax )ilow = ilow-1;
00321   //if( ihig - ilow < 3 )ihig = ilow + 3;
00322   ihig = ilow + 3;
00323 
00324  /*   printf("  third degree:   ilow %d ihig %d \n",ilow,ihig);  */
00325   nus=0;
00326   int number_of_good_samples = 0;
00327   for(i=ilow;i<=ihig;i++){
00328     maskp3[nus] = 0;
00329     adfmx[nus]  = 0.;
00330 /*    printf(" adc %f sample_flag %d number_of good_samples %d \n",bdc[i],sample_flag[i],number_of_good_samples);  */
00331     if( sample_flag[i] >= 1 ){
00332       adfmx[nus] = bdc[i];
00333       maskp3[nus] = 1.;
00334       number_of_good_samples++;
00335     }
00336     nus++;
00337   }
00338 
00339   if( number_of_good_samples < 4 ){
00340     return( -106 );
00341   }
00342 
00343   xki2 = fpol3dg( nus, &parfp3[0], &maskp3[0], &adfmx[0]);
00344   
00345   /* printf( "fpol3dg-----------------------------------> %f %f %f %f %f\n",
00346           parfp3[0], parfp3[1], parfp3[2], parfp3[3], parfp3[4] );  */
00347 
00348   tm = parfp3[4] + (float)ilow;
00349   amp = parfp3[5];
00350 
00351   if( amp * amp * errmat[0][0] < 2. )return -101.;
00352   tmp = parfp3[6] + (float)ilow;
00353 
00354   /*
00355     validation of fit quality.  Most of the time the fit is done with
00356     four samples, therefore there is no possible ki2 check. When more than
00357     4 samples are used the ki2 is often bad. So, in order to suppress some 
00358     events with bad samples, a consistency check on the position of the
00359     maximum and minimum of the 3rd degree polynomial is used.
00360   */
00361 
00362   if( xki2 > xki2_max ){
00363       return -102.;
00364   }
00365   if( (tm < (double)ilow ) || (tm > (double)ihig)){
00366     return  -103.;
00367   }
00368 
00369   if( (tmp > (double)ilow ) && (tmp < (double)ihig - 1.) ){
00370     return -104.;
00371   }
00372 
00373   nevt += 1.;
00374 
00375   ret_dat[0] = amp;
00376   ret_dat[1] = tm;
00377   ret_dat[2] = val_max;
00378   ret_dat[3] = (double)imax;
00379   ret_dat[4] = (double)ilow;
00380   ret_dat[5] = (double)ihig;
00381   ret_dat[6] = (double)tmp;
00382   int k;
00383   for(i=0;i<4;i++){
00384     k=i+7;
00385     ret_dat[k] = parfp3[i];
00386   }
00387 
00388   return xki2;
00389 }
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402