00001
00002
00003
00004
00005
00006
00007 #include "afni.h"
00008
00009 #ifndef ALLOW_PLUGINS
00010 # error "Plugins not properly set up -- see machdep.h"
00011 #endif
00012
00013
00014
00015
00016
00017
00018
00019 static char helpstring[] =
00020 " Purpose: Control the 'LSqFit' and 'LSqDtr 1D functions.\n"
00021 "\n"
00022 " Parameters: Baseline = 'Constant' or 'Linear'\n"
00023 " Is the baseline 'a' or 'a+b*t'?\n"
00024 " Ignore = Number of points to ignore at\n"
00025 " start of each timeseries.\n"
00026 " \n"
00027 " Sinusoids: Period = Fundamental period to use.\n"
00028 " Harmonics = Number of overtones to use.\n"
00029 " \n"
00030 " Timeseries: File = Input timeseries file to use.\n"
00031 ;
00032
00033 static char plehstring[] =
00034 " Purpose: Generate a timeseries and store in AFNI list\n"
00035 "\n"
00036 " Parameters: Delta = time step between points\n"
00037 " Length = number of points\n"
00038 "\n"
00039 " Output: Label = String to label timeseries by\n"
00040 " in AFNI choosers\n"
00041 "\n"
00042 " Polynomial: Order = Maximum power to include\n"
00043 " (Chebyshev polynomials are used)\n"
00044 "\n"
00045 " Sinusoid: Period = Fundamental period to use.\n"
00046 " Harmonics = Number of overtones to use.\n"
00047 ;
00048
00049
00050
00051 #define NBASE 3
00052 static char * baseline_strings[NBASE] = { "Constant" , "Linear" , "Quadratic" } ;
00053
00054
00055
00056 char * LSQ_main( PLUGIN_interface * ) ;
00057
00058 void LSQ_fitter( int nt, double to, double dt, float * vec, char ** label ) ;
00059 void LSQ_detrend( int nt, double to, double dt, float * vec, char ** label ) ;
00060 void LSQ_worker( int nt, double dt, float * vec, int dofit, char ** label ) ;
00061
00062 PLUGIN_interface * TSGEN_init(void) ;
00063 char * TSGEN_main( PLUGIN_interface * ) ;
00064
00065 PLUGIN_interface * EXP0D_init(void) ;
00066 char * EXP0D_main( PLUGIN_interface * ) ;
00067 void EXP0D_worker( int num , float * vec ) ;
00068
00069 #ifdef ALLOW_LOMO
00070 PLUGIN_interface * LOMOR_init(void) ;
00071 char * LOMOR_main( PLUGIN_interface * ) ;
00072 void LOMOR_fitter() ;
00073 #endif
00074
00075
00076
00077 static PLUGIN_interface * global_plint = NULL ;
00078
00079 #define NRMAX_SIN 2
00080 #define NRMAX_TS 2
00081 #define HARM_MAX 22
00082
00083 static int polort=1 , ignore=3 , nrsin=0 , nrts=0 , initialize=1 ;
00084 static float sinper[NRMAX_SIN] ;
00085 static int sinharm[NRMAX_SIN] ;
00086 static MRI_IMAGE * tsim[NRMAX_TS] ;
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 DEFINE_PLUGIN_PROTOTYPE
00104
00105 PLUGIN_interface * PLUGIN_init( int ncall )
00106 {
00107 int ii ;
00108 PLUGIN_interface * plint ;
00109
00110 if( ncall > 3 ) return NULL ;
00111
00112 if( ncall == 1 ) return TSGEN_init() ;
00113 if( ncall == 2 ) return EXP0D_init() ;
00114 #ifdef ALLOW_LOMO
00115 if( ncall == 3 ) return LOMOR_init() ;
00116 #else
00117 if( ncall == 3 ) return NULL ;
00118 #endif
00119
00120
00121
00122
00123
00124 plint = PLUTO_new_interface( "LSqFit & Dtr" ,
00125 "Control LSqFit and LSqDtr Functions" ,
00126 helpstring ,
00127 PLUGIN_CALL_VIA_MENU , LSQ_main ) ;
00128
00129 global_plint = plint ;
00130
00131 PLUTO_set_sequence( plint , "A:funcs:fitting" ) ;
00132
00133 PLUTO_add_hint( plint , "Control LSqFit and LSqDtr Functions" ) ;
00134
00135 PLUTO_set_runlabels( plint , "Set+Keep" , "Set+Close" ) ;
00136
00137
00138
00139 PLUTO_add_option( plint , "Parameters" , "Parameters" , TRUE ) ;
00140
00141 PLUTO_add_string( plint , "Baseline" , NBASE , baseline_strings , 1 ) ;
00142
00143 PLUTO_add_number( plint , "Ignore" , 0,20,0,3 , FALSE ) ;
00144
00145
00146
00147 for( ii=0 ; ii < NRMAX_SIN ; ii++ ){
00148 PLUTO_add_option( plint , "Sinusoid" , "Sinusoid" , FALSE ) ;
00149 PLUTO_add_number( plint , "Period" , 0,99999,0,20, TRUE ) ;
00150 PLUTO_add_number( plint , "Harmonics" , 1,HARM_MAX,0,1 , FALSE ) ;
00151 }
00152
00153
00154
00155 for( ii=0 ; ii < NRMAX_TS ; ii++ ){
00156 PLUTO_add_option( plint , "Timeseries" , "Timeseries" , FALSE ) ;
00157 PLUTO_add_timeseries( plint , "File" ) ;
00158 }
00159
00160
00161
00162 PLUTO_register_1D_funcstr( "LSqFit" , LSQ_fitter ) ;
00163 PLUTO_register_1D_funcstr( "LSqDtr" , LSQ_detrend ) ;
00164
00165 return plint ;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 char * LSQ_main( PLUGIN_interface * plint )
00175 {
00176 char * str ;
00177 int ii ;
00178 float * tsar ;
00179
00180
00181
00182 PLUTO_next_option(plint) ;
00183
00184 str = PLUTO_get_string(plint) ;
00185 polort = PLUTO_string_index( str , NBASE , baseline_strings ) ;
00186
00187 ignore = PLUTO_get_number(plint) ;
00188
00189
00190
00191 nrsin = nrts = 0 ;
00192 do {
00193 str = PLUTO_get_optiontag(plint) ; if( str == NULL ) break ;
00194
00195 if( strcmp(str,"Sinusoid") == 0 ){
00196
00197 sinper[nrsin] = PLUTO_get_number(plint) ;
00198 sinharm[nrsin] = PLUTO_get_number(plint) - 1.0 ;
00199 if( sinper[nrsin] <= 0.0 )
00200 return "************************\n"
00201 "Illegal Sinusoid Period!\n"
00202 "************************" ;
00203
00204 nrsin++ ;
00205
00206 } else if( strcmp(str,"Timeseries") == 0 ){
00207
00208 tsim[nrts] = PLUTO_get_timeseries(plint) ;
00209
00210 if( tsim[nrts] == NULL || tsim[nrts]->nx < 3 || tsim[nrts]->kind != MRI_float )
00211 return "*************************\n"
00212 "Illegal Timeseries Input!\n"
00213 "*************************" ;
00214
00215 tsar = MRI_FLOAT_PTR(tsim[nrts]) ;
00216 for( ii=ignore ; ii < tsim[nrts]->nx && tsar[ii] >= WAY_BIG ; ii++ ) ;
00217 ignore = ii ;
00218 nrts++ ;
00219
00220 } else {
00221 return "************************\n"
00222 "Illegal optiontag found!\n"
00223 "************************" ;
00224 }
00225 } while(1) ;
00226
00227
00228
00229 initialize = 1 ;
00230
00231
00232
00233 { int nref , ks ;
00234 char str[64] ;
00235
00236 nref = (polort+1) + nrts ;
00237 for( ks=0 ; ks < nrsin ; ks++ ) nref += 2*(sinharm[ks]+1) ;
00238 sprintf(str," \nNumber of fit parameters = %d\n",nref) ;
00239 PLUTO_popup_transient( plint , str ) ;
00240 }
00241
00242 return NULL ;
00243 }
00244
00245
00246
00247
00248
00249 void LSQ_fitter( int nt , double to , double dt , float * vec , char ** label )
00250 {
00251 LSQ_worker( nt , dt , vec , TRUE , label ) ;
00252 return ;
00253 }
00254
00255 void LSQ_detrend( int nt , double to , double dt , float * vec , char ** label )
00256 {
00257 LSQ_worker( nt , dt , vec , FALSE , label ) ;
00258 return ;
00259 }
00260
00261 static char lbuf[4096] ;
00262 static char sbuf[256] ;
00263
00264 void LSQ_worker( int nt , double dt , float * vec , int dofit , char ** label )
00265 {
00266 int nlen , nref ;
00267
00268 static int nlen_old = -666 , nref_old = -666 ;
00269 static double dt_old = -666.666 ;
00270 static float ** ref = NULL ;
00271 static double * dch = NULL ;
00272
00273 int ir , ii , ks,jh , j;
00274 float fac , tm , val ;
00275 float * fit , * tsar ;
00276
00277
00278
00279 nref = (polort+1) + nrts ;
00280 for( ks=0 ; ks < nrsin ; ks++ ) nref += 2*(sinharm[ks]+1) ;
00281
00282
00283
00284 nlen = nt - ignore ;
00285
00286 if( nlen <= nref ) return ;
00287
00288
00289
00290
00291
00292
00293
00294 if( nlen != nlen_old || nref != nref_old ||
00295 initialize || (dt != dt_old && nrsin > 0) ){
00296
00297
00298
00299 if( ref != NULL ){
00300 for( ir=0 ; ir < nref_old ; ir++ ) if( ref[ir] != NULL ) free(ref[ir]) ;
00301 free(ref) ;
00302 }
00303 if( dch != NULL ) free(dch) ;
00304
00305
00306
00307 ref = (float **) malloc( sizeof(float *) * nref ) ;
00308 if( ref == NULL ){fprintf(stderr,"\nmalloc error in plug_lsqfit\n\a");
00309 return;
00310
00311 }
00312 for( ir=0 ; ir < nref ; ir++ ){
00313 ref[ir] = (float *) malloc( sizeof(float) * nlen ) ;
00314 if( ref[ir] == NULL ){
00315 fprintf(stderr,"\nmalloc error in plug_lsqfit\n\a");
00316 for(j=0;j<=ir;j++)
00317 free(ref[j]);
00318 free(ref);
00319 ref = NULL;
00320 return;
00321
00322 }
00323 }
00324 nlen_old = nlen ;
00325 nref_old = nref ;
00326 dt_old = dt ;
00327
00328
00329
00330
00331
00332 for( ii=0 ; ii < nlen ; ii++ ) ref[0][ii] = 1.0 ;
00333
00334 ir = 1 ;
00335 if( polort > 0 ){
00336
00337
00338
00339 tm = 0.5 * (nlen-1.0) ; fac = 2.0 / nlen ;
00340 for( ii=0 ; ii < nlen ; ii++ ) ref[1][ii] = (ii-tm)*fac ;
00341 ir = 2 ;
00342
00343
00344
00345 for( ; ir <= polort ; ir++ )
00346 for( ii=0 ; ii < nlen ; ii++ )
00347 ref[ir][ii] = pow( (ii-tm)*fac , (double)ir ) ;
00348 }
00349
00350 if( dt == 0.0 ) dt = 1.0 ;
00351
00352
00353
00354 for( ks=0 ; ks < nrsin ; ks++ ){
00355 for( jh=0 ; jh <= sinharm[ks] ; jh++ ){
00356 fac = (2.0*PI) * dt * (jh+1) / sinper[ks] ;
00357 for( ii=0 ; ii < nlen ; ii++ ){
00358 ref[ir] [ii] = cos( fac * ii ) ;
00359 ref[ir+1][ii] = sin( fac * ii ) ;
00360 }
00361 ir += 2 ;
00362 }
00363 }
00364
00365
00366
00367 for( ks=0 ; ks < nrts ; ks++ ){
00368 if( tsim[ks] == NULL || tsim[ks]->nx - ignore < nlen ){
00369 initialize = 1 ;
00370 fprintf(stderr,"Inadequate time series #%d in LSQ plugin\n\a",ks+1) ;
00371 return ;
00372 }
00373 tsar = MRI_FLOAT_PTR(tsim[ks]) ;
00374 for( ii=0 ; ii < nlen ; ii++ ) ref[ir][ii] = tsar[ii+ignore] ;
00375 ir++ ;
00376 }
00377
00378
00379
00380 dch = startup_lsqfit( nlen , NULL , nref , ref ) ;
00381 if( dch == NULL ){
00382 initialize = 1 ;
00383 fprintf(stderr,"Choleski error in LSQ plugin\n\a") ;
00384 return ;
00385 }
00386
00387 initialize = 0 ;
00388 }
00389
00390
00391
00392 fit = delayed_lsqfit( nlen , vec+ignore , nref , ref , dch ) ;
00393
00394 for( ii=0 ; ii < nlen ; ii++ ){
00395 val = 0.0 ;
00396 for( ir=0 ; ir < nref ; ir++ ) val += fit[ir] * ref[ir][ii] ;
00397
00398 vec[ii+ignore] = (dofit) ? val : vec[ii+ignore] - val ;
00399 }
00400
00401
00402
00403
00404 if( label != NULL ){
00405
00406 lbuf[0] = '\0' ;
00407
00408
00409
00410 ir = 0 ;
00411 sprintf(sbuf,"Coef of 1 = %g\n" , fit[ir++] ) ;
00412 strcat(lbuf,sbuf) ;
00413
00414 for( ; ir <= polort ; ){
00415 sprintf(sbuf,"Coef of t**%d = %g\n" , ir,fit[ir++] ) ;
00416 strcat(lbuf,sbuf) ;
00417 }
00418
00419 for( ks=0 ; ks < nrsin ; ks++ ){
00420 for( jh=0 ; jh <= sinharm[ks] ; jh++ ){
00421 fac = sinper[ks] / (jh+1) ;
00422 sprintf(sbuf,"Coef of cos(2*Pi*t/%g) = %g\n" , fac , fit[ir++] ) ;
00423 strcat(lbuf,sbuf) ;
00424 sprintf(sbuf,"Coef of sin(2*Pi*t/%g) = %g\n" , fac , fit[ir++] ) ;
00425 strcat(lbuf,sbuf) ;
00426 }
00427 }
00428
00429 for( ks=0 ; ks < nrts ; ks++ ){
00430 sprintf(sbuf,"Coef of %s = %g\n" , tsim[ks]->name , fit[ir++] ) ;
00431 strcat(lbuf,sbuf) ;
00432 }
00433
00434 *label = lbuf ;
00435 }
00436
00437 free(fit) ;
00438 return ;
00439 }
00440
00441
00442
00443 PLUGIN_interface * TSGEN_init(void)
00444 {
00445 PLUGIN_interface * plint ;
00446
00447
00448
00449 plint = PLUTO_new_interface( "TS Generate" ,
00450 "Generate a Timeseries" ,
00451 plehstring ,
00452 PLUGIN_CALL_VIA_MENU , TSGEN_main ) ;
00453
00454 PLUTO_add_hint( plint , "Generate a 1D Timeseries" ) ;
00455
00456
00457
00458 PLUTO_add_option( plint , "Parameters" , "Parameters" , TRUE ) ;
00459 PLUTO_add_number( plint , "Delta" , 0,99999,1, 0 , TRUE ) ;
00460 PLUTO_add_number( plint , "Length" , 3,9999,0,3 , TRUE ) ;
00461
00462
00463
00464 PLUTO_add_option( plint , "Output" , "Output" , TRUE ) ;
00465 PLUTO_add_string( plint , "Label" , 0,NULL , 19 ) ;
00466
00467
00468
00469 PLUTO_add_option( plint , "Polynomial" , "Polynomial" , FALSE ) ;
00470 PLUTO_add_number( plint , "Order" , 2,20,0,2 , FALSE ) ;
00471
00472
00473
00474 PLUTO_add_option( plint , "Sinusoid" , "Sinusoid" , FALSE ) ;
00475 PLUTO_add_number( plint , "Period" , 0,99999,0,20, TRUE ) ;
00476 PLUTO_add_number( plint , "Harmonics" , 1,HARM_MAX,0,1 , FALSE ) ;
00477
00478 return plint ;
00479 }
00480
00481 char * TSGEN_main( PLUGIN_interface * plint )
00482 {
00483 char * label , * str ;
00484 int ii , jj ;
00485 float * tsar ;
00486 MRI_IMAGE * tsim ;
00487 float delta , period=0.0 ;
00488 int nx , ny=0 , npol=0 , nharm=-1 ;
00489 int pp ;
00490 double fac , val ;
00491
00492
00493
00494 PLUTO_next_option(plint) ;
00495
00496 delta = PLUTO_get_number(plint) ;
00497 if( delta <= 0.0 ) return "**********************\n"
00498 "Illegal value of Delta\n"
00499 "**********************" ;
00500
00501 nx = PLUTO_get_number(plint) ;
00502
00503
00504
00505 PLUTO_next_option(plint) ;
00506 label = PLUTO_get_string(plint) ;
00507 if( label == NULL || strlen(label) == 0 ) return "**********************\n"
00508 "Illegal value of Label\n"
00509 "**********************" ;
00510
00511
00512
00513 do {
00514 str = PLUTO_get_optiontag(plint) ; if( str == NULL ) break ;
00515
00516 if( strcmp(str,"Sinusoid") == 0 ){
00517
00518 period = PLUTO_get_number(plint) ;
00519 nharm = PLUTO_get_number(plint) - 1.0 ;
00520
00521 if( period <= 0.0 ) return "***********************\n"
00522 "Illegal Sinusoid Period\n"
00523 "***********************" ;
00524
00525
00526 } else if( strcmp(str,"Polynomial") == 0 ){
00527
00528 npol = PLUTO_get_number(plint) ;
00529
00530 } else {
00531 return "***********************\n"
00532 "Illegal optiontag found\n"
00533 "***********************" ;
00534 }
00535 } while(1) ;
00536
00537
00538
00539 ny = 0 ;
00540 if( npol > 0 ) ny = npol-1 ;
00541 if( period > 0.0 ) ny += 2*(nharm+1) ;
00542
00543 if( ny < 1 ) return "***********************\n"
00544 "No timeseries specified\n"
00545 "***********************" ;
00546
00547 tsim = mri_new( nx , ny , MRI_float ) ;
00548 jj = 0 ;
00549
00550 fac = 1.99999 / (nx-1) ;
00551 for( pp=2 ; pp <= npol ; pp++,jj++ ){
00552
00553 tsar = MRI_FLOAT_PTR(tsim) + (jj*nx) ;
00554
00555 for( ii=0 ; ii < nx ; ii++ ){
00556 val = fac * ii - 0.999995 ;
00557 tsar[ii] = cos( pp * acos(val) ) ;
00558 }
00559 }
00560
00561 for( pp=0 ; pp <= nharm ; pp++ , jj+=2 ){
00562 fac = (2.0*PI) * delta * (pp+1) / period ;
00563 tsar = MRI_FLOAT_PTR(tsim) + (jj*nx) ;
00564
00565 for( ii=0 ; ii < nx ; ii++ ){
00566 tsar[ii] = cos( fac * ii ) ;
00567 tsar[ii+nx] = sin( fac * ii ) ;
00568 }
00569 }
00570
00571 PLUTO_register_timeseries( label , tsim ) ;
00572 mri_free(tsim) ;
00573 return NULL ;
00574 }
00575
00576
00577
00578 #include "parser.h"
00579
00580 static char fredstring[] =
00581 " Purpose: Control the Expr 0D Transformation function\n"
00582 "\n"
00583 " Variable = letter used as input to expression\n"
00584 " Expression = arithmetic expression to evaluate\n"
00585 ;
00586
00587 #define NALPHA 26
00588 static char * vstring[NALPHA] = {
00589 " A ", " B ", " C ", " D ", " E ",
00590 " F ", " G ", " H ", " I ", " J ",
00591 " K ", " L ", " M ", " N ", " O ",
00592 " P ", " Q ", " R ", " S ", " T ",
00593 " U ", " V ", " W ", " X ", " Y ", " Z " } ;
00594
00595 static int exp0d_var = 23 ;
00596
00597 static PARSER_code * exp0d_pc = NULL ;
00598
00599 static PLUGIN_interface *plint_EXP0D=NULL ;
00600
00601 static void EXP0D_func_init(void)
00602 {
00603 PLUG_startup_plugin_CB( NULL , (XtPointer)plint_EXP0D , NULL ) ;
00604 }
00605
00606
00607 PLUGIN_interface * EXP0D_init(void)
00608 {
00609 PLUGIN_interface * plint ;
00610
00611
00612
00613 plint = PLUTO_new_interface( "Expr 0D" ,
00614 "Control the Expr 0D transformation" ,
00615 fredstring ,
00616 PLUGIN_CALL_VIA_MENU , EXP0D_main ) ;
00617
00618 PLUTO_add_option( plint , "Variable" , "Variable" , TRUE ) ;
00619 PLUTO_add_string( plint , NULL , NALPHA,vstring , exp0d_var ) ;
00620
00621 PLUTO_add_option( plint , "Expression" , "Expression" , TRUE ) ;
00622 PLUTO_add_string( plint , NULL , 0,NULL , 50 ) ;
00623
00624 PLUTO_register_0D_function( "Expr 0D" , EXP0D_worker ) ;
00625
00626 plint_EXP0D = plint ;
00627 AFNI_register_nD_func_init( 0 , (generic_func *)EXP0D_func_init ) ;
00628
00629 return plint ;
00630 }
00631
00632 char * EXP0D_main( PLUGIN_interface * plint )
00633 {
00634 char * str ;
00635
00636 PLUTO_next_option(plint) ;
00637 str = PLUTO_get_string(plint) ;
00638 exp0d_var = PLUTO_string_index( str , NALPHA , vstring ) ;
00639
00640 if( exp0d_pc != NULL ){ free(exp0d_pc) ; exp0d_pc = NULL ; }
00641 PLUTO_next_option(plint) ;
00642 str = PLUTO_get_string(plint) ;
00643 exp0d_pc = PARSER_generate_code( str ) ;
00644
00645 if( exp0d_pc == NULL ) return "*******************************\n"
00646 "Error when compiling expression\n"
00647 "*******************************" ;
00648
00649 return NULL ;
00650 }
00651
00652 #define VSIZE 64
00653
00654 void EXP0D_worker( int num , float * vec )
00655 {
00656 int ii , jj , jbot,jtop ;
00657
00658 static int first = 1 ;
00659 static double * atoz[26] ;
00660 static double tvec[VSIZE] ;
00661
00662 if( num <= 0 || vec == NULL || exp0d_pc == NULL ) return ;
00663
00664 #if 0
00665 fprintf(stderr,"Enter EXP0D_worker\n") ;
00666 #endif
00667
00668 if( first ){
00669 for( ii=0 ; ii < 26 ; ii++)
00670 atoz[ii] = (double *) malloc(sizeof(double) * VSIZE ) ;
00671 first = 0 ;
00672 #if 0
00673 fprintf(stderr,"Allocated atoz\n") ;
00674 #endif
00675 }
00676
00677 for( ii=0 ; ii < 26 ; ii++ )
00678 for (jj=0; jj<VSIZE; jj++) atoz[ii][jj] = 0.0 ;
00679
00680 #if 0
00681 fprintf(stderr,"Zeroed atoz\n") ;
00682 #endif
00683
00684 for( ii=0 ; ii < num ; ii+=VSIZE ){
00685 jbot = ii ;
00686 jtop = MIN( ii + VSIZE , num ) ;
00687
00688 for( jj=jbot ; jj < jtop ; jj ++ ) atoz[exp0d_var][jj-ii] = vec[jj] ;
00689
00690 PARSER_evaluate_vector( exp0d_pc , atoz , jtop-jbot , tvec ) ;
00691
00692 for( jj=jbot ; jj < jtop ; jj ++ ) vec[jj] = tvec[jj-ii] ;
00693 }
00694
00695 #if 0
00696 fprintf(stderr,"Exit EXP0D_worker\n") ;
00697 #endif
00698
00699 return ;
00700 }
00701
00702
00703
00704 #ifdef ALLOW_LOMO
00705 static int lomo_order = 3 ;
00706 static int lomo_levels = 32 ;
00707 int lomo_regress( int , int , int * , int * ) ;
00708
00709 PLUGIN_interface * LOMOR_init(void)
00710 {
00711 PLUGIN_interface * plint ;
00712
00713
00714
00715 plint = PLUTO_new_interface( "Lomo Regression" ,
00716 "Control the Local Monotone Regression" ,
00717 NULL ,
00718 PLUGIN_CALL_VIA_MENU , LOMOR_main ) ;
00719
00720 PLUTO_add_option( plint , "Parameters" , "Parameters" , TRUE ) ;
00721 PLUTO_add_number( plint , "Order" , 3, 20,0,lomo_order , FALSE ) ;
00722 PLUTO_add_number( plint , "Levels", 4,128,0,lomo_levels , FALSE ) ;
00723
00724 PLUTO_register_1D_function( "Lomo 1D" , LOMOR_fitter ) ;
00725
00726 return plint ;
00727 }
00728
00729 char * LOMOR_main( PLUGIN_interface * plint )
00730 {
00731 PLUTO_next_option(plint) ;
00732 lomo_order = PLUTO_get_number(plint) ;
00733 lomo_levels = PLUTO_get_number(plint) ;
00734 return NULL ;
00735 }
00736
00737 static int lnum = 0 ;
00738 static int * xin = NULL ;
00739 static int * yout = NULL ;
00740
00741 void LOMOR_fitter( int num , double to , double dt , float * vec )
00742 {
00743 int ii ;
00744 float top , bot , scl ;
00745
00746 if( num <= 3 || vec == NULL ) return ;
00747
00748 if( lnum < num ){
00749 if( xin != NULL ){ free(xin) ; free(yout) ; }
00750 xin = (int *) malloc( sizeof(int) * num ) ;
00751 yout = (int *) malloc( sizeof(int) * num ) ;
00752 if( xin == NULL || yout == NULL ) return ;
00753 lnum = num ;
00754 }
00755
00756 bot = top = vec[0] ;
00757 for( ii=1 ; ii < num ; ii++ ){
00758 if( vec[ii] < bot ) bot = vec[ii] ;
00759 else if( vec[ii] > top ) top = vec[ii] ;
00760 }
00761
00762 if( bot >= top ) return ;
00763 scl = (lomo_levels - 0.01) / (top-bot) ;
00764
00765 fprintf(stderr,"LOMO: range %f .. %f; scl=%f\n",bot,top,scl) ;
00766
00767 for( ii=0 ; ii < num ; ii++ ) xin[ii] = (int)((vec[ii]-bot)*scl) ;
00768
00769 ii = lomo_regress( num , lomo_order , xin , yout ) ;
00770 if( ii == -1 ) return ;
00771
00772 scl = 1.0 / scl ;
00773 for( ii=0 ; ii < num ; ii++ ) vec[ii] = bot + yout[ii]*scl ;
00774 return ;
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 #include <stdio.h>
00824 #include <math.h>
00825 #include <string.h>
00826
00827 typedef struct _state {
00828 int value, length, cumcost;
00829 struct _state *prevstate;
00830 } state;
00831
00832 #ifdef ABS
00833 #undef ABS
00834 #endif
00835 #define ABS(x) (((x)<0) ? (-x) : (x))
00836
00837 #define USE_STATIC_TRELLIS
00838 #ifdef USE_STATIC_TRELLIS
00839 # define MMAX 35
00840 # define NMAX 512
00841 # define RMAX 100
00842 static state TRELLIS[RMAX][2*MMAX][NMAX] ;
00843 # define trellis(i,j,k) TRELLIS[i][j][k]
00844 #else
00845 static state * TRELLIS = NULL ;
00846 static int TDIM1 , TDIM2 , TDIM12 , TDIM3 ;
00847 # define trellis(i,j,k) TRELLIS[i+j*TDIM1+k*TDIM12]
00848 #endif
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 int lomo_regress( int N , int m , int * yin , int * x )
00860 {
00861 int base , R , * y ;
00862 int n,v,l,pv,pl,i,j;
00863 int cost, maxcost;
00864 int peakval;
00865 state dummy_state;
00866
00867
00868
00869 if( N < 3 || m < 3 || m >= N || yin == NULL || x == NULL ) return -1 ;
00870
00871
00872
00873 y = (int *) malloc(sizeof(int)*N) ; if( y == NULL ) return -1 ;
00874 base = yin[0] ;
00875 for( i=1 ; i < N ; i++ ) if( yin[i] < base ) base = yin[i] ;
00876 R = y[0] = yin[0] - base ;
00877 for( i=1 ; i < N ; i++ ){
00878 y[i] = yin[i] - base ; if( y[i] > R ) R = y[i] ;
00879 }
00880 R++ ;
00881 if( R == 1 ){
00882 for( i=0 ; i < N ; i++ ) x[i] = yin[i] ;
00883 free(y) ; return 0 ;
00884 }
00885
00886 fprintf(stderr,"LOMO: %d points; %d levels; %d order\n",N,R,m) ;
00887
00888
00889
00890 maxcost = 0;
00891 for (n = 0; n < N; n++) maxcost += ABS(y[n]);
00892
00893
00894
00895 dummy_state.value = -1; dummy_state.length = m ;
00896 dummy_state.cumcost = 0 ; dummy_state.prevstate = NULL;
00897
00898 #ifndef USE_STATIC_TRELLIS
00899
00900
00901 TDIM1 = R ; TDIM2 = 2*m+2 ; TDIM12 = TDIM1*TDIM2 ; TDIM3 = N ;
00902 TRELLIS = (state *) calloc( TDIM1*TDIM2*TDIM3 , sizeof(state) ) ;
00903 if( TRELLIS == NULL ){ free(y) ; return -1 ; }
00904 #endif
00905
00906 fprintf(stderr,"LOMO: init trellis\n") ;
00907
00908 for (n = 0; n < N; n++)
00909 {
00910 for (l = 1; l <= 2*m; l++)
00911 {
00912 for (v = 0; v < R; v++) { trellis(v,l,n).value = v;
00913 trellis(v,l,n).length = l;
00914 if ((n == 0) && ((l == 1) || (l == m+1)))
00915 { trellis(v,l,n).cumcost = ABS((v-y[0]));
00916 trellis(v,l,n).prevstate = &dummy_state;
00917 }
00918 else
00919 { trellis(v,l,n).cumcost = maxcost;
00920 trellis(v,l,n).prevstate = NULL;
00921 }
00922 }
00923 }
00924 }
00925
00926
00927
00928
00929
00930 fprintf(stderr,"LOMO: compute trellis") ; fflush(stderr) ;
00931
00932 for (n = 1; n < N; n++)
00933 {
00934
00935
00936 fprintf(stderr,".") ; fflush(stderr) ;
00937
00938 for (v = 0; v < R; v++)
00939 {
00940 for (pv = 0; pv < v; pv++)
00941 {
00942 for (pl = 1; pl <= m; pl++)
00943 {
00944 if (trellis(pv,pl,n-1).cumcost != maxcost)
00945 {
00946 cost = trellis(pv,pl,n-1).cumcost + ABS((v-y[n]));
00947 if (cost < trellis(v,1,n).cumcost)
00948 {
00949 trellis(v,1,n).cumcost = cost;
00950 trellis(v,1,n).prevstate = &trellis(pv,pl,n-1);
00951 }
00952 }
00953 }
00954 if (trellis(pv,2*m,n-1).cumcost != maxcost)
00955 {
00956 cost = trellis(pv,2*m,n-1).cumcost + ABS((v-y[n]));
00957 if (cost < trellis(v,1,n).cumcost)
00958 {
00959 trellis(v,1,n).cumcost = cost;
00960 trellis(v,1,n).prevstate = &trellis(pv,2*m,n-1);
00961 }
00962 }
00963 }
00964 }
00965
00966
00967
00968 for (v = 0; v < R; v++)
00969 {
00970 for (pv = R - 1; pv > v; pv--)
00971 {
00972 for (pl = m + 1; pl <= 2*m; pl++)
00973 {
00974 if (trellis(pv,pl,n-1).cumcost != maxcost)
00975 {
00976 cost = trellis(pv,pl,n-1).cumcost + ABS((v-y[n]));
00977 if (cost < trellis(v,m+1,n).cumcost)
00978 {
00979 trellis(v,m+1,n).cumcost = cost;
00980 trellis(v,m+1,n).prevstate = &trellis(pv,pl,n-1);
00981 }
00982 }
00983 }
00984 if (trellis(pv,m,n-1).cumcost != maxcost)
00985 {
00986 cost = trellis(pv,m,n-1).cumcost + ABS((v-y[n]));
00987 if (cost < trellis(v,m+1,n).cumcost)
00988 {
00989 trellis(v,m+1,n).cumcost = cost;
00990 trellis(v,m+1,n).prevstate = &trellis(pv,m,n-1);
00991 }
00992 }
00993 }
00994 }
00995
00996
00997
00998 for (l = 2; l < m; l++)
00999 {
01000 for (v = 0; v < R; v++)
01001 {
01002 if (trellis(v,l-1,n-1).cumcost != maxcost)
01003 {
01004 trellis(v,l,n).cumcost = trellis(v,l-1,n-1).cumcost + ABS((v-y[n]));
01005 trellis(v,l,n).prevstate = &trellis(v,l-1,n-1);
01006 }
01007 }
01008 }
01009
01010
01011
01012 for (l = m+2; l < 2*m; l++)
01013 {
01014 for (v = 0; v < R; v++)
01015 {
01016 if (trellis(v,l-1,n-1).cumcost != maxcost)
01017 {
01018 trellis(v,l,n).cumcost = trellis(v,l-1,n-1).cumcost + ABS((v-y[n]));
01019 trellis(v,l,n).prevstate = &trellis(v,l-1,n-1);
01020 }
01021 }
01022 }
01023
01024
01025
01026 for (v = 0; v < R; v++)
01027 {
01028 if (trellis(v,m,n-1).cumcost != maxcost)
01029 {
01030 cost = trellis(v,m,n-1).cumcost + ABS((v-y[n]));
01031 if (cost < trellis(v,m,n).cumcost)
01032 {
01033 trellis(v,m,n).cumcost = cost;
01034 trellis(v,m,n).prevstate = &trellis(v,m,n-1);
01035 }
01036 }
01037
01038 if (trellis(v,m-1,n-1).cumcost != maxcost)
01039 {
01040 cost = trellis(v,m-1,n-1).cumcost + ABS((v-y[n]));
01041 if (cost < trellis(v,m,n).cumcost)
01042 {
01043 trellis(v,m,n).cumcost = cost;
01044 trellis(v,m,n).prevstate = &trellis(v,m-1,n-1);
01045 }
01046 }
01047 }
01048
01049
01050
01051 for (v = 0; v < R; v++)
01052 {
01053 if (trellis(v,2*m,n-1).cumcost != maxcost)
01054 {
01055 cost = trellis(v,2*m,n-1).cumcost + ABS((v-y[n]));
01056 if (cost < trellis(v,2*m,n).cumcost)
01057 {
01058 trellis(v,2*m,n).cumcost = cost;
01059 trellis(v,2*m,n).prevstate = &trellis(v,2*m,n-1);
01060 }
01061 }
01062
01063 if (trellis(v,2*m-1,n-1).cumcost != maxcost)
01064 {
01065 cost = trellis(v,2*m-1,n-1).cumcost + ABS((v-y[n]));
01066 if (cost < trellis(v,2*m,n).cumcost)
01067 {
01068 trellis(v,2*m,n).cumcost = cost;
01069 trellis(v,2*m,n).prevstate = &trellis(v,2*m-1,n-1);
01070 }
01071 }
01072 }
01073
01074
01075 }
01076
01077
01078
01079
01080
01081 fprintf(stderr,"\nLOMO: pick best path\n") ; fflush(stderr) ;
01082
01083 cost = maxcost;
01084 for (l = 1; l <= m; l++)
01085 {
01086 for (v = 0; v < R; v++)
01087 {
01088 if (trellis(v,l,N-1).cumcost < cost)
01089 {
01090 cost = trellis(v,l,N-1).cumcost;
01091 pl = l; pv = v;
01092 }
01093 }
01094 }
01095
01096
01097
01098 if (cost < maxcost)
01099 {
01100 x[N-1] = pv;
01101 fprintf(stderr," [%d] = %d\n",N-1,pv) ;
01102
01103 for (n = N-2; n >=0; n--)
01104 {
01105 fprintf(stderr," [%d] = %d",n,trellis(pv,pl,n+1).prevstate->value) ; fflush(stderr) ;
01106 x[n] = trellis(pv,pl,n+1).prevstate->value;
01107 fprintf(stderr," pv = %d",trellis(pv,pl,n+1).prevstate->value) ; fflush(stderr) ;
01108 pv = trellis(pv,pl,n+1).prevstate->value;
01109 fprintf(stderr," pl = %d",trellis(pv,pl,n+1).prevstate->length) ; fflush(stderr) ;
01110 pl = trellis(pv,pl,n+1).prevstate->length;
01111 fprintf(stderr,"\n") ;
01112 }
01113 }
01114 else { for (n=0;n<N;n++) x[n] = 0; }
01115
01116
01117
01118 fprintf(stderr,"\nLOMO: add base back on\n") ;
01119
01120 for( i=0 ; i < N ; i++ ) x[n] += base ;
01121
01122 fprintf(stderr,"LOMO: exit regression\n") ;
01123
01124 free(y) ;
01125 #ifndef USE_STATIC_TRELLIS
01126 free(TRELLIS) ;
01127 #endif
01128
01129 return 0 ;
01130 }
01131 #endif