00001
00005 #include <stdio.h>
00006 #include <bpm/bpm_alloc.h>
00007 #include <bpm/bpm_nr.h>
00008 #include <bpm/bpm_units.h>
00009 #include <bpm/bpm_messages.h>
00010 #include <bpm/bpm_process.h>
00011
00012 #define FIT_MAX_ITER 5000 // max iteration
00013 #define FIT_WINDOW_FACTOR 3 // number of sigma to fit withing (integer)
00014
00015
00016
00017
00018
00019
00020
00021
00022 void fcnlorjac( double *p, double *ljac, int np, int ns, void *a ) {
00023
00024 int i,j;
00025 double denom;
00026 double f;
00027
00028 for ( i=j=0; i<ns; i++ ) {
00029
00030 f = (((double*)a)[0] + (double)i + 0.5 ) / ((double*)a)[1] * ((double*)a)[2];
00031 denom = SQR( f - p[1] ) + SQR( p[2] / 2. );
00032
00033 if ( denom == 0. ) {
00034 ljac[j++] = 0.;
00035 ljac[j++] = 0.;
00036 ljac[j++] = 0.;
00037 ljac[j++] = 1.;
00038 } else {
00039 ljac[j++] = 1. / denom;
00040 ljac[j++] = 2. * p[0] * (f-p[1]) / SQR( denom );
00041 ljac[j++] = -0.5 * p[0] * p[2] / SQR( denom );
00042 ljac[j++] = 1.;
00043 }
00044
00045 }
00046
00047 return;
00048 }
00049
00050 void fcnlor( double *p, double *lor, int np, int ns, void *a ) {
00051
00052 int i;
00053 double f;
00062 for ( i=0; i<ns; i++ ) {
00063
00064 f = (((double*)a)[0] + (double) i + 0.5 ) / ((double*)a)[1] * ((double*)a)[2];
00065 lor[i] = p[0] / ( SQR( f - p[1] ) + SQR( p[2] / 2. ) ) + p[3];
00066 }
00067
00068 return;
00069 }
00070
00071
00072
00077 int fit_fft_prepare( double **fft, int ns, double fs, int *n1, int *n2,
00078 double *amp, double *freq, double *fwhm ) {
00079
00080 int i, imax=0;
00081 double pw, tmp;
00082
00083 if ( ! fft || ! amp ) {
00084 bpm_error( "Invalid pointers in fit_fft_prepare(...)",
00085 __FILE__, __LINE__ );
00086 return BPM_FAILURE;
00087 }
00088
00089
00090 *amp = 0;
00091 *freq = 20.0*MHz;
00092 *fwhm = 10.0*MHz;
00093 *n1 = 20;
00094 *n2 = 100;
00095
00096
00097 for ( i=0; i<ns/2; i++ ) {
00098 pw = SQR( fft[i][Re] ) + SQR( fft[i][Im]);
00099 if ( pw > *amp ) {
00100 *amp = pw; imax = i;
00101 }
00102 }
00103 *freq = (double) imax / (double) ns * fs;
00104
00105
00106 for ( i=imax; i>0; i-- ) {
00107 pw = SQR( fft[i][Re] ) + SQR( fft[i][Im]);
00108 if ( pw <= *amp/2. ) break;
00109 }
00110 *n1 = i;
00111
00112 for ( i=imax; i<ns/2 ; i++ ) {
00113 pw = SQR( fft[i][Re] ) + SQR( fft[i][Im]);
00114 if ( pw <= *amp/2. ) break;
00115 }
00116 *n2 = i;
00117
00118
00119 *fwhm = ( (double)( *n2 - *n1 ) / (double)ns * fs );
00120
00121
00122 *n1 = imax - FIT_WINDOW_FACTOR * ABS(imax - *n1);
00123 *n2 = imax + FIT_WINDOW_FACTOR * ABS(imax - *n2);
00124
00125
00126 if ( *n1 < 0 ) *n1 = 0;
00127 if ( *n2 > ns/2) *n2=ns/2;
00128
00129 if ( *n2 <= *n1 ) {
00130 bpm_error( "Error in fit range ( n2 <= n1 ) in fit_fft_prepare(...)",
00131 __FILE__, __LINE__ );
00132 return BPM_FAILURE;
00133 }
00134
00135 if ( *n2 - *n1 < 5 ) {
00136 bpm_error( "Error, too few number of samples in fit_fft_prepare(...)",
00137 __FILE__, __LINE__ );
00138 return BPM_FAILURE;
00139 }
00140
00141
00142 #if 0
00143 printf( "fftfit prepare : n1=%d, n2=%d, imax=%d, amp=%f, freq=%f, fwhm=%f\n",
00144 *n1, *n2, imax, *amp, *freq, *fwhm );
00145 fflush( stdout );
00146 #endif
00147
00148 return BPM_SUCCESS;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 int fit_fft( double **fft, int ns, double fs, double *freq, double *tdecay,
00169 double *A, double *C ) {
00170
00171 const int npar = 4;
00172 double *pspec, par[npar];
00173 double opt[4], info[LM_INFO_SZ];
00174 double a[3], i_amp, i_freq, i_fwhm;
00175 int i, nfit, n1, n2;
00176
00177 #if 0
00178 double *err;
00179 #endif
00180
00181 opt[0]=LM_INIT_MU; opt[1]=1E-15; opt[2]=1E-15; opt[3]=1E-20;
00182
00183
00184 *freq = 0.;
00185 *tdecay = 0.;
00186
00187 if ( ! fft ) {
00188 bpm_error( "Invalid pointer in fit_fft(...)",
00189 __FILE__, __LINE__ );
00190 return BPM_FAILURE;
00191 }
00192
00193 if ( fit_fft_prepare( fft, ns, fs, &n1, &n2, &i_amp, &i_freq, &i_fwhm ) == BPM_FAILURE ) {
00194 bpm_error( "Error in preparing fft fit, givin up in fit_fft(...)", __FILE__, __LINE__ );
00195 return BPM_FAILURE;
00196 }
00197
00198
00199 nfit = n2 - n1 + 1;
00200 pspec = alloc_simple_wave_double( nfit );
00201 for ( i=0; i<nfit; i++ ) {
00202 pspec[i] = SQR( fft[n1+i][Re] ) + SQR( fft[n1+i][Im] );
00203 }
00204
00205
00206 par[0] = i_amp;
00207 par[1] = i_freq;
00208 par[2] = i_fwhm;
00209 par[3] = 0.;
00210
00211
00212 a[0] = (double) n1;
00213 a[1] = (double) ns;
00214 a[2] = fs;
00215
00216
00217 #if 0
00218 err = alloc_simple_wave_double( nfit );
00219 nr_lmchkjac( fcnlor, fcnlorjac, par, npar, nfit, a, err );
00220 for (i=0;i<nfit;i++) printf( "err[%d] = %f\n", i, err[i] ); fflush(stdout);
00221 free(err);
00222 #endif
00223
00224
00225 nr_lmder( fcnlor, fcnlorjac, par, pspec, npar, nfit, FIT_MAX_ITER, opt, info,
00226 NULL, NULL, a );
00227
00228 *freq = par[1];
00229
00230
00231 if ( par[2] != 0. ) *tdecay = 1. / par[2] / PI;
00232
00233
00234 if ( A ) *A = par[0];
00235 if ( C ) *C = par[3];
00236
00237 free_simple_wave_double( pspec );
00238
00239 return BPM_SUCCESS;
00240 }
00241
00242 #undef FIT_MAX_ITER