bpmprocess/get_t0.c

Go to the documentation of this file.
00001 
00006 #include <stdlib.h>
00007 #include <math.h>
00008 
00009 #include <bpm/bpm_messages.h>
00010 #include <bpm/bpm_process.h>
00011 #include <bpm/bpm_nr.h>
00012 
00013 void find_t0_startfit( int *wf, double ped, 
00014                        int peak_sample, double peak_value, double peak_fraction, 
00015                        int *start_sample ) {
00016   // starts from the peak sample and goes back in the waveform as long as the
00017   // value stays > the given fraction of the peak value
00018   int S = 0;
00019   for ( S = peak_sample; S > 0; S-- ) {
00020     if ( ( ABS( wf[S] - ped ) > peak_fraction * peak_value ) && 
00021          ( ABS( wf[S] - ped ) > 6.5 ) ) {
00022       *start_sample = S;
00023     }
00024   }
00025   return;
00026 } /* find_t0_startfit(...) */
00027 
00028 // ---------------------------------------------------------------------------
00029   
00030 void find_t0_endfit( int *wf, double ped,
00031                      int peak_sample, double peak_value, double peak_fraction,
00032                      int *end_sample ) {
00033   // starts from 0 to the peak sample and advances in the waveform untill
00034   // the value is the given fraction of the peak value
00035   int S = 0;
00036   for ( S = 0; S < peak_sample; S++ ) {
00037     if ( ( ABS( wf[S] - ped ) ) < peak_fraction*peak_value ) {
00038       *end_sample = S;
00039     }
00040   }
00041   return;
00042 } /* find_t0_endfit(...) */
00043 
00044 // ---------------------------------------------------------------------------
00045 
00056 int get_t0( int *wf, int ns, double fs, double *t0 ) {
00057   
00058 
00059   double adc_ped, adc_err, peak_value, sample_value, start_value;
00060   double gradient, intercept, *xval, *yval;
00061   int peak_sample, start_sample, counter, end_sample, i, retcode;
00062   double siga, sigb, chi2, q;
00063 
00064   *t0 = -DBL_MAX; // some initial value :)
00065 
00066   if ( ! wf || ! t0 ) {
00067     bpm_error( "Invalid pointer arguments in get_t0(...)",
00068                __FILE__, __LINE__ );
00069     return BPM_FAILURE;
00070   }
00071   
00072   // Find some useful info
00073   if( get_pedestal( wf, ns, 20, &adc_ped, &adc_err ) == BPM_FAILURE ) {
00074     bpm_error( "Unable to retreive pedestal in get_t0(...)",
00075                __FILE__, __LINE__ );
00076     return BPM_FAILURE;
00077   }
00078 
00079   // Find the peak sample
00080   // Note - cut off the last 10 samples in case there is a problem 
00081   //        with the end of the waveform
00082   peak_value = adc_err * 4.;
00083   peak_sample = 0;
00084 
00085   for ( i = 0; i < ns - 10; ++i ) {
00086     sample_value = ABS( wf[i] - adc_ped );
00087     
00088     if ( sample_value > peak_value ) {
00089       peak_value  = sample_value;
00090       peak_sample = i;
00091     }
00092 
00093   } /* for ( sample = 0; sample < ns - 10; ++sample ) */
00094 
00095   // Did we find a peak?
00096   if ( peak_sample == 0 ) { // No!
00097     bpm_error( "Could not find a peak in get_t0(...)",
00098                __FILE__, __LINE__ );
00099     return BPM_FAILURE;
00100   }
00101 
00102   // Find the start point
00103   find_t0_endfit( wf, adc_ped, peak_sample, peak_value, 0.9, &end_sample );
00104   find_t0_startfit( wf, adc_ped, peak_sample, peak_value, 0.1, &start_sample );
00105   
00106   // Only one sample so try to find more
00107   if ( start_sample == end_sample ) {
00108     if ( bpm_verbose ) bpm_warning( "First fit initialisation failed, trying second",
00109                                     __FILE__, __LINE__ );
00110     find_t0_endfit( wf, adc_ped, peak_sample, peak_value, 0.95, &end_sample );
00111     find_t0_startfit( wf, adc_ped, peak_sample, peak_value, 0.05, &start_sample );
00112   } 
00113 
00114   // Still only one point? Find more!
00115   if ( start_sample == end_sample ) {
00116     if ( bpm_verbose ) bpm_warning( "Second fit initialisation failed, trying third",
00117                                     __FILE__, __LINE__ );
00118     find_t0_endfit( wf, adc_ped, peak_sample, peak_value, 0.975, &end_sample );
00119     find_t0_startfit( wf, adc_ped, peak_sample, peak_value, 0.025, &start_sample );
00120   } 
00121 
00122   // Still only one point? Give up...
00123   if ( ( end_sample == start_sample ) || 
00124        ( start_sample > end_sample  ) ) { // No!
00125     bpm_warning( "Cannot initialise fit, returning end_sample in get_t0(...)",
00126                  __FILE__, __LINE__ );
00127     *t0 = (double) end_sample / fs; // return in time units
00128     return BPM_SUCCESS;
00129   }
00130  
00131   // Fit the intervening samples to a straight line and
00132   // return the fraction point
00133   xval = (double*) calloc( end_sample - start_sample + 1, sizeof(double) );
00134   yval = (double*) calloc( end_sample - start_sample + 1, sizeof(double) );
00135 
00136   if ( ! ( xval && yval ) ) {
00137     bpm_error( "Coudn't allocate memory in get_t0(...)", 
00138                __FILE__, __LINE__ );
00139     return BPM_FAILURE;
00140   }
00141 
00142   counter = 0;
00143   for ( i = start_sample; i < end_sample + 1; i++ )  {
00144     yval[counter]   = (double) wf[i] - adc_ped;
00145     xval[counter++] = (double) i;
00146   }
00147 
00148   // perform the fit
00149   if ( nr_fit( xval, yval, end_sample - start_sample + 1, NULL, 0, &intercept, &gradient, 
00150                &siga, &sigb, &chi2, &q ) == BPM_FAILURE ) {
00151     bpm_error( "T0 straight line fit failed in get_t0(...)", __FILE__, __LINE__ );
00152     *t0 = -DBL_MAX;
00153     retcode = BPM_FAILURE;
00154   } else {
00155     // fit was successfull
00156     if( ABS( gradient ) > 0. ) {
00157       *t0 = ( peak_value * 0.5 - intercept ) / gradient;
00158       if ( *t0 < 0 || *t0 > ns ) {
00159         bpm_error( "Fitted t0 value out of range in get_t0(...)",
00160                    __FILE__, __LINE__ );
00161         *t0 = -DBL_MAX;
00162         retcode = BPM_FAILURE;
00163       } else {
00164         // we have a good and proper t0, convert to time units...
00165         *t0 /= fs; 
00166         retcode = BPM_SUCCESS;
00167       }
00168     } else {
00169       bpm_error( "Gradient in t0 fit equals 0 in get_t0(...)",
00170                  __FILE__, __LINE__ );
00171       *t0 = -DBL_MAX;
00172       retcode = BPM_FAILURE;
00173     }
00174 
00175   }
00176   
00177   // free the memory
00178   free( xval );
00179   free( yval );
00180 
00181   return retcode;
00182 }

Generated on Thu Jan 10 10:18:04 2008 for libbpm by  doxygen 1.5.1