bpmwf/doublewf.c

Go to the documentation of this file.
00001 
00006 #include  <bpm/bpm_wf.h>
00007 
00008 doublewf_t* doublewf( int ns, double fs ) {
00009   
00010   doublewf_t *w;
00011 
00012   if ( fs <= 0 ) {
00013     bpm_error( "Cannot have sampling frequency <= 0. in doublewf()",
00014                __FILE__, __LINE__ );
00015     return NULL;
00016   }
00017 
00018   if ( ns > MAX_ALLOWED_NS ) {
00019     bpm_error( "Maximum allowed number of samples exceeded, failed to allocate.",
00020                __FILE__, __LINE__ );
00021     return NULL;
00022   }
00023 
00024   if ( ns > 1 ) {
00025     w = (doublewf_t*) calloc( 1, sizeof(doublewf_t) );
00026     if ( ! w ) {
00027       bpm_error( "Cannot allocate memory for waveform structure in doublewf()",
00028                  __FILE__, __LINE__ );
00029       return NULL;
00030     }
00031     w->ns = ns;
00032     w->fs = fs;
00033     w->wf = (double*) calloc( w->ns, sizeof( double ) );
00034     if ( ! w->wf ) {
00035       bpm_error( "Cannot allocate memory for waveform data in doublewf()",
00036                  __FILE__, __LINE__ );
00037       free( w );
00038       return NULL;
00039     }
00040   } else {
00041     bpm_error( "Invalid number of samples in doublewf()", __FILE__, __LINE__ );
00042     return NULL;
00043   }
00044 
00045   return w;
00046 }
00047 
00048 // ----------------------------------------------------------------------------
00049 
00050 doublewf_t* doublewf_sample_series( int ns, double fs ) {
00051 
00052   int i = 0;
00053   doublewf_t *w = doublewf( ns, fs );
00054 
00055   if ( ! w ) return w;
00056   for ( i=0; i<w->ns; i++ ) w->wf[i] = (double) i;
00057 
00058   return w;
00059 }
00060 
00061 // ----------------------------------------------------------------------------
00062 
00063 doublewf_t* doublewf_time_series( int ns, double fs ) {
00064 
00065   int i = 0;
00066   doublewf_t *w = doublewf( ns, fs );
00067 
00068   if ( ! w ) return w;
00069   for ( i=0; i<w->ns; i++ ) w->wf[i] = (double) i / w->fs;
00070 
00071   return w;
00072 }
00073 
00074 // ----------------------------------------------------------------------------
00075 
00076 doublewf_t* doublewf_frequency_series( int ns, double fs ) {
00077 
00078   int i = 0;
00079   doublewf_t *w = doublewf( ns, fs );
00080 
00081   if ( ! w ) return w;
00082   for ( i=0; i<w->ns; i++ ) w->wf[i] = (double) i * w->fs / (double) w->ns;
00083 
00084   return w;
00085 }
00086 
00087 // ----------------------------------------------------------------------------
00088 
00089 doublewf_t* doublewf_copy_new( doublewf_t *w ) {
00090   
00091   int i = 0;
00092   doublewf_t *s = doublewf( w->ns, w->fs );
00093   
00094   if ( ! s ) {
00095     bpm_error( "Cannot allocate memory in doublewf_copy_new()", __FILE__, __LINE__ );
00096     return NULL;
00097   };
00098 
00099   for ( i=0; i<w->ns; i++ ) s->wf[i] = w->wf[i];
00100 
00101   return s;
00102 }
00103 
00104 // ----------------------------------------------------------------------------
00105 
00106 int doublewf_copy( doublewf_t *copy, doublewf_t *src ) {
00107   
00108   int i = 0;
00109 
00110   if ( ! copy || ! src ) {
00111     bpm_error( "Invalid pointer arguments in doublewf_copy()", __FILE__, __LINE__ );
00112     return BPM_FAILURE;
00113   };
00114 
00115   if ( doublewf_compat( copy, src ) ) {
00116     for ( i=0; i<copy->ns; i++ ) copy->wf[i] = src->wf[i];
00117   } else {
00118     bpm_error( "Incompatible waveforms for in doublewf_copy()", __FILE__, __LINE__ );
00119     return BPM_FAILURE;
00120   }
00121 
00122   return BPM_SUCCESS;
00123 }
00124 
00125 // ----------------------------------------------------------------------------
00126 
00127 int doublewf_subset( doublewf_t *sub, doublewf_t *w, int i1, int i2 ) {
00128   
00129   int i = 0;
00130 
00131   if ( ! sub || ! w ) {
00132     bpm_error( "Invalid pointer arguments in doublewf_subset()", __FILE__, __LINE__ );
00133     return BPM_FAILURE;
00134   };
00135 
00136   // reset the number of samples in the subset
00137   sub->ns = 0;
00138   sub->fs = w->fs;
00139 
00140   for ( i=MAX(0,i1); i<=MIN(w->ns-1,i2); i++ ) {
00141     sub->wf[i] = w->wf[i-i1];
00142     sub->ns++;
00143   }
00144 
00145 
00146   return BPM_SUCCESS;
00147 }
00148 
00149 // ----------------------------------------------------------------------------
00150 
00151 int doublewf_setvalues( doublewf_t *w, double *x ) {
00152 
00153   int i = 0;
00154   if ( ! w || ! x ) {
00155     bpm_error( "Invalid pointer arguments in doublewf_setvalues()",
00156                __FILE__, __LINE__ );
00157     return BPM_FAILURE;
00158   }
00159 
00160   for ( i=0; i<w->ns; i++ ) w->wf[i] = x[i];
00161 
00162   return BPM_SUCCESS;
00163 }
00164 
00165 // ----------------------------------------------------------------------------
00166 
00167 int doublewf_setfunction( doublewf_t *w, 
00168                           double (*wffun)( double, int, double* ),
00169                           int npars, double *par ) {
00170 
00171   int i = 0;
00172   if ( ! w || ! wffun ) {
00173     bpm_error( "Invalid pointer arguments in doublewf_setfunction()",
00174                __FILE__, __LINE__ );
00175     return BPM_FAILURE;
00176   }
00177 
00178   for ( i=0; i<w->ns; i++ ) w->wf[i] = (*wffun)( (double) i / w->fs, npars, par );
00179 
00180   return BPM_SUCCESS;
00181 }
00182 
00183 // ----------------------------------------------------------------------------
00184 
00185 int doublewf_reset( doublewf_t *w ) {
00186 
00187   int i = 0;
00188 
00189   if ( ! w  ) {
00190     bpm_error( "Invalid pointer argument in doublewf_reset()", 
00191                __FILE__, __LINE__ );
00192     return BPM_FAILURE;
00193   }
00194 
00195   for ( i=0; i<w->ns; i++ ) w->wf[i] = 0.;
00196 
00197   return BPM_SUCCESS;
00198 }
00199 
00200 // ----------------------------------------------------------------------------
00201 
00202 void doublewf_delete( doublewf_t *w ) {
00203 
00204   if ( w ) {
00205     if ( w->wf ) free( w->wf ); else
00206       bpm_warning( "Cannot free doublewf_t::wf pointer in doublewf()_delete, already NULL !",
00207                    __FILE__, __LINE__ );
00208     free( w );
00209   } else {
00210     bpm_warning( "Cannot free doublewf_t pointer in doublewf()_delete, already NULL !", 
00211                  __FILE__, __LINE__ );
00212   }
00213   
00214   return;
00215 }
00216 
00217 // ----------------------------------------------------------------------------
00218 
00219 intwf_t* intwf_cast_new( doublewf_t *w ) {
00220 
00221   int      i = 0;
00222   intwf_t *iw;
00223 
00224   if ( ! w ) {
00225     bpm_error( "Invalid pointer argument in intwf_cast_new()", 
00226                __FILE__, __LINE__ );
00227     return NULL;
00228   }
00229 
00230   iw = intwf( w->ns, w->fs );
00231   if ( ! iw ) {
00232     bpm_error( "Cannot allocate memory for intwf_t in intwf_cast_new()",
00233                __FILE__, __LINE__ );
00234     return NULL;
00235   }
00236 
00237   // cast to the integer waveform
00238   for (i=0;i<iw->ns;i++) iw->wf[i] = (int) dround( w->wf[i] );
00239 
00240   return iw;
00241 }
00242 
00243 // ----------------------------------------------------------------------------
00244 
00245 int intwf_cast( intwf_t *iw, doublewf_t *w ) {
00246 
00247   int      i = 0;
00248 
00249   if ( ! w || ! iw ) {
00250     bpm_error( "Invalid pointer argument in intwf_cast()", 
00251                __FILE__, __LINE__ );
00252     return BPM_FAILURE;
00253   }
00254 
00255   // cast to the integer waveform
00256   for (i=0;i<iw->ns;i++) iw->wf[i] = (int) dround( w->wf[i] );
00257 
00258   return BPM_SUCCESS;
00259 }
00260 
00261 // ----------------------------------------------------------------------------
00262 
00263 int doublewf_compat( doublewf_t *w1, doublewf_t *w2 ) {
00264 
00265   if ( ! w1 || ! w2 ) {
00266     bpm_error( "Invalid pointer arguments in doublewf_compat()", 
00267                __FILE__, __LINE__ );
00268     return 0;
00269   }
00270   
00271   return ((w1->ns==w2->ns)&&(fabs(w1->fs-w2->fs)<WF_EPS)?1:0);
00272 }
00273 
00274 // ----------------------------------------------------------------------------
00275 
00276 int doublewf_add( doublewf_t *w1, doublewf_t *w2 ) {
00277 
00278   int i = 0;
00279 
00280   if ( ! w1 || ! w2 ) {
00281     bpm_error( "Invalid pointer arguments in doublewf_add()", 
00282                __FILE__, __LINE__ );
00283     return BPM_FAILURE;
00284   }
00285 
00286   if ( ! doublewf_compat( w1, w2 ) ) {
00287     bpm_warning( "Incompatible waveforms in doublewf_add()", __FILE__, __LINE__ );
00288   }
00289 
00290   for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] += w2->wf[i];
00291   
00292   return BPM_SUCCESS;
00293 }
00294 
00295 // ----------------------------------------------------------------------------
00296 
00297 int doublewf_subtract( doublewf_t *w1, doublewf_t *w2 ) {
00298   
00299   int i = 0;
00300   
00301   if ( ! w1 || ! w2 ) {
00302     bpm_error( "Invalid pointer arguments in doublewf_subtract()", 
00303                __FILE__, __LINE__ );
00304     return BPM_FAILURE;
00305   }
00306 
00307   if ( ! doublewf_compat( w1, w2 ) ) {
00308     bpm_warning( "Incompatible waveforms in doublewf_subtract()", __FILE__, __LINE__ );
00309   }
00310   for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] -= w2->wf[i];
00311   
00312   return BPM_SUCCESS;
00313 }
00314 
00315 // ----------------------------------------------------------------------------
00316 
00317 int doublewf_multiply( doublewf_t *w1, doublewf_t *w2 ) {
00318 
00319   int i = 0;
00320   
00321   if ( ! w1 || ! w2 ) {
00322     bpm_error( "Invalid pointer arguments in doublewf_multiply()", 
00323                __FILE__, __LINE__ );
00324     return BPM_FAILURE;
00325   }
00326 
00327   if ( ! doublewf_compat( w1, w2 ) ) {
00328     bpm_warning( "Incompatible waveforms in doublewf_multiply()", 
00329                  __FILE__, __LINE__ );
00330   }
00331   for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] *= w2->wf[i];
00332 
00333   return BPM_SUCCESS;
00334 }
00335 
00336 // ----------------------------------------------------------------------------
00337 
00338 int doublewf_divide( doublewf_t *w1, doublewf_t *w2 ) {
00339   
00340   int i = 0;
00341   
00342   if ( ! w1 || ! w2 ) {
00343     bpm_error( "Invalid pointer arguments in doublewf_divide()", 
00344                __FILE__, __LINE__ );
00345     return BPM_FAILURE;
00346   }
00347 
00348   if ( ! doublewf_compat( w1, w2 ) ) {
00349     bpm_warning( "Incompatible waveforms in doublewf_divide()", 
00350                  __FILE__, __LINE__ );
00351   }
00352 
00353   for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) {
00354     if ( w2->wf[i] != 0. ) {
00355       w1->wf[i] /= w2->wf[i] ;
00356     } else {
00357       bpm_warning( "Trapped division by 0. in doublewf_divide()", 
00358                    __FILE__, __LINE__ );
00359       w1->wf[i] = 0.;
00360     } 
00361   } 
00362 
00363   return BPM_SUCCESS;
00364 }
00365 
00366 // ----------------------------------------------------------------------------
00367 
00368 int doublewf_scale( double f, doublewf_t *w ) {
00369 
00370   int i = 0;
00371   
00372   if ( ! w ) {
00373     bpm_error( "Invalid pointer argument in doublewf_scale()", 
00374                __FILE__, __LINE__ );
00375     return BPM_FAILURE;
00376   }
00377 
00378   for ( i=0; i<w->ns; i++ ) w->wf[i] *= f;
00379 
00380   return BPM_SUCCESS;
00381 }
00382 
00383 // ----------------------------------------------------------------------------
00384 
00385 int doublewf_bias( double c, doublewf_t *w ) {
00386 
00387   int i = 0;
00388   
00389   if ( ! w ) {
00390     bpm_error( "Invalid pointer argument in doublewf_bias()", 
00391                __FILE__, __LINE__ );
00392     return BPM_FAILURE;
00393   }
00394 
00395   for ( i=0; i<w->ns; i++ ) w->wf[i] += c;
00396 
00397   return BPM_SUCCESS;
00398 }
00399 
00400 // ----------------------------------------------------------------------------
00401 
00402 int doublewf_add_cwtone( doublewf_t *w, double amp, double phase, double freq,
00403                          double phasenoise ) {
00404 
00405   int i = 0;
00406   
00407   if ( ! w ) {
00408     bpm_error( "Invalid pointer argument in doublewf_add_cwtone()", 
00409                __FILE__, __LINE__ );
00410     return BPM_FAILURE;
00411   }
00412 
00413   for (i=0; i<w->ns; i++ ) 
00414     w->wf[i] += amp * cos( 2. * PI * freq * (double) i /  w->fs + 
00415                            nr_rangauss( phase, phasenoise ) );
00416   
00417   return BPM_SUCCESS;
00418 }
00419 
00420 // ----------------------------------------------------------------------------
00421 
00422 int doublewf_add_dcywave( doublewf_t *w, double amp, double phase, double freq, 
00423                           double ttrig, double tdcy, double phasenoise ) {
00424 
00425   int    i = 0;
00426   double t = 0.;
00427 
00428   if ( ! w ) {
00429     bpm_error( "Invalid pointer argument in doublewf_add_dcywave()", 
00430                __FILE__, __LINE__ );
00431     return BPM_FAILURE;
00432   }
00433 
00434   for (i=0; i<w->ns; i++ ) {
00435     t = (double) i / w->fs;
00436     if ( t >= ttrig ) {
00437       w->wf[i] += amp * exp( -( t - ttrig ) / tdcy ) * 
00438         cos( 2. * PI * freq * ( t - ttrig ) + nr_rangauss( phase, phasenoise ) );
00439     }
00440   }
00441 
00442   return BPM_SUCCESS;
00443 }
00444 
00445 // ----------------------------------------------------------------------------
00446 
00447 int doublewf_add_ampnoise( doublewf_t *w, double sigma ) {
00448   
00449   int i = 0;
00450 
00451   if ( ! w ) {
00452     bpm_error( "Invalid pointer argument in doublewf_add_ampnoise()", 
00453                __FILE__, __LINE__ );
00454     return BPM_FAILURE;
00455   }
00456 
00457   for (i=0; i<w->ns; i++ ) {
00458     w->wf[i] += nr_rangauss( 0., sigma );
00459   }
00460 
00461   return BPM_SUCCESS;
00462 
00463 }
00464 
00465 // ----------------------------------------------------------------------------
00466 
00467 int doublewf_basic_stats( doublewf_t *w, int s0, int s1, wfstat_t *stats ) {
00468   
00469   int i = 0;
00470 
00471   if ( ! w || ! stats ) {
00472     bpm_error( "Invalid pointer arguments in doublewf_basic_stats()", 
00473                __FILE__, __LINE__ );
00474     return BPM_FAILURE;
00475   }
00476 
00477   // reset statistics
00478   wfstat_reset( stats );
00479 
00480   // check the limits
00481   if ( s0 > s1 ) {
00482     bpm_warning( "Swapping limits in doublewf_basic_stats()", __FILE__, __LINE__ );
00483     i=s1; s1=s0; s0=i;
00484   }
00485 
00486   // check boundaries
00487   if ( s0 <  0     ) s0 = 0;
00488   if ( s1 >= w->ns ) s1 = w->ns-1;
00489 
00490   for (i=s0; i<=s1; i++ ) {
00491 
00492     stats->mean += w->wf[i];
00493     stats->rms  += SQR( w->wf[i] );
00494 
00495     if ( w->wf[i] > stats->max ) { stats->max = w->wf[i]; stats->imax = i; }
00496     if ( w->wf[i] < stats->min ) { stats->min = w->wf[i]; stats->imin = i; }
00497   }
00498 
00499   stats->mean /= (double) ( s1 - s0 + 1.);
00500   stats->rms   = sqrt( stats->rms / (double) ( s1 - s0 + 1.) - SQR( stats->mean ) );
00501 
00502   return BPM_SUCCESS;
00503 }
00504 
00505 // ----------------------------------------------------------------------------
00506 
00507 int doublewf_derive( doublewf_t *w ) {
00508 
00509   int     i = 0;
00510   double dt = 0;
00511 
00512   if ( ! w ) {
00513     bpm_error( "Invalid pointer argument in doublewf_derive()", 
00514                __FILE__, __LINE__ );
00515     return BPM_FAILURE;
00516   }
00517   
00518   // the time step...
00519   dt = 1./w->fs;
00520 
00521   // derivative...
00522   for ( i=0; i<w->ns-1; i++ ) w->wf[i] = ( w->wf[i+1] - w->wf[i] ) / dt;
00523   
00524   // the last sample.. extrapolate linear, so same slope
00525   w->wf[w->ns-1] = w->wf[w->ns-2];
00526   
00527   return BPM_SUCCESS;
00528 }
00529 
00530 // ----------------------------------------------------------------------------
00531 
00532 int doublewf_integrate( doublewf_t *w ) {
00533 
00534   int     i = 0;
00535   double dt = 0;
00536 
00537   if ( ! w ) {
00538     bpm_error( "Invalid pointer argument in doublewf_integrate()", 
00539                __FILE__, __LINE__ );
00540     return BPM_FAILURE;
00541   }
00542 
00543   // the time step...
00544   dt = 1./w->fs;
00545 
00546   // integral
00547   for ( i=0; i<w->ns; i++ ) {
00548     w->wf[i] *= dt;
00549     if ( i > 0 ) w->wf[i] += w->wf[i-1];
00550   }
00551   
00552   return BPM_SUCCESS;
00553 }
00554 
00555 // ----------------------------------------------------------------------------
00556 void doublewf_print( FILE *of, doublewf_t *w ) {
00557 
00558   int i = 0;
00559   if ( !of || !w ) {
00560     bpm_error( "Invalid pointers in doublewf_print()", __FILE__, __LINE__ );
00561     return;
00562   }
00563 
00564   fprintf( of, "Waveform:\n" );
00565   fprintf( of, "Number of samples  : %d\n",     w->ns );
00566   fprintf( of, "Sampling frequency : %f MHz\n", w->fs / MHz );
00567   for( i = 0; i < w->ns; i++ )  fprintf( of, "  wf[%5d] = %.14e \n", i, w->wf[i] );
00568   fflush( of );
00569 
00570   return;
00571 }
00572 
00573 // ----------------------------------------------------------------------------
00574 
00575 double doublewf_getvalue( doublewf_t *w, double t, unsigned int mode ) {
00576   
00577   double val = 0.;
00578   int i = 0, i0 = 0, i1 = 0;
00579   
00580   int lanczos_a = 3; // order or something, kernel width...
00581 
00582   if ( ! w ) {
00583     bpm_error( "Invalid pointer argument in doublewf_sample()", 
00584                __FILE__, __LINE__ );
00585     return -DBL_MAX;
00586   }
00587   
00588   // lanczos(x) kernel interpolate, best for waveform reconstrucution
00589   if ( mode & WF_LANCZOS ) {
00590     for ( i=0; i<w->ns; i++ ) {
00591       val += w->wf[i] * lanczos( ( t - (double) i / w->fs ) * w->fs, lanczos_a );
00592     }
00593     return val;
00594 
00595   } 
00596 
00597   // sinc(x) kernel interpolate, good for waveform reconstrucution
00598   if ( mode & WF_SINC ) {
00599     for ( i=0; i<w->ns; i++ ) {
00600       val += w->wf[i] * sinc( ( t - (double) i / w->fs ) * w->fs );
00601     }
00602     return val;
00603 
00604   } 
00605 
00606   // determine the two closest samples
00607   i0 = (int) ( t * w->fs );
00608   i1 = i0 + 1;
00609   
00610   if ( i0 < 0 ) i0 = 0;
00611   if ( i0 > w->ns-2 ) i0 = w->ns-2;
00612 
00613   if ( i1 < 1 ) i1 = 1;
00614   if ( i1 > w->ns-1 ) i1 = w->ns-1;
00615   
00616 
00617   // linear interpolation
00618   if ( mode & WF_LINEAR ) {
00619     val = w->wf[i0] + ( w->wf[i1] - w->wf[i0] ) * ( t * w->fs - (double) i0 );
00620     return val;
00621   }
00622 
00623 
00624   // parabolic interpolation
00625   if ( mode & WF_QUADRATIC ) {
00626 
00627     if ( ( t*w->fs - (double) i0 ) < 0.5 ) {
00628       if ( i0 > 0 ) {
00629         return nr_quadinterpol( t, 
00630                                 (double)(i0-1)/w->fs, (double)i0/w->fs, (double)(i1)/w->fs,
00631                                 w->wf[i0-1], w->wf[i0], w->wf[i1] );
00632       } else {
00633         return nr_quadinterpol( t, 
00634                                 (double)i0/w->fs, (double)i1/w->fs, (double)(i1+1)/w->fs,
00635                                 w->wf[i0], w->wf[i1], w->wf[i1+1] );
00636       }
00637 
00638     } else {
00639 
00640       if ( i1 < w->ns-1 ) {
00641         return nr_quadinterpol( t, 
00642                                 (double)i0/w->fs, (double)i1/w->fs, (double)(i1+1)/w->fs,
00643                                 w->wf[i0], w->wf[i1], w->wf[i1+1] );
00644       } else {
00645         return nr_quadinterpol( t, 
00646                                 (double)(i0-1)/w->fs, (double)i0/w->fs, (double)(i1)/w->fs,
00647                                 w->wf[i0-1], w->wf[i0], w->wf[i1] );
00648       }
00649 
00650     }
00651 
00652   }
00653 
00654   // no interpolation ( WF_NEAREST )
00655   if ( ( t * w->fs - (double) i0 ) < 0.5 ) {
00656     return w->wf[i0];
00657   } else return w->wf[i1];
00658 
00659   return -DBL_MAX;
00660 }
00661 
00662 // ----------------------------------------------------------------------------
00663 
00664 int doublewf_resample( doublewf_t *w2, double fs, doublewf_t *w1, unsigned int mode ) {
00665 
00666   int i = 0;
00667   if ( ! w1 || ! w2 ) {
00668     bpm_error( "Invalid pointer arguments in doublewf_resample()",
00669                __FILE__, __LINE__ );
00670     return BPM_FAILURE;
00671   }
00672 
00673   // number of samples
00674   w2->ns = (int) (w1->ns * fs / w1->fs);
00675   w2->fs = fs;
00676 
00677   if ( w2->ns > MAX_ALLOWED_NS ) {
00678     bpm_error( "Maximum allowed number of samples exceeded in doublewf_resample()",
00679                __FILE__, __LINE__ );
00680     return BPM_FAILURE;
00681   }
00682 
00683   if ( w2->ns < 1 ) {
00684     bpm_error( "Number of new samples is zero in doublewf_resample()",
00685                __FILE__, __LINE__ );
00686     return BPM_FAILURE;
00687   }
00688 
00689   // fill the new waveform
00690   for ( i=0; i<w2->ns; i++ ) {
00691     w2->wf[i] = doublewf_getvalue( w1, (double) i / w2->fs, mode );
00692   }
00693 
00694 
00695   return BPM_SUCCESS;
00696 }

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