1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "to3d.h"
8 /*#define DEBUG_PRINT 1*/
9 
10 extern void mri_read_dicom_reset_obliquity();
11 extern void mri_read_dicom_get_obliquity(float *);
12 extern void Obliquity_to_coords(THD_3dim_dataset *);
13 static void T3D_reverse_list(int, char **);
14 
15 #define LABEL_ARG(str) \
16   XtVaTypedArg , XmNlabelString , XmRString , (str) , strlen(str)+1
17 
18 #define NZBOT 1 /* min number of slices (1 or 2) [09 Aug 2001] */
19 
20 /*------------------ global variables: so shoot me ---------------------*/
21 
22 static int mri_float_convert_ushort( MRI_IMAGE * fim );
23 static to3d_widget_set wset ;
24 static to3d_data       user_inputs ;
25 
26 static THD_3dim_dataset * dset    = NULL ;
27 static THD_datablock    * dblk    = NULL ;
28 static THD_dataxes      * daxes   = NULL ;
29 static THD_diskptr      * dkptr   = NULL ;
30 static THD_marker_set   * markers = NULL ;
31 static THD_string_array * imnames = NULL ;  /* name for each slice */
32 
33 static int outliers_checked = 0 ;     /* 15 Aug 2001 */
34 static char * outliers_fname = NULL ; /* 26 Aug 2001 */
35 
36 static int     Argc , First_Image_Arg = 1 ;
37 static char ** Argv ;
38 static char *  dbrick = NULL ;  /* global image data array */
39 static int     geomparent_loaded = 0 ;
40 static int     geometry_loaded   = 0 ;
41 
42 static int     negative_shorts   = 0 ;  /* 19 Jan 2000 */
43 static int     nvox_total        = 0 ;  /* 24 Aug 2001 */
44 static int     nfloat_err        = 0 ;  /* 14 Sep 1999 */
45 
46 static float   imdx=0.0, imdy=0.0, imdz=0.0 ;  /* 05 Feb 2001 */
47 
48 static float   zpad=0 ;                        /* 05 Feb 2001 */
49 static int     zpad_mm=0 ;
50 
51 static float   zoff ;                          /* 10 May 2001 */
52 static int     use_zoff=0 ;
53 
54 static int     af_type_set=0 ;                 /* 20 Dec 2001 */
55 
56 static int     use_oblique_origin = 0;         /* 01 Dec 2008 */
57 static int     reverse_list = 0;               /* 04 Dec 2008 */
58 static int     ushort2float = 0;               /* 09 Jul 2013 [rickr] */
59 
60 /*** additions of Mar 2, 1995 ***/
61 
62 static struct {
63    int ncolor ;       /* -ncolor # */
64    float gamma ;      /* -gamma #  */
65    RwcBoolean xtwarns ;  /* -xtwarns  */
66    float gsfac ;      /* -gsfac    */
67    int   datum_all ;  /* -datum    */
68 
69    int delay_input ;  /* -in:1     */
70 
71    int editing ;      /* -edit     */
72 
73    int swap_two , swap_four ;  /* 14 Sep 1998 */
74 
75    int nofloatscan ;           /* 14 Sep 1999 */
76 
77    int swap_eight ;            /* 06 Feb 2003 */
78 
79    int quit_if_bad;            /* 25 Nov 2011 */
80 
81 } argopt  ;
82 
83 /*----------------------------------------------------------------------*/
84 static char * FALLback[] =
85   {   "AFNI*fontList:        9x15bold=charset1" ,
86       "AFNI*background:      gray30"            ,
87       "AFNI*menu*background: gray20"            ,
88       "AFNI*borderColor:     gray30"            ,
89       "AFNI*foreground:      yellow"            ,
90       "AFNI*borderWidth:     0"                 ,
91       "AFNI*troughColor:     green"             ,
92       "AFNI*XmLabel.translations: #override<Btn2Down>:" ,
93       "AFNI*help*background:      black"                ,
94       "AFNI*help*foreground:      yellow"               ,
95       "AFNI*cluefont:             9x15bold"             ,
96       "AFNI*help*waitPeriod:      1066"                 ,
97       "AFNI*help*cancelWaitPeriod: 50"                  ,
98       "AFNI*XmList.translations: #override"                /* 24 Feb 2007 */
99            "<Btn4Down>: ListPrevItem()\\n"
100            "<Btn5Down>: ListNextItem()"                  ,
101       "AFNI*XmText.translations: #override"
102            "<Btn4Down>: previous-line()\\n"
103            "<Btn5Down>: next-line()"                     ,
104 #if 0
105       "AFNI*XmScrollBar.translations: #augment"
106            "<Btn4Down>: IncrementUpOrLeft(0)\\n"
107            "<Btn5Down>: IncrementDownOrRight(0)" ,
108 #else
109       "AFNI*XmScrollBar.translations: #augment"
110            "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
111            "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
112 #endif
113    NULL } ;
114 /*-----------------------------------------------------------------------*/
115 
116 /*-----------------------------------------------------------------------
117    This routine is used to hide the Xt warnings.
118    It simply does nothing -- it replaces the default Xt warning handler.
119 -------------------------------------------------------------------------*/
120 
AFNI_handler(char * msg)121 void AFNI_handler(char * msg){}
122 
123 #define CURSOR_normalize                               \
124   do{ NORMAL_cursorize(wset.topshell) ;                \
125       XSync( XtDisplay(wset.topshell), False ) ;       \
126       XmUpdateDisplay( wset.topshell ) ; } while(0)
127 
128 #define CURSOR_watchize                                \
129   do{ WATCH_cursorize(wset.topshell) ;                 \
130       XSync( XtDisplay(wset.topshell), False ) ;       \
131       XmUpdateDisplay( wset.topshell ) ; } while(0)
132 
AFNI_startup_timeout_CB(XtPointer client_data,XtIntervalId * id)133 void AFNI_startup_timeout_CB( XtPointer client_data , XtIntervalId * id )
134 {
135    char msg[512] ;
136 
137    MCW_help_CB(NULL,NULL,NULL) ;
138    CURSOR_normalize ;
139 
140    if( negative_shorts          /* 19 Jan 2000 */
141         && ! AFNI_yesenv("AFNI_NO_NEGATIVES_WARNING")
142         && ! ushort2float ){    /*  9 Jul 2013 [rickr] */
143       float perc = (100.0*negative_shorts)/nvox_total ;
144       sprintf(msg , " \n"
145                     " to3d WARNING: %d negative voxels (%g%%)\n"
146                     "               were read in images of shorts.\n"
147                     "               It is possible the input\n"
148                     "               images need byte-swapping\n"
149                     "               (consider -ushort2float)\n\n"
150                     " ** I recommend that you View Images. **\n" ,
151               negative_shorts , perc ) ;
152 
153       (void) MCW_popup_message( wset.anatomy_parent_label , msg ,
154                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
155    }
156 
157    if( nfloat_err ){ /* 20 Jan 2000 */
158       sprintf(msg , " \n"
159                     " to3d WARNING: %d errors in floating point images\n"
160                     "               were detected.  It is possible that\n"
161                     "               the inputs need to be 4swap-ed, or\n"
162                     "               otherwise repaired.\n \n"
163                     " ** Erroneous values have been replaced by   **\n"
164                     " ** zeros. I recommend that you View Images. **\n" ,
165               nfloat_err ) ;
166 
167       (void) MCW_popup_message( wset.geometry_parent_label , msg ,
168                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
169    }
170 
171    if( user_inputs.ntt > 5 ){                 /* 15 Aug 2001 */
172       dset->taxis = myXtNew( THD_timeaxis ) ;
173       dset->taxis->ntt = user_inputs.ntt ;
174       T3D_check_outliers(0) ; outliers_checked = 1 ;
175       myXtFree(dset->taxis) ;
176    }
177 }
178 
179 /*-----------------------------------------------------------------------*/
180 
181 static char * commandline = NULL ;  /* for History */
182 
main(int argc,char * argv[])183 int main( int argc , char * argv[] )
184 {
185    XtAppContext   app ;
186    XtErrorHandler old_handler ;
187    RwcBoolean        all_good ;
188    mainENTRY("to3d:main") ;
189    machdep() ; /* 20 Apr 2001 */
190    PRINT_VERSION("to3d") ; AUTHOR("RW Cox") ;
191    INFO_message("It is best to use to3d via the Dimon program.") ;
192 
193    if( DBG_trace ){                              /* 10 Sep 2002 */
194 #ifdef ALLOW_MCW_MALLOC
195      INFO_message("Enabling mcw_malloc()") ;
196      enable_mcw_malloc() ;
197 #endif
198    }
199 
200    /* read the user data from the command line, if any */
201 
202    wset.topshell = NULL ;  /* flag that X has yet to start */
203    wset.good     = 0 ;
204 
205    /* initialize defaults for command line arguments
206       that aren't related to dataset construction    */
207 
208    INIT_ngray       = NGRAY ;
209    INIT_gamma       = GAMMA ;
210    INIT_fov         = 240.0 ;
211    argopt.ncolor    = -1 ;
212    argopt.gamma     = -1.0 ;
213    argopt.xtwarns   = False ;         /* don't show Xt warnings */
214    argopt.gsfac     = 0.0 ;           /* no global scaling factor */
215    argopt.datum_all = ILLEGAL_TYPE ;  /* use first image type */
216 
217    argopt.delay_input = FALSE ;
218    argopt.editing     = FALSE ;
219 
220    argopt.swap_two = argopt.swap_four = 0 ;  /* 14 Sep 1998 */
221    argopt.swap_eight = 0 ;                   /* 06 Feb 2003 */
222 
223    argopt.nofloatscan = 0 ;                  /* 14 Sep 1999 */
224    argopt.quit_if_bad = 0 ;
225    /* read the inputs */
226 
227    /*-- 20 Apr 2001: addto the arglist, if user wants to --*/
228 
229    { int new_argc ; char ** new_argv ;
230      addto_args( argc , argv , &new_argc , &new_argv ) ;
231      if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; }
232    }
233 
234    Argc = argc ; Argv = argv ;
235 
236    T3D_initialize_user_data() ;
237    THD_check_AFNI_version("to3d") ;
238 
239    if( user_inputs.nosave ){
240      printf("++ Opening X11 now") ; fflush(stdout) ;
241      wset.topshell = XtVaAppInitialize( &app , "AFNI" , NULL , 0 ,
242                                         &argc , argv , FALLback , NULL ) ;
243      printf("..opened\n") ;
244    }
245 
246    T3D_read_images() ;
247 
248    if( negative_shorts && ! ushort2float ){
249       float perc = (100.0*negative_shorts)/nvox_total ;
250       fprintf(stderr,
251        "++ to3d WARNING: %d negative voxels (%g%%) were read in images of shorts.\n"
252        "++               It is possible the input images need byte-swapping.\n"
253                         "Consider also -ushort2float.\n",
254        negative_shorts , perc ) ;
255    }
256 
257    if( strlen(user_inputs.geometry_parent_filename) > 0 )
258       T3D_geometry_parent_CB( NULL , NULL , NULL ) ;
259 
260    if( strlen(user_inputs.anatomy_parent_filename) > 0 )
261       T3D_anatomy_parent_CB( NULL , NULL , NULL ) ;
262 
263    /* 05 Feb 2001: [10 May 2001: moved up above auto-save]
264       if geometry not loaded at all, maybe use globals imdx, etc. */
265 
266    if( ! (geomparent_loaded || geometry_loaded) ){
267       if( imdx <= 0.0 || imdy <= 0.0 ){
268 
269 STATUS("setting default FOV") ;
270 
271          user_inputs.fov = INIT_fov ;    /* the old code */
272 
273       } else {                           /* the new code */
274          float size ;
275 
276 STATUS("setting voxel size from imdx, etc.") ;
277 
278          user_inputs.xsize = imdx ;
279          user_inputs.ysize = imdy ;
280          if( imdz > 0.0 ) user_inputs.zsize = imdz ;
281 
282          /* 10 May 2001: make sure axes are centered */
283 
284          size = 0.5 * (user_inputs.nx-1) * user_inputs.xsize ;
285          user_inputs.xorigin = size ;
286 
287          size = 0.5 * (user_inputs.ny-1) * user_inputs.ysize ;
288          user_inputs.yorigin = size ;
289 
290          size = 0.5 * (user_inputs.nz-1) * user_inputs.zsize ;
291          user_inputs.zorigin = size ;
292 
293          user_inputs.xyz_centered = (XCENTERED|YCENTERED|ZCENTERED) ;
294 
295          /* adjust voxel shape flag (for widget initialization) */
296 
297          if( user_inputs.xsize != user_inputs.ysize ){
298             user_inputs.voxshape = VOXSHAPE_IRREGULAR ;
299          } else {
300             if( user_inputs.xsize != user_inputs.zsize ){
301                user_inputs.voxshape = VOXSHAPE_SQUARE ;
302             } else {
303                user_inputs.voxshape = VOXSHAPE_CUBICAL ;
304             }
305          }
306          user_inputs.fov = user_inputs.xsize * user_inputs.nx ;
307       }
308 
309       /* 12 Mar 2001: MRILIB_ global variables may contain useful info */
310 
311       if( MRILIB_orients[0] != '\0'                  &&
312           user_inputs.xorient == user_inputs.yorient &&
313           user_inputs.xorient == user_inputs.zorient   ){
314 
315          char acod ; int icod ;
316 
317 STATUS("setting orientation from MRILIB_orients") ;
318 
319          acod=toupper(MRILIB_orients[0]); icod=ORCODE(acod); if(icod >= 0) user_inputs.xorient=icod;
320          acod=toupper(MRILIB_orients[2]); icod=ORCODE(acod); if(icod >= 0) user_inputs.yorient=icod;
321          acod=toupper(MRILIB_orients[4]); icod=ORCODE(acod); if(icod >= 0) user_inputs.zorient=icod;
322 
323          if( use_MRILIB_zoff ){                     /* use offset to voxel center from mri_read() */
324             if( fabs(user_inputs.zorigin-MRILIB_zoff) > 0.01 ){
325               user_inputs.zorigin = MRILIB_zoff ;
326               user_inputs.xyz_centered &= ~ZCENTERED ;
327             }
328          }
329 
330          if( use_MRILIB_xoff ){                     /* 20 Dec 2001 */
331             if( fabs(user_inputs.xorigin-MRILIB_xoff) > 0.01 ){
332               user_inputs.xorigin = MRILIB_xoff ;
333               user_inputs.xyz_centered &= ~XCENTERED ;
334             }
335          }
336 
337          if( use_MRILIB_yoff ){                     /* 20 Dec 2001 */
338             if( fabs(user_inputs.yorigin-MRILIB_yoff) > 0.01 ){
339               user_inputs.yorigin = MRILIB_yoff ;
340               user_inputs.xyz_centered &= ~YCENTERED ;
341             }
342          }
343       }
344 
345       /* 27 Jan 2006: use_MRILIB_dicom_matrix ?? */
346 
347       if( use_MRILIB_dicom_matrix ){
348         mat44 nmat ; int icod,jcod,kcod ;
349 
350         nmat = MRILIB_dicom_matrix ; XYINVERT_MAT44(nmat) ;
351         nifti_mat44_to_orientation( nmat , &icod, &jcod, &kcod ) ;
352         if( icod > 0 && jcod > 0 && kcod > 0 ){
353           static int orient_nifti2afni[7] =
354             { -1 , ORI_L2R_TYPE, ORI_R2L_TYPE, ORI_P2A_TYPE,
355                    ORI_A2P_TYPE, ORI_I2S_TYPE, ORI_S2I_TYPE } ;
356 
357           user_inputs.xorient = orient_nifti2afni[icod] ;
358           user_inputs.yorient = orient_nifti2afni[jcod] ;
359           user_inputs.zorient = orient_nifti2afni[kcod] ;
360 DUMP_MAT44("MRILIB_dicom_matrix",MRILIB_dicom_matrix) ;
361         }
362       }
363 
364       /* 10 May 2001: use global zoff, if given [will override MRILIB_zoff] */
365 
366       if( use_zoff ){
367         user_inputs.zorigin = zoff ;
368         user_inputs.xyz_centered &= ~ZCENTERED ;
369       }
370    }
371 
372    all_good = T3D_check_data( False ) ;
373 
374    /** Mar 1997: if any FOV or SLAB command line inputs are used,
375                  then require that they all be given.            **/
376    /** Jun 2014: but only if given axis has nvals > 1    [rickr] **/
377 
378    if( all_good ){
379       /* allow for none specified, yet some computed, as in for JPEG input */
380       int iii =  (user_inputs.xincode > 0)
381                + (user_inputs.yincode > 0)
382                + (user_inputs.zincode > 0) ;
383       /* so if somthing is specified, each must be, or be of length 1 */
384       /*                                          23 Apr 2020 [rickr] */
385       if ( iii > 0 )
386           iii =  (user_inputs.xincode > 0 || user_inputs.nx == 1 )
387                + (user_inputs.yincode > 0 || user_inputs.ny == 1 )
388                + (user_inputs.zincode > 0 || user_inputs.nz == 1 ) ;
389 
390       if( iii > 0 && iii < 3 ) all_good = False ;
391    }
392 
393    /* 03 Dec 2001: MRILIB_tr may have TR */
394 
395    if( user_inputs.ntt > 1 && MRILIB_tr > 0.0 ){
396       if( user_inputs.TR <= 0.0 ){
397          int ii ;
398          user_inputs.TR     = MRILIB_tr ;
399          user_inputs.tunits = UNITS_SEC_TYPE ;
400          if( user_inputs.tpattern != NULL ){
401            /* if no g_siemens_times use, scale tpattern by TR   13 Apr 2011 */
402            if( user_inputs.tpattern[0] != -666.0 ) {
403               for( ii=0 ; ii < user_inputs.nzz ; ii++ ){
404                 user_inputs.tpattern[ii] *= MRILIB_tr ;
405               }
406            }
407          }
408          printf("++ Setting TR=%gs from image header\n",MRILIB_tr) ;
409 
410       } else {
411          printf("++ Command line TR=%g%s ; Images TR=%gs\n",
412                 user_inputs.TR,UNITS_TYPE_LABEL(user_inputs.tunits),MRILIB_tr) ;
413       }
414    }
415    if( user_inputs.ntt > 1 && user_inputs.TR <= 0.0 ){
416      printf("++ Setting TR=1s by default\n") ;
417      user_inputs.TR = 1.0 ; user_inputs.tunits = UNITS_SEC_TYPE ;
418    }
419 
420    /* now that MRILIB_tr has been applied, check for use of siemens slice
421     * timing                                          13 Apr 2011 [rickr] */
422    if( user_inputs.ntt && user_inputs.tpattern
423                        && user_inputs.tpattern[0] == -666.0 ) {
424       int ii;
425       /* if Siemens times exist, use them */
426       if( valid_g_siemens_times(user_inputs.nzz, user_inputs.TR, 0, 2) ) {
427          for( ii=0; ii < user_inputs.nzz ; ii++ )
428             user_inputs.tpattern[ii] = g_siemens_timing_times[ii];
429       } /* else all_good = False;  cannot be fixed in GUI, just whine */
430    }
431 
432    if( all_good && !user_inputs.nosave ){      /* done! */
433      T3D_save_file_CB( NULL , NULL , NULL ) ;
434      printf("++ 3D dataset written to disk\n") ;
435      exit(0) ;
436    }
437 
438    if ( !all_good && argopt.quit_if_bad) {
439       ERROR_message (
440          "Something is wrong with the command line or the input images.\n"
441          "to3d kept from going into interactive mode by option -quit_on_err.\n");
442       exit(1);
443    }
444    /* Otherwise, initialize X11 and Xt */
445 
446    printf("++ Making widgets") ; fflush(stdout) ;
447 
448    if( wset.topshell == NULL )
449      wset.topshell = XtVaAppInitialize( &app , "AFNI" , NULL , 0 ,
450                                         &argc , argv , FALLback , NULL ) ;
451 
452    AFNI_load_defaults( wset.topshell ) ;
453    if( argopt.ncolor <= 2   ) argopt.ncolor = INIT_ngray ;
454    if( argopt.gamma  <= 0.0 ) argopt.gamma  = INIT_gamma ;
455 
456    if( argopt.xtwarns == False )
457       old_handler = XtAppSetWarningHandler(app,AFNI_handler) ;  /* turn off */
458 
459    if( MCW_isitmwm(wset.topshell) ){
460       XtVaSetValues( wset.topshell ,
461                         XmNmwmDecorations ,
462                         MWM_DECOR_ALL | MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE ,
463                      NULL ) ;
464 
465       /* turn off Drag-n-Drop (courtesy the Motif FAQ) */
466 
467       XtVaSetValues( XmGetXmDisplay(XtDisplay(wset.topshell)) ,
468                         XmNdragInitiatorProtocolStyle , XmDRAG_NONE ,
469                         XmNdragReceiverProtocolStyle  , XmDRAG_NONE ,
470                      NULL ) ;
471    }
472 
473    /* make the rest of the widgets */
474 
475    T3D_create_widgets() ;
476    MCW_help_CB(wset.topshell,NULL,NULL) ;  /* initialize help widget */
477 
478    printf("\n") ; fflush(stdout) ;
479 
480    if( AFNI_noenv("AFNI_HINTS") ) MCW_hint_toggle() ;
481 
482    /* let the user do the rest */
483 
484    (void) XtAppAddTimeOut( app , 999 , AFNI_startup_timeout_CB , NULL ) ;
485    XtAppMainLoop(app) ;
486    exit(0) ;
487 }
488 
489 /*---------------------------------------------------------------------*/
490 
T3D_create_widgets(void)491 void T3D_create_widgets(void)
492 {
493 ENTRY("T3D_create_widgets") ;
494    wset.dc  = MCW_new_DC( wset.topshell, argopt.ncolor,
495                           NCOLOVR,FD_colovr,FD_colovr, argopt.gamma , 0 );
496    wset.seq = NULL ;  /* no viewing open now */
497 
498    /*---- form to hold all widgets ----*/
499 
500    wset.topform = XtVaCreateWidget(
501                      "dialog" , xmFormWidgetClass , wset.topshell ,
502                          XmNborderWidth , 0 ,
503 #if 1
504                          XmNtraversalOn , True  ,
505 #endif
506                      NULL ) ;
507 
508    MCW_register_help( wset.topform ,
509                       "I weep for Adonais--he is dead!\n"
510                       "Oh, weep for Adonais! though our tears\n"
511                       "Thaw not the frost which binds so dear a head!\n"
512                       "And thou, sad Hour, selected from all years\n"
513                       "To mourn our loss, rouse thy obscure compeers,\n"
514                       "And teach them thine own sorrow, say: 'With me\n"
515                       "Died Adonais; till the Future dares\n"
516                       "Forget the Past, his fate and fame shall be\n"
517                       "An echo and a light unto eternity!'"
518                     ) ;
519 
520    /*---- 3 arrowvals for orientation ----*/
521 
522    wset.xorient_av = new_MCW_arrowval(
523                       wset.topform ,                     /* parent */
524                       "x orientation\n(across screen)" , /* label */
525                       MCW_AV_downup ,                    /* arrows */
526                       FIRST_ORIENT_TYPE ,                /* min */
527                       LAST_ORIENT_TYPE ,                 /* max */
528                       user_inputs.xorient ,              /* init */
529                       MCW_AV_readtext ,                  /* text */
530                       0 ,                                /* decimals */
531                       T3D_orient_av_CB , NULL ,          /* callback */
532                       T3D_text_display ,                 /* text maker */
533                       ORIENT_typestr                     /* and data */
534                      ) ;
535 
536    XtVaSetValues( wset.xorient_av->wrowcol ,
537                      XmNleftAttachment , XmATTACH_FORM ,
538                      XmNleftOffset     , T3D_FORM_SPACING ,
539                      XmNtopAttachment  , XmATTACH_FORM ,
540                      XmNtopOffset      , T3D_FORM_SPACING ,
541                   NULL ) ;
542 
543    wset.yorient_av = new_MCW_arrowval(
544                       wset.topform ,                     /* parent */
545                       "y orientation\n (down screen) " , /* label */
546                       MCW_AV_downup ,                    /* arrows */
547                       FIRST_ORIENT_TYPE ,                /* min */
548                       LAST_ORIENT_TYPE ,                 /* max */
549                       user_inputs.yorient ,              /* init */
550                       MCW_AV_readtext ,                  /* text */
551                       0 ,                                /* decimals */
552                       T3D_orient_av_CB , NULL ,          /* callback */
553                       T3D_text_display ,                 /* text maker */
554                       ORIENT_typestr                     /* and data */
555                      ) ;
556 
557    XtVaSetValues( wset.yorient_av->wrowcol ,
558                      XmNtopAttachment  , XmATTACH_WIDGET ,
559                      XmNtopWidget      , wset.xorient_av->wrowcol ,
560                      XmNtopOffset      , T3D_FORM_SPACING ,
561                      XmNleftAttachment , XmATTACH_FORM ,
562                      XmNleftOffset     , T3D_FORM_SPACING ,
563                   NULL ) ;
564 
565    wset.zorient_av = new_MCW_arrowval(
566                       wset.topform ,                     /* parent */
567                       "z orientation\n(slices 0,1,..)" , /* label */
568                       MCW_AV_downup ,                    /* arrows */
569                       FIRST_ORIENT_TYPE ,                /* min */
570                       LAST_ORIENT_TYPE ,                 /* max */
571                       user_inputs.zorient ,              /* init */
572                       MCW_AV_readtext ,                  /* text */
573                       0 ,                                /* decimals */
574                       T3D_orient_av_CB , NULL ,          /* callback */
575                       T3D_text_display ,                 /* text maker */
576                       ORIENT_typestr                     /* and data */
577                      ) ;
578 
579    XtVaSetValues( wset.zorient_av->wrowcol ,
580                      XmNtopAttachment  , XmATTACH_WIDGET ,
581                      XmNtopWidget      , wset.yorient_av->wrowcol ,
582                      XmNtopOffset      , T3D_FORM_SPACING ,
583                      XmNleftAttachment , XmATTACH_FORM ,
584                      XmNleftOffset     , T3D_FORM_SPACING ,
585                   NULL ) ;
586 
587    XtVaSetValues( wset.xorient_av->wtext ,
588                      XmNcolumns   , LONGEST_ORIENT_TYPESTR ,
589                      XmNmaxLength , LONGEST_ORIENT_TYPESTR ,
590                   NULL ) ;
591 
592    XtVaSetValues( wset.yorient_av->wtext ,
593                      XmNcolumns   , LONGEST_ORIENT_TYPESTR ,
594                      XmNmaxLength , LONGEST_ORIENT_TYPESTR ,
595                   NULL ) ;
596 
597    XtVaSetValues( wset.zorient_av->wtext ,
598                      XmNcolumns   , LONGEST_ORIENT_TYPESTR ,
599                      XmNmaxLength , LONGEST_ORIENT_TYPESTR ,
600                   NULL ) ;
601 
602    wset.xorient_av->allow_wrap = 1 ;
603    wset.yorient_av->allow_wrap = 1 ;
604    wset.zorient_av->allow_wrap = 1 ;
605 
606    MCW_reghelp_children( wset.xorient_av->wrowcol ,
607       "Choose the anatomical orientation\n"
608       "which fits the images when displayed\n"
609       "in their ORIGINAL orientation:\n"
610       "left->right, across the screen" ) ;
611    MCW_reghint_children( wset.xorient_av->wrowcol ,
612                          "Anatomical orientation across screen" ) ;
613 
614    MCW_reghelp_children( wset.yorient_av->wrowcol ,
615       "Choose the anatomical orientation\n"
616       "which fits the images when displayed\n"
617       "in their ORIGINAL orientation:\n"
618       "top->bottom, down the screen" ) ;
619    MCW_reghint_children( wset.yorient_av->wrowcol ,
620                          "Anatomical orientation down screen" ) ;
621 
622    MCW_reghelp_children( wset.zorient_av->wrowcol ,
623       "Choose the anatomical orientation\n"
624       "which fits the images when displayed\n"
625       "in their ORIGINAL orientation:\n"
626       "slice order, `thru' the screen" ) ;
627    MCW_reghint_children( wset.zorient_av->wrowcol ,
628                          "Anatomical orientation in slice direction" ) ;
629 
630    printf(".");fflush(stdout);
631 
632    /*---- bbox and arrowvals for voxel sizes ----*/
633 
634    wset.xsize_av = new_MCW_arrowval(
635                       wset.topform ,                /* parent */
636                       "x voxel\nsize (mm)" ,        /* label */
637                       MCW_AV_downup ,               /* arrows */
638                       1 ,                           /* min */
639                       9999 ,                        /* max */
640                       (int)(100*user_inputs.xsize), /* init */
641                       MCW_AV_editext ,              /* text */
642                       2 ,                           /* decimals */
643                       T3D_size_av_CB , NULL ,       /* callback */
644                       NULL , NULL                   /* text maker */
645                      ) ;
646 
647    XtVaSetValues( wset.xsize_av->wrowcol ,
648                      XmNtopAttachment  , XmATTACH_FORM ,
649                      XmNtopOffset      , T3D_FORM_SPACING ,
650                      XmNleftAttachment , XmATTACH_WIDGET ,
651                      XmNleftWidget     , wset.xorient_av->wrowcol ,
652                      XmNleftOffset     , T3D_FORM_SPACING ,
653                   NULL ) ;
654 
655 /*
656    AV_assign_fval( wset.xsize_av , user_inputs.xsize ) ;
657 */
658 
659    wset.ysize_av = new_MCW_arrowval(
660                       wset.topform ,                /* parent */
661                       "y voxel\nsize (mm)" ,        /* label */
662                       MCW_AV_downup ,               /* arrows */
663                       1 ,                           /* min */
664                       9999 ,                        /* max */
665                       (int)(100*user_inputs.ysize), /* init */
666                       MCW_AV_editext ,              /* text */
667                       2 ,                           /* decimals */
668                       T3D_size_av_CB , NULL ,       /* callback */
669                       NULL , NULL                   /* text maker */
670                      ) ;
671 
672    XtVaSetValues( wset.ysize_av->wrowcol ,
673                      XmNtopAttachment  , XmATTACH_WIDGET ,
674                      XmNtopWidget      , wset.xsize_av->wrowcol ,
675                      XmNtopOffset      , T3D_FORM_SPACING ,
676                      XmNleftAttachment , XmATTACH_WIDGET ,
677                      XmNleftWidget     , wset.xorient_av->wrowcol ,
678                      XmNleftOffset     , T3D_FORM_SPACING ,
679                   NULL ) ;
680 
681    wset.zsize_av = new_MCW_arrowval(
682                       wset.topform ,                /* parent */
683                       "z voxel\nsize (mm)" ,        /* label */
684                       MCW_AV_downup ,               /* arrows */
685                       1 ,                           /* min */
686                       9999 ,                        /* max */
687                       (int)(100*user_inputs.zsize), /* init */
688                       MCW_AV_editext ,              /* text */
689                       2 ,                           /* decimals */
690                       T3D_size_av_CB , NULL ,       /* callback */
691                       NULL , NULL                   /* text maker */
692                      ) ;
693 
694    XtVaSetValues( wset.zsize_av->wrowcol ,
695                      XmNtopAttachment  , XmATTACH_WIDGET ,
696                      XmNtopWidget      , wset.ysize_av->wrowcol ,
697                      XmNtopOffset      , T3D_FORM_SPACING ,
698                      XmNleftAttachment , XmATTACH_WIDGET ,
699                      XmNleftWidget     , wset.xorient_av->wrowcol ,
700                      XmNleftOffset     , T3D_FORM_SPACING ,
701                   NULL ) ;
702 
703 #ifdef ALLOW_NONCONTIG
704    wset.zspacing_av = new_MCW_arrowval(
705                         wset.topform ,                    /* parent */
706                         "z voxel\nspacing  " ,            /* label */
707                         MCW_AV_downup ,                   /* arrows */
708                         1 ,                               /* min */
709                         9999 ,                            /* max */
710                         (int)(100*user_inputs.zspacing),  /* init */
711                         MCW_AV_editext ,                  /* text */
712                         2 ,                               /* decimals */
713                         T3D_size_av_CB , NULL ,           /* callback */
714                         NULL , NULL                       /* text maker */
715                       ) ;
716 
717    XtVaSetValues( wset.zspacing_av->wrowcol ,
718                      XmNtopAttachment  , XmATTACH_WIDGET ,
719                      XmNtopWidget      , wset.zsize_av->wrowcol ,
720                      XmNtopOffset      , T3D_FORM_SPACING ,
721                      XmNleftAttachment , XmATTACH_WIDGET ,
722                      XmNleftWidget     , wset.xorient_av->wrowcol ,
723                      XmNleftOffset     , T3D_FORM_SPACING ,
724                   NULL ) ;
725 #endif /* ALLOW_NONCONTIG */
726 
727    wset.fov_av = new_MCW_arrowval(
728                       wset.topform ,             /* parent */
729                       "Field of\nview (mm)" ,    /* label */
730                       MCW_AV_downup ,            /* arrows */
731                       1 ,                        /* min */
732                       99999 ,                    /* max */
733                       (int)(10*user_inputs.fov), /* init */
734                       MCW_AV_editext ,           /* text */
735                       1 ,                        /* decimals */
736                       T3D_fov_av_CB , NULL ,     /* callback */
737                       NULL , NULL                /* text maker */
738                      ) ;
739 
740    XtVaSetValues( wset.fov_av->wrowcol ,
741                      XmNtopAttachment  , XmATTACH_WIDGET ,
742 #ifdef ALLOW_NONCONTIG
743                      XmNtopWidget      , wset.zspacing_av->wrowcol ,
744 #else
745                      XmNtopWidget      , wset.zsize_av->wrowcol ,
746 #endif
747                      XmNtopOffset      , T3D_FORM_SPACING ,
748                      XmNleftAttachment , XmATTACH_WIDGET ,
749                      XmNleftWidget     , wset.xorient_av->wrowcol ,
750                      XmNleftOffset     , T3D_FORM_SPACING ,
751                   NULL ) ;
752 
753    wset.voxshape_bbox = new_MCW_bbox(
754                           wset.topform ,        /* parent */
755                           3 ,                   /* num buttons */
756                           T3D_voxshape_label ,  /* labels */
757                           MCW_BB_radio_one ,    /* bbox type */
758                           MCW_BB_frame ,        /* use a frame */
759                           T3D_voxshape_CB ,     /* callback */
760                           NULL                  /* callback data */
761                         ) ;
762 
763    XtVaSetValues( wset.voxshape_bbox->wtop ,
764                      XmNrightAttachment  , XmATTACH_WIDGET ,
765                      XmNrightWidget      , wset.fov_av->wrowcol ,
766                      XmNrightOffset      , T3D_FORM_SPACING ,
767                      XmNtopAttachment    , XmATTACH_OPPOSITE_WIDGET ,
768                      XmNtopWidget        , wset.fov_av->wrowcol ,
769                      XmNtopOffset        , 0 ,
770                   NULL ) ;
771 
772 #ifdef ALLOW_NONCONTIG
773    wset.voxcontig_bbox = new_MCW_bbox(
774                           wset.topform ,        /* parent */
775                           3 ,                   /* num buttons */
776                           T3D_voxcontig_label , /* labels */
777                           MCW_BB_radio_one ,    /* bbox type */
778                           MCW_BB_frame ,        /* use a frame */
779                           T3D_voxcontig_CB ,    /* callback */
780                           NULL                  /* callback data */
781                         ) ;
782 
783    XtSetSensitive( wset.voxcontig_bbox->wbut[1] , False ) ;
784    XtSetSensitive( wset.voxcontig_bbox->wbut[2] , False ) ;
785 
786    XtVaSetValues( wset.voxcontig_bbox->wtop ,
787                      XmNrightAttachment  , XmATTACH_WIDGET ,
788                      XmNrightWidget      , wset.voxshape_bbox->wtop ,
789                      XmNrightOffset      , T3D_FORM_SPACING ,
790                      XmNtopAttachment    , XmATTACH_OPPOSITE_WIDGET ,
791                      XmNtopWidget        , wset.voxshape_bbox->wtop ,
792                      XmNtopOffset        , 0 ,
793                   NULL ) ;
794 #endif /* ALLOW_NONCONTIG */
795 
796    MCW_reghelp_children( wset.xsize_av->wrowcol ,
797     "If in-slice voxel dimensions are\n"
798     "not square, use this to set the\n"
799     "x axis (across screen) dimension" ) ;
800    MCW_reghint_children( wset.xsize_av->wrowcol ,
801                          "Across screen voxel size" ) ;
802 
803    MCW_reghelp_children( wset.ysize_av->wrowcol ,
804     "If in-slice voxel dimensions are\n"
805     "not square, use this to set the\n"
806     "y axis (down screen) dimension" ) ;
807    MCW_reghint_children( wset.ysize_av->wrowcol ,
808                          "Down screen voxel size" ) ;
809 
810    MCW_reghelp_children( wset.zsize_av->wrowcol ,
811     "If voxels are not cubical,\n"
812     "use this to set the z axis\n"
813     "(slice direction) thickness" ) ;
814    MCW_reghint_children( wset.ysize_av->wrowcol ,
815                          "Slice direction voxel size" ) ;
816 
817 #ifdef ALLOW_NONCONTIG
818    MCW_reghelp_children( wset.zspacing_av->wrowcol ,
819     "If the slices are not\n"
820     "contiguous, use this to\n"
821     "set the center-to-center\n"
822     "slice spacing" ) ;
823 #endif /* ALLOW_NONCONTIG */
824 
825    MCW_reghelp_children( wset.fov_av->wrowcol ,
826     "If the voxels are cubical,\n"
827     "or at least square, use this\n"
828     "to specify the sizes by giving\n"
829     "the Field-Of-View dimension\n"
830     "(the width across screen of images)" ) ;
831    MCW_reghint_children( wset.fov_av->wrowcol ,
832                          "In-slice width of entire image" ) ;
833 
834    MCW_reghelp_children( wset.voxshape_bbox->wrowcol ,
835                          "Choose one button to\n"
836                          "specify the voxel 'shape':\n"
837                          " cubical  = all dimensions equal\n"
838                          " square   = x & y dimensions\n"
839                          "            equal, z different\n"
840                          " irregular= all dimensions unequal" ) ;
841    MCW_reghint_children( wset.voxshape_bbox->wrowcol ,
842                          "Specify voxel shape" ) ;
843 
844 #ifdef ALLOW_NONCONTIG
845    MCW_reghelp_children( wset.voxcontig_bbox->wrowcol ,
846     "Pressed IN:  slices are contiguous\n"
847     "Pressed OUT: slices are not contiguous\n"
848     "(i.e., z size and z spacing differ)" ) ;
849 #endif /* ALLOW_NONCONTIG */
850 
851    /*-- set the vox*_bbox values depending on initial sizes --*/
852 
853    if( user_inputs.xsize != user_inputs.ysize ){
854       user_inputs.voxshape = VOXSHAPE_IRREGULAR ;
855    } else {
856       if( user_inputs.xsize != user_inputs.zsize ){
857          user_inputs.voxshape = VOXSHAPE_SQUARE ;
858       } else {
859          user_inputs.voxshape = VOXSHAPE_CUBICAL ;
860       }
861    }
862 
863    printf(".");fflush(stdout);
864 
865    /*---- Label to show the TR (for 3D+time datasets) ----*/
866 
867    { char buf[96] ;
868      XmString xstr ;
869 
870      sprintf( buf,"TR=%.3f%s Torg=%.3f\nNR=%d Nz=%d",
871               user_inputs.TR  , UNITS_TYPE_LABEL(user_inputs.tunits) ,
872               user_inputs.Torg,
873               user_inputs.ntt , user_inputs.nzz ) ;
874      xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
875 
876      wset.TR_label =
877       XtVaCreateManagedWidget(
878          "dialog" , xmLabelWidgetClass , wset.topform ,
879             XmNlabelString      , xstr ,
880             XmNrecomputeSize    , False ,
881             XmNalignment        , XmALIGNMENT_BEGINNING ,
882             XmNtopAttachment    , XmATTACH_WIDGET ,
883             XmNtopWidget        , wset.fov_av->wrowcol ,
884             XmNtopOffset        , T3D_FORM_SPACING ,
885             XmNleftAttachment   , XmATTACH_WIDGET ,
886             XmNleftWidget       , wset.voxshape_bbox->wtop ,
887             XmNleftOffset       , T3D_FORM_SPACING ,
888          NULL ) ;
889 
890       XmStringFree( xstr ) ;
891 
892       MCW_register_help( wset.TR_label ,
893          "Shows the TR (inter-brick time), number\n"
894          "of bricks NR, and number of slizes Nz,\n"
895          "for time-dependent datasets.\n"
896          "These CANNOT be changed interactively.\n"
897          "They can only be set on the command line." ) ;
898 
899       MCW_register_hint( wset.TR_label , "3D+time parameters" ) ;
900 
901      if( user_inputs.ntt < 2 )
902         XtUnmanageChild( wset.TR_label ) ;
903    }
904 
905    /*---- arrowvals for origin ----*/
906 
907    wset.xorigin_av = new_MCW_arrowval(
908                         wset.topform ,                  /* parent */
909                         "x origin (mm)\n[left edge]" ,  /* label */
910                         MCW_AV_downup ,                 /* arrows */
911                        -99999 ,                         /* min */
912                         99999 ,                         /* max */
913                         (int)(100*user_inputs.xorigin), /* init */
914                         MCW_AV_editext ,                /* text */
915                         2 ,                             /* decimals */
916                         T3D_origin_av_CB , NULL ,       /* callback */
917                         NULL , NULL                     /* text maker */
918                      ) ;
919 
920    XtVaSetValues( wset.xorigin_av->wrowcol ,
921                      XmNleftAttachment , XmATTACH_WIDGET ,
922                      XmNleftWidget     , wset.xsize_av->wrowcol ,
923                      XmNleftOffset     , T3D_FORM_SPACING ,
924                      XmNtopAttachment  , XmATTACH_FORM ,
925                      XmNtopOffset      , T3D_FORM_SPACING ,
926                   NULL ) ;
927 
928    wset.xorigin_label =
929       XtVaCreateManagedWidget(
930          "dialog" , xmLabelWidgetClass , wset.topform ,
931             LABEL_ARG("X") ,
932             XmNrecomputeSize  , False ,
933             XmNleftAttachment , XmATTACH_WIDGET ,
934             XmNleftWidget     , wset.xorigin_av->wrowcol ,
935             XmNleftOffset     , 1 ,
936             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
937             XmNtopWidget      , wset.xorigin_av->wrowcol ,
938             XmNtopOffset      , 2 ,
939          NULL ) ;
940 
941    wset.yorigin_av = new_MCW_arrowval(
942                         wset.topform ,                  /* parent */
943                         "y origin (mm)\n[top edge]" ,   /* label */
944                         MCW_AV_downup ,                 /* arrows */
945                        -99999 ,                         /* min */
946                         99999 ,                         /* max */
947                         (int)(100*user_inputs.yorigin), /* init */
948                         MCW_AV_editext ,                /* text */
949                         2 ,                             /* decimals */
950                         T3D_origin_av_CB , NULL ,       /* callback */
951                         NULL , NULL                     /* text maker */
952                      ) ;
953 
954    XtVaSetValues( wset.yorigin_av->wrowcol ,
955                      XmNtopAttachment  , XmATTACH_WIDGET ,
956                      XmNtopWidget      , wset.xorigin_av->wrowcol ,
957                      XmNtopOffset      , T3D_FORM_SPACING ,
958                      XmNleftAttachment , XmATTACH_WIDGET ,
959                      XmNleftWidget     , wset.xsize_av->wrowcol ,
960                      XmNleftOffset     , T3D_FORM_SPACING ,
961                   NULL ) ;
962 
963    wset.yorigin_label =
964       XtVaCreateManagedWidget(
965          "dialog" , xmLabelWidgetClass , wset.topform ,
966             LABEL_ARG("X") ,
967             XmNrecomputeSize  , False ,
968             XmNleftAttachment , XmATTACH_WIDGET ,
969             XmNleftWidget     , wset.yorigin_av->wrowcol ,
970             XmNleftOffset     , 1 ,
971             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
972             XmNtopWidget      , wset.yorigin_av->wrowcol ,
973             XmNtopOffset      , 2 ,
974          NULL ) ;
975 
976    wset.zorigin_av = new_MCW_arrowval(
977                         wset.topform ,                  /* parent */
978                         "z origin (mm)\n[slice 0]" ,    /* label */
979                         MCW_AV_downup ,                 /* arrows */
980                        -99999 ,                         /* min */
981                         99999 ,                         /* max */
982                         (int)(100*user_inputs.zorigin), /* init */
983                         MCW_AV_editext ,                /* text */
984                         2 ,                             /* decimals */
985                         T3D_origin_av_CB , NULL ,       /* callback */
986                         NULL , NULL                     /* text maker */
987                      ) ;
988 
989    XtVaSetValues( wset.zorigin_av->wrowcol ,
990                      XmNtopAttachment  , XmATTACH_WIDGET ,
991                      XmNtopWidget      , wset.yorigin_av->wrowcol ,
992                      XmNtopOffset      , T3D_FORM_SPACING ,
993                      XmNleftAttachment , XmATTACH_WIDGET ,
994                      XmNleftWidget     , wset.xsize_av->wrowcol ,
995                      XmNleftOffset     , T3D_FORM_SPACING ,
996                   NULL ) ;
997 
998    wset.zorigin_label =
999       XtVaCreateManagedWidget(
1000          "dialog" , xmLabelWidgetClass , wset.topform ,
1001             LABEL_ARG("X") ,
1002             XmNrecomputeSize  , False ,
1003             XmNleftAttachment , XmATTACH_WIDGET ,
1004             XmNleftWidget     , wset.zorigin_av->wrowcol ,
1005             XmNleftOffset     , 1 ,
1006             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1007             XmNtopWidget      , wset.zorigin_av->wrowcol ,
1008             XmNtopOffset      , 2 ,
1009          NULL ) ;
1010 
1011    wset.centered_bbox = new_MCW_bbox(
1012                           wset.topform ,       /* parent */
1013                           3 ,                  /* num buttons */
1014                           T3D_centered_label , /* labels */
1015                           MCW_BB_check ,       /* bbox type */
1016                           MCW_BB_frame ,       /* use a frame */
1017                           T3D_centered_CB ,    /* callback */
1018                           NULL                 /* callback data */
1019                         ) ;
1020 
1021    XtVaSetValues( wset.centered_bbox->wtop ,
1022 #if 0
1023                      XmNleftAttachment   , XmATTACH_WIDGET ,
1024                      XmNleftWidget       , wset.fov_av->wrowcol ,
1025                      XmNleftOffset       , T3D_FORM_SPACING ,
1026 #else
1027                      XmNrightAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1028                      XmNrightWidget      , wset.zorigin_av->wrowcol ,
1029                      XmNrightOffset      , 0 ,
1030 #endif
1031                      XmNtopAttachment    , XmATTACH_OPPOSITE_WIDGET ,
1032                      XmNtopWidget        , wset.fov_av->wrowcol ,
1033                      XmNtopOffset        , 0 ,
1034                   NULL ) ;
1035 
1036    MCW_reghelp_children( wset.centered_bbox->wrowcol ,
1037     "Choose any combination of\n"
1038     "buttons to indicate whether\n"
1039     "each axis is centered\n"
1040     "in the gradient coil fields:\n"
1041     "Pressed IN means centered\n"
1042     "Pressed OUT means not centered" ) ;
1043    MCW_reghint_children( wset.centered_bbox->wrowcol ,
1044                          "Is data domain centered around 0?" ) ;
1045 
1046    MCW_reghelp_children( wset.xorigin_av->wrowcol ,
1047       "Use the arrows (or type) to enter\n"
1048       "the x-axis distance from the center of\n"
1049       "the first voxel to the\n"
1050       "gradient coil (0,0,0) point" ) ;
1051    MCW_reghint_children( wset.xorigin_av->wrowcol ,
1052                          "X-axis distance to 1st voxel center" ) ;
1053 
1054    MCW_reghelp_children( wset.yorigin_av->wrowcol ,
1055       "Use the arrows (or type) to enter\n"
1056       "the y-axis distance from the center of\n"
1057       "the first voxel to the\n"
1058       "gradient coil (0,0,0) point" ) ;
1059    MCW_reghint_children( wset.yorigin_av->wrowcol ,
1060                          "Y-axis distance to 1st voxel center" ) ;
1061 
1062    MCW_reghelp_children( wset.zorigin_av->wrowcol ,
1063       "Use the arrows (or type) to enter\n"
1064       "the z-axis distance from the center of\n"
1065       "the first voxel to the\n"
1066       "gradient coil (0,0,0) point" ) ;
1067    MCW_reghint_children( wset.zorigin_av->wrowcol ,
1068                          "Z-axis distance to 1st voxel center" ) ;
1069 
1070    MCW_register_help( wset.xorigin_label ,
1071                       "Shows the direction that the\n"
1072                       "x origin distance applies" ) ;
1073    MCW_register_hint( wset.xorigin_label ,
1074                       "Direction of x origin distance" ) ;
1075 
1076    MCW_register_help( wset.yorigin_label ,
1077                       "Shows the direction that the\n"
1078                       "y origin distance applies" ) ;
1079    MCW_register_hint( wset.yorigin_label ,
1080                       "Direction of y origin distance" ) ;
1081 
1082    MCW_register_help( wset.zorigin_label ,
1083                       "Shows the direction that the\n"
1084                       "z origin distance applies" ) ;
1085    MCW_register_hint( wset.zorigin_label ,
1086                       "Direction of z origin distance" ) ;
1087 
1088    printf(".");fflush(stdout);
1089 
1090    /*----- a separator to keep the geometry stuff separate -----*/
1091 
1092    wset.region_separator =
1093       XtVaCreateManagedWidget(
1094          "dialog" , xmSeparatorGadgetClass , wset.topform ,
1095             XmNseparatorType   , XmDOUBLE_LINE ,
1096             XmNmargin          , 3             ,
1097             XmNleftAttachment  , XmATTACH_FORM ,
1098             XmNrightAttachment , XmATTACH_FORM ,
1099             XmNtopAttachment   , XmATTACH_WIDGET ,
1100             XmNtopOffset       , T3D_FORM_SPACING ,
1101             XmNtopWidget       , wset.voxshape_bbox->wtop ,
1102          NULL ) ;
1103 
1104    MCW_register_help( wset.region_separator ,
1105                         "Thou art indeed just, Lord, if I contend\n"
1106                         "With thee; but, sir, so what I plead is just.\n"
1107                         "Why do sinners' ways prosper? and why must\n"
1108                         "Disappointment all I endeavour end?\n"
1109                         "Wert thou my enemy, O thou my friend,\n"
1110                         "How wouldst thou worse, I wonder, than thou dost\n"
1111                         "Defeat, thwart me? Oh, the sots and thralls of lust\n"
1112                         "Do in spare hours more thrive than I that spend,\n"
1113                         "Sir, life upon thy cause. See, banks and brakes\n"
1114                         "Now, leav`ed how thick! lac`ed they are again\n"
1115                         "With fretty chervil, look, and fresh wind shakes\n"
1116                         "Them; birds build -- but not I build; no, but strain,\n"
1117                         "Time's eunuch, and not breed one work that wakes.\n"
1118                         "Mine, O thou lord of life, send my roots rain."
1119                     ) ;
1120 
1121    /*---- April 1996: arrowval for view_type ----*/
1122 
1123    wset.view_type_av = new_MCW_arrowval(
1124                          wset.topform ,                   /* parent */
1125                          "View:  " ,                      /* label */
1126                          MCW_AV_downup ,                  /* arrows */
1127                          FIRST_VIEW_TYPE ,                /* min */
1128                          LAST_VIEW_TYPE ,                 /* max */
1129                          user_inputs.view_type ,          /* init */
1130                          MCW_AV_readtext ,                /* text */
1131                          0 ,                              /* decimals */
1132                          T3D_orient_av_CB , NULL ,        /* callback */
1133                          T3D_text_display ,               /* text maker */
1134                          VIEW_typestr                     /* and data */
1135                        ) ;
1136 
1137    XtVaSetValues( wset.view_type_av->wrowcol ,
1138                      XmNbottomAttachment , XmATTACH_WIDGET ,
1139                      XmNbottomWidget     , wset.region_separator ,
1140                      XmNbottomOffset     , T3D_FORM_SPACING ,
1141                      XmNleftAttachment   , XmATTACH_FORM ,
1142                      XmNleftOffset       , T3D_FORM_SPACING ,
1143                   NULL ) ;
1144 
1145    XtVaSetValues( wset.view_type_av->wtext ,
1146                      XmNcolumns   , LONGEST_VIEW_TYPESTR ,
1147                      XmNmaxLength , LONGEST_VIEW_TYPESTR ,
1148                   NULL ) ;
1149 
1150    MCW_reghelp_children( wset.view_type_av->wrowcol ,
1151       "Sets the view type for the\n"
1152       "dataset being created.  Except\n"
1153       "under unusual circumstances,\n"
1154       "this should be " VIEW_ORIGINAL_STR ) ;
1155 
1156    /*---- Label to show what kind of data is stored ----*/
1157 
1158    { char buf[32] ;
1159      sprintf( buf , "Datum: %s [%dx%d]\n" ,
1160               MRI_TYPE_name[argopt.datum_all], user_inputs.nx,user_inputs.ny ) ;
1161      wset.datum_label =
1162         XtVaCreateManagedWidget(
1163            "dialog" , xmLabelWidgetClass , wset.topform ,
1164               LABEL_ARG(buf)   ,
1165               XmNbottomAttachment , XmATTACH_WIDGET ,
1166               XmNbottomWidget     , wset.view_type_av->wrowcol ,
1167               XmNbottomOffset     , 1 ,
1168               XmNleftAttachment   , XmATTACH_FORM ,
1169               XmNleftOffset       , T3D_FORM_SPACING ,
1170               XmNmarginHeight     , 0 ,
1171               XmNmarginWidth      , 0 ,
1172            NULL ) ;
1173 
1174    }
1175    MCW_register_help( wset.datum_label ,
1176      "This shows the type of data stored\n"
1177      "in the images as read into to3d.\n"
1178      "You can only alter this by exiting\n"
1179      "the program and using the -datum\n"
1180      "option when you run to3d again." ) ;
1181    MCW_register_hint( wset.datum_label , "Type of data stored in images" ) ;
1182 
1183    /*----- textfield widgets below the bar -----*/
1184 
1185    /** name widgets not being used no more **/
1186 
1187 #ifndef NO_NAMES
1188    wset.dataset_name_label =
1189       XtVaCreateManagedWidget(
1190          "dialog" , xmLabelWidgetClass , wset.topform ,
1191             LABEL_ARG("Dataset name:  ") ,
1192             XmNtopAttachment   , XmATTACH_WIDGET ,
1193             XmNtopWidget       , wset.region_separator ,
1194             XmNtopOffset       , T3D_FORM_SPACING ,
1195             XmNleftAttachment  , XmATTACH_FORM ,
1196             XmNleftOffset      , T3D_FORM_SPACING ,
1197          NULL ) ;
1198 
1199    wset.dataset_name_textfield =
1200       XtVaCreateManagedWidget(
1201          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1202             XmNcolumns         , 80 ,
1203             XmNeditable        , True ,
1204             XmNmaxLength       , THD_MAX_NAME-1 ,
1205             XmNresizeWidth     , False ,
1206             XmNcursorPositionVisible , True ,
1207             XmNblinkRate , 0 ,
1208 /*
1209             XmNmarginHeight    , 1 ,
1210             XmNmarginWidth     , 1 ,
1211 */
1212             XmNvalue           , user_inputs.dataset_name ,
1213 
1214             XmNleftAttachment , XmATTACH_WIDGET ,
1215             XmNleftWidget     , wset.dataset_name_label ,
1216             XmNleftOffset     , T3D_FORM_SPACING ,
1217             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1218             XmNtopWidget      , wset.dataset_name_label ,
1219             XmNtopOffset      , 0 ,
1220          NULL ) ;
1221 
1222    MCW_register_help( wset.dataset_name_label ,
1223     "Every 3D dataset needs a name;\n"
1224     "Type in what you need to remind\n"
1225     "you of the subject/experiment" ) ;
1226 
1227    MCW_register_help( wset.dataset_name_textfield ,
1228     "Every 3D dataset needs a label;\n"
1229     "Type in what you need to remind\n"
1230     "you of the subject/experiment" ) ;
1231 
1232    wset.short_label1_label =
1233       XtVaCreateManagedWidget(
1234          "dialog" , xmLabelWidgetClass , wset.topform ,
1235             LABEL_ARG("Short label:   ") ,
1236             XmNleftAttachment  , XmATTACH_FORM ,
1237             XmNleftOffset      , T3D_FORM_SPACING ,
1238             XmNtopAttachment   , XmATTACH_WIDGET ,
1239             XmNtopWidget       , wset.dataset_name_textfield ,
1240             XmNtopOffset       , T3D_FORM_SPACING ,
1241          NULL ) ;
1242 
1243    wset.short_label1_textfield =
1244       XtVaCreateManagedWidget(
1245          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1246             XmNcolumns         , T3D_NAME_WIDTH ,
1247             XmNeditable        , True ,
1248             XmNmaxLength       , THD_MAX_LABEL-1 ,
1249             XmNresizeWidth     , False ,
1250             XmNcursorPositionVisible , True ,
1251             XmNblinkRate , 0 ,
1252 /*
1253             XmNmarginHeight    , 1 ,
1254             XmNmarginWidth     , 1 ,
1255 */
1256             XmNvalue           , user_inputs.short_label1 ,
1257 
1258             XmNleftAttachment , XmATTACH_WIDGET ,
1259             XmNleftWidget     , wset.short_label1_label ,
1260             XmNleftOffset     , T3D_FORM_SPACING ,
1261             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1262             XmNtopWidget      , wset.short_label1_label ,
1263             XmNtopOffset      , 0 ,
1264          NULL ) ;
1265 
1266    MCW_register_help( wset.short_label1_label ,
1267     "The short label is used\n"
1268     "for a compact reminder of\n"
1269     "the dataset contents;\n"
1270     "type your choice in" ) ;
1271 
1272    MCW_register_help( wset.short_label1_textfield ,
1273     "The short label is used\n"
1274     "for a compact reminder of\n"
1275     "the dataset contents;\n"
1276     "type your choice in" ) ;
1277 #endif  /* NO_NAMES */
1278 
1279    wset.geometry_parent_label =
1280       XtVaCreateManagedWidget(
1281          "dialog" , xmLabelWidgetClass , wset.topform ,
1282             LABEL_ARG("Copy geometry  \nof this dataset") ,
1283             XmNleftAttachment  , XmATTACH_FORM ,
1284             XmNleftOffset      , T3D_FORM_SPACING ,
1285             XmNtopAttachment   , XmATTACH_WIDGET ,
1286 #ifdef NO_NAMES
1287             XmNtopWidget       , wset.region_separator ,
1288 #else
1289             XmNtopWidget       , wset.short_label1_textfield ,
1290 #endif
1291             XmNtopOffset       , T3D_FORM_SPACING ,
1292          NULL ) ;
1293 
1294    wset.geometry_parent_textfield =
1295       XtVaCreateManagedWidget(
1296          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1297             XmNcolumns         , T3D_NAME_WIDTH ,
1298             XmNeditable        , True ,
1299             XmNmaxLength       , THD_MAX_NAME-1 ,
1300             XmNresizeWidth     , False ,
1301             XmNcursorPositionVisible , True ,
1302             XmNblinkRate , 0 ,
1303 /*
1304             XmNmarginHeight    , 1 ,
1305             XmNmarginWidth     , 1 ,
1306 */
1307             XmNvalue           , user_inputs.geometry_parent_filename ,
1308 
1309             XmNleftAttachment , XmATTACH_WIDGET ,
1310             XmNleftWidget     , wset.geometry_parent_label ,
1311             XmNleftOffset     , T3D_FORM_SPACING ,
1312             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1313             XmNtopWidget      , wset.geometry_parent_label ,
1314             XmNtopOffset      , 0 ,
1315          NULL ) ;
1316 
1317    XtAddCallback( wset.geometry_parent_textfield ,
1318                   XmNactivateCallback ,
1319                   T3D_geometry_parent_CB , NULL ) ;    /* return key */
1320 
1321    XtAddCallback( wset.geometry_parent_textfield ,
1322                   XmNlosingFocusCallback ,
1323                   T3D_geometry_parent_CB , NULL ) ;    /* Tab key */
1324 
1325    XtInsertEventHandler( wset.geometry_parent_textfield ,
1326                          LeaveWindowMask ,             /* pointer leaves */
1327                          FALSE ,
1328                          T3D_pointer_leave_EV , NULL ,
1329                          XtListTail ) ;                /* last in queue */
1330 
1331    MCW_register_help( wset.geometry_parent_label ,
1332     "If a previously created 3D dataset\n"
1333     "has the same geometry (voxel sizes,\n"
1334     "etc.), enter its header filename\n"
1335     "and press the Enter key" ) ;
1336    MCW_register_hint( wset.geometry_parent_label ,
1337                       "Use the geometry of another dataset" ) ;
1338 
1339    MCW_register_help( wset.geometry_parent_textfield ,
1340     "If a previously created 3D dataset\n"
1341     "has the same geometry (voxel sizes,\n"
1342     "etc.), enter its header filename name\n"
1343     "here and press the Enter key" ) ;
1344    MCW_register_hint( wset.geometry_parent_textfield ,
1345                       "Use the geometry of another dataset" ) ;
1346 
1347    wset.anatomy_parent_label =
1348       XtVaCreateManagedWidget(
1349          "dialog" , xmLabelWidgetClass , wset.topform ,
1350             LABEL_ARG("Anatomy parent \nis this dataset") ,
1351             XmNleftAttachment  , XmATTACH_WIDGET ,
1352             XmNleftWidget      , wset.geometry_parent_textfield ,
1353             XmNleftOffset      , T3D_FORM_SPACING ,
1354             XmNtopAttachment   , XmATTACH_WIDGET ,
1355 #ifdef NO_NAMES
1356             XmNtopWidget       , wset.region_separator ,
1357 #else
1358             XmNtopWidget       , wset.short_label1_textfield ,
1359 #endif
1360             XmNtopOffset       , T3D_FORM_SPACING ,
1361          NULL ) ;
1362 
1363    wset.anatomy_parent_textfield =
1364       XtVaCreateManagedWidget(
1365          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1366             XmNcolumns         , T3D_NAME_WIDTH ,
1367             XmNeditable        , True ,
1368             XmNmaxLength       , THD_MAX_NAME-1 ,
1369             XmNresizeWidth     , False ,
1370             XmNcursorPositionVisible , True ,
1371             XmNblinkRate , 0 ,
1372 /*
1373             XmNmarginHeight    , 1 ,
1374             XmNmarginWidth     , 1 ,
1375 */
1376             XmNvalue           , user_inputs.anatomy_parent_filename ,
1377 
1378             XmNleftAttachment , XmATTACH_WIDGET ,
1379             XmNleftOffset     , T3D_FORM_SPACING ,
1380             XmNleftWidget     , wset.anatomy_parent_label ,
1381             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1382             XmNtopWidget      , wset.anatomy_parent_label ,
1383             XmNtopOffset      , 0 ,
1384          NULL ) ;
1385 
1386    XtAddCallback( wset.anatomy_parent_textfield ,
1387                   XmNactivateCallback ,
1388                   T3D_anatomy_parent_CB , NULL ) ;    /* return key */
1389 
1390    XtAddCallback( wset.anatomy_parent_textfield ,
1391                   XmNlosingFocusCallback ,
1392                   T3D_anatomy_parent_CB , NULL ) ;    /* Tab key */
1393 
1394    XtInsertEventHandler( wset.anatomy_parent_textfield ,
1395                          LeaveWindowMask ,             /* pointer leaves */
1396                          FALSE ,
1397                          T3D_pointer_leave_EV , NULL ,
1398                          XtListTail ) ;                /* last in queue */
1399 
1400    MCW_register_help( wset.anatomy_parent_label ,
1401     "A dataset may optionally be attached\n"
1402     "to an 'anatomy parent' -- that is, an\n"
1403     "anatomical dataset which is aligned\n"
1404     "with the current dataset; usually, the\n"
1405     "anatomy parent should have been acquired\n"
1406     "during the same imaging session as the\n"
1407     "current dataset, so that this requisite\n"
1408     "alignment is assured.  If no anatomy parent\n"
1409     "is given, then at the time one is needed,\n"
1410     "an appropriate dataset will be chosen from\n"
1411     "the same session directory.\n"
1412     "\n"
1413 #ifdef REQUIRE_ANAT_PARENT
1414     "N.B.: Functional datasets require anatomy parents;\n"
1415     "      for anatomical datasets, anatomy parents are\n"
1416     "      optional."
1417 #else
1418     "N.B.: You only need specify an anatomy parent\n"
1419     "      here if a specific dataset is required."
1420 #endif
1421    ) ;
1422 
1423    MCW_register_help( wset.anatomy_parent_textfield ,
1424     "A dataset may optionally be attached\n"
1425     "to an 'anatomy parent' -- that is, an\n"
1426     "anatomical dataset which is aligned\n"
1427     "with the current dataset; usually, the\n"
1428     "anatomy parent should have been acquired\n"
1429     "during the same imaging session as the\n"
1430     "current dataset, so that this requisite\n"
1431     "alignment is assured.  If no anatomy parent\n"
1432     "is given, then at the time one is needed,\n"
1433     "an appropriate dataset will be chosen from\n"
1434     "the same session directory.\n"
1435     "\n"
1436 #ifdef REQUIRE_ANAT_PARENT
1437     "N.B.: functional datasets require anatomy parents;\n"
1438     "      for anatomical datasets, anatomy parents are\n"
1439     "      optional."
1440 #else
1441     "N.B.: You only need specify an anatomy parent\n"
1442     "      here if a specific dataset is required."
1443 #endif
1444    ) ;
1445 
1446 #ifndef NO_NAMES
1447    wset.geometry_dataname_label =
1448       XtVaCreateManagedWidget(
1449          "dialog" , xmLabelWidgetClass , wset.topform ,
1450             LABEL_ARG("Geometry parent\nDataset name   ") ,
1451             XmNleftAttachment  , XmATTACH_FORM ,
1452             XmNleftOffset      , T3D_FORM_SPACING ,
1453             XmNtopAttachment   , XmATTACH_WIDGET ,
1454             XmNtopWidget       , wset.geometry_parent_textfield ,
1455             XmNtopOffset       , T3D_FORM_SPACING ,
1456             XmNsensitive       , False ,
1457          NULL ) ;
1458 
1459    wset.geometry_dataname_textfield =
1460       XtVaCreateManagedWidget(
1461          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1462             XmNcolumns         , T3D_NAME_WIDTH ,
1463             XmNeditable        , False ,
1464             XmNmaxLength       , THD_MAX_NAME-1 ,
1465             XmNresizeWidth     , False ,
1466 
1467             XmNcursorPositionVisible , False ,
1468             XmNsensitive       , False ,
1469 /*
1470             XmNmarginHeight    , 1 ,
1471             XmNmarginWidth     , 1 ,
1472 */
1473             XmNvalue           , " " ,
1474 
1475             XmNleftAttachment , XmATTACH_WIDGET ,
1476             XmNleftWidget     , wset.geometry_dataname_label ,
1477             XmNleftOffset     , T3D_FORM_SPACING ,
1478             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1479             XmNtopWidget      , wset.geometry_dataname_label ,
1480             XmNtopOffset      , 0 ,
1481          NULL ) ;
1482 
1483    MCW_register_help( wset.geometry_dataname_label ,
1484     "This item just shows the\n"
1485     "dataset name of the 'geometry\n"
1486     "parent' you selected (e.g., to\n"
1487     "let you decide if you've got\n"
1488     "the right one)." ) ;
1489 
1490    MCW_register_help( wset.geometry_dataname_textfield ,
1491     "This item just shows the\n"
1492     "dataset name of the 'geometry\n"
1493     "parent' you selected (e.g., to\n"
1494     "let you decide if you've got\n"
1495     "the right one)." ) ;
1496 
1497    wset.anatomy_dataname_label =
1498       XtVaCreateManagedWidget(
1499          "dialog" , xmLabelWidgetClass , wset.topform ,
1500             LABEL_ARG("Anatomy parent \nDataset name   ") ,
1501             XmNleftAttachment  , XmATTACH_WIDGET ,
1502             XmNleftWidget      , wset.geometry_dataname_textfield ,
1503             XmNleftOffset      , T3D_FORM_SPACING ,
1504             XmNtopAttachment   , XmATTACH_WIDGET ,
1505             XmNtopWidget       , wset.geometry_parent_textfield ,
1506             XmNtopOffset       , T3D_FORM_SPACING ,
1507             XmNsensitive       , False ,
1508          NULL ) ;
1509 
1510    wset.anatomy_dataname_textfield =
1511       XtVaCreateManagedWidget(
1512          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1513             XmNcolumns         , T3D_NAME_WIDTH ,
1514             XmNeditable        , False ,
1515             XmNmaxLength       , THD_MAX_NAME-1 ,
1516             XmNresizeWidth     , False ,
1517 
1518             XmNcursorPositionVisible , False ,
1519             XmNsensitive       , False ,
1520 /*
1521             XmNmarginHeight    , 1 ,
1522             XmNmarginWidth     , 1 ,
1523 */
1524             XmNvalue           , " " ,
1525 
1526             XmNleftAttachment , XmATTACH_WIDGET ,
1527             XmNleftWidget     , wset.anatomy_dataname_label ,
1528             XmNleftOffset     , T3D_FORM_SPACING ,
1529             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1530             XmNtopWidget      , wset.anatomy_dataname_label ,
1531             XmNtopOffset      , 0 ,
1532          NULL ) ;
1533 
1534    MCW_register_help( wset.anatomy_dataname_label ,
1535     "This item just shows the\n"
1536     "dataset name of the 'anatomy\n"
1537     "parent' you selected" ) ;
1538 
1539    MCW_register_help( wset.anatomy_dataname_textfield ,
1540     "This item just shows the\n"
1541     "dataset name of the 'anatomy\n"
1542     "parent' you selected" ) ;
1543 
1544    printf(".");fflush(stdout);
1545 #endif  /* NO_NAMES */
1546 
1547    /*----- arrowvals for dataset and function types -----*/
1548 
1549    wset.dataset_type_av =
1550       new_MCW_arrowval(
1551              wset.topform ,                     /* parent */
1552              "Type of data\nin the images    ", /* label */
1553              MCW_AV_downup ,                    /* arrows */
1554              FIRST_3DIM_TYPE ,                  /* min */
1555              LAST_3DIM_TYPE ,                   /* max */
1556              user_inputs.dataset_type ,         /* init */
1557              MCW_AV_readtext ,                  /* text type */
1558              0 ,                                /* decimals */
1559              T3D_type_av_CB , NULL ,            /* callback */
1560              T3D_text_display ,                 /* text maker */
1561              DATASET_typestr                    /* and data */
1562        ) ;
1563 
1564    wset.dataset_type_av->allow_wrap = 1 ;
1565 
1566    XtVaSetValues( wset.dataset_type_av->wtext ,
1567                      XmNcolumns   , LONGEST_3DIM_TYPESTR ,
1568                      XmNmaxLength , LONGEST_3DIM_TYPESTR ,
1569                   NULL ) ;
1570 
1571    XtVaSetValues( wset.dataset_type_av->wrowcol ,
1572                      XmNleftAttachment , XmATTACH_FORM ,
1573                      XmNleftOffset     , T3D_FORM_SPACING ,
1574                      XmNtopAttachment  , XmATTACH_WIDGET ,
1575 #ifndef NO_NAMES
1576                      XmNtopWidget      , wset.geometry_dataname_label ,
1577 #else
1578                      XmNtopWidget      , wset.geometry_parent_label ,
1579 #endif
1580                      XmNtopOffset      , T3D_FORM_SPACING ,
1581                   NULL ) ;
1582 
1583    MCW_reghelp_children( wset.dataset_type_av->wrowcol ,
1584                           "Use the arrows to specify\n"
1585                           "the type of data stored\n"
1586                           "in the image files.\n"
1587                           "N.B.: 3D+time datasets\n"
1588                           " must be anatomical."     ) ;
1589    MCW_reghint_children( wset.dataset_type_av->wrowcol ,
1590                          "Type of data you acquired" ) ;
1591 
1592    if( user_inputs.ntt > 0 )
1593       AV_SENSITIZE( wset.dataset_type_av , False ) ;
1594 
1595    wset.function_type_av =
1596       new_MCW_arrowval(
1597              wset.topform ,                      /* parent */
1598              "Type of function \nin the images", /* label */
1599              MCW_AV_downup ,                     /* arrows */
1600              FIRST_FUNC_TYPE ,                   /* min */
1601              LAST_FUNC_TYPE ,                    /* max */
1602              user_inputs.function_type ,         /* init */
1603              MCW_AV_readtext ,                   /* text type */
1604              0 ,                                 /* decimals */
1605              T3D_type_av_CB , NULL ,             /* callback */
1606              T3D_text_display ,                  /* text maker */
1607              FUNC_typestr                        /* and data */
1608        ) ;
1609 
1610    wset.function_type_av->allow_wrap = 1 ;
1611 
1612    XtVaSetValues( wset.function_type_av->wtext ,
1613                      XmNcolumns   , LONGEST_FUNC_TYPESTR ,
1614                      XmNmaxLength , LONGEST_FUNC_TYPESTR ,
1615                   NULL ) ;
1616 
1617    XtVaSetValues( wset.function_type_av->wrowcol ,
1618                      XmNleftAttachment , XmATTACH_WIDGET ,
1619                      XmNleftOffset     , T3D_FORM_SPACING ,
1620                      XmNtopAttachment  , XmATTACH_WIDGET ,
1621                      XmNtopOffset      , T3D_FORM_SPACING ,
1622                      XmNleftWidget     , wset.geometry_parent_textfield ,
1623 #ifndef NO_NAMES
1624                      XmNtopWidget      , wset.geometry_dataname_textfield ,
1625 #else
1626                      XmNtopWidget      , wset.geometry_parent_textfield ,
1627 #endif
1628                      XtNmappedWhenManaged , False ,
1629                   NULL ) ;
1630 
1631    MCW_reghelp_children( wset.function_type_av->wrowcol ,
1632     "Use the arrows to specify\n"
1633     "the type of functional data\n"
1634     "stored in the image files" ) ;
1635    MCW_reghint_children( wset.function_type_av->wrowcol ,
1636                          "Type of functional data" ) ;
1637 
1638    wset.anatomy_type_av =
1639       new_MCW_arrowval(
1640              wset.topform ,                      /* parent */
1641              "Type of anatomy  \nin the images", /* label */
1642              MCW_AV_downup ,                     /* arrows */
1643              FIRST_ANAT_TYPE ,                   /* min */
1644              LAST_ANAT_TYPE ,                    /* max */
1645              user_inputs.anatomy_type ,          /* init */
1646              MCW_AV_readtext ,                   /* text type */
1647              0 ,                                 /* decimals */
1648              T3D_type_av_CB , NULL ,             /* callback */
1649              T3D_text_display ,                  /* text maker */
1650              ANAT_typestr                        /* and data */
1651        ) ;
1652 
1653    wset.anatomy_type_av->allow_wrap = 1 ;
1654 
1655    XtVaSetValues( wset.anatomy_type_av->wtext ,
1656                      XmNcolumns   , LONGEST_ANAT_TYPESTR ,
1657                      XmNmaxLength , LONGEST_ANAT_TYPESTR ,
1658                   NULL ) ;
1659 
1660    XtVaSetValues( wset.anatomy_type_av->wrowcol ,
1661                      XmNleftAttachment , XmATTACH_WIDGET ,
1662                      XmNleftWidget     , wset.geometry_parent_textfield ,
1663 #ifndef NO_NAMES
1664                      XmNtopWidget      , wset.geometry_dataname_textfield ,
1665 #else
1666                      XmNtopWidget      , wset.geometry_parent_textfield ,
1667 #endif
1668                      XmNleftOffset     , T3D_FORM_SPACING ,
1669                      XmNtopAttachment  , XmATTACH_WIDGET ,
1670                      XmNtopOffset      , T3D_FORM_SPACING ,
1671                      XtNmappedWhenManaged , False ,
1672                   NULL ) ;
1673 
1674    MCW_reghelp_children( wset.anatomy_type_av->wrowcol ,
1675     "Use the arrows to specify\n"
1676     "the type of anatomical data\n"
1677     "stored in the image files" ) ;
1678    MCW_reghint_children( wset.anatomy_type_av->wrowcol ,
1679                          "Type of anatomical data" ) ;
1680 
1681    /*----- stat_aux data fields -----*/
1682 
1683    wset.stat_aux_label =
1684       XtVaCreateManagedWidget(
1685          "dialog" , xmLabelWidgetClass , wset.topform ,
1686             XmNleftAttachment , XmATTACH_FORM ,
1687             XmNleftOffset     , T3D_FORM_SPACING ,
1688             XmNtopAttachment  , XmATTACH_WIDGET ,
1689             XmNtopWidget      , wset.dataset_type_av->wrowcol ,
1690             XmNtopOffset      , T3D_FORM_SPACING ,
1691          NULL ) ;
1692 
1693    wset.stat_aux_textfield =
1694       XtVaCreateManagedWidget(
1695          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1696             XmNcolumns        , 80 ,
1697             XmNeditable       , True ,
1698             XmNmaxLength      , THD_MAX_NAME-1 ,
1699             XmNresizeWidth    , False ,
1700             XmNcursorPositionVisible , True ,
1701             XmNblinkRate , 0 ,
1702             XmNleftAttachment , XmATTACH_FORM ,
1703             XmNleftOffset     , T3D_FORM_SPACING ,
1704             XmNtopAttachment  , XmATTACH_WIDGET ,
1705             XmNtopWidget      , wset.stat_aux_label ,
1706             XmNtopOffset      , 1 ,
1707          NULL ) ;
1708 
1709     MCW_register_help( wset.stat_aux_label ,
1710       "Some types of functional data require input\n"
1711       "of extra statistical parameters.  These\n"
1712       "values should be entered in the text field\n"
1713       "below, separated by spaces and/or commas.\n"
1714       "\n"
1715       " Inten+Cor requires the number of\n"
1716       "   samples (images) used, the number of\n"
1717       "   fitting parameters, and the number of\n"
1718       "   orthogonalization parameters.\n"
1719       "\n"
1720       " Inten+Ttest requires the number of\n"
1721       "   degrees-of-freedom in the t-test."
1722     ) ;
1723 
1724     MCW_register_help( wset.stat_aux_textfield ,
1725       "Some types of functional data require input\n"
1726       "of extra statistical parameters.  These\n"
1727       "values should be entered in this text field,\n"
1728       "separated by spaces and/or commas.\n"
1729       "\n"
1730       " Inten+Cor requires the number of\n"
1731       "   samples (images) used, the number of\n"
1732       "   fitting parameters, and the number of\n"
1733       "   orthogonalization parameters.\n"
1734       "\n"
1735       " Inten+Ttest requires the number of\n"
1736       "   degrees-of-freedom in the t-test."
1737     ) ;
1738 
1739     MCW_register_hint( wset.stat_aux_label , "Extra statistical parameters" ) ;
1740     MCW_register_hint( wset.stat_aux_textfield , "Extra statistical parameters" ) ;
1741 
1742    /** The stuff below is commented out,
1743        since the textfield is scanned only at the write-out time **/
1744 
1745 #if 0
1746    XtAddCallback( wset.stat_aux_textfield ,
1747                   XmNactivateCallback ,
1748                   T3D_stat_aux_CB , NULL ) ;    /* return key */
1749 
1750    XtAddCallback( wset.stat_aux_textfield ,
1751                   XmNlosingFocusCallback ,
1752                   T3D_stat_aux_CB , NULL ) ;    /* Tab key */
1753 
1754    XtInsertEventHandler( wset.stat_aux_textfield ,
1755                          LeaveWindowMask ,             /* pointer leaves */
1756                          FALSE ,
1757                          T3D_pointer_leave_EV , NULL ,
1758                          XtListTail ) ;                /* last in queue */
1759 #endif
1760 
1761    /*--- output locations ---*/
1762 
1763    wset.output_file_label =
1764       XtVaCreateManagedWidget(
1765          "dialog" , xmLabelWidgetClass , wset.topform ,
1766             LABEL_ARG("Prefix for 3D  \nDataset file   ") ,
1767 
1768             XmNleftAttachment , XmATTACH_WIDGET ,
1769             XmNleftWidget     , wset.geometry_parent_textfield ,
1770             XmNleftOffset     , T3D_FORM_SPACING ,
1771             XmNtopAttachment  , XmATTACH_WIDGET ,
1772             XmNtopWidget      , wset.stat_aux_textfield ,
1773             XmNtopOffset      , T3D_FORM_SPACING ,
1774             XmNbottomAttachment , XmATTACH_FORM ,
1775             XmNbottomOffset     , T3D_FORM_SPACING ,
1776          NULL ) ;
1777 
1778    wset.output_file_textfield =
1779       XtVaCreateManagedWidget(
1780          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1781             XmNcolumns         , T3D_NAME_WIDTH ,
1782             XmNeditable        , True ,
1783             XmNmaxLength       , THD_MAX_PREFIX-1 ,
1784             XmNresizeWidth     , False ,
1785             XmNcursorPositionVisible , True ,
1786             XmNblinkRate , 0 ,
1787 /*
1788             XmNmarginHeight    , 1 ,
1789             XmNmarginWidth     , 1 ,
1790 */
1791             XmNvalue           , user_inputs.output_filename ,
1792 
1793             XmNleftAttachment , XmATTACH_WIDGET ,
1794             XmNleftOffset     , T3D_FORM_SPACING ,
1795             XmNleftWidget     , wset.output_file_label ,
1796             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1797             XmNtopWidget      , wset.output_file_label ,
1798             XmNtopOffset      , 0 ,
1799 
1800          NULL ) ;
1801 
1802    MCW_register_help( wset.output_file_label ,
1803     "Type in the 'prefix' for the filenames\n"
1804     "that the 3D dataset will be saved in.\n"
1805     "[The actual filenames will be of the\n"
1806     " form prefix+orig.suff, where suff =\n"
1807     " " DATASET_HEADER_SUFFIX " and " DATASET_BRICK_SUFFIX "]" ) ;
1808 
1809    MCW_register_help( wset.output_file_textfield ,
1810     "Type in the 'prefix' for the filenames\n"
1811     "that the 3D dataset will be saved in.\n"
1812     "[The actual filenames will be of the\n"
1813     " form prefix+orig.suff, where suff =\n"
1814     " " DATASET_HEADER_SUFFIX " and " DATASET_BRICK_SUFFIX "]" ) ;
1815 
1816    MCW_register_hint( wset.output_file_label ,
1817                       "New dataset's 'prefix' for filenames" ) ;
1818    MCW_register_hint( wset.output_file_textfield ,
1819                       "New dataset's 'prefix' for filenames" ) ;
1820 
1821    wset.session_file_label =
1822       XtVaCreateManagedWidget(
1823          "dialog" , xmLabelWidgetClass , wset.topform ,
1824             LABEL_ARG("Session direct.\nfor 3D Datasets") ,
1825 
1826             XmNleftAttachment , XmATTACH_FORM ,
1827             XmNleftOffset     , T3D_FORM_SPACING ,
1828             XmNtopAttachment  , XmATTACH_WIDGET ,
1829             XmNtopWidget      , wset.stat_aux_textfield ,
1830             XmNtopOffset      , T3D_FORM_SPACING ,
1831          NULL ) ;
1832 
1833    wset.session_file_textfield =
1834       XtVaCreateManagedWidget(
1835          "dialog" , xmTextFieldWidgetClass , wset.topform ,
1836             XmNcolumns         , T3D_NAME_WIDTH ,
1837             XmNeditable        , True ,
1838             XmNmaxLength       , THD_MAX_NAME-1 ,
1839             XmNresizeWidth     , False ,
1840             XmNcursorPositionVisible , True ,
1841             XmNblinkRate , 0 ,
1842 /*
1843             XmNmarginHeight    , 1 ,
1844             XmNmarginWidth     , 1 ,
1845 */
1846             XmNvalue           , user_inputs.session_filename ,
1847 
1848             XmNleftAttachment , XmATTACH_WIDGET ,
1849             XmNleftOffset     , T3D_FORM_SPACING ,
1850             XmNleftWidget     , wset.session_file_label ,
1851             XmNtopAttachment  , XmATTACH_OPPOSITE_WIDGET ,
1852             XmNtopWidget      , wset.session_file_label ,
1853             XmNtopOffset      , 0 ,
1854 
1855          NULL ) ;
1856 
1857    MCW_register_help( wset.session_file_label ,
1858     "Type in the name of the session\n"
1859     "directory in which to save this\n"
1860     "3D dataset, and in which to look\n"
1861     "for the 'parent' datasets" ) ;
1862 
1863    MCW_register_help( wset.session_file_textfield ,
1864     "Type in the name of the session\n"
1865     "directory in which to save this\n"
1866     "3D dataset, and in which to look\n"
1867     "for the 'parent' datasets" ) ;
1868 
1869    MCW_register_hint( wset.session_file_label , "New dataset's directory" ) ;
1870    MCW_register_hint( wset.session_file_textfield , "New dataset's directory" ) ;
1871 
1872    printf(".");fflush(stdout);
1873 
1874    /*----- action controls at lower right corner -----*/
1875 
1876    wset.action_frame =
1877       XtVaCreateManagedWidget(
1878          "dialog" , xmFrameWidgetClass , wset.topform ,
1879             XmNshadowType       , XmSHADOW_ETCHED_IN ,
1880             XmNleftAttachment   , XmATTACH_WIDGET ,
1881             XmNleftWidget       , wset.anatomy_parent_textfield ,
1882             XmNleftOffset       , T3D_FORM_SPACING ,
1883             XmNbottomAttachment , XmATTACH_FORM ,
1884             XmNbottomOffset     , T3D_FORM_SPACING ,
1885          NULL ) ;
1886 
1887    wset.action_rowcol =
1888       XtVaCreateWidget(
1889          "dialog" , xmRowColumnWidgetClass , wset.action_frame ,
1890             XmNorientation , XmVERTICAL ,
1891             XmNpacking     , XmPACK_TIGHT ,
1892          NULL ) ;
1893 
1894    /* 14 Sep 1998: add a button to swap bytes in the image data */
1895 
1896    { int    dd = mri_datum_size((MRI_TYPE)argopt.datum_all) ;
1897      char * tt = "Byte Swap[2]" ;
1898      char * ff = "Byte Swap[4]" ;
1899      if( dd == 2 || dd == 4 ){
1900         if( dd == 2 )
1901            wset.swap_pb =
1902             XtVaCreateManagedWidget(
1903                "dialog" , xmPushButtonWidgetClass , wset.action_rowcol ,
1904                   LABEL_ARG(tt) , NULL ) ;
1905          else
1906            wset.swap_pb =
1907             XtVaCreateManagedWidget(
1908                "dialog" , xmPushButtonWidgetClass , wset.action_rowcol ,
1909                   LABEL_ARG(ff) , NULL ) ;
1910 
1911          XtAddCallback( wset.swap_pb , XmNactivateCallback ,
1912                         T3D_swap_CB , NULL ) ;
1913          MCW_register_hint( wset.swap_pb , "Use if images need this" ) ;
1914      } else {
1915         wset.swap_pb = NULL ;
1916      }
1917    }
1918 
1919    wset.button_help_pb =
1920       XtVaCreateManagedWidget(
1921          "dialog" , xmPushButtonWidgetClass , wset.action_rowcol ,
1922             LABEL_ARG("button help") ,
1923          NULL ) ;
1924    XtAddCallback( wset.button_help_pb , XmNactivateCallback ,
1925                   MCW_click_help_CB , NULL ) ;
1926    MCW_register_help( wset.button_help_pb ,
1927      "Click the hand\non any button to get\na little help" ) ;
1928    MCW_register_hint( wset.button_help_pb , "Get more help" ) ;
1929 
1930    wset.open_view_pb =
1931       XtVaCreateManagedWidget(
1932          "dialog" , xmPushButtonWidgetClass , wset.action_rowcol ,
1933             LABEL_ARG("View Images") ,
1934          NULL ) ;
1935    XtAddCallback( wset.open_view_pb , XmNactivateCallback ,
1936                   T3D_open_view_CB , NULL ) ;
1937    MCW_register_help( wset.open_view_pb ,
1938     "Use this to open a window to see the images;\n"
1939     "N.B.: If you use the viewing controls to change the\n"
1940     "      orientation of the images, then you must be\n"
1941     "      aware that 'x' and 'y' in the geometry controls\n"
1942     "      above refer to the images in their ORIGINAL\n"
1943     "      orientation on the screen, NOT in the rotated\n"
1944     "      and/or mirrored orientation you will be viewing." ) ;
1945    MCW_register_hint( wset.open_view_pb , "See the input images" ) ;
1946 
1947    wset.save_file_pb =
1948       XtVaCreateManagedWidget(
1949          "dialog" , xmPushButtonWidgetClass , wset.action_rowcol ,
1950             LABEL_ARG("Save Dataset") ,
1951          NULL ) ;
1952    XtAddCallback( wset.save_file_pb , XmNactivateCallback ,
1953                   T3D_save_file_CB , NULL ) ;
1954    MCW_register_help( wset.save_file_pb ,
1955     "Use this to save the volume data\n"
1956     "into 3D dataset files when you\n"
1957     "have set all the control data." ) ;
1958    MCW_register_hint( wset.save_file_pb , "Write new dataset to disk" ) ;
1959 
1960    wset.quit_pb =
1961       XtVaCreateManagedWidget(
1962          "dialog" , xmPushButtonWidgetClass , wset.action_rowcol ,
1963             XmNrecomputeSize , False ,
1964             LABEL_ARG("quit") ,
1965          NULL ) ;
1966    XtAddCallback( wset.quit_pb , XmNactivateCallback ,
1967                   T3D_quit_CB , NULL ) ;
1968    MCW_register_help( wset.quit_pb ,
1969     "Press this button TWICE\nto exit the program" ) ;
1970    MCW_register_hint( wset.quit_pb , "Press twice to exit program" ) ;
1971 
1972    MCW_set_widget_bg( wset.quit_pb , MCW_hotcolor(wset.quit_pb) , 0 ) ;
1973 
1974    XtManageChild( wset.action_rowcol ) ;
1975 
1976    printf(".");fflush(stdout);
1977 
1978    /*----- all done -----*/
1979 
1980    XtManageChild( wset.topform ) ;
1981 
1982    XtRealizeWidget( wset.topshell ) ; NI_sleep(1) ;
1983    WAIT_for_window( wset.topshell ) ; /* 10 Sep 2002 */
1984    wset.good = 1 ;
1985 
1986    T3D_data_to_widgets() ;
1987    T3D_set_dependent_geometries() ;
1988 
1989    EXRETURN ;
1990 }
1991 
1992 /*---------------------------------------------------------------------
1993    Read any command line arguments and interpret them into
1994    the user_inputs data structure.
1995 -----------------------------------------------------------------------*/
1996 
1997 static to3d_data default_user_inputs = {
1998    ORI_R2L_TYPE , ORI_R2L_TYPE , ORI_R2L_TYPE ,      /* orientations */
1999    VOXSHAPE_IRREGULAR ,                              /* not really used */
2000    VOXCONTIG_YES ,                                   /* really used */
2001    (XCENTERED | YCENTERED | ZCENTERED) ,             /* axes centered ? */
2002    VIEW_ORIGINAL_TYPE ,                              /* original view */
2003    HEAD_ANAT_TYPE , ANAT_SPGR_TYPE , FUNC_FIM_TYPE , /* data types */
2004    0,0,0 ,                                           /* images sizes */
2005 
2006    240.0 , 0.9375 , 0.9375 , 0.9375 , 0.9375 ,  /* FOV; x,y,z sizes; z spacing */
2007 
2008    120.0 , 120.0 , 120.0   /* x,y,z origins */
2009 } ;
2010 
2011 #define EMPTY_STRING(str) ((str)[0] = '\0')
2012 
2013 /*.....................................................................*/
2014 
2015 #define WarningError(str) \
2016   { fprintf(stderr,"\n++ WARNING: %s\n",(str)) ; nopt++ ; continue ; }
2017 
T3D_initialize_user_data(void)2018 void T3D_initialize_user_data(void)
2019 {
2020    int nopt , ii ;
2021 
2022 ENTRY("T3D_initialize_user_data") ;
2023 
2024    user_inputs = default_user_inputs ;  /* copy defaults */
2025    user_inputs.nosave = 0 ;        /* save data  - head and brik */
2026    user_inputs.writebrik = 1;      /* write dataset brik out by default  */
2027 
2028    /*-- initialize strings --*/
2029 
2030    EMPTY_STRING( user_inputs.dataset_name ) ;
2031    EMPTY_STRING( user_inputs.short_label1 ) ;
2032    EMPTY_STRING( user_inputs.short_label2 ) ;
2033    EMPTY_STRING( user_inputs.geometry_parent_filename ) ;
2034    EMPTY_STRING( user_inputs.anatomy_parent_filename ) ;
2035    EMPTY_STRING( user_inputs.anatomy_dataname ) ;
2036    EMPTY_STRING( user_inputs.geometry_dataname ) ;
2037    EMPTY_STRING( user_inputs.output_filename ) ;
2038    ZERO_IDCODE( user_inputs.anatomy_parent_idcode ) ;
2039 
2040    strcpy( user_inputs.session_filename , "./" ) ;
2041 
2042    strcpy( user_inputs.dataset_type_string ,
2043            DATASET_typestr[user_inputs.dataset_type] ) ;
2044 
2045    strcpy( user_inputs.function_type_string ,
2046            FUNC_typestr[user_inputs.function_type] ) ;
2047 
2048    user_inputs.view_type = VIEW_ORIGINAL_TYPE ;
2049 
2050    for( ii=0 ; ii < MAX_STAT_AUX ; ii++ )
2051       user_inputs.stat_aux[ii] = 0.0 ;
2052 
2053    user_inputs.xincode = user_inputs.yincode = user_inputs.zincode = INCODE_NONE ;
2054 
2055    user_inputs.ntt      = 0 ;
2056    user_inputs.TR       = 1.0 ;
2057    user_inputs.Torg     = 0.0 ;  /* 23 Feb 2005 */
2058    user_inputs.nzz      = 0 ;
2059    user_inputs.t_then_z = 0 ;
2060    user_inputs.tpattern = NULL ;
2061    user_inputs.tunits   = UNITS_MSEC_TYPE ;  /* bad default */
2062 
2063    /*-- 05 Feb 2000: zpad environment --*/
2064 
2065    { char *eee=my_getenv("AFNI_TO3D_ZPAD") , *fff ;
2066      if( eee != NULL ){
2067          zpad = strtod( eee , &fff ) ;
2068          if( zpad < 0.0 ) ERROR_exit("AFNI_TO3D_ZPAD is negative") ;
2069          zpad_mm = (*fff == 'm') ;
2070      }
2071    }
2072 
2073    /*-- scan options --*/
2074 
2075    nopt = 1 ;
2076    while( nopt < Argc && Argv[nopt][0] == '-' ){
2077 
2078       if( strncmp(Argv[nopt],"-help",4) == 0 ){
2079          Syntax() ;
2080       }
2081 
2082       /* -type from the anatomy prefixes */
2083 
2084       for( ii=FIRST_ANAT_TYPE ; ii <= LAST_ANAT_TYPE ; ii++ )
2085          if( strncmp( &(Argv[nopt][1]) ,
2086                       ANAT_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
2087 
2088       if( ii <= LAST_ANAT_TYPE ){
2089          user_inputs.anatomy_type = ii ;
2090          user_inputs.dataset_type = HEAD_ANAT_TYPE ;
2091          strcpy( user_inputs.dataset_type_string ,
2092                  DATASET_typestr[user_inputs.dataset_type] ) ;
2093          strcpy( user_inputs.anatomy_type_string ,
2094                  ANAT_typestr[user_inputs.anatomy_type] ) ;
2095 
2096          af_type_set = 1 ; nopt++ ; continue ;
2097       }
2098 
2099       /* -type from the function prefixes */
2100 
2101       for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ )
2102          if( strncmp( &(Argv[nopt][1]) ,
2103                       FUNC_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
2104 
2105       if( ii <= LAST_FUNC_TYPE ){
2106          user_inputs.function_type = ii ;
2107          user_inputs.dataset_type = HEAD_FUNC_TYPE ;
2108          strcpy( user_inputs.dataset_type_string ,
2109                  DATASET_typestr[user_inputs.dataset_type] ) ;
2110          strcpy( user_inputs.function_type_string ,
2111                  FUNC_typestr[user_inputs.function_type] ) ;
2112 
2113          af_type_set = 1 ; nopt++ ; continue ;
2114       }
2115 
2116       /*--- -in:1 ---*/
2117 
2118       if( strncmp(Argv[nopt],"-in:1",5) == 0 ){
2119          argopt.delay_input = TRUE ;
2120          nopt++ ; continue ;
2121       }
2122 
2123       /*--- -view type ---*/
2124 
2125       if( strncmp(Argv[nopt],"-view",4) == 0 ){
2126          char * str ;
2127 
2128          if( ++nopt >= Argc ) ERROR_exit("-view needs a type") ;
2129 
2130          str = Argv[nopt] ; if( str[0] == '+' ) str++ ;
2131 
2132          for( ii=FIRST_VIEW_TYPE ; ii <= LAST_VIEW_TYPE ; ii++ )
2133             if( strcmp(str,VIEW_codestr[ii]) == 0 ) break ;
2134 
2135          if( ii <= LAST_VIEW_TYPE ){
2136             user_inputs.view_type = ii ;
2137          } else {
2138             WarningError("Unknown view type after -view!") ;
2139          }
2140          nopt++ ; continue ;
2141       }
2142 
2143       /* 05 Feb 2001: -zpad option */
2144 
2145       if( strncmp(Argv[nopt],"-zpad",5) == 0 ){
2146          char * eee ;
2147          if( ++nopt >= Argc ) ERROR_exit("-zpad needs a count") ;
2148          if( zpad > 0.0 ) fprintf(stderr,"++ WARNING: second -zpad option found!\n") ;
2149          zpad = strtod( Argv[nopt] , &eee ) ;
2150          if( zpad < 0.0 ) ERROR_exit("-zpad is negative") ;
2151          zpad_mm = (*eee == 'm') ;
2152          nopt++ ; continue ;
2153       }
2154 
2155       /*--- -session name ---*/
2156 
2157       if( strncmp(Argv[nopt],"-session",4) == 0 ){
2158          if( ++nopt >= Argc ) ERROR_exit("-session needs a name") ;
2159          MCW_strncpy( user_inputs.session_filename, Argv[nopt], THD_MAX_NAME ) ;
2160          nopt++ ; continue ;
2161       }
2162 
2163       /*--- -prefix name ---*/
2164 
2165       if( strncmp(Argv[nopt],"-prefix",4) == 0 ){
2166          if( ++nopt >= Argc ) ERROR_exit("-prefix needs a name") ;
2167          MCW_strncpy( user_inputs.output_filename , Argv[nopt] , THD_MAX_NAME ) ;
2168          nopt++ ; continue ;
2169       }
2170 
2171 #ifndef NO_NAMES
2172       /*--- -dname name ---*/
2173 
2174       if( strncmp(Argv[nopt],"-dname",4) == 0 ){
2175          if( ++nopt >= Argc ) ERROR_exit("-dname needs a name") ;
2176          MCW_strncpy( user_inputs.dataset_name , Argv[nopt] , THD_MAX_NAME ) ;
2177          nopt++ ; continue ;
2178       }
2179 
2180       /*--- -dlabel name ---*/
2181 
2182       if( strncmp(Argv[nopt],"-dlabel",4) == 0 ){
2183          if( ++nopt >= Argc ) ERROR_exit("-dlabel needs a name") ;
2184          MCW_strncpy( user_inputs.short_label1 , Argv[nopt] , THD_MAX_LABEL ) ;
2185          nopt++ ; continue ;
2186       }
2187 #endif
2188 
2189       /*--- -geomparent headerfile ---*/
2190 
2191       if( strncmp(Argv[nopt],"-geomparent",6) == 0 ){
2192          if( ++nopt >= Argc ) ERROR_exit("-geomparent needs a headerfile" ) ;
2193          MCW_strncpy( user_inputs.geometry_parent_filename ,
2194                       Argv[nopt] , THD_MAX_NAME ) ;
2195          nopt++ ; continue ;
2196       }
2197 
2198       /*--- -anatparent headerfile ---*/
2199 
2200       if( strncmp(Argv[nopt],"-anatparent",6) == 0 ){
2201          if( ++nopt >= Argc ) ERROR_exit("-anatparent needs a headerfile" ) ;
2202          MCW_strncpy( user_inputs.anatomy_parent_filename ,
2203                       Argv[nopt] , THD_MAX_NAME ) ;
2204          nopt++ ; continue ;
2205       }
2206 
2207       /*--- -nosave ---*/
2208 
2209       if( strncmp(Argv[nopt],"-nosave",4) == 0 ){
2210          user_inputs.nosave = 1 ;
2211          nopt++ ; continue ;
2212       }
2213 
2214       /*---- -nowritebrik -----*/
2215       if( strncmp(Argv[nopt],"-nowritebrik",4) == 0 ){
2216          user_inputs.writebrik = 0 ;
2217          nopt++ ; continue ;
2218       }
2219 
2220       /*--- 25 Sep 2001: -sinter option ---*/
2221 
2222       if( strcmp(Argv[nopt],"-sinter") == 0 ){
2223          putenv("AFNI_SIEMENS_INTERLEAVE=Yes") ; nopt++ ; continue ;
2224       }
2225 
2226       /*--- 15 Aug 2001: -skip_outliers ---*/
2227 
2228       if( strcmp(Argv[nopt],"-skip_outliers") == 0 ){
2229          putenv("AFNI_TO3D_OUTLIERS=No") ; nopt++ ; continue ;
2230       }
2231 
2232       if( strcmp(Argv[nopt],"-text_outliers") == 0 ){
2233          putenv("AFNI_TO3D_OUTLIERS=Text") ; nopt++ ; continue ;
2234       }
2235 
2236       /*--- 26 Aug 2001: -save_outliers ---*/
2237 
2238       if( strcmp(Argv[nopt],"-save_outliers") == 0 ){
2239          if(++nopt > Argc) ERROR_exit("-save_outliers needs a filename") ;
2240          outliers_fname = Argv[nopt] ;
2241          if( !THD_filename_ok(outliers_fname) )
2242             ERROR_exit("-save_outliers filename is illegal") ;
2243          nopt++ ; continue ;
2244       }
2245 
2246       /*--- July 1997: -orient code ---*/
2247 
2248       if( strncmp(Argv[nopt],"-orient",4) == 0 ){
2249          char acod ;
2250 
2251          if( ++nopt >= Argc ) ERROR_exit("-orient needs a code") ;
2252          if( strlen(Argv[nopt]) != 3 ) ERROR_exit("Illegal -orient code") ;
2253          acod = toupper(Argv[nopt][0]) ; user_inputs.xorient = ORCODE(acod) ;
2254          acod = toupper(Argv[nopt][1]) ; user_inputs.yorient = ORCODE(acod) ;
2255          acod = toupper(Argv[nopt][2]) ; user_inputs.zorient = ORCODE(acod) ;
2256          nopt++ ; continue ;
2257       }
2258 
2259       if( strncmp(Argv[nopt],"-zorigin",7) == 0 ){
2260          if( ++nopt >= Argc ) ERROR_exit("-zorigin needs a value") ;
2261          zoff = strtod( Argv[nopt] , NULL ) ;
2262          use_zoff = 1 ;
2263          nopt++ ; continue ;
2264       }
2265 
2266       /********** April 1996: new options for setting dimensions **********/
2267 
2268 /** 21 Nov 1997: alter the way dimensions are decoded **/
2269 #undef USE_OLD_DCODE
2270 
2271       /*--- -xFOV or -xSLAB ---*/
2272 
2273       if( strncmp(Argv[nopt],"-xFOV",5)==0 || strncmp(Argv[nopt],"-xSLAB",5)==0 ||
2274           strncmp(Argv[nopt],"-xfov",5)==0 || strncmp(Argv[nopt],"-xslab",5)==0   ){
2275          float val , xin_bot , xin_top ;
2276          char * ptr , * ptr2 , acod ;
2277          int dcod1 , dcod2 , xincode ;
2278 
2279          xincode = ( strncmp(Argv[nopt],"-xFOV",5)==0 ||
2280                      strncmp(Argv[nopt],"-xfov",5)==0   ) ? INCODE_FOV : INCODE_SLAB ;
2281 
2282          if( ++nopt >= Argc ) WarningError("need an argument after -xFOV/-xSLAB!") ;
2283 
2284          /* should now have something of one of the forms
2285                <number> <dircode> : <number> <dircode>
2286                <number> <dircode> - <number> <dircode>
2287                <number> <dircode> : <dircode>
2288                <number> <dircode> - <dircode>
2289 
2290             Step 1: get the first <number>   */
2291 
2292 #ifdef USE_OLD_DCODE
2293          val = strtod( Argv[nopt] , &ptr ) ;
2294          if( val < 0.0 || (val == 0.0 && ptr == Argv[nopt]) )
2295             WarningError("a nonegative number should follow -xFOV/-xSLAB!") ;
2296 
2297          xin_bot = val ;
2298 
2299          /* Step 2: get the first <dircode> */
2300 
2301          acod = toupper( *ptr ) ; dcod1 = ORCODE(acod) ; ptr++ ;
2302          if( dcod1 < 0 )
2303             WarningError("orientation code should follow first dimension in -xFOV/-xSLAB!") ;
2304 #else
2305          { int nused ;
2306            nused = decode_location( Argv[nopt] , &xin_bot , &dcod1 ) ;
2307            if( xin_bot < 0.0 || xin_bot == WAY_BIG )
2308              WarningError("a nonegative number should follow -xFOV/-xSLAB!") ;
2309            if( dcod1 < 0 )
2310              WarningError("1st orientation code illegal after -xFOV/-xSLAB!") ;
2311            ptr = Argv[nopt] + nused ;
2312          }
2313 #endif
2314 
2315 
2316          /* Step 3: get the separator */
2317 
2318          if( *ptr != ':' && *ptr != '-' )
2319 #ifdef USE_OLD_DCODE
2320             WarningError(": or - should follow orientation code in -xFOV/-xSLAB!") ;
2321 #else
2322             WarningError(": or - should follow 1st dimension in -xFOV/-xSLAB!") ;
2323 #endif
2324          ptr++ ;
2325          if( *ptr == '\0' )
2326             WarningError("orientation code or dimension should follow : or - in -xFOV/-xSLAB!") ;
2327 
2328          /* Step 4: try to get the second <dircode>.  If that fails, then get
2329                     the second <number> first, then the second <dircode>.
2330                     If the second <dircode> works, however, then the second
2331                     <number> is defined to be equal to the first <number>.   */
2332 
2333 #ifdef USE_OLD_DCODE
2334          acod = toupper( *ptr ) ; dcod2 = ORCODE(acod) ;
2335          if( dcod2 < 0 ){
2336             val = strtod( ptr , &ptr2 ) ;
2337             if( val < 0.0 || (val == 0.0 && ptr2 == ptr) )
2338               WarningError("orientation code or dimension should follow : or - in -xFOV/-xSLAB!") ;
2339             xin_top = val ;
2340             ptr = ptr2 ;
2341             acod = toupper( *ptr ) ; dcod2 = ORCODE(acod) ;
2342             if( dcod2 < 0 )
2343                WarningError("orientation code should follow second dimension in -xFOV/-xSLAB!") ;
2344          } else {
2345             xin_top = xin_bot ;
2346          }
2347 #else
2348          { int nused ;
2349            nused = decode_location( ptr , &xin_top , &dcod2 ) ;
2350            if( dcod2 < 0 )
2351              WarningError("need 2nd orientation code in -xFOV/-xSLAB!") ;
2352            if( xin_top < 0.0 )
2353              WarningError("need nonegative 2nd dimension in -xFOV/-xSLAB!") ;
2354            if( xin_top == WAY_BIG ){
2355              xin_top = xin_bot ;
2356              if( xincode == INCODE_FOV )
2357                INFO_message("%s: FOV width is %g mm",
2358                             Argv[nopt-1],2*fabs(xin_bot));
2359            }
2360          }
2361 #endif
2362 
2363          /* Now, check for consistency:
2364               Direction codes should be in the same or opposite directions;
2365               however, must be opposite if the two <number>s are identical.
2366               For example 120A-120A makes no sense,
2367               but 120A-120P is reasonable, and 10A-30A is also reasonable.  */
2368 
2369          if( xin_top == xin_bot && dcod1 != ORIENT_OPPOSITE(dcod2) )
2370             WarningError("zero thickness slab specified in -xFOV/-xSLAB!") ;
2371 
2372          if( dcod1 != dcod2 && dcod1 != ORIENT_OPPOSITE(dcod2) )
2373             WarningError("inconsistent directions given in -xFOV/-xSLAB!") ;
2374 
2375          /* If the direction codes are the same, then if the first <number>
2376             is smaller, reverse the first direction code and negate the
2377             first number.  For example, 10A:30A becomes -10P:30A, which is
2378             equivalent.  If the first number is larger, then reverse the
2379             second code and number.  For example, 30A:10A becomes 30A:-10P.
2380             Why do this?  Then the first direction code correctly expresses
2381             the sense of the input direction. The sum of numbers becomes
2382             the cross-slab thickness, needed to compute various stuff later. */
2383 
2384          if( dcod1 == dcod2 ){
2385             if( xin_bot < xin_top ){
2386                dcod1   = ORIENT_OPPOSITE(dcod1) ;
2387                xin_bot = -xin_bot ;
2388             } else {
2389                dcod2   = ORIENT_OPPOSITE(dcod2) ;
2390                xin_top = -xin_top ;
2391             }
2392          }
2393 
2394          /* All is OK, so store the results */
2395 
2396          user_inputs.xincode = xincode + dcod1 ;
2397          user_inputs.xin_bot = xin_bot ;
2398          user_inputs.xin_top = xin_top ;
2399 
2400 #if 0
2401 printf("decoded %s to give xincode=%d bot=%f top=%f\n",Argv[nopt],
2402        user_inputs.xincode, user_inputs.xin_bot, user_inputs.xin_top ) ;
2403 #endif
2404 
2405          nopt++ ; continue ;
2406       }
2407 
2408       /*--- -yFOV or -ySLAB ---*/
2409 
2410       if( strncmp(Argv[nopt],"-yFOV",5)==0 || strncmp(Argv[nopt],"-ySLAB",5)==0 ||
2411           strncmp(Argv[nopt],"-yfov",5)==0 || strncmp(Argv[nopt],"-yslab",5)==0   ){
2412 
2413          float val , yin_bot , yin_top ;
2414          char * ptr , * ptr2 , acod ;
2415          int dcod1 , dcod2 , yincode ;
2416 
2417          yincode = ( strncmp(Argv[nopt],"-yFOV",5)==0 ||
2418                      strncmp(Argv[nopt],"-yfov",5)==0   ) ? INCODE_FOV : INCODE_SLAB ;
2419 
2420          if( ++nopt >= Argc ) WarningError("need an argument after -yFOV/-ySLAB!") ;
2421 
2422          /* should now have something of one of the forms
2423                <number> <dircode> : <number> <dircode>
2424                <number> <dircode> - <number> <dircode>
2425                <number> <dircode> : <dircode>
2426                <number> <dircode> - <dircode>
2427 
2428             Step 1: get the first <number>   */
2429 
2430 #ifdef USE_OLD_DCODE
2431          val = strtod( Argv[nopt] , &ptr ) ;
2432          if( val < 0.0 || (val == 0.0 && ptr == Argv[nopt]) )
2433             WarningError("a nonegative number should follow -yFOV/-ySLAB!") ;
2434 
2435          yin_bot = val ;
2436 
2437          /* Step 2: get the first <dircode> */
2438 
2439          acod = toupper( *ptr ) ; dcod1 = ORCODE(acod) ; ptr++ ;
2440          if( dcod1 < 0 )
2441             WarningError("orientation code should follow first dimension in -yFOV/-ySLAB!") ;
2442 #else
2443          { int nused ;
2444            nused = decode_location( Argv[nopt] , &yin_bot , &dcod1 ) ;
2445            if( yin_bot < 0.0 || yin_bot == WAY_BIG )
2446              WarningError("a nonegative number should follow -yFOV/-ySLAB!") ;
2447            if( dcod1 < 0 )
2448              WarningError("1st orientation code illegal after -yFOV/-ySLAB!") ;
2449            ptr = Argv[nopt] + nused ;
2450          }
2451 #endif
2452 
2453          /* Step 3: get the separator */
2454 
2455          if( *ptr != ':' && *ptr != '-' )
2456 #ifdef USE_OLD_DCODE
2457             WarningError(": or - should follow orientation code in -yFOV/-ySLAB!") ;
2458 #else
2459             WarningError(": or - should follow 1st dimension in -yFOV/-ySLAB!") ;
2460 #endif
2461 
2462          ptr++ ;
2463          if( *ptr == '\0' )
2464             WarningError("orientation code or dimension should follow : or - in -yFOV/-ySLAB!") ;
2465 
2466          /* Step 4: try to get the second <dircode>.  If that fails, then get
2467                     the second <number> first, then the second <dircode>.
2468                     If the second <dircode> works, however, then the second
2469                     <number> is defined to be equal to the first <number>.   */
2470 
2471 #ifdef USE_OLD_DCODE
2472          acod = toupper( *ptr ) ; dcod2 = ORCODE(acod) ;
2473          if( dcod2 < 0 ){
2474             val = strtod( ptr , &ptr2 ) ;
2475             if( val < 0.0 || (val == 0.0 && ptr2 == ptr) )
2476               WarningError("orientation code or dimension should follow : or - in -yFOV/-ySLAB!") ;
2477             yin_top = val ;
2478             ptr = ptr2 ;
2479             acod = toupper( *ptr ) ; dcod2 = ORCODE(acod) ;
2480             if( dcod2 < 0 )
2481                WarningError("orientation code should follow second dimension in -yFOV/-ySLAB!") ;
2482          } else {
2483             yin_top = yin_bot ;
2484          }
2485 #else
2486          { int nused ;
2487            nused = decode_location( ptr , &yin_top , &dcod2 ) ;
2488            if( dcod2 < 0 )
2489              WarningError("need 2nd orientation code in -yFOV/-ySLAB!") ;
2490            if( yin_top < 0.0 )
2491              WarningError("need nonegative 2nd dimension in -yFOV/-ySLAB!") ;
2492            if( yin_top == WAY_BIG ){
2493              yin_top = yin_bot ;
2494              if( yincode == INCODE_FOV )
2495                INFO_message("%s: FOV width is %g mm",
2496                             Argv[nopt-1],2*fabs(yin_bot));
2497            }
2498          }
2499 #endif
2500 
2501          /* Now, check for consistency:
2502               Direction codes should be in the same or opposite directions;
2503               however, must be opposite if the two <number>s are identical.
2504               For example 120A-120A makes no sense,
2505               but 120A-120P is reasonable, and 10A-30A is also reasonable.  */
2506 
2507          if( yin_top == yin_bot && dcod1 != ORIENT_OPPOSITE(dcod2) )
2508             WarningError("zero thickness slab specified in -yFOV/-ySLAB!") ;
2509 
2510          if( dcod1 != dcod2 && dcod1 != ORIENT_OPPOSITE(dcod2) )
2511             WarningError("inconsistent directions given in -yFOV/-ySLAB!") ;
2512 
2513          /* If the direction codes are the same, then if the first <number>
2514             is smaller, reverse the first direction code and negate the
2515             first number.  For example, 10A:30A becomes -10P:30A, which is
2516             equivalent.  If the first number is larger, then reverse the
2517             second code and number.  For example, 30A:10A becomes 30A:-10P.
2518             Why do this?  Then the first direction code correctly expresses
2519             the sense of the input direction. The sum of numbers becomes
2520             the cross-slab thickness, needed to compute various stuff later. */
2521 
2522          if( dcod1 == dcod2 ){
2523             if( yin_bot < yin_top ){
2524                dcod1   = ORIENT_OPPOSITE(dcod1) ;
2525                yin_bot = -yin_bot ;
2526             } else {
2527                dcod2   = ORIENT_OPPOSITE(dcod2) ;
2528                yin_top = -yin_top ;
2529             }
2530          }
2531 
2532          /* All is OK, so store the results */
2533 
2534          user_inputs.yincode = yincode + dcod1 ;
2535          user_inputs.yin_bot = yin_bot ;
2536          user_inputs.yin_top = yin_top ;
2537 
2538 #if 0
2539 printf("decoded %s to give yincode=%d bot=%f top=%f\n",Argv[nopt],
2540        user_inputs.yincode, user_inputs.yin_bot, user_inputs.yin_top ) ;
2541 #endif
2542 
2543          nopt++ ; continue ;
2544       }
2545 
2546       /*--- -zFOV or -zSLAB ---*/
2547 
2548       if( strncmp(Argv[nopt],"-zFOV",5)==0 || strncmp(Argv[nopt],"-zSLAB",5)==0 ||
2549           strncmp(Argv[nopt],"-zfov",5)==0 || strncmp(Argv[nopt],"-zslab",5)==0   ){
2550 
2551          float val , zin_bot , zin_top ;
2552          char * ptr , * ptr2 , acod ;
2553          int dcod1 , dcod2 , zincode ;
2554 
2555          zincode = ( strncmp(Argv[nopt],"-zFOV",5)==0 ||
2556                      strncmp(Argv[nopt],"-zfov",5)==0   ) ? INCODE_FOV : INCODE_SLAB ;
2557 
2558          if( ++nopt >= Argc ) WarningError("need an argument after -zFOV/-zSLAB!") ;
2559 
2560          /* should now have something of one of the forms
2561                <number> <dircode> : <number> <dircode>
2562                <number> <dircode> - <number> <dircode>
2563                <number> <dircode> : <dircode>
2564                <number> <dircode> - <dircode>
2565 
2566             Step 1: get the first <number>   */
2567 
2568 #ifdef USE_OLD_DCODE
2569          val = strtod( Argv[nopt] , &ptr ) ;
2570          if( val < 0.0 || (val == 0.0 && ptr == Argv[nopt]) )
2571             WarningError("a nonegative number should follow -zFOV/-zSLAB!") ;
2572 
2573          zin_bot = val ;
2574 
2575          /* Step 2: get the first <dircode> */
2576 
2577          acod = toupper( *ptr ) ; dcod1 = ORCODE(acod) ; ptr++ ;
2578          if( dcod1 < 0 )
2579             WarningError("orientation code should follow first dimension in -zFOV/-zSLAB!") ;
2580 #else
2581          { int nused ;
2582            nused = decode_location( Argv[nopt] , &zin_bot , &dcod1 ) ;
2583            if( zin_bot < 0.0 || zin_bot == WAY_BIG )
2584              WarningError("a nonegative number should follow -yFOV/-ySLAB!") ;
2585            if( dcod1 < 0 )
2586              WarningError("1st orientation code illegal after -yFOV/-ySLAB!") ;
2587            ptr = Argv[nopt] + nused ;
2588          }
2589 #endif
2590 
2591          /* Step 3: get the separator */
2592 
2593          if( *ptr != ':' && *ptr != '-' )
2594 #ifdef USE_OLD_DCODE
2595             WarningError(": or - should follow orientation code in -zFOV/-zSLAB!") ;
2596 #else
2597             WarningError(": or - should follow 1st dimension in -zFOV/-zSLAB!") ;
2598 #endif
2599 
2600          ptr++ ;
2601          if( *ptr == '\0' )
2602             WarningError("orientation code or dimension should follow : or - in -zFOV/-zSLAB!") ;
2603 
2604          /* Step 4: try to get the second <dircode>.  If that fails, then get
2605                     the second <number> first, then the second <dircode>.
2606                     If the second <dircode> works, however, then the second
2607                     <number> is defined to be equal to the first <number>.   */
2608 
2609 #ifdef USE_OLD_DCODE
2610          acod = toupper( *ptr ) ; dcod2 = ORCODE(acod) ;
2611          if( dcod2 < 0 ){
2612             val = strtod( ptr , &ptr2 ) ;
2613             if( val < 0.0 || (val == 0.0 && ptr2 == ptr) )
2614               WarningError("orientation code or dimension should follow : or - in -zFOV/-zSLAB!") ;
2615             zin_top = val ;
2616             ptr = ptr2 ;
2617             acod = toupper( *ptr ) ; dcod2 = ORCODE(acod) ;
2618             if( dcod2 < 0 )
2619                WarningError("orientation code should follow second dimension in -zFOV/-zSLAB!") ;
2620          } else {
2621             zin_top = zin_bot ;
2622          }
2623 #else
2624          { int nused ;
2625            nused = decode_location( ptr , &zin_top , &dcod2 ) ;
2626            if( dcod2 < 0 )
2627              WarningError("need 2nd orientation code in -zFOV/-zSLAB!") ;
2628            if( zin_top < 0.0 )
2629              WarningError("need nonegative 2nd dimension in -zFOV/-zSLAB!") ;
2630            if( zin_top == WAY_BIG ){
2631              zin_top = zin_bot ;
2632              if( zincode == INCODE_FOV )
2633                INFO_message("%s: FOV width is %g mm",
2634                             Argv[nopt-1],2*fabs(zin_bot));
2635            }
2636          }
2637 #endif
2638 
2639          /* Now, check for consistency:
2640               Direction codes should be in the same or opposite directions;
2641               however, must be opposite if the two <number>s are identical.
2642               For example 120A-120A makes no sense,
2643               but 120A-120P is reasonable, and 10A-30A is also reasonable.  */
2644 
2645          if( zin_top == zin_bot && dcod1 != ORIENT_OPPOSITE(dcod2) )
2646             WarningError("zero thickness slab specified in -zFOV/-zSLAB!") ;
2647 
2648          if( dcod1 != dcod2 && dcod1 != ORIENT_OPPOSITE(dcod2) )
2649             WarningError("inconsistent directions given in -zFOV/-zSLAB!") ;
2650 
2651          /* If the direction codes are the same, then if the first <number>
2652             is smaller, reverse the first direction code and negate the
2653             first number.  For example, 10A:30A becomes -10P:30A, which is
2654             equivalent.  If the first number is larger, then reverse the
2655             second code and number.  For example, 30A:10A becomes 30A:-10P.
2656             Why do this?  Then the first direction code correctly expresses
2657             the sense of the input direction. The sum of numbers becomes
2658             the cross-slab thickness, needed to compute various stuff later. */
2659 
2660          if( dcod1 == dcod2 ){
2661             if( zin_bot < zin_top ){
2662                dcod1   = ORIENT_OPPOSITE(dcod1) ;
2663                zin_bot = -zin_bot ;
2664             } else {
2665                dcod2   = ORIENT_OPPOSITE(dcod2) ;
2666                zin_top = -zin_top ;
2667             }
2668          }
2669 
2670          /* All is OK, so store the results */
2671 
2672          user_inputs.zincode = zincode + dcod1 ;
2673          user_inputs.zin_bot = zin_bot ;
2674          user_inputs.zin_top = zin_top ;
2675 
2676 #if 0
2677 printf("decoded %s to give zincode=%d bot=%f top=%f\n",Argv[nopt],
2678        user_inputs.zincode, user_inputs.zin_bot, user_inputs.zin_top ) ;
2679 #endif
2680 
2681          nopt++ ; continue ;
2682       }
2683 
2684       /*---- -statpar x x x ----*/
2685 
2686       if( strncmp(Argv[nopt],"-statpar",5) == 0 ){
2687          float val ;
2688          char * ptr ;
2689 
2690          if( ++nopt >= Argc ) ERROR_exit("need an argument after -statpar!") ;
2691 
2692          ii = 0 ;
2693          do{
2694             val = strtod( Argv[nopt] , &ptr ) ;
2695             if( *ptr != '\0' ) break ;
2696             user_inputs.stat_aux[ii++] = val ;
2697             nopt++ ;
2698          } while( nopt < Argc ) ;
2699 
2700          if( ii == 0 )
2701             WarningError("No numbers given after -statpar?") ;
2702          continue ;
2703       }
2704 
2705       /***** 21 Oct 1996: options for time units *****/
2706 
2707       if( strcmp(Argv[nopt],"-t=ms")==0 || strcmp(Argv[nopt],"-t=msec")==0 ){
2708          user_inputs.tunits = UNITS_MSEC_TYPE ;
2709          if( AFNI_yesenv("AFNI_ALLOW_MILLISECONDS") )
2710            WARNING_message("TR expressed in milliseconds is deprecated.") ;
2711          else
2712            WARNING_message("TR expressed in ms will be converted to s.") ;
2713          nopt++ ; continue ;
2714       }
2715 
2716       if( strcmp(Argv[nopt],"-t=s")==0 || strcmp(Argv[nopt],"-t=sec")==0 ){
2717          user_inputs.tunits = UNITS_SEC_TYPE ;
2718          nopt++ ; continue ;
2719       }
2720 
2721       if( strcmp(Argv[nopt],"-t=Hz")==0 || strcmp(Argv[nopt],"-t=Hertz")==0 ){
2722          user_inputs.tunits = UNITS_HZ_TYPE ;
2723          nopt++ ; continue ;
2724       }
2725 
2726       /**** 23 Feb 2005: -Torg option ****/
2727 
2728       if( strncmp(Argv[nopt],"-Torg",5) == 0 ){
2729         if( nopt+1 >= Argc ) ERROR_exit("need 1 argument after -Torg") ;
2730         user_inputs.Torg = strtod( Argv[++nopt] , NULL ) ;
2731         nopt++ ; continue ;
2732       }
2733 
2734       /************* Aprille 1996: New options for specifying time ***********/
2735 
2736       if( strncmp(Argv[nopt],"-time:zt",8)==0 || strncmp(Argv[nopt],"-time:tz",8)==0 ){
2737          int   t_then_z , ntt , nzz , nerr ;
2738          float TR , tframe , tsl ;
2739          char *tpattern , *eptr ;
2740 
2741          if( nopt+4 >= Argc ) ERROR_exit("need 4 arguments after -time: options") ;
2742 
2743          t_then_z = ( strncmp(Argv[nopt],"-time:tz",8)==0 ) ;
2744 
2745          ntt = strtol( Argv[++nopt] , NULL , 10 ) ;
2746          nzz = strtol( Argv[++nopt] , NULL , 10 ) ;
2747          if( ! t_then_z ){ ii = ntt ; ntt = nzz ; nzz = ii ; }
2748 
2749          TR       = strtod( Argv[++nopt] , &eptr ) ;
2750          tpattern = Argv[++nopt] ;
2751 
2752          /** 03 Nov 1996: allow units to be written after TR **/
2753 
2754          if( strcmp(eptr,"ms")==0 || strcmp(eptr,"msec")==0 ){
2755            user_inputs.tunits = UNITS_MSEC_TYPE ;
2756          } else if( strcmp(eptr,"s")==0 || strcmp(eptr,"sec")==0 ){
2757            user_inputs.tunits = UNITS_SEC_TYPE ;
2758          } else if( strcmp(eptr,"Hz")==0 || strcmp(eptr,"Hertz")==0 ){
2759            user_inputs.tunits = UNITS_HZ_TYPE ;
2760          }
2761 
2762          if( user_inputs.tunits == UNITS_MSEC_TYPE ){
2763            if( AFNI_yesenv("AFNI_ALLOW_MILLISECONDS") )
2764              WARNING_message("TR expressed in milliseconds is deprecated.") ;
2765            else if( TR != 0.0f )
2766              WARNING_message(
2767                "TR expressed in milliseconds will be converted to TR=%.6fs",
2768                0.001*TR) ;
2769          }
2770 
2771          /** 31 July 1996: be more specific about errors **/
2772 
2773          nerr = 0 ;
2774          if( ntt < 2 ){
2775            fprintf(stderr,"** Illegal value of nt after -time: option\n") ; nerr++ ;
2776          }
2777          if( nzz < NZBOT ){
2778            fprintf(stderr,"** Illegal value of nz after -time: option\n") ; nerr++ ;
2779          }
2780          if( TR < 0.0 ){
2781            fprintf(stderr,"** Illegal value of TR after -time: option\n") ; nerr++ ;
2782          }
2783          if( nerr > 0 ){
2784            nopt++ ; continue ;  /* skip on to next option, this one is bad! */
2785          }
2786 
2787          user_inputs.tpattern = (float *) malloc( sizeof(float) * nzz ) ;
2788          for( ii=0 ; ii < nzz ; ii++ ) user_inputs.tpattern[ii] = 0.0 ;
2789 
2790          user_inputs.ntt      = ntt ;
2791          user_inputs.nzz      = nzz ;
2792          user_inputs.t_then_z = t_then_z ;
2793          user_inputs.TR       = TR ;
2794 
2795          if( TR == 0.0 ){ TR = 1.0; user_inputs.tunits = UNITS_SEC_TYPE; }
2796 
2797          tframe = TR / nzz ;  /* time per slice */
2798 
2799          if( nzz > 1 && tpattern[0] == '@' ){
2800             FILE * fp ;
2801 
2802             /*--- read pattern file (ignore EOFs!) ---*/
2803 
2804             fp = fopen( tpattern+1 , "r" ) ;
2805             if( fp == NULL ){
2806                fprintf(stderr,"** Cannot open tpattern file %s\n",tpattern+1) ;
2807             } else {
2808                for( ii=0 ; ii < nzz ; ii++ )
2809                   fscanf( fp , "%f" , user_inputs.tpattern + ii ) ;
2810                fclose( fp ) ;
2811             }
2812          } else if( nzz > 1 && (strcmp(tpattern,"FROM_IMAGE")==0) ) {
2813 
2814             /*--- expect to get the slice timing from image files ---*/
2815             /*--- (for now this is only for Siemens mosaic)       ---*/
2816 
2817             /* must exorcise timing flag later */
2818             for( ii=0 ; ii < nzz ; ii++ ) user_inputs.tpattern[ii] = -666.0;
2819 
2820          } else if( nzz > 1 &&
2821                    (strcmp(tpattern,"alt+z")==0 || strcmp(tpattern,"altplus")==0) ){
2822 
2823             /*--- set up alternating in the +z direction ---*/
2824 
2825             tsl = 0.0 ;
2826             for( ii=0 ; ii < nzz ; ii+=2 ){
2827                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2828             }
2829             for( ii=1 ; ii < nzz ; ii+=2 ){
2830                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2831             }
2832          } else if( nzz > 1 && strcmp(tpattern,"alt+z2")==0 ){  /* 22 Feb 2005 */
2833 
2834             /*--- set up alternating in the +z direction ---*/
2835 
2836             tsl = 0.0 ;
2837             for( ii=1 ; ii < nzz ; ii+=2 ){
2838                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2839             }
2840             for( ii=0 ; ii < nzz ; ii+=2 ){
2841                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2842             }
2843          } else if( nzz > 1 &&
2844                    (strcmp(tpattern,"alt-z")==0 || strcmp(tpattern,"altminus")==0) ){
2845 
2846             /*--- set up alternating in the -z direction ---*/
2847 
2848             tsl = 0.0 ;
2849             for( ii=nzz-1 ; ii >=0 ; ii-=2 ){
2850                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2851             }
2852             for( ii=nzz-2 ; ii >=0 ; ii-=2 ){
2853                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2854             }
2855          } else if( nzz > 1 && strcmp(tpattern,"alt-z2")==0 ){  /* 22 Feb 2005 */
2856 
2857             /*--- set up alternating in the -z direction ---*/
2858 
2859             tsl = 0.0 ;
2860             for( ii=nzz-2 ; ii >=0 ; ii-=2 ){
2861                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2862             }
2863             for( ii=nzz-1 ; ii >=0 ; ii-=2 ){
2864                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2865             }
2866          } else if( nzz > 1 &&
2867                    (strcmp(tpattern,"seq+z")==0 || strcmp(tpattern,"seqplus")==0) ){
2868 
2869             /*--- set up sequential in the +z direction ---*/
2870 
2871             tsl = 0.0 ;
2872             for( ii=0 ; ii < nzz ; ii++ ){
2873                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2874             }
2875          } else if( nzz > 1 &&
2876                    (strcmp(tpattern,"seq-z")==0 || strcmp(tpattern,"seqminus")==0) ){
2877 
2878             /*--- set up sequential in the -z direction ---*/
2879 
2880             tsl = 0.0 ;
2881             for( ii=nzz-1 ; ii >=0 ; ii-- ){
2882                user_inputs.tpattern[ii] = tsl ; tsl += tframe ;
2883             }
2884          } else if( nzz == 1 ||
2885                    (strcmp(tpattern,"zero")==0 || strcmp(tpattern,"simult")==0) ){
2886 
2887             /*--- delete the tpattern ---*/
2888 
2889             free(user_inputs.tpattern) ;
2890             user_inputs.tpattern = NULL ;
2891 
2892          } else {
2893             fprintf(stderr,"** Unknown tpattern = %s\n",tpattern) ;
2894          }
2895 
2896          nopt++ ; continue ;
2897       }
2898 
2899       /********** non-dataset arguments ************/
2900 
2901       /*----- -gamma # option -----*/
2902 
2903       if( strncmp(Argv[nopt],"-gamma",4) == 0 ){
2904          float val ;
2905          if( nopt+1 >= Argc ) ERROR_exit("need an argument after -gamma!");
2906 
2907          val = strtod( Argv[++nopt] , NULL ) ;
2908          if( val > 0 ) argopt.gamma = val ;
2909          else fprintf(stderr,
2910                 "\n** warning: -gamma value %s illegal\n", Argv[nopt]);
2911 
2912          nopt++ ; continue ;  /* go to next arg */
2913       }
2914 
2915       /*----- -gsfac value option -----*/
2916 
2917       if( strncmp(Argv[nopt],"-gsfac",4) == 0 ){
2918          float val ;
2919          if( nopt+1 >= Argc ) ERROR_exit("need an argument after -gsfac!");
2920 
2921          val = strtod( Argv[++nopt] , NULL ) ;
2922          if( val != 0.0 ) argopt.gsfac = val ;
2923          else fprintf(stderr,
2924                 "\n** warning: -gsfac value %s illegal\n", Argv[nopt]);
2925 
2926          nopt++ ; continue ;  /* go to next arg */
2927       }
2928 
2929       /*----- -datum type option -----*/
2930 
2931       if( strncmp(Argv[nopt],"-datum",6) == 0 ){
2932          if( ++nopt >= Argc ) ERROR_exit("need an argument after -datum!") ;
2933 
2934          if( strcmp(Argv[nopt],"short") == 0 ){
2935             argopt.datum_all = MRI_short ;
2936          } else if( strcmp(Argv[nopt],"float") == 0 ){
2937             argopt.datum_all = MRI_float ;
2938          } else if( strcmp(Argv[nopt],"complex") == 0 ){
2939             argopt.datum_all = MRI_complex ;
2940          } else if( strcmp(Argv[nopt],"byte") == 0 ){
2941             argopt.datum_all = MRI_byte ;
2942          } else if( strcmp(Argv[nopt],"rgb") == 0 ){
2943             argopt.datum_all = MRI_rgb ;
2944          } else {
2945             char buf[256] ;
2946             sprintf(buf,"-datum of type '%s' is not supported in AFNI!",
2947                     Argv[nopt] ) ;
2948             ERROR_exit(buf) ;
2949          }
2950 
2951          nopt++ ; continue ;  /* go to next arg */
2952       }
2953 
2954       /*----- -ushort2float option     9 Jul 2013 [rickr] -----*/
2955 
2956       if( strcmp(Argv[nopt],"-ushort2float") == 0 ){
2957          argopt.datum_all = MRI_float ;
2958          ushort2float = 1 ;
2959 
2960          nopt++ ; continue ;  /* go to next arg */
2961       }
2962 
2963       /*----- -ncolor # option -----*/
2964 
2965       if( strncmp(Argv[nopt],"-ncolor",4) == 0 ){
2966          float val ;
2967          if( nopt+1 >= Argc ) ERROR_exit("need an argument after -ncolor!");
2968 
2969          val = strtod( Argv[++nopt] , NULL ) ;
2970          if( val > 4 ) argopt.ncolor = val ;
2971          else fprintf(stderr,
2972                 "\n** warning: -ncolor value %s illegal\n", Argv[nopt]);
2973 
2974          nopt++ ; continue ;  /* go to next arg */
2975       }
2976 
2977       /*----- -xtwarns option -----*/
2978 
2979       if( strncmp(Argv[nopt],"-xtwarns",6) == 0 ){
2980          argopt.xtwarns = True ;
2981          nopt++ ; continue ;  /* go to next arg */
2982       }
2983 
2984       /*----- -2swap and -4swap options -----*/
2985 
2986       if( strncmp(Argv[nopt],"-2swap",4) == 0 ){
2987          argopt.swap_two = 1 ;
2988          nopt++ ; continue ;  /* go to next arg */
2989       }
2990 
2991       if( strncmp(Argv[nopt],"-4swap",4) == 0 ){
2992          argopt.swap_four = 1 ;
2993          nopt++ ; continue ;  /* go to next arg */
2994       }
2995 
2996       if( strncmp(Argv[nopt],"-8swap",4) == 0 ){    /* 06 Feb 2003 */
2997          argopt.swap_eight = 1 ;
2998          nopt++ ; continue ;  /* go to next arg */
2999       }
3000 
3001       /*----- -nofloatscan -----*/
3002 
3003       if( strncmp(Argv[nopt],"-nofloatscan",6) == 0 ){
3004          argopt.nofloatscan = 1 ;
3005          nopt++ ; continue ;  /* go to next arg */
3006       }
3007 
3008       /*----- -quit_on_err -----*/
3009 
3010       if( strncmp(Argv[nopt],"-quit_on_err",6) == 0 ){
3011          argopt.quit_if_bad = 1 ;
3012          nopt++ ; continue ;  /* go to next arg */
3013       }
3014 
3015       /*----- -assume_dicom_mosaic -----*/  /* 13 Mar 2006 [rickr] */
3016 
3017       if( strncmp(Argv[nopt],"-assume_dicom_mosaic",16) == 0 ){
3018          assume_dicom_mosaic = 1 ;  /* global in mri_read_dicom.c */
3019          nopt++ ; continue ;  /* go to next arg */
3020       }
3021 
3022       /*--- -oblique_origin ---*/ /* 01 Dec 2008 [drg] */
3023 
3024       if( strncmp(Argv[nopt],"-oblique_origin",15) == 0 ){
3025          use_oblique_origin = 1 ;
3026          nopt++ ; continue ;
3027       }
3028 
3029       /*--- -reverse_list ---*/ /* 04 Dec 2008 [drg] */
3030 
3031       if( strncmp(Argv[nopt],"-reverse_list",13) == 0 ){
3032          reverse_list = 1 ;
3033          nopt++ ; continue ;
3034       }
3035 
3036       /*----- -use_last_element -----*/  /* 10 Apr 2009 [rickr] */
3037 
3038       if( strncmp(Argv[nopt],"-use_last_elem",14) == 0 ){
3039          g_dicom_ctrl.use_last_elem = 1 ;  /* global in mri_read_dicom.c */
3040          nopt++ ; continue ;  /* go to next arg */
3041       }
3042 
3043       /*----- -use_old_mosaic_code -----*/  /* 23 Dec 2010 [rickr] */
3044 
3045       if( strcmp(Argv[nopt],"-use_old_mosaic_code") == 0 ){
3046          use_new_mosaic_code = 0 ;  /* forget mri_process_siemens.c funcs */
3047          nopt++ ; continue ;  /* go to next arg */
3048       }
3049 
3050 
3051       /* show debugging information */
3052       if( strcmp(Argv[nopt],"-verb") == 0 ){
3053          dicom_debug(3);
3054          nopt++ ; continue ;  /* go to next arg */
3055       }
3056 
3057       /*--- illegal option ---*/
3058 
3059       printf("** ILLEGAL OPTION: %s\n\n",Argv[nopt]) ;
3060       ERROR_exit("cannot continue") ;
3061 
3062    }
3063 
3064    if( user_inputs.ntt > 1 && !af_type_set ){
3065       user_inputs.anatomy_type = ANAT_EPI_TYPE ; /* 20 Dec 2001 */
3066    }
3067 
3068    First_Image_Arg = nopt ;
3069 
3070    /* 14 Sep 1999: manufacture a command line for History,
3071                    but with (possibly) fewer image inputs */
3072 
3073    { int nim=Argc-First_Image_Arg , ii ;
3074      char ** qargv ;
3075 
3076      if( nim < 9 ){     /* 8 or fewer images ==> copy them all */
3077 
3078         qargv = Argv ;
3079 
3080      } else {           /* im0 im1 im2 ... im<last-1> im<last> */
3081 
3082         qargv = (char **) malloc( sizeof(char *) * Argc ) ;   /* copy all */
3083         for( ii=0 ; ii < Argc ; ii++ ) qargv[ii] = Argv[ii] ; /* argv's   */
3084 
3085         qargv[First_Image_Arg+3] = "..." ;   /* notice of omission */
3086 
3087         for( ii=First_Image_Arg+4 ; ii < Argc-2 ; ii++ ) /* these will */
3088            qargv[ii] = NULL ;                            /* be omitted */
3089      }
3090 
3091      commandline = tross_commandline( "to3d" , Argc , qargv ) ;
3092      AFNI_log_string(commandline) ; /* 14 Aug 2001 */
3093 
3094      if( qargv != Argv ) free(qargv) ;
3095    }
3096 
3097    EXRETURN ;
3098 }
3099 
3100 /*--------------------------------------------------------------------*/
3101 
Syntax()3102 void Syntax()
3103 {
3104    int ii ;
3105 
3106    printf(
3107     "Usage: to3d [options] image_files ...\n"
3108     "       Creates 3D datasets for use with AFNI from 2D image files\n"
3109     "\n"
3110     "****** PLEASE NOTE ******************************************************\n"
3111     "****** If you are convering DICOM files to AFNI or NIfTI datasets, ******\n"
3112     "****** you will likely be happier using the Dimon program, which   ******\n"
3113     "****** can properly organize the Dicom files for you (knock wood). ******\n"
3114     "****** Example:                                                    ******\n"
3115     "******   Dimon -infile_prefix im. -dicom_org -gert_create_dataset  ******\n"
3116     "****** See the output of                                           ******\n"
3117     "******   Dimon -help                                               ******\n"
3118     "****** for more examples and the complete instructions for use.    ******\n"
3119     "\n"
3120     "The available options are\n"
3121     "  -help   show this message\n"
3122     "  -'type' declare images to contain data of a given type\n"
3123     "          where 'type' is chosen from the following options:\n" ) ;
3124 
3125    printf("       ANATOMICAL TYPES\n") ;
3126    for( ii=FIRST_ANAT_TYPE ; ii <= LAST_ANAT_TYPE ; ii++ )
3127       printf("     %8s == %s\n",ANAT_prefixstr[ii],ANAT_typestr[ii] ) ;
3128 
3129    printf("       FUNCTIONAL TYPES\n") ;
3130    for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ )
3131       printf("     %8s == %s\n",FUNC_prefixstr[ii],FUNC_typestr[ii] ) ;
3132 
3133    printf(
3134     "                 [for paired (+) types above, images are fim first,]\n"
3135     "                 [then followed by the threshold (etc.) image files]\n" ) ;
3136 
3137    printf(
3138     "\n"
3139     "  -statpar value value ... value [* NEW IN 1996 *]\n"
3140     "     This option is used to supply the auxiliary statistical parameters\n"
3141     "     needed for certain dataset types (e.g., 'fico' and 'fitt').  For\n"
3142     "     example, a correlation coefficient computed using program 'fim2'\n"
3143     "     from 64 images, with 1 ideal, and with 2 orts could be specified with\n"
3144     "       -statpar 64 1 2\n"
3145    ) ;
3146 
3147    printf(
3148     "\n"
3149 #ifndef NO_NAMES
3150     "  -dname   name      will make 3D dataset's name = 'name'\n"
3151     "  -dlabel  name      will make 3D dataset's short label = 'name'\n"
3152 #endif
3153     "  -prefix  name      will write 3D dataset using prefix 'name'\n"
3154     "  -session name      will write 3D dataset into session directory 'name'\n"
3155     "  -geomparent fname  will read geometry data from dataset file 'fname'\n"
3156     "                       N.B.: geometry data does NOT include time-dependence\n"
3157     "  -anatparent fname  will take anatomy parent from dataset file 'fname'\n"
3158     "\n"
3159     "  -nosave  will suppress autosave of 3D dataset, which normally occurs\n"
3160     "           when the command line options supply all needed data correctly\n"
3161     "\n"
3162     "  -nowritebrik  will suppress saving of the BRIK file. May be useful for\n"
3163     "           realtime saving when symbolic links are used instead\n"
3164     "\n"
3165     "  -view type [* NEW IN 1996 *]\n"
3166     "    Will set the dataset's viewing coordinates to 'type', which\n"
3167     "    must be one of these strings:  "
3168             VIEW_ORIGINAL_CODE    " "
3169             VIEW_ACPCALIGNED_CODE " "
3170             VIEW_TALAIRACH_CODE   "\n"
3171    ) ;
3172 
3173    printf(
3174     "\n"
3175     "TIME DEPENDENT DATASETS [* NEW IN 1996 *]\n"
3176     "  -time:zt nz nt TR tpattern  OR  -time:tz nt nz TR tpattern\n"
3177     "\n"
3178     "    These options are used to specify a time dependent dataset.\n"
3179     "    '-time:zt' is used when the slices are input in the order\n"
3180     "               z-axis first, then t-axis.\n"
3181     "    '-time:tz' is used when the slices are input in the order\n"
3182     "               t-axis first, then z-axis.\n"
3183     "\n"
3184     "    nz  =  number of points in the z-direction (minimum %d)\n"
3185     "    nt  =  number of points in the t-direction\n"
3186     "            (thus exactly nt * nz slices must be read in)\n"
3187     "    TR  =  repetition interval between acquisitions of the\n"
3188     "            same slice, in milliseconds (or other units, as given below)\n"
3189     "\n"
3190     "    tpattern = Code word that identifies how the slices (z-direction)\n"
3191     "               were gathered in time.  The values that can be used:\n"
3192     "\n"
3193     "       alt+z = altplus    = alternating in the plus direction\n"
3194     "       alt+z2             = alternating, starting at slice #1\n"
3195     "       alt-z = altminus   = alternating in the minus direction\n"
3196     "       alt-z2             = alternating, starting at slice #nz-2\n"
3197     "       seq+z = seqplus    = sequential in the plus direction\n"
3198     "       seq-z = seqminus   = sequential in the minus direction\n"
3199     "       zero  = simult     = simultaneous acquisition\n"
3200     "       FROM_IMAGE         = (try to) read offsets from input images\n"\
3201     "       @filename          = read temporal offsets from 'filename'\n"\
3202     "\n"
3203     "    For example if nz = 5 and TR = 1000, then the inter-slice\n"
3204     "    time is taken to be dt = TR/nz = 200.  In this case, the\n"
3205     "    slices are offset in time by the following amounts:\n"
3206     "\n"
3207     "                    S L I C E   N U M B E R\n"
3208     "      tpattern        0    1    2    3    4  Comment\n"
3209     "      ----------   ---- ---- ---- ---- ----  -------------------------------\n"
3210     "      altplus         0  600  200  800  400  Alternating in the +z direction\n"
3211     "      alt+z2        400    0  600  200  800  Alternating, but starting at #1\n"
3212     "      altminus      400  800  200  600    0  Alternating in the -z direction\n"
3213     "      alt-z2        800  200  600    0  400  Alternating, starting at #nz-2 \n"
3214     "      seqplus         0  200  400  600  800  Sequential  in the +z direction\n"
3215     "      seqminus      800  600  400  200    0  Sequential  in the -z direction\n"
3216     "      simult          0    0    0    0    0  All slices acquired at once\n"
3217     "\n"
3218     "    If @filename is used for tpattern, then nz ASCII-formatted numbers are\n"
3219     "    read from the file.  These are used to indicate the time offsets (in ms)\n"
3220     "    for each slice. For example, if 'filename' contains\n"
3221     "       0 600 200 800 400\n"
3222     "    then this is equivalent to 'altplus' in the above example.\n"
3223     "\n"
3224     "    Notes:\n"
3225     "      * Time-dependent functional datasets are not yet supported by\n"
3226     "          to3d or any other AFNI package software.  For many users,\n"
3227     "          the proper dataset type for these datasets is '-epan'.\n"
3228     "      * Time-dependent datasets with more than one value per time point\n"
3229     "          (e.g., 'fith', 'fico', 'fitt') are also not allowed by to3d.\n"
3230     "      * If you use 'abut' to fill in gaps in the data and/or to\n"
3231     "          subdivide the data slices, you will have to use the @filename\n"
3232     "          form for tpattern, unless 'simult' or 'zero' is acceptable.\n"
3233     "      * At this time, the value of 'tpattern' is not actually used in\n"
3234     "          any AFNI program.  The values are stored in the dataset\n"
3235     "          .HEAD files, and will be used in the future.\n"
3236     "      * The values set on the command line can't be altered interactively.\n"
3237     "      * The units of TR can be specified by the command line options below:\n"
3238     "            -t=ms or -t=msec  -->  milliseconds (the default)\n"
3239     "            -t=s  or -t=sec   -->  seconds\n"
3240     "            -t=Hz or -t=Hertz -->  Hertz (for chemical shift images?)\n"
3241     "          Alternatively, the units symbol ('ms', 'msec', 's', 'sec',\n"
3242     "            'Hz', or 'Hertz') may be attached to TR in the '-time:' option,\n"
3243     "            as in '-time:zt 16 64 4.0sec alt+z'\n"
3244     " ****** 15 Aug 2005 ******\n"
3245     "      * Millisecond time units are no longer stored in AFNI dataset\n"
3246     "          header files.  For backwards compatibility, the default unit\n"
3247     "          of TR (i.e., without a suffix 's') is still milliseconds, but\n"
3248     "          this value will be converted to seconds when the dataset is\n"
3249     "          written to disk.  Any old AFNI datasets that have millisecond\n"
3250     "          units for TR will be read in to all AFNI programs with the TR\n"
3251     "          converted to seconds.\n"
3252 
3253     "\n"
3254     "  -Torg ttt = set time origin of dataset to 'ttt' [default=0.0]\n"
3255 
3256       , NZBOT
3257    ) ;
3258 
3259    printf(
3260      "\n"
3261      "COMMAND LINE GEOMETRY SPECIFICATION [* NEW IN 1996 *]\n"
3262      "   -xFOV   [dimen1][direc1]-[dimen2][direc2]\n"
3263      "     or       or\n"
3264      "   -xSLAB  [dimen1][direc1]-[direc2]\n"
3265      "\n"
3266      "   (Similar -yFOV, -ySLAB, -zFOV and -zSLAB option are also present.)\n"
3267      "\n"
3268      " These options specify the size and orientation of the x-axis extent\n"
3269      " of the dataset.  [dimen#] means a dimension (in mm); [direc] is\n"
3270      " an anatomical direction code, chosen from\n"
3271      "      A (Anterior)    P (Posterior)    L (Left)\n"
3272      "      I (Inferior)    S (Superior)     R (Right)\n"
3273      " Thus, 20A-30P means that the x-axis of the input images runs from\n"
3274      " 20 mm Anterior to 30 mm Posterior.  For convenience, 20A-20P can be\n"
3275      " abbreviated as 20A-P.\n"
3276      "\n"
3277      " -xFOV  is used to mean that the distances are from edge-to-edge of\n"
3278      "          the outermost voxels in the x-direction.\n"
3279      " -xSLAB is used to mean that the distances are from center-to-center\n"
3280      "          of the outermost voxels in the x-direction.\n"
3281      "\n"
3282      " Under most circumstance, -xFOV , -yFOV , and -zSLAB would be the\n"
3283      " correct combination of geometry specifiers to use.  For example,\n"
3284      " a common type of run at MCW would be entered as\n"
3285      "    -xFOV 120L-R -yFOV 120A-P -zSLAB 60S-50I\n"
3286      "\n"
3287      " **NOTE WELL: -xFOV 240L-R does not mean a Field-of-View that is 240 mm\n"
3288      "               wide!  It means one that stretches from 240R to 240L, and\n"
3289      "               so is 480 mm wide.\n"
3290      "              The 'FOV' indicates that this direction was acquired with\n"
3291      "               with Fourier encoding, and so the distances are naturally\n"
3292      "               specified from the edge of the volume.\n"
3293      "              The 'SLAB' indicates that this direction was acquired with\n"
3294      "               slice encoding (by the RF excitation), and so distances\n"
3295      "               are naturally specified by the center of the slices.\n"
3296      "              For non-MRI data (e.g., CT), I'm not sure what the correct\n"
3297      "               input format to use here would be -- be careful out there!\n"
3298    ) ;
3299 
3300    printf(
3301      "\n"
3302      "Z-AXIS SLICE OFFSET ONLY\n"
3303      " -zorigin distz  Puts the center of the 1st slice off at the\n"
3304      "                 given distance ('distz' in mm).  This distance\n"
3305      "                 is in the direction given by the corresponding\n"
3306      "                 letter in the -orient code.  For example,\n"
3307      "                   -orient RAI -zorigin 30\n"
3308      "                 would set the center of the first slice at\n"
3309      "                 30 mm Inferior.\n"
3310      "    N.B.: This option has no effect if the FOV or SLAB options\n"
3311      "          described above are used.\n"
3312    ) ;
3313 
3314    printf(
3315     "\n"
3316     "INPUT IMAGE FORMATS [* SIGNIFICANTLY CHANGED IN 1996 *]\n"
3317     "  Image files may be single images of unsigned bytes or signed shorts\n"
3318     "  (64x64, 128x128, 256x256, 512x512, or 1024x1024) or may be grouped\n"
3319     "  images (that is, 3- or 4-dimensional blocks of data).\n"
3320     "  In the grouped case, the string for the command line file spec is like\n"
3321     "\n"
3322     "    3D:hglobal:himage:nx:ny:nz:fname   [16 bit input]\n"
3323     "    3Ds:hglobal:himage:nx:ny:nz:fname  [16 bit input, swapped bytes]\n"
3324     "                   (consider also -ushort2float for unsigned shorts)\n"
3325     "    3Db:hglobal:himage:nx:ny:nz:fname  [ 8 bit input]\n"
3326     "    3Di:hglobal:himage:nx:ny:nz:fname  [32 bit input]\n"
3327     "    3Df:hglobal:himage:nx:ny:nz:fname  [floating point input]\n"
3328     "    3Dc:hglobal:himage:nx:ny:nz:fname  [complex input]\n"
3329     "    3Dd:hglobal:himage:nx:ny:nz:fname  [double input]\n"
3330     "\n"
3331     "  where '3D:' or '3Ds': signals this is a 3D input file of signed shorts\n"
3332     "        '3Db:'          signals this is a 3D input file of unsigned bytes\n"
3333     "        '3Di:'          signals this is a 3D input file of signed ints\n"
3334     "        '3Df:'          signals this is a 3D input file of floats\n"
3335     "        '3Dc:'          signals this is a 3D input file of complex numbers\n"
3336     "                         (real and imaginary pairs of floats)\n"
3337     "        '3Dd:'          signals this is a 3D input file of double numbers\n"
3338     "                         (will be converted to floats)\n"
3339     "        hglobal = number of bytes to skip at start of whole file\n"
3340     "        himage  = number of bytes to skip at start of each 2D image\n"
3341     "        nx      = x dimension of each 2D image in the file\n"
3342     "        ny      = y dimension of each 2D image in the file\n"
3343     "        nz      = number of 2D images in the file\n"
3344     "        fname   = actual filename on disk to read\n"
3345     "\n"
3346     "  * The ':' separators are required.  The k-th image starts at\n"
3347     "      BYTE offset hglobal+(k+1)*himage+vs*k*nx*ny in file 'fname'\n"
3348     "      for k=0,1,...,nz-1.\n"
3349     "  * Here, vs=voxel length=1 for bytes, 2 for shorts, 4 for ints and floats,\n"
3350     "      and 8 for complex numbers.\n"
3351     "  * As a special case, hglobal = -1 means read data starting at\n"
3352     "      offset len-nz*(vs*nx*ny+himage), where len=file size in bytes.\n"
3353     "      (That is, to read the needed data from the END of the file.)\n"
3354     "  * Note that there is no provision for skips between data rows inside\n"
3355     "      a 2D slice, only for skips between 2D slice images.\n"
3356     "  * The int, float, and complex formats presume that the data in\n"
3357     "      the image file are in the 'native' format for this CPU; that is,\n"
3358     "      there is no provision for data conversion (unlike the 3Ds: format).\n"
3359     "  * Double input will be converted to floats (or whatever -datum is)\n"
3360     "      since AFNI doesn't support double precision datasets.\n"
3361     "  * Whether the 2D image data is interpreted as a 3D block or a 3D+time\n"
3362     "      block depends on the rest of the command line parameters.  The\n"
3363     "      various 3D: input formats are just ways of inputting multiple 2D\n"
3364     "      slices from a single file.\n"
3365     "  * SPECIAL CASE: If fname is ALLZERO, then this means not to read\n"
3366     "      data from disk, but instead to create nz nx*ny images filled\n"
3367     "      with zeros.  One application of this is to make it easy to create\n"
3368     "      a dataset of a specified geometry for use with other programs.\n"
3369     "  * ENVIRONMENT VARIABLE: You can set an environment variable\n"
3370     "      (e.g., AFNI_IMSIZE_1) to put a '3D:' type of prefix in front\n"
3371     "      of any filename whose file has a given size.  For example,\n"
3372     "        setenv AFNI_IMSIZE_1 16384=3D:0:0:64:64:1\n"
3373     "      means that any input file of size 16384 bytes will be read\n"
3374     "      as a 64x64 image of floats.\n"
3375     "\n"
3376     "The 'raw pgm' image format is also supported; it reads data into 'byte' images.\n"
3377     "\n"
3378     "* ANALYZE (TM) .hdr/.img files can now be read - give the .hdr filename on\n"
3379     "  the command line.  The program will detect if byte-swapping is needed on\n"
3380     "  these images, and can also set the voxel grid sizes from the first .hdr file.\n"
3381     "  If the 'funused1' field in the .hdr is positive, it will be used to scale the\n"
3382     "  input values.  If the environment variable AFNI_ANALYZE_FLOATIZE is YES, then\n"
3383     "  .img files will be converted to floats on input.\n"
3384     "\n"
3385     "* Siemens .ima image files can now be read.  The program will detect if\n"
3386     "  byte-swapping is needed on these images, and can also set voxel grid\n"
3387     "  sizes and orientations (correctly, I hope).\n"
3388     "* Some Siemens .ima files seems to have their EPI slices stored in\n"
3389     "  spatial order, and some in acquisition (interleaved) order.  This\n"
3390     "  program doesn't try to figure this out.  You can use the command\n"
3391     "  line option '-sinter' to tell the program to assume that the images\n"
3392     "  in a single .ima file are interleaved; for example, if there are\n"
3393     "  7 images in a file, then without -sinter, the program will assume\n"
3394     "  their order is '0 1 2 3 4 5 6'; with -sinter, the program will\n"
3395     "  assume their order is '0 2 4 6 1 3 5' (here, the number refers\n"
3396     "  to the slice location in space).\n"
3397     "\n"
3398     "* GEMS I.* (IMGF) 16-bit files can now be read. The program will detect\n"
3399     "  if byte-swapping is needed on these images, and can also set voxel\n"
3400     "  grid sizes and orientations.  It can also detect the TR in the\n"
3401     "  image header.  If you wish to rely on this TR, you can set TR=0\n"
3402     "  in the -time:zt or -time:tz option.\n"
3403     "* If you use the image header's TR and also use @filename for the\n"
3404     "  tpattern, then the values in the tpattern file should be fractions\n"
3405     "  of the true TR; they will be multiplied by the true TR once it is\n"
3406     "  read from the image header.\n"
3407     "\n"
3408     " NOTES:\n"
3409     "  * Not all AFNI programs support all datum types.  Shorts and\n"
3410     "      floats are safest. (See the '-datum' option below.)\n"
3411     "  * If '-datum short' is used or implied, then int, float, and complex\n"
3412     "      data will be scaled to fit into a 16 bit integer.  If the '-gsfac'\n"
3413     "      option below is NOT used, then each slice will be SEPARATELY\n"
3414     "      scaled according to the following choice:\n"
3415     "      (a) If the slice values all fall in the range -32767 .. 32767,\n"
3416     "          then no scaling is performed.\n"
3417     "      (b) Otherwise, the image values are scaled to lie in the range\n"
3418     "          0 .. 10000 (original slice min -> 0, original max -> 10000).\n"
3419     "      This latter option is almost surely not what you want!  Therefore,\n"
3420     "      if you use the 3Di:, 3Df:, or 3Dc: input methods and store the\n"
3421     "      data as shorts, I suggest you supply a global scaling factor.\n"
3422     "      Similar remarks apply to '-datum byte' scaling, with even more force.\n"
3423     "  * To3d now incoporates POSIX filename 'globbing', which means that\n"
3424     "      you can input filenames using 'escaped wildcards', and then to3d\n"
3425     "      will internally do the expansion to the list of files.  This is\n"
3426     "      only desirable because some systems limit the number of command-line\n"
3427     "      arguments to a program.  It is possible that you would wish to input\n"
3428     "      more slice files than your computer supports.  For example,\n"
3429     "          to3d exp.?.*\n"
3430     "      might overflow the system command line limitations.  The way to do\n"
3431     "      this using internal globbing would be\n"
3432     "          to3d exp.\\?.\\*\n"
3433     "      where the \\ characters indicate to pass the wildcards ? and *\n"
3434     "      through to the program, rather than expand them in the shell.\n"
3435     "      (a) Note that if you choose to use this feature, ALL wildcards in\n"
3436     "          a filename must be escaped with \\ or NONE must be escaped.\n"
3437     "      (b) Using the C shell, it is possible to turn off shell globbing\n"
3438     "          by using the command 'set noglob' -- if you do this, then you\n"
3439     "          do not need to use the \\ character to escape the wildcards.\n"
3440     "      (c) Internal globbing of 3D: file specifiers is supported in to3d.\n"
3441     "          For example, '3D:0:0:64:64:100:sl.\\*' could be used to input\n"
3442     "          a series of 64x64x100 files with names 'sl.01', 'sl.02' ....\n"
3443     "          This type of expansion is specific to to3d; the shell will not\n"
3444     "          properly expand such 3D: file specifications.\n"
3445     "      (d) In the C shell (csh or tcsh), you can use forward single 'quotes'\n"
3446     "          to prevent shell expansion of the wildcards, as in the command\n"
3447     "              to3d '3D:0:0:64:64:100:sl.*'\n"
3448     "    The globbing code is adapted from software developed by the\n"
3449     "    University of California, Berkeley, and is copyrighted by the\n"
3450     "    Regents of the University of California (see file mcw_glob.c).\n"
3451     "\n"
3452     "RGB datasets [Apr 2002]\n"
3453     "-----------------------\n"
3454     "You can now create RGB-valued datasets.  Each voxel contains 3 byte values\n"
3455     "ranging from 0..255.  RGB values may be input to to3d in one of two ways:\n"
3456     " * Using raw PPM formatted 2D image files.\n"
3457     " * Using JPEG formatted 2D files.\n"
3458     " * Using TIFF, BMP, GIF, PNG formatted 2D files [if netpbm is installed].\n"
3459     " * Using the 3Dr: input format, analogous to 3Df:, etc., described above.\n"
3460     "RGB datasets can be created as functional FIM datasets, or as anatomical\n"
3461     "datasets:\n"
3462     " * RGB fim overlays are transparent in AFNI only where all three\n"
3463     "    bytes are zero - that is, you can't overlay solid black.\n"
3464     " * At present, there is limited support for RGB datasets.\n"
3465     "    About the only thing you can do is display them in 2D slice\n"
3466     "    viewers in AFNI.\n"
3467     "You can also create RGB-valued datasets using program 3dThreetoRGB.\n"
3468     "\n"
3469     "Other Data Options\n"
3470     "------------------\n"
3471     "  -2swap\n"
3472     "     This option will force all input 2 byte images to be byte-swapped\n"
3473     "     after they are read in.\n"
3474     "  -4swap\n"
3475     "     This option will force all input 4 byte images to be byte-swapped\n"
3476     "     after they are read in.\n"
3477     "  -8swap\n"
3478     "     This option will force all input 8 byte images to be byte-swapped\n"
3479     "     after they are read in.\n"
3480     "  BUT PLEASE NOTE:\n"
3481     "     Input images that are auto-detected to need byte-swapping\n"
3482     "     (GEMS I.*, Siemens *.ima, ANALYZE *.img, and 3Ds: files)\n"
3483     "     will NOT be swapped again by one of the above options.\n"
3484     "     If you want to swap them again for some bizarre reason,\n"
3485     "     you'll have to use the 'Byte Swap' button on the GUI.\n"
3486     "     That is, -2swap/-4swap will swap bytes on input files only\n"
3487     "     if they haven't already been swapped by the image input\n"
3488     "     function.\n"
3489     "\n"
3490     "  -zpad N   OR\n"
3491     "  -zpad Nmm \n"
3492     "     This option tells to3d to write 'N' slices of all zeros on each side\n"
3493     "     in the z-direction.  This will make the dataset 'fatter', but make it\n"
3494     "     simpler to align with datasets from other scanning sessions.  This same\n"
3495     "     function can be accomplished later using program 3dZeropad.\n"
3496     "   N.B.: The zero slices will NOT be visible in the image viewer in to3d, but\n"
3497     "          will be visible when you use AFNI to look at the dataset.\n"
3498     "   N.B.: If 'mm' follows the integer N, then the padding is measured in mm.\n"
3499     "          The actual number of slices of padding will be rounded up.  So if\n"
3500     "          the slice thickness is 5 mm, then '-zpad 16mm' would be the equivalent\n"
3501     "          of '-zpad 4' -- that is, 4 slices on each z-face of the volume.\n"
3502     "   N.B.: If the geometry parent dataset was created with -zpad, the spatial\n"
3503     "          location (origin) of the slices is set using the geometry dataset's\n"
3504     "          origin BEFORE the padding slices were added.  This is correct, since\n"
3505     "          you need to set the origin on the current dataset as if the padding\n"
3506     "          slices were not present.\n"
3507     "   N.B.: Unlike the '-zpad' option to 3drotate and 3dvolreg, this adds slices\n"
3508     "          only in the z-direction.\n"
3509     "   N.B.: You can set the environment variable 'AFNI_TO3D_ZPAD' to provide a\n"
3510     "          default for this option.\n"
3511     "\n"
3512     "  -gsfac value\n"
3513     "     will scale each input slice by 'value'.  For example,\n"
3514     "     '-gsfac 0.31830989' will scale by 1/Pi (approximately).\n"
3515     "     This option only has meaning if one of '-datum short' or\n"
3516     "     '-datum byte' is used or implied.  Otherwise, it is ignored.\n"
3517     "\n"
3518     "  -datum type\n"
3519     "     will set the voxel data to be stored as 'type', which is currently\n"
3520     "     allowed to be short, float, byte, or complex.\n"
3521     "     If -datum is not used, then the datum type of the first input image\n"
3522     "     will determine what is used.  In that case, the first input image will\n"
3523     "     determine the type as follows:\n"
3524     "        byte       --> byte\n"
3525     "        short      --> short\n"
3526     "        int, float --> float\n"
3527     "        complex    --> complex\n"
3528     "     If -datum IS specified, then all input images will be converted\n"
3529     "     to the desired type.  Note that the list of allowed types may\n"
3530     "     grow in the future, so you should not rely on the automatic\n"
3531     "     conversion scheme.  Also note that floating point datasets may\n"
3532     "     not be portable between CPU architectures.\n"
3533     "\n"
3534     "  -nofloatscan\n"
3535     "     tells to3d NOT to scan input float and complex data files for\n"
3536     "     illegal values - the default is to scan and replace illegal\n"
3537     "     floating point values with zeros (cf. program float_scan).\n"
3538     "\n"
3539     "  -in:1\n"
3540     "     Input of huge 3D: files (with all the data from a 3D+time run, say)\n"
3541     "     can cause to3d to fail from lack of memory.  The reason is that\n"
3542     "     the images are from a file are all read into RAM at once, and then\n"
3543     "     are scaled, converted, etc., as needed, then put into the final\n"
3544     "     dataset brick.  This switch will cause the images from a 3D: file\n"
3545     "     to be read and processed one slice at a time, which will lower the\n"
3546     "     amount of memory needed.  The penalty is somewhat more I/O overhead.\n"
3547    ) ;
3548 
3549    printf(
3550     "\n"
3551     "NEW IN 1997:\n"
3552     "  -orient code\n"
3553     "     Tells the orientation of the 3D volumes.  The code must be 3 letters,\n"
3554     "     one each from the pairs {R,L} {A,P} {I,S}.  The first letter gives\n"
3555     "     the orientation of the x-axis, the second the orientation of the\n"
3556     "     y-axis, the third the z-axis:\n"
3557     "        R = right-to-left         L = left-to-right\n"
3558     "        A = anterior-to-posterior P = posterior-to-anterior\n"
3559     "        I = inferior-to-superior  S = superior-to-inferior\n"
3560     "     Note that the -xFOV, -zSLAB constructions can convey this information.\n"
3561    ) ;
3562 
3563    printf(
3564     "\n"
3565     "NEW IN 2001:\n"
3566     "  -skip_outliers\n"
3567     "     If present, this tells the program to skip the outlier check that is\n"
3568     "     automatically performed for 3D+time datasets.  You can also turn this\n"
3569     "     feature off by setting the environment variable AFNI_TO3D_OUTLIERS\n"
3570     "     to \"No\".\n"
3571     "  -text_outliers\n"
3572     "    If present, tells the program to only print out the outlier check\n"
3573     "     results in text form, not graph them.  You can make this the default\n"
3574     "     by setting the environment variable AFNI_TO3D_OUTLIERS to \"Text\".\n"
3575     "    N.B.: If to3d is run in batch mode, then no graph can be produced.\n"
3576     "          Thus, this option only has meaning when to3d is run with the\n"
3577     "          interactive graphical user interface.\n"
3578     "  -save_outliers fname\n"
3579     "    Tells the program to save the outliers count into a 1D file with\n"
3580     "    name 'fname'.  You could graph this file later with the command\n"
3581     "       1dplot -one fname\n"
3582     "    If this option is used, the outlier count will be saved even if\n"
3583     "    nothing appears 'suspicious' (whatever that means).\n"
3584     "  NOTES on outliers:\n"
3585     "    * See '3dToutcount -help' for a description of how outliers are\n"
3586     "       defined.\n"
3587     "    * The outlier count is not done if the input images are shorts\n"
3588     "       and there is a significant (> 1%%) number of negative inputs.\n"
3589     "    * There must be at least 6 time points for the outlier count to\n"
3590     "       be carried out.\n"
3591    ) ;
3592 
3593    printf(
3594     "\n"
3595     "OTHER NEW OPTIONS:\n"
3596     "  -assume_dicom_mosaic\n"
3597     "    If present, this tells the program that any Siemens DICOM file\n"
3598     "    is a potential MOSAIC image, even without the indicator string.\n"
3599     "  -oblique_origin\n"
3600     "    assume origin and orientation from oblique transformation matrix\n"
3601     "    rather than traditional cardinal information (ignores FOV/SLAB\n"
3602     "    options Sometimes useful for Siemens mosaic flipped datasets\n"
3603     "  -reverse_list\n"
3604     "    reverse the input file list.\n"
3605     "    Convenience for Siemens non-mosaic flipped datasets\n\n"
3606     "  -use_last_elem\n"
3607     "    If present, search DICOM images for the last occurance of each\n"
3608     "    element, not the first.\n"
3609     "  -use_old_mosaic_code\n"
3610     "    If present, do not use the Dec 2010 updates to siemens mosaic code.\n"
3611     "    By default, use the new code if this option is not provided.\n"
3612     "  -ushort2float\n"
3613     "    Convert input shorts to float, and add 2^16 to any negatives.\n"
3614     "  -verb\n"
3615     "    show debugging information for reading DICOM files\n\n"
3616    ) ;
3617 
3618    printf(
3619     "\n"
3620     "OPTIONS THAT AFFECT THE X11 IMAGE DISPLAY\n"
3621     "   -gamma gg    the gamma correction factor for the\n"
3622     "                  monitor is 'gg' (default gg is 1.0; greater than\n"
3623     "                  1.0 makes the image contrast larger -- this may\n"
3624     "                  also be adjusted interactively)\n"
3625     "   -ncolors nn  use 'nn' gray levels for the image\n"
3626     "                  displays (default is %d)\n"
3627     "   -xtwarns     turn on display of Xt warning messages\n"
3628     "   -quit_on_err Do not launch interactive to3d mode if input has errors.\n",
3629     INIT_ngray
3630    ) ;
3631 
3632    PRINT_COMPILE_DATE ;
3633    exit(0) ;
3634 }
3635 
3636 /*---------------------------------------------------------------------
3637   read the centered button box and set arrowvals on or off
3638 -----------------------------------------------------------------------*/
3639 
T3D_centered_CB(Widget w,XtPointer client_data,XtPointer call_data)3640 void T3D_centered_CB( Widget w ,
3641                       XtPointer client_data , XtPointer call_data )
3642 {
3643    int val ;
3644    RwcBoolean sens ;
3645 
3646 ENTRY("T3D_centered_CB") ;
3647 
3648    user_inputs.xyz_centered = val = MCW_val_bbox( wset.centered_bbox ) ;
3649 
3650    sens = (val & XCENTERED) == 0 ;
3651       AV_SENSITIZE( wset.xorigin_av , sens ) ;
3652       XtSetSensitive( wset.xorigin_label , sens ) ;
3653 
3654    sens = (val & YCENTERED) == 0 ;
3655       AV_SENSITIZE( wset.yorigin_av , sens ) ;
3656       XtSetSensitive( wset.yorigin_label , sens ) ;
3657 
3658    sens = (val & ZCENTERED) == 0 ;
3659       AV_SENSITIZE( wset.zorigin_av , sens ) ;
3660       XtSetSensitive( wset.zorigin_label , sens ) ;
3661 
3662    T3D_set_dependent_geometries() ;
3663    RESET_QUIT ;
3664    EXRETURN ;
3665 }
3666 
3667 #ifdef ALLOW_NONCONTIG
3668 /*---------------------------------------------------------------------
3669    read the voxcontig button box and set the appropriate arrowvals
3670 -----------------------------------------------------------------------*/
3671 
T3D_voxcontig_CB(Widget w,XtPointer client_data,XtPointer call_data)3672 void T3D_voxcontig_CB( Widget w ,
3673                        XtPointer client_data , XtPointer call_data )
3674 {
3675    int val ;
3676    RwcBoolean sens ;
3677 
3678    user_inputs.voxcontig = val = MCW_val_bbox( wset.voxcontig_bbox ) ;
3679 
3680    sens = (val != VOXCONTIG_YES) ; AV_SENSITIZE( wset.zspacing_av , sens ) ;
3681    T3D_set_dependent_geometries() ;
3682    RESET_QUIT ;
3683 }
3684 #endif /* ALLOW_NONCONTIG */
3685 
3686 /*---------------------------------------------------------------------
3687    Set the dependent geometry values, depending on various flags
3688 -----------------------------------------------------------------------*/
3689 
T3D_set_dependent_geometries(void)3690 void T3D_set_dependent_geometries(void)
3691 {
3692    float size ;
3693 
3694 ENTRY("T3D_set_dependent_geometries") ;
3695 
3696    if( ! XtIsRealized( wset.topshell ) ) EXRETURN ;
3697 
3698    /* Voxel shapes not irregular?  Then set them appropriately. */
3699 
3700    /* this assumes nx == ny, so check               22 Aug 2005 [rickr] */
3701    if( user_inputs.voxshape != VOXSHAPE_IRREGULAR &&
3702        user_inputs.nx > 0 && user_inputs.nx == user_inputs.ny ){
3703 
3704       size = user_inputs.fov / user_inputs.nx ;
3705 
3706       if( user_inputs.xsize != size ){
3707          AV_assign_fval( wset.xsize_av , size ) ;
3708          user_inputs.xsize = size ;
3709       }
3710 
3711       if( user_inputs.ysize != size ){
3712          AV_assign_fval( wset.ysize_av , size ) ;
3713          user_inputs.ysize = size ;
3714       }
3715 
3716       if( user_inputs.voxshape == VOXSHAPE_CUBICAL &&
3717           user_inputs.zsize    != size ){
3718          AV_assign_fval( wset.zsize_av , size ) ;
3719          user_inputs.zsize = size ;
3720       }
3721    }
3722 
3723 #ifdef ALLOW_NONCONTIG
3724    /* contiguous voxels turned on? Then set zspacing to zsize. */
3725 
3726    if( user_inputs.voxcontig == VOXCONTIG_YES &&
3727        user_inputs.zspacing  != user_inputs.zsize ){
3728       AV_assign_fval( wset.zspacing_av , user_inputs.zsize ) ;
3729       user_inputs.zspacing = user_inputs.zsize ;
3730    }
3731 #endif /* ALLOW_NONCONTIG */
3732 
3733    /* centered axes?  Then set origins from sizes. */
3734 
3735    if( (user_inputs.xyz_centered & XCENTERED) != 0 && user_inputs.nx != 0 ){
3736       size = 0.5 * (user_inputs.nx-1) * user_inputs.xsize ;
3737       if( size != user_inputs.xorigin ){
3738          AV_assign_fval( wset.xorigin_av , size ) ;
3739          user_inputs.xorigin = size ;
3740       }
3741    }
3742 
3743    if( (user_inputs.xyz_centered & YCENTERED) != 0 && user_inputs.ny != 0 ){
3744       size = 0.5 * (user_inputs.ny-1) * user_inputs.ysize ;
3745       if( size != user_inputs.yorigin ){
3746          AV_assign_fval( wset.yorigin_av , size ) ;
3747          user_inputs.yorigin = size ;
3748       }
3749    }
3750 
3751    if( (user_inputs.xyz_centered & ZCENTERED) != 0 && user_inputs.nz != 0 ){
3752 #ifdef ALLOW_NONCONTIG
3753       size = 0.5 * (user_inputs.nz-1) * user_inputs.zspacing ;
3754 #else
3755       size = 0.5 * (user_inputs.nz-1) * user_inputs.zsize ;
3756 #endif
3757       if( size != user_inputs.zorigin ){
3758          AV_assign_fval( wset.zorigin_av , size ) ;
3759          user_inputs.zorigin = size ;
3760       }
3761    }
3762 
3763    EXRETURN ;
3764 }
3765 
3766 /*---------------------------------------------------------------------
3767    read the voxshape button box and set the appropriate
3768    arrowvals to sensitive or insensitive
3769 -----------------------------------------------------------------------*/
3770 
T3D_voxshape_CB(Widget w,XtPointer client_data,XtPointer call_data)3771 void T3D_voxshape_CB( Widget w ,
3772                       XtPointer client_data , XtPointer call_data )
3773 {
3774    int val ;
3775    RwcBoolean fov_sens , xsize_sens , ysize_sens , zsize_sens ;
3776 
3777 ENTRY("T3D_voxshape_CB") ;
3778 
3779    user_inputs.voxshape = val = MCW_val_bbox( wset.voxshape_bbox ) ;
3780 
3781    switch( val ){
3782 
3783       default:  XBell( XtDisplay(wset.topshell) , 100 ) ; return ;
3784 
3785       case VOXSHAPE_CUBICAL:
3786          fov_sens   = True ;
3787          xsize_sens = ysize_sens = zsize_sens = False ;
3788       break ;
3789 
3790       case VOXSHAPE_SQUARE:
3791          fov_sens   = True ;
3792          xsize_sens = ysize_sens = False ;
3793          zsize_sens = True ;
3794       break ;
3795 
3796       case VOXSHAPE_IRREGULAR:
3797          fov_sens   = False ;
3798          xsize_sens = ysize_sens = zsize_sens = True ;
3799       break ;
3800 
3801    }
3802    AV_SENSITIZE( wset.fov_av   , fov_sens   ) ;
3803    AV_SENSITIZE( wset.xsize_av , xsize_sens ) ;
3804    AV_SENSITIZE( wset.ysize_av , ysize_sens ) ;
3805    AV_SENSITIZE( wset.zsize_av , zsize_sens ) ;
3806 
3807    T3D_set_dependent_geometries() ;
3808    RESET_QUIT ;
3809    EXRETURN ;
3810 }
3811 
3812 /*-----------------------------------------------------------------------
3813    Text displaying routine (for arrowvals)
3814 -------------------------------------------------------------------------*/
3815 
T3D_text_display(MCW_arrowval * av,XtPointer cd)3816 char * T3D_text_display( MCW_arrowval * av , XtPointer cd )
3817 {
3818    char ** tar = (char **) cd ;
3819    int  ii = av->ival ;
3820 
3821 ENTRY("T3D_text_display") ;
3822 
3823    RETURN( tar[ii] ) ;
3824 }
3825 
3826 /*----------------------------------------------------------------------*/
3827 
T3D_quit_timeout_CB(XtPointer client_data,XtIntervalId * id)3828 void T3D_quit_timeout_CB( XtPointer client_data , XtIntervalId * id )
3829 {
3830    ENTRY("T3D_quit_timeout_CB") ;
3831    RESET_QUIT ;
3832    EXRETURN ;
3833 }
3834 
T3D_quit_CB(Widget wcall,XtPointer client_data,XtPointer call_data)3835 void T3D_quit_CB( Widget wcall ,
3836                   XtPointer client_data , XtPointer call_data )
3837 {
3838    static RwcBoolean first = True ;
3839    static Widget wquit  = NULL ;
3840 
3841 ENTRY("T3D_quit_CB") ;
3842 
3843   if( wcall == NULL ){
3844     if( wquit == NULL ) return ;
3845     MCW_set_widget_label( wquit , "quit" ) ;
3846     first = True ;
3847     EXRETURN ;
3848   }
3849 
3850   if( first ){
3851      if( wquit == NULL ) wquit = wcall ;
3852      first = False ;
3853      MCW_set_widget_label( wquit , "QUIT" ) ;
3854 
3855      (void) XtAppAddTimeOut( XtWidgetToApplicationContext(wcall) ,
3856                              5000 , T3D_quit_timeout_CB , NULL ) ;
3857 
3858      EXRETURN ;
3859   }
3860 #if 0
3861   if( lrand48()%9 == 0 )
3862     MCW_melt_widget( wset.topform ) ;  /* 18 Feb 2011 */
3863 #endif
3864   exit(0) ;
3865 }
3866 
3867 /*---------------------------------------------------------------------*/
3868 
T3D_swap_CB(Widget w,XtPointer cd,XtPointer call_data)3869 void T3D_swap_CB( Widget w , XtPointer cd , XtPointer call_data )
3870 {
3871    int dd = mri_datum_size((MRI_TYPE)argopt.datum_all) ;
3872    int nx , ny , nz , nv , nvox ;
3873 
3874 ENTRY("T3D_swap_CB") ;
3875 
3876    nx = dset->daxes->nxx ; ny = dset->daxes->nyy ;
3877    nz = dset->daxes->nzz ; nv = dblk->nvals      ; nvox = nx*ny*nz*nv ;
3878 
3879    switch( dd ){
3880       case 2: swap_twobytes  ( nvox , dbrick ) ; break ;
3881       case 4: swap_fourbytes ( nvox , dbrick ) ; break ;
3882       case 8: swap_eightbytes( nvox , dbrick ) ; break ;
3883    }
3884 
3885    if( argopt.datum_all == MRI_short    /* 24 Aug 2001 */
3886         && !AFNI_yesenv("AFNI_NO_NEGATIVES_WARNING")
3887         && !ushort2float ){             /*  9 Jul 2013 [rickr] */
3888       short * sar = (short *) dbrick ; int ii ;
3889       negative_shorts = 0 ;
3890       for( ii=0 ; ii < nvox_total ; ii++ )
3891          if( sar[ii] < 0 ) negative_shorts++ ;
3892 
3893       if( negative_shorts ){
3894          float perc = (100.0*negative_shorts)/nvox_total ; char msg[512] ;
3895          sprintf(msg , " \n"
3896                        " to3d WARNING: %d negative voxels (%g%%)\n"
3897                        "               after byte-swapping.\n"     ,
3898                  negative_shorts , perc ) ;
3899 
3900          (void) MCW_popup_message( wset.anatomy_parent_label , msg ,
3901                                    MCW_USER_KILL | MCW_TIMER_KILL ) ;
3902       }
3903    }
3904 
3905    if( ISQ_REALZ(wset.seq) ){
3906       drive_MCW_imseq( wset.seq , isqDR_clearstat , NULL ) ;
3907       drive_MCW_imseq( wset.seq , isqDR_display   , (XtPointer)-1 ) ;
3908    }
3909 
3910    if( user_inputs.ntt > 5 ){                 /* 15 Aug 2001 */
3911       dset->taxis = myXtNew( THD_timeaxis ) ;
3912       dset->taxis->ntt = user_inputs.ntt ;
3913       T3D_check_outliers(0) ; outliers_checked = 1 ;
3914       myXtFree(dset->taxis) ;
3915    }
3916 
3917    EXRETURN ;
3918 }
3919 
3920 /*---------------------------------------------------------------------*/
3921 
T3D_fov_av_CB(MCW_arrowval * av,XtPointer cd)3922 void T3D_fov_av_CB( MCW_arrowval * av , XtPointer cd )
3923 {
3924    user_inputs.fov = wset.fov_av->fval ;
3925    T3D_set_dependent_geometries() ;
3926    RESET_QUIT ;
3927 }
3928 
3929 /*---------------------------------------------------------------------*/
3930 
T3D_orient_av_CB(MCW_arrowval * av,XtPointer cd)3931 void T3D_orient_av_CB( MCW_arrowval * av , XtPointer cd )
3932 {
3933    int ior = av->ival ;
3934 
3935    if( av == wset.xorient_av ){
3936       user_inputs.xorient = ior ;
3937       SET_ORIGIN_LABEL(wset.xorigin_label,user_inputs.xorient) ;
3938    } else if( av == wset.yorient_av ){
3939       user_inputs.yorient = ior ;
3940       SET_ORIGIN_LABEL(wset.yorigin_label,user_inputs.yorient) ;
3941    } else if( av == wset.zorient_av ){
3942       user_inputs.zorient = ior ;
3943       SET_ORIGIN_LABEL(wset.zorigin_label,user_inputs.zorient) ;
3944    } else if( av == wset.view_type_av ){
3945       user_inputs.view_type = ior ;
3946    } else {
3947       XBell( XtDisplay(wset.topshell) , 100 ) ;
3948       fprintf(stderr,"\n** Illegal call to T3D_orient_av_CB!\n") ;
3949    }
3950    RESET_QUIT ;
3951 }
3952 
3953 /*---------------------------------------------------------------------*/
3954 
T3D_origin_av_CB(MCW_arrowval * av,XtPointer cd)3955 void T3D_origin_av_CB( MCW_arrowval * av , XtPointer cd )
3956 {
3957    float size = av->fval ;
3958 
3959    if( av == wset.xorigin_av ){
3960       user_inputs.xorigin = size ;
3961    } else if( av == wset.yorigin_av ){
3962       user_inputs.yorigin = size ;
3963    } else if( av == wset.zorigin_av ){
3964       user_inputs.zorigin = size ;
3965    } else {
3966       XBell( XtDisplay(wset.topshell) , 100 ) ;
3967       fprintf(stderr,"\n** Illegal call to T3D_origin_av_CB!\n") ;
3968    }
3969    RESET_QUIT ;
3970 }
3971 
3972 /*---------------------------------------------------------------------*/
3973 
T3D_size_av_CB(MCW_arrowval * av,XtPointer cd)3974 void T3D_size_av_CB( MCW_arrowval * av , XtPointer cd )
3975 {
3976    float size = av->fval ;
3977 
3978    if( av == wset.xsize_av ){
3979       user_inputs.xsize = size ;
3980    } else if( av == wset.ysize_av ){
3981       user_inputs.ysize = size ;
3982    } else if( av == wset.zsize_av ){
3983       user_inputs.zsize = size ;
3984 #ifdef ALLOW_NONCONTIG
3985    } else if( av == wset.zspacing_av ){
3986       user_inputs.zspacing = size ;
3987 #endif
3988    } else {
3989       XBell( XtDisplay(wset.topshell) , 100 ) ;
3990       fprintf(stderr,"\n** Illegal call to T3D_size_av_CB!\n") ;
3991    }
3992    T3D_set_dependent_geometries() ;
3993    RESET_QUIT ;
3994 }
3995 
3996 /*---------------------------------------------------------------------*/
3997 
T3D_type_av_CB(MCW_arrowval * av,XtPointer cd)3998 void T3D_type_av_CB( MCW_arrowval * av , XtPointer cd )
3999 {
4000    int itype = av->ival ;
4001    RwcBoolean isfunc ;
4002    int nvals_old , nvals_new ;
4003 
4004    isfunc    = ISFUNCTYPE(user_inputs.dataset_type) ;
4005    nvals_old = (isfunc) ? FUNC_nvals[user_inputs.function_type]
4006                         : ANAT_nvals[user_inputs.anatomy_type]  ;
4007 
4008    if( av == wset.dataset_type_av ){
4009       user_inputs.dataset_type = itype ;
4010 
4011       isfunc = ISFUNCTYPE(itype) ;
4012 
4013 #ifdef FUNCTION_ONLY_ANAT_PARENT
4014       SENSITIZE( wset.anatomy_parent_label     , isfunc ) ;
4015       SENSITIZE( wset.anatomy_parent_textfield , isfunc ) ;
4016 #endif
4017 
4018       if( isfunc ){
4019          XtUnmapWidget( wset.anatomy_type_av->wrowcol ) ;
4020          XtMapWidget  ( wset.function_type_av->wrowcol ) ;
4021       } else {
4022          XtUnmapWidget( wset.function_type_av->wrowcol ) ;
4023          XtMapWidget  ( wset.anatomy_type_av->wrowcol ) ;
4024       }
4025 
4026    } else if( av == wset.function_type_av ){
4027       user_inputs.function_type = itype ;
4028    } else if( av == wset.anatomy_type_av ){
4029       user_inputs.anatomy_type = itype ;
4030    } else {
4031       XBell( XtDisplay(wset.topshell) , 100 ) ;
4032       fprintf(stderr,"\n** Illegal call to T3D_type_av_CB!\n") ;
4033    }
4034 
4035    /*--- check if # of values/pixel has altered ---*/
4036 
4037    isfunc    = ISFUNCTYPE(user_inputs.dataset_type) ;
4038    nvals_new = (isfunc) ? FUNC_nvals[user_inputs.function_type]
4039                         : ANAT_nvals[user_inputs.anatomy_type]  ;
4040 
4041    /*-- time-dependent data can have only 1 value per time point! --*/
4042 
4043    if( user_inputs.ntt > 0 && nvals_new != 1 ){
4044       T3D_poperr("***** DATA TYPE WARNING *****\n",
4045                  "New data type is not allowed\n"
4046                  "with time-dependent datatset!" ,1) ;
4047       return ;
4048    }
4049 
4050    if( nvals_new != nvals_old ){
4051       int nz = user_inputs.nimage / nvals_new ;
4052       if( nz * nvals_new != user_inputs.nimage ){
4053          T3D_poperr("**** DATA TYPE WARNING *****\n",
4054                     "Number of images not an even\n"
4055                     "multiple of # of data values" ,1) ;
4056       }
4057 
4058       user_inputs.nz    = nz ;
4059       user_inputs.nvals = nvals_new ;
4060       T3D_set_dependent_geometries() ;
4061       T3D_fix_dataset_dimen() ;
4062    }
4063 
4064    T3D_setup_stat_aux() ;
4065 
4066    RESET_QUIT ;
4067 }
4068 
4069 /*----------------------------------------------------------------------
4070   patch the dataset dimensions for altered nz/nvals
4071 ------------------------------------------------------------------------*/
4072 
T3D_fix_dataset_dimen(void)4073 void T3D_fix_dataset_dimen(void)
4074 {
4075    int nx , ny , nz , nv , ibr , bsize , nvold ;
4076 
4077 ENTRY("T3D_fix_dataset_dimen") ;
4078 
4079    nvold = dblk->nvals ;
4080 
4081    nv = dblk->nvals = dkptr->nvals  = user_inputs.nvals ;
4082    nx = user_inputs.nx ;
4083    ny = user_inputs.ny ;
4084    nz = daxes->nzz = dkptr->dimsizes[2]  = user_inputs.nz ;
4085 
4086    for( ibr=0 ; ibr < nvold ; ibr++ )
4087       mri_clear_data_pointer( DBLK_BRICK(dblk,ibr) ) ;
4088 
4089    myXtFree(dblk->brick_bytes) ; dblk->brick_bytes = NULL ;
4090    myXtFree(dblk->brick_fac  ) ; dblk->brick_fac   = NULL ;
4091 
4092    THD_init_datablock_brick( dblk , argopt.datum_all , NULL ) ;
4093 
4094    bsize = nx*ny*nz * mri_datum_size( argopt.datum_all ) ;
4095    for( ibr=0 ; ibr < nv ; ibr++ ){
4096       mri_fix_data_pointer( dbrick + ibr*bsize , DBLK_BRICK(dblk,ibr) ) ;
4097    }
4098 
4099    EXRETURN ;
4100 }
4101 
4102 /*------------------------------------------------------------------------
4103    read the images from the remaining command line arguments,
4104    and start the setup of the 3dim_dataset
4105 --------------------------------------------------------------------------*/
4106 
T3D_read_images(void)4107 void T3D_read_images(void)
4108 {
4109    MRI_IMAGE * im , * shim ;
4110    char * bar ;
4111    int64_t bb, bsize;       /* allow for large volumes    (Ziad's fault) */
4112                             /*                        6 Nov 2015 [rickr] */
4113                             /* more int64_t updates  26 Mar 2016 [rickr] */
4114    int npix , ii , dsize ;
4115    int nx , ny , nz , nim , lf , isfunc , nvals , kz,kim , ibr ;
4116    MRI_IMARR * arr ;
4117    char iname[THD_MAX_NAME] ;
4118    float nonshort_min=1.E38 , nonshort_max=-1.E38 ;
4119    float nonbyte_min =1.E38 , nonbyte_max =-1.E38 ;
4120    int   nonshort_num=0 , nonfloat_num=0 , noncomplex_num=0 , nonbyte_num=0 ;
4121    int   ushort_num=0 ;
4122    int     gnim ;
4123    char ** gname ;
4124    int time_dep , ltt,kzz , ntt=0,nzz=0 , nvoxt ;
4125    int kzmod ;  /* 06 Nov 2002 */
4126    int nsmax=0 ;
4127 
4128 ENTRY("T3D_read_images") ;
4129 
4130    nim = Argc - First_Image_Arg ;  /* = number of files, not images! */
4131 
4132    INIT_SARR( imnames ) ;  /* image name for each slice */
4133 
4134    MCW_warn_expand(1) ;
4135    MCW_file_expand( nim , Argv+First_Image_Arg , &gnim , &gname ) ;
4136    MCW_warn_expand(0) ;
4137 #ifdef AFNI_DEBUG
4138 printf("T3D_read_images: input file count = %d; expanded = %d\n",nim,gnim) ;
4139 #endif
4140 
4141    if( gnim < 1 ){ ERROR_exit("NO INPUT IMAGE FILES?") ; }
4142 
4143    /* may need to reverse list for some Siemens data */
4144    if(reverse_list)
4145       T3D_reverse_list(gnim, gname);
4146 
4147    /**--- count up the actual number of images into nz ---**/
4148 
4149    /** 31 Mar 2006: check for .img and .hdr goofup [the JW error] **/
4150 
4151    if( STRING_HAS_SUFFIX_CASE(gname[0],".img") ){
4152      char *hn=strdup(gname[0]) ;
4153      strcpy(hn+strlen(hn)-3,"hdr") ;
4154      if( THD_is_file(hn) )
4155        fprintf(stderr,
4156                 "++ WARNING: First image filename is '%s',\n"
4157                 "++ -- JW -: But if it is an ANALYZE or NIfTI-1 file,\n"
4158                 "++ -------: perhaps you mean to use '%s'.\n" ,
4159                gname[0] , hn ) ;
4160    }
4161 
4162 #ifndef AFNI_DEBUG
4163    printf("++ Counting images: ");fflush(stdout);
4164 #endif
4165 
4166    nz = 0 ;
4167    for( lf=0 ; lf < gnim ; lf++ ){
4168      ii = mri_imcount( gname[lf] ) ;
4169      if( ii == 0 ){
4170        if( mri_dicom_sexinfo() != NULL && !assume_dicom_mosaic )
4171          WARNING_message(
4172             "No images found. Hmmm ... try using '-assume_dicom_mosaic'?") ;
4173        ERROR_exit("bad file specifier %s\n",gname[lf]) ;
4174      }
4175      nz += ii ; nsmax = MAX(nsmax,ii) ;
4176    }
4177 #ifdef AFNI_DEBUG
4178    printf("T3D_read_images: mri_imcount totals nz=%d\n",nz) ;
4179 #else
4180    printf(" total=%d 2D slices\n",nz) ;
4181 #endif
4182 
4183    if( nsmax < 2 && mri_dicom_sexinfo() != NULL && !assume_dicom_mosaic )
4184      WARNING_message(
4185        "If images are wrong, try using '-assume_dicom_mosaic'?") ;
4186 
4187    if( nz < NZBOT ){
4188      ERROR_exit("Must have at least %d input images! ***\n",NZBOT) ;
4189    }
4190 
4191    /**------ Perform various sanity checks if the user is
4192              trying to create a time dependent dataset.  ------**/
4193 
4194    time_dep = (user_inputs.ntt > 0) ;
4195    if( time_dep ){ ntt = user_inputs.ntt ; nzz = user_inputs.nzz ; }
4196 
4197    if( time_dep && nz != ntt * nzz ){
4198       fprintf(stderr,"** Number of slices on command line   = %d\n"
4199                      "** Number of slices needed for -time: = %d\n"
4200                      "** Something is wrong with your command line!\n" ,
4201               nz , ntt * nzz ) ;
4202       exit(1) ;
4203    }
4204 
4205    if( time_dep ){
4206       isfunc = ISFUNCTYPE(user_inputs.dataset_type) ;
4207       nvals  = (isfunc) ? FUNC_nvals[user_inputs.function_type]
4208                         : ANAT_nvals[user_inputs.anatomy_type]  ;
4209 
4210       if( nvals != 1 ){
4211          fprintf(stderr,"** Sorry: time dependent datasets with more than one\n"
4212                         "**        value per time point are not yet supported!\n" ) ;
4213          exit(1) ;
4214       }
4215 
4216 #if 0
4217       if( isfunc ){
4218          fprintf(stderr,"** Sorry: time dependent functional\n"
4219                         "**        datasets are not yet supported!\n" ) ;
4220          exit(1) ;
4221       }
4222 #endif
4223    }
4224 
4225    /*--- read 1st file to get sizes ---*/
4226 
4227    CLEAR_MRILIB_globals ;  /* 12 Mar 2001 */
4228    mri_read_dicom_reset_obliquity();  /* clear any previous obliquity info */
4229    if( argopt.delay_input )
4230       arr = mri_read_file_delay( gname[0] ) ;
4231    else
4232       arr = mri_read_file( gname[0] ) ;
4233 
4234    /* maybe there is siemens slice timing info       13 Apr 2011 [rickr]
4235     * Do not fully test or apply times until MRILIB_tr has been applied,
4236     * but if user wants to populate FROM_IMAGE, check that times exist.
4237     * Also, be sure there is a tpattern to inspect.   4 May 2011 [rickr] */
4238    if( time_dep && user_inputs.tpattern && user_inputs.tpattern[0] == -666 ){
4239       populate_g_siemens_times(user_inputs.tunits);
4240       if( g_siemens_timing_nused <= 0 )
4241          ERROR_exit("No timing read for 'FROM_IMAGE' timing pattern\n");
4242    }
4243 
4244    if( arr == NULL || arr->num == 0 )
4245      ERROR_exit("Cannot read first file '%s'",gname[0]) ;
4246 
4247    im = arr->imarr[0] ;
4248 
4249    nx = im->nx ;
4250    ny = im->ny ; npix = nx * ny ;
4251 
4252    printf("++ Each 2D slice is %d X %d pixels\n",nx,ny) ;
4253 
4254    /* 05 Feb 2001: set voxel sizes, if available */
4255 
4256    if( im->dw > 0.0 ){
4257      imdx = im->dx ; imdy = im->dy ; imdz = im->dz ;  /* globals */
4258      printf("++ Voxel dimensions: %.4f X %.4f X %.4f mm\n",imdx,imdy,imdz) ;
4259    }
4260 
4261    /**--- use 1st file to set default datum type, if not set already ---**/
4262 
4263    if( argopt.datum_all < 0 ){
4264       switch( im->kind ){
4265          case MRI_byte:     argopt.datum_all = MRI_byte    ; break ;
4266 
4267          default:
4268          case MRI_short:    argopt.datum_all = MRI_short   ; break ;
4269 
4270          case MRI_int:
4271          case MRI_double:
4272          case MRI_float:    argopt.datum_all = MRI_float   ; break ;
4273 
4274          case MRI_complex:  argopt.datum_all = MRI_complex ; break ;
4275 
4276          case MRI_rgb:      argopt.datum_all = MRI_rgb     ; break ;
4277       }
4278       printf("++ Image data type = %s\n",MRI_type_name[argopt.datum_all]) ;
4279    }
4280 
4281    /**--- allocate storage for all slices to be input ---**/
4282 
4283    dsize  = mri_datum_size( (MRI_TYPE) argopt.datum_all ) ;
4284    dbrick = bar = (char*)XtMalloc( dsize * nx * ny * nz ) ;
4285    nvoxt  = nx * ny * nz ;
4286 
4287    /*--- read all files, convert to desired type if needed, put in the brick ---*/
4288 
4289 #ifndef AFNI_DEBUG
4290    printf("++ Reading images: ");fflush(stdout);
4291    kzmod = (int)(0.0234567*nz)+1 ;                /* 06 Nov 2002 */
4292 #endif
4293 
4294    kz = 0 ; if( time_dep ){ ltt = kzz = 0 ; }
4295 
4296    for( lf=0 ; lf < gnim ; lf++ ){  /** loop over files **/
4297 
4298       /*--- open this file, if not the first (which we read in a minute ago) ---*/
4299 
4300       if( lf != 0 ){
4301          if( argopt.delay_input )
4302             arr = mri_read_file_delay( gname[0] ) ;
4303          else
4304             arr = mri_read_file( gname[lf] ) ;
4305 
4306          if( arr == NULL || arr->num == 0 ){
4307            ERROR_exit("** cannot read file %s\n",gname[lf]) ;
4308          }
4309 #ifdef AFNI_DEBUG
4310 printf("T3D_read_images: file %d (%s) has #im=%d\n",lf,gname[lf],arr->num) ;
4311 #endif
4312       }
4313 
4314       for( kim=0 ; kim < arr->num ; kim++ ){  /** loop over 2D images in file **/
4315 
4316          /*--- set string for this slice for display in image viewing window ---*/
4317 
4318          if( arr->num == 1 ){
4319             strcpy( iname , gname[lf] ) ;
4320          } else {
4321             sprintf( iname , "%s#%d" , gname[lf],kim) ;
4322          }
4323          ADDTO_SARR(imnames,iname) ;
4324 
4325          /*--- get the image and check if it fits the first image dimensions ---*/
4326 
4327          im = arr->imarr[kim] ;
4328          if( im->nx != nx || im->ny != ny ){
4329            fprintf(stderr,
4330                      "\n"
4331                      "** FATAL ERROR: Image file %s has nonconforming images:\n"
4332                      "**              First file was %d X %d\n"
4333                      "**              This file  is  %d X %d\n" ,
4334                   gname[lf] , nx,ny , im->nx,im->ny) ;
4335            exit(1) ;
4336          }
4337 
4338          if( argopt.delay_input )
4339             (void) mri_data_pointer( im ) ;  /* force load of image from disk */
4340 
4341          /* 14 Sep 1998: swap bytes if ordered */
4342          /* 07 Mar 2002: but only if it wasn't already swapped */
4343 
4344          if( im->pixel_size == 2 && argopt.swap_two ){
4345             if( im->was_swapped ){  /* don't swap me */
4346               static int first=1 ;
4347               if( first ){          /* but print a message */
4348                 fprintf(stderr,"++ Ignoring -2swap on input image [%s...]\n",
4349                         (im->fname == NULL) ? "." : im->fname ) ;
4350                 first = 0 ;
4351               }
4352             } else {                /* swap me */
4353               static int first=1 ;
4354               if( first ){          /* and print a message */
4355                 fprintf(stderr,"++ Executing -2swap on input image [%s...]\n",
4356                         (im->fname == NULL) ? "." : im->fname ) ;
4357                 first = 0 ;
4358               }
4359               swap_twobytes( im->nvox , mri_data_pointer(im) ) ;
4360             }
4361          } else if( im->pixel_size == 4 && argopt.swap_four ){
4362             if( im->was_swapped ){  /* don't swap me again */
4363               static int first=1 ;
4364               if( first ){          /* but print a missive */
4365                 fprintf(stderr,"++ Ignoring -4swap on input image [%s...]\n",
4366                         (im->fname == NULL) ? "" : im->fname ) ;
4367                 first = 0 ;
4368               }
4369             } else {                /* swap me, swap me */
4370               static int first=1 ;
4371               if( first ){          /* and print a message */
4372                 fprintf(stderr,"++ Executing -4swap on input image [%s...]\n",
4373                         (im->fname == NULL) ? "." : im->fname ) ;
4374                 first = 0 ;
4375               }
4376               swap_fourbytes( im->nvox , mri_data_pointer(im) ) ;
4377             }
4378          } else if( im->pixel_size == 8 && argopt.swap_eight ){   /* 06 Feb 2003 */
4379             if( im->was_swapped ){  /* don't swap me again */
4380               static int first=1 ;
4381               if( first ){          /* but print a missive */
4382                 fprintf(stderr,"++ Ignoring -8swap on input image [%s...]\n",
4383                         (im->fname == NULL) ? "" : im->fname ) ;
4384                 first = 0 ;
4385               }
4386             } else {                /* swap me, swap me */
4387               static int first=1 ;
4388               if( first ){          /* and print a message */
4389                 fprintf(stderr,"++ Executing -8swap on input image [%s...]\n",
4390                         (im->fname == NULL) ? "." : im->fname ) ;
4391                 first = 0 ;
4392               }
4393               swap_eightbytes( im->nvox , mri_data_pointer(im) ) ;
4394             }
4395          }
4396 
4397          /* 14 Sep 1999: check float inputs for errors */
4398 
4399          if( !argopt.nofloatscan && im->kind == MRI_float )
4400             nfloat_err += thd_floatscan( im->nvox , MRI_FLOAT_PTR(im) ) ;
4401          else if( !argopt.nofloatscan && im->kind == MRI_complex )
4402             nfloat_err += thd_complexscan( im->nvox , MRI_COMPLEX_PTR(im) ) ;
4403 
4404          /*--- convert input image to desired type:  im --> shim ---*/
4405 
4406          if( im->kind == argopt.datum_all ){    /* data is desired type */
4407             shim = im ;
4408 
4409          } else {                               /* must convert data */
4410             switch( argopt.datum_all ){
4411 
4412                default: ERROR_exit("Illegal argopt.datum_all!") ;
4413 
4414                case MRI_short:{                 /** convert to shorts **/
4415                   short * shar ;
4416 
4417                   if( argopt.gsfac == 0.0 ){      /* scale each slice by itself */
4418                      float immin , immax ;
4419                      immin = mri_min( im ) ; immax = mri_max( im ) ;
4420                      if( immin >= -32767.0 && immax <= 32767.0 )
4421                         shim = mri_to_short( 1.0 , im ) ;   /* no need to scale */
4422                      else
4423                         shim = mri_to_short_scl( 0.0 , 10000.0 , im ) ;  /* scale */
4424 
4425                      nonshort_min = MIN(immin,nonshort_min) ;
4426                      nonshort_max = MAX(immax,nonshort_max) ; nonshort_num++ ;
4427                      KILL_1MRI(im) ;
4428                   } else {                         /* use global scaling factor */
4429                      float immin , immax ;
4430                      shim = mri_to_short( argopt.gsfac , im ) ;
4431                      immin = mri_min( im ) ; immax = mri_max( im ) ;
4432                      nonshort_min = MIN(immin,nonshort_min) ;
4433                      nonshort_max = MAX(immax,nonshort_max) ; nonshort_num++ ;
4434                      KILL_1MRI(im) ;
4435                   }
4436 
4437                   /* correct for oddities of FIM */
4438 
4439                   shar = MRI_SHORT_PTR( shim ) ;  /* image of shorts */
4440                   if( shar[1] == -10000 && shar[2] == 10000 ) shar[1] = shar[2] = 0 ;
4441                }
4442                break ;  /* end of conversion to shorts */
4443 
4444                case MRI_byte:{                 /** convert to bytes **/
4445 
4446                   if( argopt.gsfac == 0.0 ){      /* scale each slice by itself */
4447                      float immin , immax ;
4448                      immin = mri_min( im ) ; immax = mri_max( im ) ;
4449                      if( immin >= 0 && immax <= 255.0 )
4450                         shim = mri_to_byte_scl( 1.0 , 0.0 , im ) ; /* no scale */
4451                      else
4452                         shim = mri_to_byte_scl( 0.0 , 255.0 , im ) ;  /* scale */
4453 
4454                      nonbyte_min = MIN(immin,nonbyte_min) ;
4455                      nonbyte_max = MAX(immax,nonbyte_max) ; nonbyte_num++ ;
4456                      KILL_1MRI(im) ;
4457                   } else {                         /* use global scaling factor */
4458                      float immin , immax ;
4459                      shim = mri_to_byte_scl( argopt.gsfac , 0.0 , im ) ;
4460                      immin = mri_min( im ) ; immax = mri_max( im ) ;
4461                      nonbyte_min = MIN(immin,nonbyte_min) ;
4462                      nonbyte_max = MAX(immax,nonbyte_max) ; nonbyte_num++ ;
4463                      KILL_1MRI(im) ;
4464                   }
4465 
4466                }
4467                break ;  /* end of conversion to bytes */
4468 
4469                case MRI_float:{            /** convert to floats **/
4470                   float * shar ;
4471                   int     uconvert = ushort2float && im->kind == MRI_short;
4472 
4473                   shim = mri_to_float( im ) ;  nonfloat_num++ ;
4474                   KILL_1MRI(im) ;
4475 
4476                   shar = MRI_FLOAT_PTR( shim ) ;  /* image of floats */
4477                   if( shar[1]==-10000.0 && shar[2]==10000.0 )
4478                      shar[1]=shar[2]=0.0 ;
4479 
4480                   /* if requested and appropriate, convert negative shorts
4481                      as unsigned */
4482                   if( uconvert ) ushort_num += mri_float_convert_ushort(shim);
4483                }
4484                break ;  /* end of conversion to floats */
4485 
4486                case MRI_complex:{         /** convert to complexes **/
4487                   complex * shar ;
4488 
4489                   shim = mri_to_complex( im ) ;  noncomplex_num++ ;
4490                   KILL_1MRI(im) ;
4491 
4492                   shar = MRI_COMPLEX_PTR( shim ) ;  /* image of complexes */
4493                   if( shar[1].r == -10000.0 && shar[2].r == 10000.0 &&
4494                       shar[1].i ==      0.0 && shar[2].i ==     0.0   ){
4495 
4496                      shar[1].r=shar[2].r=0.0 ;
4497                   }
4498                }
4499                break ;  /* end of conversion to complexes */
4500 
4501                case MRI_rgb:{             /** convert to RGB **/
4502                   shim = mri_to_rgb( im ) ;
4503                   KILL_1MRI(im) ;
4504                }
4505                break ;
4506 
4507             }
4508          }  /**-- end of conversion: desired image is in shim --**/
4509 
4510 #ifdef AFNI_DEBUG
4511 printf("T3D_read_images: putting data into slice %d\n",kz) ;
4512 #endif
4513 
4514         /* random correlation testing code -- RWCox */
4515 #if 0
4516         { static MRI_IMAGE *im0 = NULL ; float cc ;
4517           if( im0 == NULL ) im0 = mri_copy(shim) ;
4518           cc = mri_spearman_corr( im0 , shim ) ;
4519           fprintf(stderr,"corr(lf=%d,kim=%d)=%f\n",lf,kim,cc) ;
4520         }
4521 #endif
4522 
4523          if( ! time_dep ){
4524 
4525             /**-- copy data from shim into the kz-th slice in bar --**/
4526 
4527             bb = (int64_t)npix * dsize * kz ;  /* might exceed 2^31-1 */
4528             memcpy( bar+bb , mri_data_pointer(shim) , npix*dsize ) ;
4529          } else {
4530 
4531             /**-- copy data from shim into the (kzz,ltt)-th slice in bar --**/
4532 
4533             /* promote early     26 Mar 2016 [rickr] */
4534             bb = npix * dsize * ( kzz + ltt * (int64_t)nzz ) ;
4535             memcpy( bar+bb , mri_data_pointer(shim) , npix*dsize ) ;
4536 
4537             /*-- step the kzz,ltt indices forward, depending on the
4538                  order in which the slices are coming in (-time:zt or :tz) --*/
4539 
4540             if( user_inputs.t_then_z ){
4541               ltt++ ; if( ltt == ntt ){ ltt = 0 ; kzz++ ; }
4542             } else {
4543               kzz++ ; if( kzz == nzz ){ kzz = 0 ; ltt++ ; }
4544             }
4545          }
4546          kz++ ;
4547 
4548          KILL_1MRI(shim) ;
4549 #ifndef AFNI_DEBUG
4550          if( kz%kzmod == 0 ){ printf(".") ; fflush(stdout); }
4551 #endif
4552       }  /** end of loop over images from 1 file **/
4553 
4554       FREE_IMARR(arr) ;
4555    }  /** end of loop over files **/
4556 #ifndef AFNI_DEBUG
4557    printf("\n");fflush(stdout);
4558 #endif
4559 
4560    if( nfloat_err > 0 )  /* 14 Sep 1999 */
4561      printf("** Found %d float errors in inputs - see program float_scan!\n",
4562             nfloat_err) ;
4563 
4564    MCW_free_expand( gnim , gname ) ;
4565 
4566    /**-- 10 Jan 2004: set slice thickness to slice spacing, if given --**/
4567 
4568    if( use_MRILIB_slicespacing && fabs(MRILIB_slicespacing-imdz) > 0.01l ){
4569      fprintf(stderr,"++ Using slice spacing=%g",MRILIB_slicespacing) ;
4570      if( imdz > 0.0 ) fprintf(stderr," instead of slice thickness=%g",imdz) ;
4571      fprintf(stderr,"\n") ;
4572      imdz = MRILIB_slicespacing ;
4573    }
4574 
4575    /**-- 19 Jan 2000: check inputs shorts for negativity --**/
4576 
4577    if( argopt.datum_all == MRI_short ){
4578      short * sar = (short *) dbrick ;
4579      for( ii=0 ; ii < nvoxt ; ii++ )
4580        if( sar[ii] < 0 ) negative_shorts++ ;
4581    }
4582    nvox_total = nvoxt ; /* 24 Aug 2001 */
4583 
4584    /**--- print conversion information ---**/
4585 
4586    if( nonshort_num > 0 )
4587       printf( "++ Number of non-short slices converted to shorts = %d\n"
4588               "++ Smallest value in them                         = %f\n"
4589               "++ Largest value in them                          = %f\n" ,
4590              nonshort_num , nonshort_min , nonshort_max ) ;
4591 
4592    if( nonbyte_num > 0 )
4593       printf( "++ Number of non-byte slices converted to bytes = %d\n"
4594               "++ Smallest value in them                       = %f\n"
4595               "++ Largest value in them                        = %f\n" ,
4596              nonbyte_num , nonbyte_min , nonbyte_max ) ;
4597 
4598    if( nonfloat_num > 0 )
4599       printf( "++ Number of non-float slices converted to floats = %d\n",
4600              nonfloat_num ) ;
4601 
4602    if( noncomplex_num > 0 )
4603       printf( "++ Number of non-complex slices converted to complexes = %d\n",
4604              noncomplex_num ) ;
4605 
4606    if( ushort_num > 0 )
4607       printf( "++ Number of overflow shorts converted to floats = %d\n",
4608              ushort_num ) ;
4609 
4610    /*--- now create the rest of the data structures, as far as we can ---*/
4611 
4612    isfunc = ISFUNCTYPE(user_inputs.dataset_type) ;
4613    nvals  = (isfunc) ? FUNC_nvals[user_inputs.function_type]
4614                      : ANAT_nvals[user_inputs.anatomy_type]  ;
4615 
4616    nim    = kz ;  /* number of images actually processed above */
4617 
4618    if( time_dep ){
4619       nvals = ntt ;
4620       if( nim != ntt * nzz ){
4621          fprintf(stderr,
4622                   "\n"
4623                   "** TIME-DEPENDENCE ERROR **\n"
4624                   "** Number of images input does not\n"
4625                   "** match number specified in -time:\n"
4626                   "** option on command line!\n" ) ;
4627          exit(1) ;
4628       }
4629    }
4630 
4631 #ifdef AFNI_DEBUG
4632 printf("T3D_read_images: nvals set to %d\n",nvals) ;
4633 #endif
4634 
4635    nz = nim / nvals ;           /* number of slices */
4636    if( nz * nvals != nim ){
4637       fprintf(stderr,
4638                "\n"
4639                "** DATA TYPE ERROR **\n"
4640                "** Number of images not an even\n"
4641                "** multiple of number of values\n"
4642                "** required for chosen data type\n" ) ;
4643       exit(1) ;
4644    }
4645 
4646    dset    =                 myXtNew( THD_3dim_dataset ) ;  /* these are */
4647    dblk    = dset->dblk    = myXtNew( THD_datablock ) ;     /* globals */
4648    daxes   = dset->daxes   = myXtNew( THD_dataxes ) ;
4649    markers = dset->markers = NULL ;                       /* later, dude */
4650    dkptr   = dblk->diskptr = myXtNew( THD_diskptr ) ;
4651 
4652    dset->tagset = NULL ;  /* Oct 1998 */
4653    dset->Label_Dtable = NULL;                  /* ZSS Feb 26 2010 */
4654 
4655    INIT_KILL(dset->kl) ; INIT_KILL(dblk->kl) ;
4656 
4657    dkptr->type         = DISKPTR_TYPE ;
4658    dkptr->rank         = 3 ;
4659    dkptr->nvals        = nvals ;
4660    dkptr->dimsizes[0]  = nx ;
4661    dkptr->dimsizes[1]  = ny ;
4662    dkptr->dimsizes[2]  = nz ;
4663    dkptr->storage_mode = STORAGE_BY_BRICK ;
4664    dkptr->byte_order   = THD_get_write_order() ;  /* 25 April 1998 */
4665    EMPTY_STRING(dkptr->prefix) ;
4666    EMPTY_STRING(dkptr->viewcode) ;
4667    EMPTY_STRING(dkptr->filecode) ;
4668    EMPTY_STRING(dkptr->directory_name) ;
4669    EMPTY_STRING(dkptr->header_name) ;
4670    EMPTY_STRING(dkptr->brick_name) ;
4671 
4672    dblk->type        = DATABLOCK_TYPE ;
4673    dblk->nvals       = dkptr->nvals ;
4674    dblk->malloc_type = DATABLOCK_MEM_MALLOC ;
4675    dblk->natr        = 0 ;
4676    dblk->natr_alloc  = 0 ;
4677    dblk->atr         = NULL ;
4678    dblk->brick       = NULL ;
4679    dblk->brick_fac   = NULL ;
4680    dblk->brick_bytes = NULL ;
4681 
4682    dblk->vedim = NULL ; /* 05 Sep 2006 */
4683 
4684    THD_init_datablock_brick( dblk , argopt.datum_all , NULL ) ;
4685    THD_null_datablock_auxdata( dblk ) ;
4686 
4687    dblk->master_nvals = 0 ;     /* 11 Jan 1999 */
4688    dblk->master_ival  = NULL ;
4689    dblk->master_bytes = NULL ;
4690 
4691    /* promote early for big volumes   26 Mar 2016 [rickr] */
4692    bsize = nx*ny*(int64_t)nz * mri_datum_size( argopt.datum_all ) ;
4693    for( ibr=0 ; ibr < nvals ; ibr++ ){
4694       mri_fix_data_pointer( dbrick + ibr*bsize , DBLK_BRICK(dblk,ibr) ) ;
4695    }
4696 
4697    daxes->type     = DATAXES_TYPE ;
4698    daxes->nxx      = nx ;
4699    daxes->nyy      = ny ;
4700    daxes->nzz      = nz ;
4701    daxes->xxorg    = - user_inputs.xorigin ;
4702    daxes->yyorg    = - user_inputs.yorigin ;
4703    daxes->zzorg    = - user_inputs.zorigin ;
4704    daxes->xxdel    =   user_inputs.xsize ;
4705    daxes->yydel    =   user_inputs.ysize ;
4706 #ifdef ALLOW_NONCONTIG
4707    daxes->zzdel    =   user_inputs.zspacing ;
4708 #else
4709    daxes->zzdel    =   user_inputs.zsize ;
4710 #endif
4711    daxes->xxorient = user_inputs.xorient ;
4712    daxes->yyorient = user_inputs.yorient ;
4713    daxes->zzorient = user_inputs.zorient ;
4714 
4715    /*--- 18 May 2007: set obliquity coordinates in header */
4716    mri_read_dicom_get_obliquity(&(daxes->ijk_to_dicom_real.m[0][0])); /*pass 16 element float */
4717 
4718    /*--- 15 Dec 2005: set the coordinate matrices in the header as well ---*/
4719 
4720    THD_set_daxes_to_dicomm(daxes) ;
4721 
4722    if( !ISVALID_MAT44(daxes->ijk_to_dicom) ) THD_daxes_to_mat44(daxes) ;
4723     /*-----*/
4724 
4725    dset->type      = user_inputs.dataset_type ;
4726    dset->view_type = user_inputs.view_type ;
4727    dset->func_type = ISANAT(dset) ? (user_inputs.anatomy_type)
4728                                   : (user_inputs.function_type) ;
4729 
4730    dset->wod_daxes   = NULL ;
4731    dset->wod_flag    = 0 ;
4732    dset->stats       = NULL ;
4733 #ifdef ALLOW_DATASET_VLIST
4734    dset->pts         = NULL ;
4735 #endif
4736    dset->death_mark  = 0 ;
4737    dset->tcat_list   = NULL ;
4738    dset->tcat_num    = 0 ;
4739    dset->tcat_len    = NULL ;
4740 
4741    ZERO_STAT_AUX( dset ) ;
4742 
4743    user_inputs.nx     = nx ;
4744    user_inputs.ny     = ny ;
4745    user_inputs.nz     = nz ;
4746    user_inputs.nimage = nim ;
4747    user_inputs.nvals  = nvals ;
4748 
4749    /**--- fix dimensions if user input axes stuff ---**/
4750 
4751    if( user_inputs.xincode > 0 ){
4752       int dcode , fov ;
4753       float dx , xorg , size ;
4754 
4755       fov   = 1 ;
4756       dcode = user_inputs.xincode - INCODE_FOV ;
4757 
4758       if( dcode < FIRST_ORIENT_TYPE || dcode > LAST_ORIENT_TYPE ){
4759          dcode = user_inputs.xincode - INCODE_SLAB ;
4760          fov   = 0 ;
4761       }
4762 
4763       if( fov ){
4764          dx   = (user_inputs.xin_bot + user_inputs.xin_top) / nx ;
4765          xorg =  user_inputs.xin_bot - 0.5*dx ;
4766       } else {
4767          dx   = (user_inputs.xin_bot + user_inputs.xin_top) / (nx-1) ;
4768          xorg =  user_inputs.xin_bot ;
4769       }
4770       user_inputs.xorient = dcode ;
4771       user_inputs.xsize   = dx ;
4772       user_inputs.xorigin = xorg ;
4773       user_inputs.fov     = nx * dx ; geometry_loaded = 1 ;
4774 
4775       size = 0.5 * (nx-1) * dx ;
4776       if( fabs(size-xorg) < 0.01 )
4777          user_inputs.xyz_centered |= XCENTERED ;
4778       else
4779          user_inputs.xyz_centered &= ~XCENTERED ;
4780    }
4781 
4782    if( user_inputs.yincode > 0 ){
4783       int dcode , fov ;
4784       float dy , yorg , size ;
4785 
4786       fov   = 1 ;
4787       dcode = user_inputs.yincode - INCODE_FOV ;
4788 
4789       if( dcode < FIRST_ORIENT_TYPE || dcode > LAST_ORIENT_TYPE ){
4790          dcode = user_inputs.yincode - INCODE_SLAB ;
4791          fov   = 0 ;
4792       }
4793 
4794       if( fov ){
4795          dy   = (user_inputs.yin_bot + user_inputs.yin_top) / ny ;
4796          yorg =  user_inputs.yin_bot - 0.5*dy ;
4797       } else {
4798          dy   = (user_inputs.yin_bot + user_inputs.yin_top) / (ny-1) ;
4799          yorg =  user_inputs.yin_bot ;
4800       }
4801       user_inputs.yorient = dcode ;
4802       user_inputs.ysize   = dy ;
4803       user_inputs.yorigin = yorg ;
4804       user_inputs.fov     = ny * dy ; geometry_loaded = 1 ;
4805 
4806       size = 0.5 * (ny-1) * dy ;
4807       if( fabs(size-yorg) < 0.01 )
4808          user_inputs.xyz_centered |= YCENTERED ;
4809       else
4810          user_inputs.xyz_centered &= ~YCENTERED ;
4811    }
4812 
4813    if( user_inputs.zincode > 0 ){
4814       int dcode , fov ;
4815       float dz , zorg , size ;
4816 
4817       fov   = 1 ;
4818       dcode = user_inputs.zincode - INCODE_FOV ;
4819 
4820       if( dcode < FIRST_ORIENT_TYPE || dcode > LAST_ORIENT_TYPE ){
4821          dcode = user_inputs.zincode - INCODE_SLAB ;
4822          fov   = 0 ;
4823       }
4824 
4825       if( fov ){
4826          dz   = (user_inputs.zin_bot + user_inputs.zin_top) / nz ;
4827          zorg =  user_inputs.zin_bot - 0.5*dz ;
4828       } else {
4829          if( nz == 1 ){
4830             fprintf(stderr,"** -zSLAB illegal with only 1 slice! ***\n") ;
4831             exit(1) ;
4832          }
4833          dz   = (user_inputs.zin_bot + user_inputs.zin_top) / (nz-1) ;
4834          zorg =  user_inputs.zin_bot ;
4835       }
4836       user_inputs.zorient = dcode ;
4837       user_inputs.zsize   = dz ;
4838       user_inputs.zorigin = zorg ;
4839 
4840       size = 0.5 * (nz-1) * dz ;
4841       if( fabs(size-zorg) < 0.01 )
4842          user_inputs.xyz_centered |= ZCENTERED ;
4843       else
4844          user_inputs.xyz_centered &= ~ZCENTERED ;
4845    } else if( use_zoff ) { /* single slice dset:   25 Jun 2014 [rickr] */
4846         user_inputs.zorigin = zoff ;
4847         user_inputs.xyz_centered &= ~ZCENTERED ;
4848    }
4849 
4850    dset->taxis = NULL ;  /* will be patched later, if necessary */
4851 
4852    if( commandline != NULL ) tross_Append_History( dset , commandline ) ;
4853 
4854    /*********** DONE **********/
4855 
4856    EXRETURN ;
4857 }
4858 
4859 /*-------------------------------------------------------------*/
4860 
T3D_open_view_CB(Widget w,XtPointer client_data,XtPointer call_data)4861 void T3D_open_view_CB( Widget w ,
4862                        XtPointer client_data , XtPointer call_data )
4863 {
4864    FD_brick * br ;
4865    char * title = "to3d" ;
4866    int nim ;
4867 
4868    if( wset.seq != NULL ){
4869       if( ISQ_REALZ(wset.seq) )
4870          XMapRaised( XtDisplay(wset.topshell) , XtWindow(wset.seq->wtop) ) ;
4871       else
4872          XBell( XtDisplay(wset.topshell) , 100 ) ; /* should never happen */
4873       return ;
4874    }
4875 
4876    daxes->xxdel = user_inputs.xsize ;  /* these are here to make */
4877    daxes->yydel = user_inputs.ysize ;  /* the aspect ratio work  */
4878 #ifdef ALLOW_NONCONTIG
4879    daxes->zzdel = user_inputs.zspacing ;
4880 #else
4881    daxes->zzdel = user_inputs.zsize ;
4882 #endif
4883 
4884    br = THD_3dim_dataset_to_brick( dset , 1,2,3 ) ;
4885 
4886    if( br == NULL ){
4887       XBell( XtDisplay(wset.topshell) , 100 ) ;
4888       fprintf(stderr,"\n** bad data in THD_3dim_dataset_to_brick!\n");
4889       return ;
4890    }
4891 
4892    wset.seq = open_MCW_imseq( wset.dc , T3D_getim , br ) ;
4893    drive_MCW_imseq( wset.seq,isqDR_realize , NULL ) ;
4894    NORMAL_cursorize( wset.seq->wimage ) ;                       /* 07 Dec 2001 */
4895 
4896    drive_MCW_imseq(wset.seq,isqDR_getimnr, (XtPointer) &nim ) ;
4897    drive_MCW_imseq(wset.seq,isqDR_title  , (XtPointer) imnames->ar[nim] ) ;
4898 
4899    drive_MCW_imseq(wset.seq,isqDR_opacitybut    ,(XtPointer)0); /* 07 Mar 2001 */
4900    drive_MCW_imseq(wset.seq,isqDR_record_disable,(XtPointer)0); /* 24 Apr 2001 */
4901    drive_MCW_imseq(wset.seq,isqDR_zoombut       ,(XtPointer)0); /* 12 Mar 2002 */
4902    drive_MCW_imseq(wset.seq,isqDR_penbbox       ,(XtPointer)0); /* 12 Mar 2002 */
4903 
4904    /* 01 Dec 1999: add "sides" markers for image viewer */
4905 
4906    { static char * ws[4] = { "-x" , "-y" , "+x" , "+y" } ;
4907      drive_MCW_imseq( wset.seq, isqDR_winfosides, (XtPointer)ws ) ;
4908    }
4909 
4910    drive_MCW_imseq( wset.seq , isqDR_display , (XtPointer)-1 ) ;
4911 
4912    MCW_invert_widget( wset.open_view_pb ) ;
4913 
4914    RESET_QUIT ;
4915 }
4916 
4917 /*-------------------------------------------------------------------*/
4918 
T3D_getim(int n,int type,FD_brick * br)4919 XtPointer T3D_getim( int n , int type , FD_brick * br )
4920 {
4921    MCW_imseq_status * stat ;
4922 
4923    if( n < 0 || n >= br->n3 || type == isqCR_getoverlay ) return NULL ;
4924 
4925    if( type == isqCR_getstatus ){
4926       stat = myXtNew( MCW_imseq_status ) ;
4927 
4928       stat->num_total  = br->n3 ;
4929       stat->num_series = br->n3 ;
4930       stat->send_CB    = T3D_imseq_CB ;
4931       stat->parent     = (XtPointer) br ;
4932       stat->aux        = NULL ;
4933 
4934       stat->transforms0D = NULL ;
4935       stat->transforms2D = NULL ;
4936       stat->slice_proj   = NULL ;
4937 
4938       return (XtPointer) stat ;
4939    }
4940 
4941    if( type == isqCR_getimage || type == isqCR_getqimage ){
4942       return (XtPointer) FD_brick_to_mri( n , 0 , br ) ;
4943    }
4944 
4945    return NULL ; /* should never be reached */
4946 }
4947 
4948 /*-------------------------------------------------------------------*/
4949 
T3D_imseq_CB(MCW_imseq * seq,FD_brick * br,ISQ_cbs * cbs)4950 void T3D_imseq_CB( MCW_imseq * seq , FD_brick * br , ISQ_cbs * cbs )
4951 {
4952    switch( cbs->reason ){
4953 
4954       case isqCR_destroy:
4955          myXtFree( seq ) ; wset.seq = NULL ;
4956          myXtFree( br ) ;
4957          MCW_invert_widget( wset.open_view_pb ) ;
4958       break ;
4959 
4960       case isqCR_newimage:
4961          drive_MCW_imseq( seq, isqDR_title, (XtPointer) imnames->ar[cbs->nim] ) ;
4962       break ;
4963 
4964       case isqCR_force_redisplay:{  /* 22 Aug 1998 */
4965          drive_MCW_imseq( seq , isqDR_display , (XtPointer)ITOP(seq->im_nr) ) ;
4966          drive_MCW_imseq( seq , isqDR_rebar   , (XtPointer)ITOP(seq->im_nr) ) ;
4967       }
4968 
4969    }
4970    return ;
4971 }
4972 
4973 /*-----------------------------------------------------------------------
4974    Save the stuff
4975 -------------------------------------------------------------------------*/
4976 
T3D_save_file_CB(Widget w,XtPointer client_data,XtPointer call_data)4977 void T3D_save_file_CB( Widget w ,
4978                        XtPointer client_data , XtPointer call_data )
4979 {
4980    RwcBoolean good , isfunc ;
4981    int ii , jj , bigfile ;
4982    Widget wmsg = NULL ;
4983    int npad ;
4984 
4985    /*-- store all control data in the user_inputs data struct --*/
4986 
4987    if( wset.topshell != NULL && wset.good ) T3D_widgets_to_data() ;
4988 
4989    /*-- check for legal values --*/
4990 
4991    good = T3D_check_data( True ) ;
4992    if( !good ) return ;
4993 
4994    AFNI_speak("Saving",0) ;
4995 
4996    /*-- store values in dataset --*/
4997 
4998    dset->type      = user_inputs.dataset_type ;
4999    dset->view_type = user_inputs.view_type ;
5000 
5001    isfunc = ISFUNC(dset) ;
5002 
5003    dset->func_type = (isfunc) ? (user_inputs.function_type)
5004                               : (user_inputs.anatomy_type) ;
5005 
5006    if( isfunc && FUNC_HAVE_THR(dset->func_type) ){
5007       int iv = FUNC_ival_thr[dset->func_type] ;
5008       switch( DBLK_BRICK_TYPE(dblk,iv) ){
5009          default:
5010             dblk->brick_fac[iv] = 0.0 ;
5011          break ;
5012 
5013          case MRI_short:
5014             dblk->brick_fac[iv] = 1.0 / FUNC_scale_short[dset->func_type] ;
5015          break ;
5016 
5017          case MRI_byte:
5018             dblk->brick_fac[iv] = 1.0 / FUNC_scale_byte[dset->func_type] ;
5019          break ;
5020       }
5021    }
5022 
5023    if( user_inputs.need_stat_aux ){
5024       INIT_STAT_AUX( dset ,
5025                      FUNC_need_stat_aux[user_inputs.function_type] ,
5026                      user_inputs.stat_aux ) ;
5027    }
5028 
5029    dset->warp = NULL ;
5030 
5031    MCW_strncpy( dset->label1 , user_inputs.short_label1 , THD_MAX_LABEL ) ;
5032    MCW_strncpy( dset->label2 , user_inputs.short_label2 , THD_MAX_LABEL ) ;
5033    dset->keywords = NULL ;
5034 
5035    if( strlen(dset->label1) == 0 ){
5036       MCW_strncpy( dset->label1 , user_inputs.output_filename , THD_MAX_LABEL ) ;
5037    }
5038 
5039    EMPTY_STRING( dset->warp_parent_name ) ;
5040    ZERO_IDCODE(dset->warp_parent_idcode) ;
5041 
5042    if( strlen(user_inputs.anatomy_dataname) > 0 ){
5043       MCW_strncpy( dset->anat_parent_name ,
5044                    user_inputs.anatomy_dataname , THD_MAX_NAME ) ;
5045       dset->anat_parent_idcode = user_inputs.anatomy_parent_idcode ;
5046    } else {
5047       EMPTY_STRING( dset->anat_parent_name ) ;
5048       ZERO_IDCODE(dset->anat_parent_idcode) ;
5049    }
5050 
5051    MCW_strncpy( dset->self_name, user_inputs.dataset_name, THD_MAX_NAME ) ;
5052 
5053    daxes->xxorient = user_inputs.xorient ;
5054    daxes->yyorient = user_inputs.yorient ;
5055    daxes->zzorient = user_inputs.zorient ;
5056 
5057    daxes->xxorg = (ORIENT_sign[user_inputs.xorient] == '+')
5058                   ? (-user_inputs.xorigin) : ( user_inputs.xorigin) ;
5059 
5060    daxes->yyorg = (ORIENT_sign[user_inputs.yorient] == '+')
5061                   ? (-user_inputs.yorigin) : ( user_inputs.yorigin) ;
5062 
5063    daxes->zzorg = (ORIENT_sign[user_inputs.zorient] == '+')
5064                   ? (-user_inputs.zorigin) : ( user_inputs.zorigin) ;
5065 
5066    daxes->xxdel = (ORIENT_sign[user_inputs.xorient] == '+')
5067                   ? ( user_inputs.xsize) : (-user_inputs.xsize) ;
5068 
5069    daxes->yydel = (ORIENT_sign[user_inputs.yorient] == '+')
5070                   ? ( user_inputs.ysize) : (-user_inputs.ysize) ;
5071 
5072 #ifdef ALLOW_NONCONTIG
5073    daxes->zzdel = (ORIENT_sign[user_inputs.zorient] == '+')
5074                   ? ( user_inputs.zspacing) : (-user_inputs.zspacing) ;
5075 #else
5076    daxes->zzdel = (ORIENT_sign[user_inputs.zorient] == '+')
5077                   ? ( user_inputs.zsize) : (-user_inputs.zsize) ;
5078 #endif
5079 
5080    /*-- this stuff is no longer used --*/
5081 
5082 #ifdef ALLOW_NONCONTIG
5083    daxes->xxskip = 0.0 ;
5084    daxes->yyskip = 0.0 ;
5085    daxes->zzskip = user_inputs.zspacing - user_inputs.zsize ;
5086 #endif
5087 
5088    /* if user has selected, get origin from obliquity */
5089    /*   overriding all the previous selections - GUI or command-line */
5090    if(use_oblique_origin)
5091       Obliquity_to_coords(dset);
5092 
5093    dset->taxis = NULL ;
5094 
5095    if( user_inputs.ntt > 0 ){
5096       dset->taxis = myXtNew( THD_timeaxis ) ;
5097 
5098       dset->taxis->type       = TIMEAXIS_TYPE ;
5099       dset->taxis->ntt        = user_inputs.ntt ;
5100       dset->taxis->ttdel      = user_inputs.TR ;
5101       dset->taxis->ttdur      = 0.0 ;
5102       dset->taxis->units_type = user_inputs.tunits ;  /* 21 Oct 1996 */
5103       dset->taxis->ttorg      = user_inputs.Torg ;    /* 23 Feb 2005 */
5104 
5105       if( user_inputs.tpattern != NULL ){
5106          dset->taxis->nsl     = daxes->nzz ;
5107          dset->taxis->zorg_sl = daxes->zzorg ;
5108          dset->taxis->dz_sl   = daxes->zzdel ;
5109          dset->taxis->toff_sl = user_inputs.tpattern ;
5110       } else {
5111          dset->taxis->nsl     = 0 ;
5112          dset->taxis->zorg_sl = 0.0 ;
5113          dset->taxis->dz_sl   = 0.0 ;
5114          dset->taxis->toff_sl = NULL ;
5115       }
5116    }
5117 
5118    /*-- get the dataset statistics --*/
5119 
5120    if( dset->taxis == NULL )
5121       bigfile = (daxes->nxx * daxes->nyy * daxes->nzz > 9999999) ;
5122    else
5123       bigfile = (daxes->nxx * daxes->nyy * daxes->nzz * dset->taxis->ntt > 9999999) ;
5124 
5125    if( wset.topshell != NULL && bigfile && wset.good ){
5126       wmsg = MCW_popup_message( wset.save_file_pb ,
5127                                    "***************\n"
5128                                    "*  Computing  *\n"
5129                                    "*  dataset    *\n"
5130                                    "*  statistics *\n"
5131                                    "***************" ,
5132                                 MCW_CALLER_KILL ) ;
5133       WATCH_cursorize( wmsg ) ;
5134       XFlush( XtDisplay(wmsg) ) ;
5135    } else {
5136       wmsg = NULL ;
5137    }
5138 
5139    THD_load_statistics( dset ) ;
5140 
5141    if( !outliers_checked ){    /* 15 Aug 2001 */
5142       T3D_check_outliers(0) ; outliers_checked = 1 ;
5143    }
5144 
5145    if( wmsg != NULL ) XtDestroyWidget( wmsg ) ;
5146 
5147    /*-- maybe some Talairach markers, too --*/
5148 
5149    if( dset->type      == HEAD_ANAT_TYPE     &&
5150        dset->view_type == VIEW_ORIGINAL_TYPE &&
5151        DSET_NUM_TIMES(dset) == 1                ){  /* no markers on 3D+t datasets! */
5152 
5153       markers = dset->markers = myXtNew( THD_marker_set ) ;
5154       markers->numdef = 0 ;
5155 
5156       for( ii=0 ; ii < MARKS_MAXNUM ; ii++ ){       /* null all data out */
5157          markers->valid[ii] = 0 ;
5158          for( jj=0 ; jj < MARKS_MAXLAB  ; jj++ )
5159             markers->label[ii][jj] = '\0';
5160          for( jj=0 ; jj < MARKS_MAXHELP ; jj++ )
5161             markers->help[ii][jj]  = '\0';
5162       }
5163 
5164       for( ii=0 ; ii < NMARK_ALIGN ; ii++ ){       /* copy strings in */
5165          MCW_strncpy( &(markers->label[ii][0]) ,
5166                       THD_align_label[ii] , MARKS_MAXLAB ) ;
5167          MCW_strncpy( &(markers->help[ii][0]) ,
5168                       THD_align_help[ii] , MARKS_MAXHELP ) ;
5169       }
5170 
5171       for( ii=0 ; ii < MARKS_MAXFLAG ; ii++ )     /* copy flags in */
5172          markers->aflags[ii] = THD_align_aflags[ii] ;
5173 
5174    } /* end of markers (for HEAD_ANAT_TYPE) */
5175 
5176    /*----- actually write the dataset out! -----*/
5177 
5178    if( wset.topshell != NULL && bigfile && wset.good ){
5179       wmsg = MCW_popup_message( wset.save_file_pb ,
5180                                    "********************\n"
5181                                    "*  Please wait for *\n"
5182                                    "*  disk operation  *\n"
5183                                    "********************" ,
5184                                 MCW_CALLER_KILL ) ;
5185       WATCH_cursorize( wmsg ) ;
5186       XFlush( XtDisplay(wmsg) ) ;
5187    } else {
5188       wmsg = NULL ;
5189    }
5190 
5191    /** make up a new idcode for this new output dataset **/
5192 
5193    dset->idcode = MCW_new_idcode() ;
5194 
5195    THD_patch_brickim(dset) ; /* 19 Dec 2011 -- don't allow grid spacing = 0 */
5196 
5197    npad = (int)zpad ;
5198    if( npad == 0 ){   /* the old code */
5199 
5200       good = THD_write_3dim_dataset( user_inputs.session_filename ,
5201                    user_inputs.output_filename , dset , user_inputs.writebrik ) ;
5202 
5203    } else {           /* 05 Feb 2001: allow for zero-padding in z-direction */
5204       THD_3dim_dataset * qset=NULL ;
5205       int flag=0 ;
5206 
5207       if( zpad_mm ) flag = ZPAD_MM ;
5208 
5209       switch( daxes->zzorient ){
5210          case ORI_R2L_TYPE:
5211          case ORI_L2R_TYPE:
5212             qset = THD_zeropad( dset, 0,0,0,0,npad,npad, user_inputs.output_filename,flag ) ;
5213          break ;
5214 
5215          case ORI_P2A_TYPE:
5216          case ORI_A2P_TYPE:
5217             qset = THD_zeropad( dset, 0,0,npad,npad,0,0, user_inputs.output_filename,flag ) ;
5218          break ;
5219 
5220          case ORI_I2S_TYPE:
5221          case ORI_S2I_TYPE:
5222             qset = THD_zeropad( dset, npad,npad,0,0,0,0, user_inputs.output_filename,flag ) ;
5223          break ;
5224 
5225          default:
5226             fprintf(stderr,"** Can't zpad: zzorient=%d\n",daxes->zzorient) ;
5227          break ;
5228       }
5229 
5230       if( commandline != NULL ) tross_Append_History( qset , commandline ) ;
5231 
5232       { int ppad[3] ;
5233         ppad[0] = ppad[1] = 0 ; ppad[2] = npad ;
5234         THD_set_int_atr( qset->dblk , "TO3D_ZPAD" , 3 , ppad ) ;
5235       }
5236 
5237       THD_load_statistics( qset ) ;
5238       good = THD_write_3dim_dataset( user_inputs.session_filename ,
5239                                      user_inputs.output_filename ,
5240                                      qset , user_inputs.writebrik ) ;
5241       DSET_delete(qset) ;
5242    }
5243 
5244    if( wmsg != NULL ) XtDestroyWidget( wmsg ) ;
5245 
5246    if( !good ) T3D_poperr("*******************\n\n" ,
5247                           "Some error occurred\n"
5248                           "while trying to write file", 1) ;
5249 
5250    else if( wset.topshell != NULL && wset.good )
5251       wmsg = MCW_popup_message( wset.save_file_pb ,
5252                                  "*********************\n"
5253                                  "*  Dataset written  *\n"
5254                                  "*  out to disk.     *\n"
5255                                  "*********************" ,
5256                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
5257 
5258    return ;
5259 }
5260 
5261 /*-------------------------------------------------------------------
5262    Just to be safe, load the data structure from the widgets
5263 ---------------------------------------------------------------------*/
5264 
T3D_widgets_to_data(void)5265 void T3D_widgets_to_data(void)
5266 {
5267    char * str ;
5268 
5269    if( wset.topshell == NULL || !wset.good ) return ;
5270 
5271    user_inputs.xorient = wset.xorient_av->ival ;
5272    user_inputs.yorient = wset.yorient_av->ival ;
5273    user_inputs.zorient = wset.zorient_av->ival ;
5274 
5275    user_inputs.voxshape     = MCW_val_bbox( wset.voxshape_bbox ) ;
5276 #ifdef ALLOW_NONCONTIG
5277    user_inputs.voxcontig    = MCW_val_bbox( wset.voxcontig_bbox ) ;
5278 #endif
5279    user_inputs.xyz_centered = MCW_val_bbox( wset.centered_bbox ) ;
5280 
5281    user_inputs.dataset_type  = wset.dataset_type_av->ival ;
5282    user_inputs.function_type = wset.function_type_av->ival ;
5283    user_inputs.anatomy_type  = wset.anatomy_type_av->ival ;
5284 
5285    MCW_strncpy( user_inputs.dataset_type_string ,
5286                 DATASET_typestr[user_inputs.dataset_type] ,
5287                 THD_MAX_NAME ) ;
5288 
5289    MCW_strncpy( user_inputs.function_type_string ,
5290                 FUNC_typestr[user_inputs.function_type] ,
5291                 THD_MAX_NAME ) ;
5292 
5293    MCW_strncpy( user_inputs.anatomy_type_string ,
5294                 ANAT_typestr[user_inputs.anatomy_type] ,
5295                 THD_MAX_NAME ) ;
5296 
5297    user_inputs.fov      = wset.fov_av->fval ;
5298    user_inputs.xsize    = wset.xsize_av->fval ;
5299    user_inputs.ysize    = wset.ysize_av->fval ;
5300    user_inputs.zsize    = wset.zsize_av->fval ;
5301 #ifdef ALLOW_NONCONTIG
5302    user_inputs.zspacing = wset.zspacing_av->fval ;
5303 #endif
5304    user_inputs.xorigin  = wset.xorigin_av->fval ;
5305    user_inputs.yorigin  = wset.yorigin_av->fval ;
5306    user_inputs.zorigin  = wset.zorigin_av->fval ;
5307 
5308 #ifndef NO_NAMES
5309    str = XmTextFieldGetString( wset.dataset_name_textfield ) ;
5310    MCW_strncpy( user_inputs.dataset_name, str, THD_MAX_NAME ) ;
5311    myXtFree(str) ;
5312 
5313    str = XmTextFieldGetString( wset.short_label1_textfield ) ;
5314    MCW_strncpy( user_inputs.short_label1, str, THD_MAX_LABEL ) ;
5315    myXtFree(str) ;
5316 #endif
5317 
5318    str = XmTextFieldGetString( wset.geometry_parent_textfield ) ;
5319    MCW_strncpy( user_inputs.geometry_parent_filename, str, THD_MAX_NAME ) ;
5320    myXtFree(str) ;
5321 
5322    str = XmTextFieldGetString( wset.anatomy_parent_textfield ) ;
5323    MCW_strncpy( user_inputs.anatomy_parent_filename, str, THD_MAX_NAME ) ;
5324    myXtFree(str) ;
5325 
5326    str = XmTextFieldGetString( wset.output_file_textfield ) ;
5327    MCW_strncpy( user_inputs.output_filename, str, THD_MAX_NAME ) ;
5328    myXtFree(str) ;
5329 
5330    str = XmTextFieldGetString( wset.session_file_textfield ) ;
5331    MCW_strncpy( user_inputs.session_filename, str, THD_MAX_NAME ) ;
5332    myXtFree(str) ;
5333 
5334 #ifndef NO_NAMES
5335    str = XmTextFieldGetString( wset.geometry_dataname_textfield ) ;
5336    MCW_strncpy( user_inputs.geometry_dataname , str, THD_MAX_NAME ) ;
5337    myXtFree(str) ;
5338 
5339    str = XmTextFieldGetString( wset.anatomy_dataname_textfield ) ;
5340    MCW_strncpy( user_inputs.anatomy_dataname , str, THD_MAX_NAME ) ;
5341    myXtFree(str) ;
5342 #endif
5343 
5344    if( user_inputs.need_stat_aux ){
5345       int ii ;
5346       char * endptr , * sstr ;
5347 
5348       for( ii=0 ; ii < MAX_STAT_AUX ; ii++ )
5349          user_inputs.stat_aux[ii] = 0.0 ;
5350 
5351       sstr = XmTextFieldGetString( wset.stat_aux_textfield ) ;
5352       if( sstr != NULL ){
5353 
5354          /** scan thru string, converting to floats **/
5355 
5356          str = sstr ;
5357          ii  = 0 ;
5358          do{
5359             /* skip ahead over whitespace or commas */
5360 
5361             while( *str != '\0' && ( isspace(*str) || *str == ',' ) ) str++ ;
5362             if( *str == '\0' ) break ;  /* end of scanning */
5363 
5364             user_inputs.stat_aux[ii++] = strtod(str,&endptr) ;
5365 
5366             if( endptr == str || *endptr == '\0' ) break ; /* end of scanning */
5367 
5368             str = endptr ; /* otherwise, move to next location */
5369          } while ( ii < MAX_STAT_AUX ) ;
5370          myXtFree(sstr) ;
5371       }
5372    }
5373 
5374    return ;
5375 }
5376 
5377 /*-------------------------------------------------------------------
5378    Load the widgets from the data structure
5379 ---------------------------------------------------------------------*/
5380 
T3D_data_to_widgets(void)5381 void T3D_data_to_widgets(void)
5382 {
5383    if( wset.topshell == NULL || !wset.good ) return ;  /* no widgets! */
5384 
5385    AV_assign_ival( wset.xorient_av , user_inputs.xorient ) ;
5386    AV_assign_ival( wset.yorient_av , user_inputs.yorient ) ;
5387    AV_assign_ival( wset.zorient_av , user_inputs.zorient ) ;
5388 
5389    MCW_set_bbox( wset.voxshape_bbox  , user_inputs.voxshape     ) ;
5390 #ifdef ALLOW_NONCONTIG
5391    MCW_set_bbox( wset.voxcontig_bbox , user_inputs.voxcontig    ) ;
5392 #endif
5393    MCW_set_bbox( wset.centered_bbox  , user_inputs.xyz_centered ) ;
5394 
5395    AV_assign_ival( wset.dataset_type_av  , user_inputs.dataset_type ) ;
5396    AV_assign_ival( wset.function_type_av , user_inputs.function_type ) ;
5397    AV_assign_ival( wset.anatomy_type_av , user_inputs.anatomy_type ) ;
5398 
5399    AV_assign_fval( wset.fov_av       , user_inputs.fov ) ;
5400    AV_assign_fval( wset.xsize_av     , user_inputs.xsize ) ;
5401    AV_assign_fval( wset.ysize_av     , user_inputs.ysize ) ;
5402    AV_assign_fval( wset.zsize_av     , user_inputs.zsize ) ;
5403 #ifdef ALLOW_NONCONTIG
5404    AV_assign_fval( wset.zspacing_av  , user_inputs.zspacing ) ;
5405 #endif
5406    AV_assign_fval( wset.xorigin_av   , user_inputs.xorigin ) ;
5407    AV_assign_fval( wset.yorigin_av   , user_inputs.yorigin ) ;
5408    AV_assign_fval( wset.zorigin_av   , user_inputs.zorigin ) ;
5409 
5410    SET_ORIGIN_LABEL(wset.xorigin_label,user_inputs.xorient) ;
5411    SET_ORIGIN_LABEL(wset.yorigin_label,user_inputs.yorient) ;
5412    SET_ORIGIN_LABEL(wset.zorigin_label,user_inputs.zorient) ;
5413 
5414    T3D_voxshape_CB (NULL,NULL,NULL) ;  /* take actions based on */
5415 #ifdef ALLOW_NONCONTIG
5416    T3D_voxcontig_CB(NULL,NULL,NULL) ;  /* settings of these toggles */
5417 #endif
5418    T3D_centered_CB (NULL,NULL,NULL) ;
5419 
5420    T3D_type_av_CB( wset.dataset_type_av , NULL ) ;  /* set dataset type */
5421 
5422 #ifndef NO_NAMES
5423    XmTextFieldSetString( wset.dataset_name_textfield ,
5424                          user_inputs.dataset_name ) ;
5425 
5426    XmTextFieldSetString( wset.short_label1_textfield ,
5427                          user_inputs.short_label1 ) ;
5428 #endif
5429 
5430    XmTextFieldSetString( wset.geometry_parent_textfield ,
5431                          user_inputs.geometry_parent_filename ) ;
5432 
5433    XmTextFieldSetString( wset.anatomy_parent_textfield ,
5434                          user_inputs.anatomy_parent_filename ) ;
5435 
5436    XmTextFieldSetString( wset.output_file_textfield ,
5437                          user_inputs.output_filename ) ;
5438 
5439    XmTextFieldSetString( wset.session_file_textfield ,
5440                          user_inputs.session_filename ) ;
5441 
5442 #ifndef NO_NAMES
5443    XmTextFieldSetString( wset.geometry_dataname_textfield ,
5444                          user_inputs.geometry_dataname ) ;
5445 
5446    XmTextFieldSetString( wset.anatomy_dataname_textfield ,
5447                          user_inputs.anatomy_dataname ) ;
5448 #endif
5449 
5450    /* April 1996: stat_aux data fields */
5451 
5452    T3D_setup_stat_aux() ;
5453 
5454    { int ii,num,bl ; char buf[256] ;
5455 
5456      for( ii=MAX_STAT_AUX-1 ; ii>=0 && user_inputs.stat_aux[ii]==0.0 ; ii-- ) ; /* nada */
5457      num = ii+1 ;
5458 
5459      if( num > 0 ){
5460        buf[0] = '\0' ;
5461        for( ii=0 ; ii < num ; ii++ ){
5462           bl = strlen(buf) ; if( bl+12 > 256 ) break ;
5463           sprintf( buf+bl , "%g " , user_inputs.stat_aux[ii] ) ;
5464        }
5465        XmTextFieldSetString( wset.stat_aux_textfield , buf ) ;
5466      }
5467    }
5468 
5469    return ;
5470 }
5471 
5472 /*-----------------------------------------------------------
5473   check data in user_inputs for legality
5474 -------------------------------------------------------------*/
5475 
5476 #define OUTERR "*** ILLEGAL INPUTS (cannot save) ***\n\n"
5477 
T3D_check_data(RwcBoolean perr)5478 RwcBoolean T3D_check_data( RwcBoolean perr )
5479 {
5480    char xlab,ylab,zlab ;
5481    int ii , ll , ll_out , ll_sess ;
5482    RwcBoolean good = True , isfunc ;
5483    char new_name[THD_MAX_NAME] ;
5484 
5485 ENTRY("T3D_check_data") ;
5486 
5487    /*-- check that orientations are legal --*/
5488 
5489    xlab = ORIENT_xyz[user_inputs.xorient] ;
5490    ylab = ORIENT_xyz[user_inputs.yorient] ;
5491    zlab = ORIENT_xyz[user_inputs.zorient] ;
5492 
5493    if( xlab == ylab || xlab == zlab || ylab == zlab ){
5494       T3D_poperr( OUTERR , "Axes orientations are not consistent!" , perr) ;
5495       good = False ;
5496    }
5497 
5498    /*-- check that the output filename is acceptable --*/
5499 
5500 STATUS("check output filename") ;
5501 
5502    ll_out = ll = strlen( user_inputs.output_filename ) ;
5503    if( ll == 0 ){
5504       if(perr)T3D_poperr( OUTERR , "No output filename provided!", perr ) ;
5505       good = False ;
5506    } else {
5507       for( ii=0 ; ii < ll ; ii++ )
5508          if( iscntrl(user_inputs.output_filename[ii]) ||
5509              isspace(user_inputs.output_filename[ii]) ||
5510              user_inputs.output_filename[ii] == '/'     ) break ;
5511 
5512       if( ii < ll ){
5513         if ( user_inputs.output_filename[ii] == '/' )
5514          T3D_poperr( OUTERR ,
5515                     "Output filename cannot contain '/' character.", perr ) ;
5516         else
5517          T3D_poperr( OUTERR ,
5518                     "Output filename contains illegal character!", perr ) ;
5519          good = False ;
5520       }
5521    }
5522 
5523    /*-- check that the session filename is acceptable --*/
5524 
5525 STATUS("check session name") ;
5526 
5527    ll_sess = ll = strlen( user_inputs.session_filename ) ;
5528    if( ll == 0 ){
5529       T3D_poperr( OUTERR , "No session directory name provided!", perr ) ;
5530       good = False ;
5531    } else {
5532       for( ii=0 ; ii < ll ; ii++ )
5533          if( iscntrl(user_inputs.session_filename[ii]) ||
5534              isspace(user_inputs.session_filename[ii])   ) break ;
5535 
5536       if( ii < ll ){
5537          T3D_poperr( OUTERR ,
5538                     "Session filename contains illegal character!", perr ) ;
5539          good = False ;
5540       }
5541    }
5542 
5543    /* Check if the file already exists */
5544 
5545 STATUS("check if file exists") ;
5546 
5547    if( ll_sess > 0 && ll_out > 0 ){
5548       PATH_CONCAT( new_name , user_inputs.session_filename ,
5549                               user_inputs.output_filename   ) ;
5550       strcat(new_name , "+orig." DATASET_HEADER_SUFFIX ) ;
5551       ll = THD_is_file( new_name ) || THD_is_directory( new_name ) ;
5552       if( ll ){
5553        T3D_poperr( OUTERR , "Output file already exists!", perr ) ;
5554        good = False ;
5555       }
5556    }
5557 
5558    /*-- if the image type is functional, check
5559         that the anatomy parent dataset name has been set --*/
5560 
5561    isfunc = ISFUNCTYPE(user_inputs.dataset_type) ;
5562 
5563 #ifdef REQUIRE_ANAT_PARENT
5564    if( isfunc && strlen(user_inputs.anatomy_dataname) == 0 ){
5565       T3D_poperr( OUTERR , "Anatomy parent not properly set!", perr ) ;
5566       good = False ;
5567    }
5568 #endif
5569 
5570    /*-- check for good data types in the bricks --*/
5571 
5572 STATUS("check data types") ;
5573 
5574    if( isfunc ){
5575       if( ! AFNI_GOOD_FUNC_DTYPE(argopt.datum_all) ){
5576          T3D_poperr(OUTERR , "Illegal functional datum type!", perr ) ;
5577          good = False ;
5578       }
5579    } else {
5580       if( ! AFNI_GOOD_DTYPE(argopt.datum_all) ){
5581          T3D_poperr(OUTERR , "Illegal anatomical datum type!", perr ) ;
5582          good = False ;
5583       }
5584    }
5585 
5586    /*-- check if a dataset name has been defined --*/
5587 
5588 #ifndef NO_NAMES
5589    if( strlen(user_inputs.dataset_name) == 0 ){
5590       T3D_poperr( OUTERR,"You **MUST** supply a name for the dataset!",
5591             perr ) ;
5592       good = False ;
5593    }
5594 #endif
5595 
5596    /*-- check if the stat_aux parameters are good --*/
5597 
5598 STATUS("check stat aux") ;
5599 
5600    T3D_setup_stat_aux() ;
5601    if( user_inputs.need_stat_aux ){
5602 
5603       for( ii=0 ; ii < FUNC_need_stat_aux[user_inputs.function_type] ; ii++ )
5604          if( user_inputs.stat_aux[ii] <= 0.0 ) break ;
5605 
5606       if( ii < FUNC_need_stat_aux[user_inputs.function_type] ){
5607          T3D_poperr(OUTERR , "Invalid statistical parameters!", perr ) ;
5608          good = False ;
5609       }
5610    }
5611 
5612    /*-- return the status we found --*/
5613 
5614    RETURN( good );
5615 }
5616 
5617 /*----------------------------------------------------------------*/
5618 
T3D_poperr(char * prefix_msg,char * msg,RwcBoolean exit_flag)5619 void T3D_poperr( char * prefix_msg , char * msg, RwcBoolean exit_flag )
5620 {
5621    static char * total_msg = NULL ;
5622    static int    len_total = 0 ;
5623    int len_needed ;
5624 
5625 ENTRY("T3D_poperr") ;
5626 
5627    len_needed = strlen(prefix_msg) + strlen(msg) + 2 ;
5628    if( len_needed > len_total ){
5629       total_msg = (char*)XtRealloc( total_msg , len_needed ) ;
5630       len_total = len_needed ;
5631    }
5632    strcpy( total_msg , prefix_msg ) ;
5633    strcat( total_msg , msg ) ;
5634 
5635    if( wset.topshell != NULL && wset.good ){
5636       (void) MCW_popup_message( wset.action_frame,
5637                                 total_msg, MCW_USER_KILL | MCW_TIMER_KILL ) ;
5638       XFlush( XtDisplay(wset.topshell) ) ;
5639       NI_sleep(999) ;
5640    } else {
5641 /*      fprintf(stderr,"%s\n",total_msg) ;*/
5642      if(exit_flag)
5643         ERROR_exit(total_msg);  /* exit with error message */
5644      else
5645         WARNING_message(total_msg); /* just show warning and continue */
5646    }
5647    EXRETURN ;
5648 }
5649 
5650 /*-----------------------------------------------------------------
5651    Simulate an activate callback when the pointer leaves a widget
5652 -------------------------------------------------------------------*/
5653 
T3D_pointer_leave_EV(Widget w,XtPointer client_data,XEvent * ev,RwcBoolean * continue_to_dispatch)5654 void T3D_pointer_leave_EV( Widget w , XtPointer client_data ,
5655                            XEvent * ev , RwcBoolean * continue_to_dispatch )
5656 {
5657    XLeaveWindowEvent * lev = (XLeaveWindowEvent *) ev ;
5658    XmAnyCallbackStruct cbs ;
5659 
5660    if( lev->type != LeaveNotify || w == NULL ) return ;
5661 
5662    cbs.reason = XmCR_ACTIVATE ;  /* simulate a return press */
5663    cbs.event  = ev ;
5664    XtCallCallbacks( w , XmNactivateCallback , &cbs ) ;
5665 }
5666 
5667 /*---------------------------------------------------------------
5668    Geometry parent name has been specified, so check it out
5669 -----------------------------------------------------------------*/
5670 
5671 #undef  DEBLANK
5672 #define DEBLANK(str) \
5673    { int iq ;        \
5674      for( iq=strlen(str)-1; iq >= 0 && str[iq]==' '; iq-- )str[iq]='\0'; \
5675    }
5676 
5677 #define INERR "*** DATASET READ ERROR ***\n\n"
5678 
T3D_geometry_parent_CB(Widget w,XtPointer client_data,XtPointer call_data)5679 void T3D_geometry_parent_CB( Widget w ,
5680                              XtPointer client_data , XtPointer call_data )
5681 {
5682    static char * old_name = NULL ;
5683    char * new_name ;
5684    float size ;
5685    char new_path[THD_MAX_NAME] , new_pref[THD_MAX_NAME] ;
5686    THD_3dim_dataset * geom_dset ;
5687    THD_dataxes      * geom_daxes ;
5688 
5689    int xpad=0,ypad=0,zpad=0 ;  /* 05 Feb 2001 */
5690 
5691 ENTRY("T3D_geometry_parent_CB") ;
5692 
5693    if( old_name == NULL ) old_name = XtNewString("Elvis Lives!!!") ;
5694 
5695    if( w != NULL ){
5696       new_name = XmTextFieldGetString( w ) ;  /* get the new text */
5697    } else {
5698       new_name = XtNewString( user_inputs.geometry_parent_filename ) ;
5699    }
5700    DEBLANK(new_name) ;
5701 
5702    if( strlen(new_name) == 0 )         { old_name = new_name ; geomparent_loaded = 0 ; EXRETURN ; }
5703    if( strcmp(new_name,old_name) == 0 ){ myXtFree(new_name) ; geomparent_loaded = 0 ; EXRETURN ; }
5704 
5705    /* have a new filename --> try to read dataset from it */
5706 
5707    myXtFree(old_name) ; old_name = new_name ;
5708 
5709    /* make a pathname to the geometry dataset */
5710 
5711    if( strstr(new_name,"/") == NULL ){
5712       char * sess ;
5713       if( w != NULL ) sess = XmTextFieldGetString(wset.session_file_textfield);
5714       else            sess = XtNewString( user_inputs.session_filename ) ;
5715       DEBLANK(sess) ;
5716       if( strlen(sess) > 0 ){
5717          PATH_CONCAT( new_path , sess , new_name ) ;
5718       } else {
5719          strcpy( new_path , new_name ) ;
5720       }
5721       myXtFree(sess) ;
5722    } else {
5723       strcpy( new_path , new_name ) ;
5724    }
5725 
5726    FILENAME_TO_PREFIX(new_path,new_pref) ;
5727 
5728    /* no +orig if file has known extension       29 Apr 2009 [rickr] */
5729    if( strlen(new_pref) == 0 && !has_known_non_afni_extension(new_path) )
5730       strcat(new_path,"+orig") ;
5731 
5732    /* read dataset from this path */
5733 
5734    geom_dset = THD_open_one_dataset( new_path ) ;
5735    if( geom_dset == NULL ){
5736       T3D_poperr( INERR ,
5737                   "Cannot read 3D dataset\nin geometry parent file", 1 ) ;
5738       geomparent_loaded = 0 ; EXRETURN ;
5739    }
5740 
5741    /* 05 Feb 2001: set if this was a 'padded' dataset from an earlier to3d */
5742 
5743    { ATR_int * atr ;
5744      atr = THD_find_int_atr( geom_dset->dblk , "TO3D_ZPAD" ) ;
5745      if( atr != NULL && atr->nin >= 3 ){
5746         xpad = atr->in[0] ;
5747         ypad = atr->in[1] ;
5748         zpad = atr->in[2] ;
5749      }
5750    }
5751 
5752    geom_daxes = geom_dset->daxes ;
5753 
5754    if( geom_daxes->nxx - 2*xpad != user_inputs.nx ||
5755        geom_daxes->nyy - 2*ypad != user_inputs.ny ||
5756        geom_daxes->nzz - 2*zpad != user_inputs.nz   ){
5757 
5758        char msg[256] ;
5759 
5760        sprintf(msg,
5761                  "*** Shape mismatch!! ***\n"
5762                  "file   nx=%d ny=%d nz=%d (zpad=%d)\n"
5763                  "images nx=%d ny=%d nz=%d",
5764                geom_daxes->nxx,geom_daxes->nyy,geom_daxes->nzz,zpad,
5765                user_inputs.nx ,user_inputs.ny ,user_inputs.nz  ) ;
5766 
5767        T3D_poperr( INERR , msg , 1) ;
5768        THD_delete_3dim_dataset( geom_dset , False ) ;
5769        geomparent_loaded = 0 ; EXRETURN ;
5770    }
5771 
5772 #ifdef ALLOW_NONCONTIG
5773    if( geom_daxes->xxskip != 0.0 || geom_daxes->yyskip != 0.0 ){
5774       T3D_poperr( INERR , "Nonzero skip factors for x and y!" , 1) ;
5775       THD_delete_3dim_dataset( geom_dset , False ) ;
5776       geomparent_loaded = 0 ; EXRETURN ;
5777    }
5778 #endif
5779 
5780    /* at this point, the geom dataset seems OK, so copy its axes data */
5781 
5782    /* but first, load all data from the widgets into the user_inputs
5783       (this will mean that the T3D_data_to_widgets call later won't
5784        clobber any un-altered but currently un-saved data fields    */
5785 
5786    T3D_widgets_to_data() ;
5787 
5788 #ifdef REQUIRE_ANAT_PARENT
5789    if( strlen(geom_dset->anat_parent_name) > 0 ){
5790       MCW_strncpy( user_inputs.anatomy_dataname ,
5791                    geom_dset->anat_parent_name, THD_MAX_NAME ) ;
5792       user_inputs.anatomy_parent_idcode = geom_dset->anat_parent_idcode ;
5793    }
5794 #endif
5795 
5796    MCW_strncpy( user_inputs.geometry_dataname ,
5797                 geom_dset->self_name , THD_MAX_NAME ) ;
5798 
5799    MCW_strncpy( user_inputs.geometry_parent_filename ,
5800                 new_name , THD_MAX_NAME ) ;
5801 
5802    user_inputs.xorient = geom_daxes->xxorient ;
5803    user_inputs.yorient = geom_daxes->yyorient ;
5804    user_inputs.zorient = geom_daxes->zzorient ;
5805 
5806 #if 0  /* Bad stuff, replaced June 20, 1995 */
5807 
5808    user_inputs.xorigin = fabs(geom_daxes->xxorg) ;
5809    user_inputs.yorigin = fabs(geom_daxes->yyorg) ;
5810    user_inputs.zorigin = fabs(geom_daxes->zzorg) ;
5811 
5812 #else  /* newer stuff [05 Feb 2001] - allow for padding in to3d before */
5813 
5814    { float xorg = geom_daxes->xxorg + xpad * geom_daxes->xxdel ;
5815      float yorg = geom_daxes->yyorg + ypad * geom_daxes->yydel ;
5816      float zorg = geom_daxes->zzorg + zpad * geom_daxes->zzdel ;
5817 
5818      user_inputs.xorigin = (ORIENT_sign[user_inputs.xorient] == '+')
5819                            ? (-xorg) : (xorg) ;
5820      user_inputs.yorigin = (ORIENT_sign[user_inputs.yorient] == '+')
5821                            ? (-yorg) : (yorg) ;
5822      user_inputs.zorigin = (ORIENT_sign[user_inputs.zorient] == '+')
5823                            ? (-zorg) : (zorg) ;
5824    }
5825 #endif
5826 
5827    user_inputs.xsize    = fabs(geom_daxes->xxdel) ;
5828    user_inputs.ysize    = fabs(geom_daxes->yydel) ;
5829 #ifdef ALLOW_NONCONTIG
5830    user_inputs.zspacing = fabs(geom_daxes->zzdel) ;
5831    user_inputs.zsize    = user_inputs.zspacing - geom_daxes->zzskip ;
5832 #else
5833    user_inputs.zsize    = fabs(geom_daxes->zzdel) ;
5834 #endif
5835 
5836    /*-- set the vox*_bbox values depending on initial sizes --*/
5837 
5838    if( user_inputs.xsize != user_inputs.ysize ){
5839       user_inputs.voxshape = VOXSHAPE_IRREGULAR ;
5840    } else {
5841       if( user_inputs.xsize != user_inputs.zsize ){
5842          user_inputs.voxshape = VOXSHAPE_SQUARE ;
5843       } else {
5844          user_inputs.voxshape = VOXSHAPE_CUBICAL ;
5845       }
5846    }
5847    user_inputs.fov = user_inputs.xsize * user_inputs.nx ;
5848 
5849 #ifdef ALLOW_NONCONTIG
5850    if( geom_daxes->zzskip == 0 ) user_inputs.voxcontig = VOXCONTIG_YES ;
5851    else                          user_inputs.voxcontig = VOXCONTIG_UNIF ;
5852 #endif
5853 
5854    user_inputs.xyz_centered = 0 ;
5855 
5856    size = 0.5 * (user_inputs.nx-1) * user_inputs.xsize ;
5857    if( fabs(size - user_inputs.xorigin) < 0.01 )
5858       user_inputs.xyz_centered |= XCENTERED ;
5859 
5860    size = 0.5 * (user_inputs.ny-1) * user_inputs.ysize ;
5861    if( fabs(size - user_inputs.yorigin) < 0.01 )
5862       user_inputs.xyz_centered |= YCENTERED ;
5863 
5864    size = 0.5 * (user_inputs.nz-1) * user_inputs.zsize ;
5865    if( fabs(size - user_inputs.zorigin) < 0.01 )
5866       user_inputs.xyz_centered |= ZCENTERED ;
5867 
5868    T3D_data_to_widgets() ;
5869 
5870    THD_delete_3dim_dataset( geom_dset , False ) ;
5871 
5872    geometry_loaded   = 1 ;
5873    geomparent_loaded = 1 ;  /* flag that load was OK */
5874 
5875    EXRETURN ;
5876 }
5877 
5878 /*---------------------------------------------------------------
5879    Anatomy parent name has been specified, so check it out
5880 -----------------------------------------------------------------*/
5881 
T3D_anatomy_parent_CB(Widget w,XtPointer client_data,XtPointer call_data)5882 void T3D_anatomy_parent_CB( Widget w ,
5883                             XtPointer client_data , XtPointer call_data )
5884 {
5885    static char * old_name = NULL ;
5886    char * new_name ;
5887    char new_path[THD_MAX_NAME] , new_pref[THD_MAX_NAME] ;
5888    RwcBoolean isfunc ;
5889    THD_3dim_dataset * anat_dset ;
5890 
5891 ENTRY("T3D_anatomy_parent_CB") ;
5892 
5893    if( old_name == NULL ) old_name = XtNewString("Elvis Lives!!!") ;
5894 
5895    /* see if the new text is any different from the old one */
5896 
5897    if( w != NULL ){
5898       new_name = XmTextFieldGetString( w ) ;  /* get the new text */
5899    } else {
5900       new_name = XtNewString( user_inputs.anatomy_parent_filename ) ;
5901    }
5902    DEBLANK(new_name) ;
5903 
5904    if( strlen(new_name) == 0 )         { old_name = new_name ; EXRETURN ; }
5905    if( strcmp(new_name,old_name) == 0 ){ myXtFree(new_name) ; EXRETURN ; }
5906 
5907    /* have a new filename --> try to read dataset from it */
5908 
5909    myXtFree(old_name) ; old_name = new_name ;
5910 
5911    /* make a pathname to the anatomy dataset */
5912 
5913    if( strstr(new_name,"/") == NULL ){
5914       char * sess ;
5915       if( w != NULL ) sess = XmTextFieldGetString(wset.session_file_textfield);
5916       else            sess = XtNewString( user_inputs.session_filename ) ;
5917       DEBLANK(sess) ;
5918       if( strlen(sess) > 0 ){
5919          PATH_CONCAT( new_path , sess , new_name ) ;
5920       } else {
5921          strcpy( new_path , new_name ) ;
5922       }
5923       myXtFree(sess) ;
5924    } else {
5925       strcpy( new_path , new_name ) ;
5926    }
5927 
5928    FILENAME_TO_PREFIX(new_path,new_pref) ;
5929    if( strlen(new_pref) == 0 ) strcat(new_path,"+orig") ;
5930 
5931    anat_dset = THD_open_one_dataset( new_path ) ;
5932    if( anat_dset == NULL ){
5933       T3D_poperr( INERR ,
5934                   "Cannot read 3D dataset\nin anatomy parent file", 1) ;
5935       EXRETURN ;
5936    }
5937 
5938    isfunc = ISFUNC(anat_dset) ;
5939    if( isfunc ){
5940       T3D_poperr( INERR ,
5941                   "Anatomy parent dataset\nis actually Function data!",1 ) ;
5942       THD_delete_3dim_dataset( anat_dset , False ) ;
5943       EXRETURN ;
5944    }
5945 
5946    /* at this point, the anat dataset seems OK, so use it */
5947 
5948    MCW_strncpy( user_inputs.anatomy_dataname ,
5949                 anat_dset->self_name , THD_MAX_NAME ) ;
5950    user_inputs.anatomy_parent_idcode = anat_dset->idcode ;
5951 
5952 #ifndef NO_NAMES
5953    if( w != NULL ) XmTextFieldSetString( wset.anatomy_dataname_textfield ,
5954                                          user_inputs.anatomy_dataname ) ;
5955 #endif
5956 
5957    MCW_strncpy( user_inputs.anatomy_parent_filename ,
5958                 new_name , THD_MAX_NAME ) ;
5959 
5960    THD_delete_3dim_dataset( anat_dset , False ) ;
5961 
5962    EXRETURN ;
5963 }
5964 
5965 /****************************************************************/
5966 /***** June 1995: routine to load constants from X defaults *****/
5967 
5968 #if 0
5969 # define NAME2INT(nnn,iii,bot,top)           \
5970   { xdef = XGetDefault(display,"AFNI",nnn) ; \
5971     if( xdef != NULL ){                      \
5972        ival = strtol( xdef , &cpt , 10 ) ;   \
5973        if( *cpt == '\0' && ival >= (bot) && ival <= (top) ) (iii) = ival ; } }
5974 
5975 # define NAME2FLOAT(nnn,fff,bot,top)         \
5976   { xdef = XGetDefault(display,"AFNI",nnn) ; \
5977     if( xdef != NULL ){                      \
5978        fval = strtod( xdef , &cpt ) ;        \
5979        if( *cpt == '\0' && fval >= (bot) && fval <= (top) ) (fff) = fval ; } }
5980 
5981 # define NAME2STRING(nnn,sss)                \
5982   { xdef = XGetDefault(display,"AFNI",nnn) ; \
5983     if( xdef != NULL ) sss  = XtNewString(xdef) ; }
5984 #else
5985 # define NAME2INT(nnn,iii,bot,top)           \
5986   { xdef = RWC_getname(display,nnn) ;        \
5987     if( xdef != NULL ){                      \
5988        ival = strtol( xdef , &cpt , 10 ) ;   \
5989        if( *cpt == '\0' && ival >= (bot) && ival <= (top) ) (iii) = ival ; } }
5990 
5991 # define NAME2FLOAT(nnn,fff,bot,top)         \
5992   { xdef = RWC_getname(display,nnn) ;        \
5993     if( xdef != NULL ){                      \
5994        fval = strtod( xdef , &cpt ) ;        \
5995        if( *cpt == '\0' && fval >= (bot) && fval <= (top) ) (fff) = fval ; } }
5996 
5997 # define NAME2STRING(nnn,sss)                \
5998   { xdef = RWC_getname(display,nnn) ;        \
5999     if( xdef != NULL ) sss  = XtNewString(xdef) ; }
6000 #endif
6001 
6002 #define BAD -999
6003 
AFNI_load_defaults(Widget w)6004 void AFNI_load_defaults( Widget w )
6005 {
6006    char    * xdef ;
6007    Display * display ;
6008    int       ival ;
6009    float     fval ;
6010    char *    cpt ;
6011 
6012 ENTRY("AFNI_load_defaults") ;
6013 
6014    if( w == NULL ) EXRETURN ;
6015    display = XtDisplay( w ) ;
6016 
6017    /** initialize display and overlay colors **/
6018 
6019    NAME2INT("ncolors",INIT_ngray,3,MAX_COLORS) ;
6020 
6021    NAME2FLOAT("gamma",INIT_gamma,0.1,9.9) ;
6022 
6023    NAME2FLOAT("init_fov",INIT_fov,1.0,1000.0) ;
6024    INIT_fov = 0.1 * ( (int)(10*INIT_fov) ) ;
6025 
6026    EXRETURN ;
6027 }
6028 
6029 /*-------------------------------------------------------------*/
6030 
T3D_stat_aux_CB(Widget w,XtPointer client_data,XtPointer call_data)6031 void T3D_stat_aux_CB( Widget w ,
6032                       XtPointer client_data , XtPointer call_data )
6033 {
6034    return ;
6035 }
6036 
T3D_setup_stat_aux(void)6037 void T3D_setup_stat_aux(void)
6038 {
6039    char lbuf[THD_MAX_NAME] ;
6040    RwcBoolean needit ;
6041 
6042 ENTRY("T3D_setup_stat_aux") ;
6043 
6044    user_inputs.need_stat_aux =
6045        ( ISFUNCTYPE(user_inputs.dataset_type) &&
6046          FUNC_need_stat_aux[user_inputs.function_type] > 0 ) ;
6047 
6048    if( wset.topshell != NULL && wset.good ){
6049       needit = (RwcBoolean) user_inputs.need_stat_aux ;
6050 
6051       if( needit ){
6052          sprintf( lbuf , "%s: statistical parameters for %s" ,
6053                   FUNC_label_stat_aux[user_inputs.function_type] ,
6054                   FUNC_typestr[user_inputs.function_type] ) ;
6055       } else {
6056          sprintf( lbuf , "Field below not applicable" ) ;
6057       }
6058       XtSetSensitive( wset.stat_aux_label , needit ) ;
6059       XtSetSensitive( wset.stat_aux_textfield , needit ) ;
6060       MCW_set_widget_label( wset.stat_aux_label , lbuf ) ;
6061    }
6062 
6063    EXRETURN ;
6064 }
6065 
6066 #ifndef USE_OLD_DCODE
6067 /***----------------------------------------------------------
6068  21 Nov 1997 [RWCox]:
6069    Decode a location string in one of the forms
6070      <number><dircode>
6071      <dircode><number>
6072      <dircode>
6073      <number>
6074    val will be WAY_BIG if the number isn't given, otherwise
6075      it will be the number;
6076    dcode will be < 0 if the dircode isn't given, otherwise
6077      it will be the direction code.
6078    The return value is the number of characters used from
6079      the input string.
6080 --------------------------------------------------------------***/
6081 
decode_location(char * str,float * val,int * dcode)6082 int decode_location( char * str , float * val , int * dcode )
6083 {
6084    char acod , * ptr , * sstr = str ;
6085 
6086    *val   = WAY_BIG ;
6087    *dcode = ILLEGAL_TYPE ;
6088    if( sstr == NULL || sstr[0] == '\0' ) return 0 ;
6089 
6090    /** see if we get a legal direction code here **/
6091 
6092    acod = toupper(sstr[0]) ; *dcode = ORCODE(acod) ;
6093    if( *dcode >= 0 ) sstr++ ;
6094 
6095    if( sstr[0] == '\0' ) return ((*dcode < 0) ? 0 : 1) ;
6096 
6097    /** get number here **/
6098 
6099    *val = strtod( sstr , &ptr ) ;
6100    if( *val == 0.0 && ptr == sstr ) return ((*dcode < 0) ? 0 : 1) ;
6101    sstr = ptr ;
6102 
6103    if( *dcode >= 0 || sstr[0] == '\0' ) return (sstr-str) ;
6104 
6105    acod = toupper(sstr[0]) ; *dcode = ORCODE(acod) ;
6106    if( *dcode >= 0 ) sstr++ ;
6107 
6108    return (sstr-str) ;
6109 }
6110 #endif /* USE_OLD_DCODE */
6111 
6112 /*----------------------- 15 Aug 2001: count outliers -----------------------------*/
6113 
6114 /* convert ushorts to short range in float image
6115    (part of converting unsigned shorts to floats)  9 Jul 2013 [rickr]
6116 
6117    Add 2^16 to any negative values (to undo 2's complement).
6118  */
mri_float_convert_ushort(MRI_IMAGE * fim)6119 static int mri_float_convert_ushort( MRI_IMAGE * fim ){
6120    float * far;
6121    int     index, nconvert;
6122 
6123 ENTRY("mri_float_convert_ushort") ;
6124 
6125    if( fim->kind != MRI_float ) {
6126       WARNING_message("have non-float image in mri_float_convert_ushort");
6127       RETURN(0);
6128    }
6129 
6130    far = MRI_FLOAT_PTR(fim);
6131    nconvert = 0;
6132    for( index = 0; index < fim->nvox; index++ )
6133       if( far[index] < 0 ) {
6134          far[index] += 65536;
6135          nconvert++;
6136       }
6137 
6138    RETURN(nconvert);
6139 }
6140 
T3D_check_outliers(int opcode)6141 void T3D_check_outliers( int opcode )
6142 {
6143    char *eee = my_getenv("AFNI_TO3D_OUTLIERS") ;
6144    int skip = (eee != NULL && (*eee == 'N' || *eee == 'n')) ;
6145    int text = (eee != NULL && (*eee == 'T' || *eee == 't')) ;
6146 
6147 ENTRY("T3D_check_outliers") ;
6148 
6149    if( dset->taxis != NULL                  &&
6150        dset->taxis->ntt > 5                 &&
6151        !skip                                &&
6152        ISANATTYPE(user_inputs.dataset_type) &&
6153        negative_shorts < 0.01*nvox_total    &&
6154        ! ushort2float  ){
6155 
6156      int *out_count, out_ctop , cc=0 ;
6157      Widget wmsg=NULL ;
6158 
6159      if( wset.topshell != NULL && wset.good ){
6160         wmsg = MCW_popup_message( wset.save_file_pb ,
6161                                    "****************\n"
6162                                    "* Checking for *\n"
6163                                    "* time series  *\n"
6164                                    "*   outliers   *\n"
6165                                    "****************" ,
6166                                 MCW_CALLER_KILL ) ;
6167         CURSOR_watchize ;
6168      } else {
6169         fprintf(stderr,"++ Checking for time series outliers\n") ;
6170      }
6171 
6172      THD_outlier_count( dset , 0.01 , &out_count , &out_ctop ) ;
6173 
6174      if( out_count != NULL && out_ctop > 0 ){  /* compute the output message */
6175         int iv,nvals=dset->taxis->ntt ; char *msg = AFMALL(char,2048+8*nvals) ;
6176 
6177         strcpy(msg," \nto3d WARNING:\nSignificant outliers detected in these sub-bricks:\n") ;
6178 
6179         for( iv=0 ; iv < nvals ; iv++ ){
6180            if( out_count[iv] > out_ctop ){
6181               sprintf(msg+strlen(msg)," %3d",iv) ; cc++ ;
6182               if( cc%12 == 0 ) strcat(msg,"\n") ;
6183            }
6184         }
6185 
6186         if( outliers_fname != NULL ){                    /* 26 Aug 2001 */
6187            FILE *fp = fopen( outliers_fname , "w" ) ;
6188            if( fp == NULL ){
6189              fprintf(stderr,"** Can't open -save_outliers %s\n",outliers_fname);
6190            } else {
6191              for( iv=0 ; iv < nvals ; iv++ )
6192                fprintf(fp,"%3d %3d\n",out_count[iv],out_ctop) ;
6193              fclose(fp) ;
6194            }
6195         }
6196 
6197         if( cc > 0 ){                             /* any sub-bricks fail? */
6198            if( cc%12 > 0 ) strcat(msg,"\n") ;
6199            strcat(msg,"You should inspect the dataset for possible corruption.\n");
6200            strcat(msg," [Outliers are defined as in program 3dToutcount.     ]\n");
6201            strcat(msg," [Outliers early in an EPI time series may be due to  ]\n");
6202            strcat(msg," [the longitudinal magnetization equilibration effect.]\n");
6203            strcat(msg," [Other causes are subject movement, scanner problems,]\n");
6204            strcat(msg," [or anything that makes a time series look irregular.]\n");
6205            strcat(msg," [  3dToutcount -save outnam dataset | 1dplot -stdin  ]\n");
6206            strcat(msg," [can be used to make a dataset 'outnam' that marks   ]\n");
6207            strcat(msg," [outlier voxels; see 3dToutcount -help for details.  ]\n");
6208 
6209            fprintf(stderr,"%s\n",msg) ;                        /* print message        */
6210            if( wset.topshell != NULL && !text && wset.good ){  /* graph outlier count  */
6211               float *y[2] ;
6212               y[0] = AFMALL(float, sizeof(float)*nvals) ;
6213               y[1] = AFMALL(float, sizeof(float)*nvals) ;
6214               for( iv=0 ; iv < nvals ; iv++ ){
6215                  y[0][iv] = out_count[iv] ; y[1][iv] = out_ctop ;
6216               }
6217               memplot_topshell_setsaver( ".jpg", memplot_to_jpg ); /* 05 Dec 2007 */
6218               memplot_topshell_setsaver( ".png", memplot_to_png );
6219               plot_ts_lab( XtDisplay(wset.topshell) ,              /* graph */
6220                            nvals , NULL , 2 , y ,
6221                            "Sub-brick Index" ,
6222                            "Outlier Count (and Threshold)" ,
6223                            user_inputs.output_filename , NULL , NULL ) ;
6224               free(y[0]); free(y[1]) ;
6225               (void) MCW_popup_message( wset.xsize_av->wrowcol , /* message */
6226                                         msg , MCW_USER_KILL     ) ;
6227            }
6228         }
6229         free(msg) ;
6230      }
6231 
6232      if( out_count != NULL ) free(out_count) ;
6233 
6234      if( wset.topshell != NULL && wset.good ){
6235         XtDestroyWidget(wmsg); CURSOR_normalize;
6236         if( cc == 0 )
6237           (void) MCW_popup_message( wset.save_file_pb ,
6238                                     " \n"
6239                                     "** No unusual outlier  **\n"
6240                                     "** concentration found **\n" ,
6241                                     MCW_USER_KILL | MCW_TIMER_KILL ) ;
6242      } else {
6243         if( cc == 0 )
6244           fprintf(stderr,"++ No unusual outlier concentration found\n") ;
6245      }
6246    }
6247 
6248    EXRETURN ;
6249 }
6250 
6251 
6252 /* reverse the list of input files */
6253 static void
T3D_reverse_list(int gnim,char ** gname)6254 T3D_reverse_list(int gnim, char ** gname)
6255 {
6256    int i;
6257    char **strlist;
6258 
6259    strlist = (char **) malloc( sizeof(char *) * gnim ) ;
6260    for(i=0; i<gnim; i++)
6261       strlist[i] = gname[gnim-i-1];
6262    for(i=0; i<gnim; i++)
6263       gname[i] = strlist[i];
6264 
6265    free(strlist);
6266 }
6267