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
00017
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 }
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
00034
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 }
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;
00065
00066 if ( ! wf || ! t0 ) {
00067 bpm_error( "Invalid pointer arguments in get_t0(...)",
00068 __FILE__, __LINE__ );
00069 return BPM_FAILURE;
00070 }
00071
00072
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
00080
00081
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 }
00094
00095
00096 if ( peak_sample == 0 ) {
00097 bpm_error( "Could not find a peak in get_t0(...)",
00098 __FILE__, __LINE__ );
00099 return BPM_FAILURE;
00100 }
00101
00102
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
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
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
00123 if ( ( end_sample == start_sample ) ||
00124 ( start_sample > end_sample ) ) {
00125 bpm_warning( "Cannot initialise fit, returning end_sample in get_t0(...)",
00126 __FILE__, __LINE__ );
00127 *t0 = (double) end_sample / fs;
00128 return BPM_SUCCESS;
00129 }
00130
00131
00132
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
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
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
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
00178 free( xval );
00179 free( yval );
00180
00181 return retcode;
00182 }