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_2dfunc.c

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

Powered by Plone

This site conforms to the following standards: