Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

afni_pplug_1dfunc.c

Go to the documentation of this file.
00001 
00002 #include "afni.h"
00003 #include "parser.h"
00004 
00005 #ifndef ALLOW_PLUGINS
00006 void F1D_init(void){}
00007 #else
00008 
00009 /***********************************************************************
00010   Pseudo-plugin to set generic 1D func
00011 ************************************************************************/
00012 
00013 /*--------------------- string to 'help' the user --------------------*/
00014 
00015 static char helpstring[] =
00016   "Purpose: control the 1DChain function\n"
00017   "\n"
00018   "The 1DChain transformation allows you to chain together a sequence\n"
00019   "of up to 8 other 0D or 1D transformation functions.  Each row of\n"
00020   "the input form controls one transformation.  If it is toggled ON,\n"
00021   "then you can choose from a menu of functions.  Each ON function is\n"
00022   "applied in turn.\n"
00023   "\n"
00024   "The special 'Expr 9' function lets you compute any expression\n"
00025   "that depends on the local 9-wide neighborhood of each voxel, where\n"
00026   "the expression is entered (a la 3dcalc) in the string field at\n"
00027   "the right of the form.  The variable names that may be used in\n"
00028   "the expresssion are:\n"
00029   "                        r s t u v w x y z\n"
00030   "\n"
00031   "where 'v' is the center voxel (remember 'v for voxel').  You may\n"
00032   "also use as a variable any name from previous active chain links\n"
00033   "(e.g., A,B,C, ...).  For example, on line C, if you select 'Expr 9'\n"
00034   "as the function and enter\n"
00035   "\n"
00036   "             (r+s+t+u+v+w+x+y+z)/9-A\n"
00037   "\n"
00038   "for the expression, this will evaluate the average of the 9\n"
00039   "local voxels and subtract the output of chain link A.\n"
00040   "On line C, you cannot use variables C or higher, since they\n"
00041   "won't have been calculated at the time C is being computed.\n"
00042   "\n"
00043   "Author -- RW Cox -- Aug 2001"
00044 ;
00045 
00046 /*----------------- prototypes for internal routines -----------------*/
00047 
00048 static char * F1D_main( PLUGIN_interface * ) ;
00049 static void F1D_chainfunc( int , double , double , float * ar ) ;
00050 
00051 /***********************************************************************
00052    Set up the interface to the user
00053 ************************************************************************/
00054 
00055 #define NUM_CHAIN 8
00056 static char alpha[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
00057 
00058 #define RR 17
00059 #define SS 18
00060 #define TT 19
00061 #define UU 20
00062 #define VV 21
00063 #define WW 22
00064 #define XX 23
00065 #define YY 24
00066 #define ZZ 25
00067 
00068 static int              num0D ,     num1D ;
00069 static generic_func ** func0D , ** func1D ;
00070 
00071 static int     numfunc  ;
00072 static char ** funcname ;
00073 
00074 static int            chain_do[NUM_CHAIN] ;
00075 static PARSER_code *  chain_pc[NUM_CHAIN] ;
00076 static int            chain_dd[NUM_CHAIN] ;
00077 static generic_func * chain_ff[NUM_CHAIN] ;
00078 
00079 PLUGIN_interface * F1D_init(void)
00080 {
00081    PLUGIN_interface * plint ;     /* will be the output of this routine */
00082    int ii , num , ll ;
00083    char str[16] ;
00084    MCW_function_list * rlist ;
00085 
00086    /*---------------- set titles and call point ----------------*/
00087 
00088    plint = PLUTO_new_interface( "1D Chain Func" ,
00089                                 "Control 1DChain function" ,
00090                                 helpstring ,
00091                                 PLUGIN_CALL_VIA_MENU ,
00092                                 (char *(*)())F1D_main  ) ;
00093 
00094    PLUTO_add_hint( plint , "Control 1DChain function" ) ;
00095 
00096    PLUTO_set_runlabels( plint , "Set+Keep" , "Set+Close" ) ;  /* 04 Nov 2003 */
00097 
00098    /*-------- Initialize list of all functions that can be chained -----*/
00099 
00100    numfunc     = 1 ;
00101    funcname    = (char **) malloc(sizeof(char **)) ;
00102    funcname[0] = "Expr 9 ---->" ;
00103 
00104    /*-------- Get list of pre-registered functions --------*/
00105 
00106    rlist = &(GLOBAL_library.registered_0D) ;
00107    num0D = rlist->num ;
00108    if( num0D > 0 ){
00109      int n0 = 0 ;
00110      funcname = (char **) realloc( (void *)funcname, sizeof(char **)*(numfunc+num0D) );
00111      func0D   = (generic_func **) malloc( sizeof(generic_func *)*num0D ) ;
00112      for( ii=0 ; ii < num0D ; ii++ ){
00113        if( rlist->flags[ii] == 0 ){            /* 18 Dec 2003: only allow "normal" funcs */
00114          ll = strlen(rlist->labels[ii]) ;
00115          funcname[numfunc] = AFMALL(char, ll+8) ;
00116          strcpy(funcname[numfunc],"0D: ") ;
00117          strcat(funcname[numfunc],rlist->labels[ii]) ;
00118          func0D[n0++] = rlist->funcs[ii] ;
00119          numfunc++ ;
00120        }
00121      }
00122      num0D = n0 ;
00123    }
00124 
00125    rlist = &(GLOBAL_library.registered_1D) ;
00126    num1D = rlist->num ;
00127    if( num1D > 0 ){
00128      int n1 = 0 ;
00129      funcname = (char **) realloc( (void *)funcname, sizeof(char **)*(numfunc+num1D) );
00130      func1D   = (generic_func **) malloc( sizeof(generic_func *)*num1D ) ;
00131      for( ii=0 ; ii < num1D ; ii++ ){
00132        if( rlist->flags[ii] == 0 ){            /* 18 Dec 2003: only allow "normal" funcs */
00133          ll = strlen(rlist->labels[ii]) ;
00134          funcname[numfunc] = AFMALL(char, ll+8) ;
00135          strcpy(funcname[numfunc],"1D: ") ;
00136          strcat(funcname[numfunc],rlist->labels[ii]) ;
00137          func1D[n1++] = rlist->funcs[ii] ;
00138          numfunc++ ;
00139        }
00140      }
00141      num1D = n1 ;
00142    }
00143 
00144    AFNI_register_1D_function( "1DChain" , F1D_chainfunc ) ;  /* add this only now */
00145 
00146    /*--------- make interface lines -----------*/
00147 
00148    for( ii=0 ; ii < NUM_CHAIN ; ii++ ){
00149 
00150       chain_do[ii] = 0 ;     /* off */
00151       chain_pc[ii] = NULL ;
00152       chain_ff[ii] = NULL ;
00153 
00154       str[0] = alpha[ii] ; str[1] = '\0' ;
00155 
00156       PLUTO_add_option( plint ,
00157                         str ,  /* label at left of input line */
00158                         str ,  /* tag to return to plugin */
00159                         FALSE  /* is this mandatory? */
00160                       ) ;
00161 
00162       PLUTO_add_string( plint , "Function"  ,
00163                         numfunc , funcname , 0 ) ;
00164 
00165       PLUTO_add_string( plint , "Expr 9" , 0,NULL,32 ) ;
00166    }
00167 
00168    /*--------- done with interface setup ---------*/
00169 
00170    return plint ;
00171 }
00172 
00173 /***************************************************************************
00174   Main routine for this plugin (will be called from AFNI).
00175   If the return string is not NULL, some error transpired, and
00176   AFNI will popup the return string in a message box.
00177 ****************************************************************************/
00178 
00179 static char * F1D_main( PLUGIN_interface * plint )
00180 {
00181    char *tag , *str ;
00182    int ii,kk,jj , ndone=0 ;
00183 
00184    /*-- turn off all function rows --*/
00185 
00186    for( ii=0 ; ii < NUM_CHAIN ; ii++ ){
00187       chain_do[ii] = 0 ;
00188       chain_ff[ii] = NULL ;
00189       if( chain_pc[ii] != NULL ){ free(chain_pc[ii]); chain_pc[ii]=NULL; }
00190    }
00191 
00192    /*--------- loop over input lines, re-enable functions rows ---------*/
00193 
00194    while(1){
00195       tag = PLUTO_get_optiontag(plint) ;  /* "A", "B", etc */
00196       if( tag == NULL ) break ;
00197 
00198       /* find which variable */
00199 
00200       for( kk=0 ; kk < NUM_CHAIN ; kk++ )
00201         if( tag[0] == alpha[kk] ) break ;
00202 
00203       if( kk >= NUM_CHAIN ) break ;       /* should not happen */
00204 
00205       chain_do[kk] = 1 ; ndone++ ;        /* mark to do this chain link */
00206 
00207       str = PLUTO_get_string(plint) ;                       /* function name */
00208       jj  = PLUTO_string_index( str , numfunc,funcname ) ;  /* index of function */
00209 
00210       if( jj < 0 || jj >= numfunc ){ /* should not happen */
00211 
00212          for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00213          return "** Internal Error **" ;
00214 
00215       } else if( jj == 0 ){          /* Expr 9 */
00216          int hasym[26] , ns ;
00217 
00218          str = PLUTO_get_string(plint) ;             /* get expression */
00219          chain_pc[kk] = PARSER_generate_code(str) ;  /* parse it */
00220          chain_dd[kk] = -1 ;                         /* code for this case */
00221 
00222          if( chain_pc[kk] == NULL ){
00223            for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00224            return "** Expr 9 parser error **" ;
00225          }
00226 
00227          /* check symbol usage */
00228 
00229          PARSER_mark_symbols( chain_pc[kk] , hasym ) ;
00230 
00231          for( ii=0 ; ii < kk ; ii++ ){                 /* previous */
00232            if( hasym[ii] && chain_do[ii] == 0 ){
00233              for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00234              return "** Expr 9 uses inactive symbol **" ;
00235            }
00236          }
00237 
00238          if( hasym[kk] ){                              /* current */
00239            for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00240            return "** Expr 9 uses current symbol **" ;
00241          }
00242 
00243          for( ii=kk+1 ; ii < NUM_CHAIN  ; ii++ ){      /* subsequent */
00244            if( hasym[ii] ){
00245              for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00246              return "** Expr 9 uses subsequent symbol **" ;
00247            }
00248          }
00249 
00250          for( ii=NUM_CHAIN ; ii < RR ; ii++ ){         /* undefined */
00251            if( hasym[ii] ){
00252              for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00253              return "** Expr 9 uses undefined symbol **" ;
00254            }
00255          }
00256 
00257          for( ns=ii=0 ; ii < kk ; ii++ ) if( hasym[ii] ) ns++ ;
00258          for( ii=RR   ; ii <=ZZ ; ii++ ) if( hasym[ii] ) ns++ ;
00259 
00260          if( ns == 0 ){
00261            for( jj=0 ; jj < NUM_CHAIN ; jj++ ) chain_do[jj] = 0 ;
00262            return "** Expr 9 doesn't use any symbols **" ;
00263          }
00264 
00265       } else if( jj >= 1 && jj <= num0D ){   /* 0D function */
00266 
00267          chain_dd[kk] = 0 ;            /* code for 0D */
00268          chain_ff[kk] = func0D[jj-1] ;
00269 
00270       } else {                               /* 1D function */
00271 
00272          chain_dd[kk] = 1 ;            /* code for 1D */
00273          chain_ff[kk] = func1D[jj-num0D-1] ;
00274       }
00275 
00276    } /* end of while(1) loop over option lines */
00277 
00278    /*--------- finished -------*/
00279 
00280    if( ndone == 0 ) return " \n** Don't you want to do anything? **\n " ;
00281 
00282    return NULL ;
00283 }
00284 
00285 /*-----------------------------------------------------------------------*/
00286 
00287 static void F1D_chainfunc( int nx , double to , double dt , float * ar )
00288 {
00289    int kk,ii,pp , ndo,nexp ;
00290    float * abc[NUM_CHAIN] , *aprev=ar ;
00291    double atoz[26] ;
00292 
00293    /* allocate vectors workspace */
00294 
00295    for( nexp=ndo=kk=0 ; kk < NUM_CHAIN ; kk++ ){
00296      if( chain_do[kk] ){
00297        abc[kk] = (float *) malloc(sizeof(float)*nx) ;
00298        ndo++ ;
00299        if( chain_pc[kk] != NULL ) nexp++ ;
00300      } else {
00301        abc[kk] = NULL ;
00302      }
00303    }
00304 
00305    if( ndo == 0 ) return ;  /* nothing to do */
00306 
00307    /* loop over chain links */
00308 
00309    for( kk=0 ; kk < NUM_CHAIN ; kk++ ){
00310      if( !chain_do[kk] ) continue ;     /* skip this link */
00311 
00312      switch( chain_dd[kk] ){
00313 
00314        case 0:                                      /* 0D func */
00315          memcpy( abc[kk] , aprev , sizeof(float)*nx ) ;
00316 #if 0
00317          chain_ff[kk]( nx , abc[kk] ) ;
00318 #else
00319          AFNI_CALL_0D_function( chain_ff[kk] , nx,abc[kk] ) ;
00320 #endif
00321        break ;
00322 
00323        case 1:                                      /* 1D func */
00324          memcpy( abc[kk] , aprev , sizeof(float)*nx ) ;
00325 #if 0
00326          chain_ff[kk]( nx , to,dt , abc[kk] ) ;
00327 #else
00328          AFNI_CALL_1D_function( chain_ff[kk] , nx,to,dt,abc[kk] ) ;
00329 #endif
00330        break ;
00331 
00332        case -1:{                                    /* Expr 9 */
00333          int hasym[26] , jj ;
00334 
00335          PARSER_mark_symbols( chain_pc[kk] , hasym ) ;  /* which symbols to load? */
00336 
00337          for( ii=0 ; ii < nx ; ii++ ){  /* loop over voxels */
00338 
00339            for( pp=0 ; pp < 26 ; pp++ ) atoz[pp] = 0.0 ; /* all variables=0 */
00340 
00341            /* load previous chain vectors at this voxel */
00342 
00343            for( pp=0 ; pp < kk ; pp++ )
00344              if( hasym[pp] ) atoz[pp] = (double) abc[pp][ii] ;
00345 
00346            /* load local voxels from the immediately previous chain vector */
00347 
00348            if( hasym[RR] ){                         /* load R */
00349              jj = ii-4 ; if( jj < 0 ) jj = 0 ;
00350              atoz[RR] = (double) aprev[jj] ;
00351            }
00352 
00353            if( hasym[SS] ){                         /* load S */
00354              jj = ii-3 ; if( jj < 0 ) jj = 0 ;
00355              atoz[SS] = (double) aprev[jj] ;
00356            }
00357 
00358            if( hasym[TT] ){                         /* load T */
00359              jj = ii-2 ; if( jj < 0 ) jj = 0 ;
00360              atoz[TT] = (double) aprev[jj] ;
00361            }
00362 
00363            if( hasym[UU] ){                         /* load U */
00364              jj = ii-1 ; if( jj < 0 ) jj = 0 ;
00365              atoz[UU] = (double) aprev[jj] ;
00366            }
00367 
00368            if( hasym[VV] ){                         /* load V */
00369              atoz[VV] = (double) aprev[ii] ;
00370            }
00371 
00372            if( hasym[WW] ){                         /* load W */
00373              jj = ii+1 ; if( jj >= nx ) jj = nx-1 ;
00374              atoz[WW] = (double) aprev[jj] ;
00375            }
00376 
00377            if( hasym[XX] ){                         /* load X */
00378              jj = ii+2 ; if( jj >= nx ) jj = nx-1 ;
00379              atoz[XX] = (double) aprev[jj] ;
00380            }
00381 
00382            if( hasym[YY] ){                         /* load Y */
00383              jj = ii+3 ; if( jj >= nx ) jj = nx-1 ;
00384              atoz[YY] = (double) aprev[jj] ;
00385            }
00386 
00387            if( hasym[ZZ] ){                         /* load Z */
00388              jj = ii+4 ; if( jj >= nx ) jj = nx-1 ;
00389              atoz[ZZ] = (double) aprev[jj] ;
00390            }
00391 
00392            /* compute this row! */
00393 
00394            abc[kk][ii] = PARSER_evaluate_one( chain_pc[kk] , atoz ) ;
00395 
00396          } /* end of loop over voxels */
00397        }
00398        break ;
00399      }
00400 
00401      aprev = abc[kk] ;  /* for next time, this is previous image */
00402 
00403    } /* end of loop over chain links */
00404 
00405    /* copy last result into input array: this is the result */
00406 
00407    memcpy( ar , aprev , sizeof(float)*nx ) ;
00408 
00409    /* take out the trash */
00410 
00411    for( kk=0 ; kk < NUM_CHAIN ; kk++ )       /* images */
00412      if( abc[kk] != NULL ) free(abc[kk]) ;
00413 
00414    return ;
00415 }
00416 #endif
 

Powered by Plone

This site conforms to the following standards: