00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
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 
00133 
00134 
00135 
00136 
00137 #include "mrilib.h"
00138 #include "parser.h"
00139 #include "SUMA_suma.h"
00140 #include "SUMA_3dSurf2Vol.h"
00141 
00142 
00143 SUMA_SurfaceViewer * SUMAg_SVv = NULL;  
00144 int                  SUMAg_N_SVv = 0;   
00145 SUMA_DO            * SUMAg_DOv = NULL;  
00146 int                  SUMAg_N_DOv = 0;   
00147 SUMA_CommonFields  * SUMAg_CF = NULL;   
00148 
00149 
00150 char * gs2v_map_names[] = { "none", "mask", "mask2", "ave", "count",
00151                             "min", "max", "max_abs" };
00152 
00153 
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     
00174     if ( ( ret_val = init_options(&opts, argc, argv) ) != 0 )
00175         return ret_val;
00176 
00177     if ( ( ret_val = validate_options(&opts, ¶ms) ) != 0 )
00178         return ret_val;
00179 
00180     if ( (ret_val = set_smap_opts( &opts, ¶ms, &sopt )) != 0 )
00181         return ret_val;
00182 
00183     
00184     ret_val = read_surf_files(&opts, ¶ms, &spec, &sopt, &node_list);
00185 
00186     if ( ret_val == 0 )
00187         ret_val = write_output( &sopt, &opts, ¶ms, &node_list, argc, argv );
00188 
00189     
00190     final_clean_up( &node_list );
00191 
00192     return ret_val;
00193 }
00194 
00195 
00196 
00197 
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 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
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     
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     
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     
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     
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     
00321     for ( sub = 0; sub < p->nsubs; sub++ )
00322     {
00323         valid = 0;
00324 
00325         
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         
00335         memset(cdata, 0, nvox*sizeof(int));
00336         memset(ddata, 0, nvox*sizeof(double));
00337 
00338         
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 )  
00353         {
00354             free( ddata );
00355             free( vdata );
00356             DSET_delete( dout );
00357             RETURN(NULL);
00358         }
00359 
00360         
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         
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] )      
00373                 fac = MRI_TYPE_maxval[sopt->datum]/amax;
00374             else if ( integral_doubles( ddata, nvox ) )  
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         
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 
00403 
00404 
00405 
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;               
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         
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 ) 
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 );        
00463 
00464         
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         
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 
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             
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 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
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 )    
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         
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 
00624 
00625 
00626 
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;               
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]++;          
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 
00705 
00706 
00707 
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 
00742 
00743 
00744 
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     
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 )     
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 
00813 
00814 
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     
00834     if ( !p->sdata_im )
00835     {
00836         fval = 1.0;     
00837 
00838         
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     
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 )             
00871     {
00872         fprintf(stderr,"** snld error: cannot use parser with col = %d\n", col);
00873         RETURN(-1);
00874     }
00875 
00876     
00877 
00878     fp = MRI_FLOAT_PTR( p->sdata_im ) + col+1;  
00879 
00880     for ( c = 0; c < N->ilen; c++ )
00881     {
00882         if ( p->parser.pcode )
00883         {
00884             
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 
00902 
00903 
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));     
00919     N->nodes = NULL;  N->fdata = NULL;  N->ilist = NULL;
00920 
00921     nsurf = SUMAg_N_DOv;        
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           
00929 
00930     if ( sopt->map == E_SMAP_MASK )
00931         nsurf = 1;
00932     else
00933     {
00934         
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 )         
00952         fprintf(stderr,"++ node list initialized\n");
00953 
00954     RETURN(rv);
00955 }
00956 
00957 
00958 
00959 
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;      
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 
01048 
01049 
01050 
01051 
01052 
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     
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     
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     
01099 
01100     fvp = N->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 
01134 
01135 
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 )       
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 
01192 
01193 
01194 
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) );   
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;  
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 )             
01223     {
01224         
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) ) ) 
01241         sopt->f_index = S2V_F_INDEX_POINT;
01242 
01243     sopt->f_p1_fr = opts->f_p1_fr;         
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 
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     
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     
01332     if ( (rv = init_node_list(opts, p, sopt, N)) != 0 )
01333         RETURN(rv);
01334 
01335     
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 
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 )     
01369     {
01370         fprintf(stderr,"** bad sxyz file '%s'?\n", opts->surf_xyz_1D_file);
01371         RETURN(-1);
01372     }
01373 
01374     
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 
01388 
01389 
01390 
01391 
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;               
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 
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     
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++;         
01455     p->parser.max_sym = max_used;
01456 
01457     
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 
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     
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     
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 
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     
01562     for ( c = 0; c < N->ilen; c++ )
01563         N->ilist[c] = c;
01564 
01565     RETURN(0);
01566 }
01567 
01568 
01569 
01570 
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     
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     
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     
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;                          
01617 
01618     RETURN(0);
01619 }
01620 
01621 
01622 
01623 
01624 
01625 
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     
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     
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     
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     
01703     if (SUMA_LoadSpec_eng(spec,SUMAg_DOv,&SUMAg_N_DOv,opts->sv_file,debug,
01704              SUMAg_CF->DsetList) == 0)     
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 
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     
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;                   
01745     opts->dvox  = -1;                   
01746 
01747     for ( ac = 1; ac < argc; ac++ )
01748     {
01749         
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) )  
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];     
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     
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 
02036 
02037 
02038 
02039 
02040 
02041 int validate_options ( opts_t * opts, param_t * p )
02042 {
02043 ENTRY("validate_options");
02044 
02045     
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 
02085 
02086 
02087 
02088 
02089 
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         
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 
02136 
02137 
02138 
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 
02167 
02168 
02169 
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 
02200 
02201 
02202 
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 )  
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     
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 
02260 
02261 
02262 
02263 
02264 
02265 
02266 
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     
02304 
02305     if ( opts->cmask_cmd != NULL )
02306     {
02307         int    clen = strlen( opts->cmask_cmd );
02308         char * cmd;
02309 
02310         
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 );                       
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             
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 
02352 
02353 
02354 
02355 
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 
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 
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 
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 
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 
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 
03152 
03153 
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     
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 
03193 
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 
03218 
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 
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