00001
00005 #include <bpm/bpm_nr.h>
00006 #include <bpm/bpm_alloc.h>
00007 #include <bpm/bpm_messages.h>
00008 #include <bpm/bpm_process.h>
00009
00010 #define FIT_MAX_ITER 10000
00011
00012 #define FIT_AMP 0
00013 #define FIT_PHASE 1
00014 #define FIT_FREQ 2
00015 #define FIT_TDECAY 3
00016
00017 #define FIT_T0 0
00018 #define FIT_FS 1
00019
00020 void fcnwfjac( double* par, double *jac, int npars, int ns, void *a ) {
00021 int i, j;
00022 double t, sinarg, exparg, cosarg;
00023
00024
00025
00026 for( i=j=0; i<ns; i++ ) {
00027 sample_to_time( ( (double*)a )[FIT_FS], ns, i, &t );
00028 if ( t >= ((double*)a)[FIT_T0] ) {
00029 sinarg = sin( 2.*PI*par[FIT_FREQ]* ( t - ((double*)a)[FIT_T0] ) + par[FIT_PHASE] );
00030 cosarg = cos( 2.*PI*par[FIT_FREQ]* ( t - ((double*)a)[FIT_T0] ) + par[FIT_PHASE] );
00031 exparg = exp( -( t - ((double*)a)[FIT_T0] ) / par[FIT_TDECAY] );
00032
00033
00034
00035
00036 jac[j++] = exparg * sinarg;
00037
00038
00039 jac[j++] = par[FIT_AMP] * exparg * cosarg;
00040
00041
00042 jac[j++] = par[FIT_AMP] * exparg * cosarg * 2.*PI*( t - ((double*)a)[FIT_T0] );
00043
00044
00045 jac[j++] = par[FIT_AMP] * exparg * (t - ((double*)a)[FIT_T0])/SQR( par[FIT_TDECAY]) * sinarg;
00046
00047 } else {
00048 jac[j++] = 0.;
00049 jac[j++] = 0.;
00050 jac[j++] = 0.;
00051 jac[j++] = 0.;
00052 }
00053
00054 }
00055 }
00056
00062 void fcnwf( double* par, double *sinwf, int npars, int ns, void *a ) {
00063
00064 double t;
00065 int i;
00066
00067 for( i=0; i<ns; i++ ) {
00068 sample_to_time( ( (double*)a )[FIT_FS], ns, i, &t );
00069 if ( t >= ( (double*)a )[FIT_T0] ) {
00070 sinwf[i] = par[FIT_AMP]
00071 * exp( - ( t-( (double*)a )[FIT_T0]) / par[FIT_TDECAY] )
00072 * sin( 2.*PI*par[FIT_FREQ]*(t-( (double*)a )[FIT_T0]) + par[FIT_PHASE] );
00073 } else {
00074 sinwf[i] = 0.;
00075 }
00076 }
00077
00078 return;
00079 }
00080
00081
00101 int fit_waveform( int *wf, int ns, double t0, double fs,
00102 double i_freq, double i_tdecay, double i_amp, double i_phase,
00103 double *freq, double *tdecay, double *amp, double *phase ) {
00104
00105 double *yval, a[2], ped, rms;
00106 const int npars = 4;
00107 double par[npars];
00108 double opt[4], info[LM_INFO_SZ];
00109 int i;
00110
00111 double err[256];
00112
00113 opt[0]=LM_INIT_MU; opt[1]=1E-15; opt[2]=1E-15; opt[3]=1E-20;
00114
00115 if ( ! wf ) {
00116 bpm_error( "Invalid waveform pointer in fit_waveform(...)",
00117 __FILE__, __LINE__ );
00118 return BPM_FAILURE;
00119 }
00120
00121
00122 yval = alloc_simple_wave_double( ns );
00123 if ( ! yval ) {
00124 bpm_error( "Unable to allocate memory for waveform in fit_waveform(...)",
00125 __FILE__, __LINE__ );
00126 return BPM_FAILURE;
00127 }
00128
00129
00130 if ( get_pedestal( wf, ns, 20, &ped, &rms ) == BPM_FAILURE ) {
00131 bpm_error( "Error getting pedestal in fit_waveform(...)", __FILE__, __LINE__ );
00132 free_simple_wave_double( yval );
00133 return BPM_FAILURE;
00134 }
00135
00136
00137 a[FIT_T0] = t0;
00138 a[FIT_FS] = fs;
00139 for ( i=0; i<ns; i++ ) {
00140 yval[i] = (double) wf[i] - ped;
00141 }
00142 par[FIT_AMP] = i_amp;
00143 par[FIT_PHASE] = i_phase;
00144 par[FIT_FREQ] = i_freq;
00145 par[FIT_TDECAY] = i_tdecay;
00146
00147
00148 nr_lmder( fcnwf, fcnwfjac, par, yval, npars, ns, FIT_MAX_ITER, opt, info, NULL, NULL, a );
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 *amp = par[FIT_AMP];
00163 *phase = par[FIT_PHASE];
00164 *freq = par[FIT_FREQ];
00165 *tdecay = par[FIT_TDECAY];
00166
00167 free_simple_wave_double( yval );
00168
00169 return BPM_SUCCESS;
00170 }
00171
00172 #undef FIT_MAX_ITER
00173 #undef FIT_AMP
00174 #undef FIT_PHASE
00175 #undef FIT_FREQ
00176 #undef FIT_TDECAY
00177 #undef FIT_T0
00178 #undef FIT_FS
00179