CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/CalibCalorimetry/EcalLaserAnalyzer/src/TSFit.cc

Go to the documentation of this file.
00001 /* 
00002  *  \class TSFit
00003  *
00004  *  $Date: 2010/01/04 15:06:28 $
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, iworst;
00115   double  h, t2, tm, delta, tmp;
00116   double xki2, dif, difmx, deglib;
00117   double bv[4], s, deter;
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   deter = 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       iworst=i;
00168       difmx=dif;
00169     }
00170   }
00171   if(deglib > 0.5) xki2=xki2/deglib;
00172   /*     amplitude and maximum position                    */
00173   delta=parom[2]*parom[2]-3.*parom[3]*parom[1];
00174   if(delta > 0.){
00175     delta=sqrt(delta);
00176     tm=-(delta+parom[2])/(3.*parom[3]);
00177     tmp=(delta-parom[2])/(3.*parom[3]);
00178   }
00179   else{
00180     parom[4] = -1000.;
00181     parom[5] = -1000.;
00182     parom[6] = -1000.;
00183     return xki2;
00184   }
00185   parom[4]=tm;
00186   parom[5]= parom[0]+parom[1]*tm+parom[2]*tm*tm+parom[3]*tm*tm*tm;
00187   parom[6]=tmp;
00188   return xki2;
00189 }
00190 double TSFit::inverms( int n, double g[matdim][matdim], double ginv[matdim][matdim] ){
00191   // inversion of a positive definite symetric matrix of size n
00192 
00193   int i, j, k, jj;
00194   double r,  s;
00195   double deter=0;
00196 
00197   /*   initialisation  */
00198 
00199   if( n > matdim ){
00200     printf(
00201     "ERROR : trying to use TSFit::inverms with size %d( max allowed %d\n",
00202     n, matdim );
00203     return -999.;
00204   }
00205 
00206   int zero = 0;
00207   memset( (char *)al, zero, 8*n*n );
00208   memset( (char *)be, zero, 8*n*n );
00209   /*
00210   for(i=0;i<n;i++){
00211     for(j=0;j<n;j++){
00212       al[i][j] = 0.;
00213       be[i][j] = 0.;
00214     }
00215   }
00216   */
00217   /*  decomposition en vecteurs sur une base orthonormee  */
00218   al[0][0] =  sqrt( g[0][0] );
00219   for(i=1;i<n;i++){
00220     al[i][0] = g[0][i] / al[0][0];
00221     for(j=1;j<=i;j++){
00222       s=0.;
00223       for(k=0;k<=j-1;k++){
00224         s = s + al[i][k] * al[j][k];
00225       }
00226       r= g[i][j] - s;
00227       if( j < i )  al[i][j] = r / al[j][j];
00228       if( j == i ) al[i][j] = sqrt( r );
00229     }
00230   }
00231   /*  inversion de la matrice al   */
00232   be[0][0] = 1./al[0][0];
00233   for(i=1;i<n;i++){
00234     be[i][i] = 1. / al[i][i];
00235     for(j=0;j<i;j++){
00236       jj=i-j-1;
00237       s=0.;
00238       for(k=jj+1;k<=i;k++){
00239         s=s+ be[i][k] * al[k][jj];
00240       }
00241       be[i][jj]=-s/al[jj][jj];
00242     }
00243   }
00244   /*   calcul de la matrice ginv   */
00245   for(i=0;i<n;i++){
00246     for(j=0;j<n;j++){
00247       s=0.;
00248       for(k=0;k<n;k++){
00249         s=s+ be[k][i] * be[k][j];
00250       }
00251       ginv[i][j]=s;
00252     }
00253   }
00254 
00255   return deter;
00256 }
00257 
00258 double TSFit::fit_third_degree_polynomial(
00259                        double *bdc,
00260                        double *ret_dat ){
00261   //  third degree polynomial fit of the pulse summit. 
00262   //  samples are contained in array bdc and must be pedestal
00263   //  substracted.
00264   //  only samples having sample_flag >= 1 are used.
00265   //  the unit of time is one clock unit, that is to say 25 ns.
00266   //  output: ret_dat[0] = pulse height
00267   //          ret_dat[1]   position of maximum in the sample frame in clock units
00268   //          ret_dat[2]   adc value of the highest sample
00269   //          ret_dat[3]   number of the highest sample
00270   //          ret_dat[4]   lower sample number used for fitting
00271   //          ret_dat[5]   upper sample number used for fitting
00272   // errmat  inverse of the error matrix
00273 
00274   int i;
00275   int nus;
00276   double xki2;
00277   double tm, tmp, amp;
00278 
00279   static double nevt;
00280 
00281   ret_dat[0] = -999.;
00282   ret_dat[1] = -999.;
00283 
00284   //    search the maximum
00285   double val_max = 0.;
00286   int imax = 0;
00287   for(i=0;i<nbs;i++){
00288     if( sample_flag[i] == 0 )continue;
00289     if( bdc[i] > val_max ){
00290       val_max = bdc[i];
00291       imax = i;
00292     }
00293   }
00294 
00295   if( (val_max*val_max) * errmat[imax][imax] < 16. )return -118;
00296 
00297   //  if( imax != 9 )printf( "imax : %d !!!!!!!!!!!!!!!!!!!!!!!!!!!\n", imax );
00298 
00299   if( norme == 0. )norme = val_max;
00300 
00301   // look for samples above 1/3 of maximum before and 1/2 after
00302   double val2 = val_max / 2.;
00303   double val3 = val_max / 2.;
00304   int ilow = iinf;
00305   int ihig = 0;
00306 
00307   for(i=iinf;i<=isup;i++){
00308     if( sample_flag[i] >= 1 ){
00309       if( ( bdc[i] < val3 ) && ( i < imax ) )ilow = i;
00310       if( bdc[i] > val2 )ihig = i;
00311     }
00312   }
00313 
00314   ilow++;
00315   
00316   //ilow = imax - 1;
00317 
00318   /*  le test suivant, apparemment idiot, est mis a cause des sequences 0. 2048. qui apparaissent dans certains mauvais evts     JPP 11/09/00 */
00319  
00320   if( ihig == ilow)return -105;
00321   if( ilow == imax )ilow = ilow-1;
00322   //if( ihig - ilow < 3 )ihig = ilow + 3;
00323   ihig = ilow + 3;
00324 
00325  /*   printf("  third degree:   ilow %d ihig %d \n",ilow,ihig);  */
00326   nus=0;
00327   int number_of_good_samples = 0;
00328   for(i=ilow;i<=ihig;i++){
00329     maskp3[nus] = 0;
00330     adfmx[nus]  = 0.;
00331 /*    printf(" adc %f sample_flag %d number_of good_samples %d \n",bdc[i],sample_flag[i],number_of_good_samples);  */
00332     if( sample_flag[i] >= 1 ){
00333       adfmx[nus] = bdc[i];
00334       maskp3[nus] = 1.;
00335       number_of_good_samples++;
00336     }
00337     nus++;
00338   }
00339 
00340   if( number_of_good_samples < 4 ){
00341     return( -106 );
00342   }
00343 
00344   xki2 = fpol3dg( nus, &parfp3[0], &maskp3[0], &adfmx[0]);
00345   
00346   /* printf( "fpol3dg-----------------------------------> %f %f %f %f %f\n",
00347           parfp3[0], parfp3[1], parfp3[2], parfp3[3], parfp3[4] );  */
00348 
00349   tm = parfp3[4] + (float)ilow;
00350   amp = parfp3[5];
00351 
00352   if( amp * amp * errmat[0][0] < 2. )return -101.;
00353   tmp = parfp3[6] + (float)ilow;
00354 
00355   /*
00356     validation of fit quality.  Most of the time the fit is done with
00357     four samples, therefore there is no possible ki2 check. When more than
00358     4 samples are used the ki2 is often bad. So, in order to suppress some 
00359     events with bad samples, a consistency check on the position of the
00360     maximum and minimum of the 3rd degree polynomial is used.
00361   */
00362 
00363   if( xki2 > xki2_max ){
00364       return -102.;
00365   }
00366   if( (tm < (double)ilow ) || (tm > (double)ihig)){
00367     return  -103.;
00368   }
00369 
00370   if( (tmp > (double)ilow ) && (tmp < (double)ihig - 1.) ){
00371     return -104.;
00372   }
00373 
00374   nevt += 1.;
00375 
00376   ret_dat[0] = amp;
00377   ret_dat[1] = tm;
00378   ret_dat[2] = val_max;
00379   ret_dat[3] = (double)imax;
00380   ret_dat[4] = (double)ilow;
00381   ret_dat[5] = (double)ihig;
00382   ret_dat[6] = (double)tmp;
00383   int k;
00384   for(i=0;i<4;i++){
00385     k=i+7;
00386     ret_dat[k] = parfp3[i];
00387   }
00388 
00389   return xki2;
00390 }
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403