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

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------
00002  * 3dSurf2Vol - create an AFNI volume dataset from a surface
00003  *
00004  * This program is meant to take as input a surface and an AFNI dataset,
00005  * and to output a new AFNI dataset consisting of the surface mapped to
00006  * the dataset grid space.
00007  *
00008  * The surface points are mapped to xyz coordinates, according to the
00009  * SURF_VOL (surface volume) AFNI dataset.  These coordinates are then
00010  * matched to voxels in the grid parent AFNI dataset.  The output dataset
00011  * will have the same grid as the grid parent dataset, with values coming
00012  * from the surface, and subject to any mask (see -cmask).
00013  *
00014  * usage:
00015  *    3dSurf2Vol [options] -spec SPEC_FILE -sv SURF_VOL -grid_parent AFNI_DSET
00016  *                         -map_func MAP_FUNC -prefix OUTPUT_DSET
00017  *
00018  * options:
00019  *
00020  *      -help
00021  *      -version
00022  *
00023  *      -spec                SPEC_FILE
00024  *      -surf_A              SURF_NAME_A
00025  *      -surf_B              SURF_NAME_B
00026  *      -sv                  SURF_VOL
00027  *      -grid_parent         AFNI_DSET
00028  *      -prefix              OUTPUT_DSET
00029  *      -map_func            MAP_FUNC
00030  *
00031  *      -surf_xyz_1D         SURF_XYZ.1D
00032  *      -sdata_1D            SURF_DATA.1D
00033  *
00034  *      -cmask               MASK_COMMAND
00035  *      -data_expr           EXPRESSION
00036  *      -datum               D_TYPE
00037  *      -debug               LEVEL
00038  *      -dnode               NODE_NUM
00039  *      -dvoxel              VOXEL_NUM
00040  *      -noscale
00041  *
00042  *      -f_steps             SEGMENT_STEPS
00043  *      -f_index             STEP_TYPE
00044  *      -f_p1_fr             FRACTION
00045  *      -f_pn_fr             FRACTION
00046  *      -f_p1_mm             DISTANCE
00047  *      -f_pn_mm             DISTANCE
00048  *
00049  * examples:
00050  *
00051  *    3dSurf2Vol -spec        SubjectA.spec                              \
00052  *               -sv          SubjectA_spgr+orig                         \ 
00053  *               -grid_parent SubjA_EPI+orig                             \
00054  *               -map_func    mask2                                      \
00055  *               -prefix      SubjA_mask
00056  *
00057  *    3dSurf2Vol -spec        SubjectA.spec                              \
00058  *               -sv          SubjectA_spgr+orig                         \ 
00059  *               -cmask       '-a SubjA.func+orig[2] -expr step(a-0.6)'  \
00060  *               -grid_parent SubjA_EPI+orig                             \
00061  *               -map_func    mask2                                      \
00062  *               -debug       2                                          \
00063  *               -prefix      SubjA_mask
00064  *
00065  *----------------------------------------------------------------------
00066 */
00067 
00068 static char g_history[] =
00069  "----------------------------------------------------------------------\n"
00070  "history:\n"
00071  "\n"
00072  "1.0  May 29, 2003 [rickr]\n"
00073  "  - initial release\n"
00074  "\n"
00075  "1.1  June 11, 2003 [rickr]\n"
00076  "  - small reorg of s2v_fill_mask2() (should have no effect)\n"
00077  "  - improve description of -f_steps option\n"
00078  "\n"
00079  "1.2  July 21, 2003 [rickr]\n"
00080  "  - make sure input points fit in output dataset\n"
00081  "  - add min/max distance output, along with out-of-bounds count\n"
00082  "\n"
00083  "2.0  October 2, 2003 [rickr]\n"
00084  "  - Major changes accepting surface data, surface coordinates, output data\n"
00085  "    type, debug options, multiple sub-brick output, and node pair segment\n"
00086  "    alterations.\n"
00087  "  - Added many options:  -surf_xyz_1D, -sdata_1D, -data_expr, -datum,\n"
00088  "                         -dnode, -dvoxel, -f_index, -f_p1_fr, -f_pn_fr,\n"
00089  "                         -f_p1_mm, -f_pn_mm\n"
00090  "\n"
00091  "2.1  October 20, 2003 [rickr]\n"
00092  "  - call the new engine function, SUMA_LoadSpec_eng()\n"
00093  "    (this will restrict the debug output from SUMA_LoadSpec())\n"
00094  "\n"
00095  "2.2  December 15, 2003 [rickr]\n"
00096  "  - added program arguments '-surf_A' and '-surf_B' (-surf_A is required)\n"
00097  "  - added option '-hist' (for program history)\n"
00098  "  - explicit pointer init to NULL (a.o.t. memset() to 0)\n"
00099  "\n"
00100  "3.0  December 18, 2003 [rickr]\n"
00101  "  - removed requirement of 2 surfaces for most functions\n"
00102  "    (so now all functions work with either 1 or 2 input surfaces)\n"
00103  "\n"
00104  "3.1  January 23, 2004 [rickr]\n"
00105  "  - SUMA_isINHmappable() is depricated, check with AnatCorrect field\n"
00106  "  - reversed order of output for '-hist' option\n"
00107  "\n"
00108  "3.2  February 10, 2004 [rickr]\n"
00109  "  - output a little more debug info for !AnatCorrect case\n"
00110  "\n"
00111  "3.3  March 26, 2004  [ziad]\n"
00112  "  - DsetList added to SUMA_LoadSpec_eng() call\n"
00113  "\n"
00114  "3.4  June 21, 2004  [rickr]\n"
00115  "  - Fixed -surf_xyz_1D option (broken in v3.0 on nsurf test).\n"
00116  "\n"
00117  "3.5  July 22, 2004  [rickr]\n"
00118  "  - Fixed bug with test for valid sdata_1D file.\n"
00119  "\n"
00120  "3.6  July 28, 2004  [rickr]\n"
00121  "  - Fixed bug: old change caused the default f_steps to revert to 1,\n"
00122  "               now it is set back to 2 (thanks, Kuba).\n"
00123  "\n"
00124  "3.6a March 22, 2005  [rickr]\n"
00125  "  - removed tabs\n"
00126  "----------------------------------------------------------------------\n";
00127  
00128 #define VERSION "version  3.6a (March 22, 2005)"
00129 
00130 
00131 /*----------------------------------------------------------------------
00132  * todo:
00133  *   - handle niml input
00134  *----------------------------------------------------------------------
00135 */
00136 
00137 #include "mrilib.h"
00138 #include "parser.h"
00139 #include "SUMA_suma.h"
00140 #include "SUMA_3dSurf2Vol.h"
00141 
00142 /* globals */
00143 SUMA_SurfaceViewer * SUMAg_SVv = NULL;  /* array of Surf View structs   */
00144 int                  SUMAg_N_SVv = 0;   /* length of SVv array          */
00145 SUMA_DO            * SUMAg_DOv = NULL;  /* array of Displayable Objects */
00146 int                  SUMAg_N_DOv = 0;   /* length of DOv array          */
00147 SUMA_CommonFields  * SUMAg_CF = NULL;   /* info common to all viewers   */
00148 
00149 /* this must match s2v_map_num enum */
00150 char * gs2v_map_names[] = { "none", "mask", "mask2", "ave", "count",
00151                             "min", "max", "max_abs" };
00152 
00153 /* AFNI prototype */
00154 extern void machdep( void );
00155 
00156 #define MAIN
00157 
00158 /*----------------------------------------------------------------------*/
00159 
00160 int main( int argc , char * argv[] )
00161 {
00162     SUMA_SurfSpecFile  spec;
00163     node_list_t        node_list;
00164     param_t            params;
00165     s2v_opts_t         sopt;
00166     opts_t             opts;
00167     int                ret_val;
00168 
00169     mainENTRY("3dSurf2Vol main");
00170     machdep();
00171     AFNI_logger("3dSurf2Vol",argc,argv);
00172 
00173     /* validate inputs and init options structure */
00174     if ( ( ret_val = init_options(&opts, argc, argv) ) != 0 )
00175         return ret_val;
00176 
00177     if ( ( ret_val = validate_options(&opts, &params) ) != 0 )
00178         return ret_val;
00179 
00180     if ( (ret_val = set_smap_opts( &opts, &params, &sopt )) != 0 )
00181         return ret_val;
00182 
00183     /* read surface files */
00184     ret_val = read_surf_files(&opts, &params, &spec, &sopt, &node_list);
00185 
00186     if ( ret_val == 0 )
00187         ret_val = write_output( &sopt, &opts, &params, &node_list, argc, argv );
00188 
00189     /* free memory */
00190     final_clean_up( &node_list );
00191 
00192     return ret_val;
00193 }
00194 
00195 
00196 /*----------------------------------------------------------------------
00197  * write_output - create and write a new afni dataset
00198  *----------------------------------------------------------------------
00199 */
00200 int write_output ( s2v_opts_t * sopt, opts_t * opts, param_t * p,
00201                    node_list_t * N, int argc, char * argv[] )
00202 {
00203 ENTRY("write_output");
00204 
00205     if ( sopt == NULL || opts == NULL || p == NULL || N == NULL )
00206     {
00207         fprintf( stderr, "** s2v_wo - bad params (%p,%p,%p,%p)\n",
00208                  sopt, opts, p, N );
00209         RETURN(-1);
00210     }
00211 
00212     p->oset = s2v_nodes2volume( N, p, sopt );
00213 
00214     if ( p->oset == NULL )
00215         RETURN(-1);
00216 
00217     EDIT_dset_items( p->oset, ADN_prefix, opts->oset_file, ADN_none );
00218 
00219     if ( THD_is_file(DSET_HEADNAME(p->oset)) )
00220     {
00221         fprintf( stderr, "** cannot overwrite existing dataset '%s'\n",
00222                  DSET_HEADNAME(p->oset) );
00223         DSET_delete( p->oset );
00224         RETURN(-1);
00225     }
00226 
00227     tross_Copy_History( p->gpar, p->oset );
00228     tross_Make_History( PROG_NAME, argc, argv, p->oset );
00229 
00230     if ( DSET_write( p->oset ) != True )
00231     {
00232         fprintf( stderr, "** failed to write dataset '%s', exiting...\n",
00233                  opts->oset_file );
00234         RETURN(-1);
00235     }
00236 
00237     RETURN(0);
00238 }
00239 
00240 
00241 /*----------------------------------------------------------------------
00242  * s2v_nodes2volume     - create an AFNI dataset from the node_list
00243  *                        and map type (subject to any mask).
00244  *
00245  * inputs:
00246  *              N       - xyz coordinate node list for surfaces
00247  *              p       - param_t struct
00248  *              map     - the surface to dataset mapping type
00249  *
00250  * return  AFNI dataset - on success
00251  *         NULL         - on failure
00252  *----------------------------------------------------------------------
00253 */
00254 THD_3dim_dataset * s2v_nodes2volume( node_list_t * N, param_t * p,
00255                                      s2v_opts_t * sopt )
00256 {
00257     THD_3dim_dataset * dout;
00258     THD_fvec3        * pary;
00259     double           * ddata;
00260     void             * vdata = NULL;
00261     int              * cdata;
00262     float              fac;
00263     int                nvox, dsize, valid;
00264     int                sub;
00265 
00266 ENTRY("s2v_nodes2volume");
00267 
00268     if ( N == NULL || ! ISVALID_DSET(p->gpar) )
00269     {
00270         fprintf(stderr,"** s2v_nodes2volume: bad params (%p,%p)\n", N, p->gpar);
00271         RETURN(NULL);
00272     }
00273 
00274     dout = EDIT_empty_copy( p->gpar );
00275     if ( ! ISVALID_3DIM_DATASET( dout ) )
00276     {
00277         fprintf( stderr, "** failed EDIT_empty_copy()\n" );
00278         RETURN(NULL);
00279     }
00280 
00281     /* output dataset will have nsubs sub-bricks */
00282     EDIT_dset_items( dout, ADN_nvals,     p->nsubs,
00283                            ADN_type,      HEAD_FUNC_TYPE,
00284                            ADN_func_type, FUNC_BUCK_TYPE,
00285                            ADN_datum_all, sopt->datum,
00286                            ADN_ntt,       0,
00287                      ADN_none );
00288 
00289     if ( sopt->debug > 1 )
00290         fprintf( stderr, "++ creating dataset '%s' of type '%s', nvals = %d\n",
00291                  DSET_HEADNAME(dout), MRI_TYPE_name[sopt->datum], p->nsubs );
00292 
00293     nvox  = DSET_NVOX(p->gpar);
00294 
00295     /* allocate a computational array of doubles */
00296     if ( (ddata = (double *)malloc(nvox * sizeof(double))) == NULL )
00297     {
00298         fprintf( stderr, "** n2v: failed to allocate %d doubles\n", nvox );
00299         DSET_delete( dout );
00300         RETURN(NULL);
00301     }
00302     
00303     /* allocate an array of ints for functional counting */
00304     if ( (cdata = (int *)malloc(nvox * sizeof(int))) == NULL )
00305     {
00306         fprintf( stderr, "** n2v: failed to allocate %d ints\n", nvox );
00307         DSET_delete( dout );  free( ddata );
00308         RETURN(NULL);
00309     }
00310 
00311     /* allocate space for the point list */
00312     if ( (pary = (THD_fvec3 *)malloc(sopt->f_steps*sizeof(THD_fvec3))) == NULL )
00313     {
00314         fprintf(stderr,"** n2v: cannot allocate %d THD_fvec3s\n",sopt->f_steps);
00315         DSET_delete( dout );  free( ddata );  free( cdata );
00316         RETURN(NULL);
00317     }
00318     
00319     dsize = mri_datum_size(sopt->datum);
00320     /* create the sub-brick data for output */
00321     for ( sub = 0; sub < p->nsubs; sub++ )
00322     {
00323         valid = 0;
00324 
00325         /* need new data after each sub-brick is attached to the dset */
00326         if ( (vdata = malloc( nvox * dsize )) == NULL )
00327         {
00328             fprintf( stderr, "** failed to allocate %d bytes for vdata\n",
00329                      nvox * dsize );
00330             DSET_delete( dout );  free( ddata );  free( cdata );
00331             RETURN(NULL);
00332         }
00333 
00334         /* init data to zeros */
00335         memset(cdata, 0, nvox*sizeof(int));
00336         memset(ddata, 0, nvox*sizeof(double));
00337 
00338         /* set node_list data */
00339         if ( set_node_list_data( N, p, sopt, sub ) != 0 )
00340         {
00341             DSET_delete(dout);
00342             free(ddata);
00343             free(cdata);
00344             free(vdata);
00345 
00346             RETURN(NULL);
00347         }
00348 
00349         if ( compute_results( p, N, sopt, ddata, cdata, pary ) == 0 )
00350             valid = 1;
00351 
00352         if ( ! valid )  /* then clean up memory */
00353         {
00354             free( ddata );
00355             free( vdata );
00356             DSET_delete( dout );
00357             RETURN(NULL);
00358         }
00359 
00360         /* convert to output data type */
00361         fac = 0.0;
00362 
00363         if ( sopt->debug > 1 )
00364             fprintf(stderr,"++ sub-brick %d, integral_doubles = %d\n",
00365                     sub, integral_doubles( ddata, nvox ));
00366 
00367         /* for int output and scaling, fac is maxval/maxabs */
00368         if ( MRI_IS_INT_TYPE( sopt->datum ) && !sopt->noscale )
00369         {
00370             float amax = MCW_vol_amax( nvox, 1, 1, MRI_double, ddata );
00371 
00372             if ( amax > MRI_TYPE_maxval[sopt->datum] )      /* we must scale */
00373                 fac = MRI_TYPE_maxval[sopt->datum]/amax;
00374             else if ( integral_doubles( ddata, nvox ) )  /* don't need scale */
00375                 fac = 0.0;
00376             else if ( amax != 0.0 )
00377                 fac = MRI_TYPE_maxval[sopt->datum]/amax;
00378 
00379             if ( sopt->debug > 1 )
00380                 fprintf(stderr,"++ fac = %f, amax = %f \n", fac, amax);
00381         }
00382 
00383         EDIT_coerce_scale_type(nvox, fac, MRI_double,ddata, sopt->datum,vdata);
00384 
00385         /* attach the final vdata to the dataset */
00386         EDIT_substitute_brick( dout, sub, sopt->datum, vdata );
00387         DSET_BRICK_FACTOR( dout, sub ) = (fac != 0.0) ? 1.0/fac : 0.0;
00388     }
00389 
00390     if (sopt->debug > 0)
00391         fprintf(stderr,"++ %d sub-brick(s) computed\n", p->nsubs);
00392 
00393     free(ddata);
00394     free(cdata);
00395     free(pary);
00396 
00397     RETURN(dout);
00398 }
00399 
00400 
00401 /*----------------------------------------------------------------------
00402  * compute_results   - fill ddata with results, cdata with count
00403  *
00404  * return     0 : success
00405  *         else : failure
00406  *----------------------------------------------------------------------
00407 */
00408 int compute_results( param_t * p, node_list_t * N, s2v_opts_t * sopt,
00409                          double * ddata, int * cdata, THD_fvec3 * pary )
00410 {
00411     THD_fvec3          p1, pn;
00412     float              dist, min_dist, max_dist;
00413     int                nindex, node;
00414     int                oobc;
00415 
00416 ENTRY("compute_results");
00417 
00418     if ( !p || !N || !sopt || !ddata || !cdata )
00419     {
00420         fprintf(stderr,"** cr: bad params (%p,%p,%p,%p,%p)\n",
00421                 p, N, sopt, ddata, cdata);
00422         RETURN(-1);
00423     }
00424 
00425     min_dist = 9999.9;
00426     max_dist = -1.0;
00427     oobc     = 0;               /* init out-of-bounds counter */
00428 
00429     for ( nindex = 0; nindex < N->ilen; nindex++ )
00430     {
00431         node = N->ilist[nindex];
00432         if ( node < 0 || node >= N->nnodes )
00433         {
00434             fprintf(stderr,"** node %d (%d) out-of-range [0,%d]\n",
00435                     nindex, node, N->nnodes);
00436             RETURN(-1);
00437         }
00438 
00439         /* initiate the endpoints */
00440         p1 = N->nodes[node];
00441 
00442         if ( N->depth > 1 )
00443             pn = N->nodes[node+N->nnodes];
00444         else
00445             pn = p1;
00446 
00447         if ( ! sopt->sxyz_ori_gpar ) /* if orient is not as gpar it is Dicom */
00448         {
00449             p1 = THD_dicomm_to_3dmm(p->gpar, p1);
00450             pn = THD_dicomm_to_3dmm(p->gpar, pn);
00451         }
00452 
00453         if ( sopt->debug > 0 && sopt->dnode == node )
00454         {
00455             fprintf(stderr,"-- debug node: %d\n", node );
00456             fprintf(stderr,"-- orig endpts: (%f, %f, %f)\n"
00457                            "                (%f, %f, %f)\n",
00458                     p1.xyz[0], p1.xyz[1], p1.xyz[2],
00459                     pn.xyz[0], pn.xyz[1], pn.xyz[2]);
00460         }
00461 
00462         adjust_endpts( sopt, &p1, &pn );        /* per user options */
00463 
00464         /* if both points are outside gpar box, skip the node */
00465         if ( f3mm_out_of_bounds( &p1, &p->f3mm_min, &p->f3mm_max ) &&
00466              f3mm_out_of_bounds( &pn, &p->f3mm_min, &p->f3mm_max ) )
00467         {
00468             oobc++;
00469             continue;
00470         }
00471 
00472         dist = dist_f3mm( &p1, &pn );
00473         if ( dist < min_dist ) min_dist = dist;
00474         if ( dist > max_dist ) max_dist = dist;
00475 
00476         make_point_list( pary, &p1, &pn, sopt );
00477 
00478         /* do all the work to insert data */
00479         if ( insert_list(N, p, sopt, pary, nindex, ddata, cdata) )
00480             RETURN(-1);
00481     }
00482 
00483     if ( sopt->debug > 0 )
00484         fprintf(stderr, "-- (min_dist, max_dist) = (%f, %f)\n"
00485                         "   %d of %d nodes were out of bounds\n",
00486                 min_dist, max_dist, oobc, N->ilen);
00487 
00488     if ( final_computations(ddata, cdata, sopt, DSET_NVOX(p->gpar)) )
00489         RETURN(-1);
00490 
00491     RETURN(0);
00492 }
00493 
00494 
00495 /*----------------------------------------------------------------------
00496  * final_computations   - perform any last computation over the dataset
00497  *----------------------------------------------------------------------
00498 */
00499 int final_computations(double *ddata, int *cdata, s2v_opts_t *sopt, int nvox)
00500 {
00501     int index;
00502 
00503 ENTRY("final_computations");
00504 
00505     if ( (sopt->debug > 1) && (sopt->dvox >= 0) && (sopt->dvox < nvox) )
00506         fprintf(stderr,"++ final: voxel %d, from values (%d, %f) ",
00507                 sopt->dvox,cdata[sopt->dvox],ddata[sopt->dvox]);
00508 
00509     switch ( sopt->map )
00510     {
00511         default:
00512             fprintf(stderr,"** fc: mapping %d not ready\n", sopt->map );
00513             RETURN(-1);
00514 
00515         case E_SMAP_AVE:
00516             /* we have sum, divide for average */
00517             for ( index = 0; index < nvox; index++ )
00518                 if ( cdata[index] > 0 )
00519                     ddata[index] /= cdata[index];
00520             break;
00521 
00522         case E_SMAP_COUNT:
00523         case E_SMAP_MAX_ABS:
00524         case E_SMAP_MAX:
00525         case E_SMAP_MIN:
00526         case E_SMAP_MASK:
00527         case E_SMAP_MASK2:
00528             break;
00529     }
00530 
00531     if ( (sopt->debug > 1) && (sopt->dvox >= 0) && (sopt->dvox < nvox) )
00532         fprintf(stderr,"to values (%d, %f)\n",
00533                 cdata[sopt->dvox],ddata[sopt->dvox]);
00534 
00535     RETURN(0);
00536 }
00537 
00538 
00539 /*----------------------------------------------------------------------
00540  * insert_list          - given xyz list, add to ddata/cdata
00541  *
00542  * for each point in list
00543  *   get voxel index
00544  *   if out of mask, skip
00545  *   if undesired voxel repeat, skip
00546  *   apply mapping function to insert data
00547  *
00548  * return   0 on success
00549  *        < 0 on error
00550  *----------------------------------------------------------------------
00551 */
00552 int insert_list( node_list_t * N, param_t * p, s2v_opts_t * sopt,
00553                  THD_fvec3 * pary, int nindex, double * ddata, int * cdata )
00554 {
00555     THD_ivec3 i3;
00556     int       vindex, prev_vind;
00557     int       step, node;
00558     int       nx, ny, debug;
00559 
00560 ENTRY("insert_list");
00561 
00562     if ( !N || !p || !sopt || !pary || nindex < 0 || !ddata || !cdata )
00563     {
00564         fprintf(stderr,"** ID params (%p,%p,%p,%p,%d,%p,%p)\n",
00565                 N, p, sopt, pary, nindex, ddata, cdata);
00566         RETURN(-1);
00567     }
00568 
00569     node = N->ilist[nindex];
00570 
00571     debug = sopt->debug && node == sopt->dnode;
00572 
00573     if ( debug )    /* show xyz coords? */
00574         fprintf(stderr,"++ point list for N[%d] = %d:\n", nindex, node);
00575 
00576     nx        = DSET_NX(p->gpar);
00577     ny        = DSET_NY(p->gpar);
00578     prev_vind = -1;
00579     for ( step = 0; step < sopt->f_steps; step++ )
00580     {
00581         if ( f3mm_out_of_bounds( pary+step, &p->f3mm_min, &p->f3mm_max ) )
00582             continue;
00583 
00584         i3 = THD_3dmm_to_3dind(p->gpar, pary[step]);
00585         vindex = i3.ijk[0] + nx * (i3.ijk[1] + ny * i3.ijk[2]);
00586 
00587         if ( debug )
00588             fprintf(stderr,"   %3d, vox %d, [%3d,%3d,%3d]: %f, %f, %f",
00589                     step, vindex, i3.ijk[0], i3.ijk[1], i3.ijk[2],
00590                     pary[step].xyz[0], pary[step].xyz[1], pary[step].xyz[2]);
00591 
00592         if ( sopt->cmask && !sopt->cmask[vindex] )
00593         {
00594             if ( debug ) fprintf(stderr, " : skip (mask)\n");
00595             continue;
00596         }
00597 
00598         if ( (vindex == prev_vind) && (sopt->f_index == S2V_F_INDEX_VOXEL) )
00599         {
00600             if ( debug ) fprintf(stderr, " : skip (repeat voxel)\n");
00601             continue;
00602         }
00603 
00604         /* hey, we finally have a new voxel to add */
00605 
00606         prev_vind = vindex;
00607 
00608         if ( debug )
00609             fprintf( stderr, " : (old) %d %f", cdata[vindex],ddata[vindex]);
00610 
00611         if (insert_value(sopt, ddata, cdata, vindex, node, N->fdata[nindex]))
00612             RETURN(-1);
00613 
00614         if ( debug )
00615             fprintf( stderr, " : (new) %d %f\n", cdata[vindex],ddata[vindex]);
00616     }
00617 
00618     RETURN(0);
00619 }
00620 
00621 
00622 /*----------------------------------------------------------------------
00623  * insert_value         - insert value based on user function
00624  *
00625  * return   0 on success
00626  *        < 0 on error
00627  *----------------------------------------------------------------------
00628 */
00629 int insert_value(s2v_opts_t * sopt, double *dv, int *cv, int vox, int node,
00630                  float value)
00631 {
00632 ENTRY("insert_value");
00633 
00634     if ( !sopt || !dv || !cv || vox < 0 )
00635     {
00636         fprintf(stderr, "** IV: bad params (%p,%p,%p,%d)\n",sopt,dv,cv,vox);
00637         RETURN(-1);
00638     }
00639 
00640     if ( (sopt->debug > 1) && (vox == sopt->dvox) )
00641         fprintf(stderr,"++ voxel %d, node %d, values (%d, %f) ",
00642                 vox, node, cv[vox], dv[vox]);
00643 
00644     switch ( sopt->map )
00645     {
00646         default:
00647             fprintf(stderr,"** IV: mapping %d not ready\n", sopt->map );
00648             RETURN(-1);
00649 
00650         case E_SMAP_AVE:
00651             if ( cv[vox] == 0 )
00652                 dv[vox] = value;
00653             else
00654                 dv[vox] += value;               /* divide by count later */
00655             break;
00656 
00657         case E_SMAP_COUNT:
00658             if ( cv[vox] == 0 )
00659                 dv[vox] = 1.0;
00660             else
00661                 dv[vox]++;
00662             break;
00663 
00664         case E_SMAP_MAX:
00665             if ( cv[vox] == 0 )
00666                 dv[vox] = value;
00667             else if (value > dv[vox])
00668                 dv[vox] = value;
00669 
00670             break;
00671 
00672         case E_SMAP_MAX_ABS:
00673             if ( cv[vox] == 0 )
00674                 dv[vox] = value;
00675             else if (fabs(value) > fabs(dv[vox]))
00676                 dv[vox] = value;
00677 
00678             break;
00679 
00680         case E_SMAP_MIN:
00681             if ( cv[vox] == 0 )
00682                 dv[vox] = value;
00683             else if (value < dv[vox])
00684                 dv[vox] = value;
00685 
00686             break;
00687 
00688         case E_SMAP_MASK:
00689         case E_SMAP_MASK2:
00690             dv[vox] = 1.0;
00691             break;
00692     }
00693 
00694     cv[vox]++;          /* in any case, increment the counter */
00695 
00696     if ( (sopt->debug > 1) && (vox == sopt->dvox) )
00697         fprintf(stderr,"to (%d, %f)\n",cv[vox],dv[vox]);
00698 
00699     RETURN(0);
00700 }
00701 
00702 
00703 /*----------------------------------------------------------------------
00704  * make_point_list  - from endpoints and steps
00705  *
00706  * return   0 on success
00707  *        < 0 on error
00708  *----------------------------------------------------------------------
00709 */
00710 int make_point_list( THD_fvec3 * list, THD_fvec3 * p1, THD_fvec3 * pn, 
00711                      s2v_opts_t * sopt )
00712 {
00713     float rat1, ratn;
00714     int   step;
00715 
00716 ENTRY("make_point_list");
00717 
00718     if ( !list || !p1 || !pn || !sopt )
00719     {
00720         fprintf(stderr,"** mpl: bad params (%p,%p,%p,%p)\n", list,p1,pn,sopt);
00721         RETURN(-1);
00722     }
00723 
00724     list[0] = *p1;
00725 
00726     for ( step = 1; step < sopt->f_steps; step++ )
00727     {
00728         ratn = step / (sopt->f_steps - 1.0);
00729         rat1 = 1.0 - ratn;
00730 
00731         list[step].xyz[0] = rat1 * p1->xyz[0] + ratn * pn->xyz[0];
00732         list[step].xyz[1] = rat1 * p1->xyz[1] + ratn * pn->xyz[1];
00733         list[step].xyz[2] = rat1 * p1->xyz[2] + ratn * pn->xyz[2];
00734     }
00735 
00736     RETURN(0);
00737 }
00738 
00739 
00740 /*----------------------------------------------------------------------
00741  * adjust_endpts                - adjust endpoints for map and options
00742  *
00743  * return   0 on success
00744  *        < 0 on error
00745  *----------------------------------------------------------------------
00746 */
00747 int adjust_endpts( s2v_opts_t * sopt, THD_fvec3 * p1, THD_fvec3 * pn )
00748 {
00749     THD_fvec3 f3_diff;
00750     float     dist, factor;
00751 
00752 ENTRY("adjust_endpts");
00753 
00754     if ( !sopt || !p1 || !pn )
00755     {
00756         fprintf(stderr,"** ae: invalid params (%p,%p,%p)\n", sopt, p1, pn);
00757         RETURN(-1);
00758     }
00759 
00760     /* first, get the difference, and distance */
00761     f3_diff.xyz[0] = pn->xyz[0] - p1->xyz[0];
00762     f3_diff.xyz[1] = pn->xyz[1] - p1->xyz[1];
00763     f3_diff.xyz[2] = pn->xyz[2] - p1->xyz[2];
00764 
00765     dist = dist_f3mm( p1, pn );
00766 
00767     if ( (sopt->f_p1_fr != 0.0) || (sopt->f_p1_mm != 0.0) )
00768     {
00769         if ( sopt->f_p1_fr != 0.0 )     /* what the heck, choose fr if both */
00770             factor = sopt->f_p1_fr;
00771         else
00772             factor = (dist == 0.0) ? 0.0 : sopt->f_p1_mm / dist;
00773 
00774         p1->xyz[0] += factor * f3_diff.xyz[0];
00775         p1->xyz[1] += factor * f3_diff.xyz[1];
00776         p1->xyz[2] += factor * f3_diff.xyz[2];
00777     }
00778 
00779     if ( (sopt->f_pn_fr != 0.0) || (sopt->f_pn_mm != 0.0) )
00780     {
00781         if ( sopt->f_pn_fr != 0.0 )
00782             factor = sopt->f_pn_fr;
00783         else
00784             factor = (dist == 0.0) ? 0.0 : sopt->f_pn_mm / dist;
00785 
00786         pn->xyz[0] += factor * f3_diff.xyz[0];
00787         pn->xyz[1] += factor * f3_diff.xyz[1];
00788         pn->xyz[2] += factor * f3_diff.xyz[2];
00789     }
00790 
00791     switch ( sopt->map )
00792     {
00793         default:
00794             fprintf(stderr,"** ae: mapping %d not ready\n", sopt->map );
00795             RETURN(-1);
00796 
00797         case E_SMAP_AVE:
00798         case E_SMAP_COUNT:
00799         case E_SMAP_MAX_ABS:
00800         case E_SMAP_MAX:
00801         case E_SMAP_MIN:
00802         case E_SMAP_MASK:
00803         case E_SMAP_MASK2:
00804             break;
00805     }
00806 
00807     RETURN(0);
00808 }
00809 
00810 
00811 /*----------------------------------------------------------------------
00812  * set_node_list_data   - fill fdata in node list
00813  *
00814  * For the given column, fill N->ilist with data from p->sdata_im.
00815  *----------------------------------------------------------------------
00816 */
00817 int set_node_list_data ( node_list_t *N, param_t *p, s2v_opts_t *sopt, int col )
00818 {
00819     float * fp, fval;
00820     int     c, lposn;
00821 
00822 ENTRY("set_node_list_data");
00823 
00824     if ( !N || !p || !sopt || col < 0 )
00825     {
00826         fprintf(stderr,"** snld: bad params (%p,%p,%p,%d)\n", N, p, sopt, col);
00827         RETURN(-1);
00828     }
00829 
00830     if ( sopt->debug > 1 )
00831         fprintf(stderr, "-- setting fdata for column %d\n", col);
00832 
00833     /* if sdata_im does not exist, fill as mask and return */
00834     if ( !p->sdata_im )
00835     {
00836         fval = 1.0;     /* init to mask value */
00837 
00838         /* if we have a PARSER_code (presumably without symbols), use it */
00839         if ( p->parser.pcode )
00840         {
00841             for ( c = 0; c < 26; c++ )
00842                 p->parser.atoz[c] = 0.0;
00843             fval = PARSER_evaluate_one( p->parser.pcode, p->parser.atoz );
00844         }
00845 
00846         for ( c = 0; c < N->ilen; c++ )
00847             N->fdata[c] = fval;
00848 
00849         RETURN(0);
00850     }
00851     
00852     /* else sdata exists: check column, and copy data from sdata_im */
00853     if ( col > (p->sdata_im->nx - 2) && !p->parser.pcode )
00854     {
00855         fprintf(stderr,"** snld error: col > nx-2 (%d > %d)\n",
00856                 col, p->sdata_im->nx-2);
00857         RETURN(-1);
00858     }
00859     else if ( p->sdata_im->ny < N->ilen )
00860     {
00861         fprintf(stderr,"** snld error: ny < ilen (%d < %d)\n",
00862                 p->sdata_im->ny, N->ilen);
00863         RETURN(-1);
00864     }
00865     else if ( !N->fdata )
00866     {
00867         fprintf(stderr,"** snld error: missing idata\n");
00868         RETURN(-1);
00869     }
00870     else if ( p->parser.pcode && col != 0 )             /* let's be safe */
00871     {
00872         fprintf(stderr,"** snld error: cannot use parser with col = %d\n", col);
00873         RETURN(-1);
00874     }
00875 
00876     /* hmmmm, we're still missing something...  oh yes, data! */
00877 
00878     fp = MRI_FLOAT_PTR( p->sdata_im ) + col+1;  /* offset by column number */
00879 
00880     for ( c = 0; c < N->ilen; c++ )
00881     {
00882         if ( p->parser.pcode )
00883         {
00884             /* fill atoz with surface node data */
00885             for ( lposn = 0; lposn < p->parser.max_sym; lposn++ )
00886                 p->parser.atoz[lposn] = fp[lposn];
00887 
00888             N->fdata[c] = PARSER_evaluate_one(p->parser.pcode, p->parser.atoz);
00889         }
00890         else
00891             N->fdata[c] = *fp;
00892 
00893         fp += p->sdata_im->nx;
00894     }
00895 
00896     RETURN(0);
00897 }
00898 
00899 
00900 /*----------------------------------------------------------------------
00901  * init_node_list       - from surfaces or from sxyz file
00902  *
00903  * Fill nodes with coordinate data.
00904  *----------------------------------------------------------------------
00905 */
00906 int init_node_list (opts_t *opts, param_t *p, s2v_opts_t *sopt, node_list_t *N)
00907 {
00908     int nsurf, rv;
00909 
00910 ENTRY("init_node_list");
00911 
00912     if ( opts == NULL || p == NULL || sopt == NULL || N == NULL )
00913     {
00914         fprintf(stderr, "** inl - bad params (%p,%p,%p,%p)\n",opts,p,sopt,N);
00915         RETURN(-1);
00916     }
00917 
00918     memset(N,0,sizeof(*N));     /* first, clear it out - have care w/pointers */
00919     N->nodes = NULL;  N->fdata = NULL;  N->ilist = NULL;
00920 
00921     nsurf = SUMAg_N_DOv;        /* verify, as long as there is no sxyz_im */
00922     if ( !p->sxyz_im && ((nsurf < 1) || (nsurf > S2V_MAX_SURFS)) )
00923     {
00924         fprintf(stderr,"** inl: SUMAg_N_DOv has invalid value of %d\n", nsurf);
00925         RETURN(-1);
00926     }
00927 
00928 #if 0           /* remove requrement of 2 surfaces for functions [v3.0] */
00929 
00930     if ( sopt->map == E_SMAP_MASK )
00931         nsurf = 1;
00932     else
00933     {
00934         /* do a quick check before slow reading action */
00935         if ( ! p->sxyz_im && (SUMAg_N_DOv < 2) )
00936         {
00937             fprintf(stderr,"** function '%s' requires 2 surfaces\n",
00938                     gs2v_map_names[sopt->map]);
00939             RETURN(-1);
00940         }
00941 
00942         nsurf = 2;
00943     }
00944 #endif
00945 
00946     if ( p->sxyz_im )
00947         rv = sxyz_1D_to_nlist( opts, sopt, p, N, &nsurf );
00948     else
00949         rv = surf_to_node_list( sopt, N, nsurf );
00950 
00951     if ( sopt->debug > 1 && rv == 0 )         /* errors reported separately */
00952         fprintf(stderr,"++ node list initialized\n");
00953 
00954     RETURN(rv);
00955 }
00956 
00957 
00958 /*----------------------------------------------------------------------
00959  * sxyz_1D_to_nlist     - nodes from sxyz 1D to node_list
00960  *
00961  *----------------------------------------------------------------------
00962 */
00963 int sxyz_1D_to_nlist(opts_t * opts, s2v_opts_t * sopt, param_t * p,
00964                      node_list_t * N, int * nsurf)
00965 {
00966     THD_fvec3 * fvp;
00967     float     * fp;
00968     int         c, sc;
00969 
00970 ENTRY("sxyz_1D_to_nlist");
00971 
00972     if ( !sopt || !p || !N )
00973     {
00974         fprintf(stderr,"** sxyz2nl: bad params (%p,%p,%p)\n",sopt,p,N);
00975         RETURN(-1);
00976     }
00977 
00978     if ( !p->sxyz_im )
00979     {
00980         fprintf(stderr,"** missing sxyz_im for sxyz surf '%s'\n",
00981                 opts->surf_xyz_1D_file);
00982         RETURN(-1);
00983     }
00984 
00985     *nsurf = p->sxyz_im->nx / 3;
00986 
00987     if ( p->sxyz_im->nx != 3 * *nsurf )
00988     {
00989         fprintf(stderr,"** sxyz surf '%s' has %d columns (%d expected)\n",
00990                 opts->surf_xyz_1D_file, p->sxyz_im->nx, 3**nsurf);
00991         RETURN(-1);
00992     }
00993     else if ( p->sxyz_im->ny <= 0 )
00994     {
00995         fprintf(stderr,"** sxyz surf '%s': bad sxyz dimensions (%d,%d)\n",
00996                 opts->surf_xyz_1D_file, p->sxyz_im->nx, p->sxyz_im->ny);
00997         RETURN(-1);
00998     }
00999 
01000     N->depth = *nsurf;
01001     N->nnodes = p->sxyz_im->ny;
01002 
01003     N->nodes = (THD_fvec3 *)malloc(N->depth*N->nnodes*sizeof(THD_fvec3));
01004     if ( N->nodes == NULL )
01005     {
01006         fprintf(stderr,"** failed to allocate %dx%d THD_fvec3's for nodes\n",
01007                 N->nnodes, N->depth);
01008         RETURN(-1);
01009     }
01010 
01011     fvp = N->nodes;
01012     for ( sc = 0; sc < *nsurf; sc++ )
01013     {
01014         fp = MRI_FLOAT_PTR( p->sxyz_im ) + sc * 3;      /* offset for surf */
01015         for ( c = 0; c < N->nnodes; c++ )
01016         {
01017             fvp->xyz[0] = fp[0];
01018             fvp->xyz[1] = fp[1];
01019             fvp->xyz[2] = fp[2];
01020 
01021             fp += p->sxyz_im->nx;
01022             fvp++;
01023         }
01024     }
01025 
01026     if ( sopt->debug > 0 )
01027     {
01028         fprintf(stderr, "++ sxyz_1D nodes from '%s': nxyz = %d, nsurf = %d\n",
01029                 opts->surf_xyz_1D_file, N->nnodes, N->depth);
01030         if ( sopt->dnode >= 0 && sopt->dnode <= p->sxyz_im->ny )
01031         {
01032             fprintf(stderr,"   debug node (%d) loc", sopt->dnode);
01033             for ( sc = 0; sc < *nsurf; sc++ )
01034                 fprintf(stderr," : (%f, %f, %f)",
01035                     N->nodes[sopt->dnode + sc*N->nnodes].xyz[0],
01036                     N->nodes[sopt->dnode + sc*N->nnodes].xyz[1],
01037                     N->nodes[sopt->dnode + sc*N->nnodes].xyz[2]);
01038             fputc('\n', stderr);
01039         }
01040     }
01041 
01042     RETURN(0);
01043 }
01044 
01045 
01046 /*----------------------------------------------------------------------
01047  * surf_to_node_list - create node list for mask mapping
01048  *
01049  * Allocate space for node list(s), and fill with xyz coordinates.
01050  *
01051  * return -1 : on error
01052  *         0 : on success
01053  *----------------------------------------------------------------------
01054 */
01055 int surf_to_node_list ( s2v_opts_t * sopt, node_list_t * N, int nsurf )
01056 {
01057     SUMA_SurfaceObject ** so;
01058     THD_fvec3          *  fvp;
01059     float              *  fp;
01060     int                   rv, nindex, sindex;
01061 
01062 ENTRY("surf_to_node_list");
01063 
01064     if ( sopt == NULL || N == NULL || nsurf < 0 || nsurf > 2 )
01065     {
01066         fprintf( stderr, "** anl: bad params (%p,%p,%d)\n",
01067                  sopt, N, nsurf );
01068         RETURN(-1);
01069     }
01070 
01071     /* create a temporary list of surface pointers */
01072     so = (SUMA_SurfaceObject **)calloc(nsurf, sizeof(SUMA_SurfaceObject *));
01073     if ( so == NULL )
01074     {
01075         fprintf( stderr, "** anl: failed to alloc %d surf pointers\n", nsurf );
01076         RETURN(-1);
01077     }
01078 
01079     if ( (rv = get_mappable_surfs( so, nsurf, sopt->debug )) != nsurf )
01080     {
01081         fprintf( stderr, "** error: found %d (of %d) mappable surfaces\n",
01082                 rv, nsurf );
01083         RETURN(-1);
01084     }
01085 
01086     /* fill node list struct */
01087     N->depth  = nsurf;
01088     N->nnodes = so[0]->N_Node;
01089     N->nodes  = (THD_fvec3 *)malloc(N->depth * N->nnodes * sizeof(THD_fvec3));
01090     if ( N->nodes == NULL )
01091     {
01092         fprintf( stderr, "** cnlm: failed to allocate %d THD_fvec3 structs\n",
01093                  N->depth * N->nnodes );
01094         free(so);
01095         RETURN(-1);
01096     }
01097 
01098     /* copy the xyz coordinates for each node */
01099 
01100     fvp = N->nodes;     /* linear coverage of all nodes */
01101     for ( sindex = 0; sindex < N->depth; sindex++ )
01102     {
01103         if ( so[sindex]->N_Node != N->nnodes )
01104         {
01105             fprintf(stderr, "** surf #%d (%s) has %d nodes (but expected %d)\n",
01106                     sindex,
01107                     so[sindex]->Label ? so[sindex]->Label : "<unnamed>",
01108                     so[sindex]->N_Node, N->nnodes );
01109             free( N->nodes );  N->nodes = NULL;
01110             free(so);
01111             RETURN(-1);
01112         }
01113 
01114         for ( nindex = 0, fp = so[sindex]->NodeList;
01115               nindex < N->nnodes;
01116               nindex++, fp += 3 )
01117         {
01118             memcpy( fvp->xyz, fp, 3*sizeof(float) );
01119             fvp++;
01120         }
01121     }
01122 
01123     if ( sopt->debug > 1 )
01124         fprintf( stderr, "++ allocated %d x %d (x %d) node list\n",
01125                  N->depth, N->nnodes, (int)sizeof(THD_fvec3) );
01126 
01127     free(so);
01128     RETURN(0);
01129 }
01130 
01131 
01132 /*----------------------------------------------------------------------
01133  * get_mappable_surfs - return mappable surface objects
01134  *
01135  * return the number of surfaces found
01136  *----------------------------------------------------------------------
01137 */
01138 int get_mappable_surfs( SUMA_SurfaceObject ** slist, int how_many, int debug )
01139 {
01140     SUMA_SurfaceObject * so;
01141     int                  count, socount = 0;
01142 
01143 ENTRY("get_mappable_surfts");
01144 
01145     if ( slist == NULL )
01146     {
01147         fprintf( stderr, "** gms: missing slist!\n" );
01148         RETURN(-1);
01149     }
01150 
01151     for ( count = 0; count < SUMAg_N_DOv; count++ )
01152     {
01153         if ( ! SUMA_isSO(SUMAg_DOv[count]) )
01154             continue;
01155 
01156         so = (SUMA_SurfaceObject *)SUMAg_DOv[count].OP;
01157 
01158         if ( ! so->AnatCorrect )
01159         {
01160             if ( debug )
01161                 fprintf(stderr,"-- surf #%d '%s', anat not correct, skipping\n",
01162                         socount, CHECK_NULL_STR(so->Label));
01163             if ( debug > 1 )
01164                 fprintf(stderr,"** consider adding the following to the "
01165                                "surface definition in the spec file:\n"
01166                                "       Anatomical = Y\n");
01167             continue;
01168         }
01169 
01170         if ( debug > 1 )
01171         {
01172             fprintf( stderr, "\n---------- surface #%d '%s' -----------\n",
01173                      socount, CHECK_NULL_STR(so->Label) );
01174             SUMA_Print_Surface_Object( so, stderr );
01175         }
01176 
01177         if ( socount < how_many )       /* store a good surface */
01178             slist[socount] = so;
01179 
01180         socount++;
01181     }
01182 
01183     if ( debug > 1 )
01184         fprintf( stderr, "++ found %d mappable surfaces\n", socount );
01185 
01186     RETURN(socount);
01187 }
01188 
01189 
01190 /*----------------------------------------------------------------------
01191  * set_smap_opts  - given options and mapping function, fill struct
01192  *
01193  * return  0 : success
01194  *        -1 : error condition
01195  *----------------------------------------------------------------------
01196 */
01197 int set_smap_opts( opts_t * opts, param_t * p, s2v_opts_t * sopt )
01198 {
01199     int nsurf;
01200 
01201 ENTRY("set_smap_opts");
01202 
01203     memset( sopt, 0, sizeof(*sopt) );   /* clear the sopt struct */
01204     sopt->cmask = NULL;
01205 
01206     if ( (sopt->map = check_map_func( opts->map_str )) == E_SMAP_INVALID )
01207         RETURN(-1);
01208 
01209     sopt->datum = check_datum_type(opts->datum_str, DSET_BRICK_TYPE(p->gpar,0));
01210     if (sopt->datum < 0)
01211         RETURN(-1);
01212 
01213     if ( opts->noscale == 1 )
01214         sopt->noscale = 1;
01215 
01216     sopt->debug         = opts->debug;  /* for output in library functions */
01217     sopt->dnode         = opts->dnode;
01218     sopt->dvox          = opts->dvox;
01219     sopt->sxyz_ori_gpar = opts->sxyz_ori_gpar;
01220     sopt->cmask         = p->cmask;
01221 
01222     if ( opts->f_steps < S2V_F_STEPS_MIN )             /* minimum is 1    */
01223     {
01224         /* if f_steps was not given, init to the number of surfaces  - v3.6 */
01225         for ( nsurf = 0; nsurf < S2V_MAX_SURFS && opts->snames[nsurf]; nsurf++ )
01226             ;
01227         if ( nsurf <= 0 )
01228         {
01229             fprintf(stderr,"** error: sso: no input surfaces\n");
01230             RETURN(-1);
01231         }
01232         sopt->f_steps = nsurf;
01233     }
01234     else
01235         sopt->f_steps = opts->f_steps;
01236 
01237     sopt->f_index = S2V_F_INDEX_VOXEL;
01238     if ( (opts->f_index_str != NULL) &&
01239          ( !strncmp(opts->f_index_str, "point", 5) ||
01240            !strncmp(opts->f_index_str, "node",  4) ) ) /* preserve old use */
01241         sopt->f_index = S2V_F_INDEX_POINT;
01242 
01243     sopt->f_p1_fr = opts->f_p1_fr;         /* copy fractions & distances */
01244     sopt->f_pn_fr = opts->f_pn_fr;
01245     sopt->f_p1_mm = opts->f_p1_mm;
01246     sopt->f_pn_mm = opts->f_pn_mm;
01247 
01248 
01249     switch (sopt->map)
01250     {
01251         default:
01252 
01253         case E_SMAP_AVE:
01254         case E_SMAP_MAX:
01255         case E_SMAP_MIN:
01256         case E_SMAP_MAX_ABS:
01257             break;
01258 
01259         case E_SMAP_COUNT:
01260         case E_SMAP_MASK:
01261         case E_SMAP_MASK2:
01262             sopt->noscale = 1;
01263             break;
01264     }
01265 
01266     if ( opts->debug > 1 )
01267         disp_s2v_opts_t( "++ s2v_opts_set :", sopt );
01268 
01269     RETURN(0);
01270 }
01271 
01272 
01273 /*----------------------------------------------------------------------
01274  * free memory, close output file
01275  *----------------------------------------------------------------------
01276 */
01277 int final_clean_up ( node_list_t * N )
01278 {
01279 ENTRY("final_clean_up");
01280 
01281     if ( ( SUMAg_DOv != NULL ) &&
01282          ( SUMA_Free_Displayable_Object_Vect(SUMAg_DOv, SUMAg_N_DOv) == 0 ) )
01283         fprintf(stderr, "** failed SUMA_Free_Displayable_Object_Vect()\n" );
01284 
01285     if ( ( SUMAg_SVv != NULL ) &&
01286          ( SUMA_Free_SurfaceViewer_Struct_Vect(SUMAg_SVv, SUMAg_N_SVv) == 0 ) )
01287         fprintf( stderr, "** failed SUMA_Free_SurfaceViewer_Struct_Vect()\n" );
01288 
01289     if ( ( SUMAg_CF != NULL ) && ( SUMA_Free_CommonFields(SUMAg_CF) == 0 ) )
01290         fprintf( stderr, "** failed SUMA_Free_CommonFields()\n" );
01291 
01292     if ( N )
01293     {
01294         if ( N->nodes )  free( N->nodes );
01295         if ( N->fdata )  free( N->fdata );
01296         if ( N->ilist )  free( N->ilist );
01297     }
01298 
01299     RETURN(0);
01300 }
01301 
01302 
01303 /*----------------------------------------------------------------------
01304  * 
01305  *----------------------------------------------------------------------
01306 */
01307 int read_surf_files ( opts_t * opts, param_t * p, SUMA_SurfSpecFile * spec,
01308                       s2v_opts_t * sopt, node_list_t * N )
01309 {
01310     int rv;
01311 
01312 ENTRY("read_surf_files");
01313 
01314     /* get surface coordinates */
01315     if ( opts->spec_file )
01316     {
01317         if ( (rv = fill_SUMA_structs(opts, spec)) != 0 )
01318             RETURN(rv);
01319     }
01320     else if ( opts->surf_xyz_1D_file )
01321     {
01322         if ( (rv = read_sxyz_1D( opts, p )) != 0 )
01323             RETURN(rv);
01324     }
01325     else
01326     {
01327         fprintf(stderr,"** missing spec or sdata file, exiting...\n");
01328         RETURN(-1);
01329     }
01330 
01331     /* assign node list nodes (xyz coords) */
01332     if ( (rv = init_node_list(opts, p, sopt, N)) != 0 )
01333         RETURN(rv);
01334 
01335     /* check status and allocate memory in node list */
01336     if ( (rv = fill_node_list(opts, p, N)) != 0 )
01337         RETURN(rv);
01338 
01339     if ( (rv = verify_parser_expr(opts, p)) != 0 )
01340         RETURN(rv);
01341 
01342     RETURN(0);
01343 }
01344 
01345 
01346 /*----------------------------------------------------------------------
01347  * read_sxyz_file       - read surf_xyz_1D_file
01348  *----------------------------------------------------------------------
01349 */
01350 int read_sxyz_1D ( opts_t * opts, param_t * p )
01351 {
01352     MRI_IMAGE * im;
01353 
01354 ENTRY("read_sxyz_1D");
01355 
01356     if ( !opts || !p )
01357     {
01358         fprintf(stderr,"** rsxyz1D: bad params (%p,%p)\n", opts, p);
01359         RETURN(-1);
01360     }
01361 
01362     if ( (im = mri_read_1D(opts->surf_xyz_1D_file)) == NULL )
01363     {
01364         fprintf(stderr,"** failed to read sxyz 1D file '%s'\n",
01365                 opts->surf_xyz_1D_file);
01366         RETURN(-1);
01367     }
01368     if ( im->nx < 1 || im->ny < 3 )     /* must have xyz coords, at least */
01369     {
01370         fprintf(stderr,"** bad sxyz file '%s'?\n", opts->surf_xyz_1D_file);
01371         RETURN(-1);
01372     }
01373 
01374     /* transpose list to node-major order, and lose temp image */
01375     p->sxyz_im = mri_transpose(im);
01376     mri_free(im);
01377 
01378     if ( opts->debug > 0 )
01379         fprintf(stderr,"++ read 1D xyz surface file '%s' (nx = %d, ny = %d)\n",
01380                 opts->surf_xyz_1D_file, p->sxyz_im->nx, p->sxyz_im->ny );
01381 
01382     RETURN(0);
01383 }
01384 
01385 
01386 /*----------------------------------------------------------------------
01387  * fill the node_list data fields
01388  *
01389  *     ilist gets index list, if any
01390  *     fdata gets allocation for data
01391  *     ilen is the length of the two lists
01392  *----------------------------------------------------------------------
01393 */
01394 int fill_node_list ( opts_t * opts, param_t * p, node_list_t * N )
01395 {
01396     int rv;
01397 
01398 ENTRY("fill_node_list");
01399 
01400     if ( !opts || !p || !N )
01401     {
01402         fprintf(stderr,"** fill_node_list: bad params (%p,%p,%p)\n",opts,p,N);
01403         RETURN(-1);
01404     }
01405 
01406     p->nsubs = 1;               /* unless we get additional surface data */
01407 
01408     if ( opts->sdata_file_1D )
01409     {
01410         if ( (rv = sdata_from_1D( opts, p, N )) != 0 )
01411             RETURN(rv);
01412         if ( ! p->parser.pcode )
01413             p->nsubs = p->sdata_im->nx - 1;
01414     }
01415     else
01416     {
01417         if ( (rv = sdata_from_default( N )) != 0 )
01418             RETURN(rv);
01419     }
01420 
01421     if ( (rv = verify_node_list( N )) != 0 )
01422         RETURN(rv);
01423 
01424     if ( opts->debug > 1 )
01425         disp_node_list_t( "++ node list filled: ", N );
01426 
01427     RETURN(0);
01428 }
01429 
01430 
01431 /*----------------------------------------------------------------------
01432  * verify that the parser expression has sufficient surface data values
01433  *----------------------------------------------------------------------
01434 */
01435 int verify_parser_expr ( opts_t * opts, param_t * p )
01436 {
01437     int max_used;
01438 
01439 ENTRY("verify_parser_expr");
01440 
01441     if ( !opts || !p )
01442     {
01443         fprintf(stderr,"** vpe: invalid params (%p,%p)\n", opts, p);
01444         RETURN(-1);
01445     }
01446 
01447     /* if no parser code, there is nothing to do */
01448     if ( ! p->parser.pcode )
01449         RETURN(0);
01450 
01451     for ( max_used = 25; max_used >= 0; max_used-- )
01452         if ( p->parser.has_sym[max_used] )
01453             break;
01454     max_used++;         /* this is the number of surface values needed */
01455     p->parser.max_sym = max_used;
01456 
01457     /* if the expression is not constant, we need some data */
01458     if ( max_used > 0 )
01459     {
01460         if ( !p->sdata_im )
01461         {
01462             fprintf(stderr, "** parser expression requires surface data\n"
01463                             "   (see '-sdata_1D')\n");
01464             RETURN(-1);
01465         }
01466         else if ( max_used > p->sdata_im->nx - 1 )
01467         {
01468             fprintf(stderr,
01469                     "** error: not enough surface values for expression\n"
01470                     "          svals = %d, exp_vals = %d, expr = '%s'\n",
01471                     p->sdata_im->nx - 1, max_used, opts->data_expr);
01472             RETURN(-1);
01473         }
01474     }
01475 
01476     if ( opts->debug > 1 )
01477         fprintf(stderr,"-- surf_vals = %d, expr_vals = %d\n",
01478                 p->sdata_im ? (p->sdata_im->nx - 1) : 0, max_used);
01479 
01480     RETURN(0);
01481 }
01482 
01483 
01484 /*----------------------------------------------------------------------
01485  * verify that the node list makes sense
01486  *----------------------------------------------------------------------
01487 */
01488 int verify_node_list ( node_list_t * N )
01489 {
01490     int icount, errs = 0;
01491 
01492 ENTRY("verify_node_list");
01493 
01494     if ( !N )
01495     {
01496         fprintf(stderr, "** vnl - no node list\n" );
01497         RETURN(-1);
01498     }
01499 
01500     if ( !N->nodes || !N->ilist )
01501     {
01502         fprintf(stderr,"** missing nodes or ilist\n" );
01503         errs++;
01504     }
01505 
01506     if ( N->depth < 1 || N->nnodes < 1 || N->ilen < 1 )
01507     {
01508         fprintf(stderr,"** invalid depth, nnodes or ilen" );
01509         errs++;
01510     }
01511 
01512     if ( errs )
01513     {
01514         disp_node_list_t("** invalid data : ", N );
01515         RETURN(-errs);
01516     }
01517 
01518     /* now check that the indices are within nnodes range */
01519     for ( icount = 0; icount < N->ilen; icount++ )
01520         if ( N->ilist[icount] < 0 || N->ilist[icount] >= N->nnodes )
01521         {
01522             fprintf(stderr,"** surf data index number %d is out of range:\n"
01523                            "   index = %d, range is [%d,%d]\n",
01524                            icount, N->ilist[icount], 0, N->nnodes-1);
01525             RETURN(-10);
01526         }
01527 
01528     /* node_list is okay, so make space for the actual data */
01529     if ( (N->fdata = (float *)malloc(N->ilen*sizeof(float))) == NULL )
01530     {
01531         fprintf(stderr,"** vnl: failed to allocate %d floats\n",N->ilen);
01532         free(N->ilist);
01533         RETURN(-20);
01534     }
01535 
01536     RETURN(0);
01537 }
01538 
01539 
01540 /*----------------------------------------------------------------------
01541  * fill ilist with default indices (i[k] = k)
01542  *----------------------------------------------------------------------
01543 */
01544 int sdata_from_default ( node_list_t * N )
01545 {
01546     int c;
01547 
01548 ENTRY("sdata_from_default");
01549 
01550     if ( !N )
01551         RETURN(-1);
01552 
01553     if ( (N->ilist = (int *)malloc(N->nnodes * sizeof(int))) == NULL )
01554     {
01555         fprintf(stderr,"** failed to allocate %d ints for ilist\n",N->nnodes);
01556         RETURN(-1);
01557     }
01558 
01559     N->ilen   = N->nnodes;
01560 
01561     /* now fill ilist with default node indices */
01562     for ( c = 0; c < N->ilen; c++ )
01563         N->ilist[c] = c;
01564 
01565     RETURN(0);
01566 }
01567 
01568 
01569 /*----------------------------------------------------------------------
01570  * fill node_list_t struct from 1D surface file
01571  *----------------------------------------------------------------------
01572 */
01573 int sdata_from_1D ( opts_t * opts, param_t * p, node_list_t * N )
01574 {
01575     MRI_IMAGE * im;
01576     float     * fim;
01577     int         c;
01578 
01579 ENTRY("sdata_from_1D");
01580 
01581     if ( !opts || !N || !p )
01582         RETURN(-1);
01583 
01584     if ( (im = mri_read_1D(opts->sdata_file_1D)) == NULL )
01585     {
01586         fprintf(stderr,"** failed to read 1D file '%s'\n", opts->sdata_file_1D);
01587         RETURN(-2);
01588     }
01589     /* transpose list to node-major order, and lose temp image */
01590     p->sdata_im = mri_transpose(im);
01591     mri_free(im);
01592 
01593     if ( p->sdata_im->nx < 2 || p->sdata_im->ny < 1 )
01594     {
01595         fprintf(stderr,"** bad (%d x %d) surf data 1D file '%s'\n",
01596                 p->sdata_im->ny, p->sdata_im->nx, opts->sdata_file_1D);
01597         RETURN(-3);
01598     }
01599 
01600     N->ilen = p->sdata_im->ny;
01601 
01602     if ( opts->debug > 0 )
01603         fprintf(stderr,"++ read 1D surface file '%s' (nx = %d, ny = %d)\n",
01604                 opts->sdata_file_1D, p->sdata_im->nx, p->sdata_im->ny );
01605 
01606     /* only allocate space ilist */
01607     if ( (N->ilist = (int *)malloc(N->ilen*sizeof(int))) == NULL )
01608     {
01609         fprintf(stderr,"** sf1D a: failed to allocate %d ints\n", N->ilen);
01610         RETURN(-1);
01611     }
01612 
01613     /* first set the node index values */
01614     fim = MRI_FLOAT_PTR( p->sdata_im );
01615     for ( c = 0; c < N->ilen; c++, fim += p->sdata_im->nx )
01616         N->ilist[c] = (int)*fim;                          /* set node index */
01617 
01618     RETURN(0);
01619 }
01620 
01621 
01622 /*----------------------------------------------------------------------
01623  * read surfaces (much stolen from SUMA_suma.c - thanks Ziad!)
01624  * 
01625  * return 0 on success
01626  *----------------------------------------------------------------------
01627 */
01628 int fill_SUMA_structs ( opts_t * opts, SUMA_SurfSpecFile * spec )
01629 {
01630     int debug = 0, rv;
01631 ENTRY("fill_SUMA_structs");
01632 
01633     if ( opts->debug > 2 )
01634         debug = 1;
01635 
01636     if ( debug )
01637         fputs( "-- SUMA_Create_CommonFields()...\n", stderr );
01638 
01639     if ( opts->spec_file == NULL )
01640         RETURN(-1);
01641 
01642     /* initialize common fields struct */
01643     SUMAg_CF = SUMA_Create_CommonFields();
01644 
01645     if ( SUMAg_CF == NULL )
01646     {
01647         fprintf( stderr, "** failed SUMA_Create_CommonFields(), exiting...\n" );
01648         RETURN(-1);
01649     }
01650 
01651     /* for SUMA type notifications */
01652     if ( opts->debug > 3 )
01653     {
01654         SUMAg_CF->MemTrace = 1;
01655 
01656         if ( opts->debug > 4 )
01657             SUMAg_CF->InOut_Notify = 1;
01658     }
01659 
01660     if ( debug )
01661         fputs( "-- SUMA_Alloc_DisplayObject_Struct()...\n", stderr );
01662 
01663     SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct(SUMA_MAX_DISPLAYABLE_OBJECTS);
01664 
01665     if ( debug )
01666         fputs( "-- SUMA_Read_SpecFile()...\n", stderr );
01667 
01668     if ( SUMA_Read_SpecFile( opts->spec_file, spec) == 0 )
01669     {
01670         fprintf( stderr, "** failed SUMA_Read_SpecFile(), exiting...\n" );
01671         RETURN(-1);
01672     }
01673 
01674     if ( debug )
01675         SUMA_ShowSpecStruct(spec, stderr, 1);
01676 
01677     rv = SUMA_spec_select_surfs(spec, opts->snames, S2V_MAX_SURFS, opts->debug);
01678     if ( rv < 1 )
01679     {
01680         if ( rv == 0 )
01681             fprintf(stderr,"** no named surfaces found in spec file\n");
01682         RETURN(-1);
01683     }
01684 
01685     if ( opts->debug > 0 )
01686         SUMA_ShowSpecStruct(spec, stderr, 1);
01687 
01688     if ( SUMA_spec_set_map_refs(spec, opts->debug) != 0 )
01689         RETURN(-1);
01690 
01691     /* make sure only group was read from spec file */
01692     if ( spec->N_Groups != 1 )
01693     {
01694         fprintf( stderr,"** error: N_Groups <%d> must be 1 in spec file <%s>\n",
01695                  spec->N_Groups, opts->spec_file );
01696         RETURN(-1);
01697     }
01698 
01699     if ( debug )
01700         fputs( "-- SUMA_LoadSpec_eng()...\n", stderr );
01701 
01702     /* actually load the surface(s) from the spec file */
01703     if (SUMA_LoadSpec_eng(spec,SUMAg_DOv,&SUMAg_N_DOv,opts->sv_file,debug,
01704              SUMAg_CF->DsetList) == 0)     /* DsetList - 26 Mar 2004 [ziad] */
01705     {
01706         fprintf( stderr, "** error: failed SUMA_LoadSpec_eng(), exiting...\n" );
01707         RETURN(-1);
01708     }
01709 
01710     if ( opts->debug > 1 )
01711         fprintf(stderr, "++ %d surfaces loaded.\n", spec->N_Surfs );
01712 
01713     RETURN(0);
01714 }
01715 
01716 
01717 /*----------------------------------------------------------------------
01718  * init_options - fill opts struct, display help
01719  *----------------------------------------------------------------------
01720 */
01721 int init_options ( opts_t * opts, int argc, char * argv [] )
01722 {
01723     int ac, ind;
01724 
01725 ENTRY("init_options");
01726 
01727     if ( argc < 2 )
01728     {
01729         usage( PROG_NAME, S2V_USE_LONG );
01730         RETURN(-1);
01731     }
01732 
01733     /* clear out the options structure, pointers get explicit NULL */
01734     memset( opts, 0, sizeof( opts_t) );
01735     opts->gpar_file        = NULL;      opts->oset_file     = NULL;
01736     opts->spec_file        = NULL;      opts->sv_file       = NULL;
01737     opts->surf_xyz_1D_file = NULL;      opts->sdata_file_1D = NULL;
01738     opts->sdata_file_niml  = NULL;      opts->cmask_cmd     = NULL;
01739     opts->data_expr        = NULL;      opts->map_str       = NULL;
01740     opts->datum_str        = NULL;      opts->f_index_str   = NULL;
01741     opts->snames[0]        = NULL;      opts->snames[1]     = NULL;
01742 
01743 
01744     opts->dnode = -1;                   /* init to something invalid */
01745     opts->dvox  = -1;                   /* init to something invalid */
01746 
01747     for ( ac = 1; ac < argc; ac++ )
01748     {
01749         /* alphabetical... */
01750         if ( ! strncmp(argv[ac], "-cmask", 6) )
01751         {
01752             if ( (ac+1) >= argc )
01753             {
01754                 fputs( "option usage: -cmask COMMAND\n\n", stderr );
01755                 usage( PROG_NAME, S2V_USE_SHORT );
01756                 RETURN(-1);
01757             }
01758 
01759             opts->cmask_cmd = argv[++ac];
01760         }
01761         else if ( ! strncmp(argv[ac], "-data_expr", 8) )
01762         {
01763             if ( (ac+1) >= argc )
01764             {
01765                 fputs( "option usage: -data_expr EXPR\n\n", stderr );
01766                 usage( PROG_NAME, S2V_USE_SHORT );
01767                 RETURN(-1);
01768             }
01769 
01770             opts->data_expr = argv[++ac];
01771         }
01772         else if ( ! strncmp(argv[ac], "-datum", 6) )
01773         {
01774             if ( (ac+1) >= argc )
01775             {
01776                 fputs( "option usage: -datum DTYPE\n\n", stderr );
01777                 usage( PROG_NAME, S2V_USE_SHORT );
01778                 RETURN(-1);
01779             }
01780 
01781             opts->datum_str = argv[++ac];
01782         }
01783         else if ( ! strncmp(argv[ac], "-debug", 6) )
01784         {
01785             if ( (ac+1) >= argc )
01786             {
01787                 fputs( "option usage: -debug LEVEL\n\n", stderr );
01788                 usage( PROG_NAME, S2V_USE_SHORT );
01789                 RETURN(-1);
01790             }
01791 
01792             opts->debug = atoi(argv[++ac]);
01793             if ( opts->debug < 0 || opts->debug > S2V_DEBUG_MAX_LEV )
01794             {
01795                 fprintf( stderr, "bad debug level <%d>, should be in [0,%d]\n",
01796                         opts->debug, S2V_DEBUG_MAX_LEV );
01797                 usage( PROG_NAME, S2V_USE_SHORT );
01798                 RETURN(-1);
01799             }
01800         }
01801         else if ( ! strncmp(argv[ac], "-dnode", 6) )
01802         {
01803             if ( (ac+1) >= argc )
01804             {
01805                 fputs( "option usage: -dnode DEBUG_NODE\n\n", stderr );
01806                 usage( PROG_NAME, S2V_USE_SHORT );
01807                 RETURN(-1);
01808             }
01809 
01810             opts->dnode = atoi(argv[++ac]);
01811         }
01812         else if ( ! strncmp(argv[ac], "-dvoxel", 5) )
01813         {
01814             if ( (ac+1) >= argc )
01815             {
01816                 fputs( "option usage: -dvoxel DEBUG_VOXEL\n\n", stderr );
01817                 usage( PROG_NAME, S2V_USE_SHORT );
01818                 RETURN(-1);
01819             }
01820 
01821             opts->dvox = atoi(argv[++ac]);
01822         }
01823         else if ( ! strncmp(argv[ac], "-f_index", 7) )
01824         {
01825             if ( (ac+1) >= argc )
01826             {
01827                 fputs( "option usage: -f_index INDEX_TYPE\n\n", stderr );
01828                 usage( PROG_NAME, S2V_USE_SHORT );
01829                 RETURN(-1);
01830             }
01831             opts->f_index_str = argv[++ac];
01832         }
01833         else if ( ! strncmp(argv[ac], "-f_p1_fr", 9) )
01834         {
01835             if ( (ac+1) >= argc )
01836             {
01837                 fputs( "option usage: -f_p1_fr FRACTION\n\n", stderr );
01838                 usage( PROG_NAME, S2V_USE_SHORT );
01839                 RETURN(-1);
01840             }
01841 
01842             opts->f_p1_fr = atof(argv[++ac]);
01843         }
01844         else if ( ! strncmp(argv[ac], "-f_pn_fr", 9) )
01845         {
01846             if ( (ac+1) >= argc )
01847             {
01848                 fputs( "option usage: -f_pn_fr FRACTION\n\n", stderr );
01849                 usage( PROG_NAME, S2V_USE_SHORT );
01850                 RETURN(-1);
01851             }
01852 
01853             opts->f_pn_fr = atof(argv[++ac]);
01854         }
01855         else if ( ! strncmp(argv[ac], "-f_p1_mm", 9) )
01856         {
01857             if ( (ac+1) >= argc )
01858             {
01859                 fputs( "option usage: -f_p1_mm DISTANCE\n\n", stderr );
01860                 usage( PROG_NAME, S2V_USE_SHORT );
01861                 RETURN(-1);
01862             }
01863 
01864             opts->f_p1_mm = atof(argv[++ac]);
01865         }
01866         else if ( ! strncmp(argv[ac], "-f_pn_mm", 9) )
01867         {
01868             if ( (ac+1) >= argc )
01869             {
01870                 fputs( "option usage: -f_pn_mm DISTANCE\n\n", stderr );
01871                 usage( PROG_NAME, S2V_USE_SHORT );
01872                 RETURN(-1);
01873             }
01874 
01875             opts->f_pn_mm = atof(argv[++ac]);
01876         }
01877         else if ( ! strncmp(argv[ac], "-f_steps", 6) )
01878         {
01879             if ( (ac+1) >= argc )
01880             {
01881                 fputs( "option usage: -f_steps NUM_STEPS\n\n", stderr );
01882                 usage( PROG_NAME, S2V_USE_SHORT );
01883                 RETURN(-1);
01884             }
01885 
01886             opts->f_steps = atoi(argv[++ac]);
01887         }
01888         else if ( ! strncmp(argv[ac], "-grid_parent", 5)||
01889                   ! strncmp(argv[ac], "-inset", 6)       ||
01890                   ! strncmp(argv[ac], "-input", 6) )
01891 
01892         {
01893             if ( (ac+1) >= argc )
01894             {
01895                 fputs( "option usage: -grid_parent INPUT_DSET\n\n", stderr );
01896                 usage( PROG_NAME, S2V_USE_SHORT );
01897                 RETURN(-1);
01898             }
01899 
01900             opts->gpar_file = argv[++ac];
01901         }
01902         else if ( ! strncmp(argv[ac], "-help", 5) )
01903         {
01904             usage( PROG_NAME, S2V_USE_LONG );
01905             RETURN(-1);
01906         }
01907         else if ( ! strncmp(argv[ac], "-hist", 5) )
01908         {
01909             usage( PROG_NAME, S2V_USE_HIST );
01910             RETURN(-1);
01911         }
01912         else if ( ! strncmp(argv[ac], "-map_func", 4) )  /* mapping function */
01913         {
01914             if ( (ac+1) >= argc )
01915             {
01916                 fputs( "option usage: -map_func FUNCTION\n\n", stderr );
01917                 RETURN(-1);
01918             }
01919 
01920             opts->map_str = argv[++ac];     /* store user string for now */
01921         }
01922         else if ( ! strncmp(argv[ac], "-noscale", 4) )
01923         {
01924             opts->noscale = 1;
01925         }
01926         else if ( ! strncmp(argv[ac], "-prefix", 4) )
01927         {
01928             if ( (ac+1) >= argc )
01929             {
01930                 fputs( "option usage: -prefix OUTPUT_PREFIX\n\n", stderr );
01931                 usage( PROG_NAME, S2V_USE_SHORT );
01932                 RETURN(-1);
01933             }
01934 
01935             opts->oset_file = argv[++ac];
01936         }
01937         else if ( ! strncmp(argv[ac], "-sdata_1D", 9) )
01938         {
01939             if ( (ac+1) >= argc )
01940             {
01941                 fputs( "option usage: -sdata_1D SURF_DATA.1D\n\n", stderr );
01942                 usage( PROG_NAME, S2V_USE_SHORT );
01943                 RETURN(-1);
01944             }
01945 
01946             opts->sdata_file_1D = argv[++ac];
01947         }
01948         else if ( ! strncmp(argv[ac], "-sdata_niml", 9) )
01949         {
01950             if ( (ac+1) >= argc )
01951             {
01952                 fputs( "option usage: -sdata_niml SURF_DATA.niml\n\n", stderr );
01953                 usage( PROG_NAME, S2V_USE_SHORT );
01954                 RETURN(-1);
01955             }
01956 
01957             opts->sdata_file_niml = argv[++ac];
01958         }
01959         else if ( ! strncmp(argv[ac], "-spec", 5) )
01960         {
01961             if ( (ac+1) >= argc )
01962             {
01963                 fputs( "option usage: -spec SPEC_FILE\n\n", stderr );
01964                 usage( PROG_NAME, S2V_USE_SHORT );
01965                 RETURN(-1);
01966             }
01967 
01968             opts->spec_file = argv[++ac];
01969         }
01970         else if ( ! strncmp(argv[ac], "-surf_xyz_1D", 9) )
01971         {
01972             if ( (ac+1) >= argc )
01973             {
01974                 fputs( "option usage: -surf_xyz_1D NODE_FILE\n\n", stderr );
01975                 usage( PROG_NAME, S2V_USE_SHORT );
01976                 RETURN(-1);
01977             }
01978 
01979             opts->surf_xyz_1D_file = argv[++ac];
01980         }
01981         else if ( ! strncmp(argv[ac], "-surf_", 6) )
01982         {
01983             if ( (ac+1) >= argc )
01984             {
01985                 fputs( "option usage: -surf_X SURF_NAME\n\n", stderr );
01986                 usage( PROG_NAME, S2V_USE_SHORT );
01987                 RETURN(-1);
01988             }
01989             ind = argv[ac][6] - 'A';
01990             if ( (ind < 0) || (ind >= S2V_MAX_SURFS) )
01991             {
01992                 fprintf(stderr,"** -surf_X option: '%s' out of range,\n"
01993                         "   use one of '-surf_A' through '-surf_%c'\n",
01994                         argv[ac], 'A'+S2V_MAX_SURFS-1);
01995                 RETURN(-1);
01996             }
01997 
01998             opts->snames[ind] = argv[++ac];
01999         }
02000         else if ( ! strncmp(argv[ac], "-sv", 3) )
02001         {
02002             if ( (ac+1) >= argc )
02003             {
02004                 fputs( "option usage: -sv SURFACE_VOLUME\n\n", stderr );
02005                 usage( PROG_NAME, S2V_USE_SHORT );
02006                 RETURN(-1);
02007             }
02008 
02009             opts->sv_file = argv[++ac];
02010         }
02011         else if ( ! strncmp(argv[ac], "-sxyz_orient_as_gpar", 20) )
02012         {
02013             opts->sxyz_ori_gpar = 1;
02014         }
02015         else if ( ! strncmp(argv[ac], "-version", 2) )
02016         {
02017             usage( PROG_NAME, S2V_USE_VERSION );
02018             RETURN(-1);
02019         }
02020         else     /* invalid option */
02021         {
02022             fprintf( stderr, "invalid option <%s>\n", argv[ac] );
02023             usage( PROG_NAME, S2V_USE_SHORT );
02024             RETURN(-1);
02025         }
02026     }
02027 
02028     if ( opts->debug > 1 )
02029         disp_opts_t ( "++ opts read: ", opts );
02030 
02031     RETURN(0);
02032 }
02033 
02034 /*----------------------------------------------------------------------
02035  * validate_options - fill param struct from options
02036  *
02037  *     - validate datasets
02038  *     - validate surface
02039  *----------------------------------------------------------------------
02040 */
02041 int validate_options ( opts_t * opts, param_t * p )
02042 {
02043 ENTRY("validate_options");
02044 
02045     /* clear param struct - pointer get explicit NULL */
02046     memset( p, 0, sizeof(*p) );
02047     p->gpar         = NULL;    p->oset     = NULL;
02048     p->sxyz_im      = NULL;    p->sdata_im = NULL;
02049     p->parser.pcode = NULL;    p->cmask    = NULL;
02050 
02051     if ( check_map_func( opts->map_str ) == E_SMAP_INVALID )
02052         RETURN(-1);
02053 
02054     if ( validate_datasets( opts, p ) != 0 )
02055         RETURN(-1);
02056 
02057     if ( validate_surface( opts, p ) != 0 )
02058         RETURN(-1);
02059 
02060     if ( opts->data_expr )
02061     {
02062         PARSER_set_printout(1);
02063         p->parser.pcode = PARSER_generate_code( opts->data_expr );
02064         if ( p->parser.pcode == NULL )
02065         {
02066             fprintf(stderr,"** failed to generate code from expression '%s'\n",
02067                     opts->data_expr);
02068             RETURN(-1);
02069         }
02070         PARSER_mark_symbols( p->parser.pcode, p->parser.has_sym );
02071 
02072         if ( opts->debug > 1 )
02073             disp_parser_t( "-- PARSER expr okay: ", &p->parser );
02074     }
02075 
02076     if ( opts->debug > 1 )
02077         disp_param_t( "++ params set: ", p );
02078 
02079     RETURN(0);
02080 }
02081 
02082 
02083 /*----------------------------------------------------------------------
02084  * check_datum_type             - determine type for output dataset
02085  *
02086  * currently allowable types are MRI_byte, MRI_short, MRI_float, MRI_double
02087  *
02088  * return  datum type : on success
02089  *         -1         : on failure (no valid type can be determined)
02090  *----------------------------------------------------------------------
02091 */
02092 int check_datum_type ( char * datum_str, int default_type )
02093 {
02094     int c, dt = -1;
02095     
02096 ENTRY("check_datum_type");
02097 
02098     if ( datum_str )
02099     {
02100         for ( c = 0; c <= MRI_rgba; c++ )
02101             if ( ! strcmp( datum_str, MRI_TYPE_name[c] ) )
02102             {
02103                 dt = c;
02104                 break;
02105             }
02106 
02107         /* if we didn't find the requested type, inform the user and quit */
02108         if ( c > MRI_rgba )
02109         {
02110             fprintf( stderr, "** invalid datum type name '%s'\n",
02111                      datum_str );
02112             RETURN(-1);
02113         }
02114     }
02115     else
02116     {
02117         dt = default_type;
02118     }
02119 
02120     if ( ( dt != MRI_byte   ) &&
02121          ( dt != MRI_short  ) &&
02122          ( dt != MRI_float  ) &&
02123          ( dt != MRI_double ) )
02124     {
02125         fprintf( stderr, "** data type '%s' is not supported\n",
02126                  MRI_TYPE_name[dt] );
02127         RETURN(-1);
02128     }
02129 
02130     RETURN(dt);
02131 }
02132 
02133 
02134 /*----------------------------------------------------------------------
02135  * check_map_func
02136  *
02137  *     - check for map_str
02138  *     - validate the map type
02139  *----------------------------------------------------------------------
02140 */
02141 int check_map_func ( char * map_str )
02142 {
02143     int map;
02144 
02145 ENTRY("check_map_func");
02146 
02147     if ( map_str == NULL )
02148     {
02149         fprintf( stderr, "** missing option: '-map_func FUNCTION'\n" );
02150         RETURN(E_SMAP_INVALID);
02151     }
02152 
02153     map = s2v_map_type( map_str );
02154 
02155     if ( map == E_SMAP_INVALID )
02156     {
02157         fprintf( stderr, "** invalid map string '%s'\n", map_str );
02158         RETURN(-1);
02159     }
02160 
02161     RETURN(map);
02162 }
02163 
02164 
02165 /*----------------------------------------------------------------------
02166  * s2v_map_type - return an E_SMAP_XXX code
02167  *
02168  * on failure, return -1 (E_SMAP_INVALID)
02169  * else        return >0 (a valid map code)
02170  *----------------------------------------------------------------------
02171 */
02172 int s2v_map_type ( char * map_str )
02173 {
02174     s2v_map_num map;
02175 
02176 ENTRY("s2v_map_type");
02177 
02178     if ( map_str == NULL )
02179     {
02180         fprintf( stderr, "** s2v_map_type: missing map_str parameter\n" );
02181         RETURN((int)E_SMAP_INVALID);
02182     }
02183 
02184     if ( sizeof(gs2v_map_names) / sizeof(char *) != (int)E_SMAP_FINAL )
02185     {
02186         fprintf( stderr, "** error:  gs2v_map_names/s2v_map_num mis-match\n");
02187         RETURN((int)E_SMAP_INVALID);
02188     }
02189 
02190     for ( map = E_SMAP_MASK; map < E_SMAP_FINAL; map++ )
02191         if ( !strcmp( map_str, gs2v_map_names[map] ) )
02192             RETURN((int)map);
02193 
02194     RETURN((int)E_SMAP_INVALID);
02195 }
02196 
02197 
02198 /*----------------------------------------------------------------------
02199  * validate_surface
02200  *
02201  * Verify that the user entered options for both the spec file and
02202  * the surface volume (AFNI dataset).
02203  *----------------------------------------------------------------------
02204 */
02205 int validate_surface ( opts_t * opts, param_t * p )
02206 {
02207     int errs = 0;
02208 
02209 ENTRY("validate_surface");
02210 
02211     if ( ! opts->surf_xyz_1D_file )  /* then check the surface input */
02212     {
02213         if ( opts->spec_file == NULL )
02214         {
02215             fprintf( stderr, "** missing '-spec_file SPEC_FILE' option\n" );
02216             errs++;
02217         }
02218 
02219         if ( opts->sv_file == NULL )
02220         {
02221             fprintf( stderr, "** missing '-sv SURF_VOL' option\n" );
02222             errs++;
02223         }
02224 
02225         if ( opts->snames[0] == NULL )
02226         {
02227             fprintf( stderr, "** missing '-surf_A SURF_NAME' option\n" );
02228             errs++;
02229         }
02230     }
02231     else if ( opts->spec_file != NULL )
02232     {
02233         fprintf(stderr,
02234                 "** cannot use both spec and xyz surface files, %s and %s\n",
02235                 opts->spec_file, opts->surf_xyz_1D_file);
02236         errs++;
02237     }
02238 
02239     if ( opts->sdata_file_1D && opts->sdata_file_niml )
02240     {
02241         fprintf(stderr,"** cannot use both NIML and 1D surface files\n");
02242         errs++;
02243     }
02244 
02245     /* rcr - hopefully this will disappear someday */
02246     if ( opts->sdata_file_niml )
02247     {
02248         fprintf(stderr,"** sorry, the niml feature is coming soon...\n");
02249         errs++;
02250     }
02251 
02252     if ( errs > 0 )
02253         RETURN(-1);
02254 
02255     RETURN(0);
02256 }
02257 
02258 /*----------------------------------------------------------------------
02259  * validate_datasets
02260  *
02261  * Note that we do not validate the SURFACE_VOLUME AFNI dataset here.
02262  * That is done in SUMA_LoadSpec_eng().
02263  *
02264  * Verify the AFNI dataset used for value output.
02265  * Check for a cmask dataset and command.
02266  * Verify that AFNI dataset and the mask have the same size.
02267  *----------------------------------------------------------------------
02268 */
02269 int validate_datasets( opts_t * opts, param_t * p )
02270 {
02271 ENTRY("validate_datasets");
02272 
02273     p->gpar = THD_open_dataset( opts->gpar_file );
02274 
02275     if ( !ISVALID_DSET(p->gpar) )
02276     {
02277         if ( opts->gpar_file == NULL )
02278             fprintf( stderr, "** error: missing '-grid_parent DSET' option\n" );
02279         else
02280             fprintf( stderr, "** error: invalid input dataset '%s'\n",
02281                      opts->gpar_file);
02282         RETURN(-1);
02283     }
02284     else if ( DSET_BRICK_TYPE(p->gpar, 0) == MRI_complex )
02285     {
02286         fprintf(stderr,
02287                 "** failure: cannot deal with complex-valued dataset, '%s'\n",
02288                 opts->gpar_file);
02289         RETURN(-1);
02290     }
02291 
02292     p->nvox = DSET_NVOX( p->gpar );
02293     set_3dmm_bounds( p->gpar, &p->f3mm_min, &p->f3mm_max );
02294 
02295     if ( ! THD_filename_ok( opts->oset_file ) )
02296     {
02297         fprintf( stderr, "** illegal output prefix: '%s'\n",
02298                  opts->oset_file ? opts->oset_file : "<none>" );
02299         RETURN(-1);
02300     }
02301 
02302     /* -------------------------------------------------------------------- */
02303     /* check for cmask - casually stolen from 3dmaskdump.c (thanks, Bob! :) */
02304 
02305     if ( opts->cmask_cmd != NULL )
02306     {
02307         int    clen = strlen( opts->cmask_cmd );
02308         char * cmd;
02309 
02310         /* save original cmask command, as EDT_calcmask() is destructive */
02311         cmd = (char *)malloc((clen + 1) * sizeof(char));
02312         strcpy( cmd, opts->cmask_cmd );
02313 
02314         p->cmask = EDT_calcmask( cmd, &p->ncmask );
02315 
02316         free( cmd );                       /* free EDT_calcmask() string */
02317 
02318         if ( p->cmask == NULL )
02319         {
02320             fprintf( stderr, "** failure: cannot compute mask from option:\n"
02321                      "   -cmask '%s'\n", opts->cmask_cmd );
02322             RETURN(-1);
02323         }
02324         if ( p->ncmask != p->nvox )
02325         {
02326             fprintf( stderr, "** error: input and cmask datasets do not have "
02327                      "the same dimensions\n" );
02328             RETURN(-1);
02329         }
02330         if ( ( p->ccount = THD_countmask( p->ncmask, p->cmask ) ) <= 0 )
02331         {
02332             fprintf( stderr, "** Warning!  No voxels in computed cmask!\n" );
02333             /* return -1;   continue, and let the user deal with it...  */
02334         }
02335     }
02336 
02337     if ( opts->debug > 0 )
02338     {
02339         fprintf( stderr, "++ input dset has nvox = %d, nvals = %d",
02340                  p->nvox, DSET_NVALS(p->gpar) );
02341         if ( p->cmask == NULL )
02342             fputc( '\n', stderr );
02343         else
02344             fprintf( stderr, " (%d voxels in mask)\n", p->ccount );
02345     }
02346 
02347     RETURN(0);
02348 }
02349 
02350 /*----------------------------------------------------------------------
02351  * usage  -  output usage information
02352  *
02353  * S2V_USE_SHORT        - display brief output
02354  * S2V_USE_LONG         - display long output
02355  * S2V_USE_VERSION      - show the VERSION of the program
02356  *----------------------------------------------------------------------
02357 */
02358 int usage ( char * prog, int level )
02359 {
02360 ENTRY("usage");
02361 
02362     if ( level == S2V_USE_SHORT )
02363         fprintf(stderr,
02364                 "  usage: %s [options] -spec SPEC_FILE -surf_A SURF_NAME \\\n"
02365                 "             -grid_parent AFNI_DSET -sv SURF_VOL \\\n"
02366                 "             -map_func MAP_FUNC -prefix OUTPUT_DSET\n"
02367                 "usage: %s -help\n",
02368                  prog, prog );
02369     else if ( level == S2V_USE_LONG )
02370     {
02371         printf(
02372             "\n"
02373             "%s - map data from a surface domain to an AFNI volume domain\n"
02374             "\n"
02375             "  usage: %s [options] -spec SPEC_FILE -surf_A SURF_NAME \\\n"
02376             "             -grid_parent AFNI_DSET -sv SURF_VOL \\\n"
02377             "             -map_func MAP_FUNC -prefix OUTPUT_DSET\n"
02378             "\n"
02379             "    This program is meant to take as input a pair of surfaces,\n"
02380             "    optionally including surface data, and an AFNI grid parent\n"
02381             "    dataset, and to output a new AFNI dataset consisting of the\n"
02382             "    surface data mapped to the dataset grid space.  The mapping\n"
02383             "    function determines how to map the surface values from many\n"
02384             "    nodes to a single voxel.\n"
02385             "\n"
02386             "    Surfaces (from the spec file) are specified using '-surf_A'\n"
02387             "    (and '-surf_B', if a second surface is input).  If two\n"
02388             "    surfaces are input, then the computed segments over node\n"
02389             "    pairs will be in the direction from surface A to surface B.\n"
02390             "\n"
02391             "    The basic form of the algorithm is:\n"
02392             "\n"
02393             "       o for each node pair (or single node)\n"
02394             "           o form a segment based on the xyz node coordinates,\n"
02395             "             adjusted by any '-f_pX_XX' options\n"
02396             "           o divide the segment up into N steps, according to \n"
02397             "             the '-f_steps' option\n"
02398             "           o for each segment point\n"
02399             "               o if the point is outside the space of the output\n"
02400             "                 dataset, skip it\n"
02401             "               o locate the voxel in the output dataset which\n"
02402             "                 corresponds to this segment point\n"
02403             "               o if the '-cmask' option was given, and the voxel\n"
02404             "                 is outside the implied mask, skip it\n"
02405             "               o if the '-f_index' option is by voxel, and this\n"
02406             "                 voxel has already been considered, skip it\n"
02407             "               o insert the surface node value, according to the\n"
02408             "                 user-specified '-map_func' option\n"
02409             "\n"
02410             "  Surface Coordinates:\n"
02411             "\n"
02412             "      Surface coordinates are assumed to be in the Dicom\n"
02413             "      orientation.  This information may come from the option\n"
02414             "      pair of '-spec' and '-sv', with which the user provides\n"
02415             "      the name of the SPEC FILE and the SURFACE VOLUME, along\n"
02416             "      with '-surf_A' and optionally '-surf_B', used to specify\n"
02417             "      actual surfaces by name.  Alternatively, the surface\n"
02418             "      coordinates may come from the '-surf_xyz_1D' option.\n"
02419             "      See these option descriptions below.\n"
02420             "\n"
02421             "      Note that the user must provide either the three options\n"
02422             "      '-spec', '-sv' and '-surf_A', or the single option,\n"
02423             "      '-surf_xyz_1D'.\n"
02424             "\n"
02425             "  Surface Data:\n"
02426             "\n"
02427             "      Surface domain data can be input via the '-sdata_1D'\n"
02428             "      option.  In such a case, the data is with respect to the\n"
02429             "      input surface.  The first column of the sdata_1D file\n"
02430             "      should be a node index, and following columns are that\n"
02431             "      node's data.  See the '-sdata_1D' option for more info.\n"
02432             "\n"
02433             "      If the surfaces have V values per node (pair), then the\n"
02434             "      resulting AFNI dataset will have V sub-bricks (unless the\n"
02435             "      user applies the '-data_expr' option).\n"
02436             "\n"
02437             "  Mapping Functions:\n"
02438             "\n"
02439             "      Mapping functions exist because a single volume voxel may\n"
02440             "      be occupied by multiple surface nodes or segment points.\n"
02441             "      Depending on how dense the surface mesh is, the number of\n"
02442             "      steps provided by the '-f_steps' option, and the indexing\n"
02443             "      type from '-f_index', even a voxel which is only 1 cubic\n"
02444             "      mm in volume may have quite a few contributing points.\n"
02445             "\n"
02446             "      The mapping function defines how multiple surface values\n"
02447             "      are combined to get a single result in each voxel.  For\n"
02448             "      example, the 'max' function will take the maximum of all\n"
02449             "      surface values contributing to each given voxel.\n"
02450             "\n"
02451             "      Current mapping functions are listed under the '-map_func'\n"
02452             "      option, below.\n"
02453             "\n"
02454             "------------------------------------------------------------\n"
02455             "\n"
02456             "  examples:\n"
02457             "\n"
02458             "    1. Map a single surface to an anatomical volume domain,\n"
02459             "       creating a simple mask of the surface.  The output\n"
02460             "       dataset will be fred_surf+orig, and the orientation and\n"
02461             "       grid spacing will follow that of the grid parent.  The\n"
02462             "       output voxels will be 1 where the surface exists, and 0\n"
02463             "       elsewhere.\n"
02464             "\n"
02465             "    %s                       \\\n"
02466             "       -spec         fred.spec                \\\n"
02467             "       -surf_A       pial                     \\\n"
02468             "       -sv           fred_anat+orig           \\\n"
02469             "       -grid_parent  fred_anat+orig           \\\n"
02470             "       -map_func     mask                     \\\n"
02471             "       -prefix       fred_surf\n"
02472             "\n"
02473             "    2. Map the cortical grey ribbon (between the white matter\n"
02474             "       surface and the pial surface) to an AFNI volume, where\n"
02475             "       the resulting volume is restriced to the mask implied by\n"
02476             "       the -cmask option.\n"
02477             "\n"
02478             "       Surface data will come from the file sdata_10.1D, which\n"
02479             "       has 10 values per node, and lists only a portion of the\n"
02480             "       entire set of surface nodes.  Each node pair will be form\n"
02481             "       a segment of 15 equally spaced points, the values from\n"
02482             "       which will be applied to the output dataset according to\n"
02483             "       the 'ave' filter.  Since the index is over points, each\n"
02484             "       of the 15 points will have its value applied to the\n"
02485             "       appropriate voxel, even multiple times.  This weights the\n"
02486             "       resulting average by the fraction of each segment that\n"
02487             "       occupies a given voxel.\n"
02488             "\n"
02489             "       The output dataset will have 10 sub-bricks, according to\n"
02490             "       the 10 values per node index in sdata_10.1D.\n"
02491             "\n"
02492             "    %s                       \\\n"
02493             "       -spec         fred.spec                               \\\n"
02494             "       -surf_A       smoothwm                                \\\n"
02495             "       -surf_B       pial                                    \\\n"
02496             "       -sv           fred_anat+orig                          \\\n"
02497             "       -grid_parent 'fred_func+orig[0]'                      \\\n"
02498             "       -cmask       '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
02499             "       -sdata_1D     sdata_10.1D                             \\\n"
02500             "       -map_func     ave                                     \\\n"
02501             "       -f_steps      15                                      \\\n"
02502             "       -f_index      points                                  \\\n"
02503             "       -prefix       fred_surf_ave\n"
02504             "\n"
02505             "    3. The inputs in this example are identical to those in\n"
02506             "       example 2, including the surface dataset, sdata_10.1D.\n"
02507             "       Again, the output dataset will have 10 sub-bricks.\n"
02508             "\n"
02509             "       The surface values will be applied via the 'max_abs'\n"
02510             "       filter, with the intention of assigning to each voxel the\n"
02511             "       node value with the most significance.  Here, the index\n"
02512             "       method does not matter, so it is left as the default,\n"
02513             "       'voxel'.\n"
02514             "\n"
02515             "       In this example, each node pair segment will be extended\n"
02516             "       by 20%% into the white matter, and by 10%% outside of the\n"
02517             "       grey matter, generating a \"thicker\" result.\n"
02518             "\n"
02519             "    %s                       \\\n"
02520             "       -spec         fred.spec                               \\\n"
02521             "       -surf_A       smoothwm                                \\\n"
02522             "       -surf_B       pial                                    \\\n"
02523             "       -sv           fred_anat+orig                          \\\n"
02524             "       -grid_parent 'fred_func+orig[0]'                      \\\n"
02525             "       -cmask       '-a fred_func+orig[2] -expr step(a-0.6)' \\\n"
02526             "       -sdata_1D     sdata_10.1D                             \\\n"
02527             "       -map_func     max_abs                                 \\\n"
02528             "       -f_steps      15                                      \\\n"
02529             "       -f_p1_fr      -0.2                                    \\\n"
02530             "       -f_pn_fr       0.1                                    \\\n"
02531             "       -prefix       fred_surf_max_abs\n"
02532             "\n"
02533             "    4. This is simliar to example 2.  Here, the surface nodes\n"
02534             "       (coordinates) come from 'surf_coords_2.1D'.  But these\n"
02535             "       coordinates do not happen to be in Dicomm orientation,\n"
02536             "       they are in the same orientation as the grid parent, so\n"
02537             "       the '-sxyz_orient_as_gpar' option is applied.\n"
02538             "\n"
02539             "       Even though the data comes from 'sdata_10.1D', the output\n"
02540             "       AFNI dataset will only have 1 sub-brick.  That is because\n"
02541             "       of the '-data_expr' option.  Here, each applied surface\n"
02542             "       value will be the average of the sines of the first 3\n"
02543             "       data values (columns of sdata_10.1D).\n"
02544             "\n"
02545             "    %s                       \\\n"
02546             "       -surf_xyz_1D  surf_coords_2.1D                        \\\n"
02547             "       -sxyz_orient_as_gpar                                  \\\n"
02548             "       -grid_parent 'fred_func+orig[0]'                      \\\n"
02549             "       -sdata_1D     sdata_10.1D                             \\\n"
02550             "       -data_expr   '(sin(a)+sin(b)+sin(c))/3'               \\\n"
02551             "       -map_func     ave                                     \\\n"
02552             "       -f_steps      15                                      \\\n"
02553             "       -f_index      points                                  \\\n"
02554             "       -prefix       fred_surf_ave_sine\n"
02555             "\n"
02556             "    5. In this example, voxels will get the maximum value from\n"
02557             "       column 3 of sdata_10.1D (as usual, column 0 is used for\n"
02558             "       node indices).  The output dataset will have 1 sub-brick.\n"
02559             "\n"
02560             "       Here, the output dataset is forced to be of type 'short',\n"
02561             "       regardless of what the grid parent is.  Also, there will\n"
02562             "       be no scaling factor applied.\n"
02563             "\n"
02564             "       To track the numbers for surface node #1234, the '-dnode'\n"
02565             "       option has been used, along with '-debug'.  Additionally,\n"
02566             "       '-dvoxel' is used to track the results for voxel #6789.\n"
02567             "\n"
02568             "    %s                       \\\n"
02569             "       -spec         fred.spec                               \\\n"
02570             "       -surf_A       smoothwm                                \\\n"
02571             "       -surf_B       pial                                    \\\n"
02572             "       -sv           fred_anat+orig                          \\\n"
02573             "       -grid_parent 'fred_func+orig[0]'                      \\\n"
02574             "       -sdata_1D     sdata_10.1D'[0,3]'                      \\\n"
02575             "       -map_func     max                                     \\\n"
02576             "       -f_steps      15                                      \\\n"
02577             "       -datum        short                                   \\\n"
02578             "       -noscale                                              \\\n"
02579             "       -debug        2                                       \\\n"
02580             "       -dnode        1234                                    \\\n"
02581             "       -dvoxel       6789                                    \\\n"
02582             "       -prefix       fred_surf_max\n"
02583             "\n"
02584             "------------------------------------------------------------\n"
02585             "\n"
02586             "  REQUIRED COMMAND ARGUMENTS:\n"
02587             "\n"
02588             "    -spec SPEC_FILE        : SUMA spec file\n"
02589             "\n"
02590             "        e.g. -spec fred.spec\n"
02591             "\n"
02592             "        The surface specification file contains the list of\n"
02593             "        mappable surfaces that are used.\n"
02594             "\n"
02595             "        See @SUMA_Make_Spec_FS and @SUMA_Make_Spec_SF.\n"
02596             "\n"
02597             "        Note: this option, along with '-sv', may be replaced\n"
02598             "              by the '-surf_xyz_1D' option.\n"
02599             "\n"
02600             "    -surf_A SURF_NAME      : specify surface A (from spec file)\n"
02601             "    -surf_B SURF_NAME      : specify surface B (from spec file)\n"
02602             "\n"
02603             "        e.g. -surf_A smoothwm\n"
02604             "        e.g. -surf_A lh.smoothwm\n"
02605             "        e.g. -surf_B lh.pial\n"
02606             "\n"
02607             "        This parameter is used to tell the program with surfaces\n"
02608             "        to use.  The '-surf_A' parameter is required, but the\n"
02609             "        '-surf_B' parameter is an option.\n"
02610             "\n"
02611             "        The surface names must uniquely match those in the spec\n"
02612             "        file, though a sub-string match is good enough.  The\n"
02613             "        surface names are compared with the names of the surface\n"
02614             "        node coordinate files.\n"
02615             "\n"
02616             "        For instance, given a spec file that has only the left\n"
02617             "        hemisphere in it, 'pial' should produce a unique match\n"
02618             "        with lh.pial.asc.  But if both hemispheres are included,\n"
02619             "        then 'pial' would not be unique (matching rh.pail.asc,\n"
02620             "        also).  In that case, 'lh.pial' would be better.\n"
02621             "\n"
02622             "    -sv SURFACE_VOLUME     : AFNI dataset\n"
02623             "\n"
02624             "        e.g. -sv fred_anat+orig\n"
02625             "\n"
02626             "        This is the AFNI dataset that the surface is mapped to.\n"
02627             "        This dataset is used for the initial surface node to xyz\n"
02628             "        coordinate mapping, in the Dicom orientation.\n"
02629             "\n"
02630             "        Note: this option, along with '-spec', may be replaced\n"
02631             "              by the '-surf_xyz_1D' option.\n"
02632             "\n"
02633             "    -surf_xyz_1D SXYZ_NODE_FILE : 1D coordinate file\n"
02634             "\n"
02635             "        e.g. -surf_xyz_1D my_surf_coords.1D\n"
02636             "\n"
02637             "        This ascii file contains a list of xyz coordinates to be\n"
02638             "        considered as a surface, or 2 sets of xyz coordinates to\n"
02639             "        considered as a surface pair.  As usual, these points\n"
02640             "        are assumed to be in Dicom orientation.  Another option\n"
02641             "        for coordinate orientation is to use that of the grid\n"
02642             "        parent dataset.  See '-sxyz_orient_as_gpar' for details.\n"
02643             "\n"
02644             "        This option is an alternative to the pair of options, \n"
02645             "        '-spec' and '-sv'.\n"
02646             "\n"
02647             "        The number of rows of the file should equal the number\n"
02648             "        of nodes on each surface.  The number of columns should\n"
02649             "        be either 3 for a single surface, or 6 for two surfaces.\n"
02650             "        \n"
02651             "        sample line of an input file (one surface):\n"
02652             "        \n"
02653             "        11.970287  2.850751  90.896111\n"
02654             "        \n"
02655             "        sample line of an input file (two surfaces):\n"
02656             "        \n"
02657             "        11.97  2.85  90.90    12.97  2.63  91.45\n"
02658             "        \n"
02659             "\n"
02660             "    -grid_parent AFNI_DSET : AFNI dataset\n"
02661             "\n"
02662             "        e.g. -grid_parent fred_function+orig\n"
02663             "\n"
02664             "        This dataset is used as a grid and orientation master\n"
02665             "        for the output AFNI dataset.\n"
02666             "\n"
02667             "    -map_func MAP_FUNC     : surface to dataset function\n"
02668             "\n"
02669             "        e.g. -map_func max\n"
02670             "        e.g. -map_func mask -f_steps 20\n"
02671             "\n"
02672             "        This function applies to the case where multiple data\n"
02673             "        points get mapped to a single voxel, which is expected\n"
02674             "        since surfaces tend to have a much higher resolution\n"
02675             "        than AFNI volumes.  In the general case data points come\n"
02676             "        from each point on each partitioned line segment, with\n"
02677             "        one segment per node pair.  Note that these segments may\n"
02678             "        have length zero, such as when only a single surface is\n"
02679             "        input.\n"
02680             "\n"
02681             "        See \"Mapping Functions\" above, for more information.\n"
02682             "\n"
02683             "        The current mapping function for one surface is:\n"
02684             "\n"
02685             "          mask   : For each xyz location, set the corresponding\n"
02686             "                   voxel to 1.\n"
02687             "\n"
02688             "        The current mapping functions for two surfaces are as\n"
02689             "        follows.  These descriptions are per output voxel, and\n"
02690             "        over the values of all points mapped to a given voxel.\n"
02691             "\n"
02692             "          mask2  : if any points are mapped to the voxel, set\n"
02693             "                   the voxel value to 1\n"
02694             "\n"
02695             "          ave    : average all values\n"
02696             "\n"
02697             "          count  : count the number of mapped data points\n"
02698             "\n"
02699             "          min    : find the minimum value from all mapped points\n"
02700             "\n"
02701             "          max    : find the maximum value from all mapped points\n"
02702             "\n"
02703             "          max_abs: find the number with maximum absolute value\n"
02704             "                   (the resulting value will retain its sign)\n"
02705             "\n"
02706             "    -prefix OUTPUT_PREFIX  : prefix for the output dataset\n"
02707             "\n"
02708             "        e.g. -prefix anat_surf_mask\n"
02709             "\n"
02710             "        This is used to specify the prefix of the resulting AFNI\n"
02711             "        dataset.\n"
02712             "\n"
02713             "  ------------------------------\n"
02714             "  SUB-SURFACE DATA FILE OPTIONS:\n"
02715             "\n"
02716             "    -sdata_1D SURF_DATA.1D : 1D sub-surface file, with data\n"
02717             "\n"
02718             "        e.g. -sdata_1D roi3.1D\n"
02719             "\n"
02720             "        This is used to specify a 1D file, which contains\n"
02721             "        surface indices and data.  The indices refer to the\n"
02722             "        surface(s) read from the spec file.\n"
02723             "        \n"
02724             "        The format of this data file is a surface index and a\n"
02725             "        list of data values on each row.  To be a valid 1D file,\n"
02726             "        each row must have the same number of columns.\n"
02727             "\n"
02728             "  ------------------------------\n"
02729             "  OPTIONS SPECIFIC TO SEGMENT SELECTION:\n"
02730             "\n"
02731             "    (see \"The basic form of the algorithm\" for more details)\n"
02732             "\n"
02733             "    -f_steps NUM_STEPS     : partition segments\n"
02734             "\n"
02735             "        e.g. -f_steps 10\n"
02736             "        default: -f_steps 2   (or 1, the number of surfaces)\n"
02737             "\n"
02738             "        This option specifies the number of points to divide\n"
02739             "        each line segment into, before mapping the points to the\n"
02740             "        AFNI volume domain.  The default is the number of input\n"
02741             "        surfaces (usually, 2).  The default operation is to have\n"
02742             "        the segment endpoints be the actual surface nodes,\n"
02743             "        unless they are altered with the -f_pX_XX options.\n"
02744             "\n"
02745             "    -f_index TYPE          : index by points or voxels\n"
02746             "\n"
02747             "        e.g. -f_index points\n"
02748             "        e.g. -f_index voxels\n"
02749             "        default: -f_index voxels\n"
02750             "\n"
02751             "        Along a single segment, the default operation is to\n"
02752             "        apply only those points mapping to a new voxel.  The\n"
02753             "        effect of the default is that a given voxel will have\n"
02754             "        at most one value applied per voxel pair.\n"
02755             "\n"
02756             "        If the user applies this option with 'points' or 'nodes'\n"
02757             "        as the argument, then every point along the segment will\n"
02758             "        be applied.  This may be preferred if, for example, the\n"
02759             "        user wishes to have the average weighted by the number\n"
02760             "        of points occupying a voxel, not just the number of node\n"
02761             "        pair segments.\n"
02762             "\n"
02763             "    Note: the following -f_pX_XX options are used to alter the\n"
02764             "          locations of the segment endpoints, per node pair.\n"
02765             "          The segments are directed, from the node on the first\n"
02766             "          surface to the node on the second surface.  To modify\n"
02767             "          the first endpoint, use a -f_p1_XX option, and use\n"
02768             "          -f_pn_XX to modify the second.\n"
02769             "\n"
02770             "    -f_p1_fr FRACTION      : offset p1 by a length fraction\n"
02771             "\n"
02772             "        e.g. -f_p1_fr -0.2\n"
02773             "        e.g. -f_p1_fr -0.2  -f_pn_fr 0.2\n"
02774             "\n"
02775             "        This option moves the first endpoint, p1, by a distance\n"
02776             "        of the FRACTION times the original segment length.  If\n"
02777             "        the FRACTION is positive, it moves in the direction of\n"
02778             "        the second endpoint, pn.\n"
02779             "\n"
02780             "        In the example, p1 is moved by 20%% away from pn, which\n"
02781             "        will increase the length of each segment.\n"
02782             "\n"
02783             "    -f_pn_fr FRACTION      : offset pn by a length fraction\n"
02784             "\n"
02785             "        e.g. -f_pn_fr  0.2\n"
02786             "        e.g. -f_p1_fr -0.2  -f_pn_fr 0.2\n"
02787             "\n"
02788             "        This option moves pn by a distance of the FRACTION times\n"
02789             "        the original segment length, in the direction from p1 to\n"
02790             "        pn.  So a positive fraction extends the segment, and a\n"
02791             "        negative fraction reduces it.\n"
02792             "\n"
02793             "        In the example above, using 0.2 adds 20%% to the segment\n"
02794             "        length past the original pn.\n"
02795             "\n"
02796             "    -f_p1_mm DISTANCE      : offset p1 by a distance in mm.\n"
02797             "\n"
02798             "        e.g. -f_p1_mm -1.0\n"
02799             "        e.g. -f_p1_mm -1.0  -f_pn_fr 1.0\n"
02800             "\n"
02801             "        This option moves p1 by DISTANCE mm., in the direction\n"
02802             "        of pn.  If the DISTANCE is positive, the segment gets\n"
02803             "        shorter.  If DISTANCE is negative, the segment will get\n"
02804             "        longer.\n"
02805             "\n"
02806             "        In the example, p1 is moved away from pn, extending the\n"
02807             "        segment by 1 millimeter.\n"
02808             "\n"
02809             "    -f_pn_mm DISTANCE      : offset pn by a distance in mm.\n"
02810             "\n"
02811             "        e.g. -f_pn_mm  1.0\n"
02812             "        e.g. -f_p1_mm -1.0  -f_pn_fr 1.0\n"
02813             "\n"
02814             "        This option moves pn by DISTANCE mm., in the direction\n"
02815             "        from the first point to the second.  So if DISTANCE is\n"
02816             "        positive, the segment will get longer.  If DISTANCE is\n"
02817             "        negative, the segment will get shorter.\n"
02818             "\n"
02819             "        In the example, pn is moved 1 millimeter farther from\n"
02820             "        p1, extending the segment by that distance.\n"
02821             "\n"
02822             "  ------------------------------\n"
02823             "  GENERAL OPTIONS:\n"
02824             "\n"
02825             "    -cmask MASK_COMMAND    : command for dataset mask\n"
02826             "\n"
02827             "        e.g. -cmask '-a fred_func+orig[2] -expr step(a-0.8)'\n"
02828             "\n"
02829             "        This option will produce a mask to be applied to the\n"
02830             "        output dataset.  Note that this mask should form a\n"
02831             "        single sub-brick.\n"
02832             "\n"
02833             "        This option follows the style of 3dmaskdump (since the\n"
02834             "        code for it was, uh, borrowed from there (thanks Bob!)).\n"
02835             "\n"
02836             "        See '3dmaskdump -help' for more information.\n"
02837             "\n"
02838             "    -data_expr EXPRESSION  : apply expression to surface input\n"
02839             "\n"
02840             "        e.g. -data_expr 17\n"
02841             "        e.g. -data_expr '(a+b+c+d)/4'\n"
02842             "        e.g. -data_expr '(sin(a)+sin(b))/2'\n"
02843             "\n"
02844             "        This expression is applied to the list of data values\n"
02845             "        from the surface data file input via '-sdata_1D'.  The\n"
02846             "        expression is applied for each node or node pair, to the\n"
02847             "        list of data values corresponding to that node.\n"
02848             "\n"
02849             "        The letters 'a' through 'z' may be used as input, and\n"
02850             "        refer to columns 1 through 26 of the data file (where\n"
02851             "        column 0 is a surface node index).  The data file must\n"
02852             "        have enough columns to support the expression.  Is is\n"
02853             "        valid to have a constant expression without a data file.\n"
02854             "\n"
02855             "    -datum DTYPE           : set data type in output dataset\n"
02856             "\n"
02857             "        e.g. -datum short\n"
02858             "        default: same as that of grid parent\n"
02859             "\n"
02860             "        This option specifies the data type for the output AFNI\n"
02861             "        dataset.  Valid choices are byte, short and float, which\n"
02862             "        are 1, 2 and 4 bytes for each data point, respectively.\n"
02863             "\n"
02864             "    -debug LEVEL           : verbose output\n"
02865             "\n"
02866             "        e.g. -debug 2\n"
02867             "\n"
02868             "        This option is used to print out status information \n"
02869             "        during the execution of the program.  Current levels are\n"
02870             "        from 0 to 5.\n"
02871             "\n"
02872             "    -dnode DEBUG_NODE      : extra output for that node\n"
02873             "\n"
02874             "        e.g. -dnode 123456\n"
02875             "\n"
02876             "        This option requests additional debug output for the\n"
02877             "        given surface node.  This index is with respect to the\n"
02878             "        input surface (included in the spec file, or through the\n"
02879             "        '-surf_xyz_1D' option).\n"
02880             "\n"
02881             "        This will have no effect without the '-debug' option.\n"
02882             "\n"
02883             "    -dvoxel DEBUG_VOXEL    : extra output for that voxel\n"
02884             "\n"
02885             "        e.g. -dvoxel 234567\n"
02886             "\n"
02887             "        This option requests additional debug output for the\n"
02888             "        given volume voxel.  This 1-D index is with respect to\n"
02889             "        the output AFNI dataset.  One good way to find a voxel\n"
02890             "        index to supply is from output via the '-dnode' option.\n"
02891             "\n"
02892             "        This will have no effect without the '-debug' option.\n"
02893             "\n"
02894             "    -hist                  : show revision history\n"
02895             "\n"
02896             "        Display module history over time.\n"
02897             "\n"
02898             "    -help                  : show this help\n"
02899             "\n"
02900             "        If you can't get help here, please get help somewhere.\n"
02901             "\n"
02902             "    -noscale               : no scale factor in output dataset\n"
02903             "\n"
02904             "        If the output dataset is an integer type (byte, shorts\n"
02905             "        or ints), then the output dataset may end up with a\n"
02906             "        scale factor attached (see 3dcalc -help).  With this\n"
02907             "        option, the output dataset will not be scaled.\n"
02908             "\n"
02909             "    -sxyz_orient_as_gpar   : assume gpar orientation for sxyz\n"
02910             "\n"
02911             "        This option specifies that the surface coordinate points\n"
02912             "        in the '-surf_xyz_1D' option file have the orientation\n"
02913             "        of the grid parent dataset.\n"
02914             "\n"
02915             "        When the '-surf_xyz_1D' option is applied the surface\n"
02916             "        coordinates are assumed to be in Dicom orientation, by\n"
02917             "        default.  This '-sxyz_orient_as_gpar' option overrides\n"
02918             "        the Dicom default, specifying that the node coordinates\n"
02919             "        are in the same orientation as the grid parent dataset.\n"
02920             "\n"
02921             "        See the '-surf_xyz_1D' option for more information.\n"
02922             "\n"
02923             "    -version               : show version information\n"
02924             "\n"
02925             "        Show version and compile date.\n"
02926             "\n"
02927             "------------------------------------------------------------\n"
02928             "\n"
02929             "  Author: R. Reynolds  - %s\n"
02930             "\n"
02931             "                (many thanks to Z. Saad and R.W. Cox)\n"
02932             "\n",
02933             prog, prog,
02934             prog, prog, prog, prog, prog,
02935             VERSION );
02936     }
02937     else if ( level == S2V_USE_HIST )
02938         fputs(g_history, stdout);
02939     else if ( level == S2V_USE_VERSION )
02940         printf( "%s : %s, compile date: %s\n", prog, VERSION, __DATE__ );
02941     else
02942         fprintf( stderr, "usage called with illegal level <%d>\n", level );
02943 
02944     RETURN(-1);
02945 }
02946 
02947 
02948 /*----------------------------------------------------------------------
02949  * disp_opts_t  -  display the contents of the opts_t struct
02950  *----------------------------------------------------------------------
02951 */
02952 int disp_opts_t ( char * info, opts_t * opts )
02953 {
02954 ENTRY("disp_opts_t");
02955 
02956     if ( info )
02957         fputs( info, stderr );
02958 
02959     if ( opts == NULL )
02960     {
02961         fprintf(stderr, "disp_opts_t: opts == NULL\n" );
02962         RETURN(-1);
02963     }
02964 
02965     fprintf(stderr,
02966             "options struct at %p :\n"
02967             "    gpar_file          = %s\n"
02968             "    oset_file          = %s\n"
02969             "    spec_file          = %s\n"
02970             "    sv_file            = %s\n"
02971             "    surf_xyz_1D_file   = %s\n"
02972             "    sdata_file_1D      = %s\n"
02973             "    sdata_file_niml    = %s\n"
02974             "    cmask_cmd          = %s\n"
02975             "    data_expr          = %s\n"
02976             "    map_str            = %s\n"
02977             "    datum_str          = %s\n"
02978             "    f_index_str        = %s\n"
02979             "    sxyz_ori_gpar      = %d\n"
02980             "    debug, dnode, dvox = %d, %d, %d\n"
02981             "    noscale, f_steps   = %d, %d\n"
02982             "    f_p1_fr, f_pn_fr   = %f, %f\n"
02983             "    f_p1_mm, f_pn_mm   = %f, %f\n"
02984             , opts,
02985             CHECK_NULL_STR(opts->gpar_file), CHECK_NULL_STR(opts->oset_file),
02986             CHECK_NULL_STR(opts->spec_file), CHECK_NULL_STR(opts->sv_file),
02987             CHECK_NULL_STR(opts->surf_xyz_1D_file),
02988             CHECK_NULL_STR(opts->sdata_file_1D),
02989             CHECK_NULL_STR(opts->sdata_file_niml),
02990             CHECK_NULL_STR(opts->cmask_cmd), CHECK_NULL_STR(opts->data_expr),
02991             CHECK_NULL_STR(opts->map_str), CHECK_NULL_STR(opts->datum_str),
02992             CHECK_NULL_STR(opts->f_index_str), opts->sxyz_ori_gpar,
02993             opts->debug, opts->dnode, opts->dvox, opts->noscale, opts->f_steps,
02994             opts->f_p1_fr, opts->f_pn_fr, opts->f_p1_mm, opts->f_pn_mm
02995             );
02996 
02997     RETURN(0);
02998 }
02999 
03000 
03001 /*----------------------------------------------------------------------
03002  * disp_param_t  -  display the contents of the param_t struct
03003  *----------------------------------------------------------------------
03004 */
03005 int disp_param_t ( char * info, param_t * p )
03006 {
03007 ENTRY("disp_param_t");
03008 
03009     if ( info )
03010         fputs( info, stderr );
03011 
03012     if ( p == NULL )
03013     {
03014         fprintf(stderr,"disp_param_t: p == NULL\n");
03015         RETURN(-1);
03016     }
03017 
03018     fprintf(stderr,
03019             "param_t struct at %p :\n"
03020             "    gpar  : vcheck    = %p : %s\n"
03021             "    oset  : vcheck    = %p : %s\n"
03022             "    sxyz_im, sdata_im = %p, %p\n"
03023             "    f3mm_min (xyz)    = (%f, %f, %f)\n"
03024             "    f3mm_max (xyz)    = (%f, %f, %f)\n"
03025             "    nvox, nsubs       = %d, %d\n"
03026             "    cmask             = %p\n"
03027             "    ncmask, ccount    = %d, %d\n"
03028             , p,
03029             p->gpar, ISVALID_DSET(p->gpar) ? "valid" : "invalid",
03030             p->oset, ISVALID_DSET(p->oset) ? "valid" : "invalid",
03031             p->sxyz_im, p->sdata_im,
03032             p->f3mm_min.xyz[0], p->f3mm_min.xyz[1], p->f3mm_min.xyz[2],
03033             p->f3mm_max.xyz[0], p->f3mm_max.xyz[1], p->f3mm_max.xyz[2],
03034             p->nvox, p->nsubs, p->cmask, p->ncmask, p->ccount
03035             );
03036 
03037     RETURN(0);
03038 }
03039 
03040 
03041 /*----------------------------------------------------------------------
03042  * disp_node_list_t  -  display the contents of the node_list_t struct
03043  *----------------------------------------------------------------------
03044 */
03045 int disp_node_list_t ( char * info, node_list_t * d )
03046 {
03047 ENTRY("disp_node_list_t");
03048 
03049     if ( info )
03050         fputs( info, stderr );
03051 
03052     if ( d == NULL )
03053     {
03054         fprintf(stderr,"disp_node_list_t: d == NULL\n");
03055         RETURN(-1);
03056     }
03057 
03058     fprintf(stderr,
03059             "node_list_t struct at %p :\n"
03060             "    nodes         = %p\n"
03061             "    depth, nnodes = %d, %d\n"
03062             "    fdata, ilist  = %p, %p\n"
03063             "    ilen          = %d\n"
03064             , d,
03065             d->nodes, d->depth, d->nnodes,
03066             d->fdata, d->ilist, d->ilen
03067             );
03068 
03069     RETURN(0);
03070 }
03071 
03072 
03073 /*----------------------------------------------------------------------
03074  * disp_s2v_opts_t  -  display the contents of the s2v_opts_t struct
03075  *----------------------------------------------------------------------
03076 */
03077 int disp_s2v_opts_t ( char * info, s2v_opts_t * sopt )
03078 {
03079 ENTRY("disp_s2v_opts_t");
03080 
03081     if ( info )
03082         fputs( info, stderr );
03083 
03084     if ( sopt == NULL )
03085     {
03086         fprintf(stderr,"disp_s2v_opts_t: sopt == NULL\n" );
03087         RETURN(-1);
03088     }
03089 
03090     fprintf(stderr,
03091             "s2v_opts_t struct at %p :\n"
03092             "    map, datum, noscale = %d, %d, %d\n"
03093             "    debug, dnode, dvox  = %d, %d, %d\n"
03094             "    sxyz_ori_gpar       = %d\n"
03095             "    cmask               = %p\n"
03096             "    f_steps, f_index    = %d, %d\n"
03097             "    f_p1_fr, f_pn_fr    = %f, %f\n"
03098             "    f_p1_mm, f_pn_mm    = %f, %f\n"
03099             , sopt,
03100             sopt->map, sopt->datum, sopt->noscale,
03101             sopt->debug, sopt->dnode, sopt->dvox, sopt->sxyz_ori_gpar,
03102             sopt->cmask, sopt->f_steps, sopt->f_index,
03103             sopt->f_p1_fr, sopt->f_pn_fr, sopt->f_p1_mm, sopt->f_pn_mm 
03104             );
03105 
03106     RETURN(0);
03107 }
03108 
03109 
03110 /*----------------------------------------------------------------------
03111  * disp_parser_t  -  display the contents of the parser_t struct
03112  *----------------------------------------------------------------------
03113 */
03114 int disp_parser_t ( char * info, parser_t * d )
03115 {
03116     int c;
03117 
03118 ENTRY("disp_parser_t");
03119 
03120     if ( info )
03121         fputs( info, stderr );
03122 
03123     if ( d == NULL )
03124     {
03125         fprintf(stderr,"disp_parser_t: d == NULL\n" );
03126         RETURN(-1);
03127     }
03128 
03129     fprintf(stderr, "parser_t struct at %p :\n"
03130                     "    pcode    = %p\n"
03131                     "    max_sym  = %d\n",
03132                     d, d->pcode, d->max_sym );
03133 
03134     if ( d->pcode )
03135     {
03136         fprintf(stderr, "    num_code = %d\n"
03137                         "    c_code   = %s\n",
03138                 d->pcode->num_code, d->pcode->c_code );
03139 
03140         fprintf(stderr, "    has_sym  =");
03141         for ( c = 0; c < 26; c++ )
03142             fprintf(stderr, " %d", d->has_sym[c]);
03143         fputc('\n', stderr);
03144     }
03145 
03146     RETURN(0);
03147 }
03148 
03149 
03150 /*----------------------------------------------------------------------
03151  * set_3dmm_bounds       - note 3dmm bounding values            - v1.2
03152  *
03153  * This is an outer bounding box, like FOV, not SLAB.
03154  *----------------------------------------------------------------------
03155 */
03156 int set_3dmm_bounds ( THD_3dim_dataset *dset, THD_fvec3 *min, THD_fvec3 *max)
03157 {
03158     float tmp;
03159     int   c;
03160 
03161 ENTRY("set_3dmm_bounds");
03162 
03163     if ( !dset || !min || !max )
03164     {
03165         fprintf(stderr, "** invalid params to set_3dmm_bounds: (%p,%p,%p)\n",
03166                 dset, min, max );
03167         RETURN(-1);
03168     }
03169 
03170     /* get undirected bounds */
03171     min->xyz[0] = DSET_XORG(dset) - 0.5 * DSET_DX(dset);
03172     max->xyz[0] = min->xyz[0] + DSET_NX(dset) * DSET_DX(dset);
03173 
03174     min->xyz[1] = DSET_YORG(dset) - 0.5 * DSET_DY(dset);
03175     max->xyz[1] = min->xyz[1] + DSET_NY(dset) * DSET_DY(dset);
03176 
03177     min->xyz[2] = DSET_ZORG(dset) - 0.5 * DSET_DZ(dset);
03178     max->xyz[2] = min->xyz[2] + DSET_NZ(dset) * DSET_DZ(dset);
03179 
03180     for ( c = 0; c < 3; c++ )
03181         if ( min->xyz[c] > max->xyz[c] )
03182         {
03183             tmp = min->xyz[c];
03184             min->xyz[c] = max->xyz[c];
03185             max->xyz[c] = tmp;
03186         }
03187 
03188     RETURN(0);
03189 }
03190 
03191 /*----------------------------------------------------------------------
03192  * dist_f3mm            - return Euclidean distance between the points
03193  *                      - v1.2
03194  *----------------------------------------------------------------------
03195  */
03196 float dist_f3mm( THD_fvec3 * p1, THD_fvec3 * p2 )
03197 {
03198     double d0, d1, d2;
03199 
03200 ENTRY("dist_f3mm");
03201 
03202     if ( p1 == NULL || p2 == NULL )
03203     {
03204         fprintf( stderr, "** dist_f3mm: invalid params (%p,%p)\n", p1, p2 );
03205         RETURN(0.0);
03206     }
03207 
03208     d0 = p1->xyz[0] - p2->xyz[0];
03209     d1 = p1->xyz[1] - p2->xyz[1];
03210     d2 = p1->xyz[2] - p2->xyz[2];
03211 
03212     RETURN(sqrt(d0*d0 + d1*d1 + d2*d2));
03213 }
03214 
03215 
03216 /*----------------------------------------------------------------------
03217  * f3mm_out_of_bounds    - check wether cp is between min and max
03218  *                       - v1.2 [rickr]
03219  *----------------------------------------------------------------------
03220 */
03221 int f3mm_out_of_bounds( THD_fvec3 * cp, THD_fvec3 * min, THD_fvec3 * max )
03222 {
03223     int c;
03224 
03225 ENTRY("f3mm_out_of_bounds");
03226 
03227     if ( !cp || !min || !max )
03228         RETURN(-1);
03229 
03230     for ( c = 0; c < 3; c++ )
03231     {
03232         if ( ( cp->xyz[c] < min->xyz[c] ) ||
03233              ( cp->xyz[c] > max->xyz[c] ) )
03234             RETURN(-1);
03235     }
03236 
03237     RETURN(0);
03238 }
03239 
03240 
03241 
03242 /*----------------------------------------------------------------------
03243  * integral_doubles      - are all double values integral?
03244  *----------------------------------------------------------------------
03245 */
03246 int integral_doubles( double * dp, int nvals )
03247 {
03248 ENTRY("integral_doubles");
03249 
03250     while ( nvals > 0 )
03251     {
03252         if ( ((double)(int)*dp) != *dp )
03253             RETURN(0);
03254 
03255         dp++;
03256         nvals--;
03257     }
03258 
03259     RETURN(1);
03260 }
03261 
 

Powered by Plone

This site conforms to the following standards: