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  

SUMA_3dVol2Surf.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------
00002  * 3dVol2Surf - dump ascii dataset values corresponding to a surface
00003  *
00004  * This program is used to display AFNI dataset values that correspond to
00005  * a surface.  The surface points are mapped to xyz coordinates, according
00006  * to the SURF_VOL (surface volume) AFNI dataset.  These coordinates are
00007  * then matched to voxels in other AFNI datasets.  So given any other
00008  * AFNI dataset, this program can output all of the sub-brick values that
00009  * correspond to each of the suface locations.  The user also has options
00010  * to mask regions for output.
00011  *
00012  * usage:
00013  *    3dVol2Surf [options] -spec SPEC_FILE -sv SURF_VOL               \
00014  *                         -grid_par AFNI_DSET -map_func MAPPING_FUNC
00015  *
00016  * options:
00017  *
00018  *      -help
00019  *      -hist
00020  *      -v2s_hist
00021  *      -version
00022  *
00023  *      -grid_par   AFNI_DSET
00024  *      -map_func   MAP_FUNCTION
00025  *      -spec       SPEC_FILE
00026  *      -sv         SURF_VOL
00027  *
00028  *      -cmask      MASK_COMMAND
00029  *      -debug      LEVEL
00030  *      -dnode      NODE_NUM
00031  *      -f_index    INDEX_TYPE
00032  *      -f_steps    NUM_STEPS
00033  *      -f_p1_mm    DISTANCE
00034  *      -f_pn_mm    DISTANCE
00035  *      -f_p1_fr    FRACTION
00036  *      -f_pn_fr    FRACTION
00037  *      -gp_index   INDEX
00038  *      -oob_index  INDEX
00039  *      -oob_value  VALUE
00040  *      -oom_value  VALUE
00041  *      -out_1D     OUTPUT_FILE
00042  *      -no_headers
00043  *
00044  * examples:
00045  *
00046  *    3dVol2Surf -spec     SubjA.spec     -sv       SubjA_anat+orig   \ 
00047  *               -grid_par SubjA_EPI+orig -map_func mask  >  output.txt
00048  *
00049  *    3dVol2Surf -spec       SubjectA.spec                              \
00050  *               -sv         SubjectA_spgr+orig                         \ 
00051  *               -grid_par   SubjA_EPI+orig                             \
00052  *               -cmask      '-a SubjA.func+orig[2] -expr step(a-0.6)'  \
00053  *               -map_func   midpoint                                   \
00054  *               -out_1D     SubjA_surf_out.txt
00055  *
00056  *----------------------------------------------------------------------
00057 */
00058 
00059 /* define program history for -hist option */
00060 
00061 static char g_history[] = 
00062 
00063     "----------------------------------------------------------------------\n"
00064     "history:\n"
00065     "\n"
00066     "1.0  February 10, 2003  [rickr]\n"
00067     "  - initial release\n"
00068     "\n"
00069     "1.1  February 11, 2003  [rickr]\n"
00070     "  - handle no arguments as with -help\n"
00071     "  - minor updates to -help\n"
00072     "\n"
00073     "1.2  February 13, 2003  [rickr]\n"
00074     "  - init SUMAg array pointers, check before calling Free_()\n"
00075     "\n"
00076     "1.3  February 14, 2003  [rickr]\n"
00077     "  - optionally enable more SUMA debugging\n"
00078     "\n"
00079     "2.0  June 06, 2003  [rickr]\n"
00080     "  - re-wrote program according to 3dSurf2Vol (which was written\n"
00081     "    according to this :) - using map functions and node lists\n"
00082     "  - added midpoint map function\n"
00083     "\n"
00084     "2.1  June 10, 2003  [rickr]\n"
00085     "  - added ave map function (see dump_ave_map)\n"
00086     "\n"
00087     "2.2  June 19, 2003  [rickr]\n"
00088     "  - added -f_index INDEX_TYPE option (to index across nodes, too)\n"
00089     "  - set the default of -f_steps to 2\n"
00090     "  - use SMD prefix for macros\n"
00091     "\n"
00092     "2.3  July 21, 2003  [rickr]\n"
00093     "  - fixed problem with nodes outside grid_par dataset\n"
00094     "  - added min/max distance info\n"
00095     "\n"
00096     "3.0  August 05, 2003  [rickr]\n"
00097     "  - renamed SUMA_3dSurfMaskDump.[ch] to SUMA_3dVol2Surf.[ch]\n"
00098     "  - all output functions now go through dump_surf_3dt\n"
00099     "  - dump_surf_3dt() is a generalized function to get an MRI_IMARR for\n"
00100     "    one or a pair of nodes, by converting to a segment of points\n"
00101     "  - added v2s_adjust_endpts() to apply segment endpoint modifications\n"
00102     "  - added segment_imarr() to get the segment of points and fill the\n"
00103     "    MRI_IMARR list (along with other info)\n"
00104     "  - filter functions have been taken to v2s_apply_filter()\n"
00105     "  - added min, max and seg_vals map functions (filters)\n"
00106     "  - added options of the form -f_pX_XX to adjust segment endpoints\n"
00107     "  - added -dnode option for specific node debugging\n"
00108     "  - changed -output option to -out_1D\n"
00109     "  - added new debug info\n"
00110     "  - added checking of surface order (process from inner to outer)\n"
00111     "\n"
00112     "3.1  September 17, 2003  [rickr]\n"
00113     "  - fixed the help instructions for '-cmask'\n"
00114     "\n"
00115     "3.2  September 20, 2003  [rickr]\n"
00116     "  - added max_abs mapping function\n"
00117     "  - added options '-oob_index' and '-oob_value'\n"
00118     "  - added CHECK_NULL_STR macro\n"
00119     "\n"
00120     "3.3  September 23, 2003  [rickr]\n"
00121     "  - added help for -no_headers option\n"
00122     "\n"
00123     "3.4  October 01, 2003  [rickr]\n"
00124     "  - added -oom_value option\n"
00125     "  - added additional help example (for -oob and -oom options)\n"
00126     "\n"
00127     "3.5  October 20, 2003  [rickr]\n"
00128     "  - call the new engine function, SUMA_LoadSpec_eng()\n"
00129     "    (this will restrict the debug output from SUMA_LoadSpec())\n"
00130     "\n"
00131     "3.6  October 21, 2003  [rickr]\n"
00132     "  - finish upates for -f_keep_surf_order option\n"
00133     "    (help and sopt)\n"
00134     "\n"
00135     "3.7  November 04, 2003  [rickr]\n"
00136     "  - added ENTRY() stuff\n"
00137     "\n"
00138     "3.8  December 15, 2003  [rickr]\n"
00139     "  - added options '-surf_A' and '-surf_B'\n"
00140     "  - called SUMA_spec_select_surfs() and SUMA_spec_set_map_refs()\n"
00141     "    to pick requested surfaces from spec file\n"
00142     "  - removed option '-kso'\n"
00143     "  - added '-hist' option\n"
00144     "\n"
00145     "3.9  January 08, 2004  [rickr]\n"
00146     "  - added '-use_norms' option (segments come from norms)\n"
00147     "  - added '-norm_len' option to alter default normal lengths\n"
00148     "  - added '-keep_norm_dir' option to prevent direction check\n"
00149     "  - reversed order from '-hist' option (newer at bottom)\n"
00150     "  - added example with normals to help, along with option descriptions\n"
00151     "\n"
00152     "4.0  January 23, 2004  [rickr]\n"
00153     "  - SUMA_isINHmappable() is depricated, check with AnatCorrect field\n"
00154     "  - version -> 4.0 to celebrate normals :)\n"
00155     "\n"
00156     "4.1  February 10, 2004  [rickr]\n"
00157     "  - output a little more debug info for !AnatCorrect case\n"
00158     "  - small updates to help examples\n"
00159     "\n"
00160     "4.2  February 18, 2004  [rickr]\n"
00161     "  - added functionality for mapping functions that require sorting\n"
00162     "  - added mapping functions: median and mode\n"
00163     "\n"
00164     "4.3  February 19, 2004  [rickr]\n"
00165     "  - track 1dindex sources for new sorting filters (median, mode)\n"
00166     "    i.e. idindex is accurate, not just defaulting to first node\n"
00167     "\n"
00168     "4.4  March 26, 2004  [ziad]\n"
00169     "  - DsetList added to SUMA_LoadSpec_eng() call\n"
00170     "\n"
00171     "4.5  April 07, 2004  [rickr]\n"
00172     "  - fixed inconsistency in check_norm_dirs(), default dirs reversed\n"
00173     "\n"
00174     "5.0  May 18, 2004  [rickr]\n"
00175     "  - added '-out_niml' option for niml output\n"
00176     "  - added '-first_node' and '-last_node' option for limited output\n"
00177     "  - made major additions for memory handling of output data\n"
00178     "    (went from 'print as you go' to 'store and output at end')\n"
00179     "\n"
00180     "5.1  May 19, 2004  [rickr]\n"
00181     "  - added help for '-first_node' and '-last_node' options (sorry, Ziad)\n"
00182     "\n"
00183     "6.0  September 1, 2004  [rickr]\n"
00184     "  - created vol2surf() library files vol2surf.[ch] from core functions\n"
00185     "  - this represents a significant re-write of many existing functions,\n"
00186     "    modifying locations of action, structure names/contents, etc.\n"
00187     "  - add library to libmri (as this will end up in afni proper)\n"
00188     "  - separate all vol2surf.[ch] functions from SUMA_3dVol2surf.[ch]\n"
00189     "  - keep allocation/free action of results struct within library\n"
00190     "  - now using SUMA_surface struct for surface info (replace node_list)\n"
00191     "  - added main vol2surf(), afni_vol2surf(), free_v2s_results(),\n"
00192     "    and disp...() functions as vol2surf library interface\n"
00193     "  - added options to control column output (-skip_col_NAME)\n"
00194     "  - added -v2s_hist option for library history access\n"
00195     "\n"
00196     "6.1  September 2, 2004  [rickr]\n"
00197     "  - library organizing: moved v2s_map_type() to vol2surf.c\n"
00198     "  - moved gv2s_map_names to vol2surf.c, and externs to vol2surf.h\n"
00199     "\n"
00200     "6.2  September 16, 2004  [rickr]\n"
00201     "  - added -gp_index option, mostly to use in plugin interface\n"
00202     "  - added -reverse_norm_dir option, for reversing the default direction\n"
00203     "\n"
00204     "6.3  October 8, 2004  [rickr]\n"
00205     "  - in suma2afni_surf(), dealt with LDP changes to SUMA_surface\n"
00206     "  - changed write_outfile functions to v2s_*() and moved them to library\n"
00207     "\n"
00208     "6.3a March 22, 2005 [rickr] - removed tabs\n"
00209     "6.4  June   2, 2005 [rickr] - added -skip_col_non_results option\n"
00210     "---------------------------------------------------------------------\n";
00211 
00212 #define VERSION "version  6.4 (June 2, 2005)"
00213 
00214 /*----------------------------------------------------------------------
00215  * todo:
00216  *----------------------------------------------------------------------
00217 */
00218 
00219 #include "mrilib.h"
00220 #include "SUMA_suma.h"
00221 #include "vol2surf.h"
00222 #include "SUMA_3dVol2Surf.h"
00223 
00224 /* --------------------  globals  -------------------- */
00225 
00226 /* for all SUMA programs... */
00227 SUMA_SurfaceViewer * SUMAg_SVv = NULL;  /* array of Surf View structs   */
00228 int                  SUMAg_N_SVv = 0;   /* length of SVv array          */
00229 SUMA_DO            * SUMAg_DOv = NULL;  /* array of Displayable Objects */
00230 int                  SUMAg_N_DOv = 0;   /* length of DOv array          */
00231 SUMA_CommonFields  * SUMAg_CF = NULL;   /* info common to all viewers   */
00232 
00233 
00234 /* --------------------  AFNI prototype(s)  -------------------- */
00235 extern void machdep( void );
00236 
00237 #define MAIN
00238 
00239 /*----------------------------------------------------------------------*/
00240 
00241 int main( int argc , char * argv[] )
00242 {
00243     SUMA_SurfSpecFile  spec;
00244     v2s_param_t        params;
00245     v2s_opts_t         sopt;
00246     opts_t             opts;
00247     int                ret_val;
00248 
00249     mainENTRY("3dVol2Surf main");
00250     machdep();
00251     AFNI_logger("3dVol2Surf",argc,argv);
00252 
00253     /* validate inputs and init options structure */
00254     if ( ( ret_val = init_options(&opts, argc, argv) ) != 0 )
00255         return ret_val;
00256 
00257     if ( ( ret_val = validate_options(&opts, &params) ) != 0 )
00258         return ret_val;
00259 
00260     if ( (ret_val = set_smap_opts( &opts, &params, &sopt )) != 0 )
00261         return ret_val;
00262 
00263     /* read surface files */
00264     if ( (ret_val = read_surf_files(&opts, &spec)) != 0 )
00265         return ret_val;
00266 
00267     /*  get node list from surfaces (multiple points per node)
00268      *  need merge function
00269      */
00270     if ( (ret_val = get_surf_data( &sopt, &params )) != 0 )
00271         return ret_val;
00272 
00273     if ( (ret_val = write_output( &sopt, &params )) != 0 )
00274         return ret_val;
00275 
00276     /* free memory */
00277     final_clean_up(&opts, &params, &spec);
00278 
00279     return ret_val;
00280 }
00281 
00282 
00283 /*----------------------------------------------------------------------
00284  * write_output
00285  *----------------------------------------------------------------------
00286 */
00287 int write_output ( v2s_opts_t * sopt, v2s_param_t * p )
00288 {
00289     v2s_results * sd;
00290     int rv = 0;
00291 ENTRY("write_output");
00292 
00293     if ( sopt == NULL || p == NULL )
00294     {
00295         fprintf( stderr, "** v2s_wo - bad params (%p,%p)\n", sopt, p );
00296         RETURN(-1);
00297     }
00298 
00299     if ( sopt->map == E_SMAP_INVALID )
00300     {
00301         fprintf(stderr,"** v2s wo: invalid map %d\n", sopt->map);
00302         RETURN(-1);
00303     }
00304 
00305     sd = vol2surf(sopt, p);
00306     if ( !sd )
00307         fprintf(stderr,"** vol2surf failed\n");
00308 
00309     if ( sd && sopt->debug > 1 ) disp_v2s_results("-- post vol2surf() : ",sd);
00310 
00311     if ( sd && sopt->outfile_1D )
00312         rv = v2s_write_outfile_1D(sopt, sd, p->surf[0].label);
00313 
00314     if ( sd && !rv && sopt->outfile_niml )
00315         rv = v2s_write_outfile_niml(sopt, sd, 1); /* request to free data */
00316 
00317     free_v2s_results( sd );
00318     sd = NULL;
00319 
00320     RETURN(rv);
00321 }
00322 
00323 
00324 /*----------------------------------------------------------------------
00325  * get_surf_data        - from surfaces
00326  *
00327  *----------------------------------------------------------------------
00328 */
00329 int get_surf_data ( v2s_opts_t * sopt, v2s_param_t * p )
00330 {
00331     int nsurf = 2;
00332 
00333 ENTRY("get_surf_data");
00334 
00335     if ( sopt == NULL || p == NULL )
00336     {
00337         fprintf( stderr, "** cnl - bad params (%p,%p)\n", sopt, p );
00338         RETURN(-1);
00339     }
00340 
00341     if ( (sopt->map == E_SMAP_MASK) || sopt->use_norms )
00342         nsurf = 1;
00343 
00344     if ( copy_surfaces( sopt, p, nsurf ) )
00345         RETURN(-1);
00346 
00347     if ( sopt->use_norms )
00348     {
00349         if ( ! p->surf[0].norm )
00350         {
00351             fprintf(stderr,"** failure: surface '%s' has no normal list\n",
00352                     CHECK_NULL_STR(p->surf[0].label));
00353             RETURN(-1);
00354         }
00355 
00356         if ((sopt->norm_dir == V2S_NORM_DEFAULT) && check_norm_dirs(sopt, p, 0))
00357             RETURN(-1);
00358         else if ( sopt->norm_dir == V2S_NORM_REVERSE)
00359         {
00360             /* okay, reverse the direction */
00361             sopt->norm_len *= -1;
00362             if ( sopt->debug > 0 )
00363                 fprintf(stderr,"++ reversing normal direction\n");
00364         }
00365         /* else V2S_NORM_KEEP, i.e. do nothing */
00366     }
00367 
00368     RETURN(0);
00369 }
00370 
00371 
00372 /*----------------------------------------------------------------------
00373  * check_norm_dirs      - check to reverse normal directions
00374  *
00375  * Count how many of six bounding points point away from the center.
00376  *     6   : perfect, no change
00377  *     5   : provide warning, but apply no change
00378  *     2-4 : cannot determine direction
00379  *           --> this is a program terminating failure condition
00380  *     1   : provide warning, and reverse direction
00381  *     0   : no warning, just reverse direction
00382  *
00383  * return   0 : success (cases 0,1,5,6)
00384  *         -1 : failure (cases 2-4)
00385  *----------------------------------------------------------------------
00386 */
00387 int check_norm_dirs ( v2s_opts_t * sopt, v2s_param_t * p, int surf )
00388 {
00389     SUMA_ixyz * coords;
00390     THD_fvec3 * norms;
00391     float       fmin[3], fmax[3];
00392     int         min[3], max[3];
00393     int         match[6];               /* +/- 1, for direction match */
00394     int         node, c, ncount;
00395 
00396 ENTRY("check_norm_dirs");
00397 
00398     norms  = p->surf[surf].norm;         /* point to norms for this surface  */
00399     coords = p->surf[surf].ixyz;         /* point to coords for this surface */
00400 
00401     /* init mins and max's from node 0 */
00402     min[0] = max[0] = min[1] = max[1] = min[2] = max[2] = 0;
00403 
00404     fmin[0] = fmax[0] = coords->x;
00405     fmin[1] = fmax[1] = coords->y;
00406     fmin[2] = fmax[2] = coords->z;
00407 
00408     /* now check the rest of them */
00409     for ( node = 1; node < p->surf[surf].num_ixyz; node++, coords++ )
00410     {
00411         if ( fmin[0] > coords[node].x )         /* x min */
00412         {
00413             min [0] = node;
00414             fmin[0] = coords[node].x;
00415         }
00416         if ( fmax[0] < coords[node].x )         /* x max */
00417         {
00418             max [0] = node;
00419             fmax[0] = coords[node].x;
00420         }
00421 
00422         if ( fmin[1] > coords[node].y )         /* y min */
00423         {
00424             min [1] = node;
00425             fmin[1] = coords[node].y;
00426         }
00427         if ( fmax[1] < coords[node].y )         /* y max */
00428         {
00429             max [1] = node;
00430             fmax[1] = coords[node].y;
00431         }
00432 
00433         if ( fmin[2] > coords[node].z )         /* z min */
00434         {
00435             min [2] = node;
00436             fmin[2] = coords[node].z;
00437         }
00438         if ( fmax[2] < coords[node].z )         /* z max */
00439         {
00440             max [2] = node;
00441             fmax[2] = coords[node].z;
00442         }
00443     }
00444 
00445     if ( sopt->debug > 1 )
00446         fprintf(stderr,"++ normals:\n"
00447                 "      mins       : %d, %d, %d\n"
00448                 "      min coords : %f, %f, %f\n"
00449                 "      mins0      : %f, %f, %f\n"
00450                 "      mins1      : %f, %f, %f\n"
00451                 "      mins2      : %f, %f, %f\n"
00452                 "\n"
00453                 "      maxs       : %d, %d, %d\n"
00454                 "      max coords : %f, %f, %f\n"
00455                 "      maxs0      : %f, %f, %f\n"
00456                 "      maxs1      : %f, %f, %f\n"
00457                 "      maxs2      : %f, %f, %f\n",
00458                 min[0], min[1], min[2], 
00459                 fmin[0], fmin[1], fmin[2], 
00460                 coords[min[0]].x, coords[min[0]].y, coords[min[0]].z, 
00461                 coords[min[1]].x, coords[min[1]].y, coords[min[1]].z, 
00462                 coords[min[2]].x, coords[min[2]].y, coords[min[2]].z, 
00463                 max[0], max[1], max[2], 
00464                 fmax[0], fmax[1], fmax[2], 
00465                 coords[max[0]].x, coords[max[0]].y, coords[max[0]].z, 
00466                 coords[max[1]].x, coords[max[1]].y, coords[max[1]].z, 
00467                 coords[max[2]].x, coords[max[2]].y, coords[max[2]].z);
00468 
00469     /* now count the number of normals pointing "away from" the center */
00470     /* fixed directions - inconsistent usage       07 Apr 2004 [rickr] */
00471     match[0] = norms[min[0]].xyz[0] < 0;
00472     match[1] = norms[min[1]].xyz[1] < 0;
00473     match[2] = norms[min[2]].xyz[2] < 0;
00474 
00475     match[3] = norms[max[0]].xyz[0] > 0;
00476     match[4] = norms[max[1]].xyz[1] > 0;
00477     match[5] = norms[max[2]].xyz[2] > 0;
00478 
00479     if ( sopt->debug > 1 )
00480         fprintf(stderr,"-- matches[0..5] = (%d, %d, %d,  %d, %d, %d)\n",
00481                 match[0], match[1], match[2], match[3], match[4], match[5] );
00482 
00483     ncount = 0;
00484     for ( c = 0; c < 6; c++ )
00485         if ( match[c] )
00486             ncount++;
00487 
00488     /* do we fail? */
00489     if ( (ncount >= 2) && (ncount <= 4) )
00490     {
00491         fprintf(stderr, "** cannot determine directions for normals:\n"
00492                 "   To proceed, use one of -keep_norm_dir/-reverse_norm_dir.\n"
00493                 "   \n"
00494                 "   It is ~%d%% likely that you will want to negate the\n"
00495                 "   normal length in '-norm_len'\n",
00496                 (int)(100*ncount/6.0) );
00497         RETURN(-1);
00498     }
00499 
00500     /* or do we just warn the user? */
00501     if ( (ncount == 1) || (ncount == 5) )
00502         fprintf(stderr,"** warning: only 83%% sure of direction of normals\n");
00503     
00504     /* do we need to reverse the direction? */
00505     if ( ncount < 2 )
00506     {
00507         fprintf(stderr,"-- reversing direction of normals\n");
00508         sopt->norm_len *= -1.0;
00509     }
00510 
00511     RETURN(0);
00512 }
00513 
00514 
00515 /*----------------------------------------------------------------------
00516  * copy_surfaces - fill SUMA_surface structures
00517  *
00518  *
00519  *
00520  * return -1 : on error
00521  *         0 : on success
00522  *----------------------------------------------------------------------
00523 */
00524 int copy_surfaces ( v2s_opts_t * sopt, v2s_param_t * p, int nsurf )
00525 {
00526     SUMA_SurfaceObject ** so;
00527     float                 radius[V2S_MAX_SURFS];
00528     int                   rv, sindex;
00529 
00530 ENTRY("copy_surfaces");
00531 
00532     if ( sopt == NULL || p == NULL || nsurf < 0 )
00533     {
00534         fprintf( stderr, "** anl: bad params (%p,%p,%d)\n", sopt, p, nsurf );
00535         RETURN(-1);
00536     }
00537 
00538     /* create a temporary list of surface pointers */
00539     so = (SUMA_SurfaceObject **)calloc(nsurf, sizeof(SUMA_SurfaceObject *));
00540     if ( so == NULL )
00541     {
00542         fprintf( stderr, "** anl: failed to alloc %d surf pointers\n", nsurf );
00543         RETURN(-1);
00544     }
00545 
00546     if ( (rv = get_mappable_surfs( so, nsurf, sopt->debug )) != nsurf )
00547     {
00548         fprintf( stderr, "** found %d mappable surfaces (but expected %d)\n",
00549                  rv, nsurf );
00550         free(so);
00551         RETURN(-1);
00552     }
00553 
00554     /* fill SUMA_surface structs */
00555 
00556     p->nsurf     = nsurf;
00557     for ( sindex = 0; sindex < nsurf; sindex++ )
00558     {
00559         if ( suma2afni_surf( sopt, p, so[sindex], sindex ) )
00560             RETURN(-1);
00561         surf_ave_radius(radius+sindex, so[sindex], sopt->debug);
00562     }
00563 
00564     if ( sopt->debug ) fprintf(stderr,"-- surfaces converted: suma to afni\n");
00565 
00566     free(so);
00567 
00568     RETURN(0);
00569 }
00570 
00571 
00572 /*----------------------------------------------------------------------
00573  * suma2afni_surf      - convert surface from SUMA to AFNI structures
00574  *----------------------------------------------------------------------
00575 */
00576 int suma2afni_surf(v2s_opts_t * sopt, v2s_param_t * p, SUMA_SurfaceObject * so,
00577                    int sindex)
00578 {
00579     SUMA_surface * sp;
00580     float        * fp;
00581     int            node;
00582 
00583 ENTRY("suma2afni_surf");
00584 
00585     if ( !sopt || !p || !so || sindex < 0 || sindex >= V2S_MAX_SURFS )
00586     {
00587         fprintf(stderr,"** s2as: bad params (%p,%p,%p,%d)\n",sopt,p,so,sindex);
00588         RETURN(-1);
00589     }
00590 
00591     sp = p->surf + sindex;
00592 
00593     sp->type      = SUMA_SURFACE_TYPE;  /* always (for a SUMA_surface)       */
00594     sp->num_ixyz  = so->N_Node;         /* number of nodes                   */
00595     sp->nall_ixyz = so->N_Node;         /* allocate later in this function   */
00596     sp->num_ijk   = 0;                  /* no triangles                      */
00597     sp->nall_ijk  = 0;                  /* twice as many triangles as before */
00598 
00599     sp->seq       = 1;                  /* surfaces are sequential           */
00600     sp->seqbase   = 0;                  /*     - from 0                      */
00601     sp->sorted    = 1;                  /*     - and therefore, a sorted lot */
00602 
00603     sp->ixyz      = NULL;               /* just for the moment ...           */
00604     sp->norm      = NULL;
00605 
00606     if ( !so->NodeList )
00607     {
00608         fprintf(stderr,"** s2as: missing surface NodeList for '%s'\n",
00609                 so->Label ? so->Label: "<no label>");
00610         RETURN(1);
00611     }
00612 
00613     if ( sopt->use_norms )
00614     {
00615         if ( so->NodeNormList )
00616         {
00617             sp->norm = (THD_fvec3 *)malloc(sp->num_ixyz * sizeof(THD_fvec3));
00618             if ( !sp->norm )
00619             {
00620                 fprintf(stderr,"** s2as: cannot allocate %d THD_fvec3's\n",
00621                         sp->num_ixyz);
00622                 RETURN(1);
00623             }
00624 
00625             if ( sopt->debug > 1 )
00626                 fprintf(stderr,"++ filling in norms for surf # %d (%d bytes)\n",
00627                         sindex, (int)(sp->num_ixyz * sizeof(THD_fvec3)));
00628 
00629             fp = so->NodeNormList;
00630             for ( node = 0; node < sp->num_ixyz; node++ )
00631             {
00632                 sp->norm[node].xyz[0] = *fp++;
00633                 sp->norm[node].xyz[1] = *fp++;
00634                 sp->norm[node].xyz[2] = *fp++;
00635             }
00636         }
00637         else
00638         {
00639             fprintf(stderr,"** missing normals for surface # %d, '%s'\n",
00640                     sindex, so->Label ? so->Label: "<no label>");
00641         }
00642     }
00643 
00644     sp->ixyz = (SUMA_ixyz *)malloc(sp->num_ixyz * sizeof(SUMA_ixyz));
00645 
00646     if ( !sp->ixyz )
00647     {
00648         fprintf(stderr,"** failed to allocate %d SUMA_ixyz\n",sp->num_ixyz);
00649         if (sp->norm) free(sp->norm);
00650         RETURN(1);
00651     }
00652     else if ( sopt->debug > 1 )
00653         fprintf(stderr,"++ s2as: allocated %d SUMA_ixyz nodes (%d bytes)\n",
00654                 sp->num_ixyz, (int)(sp->num_ixyz*sizeof(SUMA_ixyz)));
00655 
00656     fp = so->NodeList;
00657     for ( node = 0; node < sp->num_ixyz; node++ )
00658     {
00659         sp->ixyz[node].id = node;
00660         sp->ixyz[node].x  = *fp++;
00661         sp->ixyz[node].y  = *fp++;
00662         sp->ixyz[node].z  = *fp++;
00663     }
00664 
00665     sp->xbot = so->MinDims[0];
00666     sp->ybot = so->MinDims[1];
00667     sp->zbot = so->MinDims[2];
00668 
00669     sp->xtop = so->MaxDims[0];
00670     sp->ytop = so->MaxDims[1];
00671     sp->ztop = so->MaxDims[2];
00672 
00673     sp->xcen = so->Center[0];
00674     sp->ycen = so->Center[1];
00675     sp->zcen = so->Center[2];
00676 
00677     if (so->idcode_str)
00678     {
00679         strncpy(sp->idcode, so->idcode_str, 31);
00680         sp->idcode[31] = '\0';
00681     }
00682     else
00683         UNIQ_idcode_fill(sp->idcode);
00684 
00685     sp->idcode_ldp[0]  = '\0';  /* maybe assign these ... */
00686     sp->idcode_dset[0] = '\0';
00687 
00688     strncpy(sp->label, so->Label, 63);  sp->label[63] = '\0';
00689     if (so->LocalDomainParent && *so->LocalDomainParent)
00690     {
00691         strncpy(sp->label_ldp, so->LocalDomainParent, 63);
00692         sp->label[63] = '\0';
00693     }
00694     else
00695         strcpy(sp->label_ldp, "no_LDP_label");
00696 
00697     sp->vv = NULL;      /* no mappings, for now */
00698     sp->vn = NULL;
00699 
00700     RETURN(0);
00701 }
00702 
00703 
00704 /*----------------------------------------------------------------------
00705  * get_mappable_surfs - return mappable surface objects
00706  *
00707  * return the number of surfaces found
00708  *----------------------------------------------------------------------
00709 */
00710 int get_mappable_surfs( SUMA_SurfaceObject ** slist, int how_many, int debug )
00711 {
00712     SUMA_SurfaceObject * so;
00713     int                  count, socount = 0;
00714 
00715 ENTRY("get_mappable_surfs");
00716 
00717     if ( slist == NULL )
00718     {
00719         fprintf( stderr, "** gms: missing slist!\n" );
00720         RETURN(-1);
00721     }
00722 
00723     for ( count = 0; count < SUMAg_N_DOv; count++ )
00724     {
00725         if ( ! SUMA_isSO(SUMAg_DOv[count]) )
00726             continue;
00727 
00728         so = (SUMA_SurfaceObject *)SUMAg_DOv[count].OP;
00729 
00730         if ( ! so->AnatCorrect )
00731         {
00732             if ( debug )
00733                 fprintf(stderr,"-- surf #%d '%s', anat not correct, skipping\n",
00734                         socount, CHECK_NULL_STR(so->Label));
00735             if ( debug > 1 )
00736                 fprintf(stderr,"** consider adding the following to the "
00737                                "surface definition in the spec file:\n"
00738                                "       Anatomical = Y\n");
00739             continue;
00740         }
00741 
00742         if ( debug > 1 )
00743             fprintf( stderr, "\n---------- surface #%d '%s' -----------\n",
00744                      socount, CHECK_NULL_STR(so->Label) );
00745         if ( debug > 2 ) SUMA_Print_Surface_Object( so, stderr );
00746 
00747         if ( socount < how_many )       /* store a good surface */
00748             slist[socount] = so;
00749 
00750         socount++;
00751     }
00752 
00753     if ( debug > 1 )
00754         fprintf( stderr, "++ found %d mappable surfaces\n", socount );
00755 
00756     RETURN(socount);
00757 }
00758 
00759 
00760 /*----------------------------------------------------------------------
00761  * set_smap_opts  - fill v2s_opts_t struct
00762  *
00763  * return  0 : success
00764  *        -1 : error condition
00765  *----------------------------------------------------------------------
00766 */
00767 int set_smap_opts( opts_t * opts, v2s_param_t * p, v2s_opts_t * sopt )
00768 {
00769     int nsurf = 1;
00770 
00771 ENTRY("set_smap_opts");
00772 
00773     memset( sopt, 0, sizeof(*sopt) );
00774 
00775     if ( (sopt->map = check_map_func( opts->map_str )) == E_SMAP_INVALID )
00776         RETURN(-1);
00777 
00778     /* set defaults before checking map type */
00779 
00780     sopt->gp_index      = opts->gp_index;
00781     sopt->debug         = opts->debug;
00782     sopt->dnode         = opts->dnode;
00783     sopt->no_head       = opts->no_head;
00784     sopt->skip_cols     = opts->skip_cols;
00785 
00786     sopt->first_node    = opts->first_node > 0 ? opts->first_node : 0;
00787     sopt->last_node     = opts->last_node  > 0 ? opts->last_node  : 0;
00788     if ( sopt->first_node > sopt->last_node )
00789     {
00790         fprintf(stderr, "** error: -first_node (%d) > -last_node (%d)\n",
00791                 sopt->first_node, sopt->last_node);
00792         RETURN(1);
00793     }
00794 
00795     sopt->use_norms = opts->use_norms;
00796     sopt->norm_len  = opts->norm_len;
00797     sopt->norm_dir  = opts->norm_dir;
00798     sopt->f_index   = V2S_INDEX_VOXEL;       /* default is "voxel" */
00799 
00800     if ( (opts->f_index_str != NULL) &&
00801          (!strncmp(opts->f_index_str, "node", 4)) )
00802             sopt->f_index = V2S_INDEX_NODE;
00803 
00804     if ( opts->f_steps <= V2S_M2_STEPS_DEFAULT )        /* default is 2    */
00805         sopt->f_steps = V2S_M2_STEPS_DEFAULT;
00806     else
00807         sopt->f_steps = opts->f_steps;
00808 
00809     sopt->f_p1_fr      = opts->f_p1_fr;      /* copy fractions & distances */
00810     sopt->f_pn_fr      = opts->f_pn_fr;
00811     sopt->f_p1_mm      = opts->f_p1_mm;
00812     sopt->f_pn_mm      = opts->f_pn_mm;
00813     sopt->outfile_1D   = opts->outfile_1D;
00814     sopt->outfile_niml = opts->outfile_niml;
00815     sopt->oob          = opts->oob;             /* out of bounds info */
00816     sopt->oom          = opts->oom;             /* out of bounds info */
00817 
00818     if ( sopt->oom.show && !p->cmask )
00819     {
00820         fprintf(stderr,"** '-cmask' option is required with '-oom_value'\n");
00821         RETURN(1);
00822     }
00823 
00824     /* great, now my switch is ineffective - save for later */
00825     switch (sopt->map)
00826     {
00827         default:
00828             break;
00829 
00830         case E_SMAP_AVE:
00831         case E_SMAP_COUNT:
00832         case E_SMAP_MAX:
00833         case E_SMAP_MAX_ABS:
00834         case E_SMAP_MIN:
00835         case E_SMAP_MASK2:
00836         case E_SMAP_SEG_VALS:
00837         case E_SMAP_MEDIAN:
00838         case E_SMAP_MODE:
00839             nsurf = 2;
00840             break;
00841 
00842         case E_SMAP_MIDPT:      /* continue to SMAP_MASK */
00843             nsurf = 2;
00844 
00845         case E_SMAP_MASK:
00846             if (sopt->f_steps != V2S_M2_STEPS_DEFAULT)
00847             {
00848                 fprintf(stderr,"** -f_steps option not valid\n");
00849                 RETURN(-1);
00850             }
00851 
00852             /* we will only use the first point in the computation */
00853             sopt->f_steps = 1;
00854             break;
00855     }
00856 
00857     if ( (nsurf == 2) && !opts->snames[1] && !opts->use_norms )
00858     {
00859         fprintf(stderr, "** function '%s' requires 2 surfaces\n",
00860                         gv2s_map_names[sopt->map]);
00861         RETURN(-1);
00862     }
00863 
00864     p->over_steps = v2s_vals_over_steps(sopt->map);
00865 
00866     if ( opts->debug > 0 )
00867         disp_v2s_opts_t( "++ smap opts set :", sopt );
00868 
00869     RETURN(0);
00870 }
00871 
00872 
00873 /*----------------------------------------------------------------------
00874  * free memory, close output file
00875  *----------------------------------------------------------------------
00876 */
00877 int final_clean_up ( opts_t * opts, v2s_param_t * p, SUMA_SurfSpecFile * spec )
00878 {
00879     int surf;
00880 ENTRY("final_clean_up");
00881 
00882     for ( surf = 0; surf < p->nsurf; surf++ )
00883     {
00884         if ( opts->debug > 2    ) fprintf(stderr,"-- freeing nodes[%d]\n",surf);
00885         if ( p->surf[surf].ixyz ) free(p->surf[surf].ixyz);
00886         if ( opts->debug > 2    ) fprintf(stderr,"-- freeing norms[%d]\n",surf);
00887         if ( p->surf[surf].norm ) free(p->surf[surf].norm);
00888     }
00889 
00890     if ( p->cmask ) free(p->cmask);
00891 
00892     if ( opts->debug > 2 ) fprintf(stderr,"-- freeing DOV\n");
00893     if ( ( SUMAg_DOv != NULL ) &&
00894          ( SUMA_Free_Displayable_Object_Vect(SUMAg_DOv, SUMAg_N_DOv) == 0 ) )
00895         fprintf(stderr, "** failed SUMA_Free_Displayable_Object_Vect()\n" );
00896 
00897     if ( opts->debug > 2 ) fprintf(stderr,"-- freeing SVSV\n");
00898     if ( ( SUMAg_SVv != NULL ) &&
00899          ( SUMA_Free_SurfaceViewer_Struct_Vect(SUMAg_SVv, SUMAg_N_SVv) == 0 ) )
00900         fprintf( stderr, "** failed SUMA_Free_SurfaceViewer_Struct_Vect()\n" );
00901 
00902     if ( opts->debug > 2 ) fprintf(stderr,"-- freeing CF\n");
00903     if ( ( SUMAg_CF != NULL ) && ( SUMA_Free_CommonFields(SUMAg_CF) == 0 ) )
00904         fprintf( stderr, "** failed SUMA_Free_CommonFields()\n" );
00905 
00906     if ( opts->debug > 1 ) fprintf(stderr,"-- freeing complete\n");
00907 
00908     RETURN(0);
00909 }
00910 
00911 
00912 /*----------------------------------------------------------------------
00913  * read surfaces (much stolen from SUMA_suma.c - thanks Ziad!)
00914  *----------------------------------------------------------------------
00915 */
00916 int read_surf_files ( opts_t * opts, SUMA_SurfSpecFile * spec )
00917 {
00918     int debug, rv;                                      /* v3.5 [rickr] */
00919     
00920 ENTRY("read_surf_files");
00921 
00922     debug = (opts->debug > 2);
00923 
00924     if ( debug )
00925         fputs( "-- SUMA_Create_CommonFields()...\n", stderr );
00926 
00927     /* initialize common fields struct */
00928     SUMAg_CF = SUMA_Create_CommonFields();
00929 
00930     if ( SUMAg_CF == NULL )
00931     {
00932         fprintf( stderr, "** failed SUMA_Create_CommonFields(), exiting...\n" );
00933         RETURN(-1);
00934     }
00935 
00936     /* for SUMA type notifications */
00937     if ( opts->debug > 3 )
00938     {
00939         SUMAg_CF->MemTrace = 1;
00940 
00941         if ( opts->debug > 4 )
00942             SUMAg_CF->InOut_Notify = 1;
00943     }
00944 
00945     if ( debug )
00946         fputs( "-- SUMA_Alloc_DisplayObject_Struct()...\n", stderr );
00947 
00948     SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct(SUMA_MAX_DISPLAYABLE_OBJECTS);
00949 
00950     if ( debug )        /* can't SUMA_ShowSpecStruct() yet    - v3.9 */
00951         fputs( "-- SUMA_Read_SpecFile()...\n", stderr );
00952 
00953     if ( SUMA_Read_SpecFile( opts->spec_file, spec) == 0 )
00954     {
00955         fprintf( stderr, "** failed SUMA_Read_SpecFile(), exiting...\n" );
00956         RETURN(-1);
00957     }
00958 
00959     rv = SUMA_spec_select_surfs(spec, opts->snames, V2S_MAX_SURFS, opts->debug);
00960     if ( rv < 1 )
00961     {
00962         if ( rv == 0 )
00963             fprintf(stderr,"** no named surfaces found in spec file\n");
00964         RETURN(-1);
00965     }
00966 
00967     if ( debug )
00968         SUMA_ShowSpecStruct(spec, stderr, opts->debug > 2 ? 3 : 1);
00969 
00970     if ( SUMA_spec_set_map_refs(spec, opts->debug) != 0 )
00971         RETURN(-1);
00972 
00973     /* make sure only group was read from spec file */
00974     if ( spec->N_Groups != 1 )
00975     {
00976         fprintf( stderr,"** error: N_Groups <%d> must be 1 in spec file <%s>\n",
00977                  spec->N_Groups, opts->spec_file );
00978         RETURN(-1);
00979     }
00980 
00981     if ( debug )
00982         fputs( "-- SUMA_LoadSpec_eng()...\n", stderr );
00983 
00984     /* actually load the surface(s) from the spec file */
00985     if (SUMA_LoadSpec_eng(spec,SUMAg_DOv,&SUMAg_N_DOv,opts->sv_file,debug,
00986              SUMAg_CF->DsetList) == 0)     /* DsetList   26 Mar 2004 [ziad] */
00987     {
00988         fprintf( stderr, "** error: failed SUMA_LoadSpec_eng(), exiting...\n" );
00989         RETURN(-1);
00990     }
00991 
00992     if ( opts->debug > 1 )
00993         fprintf(stderr, "++ %d surfaces loaded.\n", spec->N_Surfs );
00994 
00995     RETURN(0);
00996 }
00997 
00998 
00999 /*----------------------------------------------------------------------
01000  * init_options - fill opts struct, display help
01001  *----------------------------------------------------------------------
01002 */
01003 int init_options ( opts_t * opts, int argc, char * argv [] )
01004 {
01005     int ac, ind;
01006 
01007 ENTRY("init_options");
01008 
01009     if ( argc < 2 )
01010     {
01011         usage( PROG_NAME, V2S_USE_LONG );
01012         RETURN(-1);
01013     }
01014 
01015     /* clear out the options structure */
01016     memset( opts, 0, sizeof( opts_t) );
01017     opts->gpar_file    = NULL;
01018     opts->outfile_1D   = NULL;
01019     opts->outfile_niml = NULL;
01020     opts->spec_file    = NULL;
01021     opts->sv_file      = NULL;
01022     opts->cmask_cmd    = NULL;
01023     opts->map_str      = NULL;
01024     opts->snames[0]    = NULL;
01025     opts->snames[1]    = NULL;
01026     opts->f_index_str  = NULL;
01027 
01028     opts->gp_index     = -1;            /* means none: use all       */
01029     opts->norm_len     = 1.0;           /* init to 1.0 millimeter    */
01030     opts->dnode        = -1;            /* init to something invalid */
01031 
01032     for ( ac = 1; ac < argc; ac++ )
01033     {
01034         /* alphabetical... */
01035         if ( ! strncmp(argv[ac], "-cmask", 6) )
01036         {
01037             if ( (ac+1) >= argc )
01038             {
01039                 fputs( "option usage: -cmask COMMAND\n\n", stderr );
01040                 usage( PROG_NAME, V2S_USE_SHORT );
01041                 RETURN(-1);
01042             }
01043 
01044             opts->cmask_cmd = argv[++ac];
01045         }
01046         else if ( ! strncmp(argv[ac], "-debug", 6) )
01047         {
01048             if ( (ac+1) >= argc )
01049             {
01050                 fputs( "option usage: -debug LEVEL\n\n", stderr );
01051                 usage( PROG_NAME, V2S_USE_SHORT );
01052                 RETURN(-1);
01053             }
01054 
01055             opts->debug = atoi(argv[++ac]);
01056             if ( opts->debug < 0 || opts->debug > V2S_DEBUG_MAX_LEV )
01057             {
01058                 fprintf( stderr, "bad debug level <%d>, should be in [0,%d]\n",
01059                         opts->debug, V2S_DEBUG_MAX_LEV );
01060                 usage( PROG_NAME, V2S_USE_SHORT );
01061                 RETURN(-1);
01062             }
01063         }
01064         else if ( ! strncmp(argv[ac], "-dnode", 6) )
01065         {
01066             if ( (ac+1) >= argc )
01067             {
01068                 fputs( "option usage: -dnode NODE_NUM\n\n", stderr );
01069                 usage( PROG_NAME, V2S_USE_SHORT );
01070                 RETURN(-1);
01071             }
01072 
01073             opts->dnode = atoi(argv[++ac]);
01074         }
01075         else if ( ! strncmp(argv[ac], "-f_index", 7) )
01076         {
01077             if ( (ac+1) >= argc )
01078             {
01079                 fputs( "option usage: -f_index INDEX_TYPE\n\n", stderr );
01080                 usage( PROG_NAME, V2S_USE_SHORT );
01081                 RETURN(-1);
01082             }
01083 
01084             opts->f_index_str = argv[++ac];
01085         }
01086         else if ( ! strncmp(argv[ac], "-f_keep_surf_order", 9) )
01087         {
01088             /*  opts->f_kso = 1;                v3.8 */
01089 
01090             fprintf(stderr,"** the -f_keep_surf_order option is depreciated\n"
01091                     "   in favor of -surf_A and -surf_B (version 3.8)\n");
01092             RETURN(-1);
01093         }
01094         else if ( ! strncmp(argv[ac], "-f_p1_fr", 9) )
01095         {
01096             if ( (ac+1) >= argc )
01097             {
01098                 fputs( "option usage: -f_p1_fr FRACTION\n\n", stderr );
01099                 usage( PROG_NAME, V2S_USE_SHORT );
01100                 RETURN(-1);
01101             }
01102 
01103             opts->f_p1_fr = atof(argv[++ac]);
01104         }
01105         else if ( ! strncmp(argv[ac], "-f_pn_fr", 9) )
01106         {
01107             if ( (ac+1) >= argc )
01108             {
01109                 fputs( "option usage: -f_pn_fr FRACTION\n\n", stderr );
01110                 usage( PROG_NAME, V2S_USE_SHORT );
01111                 RETURN(-1);
01112             }
01113 
01114             opts->f_pn_fr = atof(argv[++ac]);
01115         }
01116         else if ( ! strncmp(argv[ac], "-f_p1_mm", 9) )
01117         {
01118             if ( (ac+1) >= argc )
01119             {
01120                 fputs( "option usage: -f_p1_mm DISTANCE\n\n", stderr );
01121                 usage( PROG_NAME, V2S_USE_SHORT );
01122                 RETURN(-1);
01123             }
01124 
01125             opts->f_p1_mm = atof(argv[++ac]);
01126         }
01127         else if ( ! strncmp(argv[ac], "-f_pn_mm", 9) )
01128         {
01129             if ( (ac+1) >= argc )
01130             {
01131                 fputs( "option usage: -f_pn_mm DISTANCE\n\n", stderr );
01132                 usage( PROG_NAME, V2S_USE_SHORT );
01133                 RETURN(-1);
01134             }
01135 
01136             opts->f_pn_mm = atof(argv[++ac]);
01137         }
01138         else if ( ! strncmp(argv[ac], "-f_steps", 7) )
01139         {
01140             if ( (ac+1) >= argc )
01141             {
01142                 fputs( "option usage: -f_steps NUM_STEPS\n\n", stderr );
01143                 usage( PROG_NAME, V2S_USE_SHORT );
01144                 RETURN(-1);
01145             }
01146 
01147             opts->f_steps = atoi(argv[++ac]);
01148         }
01149         else if ( ! strncmp(argv[ac], "-first_node", 11) )
01150         {
01151             if ( (ac+1) >= argc )
01152             {
01153                 fputs( "option usage: -first_node NODE_INDEX\n\n", stderr );
01154                 usage( PROG_NAME, V2S_USE_SHORT );
01155                 RETURN(-1);
01156             }
01157 
01158             opts->first_node = atoi(argv[++ac]);
01159         }
01160         else if ( ! strncmp(argv[ac], "-gp_index", 7) )
01161         {
01162             if ( (ac+1) >= argc )
01163             {
01164                 fputs( "option usage: -gp_index BRICK_INDEX\n\n", stderr );
01165                 usage( PROG_NAME, V2S_USE_SHORT );
01166                 RETURN(-1);
01167             }
01168 
01169             opts->gp_index = atoi(argv[++ac]);
01170         }
01171         else if ( ! strncmp(argv[ac], "-help", 5) )
01172         {
01173             usage( PROG_NAME, V2S_USE_LONG );
01174             RETURN(-1);
01175         }
01176         else if ( ! strncmp(argv[ac], "-hist", 5) )
01177         {
01178             usage( PROG_NAME, V2S_USE_HIST );
01179             RETURN(-1);
01180         }
01181         else if ( ! strncmp(argv[ac], "-v2s_hist", 9) )
01182         {
01183             usage( PROG_NAME, V2S_USE_LIB_HIST );
01184             RETURN(-1);
01185         }
01186         else if ( ! strncmp(argv[ac], "-grid_parent", 5) ||
01187                   ! strncmp(argv[ac], "-inset", 6)       ||
01188                   ! strncmp(argv[ac], "-input", 6) )
01189         {
01190             if ( (ac+1) >= argc )
01191             {
01192                 fputs( "option usage: -grid_parent INPUT_DSET\n\n", stderr );
01193                 usage( PROG_NAME, V2S_USE_SHORT );
01194                 RETURN(-1);
01195             }
01196 
01197             opts->gpar_file = argv[++ac];
01198         }
01199         else if ( ! strncmp(argv[ac], "-keep_norm_dir", 14) )
01200         {
01201             opts->norm_dir = V2S_NORM_KEEP;
01202         }
01203         else if ( ! strncmp(argv[ac], "-last_node", 11) )
01204         {
01205             if ( (ac+1) >= argc )
01206             {
01207                 fputs( "option usage: -last_node NODE_INDEX\n\n", stderr );
01208                 usage( PROG_NAME, V2S_USE_SHORT );
01209                 RETURN(-1);
01210             }
01211 
01212             opts->last_node = atoi(argv[++ac]);
01213         }
01214         else if ( ! strncmp(argv[ac], "-map_func", 4) )  /* mapping function */
01215         {
01216             if ( (ac+1) >= argc )
01217             {
01218                 fputs( "option usage: -map_func FUNCTION\n\n", stderr );
01219                 RETURN(-1);
01220             }
01221 
01222             opts->map_str = argv[++ac];     /* store user string for now */
01223         }
01224         else if ( ! strncmp(argv[ac], "-no_headers", 5) )
01225         {
01226             opts->no_head = 1;
01227         }
01228         else if ( ! strncmp(argv[ac], "-norm_len", 9) )
01229         {
01230             if ( (ac+1) >= argc )
01231             {
01232                 fputs( "option usage: -norm_len LENGTH\n\n", stderr );
01233                 usage( PROG_NAME, V2S_USE_SHORT );
01234                 RETURN(-1);
01235             }
01236 
01237             opts->norm_len = atof(argv[++ac]);
01238         }
01239         else if ( ! strncmp(argv[ac], "-oob_index", 8) )
01240         {
01241             if ( (ac+1) >= argc )
01242             {
01243                 fputs( "option usage: -oob_index INDEX_VALUE\n\n", stderr );
01244                 usage( PROG_NAME, V2S_USE_SHORT );
01245                 RETURN(-1);
01246             }
01247 
01248             opts->oob.show  = 1;
01249             opts->oob.index = atoi(argv[++ac]);
01250         }
01251         else if ( ! strncmp(argv[ac], "-oob_value", 8) )
01252         {
01253             if ( (ac+1) >= argc )
01254             {
01255                 fputs( "option usage: -oob_value VALUE\n\n", stderr );
01256                 usage( PROG_NAME, V2S_USE_SHORT );
01257                 RETURN(-1);
01258             }
01259 
01260             opts->oob.show  = 1;
01261             opts->oob.value = atof(argv[++ac]);
01262         }
01263         else if ( ! strncmp(argv[ac], "-oom_value", 8) )
01264         {
01265             if ( (ac+1) >= argc )
01266             {
01267                 fputs( "option usage: -oob_value VALUE\n\n", stderr );
01268                 usage( PROG_NAME, V2S_USE_SHORT );
01269                 RETURN(-1);
01270             }
01271 
01272             opts->oom.show  = 1;
01273             opts->oom.value = atof(argv[++ac]);
01274         }
01275         else if ( ! strncmp(argv[ac], "-out_1D", 7) )
01276         {
01277             if ( (ac+1) >= argc )
01278             {
01279                 fputs( "option usage: -out_1D OUTPUT_FILE\n\n", stderr );
01280                 usage( PROG_NAME, V2S_USE_SHORT );
01281                 RETURN(-1);
01282             }
01283 
01284             opts->outfile_1D = argv[++ac];
01285         }
01286         else if ( ! strncmp(argv[ac], "-out_niml", 7) )
01287         {
01288             if ( (ac+1) >= argc )
01289             {
01290                 fputs( "option usage: -out_niml OUTPUT_FILE\n\n", stderr );
01291                 usage( PROG_NAME, V2S_USE_SHORT );
01292                 RETURN(-1);
01293             }
01294 
01295             opts->outfile_niml = argv[++ac];
01296         }
01297         else if ( ! strncmp(argv[ac], "-reverse_norm_dir", 8) )
01298         {
01299             opts->norm_dir = V2S_NORM_REVERSE;
01300         }
01301         else if ( ! strncmp(argv[ac], "-skip_col_non_results", 15) )
01302             opts->skip_cols |= (V2S_SKIP_ALL & ~V2S_SKIP_VALS);
01303         else if ( ! strncmp(argv[ac], "-skip_col_nodes", 13) )
01304             opts->skip_cols |= V2S_SKIP_NODES;
01305         else if ( ! strncmp(argv[ac], "-skip_col_1dindex", 12) )
01306             opts->skip_cols |= V2S_SKIP_VOLIND;
01307         else if ( ! strncmp(argv[ac], "-skip_col_i", 11) )
01308             opts->skip_cols |= V2S_SKIP_I;
01309         else if ( ! strncmp(argv[ac], "-skip_col_j", 11) )
01310             opts->skip_cols |= V2S_SKIP_J;
01311         else if ( ! strncmp(argv[ac], "-skip_col_k", 11) )
01312             opts->skip_cols |= V2S_SKIP_K;
01313         else if ( ! strncmp(argv[ac], "-skip_col_vals", 13) )
01314             opts->skip_cols |= V2S_SKIP_NVALS;
01315         else if ( ! strncmp(argv[ac], "-skip_col_results", 13) )
01316             opts->skip_cols |= V2S_SKIP_VALS;
01317         else if ( ! strncmp(argv[ac], "-spec", 3) )
01318         {
01319             if ( (ac+1) >= argc )
01320             {
01321                 fputs( "option usage: -spec SPEC_FILE\n\n", stderr );
01322                 usage( PROG_NAME, V2S_USE_SHORT );
01323                 RETURN(-1);
01324             }
01325 
01326             opts->spec_file = argv[++ac];
01327         }
01328         else if ( ! strncmp(argv[ac], "-surf_", 6) )
01329         {
01330             if ( (ac+1) >= argc )
01331             {
01332                 fputs( "option usage: -surf_X SURF_NAME\n\n", stderr );
01333                 usage( PROG_NAME, V2S_USE_SHORT );
01334                 RETURN(-1);
01335             }
01336             ind = argv[ac][6] - 'A';
01337             if ( (ind < 0) || (ind >= V2S_MAX_SURFS) )
01338             {
01339                 fprintf(stderr,"** -surf_X option: '%s' out of range,\n"
01340                         "   use one of '-surf_A' through '-surf_%c'\n",
01341                         argv[ac], 'A'+V2S_MAX_SURFS-1);
01342                 RETURN(-1);
01343             }
01344 
01345             opts->snames[ind] = argv[++ac];
01346         }
01347         else if ( ! strncmp(argv[ac], "-sv", 3) )
01348         {
01349             if ( (ac+1) >= argc )
01350             {
01351                 fputs( "option usage: -sv SURFACE_VOLUME\n\n", stderr );
01352                 usage( PROG_NAME, V2S_USE_SHORT );
01353                 RETURN(-1);
01354             }
01355 
01356             opts->sv_file = argv[++ac];
01357         }
01358         else if ( ! strncmp(argv[ac], "-use_norms", 5) )
01359         {
01360             opts->use_norms = 1;
01361         }
01362         else if ( ! strncmp(argv[ac], "-version", 2) )
01363         {
01364             usage( PROG_NAME, V2S_USE_VERSION );
01365             RETURN(-1);
01366         }
01367         else     /* invalid option */
01368         {
01369             fprintf( stderr, "invalid option <%s>\n", argv[ac] );
01370             usage( PROG_NAME, V2S_USE_SHORT );
01371             RETURN(-1);
01372         }
01373     }
01374 
01375     RETURN(0);
01376 }
01377 
01378 /*----------------------------------------------------------------------
01379  * validate_options - fill param struct from options
01380  *
01381  *     - validate datasets
01382  *     - validate surface
01383  *----------------------------------------------------------------------
01384 */
01385 int validate_options ( opts_t * opts, v2s_param_t * p )
01386 {
01387 ENTRY("validate_options");
01388 
01389     memset( p, 0, sizeof(*p) );
01390     p->gpar  = NULL;
01391     p->cmask = NULL;
01392 
01393     if ( opts->debug > 0 )
01394     {
01395         usage( PROG_NAME, V2S_USE_VERSION );
01396         disp_opts_t ( "++ opts read: ", opts );
01397     }
01398 
01399     if ( check_map_func( opts->map_str ) == E_SMAP_INVALID )
01400         RETURN(-1);
01401 
01402     if ( !opts->outfile_1D && !opts->outfile_niml )
01403     {
01404         fprintf( stderr, "** missing '-out_1D OUTPUT_FILE' option\n" );
01405         RETURN(-1);
01406     }
01407 
01408     if ( opts->spec_file == NULL )
01409     {
01410         fprintf( stderr, "** missing '-spec_file SPEC_FILE' option\n" );
01411         RETURN(-1);
01412     }
01413 
01414     if ( opts->sv_file == NULL )
01415     {
01416         fprintf( stderr, "** missing '-sv SURF_VOL' option\n" );
01417         RETURN(-1);
01418     }
01419 
01420     if ( opts->snames[0] == NULL )
01421     {
01422         fprintf(stderr,"** missing '-surf_A SURF_NAME' option\n");
01423         RETURN(-1);
01424     }
01425 
01426     if ( opts->use_norms )
01427     {
01428         if ( opts->snames[1] )
01429         {
01430             fprintf(stderr,"** no '-use_norms' option with 2 surfaces\n");
01431             RETURN(-1);
01432         }
01433     }
01434     else if ( opts->norm_len != 1.0 || opts->norm_dir )
01435     {
01436         fprintf(stderr,"** options for normals requires '-use_norms'\n");
01437         RETURN(-1);
01438     }
01439 
01440     if ( check_outfile( opts, p ) != 0 )
01441         RETURN(-1);
01442 
01443     if ( validate_datasets( opts, p ) != 0 )
01444         RETURN(-1);
01445 
01446     if ( opts->debug > 1 )
01447         disp_v2s_param_t( "++ opts validated: ", p );
01448 
01449     RETURN(0);
01450 }
01451 
01452 
01453 /*----------------------------------------------------------------------
01454  * be sure the output file does not already exist
01455  *----------------------------------------------------------------------
01456 */
01457 int check_outfile( opts_t * opts, v2s_param_t * p )
01458 {
01459 ENTRY("check_outfile");
01460 
01461     if ( opts == NULL || p == NULL )
01462         RETURN(-1);
01463 
01464     if ( THD_is_file(opts->outfile_1D) )
01465     {
01466         fprintf(stderr, "** output file '%s' already exists\n",
01467                 opts->outfile_1D);
01468         RETURN(-1);
01469     }
01470 
01471     if ( THD_is_file(opts->outfile_niml) )
01472     {
01473         fprintf(stderr, "** output file '%s' already exists\n",
01474                 opts->outfile_niml);
01475         RETURN(-1);
01476     }
01477 
01478     RETURN(0);
01479 }
01480 
01481 
01482 /*----------------------------------------------------------------------
01483  * check_map_func
01484  *
01485  *     - check for map_str
01486  *     - validate the map type
01487  *----------------------------------------------------------------------
01488 */
01489 int check_map_func ( char * map_str )
01490 {
01491     int map;
01492 
01493 ENTRY("check_map_func");
01494 
01495     if ( map_str == NULL )
01496     {
01497         fprintf( stderr, "** missing option: '-map_func FUNCTION'\n" );
01498         RETURN(E_SMAP_INVALID);
01499     }
01500 
01501     map = v2s_map_type( map_str );
01502 
01503     switch ( map )
01504     {
01505         default:
01506             map = E_SMAP_INVALID;
01507             break;
01508 
01509         case E_SMAP_COUNT:
01510         case E_SMAP_MASK2:
01511             fprintf( stderr, "** function '%s' coming soon ...\n",
01512                      gv2s_map_names[map] );
01513             RETURN(E_SMAP_INVALID);
01514             break;
01515 
01516         case E_SMAP_AVE:
01517         case E_SMAP_MASK:
01518         case E_SMAP_MAX:
01519         case E_SMAP_MAX_ABS:
01520         case E_SMAP_MIN:
01521         case E_SMAP_MIDPT:
01522         case E_SMAP_SEG_VALS:
01523         case E_SMAP_MEDIAN:
01524         case E_SMAP_MODE:
01525             break;
01526     }
01527 
01528     if ( map == E_SMAP_INVALID )
01529         fprintf( stderr, "** invalid map string '%s'\n", map_str );
01530 
01531     RETURN(map);
01532 }
01533 
01534 
01535 /*----------------------------------------------------------------------
01536  * validate_datasets
01537  *
01538  * Note that we do not validate the SURFACE_VOLUME AFNI dataset here.
01539  * That is done in SUMA_LoadSpec().
01540  *
01541  * Verify the AFNI dataset used for value output.
01542  * Check for a cmask dataset and command.
01543  * Verify that AFNI dataset and the mask have the same size.
01544  *----------------------------------------------------------------------
01545 */
01546 int validate_datasets( opts_t * opts, v2s_param_t * p )
01547 {
01548     int ccount = 0;
01549 ENTRY("validate_datasets");
01550 
01551     p->gpar = THD_open_dataset( opts->gpar_file );
01552 
01553     if ( !ISVALID_DSET(p->gpar) )
01554     {
01555         if ( opts->gpar_file == NULL )
01556             fprintf( stderr, "** error: missing '-grid_parent DSET' option\n" );
01557         else
01558             fprintf( stderr, "** error: invalid input dataset '%s'\n",
01559                      opts->gpar_file);
01560         RETURN(-1);
01561     }
01562     else if ( DSET_BRICK_TYPE(p->gpar, 0) == MRI_complex )
01563     {
01564         fprintf(stderr,
01565                 "** failure: cannot deal with complex-valued dataset, '%s'\n",
01566                 opts->gpar_file);
01567         RETURN(-1);
01568     }
01569     else if ( opts->gp_index >= DSET_NVALS(p->gpar) )
01570     {
01571         fprintf(stderr,"** error: gp_index (%d) > max grid parent index (%d)\n",
01572                 opts->gp_index, DSET_NVALS(p->gpar)-1);
01573         RETURN(-1);
01574     }
01575 
01576     p->nvox = DSET_NVOX( p->gpar );
01577 
01578     /* -------------------------------------------------------------------- */
01579     /* check for cmask - casually stolen from 3dmaskdump.c (thanks, Bob! :) */
01580 
01581     if ( opts->cmask_cmd != NULL )
01582     {
01583         int    ncmask, clen = strlen( opts->cmask_cmd );
01584         char * cmd;
01585 
01586         /* save original cmask command, as EDT_calcmask() is destructive */
01587         cmd = (char *)malloc((clen + 1) * sizeof(char));
01588         strcpy( cmd, opts->cmask_cmd );
01589 
01590         p->cmask = EDT_calcmask( cmd, &ncmask );
01591 
01592         free( cmd );                       /* free EDT_calcmask() string */
01593 
01594         if ( p->cmask == NULL )
01595         {
01596             fprintf( stderr, "** failure: cannot compute mask from option:\n"
01597                      "   -cmask '%s'\n", opts->cmask_cmd );
01598             RETURN(-1);
01599         }
01600         if ( ncmask != p->nvox )
01601         {
01602             fprintf( stderr, "** error: input and cmask datasets do not have "
01603                      "the same dimensions\n" );
01604             RETURN(-1);
01605         }
01606         if ( ( ccount = THD_countmask( ncmask, p->cmask ) ) <= 0 )
01607         {
01608             fprintf( stderr, "** Warning!  No voxels in computed cmask!\n" );
01609             /* return -1;   continue, and let the user deal with it...  */
01610         }
01611     }
01612 
01613     if ( opts->debug > 0 )
01614     {
01615         fprintf( stderr, "++ input dset has nvox = %d, nvals = %d",
01616                  p->nvox, DSET_NVALS(p->gpar) );
01617         if ( p->cmask == NULL )
01618             fputc( '\n', stderr );
01619         else
01620             fprintf( stderr, " (%d voxels in mask)\n", ccount );
01621     }
01622 
01623     RETURN(0);
01624 }
01625 
01626 /*----------------------------------------------------------------------
01627  * usage  -  output usage information
01628  *
01629  * V2S_USE_SHORT        - display brief output
01630  * V2S_USE_LONG         - display long output
01631  * V2S_USE_VERSION      - show the VERSION of the program
01632  *----------------------------------------------------------------------
01633 */
01634 int usage ( char * prog, int level )
01635 {
01636 ENTRY("usage");
01637 
01638     if ( level == V2S_USE_SHORT )
01639     {
01640         fprintf( stderr,
01641                  "usage: %s [options] -spec SPEC_FILE -sv SURF_VOL "
01642                                     " -grid_parent AFNI_DSET\n"
01643                  "usage: %s -help\n",
01644                  prog, prog );
01645     }
01646     else if ( level == V2S_USE_LONG )
01647     {
01648         printf(
01649             "\n"
01650             "%s - map data from a volume domain to a surface domain\n"
01651             "\n"
01652             "  usage: %s [options] -spec SPEC_FILE -sv SURF_VOL \\\n"
01653             "                    -grid_parent AFNI_DSET -map_func MAP_FUNC\n"
01654             "\n"
01655             "This program is used to map data values from an AFNI volume\n"
01656             "dataset to a surface dataset.  A filter may be applied to the\n"
01657             "volume data to produce the value(s) for each surface node.\n"
01658             "\n"
01659             "The surface and volume domains are spacially matched via the\n"
01660             "'surface volume' AFNI dataset.  This gives each surface node xyz\n"
01661             "coordinates, which are then matched to the input 'grid parent'\n"
01662             "dataset.  This grid parent is an AFNI dataset containing the\n"
01663             "data values destined for output.\n"
01664             "\n"
01665             "Typically, two corresponding surfaces will be input (via the\n"
01666             "spec file and the '-surf_A' and '-surf_B' options), along with\n"
01667             "a mapping function and relevant options.  The mapping function\n"
01668             "will act as a filter over the values in the AFNI volume.\n"
01669             "\n"
01670             "Note that an alternative to using a second surface with the\n"
01671             "'-surf_B' option is to define the second surface by using the\n"
01672             "normals from the first surface.  By default, the second surface\n"
01673             "would be defined at a distance of 1mm along the normals, but the\n"
01674             "user may modify the applied distance (and direction).  See the\n"
01675             "'-use_norms' and '-norm_len' options for more details.\n"
01676             "\n"
01677             "For each pair of corresponding surface nodes, let NA be the node\n"
01678             "on surface A (such as a white/grey boundary) and NB be the\n"
01679             "corresponding node on surface B (such as a pial surface).  The\n"
01680             "filter is applied to the volume data values along the segment\n"
01681             "from NA to NB (consider the average or maximum as examples of\n"
01682             "filters).\n"
01683             "\n"
01684             "Note: if either endpoint of a segment is outside the grid parent\n"
01685             "      volume, that node (pair) will be skipped.\n"
01686             "\n"
01687             "Note: surface A corresponds to the required '-surf_A' argument,\n"
01688             "      while surface B corresponds to '-surf_B'.\n"
01689             "\n",
01690             prog, prog);
01691 
01692         printf(
01693             "By default, this segment only consists of the endpoints, NA and\n"
01694             "NB (the actual nodes on the two surfaces).  However the number\n"
01695             "of evenly spaced points along the segment may be specified with\n"
01696             "the -f_steps option, and the actual locations of NA and NB may\n"
01697             "be altered with any of the -f_pX_XX options, covered below.\n"
01698             "\n"
01699             "As an example, for each node pair, one could output the average\n"
01700             "value from some functional dataset along a segment of 10 evenly\n"
01701             "spaced points, where the segment endpoints are defined by the\n"
01702             "xyz coordinates of the nodes.  This is example 3, below.\n"
01703             "\n"
01704             "The mapping function (i.e. filter) is a required parameter to\n"
01705             "the program.\n"
01706             "\n"
01707             "Brief descriptions of the current mapping functions are as\n"
01708             "follows.  These functions are defined over a segment of points.\n"
01709             "\n"
01710             "    ave       : output the average of all voxel values along the\n"
01711             "                segment\n"
01712             "    mask      : output the voxel value for the trivial case of a\n"
01713             "                segment - defined by a single surface point\n"
01714             "    median    : output the median value from the segment\n"
01715             "    midpoint  : output the dataset value at the segment midpoint\n"
01716             "    mode      : output the mode of the values along the segment\n"
01717             "    max       : output the maximum volume value over the segment\n"
01718             "    max_abs   : output the dataset value with max abs over seg\n"
01719             "    min       : output the minimum volume value over the segment\n"
01720             "    seg_vals  : output _all_ volume values over the segment (one\n"
01721             "                sub-brick only)\n"
01722             "\n"
01723             );
01724 
01725         printf(
01726             "  --------------------------------------------------\n"
01727             "\n"
01728             "  examples:\n"
01729             "\n"
01730             "    1. Apply a single surface mask to output volume values over\n"
01731             "       each surface node.  Output is one value per sub-brick\n"
01732             "       (per surface node).\n"
01733             "\n"
01734             "    %s                                \\\n"
01735             "       -spec         fred.spec                \\\n"
01736             "       -surf_A       smoothwm                 \\\n"
01737             "       -sv           fred_anat+orig           \\\n"
01738             "       -grid_parent  fred_anat+orig           \\\n"
01739             "       -map_func     mask                     \\\n"
01740             "       -out_1D       fred_anat_vals.1D\n"
01741             "\n"
01742             "    2. Apply a single surface mask to output volume values over\n"
01743             "       each surface node.  In this case restrict input to the\n"
01744             "       mask implied by the -cmask option.  Supply additional\n"
01745             "       debug output, and more for surface node 1874\n"
01746             "\n"
01747             "    %s                                                \\\n"
01748             "       -spec         fred.spec                                \\\n"
01749             "       -surf_A       smoothwm                                 \\\n"
01750             "       -sv           fred_anat+orig                           \\\n"
01751             "       -grid_parent 'fred_epi+orig[0]'                        \\\n"
01752             "       -cmask       '-a fred_func+orig[2] -expr step(a-0.6)'  \\\n"
01753             "       -map_func     mask                                     \\\n"
01754             "       -debug        2                                        \\\n"
01755             "       -dnode        1874                                     \\\n"
01756             "       -out_niml     fred_epi_vals.niml\n"
01757             "\n"
01758             "    3. Given a pair of related surfaces, for each node pair,\n"
01759             "       break the connected line segment into 10 points, and\n"
01760             "       compute the average dataset value over those points.\n"
01761             "       Since the index is nodes, each of the 10 points will be\n"
01762             "       part of the average.  This could be changed so that only\n"
01763             "       values from distinct volume nodes are considered (by\n"
01764             "       changing the -f_index from nodes to voxels).  Restrict\n"
01765             "       input voxels to those implied by the -cmask option\n"
01766             "       Output is one average value per sub-brick (per surface\n"
01767             "       node).\n"
01768             "\n"
01769             "    %s                                                \\\n"
01770             "       -spec         fred.spec                                \\\n"
01771             "       -surf_A       smoothwm                                 \\\n"
01772             "       -surf_B       pial                                     \\\n"
01773             "       -sv           fred_anat+orig                           \\\n"
01774             "       -grid_parent  fred_func+orig                           \\\n"
01775             "       -cmask        '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
01776             "       -map_func     ave                                      \\\n"
01777             "       -f_steps      10                                       \\\n"
01778             "       -f_index      nodes                                    \\\n"
01779             "       -out_1D       fred_func_ave.1D\n"
01780             "\n"
01781             "    4. Similar to example 3, but restrict the output columns to\n"
01782             "       only node indices and values (i.e. skip 1dindex, i, j, k\n"
01783             "       and vals).\n"
01784             "\n"
01785             "    %s                                                \\\n"
01786             "       -spec         fred.spec                                \\\n"
01787             "       -surf_A       smoothwm                                 \\\n"
01788             "       -surf_B       pial                                     \\\n"
01789             "       -sv           fred_anat+orig                           \\\n"
01790             "       -grid_parent  fred_func+orig                           \\\n"
01791             "       -cmask        '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
01792             "       -map_func     ave                                      \\\n"
01793             "       -f_steps      10                                       \\\n"
01794             "       -f_index      nodes                                    \\\n"
01795             "       -skip_col_1dindex                                      \\\n"
01796             "       -skip_col_i                                            \\\n"
01797             "       -skip_col_j                                            \\\n"
01798             "       -skip_col_k                                            \\\n"
01799             "       -skip_col_vals                                         \\\n"
01800             "       -out_1D       fred_func_ave_short.1D\n"
01801             "\n"
01802             "    5. Similar to example 3, but each of the node pair segments\n"
01803             "       has grown by 10%% on the inside of the first surface,\n"
01804             "       and 20%% on the outside of the second.  This is a 30%%\n"
01805             "       increase in the length of each segment.  To shorten the\n"
01806             "       node pair segment, use a '+' sign for p1 and a '-' sign\n"
01807             "       for pn.\n"
01808             "       As an interesting side note, '-f_p1_fr 0.5 -f_pn_fr -0.5'\n"
01809             "       would give a zero length vector identical to that of the\n"
01810             "       'midpoint' filter.\n"
01811             "\n"
01812             "    %s                                                \\\n"
01813             "       -spec         fred.spec                                \\\n"
01814             "       -surf_A       smoothwm                                 \\\n"
01815             "       -surf_B       pial                                     \\\n"
01816             "       -sv           fred_anat+orig                           \\\n"
01817             "       -grid_parent  fred_func+orig                           \\\n"
01818             "       -cmask        '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
01819             "       -map_func     ave                                      \\\n"
01820             "       -f_steps      10                                       \\\n"
01821             "       -f_index      voxels                                   \\\n"
01822             "       -f_p1_fr      -0.1                                     \\\n"
01823             "       -f_pn_fr      0.2                                      \\\n"
01824             "       -out_1D       fred_func_ave2.1D\n"
01825             "\n"
01826             "    6. Similar to example 3, instead of computing the average\n"
01827             "       across each segment (one average per sub-brick), output\n"
01828             "       the volume value at _every_ point across the segment.\n"
01829             "       The output here would be 'f_steps' values per node pair,\n"
01830             "       though the output could again be restricted to unique\n"
01831             "       voxels along each segment with '-f_index voxels'.\n"
01832             "       Note that only sub-brick 0 will be considered here.\n"
01833             "\n"
01834             "    %s                                                \\\n"
01835             "       -spec         fred.spec                                \\\n"
01836             "       -surf_A       smoothwm                                 \\\n"
01837             "       -surf_B       pial                                     \\\n"
01838             "       -sv           fred_anat+orig                           \\\n"
01839             "       -grid_parent  fred_func+orig                           \\\n"
01840             "       -cmask        '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
01841             "       -map_func     seg_vals                                 \\\n"
01842             "       -f_steps      10                                       \\\n"
01843             "       -f_index      nodes                                    \\\n"
01844             "       -out_1D       fred_func_segvals_10.1D\n"
01845             "\n"
01846             "    7. Similar to example 6, but make sure there is output for\n"
01847             "       every node pair in the surfaces.  Since it is expected\n"
01848             "       that some nodes are out of bounds (meaning that they lie\n"
01849             "       outside the domain defined by the grid parent dataset),\n"
01850             "       the '-oob_value' option is added to include a default\n"
01851             "       value of 0.0 in such cases.  And since it is expected\n"
01852             "       that some node pairs are \"out of mask\" (meaning that\n"
01853             "       their resulting segment lies entirely outside the cmask),\n"
01854             "       the '-oom_value' was added to output the same default\n"
01855             "       value of 0.0.\n"
01856             "\n"
01857             "    %s                                                \\\n"
01858             "       -spec         fred.spec                                \\\n"
01859             "       -surf_A       smoothwm                                 \\\n"
01860             "       -surf_B       pial                                     \\\n"
01861             "       -sv           fred_anat+orig                           \\\n"
01862             "       -grid_parent  fred_func+orig                           \\\n"
01863             "       -cmask        '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
01864             "       -map_func     seg_vals                                 \\\n"
01865             "       -f_steps      10                                       \\\n"
01866             "       -f_index      nodes                                    \\\n"
01867             "       -oob_value    0.0                                      \\\n"
01868             "       -oom_value    0.0                                      \\\n"
01869             "       -out_1D       fred_func_segvals_10_all.1D\n"
01870             "\n"
01871             "    8. This is a basic example of calculating the average along\n"
01872             "       each segment, but where the segment is produced by only\n"
01873             "       one surface, along with its set of surface normals.  The\n"
01874             "       segments will be 2.5 mm in length.\n"
01875             "\n"
01876             "    %s                                                \\\n"
01877             "       -spec         fred.spec                                \\\n"
01878             "       -surf_A       smoothwm                                 \\\n"
01879             "       -sv           fred_anat+orig                           \\\n"
01880             "       -grid_parent  fred_anat+orig                           \\\n"
01881             "       -use_norms                                             \\\n"
01882             "       -norm_len     2.5                                      \\\n"
01883             "       -map_func     ave                                      \\\n"
01884             "       -f_steps      10                                       \\\n"
01885             "       -f_index      nodes                                    \\\n"
01886             "       -out_1D       fred_anat_norm_ave.2.5.1D\n"
01887             "\n"
01888             "    9. This is the same as example 8, but where the surface\n"
01889             "       nodes are restricted to the range 1000..1999 via the\n"
01890             "       options '-first_node' and '-last_node'.\n"
01891             "\n"
01892             "    %s                                                \\\n"
01893             "       -spec         fred.spec                                \\\n"
01894             "       -surf_A       smoothwm                                 \\\n"
01895             "       -sv           fred_anat+orig                           \\\n"
01896             "       -grid_parent  fred_anat+orig                           \\\n"
01897             "       -first_node   1000                                     \\\n"
01898             "       -last_node    1999                                     \\\n"
01899             "       -use_norms                                             \\\n"
01900             "       -norm_len     2.5                                      \\\n"
01901             "       -map_func     ave                                      \\\n"
01902             "       -f_steps      10                                       \\\n"
01903             "       -f_index      nodes                                    \\\n"
01904             "       -out_1D       fred_anat_norm_ave.2.5.1D\n"
01905             "\n"
01906             "  --------------------------------------------------\n",
01907             prog, prog, prog, prog, prog, prog, prog, prog, prog );
01908 
01909         printf(
01910             "\n"
01911             "  REQUIRED COMMAND ARGUMENTS:\n"
01912             "\n"
01913             "    -spec SPEC_FILE        : SUMA spec file\n"
01914             "\n"
01915             "        e.g. -spec fred.spec\n"
01916             "\n"
01917             "        The surface specification file contains the list of\n"
01918             "        mappable surfaces that are used.\n"
01919             "\n"
01920             "        See @SUMA_Make_Spec_FS and @SUMA_Make_Spec_SF.\n"
01921             "\n"
01922             "    -surf_A SURF_NAME      : name of surface A (from spec file)\n"
01923             "    -surf_B SURF_NAME      : name of surface B (from spec file)\n"
01924             "\n"
01925             "        e.g. -surf_A smoothwm\n"
01926             "        e.g. -surf_A lh.smoothwm\n"
01927             "        e.g. -surf_B lh.pial\n"
01928             "\n"
01929             "        This is used to specify which surface(s) will be used by\n"
01930             "        the program.  The '-surf_A' parameter is required, as it\n"
01931             "        specifies the first surface, whereas since '-surf_B' is\n"
01932             "        used to specify an optional second surface, it is not\n"
01933             "        required.\n"
01934             "\n"
01935             "        Note that any need for '-surf_B' may be fulfilled using\n"
01936             "        the '-use_norms' option.\n"
01937             "\n"
01938             "        Note that any name provided must be in the spec file,\n"
01939             "        uniquely matching the name of a surface node file (such\n"
01940             "        as lh.smoothwm.asc, for example).  Note that if both\n"
01941             "        hemispheres are represented in the spec file, then there\n"
01942             "        may be both lh.pial.asc and rh.pial.asc, for instance.\n"
01943             "        In such a case, 'pial' would not uniquely determine a\n"
01944             "        a surface, but the name 'lh.pial' would.\n"
01945             "\n"
01946             "    -sv SURFACE_VOLUME     : AFNI volume dataset\n"
01947             "\n"
01948             "        e.g. -sv fred_anat+orig\n"
01949             "\n"
01950             "        This is the AFNI dataset that the surface is mapped to.\n"
01951             "        This dataset is used for the initial surface node to xyz\n"
01952             "        coordinate mapping, in the Dicom orientation.\n"
01953             "\n"
01954             "    -grid_parent AFNI_DSET : AFNI volume dataset\n"
01955             "\n"
01956             "        e.g. -grid_parent fred_function+orig\n"
01957             "\n"
01958             "        This dataset is used as a grid and orientation master\n"
01959             "        for the output (i.e. it defines the volume domain).\n"
01960             "        It is also the source of the output data values.\n"
01961             "\n"
01962             "    -map_func MAP_FUNC     : filter for values along the segment\n"
01963             "\n"
01964             "        e.g. -map_func ave\n"
01965             "        e.g. -map_func ave -f_steps 10\n"
01966             "        e.g. -map_func ave -f_steps 10 -f_index nodes\n"
01967             "\n"
01968             "        The current mapping function for 1 surface is:\n"
01969             "\n"
01970             "          mask     : For each surface xyz location, output the\n"
01971             "                     dataset values of each sub-brick.\n"
01972             "\n"
01973             "        Most mapping functions are defined for 2 related input\n"
01974             "        surfaces (such as white/grey boundary and pial).  For\n"
01975             "        each node pair, the function will be performed on the\n"
01976             "        values from the 'grid parent dataset', and along the\n"
01977             "        segment connecting the nodes.\n"
01978             "\n"
01979             "          ave      : Output the average of the dataset values\n"
01980             "                     along the segment.\n"
01981             "\n"
01982             "          max      : Output the maximum dataset value along the\n"
01983             "                     connecting segment.\n"
01984             "\n"
01985             "          max_abs  : Output the dataset value with the maximum\n"
01986             "                     absolute value along the segment.\n"
01987             "\n"
01988             "          median   : Output the median of the dataset values\n"
01989             "                     along the connecting segment.\n"
01990             "\n"
01991             "          midpoint : Output the dataset value with xyz\n"
01992             "                     coordinates at the midpoint of the nodes.\n"
01993             "\n"
01994             "          min      : Output the minimum dataset value along the\n"
01995             "                     connecting segment.\n"
01996             "\n"
01997             "          mode     : Output the mode of the dataset values along\n"
01998             "                     the connecting segment.\n"
01999             "\n"
02000             "          seg_vals : Output all of the dataset values along the\n"
02001             "                     connecting segment.  Here, only sub-brick\n"
02002             "                     number 0 will be considered.\n"
02003             "\n"
02004             "  ------------------------------\n"
02005             "\n"
02006             "  options specific to functions on 2 surfaces:\n"
02007             "\n"
02008             "          -f_steps NUM_STEPS :\n"
02009             "\n"
02010             "                     Use this option to specify the number of\n"
02011             "                     evenly spaced points along each segment.\n"
02012             "                     The default is 2 (i.e. just use the two\n"
02013             "                     surface nodes as endpoints).\n"
02014             "\n"
02015             "                     e.g.     -f_steps 10\n"
02016             "                     default: -f_steps 2\n"
02017             "\n"
02018             "          -f_index TYPE :\n"
02019             "\n"
02020             "                     This option specifies whether to use all\n"
02021             "                     segment point values in the filter (using\n"
02022             "                     the 'nodes' TYPE), or to use only those\n"
02023             "                     corresponding to unique volume voxels (by\n"
02024             "                     using the 'voxel' TYPE).\n"
02025             "\n"
02026             "                     For instance, when taking the average along\n"
02027             "                     one node pair segment using 10 node steps,\n"
02028             "                     perhaps 3 of those nodes may occupy one\n"
02029             "                     particular voxel.  In this case, does the\n"
02030             "                     user want the voxel counted only once, or 3\n"            "                     times?  Each way makes sense.\n"
02031             "                     \n"
02032             "                     Note that this will only make sense when\n"
02033             "                     used along with the '-f_steps' option.\n"
02034             "                     \n"
02035             "                     Possible values are \"nodes\", \"voxels\".\n"
02036             "                     The default value is voxels.  So each voxel\n"
02037             "                     along a segment will be counted only once.\n"
02038             "                     \n"
02039             "                     e.g.  -f_index nodes\n"
02040             "                     e.g.  -f_index voxels\n"
02041             "                     default: -f_index voxels\n"
02042             "\n"
02043             "          -f_keep_surf_order :\n"
02044             "\n"
02045             "                     Depreciated.\n"
02046             "\n"
02047             "                     See required arguments -surf_A and -surf_B,\n"
02048             "                     above.\n"
02049             "\n"
02050             "          Note: The following -f_pX_XX options are used to alter\n"
02051             "                the lengths and locations of the computational\n"
02052             "                segments.  Recall that by default, segments are\n"
02053             "                defined using the node pair coordinates as\n"
02054             "                endpoints.  And the direction from p1 to pn is\n"
02055             "                from the inner surface to the outer surface.\n"
02056             "\n"
02057             "          -f_p1_mm DISTANCE :\n"
02058             "\n"
02059             "                     This option is used to specify a distance\n"
02060             "                     in millimeters to add to the first point of\n"
02061             "                     each line segment (in the direction of the\n"
02062             "                     second point).  DISTANCE can be negative\n"
02063             "                     (which would set p1 to be farther from pn\n"
02064             "                     than before).\n"
02065             "\n"
02066             "                     For example, if a computation is over the\n"
02067             "                     grey matter (from the white matter surface\n"
02068             "                     to the pial), and it is wished to increase\n"
02069             "                     the range by 1mm, set this DISTANCE to -1.0\n"
02070             "                     and the DISTANCE in -f_pn_mm to 1.0.\n"
02071             "\n"
02072             "                     e.g.  -f_p1_mm -1.0\n"
02073             "                     e.g.  -f_p1_mm -1.0 -f_pn_mm 1.0\n"
02074             "\n"
02075             "          -f_pn_mm DISTANCE :\n"
02076             "\n"
02077             "                     Similar to -f_p1_mm, this option is used\n"
02078             "                     to specify a distance in millimeters to add\n"
02079             "                     to the second point of each line segment.\n"
02080             "                     Note that this is in the same direction as\n"
02081             "                     above, from point p1 to point pn.\n"
02082             "                     \n"
02083             "                     So a positive DISTANCE, for this option,\n"
02084             "                     would set pn to be farther from p1 than\n"
02085             "                     before, and a negative DISTANCE would set\n"
02086             "                     it to be closer.\n"
02087             "\n"
02088             "                     e.g.  -f_pn_mm 1.0\n"
02089             "                     e.g.  -f_p1_mm -1.0 -f_pn_mm 1.0\n"
02090             "\n"
02091             "          -f_p1_fr FRACTION :\n"
02092             "\n"
02093             "                     Like the -f_pX_mm options above, this\n"
02094             "                     is used to specify a change to point p1, in\n"
02095             "                     the direction of point pn, but the change\n"
02096             "                     is a fraction of the original distance,\n"
02097             "                     not a pure change in millimeters.\n"
02098             "                     \n"
02099             "                     For example, suppose one wishes to do a\n"
02100             "                     computation based on the segments spanning\n"
02101             "                     the grey matter, but to add 20%% to either\n"
02102             "                     side.  Then use -0.2 and 0.2:\n"
02103             "\n"
02104             "                     e.g.  -f_p1_fr -0.2\n"
02105             "                     e.g.  -f_p1_fr -0.2 -f_pn_fr 0.2\n"
02106             "\n"
02107             "          -f_pn_fr FRACTION :\n"
02108             "\n"
02109             "                     See -f_p1_fr above.  Note again that the\n"
02110             "                     FRACTION is in the direction from p1 to pn.\n"
02111             "                     So to extend the segment past pn, this\n"
02112             "                     FRACTION will be positive (and to reduce\n"
02113             "                     the segment back toward p1, this -f_pn_fr\n"
02114             "                     FRACTION will be negative).\n"
02115             "\n"
02116             "                     e.g.  -f_pn_fr 0.2\n"
02117             "                     e.g.  -f_p1_fr -0.2 -f_pn_fr 0.2\n"
02118             "\n"
02119             "                     Just for entertainment, one could reverse\n"
02120             "                     the order that the segment points are\n"
02121             "                     considered by adjusting p1 to be pn, and\n"
02122             "                     pn to be p1.  This could be done by adding\n"
02123             "                     a fraction of 1.0 to p1 and by subtracting\n"
02124             "                     a fraction of 1.0 from pn.\n"
02125             "\n"
02126             "                     e.g.  -f_p1_fr 1.0 -f_pn_fr -1.0\n"
02127             "\n"
02128             "  ------------------------------\n"
02129         );
02130 
02131         printf(
02132             "\n"
02133             "  options specific to use of normals:\n"
02134             "\n"
02135             "    Notes:\n"
02136             "\n"
02137             "      o Using a single surface with its normals for segment\n"
02138             "        creation can be done in lieu of using two surfaces.\n"
02139             "\n"
02140             "      o Normals at surface nodes are defined by the average of\n"
02141             "        the normals of the triangles including the given node.\n"
02142             "\n"
02143             "      o The default normals have a consistent direction, but it\n"
02144             "        may be opposite of what is should be.  For this reason,\n"
02145             "        the direction is verified by default, and may be negated\n"
02146             "        internally.  See the '-keep_norm_dir' option for more\n"
02147             "        information.\n"
02148             "\n"
02149             "    -use_norms             : use normals for second surface\n"
02150             "\n"
02151             "        Segments are usually defined by connecting corresponding\n"
02152             "        node pairs from two surfaces.  With this options the\n"
02153             "        user can use one surface, along with its normals, to\n"
02154             "        define the segments.\n"
02155             "\n"
02156             "        By default, each segment will be 1.0 millimeter long, in\n"
02157             "        the direction of the normal.  The '-norm_len' option\n"
02158             "        can be used to alter this default action.\n"
02159             "\n"
02160             "    -keep_norm_dir         : keep the direction of the normals\n"
02161             "\n"
02162             "        Normal directions are verified by checking that the\n"
02163             "        normals of the outermost 6 points point away from the\n"
02164             "        center of mass.  If they point inward instead, then\n"
02165             "        they are negated.\n"
02166             "\n"
02167             "        This option will override the directional check, and\n"
02168             "        use the normals as they come.\n"
02169             "\n"
02170             "        See also -reverse_norm_dir, below.\n"
02171             "\n"
02172             "    -norm_len LENGTH       : use LENGTH for node normals\n"
02173             "\n"
02174             "        e.g.     -norm_len  3.0\n"
02175             "        e.g.     -norm_len -3.0\n"
02176             "        default: -norm_len  1.0\n"
02177             "\n"
02178             "        For use with the '-use_norms' option, this allows the\n"
02179             "        user to specify a directed distance to use for segments\n"
02180             "        based on the normals.  So for each node on a surface,\n"
02181             "        the computation segment will be from the node, in the\n"
02182             "        direction of the normal, a signed distance of LENGTH.\n"
02183             "\n"
02184             "        A negative LENGTH means to use the opposite direction\n"
02185             "        from the normal.\n"
02186             "\n"
02187             "        The '-surf_B' option is not allowed with the use of\n"
02188             "        normals.\n"
02189             "\n"
02190             "    -reverse_norm_dir      : reverse the normal directions\n"
02191             "\n"
02192             "        Normal directions are verified by checking that the\n"
02193             "        normals of the outermost 6 points point away from the\n"
02194             "        center of mass.  If they point inward instead, then\n"
02195             "        they are negated.\n"
02196             "\n"
02197             "        This option will override the directional check, and\n"
02198             "        reverse the direction of the normals as they come.\n"
02199             "\n"
02200             "        See also -keep_norm_dir, above.\n"
02201             "\n"
02202             "  ------------------------------\n"
02203             "\n"
02204             "  general options:\n"
02205             "\n"
02206             "    -cmask MASK_COMMAND    : (optional) command for dataset mask\n"
02207             "\n"
02208             "        e.g. -cmask '-a fred_func+orig[2] -expr step(a-0.8)'\n"
02209             "\n"
02210             "        This option will produce a mask to be applied to the\n"
02211             "        input AFNI dataset.  Note that this mask should form a\n"
02212             "        single sub-brick.\n"
02213             "\n"
02214             "        This option follows the style of 3dmaskdump (since the\n"
02215             "        code for it was, uh, borrowed from there (thanks Bob!)).\n"
02216             "\n"
02217             "        See '3dmaskdump -help' for more information.\n"
02218             "\n"
02219             "    -debug LEVEL           :  (optional) verbose output\n"
02220             "\n"
02221             "        e.g. -debug 2\n"
02222             "\n"
02223             "        This option is used to print out status information \n"
02224             "        during the execution of the program.  Current levels are\n"
02225             "        from 0 to 5.\n"
02226             "\n"
02227             "    -first_node NODE_NUM   : skip all previous nodes\n"
02228             "\n"
02229             "        e.g. -first_node 1000\n"
02230             "        e.g. -first_node 1000 -last_node 1999\n"
02231             "\n"
02232             "        Restrict surface node output to those with indices as\n"
02233             "        large as NODE_NUM.  In the first example, the first 1000\n"
02234             "        nodes are ignored (those with indices from 0 through\n"
02235             "        999).\n"
02236             "\n"
02237             "        See also, '-last_node'.\n"
02238             "\n"
02239             "    -dnode NODE_NUM        :  (optional) node for debug\n"
02240             "\n"
02241             "        e.g. -dnode 1874\n"
02242             "\n"
02243             "        This option is used to print out status information \n"
02244             "        for node NODE_NUM.\n"
02245             "\n"
02246             "    -gp_index SUB_BRICK    : choose grid_parent sub-brick\n"
02247             "\n"
02248             "        e.g. -gp_index 3\n"
02249             "\n"
02250             "        This option allows the user to choose only a single\n"
02251             "        sub-brick from the grid_parent dataset for computation.\n"
02252             "        Note that this option is virtually useless when using\n"
02253             "        the command-line, as the user can more directly do this\n"
02254             "        via brick selectors, e.g. func+orig'[3]'.\n"
02255             "        \n"
02256             "        This option was written for the afni interface.\n"
02257             "\n"
02258             "    -help                  : show this help\n"
02259             "\n"
02260             "        If you can't get help here, please get help somewhere.\n"
02261             "\n"
02262             "    -hist                  : show revision history\n"
02263             "\n"
02264             "        Display module history over time.\n"
02265             "\n"
02266             "        See also, -v2s_hist\n"
02267             "\n"
02268             "    -last_node NODE_NUM    : skip all following nodes\n"
02269             "\n"
02270             "        e.g. -last_node 1999\n"
02271             "        e.g. -first_node 1000 -last_node 1999\n"
02272             "\n"
02273             "        Restrict surface node output to those with indices no\n"
02274             "        larger than NODE_NUM.  In the first example, nodes above\n"
02275             "        1999 are ignored (those with indices from 2000 on up).\n"
02276             "\n"
02277             "        See also, '-first_node'.\n"
02278             "\n"
02279             "    -no_headers            : do not output column headers\n"
02280             "\n"
02281             "        Column header lines all begin with the '#' character.\n"
02282             "        With the '-no_headers' option, these lines will not be\n"
02283             "        output.\n"
02284             "\n"
02285             "    -oob_index INDEX_NUM   : specify default index for oob nodes\n"
02286             "\n"
02287             "        e.g.     -oob_index -1\n"
02288             "        default: -oob_index  0\n"
02289             "\n"
02290             "        By default, nodes which lie outside the box defined by\n"
02291             "        the -grid_parent dataset are considered out of bounds,\n"
02292             "        and are skipped.  If an out of bounds index is provided,\n"
02293             "        or an out of bounds value is provided, such nodes will\n"
02294             "        not be skipped, and will have indices and values output,\n"
02295             "        according to the -oob_index and -oob_value options.\n"
02296             "        \n"
02297             "        This INDEX_NUM will be used for the 1dindex field, along\n"
02298             "        with the i, j and k indices.\n"
02299             "        \n"
02300             "\n"
02301             "    -oob_value VALUE       : specify default value for oob nodes\n"
02302             "\n"
02303             "        e.g.     -oob_value -999.0\n"
02304             "        default: -oob_value    0.0\n"
02305             "\n"
02306             "        See -oob_index, above.\n"
02307             "        \n"
02308             "        VALUE will be output for nodes which are out of bounds.\n"
02309             "\n"
02310             "    -oom_value VALUE       : specify default value for oom nodes\n"
02311             "\n"
02312             "        e.g. -oom_value -999.0\n"
02313             "        e.g. -oom_value    0.0\n"
02314             "\n"
02315             "        By default, node pairs defining a segment which gets\n"
02316             "        completely obscured by a command-line mask (see -cmask)\n"
02317             "        are considered \"out of mask\", and are skipped.\n"
02318             "\n"
02319             "        If an out of mask value is provided, such nodes will not\n"
02320             "        be skipped.  The output indices will come from the first\n"
02321             "        segment point, mapped to the AFNI volume.  All output vN\n"
02322             "        values will be the VALUE provided with this option.\n"
02323             "\n"
02324             "        This option is meaningless without a '-cmask' option.\n"
02325             "\n"
02326             "    -out_1D OUTPUT_FILE    : specify a 1D file for the output\n"
02327             "\n"
02328             "        e.g. -out_1D mask_values_over_dataset.1D\n"
02329             "\n"
02330             "        This is where the user will specify which file they want\n"
02331             "        the output to be written to.  In this case, the output\n"
02332             "        will be in readable, column-formatted ASCII text.\n"
02333             "\n"
02334             "        Note : the output file should not yet exist.\n"
02335             "             : -out_1D or -out_niml must be used\n"
02336             "\n"
02337             "    -out_niml OUTPUT_FILE  : specify a niml file for the output\n"
02338             "\n"
02339             "        e.g. -out_niml mask_values_over_dataset.niml\n"
02340             "\n"
02341             "        The user may use this option to get output in the form\n"
02342             "        of a niml element, with binary data.  The output will\n"
02343             "        contain (binary) columns of the form:\n"
02344             "\n"
02345             "            node_index  value_0  value_1  value_2  ...\n"
02346             "\n"
02347             "        A major difference between 1D output and niml output is\n"
02348             "        that the value_0 column number will be 6 in the 1D case,\n"
02349             "        but will be 2 in the niml case.  The index columns will\n"
02350             "        not be used for niml output.\n"
02351             "\n"
02352             "        Note : the output file should not yet exist.\n"
02353             "             : -out_1D or -out_niml must be used\n"
02354             "\n"
02355             "    -skip_col_nodes        : do not output node column\n"
02356             "    -skip_col_1dindex      : do not output 1dindex column\n"
02357             "    -skip_col_i            : do not output i column\n"
02358             "    -skip_col_j            : do not output j column\n"
02359             "    -skip_col_k            : do not output k column\n"
02360             "    -skip_col_vals         : do not output vals column\n"
02361             "    -skip_col_results      : only output ONE result column\n"
02362             "                             (seems to make the most sense)\n"
02363             "    -skip_col_non_results  : skip everything but the results\n"
02364             "                             (i.e. only output result columns)\n"
02365             "\n"
02366             "        These options are used to restrict output.  Each option\n"
02367             "        will prevent the program from writing that column of\n"
02368             "        output to the 1D file.\n"
02369             "\n"
02370             "        For now, the only effect that these options can have on\n"
02371             "        the niml output is by skipping nodes or results (all\n"
02372             "        other columns are skipped by default).\n"
02373             "\n"
02374             "    -v2s_hist              : show revision history for library\n"
02375             "\n"
02376             "        Display vol2surf library history over time.\n"
02377             "\n"
02378             "        See also, -hist\n"
02379             "\n"
02380             "    -version               : show version information\n"
02381             "\n"
02382             "        Show version and compile date.\n"
02383             "\n"
02384             "  --------------------------------------------------\n"
02385             "\n"
02386             "Output from the program defaults to 1D format, in ascii text.\n"
02387             "For each node (pair) that results in output, there will be one\n"
02388             "line, consisting of:\n"
02389             "\n"
02390             "    node    : the index of the current node (or node pair)\n"
02391             "\n"
02392             "    1dindex : the global index of the AFNI voxel used for output\n"
02393             "\n"
02394             "              Note that for some filters (min, max, midpoint,\n"
02395             "              median and mode) there is a specific location (and\n"
02396             "              therefore voxel) that the result comes from.  It\n"
02397             "              will be accurate (though median may come from one\n"
02398             "              of two voxels that are averaged).\n"
02399             "\n"
02400             "              For filters without a well-defined source (such as\n"
02401             "              average or seg_vals), the 1dindex will come from\n"
02402             "              the first point on the corresponding segment.\n"
02403             "\n"
02404             "              Note: this will _not_ be output in the niml case.\n"
02405             "\n"
02406             "    i j k   : the i j k indices matching 1dindex\n"
02407             "\n"
02408             "              These indices are based on the orientation of the\n"
02409             "              grid parent dataset.\n"
02410             "\n"
02411             "              Note: these will _not_ be output in the niml case.\n"
02412             "\n"
02413             "    vals    : the number of segment values applied to the filter\n"
02414             "\n"
02415             "              Note that when -f_index is 'nodes', this will\n"
02416             "              always be the same as -f_steps, except when using\n"
02417             "              the -cmask option.  In that case, along a single \n"
02418             "              segment, some points may be in the mask, and some\n"
02419             "              may not.\n"
02420             "\n"
02421             "              When -f_index is 'voxels' and -f_steps is used,\n"
02422             "              vals will often be much smaller than -f_steps.\n"
02423             "              This is because many segment points may in a\n"
02424             "              single voxel.\n"
02425             "\n"
02426             "              Note: this will _not_ be output in the niml case.\n"
02427             "\n"
02428             "    v0, ... : the requested output values\n"
02429             "\n"
02430             "              These are the filtered values, usually one per\n"
02431             "              AFNI sub-brick.  For example, if the -map_func\n"
02432             "              is 'ave', then there will be one segment-based\n"
02433             "              average output per sub-brick of the grid parent.\n"
02434             "\n"
02435             "              In the case of the 'seg_vals' filter, however,\n"
02436             "              there will be one output value per segment point\n"
02437             "              (possibly further restricted to voxels).  Since\n"
02438             "              output is not designed for a matrix of values,\n"
02439             "              'seg_vals' is restricted to a single sub-brick.\n"
02440             "\n"
02441             "\n"
02442             "  Author: R. Reynolds  - %s\n"
02443             "\n"
02444             "                (many thanks to Z. Saad and R.W. Cox)\n"
02445             "\n",
02446             VERSION );
02447     }
02448     else if ( level == V2S_USE_HIST )
02449         fputs(g_history, stdout);
02450     else if ( level == V2S_USE_LIB_HIST )
02451         fputs(gv2s_history, stdout);
02452     else if ( level == V2S_USE_VERSION )
02453         fprintf(stderr,"%s : %s, compile date: %s\n", prog, VERSION, __DATE__);
02454     else 
02455         fprintf( stderr, "usage called with illegal level <%d>\n", level );
02456 
02457     RETURN(-1);
02458 }
02459 
02460 
02461 /*---------------------------------------------------------------------------
02462  * surf_ave_radius  -  compute the average distance from the Center
02463  *---------------------------------------------------------------------------
02464 */
02465 int surf_ave_radius( float * radius, SUMA_SurfaceObject * so, int disp )
02466 {
02467     double   ss, sum = 0.0;
02468     float  * fp;
02469     float    c0, c1, c2;
02470     int      node;
02471 
02472 ENTRY("surf_ave_radius");
02473 
02474     if ( !so || !radius || so->N_Node <= 0 )
02475     {
02476         fprintf(stderr, "** disp_sar, so, radius == %p,%p\n", so, radius );
02477         RETURN(-1);
02478     }
02479 
02480     c0 = so->Center[0];                            /* for a little speed */
02481     c1 = so->Center[1];
02482     c2 = so->Center[2];
02483 
02484     fp = so->NodeList;
02485     for ( node = 0; node < so->N_Node; node++ )
02486     {
02487         ss  = (*fp - c0) * (*fp - c0);   fp++;
02488         ss += (*fp - c1) * (*fp - c1);   fp++;
02489         ss += (*fp - c2) * (*fp - c2);   fp++;
02490 
02491         sum += sqrt(ss);
02492     }
02493 
02494     *radius = sum/so->N_Node;
02495 
02496     if ( disp )
02497         fprintf(stderr,"-- surf %s has average dist %f\n"
02498                        "        to center (%f, %f, %f)\n",
02499                 so->Label, *radius, c0, c1, c2 );
02500 
02501     RETURN(0);
02502 }
02503 
02504 
02505 /*----------------------------------------------------------------------
02506  * disp_opts_t  -  display the contents of the opts_t struct
02507  *----------------------------------------------------------------------
02508 */
02509 int disp_opts_t ( char * info, opts_t * opts )
02510 {
02511 ENTRY("disp_opts_t");
02512 
02513     if ( info )
02514         fputs( info, stderr );
02515 
02516     if ( opts == NULL )
02517     {
02518         fprintf( stderr, "disp_opts_t: opts == NULL\n" );
02519         RETURN(-1);
02520     }
02521 
02522     fprintf(stderr,
02523             "options struct at %p :\n"
02524             "    gpar_file              = %s\n"
02525             "    outfile_1D             = %s\n"
02526             "    outfile_niml           = %s\n"
02527             "    spec_file              = %s\n"
02528             "    sv_file                = %s\n"
02529             "    cmask_cmd              = %s\n"
02530             "    map_str                = %s\n"
02531             "    snames[0,1]            = %s, %s\n"
02532             "    gp_index, no_head      = %d, %d\n"
02533             "    first_node, last_node  = %d, %d\n"
02534             "    use_norms, norm_len    = %d, %f\n"
02535             "    norm_dir, debug, dnode = %d, %d, %d\n"
02536             "    f_index_str            = %s\n"
02537             "    f_steps                = %d\n"
02538             "    f_p1_fr, f_pn_fr       = %f, %f\n"
02539             "    f_p1_mm, f_pn_mm       = %f, %f\n"
02540             , opts,
02541             CHECK_NULL_STR(opts->gpar_file), CHECK_NULL_STR(opts->outfile_1D),
02542             CHECK_NULL_STR(opts->outfile_niml),
02543             CHECK_NULL_STR(opts->spec_file), CHECK_NULL_STR(opts->sv_file),
02544             CHECK_NULL_STR(opts->cmask_cmd), CHECK_NULL_STR(opts->map_str),
02545             CHECK_NULL_STR(opts->snames[0]), CHECK_NULL_STR(opts->snames[1]),
02546             opts->gp_index, opts->no_head, opts->first_node, opts->last_node,
02547             opts->use_norms, opts->norm_len, opts->norm_dir, opts->debug,
02548             opts->dnode, CHECK_NULL_STR(opts->f_index_str), opts->f_steps,
02549             opts->f_p1_fr, opts->f_pn_fr, opts->f_p1_mm, opts->f_pn_mm
02550             );
02551 
02552     RETURN(0);
02553 }
02554 
 

Powered by Plone

This site conforms to the following standards: