bpmprocess/process_waveform.c

Go to the documentation of this file.
00001 
00005 #include <stdio.h>
00006 #include <bpm/bpm_units.h>
00007 #include <bpm/bpm_messages.h>
00008 #include <bpm/bpm_process.h>
00009 
00027 int process_waveform( enum bpmtype_t type, bpmconf_t *bpm, bpmcalib_t *cal, bpmsignal_t *sig, 
00028                       bpmproc_t *proc, bpmproc_t *trig, unsigned int mode ) {
00029 
00030 
00031   int have_fft_pars = FALSE;
00032   int have_fit_pars = FALSE;
00033   double freq, tdecay, amp, phase;
00034   char msg[128];
00035   
00036   if ( ! bpm || ! sig || ! proc || ! trig ) {
00037     bpm_error( "Invalid pointer arguments in process_waveform(...)",
00038                __FILE__, __LINE__ );
00039     return BPM_FAILURE;
00040   }
00041   
00042   // reset the success values for this pulse...
00043   proc->fft_success = FALSE;
00044   proc->fit_success = FALSE;
00045   proc->ddc_success = FALSE;
00046 
00047   // check whether we have the correct mode
00048   if( bpm->cav_type != type ) {
00049     sprintf( msg, "Wrong cavity type for BPM %s in process_waveform(...)", bpm->name );
00050     bpm_error( msg, __FILE__, __LINE__ );
00051     return BPM_FAILURE;
00052   }
00053 
00054   // do we have a signal ?
00055   if ( ! sig->wf ) {
00056     sprintf( msg, "No signal present for BPM %s in process_waveform(...)", bpm->name );
00057     bpm_error( msg, __FILE__, __LINE__ );
00058     return BPM_FAILURE;
00059   }
00060 
00061   // determing voltage offset and amplitude noise in adc channels (pedestal)
00062   if ( get_pedestal( sig->wf, bpm->digi_nsamples, 20, 
00063                      &(proc->voltageoffset) ,&(proc->ampnoise) ) == BPM_FAILURE ) {
00064     sprintf( msg, "Error getting pedestal of BPM %s in process_waveform(...)", bpm->name );
00065     bpm_error( msg, __FILE__, __LINE__ );
00066     return BPM_FAILURE;
00067   }
00068 
00069   /* ------------------------------ check whether to do FFT ? -------------------------------- */
00070   if ( mode & PROC_DO_FFT ) {
00071 
00072     // compute the ft
00073     if ( fft_waveform( sig->wf, bpm->digi_nsamples, proc->fftwf ) == BPM_FAILURE ) {
00074       sprintf( msg, "Could not perform fft for BPM %s in process_waveform(...)", bpm->name );
00075       bpm_warning( msg, __FILE__, __LINE__ );
00076 
00077     } else {
00078       // fft done, fit for frequency and tdecay
00079       if( fit_fft( proc->fftwf, bpm->digi_nsamples, bpm->digi_freq, 
00080                    &(proc->fft_freq), &(proc->fft_tdecay), NULL, NULL ) == BPM_FAILURE ) {
00081         sprintf( msg, "Could not fit the FFT for BPM %s in process_waveform(...)", bpm->name );
00082         bpm_warning( msg, __FILE__, __LINE__ );
00083       } else { 
00084         have_fft_pars = TRUE;
00085         proc->fft_success = TRUE;
00086       }
00087 
00088       
00089     }
00090 
00091   } /* if ( mode & PROC_DO_FFT ) */
00092 
00093 
00094   /* ------------------------------ check whether to do FIT ? -------------------------------- */
00095   if ( mode & PROC_DO_FIT ) {
00096     
00097     // initial parameters
00098     freq = tdecay = amp = phase = 0.;
00099 
00100     // what to use for initial parameters ?
00101     // is the fitted frequency from last pulse reasonable, as in > 0 and < nyquist freq
00102     // is amplitude and decay constant reasonable ?
00103 
00104     if ( proc->fit_freq <= 0.*MHz || proc->fit_freq > ( bpm->digi_freq/2.) ) {
00105       if ( ( bpm->rf_LOfreq > 0. ) && ( bpm->cav_freq > 0. ) ) {
00106         freq = ABS( bpm->cav_freq - bpm->rf_LOfreq );
00107       } else freq = 20.0*MHz;
00108     } else freq = proc->fit_freq; // use last fitted value
00109 
00110     if ( proc->fit_tdecay <= 10.*nsec || proc->fit_tdecay > 1.0*usec ) {
00111       if ( bpm->cav_decaytime > 0. ) tdecay = bpm->cav_decaytime;
00112       else tdecay = 0.2*usec;
00113     } else tdecay = proc->fit_tdecay; // use last fitted value
00114 
00115     // probably can think of something more clever here...
00116     if( ABS( proc->fit_amp ) < 100000. ) amp = proc->fit_amp; else amp = 3000.;
00117     phase  = proc->fit_phase;
00118     
00119     // if we have down the FFT and got the frequency from there, use that as an inital parameter
00120     // so overwrite the previous
00121     if( have_fft_pars ) {
00122       freq   = proc->fft_freq;
00123       tdecay = proc->fft_tdecay; 
00124     }
00125 
00126     // Slight hack to sort out saturation and trigger offsets
00127     // Change t0, fit, then extrapolate back
00128     int unsat_sample;
00129     if ( handle_saturation( sig->wf, bpm->digi_nsamples, 200, bpm->digi_nbits, 64, &unsat_sample ) == BPM_FAILURE ) {
00130       bpm_error( "Unable to handle saturation in process_waveform(...)",
00131                  __FILE__, __LINE__ );
00132       return BPM_FAILURE;
00133     }
00134     
00135     double t0;
00136     sample_to_time(bpm->digi_freq, bpm->digi_nsamples, unsat_sample, &t0 );
00137     t0 = ( t0 > ( trig->t0 + cal->t0Offset ) ? t0 : trig->t0 + cal->t0Offset);
00138 
00139     if ( fit_waveform( sig->wf, bpm->digi_nsamples, t0, bpm->digi_freq, 
00140                        freq, tdecay, amp, phase,
00141                        &(proc->fit_freq), &(proc->fit_tdecay), &(proc->fit_amp) ,
00142                        &(proc->fit_phase) ) == BPM_FAILURE ) {
00143         sprintf( msg, "Could not fit for BPM %s in process_waveform(...)", bpm->name );
00144         bpm_warning( msg, __FILE__, __LINE__ );
00145     } else { 
00146       have_fit_pars = TRUE;
00147       proc->fit_success = TRUE;
00148 
00149       // Extrapolate back
00150       proc->fit_amp *= exp( ( t0 - trig->t0 ) / proc->fit_tdecay );
00151       proc->fit_phase -= (t0 - trig->t0) * proc->fit_freq * 2. * PI;
00152     }
00153 
00154   } /* if ( mode & PROC_DO_FIT ) */
00155 
00156 
00157   /* ------------------------------ check whether to do DDC ? -------------------------------- */
00158   if ( mode & PROC_DO_DDC ) {
00159     
00160     // initial parameters
00161     freq = tdecay = 0.;
00162 
00163     // where does the ddc get its freq and tdecay parameters from ?
00164     if ( mode & PROC_DDC_FITFREQ ) {
00165       if ( have_fit_pars ) freq = proc->fit_freq;
00166       else freq = cal->freq; // asked for fit but it failed :(
00167     } else if ( mode & PROC_DDC_FFTFREQ ) {
00168       if ( have_fft_pars ) freq = proc->fft_freq;
00169       else freq = cal->freq; // asked for fft but it failed :(
00170     } else {
00171       // use default
00172       freq = cal->freq;
00173     }
00174 
00175     // same for tdecay
00176     if ( mode & PROC_DDC_FITTDECAY ) {
00177       if ( have_fit_pars ) tdecay = proc->fit_tdecay;
00178       else tdecay = cal->tdecay; // asked for fit but it failed :(
00179     } else if ( mode & PROC_DDC_FFTTDECAY ) {
00180       if ( have_fft_pars ) tdecay = proc->fft_tdecay;
00181       else tdecay = cal->tdecay; // asked for fft but it failed :(
00182     } else {
00183       // use default
00184       tdecay = cal->tdecay;
00185     }
00186     
00187     // do the downconversion...
00188     if ( ddc_sample_waveform( sig->wf, bpm->digi_nsamples, bpm->digi_nbits, bpm->digi_freq,
00189                               trig->t0, cal->t0Offset, freq, tdecay, 
00190                               cal->ddcfiltBW, cal->ddcepsFilt, 
00191                               &(proc->ddc_amp), &(proc->ddc_phase) ) == BPM_FAILURE ) {
00192       sprintf( msg, "Could not downconvert BPM %s waveform in process_waveform(...)", bpm->name );
00193       bpm_warning( msg, __FILE__, __LINE__ );
00194     } else {
00195 
00196       proc->ddc_success = TRUE;
00197 
00198       if ( mode & PROC_DDC_STOREFULL ) {
00199         // if the sampling ddc failed, no need in trying to get the whole waveform
00200         // otherwise, if requestes, let's do it here...
00201         ddc_waveform( sig->wf, bpm->digi_nsamples, bpm->digi_nbits, bpm->digi_freq,
00202                       trig->t0, freq, tdecay, cal->ddcfiltBW, cal->ddcepsFilt,
00203                       proc->ddcwf );
00204         
00205 
00206         // HERE if the user request to fit the DDC waveform we can update the
00207         // proc->ddc_tdecay from the fitted waveform
00208         // so need to implement something like
00209         
00210         // fit_ddc( proc->ddcwf, bpm->digi_nsamples, bpm->digi_freq, &(proc->ddc_tdecay) );
00211 
00212       }
00213 
00214 
00215     }
00216 
00217     
00218   } /* if ( mode & PROC_DO_DDC ) */
00219 
00220   return BPM_SUCCESS;
00221 }

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