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