1
2 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
3 /* This is the mother goddess of all FMRI programs, so bow down before it! */
4 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
5 /* Look on my works, Ye Mighty, and despair! */
6 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
7
8 /*****************************************************************************
9 Major portions of this software are copyrighted by the Medical College
10 of Wisconsin, 1994-2000, and are released under the Gnu General Public
11 License, Version 2 (or later). See the file README.Copyright for details.
12 ******************************************************************************/
13
14 /**********************************************************************/
15 /* MCW/GPL/NIH AFNI: */
16 /* Analysis of Functional NeuroImages */
17 /* */
18 /* Author: Robert W. Cox, PhD */
19 /* Scientific and Statistical Computing Core */
20 /* National Institute of Mental Health */
21 /* Bethesda, MD 20892 USA */
22 /* */
23 /* Acknowledgments: */
24 /* + This program would have been much more difficult had */
25 /* not Andrzej Jesmanowicz forged the way with FD. */
26 /* + Many neuroscientists have made helpful suggestions along */
27 /* the way, including Jeff Binder, Ted DeYoe, Jim Hyde, Steve */
28 /* Rao, and Elliot Stein. */
29 /* + Thanks are also due to Mike Beauchamp, who is perhaps the most */
30 /* sophisticated user of AFNI that I've met, and who has found */
31 /* many bugs or gotchas in this code. */
32 /* + Doug Ward of MCW has contributed much to the overall package. */
33 /* + Ziad Saad of NIH has also contributed many useful suggestions. */
34 /* + Peter Bandettini of NIH has asked many many "quick" questions. */
35 /* + Sean and Alex Bellgowan have contributed in their own way. */
36 /**********************************************************************/
37
38 /* the definition below is used in some header files,
39 and it indicates that the main() program is in this file */
40
41 #define MAIN
42
43 #include "afni.h"
44 #include <X11/keysym.h> /* 20 Feb 2003 */
45 #include "afni_plugout.h"
46 #include "readme_afnigui.h"
47 #include "readme_env.h"
48
49 /*------------------------------------------------------*/
50 /* if the compiler wants to 'show off' the name of this
51 edition of AFNI, then turn that macro into a string. */
52
53 /* SHSTRING comes from mrilib.h via debugtrace.h */
54
55 #ifdef SHOWOFF
56 # undef SHSH
57 # undef SHSHSH
58 # undef SHSTRING
59 # define SHSH(x) #x
60 # define SHSHSH(x) SHSH(x)
61 # define SHSTRING SHSHSH(SHOWOFF) /* now in "quotes" */
62 #else
63 # undef SHSTRING
64 #endif
65 /*------------------------------------------------------*/
66
67 #if 0 /* ANNOUNCEMENT IS NOT USED 28 Dec 2015 [rickr] */
68 #ifdef SHSTRING
69
70 #define ANNOUNCEMENT \
71 "GPL AFNI: Analysis of Functional NeuroImages, by RW Cox (" COXEMAIL ")\n" \
72 "This is Version " VERSION "\n" \
73 "[[Precompiled binary " SHSTRING ": " __DATE__ "]]\n\n" \
74 " ** This software was designed to be used only for research purposes. **\n" \
75 " ** Clinical uses are not recommended, and have never been evaluated. **\n" \
76 " ** This software comes with no warranties of any kind whatsoever, **\n" \
77 " ** and may not be useful for anything. Use it at your own risk! **\n" \
78 " ** If these terms are not acceptable, you aren't allowed to use AFNI.**\n" \
79 " ** See 'Define Datamode->Misc->License Info' for more details. **\n\n"\
80 " **** If you DO find AFNI useful, please cite this paper:\n" \
81 " RW Cox. AFNI: Software for analysis and visualization of\n" \
82 " functional magnetic resonance neuroimages.\n" \
83 " Computers and Biomedical Research, 29:162-173, 1996.\n\n" \
84 " **** If you find SUMA useful, citing this paper also would be nice:\n" \
85 " ZS Saad, RC Reynolds, B Argall, S Japee, RW Cox.\n" \
86 " SUMA: An Interface For Surface-Based Intra- And Inter-Subject Analysis\n"\
87 " With AFNI. 2nd IEEE International Symposium on Biomedical Imaging:\n" \
88 " Macro to Nano 2, 1510-1513, 2004.\n\n"
89
90 #else
91
92 #define ANNOUNCEMENT \
93 "GPL AFNI: Analysis of Functional NeuroImages, by RW Cox (" COXEMAIL ")\n" \
94 "This is Version " AVERZHN " -- compiled " __DATE__ "\n\n" \
95 " ** This software was designed to be used only for research purposes. **\n" \
96 " ** Clinical uses are not recommended, and have never been evaluated. **\n" \
97 " ** This software comes with no warranties of any kind whatsoever, **\n" \
98 " ** and may not be useful for anything. Use it at your own risk! **\n" \
99 " ** If these terms are not acceptable, you aren't allowed to use AFNI.**\n" \
100 " ** See 'Define Datamode->Misc->License Info' for more details. **\n\n"\
101 " **** If you DO find AFNI useful, please cite this paper:\n" \
102 " RW Cox. AFNI: Software for analysis and visualization of\n" \
103 " functional magnetic resonance neuroimages.\n" \
104 " Computers and Biomedical Research, 29:162-173, 1996.\n\n" \
105 " **** If you find SUMA useful, citing this paper also would be nice:\n" \
106 " ZS Saad, RC Reynolds, B Argall, S Japee, RW Cox.\n" \
107 " SUMA: An Interface For Surface-Based Intra- And Inter-Subject Analysis\n"\
108 " With AFNI. 2nd IEEE International Symposium on Biomedical Imaging:\n" \
109 " Macro to Nano 2, 1510-1513, 2004.\n\n"
110
111 #endif /* SHSTRING */
112 #endif /* if 0 - for SHSTRING and ANNOUNCEMENT */
113
114 /*------------------------------------------------------*/
115
116 #ifdef AFNI_DEBUG
117 # define USE_TRACING
118 # define REPORT_PROGRESS(str) /* nada */
119 #else
120 # define REPORT_PROGRESS(str) \
121 do{ if(AFNI_VERBOSE){fputs(str,stderr);fflush(stderr);} } while(0)
122 #endif
123
124 /*------------------------------------------------------*/
125
126 #define EMPTY_STRING(str) ((str)[0] = '\0')
127
128 #undef IMAGEIZE_CROSSHAIRS /* disable crosshairs drawn into overlay pixels */
129
130 #define USE_SIDES /* 01 Dec 1999: replace "left is xxx" */
131 /* labels with "sides" labels. */
132
133 void AFNI_print_startup_tip(int) ;
134
135 #include "afni_startup_tips.h" /* where the tips and goodbye messages live */
136
137 int num_bysub = 0 ; /* 01 Feb 2018 */
138 char **bysub = NULL ;
139 int num_bysub_dir = 0 ; /* 15 Apr 2019 */
140 char **bysub_dir = NULL ;
141
142 /*-----------------------------------------------------------------------
143 Fallback resources for AFNI. May be overridden by the user's
144 .Xdefaults file, or other resource sources. AFNI does not come
145 with an "app-defaults" file, since that would be too much like work.
146 (And would require sysadmin privileges to install.)
147 -------------------------------------------------------------------------*/
148
149 /*----- things to change the default font sizes -----*/
150
151 static void AFNI_set_4fonts(char *AA,char *BB, char *CC, char *DD) ;
152
153 #define XXX_PLUS_FONTS \
154 AFNI_set_4fonts( \
155 "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1" , \
156 "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1" , \
157 "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1" , \
158 "-adobe-courier-bold-r-normal--14-100-100-100-m-90-iso8859-1" )
159
160 #define XXX_MINUS_FONTS \
161 AFNI_set_4fonts("8x13bold","7x13","6x10","5x8")
162
163 #define XXX_BIG_FONTS \
164 AFNI_set_4fonts( \
165 "-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1" , \
166 "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1" , \
167 "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1" , \
168 "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1" )
169
170 #define XXX_NORM_FONTS \
171 AFNI_set_4fonts("9x15bold","8x13bold","7x13","6x10")
172
173 static char *FALLback[] =
174 { "AFNI*fontList: 9x15bold=charset1" , /* normal font */
175 "AFNI*pbar*fontList: 6x10=charset1" , /* next to pbar */
176 "AFNI*imseq*fontList: 7x13=charset1" , /* on imseq */
177 "AFNI*font8*fontList: 8x13bold=charset1" , /* smaller fonts */
178 "AFNI*font7*fontList: 7x13=charset1" , /* for various */
179 "AFNI*font6*fontList: 6x10=charset1" , /* usages */
180 "AFNI*background: gray22" , /* background clr */
181 "AFNI*menu*background: gray4" , /* bkgd in menus */
182 "AFNI*menu*foreground: #ffdd22" , /* menu text color */
183 "AFNI*borderColor: gray19" , /* same as bkgd! */
184 "AFNI*foreground: yellow" , /* normal text */
185 "AFNI*borderWidth: 0" , /* don't change! */
186 "AFNI*troughColor: blue3" , /* in sliders */
187 "AFNI*XmLabel.translations: #override<Btn2Down>:" , /* Motif 2.0 bug */
188 "AFNI*help*background: black" , /* for help */
189 "AFNI*help*foreground: #ffffff" ,
190 "AFNI*help*helpborder: False" ,
191 "AFNI*help*waitPeriod: 1066" ,
192 "AFNI*help*fontList: 9x15bold=charset1" ,
193 "AFNI*cluefont: 9x15bold" , /* for popup */
194 "AFNI*bigtext*fontList: 10x20=charset1" , /* hints */
195 "AFNI*help*cancelWaitPeriod: 333" ,
196 #if 0
197 "AFNI*clustA*fontList: 9x15bold=charset1" , /* for Clusterize */
198 "AFNI*clustB*fontList: 9x15bold=charset1" ,
199 "AFNI*clustA*background: gray22" ,
200 "AFNI*clustB*background: gray1" ,
201 "AFNI*clustA*foreground: yellow" ,
202 "AFNI*clustB*foreground: white" ,
203 #endif
204
205 "AFNI*XmList.translations: #augment" /* 24 Feb 2007 */
206 "<Btn4Down>: ListPrevItem()\\n" /* for scrollwheel */
207 "<Btn5Down>: ListNextItem()" ,
208
209 "AFNI*XmText.translations: #augment"
210 "<Btn4Down>: previous-line() scroll-one-line-down()\\n"
211 "<Btn5Down>: next-line() scroll-one-line-up()" ,
212 #if 0
213 "AFNI*XmScrollBar.translations: #augment"
214 "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
215 "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
216 #endif
217
218 NULL } ;
219
220 /* The trick to using multiple Xt translations in the fallback resources
221 above is to separate them not with '\n' but with '\\n'. Ugghhhhhhh. */
222
223 /*-----------------------------------------------------------------------*/
224 static int new_FALLback_num = 0 ; /* for -XXX option [24 Mar 2016] */
225 static char **new_FALLback = NULL ;
226 static char *xrdb_old = NULL ;
227 static char *xrdb_pg = NULL ;
228
229 /*-----------------------------------------------------------------------*/
230
equiv_FALLback(char * n1,char * n2)231 static int equiv_FALLback( char *n1 , char *n2 ) /* check if 2 strings */
232 { /* start the same */
233 char *c1,*c2 , *d1,*d2 ; int ee ;
234 if( n1 == NULL || *n1 == '\0' ) return 1 ;
235 if( n2 == NULL || *n2 == '\0' ) return 1 ;
236 if( strcmp(n1,n2) == 0 ) return 1 ;
237 d1 = strdup(n1) ; c1 = strchr(d1,':') ;
238 d2 = strdup(n2) ; c2 = strchr(d2,':') ;
239 if( c1 == NULL || c2 == NULL ){ free(d1); free(d2); return 1; }
240 *c1 = '\0' ; *c2 = '\0' ;
241 ee = strcmp(d1,d2) ; free(d1) ; free(d2) ;
242 return (ee==0) ;
243 }
244
245 /*-----------------------------------------------------------------------*/
246
247 /*-----------------------------------------------------------------------*/
248
249 #define ADDTO_FALLback_one(nameval) \
250 do{ int nf ; \
251 nf = new_FALLback_num ; \
252 new_FALLback = (char **)realloc( new_FALLback , sizeof(char *)*(nf+2) ) ; \
253 new_FALLback[nf] = strdup(nameval) ; \
254 new_FALLback[nf+1] = NULL ; new_FALLback_num = nf+1 ; \
255 } while(0)
256
257 #define ADDTO_FALLback_pair(name,val) \
258 do{ char *str=malloc(strlen(name)+strlen(val)+16) ; \
259 strcpy(str,name) ; strcat(str,": ") ; strcat(str,val) ; \
260 ADDTO_FALLback_one(str) ; \
261 } while(0)
262
263 /*-----------------------------------------------------------------------*/
264
AFNI_set_4fonts(char * AA,char * BB,char * CC,char * DD)265 static void AFNI_set_4fonts(char *AA,char *BB, char *CC, char *DD)
266 {
267 ADDTO_FALLback_pair("AFNI*fontList" , AA) ;
268 ADDTO_FALLback_pair("AFNI*help*fontList" , AA) ;
269 ADDTO_FALLback_pair("AFNI*bigtext*fontList", AA) ;
270 ADDTO_FALLback_pair("AFNI*cluefont" , BB) ;
271 ADDTO_FALLback_pair("AFNI*font8*fontList" , BB) ;
272 ADDTO_FALLback_pair("AFNI*imseq*fontList" , CC) ;
273 ADDTO_FALLback_pair("AFNI*font7*fontList" , CC) ;
274 ADDTO_FALLback_pair("AFNI*font6*fontList" , DD) ;
275 ADDTO_FALLback_pair("AFNI*pbar*fontList" , DD) ;
276
277 /*** INFO_message("AFNI_set_4fonts: %s %s %s %s",AA,BB,CC,DD) ; ***/
278 }
279
280 /*-----------------------------------------------------------------------*/
281
282 static int XXX_set_default = 0 ; /* 08 Apr 2016 */
283
process_XXX_options(int argc,char * argv[])284 static void process_XXX_options( int argc , char *argv[] )
285 {
286 int nopt=1 ;
287
288 while( nopt < argc ){
289
290 if( strcasecmp(argv[nopt],"-big") == 0 ){ /* 17 Mar 2020 */
291 XXX_BIG_FONTS ; nopt++ ; continue ; /* simpler font size options */
292 }
293 if( strcasecmp(argv[nopt],"-plus") == 0 ){
294 static int nplus=0 ;
295 if( nplus == 0 ){ XXX_PLUS_FONTS ; }
296 else { XXX_BIG_FONTS ; }
297 nopt++ ; nplus++ ; continue ;
298 }
299 if( strcasecmp(argv[nopt],"-minus") == 0 ){
300 XXX_MINUS_FONTS ; nopt++ ; continue ;
301 }
302 if( strcasecmp(argv[nopt],"-norm") == 0 ){ /* 10 Apr 2020 */
303 XXX_NORM_FONTS ; nopt++ ; continue ;
304 }
305
306 if( strncasecmp(argv[nopt],"-XXX",4) != 0 ){ nopt++; continue; }
307
308 if( strcasecmp(argv[nopt],"-XXX") == 0 ){
309 if( ++nopt >= argc ){
310 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
311 break ;
312 }
313 if( strncasecmp(argv[nopt],"default",7) == 0 ){ /* 08 Apr 2016 */
314 if( THD_find_executable("xrdb") != NULL ){
315 int qq ;
316 XXX_set_default = 1 ;
317 for( qq=0 ; FALLback[qq] != NULL ; qq++ )
318 ADDTO_FALLback_one(FALLback[qq]) ;
319 }
320 } else if( strchr(argv[nopt],':') != NULL ){
321 ADDTO_FALLback_one(argv[nopt]) ;
322 }
323 nopt++ ; continue ;
324 }
325
326 if( strcasecmp(argv[nopt],"-XXXnpane") == 0 ){ /* 06 May 2016 */
327 int np ;
328 if( ++nopt >= argc ){
329 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
330 break ;
331 }
332 np = (int)strtod(argv[nopt],NULL) ;
333 if( np < 256 || np > NPANE_BIGGEST ){
334 WARNING_message("value '%s' after '%s' is illegal -- ignoring",argv[nopt],argv[nopt-1]) ;
335 } else {
336 if( np%2 == 1 ) np++ ;
337 if( np > NPANE_BIGGEST ) np = NPANE_BIGGEST ;
338 npane_big = np ;
339 }
340 nopt++ ; continue ;
341 }
342
343 if( strcasecmp(argv[nopt],"-XXXbgcolor") == 0 ){
344 if( ++nopt >= argc ){
345 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
346 break ;
347 }
348 ADDTO_FALLback_pair("AFNI*background" ,argv[nopt]) ;
349 ADDTO_FALLback_pair("AFNI*menu*background",argv[nopt]) ;
350 ADDTO_FALLback_pair("AFNI*help*background",argv[nopt]) ;
351 nopt++ ; continue ;
352 }
353
354 if( strcasecmp(argv[nopt],"-XXXfgcolor") == 0 ){
355 if( ++nopt >= argc ){
356 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
357 break ;
358 }
359 ADDTO_FALLback_pair("AFNI*foreground" ,argv[nopt]) ;
360 ADDTO_FALLback_pair("AFNI*menu*foreground",argv[nopt]) ;
361 ADDTO_FALLback_pair("AFNI*help*foreground",argv[nopt]) ;
362 nopt++ ; continue ;
363 }
364
365 if( strcasecmp(argv[nopt],"-XXXfontsize") == 0 ){
366 if( ++nopt >= argc ){
367 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
368 break ;
369 }
370 if( strcasecmp(argv[nopt],"plus") == 0 || strcmp(argv[nopt],"+") == 0 ){
371 static int nplus=0 ;
372 if( nplus == 0 ){ XXX_PLUS_FONTS ; }
373 else { XXX_BIG_FONTS ; }
374 nplus++ ;
375 } else if( strcasecmp(argv[nopt],"minus") == 0 || strcmp(argv[nopt],"-") == 0 ){
376 XXX_MINUS_FONTS ;
377 } else if( strcasecmp(argv[nopt],"big") == 0 || strcmp(argv[nopt],"++") == 0 ){
378 XXX_PLUS_FONTS ;
379 } else {
380 WARNING_message("Don't understand '%s' after option '%s'",
381 argv[nopt] , argv[nopt-1] ) ;
382 }
383
384 nopt++ ; continue ;
385 }
386
387 if( strcasecmp(argv[nopt],"-XXXfontA") == 0 ){
388 char *fn ;
389 if( ++nopt >= argc ){
390 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
391 break ;
392 }
393 fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
394 sprintf(fn,"%s=charset1",argv[nopt]) ;
395 ADDTO_FALLback_pair("AFNI*fontList" ,fn) ;
396 ADDTO_FALLback_pair("AFNI*help*fontList" ,fn) ;
397 ADDTO_FALLback_pair("AFNI*bigtext*fontList",fn) ;
398 ADDTO_FALLback_pair("AFNI*cluefont" ,fn) ;
399 free(fn) ; nopt++ ; continue ;
400 }
401
402 if( strcasecmp(argv[nopt],"-XXXfontB") == 0 ){
403 char *fn ;
404 if( ++nopt >= argc ){
405 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
406 break ;
407 }
408 fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
409 sprintf(fn,"%s=charset1",argv[nopt]) ;
410 ADDTO_FALLback_pair("AFNI*font8*fontList",fn) ;
411 free(fn) ; nopt++ ; continue ;
412 }
413
414 if( strcasecmp(argv[nopt],"-XXXfontC") == 0 ){
415 char *fn ;
416 if( ++nopt >= argc ){
417 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
418 break ;
419 }
420 fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
421 sprintf(fn,"%s=charset1",argv[nopt]) ;
422 ADDTO_FALLback_pair("AFNI*imseq*fontList",fn) ;
423 ADDTO_FALLback_pair("AFNI*font7*fontList",fn) ;
424 free(fn) ; nopt++ ; continue ;
425 }
426
427 if( strcasecmp(argv[nopt],"-XXXfontD") == 0 ){
428 char *fn ;
429 if( ++nopt >= argc ){
430 WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
431 break ;
432 }
433 fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
434 sprintf(fn,"%s=charset1",argv[nopt]) ;
435 ADDTO_FALLback_pair("AFNI*font6*fontList",fn) ;
436 ADDTO_FALLback_pair("AFNI*pbar*fontList" ,fn) ;
437 free(fn) ; nopt++ ; continue ;
438 }
439
440 }
441
442 return ;
443 }
444
445 /*----------------------------------------------------------------------------
446 Global variables that used to be local variables in main(),
447 but since the advent of the splash screen and startup code
448 in MAIN_workprocess() are needed in more than one place.
449 ------------------------------------------------------------------------------*/
450
451 static XtAppContext MAIN_app ;
452 static XtErrorHandler MAIN_old_handler ; /* no longer used */
453 static Three_D_View *MAIN_im3d ;
454 static MCW_DC * MAIN_dc ;
455 static Widget MAIN_shell=NULL ;
456 static int MAIN_argc ;
457 static char **MAIN_argv ;
458 static RwcBoolean MAIN_workprocess( XtPointer ) ;
459
460 /*----- Stuff saved from the '-com' command line arguments [29 Jul 2005] -----*/
461
462 static int COM_num = 0 ;
463 #define MAX_N_COM 1024
464 static char *COM_com[MAX_N_COM] ; /* max of 1024 commands allowed!!! */
465 static char comsep = ';' ; /* command separator: 22 Feb 2007 */
466
467 static int recursed_ondot = 0 ; /* 18 Feb 2007 */
468
469 /* ---------------------------------------------------------------------- */
470 /* just display the AFNI version 26 Oct 2015 [rickr] */
471 /* (since writing to stdout, do not interfere with print-and-exit funcs) */
472
473 #include "RomanImperator.h" /* RWC Nov 2018 */
474
show_AFNI_version(void)475 void show_AFNI_version(void)
476 {
477 char *rimp = AFNI_VERSION_RomanImperator ;
478 char vvvv[1024] ;
479
480 if( rimp != NULL && *rimp != '\0' ){ sprintf(vvvv,"%s '%s'",AVERZHN,rimp); }
481 else { strcpy(vvvv,AVERZHN) ; }
482
483 #ifdef SHSTRING
484 printf( "Precompiled binary " SHSTRING ": " __DATE__ " (Version %s)\n",vvvv ) ;
485 #else
486 printf( "Compile date = " __DATE__ " " __TIME__ " (Version %s)\n",vvvv) ;
487 #endif
488 }
489
490 // [PT: Oct 7, 2019] functions to plot just the basic info, without
491 // sep parsing needs: version number and package num
show_AFNI_package(void)492 void show_AFNI_package(void)
493 {
494 #ifdef SHSTRING
495 printf(SHSTRING "\n");
496 #else
497 printf( "Compiled: " __DATE__ );
498 #endif
499 }
500
show_AFNI_vnum(void)501 void show_AFNI_vnum(void)
502 {
503 printf(AVERZHN "\n");
504 }
505
506 // [PT: Oct 17, 2019] useful to be able to get the 'readme_afnigui.h'
507 // info at the command line (ambitions to parse it for the HTML RST
508 // pages). This is called via the -tips option.
show_AFNI_readme_gui(void)509 void show_AFNI_readme_gui(void)
510 {
511 int ii;
512
513 for( ii=0 ; readme_afnigui[ii] != NULL ; ii++ ){
514 printf( "%s" , readme_afnigui[ii] ) ;
515 }
516 }
517
518 // [PT: Oct 21, 2019] useful to be able to get the 'readme_env.h' info
519 // at commandline; also for HTML RST parsing. This is called via the
520 // -env option.
show_AFNI_readme_env(void)521 void show_AFNI_readme_env(void)
522 {
523 int ii;
524
525 for( ii=0 ; readme_env[ii] != NULL ; ii++ ){
526 printf( "%s" , readme_env[ii] ) ;
527 }
528 }
529
530 /********************************************************************
531 Print out some help information and then quit quit quit
532 *********************************************************************/
533
AFNI_syntax(void)534 void AFNI_syntax(void)
535 {
536 /* printf(ANNOUNCEMENT) ;*/
537
538 if( AFNI_yesenv("AFNI_POMOC") ) /* for the Web -help page */
539 printf(
540 " **** At the bottom of this Web page are some slide images to\n"
541 " outline the usage of the AFNI Graphical User Interface (GUI).\n"
542 "\n"
543 ) ;
544 else
545 printf(
546 " **** Help for all AFNI programs can be found at the Web page\n"
547 " https://afni.nimh.nih.gov/pub/dist/doc/program_help/index.html\n"
548 "\n"
549 ) ;
550
551 printf(
552 "----------------------------------------------------------------\n"
553 "USAGE 1: read in sessions of 3D datasets (created by to3d, etc.)\n"
554 "----------------------------------------------------------------\n"
555 " afni [options] [session_directory ...]\n"
556 "\n"
557 " -bysub This new [01 Feb 2018] option allows you to have 'sessions'\n"
558 " *OR* made up from files scattered across multiple directories.\n"
559 " -BIDS The purpose of this option is to gather all the datasets\n"
560 " corresponding to a single subject identifier, as is done\n"
561 " in the BIDS file hierarchy -- http://bids.neuroimaging.io/\n"
562 " **** There are two methods for using this option.\n"
563 " method (1) ** In the first method, you put one or more subject identifiers,\n"
564 " [OLDER] which are of the form 'sub-XXX' where 'XXX' is some\n"
565 " subject code (it does not have to be exactly 3 characters).\n"
566 " ++ If an identifier does NOT start with 'sub-', then that\n"
567 " 4 letter string will be added to the front. This allows\n"
568 " you to specify your subjects by their numbers 'XXX' alone.\n"
569 " method (2) ** In the second method, you put one or more directory names,\n"
570 " [NEWER] and all immediate sub-directories whose name starts with\n"
571 " 'sub-' will be included. With this method, you can end up\n"
572 " reading in an entire BIDS hierarchy of datasets, which\n"
573 " might take a significant amount of time if there are many\n"
574 " subjects.\n"
575 " **** Note that if an identifier following '-bysub' on the\n"
576 " command line is a directory name that starts with 'sub-',\n"
577 " it will be treated using method (1), not using method (2).\n"
578 " both methods ** In either method, the list of names following '-bysub' ends\n"
579 " with any argument that starts with '-' (or with the end of\n"
580 " all command line arguments).\n"
581 " method (2) ** Each directory on the command line (after all options, and\n"
582 " including any directories directly after the '-bysub' option)\n"
583 " will be scanned recursively (down the file tree) for\n"
584 " subdirectories whose name matches each 'sub-XXX' identifier\n"
585 " exactly. All such subdirectories will have all their\n"
586 " datasets read in (recursively down the file tree) and\n"
587 " put into a single session for viewing in AFNI.\n"
588 " ++ In addition, all datasets from all subjects will be\n"
589 " available in the 'All_Datasets' session in the GUI.\n"
590 " (Unless environment variable AFNI_ALL_DATASETS is set to NO)\n"
591 " ++ If you do NOT put any directories or subject identifiers\n"
592 " directly after the '-bysub' (or '-BIDS') option, the\n"
593 " program will act as if you put '.' there, and it will\n"
594 " search below the current working directory - the directory\n"
595 " you were 'in' when you started the AFNI GUI.\n"
596 " method (1) ** If a directory on the command line after this option does\n"
597 " NOT have any subdirectories that match any of the '-bysub'\n"
598 " identifiers, then that directory will be read in the normal\n"
599 " way, with all the datasets in that particular directory\n"
600 " (but not subdirectories) read into the session.\n"
601 " both methods ** Please note that '-bysub' sessions will NOT be rescanned\n"
602 " for new datasets that might get placed there after the\n"
603 " AFNI GUI starts, unlike normal (single directory) sessions.\n"
604 " method (1) ** Example (method 1):\n"
605 " afni -bysub 10506 50073 - ~/data/OpenFMRI/ds000030\n"
606 " This will open the data for subjects 10506 and 50073 from\n"
607 " the data at the specified directory -- presumably the\n"
608 " data downloaded from https://openfmri.org/dataset/ds000030/\n"
609 " ++ If directory sub-10506 is found and has (say) sub-directories\n"
610 " anat beh dwi func\n"
611 " all AFNI-readable datasets from these sub-directories will\n"
612 " be input and collected into one session, to be easily\n"
613 " viewed together.\n"
614 " ++ Because of the recursive search, if a directory named (e.g.)\n"
615 " derivatives/sub-10506\n"
616 " is found underneath ~/data/OpenFMRI/ds000030, all the\n"
617 " datasets found underneath that will also be put into the\n"
618 " same session, so they can be viewed with the 'raw' data.\n"
619 " ++ In this context, 'dataset' also means .png and .jpg files\n"
620 " found in the sub-XXX directories. These images can be\n"
621 " opened in the AFNI GUI using the Axial image viewer.\n"
622 " (You might want to turn the AFNI crosshairs off!)\n"
623 " ++++ If you do NOT want .png and .jpg files read into AFNI,\n"
624 " set Unix environment variable AFNI_IMAGE_DATASETS to 'NO'.\n"
625 " ++ You can put multiple subject IDs after '-bysub', as\n"
626 " in the example above. You can also use the '-bysub' option\n"
627 " more than once, if you like. Each distinct subect ID will\n"
628 " get a distinct AFNI session in the GUI.\n"
629 " method (2) ** Example (method 2):\n"
630 " afni -bysub ~/data/OpenFMRI/ds000030\n"
631 " This will read in all datasets from all subjects. In this\n"
632 " particular example, there are hundreds of subjects, so this\n"
633 " command may not actually be a good idea - unless you want to\n"
634 " go get a cup of chai or coffee, and then sip it very slowly.\n"
635 " ** Example (method 2):\n"
636 " afni -BIDS\n"
637 " This will read all 'sub-*' directories from the current\n"
638 " working directory, and is the same as 'afni -BIDS .' \n"
639 " As noted earlier, this recursive operation may take a long\n"
640 " time (especially if the datasets are compressed), as AFNI\n"
641 " reads the headers from ALL datasets as it finds them,\n"
642 " to build a table for you to use in the 'OverLay' and\n"
643 " 'UnderLay' dataset choosers.\n"
644 "\n"
645 " -all_dsets Read in all datasets from all listed folders together.\n"
646 " Has the same effect as choosing 'All_Datasets' in the GUI.\n"
647 " Example: afni -all_dsets dir1 dir2 dir3\n"
648 " Can be set to default in .afnirc with ALL_DSETS_STARTUP = YES.\n"
649 " Overidden silently by AFNI_ALL_DATASETS = NO.\n"
650 "\n"
651 #if MMAP_THRESHOLD > 0
652 " -purge Conserve memory by purging unused datasets from memory.\n"
653 " [Use this if you run out of memory when running AFNI.]\n"
654 " [This will slow the code down, so use only if needed.]\n"
655 #else
656 " -nopurge Disable the automatic purging of unused datasets from\n"
657 " memory, which is invoked when you switch datasets.\n"
658 #endif
659 " [When a dataset is needed, it will be re-read from disk.]\n"
660 "\n"
661 " -posfunc Start up the color 'pbar' to use only positive function values.\n"
662 "\n"
663 " -R Recursively search each session_directory for more session\n"
664 " subdirectories.\n"
665 " WARNING: This will descend the entire filesystem hierarchy from\n"
666 " each session_directory given on the command line. On a\n"
667 " large disk, this may take a long time. To limit the\n"
668 " recursion to 5 levels (for example), use -R5.\n"
669 " ** Use of '-bysub' disables recursive descent, since '-bysub'\n"
670 " will do that for you.\n"
671 #if 0
672 "\n"
673 " -ignore N Tells the program to 'ignore' the first N points in\n"
674 " time series for graphs and FIM calculations.\n"
675 "\n"
676 " -im1 N Tells the program to use image N as the first one for\n"
677 " graphs and FIM calculations (same as '-ignore N-1')\n"
678 "\n"
679 " -tlrc_small These options set whether to use the 'small' or 'big'\n"
680 " -tlrc_big Talairach brick size. The compiled in default for\n"
681 " the program is now 'big', unlike AFNI 1.0x.\n"
682 #endif
683 "\n"
684 #ifndef WARP_4D
685 " -warp_4D Allows the program to Talairach transform and write\n"
686 " to disk 3D+time datasets. Note that the resulting\n"
687 " disk files will be gigantic (100s of Megabytes).\n"
688 "\n"
689 #endif
690 " -no1D Tells AFNI not to read *.1D timeseries files from\n"
691 " the dataset directories. The *.1D files in the\n"
692 " directories listed in the AFNI_TSPATH environment\n"
693 " variable will still be read (if this variable is\n"
694 " not set, then './' will be scanned for *.1D files).\n"
695 "\n"
696 " -nocsv Each of these option flags does the same thing (i.e.,\n"
697 " -notsv they are synonyms): each tells AFNI not to read\n"
698 " -notcsv *.csv or *.tsv files from the dataset directories.\n"
699 #if 0
700 "\n"
701 " -noqual Tells AFNI not to enforce the 'quality' checks when\n"
702 " making the transformations to +acpc and +tlrc.\n"
703 #endif
704 "\n"
705 " -unique Tells the program to create a unique set of colors\n"
706 " for each AFNI controller window. This allows\n"
707 " different datasets to be viewed with different\n"
708 " grayscales or colorscales. Note that -unique\n"
709 " will only work on displays that support 12 bit\n"
710 " PseudoColor (e.g., SGI workstations) or TrueColor.\n"
711 "\n"
712 " -orient code Tells afni the orientation in which to display\n"
713 " x-y-z coordinates (upper left of control window).\n"
714 " The code must be 3 letters, one each from the\n"
715 " pairs {R,L} {A,P} {I,S}. The first letter gives\n"
716 " the orientation of the x-axis, the second the\n"
717 " orientation of the y-axis, the third the z-axis:\n"
718 " R = right-to-left L = left-to-right\n"
719 " A = anterior-to-posterior P = posterior-to-anterior\n"
720 " I = inferior-to-superior S = superior-to-inferior\n"
721 " The default code is RAI ==> DICOM order. This can\n"
722 " be set with the environment variable AFNI_ORIENT.\n"
723 " As a special case, using the code 'flipped' is\n"
724 " equivalent to 'LPI' (this is for Steve Rao).\n"
725 "\n"
726 #ifdef ALLOW_PLUGINS
727 " -noplugins Tells the program not to load plugins.\n"
728 " (Plugins can also be disabled by setting the\n"
729 " environment variable AFNI_NOPLUGINS.)\n"
730 "\n"
731 " -seehidden Tells the program to show you which plugins\n"
732 " are hidden.\n"
733 "\n"
734 " -DAFNI_ALLOW_ALL_PLUGINS=YES\n"
735 " Tells the program NOT to hide plugins from you.\n"
736 " Note that there are a lot of hidden plugins,\n"
737 " most of which are not very useful!\n"
738 "\n"
739 " -yesplugouts Tells the program to listen for plugouts.\n"
740 " (Plugouts can also be enabled by setting the\n"
741 " environment variable AFNI_YESPLUGOUTS.)\n"
742 "\n"
743 " -YESplugouts Makes the plugout code print out lots of messages\n"
744 " (useful for debugging a new plugout).\n"
745 "\n"
746 " -noplugouts Tells the program NOT to listen for plugouts.\n"
747 " (This option is available to override\n"
748 " the AFNI_YESPLUGOUTS environment variable.)\n"
749 "\n"
750 #endif
751 " -skip_afnirc Tells the program NOT to read the file .afnirc\n"
752 " in the home directory. See README.setup for\n"
753 " details on the use of .afnirc for initialization.\n"
754 "\n"
755 " -layout fn Tells AFNI to read the initial windows layout from\n"
756 " file 'fn'. If this option is not given, then\n"
757 " environment variable AFNI_LAYOUT_FILE is used.\n"
758 " If neither is present, then AFNI will do whatever\n"
759 " it feels like.\n"
760 "\n"
761 " -niml If present, turns on listening for NIML-formatted\n"
762 " data from SUMA. Can also be turned on by setting\n"
763 " environment variable AFNI_NIML_START to YES.\n"
764 "%s"
765 " -list_ports List all port assignments and quit\n"
766 " -port_number PORT_NAME: Give port number for PORT_NAME and quit\n"
767 " -port_number_quiet PORT_NAME: Same as -port_number but writes out \n"
768 " number only\n"
769 " -available_npb: Find the first available block of port numbers, \n"
770 " print it to stdout and quit\n"
771 " The value can be used to set the -npb option for\n"
772 " a new set of chatty AFNI/SUMA/etc group.\n"
773 " -available_npb_quiet: Just print the block number to stdout and quit.\n"
774 "\n"
775 " -com ccc This option lets you specify 'command strings' to\n"
776 " drive AFNI after the program startup is completed.\n"
777 " Legal command strings are described in the file\n"
778 " README.driver. More than one '-com' option can\n"
779 " be used, and the commands will be executed in\n"
780 " the order they are given on the command line.\n"
781 " N.B.: Most commands to AFNI contain spaces, so the 'ccc'\n"
782 " command strings will need to be enclosed in quotes.\n"
783 "\n"
784 " -comsep 'c' Use character 'c' as a separator for commands.\n"
785 " In this way, you can put multiple commands in\n"
786 " a single '-com' option. Default separator is ';'.\n"
787 " N.B.: The command separator CANNOT be alphabetic or\n"
788 " numeric (a..z, A..Z, 0..9) or whitespace or a quote!\n"
789 " N.B.: -comsep should come BEFORE any -com option that\n"
790 " uses a non-semicolon separator!\n"
791 "\n"
792 " Example: -com 'OPEN_WINDOW axialimage; SAVE_JPEG axialimage zork; QUIT'\n"
793 " N.B.: You can also put startup commands (one per line) in\n"
794 " the file '~/.afni.startup_script'. For example,\n"
795 " OPEN_WINDOW axialimage\n"
796 " to always open the axial image window on startup.\n"
797 "\n"
798 " * If no session_directories are given, then the program will use\n"
799 " the current working directory (i.e., './').\n"
800 " * The maximum number of sessions is now set to %d.\n"
801 " * The maximum number of datasets per session is %d.\n"
802 " * To change these maximums, you must edit file '3ddata.h' and then\n"
803 " recompile this program.\n"
804 "\n"
805 "Global Options (available to all AFNI/SUMA programs)\n"
806 "%s\n%s"
807 , get_np_help() ,
808 THD_MAX_NUM_SESSION , THD_MAX_SESSION_SIZE ,
809 SUMA_Offset_SLines(get_help_help(),3), get_gopt_help()
810 ) ;
811
812 #if 0
813 printf(
814 "\n"
815 "-----------------------------------------------------\n"
816 "USAGE 2: read in images for 'quick and dirty' viewing\n"
817 "-----------------------------------------------------\n"
818 "** Most advanced features of AFNI will be disabled **\n"
819 "** The aiv program can be used now instead of AFNI **\n"
820 "\n"
821 " afni -im [options] im1 im2 im3 ...\n"
822 "\n"
823 " -im Flag to read in images instead of 3D datasets\n"
824 " (Talaraich and functional stuff won't work)\n"
825 " -dy yratio Tells afni the downscreen pixel size is 'yratio' times\n"
826 " the across-screen (x) pixel dimension (default=1.0)\n"
827 " -dz zratio Tells afni the slice thickness is 'zratio' times\n"
828 " the x pixel dimension (default=1.0)\n"
829 " -orient code Tells afni the orientation of the input images.\n"
830 " The code must be 3 letters, one each from the\n"
831 " pairs {R,L} {A,P} {I,S}. The first letter gives\n"
832 " the orientation of the x-axis, the second the\n"
833 " orientation of the y-axis, the third the z-axis:\n"
834 " R = right-to-left L = left-to-right\n"
835 " A = anterior-to-posterior P = posterior-to-anterior\n"
836 " I = inferior-to-superior S = superior-to-inferior\n"
837 " (the default code is ASL ==> sagittal images).\n"
838 " Note that this use of '-orient' is different from\n"
839 " the use when viewing datasets.\n"
840 " -resize Tells afni that all images should be resized to fit\n"
841 " the size of the first one, if they don't already fit\n"
842 " (by default, images must all 'fit' or afni will stop)\n"
843 " -datum type Tells afni to convert input images into the type given:\n"
844 " byte, short, float, complex are the legal types.\n"
845 " The image files (im1 ...) are the same formats as accepted by to3d.\n"
846 "\n"
847 " New image display options (alternatives to -im) [19 Oct 1999]:\n"
848 " -tim These options tell AFNI to arrange the input images\n"
849 " -tim:nt into a internal time-dependent dataset. Suppose that\n"
850 " -zim:nz there are N input 2D slices on the command line.\n"
851 " * -tim alone means these are N points in time (1 slice).\n"
852 " * -tim:nt means there are nt points in time (nt is\n"
853 " an integer > 1), so there are N/nt slices in space,\n"
854 " and the images on the command line are input in\n"
855 " time order first (like -time:tz in to3d).\n"
856 " * -zim:nz means there are nz slices in space (nz is\n"
857 " an integer > 1), so there are N/nz points in time,\n"
858 " and the images on the command line are input in\n"
859 " slice order first (like -time:zt in to3d).\n"
860 "\n"
861 " N.B.: You may wish to use the -ignore option to set the number of\n"
862 " initial points to ignore in the time series graph if you use\n"
863 " -tim or -zim, since there is no way to change this from\n"
864 " within an AFNI run (the FIM menus are disabled).\n"
865 " N.B.: The program 'aiv' (AFNI image viewer) can also be used to\n"
866 " get a quick look at images (but not time series graphs).\n"
867 ) ;
868 #endif
869
870 printf(
871 "\n"
872 "-------------------------------------------------------\n"
873 "USAGE 2: read in datasets specified on the command line\n"
874 "-------------------------------------------------------\n"
875 "\n"
876 " afni -dset [options] dname1 dname2 ...\n"
877 "\n"
878 "where 'dname1' is the name of a dataset, etc. With this option, only\n"
879 "the chosen datasets are read in, and they are all put in the same\n"
880 "'session'. Follower datasets are not created.\n"
881 "\n"
882 "* If you wish to be very tricksy, you can read in .1D files as datasets\n"
883 " using the \\' transpose syntax, as in\n"
884 " afni Fred.1D\\'\n"
885 " However, this isn't very useful (IMHO).\n"
886 "\n"
887 "* AFNI can also read image files (.jpg and .png) from the command line.\n"
888 " For just viewing images, the 'aiv' program (AFNI image viewer) is\n"
889 " simpler; but unlike aiv, you can do basic image processing on an\n"
890 " image 'dataset' using the AFNI GUI's feature. Sample command:\n"
891 " afni *.jpg\n"
892 " Each image file is a single 'dataset'; to switch between images,\n"
893 " use the 'Underlay' button. To view an image, open the 'Axial' viewer.\n"
894 "\n");
895 printf(MASTER_HELP_STRING); putchar('\n');
896 printf(CATENATE_HELP_STRING); putchar('\n');
897 printf(CALC_HELP_STRING); putchar('\n');
898
899 printf(
900 "\n"
901 "-------------------------------\n"
902 "GENERAL OPTIONS (for any usage)\n"
903 "-------------------------------\n"
904 "\n"
905 " -papers Prints out the list of AFNI papers, and exits.\n"
906 "\n"
907 " -q Tells afni to be 'quiet' on startup\n"
908 "\n"
909 " -Dname=val Sets environment variable 'name' to 'val' inside AFNI;\n"
910 " will supersede any value set in .afnirc.\n"
911 "\n"
912 " -gamma gg Tells afni that the gamma correction factor for the\n"
913 " monitor is 'gg' (default gg is 1.0; greater than\n"
914 " 1.0 makes the image contrast larger -- this may\n"
915 " also be adjusted interactively)\n"
916 "\n"
917 " -install Tells afni to install a new X11 Colormap. This only\n"
918 " means something for PseudoColor displays. Also, it\n"
919 " usually cause the notorious 'technicolor' effect.\n"
920 "\n"
921 " -ncolors nn Tells afni to use 'nn' gray levels for the image\n"
922 " displays (default is %d)\n"
923 "\n"
924 " -xtwarns Tells afni to show any Xt warning messages that may\n"
925 " occur; the default is to suppress these messages.\n"
926 #ifdef USE_TRACING
927 " -XTWARNS Trigger a debug trace when an Xt warning happens.\n"
928 "\n"
929 #endif
930 " -tbar name Uses 'name' instead of 'AFNI' in window titlebars.\n"
931 "\n"
932 " -flipim and The '-flipim' option tells afni to display images in the\n"
933 "\n"
934 " -noflipim 'flipped' radiology convention (left on the right).\n"
935 " The '-noflipim' option tells afni to display left on\n"
936 " the left, as neuroscientists generally prefer. This\n"
937 " latter mode can also be set by the Unix environment\n"
938 " variable 'AFNI_LEFT_IS_LEFT'. The '-flipim' mode is\n"
939 " the default.\n"
940 "\n"
941 #ifdef USE_TRACING
942 " -trace Turns routine call tracing on, for debugging purposes.\n"
943 " -TRACE Turns even more verbose tracing on, for more debugging.\n"
944 #endif
945 #ifdef USING_MCW_MALLOC
946 " -nomall Disables use of the mcw_malloc() library routines.\n"
947 "\n"
948 #endif
949 " -motif_ver Show the applied motif version string.\n"
950 "\n"
951 " -no_detach Do not detach from the terminal.\n"
952 "\n"
953 " -get_processed_env Show applied AFNI/NIFTI environment varables.\n"
954 "\n"
955 " -global_opts Show options that are global to all AFNI programs.\n"
956 "\n"
957 " -goodbye [n] Print a 'goodbye' message and exit (just for fun).\n"
958 " If an integer is supplied afterwards, will print that\n"
959 " many (random) goodbye messages.\n"
960 "\n"
961 " -startup [n] Similar to '-goodbye', but for startup tips.\n"
962 " [If you want REAL fun, use '-startup ALL'.]\n"
963 "\n"
964 " -julian Print out the current Julian date and exit.\n"
965 "\n"
966 " -ver Print the current AFNI version and compile date, then exit.\n"
967 " Useful to check how up-to-date you are (or aren't).\n"
968 "\n"
969 " -vnum Print just the current AFNI version number (i.e.,\n"
970 " AFNI_A.B.C), then exit.\n"
971 "\n"
972 " -package Print just the current AFNI package (i.e., \n"
973 " linux_ubuntu_12_64, macos_10.12_local, etc.),\n"
974 " then exit.\n"
975 "\n"
976 " -tips Print the tips for the GUI, such as key presses\n"
977 " and other useful advice. This is the same file that\n"
978 " would be displayed with the 'AFNI Tips' button in the\n"
979 " GUI controller. Exit after display.\n"
980 "\n"
981 " -env Print the environment variables for AFNI, which a user\n"
982 " might set in their ~/.afnirc file (wait, you *do*\n"
983 " have one on your computer, right?).\n"
984 " Exit after display.\n"
985 "\n"
986 "\n"
987 "N.B.: Many of these options, as well as the initial color set up,\n"
988 " can be controlled by appropriate X11 resources. See the\n"
989 " files AFNI.Xdefaults and README.environment for instructions\n"
990 " and examples.\n"
991
992 , DEFAULT_NGRAY
993 ) ;
994
995 printf("\n"
996 "-----------------------------------------------------------\n"
997 "Options that affect X11 Display properties: '-XXXsomething'\n"
998 "-----------------------------------------------------------\n"
999 "\n"
1000 "My intent with these options is that you use them in aliases\n"
1001 "or shell scripts, to let you setup specific appearances for\n"
1002 "multiple copies of AFNI. For example, put the following\n"
1003 "command in your shell startup file (e.g., ~/.cshrc or ~/.bashrc)\n"
1004 " alias ablue afni -XXXfgcolor white -XXXbgcolor navyblue\n"
1005 "Then the command 'ablue' will start AFNI with a blue background\n"
1006 "and using white for the default text color.\n"
1007 "\n"
1008 "Note that these options set 'properties' on the X11 server,\n"
1009 "which might survive after AFNI exits (especially if AFNI crashes).\n"
1010 "If for some reason these settings cause trouble after AFNI\n"
1011 "exits, use the option '-XXX defaults' to reset the X11\n"
1012 "properties for AFNI back to their default values.\n"
1013 "\n"
1014 "Also note that each option is of the form '-XXXsomething', followed\n"
1015 "by a single argument.\n"
1016 "\n"
1017 " -XXXfgcolor colorname = set the 'foreground' color (text color)\n"
1018 " to 'colorname'\n"
1019 " [default = yellow]\n"
1020 " ++ This should be a bright color, to contrast\n"
1021 " the background color.\n"
1022 " ++ You can find a list of X11 color names at\n"
1023 " https://en.wikipedia.org/wiki/X11_color_names\n"
1024 " However, if you use a name like Dark Cyan\n"
1025 " (with a space inside the name), you must\n"
1026 " put the name in quotes: 'Dark Cyan', or remove\n"
1027 " the space: DarkCyan.\n"
1028 " ++ Another way to specify X11 colors is in hexadecimal,\n"
1029 " as in '#rgb' or '#rrggbb', where the letters shown\n"
1030 " are replaced by hex values from 0 to f. For example,\n"
1031 " '#ffcc00' is an orange-yellow mixture.\n"
1032 "\n"
1033 " -XXXbgcolor colorname = set the 'background' color to 'colorname'\n"
1034 " [default = gray22]\n"
1035 " ++ This should be a somewhat dark color,\n"
1036 " or parts of the interface may be hard\n"
1037 " to read.\n"
1038 " ++ EXAMPLE:\n"
1039 " afni -XXXfgcolor #00ffaa -XXXbgcolor #330000 -plus\n"
1040 " You can create command aliases to open AFNI with\n"
1041 " different color schemes, to make your life simpler.\n"
1042 "\n"
1043 " -XXXfontsize plus = set all the X11 fonts used by AFNI to be one\n"
1044 " *OR* size larger ('plus') or to be one size smaller\n"
1045 " -XXXfontsize minus ('minus'). The 'plus' version I find useful for\n"
1046 " *OR* a screen resolution of about 100 dots per inch\n"
1047 " -XXXfontsize big (40 dots per cm) -- you can find what the system\n"
1048 " *OR* thinks your screen resolution is by the command\n"
1049 " -big xdpyinfo | grep -i resolution\n"
1050 " *OR* ++ Applying 'plus' twice is the same as 'big'.\n"
1051 " -plus ++ Using 'big' will use large Adobe Courier fonts.\n"
1052 " *OR* ++ Alternatively, you can control each of the 4 fonts\n"
1053 " -minus that AFNI uses, via the 4 following options ...\n"
1054 " *OR* ++ You can also set the fontsize for your copy\n"
1055 " -norm of AFNI in your ~/.afnirc file by setting\n"
1056 " environment variable AFNI_FONTSIZE to one of:\n"
1057 " big *OR* minus *or* plus\n"
1058 " ++ Using 'norm' gives the default AFNI font sizes.\n"
1059 "\n"
1060 " -XXXfontA fontname = set the X11 font name for the main AFNI\n"
1061 " controller\n"
1062 " [default = 9x15bold]\n"
1063 " ++ To see a list of all X11 font names, type the command\n"
1064 " xlsfonts | more\n"
1065 " *or* more elaborately (to show only fixed width fonts):\n"
1066 " xlsfonts | grep -e '-[cm]-' | grep -e '-iso8859-1$' | grep -e '-medium-' \\\n"
1067 " | grep -e '-r-normal-' | grep -v -e '-0-0-' | sort -t '-' -k 8 -n | uniq\n"
1068 " ++ It is best to use a fixed width font\n"
1069 " (e.g., not Helvetica), or the AFNI buttons\n"
1070 " won't line up nicely!\n"
1071 " ++ If you use an illegal font name here, you\n"
1072 " might make it hard to use the AFNI GUI!\n"
1073 " ++ The default fonts are chosen for 'normal' screen\n"
1074 " resolutions (about 72 dots per inch = 28 dots per cm).\n"
1075 " For higher resolutions ('Retina'), you might\n"
1076 " want to use larger fonts. Adding these\n"
1077 " '-XXXfont?' options is one way to address this\n"
1078 " problem. (Also see '-plus' above.)\n"
1079 " ++ An example of two quite large fonts on my computer\n"
1080 " (which at this time has a 108 dot per inch display):\n"
1081 " '-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1\n"
1082 " '-b&h-lucidatypewriter-medium-r-normal-sans-34-240-100-100-m-200-iso8859-1'\n"
1083 " Note that to use the latter font on the command line,\n"
1084 " you have to enclose the name in quotes, as shown above,\n"
1085 " since the 'foundry name' includes the character '&'.\n"
1086 " To use it in an alias, you need to do something like\n"
1087 " alias abig -XXXfontA '-b\\&h-lucidatypewriter-medium-r-normal-sans-34-240-100-100-m-200-iso8859-1'\n"
1088 " ++ When setting the fonts, it is often helpful\n"
1089 " to set the colors as well.\n"
1090 "\n"
1091 " -XXXfontB fontname = set the X11 font name for somewhat smaller text\n"
1092 " [default = 8x13bold]\n"
1093 "\n"
1094 " -XXXfontC fontname = set the X11 font name for even smaller text\n"
1095 " [default = 7x13]\n"
1096 "\n"
1097 " -XXXfontD fontname = set the X11 font name for the smallest text\n"
1098 " [default = 6x10]\n"
1099 "\n"
1100 " -XXX defaults = set the X11 properties to the AFNI defaults\n"
1101 " (the purpose of this is to restore things )\n"
1102 " (to normal if the X11 settings get mangled)\n"
1103 "\n"
1104 " -XXXnpane P = set the number of 'panes' in the continuous\n"
1105 " colorscale to the value 'P', where P is an\n"
1106 " even integer between 256 and 2048 (inclusive).\n"
1107 " Probably will work best if P is an integral\n"
1108 " multiple of 256 (e.g., 256, 512, 1024, 2048).\n"
1109 " [This option is for the mysterious Dr ZXu.]\n"
1110 "\n"
1111 ) ;
1112
1113 printf("\n"
1114 "--------------------------------------\n"
1115 "Educational and Informational Material\n"
1116 "--------------------------------------\n"
1117 "* The presentations used in our AFNI teaching classes at the NIH can\n"
1118 " all be found at\n"
1119 " https://afni.nimh.nih.gov/pub/dist/edu/latest/ (PowerPoint directories)\n"
1120 " https://afni.nimh.nih.gov/pub/dist/edu/latest/afni_handouts/ (PDF directory)\n"
1121 "\n"
1122 "* And for the interactive AFNI program in particular, see\n"
1123 " https://afni.nimh.nih.gov/pub/dist/edu/latest/afni01_intro/afni01_intro.pdf\n"
1124 " https://afni.nimh.nih.gov/pub/dist/edu/latest/afni03_interactive/afni03_interactive.pdf\n"
1125 "\n"
1126 "* For the -help on all AFNI programs, plus the README files, and more, please see\n"
1127 " https://afni.nimh.nih.gov/pub/dist/doc/program_help/index.html\n"
1128 "\n"
1129 "* For indvidualized help with AFNI problems, and to keep up with AFNI news, please\n"
1130 " use the AFNI Message Board:\n"
1131 " https://afni.nimh.nih.gov/afni/community/board/\n"
1132 "\n"
1133 "* If an AFNI program crashes, please include the EXACT error messages it outputs\n"
1134 " in your message board posting, as well as any other information needed to\n"
1135 " reproduce the problem. Just saying 'program X crashed, what's the problem?'\n"
1136 " is not helpful at all! In all message board postings, detail and context\n"
1137 " are highly relevant.\n"
1138 "\n"
1139 "* Also, be sure your AFNI distribution is up-to-date. You can check the date\n"
1140 " on your copy with the command 'afni -ver'. If it is more than a few months\n"
1141 " old, you should update your AFNI binaries and try the problematic command\n"
1142 " again -- it is quite possible the problem you encountered was already fixed!\n"
1143 #if 0
1144 "\n"
1145 "* For some fun, see this image:\n"
1146 " https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni_splashes.gif\n"
1147 #endif
1148 ) ;
1149
1150 AFNI_list_papers(NULL) ; /* 02 May 2014 */
1151 printf(
1152 "\n"
1153 "POSTERS on varied subjects from the AFNI development group can be found at\n"
1154 " * https://afni.nimh.nih.gov/sscc/posters\n"
1155 ) ;
1156
1157 /*........................................................................*/
1158 #undef NSLIDE
1159 #define NSLIDE 34
1160 if( AFNI_yesenv("AFNI_POMOC") ){ /* for the Web -help page */
1161 int ii ;
1162 printf("\n"
1163 "------------------------------------------------------------------------------------\n"
1164 " SLIDE IMAGES to help with learning the AFNI GUI\n"
1165 " https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni03/\n"
1166 "------------------------------------------------------------------------------------\n"
1167 ) ;
1168 for( ii=1 ; ii <= NSLIDE ; ii++ ){
1169 printf(
1170 "https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni03/Slide%02d.png\n"
1171 "------------------------------------------------------------------------------------\n"
1172 , ii ) ;
1173 }
1174 } else {
1175 printf("\n"
1176 "SLIDE IMAGES to help with learning the AFNI GUI can be found at\n"
1177 " * https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni03/\n"
1178 ) ;
1179 }
1180 printf("\n") ;
1181 /*........................................................................*/
1182
1183 exit(0) ;
1184 }
1185
1186 /*----------------------------------------------------------------------
1187 parse command line switches and store results in a data structure
1188 ------------------------------------------------------------------------*/
1189
AFNI_parse_args(int in_argc,char * in_argv[])1190 void AFNI_parse_args( int in_argc , char *in_argv[] )
1191 {
1192 int narg = 1 ;
1193 char *env_orient , *env ;
1194 int argc=in_argc , new_argc ; /* 18 Nov 1999 */
1195 char **argv=in_argv , **new_argv=NULL ;
1196
1197 ENTRY("AFNI_parse_args") ;
1198
1199 if( argc > 1 && strcmp(argv[1],"-help") == 0 ) AFNI_syntax() ;
1200
1201 GLOBAL_argopt.dz = 1.0 ; /* set up defaults */
1202 GLOBAL_argopt.dy = 1.0 ;
1203 GLOBAL_argopt.ignore = INIT_ignore ;
1204 GLOBAL_argopt.elide_quality = 0 ; /* Dec 1997 */
1205 GLOBAL_argopt.no_frivolities = 0 ; /* 01 Aug 1998 */
1206 GLOBAL_argopt.install_cmap = 0 ; /* 14 Sep 1998 */
1207 GLOBAL_argopt.read_1D = 1 ; /* 27 Jan 2000 */
1208 GLOBAL_argopt.read_tcsv = 1 ; /* 16 Jun 2020 */
1209
1210 GLOBAL_argopt.enable_suma = 1 ; /* 29 Aug 2001 */
1211 GLOBAL_argopt.disable_done = 0 ; /* 21 Aug 2008 */
1212
1213 GLOBAL_argopt.yes_niml = AFNI_yesenv("AFNI_NIML_START") ;
1214 /* GLOBAL_argopt.port_niml = 0 ; 10 Dec 2002 - Blocked, ZSS 2011*/
1215
1216 #if 0
1217 GLOBAL_argopt.allow_rt = 0 ; /* April 1997 */
1218 #else /* 09 Oct 2000 */
1219 GLOBAL_argopt.allow_rt = AFNI_yesenv("AFNI_REALTIME_Activate") ;
1220 GLOBAL_argopt.no_frivolities = (GLOBAL_argopt.allow_rt != 0) ;
1221 #endif
1222
1223 SESSTRAIL = 1 ;
1224 env = getenv( "AFNI_SESSTRAIL" ) ;
1225 if( env != NULL ){
1226 SESSTRAIL = strtol(env,NULL,10) ;
1227 if( SESSTRAIL < 0 ) SESSTRAIL = 0 ; /* 24 Aug 2000 */
1228 else if( SESSTRAIL > 4 ) SESSTRAIL = 4 ; /* 30 May 2018 */
1229 }
1230
1231 GLOBAL_argopt.elide_quality = AFNI_yesenv("AFNI_MARKERS_NOQUAL") ;
1232
1233 /* 24 Sep 2000: get the default layout name (add $HOME) */
1234
1235 { char *lf = getenv("AFNI_LAYOUT_FILE") ;
1236 if( lf != NULL ){
1237 char *eh = getenv("HOME") , *ff ;
1238 int ll = strlen(lf) + 8 ;
1239 if( eh != NULL ) ll += strlen(eh) ;
1240 ff = AFMALL(char, ll) ;
1241 if( eh != NULL && lf[0] != '/' ){ strcpy(ff,eh) ; strcat(ff,"/") ; }
1242 else { ff[0] = '\0' ; }
1243 strcat(ff,lf) ;
1244 GLOBAL_argopt.layout_fname = ff ;
1245 }
1246 }
1247
1248 /* 21 Jan 2003: get the startup script name */
1249
1250 { char *lf = getenv("AFNI_STARTUP_SCRIPT") ;
1251 if( lf == NULL ) lf = ".afni.startup_script" ;
1252 if( lf != NULL ){
1253 char *eh = NULL , *ff ;
1254 int ll = strlen(lf) + 8 ;
1255 if( !THD_is_file(lf) && lf[0] == '.' ){
1256 if( THD_is_file(lf+1) ) lf = lf+1 ;
1257 }
1258 if( !THD_is_file(lf) && lf[0] != '/' ) eh = getenv("HOME") ;
1259 if( eh != NULL ) ll += strlen(eh) ;
1260 ff = AFMALL(char, ll) ;
1261 if( eh != NULL ){ strcpy(ff,eh) ; strcat(ff,"/") ; }
1262 else { ff[0] = '\0' ; }
1263 strcat(ff,lf) ;
1264 GLOBAL_argopt.script_fname = ff ;
1265 }
1266 }
1267
1268 /*-- 18 Nov 1999: Allow setting of options from environment --*/
1269
1270 env = getenv( "AFNI_OPTIONS" ) ;
1271 if( env != NULL )
1272 prepend_string_to_args( env, in_argc, in_argv, &new_argc, &new_argv ) ;
1273 if( new_argv != NULL ){
1274 MAIN_argc = argc = new_argc ;
1275 MAIN_argv = argv = new_argv ;
1276 }
1277
1278 #ifdef ALLOW_PLUGINS
1279 GLOBAL_argopt.noplugins = AFNI_yesenv( "AFNI_NOPLUGINS" ) ;
1280 GLOBAL_argopt.noplugouts = !AFNI_yesenv( "AFNI_YESPLUGOUTS" ) ;
1281 #endif
1282
1283 env_orient = getenv( "AFNI_ORIENT" ) ;
1284
1285 GLOBAL_argopt.read_sessions = True ; /* exactly one of these should be True */
1286 GLOBAL_argopt.read_images = False ;
1287 GLOBAL_argopt.read_dsets = False ; /* 17 Mar 2000 */
1288
1289 GLOBAL_argopt.datum = ILLEGAL_TYPE ;
1290
1291 GLOBAL_argopt.gamma = INIT_gamma ;
1292 GLOBAL_argopt.gsfac = 0.0 ;
1293 GLOBAL_argopt.ncolor = INIT_ngray ;
1294 #if MMAP_THRESHOLD > 0
1295 GLOBAL_argopt.auto_purge = INIT_purge ;
1296 #else
1297 GLOBAL_argopt.auto_purge = (RwcBoolean)!AFNI_noenv("AFNI_AUTOPURGE") ;
1298 #endif
1299 GLOBAL_argopt.resize_images = False ; /* False means all images must match */
1300 GLOBAL_argopt.keep_logo = False ; /* For making pretty pictures? */
1301 GLOBAL_argopt.pos_func = INIT_posfunc ;/* Positive valued functions? */
1302 GLOBAL_argopt.recurse = 0 ; /* Recurse on session directories? */
1303 GLOBAL_argopt.xtwarns = 0 ; /* > 0 means keep Xt warnings turned on */
1304 GLOBAL_argopt.destruct = False ; /* True means allow overwrite of datasets */
1305 /* (Not yet properly implemented!) */
1306
1307 GLOBAL_argopt.tlrc_big = INIT_tlrc_big ; /* use the big Talairach box? */
1308 #ifndef WARP_4D
1309 GLOBAL_argopt.warp_4D = False ;
1310 #else
1311 GLOBAL_argopt.warp_4D = True ;
1312 #endif
1313
1314 GLOBAL_argopt.unique_dcs = False ; /* 06 Nov 1996 */
1315
1316 strcpy(GLOBAL_argopt.orient_code,"---") ;
1317
1318 strcpy(GLOBAL_argopt.title_name,"AFNI") ; /* default title bar name */
1319
1320 GLOBAL_argopt.left_is_left = AFNI_yesenv( "AFNI_LEFT_IS_LEFT" ) ;
1321 GLOBAL_argopt.left_is_posterior = AFNI_yesenv( "AFNI_LEFT_IS_POSTERIOR" ) ;
1322
1323 GLOBAL_argopt.read_tim = 0 ; /* 19 Oct 1999 */
1324
1325 GLOBAL_argopt.cat_sess = !AFNI_noenv("AFNI_ALL_DATASETS") ; /* 02 Jun 2016 */
1326
1327 /* 04/06/2020 discoraj */
1328 GLOBAL_argopt.all_dsets_startup = AFNI_yesenv("ALL_DSETS_STARTUP") ;
1329
1330 while( narg < argc ){
1331
1332 if( argv[narg][0] != '-' ) break ; /* no - ==> quit */
1333
1334 #ifdef USE_TRACING
1335 if( strncmp(argv[narg],"-trace",5) == 0 ){
1336 DBG_trace = 1 ;
1337 narg++ ; continue ;
1338 }
1339 if( strncmp(argv[narg],"-TRACE",5) == 0 ){ /* 23 Aug 1998 */
1340 DBG_trace = 2 ;
1341 if( MAIN_shell != NULL )
1342 XSynchronize(XtDisplay(MAIN_shell),TRUE) ; /* 01 Dec 1999 */
1343 narg++ ; continue ;
1344 }
1345 #endif
1346
1347 #if 0
1348 /*----- -Dname=val -- set environment variable [22 Mar 2005] -----*/
1349
1350 if( strncmp(argv[narg],"-D",2) == 0 && strchr(argv[narg],'=') != NULL ){
1351 (void) AFNI_setenv( argv[narg]+2 ) ;
1352 narg++ ; continue ; /* go to next arg */
1353 }
1354 #endif
1355
1356 /*----- -bysub or -BIDS -----*/
1357
1358 if( strcasecmp(argv[narg],"-bysub") == 0 ||
1359 strcasecmp(argv[narg],"-BIDS") == 0 ){ /* 01 Feb 2018 */
1360 int bb ; char **alist ; int nba,nta,aa , inc_narg ;
1361
1362 narg++ ;
1363 if( narg >= argc || argv[narg][0] == '-' ){ /* trickery to use */
1364 alist = (char **)malloc(sizeof(char *)*1) ; /* "." if aren't */
1365 alist[0] = "." ; nba = 0 ; nta = 1 ; /* any args here */
1366 inc_narg = 0 ;
1367 } else { /* scan the full arg list */
1368 alist = argv ; nba = narg ; nta = argc ; inc_narg = 1 ;
1369 }
1370
1371 for( aa=nba ; /* loop over args */
1372 aa < nta && alist[aa][0] != '-' ; /* following option */
1373 aa++ , narg += inc_narg ){
1374
1375 if( THD_is_directory(alist[aa]) &&
1376 strncmp(alist[aa],"sub-",4) != 0 && /* method 2 */
1377 alist[aa][0] != '-' ){ /* find all sub- names [15 Apr 2019] */
1378
1379 char *cmd=NULL , *flist=NULL , *qmd=NULL ; NI_str_array *qsar=NULL ; int qq ;
1380 cmd = (char *)malloc(sizeof(char)*(128+strlen(alist[aa]))) ;
1381 sprintf( cmd, "find %s -maxdepth 1 -type d -name 'sub-*'", alist[aa] ) ;
1382 flist = THD_suck_pipe( cmd ) ; free(cmd) ;
1383 if( flist == NULL || strlen(flist) < 4 ){
1384 WARNING_message("-bysub: Didn't find any 'sub-*' under %s",alist[aa]) ;
1385 continue ;
1386 }
1387 qsar = NI_decode_string_list( flist , ";" ) ;
1388 if( qsar == NULL || qsar->num == 0 ){ /* should never happen */
1389 WARNING_message("-bysub: Didn't find any 'sub-*' under %s",alist[aa]) ;
1390 free(flist) ;
1391 continue ;
1392 }
1393 for( qq=0 ; qq < qsar->num ; qq++ ){
1394 cmd = qsar->str[qq] ; if( cmd == NULL ) continue ;
1395 bb = strlen(cmd) ; if( bb < 2 ) continue ;
1396 if( cmd[bb-1] == '/' ) cmd[bb-1] = '\0' ;
1397 qmd = strrchr(cmd,'/') ;
1398 if( qmd != NULL ){ qmd++ ; } else { cmd = qmd ; }
1399 bysub = (char **)realloc(bysub,sizeof(char *)*(num_bysub+1)) ;
1400 bysub[num_bysub++] = strdup(qmd) ;
1401 bysub_dir = (char **)realloc(bysub_dir,sizeof(char *)*(num_bysub_dir+1)) ;
1402 bysub_dir[num_bysub_dir++] = strdup(alist[aa]) ;
1403 }
1404
1405 } else { /* method 1: a sub-XXX name */
1406
1407 bysub = (char **)realloc(bysub,sizeof(char *)*(num_bysub+1)) ;
1408 if( strncmp(alist[aa],"sub-",4) == 0 ){
1409 bysub[num_bysub] = strdup(alist[aa]) ;
1410 } else {
1411 bysub[num_bysub] = (char *)malloc(sizeof(char)*(strlen(alist[aa])+8)) ;
1412 sprintf( bysub[num_bysub] , "sub-%s" , alist[aa] ) ;
1413 }
1414 bb = strlen(bysub[num_bysub]) ;
1415 if( bb > 1 && bysub[num_bysub][bb-1] == '/' )
1416 bysub[num_bysub][bb-1] = '\0' ;
1417 num_bysub++ ;
1418 }
1419
1420 } /* end of loop over -bysub args */
1421
1422 if( alist != argv ) free(alist) ;
1423 if( narg < argc && strcmp(argv[narg],"-") == 0 ) narg++ ;
1424 continue ;
1425 }
1426
1427 if( strcmp(argv[narg],"-seehidden") == 0 ){
1428 first_plugin_check = 1 ;
1429 narg++ ; continue ;
1430 }
1431
1432 /*----- -layout (23 Sep 2000) -----*/
1433
1434 if( strcmp(argv[narg],"-layout") == 0 ){
1435 if( narg+1 >= argc ) ERROR_exit("need an argument after -layout!") ;
1436 GLOBAL_argopt.layout_fname = argv[++narg] ; /* just a pointer */
1437 narg++ ; continue ; /* go to next arg */
1438 }
1439
1440 /*----- -no1D option (27 Jan 2000) ----- */
1441
1442 if( strncmp(argv[narg],"-no1D",5) == 0 ){
1443 GLOBAL_argopt.read_1D = 0 ;
1444 narg++ ; continue ; /* go to next arg */
1445 }
1446
1447 /*----- -notcsv option (16 Jun 2020) ----- */
1448
1449 if( strncmp(argv[narg],"-notcsv",7) == 0 ||
1450 strncmp(argv[narg],"-notsv" ,6) == 0 ||
1451 strncmp(argv[narg],"-nocsv" ,6) == 0 ){
1452 GLOBAL_argopt.read_tcsv = 0 ;
1453 narg++ ; continue ; /* go to next arg */
1454 }
1455
1456 /*----- -skip_afnirc option (14 Jul 1998) -----*/
1457
1458 if( strncmp(argv[narg],"-skip_afnirc",12) == 0 ){
1459 GLOBAL_argopt.skip_afnirc = 1 ;
1460 narg++ ; continue ; /* go to next arg */
1461 }
1462
1463 /*----- -rt option -----*/
1464
1465 if( strncmp(argv[narg],"-rt",3) == 0 ){
1466 GLOBAL_argopt.allow_rt = -1 ;
1467 GLOBAL_argopt.no_frivolities = 1 ;
1468 #if 0
1469 #ifdef USE_TRACING
1470 DBG_trace = 0 ; /* 26 Jan 2001 */
1471 #endif
1472 #endif
1473 narg++ ; continue ; /* go to next arg */
1474 }
1475
1476 if( strncmp(argv[narg],"-nort",5) == 0 ){ /* 09 Oct 2000 */
1477 GLOBAL_argopt.allow_rt = 0 ;
1478 GLOBAL_argopt.no_frivolities = 0 ;
1479 narg++ ; continue ; /* go to next arg */
1480 }
1481
1482 /*----- -noqual -----*/
1483
1484 if( strncmp(argv[narg],"-noqual",6) == 0 ){
1485 GLOBAL_argopt.elide_quality = 1 ;
1486 narg++ ; continue ; /* go to next arg */
1487 }
1488
1489 /*---- -agni [29 Aug 2001] or -suma -----*/
1490
1491 if( strcmp(argv[narg],"-agni")==0 || strcmp(argv[narg],"-suma")==0 ){
1492 fprintf(stderr,"\n-agni/-suma are now turned on by default\n") ;
1493 GLOBAL_argopt.enable_suma = 1 ;
1494 narg++ ; continue ; /* go to next arg */
1495 }
1496
1497 /*---- -comsep c [22 Feb 2007] ----*/
1498
1499 if( strcmp(argv[narg],"-comsep") == 0 ){
1500 char cc ;
1501 if( ++narg >= argc ) ERROR_exit("need an argument after -comsep") ;
1502 cc = argv[narg][0] ;
1503 if( cc=='\0' || isalnum(cc) || isspace(cc) || cc=='\'' || cc=='\"' )
1504 ERROR_message("Illegal character after -comsep") ;
1505 else
1506 comsep = cc ;
1507
1508 narg++ ; continue ;
1509 }
1510
1511 /*---- -com ccc [29 Jul 2005] ----*/
1512
1513 if( strcmp(argv[narg],"-com") == 0 ){
1514 int ii , ll ; char *cm , *cs , *cq ;
1515 if( ++narg >= argc ) ERROR_exit("need an argument after -com!");
1516 cm = argv[narg] ; ll = strlen(cm) ; cs = strchr(cm,comsep) ;
1517 if( ll > 1024 ) ERROR_message("argument after -com is too long:\n'%s'" ,argv[narg] );
1518 else if( ll < 3 ) ERROR_message ("argument after -com is too short:\n'%s'",argv[narg] );
1519 else if( cs == NULL ) {
1520 if (COM_num < MAX_N_COM) COM_com[ COM_num++ ] = strdup(argv[narg]) ;
1521 else ERROR_message("Too many commands (max allowed=%d)",MAX_N_COM);
1522 } else { /* 22 Feb 2007: break into sub-commands */
1523 cq = cm = strdup(argv[narg]) ;
1524 for( ii=ll-1 ; isspace(cm[ii]) ; ii-- ) cm[ii] = '\0' ; /* trim end */
1525 cs = strchr(cm,comsep) ;
1526 while(1){
1527 *cs = '\0' ; /* NUL terminate command at separator */
1528 for( ; *cm != '\0' && isspace(*cm) ; cm++ ) ; /* trim front */
1529 ll = strlen(cm) ;
1530 if( ll > 2 && ll <= 1024 ) {
1531 if (COM_num < MAX_N_COM) COM_com[ COM_num++ ] = strdup(cm) ;
1532 else ERROR_message("Too many commands in total.");
1533 } cm = cs+1 ; if( *cm == '\0' ) break ; /* reached the end */
1534 cs = strchr(cm,comsep) ; /* search for next sep */
1535 if( cs == NULL ) cs = cm + strlen(cm) ;
1536 }
1537 free(cq) ;
1538 }
1539
1540 narg++ ; continue ; /* go to next arg */
1541 }
1542
1543 /*---- -disable_done [21 Aug 2008, rickr] ----*/
1544 /* This flag disables use of the "done" and X buttons.
1545 Close afni via plugout_drive or kill. */
1546
1547 if( strcmp(argv[narg],"-disable_done") == 0 ){
1548 GLOBAL_argopt.disable_done = 1 ;
1549 narg++ ; continue ;
1550 }
1551
1552 /*---- -niml [28 Feb 2002] -----*/
1553
1554 if( strcmp(argv[narg],"-niml") == 0 ){
1555 if( GLOBAL_argopt.yes_niml )
1556 fprintf(stderr,"\n-niml is already turned on\n") ;
1557 GLOBAL_argopt.yes_niml++ ;
1558 narg++ ; continue ; /* go to next arg */
1559 }
1560
1561 if( strcmp(argv[narg],"-noniml") == 0 ){
1562 GLOBAL_argopt.yes_niml-- ;
1563 if( GLOBAL_argopt.yes_niml < 0 ) GLOBAL_argopt.yes_niml = 0 ;
1564 narg++ ; continue ; /* go to next arg */
1565 }
1566
1567 /*----- -tbar 'name' option -----*/
1568
1569 if( strncmp(argv[narg],"-tbar",5) == 0 ){
1570 if( narg+1 >= argc ) ERROR_exit("need an argument after -tbar!");
1571 MCW_strncpy(GLOBAL_argopt.title_name,argv[++narg],32) ;
1572 narg++ ; continue ; /* go to next arg */
1573 }
1574
1575 /*----- -xtwarns option -----*/
1576
1577 if( strncmp(argv[narg],"-xtwarns",6) == 0 ){
1578 GLOBAL_argopt.xtwarns = 1 ;
1579 narg++ ; continue ; /* go to next arg */
1580 }
1581
1582 if( strncmp(argv[narg],"-XTWARNS",6) == 0 ){
1583 GLOBAL_argopt.xtwarns = 2 ;
1584 narg++ ; continue ; /* go to next arg */
1585 }
1586
1587 /*----- -XXX [24 Mar 2016] -----*/
1588
1589 if( strncasecmp(argv[narg],"-XXX",4) == 0 ){ /* all -XXX options are */
1590 narg += 2 ; continue ; /* followed by one arg */
1591 }
1592 if( strcasecmp(argv[narg],"-big") == 0 ){ narg++; continue; }
1593 if( strcasecmp(argv[narg],"-plus") == 0 ){ narg++; continue; }
1594 if( strcasecmp(argv[narg],"-minus") == 0 ){ narg++; continue; }
1595 if( strcasecmp(argv[narg],"-norm") == 0 ){ narg++; continue; }
1596
1597 /*----- -destruct option -----*/
1598
1599 if( strncmp(argv[narg],"-destruct",6) == 0 ){ /** has no effect at present **/
1600 fprintf(stderr,"\n** -destruct option not implemented at present! **\n") ;
1601 GLOBAL_argopt.destruct = False ;
1602 narg++ ; continue ; /* go to next arg */
1603 }
1604
1605 /*----- -posfunc option -----*/
1606
1607 if( strncmp(argv[narg],"-posfunc",6) == 0 ){
1608 GLOBAL_argopt.pos_func = True ;
1609 narg++ ; continue ; /* go to next arg */
1610 }
1611
1612 /*----- -R option -----*/
1613
1614 if( strncmp(argv[narg],"-R",2) == 0 ){
1615 int ll = strlen(argv[narg]) ;
1616 if( ll == 2 ) GLOBAL_argopt.recurse = 999 ;
1617 else {
1618 ll = strtol( argv[narg]+2 , NULL , 10 ) ;
1619 if( ll > 0 ) GLOBAL_argopt.recurse = ll ;
1620 else ERROR_exit("illegal -R option!") ;
1621 }
1622 narg++ ; continue ; /* go to next arg */
1623 }
1624
1625 /*----- -tlrc_big option -----*/
1626
1627 if( strncmp(argv[narg],"-tlrc_big",7) == 0 ){
1628 GLOBAL_argopt.tlrc_big = True ;
1629 narg++ ; continue ; /* go to next arg */
1630 }
1631
1632 /*----- -unique option (06 Nov 1996) -----*/
1633
1634 if( strncmp(argv[narg],"-unique",5) == 0 ){
1635 GLOBAL_argopt.unique_dcs = True ;
1636 narg++ ; continue ; /* go to next arg */
1637 }
1638
1639 /*----- -install option (14 Sep 1998) -----*/
1640
1641 if( strncmp(argv[narg],"-install",5) == 0 ){
1642 GLOBAL_argopt.install_cmap = True ;
1643 narg++ ; continue ; /* go to next arg */
1644 }
1645
1646 #ifndef WARP_4D
1647 /*----- -warp_4D option -----*/
1648
1649 if( strncmp(argv[narg],"-warp_4D",7) == 0 ){
1650 GLOBAL_argopt.warp_4D = True ;
1651 narg++ ; continue ; /* go to next arg */
1652 }
1653 #endif
1654
1655 /*----- -tlrc_small option -----*/
1656
1657 if( strncmp(argv[narg],"-tlrc_small",7) == 0 ){
1658 GLOBAL_argopt.tlrc_big = False ;
1659 narg++ ; continue ; /* go to next arg */
1660 }
1661
1662 /*----- -logo option -----*/
1663
1664 if( strncmp(argv[narg],"-logo",4) == 0 ){
1665 GLOBAL_argopt.keep_logo = True ;
1666 narg++ ; continue ; /* go to next arg */
1667 }
1668
1669 /*----- -resize option -----*/
1670
1671 if( strncmp(argv[narg],"-resize",4) == 0 ){
1672 GLOBAL_argopt.resize_images = True ;
1673 narg++ ; continue ; /* go to next arg */
1674 }
1675
1676 /*----- -purge option -----*/
1677
1678 if( strncmp(argv[narg],"-purge",4) == 0 ){
1679 GLOBAL_argopt.auto_purge = True ;
1680 narg++ ; continue ; /* go to next arg */
1681 }
1682 if( strncmp(argv[narg],"-nopurge",6) == 0 ){
1683 GLOBAL_argopt.auto_purge = False ;
1684 narg++ ; continue ; /* go to next arg */
1685 }
1686
1687 #ifdef ALLOW_PLUGINS
1688 /*----- -noplugins option -----*/
1689
1690 if( strncmp(argv[narg],"-noplugins",10) == 0 ){
1691 GLOBAL_argopt.noplugins = 1 ;
1692 narg++ ; continue ; /* go to next arg */
1693 }
1694
1695 /*----- -noplugouts option -----*/
1696
1697 if( strncmp(argv[narg],"-noplugouts",10) == 0 ){
1698 GLOBAL_argopt.noplugouts = 1 ;
1699 narg++ ; continue ; /* go to next arg */
1700 }
1701
1702 /*----- -yesplugouts option -----*/
1703
1704 if( strncmp(argv[narg],"-yesplugouts",10) == 0 ){
1705 GLOBAL_argopt.noplugouts = 0 ;
1706 GLOBAL_argopt.plugout_code = 0 ;
1707 narg++ ; continue ; /* go to next arg */
1708 }
1709
1710 /*----- -yesplugouts option -----*/
1711
1712 if( strncmp(argv[narg],"-YESplugouts",10) == 0 ){
1713 GLOBAL_argopt.noplugouts = 0 ;
1714 GLOBAL_argopt.plugout_code = 1 ;
1715 narg++ ; continue ; /* go to next arg */
1716 }
1717 #endif
1718
1719 /*----- -flipim option -----*/
1720
1721 if( strncmp(argv[narg],"-flipim",5) == 0 ){
1722 GLOBAL_argopt.left_is_left = 0 ;
1723 narg++ ; continue ; /* go to next arg */
1724 }
1725
1726 /*----- -noflipim option -----*/
1727
1728 if( strncmp(argv[narg],"-noflipim",5) == 0 ){
1729 GLOBAL_argopt.left_is_left = 1 ;
1730 narg++ ; continue ; /* go to next arg */
1731 }
1732
1733 /*----- -orient code option -----*/
1734
1735 if( strncmp(argv[narg],"-orient",4) == 0 ){
1736 if( narg+1 >= argc ) ERROR_exit("need an argument after -orient!");
1737
1738 MCW_strncpy(GLOBAL_argopt.orient_code,argv[++narg],4) ;
1739 narg++ ; continue ; /* go to next arg */
1740 }
1741
1742 /*----- -ignore # option -----*/
1743
1744 if( strncmp(argv[narg],"-ignore",4) == 0 ){
1745 float val ;
1746 if( narg+1 >= argc ) ERROR_exit("need an argument after -ignore!");
1747
1748 val = strtod( argv[++narg] , NULL ) ;
1749 if( val >= 0 ) GLOBAL_argopt.ignore = (int) val ;
1750 else fprintf(stderr,
1751 "\n** WARNING: -ignore value %s illegal\n", argv[narg]);
1752
1753 narg++ ; continue ; /* go to next arg */
1754 }
1755
1756 /*----- -im1 # option [must come before '-im' option!] -----*/
1757
1758 if( strncmp(argv[narg],"-im1",4) == 0 ){
1759 float val ;
1760 if( narg+1 >= argc ) ERROR_exit("need an argument after -im1!");
1761
1762 val = strtod( argv[++narg] , NULL ) ;
1763 if( val >= 1 ) GLOBAL_argopt.ignore = (int) (val-1.0) ;
1764 else fprintf(stderr,
1765 "\n** WARNING: -ignore value %s illegal\n", argv[narg]);
1766
1767 narg++ ; continue ; /* go to next arg */
1768 }
1769
1770
1771 /*----- -dy # option -----*/
1772
1773 if( strncmp(argv[narg],"-dy",3) == 0 ){
1774 float val ;
1775 if( narg+1 >= argc ) ERROR_exit("need an argument after -dy!");
1776
1777 val = strtod( argv[++narg] , NULL ) ;
1778 if( val > 0 ) GLOBAL_argopt.dy = val ;
1779 else fprintf(stderr,
1780 "\n** WARNING: -dy value %s illegal\n", argv[narg]);
1781
1782 narg++ ; continue ; /* go to next arg */
1783 }
1784
1785 /*----- -dz # option -----*/
1786
1787 if( strncmp(argv[narg],"-dz",3) == 0 ){
1788 float val ;
1789 if( narg+1 >= argc ) ERROR_exit("need an argument after -dz!");
1790
1791 val = strtod( argv[++narg] , NULL ) ;
1792 if( val > 0 ) GLOBAL_argopt.dz = val ;
1793 else fprintf(stderr,
1794 "\n** WARNING: -dz value %s illegal\n", argv[narg]);
1795
1796 narg++ ; continue ; /* go to next arg */
1797 }
1798
1799 /*----- -gamma # option -----*/
1800
1801 if( strncmp(argv[narg],"-gamma",4) == 0 ){
1802 float val ;
1803 if( narg+1 >= argc ) ERROR_exit("need an argument after -gamma!");
1804
1805 val = strtod( argv[++narg] , NULL ) ;
1806 if( val > 0 ) GLOBAL_argopt.gamma = val ;
1807 else fprintf(stderr,
1808 "\n** WARNING: -gamma value %s illegal\n", argv[narg]);
1809
1810 narg++ ; continue ; /* go to next arg */
1811 }
1812
1813 #ifdef USE_GSFAC
1814 /*----- -gsfac # option -----*/
1815
1816 if( strncmp(argv[narg],"-gsfac",4) == 0 ){
1817 float val ;
1818 if( narg+1 >= argc ) ERROR_exit("need an argument after -gsfac!");
1819
1820 val = strtod( argv[++narg] , NULL ) ;
1821 if( val != 0 ) GLOBAL_argopt.gsfac = val ;
1822 else fprintf(stderr,
1823 "\n** WARNING: -gsfac value %s illegal\n", argv[narg]);
1824
1825 narg++ ; continue ; /* go to next arg */
1826 }
1827 #endif
1828
1829 /*----- -datum type option -----*/
1830
1831 if( strncmp(argv[narg],"-datum",6) == 0 ){
1832 if( ++narg >= argc ) ERROR_exit("need an argument after -datum!") ;
1833
1834 if( strcmp(argv[narg],"short") == 0 ){
1835 GLOBAL_argopt.datum= MRI_short ;
1836 } else if( strcmp(argv[narg],"float") == 0 ){
1837 GLOBAL_argopt.datum= MRI_float ;
1838 } else if( strcmp(argv[narg],"complex") == 0 ){
1839 GLOBAL_argopt.datum= MRI_complex ;
1840 } else if( strcmp(argv[narg],"byte") == 0 ){
1841 GLOBAL_argopt.datum= MRI_byte ;
1842 } else {
1843 char buf[1024] ;
1844 sprintf(buf,"-datum of type '%s' is not supported in AFNI!",
1845 argv[narg] ) ;
1846 ERROR_exit(buf) ;
1847 }
1848 narg++ ; continue ; /* go to next arg */
1849 }
1850
1851 /*----- -ncolor # option -----*/
1852
1853 if( strncmp(argv[narg],"-ncolor",3) == 0 ){
1854 float val ;
1855 if( narg+1 >= argc ) ERROR_exit("need an argument after -ncolor!");
1856
1857 val = strtod( argv[++narg] , NULL ) ;
1858 if( val > 2 ) GLOBAL_argopt.ncolor = val ;
1859 else fprintf(stderr,
1860 "\n** WARNING: -ncolor value %s illegal\n", argv[narg]);
1861
1862 narg++ ; continue ; /* go to next arg */
1863 }
1864
1865 /*----- -dset option [17 Mar 2000] -----*/
1866
1867 if( strncmp(argv[narg],"-dset",5) == 0 ){
1868 GLOBAL_argopt.read_images = False ;
1869 GLOBAL_argopt.read_sessions = False ;
1870 GLOBAL_argopt.read_dsets = True ;
1871 narg++ ; continue ; /* go to next arg */
1872 }
1873
1874 /*----- -im option -----*/
1875
1876 if( strncmp(argv[narg],"-im",3) == 0 ){
1877 fprintf(stderr,
1878 "\n** WARNING: option '%s' for viewing plain images is old and not very useful\n" ,
1879 argv[narg] ) ;
1880 GLOBAL_argopt.read_images = True ;
1881 GLOBAL_argopt.read_sessions = False ;
1882 GLOBAL_argopt.read_dsets = False ; /* 17 Mar 2000 */
1883 narg++ ; continue ; /* go to next arg */
1884 }
1885
1886 /*----- -tim option [19 Oct 1999] -----*/
1887
1888 if( strncmp(argv[narg],"-tim",4)==0 || strncmp(argv[narg],"-zim",4)==0 ){
1889 int ll=strlen(argv[narg]) , nn ;
1890
1891 GLOBAL_argopt.read_images = True ;
1892 GLOBAL_argopt.read_sessions = False ;
1893 GLOBAL_argopt.read_dsets = False ; /* 17 Mar 2000 */
1894 GLOBAL_argopt.read_tim = 1 ;
1895
1896 if( ll > 5 && argv[narg][4] == ':' ){ /* 20 Oct 1999 */
1897 nn = strtol( argv[narg]+5 , NULL , 10 ) ;
1898 if( nn > 1 ){
1899 GLOBAL_argopt.read_tim = nn ; /* will be nz or nt */
1900 } else {
1901 ERROR_exit("Illegal value in %s",argv[narg]);
1902 }
1903 }
1904
1905 /* negate flag for time-order first (-tim) vs z-order first (-zim) */
1906
1907 if( strncmp(argv[narg],"-tim",4)==0 && GLOBAL_argopt.read_tim > 1 )
1908 GLOBAL_argopt.read_tim = - GLOBAL_argopt.read_tim ;
1909
1910 narg++ ; continue ; /* go to next arg */
1911 }
1912
1913 /* -port_number and quit */
1914 if( strncmp(argv[narg],"-port_number", 8) == 0) {
1915 int pp = 0;
1916 if( ++narg >= argc )
1917 ERROR_exit("need an argument after -port_number!");
1918 pp = get_port_named(argv[narg]);
1919 if (strcmp(argv[narg-1], "-port_number_quiet")) {
1920 fprintf(stdout, "\nPort %s: %d\n", argv[narg], pp);
1921 } else {
1922 fprintf(stdout, "%d\n", pp);
1923 }
1924 if (pp < 1) exit(1);
1925 else exit(0);
1926 }
1927
1928 /*----- -nomall option -----*/
1929
1930 if( strncmp(argv[narg],"-nomall",5) == 0 ){ /* was handled in main() */
1931 narg++ ; continue ; /* go to next arg */
1932 }
1933
1934 /*----- -motif_ver option -----*/
1935
1936 if( strncmp(argv[narg],"-motif_ver",10) == 0 ){/* was handled in main() */
1937 narg++ ; continue ; /* go to next arg */
1938 }
1939
1940 /*----- -no_detach option -----*/
1941
1942 if( strncmp(argv[narg],"-no_detach",7) == 0 ){/* was handled in main() */
1943 narg++ ; continue ; /* go to next arg */
1944 }
1945
1946 /*----- -q option -----*/
1947
1948 if( strcmp(argv[narg],"-q") == 0 ){ /* was handled in main() */
1949 narg++ ; continue ; /* go to next arg */
1950 }
1951
1952 /*----- all data sets 04/06/2020 discoraj -----*/
1953 if( strcmp(argv[narg],"-all_dsets") == 0 ){
1954
1955 // check for env variable that overides -all_dsets
1956 if( AFNI_noenv("AFNI_ALL_DATASETS") ){
1957 fprintf(stderr,
1958 "\n\n** WARNING: option -all_dsets is ignored silently.") ;
1959 fprintf(stderr,"\n AFNI_ALL_DATASETS = NO.\n") ;
1960 GLOBAL_argopt.all_dsets_startup = 0 ;
1961 }
1962 else { GLOBAL_argopt.all_dsets_startup = 1 ; }
1963
1964 GLOBAL_argopt.all_dsets_startup = 1 ;
1965 narg++ ; continue ; /* go to next arg */
1966 }
1967
1968 /*----- -- option -----*/
1969
1970 if( strcmp(argv[narg],"--") == 0 ){
1971 narg++ ; break ; /* end of args */
1972 }
1973
1974 /*----- if we get here, bad news for America! -----*/
1975
1976 ERROR_message("Unknown option %s ***",argv[narg]) ;
1977 suggest_best_prog_option(argv[0], argv[narg]);
1978 ERROR_exit ("Try 'afni -help' for a list of command line options.") ;
1979
1980 } /* end of loop over argv's starting with '-' */
1981
1982 if( num_bysub > 0 && GLOBAL_argopt.recurse ){ /* 01 Feb 2018 */
1983 WARNING_message("-bysub disables -R option") ;
1984 GLOBAL_argopt.recurse = 0 ;
1985 }
1986
1987 #if 0
1988 #ifdef USE_TRACING
1989 if( ALLOW_realtime ) DBG_trace = 0 ; /* 26 Jan 2001 */
1990 #endif
1991 #endif
1992
1993 /** 16 July 1997: orientation code change **/
1994
1995 if( GLOBAL_argopt.orient_code[0] == '-' ){
1996 if( GLOBAL_argopt.read_images )
1997 strcpy(GLOBAL_argopt.orient_code,"ASL") ;
1998 else if( env_orient != NULL )
1999 MCW_strncpy(GLOBAL_argopt.orient_code,env_orient,4) ;
2000 else
2001 strcpy(GLOBAL_argopt.orient_code,"RAI") ;
2002 }
2003
2004 THD_coorder_fill( GLOBAL_argopt.orient_code , &GLOBAL_library.cord ) ;
2005
2006 #if 0
2007 fprintf(stderr,"\ncoorder: signs = %d %d %d order = %d %d %d\n" ,
2008 GLOBAL_library.cord.xxsign ,
2009 GLOBAL_library.cord.yysign ,
2010 GLOBAL_library.cord.zzsign ,
2011 GLOBAL_library.cord.first ,
2012 GLOBAL_library.cord.second ,
2013 GLOBAL_library.cord.third ) ;
2014 #endif
2015
2016 GLOBAL_argopt.first_file_arg = narg ; /* rest of args must be files (I hope) */
2017
2018 EXRETURN ;
2019 }
2020
2021 /*-----------------------------------------------------------------------
2022 This routine is used if hiding Xt warnings is enabled.
2023 It does very little -- it replaces the default Xt warning handler.
2024 -------------------------------------------------------------------------*/
2025
AFNI_handler(char * msg)2026 void AFNI_handler(char *msg){
2027 if( GLOBAL_argopt.xtwarns > 0 &&
2028 msg != NULL &&
2029 strstr(msg,"Attempt to add wrong") == NULL ){
2030 ERROR_message("Xt message: %s", msg ) ;
2031 TRACEBACK ;
2032 }
2033 return ;
2034 }
2035
2036 /*-----------------------------------------------------------------------*/
2037 /*! Avoid fatal X11 errors. Stupid thing is so touchy sometimes. */
2038
AFNI_xerrhandler(Display * d,XErrorEvent * x)2039 int AFNI_xerrhandler( Display *d , XErrorEvent *x ){
2040 if( GLOBAL_argopt.xtwarns > 0 ){
2041 char buf[1024] = "(null)" ;
2042 if( x != NULL && d != NULL ) XGetErrorText( d,x->error_code , buf,255 ) ;
2043 ERROR_message( "Intercepted fatal X11 error: %s\n",buf) ;
2044 TRACEBACK ;
2045 }
2046 return 0 ;
2047 }
2048
2049 /*-----------------------------------------------------------------------*/
2050 /* Signal handler for fatal errors; prints out some info before death. */
2051
2052 #include <signal.h>
AFNI_sigfunc(int sig)2053 void AFNI_sigfunc(int sig)
2054 {
2055 char *sname ;
2056 static volatile int fff=0 ;
2057 if( fff ) _exit(1) ; else fff = 1 ;
2058 switch(sig){
2059 default: sname = "unknown" ; break ;
2060 case SIGINT: sname = "SIGINT" ; break ;
2061 case SIGPIPE: sname = "SIGPIPE" ; break ;
2062 case SIGSEGV: sname = "SIGSEGV" ; break ;
2063 case SIGBUS: sname = "SIGBUS" ; break ;
2064 case SIGTERM: sname = "SIGTERM" ; break ;
2065 }
2066 fprintf(stderr,"\nFatal Signal %d (%s) received\n",sig,sname); fflush(stderr);
2067 TRACEBACK ;
2068 fprintf(stderr,"** AFNI version = " AVERZHN " Compile date = " __DATE__ "\n" );
2069 #ifdef SHSTRING
2070 fprintf(stderr,"** [[Precompiled binary " SHSTRING ": " __DATE__ "]]\n") ;
2071 #endif
2072 fprintf(stderr,"** AFNI Program Is Dead :-( **\n") ;
2073 fflush(stderr) ;
2074 if( sig != SIGINT && sig != SIGTERM ){ /* add crashlog [13 Apr 2015] */
2075 FILE *dfp ; char *home , fname[1024] ;
2076 fprintf(stderr,"** If you report this crash to the AFNI message\n"
2077 "** board, please copy the error messages EXACTLY.\n") ;
2078 home = getenv("HOME") ;
2079 if( home != NULL ){
2080 strcpy(fname,home) ; strcat(fname,"/.afni.crashlog") ;
2081 } else {
2082 strcpy(fname,".afni.crashlog") ;
2083 }
2084 dfp = fopen( fname , "a" ) ;
2085 if( dfp != NULL ){
2086 fprintf(dfp,"\n*********-----------------------------------------------*********") ;
2087 fprintf(dfp,"\nFatal Signal %d (%s) received\n",sig,sname); fflush(stderr);
2088 #ifdef USE_TRACING
2089 DBG_tfp = dfp ; DBG_traceback() ; DBG_tfp = stderr ;
2090 #endif
2091 fprintf(dfp,"** AFNI version = " AVERZHN " Compile date = " __DATE__ "\n" );
2092 #ifdef SHSTRING
2093 fprintf(dfp,"** [[Precompiled binary " SHSTRING ": " __DATE__ "]]\n") ;
2094 #endif
2095 fprintf(dfp,"** AFNI Program Hideous Death **\n") ;
2096 fclose(dfp) ;
2097 fprintf(stderr,"** Crash log appended to file %s\n",fname) ;
2098 }
2099 }
2100 exit(1) ;
2101 }
2102
2103 /*----------------------------------------------------------------------------*/
2104 /* The functions below implement the delayed quit feature:
2105 - when signal SIGQUIT==3 is sent to AFNI, AFNI_sigfunc_quit() gets called
2106 - which uses alarm() to send signal SIGALRM after 5 sec
2107 - which invokes AFNI_sigfunc_alrm() == this function
2108 - which says something cute and dies
2109 This catenation of events is for Jerzy 'the Mad Pole' Bodurka.
2110 ------------------------------------------------------------------------------*/
2111
2112 extern int selenium_close(void) ;
2113
2114 /* the goodbye messages are now stored in afni_startup_tips.h */
2115
AFNI_sigfunc_alrm(int sig)2116 void AFNI_sigfunc_alrm(int sig)
2117 {
2118 int nn ;
2119
2120 #ifdef NGBY
2121 /* this first part is to print out 1 or more goodbye messages */
2122
2123 srand48((long)time(NULL)+(long)getpid()) ; /* reset random number generator */
2124 nn = (lrand48()>>3) % NGBY ; /* first message index */
2125
2126 if( !AFNI_yesenv("AFNI_NEVER_SAY_GOODBYE") ){
2127 if( nn < NGBY ){
2128 #undef NDUN
2129 #define NDUN (sizeof(dun)/sizeof(char *))
2130 static char *dun[] = { "is done" , "wraps up" , "concludes" ,
2131 "is over" , "terminates" , "finishes" } ;
2132 if( sig >= 0 ){
2133 printf("\n** AFNI %s: %s! [%d/%d]\n\n" ,
2134 dun[lrand48()%NDUN],gby[nn],nn+1,NGBY) ;
2135 } else {
2136 int kk ;
2137 int dn=AFNI_find_relprime_random(NGBY), ktop=(-sig < NGBY) ? -sig : NGBY ;
2138 for( kk=0 ; kk < ktop ; kk++ ){
2139 printf( "%s!\n\n" , gby[nn] + ((gby[nn][0]=='\n') ? 1 : 0) ) ;
2140 nn = (nn+dn)%NGBY ;
2141 }
2142 }
2143 }
2144 /** MCHECK ; **/
2145 }
2146 #endif /* NGBY */
2147
2148 /* meltdown controller on exit? (disabled) */
2149 #if 0
2150 if( sig <= 0 && !NO_frivolities ){
2151 Three_D_View *im3d = AFNI_find_open_controller() ;
2152 char *eee = getenv("AFNI_SPLASH_MELT") ;
2153 if( eee == NULL ) eee = "?" ; else eee[0] = toupper(eee[0]) ;
2154 if( im3d != NULL && MCW_widget_visible(im3d->vwid->top_shell) &&
2155 eee[0] != 'N' && (eee[0] == 'Y' || lrand48()%19==0) ){
2156 int jj ;
2157 XMapRaised( XtDisplay(im3d->vwid->top_shell) ,
2158 XtWindow(im3d->vwid->top_shell) ) ; /* raise controller */
2159 AFNI_sleep(111);
2160 MCW_melt_widget( im3d->vwid->top_form ) ;
2161 }
2162 sig = 0 ;
2163 }
2164 #endif
2165
2166 selenium_close(); /* close any selenium opened browser windows if open */
2167 exit(sig);
2168 }
2169
2170 /*-------------------------------------------------------------------------*/
2171 /* Called for sig=3 (cf. main() function) */
2172
AFNI_sigfunc_quit(int sig)2173 void AFNI_sigfunc_quit(int sig)
2174 {
2175 unsigned int nsec = (unsigned int)AFNI_numenv("AFNI_SIGQUIT_DELAY") ;
2176 if( nsec == 0 || nsec > 30 ) nsec = 5 ;
2177 fprintf(stderr,
2178 "\n** AFNI received QUIT signal ==> exit in %u seconds! **\n",nsec) ;
2179 signal(SIGALRM,AFNI_sigfunc_alrm) ; /* call the actual death dealer */
2180 (void)alarm(nsec) ; /* after a quick cigarette break */
2181 return ;
2182 }
2183
2184 /*-------------------------------------------------------------------------*/
2185 /*! Check if a particular option is present; 1=yes, 0=no. [15 Jan 2004]
2186 ---------------------------------------------------------------------------*/
2187
check_string(char * targ,int ns,char * ss[])2188 static int check_string( char *targ , int ns , char *ss[] )
2189 {
2190 int ii , lt ;
2191 if( targ == NULL || *targ == '\0' || ns <= 0 || ss == NULL ) return 0 ;
2192 lt = strlen(targ) ;
2193 for( ii=0 ; ii < ns ; ii++ )
2194 if( ss[ii] != NULL && strncmp(ss[ii],targ,lt) == 0 ) return 1 ;
2195 return 0 ;
2196 }
2197
2198 /*----------------------------------------------------------------------------*/
2199 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
2200 /*=============================================================================
2201 The new (and improved) AFNI main program.
2202 02 Aug 1999: Have moved much of the startup into a work process.
2203 ==============================================================================*/
2204 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
2205 /*----------------------------------------------------------------------------*/
2206
main(int argc,char * argv[])2207 int main( int argc , char *argv[] )
2208 {
2209 int ii ; int dienow=0 ;
2210
2211 /*--- help the pitiful user? ---*/
2212
2213 if( argc > 1 && strcasecmp(argv[1],"-help") == 0 ) AFNI_syntax() ;
2214
2215 if( argc > 1 && strncasecmp(argv[1],"-goodbye",6) == 0 ){
2216 printf("\n") ;
2217 if( argc > 2 && strcasecmp(argv[2],"ALL") == 0 ){ /* 30 Jan 2018 */
2218 AFNI_sigfunc_alrm(-666666) ;
2219 } else {
2220 ii = (argc > 2 ) ? abs((int)rintf((strtod(argv[2],NULL)))) : 0 ;
2221 AFNI_sigfunc_alrm(-ii) ;
2222 }
2223 }
2224
2225 if( argc > 1 && strncasecmp(argv[1],"-startup",6) == 0 ){ /* 05 Jan 2018 */
2226 int jj ;
2227 if( argc > 2 && strcasecmp(argv[2],"ALL") == 0 ){
2228 for( jj=0 ; jj < NTIP ; jj ++ ) AFNI_print_startup_tip(jj) ;
2229 } else {
2230 srand48((long)time(NULL)+(long)getpid()) ;
2231 ii = (argc > 2 ) ? abs((int)rintf((strtod(argv[2],NULL)))) : 1 ;
2232 for( jj=0 ; jj < ii ; jj++ ) AFNI_print_startup_tip(-1) ;
2233 }
2234 exit(0) ;
2235 }
2236
2237 if( argc > 1 && strcasecmp(argv[1],"-julian") == 0 ){ /* 30 Oct 2018 */
2238 printf("%s days since noon 01 Jan 4713 BC\n",julian_date_string()) ;
2239 exit(0) ;
2240 }
2241
2242 /** Check for -version [15 Aug 2003] **/
2243
2244
2245 if( check_string("-ver" ,argc,argv) || check_string("--ver" ,argc,argv) ||
2246 check_string("-version",argc,argv) || check_string("--version",argc,argv) ){
2247 show_AFNI_version() ;
2248 dienow++ ;
2249 }
2250
2251 if( check_string("-vnum" , argc, argv) ) {
2252 show_AFNI_vnum();
2253 dienow++ ;
2254 }
2255
2256 if( check_string("-package" , argc, argv) ) {
2257 show_AFNI_package();
2258 dienow++ ;
2259 }
2260
2261 if( check_string("-tips" , argc, argv) ) {
2262 show_AFNI_readme_gui();
2263 dienow++ ;
2264 }
2265
2266 if( check_string("-env" , argc, argv) ) {
2267 show_AFNI_readme_env();
2268 dienow++ ;
2269 }
2270
2271 /** MOTD output **/
2272
2273 if( check_string("--motd",argc,argv) || check_string("-motd",argc,argv) ){ /* 29 Nov 2005 */
2274 AFNI_display_motd(NULL) ; dienow++ ;
2275 }
2276
2277 /** just print the SHOWOFF string [26 Oct 2004] **/
2278
2279 if( check_string("-show",argc,argv) || check_string("--show",argc,argv) ){
2280 #ifdef SHSTRING
2281 printf( SHSTRING "\n" ) ;
2282 #else
2283 printf("Unknown\n") ;
2284 #endif
2285 dienow++ ;
2286 }
2287
2288 /** debug stuff **/
2289
2290 #ifdef USING_MCW_MALLOC
2291 if( !check_string("-nomall",argc,argv) && !check_string("-rt",argc,argv) )
2292 enable_mcw_malloc() ;
2293 #endif
2294
2295 #ifdef USE_TRACING
2296 if( check_string("-trace",argc,argv) ) DBG_trace = 1 ;
2297 if( check_string("-TRACE",argc,argv) ) DBG_trace = 2 ;
2298 #endif
2299
2300 if( check_string("-motif_ver",argc,argv) ) {
2301 show_motif_version_string() ;
2302 dienow++ ;
2303 }
2304
2305 /* check the processed environment, the afni way: machdep/prefilter
2306 * and the common main() way: prefilter/machdep 19 Sep 2013 [rickr] */
2307
2308 if( check_string("-get_processed_env_afni",argc,argv) ) {
2309 AFNI_prefilter_args( &argc , &argv );
2310 machdep();
2311 system("env | grep -e '^AFNI' -e '^NIFTI' | sort");
2312 dienow++ ;
2313 }
2314 else if( check_string("-get_processed_env",argc,argv) ) {
2315 machdep();
2316 AFNI_prefilter_args( &argc , &argv );
2317 system("env | grep -e '^AFNI' -e '^NIFTI' | sort");
2318 dienow++ ;
2319 }
2320
2321 if( check_string("-global_opts",argc,argv) ) { /* list global */
2322 fputs(SUMA_Offset_SLines(get_help_help(),3),
2323 stdout); /* opts used by all AFNI progs */
2324 fputs(get_gopt_help(), stdout);
2325 dienow++ ;
2326 }
2327
2328 if( check_string("-papers",argc,argv) ){ /* list AFNI papers */
2329 AFNI_list_papers(NULL) ; dienow++ ;
2330 }
2331
2332 /* getting text output, should be early 23 Oct 2015 [rickr] */
2333
2334 if( check_string("-available_npb_quiet", argc, argv) ) {
2335 fprintf(stdout,"%d\n",get_available_npb());
2336 dienow++ ;
2337 } else if( check_string("-available_npb", argc, argv) ) {
2338 fprintf(stdout,
2339 "\nFirst available npb: %d\n",get_available_npb());
2340 dienow++ ;
2341 }
2342
2343 /* -list_ports list and quit */
2344 if( check_string("-list_ports", argc, argv) ) {
2345 show_ports_list(); dienow++ ;
2346 }
2347
2348 /*** if ordered, die right now ***/
2349
2350 if( dienow ) exit(0) ; /* farewell, cruel world */
2351
2352 /***----- otherwise, perhaps become all detached from reality -----***/
2353
2354 /* no version until after quick exit checks 23 Oct 2015 [rickr] */
2355 if( ! check_string("-q",argc,argv) ) show_AFNI_version() ;
2356
2357 /* Since AFNI_DETACH is applied before machdep() or other my_getenv
2358 calls, -D cannot be used to apply this env var, so add an option.
2359 7 Mar 2014 [rickr] */
2360
2361 if( ! check_string("-no_detach",argc,argv) ) {
2362 PUTENV("AFNI_DETACH","YES") ; /* Apr 2013 */
2363 { char *eee = getenv("AFNI_DETACH") ; /* 31 May 2011 */
2364 if( YESSISH(eee) ){
2365 ii = (int)fork();
2366 if( ii != 0 ){ /* parent process dies now */
2367 AFNI_sleep(2345) ; /* msec */
2368 fprintf(stderr,"++ AFNI is detached from terminal.\n") ;
2369 _exit(0) ;
2370 }
2371 }
2372 }
2373 }
2374
2375 /*------------- Initialize some more stuff -------------*/
2376
2377 machdep() ;
2378 /*** INFO_message("before prefilter: argc=%d argv=%p",argc,(void *)argv) ; ***/
2379 AFNI_prefilter_args( &argc , &argv ) ; /* 11 Dec 2007 */
2380 /*** INFO_message("after prefilter: argc=%d argv=%p",argc,(void *)argv) ; ***/
2381
2382 THD_load_datablock_verbose(1) ; /* 21 Aug 2002 */
2383
2384 signal(SIGINT ,AFNI_sigfunc) ; /* may be superseded by mainENTRY below */
2385 signal(SIGBUS ,AFNI_sigfunc) ;
2386 signal(SIGSEGV,AFNI_sigfunc) ;
2387 signal(SIGTERM,AFNI_sigfunc) ;
2388
2389 first_plugin_check = -1 ; /* 16 Nov 2016 */
2390
2391 #if 0
2392 #ifdef USE_TRACING
2393 if( ALLOW_realtime ) DBG_trace = 0 ; /* 26 Jan 2001 */
2394 #endif
2395 #endif
2396
2397 /** 25 Oct 2001: check for -q (quiet) option right away **/
2398
2399 GLOBAL_argopt.quiet = AFNI_yesenv("AFNI_QUIET") ;
2400 if( AFNI_VERBOSE && check_string("-q",argc,argv) ) GLOBAL_argopt.quiet = 1;
2401
2402 /** 12 Dec 2002: scan for "-rt" now,
2403 to see if we want to start the version check **/
2404
2405 GLOBAL_argopt.allow_rt = check_string("-rt",argc,argv) ;
2406
2407 if( !GLOBAL_argopt.quiet && !ALLOW_realtime )
2408 #if 1 /* 30 Dec 2015 */
2409 AFNI_start_version_check() ; /* 21 Nov 2002 */
2410 #else
2411 AFNI_start_compile_date_check() ; /* 17 Jun 2014 */
2412 #endif
2413
2414 #ifdef DARWIN
2415 if( 0 && !THD_is_directory("/sw/bin") && !AFNI_noenv("AFNI_IMSAVE_WARNINGS") )
2416 WARNING_message("On Mac OS X, it helps if you install the fink software:\n"
2417 " cf. http://fink.sourceforge.net/\n"
2418 " and then do\n"
2419 " fink install netpbm\n" ) ;
2420 #endif
2421
2422 /** Start the debug traceback stuff (also resets signal handler) **/
2423
2424 mainENTRY("AFNI:main") ; /* 26 Jan 2001: replace ENTRY w/ mainENTRY */
2425
2426 signal(SIGQUIT,AFNI_sigfunc_quit) ; /* For Jerzy -- 09 Jan 2008 */
2427
2428 /** set the function to call if run out of memory when creating datasets **/
2429
2430 THD_set_freeup( AFNI_purge_unused_dsets ) ; /* 18 Oct 2001 */
2431
2432 #if 0
2433 if( argc > 1 ) AFNI_logger("afni",argc,argv) ; /* 14 Aug 2001 */
2434 #endif
2435
2436 #if 0 /* now in machdep() */
2437 srand48((long)time(NULL)+(long)getpid()) ; /* initialize random number generator */
2438 #endif
2439
2440 REPORT_PROGRESS( "\n" ) ;
2441
2442 /*-- Be friendly or trivial --*/
2443
2444 if( check_string("-trivia",argc,argv) ){ /* 27 Nov 2007 */
2445 char **triv ; int ntriv,tt ;
2446 ntriv = AFNI_get_todays_trivia( &triv ) ;
2447 for( tt=0 ; tt < ntriv ; tt++ ){
2448 REPORT_PROGRESS(triv[tt]) ; REPORT_PROGRESS("\n") ;
2449 }
2450 REPORT_PROGRESS( "\n" ) ; exit(0) ;
2451 }
2452
2453 { char *sf = AFNI_get_friend() ;
2454 REPORT_PROGRESS( sf ) ;
2455 REPORT_PROGRESS( "\n\n" ) ;
2456 if( check_string("-friend",argc,argv) ) exit(0) ;
2457 }
2458
2459 /*----- tell the user who we are -----*/
2460
2461 /* REPORT_PROGRESS( ANNOUNCEMENT ) ;*/
2462
2463 /*-------------------------------------------------------------*/
2464 /*------------ initialize the controllers list ----------------*/
2465
2466 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ )
2467 GLOBAL_library.controllers[ii] = NULL ;
2468 GLOBAL_library.dc = NULL ;
2469
2470 GLOBAL_library.controller_lock = 0 ; ENABLE_LOCK ;
2471 GLOBAL_library.time_lock = 0 ; /* 03 Nov 1998 */
2472 GLOBAL_library.ijk_lock = 0 ; /* 11 Sep 2000 */
2473 GLOBAL_library.zoompan_lock = 0 ; /* 10 Dec 2019 */
2474 SET_FIM_bkthr(10.0) ; /* 02 Jun 1999 */
2475
2476 GLOBAL_library.hints_on = 0 ; /* 07 Aug 1999 */
2477
2478 #ifdef ALLOW_PLUGINS
2479 GLOBAL_library.plugins = NULL ;
2480 #endif
2481
2482 GLOBAL_library.session = NULL ; /* 20 Dec 2001 */
2483 GLOBAL_library.warptable = NULL ; /* 28 Aug 2002 */
2484
2485 GLOBAL_library.realtime_status = NULL ; /* 01 Jun 2009 */
2486 GLOBAL_library.realtime_callback = NULL ;
2487
2488 /*--------------------------------------------------------------------*/
2489 /*--- initialize X, toplevel window, defaults, and display context ---*/
2490
2491 REPORT_PROGRESS("Initializing: X11");
2492
2493 /*--- check for font size environment control [06 Nov 2018] ---*/
2494
2495 { char *ep = getenv("AFNI_FONTSIZE") ;
2496 if( ep != NULL ){
2497 if( strcasecmp(ep,"minus") == 0 ) XXX_MINUS_FONTS ;
2498 else if( strcasecmp(ep,"plus") == 0 ) XXX_PLUS_FONTS ;
2499 else if( strcasecmp(ep,"big") == 0 ) XXX_BIG_FONTS ;
2500 else if( strcasecmp(ep,"norm") == 0 ) XXX_NORM_FONTS ;
2501 }
2502 }
2503
2504 /*--- look for -XXX options before starting X11 [24 Mar 2016] ---*/
2505
2506 process_XXX_options( argc , argv ) ; /* will set new_FALLback */
2507
2508 if( new_FALLback != NULL ){ /* if found any -XXX options, merge them */
2509 int qq,pp ;
2510 if( ! AFNI_yesenv("AFNI_DONT_USE_XRDB") )
2511 xrdb_pg = THD_find_executable("xrdb") ;
2512
2513 /* can't find xrdb executable ==> merge FALLback strings */
2514
2515 if( xrdb_pg == NULL ){
2516 for( qq=0 ; FALLback[qq] != NULL ; qq++ ){
2517 for( pp=0 ; new_FALLback[pp] != NULL ; pp++ ){
2518 if( equiv_FALLback( new_FALLback[pp] , FALLback[qq] ) ) break ;
2519 }
2520 if( new_FALLback[pp] == NULL )
2521 ADDTO_FALLback_one(FALLback[qq]) ;
2522 }
2523 for( qq=0 ; new_FALLback[qq] != NULL ; qq++ )
2524 ININFO_message("new_FALLback[%d] = \"%s\"",qq,new_FALLback[qq]) ;
2525
2526 } else { /* use xrdb to merge X11 resources */
2527
2528 #define XXXSIZ 4096
2529 char *xpg , *xout=NULL ; FILE *fp ;
2530 xpg = malloc(strlen(xrdb_pg)+64) ;
2531
2532 /* get the current resources settings */
2533
2534 sprintf(xpg,"%s -query",xrdb_pg) ;
2535 fp = popen(xpg,"r") ;
2536 if( fp != NULL ){
2537 xout = (char *)malloc(sizeof(char)*XXXSIZ) ; xout[0] = '\0' ;
2538 while( fgets(xout+strlen(xout),XXXSIZ-2,fp) != NULL ){
2539 xout = (char *)realloc(xout,sizeof(char)*(strlen(xout)+XXXSIZ)) ;
2540 }
2541 (void)pclose(fp) ;
2542 if( *xout != '\0' ) xrdb_old = xout ;
2543 }
2544
2545 /* set the new ones */
2546
2547 sprintf(xpg,"%s -override -",xrdb_pg) ;
2548 fp = popen( xpg , "w" ) ;
2549 if( fp != NULL ){
2550 for( pp=0 ; new_FALLback[pp] != NULL ; pp++ )
2551 fprintf(fp,"%s\n",new_FALLback[pp]) ;
2552 (void)pclose(fp) ;
2553 }
2554
2555 /* don't need new_FALLback any more */
2556
2557 for( pp=0 ; new_FALLback[pp] != NULL ; pp++ ) free(new_FALLback[pp]) ;
2558 free(new_FALLback) ; new_FALLback = NULL ; free(xpg) ;
2559 #undef XXXSIZ
2560 }
2561 }
2562
2563 /*--- now ready to start X11 for true --*/
2564
2565 #ifdef DARWIN
2566 { char *eee = getenv("DYLD_LIBRARY_PATH") ;
2567 char *fff = getenv("AFNI_SKIP_DYLD_WARNING") ;
2568 if( (fff == NULL || toupper(*fff) != 'Y') &&
2569 (eee == NULL || strstr(eee,"flat_namespace") == NULL) ){
2570 int vmajor=0, vminor=0 , vmicro=0 ;
2571 #if 0
2572 eee = get_XQuartz_version() ; /* Check XQuartz version [27 Jan 2017] */
2573 if( eee != NULL && isdigit(*eee) ){
2574 sscanf(eee,"%d.%d.%d",&vmajor,&vminor,&vmicro) ;
2575 /* INFO_message("XQuartz version: %d %d %d",vmajor,vminor,vmicro) ; */
2576 }
2577 #endif
2578 if( vmajor == 0 || vminor == 0 || vmajor > 2 ||
2579 (vmajor == 2 && vminor > 7) ||
2580 (vmajor == 2 && vminor == 7 && (vmicro > 9 || vmicro == 0)) ){
2581 fprintf(stderr,
2582 "\n"
2583 "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
2584 "++ If you are using XQuartz 2.7.10 (or later), and AFNI crashes when\n"
2585 " + opening windows, or you cannot type text into AFNI popup windows,\n"
2586 " + you might need to set an environment variable to solve this problem:\n"
2587 " + setenv DYLD_LIBRARY_PATH /opt/X11/lib/flat_namespace # tcsh\n"
2588 " + export DYLD_LIBRARY_PATH=/opt/X11/lib/flat_namespace # bash\n"
2589 " + This command is best put in your startup ~/.cshrc file, so that\n"
2590 " + it will be invoked for every (t)csh shell you open (mutatis mutandis\n"
2591 " + for the bash shell, of course).\n"
2592 " +\n"
2593 " + If things are OK and you want to avoid having this warning message\n"
2594 " + pollute your terminal, use this:\n"
2595 " + setenv AFNI_SKIP_DYLD_WARNING YES # tcsh\n"
2596 " + export AFNI_SKIP_DYLD_WARNING=YES # bash\n\n"
2597 "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
2598 ) ;
2599 }
2600 }
2601 }
2602 #endif
2603
2604 memset(&MAIN_app, 0, sizeof(MAIN_app)) ; /* 11 Feb 2009 [lesstif patrol] */
2605 MAIN_shell = XtVaAppInitialize( &MAIN_app , "AFNI" , NULL , 0 ,
2606 &argc , argv ,
2607 (new_FALLback!=NULL)?new_FALLback:FALLback ,
2608 NULL ) ;
2609
2610 if( MAIN_shell == NULL ) ERROR_exit("Cannot initialize X11") ;
2611
2612 #if 1
2613 { Display *dpy = XtDisplay(MAIN_shell) ;
2614 char msg[1024] , *xsv ; int xvr ;
2615 xsv = XServerVendor(dpy) ; xvr = XVendorRelease(dpy) ;
2616 if( xsv != NULL ){ sprintf(msg,"[%s v %d]",xsv,xvr); REPORT_PROGRESS(msg); }
2617 }
2618 #endif
2619
2620 { char *eee = getenv("DISPLAY") ; /* Sound stuff [20 Aug 2018] */
2621 GLOBAL_library.local_display = (eee == NULL) || (strstr(eee,":0") != NULL ) ;
2622 GLOBAL_library.have_sox = ( THD_find_executable("sox") != NULL ) ;
2623 GLOBAL_library.sound_player = get_sound_player() ;
2624 sound_set_note_ADSR(1) ;
2625 sound_set_note_waveform(SOUND_WAVEFORM_TRIANGLE) ;
2626 }
2627
2628 /* if we used xrdb to set X11 resources, re-set them back to their old
2629 state so that other AFNIs don't use these new settings by default */
2630
2631 if( xrdb_old != NULL && !XXX_set_default ){ /* 24 Mar 2016 */
2632 FILE *fp ; char *xpg ;
2633 xpg = malloc(strlen(xrdb_pg)+64) ;
2634 sprintf(xpg,"%s -override -",xrdb_pg) ;
2635 fp = popen( xpg , "w" ) ;
2636 if( fp != NULL ){
2637 fprintf(fp,"%s",xrdb_old) ;
2638 (void)pclose(fp) ;
2639 }
2640 free(xpg) ;
2641 }
2642
2643 #ifdef USE_TRACING
2644 if( DBG_trace == 2 ){ /* 01 Dec 1999 */
2645 XSynchronize(XtDisplay(MAIN_shell),TRUE) ;
2646 STATUS("XSynchronize is enabled") ;
2647 }
2648 #endif
2649 XtVaSetValues( MAIN_shell, XmNkeyboardFocusPolicy,XmEXPLICIT , NULL ) ;
2650
2651 MAIN_argc = argc ; MAIN_argv = argv ; /* what's left after XtVaAppInit */
2652
2653 REPORT_PROGRESS(".") ;
2654
2655 /** set default values of some environment variables [22 Jun 2004] **/
2656
2657 PUTENV("AFNI_LEFT_IS_LEFT","YES") ; /* 20 Jun 2019 */
2658 PUTENV("AFNI_CROSSHAIR_LINES","YES") ;
2659 PUTENV("AFNI_ALWAYS_LOCK","YES") ;
2660 PUTENV("AFNI_IMAGE_SAVESQUARE","YES") ;
2661 PUTENV("AFNI_DECONFLICT","OVERWRITE") ; /* 24 Sep 2007 */
2662 PUTENV("AFNI_X11_REDECORATE","NO") ;
2663 PUTENV("AFNI_RESCAN_AT_SWITCH","YES") ; /* 16 Nov 2007 */
2664 PUTENV("AFNI_VIDEO_DELAY","33") ; /* 20 Aug 2009 */
2665 PUTENV("AFNI_GRAPH_FADE","YES") ; /* Apr 2013 */
2666 PUTENV("AFNI_MPEG_DATASETS","NO") ; /* Feb 2015 */
2667 PUTENV("AFNI_FLASH_VIEWSWITCH","NO") ; /* 14 Apr 2016 */
2668 PUTENV("AFNI_DATASET_BROWSE","YES") ; /* 07 Nov 2018 */
2669 PUTENV("AFNI_VERSION_CHECK","NO") ; /* 04 Jan 2019 */
2670 PUTENV("AFNI_PBAR_FULLRANGE","YES") ; /* 03 Jun 2014 */
2671
2672 PUTENV("AFNI_COLORSCALE_DEFAULT","Reds_and_Blues_Inv") ; /* 24 May 2019 */
2673 PUTENV("AFNI_THRESH_TOP_EXPON" , "5" ) ;
2674 PUTENV("AFNI_THRESH_INIT_EXPON" , "1" ) ;
2675 PUTENV("AFNI_AUTORANGE_PERC" , "0" ) ;
2676
2677 PUTENV("AFNI_FIX_SCALE_SIZE" , "YES" ) ; /* (from Lucca) */
2678 PUTENV("AFNI_OPACITY_LOCK" , "YES" ) ;
2679
2680 PUTENV("AFNI_INSTACORR_JUMP", "YES" ) ; /* 24 Sep 2021 */
2681
2682 #if 0
2683 PUTENV("AFNI_IMAGE_LABEL_MODE","1") ;
2684 PUTENV("AFNI_IMAGE_LABEL_SIZE","2") ;
2685 PUTENV("AFNI_IMAGE_LABEL_SETBACK","01") ;
2686 PUTENV("AFNI_IMAGE_LABEL_COLOR","yellow") ;
2687 #endif
2688
2689 /*-- 04 Jun 1999: modify order of loading arguments and defaults --*/
2690
2691 if( ! GLOBAL_argopt.skip_afnirc ){
2692 char *sysenv = getenv("AFNI_SYSTEM_AFNIRC") ; /* 12 Apr 2000 */
2693 if( sysenv != NULL ) AFNI_process_environ(sysenv) ; /* 12 Apr 2000 */
2694
2695 AFNI_process_environ(NULL) ; /* 07 Jun 1999 */
2696 } else {
2697 AFNI_mark_environ_done() ; /* 16 Apr 2000 */
2698 }
2699
2700 /*-- 30 Apr 2015: some messages about obsolete environment variables --*/
2701
2702 if( getenv("AFNI_SLAVE_THRTIME") != NULL ){
2703 WARNING_message("environment variable AFNI_SLAVE_THRTIME is no longer used!") ;
2704 WARNING_message(" -- see AFNI_SLAVE_FUNCTIME and AFNI_SLAVE_THROLAY instead") ;
2705 }
2706
2707 if( getenv("AFNI_SLAVE_BUCKETS_TOO") != NULL ){ /* 30 May 2015 */
2708 WARNING_message("environment variable AFNI_SLAVE_BUCKETS_TOO is no longer used!") ;
2709 WARNING_message(" -- see AFNI_SLAVE_FUNCTIME and AFNI_SLAVE_THROLAY instead") ;
2710 }
2711
2712 /* set top exponent for threshold slider [04 Nov 2010] -- for Allison */
2713
2714 { static float tval[9] = { 1.0f , 10.0f , 100.0f , 1000.0f , 10000.0f ,
2715 100000.0f , 1000000.0f , 10000000.0f , 100000000.0f } ;
2716 ii = AFNI_numenv("AFNI_THRESH_TOP_EXPON") ;
2717 if( ii < 4 ) ii = 4 ;
2718 else if( ii > 6 ) ii = 6 ;
2719 THR_top_expon = ii ;
2720 THR_factor = 1.0f / tval[ii] ;
2721 THR_top_value = tval[ii] - 1.0f ;
2722 }
2723
2724 PBAR_FULLRANGE = AFNI_yesenv("AFNI_PBAR_FULLRANGE") ; /* 03 Jun 2014 */
2725
2726 AUTORANGE_PERC = (float)AFNI_numenv("AFNI_AUTORANGE_PERC") ; /* 24 May 2019 */
2727
2728 AFNI_load_defaults( MAIN_shell ) ;
2729
2730 if( ! GLOBAL_argopt.skip_afnirc ){ /* this line added 14 Jul 1998 */
2731 char *home = getenv("HOME") ; char fname[1024] ;
2732 char *sysenv = getenv("AFNI_SYSTEM_AFNIRC") ; /* 12 Apr 2000 */
2733
2734 GPT = NULL ; /* 19 Dec 1997 */
2735
2736 if( sysenv != NULL ) /* 12 Apr 2000 */
2737 AFNI_process_setup( sysenv , SETUP_INIT_MODE , NULL ) ;
2738
2739 if( home != NULL ){ strcpy(fname,home) ; strcat(fname,"/.afnirc") ; }
2740 else { strcpy(fname,".afnirc") ; }
2741 AFNI_process_setup( fname , SETUP_INIT_MODE , NULL ) ;
2742
2743 #ifdef AFNI_DEBUG
2744 home = dump_PBAR_palette_table(0) ;
2745 if( home != NULL ){ puts(home) ; free(home) ; }
2746 #endif
2747
2748 } else { /* these lines also 14 Jul 1998 */
2749 REPORT_PROGRESS( "[skip .afnirc]" ) ;
2750 }
2751
2752 /*--- finally, read the command line for other options ---*/
2753
2754 AFNI_parse_args( argc , argv ) ; /* after Xt init above, only my args left */
2755
2756 /*-- disable X11 and Xt error messages and crashes (we hope) --*/
2757
2758 (void) XSetErrorHandler( AFNI_xerrhandler ) ; /* 26 Jun 2003 */
2759 (void) XtAppSetErrorHandler(MAIN_app,AFNI_handler) ;
2760
2761 if( GLOBAL_argopt.xtwarns != 1 )
2762 (void) XtAppSetWarningHandler(MAIN_app,AFNI_handler) ; /* turn off */
2763
2764 /* FIM background threshold */
2765
2766 { char *lenv = getenv("AFNI_FIM_BKTHR") ; /* 04 Jun 1999 */
2767 if( lenv != NULL ){
2768 float bk = strtod(lenv,NULL) ;
2769 if( bk >= 0.0 && bk < 100.0 ) SET_FIM_bkthr(bk) ;
2770 }
2771 }
2772
2773 /* locking? */
2774
2775 if( AFNI_yesenv("AFNI_ALWAYS_LOCK") ){
2776 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ )
2777 GLOBAL_library.controller_lock |= (1<<ii) ;
2778 }
2779
2780 if( AFNI_yesenv("AFNI_TIME_LOCK") ){
2781 GLOBAL_library.time_lock = 1 ;
2782 }
2783
2784 if( AFNI_yesenv("AFNI_ZOOM_LOCK") ){ /* 10 Dec 2019 */
2785 GLOBAL_library.zoompan_lock = 1 ;
2786 }
2787
2788 /* default opacity [06 Jun 2019] */
2789
2790 { int opval = (int)AFNI_numenv("AFNI_DEFAULT_OPACITY") ;
2791 if( opval > 0 && opval <= 9 )
2792 GLOBAL_library.opacity_setting = opval ;
2793 else
2794 GLOBAL_library.opacity_setting = 6 ;
2795 }
2796
2797 /*-- now create first display context: MAIN_dc --*/
2798
2799 GLOBAL_library.dc = MAIN_dc =
2800 MCW_new_DC( MAIN_shell , GLOBAL_argopt.ncolor ,
2801 INIT_ncolovr , INIT_colovr , INIT_labovr ,
2802 GLOBAL_argopt.gamma , GLOBAL_argopt.install_cmap ) ;
2803
2804 memplot_to_X11_set_DC(MAIN_dc) ; /* 30 Apr 2012 */
2805
2806 /* for the old PseudoColor world (does anyone live there anymore?) */
2807
2808 if( MAIN_dc->depth < 9 && MAIN_dc->visual_class != TrueColor && GLOBAL_argopt.unique_dcs ){
2809 GLOBAL_argopt.unique_dcs = False ;
2810 REPORT_PROGRESS("[-unique off]") ;
2811 }
2812
2813 /*------------------------------------*/
2814 /*------- take it away, Goldie -------*/
2815 /*------------------------------------*/
2816
2817 #if 0
2818 (void) XtAppAddWorkProc( MAIN_app, MAIN_workprocess, NULL ) ;
2819 #else
2820 PLUTO_register_workproc( MAIN_workprocess , NULL ) ; /* rest of startup */
2821 #endif
2822
2823 MCW_disable_help() ;
2824
2825 STATUS("start XtAppMainLoop") ;
2826
2827 XtAppMainLoop(MAIN_app) ; /* never returns */
2828 AFexit(0) ; /* should never be reached */
2829 }
2830
2831
2832 #undef HUBERIZE
2833 #ifdef HUBERIZE
2834 #include "huber.c" /* this is useless drivel */
2835 #endif
2836
2837 /*---------------------------------------------------------------------------------
2838 Xt work process to do most of the initialization stuff.
2839 (So we can so a splash screen to pacify and amuse the user.)
2840 -----------------------------------------------------------------------------------*/
2841
2842 #define REFRESH XmUpdateDisplay(MAIN_im3d->vwid->top_shell)
2843
MAIN_workprocess(XtPointer fred)2844 static RwcBoolean MAIN_workprocess( XtPointer fred )
2845 {
2846 static int MAIN_calls = 0 ; /* controls what happens */
2847 static int nosplash = 0 ;
2848 static double eltime=0.0 , max_splash=3.0 ;
2849 int ii ;
2850
2851 ENTRY("MAIN_workprocess") ; /* 23 Jan 2001: added ENTRY/RETURN to this routine */
2852
2853 if(PRINT_TRACING){ char str[256]; sprintf(str,"MAIN_calls=%d",MAIN_calls); STATUS(str); }
2854
2855 switch( MAIN_calls ){
2856
2857 /*============================================================================
2858 This code is executed at the end (when MAIN_calls gets too big).
2859 ============================================================================*/
2860
2861 default:{
2862 STATUS("default call") ;
2863
2864 RETURN(True) ; /* I hope this keeps you happy, Ziad :-) */
2865 }
2866 break ;
2867
2868 /*============================================================================
2869 Stuff to popup the AFNI splash screen (see afni_splash.[ch]).
2870 ============================================================================*/
2871
2872 case 0:{
2873 STATUS("call 0") ;
2874
2875 #ifdef NO_FRIVOLITIES
2876 nosplash = 1 ;
2877 #else
2878 nosplash = AFNI_yesenv("AFNI_NOSPLASH") ;
2879 #endif
2880 if( !nosplash ){
2881 char *hh ;
2882 AFNI_splashup() ; eltime = COX_clock_time() ;
2883 hh = getenv("AFNI_SPLASHTIME") ;
2884 if( hh != NULL ){
2885 max_splash = strtod(hh,NULL) ;
2886 if( max_splash > 9.0 ) max_splash = 9.0 ;
2887 }
2888 }
2889 }
2890 break ;
2891
2892 /*** For the Mac users! ***/
2893
2894 case 1:
2895 #if 0
2896 AFNI_speak("[[volm 0.65; inpt PHON; rate -10; pbas +5]]1AEf=nnnIY",0) ; /* fall thru */
2897 #endif
2898
2899 #if 1
2900 if( check_string("-com",MAIN_argc,MAIN_argv) == 0 &&
2901 GLOBAL_library.local_display &&
2902 GLOBAL_library.have_sox &&
2903 AFNI_yesenv("AFNI_STARTUP_SOUND") ) AFNI_startup_sound(1) ;
2904 #endif
2905
2906 case 2:
2907 case 3:
2908 case 4:
2909 case 5:
2910 case 6:
2911 case 7:
2912 case 8:
2913 case 9:
2914 case 10:
2915 STATUS("sleep call") ;
2916 if( !nosplash) AFNI_sleep(1) ; /* burn some time to let splash windo popup */
2917 break ;
2918
2919 /*============================================================================
2920 Next, create the first AFNI controller window.
2921 ============================================================================*/
2922
2923 case 11:{
2924
2925 int do_images ; /* 19 Oct 1999 */
2926
2927 STATUS("call 11") ;
2928
2929 REPORT_PROGRESS(". Widgets") ;
2930
2931 MCW_enable_help() ;
2932
2933 do_images = GLOBAL_argopt.read_images ;
2934
2935 MAIN_im3d = new_AFNI_controller( MAIN_shell , MAIN_dc ,
2936 do_images ? AFNI_IMAGES_VIEW
2937 : AFNI_3DDATA_VIEW ) ;
2938
2939 GLOBAL_library.controllers[0] = MAIN_im3d ;
2940
2941 REPORT_PROGRESS(".") ;
2942
2943 /* Always turn off Drag-n-Drop (courtesy the Motif FAQ) */
2944
2945 XtVaSetValues( XmGetXmDisplay(XtDisplay(MAIN_im3d->vwid->top_shell)) ,
2946 XmNdragInitiatorProtocolStyle , XmDRAG_NONE ,
2947 XmNdragReceiverProtocolStyle , XmDRAG_NONE ,
2948 NULL ) ;
2949 }
2950 break ;
2951
2952 /*============================================================================
2953 Next, read the input files -- may take a while --
2954 which is one reason why we need a splash screen (the other is it's fun)
2955 ============================================================================*/
2956
2957 case 12:{
2958
2959 STATUS("call 12") ;
2960
2961 REPORT_PROGRESS(". Input files:") ;
2962
2963 AFNI_read_inputs( MAIN_argc , MAIN_argv ) ;
2964
2965 if( GLOBAL_library.have_dummy_dataset &&
2966 MAIN_im3d->type == AFNI_3DDATA_VIEW ){
2967
2968 XtSetSensitive( MAIN_im3d->vwid->prog->clone_pb , False ) ;
2969 MAIN_im3d->dummied = 1 ; /* 27 Jan 2004 */
2970 MCW_set_widget_bg( MAIN_im3d->vwid->view->sess_lab ,
2971 MCW_hotcolor(MAIN_im3d->vwid->view->sess_lab) , 0 ) ;
2972 }
2973 }
2974 break ;
2975
2976 /*============================================================================
2977 Next, setup the plugins, and things like that ...
2978 ============================================================================*/
2979
2980 case 13:{
2981
2982 STATUS("call 13") ;
2983
2984 /* registered transformation functions, etc. */
2985
2986 GLOBAL_library.registered_0D.num = 0 ; /* initialize registry */
2987 GLOBAL_library.registered_1D.num = 0 ; /* initialize registry */
2988 GLOBAL_library.registered_2D.num = 0 ; /* initialize registry */
2989
2990 GLOBAL_library.registered_fim.num = 0 ; /* 30 Jan 2000 */
2991
2992 GLOBAL_library.registered_slice_proj.num = 0 ; /* 31 Jan 2002 */
2993
2994 /* these functions are now in afni_transforms.c [01 Feb 2002] */
2995
2996 AFNI_register_0D_function( "Log10" , log10_func ) ;
2997 AFNI_register_0D_function( "SSqrt" , ssqrt_func ) ;
2998 AFNI_register_0D_function( "Abs" , absval_func ) ; /* 20 Oct 2020 */
2999
3000 AFNI_register_1D_function( "Median3" , median3_func) ;
3001 #if 0
3002 AFNI_register_1D_function( "OSfilt3" , osfilt3_func) ;
3003 #endif
3004 AFNI_register_1D_function( "AdptMean9" , adpt_wt_mn9 ) ; /* 04 Sep 2009 */
3005 AFNI_register_1D_function( "AdptMean19", adpt_wt_mn19 ); /* 29 Sep 2016 */
3006
3007 { int nad = (int)AFNI_numenv("AFNI_AdptMeanWidth1D") ; /* 30 Sep 2016 */
3008 char lab[32] ; /* user specified width */
3009 if( nad > 3 && nad != 9 && nad != 19 && nad < 100 ){
3010 if( nad%2 == 0 ){ nad++; INFO_message("increased AFNI_AdptMeanWidth1D to %d",nad); }
3011 sprintf(lab,"AdptMean%d",nad) ;
3012 AFNI_register_1D_function( lab , adpt_wt_mnXX ) ;
3013 adpt_wt_mnXX(nad,0.0,0.0,NULL) ;
3014 }
3015 }
3016
3017 AFNI_register_1D_function( "Despike9" , despike9_func); /* 08 Oct 2010 */
3018 AFNI_register_1D_function( "Despike25" , DES_despike25); /* 18 May 2018 */
3019 AFNI_register_1D_function( "HRF decon" , hrfdecon_func); /* 29 Oct 2010 */
3020 AFNI_register_1D_function( "|FFT()|" , absfft_func ) ;
3021 #if 0
3022 AFNI_register_1D_function( "ZeroToOne" , ztone_func ) ; /* 02 Sep 2009 */
3023 AFNI_register_1D_function( "Normlz_L1" , L1normalize_func ) ; /* 03 Sep 2009 */
3024 AFNI_register_1D_function( "Normlz_L2" , L2normalize_func ) ; /* 03 Sep 2009 */
3025 #endif
3026
3027 F1D_null() ; /* should be last 1D func - 20 Oct 2020 */
3028
3029 AFNI_register_2D_function( "Median9" , median9_box_func ) ;
3030 AFNI_register_2D_function( "Winsor9" , winsor9_box_func ) ;
3031 AFNI_register_2D_function( "OSfilt9" , osfilt9_box_func ) ;
3032
3033 AFNI_register_2D_function( "Median21" , median21_box_func );
3034 AFNI_register_2D_function( "Winsor21" , winsor21_box_func );
3035 AFNI_register_2D_function( "AdptMean21", adapt_mean_21_box_func ); /* 04 Sep 2009 */
3036
3037 AFNI_register_2D_function( "abs[FFT2D]" , fft2D_absfunc );
3038 AFNI_register_2D_function( "arg[FFT2D]" , fft2D_phasefunc );
3039 AFNI_register_2D_function( "Sharpness" , sharpness2D_func); /* 28 Oct 2014 */
3040
3041 F2D_null() ; /* should be last 2D func - 20 Oct 2020 */
3042
3043 /* 01 Feb 2000: see afni_fimfunc.c */
3044
3045 AFNI_register_fimfunc("Spearman CC",1,(generic_func *)spearman_fimfunc,NULL);
3046 AFNI_register_fimfunc("Quadrant CC",1,(generic_func *)quadrant_fimfunc,NULL);
3047
3048 /* 31 Jan 2002 */
3049
3050 AFNI_register_slice_proj( "Minimum" , min_proj ) ;
3051 AFNI_register_slice_proj( "Maximum" , max_proj ) ;
3052 AFNI_register_slice_proj( "Mean" , mean_proj ) ;
3053
3054 AFNI_register_slice_proj( "Median" , qmed_float ) ; /* cs_qmed.c */
3055 AFNI_register_slice_proj( "OSfilt" , osfilt_proj ) ; /* 07 Dec 2007 */
3056 AFNI_register_slice_proj( "Extreme" , extreme_proj ) ; /* 02 Feb 2002 */
3057 AFNI_register_slice_proj( "MAD" , mad_proj ) ; /* 07 Dec 2007 */
3058
3059 AFNI_register_slice_proj( "AdptMean", adaptive_weighted_mean ) ; /* 04 Sep 2009 */
3060
3061 #ifdef HUBERIZE
3062 AFNI_register_1D_funcstr( "Huber Fit" , huber_func ) ;
3063 #endif
3064
3065 /** find and load the plugins at last! **/
3066
3067 #ifdef ALLOW_PLUGINS
3068 if( MAIN_im3d->type == AFNI_3DDATA_VIEW ){
3069 int nplug = 0 ;
3070 char str[1024] ;
3071
3072 if( ! GLOBAL_argopt.noplugins ){
3073 STATUS("initialize plugins") ;
3074 GLOBAL_library.plugins = PLUG_get_many_plugins( MAIN_argv[0] ) ;
3075 AFNI_plugin_button( MAIN_im3d ) ;
3076 }
3077
3078 if( GLOBAL_library.plugins != NULL ) nplug = GLOBAL_library.plugins->num ;
3079 sprintf(str,"\n Plugins = %d libraries read",nplug) ;
3080 REPORT_PROGRESS(str) ;
3081 if( nplug == 0 && ! GLOBAL_argopt.noplugins ) /* 18 May 2005 */
3082 REPORT_PROGRESS(
3083 "\n ** Your Unix path must include the AFNI binary directory"
3084 "\n ** OR you must setenv AFNI_PLUGINPATH to that directory!");
3085
3086 /** and plugouts! **/
3087
3088 if( !GLOBAL_argopt.noplugouts ){ /* June 1997 */
3089 AFNI_init_plugouts() ;
3090 if( MAIN_im3d->vwid->dmode->misc_plugout_pb != NULL ) /* 07 Nov 2001 */
3091 XtSetSensitive(MAIN_im3d->vwid->dmode->misc_plugout_pb,False) ;
3092 REPORT_PROGRESS("\n Plugouts = listening for connections") ;
3093 }
3094 }
3095 #endif
3096
3097 TT_setup_popup_func( AFNI_popup_message ) ; /* 26 May 2006 */
3098
3099 /* 04/06/2020 discoraj */
3100 if( GLOBAL_argopt.all_dsets_startup ){
3101 ii = AFNI_find_session( "All_Datasets") ;
3102 if( ii >= 0 ) MAIN_im3d->vinfo->sess_num = ii ;
3103 }
3104 }
3105 break ;
3106
3107 /*============================================================================
3108 Next, do the initial setup on entering the initial view.
3109 ============================================================================*/
3110
3111 case 14:{
3112
3113 STATUS("call 14") ;
3114
3115 OPEN_CONTROLLER( MAIN_im3d ) ;
3116
3117 if( GLOBAL_argopt.only_images ){ /* 24 Feb 2017 */
3118 AV_assign_ival( MAIN_im3d->vwid->imag->crosshair_av,0) ;
3119 MAIN_im3d->vinfo->crosshair_visible = False ;
3120 #if 0
3121 GLOBAL_argopt.left_is_left = 0 ;
3122 putenv("AFNI_LEFT_IS_LEFT=NO" ) ;
3123 #endif
3124 }
3125 if( AFNI_yesenv("AFNI_CROSSHAIRS_OFF") )
3126 MAIN_im3d->vinfo->crosshair_visible = False ;
3127
3128 AFNI_initialize_controller( MAIN_im3d ) ; /* decide what to see */
3129 AFNI_initialize_view( NULL, MAIN_im3d ) ; /* set up to see it */
3130
3131 /*--- Other small and quick startup stuff before AFNI can go ---*/
3132
3133 STATUS("initialize help") ;
3134
3135 MCW_help_CB( MAIN_im3d->vwid->top_shell,NULL,NULL ); /* initialize help */
3136
3137 #if 0
3138 { char str[64] ;
3139 sprintf(str,"\n -orient = %s", GLOBAL_library.cord.orcode ) ;
3140 REPORT_PROGRESS(str) ;
3141 }
3142 #endif
3143
3144 /* initialize hints */
3145
3146 STATUS("initialize hints") ;
3147
3148 GLOBAL_library.hints_on = !AFNI_noenv("AFNI_HINTS") ;
3149 if( !GLOBAL_library.hints_on ) MCW_hint_toggle() ;
3150
3151 if( MAIN_im3d->vwid->dmode->misc_hints_pb != NULL )
3152 MCW_set_bbox( MAIN_im3d->vwid->dmode->misc_hints_bbox ,
3153 GLOBAL_library.hints_on ) ;
3154
3155 /* Feb 1998: setup write compression from environment */
3156 /* (read de-compression always works) */
3157
3158 STATUS("initialize compression mode (if any)") ;
3159
3160 ii = THD_enviro_write_compression() ;
3161 if( ii >= 0 && ii <= COMPRESS_LASTCODE ){
3162 char str[256] ;
3163 sprintf(str,"\n write compress= %s", COMPRESS_enviro[ii]) ;
3164 REPORT_PROGRESS(str) ;
3165 }
3166
3167 if( ALLOW_realtime > 0 )
3168 REPORT_PROGRESS("\nRT: AFNI realtime plugin is active; cf. README.realtime document") ;
3169
3170 /* 23 Sep 2000: this function will be called 0.123 seconds
3171 from now to initialize the window layouts, if any */
3172
3173 if( GLOBAL_argopt.layout_fname != NULL &&
3174 MAIN_im3d->type == AFNI_3DDATA_VIEW ){
3175
3176 STATUS("start user's layout timer") ;
3177
3178 (void) XtAppAddTimeOut( MAIN_app , 123 ,
3179 AFNI_startup_layout_CB , GLOBAL_argopt.layout_fname ) ;
3180
3181 } else if (MAIN_im3d->type == AFNI_3DDATA_VIEW){ /* ZSS Dec 02 2010. */
3182
3183 STATUS("start default layout timer") ;
3184
3185 (void) XtAppAddTimeOut( MAIN_app , 123 ,
3186 AFNI_startup_layout_CB ,
3187 "GIMME_SOMETHING" ) ;
3188 }
3189
3190 /* 21 Jan 2003: this function will be called 0.246 seconds
3191 from now to run the startup script commands, if any */
3192
3193 if( GLOBAL_argopt.script_fname != NULL &&
3194 MAIN_im3d->type == AFNI_3DDATA_VIEW ){
3195
3196 STATUS("start script timeout") ;
3197
3198 (void) XtAppAddTimeOut( MAIN_app , 246 ,
3199 AFNI_startup_script_CB , GLOBAL_argopt.script_fname ) ;
3200 }
3201
3202 if( MAIN_im3d->vwid->func->do_setup ){
3203 int ii = (int)AFNI_numenv("AFNI_THRESH_INIT_EXPON") ;
3204 if( ii > 0 && ii < THR_top_expon ) AFNI_set_thresh_itop(MAIN_im3d,ii) ;
3205 MAIN_im3d->vwid->func->do_setup = 0 ;
3206 }
3207
3208 /* this function will be called 1.666 seconds from now to finalize
3209 anything else that needs fixing up once AFNI is fully started */
3210
3211 STATUS("start startup timeout") ;
3212
3213 PICTURE_ON(MAIN_im3d) ;
3214 (void) XtAppAddTimeOut( MAIN_app, 1666, AFNI_startup_timeout_CB, MAIN_im3d ) ;
3215
3216 (void) TRUST_host(NULL) ; /* 21 Feb 2001: initialize trust mechanism */
3217
3218 /* see if there is an initial FIM ideal timeseries */
3219
3220 { char *eee = getenv( "AFNI_FIM_IDEAL" ) ;
3221 static MRI_IMAGE *tsim ;
3222 tsim = mri_read_1D( eee ) ;
3223 if( tsim != NULL ){
3224 float *far = MRI_FLOAT_PTR(tsim) ; int ii ; char *tname ;
3225 for( ii=0 ; ii < tsim->nvox ; ii++ )
3226 if( fabs(far[ii]) >= 33333.0 ) far[ii] = WAY_BIG ;
3227 tname = THD_trailname(eee,1) ;
3228 mri_add_name( tname , tsim ) ;
3229 AFNI_fimmer_setref( MAIN_im3d , tsim ) ;
3230 }
3231 }
3232
3233 /* 05 Mar 2007: auto-threshold? */
3234
3235 if( AFNI_yesenv("AFNI_THRESH_AUTO") ){
3236 float new_thresh = AFNI_get_autothresh(MAIN_im3d) ;
3237 if( new_thresh > 0.0f ) AFNI_set_threshold(MAIN_im3d,new_thresh) ;
3238 }
3239
3240 PUTENV("AFNI_DECONFLICT","OVERWRITE") ; /* 24 Sep 2007 */
3241 putenv("AFNI_IS_RUNNING=YES") ; /* 08 Jun 2007 */
3242
3243 memplot_topshell_setsaver( ".jpg" , memplot_to_jpg ) ; /* 05 Dec 2007 */
3244 memplot_topshell_setsaver( ".png" , memplot_to_png ) ;
3245
3246 REPORT_PROGRESS("\n") ;
3247
3248 { long long lfs = AFNI_logfilesize(); /* 17 Oct 2007 */
3249 if( lfs > 10000000 ){
3250 char msg[1024] ;
3251 sprintf(msg,"\n++ WARNING: ~/.afni.log is now %s (%s) bytes long!"
3252 "\n + (Is that you, Kevin?)\n" ,
3253 commaized_integer_string(lfs) ,
3254 approximate_number_string((double)lfs) ) ;
3255 REPORT_PROGRESS(msg) ;
3256 }
3257 }
3258
3259 if( AFNI_yesenv("AFNI_ENFORCE_ASPECT") ){ /* 10 May 2018 */
3260 REPORT_PROGRESS(
3261 "\n++ NOTICE: AFNI_ENFORCE_ASPECT no longer has any effect!\n") ;
3262 }
3263
3264 /* X11_SET_NEW_PLOT ; */
3265
3266 STATUS("exit call 14") ;
3267
3268 }
3269 break ; /* end of 14th entry case */
3270
3271 /*============================================================================*/
3272 #if 0
3273 case 15:{ /* not used at present, but ready to be added when needed */
3274 STATUS("call 15") ;
3275 }
3276 break ;
3277 #endif
3278 }
3279
3280 MAIN_calls++ ; RETURN(False) ;
3281 }
3282
3283 /*-------------------------------------------------------------------------*/
3284
random_goodbye(void)3285 static char * random_goodbye(void)
3286 {
3287 static char *bye[] = { "[[volm 0.64]] Farewell",
3288 "[[volm 0.64]] Goodbye" ,
3289 "[[volm 0.64]] Until next time" } ;
3290 int nn = sizeof(bye)/sizeof(char *) ;
3291 return bye[ lrand48() % nn ] ;
3292 }
3293
3294 /*-------------------------------------------------------------------------
3295 Callback for the quit button. If called with the widget == NULL,
3296 resets the button to the lowercase state.
3297 ---------------------------------------------------------------------------*/
3298
AFNI_quit_CB(Widget wcall,XtPointer cd,XtPointer cbs)3299 void AFNI_quit_CB( Widget wcall , XtPointer cd , XtPointer cbs )
3300 {
3301 Three_D_View *im3d = (Three_D_View *)cd ;
3302 XmPushButtonCallbackStruct *pbcbs = (XmPushButtonCallbackStruct *)cbs ;
3303
3304 ENTRY("AFNI_quit_CB") ;
3305
3306 if( cd == NULL ) AFexit(0) ; /* 27 Jul 2015 */
3307
3308 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3309
3310 /* NULL widget --> reset button to lowercase */
3311
3312 if( wcall == NULL ){
3313 if( im3d->vwid->prog->quit_first == False ){
3314 MCW_set_widget_label( im3d->vwid->prog->quit_pb , "done " ) ;
3315 im3d->vwid->prog->quit_first = True ;
3316 if( im3d->vwid->picture != NULL && !GLOBAL_argopt.keep_logo )
3317 PICTURE_OFF( im3d ) ;
3318 }
3319 EXRETURN ;
3320 }
3321
3322 /* Press of button with Shift or Control key pressed --> Death Now */
3323
3324 if( pbcbs != NULL &&
3325 pbcbs->event != NULL &&
3326 pbcbs->event->type == ButtonRelease &&
3327 ((XButtonEvent *)(pbcbs->event))->state & /* note single & here! */
3328 (ShiftMask|ControlMask|Button2Mask|Button3Mask) ){
3329
3330 XtCloseDisplay( XtDisplay(im3d->vwid->top_shell) ) ;
3331 #if 0
3332 AFNI_speak(random_goodbye(),0) ;
3333 #endif
3334 AFexit(0) ;
3335 }
3336
3337 /* First press --> just change button label */
3338
3339 if( wcall == im3d->vwid->prog->quit_pb && im3d->vwid->prog->quit_first ){
3340 MCW_set_widget_label( im3d->vwid->prog->quit_pb , "DONE " ) ;
3341 im3d->vwid->prog->quit_first = False ;
3342 if( im3d->vwid->picture != NULL ) PICTURE_ON( im3d ) ;
3343
3344 /* if not re-pressed in 5 seconds, will reset to lowercase */
3345
3346 (void) XtAppAddTimeOut(
3347 XtWidgetToApplicationContext(im3d->vwid->prog->quit_pb) ,
3348 5000 , AFNI_quit_timeout_CB , im3d ) ;
3349
3350 EXRETURN ;
3351 }
3352
3353 /* close window callback OR button already uppercase --> close window */
3354
3355 /* if no controller windows will be left, exit the program */
3356
3357 if( AFNI_count_controllers() <= 1 ){
3358 XtCloseDisplay( XtDisplay(im3d->vwid->top_shell) ) ;
3359 AFNI_speak(random_goodbye(),0) ;
3360 STATUS("calling exit(0) -- farewell cruel world!") ;
3361 AFexit(0) ;
3362
3363 } else { /* otherwise, patch up the other windows and continue */
3364
3365 CLOSE_CONTROLLER(im3d) ; /* close window */
3366 AFNI_controller_clonify() ; /* let other controllers know */
3367 }
3368 EXRETURN ;
3369 }
3370
3371 /*----------------------------------------------------------------------
3372 Timeout routine to change 'DONE' button label back to 'done'
3373 after 5 seconds have passed.
3374 ------------------------------------------------------------------------*/
3375
AFNI_quit_timeout_CB(XtPointer client_data,XtIntervalId * id)3376 void AFNI_quit_timeout_CB( XtPointer client_data , XtIntervalId *id )
3377 {
3378 Three_D_View *im3d = (Three_D_View *)client_data ;
3379 ENTRY("AFNI_quit_timeout_CB") ;
3380 RESET_AFNI_QUIT(im3d) ;
3381 EXRETURN ;
3382 }
3383
3384 /*----------------------------------------------------------------------*/
3385
AFNI_vcheck_flasher(Three_D_View * im3d)3386 void AFNI_vcheck_flasher( Three_D_View *im3d )
3387 {
3388 int pp ;
3389 if( im3d == NULL || vers_pixmap == XmUNSPECIFIED_PIXMAP ) return ;
3390
3391 for( pp=0 ; pp < 19 ; pp++ ){
3392 PICTURE_SET(im3d,vers_pixmap) ;
3393 XmUpdateDisplay(im3d->vwid->top_shell); AFNI_sleep(166);
3394 PICTURE_OFF(im3d) ;
3395 XmUpdateDisplay(im3d->vwid->top_shell); AFNI_sleep(166);
3396 }
3397 logo_pixmap = vers_pixmap ; /* replace logo with version warning */
3398 return ;
3399 }
3400
3401 /*----------------------------------------------------------------------*/
3402 /* the tips are stored in afni_startup_tips.h */
3403
AFNI_print_startup_tip(int qq)3404 void AFNI_print_startup_tip(int qq) /* 03 Jan 2018 */
3405 {
3406 int nn = (lrand48()>>3) % NTIP ;
3407
3408 if( qq >= 0 && qq < NTIP ) nn = qq ;
3409
3410 if( tip[nn] != NULL )
3411 fprintf( stdout , "\n\n"
3412 "------------------------- AFNI Startup Tip (%d/%d)----------------------------\n"
3413 "%s\n"
3414 "-------------------------------------------------------------------------------\n" ,
3415 nn+1 , NTIP , tip[nn] ) ;
3416 return ;
3417 }
3418
3419 /*-------------------------------------------------------------------------
3420 This function is called periodically to do unimportant stuff [Oct 2019]
3421 ---------------------------------------------------------------------------*/
3422
AFNI_periodic_timeout_CB(XtPointer client_data,XtIntervalId * id)3423 void AFNI_periodic_timeout_CB( XtPointer client_data , XtIntervalId *id )
3424 {
3425 int qq ; Three_D_View *qq3d ;
3426
3427 ENTRY("AFNI_periodic_timeout_CB") ;
3428
3429 /* turn off the 'working' pictures and reset to normal cursor */
3430
3431 SHOW_AFNI_READY ;
3432
3433 /* restart timer */
3434
3435 (void) XtAppAddTimeOut( MAIN_app, 9999, AFNI_periodic_timeout_CB, MAIN_im3d ) ;
3436 EXRETURN ;
3437 }
3438
3439 /*----------------------------------------------------------------------
3440 This function is called about 1 s after AFNI startup is completed.
3441 It's original purpose was to make sure that the help window was
3442 popped down - the help initializing routine does this, too, but
3443 it didn't work properly on the old Tektronix X-terminal at MCW.
3444 Thus, the timeout - waiting a little made things work OK.
3445 ------------------------------------------------------------------------*/
3446
AFNI_startup_timeout_CB(XtPointer client_data,XtIntervalId * id)3447 void AFNI_startup_timeout_CB( XtPointer client_data , XtIntervalId *id )
3448 {
3449 Three_D_View *im3d = (Three_D_View *)client_data ;
3450 int vv ;
3451
3452 ENTRY("AFNI_startup_timeout_CB") ;
3453
3454 /*--- make sure help window is popped down ---*/
3455
3456 #if 0
3457 MCW_help_CB( MAIN_im3d->vwid->top_shell,NULL,NULL ); /* initialize help */
3458 #endif
3459
3460 MCW_help_CB(NULL,NULL,NULL) ;
3461
3462 /*--- test geometry of main window [08 Aug 2016]
3463 if it is negative territory, move it back to positive land;
3464 this is to (hopefull) fix a peculiarity in XQuartz on El Capitan ---*/
3465
3466 { Position xroot,yroot ;
3467 WAIT_for_window( MAIN_im3d->vwid->top_shell ) ;
3468 XtTranslateCoords( MAIN_im3d->vwid->top_shell , 0,0, &xroot , &yroot ) ;
3469 #if 0
3470 INFO_message("AFNI controller xroot=%d yroot=%d",(int)xroot,(int)yroot) ;
3471 #endif
3472 if( xroot < 0 || yroot < 0 ){
3473 INFO_message("AFNI was off screen at x=%d y=%d -- repositioning" ,
3474 (int)xroot , (int)yroot ) ;
3475 XtVaSetValues( MAIN_im3d->vwid->top_shell, XmNx,20, XmNy,20, NULL ) ;
3476 REFRESH ;
3477 }
3478 }
3479
3480 /*--- tell user if any mixed-type datasets transpired [06 Sep 2006] ---*/
3481
3482 AFNI_inconstancy_check( im3d , NULL ) ;
3483
3484 /*--- NIML listening on [moved here 17 Mar 2002] ---*/
3485
3486 if( MAIN_im3d->type == AFNI_3DDATA_VIEW && GLOBAL_argopt.yes_niml ){
3487 AFNI_init_niml() ;
3488 if( MAIN_im3d->vwid->dmode->misc_niml_pb != NULL )
3489 XtSetSensitive(MAIN_im3d->vwid->dmode->misc_niml_pb,False) ;
3490 } else if( 0 && get_user_np() > 0 ){ /* 10 Dec 2002 -- ZSS June 2011 */
3491 /* No need to warn anymore, -np can be set by environment
3492 variables too. */
3493 fprintf(stderr,
3494 "** WARNING: -np was given, but NIML is turned off.\n") ;
3495 }
3496
3497 if( AFNI_have_niml() && AFNI_have_plugouts() ) /* 02 Feb 2007 */
3498 XtSetSensitive(MAIN_im3d->vwid->view->nimlpo_pb,False) ;
3499
3500 if( !AFNI_noenv("AFNI_STARTUP_WARNINGS") ){ /* 22 Jul 2003 */
3501
3502 #ifdef LESSTIF_VERSION /* 13 Jan 2003: If LessTif was used for this AFNI */
3503 #ifndef USING_LESSTIF /* Lesstif is good for you!
3504 Keep the warning if the proper
3505 -DUSING_LESSTIF was not used
3506 when compiling */
3507 (void) MCW_popup_message( MAIN_im3d->vwid->picture ,
3508 " \n"
3509 "*** WARNING: ***\n"
3510 "*** This copy of AFNI was ***\n"
3511 "*** built using the LessTif ***\n"
3512 "*** library, but without the***\n"
3513 "*** -DUSING_LESSTIF flag at ***\n"
3514 "*** compile time. ***\n"
3515 "*** You will find problems; ***\n"
3516 "*** AFNI works with either ***\n"
3517 "*** Motif or OpenMotif, or ***\n"
3518 "*** Lesstif with the proper ***\n"
3519 "*** compiler flag. ***\n" ,
3520 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3521 #endif
3522 #endif
3523
3524 #ifdef BAD_BUTTON3_POPUPS /* 21 Jul 2003: If this is a stupid system */
3525
3526 (void) MCW_popup_message( MAIN_im3d->vwid->imag->topper,
3527 " \n"
3528 "*** WARNING: ***\n"
3529 "*** This computer system has ***\n"
3530 "*** a bug with Button-3 popup ***\n"
3531 "*** menus -- to use a button ***\n"
3532 "*** on such a menu, you have ***\n"
3533 "*** to keep Button-3 pressed ***\n"
3534 "*** down and then click the ***\n"
3535 "*** menu button with Button-1 ***\n"
3536 "*** at the same time. ***\n" ,
3537 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3538 #endif
3539 }
3540
3541 if( recursed_ondot ) /* 18 Feb 2007 */
3542 (void) MCW_popup_message( MAIN_im3d->vwid->picture ,
3543 " \n"
3544 "++ NOTICE: ++\n"
3545 "++ No data was found in './' directory, ++\n"
3546 "++ so its subdirectories were searched ++\n"
3547 "++ for dataset files. ++\n " ,
3548 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3549 else if( !ALLOW_realtime &&
3550 GLOBAL_library.have_dummy_dataset &&
3551 MAIN_im3d->type == AFNI_3DDATA_VIEW ){
3552 int horz = MAIN_im3d->vwid->view->session_horz ; /* 29 Apr 2010 */
3553 char hstr[1024] ;
3554 sprintf( hstr ,
3555 "***** NOTICE *** UWAGA *** AVVISO *** WARNUNG *** RABHADH *****\n"
3556 " \n"
3557 "++ No valid datasets were found. A dummy dataset has been ++\n"
3558 "++ created for your viewing pleasure :-) To read in a real ++\n"
3559 "%s"
3560 "\n"
3561 "** Or, quit AFNI and restart it with the name of a dataset **\n"
3562 "** directory on the command line, as in **\n"
3563 "\n"
3564 " afni name_of_data_directory \n"
3565 " \n"
3566 "++ For general AFNI program help, see the Web page ++\n"
3567 "\n"
3568 " https://afni.nimh.nih.gov/pub/dist/doc/program_help/index.html \n"
3569 "%s"
3570 "\n"
3571 "++ [To close this message window, left-click inside of it.] ++\n"
3572 ,
3573 (horz)
3574 ? "++ dataset directory, use the 'Read' button near 'DataDir'. ++\n"
3575 : "++ dataset directory, use the 'Read New Directory' button, ++\n"
3576 "++ located below the 'Data Directory' label. ++\n" ,
3577 (GLOBAL_browser == NULL)
3578 ? " "
3579 : "\n"
3580 "++ which you can open by right-clicking on the logo space to ++\n"
3581 "++ the right of the 'done' button, and from the resulting ++\n"
3582 "++ popup menu, choose the 'Web Browser: Help' item. ++\n"
3583 ) ;
3584 (void)MCW_popup_message( MAIN_im3d->vwid->prog->quit_pb,hstr,MCW_USER_KILL ) ;
3585 MCW_flash_widget_list( 9 , MAIN_im3d->vwid->view->sess_lab ,
3586 MAIN_im3d->vwid->view->choose_sess_pb ,
3587 MAIN_im3d->vwid->view->read_sess_pb ,
3588 NULL ) ; /* 12 Feb 2010 */
3589 }
3590
3591 /*--- 05 May 2009: make sure the Cluster widgets show up properly ---*/
3592
3593 AFNI_vedit_CB( im3d->vwid->func->options_vedit_av , im3d ) ;
3594
3595 /* 21 Nov 2002: check the AFNI version */
3596
3597 /* changed if 0 to if 1 to revert to version_check() 30 Dec 2015 */
3598 #if 1
3599 /* do nothing if AFNI_start_version_check() says inactive */
3600 vv = AFNI_version_check() ;
3601
3602 if( vv && vers_pixmap != XmUNSPECIFIED_PIXMAP ) /* 08 Aug 2005 */
3603 AFNI_vcheck_flasher(im3d) ;
3604
3605 #else
3606
3607 vv = AFNI_compile_date_check() ; /* 17 Jun 2014 */
3608 if( vv >= 93 ){
3609 /* fixed %31 to /31 28 Dec 2015 [rickr] */
3610 WARNING_message(
3611 "Your copy of AFNI is over %d months old -- please update it (if practicable)." ,
3612 vv / 31 ) ;
3613 if( im3d->vwid->tips_pb != NULL ){
3614 char msg[1024] ;
3615 sprintf( msg, " \n"
3616 " Your copy of AFNI is over %d months old.\n"
3617 " Please update it (if practicable).\n " , vv / 31 ) ;
3618 (void) MCW_popup_message( im3d->vwid->tips_pb , msg ,
3619 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3620 }
3621 } else if( vv < 0 ){
3622 INFO_message("You are %d days AHEAD of the official AFNI compile date -- impressive!",-vv) ;
3623 }
3624 #endif
3625
3626 /*--- finish up getting AFNI ready to be presented to the world ---*/
3627
3628 if( im3d->vwid->tips_pb != NULL && lrand48()%2==0 )
3629 MCW_flash_widget(1,im3d->vwid->tips_pb) ;
3630
3631 SHOW_AFNI_READY ;
3632 RESET_AFNI_QUIT(im3d) ;
3633 PICTURE_OFF(im3d) ;
3634
3635 if( im3d->vwid->tips_pb != NULL && lrand48()%2==0 )
3636 MCW_flash_widget(1,im3d->vwid->tips_pb) ;
3637
3638 /*--- 29 Jul 2005: run any driver commands from the command line ---*/
3639
3640 for( vv=0 ; vv < COM_num ; vv++ ){
3641 AFNI_driver(COM_com[vv]) ; free(COM_com[vv]) ;
3642 }
3643
3644 /*--- 29 Nov 2005: Message Of The Day -- did it change? ---*/
3645
3646 if( GLOBAL_motd != NULL && !AFNI_noenv("AFNI_MOTD_CHECK") )
3647 AFNI_display_motd( im3d->vwid->imag->topper ) ;
3648
3649 /*--- 09 Nov 2005: start checking periodically for updated datasets ---*/
3650
3651 if( AFNI_yesenv("AFNI_AUTO_RESCAN") )
3652 (void) XtAppAddTimeOut( MAIN_app,29999, AFNI_rescan_timeout_CB,&MAIN_app );
3653
3654 AFNI_coord_filer_setup(im3d) ; /* 07 May 2010 */
3655
3656 /*--- 12 May 2010: As the last printout, say when this version was created ---*/
3657
3658 fprintf(stderr,"\n++ NOTE: This version of AFNI was built " __DATE__ " ++\n" ) ;
3659
3660 if( MAIN_im3d->type == AFNI_3DDATA_VIEW &&
3661 !AFNI_yesenv("AFNI_ENABLE_MARKERS") )
3662 fprintf(stderr,"++ NOTE: 'Define Markers' is hidden: right-click 'DataDir' to see it\n") ;
3663
3664 if( MAIN_im3d->type == AFNI_3DDATA_VIEW && first_plugin_check < 0 && !GLOBAL_argopt.noplugins )
3665 fprintf(stderr,"++ NOTE: Use '-seehidden' option to see which plugins are hidden\n") ;
3666
3667 #if 0
3668 /**--- Apr 2013: delete this message in a few months ---**/
3669
3670 if( __DATE__[10] == '3' && (__DATE__[0] == 'A' || __DATE__[0] == 'M') )
3671 fprintf(stderr,
3672 "++ NOTE: Graph viewer threshold 'fading' is now on by default. To turn it off,\n"
3673 " press the 'F' key in a graph viewer window, or set environment variable\n"
3674 " AFNI_GRAPH_FADE to NO. -- [Apr 2013]\n"
3675 "++ NOTE: The AFNI GUI now detaches itself from the terminal at startup, so that\n"
3676 " it is no longer necessary or useful to start the program with the '&'\n"
3677 " key at the end of the command line. To disable this feature, set\n"
3678 " environment variable AFNI_DETACH to NO. To kill all running copies\n"
3679 " of AFNI, you could use the Unix command 'killall afni'. -- [Apr 2013]\n"
3680 ) ;
3681 #endif
3682
3683 if( AFNI_check_environ_done() == 0 )
3684 fprintf(stderr,
3685 "++ NOTE: you may want to consider creating a '.afnirc' file in your home\n"
3686 " directory, to control AFNI's setup. For more details, see\n"
3687 " https://afni.nimh.nih.gov/pub/dist/doc/program_help/README.environment.html\n") ;
3688
3689
3690 /*--- splash window down -- moved here 29 May 2013 ---*/
3691
3692 #ifndef NO_FRIVOLITIES
3693 if( lrand48()%17 == 3 )
3694 INFO_message("Want your picture in the AFNI splash screen? Email us a square JPEG!") ;
3695 #endif
3696
3697 AFNI_splashdown(); STATUS("splashed down");
3698
3699 /* Startup tip message [03 Jan 2018] */
3700
3701 if( !ALLOW_realtime &&
3702 !AFNI_yesenv("AFNI_NEVER_SAY_GOODBYE") &&
3703 MAIN_im3d->type == AFNI_3DDATA_VIEW ) AFNI_print_startup_tip(-1) ;
3704
3705 /* this is for me, myself, and I only! */
3706
3707 { char *eee = getenv("USER") ;
3708 set_program_name("afni") ;
3709 #ifdef USE_TRACING
3710 if( eee != NULL && strcmp(eee,"rwcox") == 0 ) atexit(clock_time_atexit) ;
3711 #endif
3712 }
3713
3714 /* Start timer to repeatedly fix threshold scale sizes [05 Jun 2019] */
3715
3716 if( ! AFNI_yesenv("AFNI_DONT_FIX_SCALE_SIZE") )
3717 AFNI_fix_scale_size_timer_CB(NULL,NULL) ;
3718
3719 /*--- and AWAY WE GO (how sweet it is!) ---*/
3720
3721 MPROBE ; /* check mcw_malloc() for integrity */
3722
3723 /*--- Start period timeout [17 Oct 2019] ---*/
3724
3725 (void) XtAppAddTimeOut( MAIN_app, 9999, AFNI_periodic_timeout_CB, MAIN_im3d ) ;
3726 EXRETURN ;
3727 }
3728
3729 /*----------------------------------------------------------------------
3730 Return the underlay or overlay brick and the sub-brick index that
3731 the user had selected in the 'Underlay' and 'Overlay' menus.
3732
3733 So whether or not the user has bkgd:ULay or bkgd:OLay is irrelevant
3734 to what gets returned.
3735
3736 The returned structure is brr
3737 brr->dset will contain the dset selected as underlay if
3738 type == isqCR_getulayim
3739 and the dset selected as overlay if
3740 type == isqCR_getolayim
3741
3742 brr = br if type is set to anything other than isqCR_get[uo]ayim
3743
3744 See also Get_UO_Dset
3745 ----------------------------------------------------------------------*/
3746
Get_FD_Brick_As_Selected(FD_brick * br,int type,int * rival)3747 FD_brick *Get_FD_Brick_As_Selected(FD_brick *br, int type, int *rival)
3748 {
3749 Three_D_View *im3d = (Three_D_View *)br->parent ;
3750 FD_brick *brr=NULL ;
3751 int ival , banat , uu=im3d->vinfo->underlay_type ;
3752
3753 banat = EQUIV_DSETS(br->dset,im3d->anat_now) ;
3754 switch( type ){
3755 case isqCR_getulayim: brr = (banat) ? br : br->brother ; break ;
3756 case isqCR_getolayim: brr = (banat) ? br->brother : br ; break ;
3757 }
3758 if( brr == NULL ) brr = br ; /* I wish it was 'brr' right now -- July 2014 */
3759
3760 /*** decide which 3D brick to extract data from (ival) ***/
3761
3762 if( EQUIV_DSETS(im3d->anat_now,im3d->fim_now) ){ /* RWCox [03 Jul 2014] */
3763 if( type == isqCR_getolayim ) /* datasets are the same */
3764 ival = im3d->vinfo->fim_index ; /* so need to be careful with ival */
3765 else if( type == isqCR_getulayim || uu == UNDERLAY_ANAT )
3766 ival = im3d->vinfo->anat_index ;
3767 else
3768 ival = im3d->vinfo->fim_index ;
3769 } else { /* the old (Ziad's) way */
3770 if( EQUIV_DSETS(brr->dset,im3d->anat_now) ) /* underlay dataset */
3771 ival = im3d->vinfo->anat_index ;
3772 else if( EQUIV_DSETS(brr->dset,im3d->fim_now) ) /* overlay dataset */
3773 ival = im3d->vinfo->fim_index ;
3774 else
3775 ival = 0 ; /* shouldn't happen */
3776 }
3777
3778 if( br->deltival != 0 && DSET_NVALS(brr->dset) > 1 ){ /* 23 Feb 2011 */
3779 /* This is for allowing montage to cycle trough sub-bricks */
3780 ival += br->deltival ;
3781 ININFO_message("afni: deltival changes ival to %d",ival) ;
3782 if( ival < 0 || ival >= DSET_NVALS(brr->dset) ) RETURN( NULL ) ;
3783 }
3784
3785 if( type == isqCR_getqimage ) ival = -1; /* get empty image */
3786 else if( ival >= DSET_NVALS(brr->dset) ) ival = brr->dset->dblk->nvals-1;
3787
3788 *rival = ival;
3789 /*
3790 fprintf(stderr,"Get_FD_Brick_As_Selected:\n"
3791 " br->dset %s, brr->dset %s\n"
3792 " anat_now %s, fim_now %s\n"
3793 " banat = %d, ival = %d\n"
3794 " type %d (%s)\n",
3795 DSET_PREFIX(br->dset), DSET_PREFIX(brr->dset),
3796 DSET_PREFIX(im3d->anat_now), DSET_PREFIX(im3d->fim_now),
3797 banat, ival,
3798 type,
3799 type == isqCR_getulayim ? "getULAY" :
3800 type == isqCR_getolayim ? "getOLAY" : "Other");
3801 */
3802 return(brr);
3803 }
3804
3805 /*
3806 Return the overlay or underaly dset currently selected and set
3807 the sub-brick number.
3808
3809 Peculiar input:
3810 UOlay: 'O' --> Return the overlay
3811 'U' Return the underlay
3812 AsSet: 1 --> Return the dataset that is set by the 'Underlay'
3813 or 'Overlay' selectors.
3814 0 --> Return the 'displayed' overlay or underlay dset.
3815 This means, take into account the bkgd:ULay or bkgd:OLay
3816 setting.
3817 */
Get_UO_Dset(FD_brick * br,char UOlay,byte AsSet,int * rival)3818 THD_3dim_dataset *Get_UO_Dset(FD_brick *br, char UOlay,
3819 byte AsSet, int *rival)
3820 {
3821 Three_D_View *im3d = (Three_D_View *)br->parent ;
3822 FD_brick *brt=NULL;
3823 THD_3dim_dataset *dset=NULL;
3824
3825 /* set up with basics */
3826 if (UOlay=='O') {
3827 dset = im3d->fim_now;
3828 *rival = im3d->vinfo->fim_index;
3829 } else {
3830 dset = im3d->anat_now;
3831 *rival = im3d->vinfo->anat_index;
3832 }
3833
3834 /* now allow for things like deltival, and other stuff */
3835 if (AsSet) { /* as selected in 'Underlay' and 'Overlay' */
3836 if (!(brt = Get_FD_Brick_As_Selected(br,
3837 UOlay=='O' ? isqCR_getolayim : isqCR_getulayim, rival))) {
3838 ERROR_message("Case 1: Failed to select brick, returning defaults");
3839 return(dset);
3840 }
3841 } else { /* as displayed, works OK, not well tested for rival below */
3842 if (EQUIV_DSETS(br->dset,im3d->anat_now)) {
3843 /* vanilla */
3844 if (!(brt = Get_FD_Brick_As_Selected(br,
3845 UOlay=='O' ? isqCR_getolayim : isqCR_getulayim, rival))) {
3846 ERROR_message("Case 2: Failed to select brick, returning defaults");
3847 return(dset);
3848 }
3849 } else {
3850 /* Olay as Ulay: always return the overlay */
3851 if (!(brt = Get_FD_Brick_As_Selected(br, isqCR_getolayim, rival))) {
3852 ERROR_message("Case 3: Failed to select brick, returning defaults");
3853 return(dset);
3854 }
3855 }
3856 }
3857 if (brt) dset = brt->dset;
3858 return(dset);
3859 }
3860
3861 /*!
3862 Return 0 if FD_brick is not in montage mode.
3863 1 if Axial montage
3864 2 if Sagittal montage
3865 4 if Coronal montage
3866 */
FD_brick_montized(FD_brick * br)3867 int FD_brick_montized(FD_brick *br )
3868 {
3869 Three_D_View *im3d = (Three_D_View *)br->parent ;
3870
3871 if ( (br == im3d->b123_anat || br == im3d->b123_fim) &&
3872 (im3d->s123->mont_nx > 1|| im3d->s123->mont_ny > 1) ) {
3873 return(1); /* Axial brick and in montage */
3874 }
3875 if ( (br == im3d->b231_anat || br == im3d->b231_fim) &&
3876 (im3d->s231->mont_nx > 1|| im3d->s231->mont_ny > 1) ) {
3877 return(2); /* Sagittal brick and in montage */
3878 }
3879 if ( (br == im3d->b312_anat || br == im3d->b312_fim) &&
3880 (im3d->s312->mont_nx > 1|| im3d->s312->mont_ny > 1) ) {
3881 return(4); /* Coronal brick and in montage */
3882 }
3883 return(0);
3884 }
3885
3886 /*----------------------------------------------------------------------
3887 Fill the various possible string values used in an imseq getlabel.
3888 Return value is 0 if things are good, 1 if things are bad.
3889 ------------------------------------------------------------------------*/
3890
3891 #define LPART_SLICE_INDEX 0 /* %i% */
3892 #define LPART_SLICE_COORD 1 /* %s% */
3893 #define LPART_TIME_INDEX 2 /* %l% */
3894 #define LPART_TIME_COORD 3 /* %t% */
3895 #define NUM_LPART 4
3896
AFNI_brick_to_label_parts(int n,FD_brick * br,char ** lpart)3897 int AFNI_brick_to_label_parts( int n , FD_brick *br , char **lpart )
3898 {
3899 Three_D_View *im3d = (Three_D_View *)br->parent ;
3900 char *lab , *dd , *eee=NULL , str[256] ;
3901 THD_ivec3 iv,ivp,ivm ;
3902 THD_fvec3 fv,fvp,fvm ;
3903 float dxyz , cc ;
3904 int ii, ival;
3905 double dval;
3906 THD_3dim_dataset *dset=br->dset ;
3907 int nnn ; char *fmt ;
3908
3909 if( lpart == NULL || im3d->type != AFNI_3DDATA_VIEW ) return 1 ;
3910
3911 /* format slice index */
3912
3913 LOAD_IVEC3(iv,0,0,n) ;
3914 ivp = THD_fdind_to_3dind( br , iv ) ;
3915
3916 if( n == 0 ) LOAD_IVEC3(iv,0,0,1) ;
3917 else LOAD_IVEC3(iv,0,0,n-1) ;
3918 ivm = THD_fdind_to_3dind( br , iv ) ;
3919
3920 nnn = MAX(br->n1,br->n2) ; nnn = MAX(nnn,br->n3) ;
3921 fmt = (nnn < 10) ? "#%1d"
3922 : (nnn < 100) ? "#%02d"
3923 : (nnn < 1000) ? "#%03d"
3924 : (nnn < 10000) ? "#%04d"
3925 : (nnn < 100000)? "#%05d"
3926 : "#%06d" ;
3927 if( ivm.ijk[0] != ivp.ijk[0] ){
3928 sprintf(str,fmt,ivp.ijk[0]) ;
3929 } else if( ivm.ijk[1] != ivp.ijk[1] ){
3930 sprintf(str,fmt,ivp.ijk[1]) ;
3931 } else if( ivm.ijk[2] != ivp.ijk[2] ){
3932 sprintf(str,fmt,ivp.ijk[2]) ;
3933 } else {
3934 sprintf(str,fmt,nnn) ; /* should be impossible */
3935 }
3936 strcpy( lpart[LPART_SLICE_INDEX] , str ) ;
3937
3938 /* slice coordinate */
3939
3940 fvp = THD_3dind_to_3dmm ( dset , ivp ) ;
3941 fvp = THD_3dmm_to_dicomm( dset , fvp ) ;
3942
3943 fvm = THD_3dind_to_3dmm ( dset , ivm ) ;
3944 fvm = THD_3dmm_to_dicomm( dset , fvm ) ;
3945
3946 dxyz = MIN(br->del1,br->del2) ;
3947 dxyz = MIN(dxyz ,br->del3) ; dxyz *= 0.1f ;
3948 if( dxyz <= 1.e-4f ) dxyz = 1.e-4f ;
3949
3950 if( fabs(fvm.xyz[0]-fvp.xyz[0]) > dxyz ){ /* +=R -=L */
3951 cc = fvp.xyz[0] ;
3952 dd = ( cc >= 0.0 ) ? "L" : "R" ;
3953 } else if( fabs(fvm.xyz[1]-fvp.xyz[1]) > dxyz ){ /* +=P -=A */
3954 cc = fvp.xyz[1] ;
3955 dd = ( cc >= 0.0 ) ? "P" : "A" ;
3956 } else if( fabs(fvm.xyz[2]-fvp.xyz[2]) > dxyz ){ /* +=S -=I */
3957 cc = fvp.xyz[2] ;
3958 dd = ( cc >= 0.0 ) ? "S" : "I" ;
3959 } else {
3960 cc = 0.0f ; dd = "" ; /* should be impossible */
3961 }
3962
3963 sprintf(str,"%6.2f",fabs(cc)) ;
3964 for( ii=strlen(str)-1 ; ii > 0 && str[ii] == '0' ; ii-- ) str[ii] = '\0' ;
3965 if( str[ii] == '.' ) str[ii] = '\0' ;
3966 strcat(str, dd) ;
3967 strcpy( lpart[LPART_SLICE_COORD] , str ) ;
3968
3969 /* time index */
3970
3971 nnn = DSET_NVALS(dset) ;
3972 fmt = (nnn < 10) ? "#%1d"
3973 : (nnn < 100) ? "#%02d"
3974 : (nnn < 1000) ? "#%03d"
3975 : (nnn < 10000) ? "#%04d"
3976 : (nnn < 100000)? "#%05d"
3977 : "#%06d" ;
3978 sprintf(str,fmt,im3d->vinfo->time_index) ;
3979 strcpy( lpart[LPART_TIME_INDEX] , str ) ;
3980
3981 /* time coord */
3982
3983 cc = DSET_TIMEORIGIN(dset) + im3d->vinfo->time_index * DSET_TR(dset) ;
3984
3985 sprintf(str,"%-16.5f",cc) ; /* %- means will be left justified, not right */
3986 for( ii=strlen(str)-1 ;
3987 ii > 0 && (str[ii] == '0' || str[ii] == ' ') ; ii-- ) str[ii] = '\0' ;
3988 if( str[ii] == '.' ) str[ii] = '\0' ;
3989 strcpy( lpart[LPART_TIME_COORD] , str ) ;
3990
3991 return 0 ;
3992 }
3993
3994 /*----------------------------------------------------------------------
3995 routine to extract a plane of data from a 3D brick
3996 (used as a "get_image" routine for an MCW_imseq)
3997 ------------------------------------------------------------------------*/
3998
AFNI_brick_to_mri(int n,int type,FD_brick * br)3999 XtPointer AFNI_brick_to_mri( int n , int type , FD_brick *br )
4000 {
4001 MRI_IMAGE *im ;
4002 MCW_imseq_status *stat ;
4003 int i1,i2,jb,bb , dd1,dd2,tt1,tt2 ;
4004
4005 ENTRY("AFNI_brick_to_mri") ;
4006
4007 if(PRINT_TRACING){ char str[1024] ; sprintf(str,"n=%d type=%d",n,type) ; STATUS(str) ; }
4008
4009 if( br == NULL ){ /* should never happen */
4010 ERROR_message("AFNI_brick_to_mri: bad FD_brick :-(") ; RETURN(NULL) ;
4011 }
4012
4013 /*-------------------------------------------------*/
4014 /*-------- May 1996: graph callbacks first --------*/
4015
4016 if( type == graCR_getlabel ){ /* 18 Apr 2011 */
4017 char *lab = DSET_BRICK_LABEL(br->dset,n) ;
4018 RETURN( (XtPointer)lab ) ;
4019 }
4020
4021 if( type == graCR_getstatus ){
4022 MCW_grapher_status *grstat = myXtNew( MCW_grapher_status ) ;
4023
4024 grstat->num_total = grstat->num_series = br->dset->dblk->nvals ;
4025 grstat->nx = br->n1 ;
4026 grstat->ny = br->n2 ;
4027 grstat->nz = br->n3 ;
4028
4029 grstat->send_CB = AFNI_gra_send_CB ;
4030 grstat->parent = (XtPointer) br ;
4031 grstat->aux = NULL ;
4032
4033 grstat->transforms0D = & (GLOBAL_library.registered_0D) ;
4034 grstat->transforms1D = & (GLOBAL_library.registered_1D) ;
4035
4036 MCW_strncpy( grstat->namecode , br->namecode , 32 ) ;
4037
4038 RETURN( (XtPointer) grstat ) ;
4039 }
4040
4041 if( type == graCR_getseries ){
4042 Three_D_View *im3d = (Three_D_View *)br->parent ;
4043 MCW_grapher *grapher = UNDERLAY_TO_GRAPHER(im3d,br) ;
4044
4045 im = FD_brick_to_series( n , br ) ; if( im == NULL ) RETURN(NULL) ;
4046 im->flags = 1 ;
4047
4048 if( grapher->thresh_fade && im3d->vinfo->func_visible ){ /* Mar 2013 */
4049 int nsl = n / (br->n1 * br->n2) ;
4050 #if 0
4051 INFO_message("thresh_fade: nsl=%d",nsl) ;
4052 #endif
4053 if( br->ntmask != nsl ){
4054 FD_brick *br_fim = UNDERLAY_TO_OVERLAY(im3d,br) ;
4055 MRI_IMAGE *fov = AFNI_func_overlay(nsl,br_fim) ;
4056 STATUS("clear overlay tmask") ;
4057 CLEAR_TMASK(br) ;
4058 #if 0
4059 ININFO_message(" get new tmask") ;
4060 #endif
4061 if( fov != NULL ){
4062 br->tmask = ISQ_binarize_overlay(fov) ;
4063 STATUSp("new tmask",br->tmask) ;
4064 br->ntmask = nsl ; mri_free(fov) ;
4065 }
4066 }
4067 if( br->tmask != NULL ){
4068 byte *tar = MRI_BYTE_PTR(br->tmask) ;
4069 int ij = n % (br->n1 * br->n2) ;
4070 im->flags = (int)tar[ij] ;
4071 #if 0
4072 ININFO_message(" set tsim flags=%d at ij=%d",im->flags) ;
4073 #endif
4074 }
4075 }
4076
4077 RETURN( (XtPointer)im ) ;
4078 }
4079
4080 /*----------------------------------------*/
4081 /*-------- Now do imseq callbacks --------*/
4082
4083 /*--- set the sub-brick (ival) index shift ---*/
4084
4085 if( type == isqCR_deltival ){ /* 23 Feb 2011 */
4086 Three_D_View *im3d = (Three_D_View *)br->parent ;
4087 FD_brick *brfim ;
4088 br->deltival = n ;
4089 brfim = UNDERLAY_TO_OVERLAY(im3d,br) ;
4090 if( brfim != NULL ) brfim->deltival = n ;
4091 RETURN( NULL ) ;
4092 }
4093
4094 if( n < 0 || n >= br->n3 ) RETURN(NULL) ;
4095
4096 /*--- overlay # n ---*/
4097
4098 if( type == isqCR_getoverlay ){
4099 Three_D_View *im3d = (Three_D_View *)br->parent ;
4100
4101 STATUS("get overlay") ;
4102
4103 im = AFNI_overlay( n , br ) ;
4104 if( !AFNI_noenv("AFNI_VALUE_LABEL") ) AFNI_do_bkgd_lab( im3d ) ;
4105 RETURN( (XtPointer) im ) ;
4106 }
4107
4108 /*--- status ---*/
4109
4110 if( type == isqCR_getstatus ){
4111
4112 STATUS("get status") ;
4113
4114 stat = myXtNew( MCW_imseq_status ) ;
4115
4116 stat->num_total = br->n3 ;
4117 stat->num_series = br->n3 ;
4118 stat->send_CB = AFNI_seq_send_CB ;
4119 stat->parent = (XtPointer) br ;
4120 stat->aux = NULL ;
4121
4122 stat->transforms0D = & (GLOBAL_library.registered_0D) ;
4123 stat->transforms2D = & (GLOBAL_library.registered_2D) ;
4124 stat->slice_proj = & (GLOBAL_library.registered_slice_proj) ;
4125
4126 RETURN( (XtPointer) stat ) ;
4127 }
4128
4129 /*--- 26 Feb 2001: return a memplot drawing struct ---*/
4130 /*--- 22 Mar 2002: add crosshairs to surface stuff ---*/
4131
4132 #define RX 0.2
4133 if( type == isqCR_getmemplot ){
4134 Three_D_View *im3d = (Three_D_View *)br->parent ;
4135 THD_3dim_dataset *udset = im3d->anat_now ; /* 07 Jan 2008 */
4136 #ifdef IMAGEIZE_CROSSHAIRS /* disable crosshairs drawn into overlay pixels */
4137 int do_xhar=(im3d->vinfo->crosshair_visible && AFNI_yesenv("AFNI_CROSSHAIR_LINES"));
4138 #else
4139 int do_xhar=(im3d->vinfo->crosshair_visible) ;
4140 #endif
4141 int do_surf;
4142 MEM_plotdata *mp ;
4143 AFNI_surface_widgets *swid = im3d->vwid->view->swid ; /* 19 Aug 2002 */
4144 THD_session *suss=im3d->ss_now ; /* 20 Jan 2004 */
4145 THD_dataxes *daxes=CURRENT_DAXES(udset) ;
4146
4147 if( !IM3D_OPEN(im3d) ) RETURN(NULL) ;
4148
4149 /* 20 Jan 2004: surfaces are now in the session, not on the dataset! */
4150
4151 do_surf = SUMA_ENABLED && SESSION_HAS_SUMA(suss) ;
4152 if( !do_surf && !do_xhar ) RETURN(NULL) ; /* nothing to do */
4153
4154 /* get ready to plot */
4155
4156 STATUS("creating memplot for image overlay") ;
4157 create_memplot_surely( "SUMA_plot" , 1.0 ) ;
4158 mp = get_active_memplot() ;
4159
4160 /* plot surface stuff, if any (this is long) */
4161
4162 if( do_surf ){
4163 int ks , qs , rs ;
4164 int kbest=-1 , ibest=-1 ; /* 24 Feb 2003 */
4165 int nsurf; SUMA_surface **aglist=NULL; /* 07 Apr 2014 */
4166
4167 AFNI_get_xhair_node( im3d , &kbest , &ibest ) ; /* 24 Feb 2003 */
4168
4169 /* Find all the surfaces to draw -- more complex after 07 Apr 2014 */
4170
4171 nsurf = suss->su_num ;
4172 for( qs=0 ; qs < suss->su_nummask ; qs++ )
4173 nsurf += suss->su_mask[qs]->num_surf ;
4174
4175 aglist = (SUMA_surface **)calloc(nsurf,sizeof(SUMA_surface *)) ;
4176
4177 for( qs=0 ; qs < suss->su_num ; qs++ ){
4178 aglist[qs] = suss->su_surf[qs] ;
4179 }
4180 for( ks=qs,qs=0 ; qs < suss->su_nummask ; qs++ ){
4181 for( rs=0 ; rs < suss->su_mask[qs]->num_surf ; rs++ ){
4182 aglist[ks] = suss->su_mask[qs]->surf[rs] ;
4183 }
4184 }
4185
4186 for( ks=0 ; ks < nsurf ; ks++ ){ /* 14 Aug 2002: loop over surfaces */
4187 SUMA_surface *ag = aglist[ks] ; SUMA_mask *msk = NULL ;
4188 int nn , ii,jj , relxyz=0 ;
4189 SUMA_ixyz *nod ;
4190 THD_ivec3 iv,ivp,ivm ;
4191 THD_fvec3 fv,fvp,fvm ;
4192 float s1=1.0/br->n1 , s2=1.0/br->n2 , dxyz ;
4193 float rr_box=1.0,gg_box=0.0,bb_box=0.0 ; /* white */
4194 float rr_lin=0.4,gg_lin=0.0,bb_lin=0.7 ; /* dark blue */
4195 float rr_led=1.0,gg_led=0.0,bb_led=0.0 ;
4196 char str[128] , *eee ;
4197 float rx=RX ; /* default rectangle halfsize */
4198 int kkk=0 ;
4199 float xyz=0.0,xyzp=0.0,xyzm=0.0 , rxm,rxp ;
4200 int skip_boxes=1 , skip_lines=0 , skip_lcen=0, skip_ledg=1 ;
4201 float boxsize=RX , linewidth=0.0 ; /* 23 Feb 2003 */
4202 int firstb ; /* 23 Jan 2004 */
4203 float xrel=0.0f,yrel=0.0f,zrel=0.0f ;
4204
4205 if( ag == NULL ) continue ; /* skip this non-existent one */
4206 nn = ag->num_ixyz ; nod = ag->ixyz ;
4207 if( nn < 1 || nod == NULL ) continue ; /* nothing can be done */
4208
4209 if( ag->parent_type == SUMA_MASK_TYPE ){ /* relative coords */
4210 relxyz = 1 ; msk = (SUMA_mask *)ag->parent ; /* in a mask surf? */
4211 xrel = msk->show_cen.xyz[0] - msk->init_cen.xyz[0] ;
4212 yrel = msk->show_cen.xyz[1] - msk->init_cen.xyz[1] ;
4213 zrel = msk->show_cen.xyz[2] - msk->init_cen.xyz[2] ;
4214 /** INFO_message("SUMA_mask draw: xyz rel = %g %g %g",xrel,yrel,zrel) ; **/
4215 }
4216
4217 /* define parameters for node boxes and triangle lines */
4218
4219 STATUS("defining surface drawing parameters") ;
4220 if( swid != NULL && ks < swid->nrow ){ /* 19 Aug 2002: the new way */
4221 int cc, dd ; /* to set colors: */
4222 /* from the surface widgets */
4223
4224 cc = MCW_val_bbox(swid->surf_bbox[ks]) ; /* 19 Feb 2003: skip it all? */
4225 if( cc == 0 ){
4226 skip_boxes = skip_lines = 1 ;
4227 } else { /* see what is turned on */
4228 cc = swid->surf_node_av[ks]->ival ;
4229 skip_boxes = (cc == 0) ;
4230 if( !skip_boxes ){
4231 rr_box = DCOV_REDBYTE(im3d->dc,cc) / 255.0 ;
4232 gg_box = DCOV_GREENBYTE(im3d->dc,cc) / 255.0 ;
4233 bb_box = DCOV_BLUEBYTE(im3d->dc,cc) / 255.0 ;
4234 }
4235 cc = swid->surf_line_av[ks]->ival ;
4236 dd = swid->surf_ledg_av[ks]->ival ; /* 26 Feb 2003 */
4237 skip_lcen = (cc == 0) ;
4238 skip_ledg = (dd == 0) ;
4239 skip_lines = (skip_lcen && skip_ledg) ;
4240 if( cc > 0 ){
4241 rr_lin = DCOV_REDBYTE(im3d->dc,cc) / 255.0 ;
4242 gg_lin = DCOV_GREENBYTE(im3d->dc,cc) / 255.0 ;
4243 bb_lin = DCOV_BLUEBYTE(im3d->dc,cc) / 255.0 ;
4244 }
4245 if( dd > 0 ){ /* 26 Feb 2003 */
4246 rr_led = DCOV_REDBYTE(im3d->dc,dd) / 255.0 ;
4247 gg_led = DCOV_GREENBYTE(im3d->dc,dd) / 255.0 ;
4248 bb_led = DCOV_BLUEBYTE(im3d->dc,dd) / 255.0 ;
4249 }
4250 boxsize = swid->boxsize_av->ival * 0.1 ; /* 23 Feb 2003 */
4251 linewidth = swid->linewidth_av->ival * 0.002 ;
4252 }
4253
4254 } else if( msk != NULL ){ /* set from inside the surf struct [Apr 2014] */
4255
4256 DC_parse_color( im3d->dc , ag->line_color , &rr_lin,&gg_lin,&bb_lin ) ;
4257 DC_parse_color( im3d->dc , ag->box_color , &rr_box,&gg_box,&bb_box ) ;
4258 linewidth = ag->line_width * 0.002f ;
4259 skip_boxes = 1 ; skip_lines = 0 ; skip_lcen = 0; skip_ledg = 1 ;
4260
4261 } else { /* the old way */
4262 /* to set colors: */
4263 rgbyte bcolor , lcolor ; /* from environment */
4264 AFNI_get_suma_color( ks , &bcolor , &lcolor ) ;
4265 if( bcolor.r == 1 && bcolor.g == 1 && bcolor.b == 1 ){
4266 skip_boxes = 1 ; /* don't do boxes */
4267 } else {
4268 rr_box = bcolor.r / 255.0f ;
4269 gg_box = bcolor.g / 255.0f ;
4270 bb_box = bcolor.b / 255.0f ;
4271 }
4272 if( lcolor.r == 1 && lcolor.g == 1 && lcolor.b == 1 ){
4273 skip_lines = 1 ; /* don't do lines */
4274 } else {
4275 rr_lin = lcolor.r / 255.0f ;
4276 gg_lin = lcolor.g / 255.0f ;
4277 bb_lin = lcolor.b / 255.0f ;
4278 }
4279
4280 eee = getenv("AFNI_SUMA_BOXSIZE") ; /* maybe set boxsize? */
4281 if( eee != NULL ){
4282 float val=strtod(eee,NULL) ;
4283 if( val > 0.0 ) boxsize = val ;
4284 } else if( swid != NULL ){
4285 boxsize = swid->boxsize_av->ival * 0.1 ;
4286 }
4287
4288 eee = getenv( "AFNI_SUMA_LINESIZE" ) ; /* maybe set linewidth? */
4289 if( eee != NULL ){
4290 float val = strtod(eee,NULL) ;
4291 if( val < 0.0 || val > 0.1 ) val = 0.0 ;
4292 linewidth = val ;
4293 } else if( swid != NULL ){
4294 linewidth = swid->linewidth_av->ival * 0.002 ;
4295 }
4296 }
4297
4298 if( skip_boxes && skip_lines ) continue ; /* nothing to do? */
4299
4300 /** 21 Mar 2002:
4301 We calculate plotting coordinates in "fdfind" coordinates,
4302 which are floating point indexes into the FD_brick. However,
4303 these run from 0..n1-1 (in x), which are the centers of the
4304 voxels. In turn these must be mapped to screen locations.
4305 For example, with n1=5, we have these voxels
4306
4307 0 1 2 3 4 = index of voxel
4308 ---------------------
4309 | | | | | |
4310 ---------------------
4311 0.0 1.0 = screen coordinate (for memplot)
4312
4313 Thus voxel index i maps to screen location (i+0.5)/n1.
4314 Previously, I forgot the +0.5, which didn't matter much,
4315 until the introduction of the image zoom feature last week. **/
4316
4317 rx = boxsize ; /* 23 Feb 2003 */
4318 rxm = rx-0.5 ; rxp = rx+0.5 ; /* The 0.5 voxel shift */
4319
4320 /* find DICOM coordinates of next slice and previous slice */
4321
4322 LOAD_IVEC3(iv,0,0,n+1) ; /* next */
4323 ivp = THD_fdind_to_3dind( br , iv ) ;
4324 fvp = THD_3dind_to_3dmm ( udset , ivp ) ;
4325 fvp = THD_3dmm_to_dicomm( udset , fvp ) ;
4326 LOAD_IVEC3(iv,0,0,n-1) ; /* previous */
4327 ivm = THD_fdind_to_3dind( br , iv ) ;
4328 fvm = THD_3dind_to_3dmm ( udset , ivm ) ;
4329 fvm = THD_3dmm_to_dicomm( udset , fvm ) ;
4330
4331 /* threshold for determining which axis this slice is along */
4332
4333 dxyz = MIN(br->del1,br->del2) ;
4334 dxyz = MIN(dxyz ,br->del3) ; dxyz *= 0.1f ;
4335
4336 set_color_memplot(rr_box,gg_box,bb_box) ; /* box drawing colors */
4337 set_thick_memplot(0.0) ;
4338 firstb = 1 ; /* 23 Jan 2004 */
4339
4340 /* find nodes inside this slice */
4341
4342 if( skip_boxes ) STATUS("finding slice planes") ;
4343 else STATUS("drawing node boxes") ;
4344
4345 if( fabs(fvm.xyz[0]-fvp.xyz[0]) > dxyz ){ /* search x */
4346 float xb=fvm.xyz[0] , xt=fvp.xyz[0] , xm,xw ; /* range of */
4347 float nodx,nody,nodz ;
4348 if( xb > xt ){ float t=xb ; xb=xt ; xt=t ; } /* x in slice */
4349 xm = 0.5*(xb+xt); xw = 0.25*(xt-xb); xb = xm-xw; xt = xm+xw;
4350 STATUS(" - x plane") ;
4351 if( !skip_boxes ){
4352 for( ii=0 ; ii < nn ; ii++ ){
4353 nodx = nod[ii].x ; nody = nod[ii].y ; nodz = nod[ii].z ;
4354 if( relxyz ){ nodx += xrel ; nody += yrel ; nodz += zrel ; }
4355 if( nodx >= xb && nodx <= xt ){ /* inside? */
4356 LOAD_FVEC3(fv,nodx,nody,nodz) ; /* convert */
4357 fv = THD_dicomm_to_3dmm( udset , fv ) ; /* coords */
4358 fv = THD_3dmm_to_3dfind( udset , fv ) ; /* to slice */
4359 fv = THD_3dfind_to_fdfind( br , fv ) ; /* indexes */
4360
4361 if( firstb ){
4362 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4363 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) );
4364 firstb = 0 ;
4365 }
4366
4367 plotrect_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4368 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) ) ;
4369
4370 if( ks == kbest && nod[ii].id == ibest ){ /* 24 Feb 2003 */
4371 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4372 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) );
4373 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+rxp),
4374 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]-rxm) );
4375 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+0.5),
4376 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+0.5) );
4377 plotline_memplot( s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]-rxm),
4378 s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]+rxp) );
4379 }
4380 }
4381 }
4382 }
4383 kkk = 0; xyz = xm; xyzp = xt; xyzm = xb; /* for the triangles/lines below */
4384 }
4385 else if( fabs(fvm.xyz[1]-fvp.xyz[1]) > dxyz ){ /* search y */
4386 float yb=fvm.xyz[1] , yt=fvp.xyz[1] , ym,yw ;
4387 float nodx,nody,nodz ;
4388 if( yb > yt ){ float t=yb ; yb=yt ; yt=t ; }
4389 ym = 0.5*(yb+yt); yw = 0.25*(yt-yb); yb = ym-yw; yt = ym+yw;
4390 STATUS(" - y plane") ;
4391 if( !skip_boxes ){
4392 for( ii=0 ; ii < nn ; ii++ ){
4393 nodx = nod[ii].x ; nody = nod[ii].y ; nodz = nod[ii].z ;
4394 if( relxyz ){ nodx += xrel ; nody += yrel ; nodz += zrel ; }
4395 if( nody >= yb && nody <= yt ){
4396 LOAD_FVEC3(fv,nodx,nody,nodz) ;
4397 fv = THD_dicomm_to_3dmm( udset , fv ) ;
4398 fv = THD_3dmm_to_3dfind( udset , fv ) ;
4399 fv = THD_3dfind_to_fdfind( br , fv ) ;
4400
4401 if( firstb ){
4402 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4403 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) );
4404 firstb = 0 ;
4405 }
4406
4407 plotrect_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4408 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) ) ;
4409
4410 if( ks == kbest && nod[ii].id == ibest ){ /* 24 Feb 2003 */
4411 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4412 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) );
4413 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+rxp),
4414 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]-rxm) );
4415 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+0.5),
4416 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+0.5) );
4417 plotline_memplot( s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]-rxm),
4418 s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]+rxp) );
4419 }
4420 }
4421 }
4422 }
4423 kkk = 1; xyz = ym; xyzp = yt; xyzm = yb; /* for the triangles/lines below */
4424 }
4425 else if( fabs(fvm.xyz[2]-fvp.xyz[2]) > dxyz ){ /* search z */
4426 float zb=fvm.xyz[2] , zt=fvp.xyz[2] , zm,zw ;
4427 float nodx,nody,nodz ;
4428 if( zb > zt ){ float t=zb ; zb=zt ; zt=t ; }
4429 zm = 0.5*(zb+zt); zw = 0.25*(zt-zb); zb = zm-zw; zt = zm+zw;
4430 STATUS(" - z plane") ;
4431 if( !skip_boxes ){
4432 for( ii=0 ; ii < nn ; ii++ ){
4433 nodx = nod[ii].x ; nody = nod[ii].y ; nodz = nod[ii].z ;
4434 if( relxyz ){ nodx += xrel ; nody += yrel ; nodz += zrel ; }
4435 if( nodz >= zb && nodz <= zt ){
4436 LOAD_FVEC3(fv,nod[ii].x,nod[ii].y,nod[ii].z) ;
4437 fv = THD_dicomm_to_3dmm( udset , fv ) ;
4438 fv = THD_3dmm_to_3dfind( udset , fv ) ;
4439 fv = THD_3dfind_to_fdfind( br , fv ) ;
4440
4441 if( firstb ){
4442 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4443 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) );
4444 firstb = 0 ;
4445 }
4446
4447 plotrect_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4448 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) ) ;
4449
4450 if( ks == kbest && nod[ii].id == ibest ){ /* 24 Feb 2003 */
4451 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4452 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp) );
4453 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+rxp),
4454 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]-rxm) );
4455 plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+0.5),
4456 s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+0.5) );
4457 plotline_memplot( s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]-rxm),
4458 s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]+rxp) );
4459 }
4460 }
4461 }
4462 }
4463 kkk = 2; xyz = zm; xyzp = zt; xyzm = zb; /* for the triangles/lines below */
4464 }
4465
4466 /* 10 Mar 2002:
4467 For each triangle that crosses the plane of the slice,
4468 plot a line segment at the intersection of the plane and triangle.
4469 The plane is along DICOM axis #kkk at coordinate xyz;
4470 these variables were set just above in the node display code. */
4471
4472 if( !skip_lines && ag->num_ijk > 0 && ag->ijk != NULL ){
4473 SUMA_ijk *tr = ag->ijk ; /* triangle list */
4474 int ntr = ag->num_ijk ; /* number of triangles */
4475 int id,jd,kd ;
4476 THD_fvec3 fvijk[3] ;
4477 float ci,cj,ck , xlev ;
4478 int ilev ;
4479
4480 for( ilev=0 ; ilev <= 2 ; ilev++ ){ /* 26 Feb 2003: loop over levels: */
4481 /* slice center, top & bot edges */
4482 if( ilev == 0 ){
4483 if( skip_lcen ) continue ; /* don't do center plane */
4484 xlev = xyz ;
4485 set_color_memplot(rr_lin,gg_lin,bb_lin) ; /* line drawing colors */
4486 set_thick_memplot(linewidth) ;
4487 } else {
4488 if( skip_ledg ) continue ; /* don't do edge planes */
4489 xlev = (ilev == 1) ? xyzp : xyzm ;
4490 set_color_memplot(rr_led,gg_led,bb_led) ;
4491 set_thick_memplot(0.0) ;
4492 }
4493
4494 STATUS("drawing triangle lines") ;
4495
4496 /* loop over triangles */
4497
4498 for( ii=0 ; ii < ntr ; ii++ ){
4499
4500 /* get indexes of triangle's nodes (from their id's) */
4501
4502 id = SUMA_find_node_id(ag,tr[ii].id); if( id < 0 ) continue;
4503 jd = SUMA_find_node_id(ag,tr[ii].jd); if( jd < 0 ) continue;
4504 kd = SUMA_find_node_id(ag,tr[ii].kd); if( kd < 0 ) continue;
4505
4506 /* load DICOM coords of triangle's nodes */
4507
4508 LOAD_FVEC3(fvijk[0], nod[id].x, nod[id].y, nod[id].z) ;
4509 LOAD_FVEC3(fvijk[1], nod[jd].x, nod[jd].y, nod[jd].z) ;
4510 LOAD_FVEC3(fvijk[2], nod[kd].x, nod[kd].y, nod[kd].z) ;
4511
4512 if( relxyz ){ /* 07 Apr 2014 */
4513 fvijk[0].xyz[0] += xrel; fvijk[1].xyz[0] += xrel; fvijk[2].xyz[0] += xrel;
4514 fvijk[0].xyz[1] += yrel; fvijk[1].xyz[1] += yrel; fvijk[2].xyz[1] += yrel;
4515 fvijk[0].xyz[2] += zrel; fvijk[1].xyz[2] += zrel; fvijk[2].xyz[2] += zrel;
4516 }
4517
4518 /* want 1 node on one size of plane, and 2 on the other */
4519
4520 ci = fvijk[0].xyz[kkk] - xlev; /* differences from center */
4521 cj = fvijk[1].xyz[kkk] - xlev; /* of current slice plane */
4522 ck = fvijk[2].xyz[kkk] - xlev;
4523 jj = 4*(ci > 0.0) + 2*(cj > 0.0) + (ck > 0.0) ;
4524 if( jj == 0 || jj == 7 ) continue ; /* all have same sign */
4525
4526 /* setup id,jd,kd so fvijk[id] is on one side of plane,
4527 and so that fvijk[jd] and fvijk[kd] are on other side */
4528
4529 switch( jj ){
4530 case 6:
4531 case 1: id = 2 ; jd = 0 ; kd = 1 ; break ; /* kd is the 1 */
4532 case 5:
4533 case 2: id = 1 ; jd = 0 ; kd = 2 ; break ; /* jd is the 1 */
4534 case 4:
4535 case 3: id = 0 ; jd = 1 ; kd = 2 ; break ; /* id is the 1 */
4536 }
4537
4538 /* linearly interpolate between fvijk[id] and fvijk[jd]
4539 to find the point where this line hits the slice plane */
4540
4541 ci = fvijk[id].xyz[kkk] - xlev;
4542 cj = fvijk[id].xyz[kkk] - fvijk[jd].xyz[kkk] ;
4543 if( cj == 0.0 ) continue ; /* should not happen */
4544 ck = ci / cj ;
4545 if( ck < 0.0 || ck > 1.0 ) continue ; /* should not happen */
4546 cj = 1.0 - ck ;
4547 fvp = SCLADD_FVEC3(cj,fvijk[id],ck,fvijk[jd]) ;
4548
4549 /* linearly interpolate between fvijk[id] and fvijk[kd] */
4550
4551 cj = fvijk[id].xyz[kkk] - fvijk[kd].xyz[kkk] ;
4552 if( cj == 0.0 ) continue ;
4553 ck = ci / cj ;
4554 if( ck < 0.0 || ck > 1.0 ) continue ;
4555 cj = 1.0 - ck ;
4556 fvm = SCLADD_FVEC3(cj,fvijk[id],ck,fvijk[kd]) ;
4557
4558 /* transform interpolated points to FD_brick coords */
4559
4560 fvp = THD_dicomm_to_3dmm( udset , fvp ) ;
4561 if( fvp.xyz[0] < daxes->xxmin ||
4562 fvp.xyz[0] > daxes->xxmax ||
4563 fvp.xyz[1] < daxes->yymin ||
4564 fvp.xyz[1] > daxes->yymax ||
4565 fvp.xyz[2] < daxes->zzmin ||
4566 fvp.xyz[2] > daxes->zzmax ) continue ; /* 08 Jan 2004 */
4567 fvp = THD_3dmm_to_3dfind( udset , fvp ) ;
4568 fvp = THD_3dfind_to_fdfind( br , fvp ) ;
4569
4570 fvm = THD_dicomm_to_3dmm( udset , fvm ) ;
4571 if( fvm.xyz[0] < daxes->xxmin ||
4572 fvm.xyz[0] > daxes->xxmax ||
4573 fvm.xyz[1] < daxes->yymin ||
4574 fvm.xyz[1] > daxes->yymax ||
4575 fvm.xyz[2] < daxes->zzmin ||
4576 fvm.xyz[2] > daxes->zzmax ) continue ; /* 08 Jan 2004 */
4577 fvm = THD_3dmm_to_3dfind( udset , fvm ) ;
4578 fvm = THD_3dfind_to_fdfind( br , fvm ) ;
4579
4580 /* plot a line segment between them, in the plane of the slice */
4581 /* [21 Mar 2002: include the 0.5 shift mentioned way up above] */
4582
4583 plotline_memplot( s1*(fvp.xyz[0]+0.5) , 1.0-s2*(fvp.xyz[1]+0.5) ,
4584 s1*(fvm.xyz[0]+0.5) , 1.0-s2*(fvm.xyz[1]+0.5) ) ;
4585
4586 } /* end of loop over triangles */
4587 set_thick_memplot(0.0) ; /* 15 Jan 2003 */
4588 } /* end of loop over levels: 26 Feb 2003 */
4589 } /* end of if over doing lines */
4590 } /* end of loop over surface index ks */
4591 } /* end of plotting surface stuff */
4592
4593 /*----- put crosshairs on with lines, if desired -----*/
4594 /****** 22 Mar 2002: adapted from pixel overlay ******/
4595
4596 if( do_xhar ){
4597 MCW_grapher *grapher = UNDERLAY_TO_GRAPHER(im3d,br) ;
4598 float thth = (float)AFNI_numenv("AFNI_CROSSHAIR_THICKNESS") ;
4599
4600 THD_ivec3 ib = THD_3dind_to_fdind( br ,
4601 TEMP_IVEC3( im3d->vinfo->i1 ,
4602 im3d->vinfo->j2 ,
4603 im3d->vinfo->k3 ) ) ;
4604 STATUS("drawing crosshairs") ;
4605
4606 if( thth < 0.0f || thth > 0.05f ) thth = 0.0f ;
4607 set_thick_memplot(thth) ;
4608
4609 if( n == ib.ijk[2] || im3d->vinfo->xhairs_all ){
4610 int jp,ip , jcen,icen , gappp , jj,ii ;
4611 int idown,iup,iskip , jdown,jup,jskip , imon,jmon ;
4612 int a1 = br->a123.ijk[0] , /* x axis of the brick? */
4613 ax = abs(a1) - 1 ; /* 0,1,2 for dataset x,y,z */
4614 int a2 = br->a123.ijk[1] , /* y axis of the brick? */
4615 ay = abs(a2) - 1 ; /* 0,1,2 for dataset x,y,z */
4616 int a3 = br->a123.ijk[2] , /* z axis of the brick? */
4617 az = abs(a3) - 1 ; /* 0,1,2 for dataset x,y,z */
4618
4619 int gap,icr,jcr , nx=br->n1 , ny=br->n2 ;
4620
4621 float rr,gg,bb ; /* colors */
4622 float s1=1.0/br->n1 , s2=1.0/br->n2 ; /* scale pixels to plot coords */
4623 #define PSX(i) (s1*((i)+0.5))
4624 #define PSY(j) (1.0-s2*((j)+0.5))
4625
4626 /* spatial orientations of image axes */
4627
4628 int ox = (ax==0) ? br->dset->daxes->xxorient :
4629 (ax==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
4630
4631 int oy = (ay==0) ? br->dset->daxes->xxorient :
4632 (ay==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
4633
4634 jp = im3d->vinfo->crosshair_ovcolor ;
4635 rr = DCOV_REDBYTE (im3d->dc,jp) / 255.0 ;
4636 gg = DCOV_GREENBYTE(im3d->dc,jp) / 255.0 ;
4637 bb = DCOV_BLUEBYTE (im3d->dc,jp) / 255.0 ;
4638 set_color_memplot(rr,gg,bb) ;
4639
4640 gap = (grapher==NULL) ? im3d->vinfo->crosshair_gap : (grapher->mat+1)/2 ;
4641
4642 icen = ib.ijk[0] ; /* x-index of image pixel at focus */
4643 jcen = ib.ijk[1] ; /* y-index */
4644
4645 /** initialize montage steps **/
4646
4647 if( im3d->vinfo->xhairs_show_montage ){ /* in "Multi" mode */
4648 iskip = im3d->vinfo->xhairs_nskip.ijk[ax] + 1 ;
4649 jskip = im3d->vinfo->xhairs_nskip.ijk[ay] + 1 ;
4650 if( a1 > 0 ){
4651 idown = im3d->vinfo->xhairs_ndown.ijk[ax] ;
4652 iup = im3d->vinfo->xhairs_nup.ijk[ax] ;
4653 } else {
4654 iup = im3d->vinfo->xhairs_ndown.ijk[ax] ;
4655 idown = im3d->vinfo->xhairs_nup.ijk[ax] ;
4656 }
4657 if( a2 > 0 ){
4658 jdown = im3d->vinfo->xhairs_ndown.ijk[ay] ;
4659 jup = im3d->vinfo->xhairs_nup.ijk[ay] ;
4660 } else {
4661 jup = im3d->vinfo->xhairs_ndown.ijk[ay] ;
4662 jdown = im3d->vinfo->xhairs_nup.ijk[ay] ;
4663 }
4664
4665 } else { /* in "Single" Mode */
4666 idown = iup = jdown = jup = iskip = jskip = 0 ;
4667 if( grapher != NULL ){ idown=-(iup+1); jdown=-(jup+1); } /* skip lines? */
4668 }
4669
4670 /* draw vertical lines first */
4671
4672 if( (im3d->vinfo->xhairs_orimask & (1<<oy)) != 0 ){
4673 for( imon=-idown ; imon <= iup ; imon++ ){
4674 icr = icen + imon * iskip ;
4675
4676 if( im3d->vinfo->xhairs_periodic ){
4677 while( icr < 0 ) icr += nx ;
4678 while( icr >= nx ) icr -= nx ;
4679 } else {
4680 if( icr < 0 || icr >= nx ) continue ;
4681 }
4682
4683 gappp = (abs(icr-icen) <= gap) ? gap : -1 ; /* no gap if far from center */
4684
4685 if( gappp < 0 ){ /* no gap => 1 vertical line */
4686
4687 plotline_memplot( PSX(icr) , 0.0 , PSX(icr) , 1.0 ) ;
4688
4689 } else { /* gap => 2 vertical lines */
4690
4691 jj = jcen-gappp-1 ;
4692 if( jj >= 0 )
4693 plotline_memplot( PSX(icr) , 1.0 , PSX(icr) , PSY(jj+0.5) ) ;
4694
4695 jj = jcen+gappp+1 ;
4696 if( jj < ny )
4697 plotline_memplot( PSX(icr) , PSY(jj-0.5) , PSX(icr) , 0.0 ) ;
4698 }
4699
4700 }
4701 }
4702
4703 /* draw horizontal lines */
4704
4705 if( (im3d->vinfo->xhairs_orimask & (1<<ox)) != 0 ){ /* 31 Dec 1998 */
4706 for( jmon=-jdown ; jmon <= jup ; jmon++ ){
4707 jcr = jcen + jmon * jskip ;
4708 if( im3d->vinfo->xhairs_periodic ){
4709 while( jcr < 0 ) jcr += ny ;
4710 while( jcr >= ny ) jcr -= ny ;
4711 } else {
4712 if( jcr < 0 || jcr >= ny ) continue ;
4713 }
4714
4715 gappp = (abs(jcr-jcen) <= gap) ? gap : -1 ; /* no gap if far from center */
4716
4717 if( gappp < 0 ){ /* no gap => 1 horizontal line */
4718
4719 plotline_memplot( 0.0 , PSY(jcr) , 1.0 , PSY(jcr) ) ;
4720
4721 } else { /* gap => 2 horizontal lines */
4722
4723 ii = icen-gappp-1 ;
4724 if( ii >= 0 )
4725 plotline_memplot( 0.0 , PSY(jcr) , PSX(ii+0.5) , PSY(jcr) ) ;
4726
4727 ii = icen+gappp+1 ;
4728 if( ii < nx )
4729 plotline_memplot( PSX(ii-0.5) , PSY(jcr) , 1.0 , PSY(jcr) ) ;
4730 }
4731 }
4732 }
4733
4734 /* draw grapher frame, if needed */
4735
4736 if( grapher != NULL ){
4737 int gs = gap , gb = (grapher->mat +2)/2 ;
4738
4739 jcr = jcen ; icr = icen ;
4740
4741 ip = icr - gb ; if( ip < 0 ) ip = 0 ;
4742 ii = icr + gs ; if( ii >= nx ) ii = nx-1 ;
4743
4744 jp = jcr - gb ; if( jp < 0 ) jp = 0 ;
4745 jj = jcr + gs ; if( jj >= ny ) jj = ny-1 ;
4746
4747 plotline_memplot( PSX(ip+0.5),PSY(jp+0.5) , PSX(ii-0.5),PSY(jp+0.5) ) ;
4748 plotline_memplot( PSX(ii-0.5),PSY(jp+0.5) , PSX(ii-0.5),PSY(jj-0.5) ) ;
4749 plotline_memplot( PSX(ii-0.5),PSY(jj-0.5) , PSX(ip+0.5),PSY(jj-0.5) ) ;
4750 plotline_memplot( PSX(ip+0.5),PSY(jj-0.5) , PSX(ip+0.5),PSY(jp+0.5) ) ;
4751
4752 } /* end if "if grapher exists" */
4753
4754 } /* end of "if correct slice" (or do all slices) */
4755 } /* end of crosshairs */
4756
4757 /*----- return the completed plot -----*/
4758
4759 if( MEMPLOT_NLINE(mp) < 1 ) DESTROY_MEMPLOT(mp) ;
4760
4761 RETURN(mp) ; /* will be destroyed in imseq */
4762 }
4763
4764 /*--- 20 Sep 2001: image label ---*/
4765
4766 if( type == isqCR_getlabel ){
4767 Three_D_View *im3d = (Three_D_View *) br->parent ;
4768 char *lab , str[2048] , *dd , *eee=NULL;
4769 char labstrf[256]={""}, labstra[256]={""};
4770 THD_ivec3 iv,ivp,ivm ;
4771 THD_fvec3 fv,fvp,fvm ;
4772 float dxyz , cc ;
4773 int ii, ival;
4774 double dval;
4775 THD_3dim_dataset *dset=NULL ;
4776
4777 if( im3d->type != AFNI_3DDATA_VIEW ) RETURN(NULL) ;
4778
4779 LOAD_IVEC3(iv,0,0,n) ;
4780 ivp = THD_fdind_to_3dind( br , iv ) ;
4781
4782 if( n == 0 ) LOAD_IVEC3(iv,0,0,1) ;
4783 else LOAD_IVEC3(iv,0,0,n-1) ;
4784 ivm = THD_fdind_to_3dind( br , iv ) ;
4785
4786 if( AFNI_yesenv("AFNI_IMAGE_LABEL_IJK") ){ /* 27 Feb 2017 */
4787
4788 int nnn ; char *fmt ;
4789 nnn = MAX(br->n1,br->n2) ; nnn = MAX(nnn,br->n3) ;
4790 fmt = (nnn < 10) ? "#%1d"
4791 : (nnn < 100) ? "#%02d"
4792 : (nnn < 1000)? "#%03d"
4793 : "#%04d" ;
4794
4795 if( ivm.ijk[0] != ivp.ijk[0] ){
4796 sprintf(str,fmt,ivp.ijk[0]) ;
4797
4798 } else if( ivm.ijk[1] != ivp.ijk[1] ){
4799 sprintf(str,fmt,ivp.ijk[1]) ;
4800
4801 } else if( ivm.ijk[2] != ivp.ijk[2] ){
4802 sprintf(str,fmt,ivp.ijk[2]) ;
4803
4804 } else { /* should never happen */
4805 RETURN(NULL) ;
4806 }
4807
4808 } else {
4809 fvp = THD_3dind_to_3dmm ( br->dset , ivp ) ;
4810 fvp = THD_3dmm_to_dicomm( br->dset , fvp ) ;
4811
4812 fvm = THD_3dind_to_3dmm ( br->dset , ivm ) ;
4813 fvm = THD_3dmm_to_dicomm( br->dset , fvm ) ;
4814
4815 dxyz = MIN(br->del1,br->del2) ;
4816 dxyz = MIN(dxyz ,br->del3) ; dxyz *= 0.1 ;
4817
4818 if( fabs(fvm.xyz[0]-fvp.xyz[0]) > dxyz ){ /* +=R -=L */
4819 cc = fvp.xyz[0] ;
4820 dd = ( cc >= 0.0 ) ? "L" : "R" ;
4821 } else if( fabs(fvm.xyz[1]-fvp.xyz[1]) > dxyz ){ /* +=P -=A */
4822 cc = fvp.xyz[1] ;
4823 dd = ( cc >= 0.0 ) ? "P" : "A" ;
4824 } else if( fabs(fvm.xyz[2]-fvp.xyz[2]) > dxyz ){ /* +=S -=I */
4825 cc = fvp.xyz[2] ;
4826 dd = ( cc >= 0.0 ) ? "S" : "I" ;
4827 } else {
4828 RETURN(NULL) ; /* should never happen */
4829 }
4830
4831 sprintf(str,"%3.2f",fabs(cc)) ;
4832 for( ii=strlen(str)-1 ; ii > 0 && str[ii] == '0' ; ii-- ) str[ii] = '\0' ;
4833 if( str[ii] == '.' ) str[ii] = '\0' ;
4834 strcat(str, dd) ;
4835 }
4836
4837 if (!FD_brick_montized(br)){ /* Show labels if any. ZSS Dec. 2011*/
4838 dset = Get_UO_Dset(br, 'U', 1, &ival);
4839 if ((dval = (double)THD_get_voxel_dicom(dset,
4840 im3d->vinfo->xi,
4841 im3d->vinfo->yj,
4842 im3d->vinfo->zk, ival))>0.0) {
4843 AFNI_get_dset_val_label_maybeCR(dset, /* Dec 7 2011 ZSS/DRG 2021 */
4844 dval, labstra);
4845 }
4846 dset = Get_UO_Dset(br, 'O', 1, &ival);
4847 if ((dval = (double)THD_get_voxel_dicom(dset,
4848 im3d->vinfo->xi,
4849 im3d->vinfo->yj,
4850 im3d->vinfo->zk, ival))>0.0) {
4851 AFNI_get_dset_val_label_maybeCR(dset, /* Dec 7 2011 ZSS/DRG 2021 */
4852 dval, labstrf);
4853
4854 }
4855
4856 if (labstrf[0] != '\0' || labstra[0] != '\0') {
4857 strcat(str, " \\noesc ");
4858 if (!strcmp(labstrf, labstra)) {
4859 strcat(str, "U+O:");
4860 strncat(str, labstra, 126*sizeof(char));
4861 } else {
4862 if (labstra[0] != '\0') {
4863 strcat(str, "U:");
4864 strncat(str, labstra, 126*sizeof(char));
4865 }
4866 if (labstrf[0] != '\0') {
4867 strcat(str, labstra[0] != '\0' ? " O:" : "O:");
4868 strncat(str, labstrf, 126*sizeof(char));
4869 }
4870 }
4871 }
4872 }
4873
4874 lab = strdup(str) ;
4875
4876 RETURN(lab) ;
4877 }
4878
4879 /*--- underlay image # n ---*/
4880 if( type == isqCR_getimage || type == isqCR_getqimage ||
4881 type == isqCR_getulayim || type == isqCR_getolayim ){
4882
4883 Three_D_View *im3d = (Three_D_View *)br->parent ;
4884 FD_brick *brr=NULL ;
4885 int ival;
4886
4887 if (!(brr = Get_FD_Brick_As_Selected(br, type, &ival))) RETURN(NULL);
4888
4889 #if 0
4890 INFO_message("%s: brr=%p ival=%d",
4891 (type == isqCR_getimage ) ? "isqCR_getimage"
4892 : (type == isqCR_getqimage) ? "isqCR_getqimage"
4893 : (type == isqCR_getulayim) ? "isqCR_getulayim"
4894 : (type == isqCR_getolayim) ? "isqCR_getolayim" : "unknown" , brr , ival ) ;
4895 #endif
4896
4897 if(PRINT_TRACING)
4898 { char str[256] ;
4899 sprintf(str,"getting image n1=%d n2=%d ival=%d",br->n1,br->n2,ival) ;
4900 STATUS(str) ; }
4901
4902 LOAD_DSET_VIEWS(im3d) ; /* 02 Nov 1996 */
4903
4904 AFNI_set_ignore_vedit(1) ; /* 28 Jan 2008 */
4905 im = FD_warp_to_mri( n , ival , brr ) ; /* get image from dataset */
4906 AFNI_set_ignore_vedit(0) ;
4907
4908 if( ival < 0 ) RETURN( (XtPointer) im ) ; /* return fake image */
4909
4910 /* Load value of current pixel into display label */
4911 /* April 1996: only if image is at current slice */
4912
4913 if( brr == br ){
4914 char buf[64] = "\0" ; int ibest=-1 ;
4915 AFNI_set_valabel( br , n , im , buf ) ;
4916 if( buf[0] != '\0' ){
4917 if( im3d->vinfo->underlay_type == UNDERLAY_ANAT )
4918 strcpy( im3d->vinfo->anat_val , buf ) ;
4919 else
4920 im3d->vinfo->anat_val[0] = '\0' ;
4921
4922 if( !AFNI_noenv("AFNI_VALUE_LABEL") ) AFNI_do_bkgd_lab( im3d ) ;
4923
4924 if( im->kind != MRI_complex && im->kind != MRI_rgb ){
4925 char qbuf[64] = "bg =" ;
4926 strcat(qbuf,buf) ; strcpy(buf,qbuf) ;
4927 }
4928 AFNI_get_xhair_node( im3d , NULL , &ibest ) ; /* 21 Feb 2003 */
4929 if( ibest >= 0 ){
4930 char qbuf[64]; sprintf(qbuf,"\nxh = #%d",ibest); strcat(buf,qbuf);
4931 }
4932 MCW_set_widget_label( im3d->vwid->imag->pop_bkgd_lab , buf ) ;
4933 XtManageChild( im3d->vwid->imag->pop_bkgd_lab ) ;
4934 }
4935 }
4936
4937 RETURN( (XtPointer) im ) ;
4938 }
4939
4940 STATUS("get something else, but I don't care!") ;
4941
4942 RETURN( NULL ) ;
4943 }
4944
4945 /*-----------------------------------------------------------------------------*/
4946
4947 #undef PFVAL
4948 #if 1
4949 # define PFVAL(vv,bb) strcpy((bb),AV_uformat_fval(vv))
4950 #else
4951 # define PFVAL(vv,bb) AV_fval_to_char((vv),(bb))
4952 #endif
4953
4954 /*-----------------------------------------------------------------------------*/
4955 /*! Set a value label when the nsl-th image is in "im".
4956 *//*---------------------------------------------------------------------------*/
4957
AFNI_set_valabel(FD_brick * br,int nsl,MRI_IMAGE * im,char * blab)4958 void AFNI_set_valabel( FD_brick *br , int nsl , MRI_IMAGE *im , char *blab )
4959 {
4960 Three_D_View *im3d = (Three_D_View *) br->parent ;
4961 THD_ivec3 ib ;
4962
4963 ENTRY("AFNI_set_valabel") ;
4964
4965 if( ! IM3D_VALID(im3d) || ! im3d->vwid->imag->do_bkgd_lab ||
4966 im == NULL || blab == NULL ) EXRETURN ;
4967
4968 /* convert current voxel index location to FD_brick indexes */
4969
4970 ib = THD_3dind_to_fdind( br , TEMP_IVEC3( im3d->vinfo->i1 ,
4971 im3d->vinfo->j2 ,
4972 im3d->vinfo->k3 ) ) ;
4973
4974 /* if the input image slice index (nsl) doesn't match the current
4975 location of the crosshairs, then we don't care about this image */
4976
4977 if( nsl != ib.ijk[2] ) EXRETURN ;
4978
4979 /* otherwise, extract a value from the image and put into blab */
4980
4981 switch( im->kind ){
4982 default: strcpy(blab,":(") ;
4983
4984 case MRI_byte:{
4985 int val = MRI_BYTE_2D(im , ib.ijk[0],ib.ijk[1]) ;
4986 sprintf( blab , "%d" , val ) ;
4987 }
4988 break ;
4989
4990 case MRI_short:{
4991 int val = MRI_SHORT_2D(im , ib.ijk[0],ib.ijk[1]) ;
4992 sprintf( blab , "%d" , val ) ;
4993 }
4994 break ;
4995
4996 case MRI_int:{
4997 int val = MRI_INT_2D(im , ib.ijk[0],ib.ijk[1]) ;
4998 sprintf( blab , "%d" , val ) ;
4999 }
5000 break ;
5001
5002 case MRI_float:{
5003 float val = MRI_FLOAT_2D(im , ib.ijk[0],ib.ijk[1]) ;
5004 PFVAL(val,blab) ;
5005 }
5006 break ;
5007
5008 case MRI_complex:{
5009 int iblab ; char qbuf[16] ; complex val ;
5010 val = MRI_COMPLEX_2D(im , ib.ijk[0],ib.ijk[1]) ;
5011 PFVAL(val.r,blab) ; iblab = strlen(blab) ;
5012 if( val.i >= 0.0 ) blab[iblab++] = '+' ;
5013 PFVAL(val.i,blab+iblab) ; iblab = strlen(blab) ;
5014 blab[iblab++] = 'I' ; blab[iblab++] = '\0' ;
5015 }
5016 break ;
5017
5018 case MRI_rgb:{
5019 byte *rgb = MRI_RGB_PTR(im) ;
5020 int ii = ib.ijk[0] + im->nx * ib.ijk[1] ;
5021 sprintf(blab,"(%d,%d,%d)",(int)rgb[3*ii],(int)rgb[3*ii+1],(int)rgb[3*ii+2]) ;
5022 }
5023 break ;
5024 }
5025 EXRETURN ;
5026 }
5027
5028 /*----------------------------------------------------------------------
5029 read image files directly into a 3D dataset.
5030 this will be incomplete, but is enough for display purposes.
5031 ------------------------------------------------------------------------*/
5032
AFNI_read_images(int nf,char * fname[])5033 THD_3dim_dataset * AFNI_read_images( int nf , char *fname[] )
5034 {
5035 MRI_IMAGE *im , *shim ;
5036 char *bar ;
5037 int nx , ny , nz , lf , kz , kim , npix,ii ;
5038 MRI_IMARR *arr ;
5039 char str[256] ;
5040 THD_3dim_dataset *dset ;
5041 int datum = GLOBAL_argopt.datum , dsize ;
5042
5043 int nvals , nzz , nzin=0 ; /* 19 Oct 1999 */
5044 float dx=0.0, dy=0.0 , dz=0.0 ; /* 29 Jul 2002 */
5045
5046 ENTRY("AFNI_read_images") ;
5047
5048 /*----- see if there are any images to read! -----*/
5049
5050 if( nf < 1 ) ERROR_exit("No images on command line!?") ;
5051
5052 /* count total number of images */
5053
5054 nz = 0 ;
5055 for( lf=0 ; lf < nf ; lf++ ){
5056 if( THD_is_directory(fname[lf]) ){ /* 21 Feb 2007 */
5057 fprintf(stderr,
5058 "\n** Fatal Error: %s is a directory, not an image file!",
5059 fname[lf]) ;
5060 exit(1) ;
5061 }
5062 ii = mri_imcount( fname[lf] ) ;
5063 if( ii == 0 )
5064 ERROR_exit("Illegal image file specifier: %s",fname[lf]) ;
5065 nz += ii ;
5066 }
5067 if( nz == 1 ) nz = 2 ; /* special case for just one image */
5068
5069 /*--- read 1st file to get sizes ---*/
5070
5071 STATUS("read first file") ;
5072 arr = mri_read_file( fname[0] ) ;
5073 if( arr == NULL || arr->num == 0 )
5074 ERROR_exit("Cannot read first image file: %s",fname[0]) ;
5075
5076 im = arr->imarr[0] ;
5077 nx = im->nx ;
5078 ny = im->ny ; npix = nx * ny ;
5079
5080 if( im->dw > 0.0 ){
5081 dx = fabs(im->dx); dy = fabs(im->dy); dz = fabs(im->dz); /* 29 Jul 2002 */
5082 }
5083
5084 if( datum < 0 ) datum = im->kind ;
5085 if( ! AFNI_GOOD_DTYPE(datum) )
5086 ERROR_exit("Illegal datum type found in image") ;
5087
5088 dsize = mri_datum_size( (MRI_TYPE) datum ) ;
5089 bar = (char *) malloc( dsize * nx*ny*nz ) ;
5090 if( bar == NULL )
5091 ERROR_exit("Can't malloc memory for image input :-( !!!") ;
5092
5093 /*--- read all files, convert if needed, put in the cube ---*/
5094
5095 REPORT_PROGRESS("\nReading unoriented image data") ;
5096 kz = 0 ;
5097 for( lf=0 ; lf < nf ; lf++ ){
5098
5099 /** read the file (except the first, which we already have **/
5100
5101 if( lf != 0 ){
5102 STATUS("read next file") ;
5103 arr = mri_read_file( fname[lf] ) ;
5104 if( arr == NULL || arr->num == 0 )
5105 ERROR_exit("Cannot read image file: %s",fname[lf]) ;
5106 }
5107
5108 /** for each image in file ... **/
5109
5110 for( kim=0 ; kim < arr->num ; kim++ ){
5111 im = arr->imarr[kim] ;
5112
5113 /** check if image matches dimensions of first slice **/
5114
5115 if( im->nx != nx || im->ny != ny ){
5116 if( ! GLOBAL_argopt.resize_images ){
5117 sprintf(str, "Image size mismatch:\n"
5118 " ** expected nx=%d ny=%d but got nx=%d ny=%d in file %s" ,
5119 nx,ny,im->nx,im->ny , fname[lf] ) ;
5120 ERROR_exit(str) ;
5121 } else {
5122 MRI_IMAGE *rim ;
5123 rim = mri_resize( im , nx , ny ) ;
5124 mri_free( im ) ;
5125 im = rim ;
5126 }
5127 }
5128
5129 /** check if image data type matches the kind we want **/
5130
5131 if( im->kind == datum ){
5132 shim = im ;
5133 } else {
5134 shim = mri_to_mri( datum , im ) ;
5135 if( shim == NULL ) ERROR_exit("Illegal datum convert!") ;
5136 mri_free( im ) ;
5137 }
5138
5139 /** copy bytes from slice into the "bar" brick **/
5140
5141 memcpy( bar + dsize*npix*kz , mri_data_pointer(shim) , dsize*npix ) ;
5142 kz++ ;
5143
5144 mri_free(shim) ;
5145 if( kz%100 == 1 ) REPORT_PROGRESS(".") ;
5146 }
5147 FREE_IMARR(arr) ; /* not DESTROY_IMARR, since images are already gone */
5148 }
5149
5150 /*** special case of one input image: duplicate the image data ***/
5151
5152 if( kz == 1 && nz == 2 ){
5153 memcpy( bar + dsize*npix , bar , dsize*npix ) ;
5154 }
5155
5156 /*** tell the user what all we've read ***/
5157
5158 sprintf(str,": nx=%d ny=%d nslice=%d (%s)",nx,ny,nz,MRI_TYPE_name[datum]) ;
5159 REPORT_PROGRESS(str) ;
5160
5161 /*- 19 Oct 1999: if we are doing a -tim read,
5162 then have to setup the time and z dimensions -*/
5163
5164 if( GLOBAL_argopt.read_tim != 0 ){
5165
5166 if( GLOBAL_argopt.read_tim > 0 ){ /* 20 Oct 1999 */
5167 nzin = nzz = GLOBAL_argopt.read_tim ; /* -zim:nzz */
5168 nvals = nz / nzz ;
5169
5170 if( nvals*nzz != nz )
5171 fprintf(stderr,
5172 "\n** Warning: -zim:%d does not evenly divide"
5173 "number of 2D slices read=%d\n",
5174 nzz , nz ) ;
5175
5176 } else {
5177 nvals = - GLOBAL_argopt.read_tim ; /* -tim:nvals */
5178 nzin = nzz = nz / nvals ;
5179
5180 if( nvals*nzz != nz )
5181 fprintf(stderr,
5182 "\n** Warning: -tim:%d does not evenly divide"
5183 "number of 2D slices read=%d\n",
5184 nvals , nz ) ;
5185 }
5186
5187 if( nvals == 1 ){
5188 fprintf(stderr,
5189 "\n** Error: -tim or -zim has only 1 point in time!\n") ;
5190 exit(1) ;
5191 }
5192
5193 if( nzz == 1 ) nzz = 2 ; /* can't have just 1 slice */
5194
5195 } else { /* the old code */
5196 nvals = 1 ;
5197 nzz = nz ;
5198 }
5199
5200 /*--- now create the rest of the data structure, as far as we can ---*/
5201
5202 dset = myXtNew( THD_3dim_dataset ) ;
5203 dset->dblk = myXtNew( THD_datablock ) ;
5204 dset->daxes = myXtNew( THD_dataxes ) ;
5205 dset->dblk->diskptr = myXtNew( THD_diskptr ) ;
5206 dset->markers = NULL ;
5207 dset->warp = NULL ;
5208 dset->vox_warp = NULL ;
5209 dset->self_warp = NULL ; /* 26 Aug 2002 */
5210 dset->warp_parent = NULL ;
5211 dset->anat_parent = NULL ;
5212 dset->stats = NULL ;
5213 dset->death_mark = 0 ;
5214 dset->tcat_list = NULL ; /* 04 Aug 2004 */
5215 dset->tcat_num = 0 ;
5216 dset->tcat_len = NULL ;
5217 dset->taxis = NULL ;
5218 dset->tagset = NULL ; /* Oct 1998 */
5219 dset->Label_Dtable = NULL; /* ZSS Feb 26 2010 */
5220 ZERO_STAT_AUX( dset ) ;
5221 #ifdef ALLOW_DATASET_VLIST
5222 dset->pts = NULL ;
5223 #endif
5224
5225 INIT_KILL(dset->kl) ;
5226 INIT_KILL(dset->dblk->kl) ;
5227
5228 dset->dblk->diskptr->type = DISKPTR_TYPE ;
5229 dset->dblk->diskptr->rank = 3 ;
5230 dset->dblk->diskptr->nvals = nvals ; /* modified 19 Oct 1999 */
5231 dset->dblk->diskptr->dimsizes[0] = nx ;
5232 dset->dblk->diskptr->dimsizes[1] = ny ;
5233 dset->dblk->diskptr->dimsizes[2] = nzz ; /* modified 19 Oct 1999 */
5234 dset->dblk->diskptr->storage_mode = STORAGE_UNDEFINED ;
5235 dset->dblk->diskptr->byte_order = THD_get_write_order() ; /* 25 April 1998 */
5236
5237 dset->dblk->vedim = NULL ; /* 05 Sep 2006 */
5238
5239 EMPTY_STRING(dset->dblk->diskptr->prefix) ;
5240 EMPTY_STRING(dset->dblk->diskptr->viewcode) ;
5241 EMPTY_STRING(dset->dblk->diskptr->filecode) ;
5242 EMPTY_STRING(dset->dblk->diskptr->directory_name) ;
5243 EMPTY_STRING(dset->dblk->diskptr->header_name) ;
5244 EMPTY_STRING(dset->dblk->diskptr->brick_name) ;
5245
5246 dset->dblk->type = DATABLOCK_TYPE ;
5247 dset->dblk->nvals = nvals ; /* modified 19 Oct 1999 */
5248
5249 /** here is where we attach "bar" to the dataset **/
5250
5251 dset->dblk->malloc_type = DATABLOCK_MEM_MALLOC ;
5252 dset->dblk->brick_fac = NULL ; /* let THD_init_datablock_brick do these */
5253 dset->dblk->brick_bytes = NULL ;
5254 dset->dblk->brick = NULL ;
5255
5256 DSET_lock(dset) ; /* Feb 1998: lock into memory */
5257
5258 dset->dblk->brick_lab = NULL ; /* 30 Nov 1997 */
5259 dset->dblk->brick_keywords = NULL ;
5260 dset->dblk->brick_statcode = NULL ;
5261 dset->dblk->brick_stataux = NULL ;
5262 dset->keywords = NULL ;
5263
5264 THD_init_datablock_brick( dset->dblk , datum , NULL ) ;
5265
5266 if( nvals == 1 ){
5267
5268 mri_fix_data_pointer( bar , DSET_BRICK(dset,0) ) ; /* the attachment! */
5269
5270 } else { /* 19 Oct 1999: make up a lot of bricks and attach them all */
5271 /* 20 Oct 1999: allow for the 3rd dimension as well */
5272
5273 int iv , jj , kk ;
5274 char *qbar ;
5275
5276 for( iv=0 ; iv < nvals ; iv++ ){
5277 qbar = (char *) malloc( dsize*npix*nzz ) ; /* space for nzz slices */
5278
5279 if( GLOBAL_argopt.read_tim > 0 ){
5280 for( jj=0 ; jj < nzz ; jj++ ){ /* copy slices */
5281 kk = MIN(jj,nzin-1) ;
5282 memcpy( qbar + jj*dsize*npix ,
5283 bar + (iv*nzin+kk)*dsize*npix , dsize*npix ) ;
5284 }
5285 } else {
5286 for( jj=0 ; jj < nzz ; jj++ ){ /* copy slices */
5287 kk = MIN(jj,nzin-1) ;
5288 memcpy( qbar + jj*dsize*npix ,
5289 bar + (kk*nvals+iv)*dsize*npix , dsize*npix ) ;
5290 }
5291 }
5292
5293 mri_fix_data_pointer( qbar , DSET_BRICK(dset,iv) ) ;
5294 }
5295
5296 free(bar) ; /* not needed no more no how */
5297
5298 EDIT_dset_items( dset , ADN_ntt,nvals , ADN_ttdel,1.0 , ADN_none ) ;
5299 }
5300
5301 dset->dblk->natr = dset->dblk->natr_alloc = 0 ;
5302 dset->dblk->atr = NULL ;
5303 dset->dblk->parent = (XtPointer) dset ;
5304
5305 dset->daxes->type = DATAXES_TYPE ;
5306 dset->daxes->nxx = nx ;
5307 dset->daxes->nyy = ny ;
5308 dset->daxes->nzz = nzz ; /* modified 19 Oct 1999 */
5309 dset->daxes->xxdel = 1.0 ; /* arbitary units */
5310 dset->daxes->yydel = GLOBAL_argopt.dy ; /* these allow user to alter */
5311 dset->daxes->zzdel = GLOBAL_argopt.dz ; /* the images' aspect ratio */
5312 dset->daxes->xxorg = dset->daxes->yyorg = dset->daxes->zzorg = 0.0 ;
5313 dset->daxes->parent= (XtPointer) dset ;
5314
5315 if( dx > 0.0 ) dset->daxes->xxdel = dx ; /* 29 Jul 2002 */
5316 if( dy > 0.0 ) dset->daxes->yydel = dy ;
5317 if( dz > 0.0 ) dset->daxes->zzdel = dz ;
5318
5319 dset->idcode = MCW_new_idcode() ;
5320 ZERO_IDCODE(dset->anat_parent_idcode) ;
5321 ZERO_IDCODE(dset->warp_parent_idcode) ;
5322
5323 /* set the daxes orientation codes from the command line argument */
5324
5325 #define ORCODE(aa) \
5326 ( (aa)=='R' ? ORI_R2L_TYPE : (aa)=='L' ? ORI_L2R_TYPE : \
5327 (aa)=='P' ? ORI_P2A_TYPE : (aa)=='A' ? ORI_A2P_TYPE : \
5328 (aa)=='I' ? ORI_I2S_TYPE : (aa)=='S' ? ORI_S2I_TYPE : ILLEGAL_TYPE )
5329
5330 #define OR3OK(x,y,z) ( ((x)&6) + ((y)&6) + ((z)&6) == 6 )
5331
5332 { char acod ;
5333 int xx,yy,zz ;
5334
5335 acod = toupper(GLOBAL_argopt.orient_code[0]) ; xx = ORCODE(acod) ;
5336 acod = toupper(GLOBAL_argopt.orient_code[1]) ; yy = ORCODE(acod) ;
5337 acod = toupper(GLOBAL_argopt.orient_code[2]) ; zz = ORCODE(acod) ;
5338
5339 if( xx < 0 || yy < 0 || zz < 0 || ! OR3OK(xx,yy,zz) )
5340 ERROR_exit("Unusable -orient code!") ;
5341
5342 dset->daxes->xxorient = xx ;
5343 dset->daxes->yyorient = yy ;
5344 dset->daxes->zzorient = zz ;
5345 }
5346
5347 if( !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
5348 THD_daxes_to_mat44( dset->daxes ) ;
5349
5350 dset->wod_flag = False ; /* no warp-on-demand */
5351 dset->wod_daxes = NULL ; /* 02 Nov 1996 */
5352
5353 dset->type = GEN_ANAT_TYPE ;
5354 dset->view_type = dset->func_type = 0 ;
5355
5356 MCW_strncpy( dset->self_name , fname[0] , THD_MAX_NAME ) ;
5357 MCW_strncpy( dset->label1 , "Image Display Mode" , THD_MAX_LABEL ) ;
5358 EMPTY_STRING( dset->label2 ) ;
5359 EMPTY_STRING( dset->warp_parent_name ) ;
5360 EMPTY_STRING( dset->anat_parent_name ) ;
5361
5362 RETURN( dset ) ;
5363 }
5364
5365 /*----------------------------------------------------------------------*/
5366 /* Jumpto current cluster peak */
5367
AFNI_jumpto_clus(Three_D_View * im3d)5368 void AFNI_jumpto_clus( Three_D_View *im3d ) /* 19 Oct 2012 */
5369 {
5370 int ic ; float px,py,pz , xx,yy,zz ;
5371 AFNI_clu_widgets *cwid = im3d->vwid->func->cwid ;
5372 mri_cluster_detail *cld = im3d->vwid->func->clu_det ;
5373 if( cwid == NULL || cld == NULL ) return ;
5374 ic = AFNI_clus_find_xyz_nearest( im3d,
5375 im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ) ;
5376 if( ic < 0 ) return ;
5377 AFNI_clus_action_CB( cwid->clu_jump_pb[ic] , (XtPointer)im3d , (XtPointer)666 ) ;
5378 return ;
5379 }
5380
5381 /*----------------------------------------------------------------------*/
5382 /* Jumpto nearby cluster peak */
5383
AFNI_jumpto_clus_nearby(Three_D_View * im3d,int dci)5384 void AFNI_jumpto_clus_nearby( Three_D_View *im3d , int dci ) /* 29 Apr 2019 */
5385 {
5386 int ic,nic,nclu ; float px,py,pz , xx,yy,zz ;
5387 AFNI_clu_widgets *cwid = im3d->vwid->func->cwid ;
5388 mri_cluster_detail *cld = im3d->vwid->func->clu_det ;
5389 MCW_cluster_array *clar ; MCW_cluster *cl ;
5390
5391 if( cwid == NULL || cld == NULL ) return ;
5392 clar = im3d->vwid->func->clu_list ; if( clar == NULL ) return ;
5393 nclu = clar->num_clu ; if( nclu == 0 ) return ;
5394 ic = AFNI_clus_find_xyz( im3d,
5395 im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ) ;
5396 if( ic >= 0 ){
5397 nic = ic + dci ;
5398 if( nic >= nclu ) nic = nic % nclu ;
5399 else if( nic < 0 ) nic = (nic + 99*nclu) % nclu ;
5400 } else {
5401 nic = AFNI_clus_find_xyz_nearest( im3d,
5402 im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ) ;
5403 }
5404 if( nic < 0 ) return ;
5405 AFNI_clus_action_CB( cwid->clu_jump_pb[nic], (XtPointer)im3d, (XtPointer)666 ) ;
5406 return ;
5407 }
5408
5409 /*----------------------------------------------------------------------
5410 respond to events that one of the MCW_imseq's sends to us
5411 ------------------------------------------------------------------------*/
5412
AFNI_seq_send_CB(MCW_imseq * seq,FD_brick * br,ISQ_cbs * cbs)5413 void AFNI_seq_send_CB( MCW_imseq *seq , FD_brick *br , ISQ_cbs *cbs )
5414 {
5415 Three_D_View *im3d = (Three_D_View *) seq->parent ;
5416
5417 ENTRY("AFNI_seq_send_CB") ;
5418
5419 if(PRINT_TRACING)
5420 { char str[256] ; sprintf(str,"reason=%d",cbs->reason) ; STATUS(str) ; }
5421
5422 if( ! IM3D_VALID(im3d) ||
5423 ( im3d->ignore_seq_callbacks == AFNI_IGNORE_EVERYTHING
5424 && cbs->reason != isqCR_getxynim ) ){
5425
5426 STATUS("ignoring call") ; EXRETURN ;
5427 }
5428
5429 switch( cbs->reason ){
5430
5431 default: break ;
5432
5433 case isqCR_destroy:{
5434 MCW_imseq *sxyz = im3d->s123 ,
5435 *syzx = im3d->s231 ,
5436 *szxy = im3d->s312 ;
5437 Widget w ;
5438 int a3 = br->a123.ijk[2] , /* z axis of the brick? */
5439 az = abs(a3) - 1 ; /* 0,1,2 for dataset x,y,z */
5440
5441 if( seq == sxyz ){
5442 w = im3d->vwid->imag->image_xyz_pb ; im3d->s123 = NULL ; }
5443 else if( seq == syzx ){
5444 w = im3d->vwid->imag->image_yzx_pb ; im3d->s231 = NULL ; }
5445 else if( seq == szxy ){
5446 w = im3d->vwid->imag->image_zxy_pb ; im3d->s312 = NULL ; }
5447 else
5448 EXRETURN ; /* something goofy happened? */
5449
5450 myXtFree( seq->status ) ; /* 28 Sep 1998: via Purify */
5451 myXtFree( seq ) ;
5452 MCW_invert_widget(w) ; /* back to normal */
5453 NORMAL_cursorize(w) ; /* 20 Jul 2005 */
5454 INIT_BKGD_LAB(im3d) ;
5455 AFNI_view_setter(im3d,NULL) ;
5456
5457 /* July 1996: redraw if we just lost a crosshair montage
5458 (it would have been in the z direction of the brick) */
5459
5460 if( im3d->vinfo->xhairs_ndown.ijk[az] > 0 ||
5461 im3d->vinfo->xhairs_nup.ijk[az] > 0 ){
5462
5463 if(PRINT_TRACING)
5464 { char str[256] ;
5465 sprintf(str,"imseq close on axis %d --> lost xhairs in that direction",az) ;
5466 STATUS(str) ; }
5467
5468 CLEAR_MONTAGE(im3d,br) ;
5469
5470 if( im3d->vinfo->xhairs_show_montage &&
5471 im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5472
5473 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
5474 }
5475 }
5476 }
5477 MPROBE ;
5478 break ; /* end of destroy */
5479
5480 case isqCR_buttonmove:{ /* 17 Mar 2010: InstaCorr on the go go go! */
5481 XMotionEvent *xev = (XMotionEvent *)cbs->event ;
5482
5483 if( im3d->ignore_seq_callbacks != AFNI_IGNORE_NOTHING ) EXRETURN ;
5484 if( !(xev->state&ShiftMask) || !(xev->state&ControlMask) ) EXRETURN ;
5485
5486 if( cbs->xim >= 0 && cbs->xim < br->n1 &&
5487 cbs->yim >= 0 && cbs->yim < br->n2 &&
5488 cbs->nim >= 0 && cbs->nim < br->n3 ){ /* inside brick? */
5489
5490 THD_ivec3 id ; int qq , ii,jj,kk ;
5491
5492 /* find location in underlay dataset */
5493
5494 id = THD_fdind_to_3dind(br,TEMP_IVEC3(cbs->xim,cbs->yim,cbs->nim));
5495 UNLOAD_IVEC3(id,ii,jj,kk) ;
5496
5497 qq = AFNI_icor_setref_anatijk(im3d,ii,jj,kk) ;
5498 if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ;
5499 }
5500 }
5501 MPROBE ;
5502 break ; /* end of button move (while clicked down) */
5503
5504 case isqCR_buttonpress:{
5505 XButtonEvent *xev = (XButtonEvent *)cbs->event ;
5506 int doing_icor = ( (xev->state&ShiftMask) && (xev->state&ControlMask) ) ;
5507 int doing_jump = AFNI_yesenv("AFNI_INSTACORR_JUMP") ;
5508
5509 if(PRINT_TRACING){
5510 char str[256] ;
5511 sprintf(str,"isqCR_buttonpress: button=%d state=%x",(int)xev->button,xev->state) ;
5512 STATUS(str) ; }
5513
5514 im3d->vwid->butx = xev->x_root ; /* 17 May 2005 */
5515 im3d->vwid->buty = xev->y_root ;
5516 switch( xev->button ){
5517
5518 default: EXRETURN ; /* unused button */
5519
5520 case Button3:{ /* popup menu */
5521 XtVaSetValues( im3d->vwid->imag->popmenu ,
5522 XmNuserData , (XtPointer) seq , /* who */
5523 NULL ) ;
5524 XmMenuPosition( im3d->vwid->imag->popmenu , xev ) ; /* where */
5525 XtManageChild ( im3d->vwid->imag->popmenu ) ; /* pop */
5526 }
5527 break ;
5528
5529 case Button1:{ /* set viewpoint? set InstaCorr? */
5530 THD_ivec3 id ;
5531
5532 /* April 1996: only use this button press if
5533 it is inside the confines of the brick */
5534
5535 if(PRINT_TRACING)
5536 { char str[256] ;
5537 sprintf(str,"Button1 at %d %d %d",
5538 cbs->xim,cbs->yim,cbs->nim) ; STATUS(str) ; }
5539
5540 if( cbs->xim >= 0 && cbs->xim < br->n1 &&
5541 cbs->yim >= 0 && cbs->yim < br->n2 &&
5542 cbs->nim >= 0 && cbs->nim < br->n3 ){
5543
5544 /* get index triple in 3D dataset from viewing FD brick */
5545
5546 id = THD_fdind_to_3dind(
5547 br , TEMP_IVEC3(cbs->xim,cbs->yim,cbs->nim) );
5548
5549 if(PRINT_TRACING)
5550 { char str[256] ;
5551 sprintf(str," 3D dataset coordinates %d %d %d",
5552 id.ijk[0],id.ijk[1],id.ijk[2] ) ; STATUS(str) ; }
5553
5554 /* jump viewpoint (crosshairs) to the selected point */
5555
5556 if( !doing_icor || (doing_icor && doing_jump) ){
5557 SAVE_VPT(im3d) ; /* save current location as jumpback */
5558
5559 if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5560
5561 /* 20 Feb 2003: set plane from which viewpoint is controlled */
5562
5563 AFNI_view_setter(im3d,seq) ;
5564 AFNI_set_viewpoint(
5565 im3d , id.ijk[0] , id.ijk[1] , id.ijk[2] ,
5566 (im3d->vinfo->crosshair_visible==True) ?
5567 REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
5568 }
5569 }
5570
5571 /* 08 May 2009: if Shift+Control both pressed, do InstaCorr */
5572
5573 if( doing_icor ){
5574 int qq = AFNI_icor_setref_anatijk(im3d,id.ijk[0],id.ijk[1],id.ijk[2]) ;
5575 if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ; /* 15 May 2009 */
5576 }
5577 }
5578 } /* end of button 1 */
5579 break ;
5580 } /* end of switch on which button */
5581 }
5582 break ; /* end of button press */
5583
5584 case isqCR_newimage:{
5585 THD_ivec3 id ;
5586
5587 id = THD_fdind_to_3dind( br, TEMP_IVEC3(-99999,-99999,cbs->nim) );
5588
5589 if(PRINT_TRACING)
5590 { char str[256] ;
5591 sprintf(str,"newimage input %d -> %d %d %d",
5592 cbs->nim , id.ijk[0],id.ijk[1],id.ijk[2] ) ;
5593 STATUS(str) ; }
5594
5595 if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5596
5597 /* 20 Feb 2003: set plane from which viewpoint is controlled */
5598
5599 AFNI_view_setter(im3d,seq) ;
5600 AFNI_set_viewpoint(
5601 im3d , id.ijk[0] , id.ijk[1] , id.ijk[2] ,
5602 (im3d->vinfo->crosshair_visible==True) ?
5603 REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
5604 }
5605 }
5606 break ; /* end of new image */
5607
5608 /** July 1996: an image viewer changed montage layout **/
5609
5610 case isqCR_newmontage:{
5611 THD_ivec3 *minf = (THD_ivec3 *) cbs->userdata ;
5612 int ndown = minf->ijk[0], nup = minf->ijk[1], nskip = minf->ijk[2] ;
5613 int a3 = br->a123.ijk[2] , /* z axis of the brick? */
5614 az = abs(a3) - 1 ; /* 0,1,2 for dataset x,y,z */
5615
5616 if(PRINT_TRACING)
5617 { char str[256] ;
5618 sprintf(str,"newmontage: ndown=%d nup=%d nskip=%d a3=%d (on axis az=%d)",
5619 ndown,nup,nskip,a3,az) ; STATUS(str) ; }
5620
5621 im3d->vinfo->xhairs_nskip.ijk[az] = nskip ;
5622
5623 if( a3 > 0 ){
5624 im3d->vinfo->xhairs_ndown.ijk[az] = ndown ;
5625 im3d->vinfo->xhairs_nup.ijk[az] = nup ;
5626 } else {
5627 im3d->vinfo->xhairs_ndown.ijk[az] = nup ;
5628 im3d->vinfo->xhairs_nup.ijk[az] = ndown ;
5629 }
5630
5631 if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING )
5632 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
5633 }
5634 break ;
5635
5636 /* 30 Dec 1998: return the current focus position */
5637
5638 case isqCR_getxynim:{
5639 THD_ivec3 ib ;
5640
5641 ib = THD_3dind_to_fdind( br , TEMP_IVEC3( im3d->vinfo->i1 ,
5642 im3d->vinfo->j2 ,
5643 im3d->vinfo->k3 ) ) ;
5644
5645 cbs->xim = ib.ijk[0] ; cbs->yim = ib.ijk[1] ; cbs->nim = ib.ijk[2] ;
5646 }
5647 break ; /* end of getxynim */
5648
5649 /* Arrowpad stuff */
5650
5651 case isqCR_appress:{
5652 if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5653 AFNI_view_setter(im3d,seq) ;
5654 AFNI_crosshair_gap_CB( NULL , (XtPointer) im3d ) ;
5655 }
5656 }
5657 break ; /* end of arrowpad center key press */
5658
5659 case isqCR_dxplus:
5660 case isqCR_dxminus:
5661 case isqCR_dyplus:
5662 case isqCR_dyminus:{
5663 THD_ivec3 ib , id ;
5664 XButtonEvent *xev = (XButtonEvent *) cbs->event ;
5665 int step = 1 ;
5666 THD_dataxes *daxes ;
5667
5668 if( xev != NULL &&
5669 ( xev->type == ButtonPress ||
5670 xev->type == ButtonRelease ) &&
5671 (xev->state & (ShiftMask | ControlMask)) ) step = INIT_bigscroll ;
5672
5673 ib = THD_3dind_to_fdind( br , TEMP_IVEC3( im3d->vinfo->i1 ,
5674 im3d->vinfo->j2 ,
5675 im3d->vinfo->k3 ) ) ;
5676 switch( cbs->reason ){
5677 case isqCR_dxplus: ib.ijk[0] += step ; break ;
5678 case isqCR_dxminus: ib.ijk[0] -= step ; break ;
5679 case isqCR_dyplus: ib.ijk[1] += step ; break ;
5680 case isqCR_dyminus: ib.ijk[1] -= step ; break ;
5681 }
5682
5683 id = THD_fdind_to_3dind( br , ib ) ;
5684
5685 /* 13 May 2003: allow for wraparound */
5686
5687 LOAD_DSET_VIEWS(im3d) ; /* 20 Nov 2003 */
5688 daxes = CURRENT_DAXES(im3d->anat_now) ;
5689 if( id.ijk[0] < 0 ) id.ijk[0] += daxes->nxx ;
5690 else if( id.ijk[0] >= daxes->nxx ) id.ijk[0] -= daxes->nxx ;
5691 if( id.ijk[1] < 0 ) id.ijk[1] += daxes->nyy ;
5692 else if( id.ijk[1] >= daxes->nyy ) id.ijk[1] -= daxes->nyy ;
5693 if( id.ijk[2] < 0 ) id.ijk[2] += daxes->nzz ;
5694 else if( id.ijk[2] >= daxes->nzz ) id.ijk[2] -= daxes->nzz ;
5695
5696 if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5697
5698 /* 20 Feb 2003: set plane from which viewpoint is controlled */
5699
5700 AFNI_view_setter(im3d,seq) ;
5701 AFNI_set_viewpoint(
5702 im3d , id.ijk[0] , id.ijk[1] , id.ijk[2] ,
5703 (im3d->vinfo->crosshair_visible==True) ?
5704 REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
5705 }
5706 }
5707 break ; /* end of arrowpad arrow press */
5708
5709 case isqCR_keypress:{
5710 #if 1
5711 switch( cbs->key ){ /* 05 Mar 2007: keys that AFNI needs */
5712 /* to process, not imseq.c */
5713 case 'U':
5714 case 'u':{
5715 int uu = im3d->vinfo->underlay_type ; /* toggle Overlay as Underlay */
5716 uu = (uu+1) % (LAST_UNDERLAY_TYPE+1) ;
5717 #ifdef USE_UNDERLAY_BBOX
5718 MCW_set_bbox( im3d->vwid->func->underlay_bbox , 1<<uu ) ;
5719 AFNI_underlay_CB( im3d->vwid->func->underlay_bbox->wbut[0] , im3d , NULL ) ;
5720 #else
5721 im3d->vinfo->underlay_type = uu ;
5722 AFNI_underlay_CB( NULL , im3d , (XtPointer)666 ) ;
5723 if( cbs->key == 'U' ){
5724 int qq ; Three_D_View *qq3d ;
5725 for( qq=0 ; qq < MAX_CONTROLLERS ; qq++ ){
5726 qq3d = GLOBAL_library.controllers[qq] ;
5727 if( qq3d == im3d || !IM3D_OPEN(qq3d) ) continue ;
5728 qq3d->vinfo->underlay_type = uu ;
5729 AFNI_underlay_CB( NULL , qq3d , (XtPointer)666 ) ;
5730 }
5731 }
5732 #endif
5733 }
5734 break ;
5735
5736 case 'o':{ /* turn overlay on or off */
5737 int ov = MCW_val_bbox( im3d->vwid->view->see_func_bbox ) ;
5738 MCW_set_bbox( im3d->vwid->view->see_func_bbox , !ov ) ;
5739 AFNI_see_func_CB( NULL , im3d , NULL ) ;
5740 }
5741 break ;
5742
5743 case '{': /* Actually: Mod+Button4/5 = Mod+ScrollWheel */
5744 case '}':{ /* Change the threshold slider up or down */
5745 int scl ; float fff,dff,nff ;
5746 XmScaleGetValue( im3d->vwid->func->thr_scale , &scl ) ;
5747 fff = scl * im3d->vinfo->func_thresh_top * THR_factor ;
5748 dff = im3d->vinfo->func_thresh_top * 0.01f ;
5749 if( cbs->key == '{' ) dff = -dff ;
5750 nff = fff+dff ;
5751 if( nff < 0.0f ) nff = 0.0f ;
5752 else if( nff > THR_top_value ) nff = THR_top_value ;
5753 if( nff != fff ) AFNI_set_threshold( im3d , nff ) ;
5754 }
5755 break ;
5756
5757 case 'j': /* jump to cluster peak -- for Dale [17 Oct 2012] */
5758 AFNI_jumpto_clus(im3d) ;
5759 break ;
5760
5761 case 'N': /* jump to nearby cluster [29 Apr 2019] */
5762 case 'n':{ /* (for John Butman) */
5763 int dci = (cbs->key == 'n') ? 1 : -1 ;
5764 AFNI_jumpto_clus_nearby(im3d,dci) ;
5765 }
5766 break ;
5767
5768 case 'f':{ /* flash cluster [17 Oct 2012] */
5769 int ic ; float px,py,pz , xx,yy,zz ;
5770 AFNI_clu_widgets *cwid = im3d->vwid->func->cwid ;
5771 mri_cluster_detail *cld = im3d->vwid->func->clu_det ;
5772 if( cwid == NULL || cld == NULL ){ BEEPIT ; break ; }
5773 ic = AFNI_clus_find_xyz( im3d ,
5774 im3d->vinfo->xi , im3d->vinfo->yj , im3d->vinfo->zk ) ;
5775 if( ic < 0 ){ BEEPIT ; break ; }
5776 AFNI_clus_action_CB( cwid->clu_flsh_pb[ic] , (XtPointer)im3d , NULL ) ;
5777 }
5778 break ;
5779
5780 }
5781
5782 #else /* OLD OLD OLD */
5783 MCW_grapher *grapher = VIEWER_TO_GRAPHER(im3d,seq) ;
5784 if( grapher != NULL ){
5785 char buf[2] ;
5786 buf[0] = cbs->key ; buf[1] = '\0' ;
5787 GRA_handle_keypress( grapher , buf , cbs->event ) ;
5788 }
5789 #endif
5790 }
5791 break ; /* end of keyboard press */
5792
5793 /*--- 20 Feb 2003: keypress while in button2 mode ---*/
5794
5795 case isqCR_button2_key:{
5796 KeySym ks = (KeySym) cbs->key ;
5797
5798 switch( ks ){
5799 case XK_Delete:
5800 AFNI_process_drawing( im3d , UNDO_MODE , 0,NULL,NULL,NULL ) ;
5801 break ;
5802
5803 case XK_F4:
5804 case XK_F3: /* 13 Sep 2008 */
5805 AFNI_process_drawing( im3d ,
5806 (ks==XK_F3) ? DECVAL_MODE : INCVAL_MODE , 0,NULL,NULL,NULL ) ;
5807 break ;
5808 }
5809 }
5810 break ; /* end of button2 mode keypress */
5811
5812 /*--- Feb 1998: list of coordinates from button2 drawing ---*/
5813
5814 case isqCR_button2_points:{
5815 int npts = cbs->key , zim = cbs->nim ;
5816 int *xyout = (int *) cbs->userdata ;
5817 THD_ivec3 id ;
5818 int nvec , ii , xim,yim , fixed_plane ;
5819 int *xdset , *ydset , *zdset ;
5820
5821 if( zim >= 0 && zim < br->n3 && npts > 0 ){ /* if input is good */
5822
5823 /* make space for translated coordinates */
5824
5825 xdset = (int *) malloc( npts * sizeof(int) ) ;
5826 ydset = (int *) malloc( npts * sizeof(int) ) ;
5827 zdset = (int *) malloc( npts * sizeof(int) ) ;
5828
5829 /* translate coordinates to dataset xyz indices,
5830 casting out any that are outside the dataset brick */
5831
5832 nvec = 0 ;
5833 for( ii=0 ; ii < npts ; ii++ ){
5834 xim = xyout[2*ii] ; yim = xyout[2*ii+1] ;
5835
5836 /* skip points not in the volume */
5837
5838 if( xim >= 0 && xim < br->n1 && yim >= 0 && yim < br->n2 ){
5839
5840 id = THD_fdind_to_3dind( br , TEMP_IVEC3(xim,yim,zim) );
5841 xdset[nvec] = id.ijk[0] ;
5842 ydset[nvec] = id.ijk[1] ;
5843 zdset[nvec] = id.ijk[2] ;
5844
5845 /* skip sequentially duplicate points */
5846
5847 if( nvec == 0 ||
5848 xdset[nvec] != xdset[nvec-1] ||
5849 ydset[nvec] != ydset[nvec-1] ||
5850 zdset[nvec] != zdset[nvec-1] ) nvec++ ;
5851 }
5852 }
5853
5854 /* send coordinates to processing routine */
5855
5856 fixed_plane = abs(br->a123.ijk[2]) ;
5857
5858 if( nvec > 0 ) AFNI_process_drawing( im3d ,
5859 PLANAR_MODE+fixed_plane ,
5860 nvec,xdset,ydset,zdset ) ;
5861
5862 /* free coordinate memory */
5863
5864 free(xdset) ; free(ydset) ; free(zdset) ;
5865 }
5866 }
5867 break ; /* end of button2 coordinates */
5868
5869 /*--- 22 Aug 1998: redraw everything ---*/
5870
5871 case isqCR_force_redisplay:{
5872 AFNI_view_setter(im3d,seq) ;
5873 PLUTO_force_redisplay() ; /* see afni_plugin.c */
5874 PLUTO_force_rebar() ; /* ditto [23 Aug 1998] */
5875 }
5876 break ; /* end of forced redisplay */
5877
5878 /*--- 06 Jun 2019: force opacity change ---*/
5879
5880 case isqCR_opacitychange:{
5881 int opval = cbs->nim ;
5882 if( opval > 0 && opval <= 9 && opval != GLOBAL_library.opacity_setting ){
5883 GLOBAL_library.opacity_setting = opval ;
5884 PLUTO_force_opacity_change() ;
5885 }
5886 }
5887 break ; /* end of opacity change */
5888
5889 /*--- 10 Dec 2019: zoom change ---*/
5890
5891 case isqCR_zoomchange:{
5892 AFNI_zoompan_lock_carryout(im3d) ;
5893 }
5894 break ; /* end of opacity change */
5895
5896 /*--- 26 Apr 2007: time indexing ---*/
5897
5898 case isqCR_setindex:{
5899 MCW_arrowval *tav = im3d->vwid->imag->time_index_av ;
5900 MCW_arrowval *aav = im3d->vwid->func->anat_buck_av ;
5901 int new_index = im3d->vinfo->anat_index + cbs->key ;
5902
5903 if( new_index != im3d->vinfo->anat_index ){
5904 if( im3d->vinfo->time_on ){
5905 AV_assign_ival( tav , new_index ) ; /* set time_index */
5906 AFNI_time_index_CB( tav, (XtPointer) im3d ); /* will set anat_index */
5907 } else {
5908 AV_assign_ival( aav, new_index ) ; /* set anat index directly */
5909 AFNI_bucket_CB( aav, im3d ) ;
5910 }
5911 }
5912 }
5913 break ;
5914
5915 /*--- raise the controller [17 Jun 2011] ---*/
5916
5917 case isqCR_raiseupthedead:{
5918 if( IM3D_OPEN(im3d) ) XMapRaised( XtDisplay(im3d->vwid->top_shell) ,
5919 XtWindow(im3d->vwid->top_shell) ) ;
5920 }
5921 break ;
5922
5923 /*--- cycle global range [03 Feb 2013] ---*/
5924 case isqCR_globalrange:{
5925 int ig;
5926 THD_cycle_image_globalrange();
5927 ig = THD_get_image_globalrange();
5928 THD_set_image_globalrange_env(ig);
5929 ENV_globalrange_view( "AFNI_IMAGE_GLOBALRANGE" );
5930 }
5931 break ;
5932
5933 /*--- reset global range to use new environment value set elsewhere [03 Feb 2013] ---*/
5934 case isqCR_resetglobalrange:{
5935 int ig;
5936 ig = THD_get_image_globalrange();
5937 THD_set_image_globalrange_env(ig);
5938 ENV_globalrange_view( "AFNI_IMAGE_GLOBALRANGE" );
5939 }
5940 break ;
5941
5942 } /* end of switch on reason for call */
5943
5944 EXRETURN ;
5945 }
5946
5947 /*----------------------------------------------------------------------
5948 respond to events that one of the MCW_grapher's sends to us
5949 ------------------------------------------------------------------------*/
5950
AFNI_gra_send_CB(MCW_grapher * grapher,FD_brick * br,GRA_cbs * cbs)5951 void AFNI_gra_send_CB( MCW_grapher *grapher , FD_brick *br , GRA_cbs *cbs )
5952 {
5953 Three_D_View *im3d = (Three_D_View *)grapher->parent ;
5954
5955 ENTRY("AFNI_gra_send_CB") ;
5956
5957 if(PRINT_TRACING)
5958 { char str[256] ; sprintf(str,"reason=%d",cbs->reason) ; STATUS(str) ; }
5959
5960 if( ! IM3D_VALID(im3d) ||
5961 (im3d->ignore_seq_callbacks==AFNI_IGNORE_EVERYTHING) ) EXRETURN ;
5962
5963 switch( cbs->reason ){
5964
5965 default: break ; /* unimplemented reasons */
5966
5967 /*** 17 Jun 2011 ***/
5968
5969 case graCR_raiseupthedead:{
5970 if( IM3D_OPEN(im3d) ) XMapRaised( XtDisplay(im3d->vwid->top_shell) ,
5971 XtWindow(im3d->vwid->top_shell) ) ;
5972 }
5973 break ;
5974
5975 /*** Death ***/
5976
5977 case graCR_destroy:{
5978 MCW_grapher *gxyz = im3d->g123 ,
5979 *gyzx = im3d->g231 ,
5980 *gzxy = im3d->g312 ;
5981 MCW_imseq *seq = GRAPHER_TO_VIEWER(im3d,grapher) ;
5982 Widget w ;
5983
5984 if( grapher == gxyz ){
5985 w = im3d->vwid->imag->graph_xyz_pb ; im3d->g123 = NULL ;
5986 STATUS("destruction of g123") ;
5987 }
5988 else if( grapher == gyzx ){
5989 w = im3d->vwid->imag->graph_yzx_pb ; im3d->g231 = NULL ;
5990 STATUS("destruction of g231") ;
5991 }
5992 else if( grapher == gzxy ){
5993 w = im3d->vwid->imag->graph_zxy_pb ; im3d->g312 = NULL ;
5994 STATUS("destruction of g312") ;
5995 }
5996 else
5997 EXRETURN ; /* something goofy happened? */
5998
5999 myXtFree( grapher->status ) ; /* 08 Mar 1999: via mcw_malloc.c */
6000 myXtFree( grapher ) ; /* free the data space */
6001 MCW_invert_widget(w) ; /* back to normal */
6002 NORMAL_cursorize(w) ; /* 20 Jul 2005 */
6003
6004 /* redisplay the crosshairs, if needed */
6005
6006 if( seq != NULL && im3d->vinfo->crosshair_visible==True &&
6007 im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING )
6008
6009 drive_MCW_imseq( seq , isqDR_overlay , (XtPointer) -1 ) ;
6010 }
6011 MPROBE ;
6012 break ; /* end of destroy */
6013
6014 /*** User sets new location ***/
6015
6016 case graCR_newxyzm:{
6017 THD_ivec3 id ;
6018
6019 if( cbs->xcen >= 0 && cbs->xcen < br->n1 &&
6020 cbs->ycen >= 0 && cbs->ycen < br->n2 &&
6021 cbs->zcen >= 0 && cbs->zcen < br->n3 ){
6022
6023 id = THD_fdind_to_3dind(
6024 br , TEMP_IVEC3(cbs->xcen,cbs->ycen,cbs->zcen) );
6025
6026 if(PRINT_TRACING)
6027 { char str[256] ;
6028 sprintf(str," 3D dataset coordinates %d %d %d",
6029 id.ijk[0],id.ijk[1],id.ijk[2] ) ; STATUS(str) ; }
6030
6031 if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
6032 AFNI_view_setter(im3d,NULL) ;
6033 AFNI_set_viewpoint(
6034 im3d ,
6035 id.ijk[0] , id.ijk[1] , id.ijk[2] ,
6036 (im3d->vinfo->crosshair_visible==True) ?
6037 REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
6038 }
6039 }
6040 }
6041 break ; /* end of newxyzm */
6042
6043 /*** User asks for a reference function ***/
6044
6045 case graCR_pickref:{
6046
6047 STATUS("graCR_pickref") ;
6048
6049 if( IMARR_COUNT(GLOBAL_library.timeseries) > 0 ){
6050 int init_ts = AFNI_ts_in_library( im3d->fimdata->fimref ) ;
6051
6052 MCW_choose_timeseries( grapher->fdw_graph , "FIM Reference Vector" ,
6053 GLOBAL_library.timeseries , init_ts ,
6054 AFNI_fimmer_pickref_CB , (XtPointer) im3d ) ;
6055 } else {
6056 (void) MCW_popup_message(
6057 grapher->option_rowcol ,
6058 "No timeseries library\nexists to pick from!" ,
6059 MCW_USER_KILL | MCW_TIMER_KILL ) ;
6060 }
6061 }
6062 break ; /* end of pickref */
6063
6064 /*** User asks for an ort function ***/
6065
6066 case graCR_pickort:{
6067
6068 STATUS("graCR_pickort") ;
6069
6070 if( IMARR_COUNT(GLOBAL_library.timeseries) > 0 ){
6071 int init_ts = AFNI_ts_in_library( im3d->fimdata->fimort ) ;
6072
6073 MCW_choose_timeseries( grapher->fdw_graph , "FIM Ort Vector" ,
6074 GLOBAL_library.timeseries , init_ts ,
6075 AFNI_fimmer_pickort_CB , (XtPointer) im3d ) ;
6076 } else {
6077 (void) MCW_popup_message(
6078 grapher->option_rowcol ,
6079 "No timeseries library\nexists to pick from!" ,
6080 MCW_USER_KILL | MCW_TIMER_KILL ) ;
6081 }
6082 }
6083 break ; /* end of pickort */
6084
6085
6086 /*** User asks to clear FIM ***/
6087
6088 case graCR_clearfim:{
6089 AFNI_fimmer_setref( im3d , NULL ) ;
6090 im3d->fimdata->refadd_count = 0 ;
6091 }
6092 break ; /* end of clearfim */
6093
6094 /*** User asks to clear Ort ***/
6095
6096 case graCR_clearort:{
6097 AFNI_fimmer_setort( im3d , NULL ) ;
6098 }
6099 break ; /* end of clearfim */
6100
6101 /*** 27 Jan 2004:
6102 User toggled WinAver on in one graph window,
6103 so we toggle it off in the other windows. ***/
6104
6105 case graCR_winaver:{
6106 if( im3d->g123 != NULL && im3d->g123 != grapher )
6107 drive_MCW_grapher( im3d->g123 , graDR_winaver , 0 ) ;
6108 if( im3d->g231 != NULL && im3d->g231 != grapher )
6109 drive_MCW_grapher( im3d->g231 , graDR_winaver , 0 ) ;
6110 if( im3d->g312 != NULL && im3d->g312 != grapher )
6111 drive_MCW_grapher( im3d->g312 , graDR_winaver , 0 ) ;
6112 }
6113 break ; /* end of winaver */
6114
6115 /*** 12 Nov 1996:
6116 User supplies a timeseries to add to the global library ***/
6117
6118 case graCR_timeseries_library:{
6119 MRI_IMAGE *tsim = (MRI_IMAGE *) cbs->userdata ;
6120
6121 AFNI_add_timeseries( tsim ) ;
6122 }
6123 break ; /* end of timeseries_library */
6124
6125 /*** User supplies a timeseries for FIM (equals or add) ***/
6126
6127 case graCR_refadd:
6128 case graCR_refequals:{
6129 MRI_IMAGE *tsim = (MRI_IMAGE *) cbs->userdata ;
6130 MRI_IMAGE *qim , *sim ;
6131 float *sar , *qar ;
6132
6133 if( tsim != NULL ){
6134 qim = mri_to_float( tsim ) ; /* make a copy of input */
6135 if( im3d->fimdata->fimref == NULL ||
6136 cbs->reason == graCR_refequals ||
6137 im3d->fimdata->refadd_count < 1 ){
6138
6139 /** equals **/
6140
6141 AFNI_fimmer_setref( im3d , qim ) ;
6142 im3d->fimdata->refadd_count = 1 ;
6143
6144 } else {
6145 int jj,ii , nxs , nyy , nxq , nxx , npix ;
6146 float fs , fq ;
6147
6148 /** average **/
6149
6150 sim = mri_to_float( im3d->fimdata->fimref ) ; /* add into this copy */
6151 sar = MRI_FLOAT_PTR(sim) ;
6152 qar = MRI_FLOAT_PTR(qim) ;
6153 nxs = sim->nx ; nxq = qim->nx ; nxx = MIN(nxs,nxq) ;
6154 nyy = MIN( sim->ny , qim->ny ) ;
6155 npix = MIN( sim->nvox , qim->nvox ) ;
6156
6157 fq = 1.0/( im3d->fimdata->refadd_count + 1.0 ) ;
6158 fs = 1.0 - fq ;
6159
6160 for( jj=0 ; jj < nyy ; jj++ ){
6161 for( ii=0 ; ii < nxx ; ii++ ){
6162 if( sar[ii+jj*nxs] >= WAY_BIG || qar[ii+jj*nxq] >= WAY_BIG )
6163 sar[ii+jj*nxs] = WAY_BIG ;
6164 else
6165 sar[ii+jj*nxs] = fs * sar[ii+jj*nxs] + fq * qar[ii+jj*nxq] ;
6166 }
6167 }
6168 mri_free( qim ) ;
6169
6170 AFNI_fimmer_setref( im3d , sim ) ; /* since caller may free it later */
6171 im3d->fimdata->refadd_count++ ;
6172 }
6173 }
6174 }
6175 break ;
6176
6177 /*** User asks to smooth reference ***/
6178
6179 case graCR_refsmooth:{
6180 if( im3d->fimdata->fimref != NULL ){
6181 MRI_IMAGE *sim = mri_to_float(im3d->fimdata->fimref) ; /* copy */
6182 float *sar = MRI_FLOAT_PTR(sim) ;
6183 float aa,bb,cc ;
6184 int ii,jj , nx=sim->nx , ny=sim->ny ;
6185
6186 for( jj=0 ; jj < ny ; jj++ ){
6187 bb = sar[jj*nx] ; cc = sar[1+jj*nx] ;
6188 for( ii=1 ; ii < nx-1 ; ii++ ){
6189 aa = bb ; bb = cc ; cc = sar[ii+1+jj*nx] ;
6190 if( aa < WAY_BIG && bb < WAY_BIG &&
6191 cc < WAY_BIG && ii > im3d->fimdata->init_ignore )
6192 sar[ii+jj*nx] = OSFILT(aa,bb,cc) ;
6193 }
6194 }
6195 AFNI_fimmer_setref( im3d , sim ) ;
6196 }
6197 }
6198 break ;
6199
6200 /*** User asks to do fim! ***/
6201
6202 case graCR_dofim:{
6203 AFNI_fimmer_execute( im3d , cbs->key , cbs->mat ) ;
6204 }
6205 break ; /* end of dofim */
6206
6207 /*** User sets initial ignore count ***/
6208
6209 case graCR_setignore:{
6210 AFNI_fimmer_setignore( im3d , cbs->key ) ;
6211 }
6212 break ;
6213
6214 /*** User sets the polort order [27 May 1999] ***/
6215
6216 case graCR_polort:{
6217 AFNI_fimmer_setpolort( im3d , cbs->key ) ;
6218 }
6219 break ;
6220
6221 /*** User sets time_index (from graph) ***/
6222 /*** 24 Jan 2001: or bucket index ***/
6223 /*** 29 Jul 2003: time_index and anat_index are almost merged now ***/
6224
6225 case graCR_setindex:{
6226 MCW_arrowval *tav = im3d->vwid->imag->time_index_av ;
6227 MCW_arrowval *aav = im3d->vwid->func->anat_buck_av ;
6228 int new_index = cbs->key ;
6229
6230 if( new_index != im3d->vinfo->anat_index ){
6231 if( im3d->vinfo->time_on ){
6232 AV_assign_ival( tav , new_index ) ; /* set time_index */
6233 AFNI_time_index_CB( tav, (XtPointer) im3d ); /* will set anat_index */
6234 } else {
6235 AV_assign_ival( aav, new_index ) ; /* set anat index directly */
6236 AFNI_bucket_CB( aav, im3d ) ;
6237 }
6238 }
6239 }
6240 break ;
6241
6242 /*** Feb 1998: user clicked button2 ***/
6243
6244 case graCR_button2_points:{
6245 THD_ivec3 id ;
6246 int fixed_plane ;
6247
6248 if( cbs->xcen >= 0 && cbs->xcen < br->n1 &&
6249 cbs->ycen >= 0 && cbs->ycen < br->n2 &&
6250 cbs->zcen >= 0 && cbs->zcen < br->n3 ){
6251
6252 /* translate image to dataset coordinates */
6253
6254 id = THD_fdind_to_3dind(
6255 br , TEMP_IVEC3(cbs->xcen,cbs->ycen,cbs->zcen) );
6256
6257 /* send a single point */
6258
6259 fixed_plane = abs(br->a123.ijk[2]) ;
6260
6261 AFNI_process_drawing( im3d , SINGLE_MODE + fixed_plane ,
6262 1, &id.ijk[0], &id.ijk[1], &id.ijk[2] ) ;
6263 }
6264 }
6265 break ;
6266
6267 } /* end of switch on callback reasons */
6268
6269 EXRETURN ;
6270 }
6271
6272 /*----------------------------------------------------------------------*/
6273 /*! Report on datasets with mixed type sub-bricks,
6274 as they tend to cause problems. */
6275
AFNI_inconstancy_check(Three_D_View * im3d,THD_3dim_dataset * dset)6276 void AFNI_inconstancy_check( Three_D_View *im3d , THD_3dim_dataset *dset )
6277 {
6278 static int nbad = 0 ;
6279 static char **sbad = NULL ;
6280
6281 ENTRY("AFNI_inconstancy_check") ;
6282
6283 if( dset == NULL ){
6284 char *msg ; int ii,nn ; Widget wp ;
6285 if( nbad == 0 || sbad == NULL ) EXRETURN ; /* nothing to report */
6286 if( !IM3D_OPEN(im3d) ) im3d =AFNI_find_open_controller();
6287 wp = im3d->vwid->imag->crosshair_label ;
6288 BEEPIT ;
6289 STATUS("creating inconstancy message") ;
6290 for(ii=nn=0;ii<nbad;ii++) nn += strlen(sbad[ii]) ;
6291 nn += 255+4*nbad ; msg = malloc(nn) ;
6292 sprintf(msg,
6293 "\n========== Datasets With Inconstant Data Types =========\n\n");
6294 for(ii=0;ii<nbad;ii++) sprintf(msg+strlen(msg)," %s\n",sbad[ii]) ;
6295 sprintf(msg+strlen(msg),
6296 "\n===== This is known as the Mike Beauchamp SINdrome =====\n"
6297 "===== Funky things may happen with these datasets! =====\n" ) ;
6298 MCW_textwin_setbig(1) ;
6299 (void)new_MCW_textwin( wp , msg , TEXT_READONLY ) ;
6300 free((void *)msg) ;
6301 for(ii=0;ii<nbad;ii++)free((void *)sbad[ii]);
6302 free((void *)sbad) ; nbad=0 ; sbad=NULL ;
6303 BEEPIT ;
6304 EXRETURN ;
6305 } else if( ISVALID_DSET(dset) && !DSET_datum_constant(dset) ){
6306 char *str = DSET_BRIKNAME(dset) ;
6307 sbad = (char **)realloc((void *)sbad,sizeof(char *)*(nbad+1)) ;
6308 sbad[nbad++] = strdup(str) ;
6309 }
6310 EXRETURN ;
6311 }
6312
6313 /*----------------------------------------------------------------------------
6314 read the files specified on the command line and create the data structures
6315 ------------------------------------------------------------------------------*/
6316
AFNI_read_inputs(int argc,char * argv[])6317 void AFNI_read_inputs( int argc , char *argv[] )
6318 {
6319 int id , last_color ;
6320 RwcBoolean isfunc ;
6321
6322
6323 ENTRY("AFNI_read_inputs") ;
6324
6325 /* create empty library of dataset sessions */
6326
6327 GLOBAL_library.sslist = myXtNew( THD_sessionlist ) ;
6328 GLOBAL_library.sslist->type = SESSIONLIST_TYPE ;
6329 BLANK_SESSIONLIST(GLOBAL_library.sslist) ;
6330 GLOBAL_library.sslist->parent = NULL ;
6331 GLOBAL_argopt.only_images = 0 ; /* 24 Feb 2017 */
6332
6333 /*----- read files -----*/
6334
6335 if( GLOBAL_argopt.first_file_arg >= argc && GLOBAL_argopt.read_images ){
6336 ERROR_exit("No image files on command line!!") ;
6337 }
6338
6339 /*--- read directly from images (the old-fashioned way) ---*/
6340
6341 if( GLOBAL_argopt.read_images ){ /* pretty much obsolete */
6342 THD_3dim_dataset *dset ;
6343 THD_session *new_ss ;
6344 int vv ;
6345 int gnim ; /* 16 Mar 1998: names from globbing */
6346 char **gname ;
6347
6348 MCW_warn_expand(1) ; /* 13 Jul 2001 */
6349
6350 MCW_file_expand( argc - GLOBAL_argopt.first_file_arg ,
6351 &(argv[GLOBAL_argopt.first_file_arg]) ,
6352 &gnim , &gname ) ;
6353
6354 MCW_warn_expand(0) ; /* 13 Jul 2001 */
6355
6356 if( gnim < 1 )
6357 ERROR_exit("No valid filenames on command line?!") ;
6358
6359 dset = AFNI_read_images( gnim , gname ) ;
6360
6361 if( dset == NULL )
6362 ERROR_exit("Could not form 3D dataset from images!" ) ;
6363
6364 MCW_free_expand( gnim , gname ) ;
6365
6366 /* set up minuscule session and session list */
6367
6368 new_ss = myXtNew( THD_session ) ;
6369 new_ss->type = SESSION_TYPE ;
6370 new_ss->dsrow = NULL; /* row of datasets across spaces not defined yet */
6371 BLANK_SESSION(new_ss) ;
6372 new_ss->num_dsset = 1 ;
6373 SET_SESSION_DSET(dset, new_ss, 0,0);
6374 /* new_ss->dsset_xform_table[0][0] = dset ;*/
6375 new_ss->parent = NULL ;
6376
6377 MCW_strncpy( new_ss->sessname ,
6378 argv[GLOBAL_argopt.first_file_arg] , THD_MAX_NAME ) ;
6379 MCW_strncpy( new_ss->lastname ,
6380 argv[GLOBAL_argopt.first_file_arg] , THD_MAX_NAME ) ;
6381
6382 GLOBAL_library.sslist->num_sess = 1 ;
6383 GLOBAL_library.sslist->ssar[0] = new_ss ;
6384 GLOBAL_library.have_dummy_dataset = 1 ;
6385
6386 } /** end of images input **/
6387
6388 /*--- sessions of 3D datasets (from to3d or other AFNI programs) ---*/
6389
6390 else if( GLOBAL_argopt.read_sessions ){ /*--- the usual method ---*/
6391
6392 char str[256] ;
6393 RwcBoolean good ;
6394 int num_ss , qd , qs , vv=0 , no_args , jj , nskip_noanat=0 ;
6395 THD_string_array *flist , *dlist=NULL , *elist=NULL , *qlist ;
6396 char *dname , *eee ;
6397 THD_session *new_ss ;
6398 THD_session **new_ssar=NULL ; int num_ssar , qss ;
6399 int num_dsets=0 ; /* 04 Jan 2000 */
6400 THD_session *gss=NULL ; /* 11 May 2002: global session */
6401 THD_session *dss=NULL ; /* 28 Aug 2003: session for command-line datasets */
6402 THD_3dim_dataset *temp_dset=NULL; /* 16 Jul 2010: place holder dummy datasets */
6403
6404 THD_session *css=NULL ; /* 02 Jun 2016: catenated sessions */
6405 int do_css=GLOBAL_argopt.cat_sess ;
6406 int num_css=0 ;
6407
6408 /*-- 20 Dec 2001: Try to read a "global" session --*/
6409 /*-- 11 May 2002: Move read global session up here --*/
6410
6411 eee = getenv( "AFNI_GLOBAL_SESSION" ) ; /* where it's supposed to be */
6412 if( eee != NULL ){
6413 THD_3dim_dataset *dset ;
6414 STATUS("reading global session") ;
6415 gss =
6416 GLOBAL_library.session = THD_init_session( eee ); /* try to read datasets */
6417
6418 if( gss != NULL ){ /* got at least one */
6419 REPORT_PROGRESS("[Global]") ;
6420 gss->parent = NULL ; /* parentize them */
6421 for( qd=0 ; qd < gss->num_dsset ; qd++ )
6422 for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
6423 dset = GET_SESSION_DSET(gss, qd, vv) ;
6424 /* dset = gss->dsset_xform_table[qd][vv] ;*/
6425 if( dset != NULL ){
6426 PARENTIZE( dset , NULL ) ;
6427 DSET_MARK_FOR_IMMORTALITY( dset ) ;
6428 AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6429 }
6430 }
6431 } else {
6432 sprintf(str,"\n** No datasets in AFNI_GLOBAL_SESSION=%s",eee) ;
6433 REPORT_PROGRESS(str) ;
6434 }
6435 }
6436
6437 /* 28 Aug 2003:
6438 set up session for datasets from command line (vs. directories) */
6439
6440 dss = myXtNew( THD_session ) ;
6441 dss->type = SESSION_TYPE ;
6442 dss->parent = NULL ;
6443 dss->ndsets = 0;
6444 dss->dsrow = NULL;
6445 BLANK_SESSION(dss) ;
6446 MCW_strncpy( dss->sessname , "fromCLI" , THD_MAX_NAME ) ;
6447 MCW_strncpy( dss->lastname , "fromCLI" , THD_MAX_NAME ) ;
6448
6449 if( do_css ){ /* catenated sessions [02 Jun 2016] */
6450 css = myXtNew( THD_session ) ;
6451 css->type = SESSION_TYPE ;
6452 css->parent = NULL ;
6453 css->ndsets = 0;
6454 css->dsrow = NULL;
6455 BLANK_SESSION(css) ;
6456 css->is_collection = 1 ; /* 01 Feb 2018 */
6457 MCW_strncpy( css->sessname , "All_Datasets" , THD_MAX_NAME ) ;
6458 MCW_strncpy( css->lastname , "All_Datasets" , THD_MAX_NAME ) ;
6459 }
6460
6461 /* now get the list of strings to read as directories */
6462
6463 num_ss = argc - GLOBAL_argopt.first_file_arg ;
6464 no_args = (num_ss < 1) ;
6465
6466 INIT_SARR(dlist) ;
6467
6468 /** 15 Apr 2018: put in any bysub dirs **/
6469
6470 for( id=0; id < num_bysub_dir; id++ ){ ADDTO_SARR(dlist,bysub_dir[id]); }
6471
6472 if( no_args && num_bysub_dir <= 0 ){
6473 if( GLOBAL_argopt.recurse > 0 ){
6474 STATUS("no args: recursion on ./") ;
6475 flist = THD_get_all_subdirs( GLOBAL_argopt.recurse , "./" ) ;
6476 if( flist != NULL ){
6477 for( jj=0 ; jj < flist->num ; jj++ ){
6478 ADDTO_SARR(dlist,flist->ar[jj]) ;
6479 }
6480 DESTROY_SARR(flist) ;
6481 }
6482 } else {
6483 STATUS("no args: using ./") ;
6484 ADDTO_SARR(dlist,"./") ;
6485 elist = THD_get_all_subdirs( 1 , "./" ) ; /* 18 Feb 2007 */
6486 }
6487 } else {
6488 for( id=0 ; id < num_ss ; id++ ){
6489 if( GLOBAL_argopt.recurse > 0 ){
6490 flist = THD_get_all_subdirs( GLOBAL_argopt.recurse ,
6491 argv[GLOBAL_argopt.first_file_arg+id] ) ;
6492 if( flist != NULL ){
6493 for( jj=0 ; jj < flist->num ; jj++ ){
6494 ADDTO_SARR(dlist,flist->ar[jj]) ;
6495 }
6496 DESTROY_SARR(flist) ;
6497 }
6498 } else {
6499 ADDTO_SARR(dlist,argv[GLOBAL_argopt.first_file_arg+id]) ;
6500 }
6501 }
6502 }
6503
6504 if( dlist->num < 1 ) ADDTO_SARR(dlist,"./") ; /* just in case */
6505
6506 /** 09 Sep 1998: eliminate duplicates from the directory list **/
6507
6508 STATUS("normalizing directory list") ;
6509 qlist = THD_normalize_flist( dlist ) ;
6510 if( qlist != NULL ){ DESTROY_SARR(dlist); dlist = qlist; }
6511
6512 if( dlist->num == 1 && css != NULL && gss == NULL ){ /* 02 Jun 2016 */
6513 myXtFree(css) ; do_css = 0 ; num_css = 0 ;
6514 }
6515
6516 REFRESH ;
6517
6518 /*----- read each session, set parents, put into session list -----*/
6519
6520 GLOBAL_argopt.only_images = 1 ; /* 24 Feb 2017 */
6521
6522 qlist = dlist ;
6523 RESTART_DIRECTORY_SCAN: /* 18 Feb 2007 */
6524 num_ss = qlist->num ;
6525
6526 for( id=0 ; id < num_ss ; id++ ){
6527
6528 if(PRINT_TRACING)
6529 { char str[256] ;
6530 sprintf(str,"try to read directory %s",qlist->ar[id]) ; STATUS(str) ; }
6531
6532 dname = qlist->ar[id] ;
6533 new_ss = NULL ;
6534
6535 if( new_ssar != NULL ) free(new_ssar) ; /* 01 Feb 2018 */
6536 new_ssar = NULL ; num_ssar = 0 ;
6537
6538 if( THD_is_directory(dname) ){ /* directory? read session(s) */
6539 static int first=1 ;
6540
6541 for( qss=0 ; qss < num_bysub ; qss++ ){ /* bysub [01 Feb 2018] */
6542 if( first ){ fprintf(stderr,"[bysub/BIDS]"); first = 0; }
6543 new_ss = THD_init_session_bysub(dname,bysub[qss]) ;
6544 if( new_ss != NULL ){
6545 new_ssar = (THD_session **)realloc( new_ssar ,
6546 sizeof(THD_session *)*(num_ssar+1) ) ;
6547 new_ssar[num_ssar++] = new_ss ;
6548 fprintf(stderr,"+%s",bysub[qss]) ;
6549 }
6550 }
6551 if( num_ssar == 0 ){ /* bysub did nothing, try again */
6552 new_ss = THD_init_session(dname) ;
6553 if( new_ss != NULL ){
6554 new_ssar = (THD_session **)malloc(sizeof(THD_session *)) ;
6555 new_ssar[0] = new_ss ; num_ssar = 1 ;
6556 fprintf(stderr,"+%s",dname) ;
6557 }
6558 }
6559 }
6560
6561 REFRESH ;
6562
6563 if( new_ssar == NULL && !THD_is_directory(dname) ){ /* 28 Aug 2003 */
6564 STATUS("trying to read it as a dataset file") ;
6565 qd = dss->num_dsset ;
6566 if( qd < THD_MAX_SESSION_SIZE ){
6567 THD_3dim_dataset *dset = THD_open_dataset( dname ) ;
6568 if( ISVALID_DSET(dset) ){
6569 STATUS("it IS a dataset file!") ;
6570 SET_SESSION_DSET(dset, dss, qd, dset->view_type);
6571 /* dss->dsset_xform_table[qd][dset->view_type] = dset ;*/
6572 dss->num_dsset ++ ;
6573 if( dset->dblk->diskptr->storage_mode != STORAGE_BY_IMAGE_FILE )
6574 GLOBAL_argopt.only_images = 0 ; /* 24 Feb 2017 */
6575 AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6576 } else if( qlist == dlist ){
6577 fprintf(stderr,
6578 "\n** Couldn't open %s as session OR as dataset!" ,
6579 dname ) ;
6580 }
6581 }
6582 }
6583
6584 if( new_ssar != NULL && num_ssar > 0 ){ /* got something? */
6585 THD_3dim_dataset *dset ;
6586
6587 GLOBAL_argopt.only_images = 0 ; /* 24 Feb 2017 */
6588
6589 /* set parent pointers */
6590
6591 for( qss=0 ; qss < num_ssar ; qss++ ){ /* 01 Feb 2018 */
6592 new_ss = new_ssar[qss] ;
6593 new_ss->parent = NULL ;
6594 for( qd=0 ; qd < new_ss->num_dsset ; qd++ ){
6595 for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
6596 dset = GET_SESSION_DSET(new_ss, qd, vv);
6597 /* dset = new_ss->dsset_xform_table[qd][vv] ;*/
6598 if( dset != NULL ){
6599 PARENTIZE( dset , NULL ) ;
6600 AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6601 }
6602 } }
6603
6604 /* put the new session into place in the list of sessions */
6605
6606 GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = new_ss ;
6607 if( qlist == elist ) recursed_ondot++ ; /* 18 Feb 2007 */
6608
6609 sprintf(str,"\n session #%3d = %s ==> %d dataset%s" ,
6610 GLOBAL_library.sslist->num_sess ,
6611 new_ss->lastname , new_ss->num_dsset ,
6612 (new_ss->num_dsset > 1) ? "s" : " " ) ;
6613 REPORT_PROGRESS(str) ;
6614
6615 num_dsets += new_ss->num_dsset ;
6616
6617 /* 28 Aug 2002: add any inter-dataset warps to global warptable */
6618
6619 if( new_ss->warptable != NULL ){
6620 if( GLOBAL_library.warptable == NULL ) /* create global warptable */
6621 GLOBAL_library.warptable = new_Htable(101) ;
6622 subsume_Htable( new_ss->warptable , GLOBAL_library.warptable ) ;
6623 destroy_Htable( new_ss->warptable ) ;
6624 new_ss->warptable = NULL ;
6625 }
6626
6627 /* 02 Jun 2016: catenate this session with the css (all datasets) */
6628
6629 if( do_css )
6630 THD_append_sessions( css , new_ss ) ; num_css++ ;
6631
6632 /* 11 May 2002: put global datasets into session now */
6633
6634 if( new_ss != NULL && gss != NULL )
6635 THD_append_sessions( new_ss , gss ) ;
6636
6637 /* if we've maxed out on sessions */
6638
6639 if( GLOBAL_library.sslist->num_sess == THD_MAX_NUM_SESSION ){
6640 sprintf(str,"\n *** reached max no. sessions (%d) ***",
6641 THD_MAX_NUM_SESSION) ;
6642 REPORT_PROGRESS(str) ;
6643 goto END_OF_ID_LOOP ; /* exit loop over id [bad news, baby] */
6644 }
6645 } /* end of loop over array of new sessions */
6646
6647 } else if( num_bysub == 0 ){ /* 18 Feb 2007: do -R2 on "./" if no data found */
6648 if( qlist == dlist && elist != NULL ){
6649 fprintf(stderr,"\n** Searching subdirectories of './' for data") ;
6650 qlist = elist; goto RESTART_DIRECTORY_SCAN;
6651 }
6652 }
6653
6654 } /*----- end of id loop (over input directory names) -----*/
6655
6656 END_OF_ID_LOOP: /* for the bad news above [01 Feb 2018] */
6657
6658 /* 28 Aug 2003: if have datasets in session dss, use it */
6659
6660 if( dss->num_dsset > 0 ){
6661 if( GLOBAL_library.sslist->num_sess < THD_MAX_NUM_SESSION ){
6662 if( do_css ){ /* 02 Jun 2016 */
6663 THD_append_sessions(css,dss); num_css++;
6664 }
6665 GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = dss ;
6666 num_dsets += dss->num_dsset ;
6667 sprintf(str,"\n session #%3d = %s ==> %d dataset%s" ,
6668 GLOBAL_library.sslist->num_sess, dss->sessname, dss->num_dsset,
6669 (dss->num_dsset > 1) ? "s" : " " ) ;
6670 REPORT_PROGRESS(str) ;
6671 if( gss != NULL ) THD_append_sessions( dss , gss ) ;
6672 } else {
6673 fprintf(stderr,"\n** Can't use command line datasets: session overflow!\n") ;
6674 free(dss) ;
6675 }
6676 } else {
6677 free(dss) ;
6678 }
6679
6680 if( gss != NULL && do_css ){
6681 THD_append_sessions(css,gss); num_css++;
6682 }
6683
6684 /* 11 May 2002: if have global session but no others, use it */
6685
6686 if( gss != NULL && GLOBAL_library.sslist->num_sess == 0 ){
6687
6688 GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = gss ;
6689
6690 sprintf(str,"\n AFNI_GLOBAL_SESSION = %s %d datasets" ,
6691 gss->sessname , gss->num_dsset ) ;
6692
6693 num_dsets += gss->num_dsset ;
6694
6695 REPORT_PROGRESS(str) ;
6696 }
6697
6698 /* add the catenated session list, if nontrivial */
6699 /* only if do_css 7 Mar 2018 [rickr] */
6700
6701 if( css && do_css ) {
6702 if( num_css > 1 && GLOBAL_library.sslist->num_sess < THD_MAX_NUM_SESSION ){
6703 GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = css ;
6704 sprintf(str,"\n Catenated %d sessions = %s has %d datasets" ,
6705 num_css , css->sessname , css->num_dsset ) ;
6706 REPORT_PROGRESS(str) ;
6707 } else {
6708 myXtFree(css) ;
6709 }
6710 }
6711
6712 /** if nothing read yet, try some canonical files [22 Oct 2019] **/
6713
6714 if( GLOBAL_library.sslist->num_sess <= 0 ){
6715 }
6716
6717 /**** if nothing read at all, make up something ****/
6718
6719 GLOBAL_library.have_dummy_dataset = 0 ;
6720
6721 if( GLOBAL_library.sslist->num_sess <= 0 ){
6722 #define NCANON 3 /* added 22 Oct 2019 */
6723 static char *cds[NCANON] = { "MNI152_2009_template_SSW.nii.gz" ,
6724 "MNI_N27.nii.gz" ,
6725 "TT_N27_SSW.nii.gz" } ;
6726
6727 char *aaa = THD_find_executable( "afni" ) ;
6728 char *snam = dlist->ar[0] ; /* 10 Mar 2002 */
6729 char *cpt ; int found_canon=0 ;
6730
6731 temp_dset = NULL ; /* this will be the made up dataset */
6732
6733 if( aaa != NULL && *aaa != '\0' ){ /* try to find canonical dataset */
6734 char *ddd ; int lll , ccc ; /* from afni executable directory */
6735 lll = strlen(aaa) ;
6736 ddd = malloc(sizeof(char)*(lll+64)) ;
6737 strcpy(ddd,aaa) ;
6738 for( ccc=0 ; ccc < NCANON ; ccc++ ){
6739 strcpy( ddd+(lll-4) , cds[ccc] ) ; /* cut off the last 4 chars */
6740 temp_dset = THD_open_dataset( ddd ) ;
6741 if( temp_dset != NULL ) break ;
6742 }
6743 found_canon = (temp_dset != NULL) ; /* found a canonical dataset */
6744 }
6745
6746 if( !THD_is_directory(snam) ) snam = "./" ;
6747
6748 REPORT_PROGRESS("\n** No datasets found -- making up something **") ;
6749
6750 /** manufacture a minimal session **/
6751
6752 new_ss = myXtNew( THD_session ) ;
6753 new_ss->type = SESSION_TYPE ;
6754 new_ss->parent = NULL ;
6755 BLANK_SESSION(new_ss) ;
6756 MCW_strncpy( new_ss->sessname, snam, THD_MAX_NAME ); /* pretend dummy session */
6757 MCW_strncpy( new_ss->lastname, snam, THD_MAX_NAME ); /* is first argv dir */
6758 GLOBAL_library.sslist->num_sess = 1 ;
6759 GLOBAL_library.sslist->ssar[0] = new_ss ;
6760
6761 /** if nothing yet, make up a minimal dataset [cf. thd_dumdset.c] **/
6762
6763 new_ss->num_dsset = 1 ;
6764 GLOBAL_argopt.only_images = 0 ; /* 24 Feb 2017 */
6765
6766 cpt = getenv("AFNI_DUMMY_DATASET") ; /* specify type of dummy dset */
6767
6768 if( temp_dset == NULL && cpt != NULL &&
6769 ( strcasecmp(cpt,"RWCOX")==0 || strcasecmp(cpt,"OLD")==0 ) ){
6770 temp_dset = THD_dummy_RWCOX();
6771 SET_SESSION_DSET(temp_dset,new_ss, 0, 0); /* the olden way */
6772 GLOBAL_library.have_dummy_dataset = 1 ;
6773
6774 } else if( temp_dset == NULL ){
6775 temp_dset = THD_dummy_N27();
6776 SET_SESSION_DSET(temp_dset,new_ss, 0, 0); /* 12 Feb 2010 */
6777 SET_SESSION_DSET(temp_dset,new_ss, 0, 2);
6778 GLOBAL_library.have_dummy_dataset = 1 ;
6779 } else { /* use canonical dataset [22 Oct 2019] */
6780 SET_SESSION_DSET(temp_dset,new_ss, 0, 0);
6781 SET_SESSION_DSET(temp_dset,new_ss, 0, 2);
6782 }
6783
6784 if( !found_canon ) DSET_lock(temp_dset) ; /* lock into memory */
6785 PARENTIZE( temp_dset , NULL ) ;
6786
6787 } else { /* 04 Jan 2000: show total number of datasets */
6788
6789 if( GLOBAL_argopt.only_images ) /* 24 Feb 2017 */
6790 sprintf(str,"\n image count = %d" , num_dsets ) ;
6791 else
6792 sprintf(str,"\n dataset count = %d" , num_dsets ) ;
6793 GLOBAL_num_dsets = num_dsets ;
6794 REPORT_PROGRESS(str) ;
6795 }
6796
6797 /*** read all timeseries files from all directories ***/
6798
6799 STATUS("reading timeseries files") ;
6800
6801 /* 27 Jan 2000: allow skipping *.1D files from dataset directories */
6802 /* 10 Feb 2016: broke sometime - allow skipping */
6803 if(GLOBAL_argopt.read_1D)
6804 GLOBAL_library.timeseries = THD_get_many_timeseries(qlist);
6805 else
6806 GLOBAL_library.timeseries = NULL;
6807 REFRESH ;
6808 if( GLOBAL_library.timeseries == NULL ) /* empty but not NULL */
6809 INIT_IMARR(GLOBAL_library.timeseries) ;
6810 sprintf( str , "\n Timeseries.1D = %d files read" ,
6811 IMARR_COUNT(GLOBAL_library.timeseries) ) ;
6812 REPORT_PROGRESS(str) ;
6813
6814 /* 16 Jun 2020: same stuff for *.tsv and *.csv files */
6815 if(GLOBAL_argopt.read_tcsv)
6816 GLOBAL_library.tcsv_data = THD_get_many_tcsv(qlist);
6817 else
6818 GLOBAL_library.tcsv_data = NULL;
6819 REFRESH ;
6820 if( GLOBAL_library.tcsv_data == NULL ) /* empty but not NULL */
6821 INIT_ELARR(GLOBAL_library.tcsv_data) ;
6822 sprintf( str , "\n .[tc]sv data = %d files read" ,
6823 ELARR_COUNT(GLOBAL_library.tcsv_data) ) ;
6824 REPORT_PROGRESS(str) ;
6825
6826 /*** throw away the list of directories that were scanned ***/
6827
6828 DESTROY_SARR(dlist) ;
6829 if( elist != NULL ){ DESTROY_SARR(elist); } /* 18 Feb 2007 */
6830
6831 /* assign the warp and anatomy parent pointers;
6832 then, make any datasets that don't exist but logically
6833 descend from the warp and anatomy parents just assigned */
6834
6835 if( !GLOBAL_library.have_dummy_dataset ){
6836
6837 STATUS("checking idcodes for duplicates") ;
6838 THD_check_idcodes( GLOBAL_library.sslist ) ; /* 08 Jun 1999 */
6839
6840 STATUS("reconciling parent pointers") ;
6841 THD_reconcile_parents( GLOBAL_library.sslist ) ;
6842
6843 STATUS("forcible adoption of unparented datasets") ;
6844 for( id=0 ; id < GLOBAL_library.sslist->num_sess ; id++ ){ /* functions w/o parents, */
6845 new_ss = GLOBAL_library.sslist->ssar[id] ; /* forcibly get one */
6846 AFNI_force_adoption( new_ss , GLOBAL_argopt.warp_4D ) ;
6847 }
6848
6849 } /* end of if don't have dummy dataset */
6850
6851 if( GLOBAL_library.session != NULL )
6852 AFNI_force_adoption( GLOBAL_library.session , GLOBAL_argopt.warp_4D ) ;
6853
6854 STATUS("making descendant datasets") ;
6855
6856 AFNI_make_descendants( GLOBAL_library.sslist ) ;
6857
6858 } /** end of sessions input **/
6859
6860 else if( GLOBAL_argopt.read_dsets ){ /* 17 Mar 2000 */
6861
6862 int nds = argc - GLOBAL_argopt.first_file_arg ;
6863 char str[256] ;
6864 THD_3dim_dataset *dset ;
6865 RwcPointer_array *dsar ;
6866 MRI_IMARR *webtsar ; /* 26 Mar 2001 */
6867 THD_session *new_ss ;
6868 int ii,nerr=0,vv,nn , dd ;
6869
6870 if( nds <= 0 ){
6871 fprintf(stderr,"\a\n** No datasets on command line?!\n"); exit(1);
6872 }
6873 nds = 0 ;
6874
6875 /* set up minuscule session and session list */
6876
6877 new_ss = myXtNew( THD_session ) ;
6878 new_ss->type = SESSION_TYPE ;
6879 BLANK_SESSION(new_ss) ;
6880 new_ss->parent = NULL ;
6881
6882 strcpy( new_ss->sessname , "." ) ;
6883 strcpy( new_ss->lastname , "." ) ;
6884
6885 GLOBAL_library.sslist->num_sess = 1 ;
6886 GLOBAL_library.sslist->ssar[0] = new_ss ;
6887 GLOBAL_library.have_dummy_dataset = 0 ;
6888
6889 /* read datasets from command line */
6890
6891 STATUS("reading commandline dsets") ;
6892
6893 INIT_IMARR(webtsar) ; /* 26 Mar 2001 */
6894
6895 for( ii=GLOBAL_argopt.first_file_arg ; ii < argc ; ii++ ){
6896
6897 /** 23 Mar 2001: modified code to deal with an array of
6898 datasets, rather than just one at a time **/
6899
6900 if( strstr(argv[ii],"://") != NULL &&
6901 strstr(argv[ii],"AFNILIST") != NULL ){ /** 23 Mar 2001: read from Web list **/
6902
6903 dsar = THD_fetch_many_datasets( argv[ii] ) ;
6904 if( dsar == NULL || dsar->num == 0 ){
6905 fprintf(stderr,"\a\n** Can't read datasets from %s\n",argv[ii]) ;
6906 nerr++ ; continue ; /* next ii */
6907 }
6908
6909 } else { /** read from one file (local or Web), make a small array **/
6910
6911 dset = THD_open_dataset( argv[ii] ) ;
6912 if( dset == NULL ){
6913 fprintf(stderr,"\a\n** Can't read dataset %s\n",argv[ii]) ;
6914 nerr++ ; continue ; /* next ii */
6915 }
6916 INIT_XTARR(dsar) ; ADDTO_XTARR(dsar,dset) ;
6917 XTARR_IC(dsar,0) = IC_DSET ;
6918 }
6919
6920 for( dd=0 ; dd < dsar->num ; dd++ ){ /* over all entries in array */
6921
6922 /* 26 Mar 2001: might get some 1D files, too */
6923
6924 if( XTARR_IC(dsar,dd) == IC_FLIM ){ /* save 1D file for later */
6925 MRI_IMAGE *im = (MRI_IMAGE *) XTARR_XT(dsar,dd) ;
6926 ADDTO_IMARR(webtsar,im) ;
6927 continue ; /* next one */
6928 }
6929 if( XTARR_IC(dsar,dd) != IC_DSET ){
6930 fprintf(stderr,"\n** Unknown filetype returned from %s\n",argv[ii]) ;
6931 nerr++ ; continue ; /* bad */
6932 }
6933
6934 /* get to here ==> have a dataset */
6935
6936 dset = (THD_3dim_dataset *) XTARR_XT(dsar,dd) ;
6937 if( !ISVALID_DSET(dset) ) continue ; /* bad */
6938 AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6939 nds++ ; /* increment count of dataset */
6940 REFRESH ;
6941 vv = dset->view_type ;
6942 nn = new_ss->num_dsset ;
6943 if( nn >= THD_MAX_SESSION_SIZE ){
6944 fprintf(stderr,"\a\n** too many datasets!\n") ;
6945 nerr++ ;
6946 } else {
6947 SET_SESSION_DSET(dset, new_ss, nn, vv);
6948 /* new_ss->dsset_xform_table[nn][vv] = dset ; */
6949 new_ss->num_dsset ++ ;
6950 }
6951 } /* end of loop over dd=datasets in dsar */
6952
6953 FREE_XTARR(dsar) ; /* don't need array no more */
6954
6955 } /* end of loop over ii=command line arguments past options */
6956
6957 if( nerr > 0 ){
6958 fprintf(stderr,"** FATAL ERRORS on input\n") ; exit(1) ; /* bad */
6959 }
6960
6961 sprintf(str,"\n dataset count = %d" , nds ) ;
6962 if( new_ss->num_dsset == 0 ){
6963 fprintf(stderr,"\n** No datasets read from the list!\n") ;
6964 exit(1) ;
6965 }
6966 REPORT_PROGRESS(str) ;
6967
6968 STATUS("reading timeseries files") ;
6969
6970 GLOBAL_library.timeseries = THD_get_many_timeseries( NULL ) ;
6971
6972 REFRESH ;
6973
6974 if( GLOBAL_library.timeseries == NULL )
6975 INIT_IMARR(GLOBAL_library.timeseries) ;
6976
6977 /* 26 Mar 2001: store timeseries fetched from the Web */
6978
6979 for( dd=0 ; dd < IMARR_COUNT(webtsar) ; dd++ )
6980 AFNI_add_timeseries( IMARR_SUBIMAGE(webtsar,dd) ) ;
6981
6982 FREE_IMARR(webtsar) ;
6983
6984 sprintf( str , "\n Timeseries.1D = %d files read" ,
6985 IMARR_COUNT(GLOBAL_library.timeseries) ) ;
6986 REPORT_PROGRESS(str) ;
6987
6988 /* assign the warp and anatomy parent pointers;
6989 then, make any datasets that don't exist but logically
6990 descend from the warp and anatomy parents just assigned */
6991
6992 STATUS("checking idcodes for duplicates") ;
6993
6994 THD_check_idcodes( GLOBAL_library.sslist ) ;
6995
6996 #if 0
6997 STATUS("reconciling parent pointers") ;
6998
6999 THD_reconcile_parents( GLOBAL_library.sslist ) ; /* parents from .HEAD files */
7000
7001 STATUS("forcible adoption of unparented datasets") ;
7002
7003 for( id=0 ; id < GLOBAL_library.sslist->num_sess ; id++ ){ /* functions w/o parents, */
7004 new_ss = GLOBAL_library.sslist->ssar[id] ; /* forcibly get one */
7005 AFNI_force_adoption( new_ss , GLOBAL_argopt.warp_4D ) ;
7006 }
7007 #endif
7008
7009 } /** end of read datasets from command line **/
7010
7011 else { /* should never occur! */
7012
7013 fprintf(stderr,"\a\n** Illegal Usage configuration detected!\n"); exit(1);
7014 }
7015
7016 /** done at last **/
7017
7018 MPROBE ; EXRETURN ;
7019 }
7020
7021 /*--------------------------------------------------------------------------
7022 Final adjustments before a controller is opened for use - 15 Jun 2000
7023 ----------------------------------------------------------------------------*/
7024
AFNI_startup_3dview(Three_D_View * im3d)7025 void AFNI_startup_3dview( Three_D_View *im3d )
7026 {
7027 static int old_0D_num=0 , old_2D_num=0 ;
7028
7029 ENTRY("AFNI_startup_3dview") ;
7030
7031 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7032
7033 /* the pbar Tran 0D menu */
7034
7035 if( GLOBAL_library.registered_0D.num != old_0D_num ){
7036 old_0D_num = GLOBAL_library.registered_0D.num ;
7037 refit_MCW_optmenu( im3d->vwid->func->pbar_transform0D_av ,
7038 0 , /* new minval */
7039 GLOBAL_library.registered_0D.num , /* new maxval */
7040 0 , /* new inival */
7041 0 , /* new decim? */
7042 ISQ_transform_label , /* text func */
7043 &(GLOBAL_library.registered_0D) /* text data */
7044 ) ;
7045 XtManageChild( im3d->vwid->func->pbar_transform0D_av->wrowcol ) ;
7046 } else {
7047 if( old_0D_num == 0 )
7048 XtUnmanageChild( im3d->vwid->func->pbar_transform0D_av->wrowcol ) ;
7049 }
7050
7051 im3d->vwid->func->pbar_transform0D_index = 0 ;
7052 im3d->vwid->func->pbar_transform0D_func = NULL ;
7053
7054 /* the pbar Tran 2D menu */
7055
7056 if( GLOBAL_library.registered_2D.num != old_2D_num ){
7057 old_2D_num = GLOBAL_library.registered_2D.num ;
7058 refit_MCW_optmenu( im3d->vwid->func->pbar_transform2D_av ,
7059 0 , /* new minval */
7060 GLOBAL_library.registered_2D.num , /* new maxval */
7061 0 , /* new inival */
7062 0 , /* new decim? */
7063 ISQ_transform_label , /* text func */
7064 &(GLOBAL_library.registered_2D) /* text data */
7065 ) ;
7066 XtManageChild( im3d->vwid->func->pbar_transform2D_av->wrowcol ) ;
7067 } else {
7068 if( old_2D_num == 0 )
7069 XtUnmanageChild( im3d->vwid->func->pbar_transform2D_av->wrowcol ) ;
7070 }
7071
7072 im3d->vwid->func->pbar_transform2D_index = 0 ;
7073 im3d->vwid->func->pbar_transform2D_func = NULL ;
7074
7075 /* 08 Apr 2005: the cursor on the pbar? */
7076
7077 if( im3d->vwid->func->inten_pbar->bigmode )
7078 POPUP_cursorize( im3d->vwid->func->inten_pbar->panew ) ;
7079
7080 POPUP_cursorize( im3d->vwid->view->sess_lab ) ; /* 30 Apr 2010 */
7081
7082 /* Hey Rocky! Watch me pull a rabbit out of my hat! */
7083
7084 EXRETURN ;
7085 }
7086
7087 /*--------------------------------------------------------------------------
7088 delete the viewers associated with this controller panel
7089 ---------------------------------------------------------------------------*/
7090
AFNI_closedown_3dview(Three_D_View * im3d)7091 void AFNI_closedown_3dview( Three_D_View *im3d )
7092 {
7093 ENTRY("AFNI_closedown_3dview") ;
7094
7095 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7096 /* Mar 1999: shutoff receivers, if any */
7097
7098 AFNI_receive_destroy( im3d ) ;
7099
7100 /* destroy any viewers attached */
7101
7102 drive_MCW_imseq( im3d->s123 , isqDR_destroy , NULL ) ;
7103 drive_MCW_imseq( im3d->s231 , isqDR_destroy , NULL ) ;
7104 drive_MCW_imseq( im3d->s312 , isqDR_destroy , NULL ) ;
7105
7106 drive_MCW_grapher( im3d->g123 , graDR_destroy , NULL ) ;
7107 drive_MCW_grapher( im3d->g231 , graDR_destroy , NULL ) ;
7108 drive_MCW_grapher( im3d->g312 , graDR_destroy , NULL ) ;
7109
7110 /* erase FD bricks */
7111
7112 DESTROY_FD_BRICK(im3d->b123_anat) ;
7113 DESTROY_FD_BRICK(im3d->b231_anat) ;
7114 DESTROY_FD_BRICK(im3d->b312_anat) ;
7115
7116 DESTROY_FD_BRICK(im3d->b123_fim) ;
7117 DESTROY_FD_BRICK(im3d->b231_fim) ;
7118 DESTROY_FD_BRICK(im3d->b312_fim) ;
7119
7120 im3d->b123_ulay = im3d->b231_ulay = im3d->b312_ulay = NULL ;
7121
7122 if( XtIsManaged(im3d->vwid->view->frame) == True )
7123 AFNI_controller_panel_CB( NULL , im3d , NULL ) ;
7124
7125 /* null out montage info */
7126
7127 LOAD_IVEC3(im3d->vinfo->xhairs_ndown,0,0,0) ;
7128 LOAD_IVEC3(im3d->vinfo->xhairs_nup ,0,0,0) ;
7129 LOAD_IVEC3(im3d->vinfo->xhairs_nskip,0,0,0) ;
7130
7131 /* de-fim */
7132
7133 AFNI_fimmer_setref(im3d,NULL) ; CLEAR_FIMDATA(im3d) ;
7134
7135 /* Jul 2010 */
7136
7137 CLU_free_table(im3d->vwid->func->clu_tabNN1_1sid); im3d->vwid->func->clu_tabNN1_1sid = NULL;
7138 CLU_free_table(im3d->vwid->func->clu_tabNN2_1sid); im3d->vwid->func->clu_tabNN2_1sid = NULL;
7139 CLU_free_table(im3d->vwid->func->clu_tabNN3_1sid); im3d->vwid->func->clu_tabNN3_1sid = NULL;
7140
7141 CLU_free_table(im3d->vwid->func->clu_tabNN1_2sid); im3d->vwid->func->clu_tabNN1_2sid = NULL;
7142 CLU_free_table(im3d->vwid->func->clu_tabNN2_2sid); im3d->vwid->func->clu_tabNN2_2sid = NULL;
7143 CLU_free_table(im3d->vwid->func->clu_tabNN3_2sid); im3d->vwid->func->clu_tabNN3_2sid = NULL;
7144
7145 CLU_free_table(im3d->vwid->func->clu_tabNN1_bsid); im3d->vwid->func->clu_tabNN1_bsid = NULL;
7146 CLU_free_table(im3d->vwid->func->clu_tabNN2_bsid); im3d->vwid->func->clu_tabNN2_bsid = NULL;
7147 CLU_free_table(im3d->vwid->func->clu_tabNN3_bsid); im3d->vwid->func->clu_tabNN3_bsid = NULL;
7148
7149 if( im3d->vwid->func->clu_mask != NULL ){
7150 free(im3d->vwid->func->clu_mask) ; im3d->vwid->func->clu_mask = NULL ;
7151 }
7152
7153 RESET_AFNI_QUIT(im3d) ;
7154
7155 im3d->anat_now = im3d->fim_now = NULL ;
7156 AFNI_SEE_FUNC_OFF(im3d) ; /* 22 May 2009 */
7157
7158 AFNI_purge_unused_dsets() ;
7159
7160 /* 19 Aug 2002: close surface widgets, too */
7161
7162 if( im3d->vwid->view->swid != NULL )
7163 XtUnmapWidget( im3d->vwid->view->swid->wtop ) ;
7164
7165 im3d->vinfo->fix_qval = 0 ; /* 27 Feb 2014 */
7166 im3d->vinfo->fixed_qval = 0.0f ;
7167 im3d->vinfo->fix_pval = 0 ; /* 27 Feb 2014 */
7168 im3d->vinfo->fixed_pval = 0.0f ;
7169
7170 MPROBE ;
7171 EXRETURN ;
7172 }
7173
7174 /*-------------------------------------------------------------------------
7175 Open or close the viewing controls panel
7176 ---------------------------------------------------------------------------*/
7177
AFNI_controller_panel_CB(Widget wcall,XtPointer cd,XtPointer cbs)7178 void AFNI_controller_panel_CB( Widget wcall , XtPointer cd , XtPointer cbs )
7179 {
7180 Three_D_View *im3d = (Three_D_View *)cd ;
7181
7182 ENTRY("AFNI_controller_panel_CB") ;
7183
7184 if( ! IM3D_OPEN(im3d) || im3d->vwid->prog->panel_pb == NULL ) EXRETURN ;
7185
7186 /** if view frame is open, close it and all its children **/
7187
7188 if( XtIsManaged(im3d->vwid->view->frame) == True ){
7189
7190 if( XtIsManaged(im3d->vwid->marks->frame) == True ){
7191 AFNI_marks_action_CB( NULL , (XtPointer) im3d , NULL ) ;
7192 }
7193
7194 if( XtIsManaged(im3d->vwid->func->frame) ){
7195 CLOSE_PANEL(im3d,func) ;
7196 }
7197
7198 if( XtIsManaged(im3d->vwid->dmode->frame) ){
7199 CLOSE_PANEL(im3d,dmode) ;
7200 }
7201
7202 XtUnmanageChild(im3d->vwid->view->frame) ;
7203 if( im3d->vwid->prog->panel_pb_inverted ){
7204 MCW_invert_widget(im3d->vwid->prog->panel_pb) ;
7205 im3d->vwid->prog->panel_pb_inverted = False ;
7206 }
7207 XtUnmanageChild(im3d->vwid->forum_pb) ;
7208 XtUnmanageChild(im3d->vwid->phelp_pb) ;
7209 XtUnmanageChild(im3d->vwid->ytube_pb) ;
7210
7211 SHIFT_TIPS( im3d , TIPS_TOTAL_SHIFT ) ;
7212 SHIFT_NEWS( im3d , TIPS_TOTAL_SHIFT ) ;
7213
7214 } else { /** open the view frame (but not its children) **/
7215
7216 XtManageChild(im3d->vwid->view->frame) ;
7217 if( ! im3d->vwid->prog->panel_pb_inverted ){
7218 MCW_invert_widget(im3d->vwid->prog->panel_pb) ;
7219 im3d->vwid->prog->panel_pb_inverted = True ;
7220 }
7221 XtManageChild(im3d->vwid->forum_pb) ;
7222 XtManageChild(im3d->vwid->phelp_pb) ;
7223 XtManageChild(im3d->vwid->ytube_pb) ;
7224
7225
7226 SHIFT_TIPS( im3d , (im3d->vwid->view->marks_enabled) ? TIPS_MINUS_SHIFT
7227 : TIPS_PLUS_SHIFT ) ;
7228 SHIFT_NEWS( im3d , (im3d->vwid->view->marks_enabled) ? TIPS_MINUS_SHIFT
7229 : TIPS_PLUS_SHIFT ) ;
7230 }
7231
7232 RESET_AFNI_QUIT(im3d) ;
7233 EXRETURN ;
7234 }
7235
7236 /*-------------------------------------------------------------------------
7237 Called when the user selects a new option for crosshair visibility
7238 ---------------------------------------------------------------------------*/
7239
AFNI_crosshair_visible_CB(MCW_arrowval * av,XtPointer client_data)7240 void AFNI_crosshair_visible_CB( MCW_arrowval *av , XtPointer client_data )
7241 {
7242 Three_D_View *im3d = (Three_D_View *) client_data ;
7243 int val , omold ;
7244
7245 ENTRY("AFNI_crosshair_visible_CB") ;
7246
7247 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7248
7249 if( av->ival == av->old_ival ) EXRETURN ;
7250
7251 switch( av->ival ){
7252 case AFNI_XHAIRS_OFF:
7253 im3d->vinfo->crosshair_visible = False ;
7254 im3d->vinfo->xhairs_show_montage = False ;
7255 break ;
7256
7257 case AFNI_XHAIRS_SINGLE:
7258 im3d->vinfo->crosshair_visible = True ;
7259 im3d->vinfo->xhairs_show_montage = False ;
7260 break ;
7261
7262 default: /* 31 Dec 1998: */
7263 case AFNI_XHAIRS_MULTI: /* new options */
7264 im3d->vinfo->crosshair_visible = True ; /* like Multi */
7265 im3d->vinfo->xhairs_show_montage = True ;
7266 break ;
7267 }
7268
7269 /* 31 Dec 1998: only allow crosshairs of some orientations */
7270
7271 omold = im3d->vinfo->xhairs_orimask ; /* 02 Jun 1999 */
7272
7273 switch( av->ival ){
7274 default: im3d->vinfo->xhairs_orimask = ORIMASK_ALL ; break;
7275 case AFNI_XHAIRS_LR_AP: im3d->vinfo->xhairs_orimask = ORIMASK_LR_AP; break;
7276 case AFNI_XHAIRS_LR_IS: im3d->vinfo->xhairs_orimask = ORIMASK_LR_IS; break;
7277 case AFNI_XHAIRS_AP_IS: im3d->vinfo->xhairs_orimask = ORIMASK_AP_IS; break;
7278 case AFNI_XHAIRS_LR: im3d->vinfo->xhairs_orimask = ORIMASK_LR ; break;
7279 case AFNI_XHAIRS_AP: im3d->vinfo->xhairs_orimask = ORIMASK_AP ; break;
7280 case AFNI_XHAIRS_IS: im3d->vinfo->xhairs_orimask = ORIMASK_IS ; break;
7281 }
7282
7283 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7284
7285 /* 02 Jun 1999: if xhairs layout has changed, send a notice */
7286
7287 if( omold != im3d->vinfo->xhairs_orimask ) AFNI_process_viewpoint( im3d ) ;
7288
7289 RESET_AFNI_QUIT(im3d) ;
7290 EXRETURN ;
7291 }
7292
7293 /*-----------------------------------------------------------------*/
7294
AFNI_wrap_bbox_CB(Widget w,XtPointer client_data,XtPointer call_data)7295 void AFNI_wrap_bbox_CB( Widget w ,
7296 XtPointer client_data , XtPointer call_data )
7297 {
7298 Three_D_View *im3d = (Three_D_View *) client_data ;
7299 int bval ;
7300
7301 ENTRY("AFNI_wrap_bbox_CB") ;
7302
7303 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7304
7305 bval = MCW_val_bbox( im3d->vwid->imag->wrap_bbox ) ;
7306
7307 if( (RwcBoolean) bval == im3d->vinfo->xhairs_periodic ) EXRETURN ;
7308
7309 im3d->vinfo->xhairs_periodic = (RwcBoolean) bval ;
7310
7311 if( w != NULL ){
7312 drive_MCW_imseq( im3d->s123, isqDR_periodicmont, (XtPointer)ITOP(bval) );
7313 drive_MCW_imseq( im3d->s231, isqDR_periodicmont, (XtPointer)ITOP(bval) );
7314 drive_MCW_imseq( im3d->s312, isqDR_periodicmont, (XtPointer)ITOP(bval) );
7315 }
7316
7317 RESET_AFNI_QUIT(im3d) ;
7318 EXRETURN ;
7319 }
7320
7321 /*-----------------------------------------------------------------*/
7322
AFNI_xhall_bbox_CB(Widget w,XtPointer client_data,XtPointer call_data)7323 void AFNI_xhall_bbox_CB( Widget w ,
7324 XtPointer client_data , XtPointer call_data )
7325 {
7326 Three_D_View *im3d = (Three_D_View *) client_data ;
7327 int bval ;
7328
7329 ENTRY("AFNI_xhall_bbox_CB") ;
7330
7331 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7332
7333 bval = MCW_val_bbox( im3d->vwid->imag->xhall_bbox ) ;
7334
7335 if( (RwcBoolean) bval == im3d->vinfo->xhairs_all ) EXRETURN ;
7336
7337 im3d->vinfo->xhairs_all = (RwcBoolean) bval ;
7338
7339 if( im3d->vinfo->crosshair_visible ){
7340 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7341 }
7342
7343 RESET_AFNI_QUIT(im3d) ;
7344 EXRETURN ;
7345 }
7346
7347 /*------------------------------------------------------------------------*/
7348
AFNI_crosshair_color_CB(MCW_arrowval * av,XtPointer client_data)7349 void AFNI_crosshair_color_CB( MCW_arrowval *av , XtPointer client_data )
7350 {
7351 Three_D_View *im3d = (Three_D_View *) client_data ;
7352 int ipx = av->ival ;
7353
7354 ENTRY("AFNI_crosshair_color_CB") ;
7355
7356 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7357
7358 im3d->vinfo->crosshair_ovcolor = ipx ;
7359 if( im3d->vinfo->crosshair_visible ){
7360 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7361 }
7362
7363 RESET_AFNI_QUIT(im3d) ;
7364 EXRETURN ;
7365 }
7366
7367 /*------------------------------------------------------------------------*/
7368
AFNI_crosshair_gap_CB(MCW_arrowval * av,XtPointer client_data)7369 void AFNI_crosshair_gap_CB( MCW_arrowval *av , XtPointer client_data )
7370 {
7371 Three_D_View *im3d = (Three_D_View *) client_data ;
7372 int ipx ;
7373
7374 ENTRY("AFNI_crosshair_gap_CB") ;
7375
7376 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7377
7378 if( av != NULL ){
7379 ipx = av->ival ;
7380 } else {
7381 if( im3d->vinfo->crosshair_gap_old > 0 ){
7382 ipx = im3d->vinfo->crosshair_gap_old ;
7383 im3d->vinfo->crosshair_gap_old = 0 ;
7384 } else {
7385 im3d->vinfo->crosshair_gap_old = im3d->vinfo->crosshair_gap ;
7386 ipx = 0 ;
7387 }
7388 }
7389
7390 im3d->vinfo->crosshair_gap = ipx ;
7391 if( im3d->vinfo->crosshair_visible ){
7392 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7393 }
7394
7395 RESET_AFNI_QUIT(im3d) ;
7396 EXRETURN ;
7397 }
7398
7399 /*------------------------------------------------------------------------*/
7400
AFNI_time_index_set_fstep(Three_D_View * im3d,int istep)7401 void AFNI_time_index_set_fstep( Three_D_View *im3d , int istep )
7402 {
7403 MCW_arrowval *av ; char lll[16] ;
7404
7405 ENTRY("AFNI_time_index_set_fstep") ;
7406
7407 if( ! IM3D_VALID(im3d) ) EXRETURN ;
7408
7409 if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7410
7411 av = im3d->vwid->imag->time_index_av ;
7412
7413 if( istep == 1 ) strcpy(lll, "Index ") ;
7414 else sprintf(lll,"Idx[%d]",istep) ;
7415
7416 MCW_set_widget_label( av->wlabel , lll ) ;
7417 av->fstep = (istep == 1) ? 0.0f : (float)istep ;
7418 EXRETURN ;
7419 }
7420
7421 /*------------------------------------------------------------------------*/
7422
7423 static char *yesno[2] = { "No" , "Yes" } ;
7424 static char *throx[3] = { "free" , " == " , " +1 " } ;
7425
AFNI_time_index_step_CB(Widget w,XtPointer cd,int nval,void ** val)7426 void AFNI_time_index_step_CB( Widget w, XtPointer cd, int nval , void **val )
7427 {
7428 Three_D_View *im3d = (Three_D_View *)cd ;
7429 char *cpt , cmd[128] ; MCW_bbox *bb ; int ib ;
7430
7431 ENTRY("AFNI_time_index_step_CB") ;
7432
7433 if( ! IM3D_VALID(im3d) || nval != 3 || val == NULL ) EXRETURN ;
7434
7435 AFNI_time_index_set_fstep( im3d , (int)(intptr_t)val[0] ) ;
7436
7437 sprintf(cmd,"AFNI_SLAVE_FUNCTIME %s",(char *)val[1]) ;
7438 (void)AFNI_setenv(cmd) ;
7439
7440 cpt = (char *)val[2] ;
7441 bb = im3d->vwid->func->thr_olayx_bbox ; ib = MCW_val_bbox(bb) ;
7442 if( strcmp(cpt,throx[1]) == 0 ){ /* Thr = OLay */
7443 if( ib != 1 ) MCW_set_bbox(bb,1) ;
7444 } else if( strcmp(cpt,throx[2]) == 0 ){ /* Thr = Olay + 1 */
7445 if( ib != 2 ) MCW_set_bbox(bb,2) ;
7446 } else { /* Thr = free and wild */
7447 if( ib != 0 ) MCW_set_bbox(bb,0) ;
7448 }
7449 AFNI_throlayx_change_CB(NULL,im3d,NULL) ;
7450 EXRETURN ;
7451 }
7452
7453 /*------------------------------------------------------------------------*/
7454
AFNI_time_index_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)7455 void AFNI_time_index_EV( Widget w , XtPointer cd ,
7456 XEvent *ev , RwcBoolean *continue_to_dispatch )
7457 {
7458 Three_D_View *im3d = (Three_D_View *)cd ;
7459
7460 ENTRY("AFNI_time_index_EV") ;
7461
7462 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
7463
7464 /*** handle events ***/
7465
7466 switch( ev->type ){
7467
7468 /*----- take button press -----*/
7469
7470 case ButtonPress:{
7471 XButtonEvent *event = (XButtonEvent *)ev ;
7472
7473 if( event->button == Button3 ){
7474 int istep = (int)im3d->vwid->imag->time_index_av->fstep ;
7475 int sftin , thrin ;
7476
7477 if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7478 sftin = ( !AFNI_noenv("AFNI_SLAVE_FUNCTIME") ) ? 1 : 0 ;
7479 thrin = im3d->vinfo->thr_olayx ; if( thrin < 0 || thrin > 2 ) thrin = 0 ;
7480
7481 MCW_choose_stuff( im3d->vwid->imag->time_index_av->wlabel ,
7482 "Time Index Stepping" ,
7483 AFNI_time_index_step_CB , im3d ,
7484 MSTUF_INT , "Index Step " , 1 , 9 , istep ,
7485 MSTUF_STRLIST , "SLAVE_FUNCTIME " , 2 , sftin , yesno ,
7486 MSTUF_STRLIST , "Thr = Olay?+1? " , 3 , thrin , throx ,
7487 MSTUF_END ) ;
7488 } else if( event->button == Button4 ){
7489 int istep = (int)im3d->vwid->imag->time_index_av->fstep ;
7490 if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7491 AFNI_time_index_set_fstep( im3d , istep-1 ) ;
7492 } else if( event->button == Button5 ){
7493 int istep = (int)im3d->vwid->imag->time_index_av->fstep ;
7494 if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7495 AFNI_time_index_set_fstep( im3d , istep+1 ) ;
7496 } else {
7497 (void) MCW_popup_message(
7498 im3d->vwid->imag->time_index_av->wlabel ,
7499 (event->button == Button1) ? " \n I really wish you "
7500 "\n wouldn't do that! \n "
7501 : " \n Why do you "
7502 "\n torment me so? \n "
7503 , MCW_USER_KILL | MCW_QUICK_KILL ) ;
7504 }
7505 }
7506 break ;
7507 }
7508
7509 EXRETURN ;
7510 }
7511
7512 /*------------------------------------------------------------------------*/
7513
AFNI_time_index_CB(MCW_arrowval * av,XtPointer client_data)7514 void AFNI_time_index_CB( MCW_arrowval *av , XtPointer client_data )
7515 {
7516 Three_D_View *im3d = (Three_D_View *) client_data ;
7517 int ipx ;
7518
7519 ENTRY("AFNI_time_index_CB") ;
7520
7521 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
7522
7523 ipx = av->ival ;
7524 if( ipx >= im3d->vinfo->top_index ) /* don't let index be too big */
7525 ipx = im3d->vinfo->top_index - 1 ;
7526
7527 im3d->vinfo->time_index = ipx ; /* change time index */
7528
7529 /* 29 Jul 2003: slave underlay and overlay to time_index (maybe) */
7530
7531 im3d->vinfo->anat_index = ipx ;
7532 if( im3d->vinfo->anat_index >= DSET_NVALS(im3d->anat_now) )
7533 im3d->vinfo->anat_index = DSET_NVALS(im3d->anat_now) - 1 ;
7534 AV_assign_ival( im3d->vwid->func->anat_buck_av , im3d->vinfo->anat_index ) ;
7535
7536 if( ISVALID_DSET(im3d->fim_now) &&
7537 DSET_NVALS(im3d->fim_now) > 1 &&
7538 !AFNI_noenv("AFNI_SLAVE_FUNCTIME") ){
7539
7540 im3d->vinfo->fim_index = ipx ;
7541 if( im3d->vinfo->fim_index >= DSET_NVALS(im3d->fim_now) )
7542 im3d->vinfo->fim_index = DSET_NVALS(im3d->fim_now) - 1 ;
7543 AV_assign_ival( im3d->vwid->func->fim_buck_av , im3d->vinfo->fim_index ) ;
7544
7545 #if 0
7546 if( AFNI_yesenv("AFNI_SLAVE_THRTIME") ){ /* 24 Jan 2005 - RWCox */
7547 im3d->vinfo->thr_index = ipx ;
7548 if( im3d->vinfo->thr_index >= DSET_NVALS(im3d->fim_now) )
7549 im3d->vinfo->thr_index = DSET_NVALS(im3d->fim_now) - 1 ;
7550 AV_assign_ival( im3d->vwid->func->thr_buck_av , im3d->vinfo->thr_index ) ;
7551 } else {
7552 AFNI_enforce_throlayx(im3d) ; /* 13 Aug 2010 */
7553 }
7554 #else
7555 AFNI_enforce_throlayx(im3d) ;
7556 #endif
7557 }
7558
7559 im3d->vinfo->tempflag = 1 ;
7560 AFNI_modify_viewing( im3d , False ) ; /* setup new bricks to view */
7561
7562 if( im3d->vinfo->fix_pval && im3d->vinfo->fixed_pval > 0.0f )
7563 AFNI_set_pval(im3d,im3d->vinfo->fixed_pval) ;
7564 else if( im3d->vinfo->fix_qval && im3d->vinfo->fixed_qval > 0.0f )
7565 AFNI_set_qval(im3d,im3d->vinfo->fixed_qval) ;
7566
7567 if( ISVALID_DSET(im3d->fim_now) && /* if time index on */
7568 DSET_NUM_TIMES(im3d->fim_now) > 1 ) /* function changed */
7569 AFNI_process_funcdisplay( im3d ) ; /* notify receivers */
7570
7571 AFNI_time_lock_carryout( im3d ) ; /* 03 Nov 1998 */
7572 AFNI_process_timeindex ( im3d ) ; /* 29 Jan 2003 */
7573
7574 RESET_AFNI_QUIT(im3d) ;
7575 EXRETURN ;
7576 }
7577
7578 /*-------------------------------------------------------------------------*/
7579 /* Set rinfo label in an image viewer */
7580
AFNI_set_rinfo_labels(Three_D_View * im3d)7581 void AFNI_set_rinfo_labels( Three_D_View *im3d )
7582 {
7583 float angle ;
7584 char *label ;
7585 MCW_imseq *ssss ;
7586
7587 if( !IM3D_OPEN(im3d) ) return ;
7588
7589 angle = THD_compute_oblique_angle(im3d->anat_now->daxes->ijk_to_dicom_real,0) ;
7590 label = (angle < 1.0f) ? "Card" : "Obliq" ;
7591
7592 ssss = im3d->s123 ;
7593 if( ssss != NULL && ISQ_REALZ(ssss) )
7594 drive_MCW_imseq( ssss , isqDR_rinfolabel , label ) ;
7595
7596 ssss = im3d->s231 ;
7597 if( ssss != NULL && ISQ_REALZ(ssss) )
7598 drive_MCW_imseq( ssss , isqDR_rinfolabel , label ) ;
7599
7600 ssss = im3d->s312 ;
7601 if( ssss != NULL && ISQ_REALZ(ssss) )
7602 drive_MCW_imseq( ssss , isqDR_rinfolabel , label ) ;
7603
7604 return ;
7605 }
7606
7607 /*-------------------------------------------------------------------------
7608 Start a view (12-3, 23-1, or 31-2)
7609 ---------------------------------------------------------------------------*/
7610
7611 static char * AFNI_image_help =
7612 "Button 1 = Set crosshair location\n"
7613 "Button 3 = Pop up image menu\n"
7614 "Shift+Button2 = drag crop region\n"
7615 "Scrollwheel = change slice up/down\n"
7616 "Alt/Opt-Scrollwheel = adjust threshold\n"
7617 "\n"
7618 "q = close window a = fix aspect ratio\n"
7619 "p = toggle panning mode c = crop image mode\n"
7620 "s = sharpen image m = toggle Min-to-Max\n"
7621 "D = open Disp panel M = open Montage panel\n"
7622 "S = Save image l = left-right mirror\n"
7623 "[ = time index down 1 ] = time index up 1\n"
7624 "i/I = image frac down/up z/Z = zoom out/in\n"
7625 "> = Page Up = forward 1 image (e.g., slice)\n"
7626 "< = Page Down = backward 1 image (e.g., slice)\n"
7627 "Ctrl+m = cycle through image global range settings\n"
7628 "o = toggle (color) overlay on/off\n"
7629 "u = toggle background from underlay/overlay dataset\n"
7630 "U = toggle background in ALL image viewers\n"
7631 "e = toggle edge detection in underlay\n"
7632 "#/3 = toggle underlay/overlay checkerboard display\n"
7633 "4 or 5 or 6 = slider for merging ULay/OLay images\n"
7634 "v/V = Video image sequence up/down\n"
7635 "r/R = Ricochet image sequence up/down\n"
7636 "Del = drawing undo F1 = Help!\n"
7637 "F2 = drawing pencil F3 = drawing value --\n"
7638 "F4 = drawing value ++ F5 = Meltdown!!\n"
7639 "Left/Right/Up/Down arrow keys\n"
7640 " = move crosshairs OR pan zoomed image\n"
7641 "Shift+keyboard arrow keys = pan crop region around\n"
7642 "Ctrl+keyboard arrow keys = expand/shrink crop region\n"
7643 "Shift+Home = center crop region on current crosshairs\n"
7644 "--- THESE NEXT KEYSTROKES OPERATE WITH CLUSTERIZE ---\n"
7645 "j = Jump to nearest cluster's peak (or cmass)\n"
7646 "f = Flash current cluster (if Xhairs inside one)\n"
7647 "n/N = Jump to next/previous cluster's peak/cmass"
7648 ;
7649
7650 static char * AFNI_arrowpad_help =
7651 "THD_compute_oblique_angle(dset->daxes->ijk_to_dicom_realClick arrows to scroll crosshair position\n"
7652 "Click button to open/close crosshair gap " ;
7653
7654 static char * AFNI_arrowpad_hint[] = {
7655 "Scroll crosshairs down" ,
7656 "Scroll crosshairs up" ,
7657 "Scroll crosshairs left" ,
7658 "Scroll crosshairs right" ,
7659 "Close/open crosshairs gap"
7660 } ;
7661
7662 #undef WID2EV
7663 #define WID2EV(w,ev) XtVaSetValues( (w), XmNx,(int)((ev)->x_root)-24, \
7664 XmNy,(int)((ev)->y_root)-4 , NULL )
7665
7666 /*.........................................................................*/
7667
AFNI_view_xyz_CB(Widget w,XtPointer client_data,XtPointer call_data)7668 void AFNI_view_xyz_CB( Widget w ,
7669 XtPointer client_data , XtPointer call_data )
7670 {
7671 Three_D_View *im3d = (Three_D_View *)client_data ;
7672 MCW_imseq *sxyz , *syzx , *szxy , **snew = NULL ;
7673 MCW_grapher *gxyz , *gyzx , *gzxy , **gnew = NULL ;
7674 Widget pboff , pb_xyz , pb_yzx , pb_zxy ;
7675 Widget groff , gr_xyz , gr_yzx , gr_zxy ;
7676 FD_brick *brnew ;
7677 int mirror=0 ;
7678 int m2m=0 ; /* 04 Nov 2003 */
7679 int c2c=0 ; /* 17 Sep 2007 */
7680 XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data ;
7681 XButtonEvent *event = NULL ;
7682
7683 ENTRY("AFNI_view_xyz_CB") ;
7684
7685 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
7686
7687 if( cbs != NULL ) event = (XButtonEvent *)cbs->event ;
7688
7689 sxyz = im3d->s123 ; gxyz = im3d->g123 ;
7690 syzx = im3d->s231 ; gyzx = im3d->g231 ;
7691 szxy = im3d->s312 ; gzxy = im3d->g312 ;
7692
7693 pb_xyz = im3d->vwid->imag->image_xyz_pb ;
7694 pb_yzx = im3d->vwid->imag->image_yzx_pb ;
7695 pb_zxy = im3d->vwid->imag->image_zxy_pb ;
7696
7697 gr_xyz = im3d->vwid->imag->graph_xyz_pb ;
7698 gr_yzx = im3d->vwid->imag->graph_yzx_pb ;
7699 gr_zxy = im3d->vwid->imag->graph_zxy_pb ;
7700
7701 /* handle case of button press of already
7702 open window by bringing that window to the top */
7703
7704 if( w == pb_xyz && sxyz != NULL ){
7705 if( ISQ_REALZ(sxyz) ){
7706 if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7707 drive_MCW_imseq( sxyz , isqDR_destroy , NULL ) ;
7708 else
7709 XMapRaised( XtDisplay(sxyz->wtop) , XtWindow(sxyz->wtop) ) ;
7710 }
7711 EXRETURN ;
7712 } else if( w == pb_yzx && syzx != NULL ){
7713 if( ISQ_REALZ(syzx) ){
7714 if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7715 drive_MCW_imseq( syzx , isqDR_destroy , NULL ) ;
7716 else
7717 XMapRaised( XtDisplay(syzx->wtop) , XtWindow(syzx->wtop) ) ;
7718 }
7719 EXRETURN ;
7720 } else if( w == pb_zxy && szxy != NULL ){
7721 if( ISQ_REALZ(szxy) ){
7722 if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7723 drive_MCW_imseq( szxy , isqDR_destroy , NULL ) ;
7724 else
7725 XMapRaised( XtDisplay(szxy->wtop) , XtWindow(szxy->wtop) ) ;
7726 }
7727 EXRETURN ;
7728 } else if( w == gr_xyz && gxyz != NULL ){
7729 if( GRA_REALZ(gxyz) ){
7730 if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7731 drive_MCW_grapher( gxyz , graDR_destroy , NULL ) ;
7732 else
7733 XMapRaised( XtDisplay(gxyz->fdw_graph) , XtWindow(gxyz->fdw_graph) ) ;
7734 }
7735 EXRETURN ;
7736 } else if( w == gr_yzx && gyzx != NULL ){
7737 if( GRA_REALZ(gyzx) ){
7738 if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7739 drive_MCW_grapher( gyzx , graDR_destroy , NULL ) ;
7740 else
7741 XMapRaised( XtDisplay(gyzx->fdw_graph) , XtWindow(gyzx->fdw_graph) ) ;
7742 }
7743 EXRETURN ;
7744 } else if( w == gr_zxy && gzxy != NULL ){
7745 if( GRA_REALZ(gzxy) ){
7746 if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7747 drive_MCW_grapher( gzxy , graDR_destroy , NULL ) ;
7748 else
7749 XMapRaised( XtDisplay(gzxy->fdw_graph) , XtWindow(gzxy->fdw_graph) ) ;
7750 }
7751 EXRETURN ;
7752 }
7753
7754 /* button pressed and window not open, so prepare to open it */
7755
7756 m2m = AFNI_yesenv("AFNI_IMAGE_MINTOMAX") ;
7757 c2c = AFNI_yesenv("AFNI_IMAGE_CLIPPED") ; /* 17 Sep 2007 */
7758
7759 if( !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
7760 STATUS("incoherent ulay -- patching") ;
7761 ERROR_message("AFNI_view_xyz_CB: incoherent ulay -- patching") ;
7762 AFNI_assign_ulay_bricks(im3d) ;
7763 }
7764
7765 if( w == pb_xyz && sxyz == NULL ){ /* axial image */
7766 snew = &(im3d->s123) ;
7767 brnew = im3d->b123_ulay ;
7768 pboff = pb_xyz ;
7769 mirror= GLOBAL_argopt.left_is_left ;
7770
7771 } else if( w == pb_yzx && syzx == NULL ){ /* sagittal image */
7772 snew = &(im3d->s231) ;
7773 brnew = im3d->b231_ulay ;
7774 pboff = pb_yzx ;
7775 mirror= GLOBAL_argopt.left_is_posterior ;
7776
7777 } else if( w == pb_zxy && szxy == NULL ){ /* coronal image */
7778 snew = &(im3d->s312) ;
7779 brnew = im3d->b312_ulay ;
7780 pboff = pb_zxy ;
7781 mirror= GLOBAL_argopt.left_is_left ;
7782
7783 } else if( w == gr_xyz && gxyz == NULL ){ /* axial graph */
7784 gnew = &(im3d->g123) ;
7785 brnew = im3d->b123_ulay ;
7786 pboff = gr_xyz ;
7787 mirror= GLOBAL_argopt.left_is_left ;
7788
7789 } else if( w == gr_yzx && gyzx == NULL ){ /* sagittal graph */
7790 gnew = &(im3d->g231) ;
7791 brnew = im3d->b231_ulay ;
7792 pboff = gr_yzx ;
7793 mirror= GLOBAL_argopt.left_is_posterior ;
7794
7795 } else if( w == gr_zxy && gzxy == NULL ){ /* coronal graph */
7796 gnew = &(im3d->g312) ;
7797 brnew = im3d->b312_ulay ;
7798 pboff = gr_zxy ;
7799 mirror= GLOBAL_argopt.left_is_left ;
7800
7801 } else
7802 EXRETURN ; /* something funny */
7803
7804 /** Mar 1997: don't open if x or y dimension is 1 **/
7805
7806 if( snew != NULL && (brnew->n1 < 2 || brnew->n2 < 2) ) EXRETURN ;
7807
7808 SHOW_AFNI_PAUSE ;
7809
7810 if( snew != NULL ){
7811 STATUS("opening an image window") ;
7812 MCW_invert_widget(pboff) ;
7813 POPUP_cursorize(pboff) ; /* 20 Jul 2005 */
7814 *snew = open_MCW_imseq( im3d->dc, AFNI_brick_to_mri, (XtPointer) brnew ) ;
7815
7816 (*snew)->parent = (XtPointer)im3d ;
7817
7818 INIT_BKGD_LAB(im3d) ;
7819
7820 drive_MCW_imseq( *snew, isqDR_imhelptext, (XtPointer) AFNI_image_help ) ;
7821 drive_MCW_imseq( *snew, isqDR_arrowpadon, (XtPointer) AFNI_arrowpad_help ) ;
7822 drive_MCW_imseq( *snew, isqDR_arrowpadhint , (XtPointer) AFNI_arrowpad_hint );
7823 STATUS("realizing new image viewer") ;
7824 drive_MCW_imseq( *snew, isqDR_ignore_redraws, (XtPointer) 1 ) ; /* 16 Aug 2002 */
7825 drive_MCW_imseq( *snew, isqDR_realize, NULL ) ;
7826 AFNI_sleep(17) ; /* 17 Oct 2005 */
7827 drive_MCW_imseq( *snew, isqDR_title, (XtPointer) im3d->window_title ) ;
7828 if( !AFNI_yesenv("TMONT") )
7829 drive_MCW_imseq( *snew, isqDR_periodicmont,
7830 (XtPointer)ITOP(im3d->vinfo->xhairs_periodic) );
7831 drive_MCW_imseq( *snew , isqDR_allowmerger , NULL ) ; /* 25 Aug 2014 */
7832 AFNI_set_rinfo_labels( im3d ) ; /* 11 Mar 2020 */
7833
7834 /* 09 Oct 1998: force L-R mirroring on axial and coronal images? */
7835 /* 04 Nov 2003: or min-to-max on grayscaling? */
7836
7837 if( mirror || m2m || c2c ){
7838 ISQ_options opt ;
7839
7840 STATUS("setting image view to be L-R mirrored") ;
7841
7842 ISQ_DEFAULT_OPT(opt) ;
7843 if( mirror ) opt.mirror = TRUE ;
7844 if( m2m ) opt.scale_range = ISQ_RNG_MINTOMAX ;
7845 if( c2c ) opt.scale_range = ISQ_RNG_CLIPPED ;
7846 drive_MCW_imseq( *snew,isqDR_options ,(XtPointer) &opt ) ;
7847 }
7848
7849 #if 0
7850 /* 23 Jan 2003: set default save? */
7851
7852 drive_MCW_imseq( *snew , isqDR_setimsave ,
7853 (XtPointer)getenv("AFNI_DEFAULT_IMSAVE") ) ;
7854 #endif
7855
7856 #ifdef USE_SIDES
7857 #undef LL
7858 #undef RR
7859 #undef AA
7860 #undef PP
7861 #undef SS
7862 #undef II
7863 #define LL 0
7864 #define RR 1
7865 #define AA 2
7866 #define PP 3
7867 #define SS 4
7868 #define II 5
7869 if( !AFNI_yesenv("AFNI_NO_SIDES_LABELS") ){
7870 static char *ssix[6] = { "Left" , "Right" ,
7871 "Anterior" , "Posterior" ,
7872 "Superior" , "Inferior" } ;
7873 char *ws[4] ;
7874
7875 if( *snew == im3d->s123 ){
7876 ws[0] = ssix[RR]; ws[1] = ssix[AA]; ws[2] = ssix[LL]; ws[3] = ssix[PP];
7877 } else if( *snew == im3d->s231 ){
7878 ws[0] = ssix[AA]; ws[1] = ssix[SS]; ws[2] = ssix[PP]; ws[3] = ssix[II];
7879 } else if( *snew == im3d->s312 ){
7880 ws[0] = ssix[RR]; ws[1] = ssix[SS]; ws[2] = ssix[LL]; ws[3] = ssix[II];
7881 } else {
7882 ws[0] = ws[1] = ws[2] = ws[3] = NULL ;
7883 }
7884
7885 STATUS("setting image viewer 'sides'") ;
7886
7887 drive_MCW_imseq( *snew,isqDR_winfosides,(XtPointer)ws ) ;
7888
7889 /* 10 Dec 2007: label image orientation */
7890
7891 if( *snew == im3d->s123 )
7892 drive_MCW_imseq( *snew,isqDR_winfoprefix,(XtPointer)"Axial" ) ;
7893 else if( *snew == im3d->s231 )
7894 drive_MCW_imseq( *snew,isqDR_winfoprefix,(XtPointer)"Sagittal" ) ;
7895 else if( *snew == im3d->s312 )
7896 drive_MCW_imseq( *snew,isqDR_winfoprefix,(XtPointer)"Coronal" ) ;
7897
7898 }
7899 #undef LL
7900 #undef RR
7901 #undef AA
7902 #undef PP
7903 #undef SS
7904 #undef II
7905 #endif
7906
7907 AFNI_toggle_drawing( im3d ) ;
7908
7909 #ifndef DONT_INSTALL_ICONS
7910 if( afni48_good ){
7911 Pixmap pm = XmUNSPECIFIED_PIXMAP ;
7912
7913 if( w == pb_xyz ) pm = afni48axi_pixmap ;
7914 else if( w == pb_yzx ) pm = afni48sag_pixmap ;
7915 else if( w == pb_zxy ) pm = afni48cor_pixmap ;
7916
7917 drive_MCW_imseq( *snew, isqDR_icon , (XtPointer) pm ) ;
7918 }
7919 #endif
7920 { int ii=AFNI_controller_index(im3d) ;
7921 if( ii >= 0 )
7922 drive_MCW_imseq( *snew, isqDR_bgicon, (XtPointer)afni16_pixmap[ii] ) ;
7923 }
7924
7925 if( AFNI_yesenv("AFNI_OPACITY_LOCK") ) /* 06 Jun 2019 */
7926 drive_MCW_imseq( *snew, isqDR_setopacity,
7927 (XtPointer)ITOP(GLOBAL_library.opacity_setting) );
7928
7929 drive_MCW_imseq( *snew, isqDR_ignore_redraws, (XtPointer) 0 ) ; /* 16 Aug 2002 */
7930
7931 AFNI_view_setter ( im3d , *snew ) ;
7932 AFNI_range_setter( im3d , *snew ) ; /* 04 Nov 2003 */
7933 AFNI_sleep(17) ; /* 17 Oct 2005 */
7934 if( event != NULL ) WID2EV( (*snew)->wtop , event ) ; /* 23 Nov 2010 */
7935
7936 } /* end of creating a new image viewer */
7937
7938 /** Don't forget to send information like the reference timeseries ... **/
7939
7940 if( gnew != NULL && DSET_GRAPHABLE(brnew->dset) ){
7941 MCW_grapher *gr ;
7942
7943 STATUS("opening a graph window") ;
7944
7945 MCW_invert_widget(pboff) ;
7946 POPUP_cursorize(pboff) ; /* 20 Jul 2005 */
7947 gr = new_MCW_grapher( im3d->dc , AFNI_brick_to_mri , (XtPointer) brnew ) ;
7948 drive_MCW_grapher( gr, graDR_title, (XtPointer) im3d->window_title );
7949 drive_MCW_grapher( gr, graDR_addref_ts, (XtPointer) im3d->fimdata->fimref );
7950 drive_MCW_grapher( gr, graDR_setignore, (XtPointer)ITOP(im3d->fimdata->init_ignore) );
7951 drive_MCW_grapher( gr, graDR_polort, (XtPointer)ITOP(im3d->fimdata->polort) );
7952 drive_MCW_grapher( gr, graDR_setindex , (XtPointer)ITOP(im3d->vinfo->time_index) );
7953
7954 if( im3d->type == AFNI_IMAGES_VIEW )
7955 drive_MCW_grapher( gr , graDR_fim_disable , NULL ) ; /* 19 Oct 1999 */
7956
7957 if( mirror ) /* 12 Jul 2000 */
7958 drive_MCW_grapher( gr , graDR_mirror , (XtPointer) 1 ) ;
7959
7960 /* 07 Aug 2001: set global baseline level, if possible */
7961
7962 if( ISVALID_STATISTIC(brnew->dset->stats) ){
7963 char *eee = getenv( "AFNI_GRAPH_GLOBALBASE" ) ; /* 08 Mar 2002 */
7964 if( eee == NULL ){ /* skip this? */
7965 float vbot=WAY_BIG ; int ii ;
7966 for( ii=0 ; ii < brnew->dset->stats->nbstat ; ii++ )
7967 if( ISVALID_BSTAT(brnew->dset->stats->bstat[ii]) )
7968 vbot = MIN( vbot , brnew->dset->stats->bstat[ii].min ) ;
7969
7970 if( vbot < WAY_BIG )
7971 drive_MCW_grapher( gr, graDR_setglobalbaseline, (XtPointer)&vbot );
7972 }
7973 }
7974
7975 STATUS("realizing new grapher") ;
7976
7977 drive_MCW_grapher( gr , graDR_realize , NULL ) ;
7978
7979 *gnew = gr ;
7980 (*gnew)->parent = (XtPointer) im3d ;
7981
7982 #ifndef DONT_INSTALL_ICONS
7983 if( afni48_good ){
7984 Pixmap pm = XmUNSPECIFIED_PIXMAP ;
7985
7986 if( w == gr_xyz ) pm = afni48graaxi_pixmap ;
7987 else if( w == gr_yzx ) pm = afni48grasag_pixmap ;
7988 else if( w == gr_zxy ) pm = afni48gracor_pixmap ;
7989
7990 drive_MCW_grapher( gr , graDR_icon , (XtPointer) pm ) ;
7991 }
7992 #endif
7993
7994 AFNI_sleep(17) ;
7995 if( event != NULL ) WID2EV( gr->fdw_graph , event ) ; /* 23 Nov 2010 */
7996
7997 } /* end of creating a new graph viewer */
7998
7999 /*-- force a jump to the viewpoint of the current location --*/
8000
8001 XSync( im3d->dc->display , False ) ;
8002 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
8003
8004 SHOW_AFNI_READY ;
8005 RESET_AFNI_QUIT(im3d) ;
8006
8007 MPROBE ;
8008 EXRETURN ;
8009 }
8010
8011 /*--------------------------------------------------------------------------*/
8012 /* Button-3 click on an Image or Graph button:
8013 recall the corresponding window from offscreen purgatory. [13 Jul 2005]
8014 ----------------------------------------------------------------------------*/
8015
8016 #undef GETWIN
8017 #define GETWIN(w) \
8018 do{ XtVaSetValues( (w) , XmNx,(int)(event->x_root), \
8019 XmNy,(int)(event->y_root), NULL ); \
8020 XMapRaised( XtDisplay(w) , XtWindow(w) ) ; \
8021 } while(0)
8022
AFNI_viewbut_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)8023 void AFNI_viewbut_EV( Widget w , XtPointer cd ,
8024 XEvent *ev , RwcBoolean *continue_to_dispatch )
8025 {
8026 Three_D_View *im3d = (Three_D_View *)cd ;
8027 XButtonEvent *event=(XButtonEvent *)ev ;
8028
8029 MCW_imseq *sxyz , *syzx , *szxy ;
8030 MCW_grapher *gxyz , *gyzx , *gzxy ;
8031 Widget pb_xyz , pb_yzx , pb_zxy ;
8032 Widget gr_xyz , gr_yzx , gr_zxy ;
8033
8034 ENTRY("AFNI_viewbut_EV") ;
8035
8036 if( ev->type != ButtonPress || !IM3D_OPEN(im3d) ) EXRETURN ;
8037 if( event->button != Button3 ) EXRETURN ;
8038
8039 sxyz = im3d->s123 ; gxyz = im3d->g123 ; /* viewer structs */
8040 syzx = im3d->s231 ; gyzx = im3d->g231 ;
8041 szxy = im3d->s312 ; gzxy = im3d->g312 ;
8042
8043 pb_xyz = im3d->vwid->imag->image_xyz_pb ; /* buttons */
8044 pb_yzx = im3d->vwid->imag->image_yzx_pb ;
8045 pb_zxy = im3d->vwid->imag->image_zxy_pb ;
8046
8047 gr_xyz = im3d->vwid->imag->graph_xyz_pb ;
8048 gr_yzx = im3d->vwid->imag->graph_yzx_pb ;
8049 gr_zxy = im3d->vwid->imag->graph_zxy_pb ;
8050
8051 /* if the input Widget matches a button, and the item is open, get it */
8052
8053 if( w == pb_xyz && ISQ_REALZ(sxyz) ) GETWIN(sxyz->wtop) ;
8054 else if( w == pb_yzx && ISQ_REALZ(syzx) ) GETWIN(syzx->wtop) ;
8055 else if( w == pb_zxy && ISQ_REALZ(szxy) ) GETWIN(szxy->wtop) ;
8056 else if( w == gr_xyz && GRA_REALZ(gxyz) ) GETWIN(gxyz->fdw_graph) ;
8057 else if( w == gr_yzx && GRA_REALZ(gyzx) ) GETWIN(gyzx->fdw_graph) ;
8058 else if( w == gr_zxy && GRA_REALZ(gzxy) ) GETWIN(gzxy->fdw_graph) ;
8059
8060 EXRETURN ;
8061 }
8062
8063 /*------------------------------------------------------------------------*/
8064
8065 static int ignore_redisplay_func = 0 ; /* 03 Jun 2014 */
AFNI_redisplay_func_ignore(int ig)8066 void AFNI_redisplay_func_ignore( int ig ){ ignore_redisplay_func = ig ; }
8067
AFNI_redisplay_func(Three_D_View * im3d)8068 void AFNI_redisplay_func( Three_D_View *im3d ) /* 05 Mar 2002 */
8069 {
8070 ENTRY("AFNI_redisplay_func") ;
8071 if( !ignore_redisplay_func && IM3D_OPEN(im3d) && IM3D_IMAGIZED(im3d) ){
8072 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
8073 AFNI_process_funcdisplay( im3d ) ;
8074 }
8075 EXRETURN ;
8076 }
8077
8078 /*------------------------------------------------------------------------*/
8079
AFNI_redisplay_func_all(Three_D_View * im3d)8080 void AFNI_redisplay_func_all( Three_D_View *im3d ) /* 03 Jul 2014 */
8081 {
8082 Three_D_View *qq3d ; int ii ;
8083
8084 ENTRY("AFNI_redisplay_func_all") ;
8085
8086 ignore_redisplay_func = 0 ;
8087 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
8088 qq3d = GLOBAL_library.controllers[ii] ;
8089 if( !IM3D_OPEN(qq3d) || qq3d == im3d ) continue ;
8090 IM3D_CLEAR_TMASK(qq3d) ;
8091 IM3D_CLEAR_THRSTAT(qq3d) ;
8092 AFNI_redisplay_func(qq3d) ;
8093 }
8094
8095 EXRETURN ;
8096 }
8097
8098 /*------------------------------------------------------------------------*/
8099
AFNI_do_bkgd_lab(Three_D_View * im3d)8100 void AFNI_do_bkgd_lab( Three_D_View *im3d )
8101 {
8102 char str[256] ;
8103 char labstrf[256]={""}, labstra[256]={""};
8104 char strhint[256]={"Values at crosshairs voxel"};
8105
8106 ENTRY("AFNI_do_bkgd_lab") ;
8107
8108 if( !IM3D_VALID(im3d) || !im3d->vwid->imag->do_bkgd_lab ) EXRETURN ;
8109
8110 AFNI_get_dset_val_label(im3d->anat_now, /* 26 Feb 2010 ZSS */
8111 strtod(im3d->vinfo->anat_val, NULL), labstra);
8112 AFNI_get_dset_val_label(im3d->fim_now, /* 26 Feb 2010 ZSS */
8113 strtod(im3d->vinfo->func_val, NULL), labstrf);
8114
8115 #define VSTR(x) ( ((x)[0] == '\0') ? ("?") : (x) )
8116
8117 sprintf(str,"ULay = %s %s\n"
8118 "OLay = %s %s\n"
8119 "Thr = %s" ,
8120 VSTR(im3d->vinfo->anat_val), labstra,
8121 VSTR(im3d->vinfo->func_val), labstrf,
8122 VSTR(im3d->vinfo->thr_val ) ) ;
8123
8124 #undef VSTR
8125
8126 if (labstra[0] != '\0' || labstrf[0] != '\0') { /* 26 Feb 2010 ZSS */
8127 sprintf(strhint,"Values at crosshairs: "
8128 "%s%s%s%s",
8129 (labstra[0] == '\0') ? "OLay=":"ULay=",
8130 labstra,
8131 (labstra[0] != '\0' && labstrf[0] != '\0') ? ", OLay=":"",
8132 labstrf);
8133 MCW_register_hint( im3d->vwid->func->bkgd_lab, strhint);
8134 }
8135
8136 MCW_set_widget_label( im3d->vwid->func->bkgd_lab , str ) ;
8137 XtManageChild( im3d->vwid->func->bkgd_lab ) ;
8138 FIX_SCALE_SIZE(im3d) ;
8139 EXRETURN ;
8140 }
8141
8142 /*------------------------------------------------------------------------*/
8143 /*! Set the grayscale range in the image window, maybe. [04 Nov 2003]
8144 --------------------------------------------------------------------------*/
8145
AFNI_range_setter(Three_D_View * im3d,MCW_imseq * seq)8146 void AFNI_range_setter( Three_D_View *im3d , MCW_imseq *seq )
8147 {
8148 float rng[3] = {0.0f,0.0f,0.0f} ;
8149 int ival ;
8150 FD_brick *br ;
8151 THD_3dim_dataset *ds ;
8152 static int first=1 ;
8153 static THD_3dim_dataset *last_ds = NULL ;
8154 static int last_ival = -1 ;
8155 static float last_tc = 0.0f ;
8156 float min = 0.0, max = 0.0;
8157
8158 ENTRY("AFNI_range_setter") ;
8159
8160 if( !IM3D_VALID(im3d) || !ISQ_VALID(seq) ) EXRETURN ;
8161
8162 if( !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
8163 STATUS("AFNI_range_setter: incoherent ulay -- patching") ;
8164 ERROR_message("incoherent ulay -- patching") ;
8165 AFNI_assign_ulay_bricks(im3d) ;
8166 }
8167
8168 br = (FD_brick *)im3d->b123_ulay ; if( br == NULL ) EXRETURN ;
8169 ds = br->dset ; if( ds == NULL ) EXRETURN ;
8170
8171 if( EQUIV_DSETS(ds,im3d->anat_now) ) /* underlay dataset */
8172 ival = im3d->vinfo->anat_index ;
8173 else if( EQUIV_DSETS(ds,im3d->fim_now) ) /* overlay dataset */
8174 ival = im3d->vinfo->fim_index ;
8175 else
8176 ival = 0 ; /* shouldn't happen */
8177
8178 if( !EQUIV_DSETS(ds,last_ds) || last_ival != ival ){ /* 14 Sep 2007 */
8179 float tc=0.0f ;
8180 if( DSET_INMEMORY(ds) ){
8181 if( !DSET_BRICK_LOADED(ds,ival) ) DSET_load(ds) ;
8182 if( DSET_BRICK_LOADED(ds,ival) ){
8183 float ff = DSET_BRICK_FACTOR(ds,ival) ;
8184 tc = mri_min( DSET_BRICK(ds,ival) ) ;
8185 if( tc < 0.0f ) tc = 0.0f ;
8186 else tc = mri_topclip( DSET_BRICK(ds,ival) ) ;
8187 if( ff > 0.0f ) tc *= ff ;
8188 }
8189 }
8190 last_ds = ds ; last_ival = ival ; last_tc = tc ;
8191 }
8192 drive_MCW_imseq( seq , isqDR_settopclip , (XtPointer)(&last_tc) ) ;
8193
8194 /* if default slice-based AFNI_IMAGE_GLOBALRANGE, just return */
8195 if( !THD_get_image_globalrange() ){ first=1; EXRETURN ; }
8196
8197 if( ISVALID_STATISTIC(ds->stats)){
8198 if((THD_get_image_globalrange()==1) /* user wants sub-brick range */
8199 && ISVALID_BSTAT(ds->stats->bstat[ival])){
8200 rng[0] = ds->stats->bstat[ival].min ;
8201 rng[1] = ds->stats->bstat[ival].max ;
8202 }
8203 else { /* user wants range scaling by whole dataset */
8204 if(THD_dset_minmax(ds, 1, &min, &max)) {
8205 rng[0] = min ;
8206 rng[1] = max ;
8207 }
8208 else { /* no good dset range, so revert to sub-brick range */
8209 rng[0] = ds->stats->bstat[ival].min ;
8210 rng[1] = ds->stats->bstat[ival].max ;
8211 }
8212 }
8213
8214 /* first time globalrange has been set to something? */
8215 if( first ){
8216 INFO_message(
8217 "AFNI_IMAGE_GLOBALRANGE is no longer slice-based ==> reset image range to %g .. %g",
8218 rng[0],rng[1] ) ;
8219 first = 0 ;
8220 }
8221 }
8222 rng[2] = 1.0f ; /* 21 Dec 2006: do NOT redisplay image */
8223
8224 drive_MCW_imseq( seq , isqDR_setrange , (XtPointer) rng ) ;
8225 EXRETURN ;
8226 }
8227
8228 /*-----------------------------------------------------------------------*/
8229 /* reset globalrange - called by environment GUI and plugout driver */
ENV_globalrange_view(char * vname)8230 void ENV_globalrange_view( char *vname ) /* no longer static definition */
8231 {
8232 Three_D_View *im3d ;
8233 int ii , gbr ;
8234 char sgr_str[64];
8235
8236 /* reset image_globalrange */
8237 THD_set_image_globalrange(-1);
8238 #if 0
8239 sprintf(sgr_str,"AFNI_IMAGE_GLOBALRANGE=%s",vname);
8240 printf("setting env %s\n",sgr_str);
8241 AFNI_setenv(sgr_str);
8242 #endif
8243
8244 gbr = THD_get_image_globalrange(); /* resets from environment variable setting */
8245
8246 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
8247 im3d = GLOBAL_library.controllers[ii] ;
8248 if( ! IM3D_VALID(im3d) ) continue ;
8249 if( gbr ){
8250 AFNI_range_setter( im3d , im3d->s123 ) ;
8251 AFNI_range_setter( im3d , im3d->s231 ) ;
8252 AFNI_range_setter( im3d , im3d->s312 ) ;
8253 drive_MCW_imseq( im3d->s123 , isqDR_display , (XtPointer)(-1) ) ;
8254 drive_MCW_imseq( im3d->s231 , isqDR_display , (XtPointer)(-1) ) ;
8255 drive_MCW_imseq( im3d->s312 , isqDR_display , (XtPointer)(-1) ) ;
8256 } else {
8257 drive_MCW_imseq( im3d->s123 , isqDR_setrange , (XtPointer)NULL ) ;
8258 drive_MCW_imseq( im3d->s231 , isqDR_setrange , (XtPointer)NULL ) ;
8259 drive_MCW_imseq( im3d->s312 , isqDR_setrange , (XtPointer)NULL ) ;
8260 }
8261 }
8262 return ;
8263 }
8264
8265 /* set environment variable too */
THD_set_image_globalrange_env(int ig)8266 void THD_set_image_globalrange_env(int ig)
8267 {
8268 THD_set_image_globalrange(ig);
8269 switch(ig) {
8270 default:
8271 case 0:
8272 AFNI_setenv("AFNI_IMAGE_GLOBALRANGE=SLICE");
8273 break;
8274 case 1:
8275 AFNI_setenv("AFNI_IMAGE_GLOBALRANGE=VOLUME");
8276 break;
8277 case 2:
8278 AFNI_setenv("AFNI_IMAGE_GLOBALRANGE=DSET");
8279 break;
8280 }
8281 ENV_globalrange_view( "AFNI_IMAGE_GLOBALRANGE" );
8282 }
8283
8284 /*------------------------------------------------------------------------*/
8285 /*! Define the view_setter code, which says which image viewer plane
8286 was used to set the current viewpoint. [26 Feb 2003]
8287 --------------------------------------------------------------------------*/
8288
AFNI_view_setter(Three_D_View * im3d,MCW_imseq * seq)8289 void AFNI_view_setter( Three_D_View *im3d , MCW_imseq *seq )
8290 {
8291 MCW_imseq *sxyz, *syzx, *szxy ;
8292 int val=-1 ;
8293
8294 ENTRY("AFNI_view_setter") ;
8295
8296 if( !IM3D_VALID(im3d) ) EXRETURN ;
8297
8298 sxyz = im3d->s123 ; syzx = im3d->s231 ; szxy = im3d->s312 ;
8299
8300 if( !ISQ_REALZ(seq) ){
8301 int code = 4*(sxyz!=NULL) + 2*(syzx!=NULL) + (szxy!=NULL) ;
8302 switch(code){
8303 case 4: val = AXIAL ; break ;
8304 case 2: val = SAGITTAL; break ;
8305 case 1: val = CORONAL ; break ;
8306 }
8307 } else {
8308 if( seq == sxyz ) val = AXIAL ;
8309 else if( seq == syzx ) val = SAGITTAL;
8310 else if( seq == szxy ) val = CORONAL ;
8311 }
8312
8313 im3d->vinfo->view_setter = val ;
8314 EXRETURN ;
8315 }
8316
8317 /*------------------------------------------------------------------------*/
8318
AFNI_set_index_viewpoint(Three_D_View * im3d,int ijk,int redisplay_option)8319 void AFNI_set_index_viewpoint( Three_D_View *im3d ,
8320 int ijk, int redisplay_option ) /* ZSS July 2010 */
8321 {
8322 int nij, ni, ii, jj, kk;
8323
8324 if ( ijk<0 || !im3d ||
8325 !IM3D_VALID(im3d) ||
8326 !ISVALID_3DIM_DATASET(im3d->anat_now)) return;
8327
8328 if (ijk < DSET_NVOX(im3d->anat_now)) {
8329
8330 ni = DSET_NX(im3d->anat_now);
8331 nij = (ni * DSET_NY(im3d->anat_now));
8332
8333 kk = (ijk / nij);
8334 jj = (ijk % nij);
8335 ii = (jj % ni);
8336 jj = (jj / ni);
8337
8338 AFNI_set_viewpoint( im3d, ii, jj, kk, redisplay_option );
8339 }
8340
8341 return;
8342 }
8343
8344 /*------------------------------------------------------------------------*/
8345
AFNI_check_for_multiple_vedits(Three_D_View * im3d)8346 void AFNI_check_for_multiple_vedits( Three_D_View *im3d )
8347 {
8348 static int first=1 ;
8349 Three_D_View *qq3d ; int qq ;
8350
8351 ENTRY("AFNI_check_for_multiple_vedits") ;
8352
8353 if( !first || !IM3D_VALID(im3d) ) EXRETURN ;
8354
8355 for( qq=0 ; qq < MAX_CONTROLLERS ; qq++ ){
8356 qq3d = GLOBAL_library.controllers[qq] ;
8357 if( !IM3D_OPEN(qq3d) ) continue ;
8358 if( qq3d == im3d ) continue ;
8359 if( qq3d->vedset.code <= 0 || qq3d->vedset.ival < 0 ) continue ;
8360 if( qq3d->fim_now == im3d->fim_now ){
8361 #undef MCMESS
8362 #define MCMESS " \n" \
8363 " Multiple Clusterize \n" \
8364 " operations are open \n" \
8365 " on the same Overlay \n" \
8366 " dataset -- they may \n" \
8367 " conflict & confuse! \n "
8368 AFNI_popup_message( MCMESS ) ;
8369 WARNING_message ( MCMESS ) ;
8370 first = 0 ; break ;
8371 #undef MCMESS
8372 }
8373 }
8374 EXRETURN ;
8375 }
8376
8377 /*------------------------------------------------------------------------*/
8378
AFNI_set_viewpoint(Three_D_View * im3d,int xx,int yy,int zz,int redisplay_option)8379 void AFNI_set_viewpoint( Three_D_View *im3d ,
8380 int xx,int yy,int zz , int redisplay_option )
8381 {
8382 int old_i1 , old_j2 , old_k3 , i1,j2,k3 ;
8383 int dim1,dim2,dim3 , isq_driver , do_lock , new_xyz ;
8384 int newti ; /* 24 Jan 2001 */
8385 int ihave , doflash ; /* 02 Mar 2011 */
8386
8387 THD_dataxes *daxes ;
8388 THD_fvec3 fv ;
8389 THD_ivec3 old_ib , new_ib , old_id , new_id ;
8390
8391 #undef EXRR
8392 #define EXRR do{ recurse-- ; EXRETURN ; } while(0)
8393 static int recurse=0 ;
8394 if( recurse > 1 ) return ; /* changed from 3 to 1 [16 Sep 2009] */
8395 recurse++ ;
8396
8397 ENTRY("AFNI_set_viewpoint") ;
8398
8399 if(PRINT_TRACING)
8400 { char str[256] ;
8401 sprintf(str,"input xx=%d yy=%d zz=%d",xx,yy,zz) ;
8402 STATUS(str) ; }
8403
8404 if( ! IM3D_VALID(im3d) || ! ISVALID_3DIM_DATASET(im3d->anat_now) ) EXRR ;
8405
8406 /** 02 Nov 1996:
8407 Attach view-specific dataxes and warps to the datasets **/
8408
8409 LOAD_DSET_VIEWS(im3d) ;
8410
8411 /** find if input points are inside axes of current display **/
8412
8413 daxes = CURRENT_DAXES(im3d->anat_now) ;
8414 dim1 = daxes->nxx ; dim2 = daxes->nyy ; dim3 = daxes->nzz ;
8415
8416 /** save old ijk coordinates **/
8417
8418 old_i1 = im3d->vinfo->i1 ;
8419 old_j2 = im3d->vinfo->j2 ;
8420 old_k3 = im3d->vinfo->k3 ;
8421
8422 /** get and store new ijk coordinates **/
8423
8424 i1 = im3d->vinfo->i1 = (xx < 0 || xx >= dim1) ? (old_i1) : xx ;
8425 j2 = im3d->vinfo->j2 = (yy < 0 || yy >= dim2) ? (old_j2) : yy ;
8426 k3 = im3d->vinfo->k3 = (zz < 0 || zz >= dim3) ? (old_k3) : zz ;
8427
8428 /** determine redisplay mode for image viewers **/
8429
8430 new_xyz =
8431 do_lock = !( i1 == old_i1 && j2 == old_j2 && k3 == old_k3 ) ; /* 11 Nov 1996 */
8432
8433 if( !redisplay_option && !new_xyz ) EXRR ;
8434
8435 ihave = (im3d->s123 != NULL || im3d->s231 != NULL || im3d->s312 != NULL);
8436 doflash = (redisplay_option == REDISPLAY_FLASH) ;
8437 isq_driver = (redisplay_option == REDISPLAY_ALL) ? isqDR_display
8438 : isqDR_overlay ;
8439
8440 if( !AFNI_noenv("AFNI_VALUE_LABEL") && new_xyz && !ihave )
8441 isq_driver = isqDR_display ; /* 08 Mar 2002 */
8442
8443 LOAD_IVEC3(old_id,old_i1,old_j2,old_k3) ;
8444 LOAD_IVEC3(new_id, i1, j2, k3) ;
8445
8446 #ifdef AFNI_DEBUG
8447 STATUS(" ") ;
8448 DUMP_IVEC3(" old_id",old_id) ;
8449 DUMP_IVEC3(" new_id",new_id) ;
8450 #endif
8451
8452 /** store new xyz coordinates into im3d struct **/
8453
8454 if( im3d->type == AFNI_3DDATA_VIEW ){
8455 fv = THD_3dind_to_3dmm ( im3d->anat_now , new_id ) ;
8456 fv = THD_3dmm_to_dicomm( im3d->anat_now , fv ) ;
8457 im3d->vinfo->xi = fv.xyz[0] ; /* set display coords */
8458 im3d->vinfo->yj = fv.xyz[1] ; /* to Dicom standard */
8459 im3d->vinfo->zk = fv.xyz[2] ;
8460 }
8461
8462 /* clear labels */
8463
8464 im3d->vinfo->func_val[0] = im3d->vinfo->thr_val[0] = '\0' ;
8465 if( do_lock || isq_driver==isqDR_display )
8466 im3d->vinfo->anat_val[0] = '\0';
8467 if( !AFNI_noenv( "AFNI_VALUE_LABEL") ) AFNI_do_bkgd_lab( im3d ) ;
8468
8469 /*--- 05 Sep 2006: volume edit on demand? ---*/
8470
8471 if( IM3D_IMAGIZED(im3d) && im3d->vinfo->thr_onoff &&
8472 ihave && im3d->vinfo->func_visible && !doflash ){
8473 int changed=0 ;
8474 if( VEDIT_good(im3d->vedset) ){
8475 STATUS("starting vedit") ;
8476 im3d->vedset.ival = im3d->vinfo->fim_index ;
8477 switch( VEDIT_CODE(im3d->vedset) ){
8478 case VEDIT_CLUST: /* params 2,3,6 set in afni_cluster.c */
8479 im3d->vedset.param[0] = (float)im3d->vinfo->thr_index ;
8480 im3d->vedset.param[1] = get_3Dview_func_thresh(im3d,1);
8481 im3d->vedset.param[4] = im3d->vinfo->thr_sign ;
8482 im3d->vedset.param[5] = im3d->vinfo->use_posfunc ;
8483 im3d->vedset.exinfo = NULL ;
8484 break ;
8485 }
8486 if( !im3d->vedskip ){
8487 byte *mmm = (im3d->vednomask) ? NULL : im3d->vwid->func->clu_mask ;
8488 changed = AFNI_vedit( im3d->fim_now , im3d->vedset , mmm ) ;
8489 }
8490 if( !DSET_VEDIT_good(im3d->fim_now) ){
8491 STATUS("vedit not completed") ;
8492 UNCLUSTERIZE(im3d) ;
8493 } else if( changed ){
8494 mri_cluster_detail *cld ; int nc ; char *rrr ;
8495 STATUS("vedit completed") ;
8496 VEDIT_cluster_helpize(im3d);
8497 if( im3d->vwid->func->clu_rep != NULL ){
8498 free(im3d->vwid->func->clu_rep); im3d->vwid->func->clu_rep = NULL;
8499 }
8500 rrr = mri_clusterize_report() ;
8501 if( rrr != NULL && *rrr != '\0' ) im3d->vwid->func->clu_rep = strdup(rrr) ;
8502 DESTROY_CLARR(im3d->vwid->func->clu_list) ;
8503 im3d->vwid->func->clu_list = mri_clusterize_array(1) ;
8504 AFNI_cluster_dispize(im3d,0); /* display the results */
8505 AFNI_check_for_multiple_vedits(im3d) ; /* 24 Jul 2014 */
8506 STATUS("vedit processed") ;
8507 }
8508 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
8509 } else {
8510 UNCLUSTERIZE(im3d) ; /* macro-ized 13 Feb 2008 */
8511 }
8512 }
8513
8514 /*--- 12 Jun 2014: thresholded statistics on fim ---*/
8515
8516 AFNI_setup_thrstat(im3d,0) ; /* function-ized 27 Jun 2019 */
8517
8518 /*--- redraw images now ---*/
8519
8520 im3d->ignore_seq_callbacks = AFNI_IGNORE_EVERYTHING ;
8521
8522 if( !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
8523 STATUS("AFNI_set_viewpoint: incoherent ulay -- patching") ;
8524 ERROR_message("incoherent ulay -- patching") ;
8525 AFNI_assign_ulay_bricks(im3d) ;
8526 }
8527
8528 if( im3d->s123 != NULL || im3d->g123 != NULL ){
8529 int xyzm[4] ;
8530
8531 old_ib = THD_3dind_to_fdind( im3d->b123_ulay , old_id ) ;
8532 new_ib = THD_3dind_to_fdind( im3d->b123_ulay , new_id ) ;
8533
8534 #ifdef AFNI_DEBUG
8535 STATUS(" ") ;
8536 DUMP_IVEC3(" redraw s123 old_ib",old_ib) ;
8537 DUMP_IVEC3(" new_ib",new_ib) ;
8538 #endif
8539
8540 if( redisplay_option || old_ib.ijk[2] != new_ib.ijk[2] )
8541 drive_MCW_imseq( im3d->s123 ,
8542 isq_driver , (XtPointer)ITOP(new_ib.ijk[2]) ) ;
8543
8544
8545 xyzm[0] = new_ib.ijk[0] ; xyzm[1] = new_ib.ijk[1] ;
8546 xyzm[2] = new_ib.ijk[2] ; xyzm[3] = 0 ;
8547
8548 if( im3d->g123 != NULL && !doflash &&
8549 ( im3d->g123->never_drawn || redisplay_option == REDISPLAY_ALL ||
8550 new_xyz || im3d->g123->thresh_fade ) )
8551 drive_MCW_grapher( im3d->g123 , graDR_redraw , (XtPointer) xyzm ) ;
8552 }
8553
8554 if( im3d->s231 != NULL || im3d->g231 != NULL ){
8555 int xyzm[4] ;
8556
8557 old_ib = THD_3dind_to_fdind( im3d->b231_ulay , old_id ) ;
8558 new_ib = THD_3dind_to_fdind( im3d->b231_ulay , new_id ) ;
8559
8560 #ifdef AFNI_DEBUG
8561 STATUS(" ") ;
8562 DUMP_IVEC3(" redraw s231 old_ib",old_ib) ;
8563 DUMP_IVEC3(" new_ib",new_ib) ;
8564 #endif
8565
8566 if( redisplay_option || old_ib.ijk[2] != new_ib.ijk[2] )
8567 drive_MCW_imseq( im3d->s231 ,
8568 isq_driver , (XtPointer)ITOP(new_ib.ijk[2]) ) ;
8569
8570 xyzm[0] = new_ib.ijk[0] ; xyzm[1] = new_ib.ijk[1] ;
8571 xyzm[2] = new_ib.ijk[2] ; xyzm[3] = 0 ;
8572
8573 if( im3d->g231 != NULL && !doflash &&
8574 ( im3d->g231->never_drawn || redisplay_option == REDISPLAY_ALL ||
8575 new_xyz || im3d->g231->thresh_fade ) )
8576 drive_MCW_grapher( im3d->g231 , graDR_redraw , (XtPointer) xyzm ) ;
8577 }
8578
8579 if( im3d->s312 != NULL || im3d->g312 != NULL ){
8580 int xyzm[4] ;
8581
8582 old_ib = THD_3dind_to_fdind( im3d->b312_ulay , old_id ) ;
8583 new_ib = THD_3dind_to_fdind( im3d->b312_ulay , new_id ) ;
8584
8585 #ifdef AFNI_DEBUG
8586 STATUS(" ") ;
8587 DUMP_IVEC3(" redraw s312 old_ib",old_ib) ;
8588 DUMP_IVEC3(" new_ib",new_ib) ;
8589 #endif
8590
8591 if( redisplay_option || old_ib.ijk[2] != new_ib.ijk[2] )
8592 drive_MCW_imseq( im3d->s312 ,
8593 isq_driver , (XtPointer)ITOP(new_ib.ijk[2]) ) ;
8594
8595 xyzm[0] = new_ib.ijk[0] ; xyzm[1] = new_ib.ijk[1] ;
8596 xyzm[2] = new_ib.ijk[2] ; xyzm[3] = 0 ;
8597
8598 if( im3d->g312 != NULL && !doflash &&
8599 ( im3d->g312->never_drawn || redisplay_option == REDISPLAY_ALL ||
8600 new_xyz || im3d->g312->thresh_fade ) )
8601 drive_MCW_grapher( im3d->g312 , graDR_redraw , (XtPointer) xyzm ) ;
8602 }
8603
8604 im3d->ignore_seq_callbacks = AFNI_IGNORE_NOTHING ;
8605
8606 /*--- redraw coordinate display now ---*/
8607
8608 if( !doflash && (redisplay_option || new_xyz) ){
8609 AFNI_crosshair_relabel( im3d ) ; /* 12 Mar 2004: moved this to a function, too */
8610 AFNI_do_bkgd_lab( im3d ) ; /* 08 Mar 2002: moved labelizing to function */
8611 }
8612
8613 /* 24 Jan 2001: set grapher index based on type of dataset */
8614
8615 newti = im3d->vinfo->anat_index ;
8616
8617 if( newti >= 0 && !doflash ){ /* ITOP = Integer to Pointer cast */
8618 drive_MCW_grapher( im3d->g123, graDR_setindex, (XtPointer)ITOP(newti) );
8619 drive_MCW_grapher( im3d->g231, graDR_setindex, (XtPointer)ITOP(newti) );
8620 drive_MCW_grapher( im3d->g312, graDR_setindex, (XtPointer)ITOP(newti) );
8621 }
8622
8623 if( do_lock && !doflash ) /* 11 Nov 1996 */
8624 AFNI_space_lock_carryout( im3d ) ; /* 04 Nov 1996 */
8625
8626 /** Feb 1998: if desired, send coordinates to receiver **/
8627 /** Mar 1999: do it in an external routine, not here. **/
8628
8629 if( !doflash ){
8630 if( new_xyz ) AFNI_process_viewpoint( im3d ) ;
8631 else AFNI_process_redisplay( im3d ) ;
8632 }
8633
8634 if( !doflash && AFNI_HAVE_WAMI_WIDGET(im3d) ){
8635
8636 char *tlab = AFNI_ttatlas_query( im3d ) ;
8637
8638 AFNI_alter_wami_text(im3d, tlab);
8639
8640 if (tlab) free(tlab) ;
8641 }
8642
8643 /*** 15 Jan 2014 **/
8644
8645 AFNI_sleep(1) ;
8646 if( im3d->s123 != NULL && im3d->s123->crop_autocenter )
8647 ISQ_adjust_crop( im3d->s123 , 0,0,0,0 , 1 ) ;
8648 if( im3d->s231 != NULL && im3d->s231->crop_autocenter )
8649 ISQ_adjust_crop( im3d->s231 , 0,0,0,0 , 1 ) ;
8650 if( im3d->s312 != NULL && im3d->s312->crop_autocenter )
8651 ISQ_adjust_crop( im3d->s312 , 0,0,0,0 , 1 ) ;
8652
8653 EXRR ;
8654 }
8655 #undef EXRR
8656
8657 /*----------------------------------------------------------------------------
8658 get the n-th overlay as an MRI_IMAGE *
8659 (return NULL if none; the result must be mri_free-d by the user)
8660 NOTE: most of the code in this function is no longer executed
8661 under 'normal' circumstances
8662 ------------------------------------------------------------------------------*/
8663
AFNI_overlay(int n,FD_brick * br)8664 MRI_IMAGE * AFNI_overlay( int n , FD_brick *br )
8665 {
8666 Three_D_View *im3d = (Three_D_View *) br->parent ;
8667 MRI_IMAGE *im = NULL , *fov = NULL ;
8668 register short *oar ;
8669 int ii,jj , npix , xx,yy,zz , nx,ny , gap,ovc , icr,jcr,kcr ;
8670 RwcBoolean ovgood ;
8671 THD_ivec3 ib ;
8672 THD_3dim_dataset *dset ;
8673 FD_brick *br_fim ;
8674 int do_xhar=0 ; /* 22 Mar 2002 */
8675 MRI_IMAGE *rgbov = NULL ; /* 30 Jan 2003 */
8676 int jill = im3d->vinfo->see_ttatlas && AFNI_yesenv("AFNI_JILL_TRAVESTY") ; /* Jill is trouble */
8677
8678 ENTRY("AFNI_overlay") ;
8679
8680 if( ! IM3D_OPEN(im3d) ) RETURN(NULL) ;
8681
8682 /*--- check if crosshairs, markers, or functions are visible ---*/
8683
8684 #ifdef IMAGEIZE_CROSSHAIRS /* since this is disabled, do_xhar is always 0 */
8685 do_xhar = (im3d->vinfo->crosshair_visible && !AFNI_yesenv("AFNI_CROSSHAIR_LINES")) ;
8686 #endif
8687
8688 dset = im3d->anat_now ;
8689
8690 ovgood = do_xhar /* crosshairs in overlay pixels? */ ||
8691
8692 ( dset->markers != NULL && /* Talairach */
8693 (dset->markers->numset > 0) && /* markers? */
8694 (im3d->vwid->marks->ov_visible == True) ) ||
8695
8696 ( dset->tagset != NULL && /* user-input tags? */
8697 dset->tagset->num > 0 &&
8698 (im3d->vwid->marks->tag_visible == True) ) ||
8699
8700 #ifdef ALLOW_DATASET_VLIST /* other random points? */
8701 ( dset->pts != NULL && im3d->vinfo->pts_visible == True ) ||
8702 #endif
8703
8704 ( im3d->vinfo->func_visible == True ) /* overlay on? */ ||
8705
8706 ( im3d->vinfo->see_ttatlas && /* Atlas colors on? */
8707 im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE ) ;
8708
8709 if( ! ovgood ) RETURN(NULL) ; /* nothing is asked of us! */
8710
8711 /*-- at least one source of an overlay is present --*/
8712
8713 if(PRINT_TRACING)
8714 { char str[256] ; sprintf(str,"n1=%d n2=%d",br->n1,br->n2) ; STATUS(str) ; }
8715
8716 LOAD_DSET_VIEWS(im3d) ; /* 02 Nov 1996 */
8717
8718 /*----- get functional overlay, if desired -----*/
8719 /* Due to the ALWAYS_USE_BIGMODE change in afni_func.c, the */
8720 /* return from AFNI_func_overlay() is now always RGBA format */
8721
8722 if( im3d->vinfo->func_visible ){
8723 br_fim = UNDERLAY_TO_OVERLAY(im3d,br) ; /* get overlay FD brick struct */
8724 fov = AFNI_func_overlay( n , br_fim ) ; /* get overlay image (afni_func.c) */
8725 /* get rid of it if it contains nothing [12 Feb 2020] */
8726 if( fov != NULL && mri_allzero(fov) ){
8727 mri_free(fov) ; fov = NULL ;
8728 }
8729
8730 /* in the olden days, fov might be shorts (indexes to colors),
8731 or might be RGB, but now it is always RGBA. However, the older
8732 codes below are built around short (indexed) overlays, and so
8733 we set aside the RGBA output to build the (obsolescent) short
8734 overlays, and then merge the RGBA and short overlay images later */
8735
8736 /* so if by some weird chance (or later code change), we still get
8737 a color-indexed overlay image back here, convert it to RGB now */
8738
8739 if( fov != NULL && fov->kind == MRI_short ){ /* should not happen */
8740 rgbov = ISQ_index_to_rgb( im3d->dc , 1 , fov ) ; /* conversion to RGB */
8741 mri_free(fov) ; fov = NULL ;
8742 } else if( fov != NULL && IS_RGB_TYPE(fov->kind) ){ /* should happen */
8743 rgbov = fov ; fov = NULL ;
8744 } else if( fov != NULL ){ /* should NEVER happen */
8745 ERROR_message("AFNI_func_overlay returns illegal image type: %s",MRI_TYPE_NAME(fov)) ;
8746 mri_free(fov) ; fov = rgbov = NULL ;
8747 }
8748
8749 if( jill ){
8750 if( rgbov == NULL ) INFO_message("AFNI_func_overlay is NULL") ;
8751 else INFO_message("AFNI_func_overlay is %s",MRI_TYPE_NAME(rgbov)) ;
8752 }
8753
8754 /* at this point, the functional overlay is in rgbov (which might be NULL) */
8755 /* and the color index overlay image (fov) is NULL for sure */
8756 }
8757
8758 /*----- 25 Jul 2001: get an atlas overlay, if desired and possible -----*/
8759 /*----- which will be merged with functional overlay -----*/
8760
8761 if( im3d->vinfo->see_ttatlas &&
8762 im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE ){
8763
8764 MRI_IMAGE *tov ;
8765
8766 int ax_1 = br->a123.ijk[0] ;
8767 int ax_2 = br->a123.ijk[1] ;
8768 int ax_3 = br->a123.ijk[2] ;
8769
8770 /* if rgbov is non-NULL, the return will be rgbov again,
8771 after suitable editing; otherwise, the return is a new image;
8772 however, if nothing is overlaid, then tov will be returned NULL */
8773
8774 tov = AFNI_ttatlas_overlay( im3d , n , ax_1 , ax_2 , ax_3 , rgbov ) ;
8775
8776 /* if tov came back as shorts, convert it to RGB [old code] */
8777 /* if it came back as RGB(A), it is the new RGB(A) overlay */
8778 /* [this latter situation should be what happens nowadays] */
8779
8780 if( tov != NULL && tov->kind == MRI_short ){ /* should not happen */
8781 if( jill ) WARNING_message("AFNI_ttatlas_overlay returned a short-valued image!") ;
8782 mri_free(rgbov) ;
8783 rgbov = ISQ_index_to_rgb( im3d->dc , 1 , tov ) ;
8784 mri_free(tov) ;
8785 } else if( tov != NULL && IS_RGB_TYPE(tov->kind) && tov != rgbov ){
8786 if( jill && rgbov != NULL ) ININFO_message(" replacing rgbov with AFNI_ttatlas_tov combo") ;
8787 else if( jill ) ININFO_message(" making rgbov = AFNI_ttatlas_tov output") ;
8788 if( rgbov != NULL ) mri_free(rgbov) ; /* might happen??? */
8789 rgbov = tov ;
8790 }
8791
8792 /* at this point, rgbov is the merged functional + atlas overlay */
8793 }
8794
8795 /*----- now set up short (indexed) overlay image as the functional
8796 overlay (if present), or as a new blank image (otherwise) -----*/
8797
8798 if( fov != NULL ){ /* if short overlay already exists [not any more] */
8799
8800 if(PRINT_TRACING)
8801 { char str[256] ;
8802 sprintf(str,"new overlay from AFNI_func_overlay: nx=%d ny=%d\n",fov->nx,fov->ny) ;
8803 STATUS(str) ; }
8804
8805 im = fov ; ovgood = True ;
8806 oar = MRI_SHORT_PTR(im) ;
8807
8808 } else { /* this should be the case from now on [13 Feb 2020] */
8809
8810 STATUS("new overlay is created de novo") ;
8811 im = mri_new( br->n1 , br->n2 , MRI_short ) ; ovgood = False ;
8812 oar = MRI_SHORT_PTR(im) ;
8813 }
8814
8815 nx = im->nx ;
8816 ny = im->ny ;
8817 npix = nx * ny ;
8818 im->dx = br->del1 ; /* load dimensions (not that anyone cares) */
8819 im->dy = br->del2 ;
8820 im->dz = br->del3 ;
8821
8822 /*----- put crosshairs on image directly, if desired (and allowed) -----*/
8823
8824 #ifdef IMAGEIZE_CROSSHAIRS /* this is now disabled, far above */
8825 if( do_xhar ){
8826 MCW_grapher *grapher = UNDERLAY_TO_GRAPHER(im3d,br) ;
8827
8828 ib = THD_3dind_to_fdind( br ,
8829 TEMP_IVEC3( im3d->vinfo->i1 ,
8830 im3d->vinfo->j2 ,
8831 im3d->vinfo->k3 ) ) ;
8832
8833 /** April 1996: Only put crosshairs on if image number
8834 matches current slice number of viewpoint.
8835 (This allows for the montage multislice view) **/
8836
8837 /** July 1996: Allow for multiple crosshairs to indicate
8838 the location of montage multislice views. **/
8839
8840 /** Aug 1996: Allow for periodic (wrap) or non-periodic montages.
8841 Also, if in "Single" mode and also are graphing,
8842 then only draw the grapher frame, not the crosshairs. **/
8843
8844 /** Dec 1998: Allow for user to turn off some directions of crosshairs **/
8845
8846 if( n == ib.ijk[2] || im3d->vinfo->xhairs_all ){
8847 int jp,ip , jcen,icen , gappp ;
8848 int idown,iup,iskip , jdown,jup,jskip , imon,jmon ;
8849 int a1 = br->a123.ijk[0] , /* x axis of the brick? */
8850 ax = abs(a1) - 1 ; /* 0,1,2 for dataset x,y,z */
8851 int a2 = br->a123.ijk[1] , /* y axis of the brick? */
8852 ay = abs(a2) - 1 ; /* 0,1,2 for dataset x,y,z */
8853 int a3 = br->a123.ijk[2] , /* z axis of the brick? */
8854 az = abs(a3) - 1 ; /* 0,1,2 for dataset x,y,z */
8855
8856 /* 31 Dec 1998: spatial orientations of image axes */
8857
8858 int ox = (ax==0) ? br->dset->daxes->xxorient :
8859 (ax==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
8860
8861 int oy = (ay==0) ? br->dset->daxes->xxorient :
8862 (ay==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
8863
8864 ovc = im3d->vinfo->crosshair_ovcolor ;
8865 gap = (grapher==NULL) ? im3d->vinfo->crosshair_gap : (grapher->mat+1)/2 ;
8866 icen = ib.ijk[0] ;
8867 jcen = ib.ijk[1] ;
8868
8869 /** initialize montage steps **/
8870
8871 if( im3d->vinfo->xhairs_show_montage ){ /* in "Multi" mode */
8872 iskip = im3d->vinfo->xhairs_nskip.ijk[ax] + 1 ;
8873 jskip = im3d->vinfo->xhairs_nskip.ijk[ay] + 1 ;
8874 if( a1 > 0 ){
8875 idown = im3d->vinfo->xhairs_ndown.ijk[ax] ;
8876 iup = im3d->vinfo->xhairs_nup.ijk[ax] ;
8877 } else {
8878 iup = im3d->vinfo->xhairs_ndown.ijk[ax] ;
8879 idown = im3d->vinfo->xhairs_nup.ijk[ax] ;
8880 }
8881 if( a2 > 0 ){
8882 jdown = im3d->vinfo->xhairs_ndown.ijk[ay] ;
8883 jup = im3d->vinfo->xhairs_nup.ijk[ay] ;
8884 } else {
8885 jup = im3d->vinfo->xhairs_ndown.ijk[ay] ;
8886 jdown = im3d->vinfo->xhairs_nup.ijk[ay] ;
8887 }
8888
8889 if(PRINT_TRACING)
8890 { char str[256] ;
8891 sprintf(str,"montage xhairs: ax =%d ay =%d az =%d",ax,ay,az) ; STATUS(str);
8892 sprintf(str," iskip=%d idown=%d iup=%d",iskip,idown,iup); STATUS(str);
8893 sprintf(str," jskip=%d jdown=%d jup=%d",jskip,jdown,jup); STATUS(str);
8894 sprintf(str,"orimask=%d ox=%d oy=%d",im3d->vinfo->xhairs_orimask,ox,oy); STATUS(str);
8895 }
8896
8897 } else { /* in "Single" Mode */
8898 idown = iup = jdown = jup = iskip = jskip = 0 ;
8899 if( grapher != NULL ){ idown=-(iup+1); jdown=-(jup+1); } /* skip lines? */
8900 }
8901
8902 /* draw vertical lines first */
8903
8904 if( (im3d->vinfo->xhairs_orimask & (1<<oy)) != 0 ){ /* 31 Dec 1998 */
8905 for( imon=-idown ; imon <= iup ; imon++ ){
8906 icr = icen + imon * iskip ;
8907
8908 if( im3d->vinfo->xhairs_periodic ){
8909 while( icr < 0 ) icr += nx ;
8910 while( icr >= nx ) icr -= nx ;
8911 } else {
8912 if( icr < 0 || icr >= nx ) continue ;
8913 }
8914
8915 gappp = (abs(icr-icen) <= gap) ? gap : -1 ; /* no gap if far from center */
8916
8917 /* if lines are closely packed, only do alternate pixels */
8918
8919 if( idown+iup > 0 && iskip == 1 && icr != icen ){
8920 for( jj=(imon+idown)%2 ; jj < ny ; jj+=2 )
8921 if( abs(jj-jcen) > gappp ) oar[icr+nx*jj] = ovc ;
8922 } else {
8923 for( jj=0 ; jj < ny ; jj++ )
8924 if( abs(jj-jcen) > gappp ) oar[icr+nx*jj] = ovc ;
8925 }
8926 }
8927 }
8928
8929 /* draw horizontal lines */
8930
8931 if( (im3d->vinfo->xhairs_orimask & (1<<ox)) != 0 ){ /* 31 Dec 1998 */
8932 for( jmon=-jdown ; jmon <= jup ; jmon++ ){
8933 jcr = jcen + jmon * jskip ;
8934 if( im3d->vinfo->xhairs_periodic ){
8935 while( jcr < 0 ) jcr += ny ;
8936 while( jcr >= ny ) jcr -= ny ;
8937 } else {
8938 if( jcr < 0 || jcr >= ny ) continue ;
8939 }
8940
8941 gappp = (abs(jcr-jcen) <= gap) ? gap : -1 ; /* no gap if far from center */
8942
8943 /* if lines are closely packed, only do alternate pixels */
8944
8945 if( jdown+jup > 0 && jskip == 1 && jcr != jcen ){
8946 for( ii=(jmon+jdown)%2 ; ii < nx ; ii+=2 )
8947 if( abs(ii-icen) > gappp ) oar[ii+nx*jcr] = ovc ;
8948 } else {
8949 for( ii=0 ; ii < nx ; ii++ )
8950 if( abs(ii-icen) > gappp ) oar[ii+nx*jcr] = ovc ;
8951 }
8952 }
8953 }
8954
8955 /* draw grapher frame, if needed */
8956
8957 if( grapher != NULL ){
8958 int gs = gap , gb = (grapher->mat +2)/2 ;
8959
8960 jcr = jcen ; icr = icen ;
8961
8962 ip = icr - gb ; if( ip < 0 ) ip += nx ;
8963 ii = icr + gs ; if( ii >= nx ) ii -= nx ;
8964 for( jj=jcr-gb ; jj <= jcr+gs ; jj++ ){
8965 jp = jj ; if( jp < 0 ) jp += ny ;
8966 else if( jp >= ny ) jp -= ny ;
8967 oar[ip+nx*jp] = ovc ;
8968 oar[ii+nx*jp] = ovc ;
8969 }
8970
8971 jp = jcr - gb ; if( jp < 0 ) jp += ny ;
8972 jj = jcr + gs ; if( jj >= ny ) jj -= ny ;
8973 for( ii=icr-gb ; ii <= icr+gs ; ii++ ){
8974 ip = ii ; if( ip < 0 ) ip += nx ;
8975 else if( ip >= nx ) ip -= nx ;
8976 oar[ip+nx*jp] = ovc ;
8977 oar[ip+nx*jj] = ovc ;
8978 }
8979 } /* end if "if grapher exists" */
8980
8981 ovgood = True ;
8982 } /* end of "if correct slice" */
8983
8984 } /* end of crosshairs */
8985 #endif
8986
8987 /*----- put Talairach markers on, if desired [ancient code] -----*/
8988
8989 if( im3d->anat_now->markers != NULL &&
8990 im3d->anat_now->markers->numset > 0 &&
8991 (im3d->vwid->marks->ov_visible == True) ){
8992
8993 THD_marker_set *markers = im3d->anat_now->markers ;
8994 AFNI_marks_widgets *marks = im3d->vwid->marks ;
8995 AFNI_ovtemplate *tem = &(marks->ov_mask) ;
8996 int xbase , ybase , zbase , color ;
8997 THD_ivec3 ib ;
8998
8999 /* do secondary points first */
9000
9001 color = marks->ov_scolor ;
9002
9003 for( jj=0 ; jj < MARKS_MAXNUM ; jj++ ){
9004 if( markers->valid[jj] && /* is point set? */
9005 color > 0 && /* will show up? */
9006 !marks->isprimary[jj] ){ /* is secondary? */
9007
9008 ib = THD_3dmm_to_3dind( br->dset ,
9009 TEMP_FVEC3( markers->xyz[jj][0] ,
9010 markers->xyz[jj][1] ,
9011 markers->xyz[jj][2] ) ) ;
9012 ib = THD_3dind_to_fdind( br , ib ) ;
9013
9014 xbase = ib.ijk[0] ; /* coordinates */
9015 ybase = ib.ijk[1] ; /* in and out */
9016 zbase = ib.ijk[2] ; /* of plane */
9017
9018 if( zbase == n ){ /* in this display plane */
9019 ovgood = True ;
9020 for( ii=0 ; ii < tem->numpix ; ii++ ){
9021 xx = xbase + tem->dx[ii] ;
9022 yy = ybase + tem->dy[ii] ;
9023 if( xx >= 0 && xx < nx && yy >=0 && yy < ny )
9024 oar[xx+nx*yy] = color ;
9025 }
9026 }
9027 } /* end if point set, and secondary */
9028 } /* end for loop over all secondary points */
9029
9030 /* duplicate above for primary points */
9031
9032 color = marks->ov_pcolor ;
9033
9034 for( jj=0 ; jj < MARKS_MAXNUM ; jj++ ){
9035 if( markers->valid[jj] && /* is point set? */
9036 color > 0 && /* will show up? */
9037 marks->isprimary[jj] ){ /* is primary? */
9038
9039 ib = THD_3dmm_to_3dind( br->dset ,
9040 TEMP_FVEC3( markers->xyz[jj][0] ,
9041 markers->xyz[jj][1] ,
9042 markers->xyz[jj][2] ) ) ;
9043 ib = THD_3dind_to_fdind( br , ib ) ;
9044
9045 xbase = ib.ijk[0] ; /* coordinates */
9046 ybase = ib.ijk[1] ; /* in and out */
9047 zbase = ib.ijk[2] ; /* of plane */
9048
9049 if( zbase == n ){ /* in this display plane */
9050 ovgood = True ;
9051 for( ii=0 ; ii < tem->numpix ; ii++ ){
9052 xx = xbase + tem->dx[ii] ;
9053 yy = ybase + tem->dy[ii] ;
9054 if( xx >= 0 && xx < nx && yy >=0 && yy < ny )
9055 oar[xx+nx*yy] = color ;
9056 }
9057 }
9058 } /* end if point set, and primary */
9059 } /* end for loop over all secondary points */
9060
9061 } /* end if markers to be shown */
9062
9063 /*----- put tags on, if desired [also ancient code] -----*/
9064
9065 if( im3d->anat_now->tagset != NULL &&
9066 im3d->anat_now->tagset->num > 0 &&
9067 (im3d->vwid->marks->tag_visible == True) ){
9068
9069 static AFNI_ovtemplate *tem = NULL ;
9070 static int npold = -1 ;
9071
9072 THD_usertaglist *tl = im3d->anat_now->tagset ;
9073 int xbase , ybase , zbase , color , np ;
9074 THD_ivec3 ib ;
9075 THD_fvec3 fb ;
9076
9077 if( tem == NULL ) tem = myXtNew(AFNI_ovtemplate) ; /* once only */
9078 np = MAX(nx,ny)/64 ; np = MAX(np,2) ;
9079 if( np != npold ){ npold = np ; AFNI_make_tagmask(np,0,tem) ; }
9080
9081 color = im3d->vwid->marks->ov_pcolor ; /* doesn't have its own color */
9082
9083 for( jj=0 ; jj < tl->num ; jj++ ){
9084 if( tl->tag[jj].set && color > 0 ){
9085
9086 fb = THD_dicomm_to_3dmm( br->dset, TEMP_FVEC3( tl->tag[jj].x ,
9087 tl->tag[jj].y ,
9088 tl->tag[jj].z ) );
9089 ib = THD_3dmm_to_3dind( br->dset , fb ) ;
9090 ib = THD_3dind_to_fdind( br , ib ) ;
9091
9092 xbase = ib.ijk[0] ; /* coordinates */
9093 ybase = ib.ijk[1] ; /* in and out */
9094 zbase = ib.ijk[2] ; /* of plane */
9095
9096 if( zbase == n ){ /* in this display plane */
9097 ovgood = True ;
9098 for( ii=0 ; ii < tem->numpix ; ii++ ){
9099 xx = xbase + tem->dx[ii] ;
9100 yy = ybase + tem->dy[ii] ;
9101 if( xx >= 0 && xx < nx && yy >=0 && yy < ny )
9102 oar[xx+nx*yy] = color ;
9103 }
9104 }
9105 }
9106 }
9107 } /* end if tags to be shown */
9108
9109 #ifdef ALLOW_DATASET_VLIST /* this is currently disabled in 3ddata.h */
9110 /*----- May 1995: additional points (single pixels) -----*/
9111
9112 if( im3d->vinfo->pts_visible &&
9113 dset->pts != NULL &&
9114 im3d->vinfo->pts_color > 0 ){
9115
9116 int color , jj ;
9117 THD_ivec3 ib ;
9118
9119 color = im3d->vinfo->pts_color ;
9120
9121 for( jj=0 ; jj < dset->pts->num ; jj++ ){
9122 ib = THD_3dind_to_fdind( br , dset->pts->ijk[jj] ) ;
9123 if( ib.ijk[2] == n ){
9124 oar[ ib.ijk[0] + nx * ib.ijk[1] ] = color ;
9125 ovgood = True ;
9126 }
9127 }
9128 }
9129 #endif
9130
9131 /*----- return overlay (kill it if nothing happened) -----*/
9132 /* [this should be the 'normal' case these days] */
9133
9134 if( !ovgood ) KILL_1MRI(im) ;
9135
9136 /* 30 Jan 2003:
9137 If the functional overlay is in RGB format,
9138 then must meld that with the short color index image */
9139
9140 if( rgbov != NULL ){
9141 if( im != NULL ){ /* if short overlay is present */
9142 MRI_IMAGE *qim ;
9143 qim = ISQ_overlay( im3d->dc , rgbov , im , 1.0f ) ;
9144 mri_free(rgbov); mri_free(im); rgbov = qim;
9145 }
9146 im = rgbov ; /* overlay is now the RGB(A) image */
9147 }
9148
9149 RETURN( im ) ;
9150 }
9151
9152 /*------------------------------------------------------------------------*/
9153
AFNI_crosshair_label(Three_D_View * im3d)9154 XmString AFNI_crosshair_label( Three_D_View *im3d )
9155 {
9156 char buf[128] ;
9157 XmString xstr ;
9158 static char *RR="[R]" , *LL="[L]" ,
9159 *PP="[P]" , *AA="[A]" ,
9160 *SS="[S]" , *II="[I]" , *ZZ=" " ;
9161 char *xx , *yy , *zz ;
9162 float xval,yval,zval ;
9163
9164 ENTRY("AFNI_crosshair_label") ;
9165
9166 if( ! IM3D_VALID(im3d) ) RETURN( NULL );
9167
9168 if( ! IM3D_OPEN(im3d) ){
9169
9170 buf[0] = '\0' ;
9171 if( im3d->type != AFNI_IMAGES_VIEW ) strcat(buf," \n") ;
9172 strcat(buf, "1234567890123456789\n"
9173 "1234567890123456789\n"
9174 "1234567890123456789" ) ;
9175
9176 } else if( im3d->type == AFNI_IMAGES_VIEW || im3d->vinfo->show_voxind ){
9177 int ixyz = DSET_ixyz_to_index( im3d->anat_now ,
9178 im3d->vinfo->i1, im3d->vinfo->j2, im3d->vinfo->k3 ) ;
9179
9180 STATUS("voxel indexes") ;
9181
9182 if( ISVALID_3DIM_DATASET(im3d->fim_now) &&
9183 im3d->vinfo->func_visible && DSET_INMEMORY(im3d->fim_now) ){
9184 THD_fvec3 fv ;
9185 THD_ivec3 iv ;
9186 int flag , fxyz ;
9187
9188 flag = im3d->fim_now->wod_flag ;
9189 im3d->fim_now->wod_flag = False ;
9190
9191 fv = THD_dicomm_to_3dmm( im3d->fim_now ,
9192 TEMP_FVEC3(im3d->vinfo->xi,im3d->vinfo->yj,im3d->vinfo->zk) ) ;
9193 iv = THD_3dmm_to_3dind( im3d->fim_now , fv ) ;
9194 fxyz = DSET_ixyz_to_index( im3d->fim_now , iv.ijk[0],iv.ijk[1],iv.ijk[2] ) ;
9195
9196 im3d->fim_now->wod_flag = flag ;
9197
9198 sprintf( buf , "Ul=%d Ol=%d\nx: Ul=%4d Ol=%4d\ny: Ul=%4d Ol=%4d\nz: Ul=%4d Ol=%4d" ,
9199 ixyz , fxyz ,
9200 im3d->vinfo->i1,iv.ijk[0] ,
9201 im3d->vinfo->j2,iv.ijk[1] ,
9202 im3d->vinfo->k3,iv.ijk[2] ) ;
9203 } else {
9204 sprintf( buf , "index %d:\nvoxel x = %4d\nvoxel y = %4d\nvoxel z = %4d" ,
9205 ixyz , im3d->vinfo->i1 , im3d->vinfo->j2 , im3d->vinfo->k3 ) ;
9206 }
9207 } else {
9208 char bxyz[3][32] , *cname, obl[8] ;
9209 float angle=0.0;
9210
9211 STATUS("voxel coordinates") ;
9212
9213 xval = im3d->vinfo->xi ;
9214 yval = im3d->vinfo->yj ;
9215 zval = im3d->vinfo->zk ;
9216
9217 xx = (xval==0.0) ? (ZZ) : ( (xval<0.0) ? (RR) : (LL) ) ;
9218 yy = (yval==0.0) ? (ZZ) : ( (yval<0.0) ? (AA) : (PP) ) ;
9219 zz = (zval==0.0) ? (ZZ) : ( (zval<0.0) ? (II) : (SS) ) ;
9220
9221 /** 16 July 1997 **/
9222 #if 1
9223 sprintf( bxyz[0] , "=%9.3f mm %s" ,
9224 GLOBAL_library.cord.xxsign * xval , xx ) ;
9225
9226 sprintf( bxyz[1] , "=%9.3f mm %s" ,
9227 GLOBAL_library.cord.yysign * yval , yy ) ;
9228
9229 sprintf( bxyz[2] , "=%9.3f mm %s" ,
9230 GLOBAL_library.cord.zzsign * zval , zz ) ;
9231
9232 if( strcmp(GLOBAL_library.cord.orcode,"RAI") == 0 )
9233 cname = "=DICOM" ;
9234 else if( strcmp(GLOBAL_library.cord.orcode,"LPI") == 0 )
9235 cname = "=SPM " ;
9236 else
9237 cname = " " ;
9238
9239
9240 if (dset_obliquity(im3d->anat_now, &angle)==1) sprintf(obl," *");
9241 else obl[0]='\0';
9242
9243 sprintf( buf , "[order: %s%s%s]\nx %17s\ny %17s\nz %17s" ,
9244 GLOBAL_library.cord.orcode , cname , obl,
9245 bxyz[GLOBAL_library.cord.first] ,
9246 bxyz[GLOBAL_library.cord.second] ,
9247 bxyz[GLOBAL_library.cord.third] ) ;
9248 #else
9249 sprintf( buf , "x =%9.3f mm %s\ny =%9.3f mm %s\nz =%9.3f mm %s" ,
9250 xval,xx , yval,yy , zval,zz ) ;
9251 #endif
9252 }
9253
9254 xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
9255
9256 RETURN( xstr ) ;
9257 }
9258
9259 /*-------------------------------------------------------------------------
9260 handle the selection of a marker name by the user
9261 (using the toggle buttons from the control panel or the popup menu)
9262 ---------------------------------------------------------------------------*/
9263
AFNI_marktog_CB(Widget w,XtPointer client_data,XtPointer call_data)9264 void AFNI_marktog_CB( Widget w ,
9265 XtPointer client_data , XtPointer call_data )
9266 {
9267 Three_D_View *im3d = (Three_D_View *)client_data ;
9268 XmToggleButtonCallbackStruct *cbs = (XmToggleButtonCallbackStruct *)call_data;
9269
9270 int bval , ip , xx=-1 , yy=-1 , zz=-1 ;
9271 Widget *other_tog=NULL ;
9272
9273 ENTRY("AFNI_marktog_CB") ;
9274
9275 if( ! IM3D_OPEN(im3d) || im3d->anat_now->markers == NULL ) EXRETURN ;
9276
9277 switch( cbs->reason ){
9278
9279 default: EXRETURN ; /* error */
9280
9281 /** case XmCR_ACTIVATE: **/
9282 case XmCR_DISARM: /* button on the control panel */
9283 bval = AFNI_first_tog( MARKS_MAXNUM ,
9284 im3d->vwid->marks->tog ) ;
9285 #ifdef POPTOG
9286 other_tog = im3d->vwid->marks->poptog ;
9287 #endif
9288 break ;
9289
9290 #ifdef POPTOG
9291 case XmCR_VALUE_CHANGED: /* button on the menu panel */
9292 bval = AFNI_first_tog( MARKS_MAXNUM ,
9293 im3d->vwid->marks->poptog ) ;
9294 other_tog = im3d->vwid->marks->tog ;
9295 break ;
9296 #endif
9297 }
9298
9299 /* bval = index of toggle that is set (-1 if none)
9300 other_tog = pointer to other set of toggles;
9301 set those buttons to match now */
9302
9303 if( other_tog != NULL )
9304 AFNI_set_tog( bval , MARKS_MAXNUM , other_tog ) ;
9305
9306 /* set point overlay colors based on bval */
9307
9308 for( ip=0 ; ip < MARKS_MAXNUM ; ip++ )
9309 im3d->vwid->marks->isprimary[ip] = False ;
9310
9311 if( bval >= 0 ){
9312 im3d->vwid->marks->isprimary[bval] = True ;
9313
9314 if( im3d->anat_now->markers->valid[bval] ){ /* jump to this point */
9315 THD_ivec3 ib ;
9316
9317 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
9318 ib = THD_3dmm_to_3dind(
9319 im3d->anat_now ,
9320 TEMP_FVEC3( im3d->anat_now->markers->xyz[bval][0] ,
9321 im3d->anat_now->markers->xyz[bval][1] ,
9322 im3d->anat_now->markers->xyz[bval][2] )) ;
9323
9324 xx = ib.ijk[0] ; yy = ib.ijk[1] ; zz = ib.ijk[2] ; /* jump is below */
9325 SAVE_VPT(im3d) ; /* save current location as jumpback point */
9326 }
9327 }
9328
9329 if( im3d->anat_now->markers->numset > 0 ){
9330 AFNI_set_viewpoint( im3d , xx,yy,zz , REDISPLAY_OVERLAY ) ; /* redraw */
9331 }
9332
9333 RESET_AFNI_QUIT(im3d) ;
9334 EXRETURN ;
9335 }
9336
AFNI_set_tog(int nset,int ntog,Widget * tog)9337 void AFNI_set_tog( int nset , int ntog , Widget *tog )
9338 {
9339 int ib ;
9340
9341 ENTRY("AFNI_set_tog") ;
9342
9343 for( ib=0 ; ib < ntog ; ib++ )
9344 XmToggleButtonSetState( tog[ib] , ib==nset , False ) ;
9345
9346 EXRETURN ;
9347 }
9348
AFNI_first_tog(int ntog,Widget * tog)9349 int AFNI_first_tog( int ntog , Widget *tog )
9350 {
9351 int ib ;
9352
9353 ENTRY("AFNI_first_tog") ;
9354
9355 for( ib=0 ; ib < ntog ; ib++ )
9356 if( XmToggleButtonGetState(tog[ib]) ) break ;
9357
9358 if( ib >= ntog ) ib = -1 ;
9359 RETURN(ib) ;
9360 }
9361
9362 #if 0
9363 int AFNI_all_tog( int ntog , Widget *tog )
9364 {
9365 int ib , val = 0 ;
9366
9367 for( ib=0 ; ib < ntog ; ib++ )
9368 if( XmToggleButtonGetState(tog[ib]) ) val |= (1<<ib) ;
9369 return val ;
9370 }
9371 #endif
9372
9373 /*-------------------------------------------------------------------------
9374 handle pushbuttons for marks actions: set and clear markers, etc.
9375 ---------------------------------------------------------------------------*/
9376
AFNI_marks_action_CB(Widget w,XtPointer client_data,XtPointer call_data)9377 void AFNI_marks_action_CB( Widget w ,
9378 XtPointer client_data , XtPointer call_data )
9379 {
9380 Three_D_View *im3d = (Three_D_View *) client_data ;
9381 int itog , ipt , setmask , vwarp ;
9382 RwcBoolean sens , transformable ;
9383 THD_marker_set *markers ;
9384 AFNI_marks_widgets *marks ;
9385 THD_fvec3 fv ;
9386
9387 ENTRY("AFNI_marks_action_CB") ;
9388
9389 /* sanity check */
9390
9391 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9392
9393 marks = im3d->vwid->marks ;
9394
9395 /*------ done button (it used to exist) -----*/
9396
9397 if( w == NULL ){ /* close down */
9398
9399 RwcBoolean redisplay ;
9400
9401 MCW_set_bbox( marks->edits_bbox , 0 ) ;
9402 AFNI_marks_edits_CB( NULL , (XtPointer) im3d , NULL ) ;
9403
9404 MCW_set_bbox( im3d->vwid->view->see_marks_bbox ,
9405 marks->old_visible ? 1 : 0 ) ;
9406 AFNI_see_marks_CB( NULL , (XtPointer) im3d , NULL ) ;
9407
9408 redisplay = ! marks->old_visible ;
9409
9410 for( ipt=0 ; ipt < MARKS_MAXNUM ; ipt++ ){ /* all display as */
9411 redisplay = ( redisplay || marks->isprimary[ipt] == True ) ;
9412 marks->isprimary[ipt] = False ; /* secondary now */
9413 }
9414
9415 CLOSE_PANEL(im3d,marks) ; /* close this panel */
9416
9417 if( redisplay )
9418 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ; /* redraw */
9419
9420 /* save markers as they exist now, if any changes made */
9421
9422 if( im3d->anat_now->markers != NULL && marks->changed ){
9423 #if 0
9424 (void) MCW_popup_message(
9425 im3d->vwid->view->define_marks_pb ,
9426 "Saved changed markers\nto dataset disk file." ,
9427 MCW_USER_KILL | MCW_TIMER_KILL ) ;
9428 #endif
9429
9430 tross_Append_History( im3d->anat_now , "AFNI: markers were edited" ) ;
9431 DSET_overwrite_header(im3d->anat_now) ;
9432 }
9433
9434 EXRETURN ;
9435 }
9436
9437 /*----- quality button (only on when all markers are defined) -----*/
9438
9439 if( w == marks->action_quality_pb ){
9440 transformable = AFNI_marks_quality_check(True,im3d) ;
9441 SENSITIZE( marks->transform_pb , transformable ) ;
9442 EXRETURN ;
9443 }
9444
9445 /*----- if here, either a Set or a Clear -----*/
9446
9447 markers = im3d->anat_now->markers ;
9448 if( markers == NULL ) EXRETURN ; /* should not happen */
9449
9450 /* find which point is active (i.e., which toggle is set, if any) */
9451
9452 itog = AFNI_first_tog( MARKS_MAXNUM , marks->tog ) ;
9453
9454 if( itog < 0 || ! marks->editable ){
9455 BEEPIT ; EXRETURN ;
9456 }
9457
9458 ipt = itog ; /* index of point to deal with */
9459
9460 /*----- set button pressed -----*/
9461
9462 #ifdef POPTOG
9463 if( w == marks->action_set_pb || w == marks->pop_set_pb ){
9464 #else
9465 if( w == marks->action_set_pb ){
9466 #endif
9467
9468 if( ! markers->valid[ipt] ) (markers->numset) ++ ; /* newly set */
9469
9470 if(PRINT_TRACING)
9471 { char str[256] ;
9472 sprintf(str,"set #%d numset=%d",ipt,markers->numset) ;
9473 STATUS(str) ; }
9474
9475 markers->valid[ipt] = True ;
9476
9477 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
9478 fv = THD_3dind_to_3dmm( im3d->anat_now , /* convert to mm */
9479 TEMP_IVEC3( im3d->vinfo->i1 ,
9480 im3d->vinfo->j2 ,
9481 im3d->vinfo->k3 ) ) ;
9482
9483 markers->xyz[ipt][0] = fv.xyz[0] ; /* mm in local x,y,z */
9484 markers->xyz[ipt][1] = fv.xyz[1] ;
9485 markers->xyz[ipt][2] = fv.xyz[2] ;
9486
9487 /* invert colors to mark that the point is set */
9488
9489 if( ! marks->inverted[itog] ){
9490 MCW_invert_widget( marks->tog[itog] ) ;
9491 #ifdef POPTOG
9492 MCW_invert_widget( marks->poptog[itog] ) ;
9493 #endif
9494 marks->inverted[itog] = True ;
9495 }
9496
9497 marks->changed = True ; /* set or reset a marker --> a change */
9498 }
9499
9500 /*----- clear button pressed -----*/
9501
9502 else if( w == marks->action_clear_pb || w == marks->pop_clear_pb ){
9503
9504 if( ! markers->valid[ipt] ){
9505 EXRETURN ;
9506 } else {
9507 (markers->numset) -- ; /* newly unset --> sub one from count */
9508 marks->changed = True ; /* cleared a set marker --> a change */
9509 }
9510
9511 if(PRINT_TRACING)
9512 { char str[256] ;
9513 sprintf(str,"clr #%d numset=%d",ipt,markers->numset) ;
9514 STATUS(str) ; }
9515
9516 markers->valid[ipt] = False ;
9517
9518 /* restore colors to mark that the point is unset */
9519
9520 if( marks->inverted[itog] ){
9521 MCW_invert_widget( marks->tog[itog] ) ;
9522 #ifdef POPTOG
9523 MCW_invert_widget( marks->poptog[itog] ) ;
9524 #endif
9525 marks->inverted[itog] = False ;
9526 }
9527 }
9528
9529 /*--- allow transformation if all marks are set, etc. ---*/
9530
9531 vwarp = WARPED_VIEW(im3d->vinfo->view_type) ;
9532 transformable = marks->editable &&
9533 (markers->aflags[1] != MARKACTION_NONE) &&
9534 (markers->numdef == markers->numset) &&
9535 ISVALID_VIEW(vwarp) ;
9536
9537 SENSITIZE( marks->action_quality_pb , transformable ) ;
9538 SENSITIZE( marks->transform_pb , False ) ; /* require QC first */
9539
9540 /*--- force a redraw ---*/
9541
9542 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
9543 RESET_AFNI_QUIT(im3d) ;
9544 EXRETURN ;
9545 }
9546
9547 /*-----------------------------------------------------------------------
9548 change the resampling size
9549 -------------------------------------------------------------------------*/
9550
9551 void AFNI_resam_vox_av_CB( MCW_arrowval *av , XtPointer cd )
9552 {
9553 Three_D_View *im3d = (Three_D_View *) cd ;
9554
9555 ENTRY("AFNI_resam_vox_av_CB") ;
9556
9557 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9558
9559 if( av == im3d->vwid->dmode->resam_vox_av ){
9560 im3d->vinfo->resam_vox = av->fval ;
9561 SHOW_AFNI_PAUSE ;
9562 im3d->vinfo->tempflag = 1 ;
9563 AFNI_modify_viewing( im3d , True ) ; /* redisplay */
9564 SHOW_AFNI_READY ;
9565 }
9566 RESET_AFNI_QUIT(im3d) ;
9567 EXRETURN ;
9568 }
9569
9570 /*------------------------------------------------------------------------
9571 handle the changing arrowvals for marker display controls
9572 (set colors and sizes of markers)
9573 --------------------------------------------------------------------------*/
9574
9575 void AFNI_marks_disp_av_CB( MCW_arrowval *av , XtPointer client_data )
9576 {
9577 Three_D_View *im3d = (Three_D_View *) client_data ;
9578 int ipx = av->ival ;
9579
9580 ENTRY("AFNI_marks_disp_av_CB") ;
9581
9582 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9583
9584 if( av == im3d->vwid->marks->disp_pcolor_av ){
9585
9586 im3d->vwid->marks->ov_pcolor = ipx ;
9587
9588 } else if( av == im3d->vwid->marks->disp_scolor_av ){
9589
9590 im3d->vwid->marks->ov_scolor = ipx ;
9591
9592 } else if( av == im3d->vwid->marks->disp_size_av ){
9593
9594 im3d->vwid->marks->ov_size = ipx ;
9595
9596 AFNI_make_ptmask( im3d->vwid->marks->ov_size ,
9597 im3d->vwid->marks->ov_gap ,
9598 &(im3d->vwid->marks->ov_mask) ) ;
9599
9600 } else if( av == im3d->vwid->marks->disp_gap_av ){
9601
9602 im3d->vwid->marks->ov_gap = ipx ;
9603
9604 AFNI_make_ptmask( im3d->vwid->marks->ov_size ,
9605 im3d->vwid->marks->ov_gap ,
9606 &(im3d->vwid->marks->ov_mask) ) ;
9607
9608 } else
9609 EXRETURN ; /* some error */
9610
9611 /* force a redraw if any points are set */
9612
9613 if( im3d->anat_now->tagset != NULL ||
9614 (im3d->anat_now->markers != NULL && im3d->anat_now->markers->numset > 0) ){
9615
9616 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
9617 }
9618
9619 RESET_AFNI_QUIT(im3d) ;
9620 EXRETURN ;
9621 }
9622
9623 /*------------------------------------------------------------------------*/
9624
9625 #define PUTPIX(x,y) (tem->dx[npix] = (x) , tem->dy[npix++] = (y))
9626 #define CHKPIX if( npix >= MAXOVPIX ) break
9627
9628 void AFNI_make_ptmask( int size , int gap , AFNI_ovtemplate *tem )
9629 {
9630 register int ix , npix=0 , ax ;
9631
9632 ENTRY("AFNI_make_ptmask") ;
9633
9634 for( ix=-size ; ix <= size ; ix++ ){
9635 PUTPIX(ix,-size) ; CHKPIX ;
9636 PUTPIX(ix, size) ; CHKPIX ;
9637 ax = abs(ix) ;
9638 if( ax != size ){ PUTPIX( size,ix); CHKPIX; PUTPIX(-size,ix); CHKPIX; }
9639 if( ax > gap ){ PUTPIX(ix,0) ; CHKPIX; PUTPIX(0,ix) ; CHKPIX; }
9640 }
9641
9642 tem->numpix = npix ;
9643 EXRETURN ;
9644 }
9645
9646 /*------------- October 1998 --------------------------------------------*/
9647
9648 void AFNI_make_tagmask( int size , int gap , AFNI_ovtemplate *tem )
9649 {
9650 register int ix , npix=0 , ax ;
9651
9652 ENTRY("AFNI_make_tagmask") ;
9653
9654 PUTPIX(-size,0) ; PUTPIX(size,0) ;
9655 for( ix=-size+1 ; ix < size ; ix++ ){
9656 ax = abs(ix) ;
9657 PUTPIX(ix,ax-size) ; CHKPIX ;
9658 PUTPIX(ix,size-ax) ; CHKPIX ;
9659
9660 if( ax > gap ){ PUTPIX(ix,0); CHKPIX; PUTPIX(0,ix); CHKPIX; }
9661 }
9662
9663 tem->numpix = npix ;
9664 EXRETURN ;
9665 }
9666
9667
9668 /*========================================================================
9669 routines to switch "views" on a dataset
9670 ==========================================================================*/
9671
9672 void AFNI_switchview_CB( Widget w ,
9673 XtPointer client_data , XtPointer call_data )
9674 {
9675 Three_D_View *im3d = (Three_D_View *) client_data ;
9676 int bval ;
9677
9678 ENTRY("AFNI_switchview_CB") ;
9679
9680 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9681
9682 bval = AFNI_first_tog( LAST_VIEW_TYPE+1 ,
9683 im3d->vwid->view->view_bbox->wbut ) ;
9684
9685 if( bval < 0 || bval == im3d->vinfo->view_type ) EXRETURN ;
9686 if( im3d->anat_dset[bval] == NULL ) EXRETURN ;
9687
9688 SHOW_AFNI_PAUSE ;
9689
9690 DISABLE_INSTACORR(im3d) ; DESTROY_ICOR_setup(im3d->iset) ; /* 08 May 2009 */
9691
9692 POPDOWN_strlist_chooser ; /* might be choosing datasets */
9693 UNCLUSTERIZE(im3d) ; /* 13 Feb 2008 */
9694
9695 im3d->vinfo->view_type = bval ; /* set the new view type */
9696 AFNI_initialize_view( im3d->anat_now , im3d ) ; /* and initialize it */
9697
9698 SHOW_AFNI_READY ;
9699 RESET_AFNI_QUIT(im3d) ;
9700 EXRETURN ;
9701 }
9702
9703 /*--------------------------------------------------------
9704 Routines to clear out datasets
9705 ----------------------------------------------------------*/
9706
9707 void AFNI_purge_unused_dsets(void)
9708 {
9709 AFNI_purge_dsets( 0 ) ;
9710 }
9711
9712 void AFNI_purge_dsets( int doall )
9713 {
9714 int icc , iss , idd , ivv ;
9715 Three_D_View *im3d ;
9716 THD_session *sess ;
9717 THD_sessionlist *ssl = GLOBAL_library.sslist ;
9718 THD_3dim_dataset *dset ;
9719
9720 ENTRY("AFNI_purge_dsets") ;
9721
9722 /*-- sanity check --*/
9723
9724 if( ! ISVALID_SESSIONLIST(ssl) || ssl->num_sess <= 0 ) EXRETURN ;
9725
9726 /*-- for each session in the list --*/
9727
9728 for( iss=0 ; iss < ssl->num_sess ; iss++ ){
9729 sess = ssl->ssar[iss] ;
9730
9731 /*-- for each anat dataset in the session --*/
9732
9733 for( idd=0 ; idd < sess->num_dsset ; idd++ ){
9734 for( ivv=FIRST_VIEW_TYPE ; ivv <= LAST_VIEW_TYPE ; ivv++ ){
9735 dset = GET_SESSION_DSET(sess,idd,ivv) ;
9736 /* dset = sess->dsset_xform_table[idd][ivv] ; */
9737 if( dset == NULL ) continue ;
9738 if( doall ){ PURGE_DSET(dset) ; continue ; }
9739
9740 /*-- for each controller now running --*/
9741
9742 for( icc=0 ; icc < MAX_CONTROLLERS ; icc++ ){
9743 im3d = GLOBAL_library.controllers[icc] ;
9744 if( IM3D_VALID(im3d) &&
9745 ((dset==im3d->anat_now) ||
9746 (dset==im3d->fim_now) ||
9747 (dset==im3d->fimdata->fimdset)) ) break ;
9748 }
9749
9750 /*-- if didn't find it, purge it --*/
9751 if( icc == MAX_CONTROLLERS ){ PURGE_DSET(dset) ; }
9752 }
9753 }
9754
9755 } /* end of loop over sessions */
9756 EXRETURN ;
9757 }
9758
9759 /*---------------------------------------------------------------------
9760 setup for viewing, given the choices in im3d->vinfo
9761 (the indexes of the desired session and datasets, that is)
9762 -----------------------------------------------------------------------*/
9763
9764 void AFNI_initialize_view( THD_3dim_dataset *old_anat, Three_D_View *im3d )
9765 {
9766 int vvv , itog , lll , sss , aaa , fff , id ;
9767 THD_3dim_dataset *dset , *new_anat , *new_func ;
9768 THD_marker_set *markers ;
9769 AFNI_viewing_widgets *view ;
9770 AFNI_marks_widgets *marks ;
9771 THD_fvec3 fv ;
9772 THD_ivec3 iv ;
9773 static int first_image=1 ; /* 02 Feb 2018 */
9774
9775 ENTRY("AFNI_initialize_view") ;
9776
9777 if( ! IM3D_VALID(im3d) ) EXRETURN ;
9778
9779 vvv = im3d->vinfo->view_type ; /* locations of new data to view */
9780 sss = im3d->vinfo->sess_num ;
9781 aaa = im3d->vinfo->anat_num ;
9782 fff = im3d->vinfo->func_num ;
9783
9784 if(PRINT_TRACING)
9785 { char str[256] ;
9786 sprintf(str,"view=%d session=%d anat=%d func=%d",vvv,sss,aaa,fff);
9787 STATUS(str) ; }
9788
9789 new_anat = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], aaa, vvv) ;
9790 new_func = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], fff, vvv) ;
9791
9792 /* new_anat = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][vvv] ;
9793 new_func = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[fff][vvv] ;
9794 */
9795 AFNI_vedit_clear( im3d->fim_now ) ; /* 05 Sep 2006 */
9796
9797 /*----------------------------------------------*/
9798 /*--- if the old dataset has markers and the
9799 marker panel is open, shut it down now ---*/
9800
9801 if( old_anat != NULL && /** old_anat->markers != NULL && **/
9802 old_anat != new_anat && XtIsManaged(im3d->vwid->marks->frame) ){
9803
9804 AFNI_marks_action_CB( NULL, (XtPointer) im3d, NULL) ; /* "done" */
9805 }
9806
9807 if( GLOBAL_argopt.auto_purge == True ){ /* purge old datasets? */
9808
9809 STATUS("purging old datasets from memory (maybe)") ;
9810
9811 im3d->anat_now = new_anat ;
9812 im3d->fim_now = new_func ;
9813 AFNI_purge_unused_dsets() ;
9814 }
9815
9816 /*---------------------------------------------------------*/
9817 /* set the new datasets that we will deal with from now on */
9818
9819 for( id=0 ; id <= LAST_VIEW_TYPE ; id++ ){
9820 im3d->anat_dset[id] = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], aaa, id) ;
9821 im3d->fim_dset[id] = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], fff, id) ;
9822
9823 /* im3d->anat_dset[id] = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][id] ;
9824 im3d->fim_dset[id] = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[fff][id] ;
9825 */
9826 if( ISVALID_3DIM_DATASET(im3d->anat_dset[id]) )
9827 SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], True ) ;
9828 else
9829 SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], False) ;
9830 }
9831
9832 im3d->anat_now = im3d->anat_dset[vvv] ;
9833 im3d->fim_now = im3d->fim_dset[vvv] ;
9834 im3d->ss_now = GLOBAL_library.sslist->ssar[sss] ;
9835
9836 if( !ISVALID_DSET(im3d->fim_now) ) AFNI_SEE_FUNC_OFF(im3d) ; /* 22 May 2009 */
9837
9838 SENSITIZE( im3d->vwid->func->clu_rowcol , DSET_INMEMORY(im3d->fim_now) ) ;
9839
9840 if( !DSET_INMEMORY(im3d->fim_now) ) UNCLUSTERIZE(im3d) ; /* 14 Feb 2008 */
9841
9842 /*------------------------------------------------*/
9843 /*--- if markers are defined, then set them up ---*/
9844
9845 dset = im3d->anat_now ;
9846 markers = dset->markers ;
9847 view = im3d->vwid->view ;
9848 marks = im3d->vwid->marks ;
9849
9850 if( markers == NULL ){ /*--------- markers NOT defined ---------*/
9851
9852 STATUS("turning markers off") ;
9853
9854 /* turn controls off */
9855
9856 #if 0
9857 SENSITIZE( view->define_marks_pb , False ) ;
9858 SENSITIZE( view->see_marks_bbox->wrowcol , False ) ;
9859 #endif
9860
9861 marks->editable = False ;
9862
9863 vvv = MCW_val_bbox( view->see_marks_bbox ) ;
9864 marks->tag_visible = marks->ov_visible = (vvv) ? True : False ;
9865
9866 XtUnmanageChildren( marks->always_popup , marks->num_always_popup ) ;
9867 XtUnmanageChildren( marks->sometimes_popup , marks->num_sometimes_popup ) ;
9868
9869 } else { /*------------- markers ARE defined ----------------*/
9870
9871 STATUS("turning markers on") ;
9872
9873 /* turn controls on */
9874
9875 SENSITIZE( view->define_marks_pb , True ) ;
9876 SENSITIZE( view->see_marks_bbox->wrowcol , True ) ;
9877
9878 vvv = MCW_val_bbox( view->see_marks_bbox ) ;
9879 marks->tag_visible = marks->ov_visible = (vvv) ? True : False ;
9880
9881 marks->editable = False ;
9882 MCW_set_bbox( marks->edits_bbox , 0 ) ;
9883
9884 #ifdef POPTOG
9885 SENSITIZE( marks->pop_set_pb , marks->editable ) ;
9886 SENSITIZE( marks->pop_clear_pb , marks->editable ) ;
9887 #endif
9888
9889 /* copy help into location where MCW_help will find it */
9890
9891 for( itog=0 ; itog < MARKS_MAXNUM ; itog++ ){
9892 MCW_strncpy( &(marks->tog_help[itog][0]) ,
9893 &(markers->help[itog][0]) , MARKS_MAXHELP ) ;
9894 }
9895
9896 /* copy the non-empty labels into the toggle labels,
9897 and make the toggle buttons active (panel AND popup) */
9898
9899 XtManageChildren( marks->always_popup ,
9900 marks->num_always_popup ) ;
9901
9902 for( itog=0 ; itog < MARKS_MAXNUM ; itog++ ){
9903 lll = strlen( &(markers->label[itog][0]) ) ;
9904
9905 if( lll == 0 ){
9906 XtUnmanageChild( marks->tog[itog] ) ; /* empty label! */
9907 #ifdef POPTOG
9908 XtUnmanageChild( marks->poptog[itog] ) ;
9909 #endif
9910 } else {
9911 MCW_set_widget_label( marks->tog[itog] ,
9912 &(markers->label[itog][0]) ) ;
9913 SENSITIZE( marks->tog[itog] , True ) ;
9914 XtManageChild( marks->tog[itog] ) ;
9915
9916 #ifdef POPTOG
9917 MCW_set_widget_label( marks->poptog[itog] ,
9918 &(markers->label[itog][0]) ) ;
9919 SENSITIZE( marks->poptog[itog] , True ) ;
9920 XtManageChild( marks->poptog[itog] ) ;
9921 #endif
9922
9923 if( markers->valid[itog] && ! marks->inverted[itog] ){
9924 MCW_invert_widget( marks->tog[itog] ) ;
9925 #ifdef POPTOG
9926 MCW_invert_widget( marks->poptog[itog] ) ;
9927 #endif
9928 marks->inverted[itog] = True ;
9929 }
9930
9931 if( ! markers->valid[itog] && marks->inverted[itog] ){
9932 MCW_invert_widget( marks->tog[itog] ) ;
9933 #ifdef POPTOG
9934 MCW_invert_widget( marks->poptog[itog] ) ;
9935 #endif
9936 marks->inverted[itog] = False ;
9937 }
9938 }
9939 } /* end of loop over markers */
9940
9941 } /* end of dealing with markers */
9942
9943 /*------------------------------*/
9944 /*----- set up for viewing -----*/
9945
9946 AFNI_setup_viewing( im3d , True ) ;
9947 AFNI_set_rinfo_labels( im3d ) ; /* 11 Mar 2020 */
9948
9949 /*-----------------------------------------------------*/
9950 /*----- reset viewpoint to same Dicom coordinates -----*/
9951
9952 if( im3d->type == AFNI_3DDATA_VIEW ){
9953 fv = AFNI_transform_vector(
9954 old_anat ,
9955 TEMP_FVEC3( im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ),
9956 dset ) ;
9957
9958 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
9959 fv = THD_dicomm_to_3dmm( dset , fv ) ;
9960 iv = THD_3dmm_to_3dind( dset , fv ) ;
9961 } else {
9962 LOAD_IVEC3( iv, im3d->vinfo->i1, im3d->vinfo->j2, im3d->vinfo->k3 ) ;
9963 }
9964
9965 /* 27 Jan 2004: set coordinate to center of dataset
9966 if we were formerly looking at the dummy dataset */
9967
9968 if( (im3d->dummied && !GLOBAL_library.have_dummy_dataset) ||
9969 AFNI_yesenv("AFNI_RECENTER_VIEWING") ){
9970 im3d->dummied = 0 ;
9971 LOAD_IVEC3( iv , im3d->anat_now->daxes->nxx/2 ,
9972 im3d->anat_now->daxes->nyy/2 ,
9973 im3d->anat_now->daxes->nzz/2 ) ;
9974 }
9975
9976 DISABLE_LOCK ; /* 11 Nov 1996 */
9977
9978 CLU_setup_alpha_tables(im3d) ; /* Jul 2010 */
9979
9980 AFNI_view_setter(im3d,NULL) ;
9981 AFNI_set_viewpoint( im3d, iv.ijk[0],iv.ijk[1],iv.ijk[2] , REDISPLAY_ALL ) ;
9982
9983 ENABLE_LOCK ; /* 11 Nov 1996 */
9984
9985 SAVE_VPT(im3d) ; /* save current location as jumpback */
9986
9987 #if 0 /* no longer needed */
9988 if( first_image &&
9989 GLOBAL_argopt.left_is_left &&
9990 im3d->anat_now->dblk->diskptr->storage_mode == STORAGE_BY_IMAGE_FILE ){
9991
9992 first_image = 0 ;
9993 (void) MCW_popup_message( im3d->vwid->picture ,
9994 " \n"
9995 "*****--- WARNING: ---*****\n"
9996 " Image viewing is set to\n"
9997 " Left-is-Left, so that\n"
9998 " viewing .jpg or .png\n"
9999 " 'datasets' might show\n"
10000 " as reflected left-right.\n"
10001 " To fix this, press the\n"
10002 " l (lower case L) key\n"
10003 " when the mouse cursor\n"
10004 " focus is over the image\n"
10005 " viewer window.\n"
10006 , MCW_USER_KILL | MCW_TIMER_KILL ) ;
10007 }
10008 #endif
10009
10010 EXRETURN ;
10011 }
10012
10013 /*----------------------------------------------------------------------*/
10014 /*! Find the warp that takes one dataset to another, if it exists.
10015 [28 Aug 2002]
10016 ------------------------------------------------------------------------*/
10017
10018 THD_warp * AFNI_find_warp( THD_3dim_dataset *dset_to , THD_3dim_dataset *dset_from )
10019 {
10020 THD_warp *swarp = NULL ;
10021 char idkey[256] ;
10022
10023 if( GLOBAL_library.warptable == NULL ||
10024 dset_to == NULL ||
10025 dset_from == NULL ) return NULL ;
10026
10027 sprintf(idkey,"%s,%s",dset_to->idcode.str,dset_from->idcode.str) ;
10028 swarp = (THD_warp *) findin_Htable( idkey , GLOBAL_library.warptable ) ;
10029 return swarp ;
10030 }
10031
10032 /*----------------------------------------------------------------------------*/
10033 /* Set up the thresholded statistic on the fim [moved here 27 Jun 2019] */
10034
10035 #undef THBOT
10036 #undef THTOP
10037 #undef THBIG
10038 #define THBIG 1.e+37f
10039 #define THBOT(t) ((im3d->vinfo->thr_sign==0 || im3d->vinfo->thr_sign==2) ? (-(t)) : (-THBIG))
10040 #define THTOP(t) ((im3d->vinfo->thr_sign==0 || im3d->vinfo->thr_sign==1) ? (t) : (THBIG))
10041
10042 void AFNI_setup_thrstat( Three_D_View *im3d , int force )
10043 {
10044 ENTRY("AFNI_setup_thrstat") ;
10045
10046 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
10047
10048 if( im3d->vinfo->func_visible ){
10049 float thr,thbot,thtop,fac ; MRI_IMAGE *thim , *ovim ; float_pair ovmm ;
10050 thr = get_3Dview_func_thresh(im3d,1) ;
10051 thbot = THBOT(thr) ; thtop = THTOP(thr) ;
10052 DSET_load(im3d->fim_now) ; /* 24 Jun 2019 */
10053 if( force || im3d->vinfo->fim_index != im3d->fim_thrindex ||
10054 FLDIF(thbot,im3d->fim_thrbot) || FLDIF(thtop,im3d->fim_thrtop) ){
10055 ovim = AFNI_dataset_displayim(im3d->fim_now,im3d->vinfo->fim_index) ;
10056 thim = AFNI_dataset_displayim(im3d->fim_now,im3d->vinfo->thr_index) ;
10057 IM3D_CLEAR_THRSTAT(im3d) ;
10058 if( ovim != NULL && thim != NULL ){
10059 im3d->fim_thrbot = thbot ; im3d->fim_thrtop = thtop ;
10060 fac = DSET_BRICK_FACTOR(im3d->fim_now,im3d->vinfo->thr_index) ;
10061 if( fac > 0.0f ){ thbot /= fac ; thtop /= fac ; }
10062 ovmm = mri_threshold_minmax(thbot,thtop,thim,ovim) ;
10063 im3d->fim_thresh_min = ovmm.a ; im3d->fim_thresh_max = ovmm.b ;
10064 fac = DSET_BRICK_FACTOR(im3d->fim_now,im3d->vinfo->fim_index) ;
10065 if( fac > 0.0f ){ im3d->fim_thresh_min *= fac ; im3d->fim_thresh_max *= fac ; }
10066 }
10067 if( im3d->fim_thresh_min <= im3d->fim_thresh_max ){
10068 char str[256] ; int_pair mij = mri_threshold_minmax_indexes() ;
10069 sprintf(str,"OLay thresholded range: %f : %f",im3d->fim_thresh_min,im3d->fim_thresh_max ) ;
10070 MCW_register_hint( im3d->vwid->func->range_label , str ) ;
10071 im3d->fim_thresh_min_ijk = mij.i ;
10072 im3d->fim_thresh_max_ijk = mij.j ;
10073 im3d->fim_thrindex = im3d->vinfo->fim_index ;
10074 } else {
10075 MCW_register_hint( im3d->vwid->func->range_label , "OLay thresholded range: unknown" ) ;
10076 im3d->fim_thrindex = -1 ;
10077 }
10078 SENSITIZE(im3d->vwid->func->pbar_jumpto_thmax_pb,(im3d->fim_thresh_max_ijk > 0)) ;
10079 SENSITIZE(im3d->vwid->func->pbar_jumpto_thmin_pb,
10080 (im3d->fim_thresh_min_ijk > 0)
10081 && (im3d->fim_thresh_min_ijk != im3d->fim_thresh_max_ijk) ) ;
10082 }
10083 } else {
10084 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
10085 MCW_register_hint( im3d->vwid->func->range_label , "OLay thresholded range: unknowable" ) ;
10086 }
10087
10088 EXRETURN ;
10089 }
10090
10091 #undef THBOT
10092 #undef THTOP
10093 #undef THBIG
10094
10095 /*----------------------------------------------------------------------
10096 set the stage for viewing:
10097 -- prepare for warp-on-demand image production
10098 -- setup the viewing FD_bricks
10099 -- attach them to the viewing windows
10100 -- turn widget controls on and off, based on data status
10101
10102 02 Nov 1996: set up view specific viewing stuff in im3d,
10103 rather than in the datasets. This is to allow
10104 for the possibility that more than one im3d
10105 may be looking at the same dataset at once.
10106
10107 30 Nov 1997: add bucket stuff
10108 ------------------------------------------------------------------------*/
10109
10110 void AFNI_setup_viewing( Three_D_View *im3d , RwcBoolean rescaled )
10111 {
10112 FD_brick **fbr ;
10113 XmString xstr ;
10114 RwcBoolean same , dont_fix_pts , writer ,
10115 anat_brick_possible , func_brick_possible ;
10116 int val , top ;
10117
10118 static THD_3dim_dataset *old_fim = NULL ; /* 12 Dec 2001 */
10119 static Three_D_View *old_im3d = NULL ; /* 29 Jan 2002 */
10120 static THD_3dim_dataset *old_anat = NULL ; /* 12 Dec 2001 */
10121 static int old_anat_nvals = -1 ; /* 21 Jul 2009 */
10122 static int old_func_nvals = -1 ; /* 21 Jul 2009 */
10123
10124 ENTRY("AFNI_setup_viewing") ;
10125
10126 if( ! IM3D_VALID(im3d) ) EXRETURN ;
10127
10128 /*-----------------------------------------------------*/
10129 /*--- set up the anat w-o-d axes and viewing bricks ---*/
10130
10131 anat_brick_possible = DSET_INMEMORY(im3d->anat_now) ;
10132
10133 /*- The Ides of March, 2000: allow switching back to "view brick" -*/
10134
10135 if( anat_brick_possible &&
10136 im3d->vinfo->force_anat_wod &&
10137 im3d->vinfo->tempflag == 0 &&
10138 !AFNI_noenv("AFNI_VIEW_ANAT_BRICK") ){
10139
10140 STATUS("setting anatmode_bbox back to 'View ULay Data Brick'") ;
10141 im3d->vinfo->force_anat_wod = 0 ;
10142 MCW_set_bbox( im3d->vwid->dmode->anatmode_bbox , DMODE_BRICK_BVAL ) ;
10143 }
10144
10145 im3d->anat_wod_flag = ( im3d->vinfo->force_anat_wod || /* 02 Nov 1996 */
10146 !anat_brick_possible ) ;
10147
10148 if( im3d->anat_wod_flag ) /* 02 Nov 1996 */
10149 THD_edit_dataxes( im3d->vinfo->resam_vox ,
10150 im3d->anat_now->daxes , im3d->wod_daxes ) ;
10151 else
10152 *(im3d->wod_daxes) = *(im3d->anat_now->daxes) ;
10153
10154 im3d->anat_voxwarp->type =
10155 im3d->fim_voxwarp->type = ILLEGAL_TYPE ; /* 02 Nov 1996 */
10156
10157 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
10158
10159 fbr = THD_setup_bricks( im3d->anat_now ) ;
10160 if( fbr == NULL ){
10161 ERROR_message("THD_setup_bricks of anat_now fails!") ; EXRETURN ;
10162 }
10163 DESTROY_FD_BRICK(im3d->b123_anat) ; im3d->b123_anat = fbr[0] ;
10164 DESTROY_FD_BRICK(im3d->b231_anat) ; im3d->b231_anat = fbr[1] ;
10165 DESTROY_FD_BRICK(im3d->b312_anat) ; im3d->b312_anat = fbr[2] ;
10166 myXtFree(fbr) ;
10167
10168 im3d->b123_anat->parent =
10169 im3d->b231_anat->parent =
10170 im3d->b312_anat->parent = (XtPointer) im3d ;
10171
10172 im3d->b123_anat->resam_code =
10173 im3d->b231_anat->resam_code =
10174 im3d->b312_anat->resam_code = im3d->vinfo->anat_resam_mode ;
10175
10176 im3d->b123_anat->thr_resam_code = /* 30 Jul 2003 */
10177 im3d->b231_anat->thr_resam_code =
10178 im3d->b312_anat->thr_resam_code = im3d->vinfo->anat_resam_mode ;
10179
10180 /* 30 Nov 1997: don't go past end of dataset */
10181
10182 if( im3d->vinfo->anat_index >= DSET_NVALS(im3d->anat_now) )
10183 im3d->vinfo->anat_index = DSET_NVALS(im3d->anat_now) - 1 ;
10184
10185 /*-----------------------------------------------------*/
10186 /*--- set up the func w-o-d axes and viewing bricks ---*/
10187
10188 if( ISVALID_3DIM_DATASET(im3d->fim_now) ){ /* that is, if we have func */
10189
10190 STATUS("function brick setup") ;
10191
10192 /*-- access data in dataset im3d->fim_now IF AND ONLY IF
10193 1) its actual data axes are the same as the wod_daxes
10194 2) it has actual data
10195 3) the user hasn't officially declared for warp-on-demand
10196 4) the dataset doesn't have a warp to bring it into
10197 alignment with the current anat dataset (self_warp) --*/
10198
10199 STATUS("deciding whether to use function WOD") ;
10200
10201 func_brick_possible =
10202 EQUIV_DATAXES( im3d->fim_now->daxes , im3d->wod_daxes ) && /* 02 Nov 1996 */
10203 DSET_INMEMORY( im3d->fim_now ) ;
10204
10205 /*- 27 Aug 2002: see if there is a self_warp from
10206 fim_now back to anat_now; if so, install it;
10207 this is a coordinate-to-coordinate tranformation,
10208 and requires warp-on-demand viewing -*/
10209
10210 { THD_warp *swarp = AFNI_find_warp( im3d->anat_now , im3d->fim_now ) ;
10211 im3d->fim_selfwarp = swarp ; /* transform from fim to anat coords */
10212 if( swarp != NULL ) func_brick_possible = 0 ; /* require warp-on-demand */
10213 }
10214
10215 /*- The Ides of March, 2000: allow switching back to "view brick" -*/
10216
10217 if( func_brick_possible &&
10218 ( ( im3d->vinfo->force_func_wod &&
10219 im3d->vinfo->tempflag == 0 &&
10220 !AFNI_noenv("AFNI_VIEW_FUNC_BRICK") ) ||
10221 ( !im3d->anat_wod_flag && /* 08 Aug 2003 */
10222 im3d->anat_now == im3d->fim_now ) ) ){
10223
10224 STATUS("setting funcmode_bbox back to 'View Func Data Brick'") ;
10225 im3d->vinfo->force_func_wod = 0 ;
10226 MCW_set_bbox( im3d->vwid->dmode->funcmode_bbox , DMODE_BRICK_BVAL ) ;
10227 }
10228
10229 if( func_brick_possible && ! im3d->vinfo->force_func_wod ){
10230 STATUS("not forcing function WOD") ;
10231 im3d->fim_wod_flag = False ; /* 02 Nov 1996 */
10232 } else {
10233 STATUS("forcing function WOD") ;
10234 im3d->fim_wod_flag = True ; /* 02 Nov 1996 */
10235 }
10236
10237 LOAD_FUNC_VIEW(im3d) ; /* 02 Nov 1996 */
10238
10239 fbr = THD_setup_bricks( im3d->fim_now ) ;
10240 if( fbr == NULL ){
10241 fprintf(stderr,"THD_setup_bricks of fim_now fails!\n") ; EXRETURN ;
10242 }
10243 DESTROY_FD_BRICK(im3d->b123_fim) ; im3d->b123_fim = fbr[0] ;
10244 DESTROY_FD_BRICK(im3d->b231_fim) ; im3d->b231_fim = fbr[1] ;
10245 DESTROY_FD_BRICK(im3d->b312_fim) ; im3d->b312_fim = fbr[2] ;
10246 myXtFree(fbr) ;
10247
10248 im3d->b123_fim->brother = (XtPointer)im3d->b123_anat ;
10249 im3d->b231_fim->brother = (XtPointer)im3d->b231_anat ;
10250 im3d->b312_fim->brother = (XtPointer)im3d->b312_anat ;
10251
10252 im3d->b123_anat->brother = (XtPointer)im3d->b123_fim ;
10253 im3d->b231_anat->brother = (XtPointer)im3d->b231_fim ;
10254 im3d->b312_anat->brother = (XtPointer)im3d->b312_fim ;
10255
10256 im3d->b123_fim->parent =
10257 im3d->b231_fim->parent =
10258 im3d->b312_fim->parent = (XtPointer) im3d ;
10259
10260 im3d->b123_fim->resam_code =
10261 im3d->b231_fim->resam_code =
10262 im3d->b312_fim->resam_code = im3d->vinfo->func_resam_mode ;
10263
10264 im3d->b123_fim->thr_resam_code = /* 09 Dec 1997 */
10265 im3d->b231_fim->thr_resam_code =
10266 im3d->b312_fim->thr_resam_code = im3d->vinfo->thr_resam_mode ;
10267
10268 /* 30 Nov 1997: don't go past end of bucket */
10269
10270 if( im3d->vinfo->fim_index >= DSET_NVALS(im3d->fim_now) )
10271 im3d->vinfo->fim_index = DSET_NVALS(im3d->fim_now) - 1 ;
10272
10273 if( im3d->vinfo->thr_index >= DSET_NVALS(im3d->fim_now) )
10274 im3d->vinfo->thr_index = DSET_NVALS(im3d->fim_now) - 1 ;
10275
10276 /* first time in for this controller (or if so ordered),
10277 set fim_index and thr_index to reasonable values (IMHO)
10278 -- modified 12 Jan 2017 to define 'reasonable' more reasonably */
10279
10280 { static int first=1, ffim[MAX_CONTROLLERS] ; int qq ;
10281 if( first ){
10282 first=0; for( qq=0; qq < MAX_CONTROLLERS; qq++ ) ffim[qq]=1;
10283 }
10284 qq = AFNI_controller_index(im3d) ;
10285 if( ffim[qq] || im3d->vinfo->func_init_subbricks ){
10286 int_pair otp = find_reasonable_overlay_indexes(im3d->fim_now) ;
10287 if( otp.i >= 0 ) im3d->vinfo->fim_index = otp.i ;
10288 if( otp.j >= 0 ) im3d->vinfo->thr_index = otp.j ;
10289 ffim[qq] = 0 ;
10290 }
10291 }
10292
10293 im3d->vinfo->func_init_subbricks = 0 ; /* 12 Jan 2017 */
10294
10295 /* 29 Jan 2008: enable/disable the FDR-izing button */
10296
10297 { int scod=DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ,
10298 doit=FUNC_IS_STAT(scod) && DSET_INMEMORY(im3d->fim_now) ;
10299 XtSetSensitive( im3d->vwid->func->thr_fdr_pb , (RwcBoolean)doit ) ;
10300 }
10301
10302 } else { /* 29 Jul 2003: no longer possible */
10303
10304 STATUS("no function dataset") ;
10305
10306 DESTROY_FD_BRICK(im3d->b123_fim) ; im3d->b123_fim = NULL ;
10307 DESTROY_FD_BRICK(im3d->b231_fim) ; im3d->b231_fim = NULL ;
10308 DESTROY_FD_BRICK(im3d->b312_fim) ; im3d->b312_fim = NULL ;
10309
10310 func_brick_possible = False ;
10311 }
10312
10313 /*------------------------------------------------------------------*/
10314 /*--- set widget sensitivity based on kind of data now available ---*/
10315
10316 STATUS("turning widgets on and/or off:") ;
10317
10318 /*--- datamode controls ---*/
10319
10320 STATUS(" -- datamode widgets") ;
10321
10322 if( anat_brick_possible ){
10323 SENSITIZE( im3d->vwid->dmode->anatmode_bbox->wbut[DMODE_BRICK] , True ) ;
10324 } else {
10325 SENSITIZE( im3d->vwid->dmode->anatmode_bbox->wbut[DMODE_BRICK] , False ) ;
10326 MCW_set_bbox( im3d->vwid->dmode->anatmode_bbox , DMODE_WOD_BVAL ) ;
10327 im3d->vinfo->force_anat_wod = 1 ;
10328 }
10329
10330 if( func_brick_possible ){
10331 SENSITIZE( im3d->vwid->dmode->funcmode_bbox->wbut[DMODE_BRICK] , True ) ;
10332 } else {
10333 SENSITIZE( im3d->vwid->dmode->funcmode_bbox->wbut[DMODE_BRICK] , False ) ;
10334 MCW_set_bbox( im3d->vwid->dmode->funcmode_bbox , DMODE_WOD_BVAL ) ;
10335 im3d->vinfo->force_func_wod = 1 ;
10336 }
10337
10338 AV_SENSITIZE( im3d->vwid->dmode->anat_resam_av , im3d->anat_wod_flag ) ;
10339
10340 AV_SENSITIZE( im3d->vwid->dmode->resam_vox_av , im3d->anat_wod_flag ) ;
10341
10342 /* Jan 31, 1995: don't allow writes of datasets without warp parents */
10343 /* Jun 22, 1995: allow it if destruct mode is actuated! */
10344
10345 if( GLOBAL_argopt.destruct ){ /* not currently implemented */
10346 writer = True ;
10347 } else {
10348 writer = (RwcBoolean) DSET_WRITEABLE(im3d->anat_now) ; /* mod 26 Mar 2001 */
10349 }
10350
10351 SENSITIZE( im3d->vwid->dmode->write_anat_pb , writer ) ;
10352
10353 if( GLOBAL_argopt.destruct ){ /* not currently implemented */
10354 writer = (RwcBoolean) ISVALID_3DIM_DATASET(im3d->fim_now) ;
10355 } else {
10356 writer = (RwcBoolean) DSET_WRITEABLE(im3d->fim_now) ; /* mod 26 Mar 2001 */
10357 }
10358
10359 SENSITIZE( im3d->vwid->dmode->write_func_pb , writer ) ;
10360
10361 /* 18 Oct 2010: SaveAs buttons on or off? */
10362
10363 writer = DSET_INMEMORY(im3d->anat_now) ;
10364 SENSITIZE( im3d->vwid->dmode->saveas_anat_pb , writer ) ;
10365
10366 writer = DSET_INMEMORY(im3d->fim_now) ;
10367 SENSITIZE( im3d->vwid->dmode->saveas_func_pb , writer ) ;
10368
10369 /*--- function controls (always see them) ---*/
10370
10371 { RwcBoolean have_fim = ISVALID_3DIM_DATASET(im3d->fim_now) ;
10372 RwcBoolean have_thr = have_fim ;
10373
10374 static int first=1, zfim[MAX_CONTROLLERS] ; int qq ;
10375 if( first ){
10376 first=0; for( qq=0; qq < MAX_CONTROLLERS; qq++ ) zfim[qq]=1;
10377 }
10378
10379 STATUS(" -- function widgets ON") ;
10380
10381 SENSITIZE( im3d->vwid->view->define_func_pb , True ) ; /* always on */
10382 SENSITIZE( im3d->vwid->view->see_func_bbox->wtop , True ) ;
10383
10384 /* setup threshold slider to be always on */
10385
10386 XtManageChild( im3d->vwid->func->thr_rowcol ) ;
10387 qq = AFNI_controller_index(im3d) ;
10388 if( zfim[qq] && ISVALID_DSET(im3d->fim_now) ){
10389 STATUS(" -- set threshold to zero (startup)") ;
10390 XmScaleSetValue( im3d->vwid->func->thr_scale , 1 ) ;
10391 im3d->vinfo->func_threshold = THR_factor ; zfim[qq] = 0 ;
10392 }
10393 FIX_SCALE_SIZE(im3d) ; FIX_SCALE_VALUE(im3d) ;
10394
10395 /* turn on various ways of making function into underlay */
10396
10397 #ifdef USE_UNDERLAY_BBOX
10398 SENSITIZE( im3d->vwid->func->underlay_bbox->wbut[UNDERLAY_ALLFUNC], have_fim ) ;
10399 #endif
10400
10401 /* set underlay type back to anat if no function */
10402
10403 if( ! have_fim ) im3d->vinfo->underlay_type = UNDERLAY_ANAT ;
10404
10405 /* allow resample control only if we are using w-o-d */
10406
10407 AV_SENSITIZE( im3d->vwid->dmode->func_resam_av,
10408 have_fim && im3d->fim_wod_flag ) ;
10409
10410 AV_SENSITIZE( im3d->vwid->dmode->thr_resam_av, /* 09 Dec 1997 */
10411 have_fim && im3d->fim_wod_flag ) ;
10412
10413 /** Mar 1996: modify the threshold scale stuff **/
10414 /** Oct 1996: increase decim by 1 to allow for
10415 new precision 0..999 of scale (used to be 0..99) **/
10416 /** Nov 1997: the scale precision is now set by macro THR_top_expon,
10417 and its settings are done in routine AFNI_set_thresh_top **/
10418
10419 #if 0
10420 if( have_thr ){
10421 int iv = im3d->vinfo->thr_index , jj ;
10422
10423 jj = DSET_BRICK_STATCODE(im3d->fim_now,iv) ;
10424 if( jj > 0 )
10425 MCW_set_widget_label( im3d->vwid->func->thr_label ,
10426 FUNC_label[jj] ) ;
10427 else
10428 MCW_set_widget_label( im3d->vwid->func->thr_label ,
10429 DSET_BRICK_LABEL(im3d->fim_now,iv) ) ;
10430 }
10431 #endif
10432
10433 /* set the pval label at the bottom of the scale */
10434
10435 AFNI_set_thr_pval( im3d ) ;
10436
10437 /*** 29 Jul 2003: always do buckets now ***/
10438
10439 XtManageChild( im3d->vwid->func->anat_buck_av->wrowcol ) ;
10440 XtManageChild( im3d->vwid->func->fim_buck_av->wrowcol ) ;
10441 XtManageChild( im3d->vwid->func->thr_buck_av->wrowcol ) ;
10442
10443 /** 12 Dec 2001: only refit menus if dataset has changed **/
10444
10445 if( have_fim &&
10446 (im3d->fim_now != old_fim || im3d != old_im3d ||
10447 DSET_NVALS(im3d->fim_now) != old_func_nvals ) ){
10448 refit_MCW_optmenu( im3d->vwid->func->fim_buck_av ,
10449 0 , /* new minval */
10450 DSET_NVALS(im3d->fim_now)-1 , /* new maxval */
10451 im3d->vinfo->fim_index , /* new inival */
10452 0 , /* new decim? */
10453 AFNI_bucket_label_CB , /* text routine */
10454 im3d->fim_now /* text data */
10455 ) ;
10456 refit_MCW_optmenu( im3d->vwid->func->thr_buck_av ,
10457 0 , /* new minval */
10458 DSET_NVALS(im3d->fim_now)-1 , /* new maxval */
10459 im3d->vinfo->thr_index , /* new inival */
10460 0 , /* new decim? */
10461 AFNI_bucket_label_CB , /* text routine */
10462 im3d->fim_now /* text data */
10463 ) ;
10464 }
10465
10466 if( im3d->anat_now != old_anat || im3d != old_im3d ||
10467 DSET_NVALS(im3d->anat_now) != old_anat_nvals ){
10468 refit_MCW_optmenu( im3d->vwid->func->anat_buck_av ,
10469 0 , /* new minval */
10470 DSET_NVALS(im3d->anat_now)-1 , /* new maxval */
10471 im3d->vinfo->anat_index , /* new inival */
10472 0 , /* new decim? */
10473 AFNI_bucket_label_CB , /* text routine */
10474 im3d->anat_now /* text data */
10475 ) ;
10476 }
10477
10478 XtManageChild( im3d->vwid->func->buck_rowcol ) ; /* make itvisible */
10479 XtManageChild( im3d->vwid->func->buck_frame ) ;
10480 }
10481
10482 /*--- set the function type bboxes based on the current
10483 viewing set up (which may have changed due to lack of function) ---*/
10484
10485 STATUS(" -- function underlay widgets") ;
10486
10487 #ifdef USE_UNDERLAY_BBOX
10488 MCW_set_bbox( im3d->vwid->func->underlay_bbox , 1 << im3d->vinfo->underlay_type ) ;
10489 #endif
10490
10491 AFNI_assign_ulay_bricks(im3d) ; /* 10 Jun 2014 */
10492
10493 /*--------------------------------------------------------*/
10494 /*--- 3/24/95: deal with the new range widgets in func ---*/
10495
10496 AFNI_reset_func_range( im3d ) ;
10497
10498 #ifdef ALLOW_DATASET_VLIST
10499 /*---------------------------------------------------------*/
10500 /*--- May 1995: if points exist in some other dataset ---*/
10501 /*--- associated with this one, but not here, ---*/
10502 /*--- transform the points to this dataset. ---*/
10503
10504 dont_fix_pts = ! rescaled ; /* if didn't rescale, don't need to fix */
10505
10506 if( im3d->anat_now->pts == NULL ){
10507 int ii ;
10508 THD_3dim_dataset *dset_orig = NULL ;
10509 THD_fvec3 fv ;
10510
10511 STATUS(" -- scanning for points in other datasets") ;
10512 for( ii=0 ; ii <= LAST_VIEW_TYPE ; ii++ ){
10513 if( ISVALID_3DIM_DATASET(im3d->anat_dset[ii]) &&
10514 im3d->anat_dset[ii]->pts != NULL &&
10515 im3d->anat_dset[ii]->pts_original == True ){
10516
10517 dset_orig = im3d->anat_dset[ii] ;
10518 break ;
10519 }
10520 }
10521
10522 if( dset_orig != NULL ){
10523 STATUS(" -- processing points in other dataset") ;
10524
10525 dont_fix_pts = True ; /* fixing here, so not later */
10526 im3d->anat_now->pts_original = False ;
10527 INIT_VLIST( im3d->anat_now->pts , im3d->anat_now ) ;
10528
10529 for( ii=0 ; ii < dset_orig->pts->num ; ii++ ){
10530 fv = THD_3dmm_to_dicomm( dset_orig , dset_orig->pts->xyz[ii] ) ;
10531 fv = AFNI_transform_vector( dset_orig , fv , im3d->anat_now ) ;
10532 fv = THD_dicomm_to_3dmm( im3d->anat_now , fv ) ;
10533 ADD_FVEC_TO_VLIST( im3d->anat_now->pts , fv ) ;
10534 }
10535 }
10536 }
10537
10538 /*--------------------------------------------------*/
10539 /*--- May 1995: if points exist in this dataset, ---*/
10540 /*--- load their 3dind coordinates. ---*/
10541
10542 if( im3d->anat_now->pts != NULL && ! dont_fix_pts ){
10543 int ii ;
10544 STATUS(" -- processing points in this dataset") ;
10545
10546 for( ii=0 ; ii < im3d->anat_now->pts->num ; ii++ )
10547 im3d->anat_now->pts->ijk[ii] =
10548 THD_3dmm_to_3dind( im3d->anat_now , im3d->anat_now->pts->xyz[ii] ) ;
10549 }
10550 #endif /* ALLOW_DATASET_VLIST */
10551
10552 /*------ 06 Mar 2002: turn "SUMA to" on image popup on or off ------*/
10553
10554 if( im3d->vwid->imag->pop_sumato_pb != NULL ){
10555 if( SESSION_HAS_SUMA(im3d->ss_now) )
10556 XtManageChild( im3d->vwid->imag->pop_sumato_pb ) ;
10557 else
10558 XtUnmanageChild( im3d->vwid->imag->pop_sumato_pb ) ;
10559 }
10560
10561 /*------ 01 May 2002: turn "Jump to (MNI)" on or off ------*/
10562
10563 if( im3d->vwid->imag->pop_mnito_pb != NULL ){
10564 if( CAN_TALTO(im3d) )
10565 XtManageChild( im3d->vwid->imag->pop_mnito_pb ) ;
10566 else
10567 XtUnmanageChild( im3d->vwid->imag->pop_mnito_pb ) ;
10568 }
10569
10570 /*-------------------------------------------------------------------*/
10571 /*--- Sep 1995: turn "Go to atlas position" button on
10572 image popup on or off ---*/
10573
10574 STATUS(" -- managing Go to atlas position button, etc") ;
10575
10576 if( im3d->vwid->imag->pop_talto_pb != NULL ){
10577 if( CAN_TALTO(im3d) ){
10578 XtSetSensitive( im3d->vwid->imag->pop_talto_pb , True ) ;
10579 if( im3d->vwid->imag->pop_whereami_pb != NULL )
10580 XtSetSensitive( im3d->vwid->imag->pop_whereami_pb , True ); /* 10 Jul 2001 */
10581 if( im3d->vwid->imag->pop_ttren_pb != NULL )
10582 XtSetSensitive( im3d->vwid->imag->pop_ttren_pb , /* 12 Jul 2001 */
10583 im3d->vinfo->view_type==VIEW_TALAIRACH_TYPE); /* 01 Aug 2001 */
10584 } else {
10585 XtSetSensitive( im3d->vwid->imag->pop_talto_pb, False ) ;
10586 if( im3d->vwid->imag->pop_whereami_pb != NULL )
10587 XtSetSensitive( im3d->vwid->imag->pop_whereami_pb, False ); /* 10 Jul 2001 */
10588 if( im3d->vwid->imag->pop_ttren_pb != NULL )
10589 XtSetSensitive( im3d->vwid->imag->pop_ttren_pb , False ); /* 12 Jul 2001 */
10590 }
10591 }
10592
10593 if( im3d->vwid->imag->pop_instacorr_pb != NULL ){
10594 if( ISREADY_EITHER_ICOR(im3d) ) ENABLE_INSTACORR(im3d) ;
10595 else DISABLE_INSTACORR(im3d) ;
10596 }
10597
10598 /*--- 25 Jul 2001: sensitize 'See TT Atlas Regions' button ---*/
10599
10600 #if 1
10601 XtSetSensitive( im3d->vwid->func->see_ttatlas_bbox->wrowcol ,
10602 (RwcBoolean)( im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE &&
10603 TT_retrieve_atlas_dset(Current_Atlas_Default_Name(), 0) != NULL) ) ;
10604 #else
10605 XtSetSensitive( im3d->vwid->func->see_ttatlas_bbox->wrowcol , False ) ;
10606 #endif
10607
10608 /*------------------------------------*/
10609 /*--- May 1996: Time index control ---*/
10610 /*--- Mar 1997: Allow FIM also ---*/
10611
10612 #if 0
10613 top = DSET_NUM_TIMES(im3d->anat_now) ;
10614 if( ISVALID_3DIM_DATASET(im3d->fim_now) )
10615 top = MAX( top , DSET_NUM_TIMES(im3d->fim_now) ) ;
10616 #else
10617 top = DSET_NVALS(im3d->anat_now) ;
10618 if( ISVALID_3DIM_DATASET(im3d->fim_now) )
10619 top = MAX( top , DSET_NVALS(im3d->fim_now) ) ;
10620 #endif
10621
10622 if( top > 1 ){
10623 MCW_arrowval *tav = im3d->vwid->imag->time_index_av ;
10624 STATUS(" -- turning time index control on") ;
10625
10626 AV_SENSITIZE( tav , True ) ; im3d->vinfo->time_on = 1 ;
10627 tav->fmax = tav->imax = top - 1 ; im3d->vinfo->top_index = top ;
10628 if( im3d->vinfo->time_index > tav->imax ){
10629 im3d->vinfo->time_index = tav->imax ;
10630 AV_assign_ival( tav , tav->imax ) ;
10631 AFNI_process_timeindex(im3d) ; /* 29 Jan 2003 */
10632 }
10633 } else {
10634 STATUS(" -- turning time index control off") ;
10635 AV_SENSITIZE( im3d->vwid->imag->time_index_av , False ) ;
10636 im3d->vinfo->time_on = 0 ;
10637 }
10638
10639 /*--------------------------------------------------------------*/
10640 /*--- 19 Nov 1996: Set FIM-able dataset to this, if possible ---*/
10641
10642 if( DSET_GRAPHABLE(im3d->anat_now) )
10643 im3d->fimdata->fimdset = im3d->anat_now ;
10644
10645 ALLOW_COMPUTE_FIM(im3d) ;
10646
10647 /*----------------------------------------------------------------*/
10648 /*--- 19 Aug 2002: enable/disable surface chooser button, etc. ---*/
10649
10650 AFNI_update_surface_widgets( im3d ) ;
10651
10652 /*------------------------------------------*/
10653 /*--- attach to viewing windows (if any) ---*/
10654
10655 AFNI_underlay_CB( NULL , im3d , NULL ) ;
10656
10657 /* 04 Nov 2003: set range for image grayscaling? */
10658
10659 AFNI_range_setter( im3d , im3d->s123 ) ;
10660 AFNI_range_setter( im3d , im3d->s231 ) ;
10661 AFNI_range_setter( im3d , im3d->s312 ) ;
10662
10663 im3d->vinfo->tempflag = 0 ;
10664
10665 old_im3d = im3d ;
10666 old_fim = im3d->fim_now ; /* remembrance */
10667 old_anat = im3d->anat_now ;
10668
10669 old_anat_nvals = DSET_NVALS(im3d->anat_now) ; /* 21 Jul 2009 */
10670
10671 /* This next line can fail if fim_now is NULL.
10672 fim_now can be NULL if you switch to tlrc view and
10673 for some reason, the transform fails on the fim image.
10674 We have seen this happen when:
10675 1st volume in list is anat and has a +orig only.
10676 2nd volume in list is anat2 and has a +orig and +tlrc
10677 3rd volume in list is a functional dset (selected as overlay)
10678 You switch to anat2 and select TLRC view, BOOM.
10679 Our guess is that since the first dset has no tlrc xform,
10680 the third one, which is the overlay seems to get no TLRC daddy,
10681 even if the second anat has a tlrc xform .
10682 Should be able to test this hypothesis by expressly setting the
10683 anat parent of all volumes to that of the anat with the TLRC xform....
10684
10685 ZSS, RICKR, with no time to fix this quite yet. July 28 2009 */
10686
10687 /** 10 Aug 2009: the fix is below -- RWCox **/
10688
10689 if( ISVALID_DSET(im3d->fim_now) )
10690 old_func_nvals = DSET_NVALS(im3d->fim_now) ;
10691 else
10692 old_func_nvals = -1 ;
10693
10694 /* DRG 25 Apr 2016 */
10695 /* extra fix for percentile flag not working with warp-on-demand switch views */
10696 if(DSET_ONDISK(im3d->fim_now)) {
10697 MCW_set_bbox( im3d->vwid->func->perc_bbox ,
10698 (im3d->cont_perc_thr) ? (1) : (0) ) ;
10699 SENSITIZE( im3d->vwid->func->perc_bbox->wbut[PERC_AUTOBUT] , TRUE ) ;
10700 }
10701 else {
10702 MCW_set_bbox( im3d->vwid->func->perc_bbox , 0 ) ;
10703 im3d->cont_perc_thr = 0;
10704 SENSITIZE( im3d->vwid->func->perc_bbox->wbut[PERC_AUTOBUT] , False ) ;
10705 }
10706
10707 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
10708 AFNI_setup_thrstat(im3d,1) ; /* 27 Jun 2019 */
10709
10710 AFNI_sleep(13) ; /* 18 Oct 2005: for luck */
10711
10712 EXRETURN ;
10713 }
10714
10715 /*-----------------------------------------------------------------------
10716 Tell if AFNI_transform_vector can take a vector from old_dset
10717 to new_dset coordinates -- 09 Jul 2001 -- RWCox.
10718 -------------------------------------------------------------------------*/
10719
10720 int AFNI_can_transform_vector( THD_3dim_dataset *old_dset ,
10721 THD_3dim_dataset *new_dset )
10722 {
10723 if( old_dset==NULL || new_dset==NULL ) return 0 ;
10724
10725 if( old_dset == new_dset->warp_parent ) return 1 ;
10726
10727 if( old_dset->warp_parent == new_dset ) return 1 ;
10728
10729 if( old_dset->warp_parent == new_dset->warp_parent &&
10730 old_dset->warp_parent != NULL ) return 1 ;
10731
10732 if( new_dset->view_type == VIEW_ORIGINAL_TYPE &&
10733 old_dset->view_type != VIEW_ORIGINAL_TYPE &&
10734 old_dset->anat_parent != NULL &&
10735 old_dset->anat_parent->warp_parent != NULL ) return 1 ;
10736
10737 if( old_dset->view_type == VIEW_ORIGINAL_TYPE &&
10738 new_dset->view_type != VIEW_ORIGINAL_TYPE &&
10739 new_dset->anat_parent != NULL &&
10740 new_dset->anat_parent->warp_parent != NULL ) return 1 ;
10741
10742 return 0 ;
10743 }
10744
10745 /*-----------------------------------------------------------------------
10746 Eventually, will warp an input Dicom vector from one dataset to another.
10747 -------------------------------------------------------------------------*/
10748
10749 THD_fvec3 AFNI_transform_vector( THD_3dim_dataset *old_dset ,
10750 THD_fvec3 old_fv ,
10751 THD_3dim_dataset *new_dset )
10752 {
10753 if( old_dset==NULL || new_dset==NULL || old_dset==new_dset ) return old_fv ;
10754
10755 if( old_dset == new_dset->warp_parent ){
10756
10757 return AFNI_forward_warp_vector( new_dset->warp , old_fv ) ;
10758
10759 } else if( old_dset->warp_parent == new_dset ){
10760
10761 return AFNI_backward_warp_vector( old_dset->warp , old_fv ) ;
10762
10763 } else if( old_dset->warp_parent == new_dset->warp_parent &&
10764 old_dset->warp_parent != NULL ){
10765
10766 THD_fvec3 par_fv ;
10767 par_fv = AFNI_backward_warp_vector( old_dset->warp , old_fv ) ;
10768 return AFNI_forward_warp_vector ( new_dset->warp , par_fv ) ;
10769 }
10770
10771 /*-- 09 Jul 2001:
10772 If old_dset is in +tlrc/+acpc and new_dset is in +orig,
10773 see if can find anat_parent to do the job for us --*/
10774
10775 if( new_dset->view_type == VIEW_ORIGINAL_TYPE &&
10776 old_dset->view_type != VIEW_ORIGINAL_TYPE &&
10777 old_dset->anat_parent != NULL &&
10778 old_dset->anat_parent->warp_parent != NULL ){
10779
10780 return AFNI_backward_warp_vector( old_dset->anat_parent->warp , old_fv ) ;
10781 }
10782
10783 /*-- If old_dset is +orig and new_dset is +tlrc/+acpc, try anat_parent --*/
10784
10785 if( old_dset->view_type == VIEW_ORIGINAL_TYPE &&
10786 new_dset->view_type != VIEW_ORIGINAL_TYPE &&
10787 new_dset->anat_parent != NULL &&
10788 new_dset->anat_parent->warp_parent != NULL ){
10789
10790 return AFNI_forward_warp_vector( new_dset->anat_parent->warp , old_fv ) ;
10791 }
10792
10793 /*-- 28 Aug 2002: see if there is a special warp between datasets --*/
10794
10795 { THD_warp *swarp = AFNI_find_warp(new_dset,old_dset) ;
10796 if( swarp != NULL ) return AFNI_forward_warp_vector( swarp , old_fv ) ;
10797 swarp = AFNI_find_warp(old_dset,new_dset) ;
10798 if( swarp != NULL ) return AFNI_backward_warp_vector( swarp, old_fv ) ;
10799 }
10800
10801 /*-- default is no change --*/
10802
10803 return old_fv ;
10804 }
10805
10806 /*------------------------------------------------------------------------
10807 09 May 2001: fix a Solaris stupidity, where the scale is resized
10808 improperly when the Define Function panel is opened!
10809 --------------------------------------------------------------------------*/
10810
10811 #ifdef FIX_SCALE_SIZE_LATER
10812 static void fixscale( XtPointer client_data , XtIntervalId *id )
10813 {
10814 Three_D_View *im3d = (Three_D_View *) client_data ;
10815 AFNI_fix_scale_size_direct(im3d) ; /* 03 Jun 2019 */
10816 #if 0
10817 XtVaSetValues( im3d->vwid->func->thr_scale , XmNscaleWidth,24 , NULL ) ;
10818 #endif
10819 }
10820 #endif
10821
10822 /*------------------------------------------------------------------------*/
10823
10824 void AFNI_define_CB( Widget w , XtPointer client_data , XtPointer call_data )
10825 {
10826 Three_D_View *im3d = (Three_D_View *)client_data ;
10827 int vwarp ;
10828
10829 ENTRY("AFNI_define_CB") ;
10830
10831 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
10832
10833 /*----- define marks panel -----*/
10834
10835 if( w == im3d->vwid->view->define_marks_pb ){
10836
10837 AFNI_viewing_widgets *view = im3d->vwid->view ;
10838 AFNI_marks_widgets *marks = im3d->vwid->marks ;
10839
10840 if( XtIsManaged(marks->frame) == True ){ /* close it down */
10841
10842 STATUS("closing marks") ;
10843
10844 AFNI_marks_action_CB( NULL , (XtPointer) im3d , NULL ) ;
10845
10846 } else { /* open it up */
10847
10848 static int first=1 ; /* 21 Sep 2007 */
10849
10850 STATUS("opening marks") ;
10851
10852 marks->old_visible = marks->ov_visible ;
10853 marks->ov_visible = True ;
10854 marks->changed = False ; /* not changed yet! */
10855
10856 MCW_set_bbox( marks->edits_bbox , 0 ) ;
10857 AFNI_marks_edits_CB( NULL , (XtPointer) im3d , NULL ) ;
10858
10859 MCW_set_bbox( view->see_marks_bbox , 1 ) ;
10860 if( marks->old_visible != marks->ov_visible )
10861 AFNI_see_marks_CB( NULL , (XtPointer) im3d , NULL ) ;
10862
10863 /* Oct 1998: turn off some controls if no markers present */
10864
10865 if( im3d->anat_now->markers == NULL ){
10866 SENSITIZE( marks->edits_bbox->wrowcol , False ) ;
10867 SENSITIZE( marks->tlrc_big_bbox->wrowcol , False ) ;
10868 AV_SENSITIZE( marks->disp_scolor_av , False ) ;
10869 AV_SENSITIZE( marks->disp_size_av , False ) ;
10870 AV_SENSITIZE( marks->disp_gap_av , False ) ;
10871 SENSITIZE( marks->action_rowcol , False ) ;
10872 SENSITIZE( marks->transform_pb , False ) ;
10873 } else {
10874 vwarp = WARPED_VIEW(im3d->vinfo->view_type) ;
10875 SENSITIZE( marks->edits_bbox->wrowcol ,
10876 (RwcBoolean) ISVALID_VIEW(vwarp) ) ;
10877 SENSITIZE( marks->tlrc_big_bbox->wrowcol ,
10878 (RwcBoolean) (vwarp==VIEW_TALAIRACH_TYPE) ) ;
10879 AV_SENSITIZE( marks->disp_scolor_av , True ) ;
10880 AV_SENSITIZE( marks->disp_size_av , True ) ;
10881 AV_SENSITIZE( marks->disp_gap_av , True ) ;
10882 SENSITIZE( marks->action_rowcol , True ) ;
10883 }
10884
10885 /*** I don't know why this is needed, but it prevents the
10886 marks panels geometry from getting screwed up, so it's here ***/
10887
10888 #ifndef USING_LESSTIF
10889 #define REMANAGE_MARKS 1
10890 #else
10891 #define REMANAGE_MARKS 0
10892 #endif
10893
10894 #if 1
10895 { static int first=1 ;
10896 if( REMANAGE_MARKS || first ){ /* CYGWIN: must do 1st time in */
10897 XtUnmanageChild( marks->rowcol ) ; /* but not on later times -- */
10898 XtUnmanageChild( marks->tog_rowcol ) ; /* probably a LessTif bug */
10899 XtUnmanageChild( marks->control_rowcol ) ;
10900 XtUnmanageChild( marks->control_frame ) ;
10901 XtUnmanageChild( marks->tog_frame ) ;
10902 first = 0 ;
10903 }
10904 }
10905 #endif
10906
10907 OPEN_PANEL(im3d,marks) ;
10908
10909 #if 1
10910 #if 0
10911 XFlush( XtDisplay(marks->rowcol) ) ; XSync( XtDisplay(marks->rowcol),False ) ;
10912 #endif
10913 if( im3d->anat_now->markers != NULL ){ /* Oct 1998 */
10914 XtManageChild( marks->tog_rowcol ) ;
10915 XtManageChild( marks->tog_frame ) ;
10916 }
10917 XtManageChild( marks->control_rowcol ) ;
10918 XtManageChild( marks->control_frame ) ;
10919 XtManageChild( marks->rowcol ) ;
10920 #endif
10921
10922 /* redraw markers if not visible already (if there are any to redraw) */
10923
10924 if( marks->old_visible != True &&
10925 im3d->anat_now->markers != NULL &&
10926 im3d->anat_now->markers->numset > 0 )
10927 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
10928
10929 if( first && im3d->anat_now->markers == NULL ){ /* 21 Sep 2007 */
10930 first = 0 ;
10931 (void)MCW_popup_message(
10932 im3d->vwid->view->define_marks_pb ,
10933 " \n"
10934 " No Talairach markers defined for Underlay. \n"
10935 " You can add markers to a dataset via\n"
10936 " 3drefit -markers datasetname\n"
10937 " and then re-starting this AFNI program.\n" ,
10938 MCW_USER_KILL | MCW_TIMER_KILL ) ;
10939 }
10940 }
10941
10942 EXRETURN ;
10943 }
10944
10945 /*----- define function panel -----*/
10946
10947 if( w == im3d->vwid->view->define_func_pb ){
10948 AFNI_viewing_widgets *view = im3d->vwid->view ;
10949 AFNI_function_widgets *func = im3d->vwid->func ;
10950
10951 if( XtIsManaged(func->frame) ){
10952
10953 STATUS("closing function") ;
10954
10955 CLOSE_PANEL(im3d,func) ;
10956 } else {
10957
10958 STATUS("opening function" ) ;
10959
10960 #ifndef USING_LESSTIF
10961 #define REMANAGE_FUNC
10962 #endif
10963
10964 #ifdef REMANAGE_FUNC
10965 STATUS("unmanaging children") ;
10966 XtUnmanageChild( im3d->vwid->func->rowcol ) ;
10967 XtUnmanageChild( im3d->vwid->func->thr_rowcol ) ;
10968 XtUnmanageChild( im3d->vwid->func->inten_rowcol ) ;
10969 XtUnmanageChild( im3d->vwid->func->options_rowcol ) ;
10970 #endif
10971
10972 STATUS("opening panel") ;
10973 OPEN_PANEL(im3d,func) ;
10974
10975 #ifdef REMANAGE_FUNC
10976 STATUS("remanaging children") ;
10977 XtManageChild( im3d->vwid->func->thr_rowcol ) ;
10978 XtManageChild( im3d->vwid->func->inten_rowcol ) ;
10979 XtManageChild( im3d->vwid->func->options_rowcol ) ;
10980 XtManageChild( im3d->vwid->func->rowcol ) ;
10981 #endif
10982 HIDE_SCALE(im3d) ;
10983 im3d->vwid->func->inten_pbar->update_me = 2 ;
10984 update_MCW_pbar( im3d->vwid->func->inten_pbar ) ;
10985 FIX_SCALE_SIZE(im3d) ; FIX_SCALE_VALUE(im3d) ;
10986
10987 /* first time open? do some setup finalization [24 May 2019] */
10988 if( im3d->vwid->func->do_setup ){
10989 int ii = (int)AFNI_numenv("AFNI_THRESH_INIT_EXPON") ;
10990 if( ii > 0 && ii < THR_top_expon ) AFNI_set_thresh_itop(im3d,ii) ;
10991 im3d->vwid->func->do_setup = 0 ;
10992 }
10993
10994 #ifdef FIX_SCALE_SIZE_LATER
10995 (void) XtAppAddTimeOut( MAIN_app,50,fixscale,im3d ) ; /* 09 May 2001 */
10996 #else
10997 AFNI_fix_scale_size_direct(im3d) ; /* 03 Jun 2019 */
10998 #endif
10999
11000 /*** XtManageChild( im3d->vwid->func->inten_bbox->wrowcol ) ; ***/
11001 }
11002
11003 EXRETURN ;
11004 }
11005
11006 /*-- define datamode panel --*/
11007
11008 if( w == im3d->vwid->view->define_dmode_pb ){
11009 AFNI_viewing_widgets *view = im3d->vwid->view ;
11010 AFNI_datamode_widgets *dmode = im3d->vwid->dmode ;
11011
11012 if( XtIsManaged(dmode->frame) ){
11013
11014 STATUS("closing dmode") ;
11015
11016 CLOSE_PANEL(im3d,dmode) ;
11017 } else {
11018
11019 STATUS("opening dmode" ) ;
11020
11021 OPEN_PANEL(im3d,dmode) ;
11022 }
11023
11024 EXRETURN ;
11025 }
11026
11027 RESET_AFNI_QUIT(im3d) ;
11028 EXRETURN ;
11029 }
11030
11031 /*--------------------------------------------------------------------*/
11032
11033 void AFNI_marks_edits_CB( Widget w ,
11034 XtPointer client_data , XtPointer call_data )
11035 {
11036 Three_D_View *im3d = (Three_D_View *) client_data ;
11037 AFNI_marks_widgets *marks ;
11038 int bval , vwarp ;
11039 RwcBoolean transformable ;
11040
11041 ENTRY("AFNI_marks_edits_CB") ;
11042
11043 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11044
11045 marks = im3d->vwid->marks ;
11046 bval = MCW_val_bbox( marks->edits_bbox ) ;
11047
11048 marks->editable = (bval == 0) ? (False) : (True) ;
11049
11050 if( im3d->anat_now->markers == NULL ) EXRETURN ;
11051
11052 /*----- allow transformation if
11053 edits are allowed, AND
11054 the markers are flagged for it, AND
11055 all the markers are defined ----------*/
11056
11057 vwarp = WARPED_VIEW(im3d->vinfo->view_type) ;
11058
11059 transformable =
11060 marks->editable &&
11061 (im3d->anat_now->markers->aflags[1] != MARKACTION_NONE) &&
11062 (im3d->anat_now->markers->numdef == im3d->anat_now->markers->numset) &&
11063 ISVALID_VIEW(vwarp) ;
11064
11065 /* turn some buttons on or off, depending on editability */
11066
11067 SENSITIZE( marks->tog_frame , True ) ;
11068 SENSITIZE( marks->action_set_pb , marks->editable ) ;
11069 SENSITIZE( marks->action_clear_pb , marks->editable ) ;
11070 #ifdef POPTOG
11071 SENSITIZE( marks->pop_set_pb , marks->editable ) ;
11072 SENSITIZE( marks->pop_clear_pb , marks->editable ) ;
11073 #endif
11074 SENSITIZE( marks->action_quality_pb , transformable ) ;
11075 SENSITIZE( marks->transform_pb , False ) ; /* require QC first */
11076
11077 if( ! marks->editable ){
11078 AFNI_set_tog( -1 , MARKS_MAXNUM , marks->tog ) ; /* none will */
11079 #ifdef POPTOG
11080 AFNI_set_tog( -1 , MARKS_MAXNUM , marks->poptog ) ; /* be "on" */
11081 #endif
11082 }
11083
11084 RESET_AFNI_QUIT(im3d) ;
11085 EXRETURN ;
11086 }
11087
11088 /*-----------------------------------------------------------------*/
11089
11090 void AFNI_see_marks_CB( Widget w ,
11091 XtPointer client_data , XtPointer call_data )
11092 {
11093 Three_D_View *im3d = (Three_D_View *) client_data ;
11094 AFNI_marks_widgets *marks ;
11095 AFNI_viewing_widgets *view ;
11096 int bval ;
11097
11098 ENTRY("AFNI_see_marks_CB") ;
11099
11100 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11101
11102 view = im3d->vwid->view ;
11103 marks = im3d->vwid->marks ;
11104 bval = MCW_val_bbox( view->see_marks_bbox ) ;
11105
11106 marks->tag_visible = marks->ov_visible = (bval == 0) ? (False) : (True) ;
11107
11108 if( w != NULL )
11109 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
11110
11111 RESET_AFNI_QUIT(im3d) ;
11112 EXRETURN ;
11113 }
11114
11115 /*------------------------------------------------------------------------
11116 Event handler to find #3 button press for crosshair label [12 Mar 2004]
11117 --------------------------------------------------------------------------*/
11118
11119 void AFNI_crosshair_EV( Widget w , XtPointer cd ,
11120 XEvent *ev , RwcBoolean *continue_to_dispatch )
11121 {
11122 Three_D_View *im3d = (Three_D_View *)cd ;
11123
11124 ENTRY("AFNI_crosshair_EV") ;
11125
11126 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11127
11128 /*** handle events ***/
11129
11130 switch( ev->type ){
11131
11132 /*----- take button press -----*/
11133
11134 case ButtonPress:{
11135 XButtonEvent *event = (XButtonEvent *)ev ;
11136
11137 if( event->button == Button3 ||
11138 (event->button == Button1 &&
11139 (event->state & (ShiftMask|ControlMask))) ){
11140
11141 im3d->vwid->butx = event->x_root ; /* 17 May 2005 */
11142 im3d->vwid->buty = event->y_root ;
11143 event->button = Button3 ; /* fake */
11144 XmMenuPosition( im3d->vwid->imag->crosshair_menu , event ); /* where */
11145 XtManageChild ( im3d->vwid->imag->crosshair_menu ) ; /* popup */
11146 }
11147
11148 else if( event->button == Button1 ) {
11149 static int nn=0 ;
11150 if( nn < 9 )
11151 (void) MCW_popup_message( im3d->vwid->imag->crosshair_label ,
11152 " The road goes ever on and on\n"
11153 " Out from the door from where it began.\n"
11154 " Now, far ahead the road has gone\n"
11155 " And I must follow if I can.\n"
11156 " Pursuing it with eager feet\n"
11157 " Until it meets some other way\n"
11158 " Where many paths and errands meet\n"
11159 " And whither then I cannot say." ,
11160 MCW_USER_KILL | MCW_TIMER_KILL ) ;
11161 nn++ ;
11162 }
11163 }
11164 break ;
11165
11166 /*----- take key press -----*/
11167
11168 #if 0
11169 case KeyPress:{
11170 XKeyEvent *event = (XKeyEvent *) ev ;
11171 char buf[32] ;
11172 KeySym ks ;
11173 int nbuf ;
11174
11175 buf[0] = '\0' ;
11176 nbuf = XLookupString( event , buf , 32 , &ks , NULL ) ;
11177
11178 switch( buf[0] ){
11179 default: break ;
11180 }
11181 }
11182 break ;
11183 #endif
11184 }
11185
11186 EXRETURN ;
11187 }
11188
11189 /*------------------------------------------------------------------*/
11190 /* Redraw the crosshair label in this controller [12 Mar 2004]
11191 --------------------------------------------------------------------*/
11192
11193 void AFNI_crosshair_relabel( Three_D_View *im3d )
11194 {
11195 XmString xstr ;
11196 RwcBoolean same ;
11197
11198 ENTRY("AFNI_crosshair_relabel") ;
11199
11200 if( !IM3D_OPEN(im3d) ) EXRETURN ;
11201 xstr = AFNI_crosshair_label( im3d ) ; if( xstr == NULL ) EXRETURN ;
11202 if( im3d->vinfo->old_crosshair_label == (XmString)NULL ) /* shouldn't */
11203 same = False ; /* happen */
11204 else
11205 same = XmStringCompare( xstr , im3d->vinfo->old_crosshair_label ) ;
11206
11207 if( same == False ){
11208 XtVaSetValues( im3d->vwid->imag->crosshair_label , /* redisplay */
11209 XmNlabelString , xstr , /* if changed */
11210 NULL ) ;
11211 MCW_expose_widget( im3d->vwid->imag->crosshair_label ) ; /* redraw now! */
11212 if( im3d->vinfo->old_crosshair_label != (XmString)NULL )
11213 XmStringFree(im3d->vinfo->old_crosshair_label) ; /* toss old */
11214 im3d->vinfo->old_crosshair_label = xstr ; /* new old */
11215 } else {
11216 XmStringFree( xstr ) ; /* was same --> don't need this copy */
11217 }
11218
11219 EXRETURN ;
11220 }
11221
11222 /*------------------------------------------------------------------
11223 callback for crosshair label popup menu [12 Mar 2004]
11224 --------------------------------------------------------------------*/
11225
11226 static char *last_jumpto_xyz_string = NULL ; /* 23 Sep 2008 */
11227 static char *last_jumpto_ijk_string = NULL ;
11228 static char *last_mnito_string = NULL ;
11229 static char *last_sumato_string = NULL ;
11230 static char jumpstring[128]; /* 13 Jun 2014 */
11231
11232 static char *last_jumpto_ijk_olay_string = NULL ; /* 20 Apr 2016 */
11233
11234 void AFNI_crosshair_pop_CB( Widget w ,
11235 XtPointer client_data , XtPointer call_data )
11236 {
11237 Three_D_View *im3d = (Three_D_View *)client_data ;
11238 static char *cord_dicom="RAI" , *cord_spm="LPI" ;
11239 char *val=NULL ;
11240 int ii ;
11241
11242 ENTRY("AFNI_crosshair_pop_CB") ;
11243
11244 if( !IM3D_OPEN(im3d) ) EXRETURN ;
11245
11246 /*-- jumpto stuff added 01 Aug 2011 --*/
11247
11248 if( w == im3d->vwid->imag->crosshair_jtxyz_pb ){
11249 char tbuf[128] ;
11250 sprintf(tbuf , "Enter new x y z (%s mm):" , GLOBAL_library.cord.orcode ) ;
11251 MCW_choose_string( im3d->vwid->imag->crosshair_label , tbuf ,
11252 last_jumpto_xyz_string,
11253 AFNI_jumpto_CB, (XtPointer) im3d ) ;
11254 EXRETURN ;
11255 } else if ( w == im3d->vwid->imag->crosshair_jtijk_pb ){
11256 MCW_choose_string( im3d->vwid->imag->crosshair_label , "Enter new i j k (UnderLay):" ,
11257 last_jumpto_ijk_string ,
11258 AFNI_jumpto_ijk_CB , (XtPointer) im3d ) ;
11259 EXRETURN ;
11260 } else if ( w == im3d->vwid->imag->crosshair_jtijk_olay_pb ){ /* 20 Apr 2016 */
11261 MCW_choose_string( im3d->vwid->imag->crosshair_label , "Enter new i j k (OverLay):" ,
11262 last_jumpto_ijk_olay_string ,
11263 AFNI_jumpto_ijk_olay_CB , (XtPointer) im3d ) ;
11264 EXRETURN ;
11265 }
11266
11267 /*-- the other options --*/
11268
11269 if( w == im3d->vwid->imag->crosshair_dicom_pb ) val = cord_dicom ;
11270 else if( w == im3d->vwid->imag->crosshair_spm_pb ) val = cord_spm ;
11271 else if( w == im3d->vwid->imag->crosshair_ijk_pb ){ /* 04 Oct 2010 */
11272 im3d->vinfo->show_voxind = 1 ;
11273 POPDOWN_string_chooser ;
11274 AFNI_crosshair_relabel(im3d) ;
11275 MCW_set_bbox(im3d->vwid->dmode->misc_voxind_bbox,1) ;
11276 }
11277
11278 if( val != NULL ){
11279 POPDOWN_string_chooser ;
11280 MCW_strncpy(GLOBAL_argopt.orient_code,val,4) ;
11281 THD_coorder_fill( GLOBAL_argopt.orient_code , &GLOBAL_library.cord ) ;
11282 im3d->vinfo->show_voxind = 0 ;
11283 MCW_set_bbox(im3d->vwid->dmode->misc_voxind_bbox,0) ;
11284 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
11285 AFNI_crosshair_relabel ( GLOBAL_library.controllers[ii] );
11286 AFNI_clus_update_widgets( GLOBAL_library.controllers[ii] ); /* 21 Dec 2007 */
11287 }
11288 }
11289
11290 EXRETURN ;
11291 }
11292
11293 /*------------------------------------------------------------------
11294 callback for non-marker buttons on the popup
11295 --------------------------------------------------------------------*/
11296
11297 void AFNI_imag_pop_CB( Widget w ,
11298 XtPointer client_data , XtPointer call_data )
11299 {
11300 Three_D_View *im3d = (Three_D_View *)client_data ;
11301 MCW_imseq *seq=NULL ;
11302
11303 ENTRY("AFNI_imag_pop_CB") ;
11304
11305 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11306
11307 XtVaGetValues( im3d->vwid->imag->popmenu, XmNuserData, &seq, NULL ) ;
11308 AFNI_view_setter(im3d,seq) ;
11309
11310 /*-- jump back to old location --*/
11311
11312 if( w == im3d->vwid->imag->pop_jumpback_pb ){
11313 int ii,jj,kk ;
11314
11315 ii = im3d->vinfo->i1_old ; /* extract old place */
11316 jj = im3d->vinfo->j2_old ;
11317 kk = im3d->vinfo->k3_old ;
11318
11319 SAVE_VPT(im3d) ; /* save current place as old one */
11320 AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_OVERLAY ) ; /* jump */
11321 }
11322
11323 /*-- switch window display mode --*/
11324
11325 else if( w == im3d->vwid->imag->pop_imageonly_pb ){
11326 if( ISQ_REALZ(seq) )
11327 drive_MCW_imseq( seq , isqDR_onoffwid , (XtPointer) isqDR_togwid ) ;
11328 }
11329
11330 /*-- jump to a point --*/
11331
11332 else if( w == im3d->vwid->imag->pop_jumpto_pb &&
11333 im3d->type == AFNI_3DDATA_VIEW ){
11334
11335 char tbuf[128] ;
11336
11337 if( ISQ_REALZ(seq) ){
11338 sprintf(tbuf , "Enter new x y z (%s mm):" , GLOBAL_library.cord.orcode ) ;
11339 MCW_choose_string( seq->wbar , tbuf , last_jumpto_xyz_string ,
11340 AFNI_jumpto_CB , (XtPointer) im3d ) ;
11341 }
11342 }
11343
11344 else if( w == im3d->vwid->imag->pop_jumpto_ijk_pb &&
11345 im3d->type == AFNI_3DDATA_VIEW ){
11346
11347 if( ISQ_REALZ(seq) ){
11348 MCW_choose_string( seq->wbar , "Enter new i j k (UnderLay):" , last_jumpto_ijk_string ,
11349 AFNI_jumpto_ijk_CB , (XtPointer) im3d ) ;
11350 }
11351 }
11352
11353 else if( w == im3d->vwid->imag->pop_jumpto_ijk_olay_pb &&
11354 im3d->type == AFNI_3DDATA_VIEW ){ /* 20 Apr 2016 */
11355
11356 if( ISQ_REALZ(seq) ){
11357 MCW_choose_string( seq->wbar , "Enter new i j k (OverLay):" , last_jumpto_ijk_olay_string ,
11358 AFNI_jumpto_ijk_olay_CB , (XtPointer) im3d ) ;
11359 }
11360 }
11361
11362 /*-- 01 May 2002: jump to MNI coordinates --*/
11363
11364 else if( w == im3d->vwid->imag->pop_mnito_pb &&
11365 im3d->type == AFNI_3DDATA_VIEW ){
11366 /* configure menu to show what space coordinates might be in */
11367 if( ISQ_REALZ(seq) && CAN_TALTO(im3d) ){
11368 sprintf(jumpstring,"Enter %s x,y,z (LPI mm):", get_jump_space());
11369 MCW_choose_string( seq->wbar , jumpstring ,
11370 last_mnito_string ,
11371 AFNI_mnito_CB , (XtPointer) im3d ) ;
11372 } else {
11373 BEEPIT ; /* should never happen */
11374 }
11375 }
11376
11377 /*-- 19 Oct 2012: jump to cluster peak --*/
11378
11379 else if( w == im3d->vwid->imag->pop_jumpto_clus_pb &&
11380 im3d->type == AFNI_3DDATA_VIEW ){
11381 AFNI_jumpto_clus(im3d) ;
11382 }
11383
11384 /*-- 06 Mar 2002: jump to a node in a surface --*/
11385
11386 else if( w == im3d->vwid->imag->pop_sumato_pb &&
11387 SESSION_HAS_SUMA(im3d->ss_now) &&
11388 im3d->type == AFNI_3DDATA_VIEW ){
11389
11390 if( ISQ_REALZ(seq) ){
11391 MCW_choose_string( seq->wbar , "Enter SUMA node ID:" , last_sumato_string ,
11392 AFNI_sumato_CB , (XtPointer) im3d ) ;
11393 }
11394 }
11395
11396 /*-- jump to a predetermined atlas-based anatomical reference point --*/
11397
11398 else if( w == im3d->vwid->imag->pop_talto_pb &&
11399 im3d->type == AFNI_3DDATA_VIEW &&
11400 CAN_TALTO(im3d) ){
11401
11402 { /* initialize labels */
11403 char **at_labels=NULL ;
11404 int iii , flipxy=(GLOBAL_library.cord.xxsign < 0 && GLOBAL_library.cord.yysign < 0);
11405 char title_str[256];
11406
11407 at_labels = atlas_chooser_formatted_labels( Current_Atlas_Default_Name() , flipxy ) ;
11408 if( ISQ_REALZ(seq) && at_labels ){
11409 if( AFNI_yesenv("AFNI_DATASET_BROWSE") ) MCW_set_browse_select(1) ;
11410
11411 sprintf(title_str, "Brain Structure (%s) [%s]",
11412 Current_Atlas_Default_Name() ,
11413 (flipxy) ? "SPM order" : "DICOM order"
11414 ) ;
11415 MCW_choose_strlist( seq->wbar ,
11416 title_str ,
11417 atlas_n_points(Current_Atlas_Default_Name()) ,
11418 atlas_current_structure ,
11419 at_labels ,
11420 AFNI_talto_CB , (XtPointer) im3d ) ;
11421 for (iii=0; iii<atlas_n_points(Current_Atlas_Default_Name()); ++iii) {
11422 if (at_labels[iii]) free(at_labels[iii]);
11423 }
11424 free(at_labels); at_labels=NULL;
11425 }
11426 }
11427 }
11428
11429 /*---- 10 Jul 2001: Talairach "Where Am I?" ----*/
11430
11431 else if( w == im3d->vwid->imag->pop_whereami_pb &&
11432 w != NULL &&
11433 im3d->type == AFNI_3DDATA_VIEW &&
11434 CAN_TALTO(im3d) ){
11435
11436 char *tlab ;
11437 tlab = AFNI_ttatlas_query( im3d ) ;
11438 if (AFNI_wami_output_mode() == 0) { /* old spice */
11439
11440 /*- if one is already open, kill it -*/
11441
11442 if( im3d->vwid->imag->pop_whereami_twin != NULL ){
11443 MCW_textwinkill_CB(NULL,
11444 (XtPointer)im3d->vwid->imag->pop_whereami_twin,NULL);
11445 im3d->vwid->imag->pop_whereami_twin = NULL ;
11446 }
11447
11448 /*- get TT atlas location, if any -*/
11449
11450 /*- open a window to show it -*/
11451
11452 if( tlab != NULL ){
11453 char *eee = getenv("AFNI_TTATLAS_FONTSIZE") ;
11454
11455 if( eee != NULL ){
11456 if( *eee == 'B' || *eee == 'b' || isdigit(*eee) ) MCW_textwin_setbig( 1);
11457 else if( *eee == 'S' || *eee == 's' || *eee == '-' ) MCW_textwin_setbig(-1);
11458 }
11459
11460 im3d->vwid->imag->pop_whereami_twin =
11461 new_MCW_textwin_2001( im3d->vwid->imag->crosshair_label , tlab ,
11462 TEXT_READONLY , AFNI_pop_whereami_kill , im3d ) ;
11463
11464 #if 0
11465 /* 31 Jul 2001: NULL out the pointer when the window is destroyed */
11466
11467 NULLIFY_ON_DESTROY( im3d->vwid->imag->pop_whereami_twin ,
11468 im3d->vwid->imag->pop_whereami_twin->wshell ) ;
11469 #endif
11470
11471 XtVaSetValues( im3d->vwid->imag->pop_whereami_twin->wtext ,
11472 XmNresizeHeight , True ,
11473 XmNresizeWidth , True ,
11474 NULL ) ;
11475
11476 MCW_register_hint( im3d->vwid->imag->pop_whereami_twin->wtext ,
11477 "Use BHelp for documentation" ) ;
11478
11479 MCW_register_help( im3d->vwid->imag->pop_whereami_twin->wtext ,
11480 "Lists the brain structures near the crosshair focus point\n"
11481 "according to a set of atlases defined in AFNI_atlas_spaces.niml\n"
11482 "and limited by the environment variable,AFNI_ATLAS_LIST.\n"
11483 "The default list includes the original Talairach Daemon database\n"
11484 "(kindly provided by Jack Lancaster and Peter Fox of RIC UTHSCSA,\n"
11485 "the cytoarchitectonic and macrolabel atlases provided by Simon\n"
11486 "Eickhoff and Karl Zilles, and the probabilistic atlases provided\n"
11487 "Rutvik Desai.\n"
11488 "\n"
11489 "The search is conducted outwards from the focus point, until\n"
11490 "9 different structures are found, or a 7.5 mm radius is reached,\n"
11491 "whichever occurs first. (Distances are rounded to nearest 1 mm,\n"
11492 "by default.) The defaults can be adjusted with AFNI environment\n"
11493 "Please see whereami help, README.environment for more details.\n"
11494 "\n"
11495 "In the database, voxels may have multiple labels for a particular\n"
11496 "atlas. For example, the voxels may a larger scale 'gyral' name\n"
11497 "and a finer scale 'area' name. Locations that are doubly labeled\n"
11498 "will appear with a listing like\n"
11499 " Within 2 mm: Right Precuneus -AND- Right Brodmann area 31\n"
11500 "A list of all the labels for the principal default atlas is\n"
11501 "presented by the 'Go to atlas location' control or from the\n"
11502 "command line program, 'whereami -show_atlas_code', for any atlas.\n"
11503 "Note Very Well:\n"
11504 "* The Atlas is only useful as a ROUGH guide to determining where\n"
11505 " you are in any individual brain. Do not rely exclusively on\n"
11506 " the Atlas for brain region identification: you must use your\n"
11507 " knowledge, skills, and abilities as well.\n"
11508 "* Do NOT use this feature for surgical or therapeutic planning!!!"
11509 ) ;
11510 }
11511 } else { /* web */
11512 AFNI_alter_wami_text(im3d, tlab);
11513 } /* web */
11514 if (tlab) free(tlab) ;
11515 }
11516
11517 /*---- 12 Jul 2001 ----*/
11518
11519 else if( w == im3d->vwid->imag->pop_ttren_pb &&
11520 w != NULL &&
11521 im3d->type == AFNI_3DDATA_VIEW &&
11522 im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE && /* 01 Aug 2001 */
11523 CAN_TALTO(im3d) ){
11524
11525 TTRR_popup( im3d ) ;
11526
11527 if( im3d->vinfo->see_ttatlas == 0 ){ /* 03 Aug 2007: for the Daniel */
11528 MCW_set_bbox( im3d->vwid->func->see_ttatlas_bbox , 1 ) ;
11529 im3d->vinfo->see_ttatlas = 1 ;
11530 }
11531 }
11532
11533 /*---- 05 Nov 2003: start the Edit Environment pseudo-plugin ----*/
11534
11535 else if( w == im3d->vwid->imag->pop_environment_pb &&
11536 w != NULL ){
11537
11538 AFNI_misc_CB( im3d->vwid->dmode->misc_environ_pb ,
11539 (XtPointer) im3d , (XtPointer) NULL ) ;
11540 }
11541
11542 /*---- 17 May 2005: open Draw Dataset plugin ----*/
11543
11544 else if( w == im3d->vwid->imag->pop_drawdataset_pb &&
11545 w != NULL ){
11546
11547 char cmd[128] , cc='A'+AFNI_controller_index(im3d) ;
11548 int xx,yy ;
11549
11550 #if 0
11551 MCW_widget_geom(im3d->vwid->top_shell,NULL,NULL,&xx,&yy); xx+=29; yy+=19;
11552 #else
11553 xx = im3d->vwid->butx ; yy = im3d->vwid->buty ;
11554 #endif
11555 sprintf(cmd,"OPEN_WINDOW %c.plugin.Draw_Dataset geom=+%d+%d",cc,xx,yy) ;
11556 (void) AFNI_driver(cmd) ;
11557 }
11558
11559 /*---- 06 May 2009: set InstaCorr point ----*/
11560
11561 else if( w == im3d->vwid->imag->pop_instacorr_pb && w != NULL ){
11562 int qq = AFNI_icor_setref(im3d) ;
11563 if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ; /* 15 May 2009 */
11564 }
11565
11566 /*---- 08 May 2009: jump to InstaCorr point ----*/
11567
11568 else if( w == im3d->vwid->imag->pop_icorrjump_pb &&
11569 w != NULL && ISREADY_EITHER_ICOR(im3d) ){
11570 int ii,jj,kk ;
11571
11572 ii = im3d->vinfo->i1_icor ; /* extract icor place */
11573 jj = im3d->vinfo->j2_icor ;
11574 kk = im3d->vinfo->k3_icor ;
11575 if( ii >= 0 && jj >= 0 && kk >=0 ){
11576 SAVE_VPT(im3d) ;
11577 #if 0 /* OLD */
11578 AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_OVERLAY ) ;
11579 #else /* NEW [27 Sep 2021] */
11580 AFNI_jumpto_dicom( im3d, im3d->vinfo->xi_icor,im3d->vinfo->yj_icor,im3d->vinfo->zk_icor) ;
11581 #endif
11582 }
11583 }
11584
11585 /*---- Apr 2013: set 3dGroupInCorr Apair point ----*/
11586
11587 else if( w == im3d->vwid->imag->pop_icorrapair_pb && w != NULL ){
11588 AFNI_gicor_setapair_xyz( im3d , im3d->vinfo->xi ,
11589 im3d->vinfo->yj , im3d->vinfo->zk ) ;
11590 }
11591
11592 else if( w == im3d->vwid->imag->pop_icorramirr_pb && w != NULL ){
11593 if( im3d->giset != NULL && GICOR_apair_allow_bit(im3d->giset) ){
11594 GICOR_flip_apair_mirror_bit(im3d->giset) ;
11595 MCW_set_widget_label( w , GICOR_apair_mirror_bit(im3d->giset)
11596 ? "GIC: Apair MirrorON*"
11597 : "GIC: Apair MirrorOFF" ) ;
11598 SENSITIZE_INSTACORR_GROUP(im3d,im3d->giset->ready) ;
11599 }
11600 }
11601
11602 /*--- unmap of the popup itself [elided] ---*/
11603
11604 /*--- exit ---*/
11605
11606 RESET_AFNI_QUIT(im3d) ;
11607 EXRETURN ;
11608 }
11609
11610 /*---------------------------------------------------------------------
11611 called when the talto chooser is set - now "Go to Atlas position"
11612 for generic atlas usage
11613 -----------------------------------------------------------------------*/
11614
11615 void AFNI_talto_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
11616 {
11617 Three_D_View *im3d = (Three_D_View *) cd ;
11618 THD_dataxes *daxes ;
11619 float xx,yy,zz ;
11620 int nn , ii,jj,kk ;
11621 ATLAS_POINT *tto_list=NULL;
11622 THD_fvec3 fv,tv ; THD_ivec3 iv ;
11623
11624 ENTRY("AFNI_talto_CB") ;
11625
11626 /* check for errors */
11627
11628 if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
11629
11630 if( !CAN_TALTO(im3d) ||
11631 cbs->reason != mcwCR_integer ){
11632
11633 POPDOWN_strlist_chooser ;
11634 BEEPIT ; WARNING_message("Can't 'Go to Atlas position'!?") ;
11635 EXRETURN ;
11636 }
11637
11638 if (!(tto_list = atlas_points(Current_Atlas_Default_Name()))) {
11639 BEEPIT ; WARNING_message("Can't get atlas: %s", Current_Atlas_Default_Name()) ;
11640 EXRETURN ;
11641 }
11642
11643 nn = cbs->ival ;
11644 if( nn < 0 || nn >= atlas_n_points(Current_Atlas_Default_Name()) ) EXRETURN ;
11645 atlas_current_structure = nn ; /* index for structure in list for atlas */
11646
11647 /* transform point from Dicom to local coords and go there */
11648
11649 xx = tto_list[nn].xx ; yy = tto_list[nn].yy ; zz = tto_list[nn].zz ;
11650
11651 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
11652
11653 LOAD_FVEC3(tv,xx,yy,zz) ; /* Talairach coords */
11654
11655 /* 09 Jul 2001: if not now viewing in Talairach coordinates,
11656 then transform vector to current coordinates */
11657
11658 if( im3d->anat_now->view_type != VIEW_TALAIRACH_TYPE )
11659 tv = AFNI_transform_vector( im3d->anat_dset[VIEW_TALAIRACH_TYPE] ,
11660 tv , im3d->anat_now ) ;
11661
11662 fv = THD_dicomm_to_3dmm( im3d->anat_now , tv ) ;
11663 iv = THD_3dmm_to_3dind ( im3d->anat_now , fv ) ;
11664 ii = iv.ijk[0] ; jj = iv.ijk[1] ; kk = iv.ijk[2] ;
11665
11666 daxes = CURRENT_DAXES(im3d->anat_now) ;
11667 if( ii >= 0 && ii < daxes->nxx &&
11668 jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
11669
11670 SAVE_VPT(im3d) ;
11671 AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_ALL ) ; /* jump */
11672 } else {
11673 BEEPIT ; WARNING_message("Bad 'Go atlas position' coordinates!?") ;
11674 }
11675 EXRETURN ;
11676 }
11677
11678 /*-------------------------------------------------------------------------
11679 10 Jul 2001
11680 ---------------------------------------------------------------------------*/
11681
11682 void AFNI_pop_whereami_kill( Three_D_View *im3d )
11683 {
11684 if( im3d == NULL ) return ;
11685
11686 MCW_unregister_hint( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11687 MCW_unregister_help( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11688
11689 im3d->vwid->imag->pop_whereami_twin = NULL ;
11690 return ;
11691 }
11692
11693
11694 /*-------------------------------------------------------------------------
11695 A newer output form for whereami
11696 ---------------------------------------------------------------------------*/
11697 static int htmlwami_open = 0 ;
11698
11699 void AFNI_htmlwami_killfun( XtPointer pp ){
11700 Three_D_View *im3d = (Three_D_View *)pp;
11701
11702 if (!im3d) return;
11703
11704 im3d->vwid->imag->pop_whereami_htmlwin=NULL;
11705 /* not there yet
11706 MCW_unregister_hint( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11707 MCW_unregister_help( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11708 */
11709
11710 htmlwami_open = 0 ; return ;
11711 }
11712
11713 void AFNI_htmlwami_CB( Widget w , XtPointer cd , XtPointer cbd )
11714 {
11715 Three_D_View *im3d = (Three_D_View *)cd ;
11716 char *uinf=(char *)cbd , *inf=NULL ; int ii ;
11717 MCW_htmlwin *htmlwami_hw = im3d->vwid->imag->pop_whereami_htmlwin;
11718
11719 ENTRY("AFNI_htmlwami_CB") ;
11720
11721 if( uinf != NULL && *uinf != '\0' ){
11722 inf = (char *)malloc(sizeof(char)*(strlen(uinf)+16)) ;
11723 strcpy(inf,"wami:") ; strcat(inf,uinf) ;
11724 }
11725
11726 if( htmlwami_open && htmlwami_hw != NULL ){
11727 XMapRaised( XtDisplay(htmlwami_hw->wshell), XtWindow(htmlwami_hw->wshell)) ;
11728 MCW_htmlwin_alter( htmlwami_hw , inf );
11729 EXRETURN ;
11730 } else {
11731 htmlwami_hw = new_MCW_htmlwin( im3d->vwid->imag->topper, inf,
11732 AFNI_htmlwami_killfun , im3d , NULL, 0 ) ;
11733 im3d->vwid->imag->pop_whereami_htmlwin = htmlwami_hw;
11734 }
11735 free(inf) ; inf = NULL ; htmlwami_open = 1 ;
11736
11737 EXRETURN ;
11738 }
11739
11740 void AFNI_alter_wami_text(Three_D_View *im3d, char *utlab)
11741 {
11742 char *tlab=NULL;
11743
11744 ENTRY("AFNI_alter_wami_text");
11745
11746 if (!im3d || !im3d->vwid || !im3d->vwid->imag) EXRETURN;
11747
11748 if (!utlab) tlab = "\n** Can not use whereami functionality with this dataset**<br>\n"
11749 "Please set AFNI_ATLAS_LIST and AFNI_TEMPLATE_SPACE_LIST appropriately<br>\n"
11750 "Also set the space of the dataset to a corresponding space<br>\n" ;
11751 else tlab = utlab;
11752
11753 if (AFNI_wami_output_mode() == 0) {
11754 if (!im3d->vwid->imag->pop_whereami_twin) EXRETURN;
11755 MCW_textwin_alter( im3d->vwid->imag->pop_whereami_twin , tlab ) ;
11756 } else {
11757 AFNI_htmlwami_CB( NULL , (XtPointer)im3d , (XtPointer) tlab );
11758 }
11759 EXRETURN;
11760 }
11761
11762
11763 /*-------------------------------------------------------------------------*/
11764
11765 char * AFNI_ttatlas_query( Three_D_View *im3d )
11766 {
11767 static int have_TT = 1 ;
11768 THD_3dim_dataset *dset;
11769 ATLAS_LIST *atlas_alist;
11770
11771 if( !IM3D_OPEN(im3d) || !CAN_TALTO(im3d) ) return NULL ;
11772
11773 set_TT_whereami_version(0,0);
11774 set_wami_web_reqtype(WAMI_WEB_STRUCT); /* set web atlas output to simple structure */
11775
11776 #if 0
11777 /*-- make sure we have the TT atlas --*/
11778 have_TT = 0;
11779 if( TT_retrieve_atlas_dset("TT_Daemon",0)){
11780 have_TT = 1 ;
11781 }
11782 if( !have_TT ) return NULL ;
11783 #endif
11784
11785 if( have_TT ){
11786 THD_fvec3 tv ; char *tlab ;
11787
11788 /*-- current position --*/
11789
11790 LOAD_FVEC3(tv,im3d->vinfo->xi,im3d->vinfo->yj,im3d->vinfo->zk) ;
11791
11792 /*-- transform to Talairach, if needed --*/
11793
11794 if( im3d->anat_now->view_type != VIEW_TALAIRACH_TYPE )
11795 tv = AFNI_transform_vector( im3d->anat_now , tv ,
11796 im3d->anat_dset[VIEW_TALAIRACH_TYPE] ) ;
11797
11798 /*-- get result string --*/
11799 /* use space of "talairach view" dataset */
11800 /* will want to change this for flexibility not to use preset xform */
11801 dset = im3d->anat_dset[VIEW_TALAIRACH_TYPE];
11802
11803 atlas_alist = get_G_atlas_list(); /* get the whole atlas list */
11804
11805 tlab = TT_whereami( tv.xyz[0] , tv.xyz[1] , tv.xyz[2],
11806 THD_get_space(dset) , env_atlas_list() );
11807
11808 return tlab ;
11809 }
11810
11811 return NULL ;
11812 }
11813
11814 /*-------------------------------------------------------------------------
11815 See the TT atlas in the overlay? -- 25 Jul 2001
11816 ---------------------------------------------------------------------------*/
11817
11818 void AFNI_see_ttatlas_CB( Widget w, XtPointer cd, XtPointer cb)
11819 {
11820 Three_D_View *im3d = (Three_D_View *) cd ;
11821 int newsee = MCW_val_bbox(im3d->vwid->func->see_ttatlas_bbox) ;
11822
11823 if( newsee == im3d->vinfo->see_ttatlas ) return ;
11824
11825 im3d->vinfo->see_ttatlas = newsee ;
11826
11827 if( im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE )
11828 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ; /* redraw */
11829
11830 return ;
11831 }
11832
11833 /*---------------------------------------------------------------------
11834 called when the mnito chooser is set - 01 May 2002
11835 -----------------------------------------------------------------------*/
11836
11837 void AFNI_mnito_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
11838 {
11839 Three_D_View *im3d = (Three_D_View *) cd ;
11840 float xx,yy,zz, xout, yout, zout;
11841 char dum1[32],dum2[32];
11842 int nn ;
11843 THD_fvec3 tv ;
11844
11845 ENTRY("AFNI_mnito_CB") ;
11846
11847 if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
11848
11849 if( !CAN_TALTO(im3d) || cbs->reason != mcwCR_string ){ /* error */
11850 POPDOWN_string_chooser ;
11851 BEEPIT ; WARNING_message("Can't 'MNI To'!?") ;
11852 EXRETURN ;
11853 }
11854
11855 if( last_mnito_string != NULL ) free(last_mnito_string) ;
11856 last_mnito_string = strdup(cbs->cval) ;
11857
11858 nn = sscanf( cbs->cval , "%f%[ ,]%f%[ ,]%f" , &xx,dum1,&yy,dum2,&zz ) ;
11859 if( nn != 5 ){ BEEPIT ; WARNING_message("bad 'MNI To' entries!?") ; EXRETURN ; }
11860
11861 xx = -xx, yy = -yy; /* LPI to RAI coordinates */
11862 LOAD_ANAT_VIEW(im3d) ;
11863 /* tv = THD_mni_to_tta( tv ) ; */ /* Talairach coords */
11864 /* transform the MNI coordinates to whatever space the +tlrc view is in */
11865 if(wami_xform_xyz(xx, yy, zz, &xout, &yout, &zout, get_jump_space(),
11866 THD_get_space(im3d->anat_dset[VIEW_TALAIRACH_TYPE]))!=0) {
11867 BEEPIT ; WARNING_message("'MNI To' failed!?") ;
11868 }
11869 LOAD_FVEC3(tv,xout,yout,zout) ; /* load vector with new coordinates
11870 in dset's std space of tlrc view */
11871
11872 /* transform from +tlrc view space to current view (maybe orig) if needed */
11873 if( im3d->anat_now->view_type != VIEW_TALAIRACH_TYPE )
11874 tv = AFNI_transform_vector( im3d->anat_dset[VIEW_TALAIRACH_TYPE] ,
11875 tv , im3d->anat_now ) ;
11876
11877 nn = AFNI_jumpto_dicom( im3d , tv.xyz[0], tv.xyz[1], tv.xyz[2] ) ;
11878 if( nn < 0 ){ BEEPIT ; WARNING_message("'MNI To' failed!?") ; }
11879
11880 RESET_AFNI_QUIT(im3d) ;
11881 EXRETURN ;
11882 }
11883
11884 /*---------------------------------------------------------------------
11885 called when the jumpto chooser is set
11886 -----------------------------------------------------------------------*/
11887
11888 void AFNI_jumpto_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
11889 {
11890 Three_D_View *im3d = (Three_D_View *) cd ;
11891 float xx,yy,zz ;
11892 char dum1[32],dum2[32];
11893 int nn ;
11894
11895 ENTRY("AFNI_jumpto_CB") ;
11896
11897 if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
11898 if( cbs->reason != mcwCR_string ) EXRETURN ; /* error */
11899
11900 if( last_jumpto_xyz_string != NULL ) free(last_jumpto_xyz_string) ;
11901 last_jumpto_xyz_string = strdup(cbs->cval) ;
11902
11903 nn = sscanf( cbs->cval , "%f%[ ,]%f%[ ,]%f" , &xx,dum1,&yy,dum2,&zz ) ;
11904 if( nn != 5 ){ BEEPIT ; WARNING_message("bad Jumpto entries!?") ; EXRETURN ; }
11905
11906 THD_coorder_to_dicom( &GLOBAL_library.cord , &xx,&yy,&zz ) ;
11907
11908 SAVE_VPT(im3d) ; /* save current place as old one */
11909 nn = AFNI_jumpto_dicom( im3d , xx,yy,zz ) ;
11910 if( nn < 0 ){ BEEPIT ; WARNING_message("Jumpto failed!") ; }
11911
11912 RESET_AFNI_QUIT(im3d) ;
11913 EXRETURN ;
11914 }
11915
11916 /*---------------------------------------------------------------------*/
11917
11918 int AFNI_jumpto_dicom_OLD( Three_D_View *im3d , float xx, float yy, float zz )
11919 {
11920 THD_dataxes *daxes ;
11921 THD_fvec3 fv ; THD_ivec3 iv ;
11922 int ii,jj,kk ;
11923
11924 ENTRY("AFNI_jumpto_dicom_OLD") ;
11925
11926 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
11927
11928 fv = THD_dicomm_to_3dmm( im3d->anat_now , TEMP_FVEC3(xx,yy,zz) ) ;
11929 iv = THD_3dmm_to_3dind ( im3d->anat_now , fv ) ;
11930 ii = iv.ijk[0] ; jj = iv.ijk[1] ; kk = iv.ijk[2] ;
11931
11932 daxes = CURRENT_DAXES(im3d->anat_now) ;
11933 if( ii >= 0 && ii < daxes->nxx &&
11934 jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
11935
11936 AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_ALL ) ; /* jump */
11937 RETURN(1) ;
11938 } else {
11939 BEEPIT ; WARNING_message("Jumpto DICOM failed -- bad coordinates?!") ;
11940 RETURN(-1) ;
11941 }
11942 }
11943
11944 /*---------------------------------------------------------------------*/
11945
11946 int AFNI_jump_and_seed( Three_D_View *im3d , float xx, float yy, float zz )
11947 {
11948 THD_dataxes *daxes ;
11949 THD_fvec3 fv ; THD_ivec3 iv ;
11950 int ii,jj,kk,qq ;
11951 static int iil = -1, jjl = -1, kkl = -1;
11952
11953 ENTRY("AFNI_jump_and_seed") ;
11954
11955 LOAD_ANAT_VIEW(im3d) ; /* 02 Nov 1996 */
11956
11957 fv = THD_dicomm_to_3dmm( im3d->anat_now , TEMP_FVEC3(xx,yy,zz) ) ;
11958 iv = THD_3dmm_to_3dind ( im3d->anat_now , fv ) ;
11959 ii = iv.ijk[0] ; jj = iv.ijk[1] ; kk = iv.ijk[2] ;
11960
11961 daxes = CURRENT_DAXES(im3d->anat_now) ;
11962 if( ii >= 0 && ii < daxes->nxx &&
11963 jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
11964
11965 /* Note that the locations of the last click should be set
11966 per im3d, perhaps within function AFNI_icor_setref_anatijk().
11967 This current static storage might fail whith multiple
11968 controllers. */
11969 if (ii != iil || jj != jjl || kk != kkl) {
11970 DONT_TELL_SUMA;
11971 AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_OPTIONAL ) ;
11972 TELL_SUMA;
11973 qq = AFNI_icor_setref_anatijk(im3d,ii,jj,kk) ;
11974 if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ;
11975 iil = ii; jjl = jj; kkl = kk;
11976 }
11977 RETURN(1) ;
11978 } else {
11979 BEEPIT ;
11980 WARNING_message("AFNI_icor_seed_SUMA failed -- bad coordinates?!") ;
11981 RETURN(-1) ;
11982 }
11983 }
11984
11985 /*---------------------------------------------------------------------*/
11986
11987 int AFNI_creepto_dicom( Three_D_View *im3d , float xx, float yy, float zz )
11988 {
11989 float xc,yc,zc , dxx,dyy,dzz ; int ndd,qq,ii=0 ;
11990
11991 ENTRY("AFNI_creepto_dicom") ;
11992
11993 xc = im3d->vinfo->xi ; yc = im3d->vinfo->yj ; zc = im3d->vinfo->zk ;
11994
11995 dxx = fabsf( (xx-xc) / DSET_DX(im3d->anat_now) ) ;
11996 dyy = fabsf( (yy-yc) / DSET_DY(im3d->anat_now) ) ;
11997 dzz = fabsf( (zz-zc) / DSET_DZ(im3d->anat_now) ) ;
11998 ndd = (int)sqrtf(dxx*dxx+dyy*dzz+dzz*dzz) ; ndd = MIN(ndd,32) ;
11999
12000 SAVE_VPT(im3d) ;
12001 if( ndd < 2 ){ ii = AFNI_jumpto_dicom_OLD(im3d,xx,yy,zz) ; RETURN(ii) ; }
12002
12003 dxx = (xx-xc) / ndd ; dyy = (yy-yc) / ndd ; dzz = (zz-zc) / ndd ;
12004
12005 for( qq=ndd-1 ; qq >= 0 ; qq-- )
12006 ii = AFNI_jumpto_dicom_OLD( im3d , xx-dxx*qq , yy-dyy*qq , zz-dzz*qq ) ;
12007
12008 RETURN(ii) ;
12009 }
12010
12011 /*---------------------------------------------------------------------*/
12012
12013 int AFNI_jumpto_dicom( Three_D_View *im3d , float xx, float yy, float zz )
12014 {
12015 int ii ;
12016 SAVE_VPT(im3d) ;
12017 if( AFNI_yesenv("AFNI_CREEPTO") )
12018 ii = AFNI_creepto_dicom(im3d,xx,yy,zz) ;
12019 else
12020 ii = AFNI_jumpto_dicom_OLD(im3d,xx,yy,zz) ;
12021 return ii ;
12022 }
12023
12024 /*----------- the two functions below date to 19 Aug 1999 -------------*/
12025
12026 int AFNI_jumpto_ijk( Three_D_View *im3d , int ii, int jj, int kk )
12027 {
12028 THD_dataxes *daxes ;
12029
12030 ENTRY("AFNI_jumpto_ijk") ;
12031
12032 LOAD_ANAT_VIEW(im3d) ;
12033
12034 daxes = CURRENT_DAXES(im3d->anat_now) ;
12035 if( ii >= 0 && ii < daxes->nxx &&
12036 jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
12037
12038 SAVE_VPT(im3d) ;
12039 AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_ALL ) ; /* jump */
12040 RETURN(1) ;
12041 } else {
12042 BEEPIT ; WARNING_message("Jumpto IJK failed -- bad input values?!") ;
12043 WARNING_message(" i range = 0 .. %d (inclusive)",daxes->nxx-1) ;
12044 WARNING_message(" j range = 0 .. %d (inclusive)",daxes->nyy-1) ;
12045 WARNING_message(" k range = 0 .. %d (inclusive)",daxes->nzz-1) ;
12046 RETURN(-1) ;
12047 }
12048 }
12049
12050 /*---------------------------------------------------------------------*/
12051
12052 void AFNI_jumpto_thminmax_CB( Widget w , XtPointer cd , XtPointer cb )
12053 {
12054 Three_D_View *im3d = (Three_D_View *)cd ;
12055 int ijk=-777, ii,jj,kk ;
12056 float xx,yy,zz ;
12057
12058 ENTRY("AFNI_jumpto_thminmax_CB") ;
12059
12060 if( !IM3D_OPEN(im3d) ) EXRETURN ;
12061
12062 if( w == im3d->vwid->func->pbar_jumpto_thmax_pb )
12063 ijk = im3d->fim_thresh_max_ijk ;
12064 else if( w == im3d->vwid->func->pbar_jumpto_thmin_pb )
12065 ijk = im3d->fim_thresh_min_ijk ;
12066
12067 if( ijk == -777 || im3d->fim_thrindex < 0 ) EXRETURN ;
12068 if( ijk < 0 ){ BEEPIT ; SENSITIZE(w,False) ; EXRETURN ; }
12069
12070 ii = DSET_index_to_ix(im3d->fim_now,ijk) ;
12071 jj = DSET_index_to_jy(im3d->fim_now,ijk) ;
12072 kk = DSET_index_to_kz(im3d->fim_now,ijk) ;
12073
12074 MAT44_VEC( im3d->fim_now->daxes->ijk_to_dicom , ii,jj,kk , xx,yy,zz ) ;
12075 (void)AFNI_jumpto_dicom( im3d , xx,yy,zz ) ;
12076
12077 EXRETURN ;
12078 }
12079
12080 /*---------------------------------------------------------------------*/
12081 /* Jump to ijk in Overlay [20 Apr 2016] */
12082
12083 int AFNI_jumpto_ijk_olay( Three_D_View *im3d , int ii, int jj, int kk )
12084 {
12085 THD_dataxes *daxes ;
12086
12087 ENTRY("AFNI_jumpto_ijk_olay") ;
12088
12089 if( !ISVALID_DSET(im3d->fim_now) ){ BEEPIT; RETURN(-1); }
12090
12091 daxes = im3d->fim_now->daxes ;
12092
12093 if( ii >= 0 && ii < daxes->nxx &&
12094 jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
12095
12096 THD_fvec3 fv ;
12097 SAVE_VPT(im3d) ;
12098
12099 fv = THD_3dind_to_dicomm_no_wod( im3d->fim_now , TEMP_IVEC3(ii,jj,kk) ) ;
12100 RETURN( AFNI_jumpto_dicom_OLD( im3d , fv.xyz[0], fv.xyz[1], fv.xyz[2] ) ) ;
12101 }
12102
12103 BEEPIT ; WARNING_message("Jumpto IJK (OL) failed -- bad indexes?!") ;
12104 RETURN(-1) ;
12105 }
12106
12107 /*---------------------------------------------------------------------*/
12108
12109 void AFNI_jumpto_ijk_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
12110 {
12111 Three_D_View *im3d = (Three_D_View *) cd ;
12112 int ii=-1,jj=-1,kk=-1 ;
12113 int nn ;
12114 char dum1[32],dum2[32];
12115
12116 ENTRY("AFNI_jumpto_ijk_CB") ;
12117
12118 if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
12119 if( cbs->reason != mcwCR_string ) EXRETURN ; /* error */
12120
12121 if( last_jumpto_ijk_string != NULL ) free(last_jumpto_ijk_string) ;
12122 last_jumpto_ijk_string = strdup(cbs->cval) ;
12123
12124 nn = sscanf( cbs->cval , "%d%[ ,]%d%[ ,]%d" , &ii,dum1,&jj,dum2,&kk ) ;
12125 if( nn > 0 && nn < 3 && ii >= 0 ){ /* 1D index jump [26 Jun 2009] */
12126 nn = ii ;
12127 ii = DSET_index_to_ix(im3d->anat_now,nn) ;
12128 jj = DSET_index_to_jy(im3d->anat_now,nn) ;
12129 kk = DSET_index_to_kz(im3d->anat_now,nn) ;
12130 } else if( nn != 5 ){
12131 BEEPIT; WARNING_message("Jumpto IJK failed -- bad entries?!"); EXRETURN;
12132 }
12133
12134 nn = AFNI_jumpto_ijk( im3d , ii,jj,kk ) ;
12135 if( nn < 0 ) BEEPIT ;
12136
12137 RESET_AFNI_QUIT(im3d) ;
12138 EXRETURN ;
12139 }
12140
12141 /*---------------------------------------------------------------------*/
12142
12143 void AFNI_jumpto_ijk_olay_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
12144 {
12145 Three_D_View *im3d = (Three_D_View *) cd ;
12146 int ii=-1,jj=-1,kk=-1 ;
12147 int nn ;
12148 char dum1[32],dum2[32];
12149
12150 ENTRY("AFNI_jumpto_ijk_olay_CB") ;
12151
12152 if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
12153 if( cbs->reason != mcwCR_string ) EXRETURN ; /* error */
12154
12155 if( last_jumpto_ijk_olay_string != NULL ) free(last_jumpto_ijk_olay_string) ;
12156 last_jumpto_ijk_olay_string = strdup(cbs->cval) ;
12157
12158 nn = sscanf( cbs->cval , "%d%[ ,]%d%[ ,]%d" , &ii,dum1,&jj,dum2,&kk ) ;
12159 if( nn > 0 && nn < 3 && ii >= 0 ){
12160 nn = ii ;
12161 ii = DSET_index_to_ix(im3d->fim_now,nn) ;
12162 jj = DSET_index_to_jy(im3d->fim_now,nn) ;
12163 kk = DSET_index_to_kz(im3d->fim_now,nn) ;
12164 } else if( nn != 5 ){
12165 BEEPIT; WARNING_message("Jumpto IJK failed -- bad entries?!"); EXRETURN;
12166 }
12167
12168 nn = AFNI_jumpto_ijk_olay( im3d , ii,jj,kk ) ;
12169 if( nn < 0 ) BEEPIT ;
12170
12171 RESET_AFNI_QUIT(im3d) ;
12172 EXRETURN ;
12173 }
12174
12175 /*---------------------------------------------------------------------
12176 called when the sumato chooser is set
12177 -----------------------------------------------------------------------*/
12178
12179 void AFNI_sumato_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
12180 {
12181 Three_D_View *im3d = (Three_D_View *) cd ;
12182 int nn , ii ;
12183
12184 ENTRY("AFNI_sumato_CB") ;
12185
12186 if( !IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
12187 if( cbs->reason != mcwCR_string ) EXRETURN ;
12188 if( !SESSION_HAS_SUMA(im3d->ss_now) ) EXRETURN ;
12189
12190 if( last_sumato_string != NULL ) free(last_sumato_string) ;
12191 last_sumato_string = strdup(cbs->cval) ;
12192
12193 nn = -1 ;
12194 sscanf( cbs->cval , "%d" , &nn ) ;
12195 ii = SUMA_find_node_id( im3d->ss_now->su_surf[0] , nn ) ;
12196 if( ii < 0 ){ BEEPIT; WARNING_message("SUMA To fails -- bad entry?!"); EXRETURN; }
12197
12198 (void) AFNI_jumpto_dicom( im3d ,
12199 im3d->ss_now->su_surf[0]->ixyz[ii].x ,
12200 im3d->ss_now->su_surf[0]->ixyz[ii].y ,
12201 im3d->ss_now->su_surf[0]->ixyz[ii].z ) ;
12202
12203 RESET_AFNI_QUIT(im3d) ;
12204 EXRETURN ;
12205 }
12206
12207 /*---------------------------------------------------------------------
12208 Transform current dataset based on the existing set of markers
12209 -----------------------------------------------------------------------*/
12210
12211 #define BEEP_AND_RETURN { BEEPIT; EXRETURN; }
12212
12213 void AFNI_marks_transform_CB( Widget w ,
12214 XtPointer client_data , XtPointer call_data )
12215 {
12216 Three_D_View *im3d = (Three_D_View *) client_data ;
12217 THD_marker_set *markers ;
12218 THD_warp *warp ;
12219 THD_3dim_dataset *new_dset ;
12220 THD_session *ss ;
12221 int vnew , vvv , sss , aaa , fff , id ;
12222 float resam_size ;
12223 Widget wmsg ;
12224
12225 ENTRY("AFNI_marks_transform_CB") ;
12226
12227 /*--- sanity checks ---*/
12228
12229 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
12230
12231 markers = im3d->anat_now->markers ;
12232 if(markers == NULL || markers->aflags[1] != MARKACTION_WARP) BEEP_AND_RETURN ;
12233
12234 vnew = WARPED_VIEW(im3d->vinfo->view_type) ; /* view index of new dataset */
12235 if( !ISVALID_VIEW(vnew) ) BEEP_AND_RETURN ;
12236
12237 /*--- make warp ---*/
12238
12239 warp = AFNI_make_warp( im3d ) ;
12240 if( warp == NULL ) BEEP_AND_RETURN ;
12241
12242 /*--- create new dataset (empty at this point) ---*/
12243
12244 resam_size = im3d->vinfo->resam_vox ;
12245 new_dset = AFNI_init_warp( im3d , im3d->anat_now , warp , resam_size ) ;
12246 if( new_dset == NULL ) BEEP_AND_RETURN ;
12247
12248 { char his[128] ;
12249 tross_Copy_History( im3d->anat_now , new_dset ) ;
12250 sprintf(his,"afni: transformed to %s",VIEW_typestr[vnew]) ;
12251 tross_Append_History( new_dset , his ) ;
12252 }
12253
12254 /*----- This new dataset may replace a current dataset,
12255 and if so, THAT dataset may have a warp child,
12256 and so on. Mark those datasets for destruction,
12257 mark their anatomy children for destruction, and destroy them -----*/
12258
12259 vvv = vnew ;
12260 while( ISVALID_VIEW(vvv) && ISVALID_3DIM_DATASET(im3d->anat_dset[vvv]) ){
12261 DSET_MARK_FOR_DEATH( im3d->anat_dset[vvv] ) ;
12262 vvv = WARPED_VIEW(vvv) ;
12263 }
12264
12265 AFNI_mark_for_death(GLOBAL_library.sslist ) ; /* find descendants */
12266 AFNI_andersonville (GLOBAL_library.sslist , True ) ; /* kill (including files) */
12267
12268 /*----- Can now place the new dataset into its rightful place -----*/
12269
12270 sss = im3d->vinfo->sess_num ;
12271 aaa = im3d->vinfo->anat_num ;
12272 fff = im3d->vinfo->func_num ;
12273
12274 SET_SESSION_DSET(new_dset, GLOBAL_library.sslist->ssar[sss], aaa, vnew);
12275 /* GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][vnew] = new_dset ;*/
12276
12277 /* reload active datasets, to allow for destruction that may
12278 have occured (this code is copied from AFNI_initialize_view) */
12279
12280 for( id=0 ; id <= LAST_VIEW_TYPE ; id++ ){
12281 im3d->anat_dset[id] = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], aaa, id) ;
12282 im3d->fim_dset[id] = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], fff, id) ;
12283 /* im3d->anat_dset[id] = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][id] ;
12284 im3d->fim_dset[id] = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[fff][id] ;
12285 */
12286 if( ISVALID_3DIM_DATASET(im3d->anat_dset[id]) )
12287 SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], True ) ;
12288 else
12289 SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], False) ;
12290 }
12291
12292 STATUS("writing new dataset") ;
12293
12294 DSET_overwrite_header(new_dset) ;
12295
12296 /*--- have transformed this anatomy dataset
12297 ==> if the input was the original view, then
12298 destroy any other marker sets in the original view
12299 and make their datasets anatomical children of this one ---*/
12300
12301 if( im3d->vinfo->view_type == VIEW_ORIGINAL_TYPE ){
12302 int id ;
12303 THD_3dim_dataset *dss ;
12304
12305 /* perform surgery on the anat datasets in this session */
12306
12307 STATUS("re-anat_parenting anatomical datasets in this session") ;
12308
12309 for( id=0 ; id < im3d->ss_now->num_dsset ; id++ ){
12310 dss = GET_SESSION_DSET(im3d->ss_now, id, 0) ;
12311 /* dss = im3d->ss_now->dsset_xform_table[id][0] ;*/
12312
12313 if( ! ISVALID_3DIM_DATASET(dss) || dss == im3d->anat_now ) continue ;
12314
12315 if( dss->markers != NULL ) SINGLE_KILL(dss->kl,dss->markers) ;
12316 dss->markers = NULL ;
12317
12318 if( dss->anat_parent == NULL ){
12319 dss->anat_parent = im3d->anat_now ;
12320 MCW_strncpy( dss->anat_parent_name ,
12321 im3d->anat_now->self_name , THD_MAX_NAME ) ;
12322 dss->anat_parent_idcode = im3d->anat_now->idcode ;
12323 }
12324 }
12325 }
12326
12327 /*--- now that we have a new potential parent (the warped dataset),
12328 and maybe some links to its warp_parent (done just above),
12329 try to make some descendants (followup warps) from it ---*/
12330
12331 AFNI_make_descendants( GLOBAL_library.sslist ) ;
12332
12333 /*--- clean up some stuff ---*/
12334
12335 if( GLOBAL_argopt.auto_purge == True ) AFNI_purge_unused_dsets() ;
12336
12337 /* Jan 31, 1995: force adoption of any dataset
12338 that was orphaned at Andersonville */
12339
12340 for( sss=0 ; sss < GLOBAL_library.sslist->num_sess ; sss++ ){
12341 ss = GLOBAL_library.sslist->ssar[sss] ;
12342 if( ISVALID_SESSION(ss) ) AFNI_force_adoption( ss , GLOBAL_argopt.warp_4D ) ;
12343 }
12344
12345 /*--- close marks panel and exit ---*/
12346
12347 #if 0
12348 XtSetSensitive( im3d->vwid->top_shell , True ) ;
12349 SHOW_AFNI_READY ;
12350 #endif
12351
12352 AFNI_marks_action_CB( NULL , (XtPointer) im3d , NULL ) ;
12353
12354 MPROBE ;
12355 EXRETURN ;
12356 }
12357
12358 /*-------------------------------------------------------------------
12359 Compute the warp.
12360
12361 Notice the convention: the warp is always stored as Dicom-to-Dicom
12362 coordinates. For actual use, it must be converted into the
12363 correct form for 3dmm-to-3dmm, or 3dfind-to-3dfind, etc.
12364
12365 The reason for this convention is that anatomical warps will be
12366 applied to functional datasets, which will in general be oriented
12367 differently from the anatomical dataset that the warp was computed
12368 upon. By keeping the warp in the generic Dicom system, this
12369 application of a warp to another dataset will be possible.
12370 ---------------------------------------------------------------------*/
12371
12372 /* macro to extract the im-th marker vector into a THD_fvec3 structure */
12373
12374 #define MVEC(im) \
12375 TEMP_FVEC3(markers->xyz[im][0],markers->xyz[im][1],markers->xyz[im][2])
12376
12377 THD_warp * AFNI_make_warp( Three_D_View *im3d )
12378 {
12379 THD_3dim_dataset *anat = im3d->anat_now ;
12380 THD_marker_set *markers = im3d->anat_now->markers ;
12381 THD_warp *warp ;
12382 RwcBoolean good ;
12383
12384 ENTRY("AFNI_make_warp") ;
12385
12386 /*--- check the markers for OK-osity ---*/
12387
12388 good = AFNI_marks_quality_check( False , im3d ) ;
12389 if( !good ) RETURN(NULL) ;
12390
12391 /*--- make a new warp, and then construct it,
12392 based on the type of marker set we have here ---*/
12393
12394 warp = myXtNew( THD_warp ) ;
12395
12396 switch( markers->type ){ /* type of marker set */
12397
12398 default: RETURN(NULL) ; /* something bad happened */
12399
12400 /*--- bounding box markers set ---*/
12401
12402 case MARKSET_BOUNDING:{
12403 THD_talairach_12_warp *twarp = (THD_talairach_12_warp *) warp ;
12404 THD_fvec3 mant,mpos,msup,minf,mrig,mlef , pcie ;
12405 float dist_sup , dist_inf , dist_ant , dist_med , dist_pos ,
12406 dist_lef , dist_rig ;
12407 float scale_S , scale_I , scale_A , scale_M , scale_P ,
12408 scale_L , scale_R , shift_P ;
12409 float bot_S , bot_I , bot_A , bot_M , bot_P ,
12410 bot_L , bot_R ;
12411 float top_S , top_I , top_A , top_M , top_P ,
12412 top_L , top_R ;
12413 THD_fvec3 bv_A , bv_M , bv_P , sv_A , sv_M , sv_P ;
12414
12415 /* let the world know what kind of warp is being built */
12416
12417 twarp->type = WARP_TALAIRACH_12_TYPE ;
12418
12419 /* extract the marker vectors, put in Dicom coords */
12420
12421 mant = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MANT) ) ;
12422 mpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MPOS) ) ;
12423 msup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSUP) ) ;
12424 minf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MINF) ) ;
12425 mrig = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MRIG) ) ;
12426 mlef = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MLEF) ) ;
12427
12428 /* convert Posterior Commissure from parent to current coords */
12429
12430 LOAD_FVEC3( pcie ,
12431 anat->warp_parent->markers->xyz[IMARK_PCIE][0] ,
12432 anat->warp_parent->markers->xyz[IMARK_PCIE][1] ,
12433 anat->warp_parent->markers->xyz[IMARK_PCIE][2] ) ;
12434
12435 pcie = THD_3dmm_to_dicomm( anat->warp_parent , pcie ) ;
12436 pcie = AFNI_transform_vector( anat->warp_parent , pcie , anat ) ;
12437
12438 /* compute distances between points in various directions */
12439
12440 dist_ant = -mant.xyz[1] ;
12441 dist_med = pcie.xyz[1] ;
12442 dist_pos = mpos.xyz[1] - pcie.xyz[1] ;
12443
12444 dist_sup = msup.xyz[2] ;
12445 dist_inf = -minf.xyz[2] ;
12446 dist_lef = mlef.xyz[0] ;
12447 dist_rig = -mrig.xyz[0] ;
12448
12449 /* from these, compute the scalings needed in each
12450 direction and the shift needed posterior to the PC */
12451
12452 scale_A = ATLAS_FRONT_TO_AC / dist_ant ;
12453 scale_M = ATLAS_AC_TO_PC / dist_med ;
12454 scale_P = ATLAS_PC_TO_BACK / dist_pos ;
12455 scale_S = ATLAS_AC_TO_TOP / dist_sup ;
12456 scale_I = ATLAS_BOT_TO_AC / dist_inf ;
12457 scale_L = ATLAS_AC_TO_LAT / dist_lef ;
12458 scale_R = ATLAS_AC_TO_LAT / dist_rig ;
12459
12460 shift_P = scale_P * dist_med - ATLAS_AC_TO_PC ;
12461
12462 /* shift vectors in each direction, for each y cell (A,M,P) */
12463
12464 LOAD_FVEC3( bv_A , 0,0,0 ) ; bv_M = sv_A = sv_M = bv_A ;
12465
12466 LOAD_FVEC3( bv_P , 0 , shift_P , 0 ) ;
12467 LOAD_FVEC3( sv_P , 0 , -shift_P / scale_P , 0 ) ;
12468
12469 /* bounds information for each direction, for each cell */
12470
12471 bot_A = -9999.0 ; top_A = 0.0 ;
12472 bot_M = 0.0 ; top_M = ATLAS_AC_TO_PC ;
12473 bot_P = ATLAS_AC_TO_PC ; top_P = 9999.0 ;
12474
12475 bot_R = -9999.0 ; top_R = 0.0 ;
12476 bot_L = 0.0 ; top_L = 9999.9 ;
12477
12478 bot_I = -9999.0 ; top_I = 0.0 ;
12479 bot_S = 0.0 ; top_S = 9999.9 ;
12480
12481 /* Compute the 12 linear maps:
12482 They are all linear scalings (diagonal matrices);
12483 posterior to the PC, they also contain shifts
12484 to align stuff to the nominal PC location.
12485 N.B.: these are maps from AC-PC aligned coordinates
12486 to the Talairach system. Maps from the
12487 original data to the Talairach system
12488 will be computed later (in AFNI_concatenate_warps). */
12489
12490 /* ------- a macro to automate map making:
12491 xx = R or L , yy = A, M, or P , zz = I or S --------*/
12492
12493 #define MAKE_MAP(xx,yy,zz) \
12494 (\
12495 LOAD_DIAG_MAT( twarp->warp[W_ ## xx ## yy ## zz].mfor , \
12496 scale_ ## xx , scale_ ## yy , scale_ ## zz ) ,\
12497 \
12498 LOAD_DIAG_MAT( twarp->warp[W_ ## xx ## yy ## zz].mbac , \
12499 1.0 / scale_ ## xx , 1.0 / scale_ ## yy , 1.0 / scale_ ## zz ) ,\
12500 \
12501 twarp->warp[W_ ## xx ## yy ## zz].bvec = bv_ ## yy , \
12502 \
12503 twarp->warp[W_ ## xx ## yy ## zz].svec = sv_ ## yy , \
12504 \
12505 LOAD_FVEC3( twarp->warp[W_ ## xx ## yy ## zz].bot , \
12506 bot_ ## xx , bot_ ## yy , bot_ ## zz ) ,\
12507 \
12508 LOAD_FVEC3( twarp->warp[W_ ## xx ## yy ## zz].top , \
12509 top_ ## xx , top_ ## yy , top_ ## zz ) \
12510 )
12511
12512 /*------- end of MAKE_MAP macro --------*/
12513
12514 MAKE_MAP(R,A,S) ; /* right-anterior -superior */
12515 MAKE_MAP(L,A,S) ; /* left -anterior -superior */
12516 MAKE_MAP(R,M,S) ; /* right-medial -superior */
12517 MAKE_MAP(L,M,S) ; /* left -medial -superior */
12518 MAKE_MAP(R,P,S) ; /* right-posterior-superior */
12519 MAKE_MAP(L,P,S) ; /* left -posterior-superior */
12520 MAKE_MAP(R,A,I) ; /* right-anterior -inferior */
12521 MAKE_MAP(L,A,I) ; /* left -anterior -inferior */
12522 MAKE_MAP(R,M,I) ; /* right-medial -inferior */
12523 MAKE_MAP(L,M,I) ; /* left -medial -inferior */
12524 MAKE_MAP(R,P,I) ; /* right-posterior-inferior */
12525 MAKE_MAP(L,P,I) ; /* left -posterior-inferior */
12526
12527 #undef MAKE_MAP
12528
12529 }
12530 break ; /* end of Bounding markers set */
12531
12532 /*--- AC-PC alignment markers set ---*/
12533
12534 case MARKSET_ALIGN:{
12535 THD_affine_warp *awarp = (THD_affine_warp *) warp ;
12536
12537 THD_fvec3 acsup , acpos , pcinf , msag1 , msag2 ,
12538 alpha1,alpha2,alpha,beta,gamma,rr1,rr2,rr , dif ;
12539 THD_mat33 to_al ;
12540 float size ;
12541
12542 /* let the world know what kind of warp is being built */
12543
12544 awarp->type = WARP_AFFINE_TYPE ;
12545
12546 /* extract the marker vectors, put in Dicom coords */
12547
12548 acsup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACSE) ) ;
12549 acpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACPM) ) ;
12550 pcinf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_PCIE) ) ;
12551 msag1 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA1) ) ;
12552 msag2 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA2) ) ;
12553
12554 /*--- new y direction (beta) ---*/
12555
12556 beta = SUB_FVEC3(pcinf,acsup) ; beta = NORMALIZE_FVEC3(beta) ;
12557
12558 /*--- new x direction (alpha) ---*/
12559
12560 rr = SUB_FVEC3(msag1,acsup) ;
12561 alpha1 = CROSS_FVEC3(beta,rr) ; alpha1 = NORMALIZE_FVEC3(alpha1) ;
12562
12563 rr = SUB_FVEC3(msag2,acsup) ;
12564 alpha2 = CROSS_FVEC3(beta,rr) ; alpha2 = NORMALIZE_FVEC3(alpha2) ;
12565
12566 alpha = SCLADD_FVEC3(0.5,alpha1,0.5,alpha2) ;
12567 alpha = NORMALIZE_FVEC3(alpha) ;
12568
12569 /*--- new z direction (gamma) ---*/
12570
12571 gamma = CROSS_FVEC3(alpha,beta) ; gamma = NORMALIZE_FVEC3(gamma) ;
12572
12573 /*--- origin of Talairach coordinates (rr) --*/
12574
12575 dif = SUB_FVEC3(acsup,acpos) ;
12576 size = DOT_FVEC3(dif,gamma) ;
12577 rr1 = SCLADD_FVEC3(1.0,acpos,size,gamma) ;
12578
12579 size = DOT_FVEC3(dif,beta) ;
12580 rr2 = SCLADD_FVEC3(1.0,acsup,-size,beta) ;
12581
12582 rr = SCLADD_FVEC3(0.5,rr1,0.5,rr2) ;
12583
12584 /*--- at this point, have:
12585 new origin in rr ;
12586 new axes directions in alpha,beta,gamma.
12587 Now construct the transformation between
12588 the Dicom coordinate systems ---------------------*/
12589
12590 to_al.mat[0][0] = alpha.xyz[0] ; /* first row is alpha */
12591 to_al.mat[0][1] = alpha.xyz[1] ;
12592 to_al.mat[0][2] = alpha.xyz[2] ;
12593
12594 to_al.mat[1][0] = beta.xyz[0] ; /* second row is beta */
12595 to_al.mat[1][1] = beta.xyz[1] ;
12596 to_al.mat[1][2] = beta.xyz[2] ;
12597
12598 to_al.mat[2][0] = gamma.xyz[0] ; /* third row is gamma */
12599 to_al.mat[2][1] = gamma.xyz[1] ;
12600 to_al.mat[2][2] = gamma.xyz[2] ;
12601
12602 /*--- put into warp structure ---*/
12603
12604 awarp->warp.type = MAPPING_LINEAR_TYPE ;
12605 awarp->warp.mfor = to_al ;
12606 awarp->warp.mbac = TRANSPOSE_MAT(to_al) ; /* orthog^(-1) */
12607 awarp->warp.bvec = MATVEC(to_al,rr) ;
12608 awarp->warp.svec = rr ; NEGATE_FVEC3(awarp->warp.svec) ;
12609
12610 /* load bot & top with largest possible excursions from
12611 origin (the ALIGNBOX dimensions were added 3/25/95) */
12612
12613 {
12614 float zbot = ATLAS_ALIGNBOX_INF;
12615 float ztop = ATLAS_ALIGNBOX_SUP;
12616 float xtop = ATLAS_ALIGNBOX_LAT;
12617 float ytop = ATLAS_ALIGNBOX_POS;
12618 float ybot = ATLAS_ALIGNBOX_ANT;
12619 #define GETVAL(vvv,nnn) do{ char *eee = getenv(nnn) ; \
12620 if( eee != NULL ){ \
12621 float val=strtod(eee,NULL); if(val>0.0) vvv = val; \
12622 } } while(0)
12623
12624 GETVAL(xtop,"AFNI_ACPC_BBOX_LAT") ; /* ZSS: Apr 2007: get new bounding box */
12625 GETVAL(ybot,"AFNI_ACPC_BBOX_ANT") ; /* from environment variables, maybe */
12626 GETVAL(ytop,"AFNI_ACPC_BBOX_POS") ;
12627 GETVAL(zbot,"AFNI_ACPC_BBOX_INF") ;
12628 GETVAL(ztop,"AFNI_ACPC_BBOX_SUP") ;
12629
12630 #undef GETVAL
12631
12632 LOAD_FVEC3(awarp->warp.bot,
12633 -xtop, -ybot, -zbot);
12634 LOAD_FVEC3(awarp->warp.top,
12635 xtop, ytop, ztop);
12636 }
12637
12638 #ifdef AFNI_DEBUG
12639 STATUS("Original -> Aligned Map::") ;
12640 DUMP_LMAP(awarp->warp) ;
12641 #endif
12642
12643 } /* end of AC-PC alignment case */
12644 break ;
12645
12646 } /* end of switch on marker set type */
12647
12648 RETURN(warp) ;
12649 }
12650
12651 /*---------------------------------------------------------------------*/
12652
12653 #define ADD_ERROR(str) \
12654 { int ll = strlen(str) + strlen(error_list) + 16 ; \
12655 STATUS(str) ; \
12656 error_list = (char*) XtRealloc( error_list , ll ) ; \
12657 strcat( error_list , "*** ERROR: ") ; \
12658 strcat( error_list , str ) ; num_error++ ; }
12659
12660 #define ADD_REPORT(str) \
12661 { int ll = strlen(str) + strlen(error_list) + 16 ; \
12662 STATUS(str) ; \
12663 error_list = (char*)XtRealloc( error_list , ll ) ; \
12664 strcat( error_list , str ) ; num_report++ ; }
12665
12666 RwcBoolean AFNI_marks_quality_check( RwcBoolean make_report, Three_D_View *im3d )
12667 {
12668 THD_3dim_dataset *anat = im3d->anat_now ;
12669 THD_marker_set *markers = im3d->anat_now->markers ;
12670
12671 char *error_list ;
12672 int num_error , num_report ;
12673 char msg[128] ;
12674 RwcBoolean good ;
12675
12676 ENTRY("AFNI_marks_quality_check") ;
12677
12678 /*--- for compiling a list of errors and/or reports ---*/
12679
12680 if( markers == NULL ){ BEEPIT ; RETURN(False) ; } /* should not happen */
12681
12682 error_list = XtNewString(
12683 " *** MARKERS QUALITY REPORT *** \n\n") ;
12684 num_error = 0 ;
12685 num_report = 0 ;
12686
12687 /*--- what we do depends on the kinds of markers we have ---*/
12688
12689 switch( markers->type ){
12690
12691 default: RETURN(False) ; /* something bad happened */
12692
12693 /*--- bounding box markers set ---*/
12694
12695 case MARKSET_BOUNDING:{
12696 THD_fvec3 mant,mpos,msup,minf,mrig,mlef , pcie ;
12697 float dist_sup , dist_inf , dist_ant , dist_med , dist_pos ,
12698 dist_lef , dist_rig ;
12699
12700 /* extract the marker vectors, put in Dicom coords */
12701
12702 mant = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MANT) ) ;
12703 mpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MPOS) ) ;
12704 msup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSUP) ) ;
12705 minf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MINF) ) ;
12706 mrig = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MRIG) ) ;
12707 mlef = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MLEF) ) ;
12708
12709 /* convert Posterior Commissure from parent to current coords */
12710
12711 LOAD_FVEC3( pcie ,
12712 anat->warp_parent->markers->xyz[IMARK_PCIE][0] ,
12713 anat->warp_parent->markers->xyz[IMARK_PCIE][1] ,
12714 anat->warp_parent->markers->xyz[IMARK_PCIE][2] ) ;
12715
12716 pcie = THD_3dmm_to_dicomm( anat->warp_parent , pcie ) ;
12717 pcie = AFNI_transform_vector( anat->warp_parent , pcie , anat ) ;
12718
12719 /* compute distances between points in various directions */
12720
12721 dist_ant = -mant.xyz[1] ;
12722 dist_med = pcie.xyz[1] ;
12723 dist_pos = mpos.xyz[1] - pcie.xyz[1] ;
12724
12725 dist_sup = msup.xyz[2] ;
12726 dist_inf = -minf.xyz[2] ;
12727
12728 dist_lef = mlef.xyz[0] ;
12729 dist_rig = -mrig.xyz[0] ;
12730
12731 /* check anterior distance and report it */
12732
12733 if( dist_ant/ATLAS_FRONT_TO_AC < MIN_ALLOWED_DEVIATION ||
12734 dist_ant/ATLAS_FRONT_TO_AC > MAX_ALLOWED_DEVIATION )
12735 ADD_ERROR("The following measurement is outside the allowed range!\n");
12736
12737 sprintf(msg,"Front to Anterior commissure: %5.1f mm (Atlas:%5.1f)\n",
12738 dist_ant,ATLAS_FRONT_TO_AC) ;
12739 ADD_REPORT(msg) ;
12740
12741 /* medial */
12742
12743 #if 0
12744 if( dist_med/ATLAS_AC_TO_PC < MIN_ALLOWED_DEVIATION ||
12745 dist_med/ATLAS_AC_TO_PC > MAX_ALLOWED_DEVIATION )
12746 ADD_ERROR("The following measurement is outside the allowed range!\n");
12747 #endif
12748 sprintf(msg,"Intercommissural distance: %5.1f mm (Atlas:%5.1f)\n",
12749 dist_med,ATLAS_AC_TO_PC) ;
12750 ADD_REPORT(msg) ;
12751
12752
12753 /* posterior */
12754
12755 if( dist_pos/ATLAS_PC_TO_BACK < MIN_ALLOWED_DEVIATION ||
12756 dist_pos/ATLAS_PC_TO_BACK > MAX_ALLOWED_DEVIATION )
12757 ADD_ERROR("The following measurement is outside the allowed range!\n");
12758
12759 sprintf(msg,"Posterior commissure to back: %5.1f mm (Atlas:%5.1f)\n",
12760 dist_pos,ATLAS_PC_TO_BACK) ;
12761 ADD_REPORT(msg) ;
12762
12763 /* inferior */
12764
12765 if( dist_inf/ATLAS_BOT_TO_AC < MIN_ALLOWED_DEVIATION ||
12766 dist_inf/ATLAS_BOT_TO_AC > MAX_ALLOWED_DEVIATION )
12767 ADD_ERROR("The following measurement is outside the allowed range!\n");
12768
12769 sprintf(msg,"Bottom to Anterior commissure:%5.1f mm (Atlas:%5.1f)\n",
12770 dist_inf,ATLAS_BOT_TO_AC) ;
12771 ADD_REPORT(msg) ;
12772
12773 /* superior */
12774
12775 if( dist_sup/ATLAS_AC_TO_TOP < MIN_ALLOWED_DEVIATION ||
12776 dist_sup/ATLAS_AC_TO_TOP > MAX_ALLOWED_DEVIATION )
12777 ADD_ERROR("The following measurement is outside the allowed range!\n");
12778
12779 sprintf(msg,"Anterior commissure to top: %5.1f mm (Atlas:%5.1f)\n",
12780 dist_sup,ATLAS_AC_TO_TOP) ;
12781 ADD_REPORT(msg) ;
12782
12783 /* left */
12784
12785 if( dist_lef/ATLAS_AC_TO_LAT < MIN_ALLOWED_DEVIATION ||
12786 dist_lef/ATLAS_AC_TO_LAT > MAX_ALLOWED_DEVIATION )
12787 ADD_ERROR("The following measurement is outside the allowed range!\n");
12788
12789 sprintf(msg,"Anterior commissure to left: %5.1f mm (Atlas:%5.1f)\n",
12790 dist_lef,ATLAS_AC_TO_LAT) ;
12791 ADD_REPORT(msg) ;
12792
12793 /* right */
12794
12795 if( dist_rig/ATLAS_AC_TO_LAT < MIN_ALLOWED_DEVIATION ||
12796 dist_rig/ATLAS_AC_TO_LAT > MAX_ALLOWED_DEVIATION )
12797 ADD_ERROR("The following measurement is outside the allowed range!\n");
12798
12799 sprintf(msg,"Anterior commissure to right: %5.1f mm (Atlas:%5.1f)\n",
12800 dist_rig,ATLAS_AC_TO_LAT) ;
12801 ADD_REPORT(msg) ;
12802 }
12803 break ; /* end of Boundings marker case */
12804
12805 /*--- AC-PC alignment markers set ---*/
12806
12807 case MARKSET_ALIGN:{
12808 THD_fvec3 acsup , acpos , pcinf , msag1 , msag2 ,
12809 alpha1,alpha2,alpha,beta,gamma,rr1,rr2,rr , dif ;
12810 float size , slim ;
12811
12812 /* extract the marker vectors, put in Dicom coords */
12813
12814 acsup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACSE) ) ;
12815 acpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACPM) ) ;
12816 pcinf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_PCIE) ) ;
12817 msag1 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA1) ) ;
12818 msag2 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA2) ) ;
12819
12820 /*-- check the points for proper distances between each other --*/
12821
12822 rr = SUB_FVEC3(acsup,acpos) ; size = SIZE_FVEC3(rr) ;
12823 if( size > 4.0 )
12824 ADD_ERROR("The two AC points are more than 4 mm apart.\n") ;
12825
12826 slim = MIN_ALLOWED_DEVIATION * ATLAS_AC_TO_PC ;
12827 rr = SUB_FVEC3(acsup,pcinf) ; size = SIZE_FVEC3(rr) ;
12828 if( size <= slim ){
12829 sprintf(msg, "The AC & PC points are separated by %5.2f mm\n"
12830 "which is closer than the minimum %5.2f mm!\n" ,
12831 size,slim ) ;
12832 ADD_ERROR(msg) ;
12833 }
12834
12835 rr = SUB_FVEC3(acsup,msag1) ; size = SIZE_FVEC3(rr) ;
12836 if( size < 20.0 )
12837 ADD_ERROR("The AC and 1st mid-sag points are closer than 20 mm.\n");
12838
12839 rr = SUB_FVEC3(acsup,msag2) ; size = SIZE_FVEC3(rr) ;
12840 if( size < 20.0 )
12841 ADD_ERROR("The AC and 2nd mid-sag points are closer than 20 mm.\n");
12842
12843 rr = SUB_FVEC3(msag1,msag2) ; size = SIZE_FVEC3(rr) ;
12844 if( size < 20.0 )
12845 ADD_ERROR("The two mid-sag points are closer than 20 mm.\n");
12846
12847 rr = SUB_FVEC3(pcinf,msag1) ; size = SIZE_FVEC3(rr) ;
12848 if( size < 20.0 )
12849 ADD_ERROR("The PC and 1st mid-sag points are closer than 20 mm.\n");
12850
12851 rr = SUB_FVEC3(pcinf,msag2) ; size = SIZE_FVEC3(rr) ;
12852 if( size < 20.0 )
12853 ADD_ERROR("The PC and 2nd mid-sag points are closer than 20 mm.\n");
12854
12855 /*--- compute the new y direction (beta) ---*/
12856
12857 beta = SUB_FVEC3(pcinf,acsup) ; beta = NORMALIZE_FVEC3(beta) ;
12858
12859 /*--- compute the new x direction (alpha) ---*/
12860
12861 rr = SUB_FVEC3(msag1,acsup) ;
12862 alpha1 = CROSS_FVEC3(beta,rr) ; alpha1 = NORMALIZE_FVEC3(alpha1) ;
12863
12864 rr = SUB_FVEC3(msag2,acsup) ;
12865 alpha2 = CROSS_FVEC3(beta,rr) ; alpha2 = NORMALIZE_FVEC3(alpha2) ;
12866
12867 size = DOT_FVEC3(alpha1,alpha2) ; /* angle < 2 degrees ? */
12868 if( size < 0.99939 ) /* (size = cos(angle) */
12869 ADD_ERROR("The AC + PC + mid-sag pts do not form a good plane.\n");
12870
12871 size = acos((double)size) * 180/3.14159265 ; /* report angle */
12872 sprintf(msg,
12873 "Angular deviation between AC+PC+mid-sag pts: %6.2f degrees\n",size);
12874 ADD_REPORT(msg) ;
12875
12876 alpha = SCLADD_FVEC3(0.5,alpha1,0.5,alpha2) ;
12877 alpha = NORMALIZE_FVEC3(alpha) ;
12878
12879 /*--- compute the new z direction (gamma) ---*/
12880
12881 gamma = CROSS_FVEC3(alpha,beta) ; gamma = NORMALIZE_FVEC3(gamma) ;
12882
12883 /*--- now, consider the ray from the AC posterior margin (acpos)
12884 in the gamma direction, and the ray from the AC superior
12885 edge (acsup) in the beta direction. Nominally, these rays
12886 should intersect. Find their points of closest approach
12887 (rr1,rr2). The average of these is the Talairach center
12888 of coordinates (rr). ------------------------------------*/
12889
12890 dif = SUB_FVEC3(acsup,acpos) ;
12891 size = DOT_FVEC3(dif,gamma) ;
12892 rr1 = SCLADD_FVEC3(1.0,acpos,size,gamma) ;
12893
12894 size = DOT_FVEC3(dif,beta) ;
12895 rr2 = SCLADD_FVEC3(1.0,acsup,-size,beta) ;
12896
12897 dif = SUB_FVEC3(rr1,rr2) ; size = SIZE_FVEC3(dif) ;
12898 if( size > 2.0 )
12899 ADD_ERROR("AC Talairach origin mismatch more than 2 mm!\n") ;
12900
12901 sprintf(msg,
12902 "Mismatch between AC-PC line and Talairach origin: %6.2f mm\n",size);
12903 ADD_REPORT(msg) ;
12904
12905 rr = SCLADD_FVEC3(0.5,rr1,0.5,rr2) ;
12906
12907 /*-- Use the trace of the rotation matrix to find
12908 the total rotation angle [suggested by M. Klosek] --*/
12909
12910 { float theta, costheta ;
12911
12912 costheta = 0.5 * sqrt(1.0+alpha.xyz[0]+beta.xyz[1]+gamma.xyz[2]) ;
12913 theta = 2.0 * acos(costheta) * 180/3.14159265 ;
12914 sprintf(msg,
12915 "Total rotation to align AC-PC and mid-sag: %6.2f degrees\n",theta) ;
12916 ADD_REPORT(msg) ;
12917 }
12918
12919 #ifdef AFNI_DEBUG
12920 STATUS("AC-PC alignment markers computation:") ;
12921 DUMP_FVEC3(" acsup ",acsup ) ;
12922 DUMP_FVEC3(" acpos ",acpos ) ;
12923 DUMP_FVEC3(" pcinf ",pcinf ) ;
12924 DUMP_FVEC3(" msag1 ",msag1 ) ;
12925 DUMP_FVEC3(" msag2 ",msag2 ) ;
12926 DUMP_FVEC3(" beta ",beta ) ;
12927 DUMP_FVEC3(" alpha1",alpha1) ;
12928 DUMP_FVEC3(" alpha2",alpha2) ;
12929 DUMP_FVEC3(" alpha ",alpha ) ;
12930 DUMP_FVEC3(" gamma ",gamma ) ;
12931 DUMP_FVEC3(" rr1 ",rr1 ) ;
12932 DUMP_FVEC3(" rr2 ",rr2 ) ;
12933 DUMP_FVEC3(" rr ",rr ) ;
12934 printf("\n") ;
12935 #endif
12936
12937 } /* end of AC-PC alignment case */
12938 break ;
12939
12940 } /* end of switch on marker set type */
12941
12942 if( num_error > 0 || (make_report && num_report > 0) ){
12943 (void) MCW_popup_message( im3d->vwid->marks->frame ,
12944 error_list ,
12945 MCW_USER_KILL | MCW_TIMER_KILL ) ;
12946 }
12947
12948 myXtFree( error_list ) ;
12949
12950 if( num_error > 0 && ! ELIDE_quality ) RETURN(False) ;
12951 RETURN(True) ;
12952 }
12953
12954 /*------------------------------------------------------------------
12955 Create a new dataset that has the geometry specified as the
12956 warp from the parent. The actual data will not be filled in yet.
12957 --------------------------------------------------------------------*/
12958
12959 THD_3dim_dataset * AFNI_init_warp( Three_D_View *im3d ,
12960 THD_3dim_dataset *parent_dset ,
12961 THD_warp *warp_init , float resam_vox )
12962 {
12963 THD_3dim_dataset *adam_dset ; /* the farthest ancestor */
12964 THD_warp *warp_total ; /* the warp from that ancestor */
12965 THD_fvec3 xnew_bot , xnew_top ;
12966
12967 THD_3dim_dataset *new_dset ;
12968 THD_datablock *new_dblk , *adam_dblk , *parent_dblk ;
12969 THD_dataxes *new_daxes , *adam_daxes , *parent_daxes ;
12970 THD_diskptr *new_dkptr , *adam_dkptr , *parent_dkptr ;
12971 THD_marker_set *new_markers ;
12972
12973 int new_nx , new_ny , new_nz , ii ;
12974 THD_ivec3 ivbot , ivtop ;
12975
12976 ENTRY("AFNI_init_warp") ;
12977
12978 /*----- It is possible that this warp is one in a succession
12979 of warps. In that case, the actual transformation is
12980 to be done directly from the "adam" dataset, rather
12981 than in succession from the parent. The reason for
12982 this is to avoid repeated interpolation. Thus, we
12983 first scan backward along the line of descent, and
12984 create the total warp from "adam" to the new dataset -----*/
12985
12986 adam_dset = parent_dset ;
12987 warp_total = myXtNew( THD_warp ) ; /* copy initial warp into final warp */
12988 *warp_total = *warp_init ;
12989
12990 while( adam_dset->warp != NULL ){
12991 AFNI_concatenate_warp( warp_total , adam_dset->warp ) ;
12992 adam_dset = adam_dset->warp_parent ;
12993 }
12994
12995 if( warp_total->type < FIRST_WARP_TYPE ||
12996 warp_total->type > LAST_WARP_TYPE ) RETURN(NULL) ; /* error! */
12997
12998 #ifdef AFNI_DEBUG
12999 { char str[256] ;
13000 sprintf(str,"parent = %s ; adam = %s",
13001 parent_dset->self_name , adam_dset->self_name ) ;
13002 STATUS(str) ;
13003
13004 STATUS("warp_total dump:") ;
13005 if( warp_total->type == WARP_AFFINE_TYPE ){
13006 DUMP_LMAP(warp_total->rig_bod.warp) ;
13007 } else {
13008 DUMP_T12_WARP(warp_total->tal_12) ;
13009 }
13010 }
13011 #endif
13012
13013 adam_dblk = adam_dset->dblk ;
13014 adam_daxes = adam_dset->daxes ;
13015 adam_dkptr = adam_dblk->diskptr ;
13016
13017 parent_dblk = parent_dset->dblk ;
13018 parent_daxes = parent_dset->daxes ;
13019 parent_dkptr = parent_dblk->diskptr ;
13020
13021 /*----- We now determine the bounding box of the new dataset.
13022 This depends on the warp type:
13023 affine warps --> use transformed bounding box of adam;
13024 Talairach warp --> use Talairach standard geometry;
13025 The results are in the vectors xnew_bot and xnew_top. -----*/
13026
13027 switch( warp_total->type ){
13028
13029 default: RETURN(NULL) ; /* something bad happened */
13030
13031 /*--- 12 case Talairach mapping
13032 (sizes chosen to include borders of Atlas figures) ---*/
13033
13034 case WARP_TALAIRACH_12_TYPE:{
13035 int use_tlrc_big=MCW_val_bbox( im3d->vwid->marks->tlrc_big_bbox ) ;
13036 float xtop=ATLAS_BBOX_LAT ,
13037 ybot=ATLAS_BBOX_ANT ,
13038 ytop=ATLAS_BBOX_POS ,
13039 zbot=(use_tlrc_big) ? ATLAS_BBOX_INF_NEW : ATLAS_BBOX_INF ,
13040 ztop=ATLAS_BBOX_SUP ;
13041
13042 #define GETVAL(vvv,nnn) do{ char *eee = getenv(nnn) ; \
13043 if( eee != NULL ){ \
13044 float val=strtod(eee,NULL); if(val>0.0) vvv = val; \
13045 } } while(0)
13046
13047 GETVAL(xtop,"AFNI_TLRC_BBOX_LAT") ; /* 16 Apr 2002: get new bounding box */
13048 GETVAL(ybot,"AFNI_TLRC_BBOX_ANT") ; /* from environment variables, maybe */
13049 GETVAL(ytop,"AFNI_TLRC_BBOX_POS") ;
13050 GETVAL(zbot,"AFNI_TLRC_BBOX_INF") ;
13051 GETVAL(ztop,"AFNI_TLRC_BBOX_SUP") ;
13052
13053 #undef GETVAL
13054
13055 LOAD_FVEC3( xnew_bot ,-xtop,-ybot,-zbot ) ;
13056 LOAD_FVEC3( xnew_top , xtop, ytop, ztop ) ;
13057 }
13058 break ;
13059
13060 /*--- linear warp ---*/
13061
13062 case WARP_AFFINE_TYPE:{
13063 THD_fvec3 corner , base , xnew , aff_bot , aff_top ;
13064 THD_mat33 to_new ;
13065
13066 to_new = warp_total->rig_bod.warp.mfor ;
13067 base = warp_total->rig_bod.warp.bvec ;
13068
13069 /*--- transform each of the 8 corner locations in
13070 the adam dataset to the aligned system, and
13071 determine the outer limits of the new datablock ---*/
13072
13073 LOAD_FVEC3(corner,adam_daxes->xxmin,
13074 adam_daxes->yymin,adam_daxes->zzmin) ; /* 1 */
13075 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13076 xnew_bot = xnew_top = MATVEC_SUB(to_new,corner,base) ;
13077
13078 LOAD_FVEC3(corner,adam_daxes->xxmax,
13079 adam_daxes->yymin,adam_daxes->zzmin) ; /* 2 */
13080 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13081 xnew = MATVEC_SUB(to_new,corner,base) ;
13082 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13083 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13084
13085 LOAD_FVEC3(corner,adam_daxes->xxmin,
13086 adam_daxes->yymax,adam_daxes->zzmin) ; /* 3 */
13087 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13088 xnew = MATVEC_SUB(to_new,corner,base) ;
13089 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13090 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13091
13092 LOAD_FVEC3(corner,adam_daxes->xxmax,
13093 adam_daxes->yymax,adam_daxes->zzmin) ; /* 4 */
13094 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13095 xnew = MATVEC_SUB(to_new,corner,base) ;
13096 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13097 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13098
13099 LOAD_FVEC3(corner,adam_daxes->xxmin,
13100 adam_daxes->yymin,adam_daxes->zzmax) ; /* 5 */
13101 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13102 xnew = MATVEC_SUB(to_new,corner,base) ;
13103 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13104 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13105
13106 LOAD_FVEC3(corner,adam_daxes->xxmax,
13107 adam_daxes->yymin,adam_daxes->zzmax) ; /* 6 */
13108 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13109 xnew = MATVEC_SUB(to_new,corner,base) ;
13110 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13111 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13112
13113 LOAD_FVEC3(corner,adam_daxes->xxmin,
13114 adam_daxes->yymax,adam_daxes->zzmax) ; /* 7 */
13115 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13116 xnew = MATVEC_SUB(to_new,corner,base) ;
13117 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13118 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13119
13120 LOAD_FVEC3(corner,adam_daxes->xxmax,
13121 adam_daxes->yymax,adam_daxes->zzmax) ; /* 8 */
13122 corner = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13123 xnew = MATVEC_SUB(to_new,corner,base) ;
13124 xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13125 xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13126
13127 /* If the warp had any data in it about
13128 the region to map to, apply that data. */
13129
13130 aff_bot = warp_total->rig_bod.warp.bot ;
13131 aff_top = warp_total->rig_bod.warp.top ;
13132
13133 if( (aff_bot.xyz[0] < aff_top.xyz[0]) &&
13134 (aff_bot.xyz[1] < aff_top.xyz[1]) &&
13135 (aff_bot.xyz[2] < aff_top.xyz[2]) ){
13136
13137 /* 3/25/95: use the bot & top INSTEAD of the corners
13138 (old version used in ADDITION to corners) */
13139
13140 #if 0
13141 xnew_bot = MIN_FVEC3(xnew_bot,aff_bot) ;
13142 xnew_top = MAX_FVEC3(xnew_top,aff_top) ;
13143 #else
13144 xnew_bot = aff_bot ;
13145 xnew_top = aff_top ;
13146 #endif
13147 }
13148
13149 } /* end of affine warp case */
13150 break ;
13151
13152 } /* end of xnew_bot & xnew_top computed from warp */
13153
13154 /* force bounds to be integral multiples of resampling size */
13155
13156 #define FLOOR(qq) ( ((qq) >= 0) ? ((int)(qq)) : (-1+(int)(qq)) )
13157
13158 ivbot.ijk[0] = FLOOR( 0.01 + xnew_bot.xyz[0] / resam_vox ) ;
13159 ivbot.ijk[1] = FLOOR( 0.01 + xnew_bot.xyz[1] / resam_vox ) ;
13160 ivbot.ijk[2] = FLOOR( 0.01 + xnew_bot.xyz[2] / resam_vox ) ;
13161
13162 ivtop.ijk[0] = FLOOR( 0.99 + xnew_top.xyz[0] / resam_vox ) ;
13163 ivtop.ijk[1] = FLOOR( 0.99 + xnew_top.xyz[1] / resam_vox ) ;
13164 ivtop.ijk[2] = FLOOR( 0.99 + xnew_top.xyz[2] / resam_vox ) ;
13165
13166 #undef FLOOR
13167
13168 xnew_bot.xyz[0] = ivbot.ijk[0] * resam_vox ;
13169 xnew_bot.xyz[1] = ivbot.ijk[1] * resam_vox ;
13170 xnew_bot.xyz[2] = ivbot.ijk[2] * resam_vox ;
13171
13172 xnew_top.xyz[0] = ivtop.ijk[0] * resam_vox ;
13173 xnew_top.xyz[1] = ivtop.ijk[1] * resam_vox ;
13174 xnew_top.xyz[2] = ivtop.ijk[2] * resam_vox ;
13175
13176 /* compute dimensions of the new brick */
13177
13178 new_nx = (xnew_top.xyz[0] - xnew_bot.xyz[0])/resam_vox + 1.5 ;
13179 new_ny = (xnew_top.xyz[1] - xnew_bot.xyz[1])/resam_vox + 1.5 ;
13180 new_nz = (xnew_top.xyz[2] - xnew_bot.xyz[2])/resam_vox + 1.5 ;
13181
13182 xnew_top.xyz[0] = xnew_bot.xyz[0] + (new_nx-1) * resam_vox ;
13183 xnew_top.xyz[1] = xnew_bot.xyz[1] + (new_ny-1) * resam_vox ;
13184 xnew_top.xyz[2] = xnew_bot.xyz[2] + (new_nz-1) * resam_vox ;
13185
13186 #ifdef AFNI_DEBUG
13187 DUMP_FVEC3(" -- xnew_bot",xnew_bot) ;
13188 DUMP_FVEC3(" -- xnew_top",xnew_top) ;
13189 printf(" ==> new nx=%d ny=%d nz=%d\n",new_nx,new_ny,new_nz) ;
13190 #endif
13191
13192 /*----- make a new 3D dataset !!! -----*/
13193
13194 new_dset = myXtNew( THD_3dim_dataset ) ;
13195 new_dblk = new_dset->dblk = myXtNew( THD_datablock ) ;
13196 new_daxes = new_dset->daxes = myXtNew( THD_dataxes ) ;
13197 new_markers = new_dset->markers = NULL ; /* later, dude */
13198 new_dkptr = new_dblk->diskptr = myXtNew( THD_diskptr ) ;
13199 new_dset->Label_Dtable = NULL; /* ZSS Feb 26 2010 */
13200
13201 INIT_KILL(new_dset->kl) ; INIT_KILL(new_dblk->kl) ;
13202
13203 ADDTO_KILL(new_dset->kl,new_dblk) ;
13204 ADDTO_KILL(new_dset->kl,new_daxes) ;
13205 ADDTO_KILL(new_dset->kl,new_dkptr) ;
13206
13207 ADDTO_KILL(new_dset->kl,warp_total) ;
13208
13209 new_dset->wod_daxes = NULL ;
13210 new_dset->wod_flag = True ;
13211
13212 new_dset->taxis = NULL ;
13213 new_dset->tagset = NULL ; /* Oct 1998 */
13214
13215 INIT_STAT_AUX( new_dset , MAX_STAT_AUX , parent_dset->stat_aux ) ;
13216
13217 #define PARENT_MYSELF /* 14 Dec 1999 */
13218
13219 new_dset->idcode = MCW_new_idcode() ;
13220 new_dset->warp_parent_idcode = adam_dset->idcode ;
13221 #ifndef PARENT_MYSELF
13222 ZERO_IDCODE(new_dset->anat_parent_idcode) ;
13223 new_dset->anat_parent = NULL ;
13224 #else
13225 new_dset->anat_parent_idcode = new_dset->idcode ; /* 14 Dec 1999 */
13226 new_dset->anat_parent = new_dset ; /* 14 Dec 1999 */
13227 #endif
13228
13229 EMPTY_STRING(new_dset->anat_parent_name) ;
13230
13231 /*------------ initialize dataset fields -------------*/
13232 /**** July 1997: be careful about adam and parent ****/
13233
13234 STATUS("init new_dset") ;
13235
13236 new_dset->type = parent_dset->type; /* data types */
13237 new_dset->func_type = parent_dset->func_type;
13238 new_dset->view_type = WARPED_VIEW(parent_dset->view_type) ; /* view type */
13239
13240 new_dset->warp = warp_total ; /* warp info */
13241 new_dset->vox_warp = NULL ;
13242 new_dset->self_warp = NULL ; /* 26 Aug 2002 */
13243
13244 new_dset->warp_parent = adam_dset ;
13245 MCW_strncpy( new_dset->warp_parent_name ,
13246 adam_dset->self_name , THD_MAX_NAME ) ;
13247
13248 MCW_strncpy( new_dset->label1 , parent_dset->label1 , THD_MAX_LABEL ) ;
13249 MCW_strncpy( new_dset->label2 , parent_dset->label2 , THD_MAX_LABEL ) ;
13250
13251 MCW_strncpy( new_dset->self_name ,
13252 parent_dset->self_name , THD_MAX_NAME ) ; /* make up */
13253 ii = strlen( new_dset->self_name ) ; /* a new name */
13254 new_dset->self_name[ii++] = '+' ;
13255 MCW_strncpy( &(new_dset->self_name[ii]) ,
13256 VIEW_typestr[new_dset->view_type] ,
13257 THD_MAX_NAME-ii ) ;
13258
13259 new_dset->death_mark = 0 ;
13260 new_dset->tcat_list = 0 ;
13261 new_dset->tcat_num = 0 ;
13262 new_dset->tcat_len = NULL ;
13263
13264 /*--- initialize disk pointer fields ---*/
13265
13266 STATUS("init new_dkptr") ;
13267
13268 new_dkptr->type = DISKPTR_TYPE ;
13269 new_dkptr->rank = 3 ;
13270 new_dkptr->nvals = adam_dkptr->nvals ;
13271 new_dkptr->dimsizes[0] = new_nx ;
13272 new_dkptr->dimsizes[1] = new_ny ;
13273 new_dkptr->dimsizes[2] = new_nz ;
13274 new_dkptr->storage_mode = STORAGE_UNDEFINED ;
13275 new_dkptr->byte_order = THD_get_write_order() ; /* 25 April 1998 */
13276
13277 THD_init_diskptr_names( new_dkptr ,
13278 parent_dkptr->directory_name, NULL, parent_dkptr->prefix ,
13279 new_dset->view_type , True ) ;
13280
13281 /*--- initialize datablock fields ---*/
13282
13283 STATUS("init new_dblk") ;
13284
13285 new_dblk->type = DATABLOCK_TYPE ;
13286 new_dblk->nvals = adam_dblk->nvals ;
13287 new_dblk->malloc_type = DATABLOCK_MEM_UNDEFINED ;
13288 new_dblk->natr = new_dblk->natr_alloc = 0 ;
13289 new_dblk->atr = NULL ;
13290 new_dblk->parent = (XtPointer) new_dset ;
13291
13292 new_dblk->brick_fac = NULL ; /* THD_init_datablock_brick */
13293 new_dblk->brick_bytes = NULL ; /* will initialize these arrays */
13294 new_dblk->brick = NULL ;
13295 THD_init_datablock_brick( new_dblk , -1 , adam_dblk ) ;
13296
13297 new_dblk->master_nvals = 0 ; /* 11 Jan 1999 */
13298 new_dblk->master_ival = NULL ;
13299 new_dblk->master_bytes = NULL ;
13300
13301 new_dblk->vedim = NULL ; /* 05 Sep 2006 */
13302
13303 DSET_unlock(new_dset) ;
13304
13305 THD_null_datablock_auxdata( new_dblk ) ;
13306 THD_copy_datablock_auxdata( adam_dblk , new_dblk ) ; /* 30 Nov 1997 */
13307
13308 /*--- initialize data axes fields ---*/
13309
13310 STATUS("init new_daxes") ;
13311
13312 new_daxes->type = DATAXES_TYPE ;
13313 new_daxes->nxx = new_nx ;
13314 new_daxes->nyy = new_ny ;
13315 new_daxes->nzz = new_nz ;
13316 new_daxes->xxorg = xnew_bot.xyz[0] ;
13317 new_daxes->yyorg = xnew_bot.xyz[1] ;
13318 new_daxes->zzorg = xnew_bot.xyz[2] ;
13319 new_daxes->xxdel = resam_vox ; /* cubical voxels */
13320 new_daxes->yydel = resam_vox ;
13321 new_daxes->zzdel = resam_vox ;
13322 new_daxes->xxmin = xnew_bot.xyz[0] ; /* save new bounding box */
13323 new_daxes->yymin = xnew_bot.xyz[1] ;
13324 new_daxes->zzmin = xnew_bot.xyz[2] ;
13325 new_daxes->xxmax = xnew_top.xyz[0] ;
13326 new_daxes->yymax = xnew_top.xyz[1] ;
13327 new_daxes->zzmax = xnew_top.xyz[2] ;
13328 new_daxes->parent = (XtPointer) new_dset ;
13329
13330 new_daxes->xxorient = ORI_R2L_TYPE ; /* Dicom standard axes! */
13331 new_daxes->yyorient = ORI_A2P_TYPE ;
13332 new_daxes->zzorient = ORI_I2S_TYPE ;
13333 LOAD_DIAG_MAT(new_daxes->to_dicomm,1,1,1) ; /* identity matrix */
13334
13335 if( !ISVALID_MAT44(new_daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
13336 THD_daxes_to_mat44( new_daxes ) ;
13337
13338 /*--- if view type is appropriate, set new markers ---*/
13339
13340 switch( new_dset->view_type ){
13341
13342 default:
13343 STATUS("no new_markers") ;
13344 break ; /* no markers */
13345
13346 /*--- AC-PC aligned ==> can do the BOUNDING set of markers ---*/
13347
13348 case VIEW_ACPCALIGNED_TYPE:
13349 if( new_dset->type == HEAD_ANAT_TYPE ){
13350 int ii , jj ;
13351
13352 STATUS("init new_markers") ;
13353
13354 new_markers = new_dset->markers = myXtNew( THD_marker_set ) ;
13355 ADDTO_KILL(new_dset->kl,new_markers) ;
13356
13357 new_markers->numdef = NMARK_BOUNDING ;
13358 new_markers->numset = 0 ; /* null data out */
13359 for( ii=0 ; ii < MARKS_MAXNUM ; ii++ ){
13360
13361 new_markers->xyz[ii][0] =
13362 new_markers->xyz[ii][1] =
13363 new_markers->xyz[ii][2] = -99999999.99 ;
13364
13365 for( jj=0 ; jj < MARKS_MAXLAB ; jj++ )
13366 new_markers->label[ii][jj] = '\0' ;
13367
13368 for( jj=0 ; jj < MARKS_MAXHELP ; jj++ )
13369 new_markers->help[ii][jj] = '\0' ;
13370
13371 new_markers->valid[ii] = False ;
13372 new_markers->ovcolor[ii] = -1 ; /* not used yet */
13373 }
13374
13375 for( ii=0 ; ii < NMARK_BOUNDING ; ii++ ){ /* copy strings in */
13376 MCW_strncpy( &(new_markers->label[ii][0]) ,
13377 THD_bounding_label[ii] , MARKS_MAXLAB ) ;
13378 MCW_strncpy( &(new_markers->help[ii][0]) ,
13379 THD_bounding_help[ii] , MARKS_MAXHELP ) ;
13380 }
13381
13382 for( ii=0 ; ii < MARKS_MAXFLAG ; ii++ ) /* copy flags in */
13383 new_markers->aflags[ii] = THD_bounding_aflags[ii] ;
13384 new_markers->type = new_markers->aflags[0] ;
13385 }
13386 break ; /* end of BOUNDING markers */
13387
13388 } /* end of marker creation */
13389
13390 /*----- copy statistics, if any -----*/
13391
13392 new_dset->stats = NULL ;
13393 AFNI_copy_statistics( adam_dset , new_dset ) ;
13394
13395 #ifdef ALLOW_DATASET_VLIST
13396 new_dset->pts = NULL ;
13397 #endif
13398
13399 /*----- dataset ready for warping -----*/
13400
13401 PARENTIZE(new_dset,adam_dset->parent) ;
13402
13403 STATUS("initialization complete") ;
13404
13405 RETURN( new_dset ) ;
13406 }
13407
13408 /*-----------------------------------------------------------------*/
13409
13410 void AFNI_copy_statistics( THD_3dim_dataset *dsold , THD_3dim_dataset *dsnew )
13411 {
13412 int ibr , nvold , nvnew ;
13413 THD_statistics *stold , *stnew ;
13414
13415 ENTRY("AFNI_copy_statistics") ;
13416
13417 if( !ISVALID_3DIM_DATASET(dsold) || !ISVALID_3DIM_DATASET(dsnew) ) EXRETURN ;
13418
13419 nvold = dsold->dblk->nvals ;
13420 nvnew = dsnew->dblk->nvals ;
13421 stold = dsold->stats ;
13422 stnew = dsnew->stats ;
13423 if( !ISVALID_STATISTIC(stold) ) EXRETURN ;
13424
13425 if( stnew == NULL ){
13426 dsnew->stats = stnew = myXtNew( THD_statistics ) ;
13427 stnew->type = STATISTICS_TYPE ;
13428 stnew->nbstat = nvnew ;
13429 stnew->bstat = (THD_brick_stats *)
13430 XtMalloc( sizeof(THD_brick_stats) * nvnew ) ;
13431 ADDTO_KILL(dsnew->kl,stnew) ;
13432 stnew->parent = (XtPointer) dsnew ;
13433 } else {
13434 stnew->nbstat = nvnew ;
13435 stnew->bstat = (THD_brick_stats *)
13436 XtRealloc( (char *) stnew->bstat ,
13437 sizeof(THD_brick_stats) * nvnew ) ;
13438 }
13439
13440 for( ibr=0 ; ibr < nvnew ; ibr++ ){
13441 if( ibr < nvold )
13442 stnew->bstat[ibr] = stold->bstat[ibr] ;
13443 else
13444 INVALIDATE_BSTAT(stnew->bstat[ibr]) ;
13445 }
13446
13447 EXRETURN ;
13448 }
13449
13450 /*-----------------------------------------------------------------*/
13451
13452 void AFNI_set_cursor( int cursor_code )
13453 {
13454 Three_D_View *im3d ;
13455 int id ;
13456
13457 ENTRY("AFNI_set_cursor") ;
13458
13459 for( id=0 ; id < MAX_CONTROLLERS ; id++ ){
13460 im3d = GLOBAL_library.controllers[id] ;
13461 if( IM3D_OPEN(im3d) ){
13462 switch( cursor_code ){
13463
13464 default:
13465 case AFNI_DEFAULT_CURSOR:
13466 NORMAL_cursorize( im3d->vwid->top_shell ) ;
13467
13468 if( ISQ_REALZ(im3d->s123) )
13469 NORMAL_cursorize( im3d->s123->wtop ) ;
13470
13471 if( ISQ_REALZ(im3d->s231) )
13472 NORMAL_cursorize( im3d->s231->wtop ) ;
13473
13474 if( ISQ_REALZ(im3d->s312) )
13475 NORMAL_cursorize( im3d->s312->wtop ) ;
13476
13477 if( GRA_REALZ(im3d->g123) )
13478 NORMAL_cursorize( im3d->g123->fdw_graph ) ;
13479
13480 if( GRA_REALZ(im3d->g231) )
13481 NORMAL_cursorize( im3d->g231->fdw_graph ) ;
13482
13483 if( GRA_REALZ(im3d->g312) )
13484 NORMAL_cursorize( im3d->g312->fdw_graph ) ;
13485
13486 if( im3d->vinfo->inverted_pause ){
13487 im3d->vinfo->inverted_pause = False ;
13488 if( im3d->vwid->picture != NULL ){
13489 if( !GLOBAL_argopt.keep_logo ) PICTURE_OFF(im3d) ;
13490 } else
13491 MCW_invert_widget( im3d->vwid->top_form ) ;
13492 }
13493
13494 break ;
13495
13496 case AFNI_WAITING_CURSOR:
13497 WATCH_cursorize( im3d->vwid->top_shell ) ;
13498
13499 if( ISQ_REALZ(im3d->s123) )
13500 WATCH_cursorize( im3d->s123->wtop ) ;
13501
13502 if( ISQ_REALZ(im3d->s231) )
13503 WATCH_cursorize( im3d->s231->wtop ) ;
13504
13505 if( ISQ_REALZ(im3d->s312) )
13506 WATCH_cursorize( im3d->s312->wtop ) ;
13507
13508 if( GRA_REALZ(im3d->g123) )
13509 WATCH_cursorize( im3d->g123->fdw_graph ) ;
13510
13511 if( GRA_REALZ(im3d->g231) )
13512 WATCH_cursorize( im3d->g231->fdw_graph ) ;
13513
13514 if( GRA_REALZ(im3d->g312) )
13515 WATCH_cursorize( im3d->g312->fdw_graph ) ;
13516
13517 if( ! im3d->vinfo->inverted_pause ){
13518 im3d->vinfo->inverted_pause = True ;
13519 if( im3d->vwid->picture != NULL )
13520 PICTURE_ON(im3d) ;
13521 else
13522 MCW_invert_widget( im3d->vwid->top_form ) ;
13523 }
13524
13525 break ;
13526 }
13527
13528 XSync( XtDisplay(im3d->vwid->top_shell) , False ) ;
13529 XmUpdateDisplay( im3d->vwid->top_shell ) ;
13530 }
13531 }
13532
13533 EXRETURN ;
13534 }
13535
13536 /****************************************************************/
13537 /***** June 1995: routine to load constants from X defaults *****/
13538 /***** June 1999: also allow loading from Unix environment *****/
13539
13540 #if 0
13541 # define NAME2INT(nnn,iii,bot,top) \
13542 { xdef = XGetDefault(display,"AFNI",nnn) ; \
13543 if( xdef != NULL ){ \
13544 ival = strtol( xdef , &cpt , 10 ) ; \
13545 if( *cpt == '\0' && ival >= (bot) && ival <= (top) ) (iii) = ival ; } }
13546
13547 # define NAME2FLOAT(nnn,fff,bot,top) \
13548 { xdef = XGetDefault(display,"AFNI",nnn) ; \
13549 if( xdef != NULL ){ \
13550 fval = strtod( xdef , &cpt ) ; \
13551 if( *cpt == '\0' && fval >= (bot) && fval <= (top) ) (fff) = fval ; } }
13552
13553 # define NAME2STRING(nnn,sss) \
13554 { xdef = XGetDefault(display,"AFNI",nnn) ; \
13555 if( xdef != NULL ) sss = XtNewString(xdef) ; }
13556 #else
13557 # define NAME2INT(nnn,iii,bot,top) \
13558 { xdef = RWC_getname(display,nnn) ; \
13559 if( xdef != NULL ){ \
13560 ival = strtol( xdef , &cpt , 10 ) ; \
13561 if( *cpt == '\0' && ival >= (bot) && ival <= (top) ) (iii) = ival ; } }
13562
13563 # define NAME2FLOAT(nnn,fff,bot,top) \
13564 { xdef = RWC_getname(display,nnn) ; \
13565 if( xdef != NULL ){ \
13566 fval = strtod( xdef , &cpt ) ; \
13567 if( *cpt == '\0' && fval >= (bot) && fval <= (top) ) (fff) = fval ; } }
13568
13569 # define NAME2STRING(nnn,sss) \
13570 { xdef = RWC_getname(display,nnn) ; \
13571 if( xdef != NULL ) sss = XtNewString(xdef) ; }
13572 #endif
13573
13574 #define BAD -999
13575
13576 void AFNI_load_defaults( Widget w )
13577 {
13578 char *xdef ;
13579 Display *display ;
13580 int ival , ii,jj ;
13581 float fval ;
13582 char *cpt ;
13583 char buf[64] ;
13584 float pthr[NPANE_MAX+1] ;
13585 int pov[NPANE_MAX+1] ;
13586
13587 ENTRY("AFNI_load_defaults") ;
13588
13589 if( w == NULL ){
13590 ERROR_message("\n** AFNI_load_defaults: NULL input widget") ;
13591 EXRETURN ;
13592 }
13593
13594 display = XtDisplay( w ) ;
13595
13596 /** initialize overlay color arrays from defaults **/
13597
13598 for( ii=0 ; ii < DEFAULT_NCOLOVR ; ii++ ){
13599 INIT_colovr[ii] = XtNewString(INIT_def_colovr[ii]) ;
13600 INIT_labovr[ii] = XtNewString(INIT_def_labovr[ii]) ;
13601 }
13602 for( ; ii < MAX_NCOLOVR ; ii++ )
13603 INIT_colovr[ii] = INIT_labovr[ii] = NULL ;
13604
13605 /** initialize display and overlay colors **/
13606
13607 NAME2INT("ncolors",INIT_ngray,3,MAX_COLORS) ;
13608
13609 NAME2INT("ncolovr",INIT_ncolovr,2,MAX_NCOLOVR) ;
13610
13611 NAME2FLOAT("gamma",INIT_gamma,0.1,9.9) ;
13612
13613 for( ii=0 ; ii < INIT_ncolovr ; ii++ ){
13614 sprintf( buf , "ovdef%02d" , ii+1 ) ;
13615 NAME2STRING(buf,INIT_colovr[ii] ) ;
13616
13617 sprintf( buf , "ovlab%02d" , ii+1 ) ;
13618 NAME2STRING(buf,INIT_labovr[ii] ) ;
13619 }
13620
13621 NAME2INT("ovcrosshair" , INIT_crosshair_color,0,INIT_ncolovr) ;
13622 NAME2INT("ovmarksprimary" , INIT_marks1_color ,0,INIT_ncolovr) ;
13623 NAME2INT("ovmarkssecondary" , INIT_marks2_color ,0,INIT_ncolovr) ;
13624 NAME2INT("markssize" , INIT_marks_size ,2,MAXOVSIZE ) ;
13625 NAME2INT("marksgap" , INIT_marks_gap ,0,MAXOVSIZE-1 ) ;
13626 NAME2INT("crosshairgap" , INIT_crosshair_gap ,0,MAXOVSIZE ) ;
13627 NAME2INT("bigscroll" , INIT_bigscroll ,1,MAXOVSIZE ) ;
13628
13629 NAME2INT("graph_boxes_color" ,INIT_GR_boxes_color ,BLUEST_COLOR,INIT_ncolovr) ;
13630 NAME2INT("graph_backg_color" ,INIT_GR_backg_color ,BLUEST_COLOR,INIT_ncolovr) ;
13631 NAME2INT("graph_grid_color" ,INIT_GR_grid_color ,BLUEST_COLOR,INIT_ncolovr) ;
13632 NAME2INT("graph_text_color" ,INIT_GR_text_color ,BLUEST_COLOR,INIT_ncolovr) ;
13633 NAME2INT("graph_data_color" ,INIT_GR_data_color ,BLUEST_COLOR,INIT_ncolovr) ;
13634 NAME2INT("graph_ideal_color" ,INIT_GR_ideal_color ,BLUEST_COLOR,INIT_ncolovr) ;
13635 NAME2INT("graph_ort_color" ,INIT_GR_ort_color ,BLUEST_COLOR,INIT_ncolovr) ;
13636 NAME2INT("graph_ignore_color",INIT_GR_ignore_color,BLUEST_COLOR,INIT_ncolovr) ;
13637 NAME2INT("graph_dplot_color" ,INIT_GR_dplot_color ,BLUEST_COLOR,INIT_ncolovr) ;
13638
13639 NAME2INT("graph_boxes_thick" ,INIT_GR_boxes_thick ,0,1) ;
13640 NAME2INT("graph_grid_thick" ,INIT_GR_grid_thick ,0,1) ;
13641 NAME2INT("graph_data_thick" ,INIT_GR_data_thick ,0,1) ;
13642 NAME2INT("graph_ideal_thick" ,INIT_GR_ideal_thick ,0,1) ;
13643 NAME2INT("graph_ort_thick" ,INIT_GR_ort_thick ,0,1) ;
13644 NAME2INT("graph_dplot_thick" ,INIT_GR_dplot_thick ,0,1) ;
13645
13646 NAME2INT("graph_ggap" ,INIT_GR_ggap ,0,19); /* 27 May 1999 */
13647 NAME2INT("fim_polort" ,INIT_fim_polort ,0,MAX_POLORT); /* 30 May 1999 */
13648 NAME2INT("graph_matrix" ,INIT_GR_gmat ,1,MAT_MAX); /* 10 Feb 2003 */
13649 NAME2INT("graph_gthick" ,INIT_GR_gthick ,2,10); /* 06 Oct 2004 */
13650
13651 /** initialize other junk **/
13652
13653 cpt = NULL ;
13654 NAME2STRING( "tlrc_big" , cpt ) ;
13655 if( cpt != NULL ){
13656 INIT_tlrc_big = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13657 XtFree(cpt) ;
13658 }
13659
13660 cpt = NULL ;
13661 NAME2STRING( "montage_periodic" , cpt ) ;
13662 if( cpt != NULL ){
13663 INIT_montage_periodic = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13664 XtFree(cpt) ;
13665 }
13666
13667 NAME2INT("fim_ignore",INIT_ignore,0,999) ;
13668
13669 cpt = NULL ;
13670 NAME2STRING( "purge" , cpt ) ;
13671 if( cpt != NULL ){
13672 INIT_purge = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13673 myXtFree(cpt) ;
13674 }
13675
13676 NAME2FLOAT("resam_vox",INIT_resam_vox,0.1,4.0) ;
13677 INIT_resam_vox = 0.1 * ( (int)(10*INIT_resam_vox) ) ;
13678
13679 cpt = NULL ;
13680 NAME2STRING( "resam_anat" , cpt ) ;
13681 if( cpt != NULL ){
13682 for( ii=FIRST_RESAM_TYPE ; ii <= LAST_RESAM_TYPE ; ii++ )
13683 if( strcmp(cpt,RESAM_shortstr[ii]) == 0 ) break ;
13684
13685 if( ii <= LAST_RESAM_TYPE ) INIT_resam_anat = ii ;
13686 myXtFree(cpt) ;
13687 }
13688
13689 cpt = NULL ;
13690 NAME2STRING( "resam_func" , cpt ) ;
13691 if( cpt != NULL ){
13692 for( ii=FIRST_RESAM_TYPE ; ii <= LAST_RESAM_TYPE ; ii++ )
13693 if( strcmp(cpt,RESAM_shortstr[ii]) == 0 ) break ;
13694
13695 if( ii <= LAST_RESAM_TYPE ) INIT_resam_func = ii ;
13696 (char*)myXtFree(cpt) ;
13697 }
13698
13699 cpt = NULL ;
13700 NAME2STRING( "resam_thr" , cpt ) ;
13701 if( cpt != NULL ){
13702 for( ii=FIRST_RESAM_TYPE ; ii <= LAST_RESAM_TYPE ; ii++ )
13703 if( strcmp(cpt,RESAM_shortstr[ii]) == 0 ) break ;
13704
13705 if( ii <= LAST_RESAM_TYPE ) INIT_resam_thr = ii ;
13706 myXtFree(cpt) ;
13707 }
13708
13709 /** initialize pbar panes **/
13710
13711 cpt = NULL ;
13712 NAME2STRING( "pbar_posfunc" , cpt ) ;
13713 if( cpt != NULL ){
13714 INIT_posfunc = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13715 myXtFree(cpt) ;
13716 }
13717
13718 cpt = NULL ;
13719 NAME2STRING( "pbar_hide" , cpt ) ;
13720 if( cpt != NULL ){
13721 INIT_panes_hide = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13722 myXtFree(cpt) ;
13723 }
13724
13725 NAME2INT("pbar_pos_pane_count" , INIT_panes_pos , NPANE_MIN , NPANE_MAX ) ;
13726 NAME2INT("pbar_sgn_pane_count" , INIT_panes_sgn , NPANE_MIN , NPANE_MAX ) ;
13727
13728 /* start with positive panes */
13729
13730 for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
13731 fval = 1.0 / ii ;
13732 pthr[0] = 1.0 ;
13733 pthr[ii] = 0.0 ;
13734 for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-jj) ;
13735 for( jj=0 ; jj < ii ; jj++ ) pov[jj] = (jj % INIT_ncolovr) + 1 ;
13736
13737 for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_pos[ii][jj] = pthr[jj] ;
13738 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = pov[jj] ;
13739 }
13740
13741 for( ii=NPANE_MIN ; ii <= NPANE_MAX ; ii++ ){
13742
13743 for( jj=0 ; jj <= ii ; jj++ ){
13744 sprintf( buf , "pbar_pos_pane%02d_thr%02d" , ii,jj ) ;
13745 pthr[jj] = BAD ;
13746 NAME2FLOAT(buf,pthr[jj],0.0,1.0) ;
13747 }
13748
13749 for( jj=0 ; jj < ii ; jj++ ){
13750 sprintf( buf , "pbar_pos_pane%02d_ov%02d" , ii,jj ) ;
13751 pov[jj] = BAD ;
13752 NAME2INT(buf,pov[jj],0,INIT_ncolovr) ;
13753 }
13754
13755 /* check pthr for OK-ness; if not good, skip to next pane count (ii) */
13756
13757 if( pthr[0] != 1.0 || pthr[jj] != 0.0 ) continue ;
13758 for( jj=1 ; jj <= ii ; jj++ )
13759 if( pthr[jj] == BAD || pthr[jj] >= pthr[jj-1] ) break ;
13760 if( jj <= ii ) continue ;
13761
13762 /* check pov for OK-ness */
13763
13764 for( jj=0 ; jj < ii ; jj++ ) if( pov[jj] == BAD ) break ;
13765 if( jj < ii ) continue ;
13766
13767 /* get to here --> load pthr and pov into arrays */
13768
13769 for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_pos[ii][jj] = pthr[jj] ;
13770 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = pov[jj] ;
13771
13772 }
13773
13774 /** initialize signed pbar panes **/
13775
13776 for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
13777 fval = 1.0 / ii ;
13778 pthr[0] = 1.0 ;
13779 pthr[ii] = -1.0 ;
13780 for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-2*jj) ;
13781 for( jj=0 ; jj < ii ; jj++ ) pov[jj] = (jj % INIT_ncolovr) + 1 ;
13782
13783 for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_sgn[ii][jj] = pthr[jj] ;
13784 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = pov[jj] ;
13785 }
13786
13787 for( ii=NPANE_MIN ; ii <= NPANE_MAX ; ii++ ){
13788
13789 for( jj=0 ; jj <= ii ; jj++ ){
13790 sprintf( buf , "pbar_sgn_pane%02d_thr%02d" , ii,jj ) ;
13791 pthr[jj] = BAD ;
13792 NAME2FLOAT(buf,pthr[jj],-1.0,1.0) ; /* 14 Apr 1999: 0.0 changed to -1.0! */
13793 }
13794
13795 for( jj=0 ; jj < ii ; jj++ ){
13796 sprintf( buf , "pbar_sgn_pane%02d_ov%02d" , ii,jj ) ;
13797 pov[jj] = BAD ;
13798 NAME2INT(buf,pov[jj],0,INIT_ncolovr) ;
13799 }
13800
13801 /* check pthr for OK-ness; if not good, skip to next pane count (ii) */
13802
13803 if( pthr[0] != 1.0 || pthr[jj] != -1.0 ) continue ;
13804 for( jj=1 ; jj <= ii ; jj++ )
13805 if( pthr[jj] == BAD || pthr[jj] >= pthr[jj-1] ) break ;
13806 if( jj <= ii ) continue ;
13807
13808 /* check pov for OK-ness */
13809
13810 for( jj=0 ; jj < ii ; jj++ ) if( pov[jj] == BAD ) break ;
13811 if( jj < ii ) continue ;
13812
13813 /* get to here --> load pthr and pov into arrays */
13814
13815 for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_sgn[ii][jj] = pthr[jj] ;
13816 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = pov[jj] ;
13817
13818 }
13819
13820 /* 10 Jun 2002: put RGB cyclic maps in place */
13821
13822 #if defined(RGBCYC_COUNT) && RGBCYC_COUNT <= NPANE_MAX
13823 ii = RGBCYC_COUNT ;
13824 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = RGBCYC_FIRST+jj+1 ;
13825 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = RGBCYC_FIRST+jj+1 ;
13826 #endif
13827
13828 EXRETURN ;
13829 }
13830
13831 /********************************************************************/
13832 #ifdef USE_SONNETS
13833
13834 void AFNI_popup_sonnet( Widget w , int ii ) /* 12 Dec 2001 */
13835 {
13836 char buf[3192] ; int jj=MCW_USER_KILL ;
13837
13838 if( w == NULL ) return ;
13839
13840 if( ii < 1 || ii > NUM_SONNETS ){
13841 ii = (lrand48()%NUM_SONNETS) + 1 ;
13842 jj |= MCW_TIMER_KILL ;
13843 }
13844
13845 sprintf( buf , " * %d *\n" , ii ) ;
13846 strcat( buf , sonnets[ii-1] ) ;
13847 (void) MCW_popup_message( w , buf , jj ) ;
13848 return ;
13849 }
13850
13851 /*..................................................................*/
13852
13853 void AFNI_sonnet_CB( Widget w , XtPointer client_data , XtPointer call_data )
13854 {
13855 Three_D_View *im3d = (Three_D_View *) client_data ;
13856 MCW_choose_cbs *cbs ;
13857
13858 if( NO_frivolities || !IM3D_OPEN(im3d) ) return ;
13859
13860 if( w == im3d->vwid->prog->hidden_sonnet_pb ){ /* start the process */
13861
13862 MCW_choose_integer( im3d->vwid->picture ,
13863 "Sonnet " ,
13864 1 , NUM_SONNETS , sonnet_index+1 ,
13865 AFNI_sonnet_CB , (XtPointer) im3d ) ;
13866 return ;
13867 }
13868
13869 /** if get to here, finish the process **/
13870
13871 cbs = (MCW_choose_cbs *) call_data ;
13872 if( cbs->reason != mcwCR_integer ){ /* error */
13873 BEEPIT ; return ;
13874 }
13875
13876 AFNI_popup_sonnet( im3d->vwid->picture , cbs->ival ) ;
13877 return ;
13878 }
13879 #endif /* USE_SONNETS */
13880 /********************************************************************/
13881
13882 /*----------------------------------------------------------------------*/
13883 /*! Put a function on the list of n-dimensional transformations
13884 - modified 03 Nov 1996 from just 0D transforms
13885 - modified 22 Apr 1997 to add int flags to each function
13886 - modified 31 Jan 2002 to add slice_proj for nd=-1
13887 - modified 21 Jul 2003 to add func_init
13888 ------------------------------------------------------------------------*/
13889
13890 void AFNI_register_nD_function( int nd, char *name,
13891 generic_func *func, int flags )
13892 {
13893 MCW_function_list *rlist ;
13894 int num ;
13895
13896 if( name == NULL || strlen(name) == 0 || func == NULL ) return ;
13897
13898 switch( nd ){
13899 default: return ;
13900
13901 case 0: rlist = &(GLOBAL_library.registered_0D) ; break ;
13902 case 1: rlist = &(GLOBAL_library.registered_1D) ; break ;
13903 case 2: rlist = &(GLOBAL_library.registered_2D) ; break ;
13904
13905 case -1: rlist= &(GLOBAL_library.registered_slice_proj) ; break ;
13906 }
13907
13908 num = rlist->num ;
13909
13910 if( num == 0 ){
13911 rlist->flags=NULL; rlist->labels=NULL; rlist->funcs=NULL;
13912 rlist->func_data=NULL; rlist->func_code=NULL; rlist->func_init=NULL;
13913 }
13914
13915 rlist->flags = (int *) XtRealloc( (char *)rlist->flags, sizeof(int)*(num+1) ) ;
13916
13917 rlist->labels = (char **) XtRealloc( (char *)rlist->labels ,
13918 sizeof(char *)*(num+1) ) ;
13919
13920 rlist->funcs = (generic_func **) XtRealloc( (char *)rlist->funcs ,
13921 sizeof(generic_func *)*(num+1) ) ;
13922
13923 rlist->func_data = (void **) XtRealloc( (char *)rlist->func_data ,
13924 sizeof(void *)*(num+1) ) ;
13925
13926 rlist->func_code = (int *) XtRealloc( (char *)rlist->func_code, sizeof(int)*(num+1) ) ;
13927
13928 rlist->func_init = (generic_func **) XtRealloc( (char *)rlist->func_init ,
13929 sizeof(generic_func *)*(num+1) ) ;
13930
13931 rlist->flags[num] = flags ;
13932 rlist->labels[num] = XtNewString(name) ;
13933 rlist->funcs[num] = func ;
13934 rlist->func_data[num] = NULL ;
13935 rlist->func_code[num] = nd ;
13936 rlist->func_init[num] = NULL ;
13937
13938 rlist->num = num+1 ;
13939 return ;
13940 }
13941
13942 /*-------------------------------------------------------------------------*/
13943 /*! Add init function to last registered function. This function
13944 should be called just after AFNI_register_nD_function(). [21 Jul 2003] */
13945
13946 void AFNI_register_nD_func_init( int nd , generic_func *fin )
13947 {
13948 MCW_function_list *rlist ;
13949 int num ;
13950
13951 if( fin == NULL ) return ;
13952
13953 switch( nd ){
13954 default: return ;
13955
13956 case 0: rlist = &(GLOBAL_library.registered_0D) ; break ;
13957 case 1: rlist = &(GLOBAL_library.registered_1D) ; break ;
13958 case 2: rlist = &(GLOBAL_library.registered_2D) ; break ;
13959
13960 case -1: rlist= &(GLOBAL_library.registered_slice_proj) ; break ;
13961 }
13962
13963 num = rlist->num ; if( num <= 0 ) return ;
13964 rlist->func_init[num-1] = fin ;
13965 return ;
13966 }
13967
13968 #if 0
13969 /*---------- 18 May 2000: save/get dataset index for function calls -------*/
13970
13971 static int dset_ijk=-1 , dset_tin=-1 ;
13972
13973 void AFNI_store_dset_index( int ijk , int tin )
13974 {
13975 dset_ijk = ijk ; dset_tin = tin ; return ;
13976 }
13977
13978 int AFNI_needs_dset_ijk(void){ return dset_ijk ; }
13979 int AFNI_needs_dset_tin(void){ return dset_tin ; }
13980 #endif
13981
13982 /*-----------------------------------------------------------------------*/
13983 /*! Add a timeseries to the global library.
13984 *//*---------------------------------------------------------------------*/
13985
13986 void AFNI_add_timeseries( MRI_IMAGE *tsim )
13987 {
13988 ENTRY("AFNI_add_timeseries") ;
13989
13990 if( tsim != NULL ){
13991 POPDOWN_timeseries_chooser ;
13992 ADDTO_IMARR(GLOBAL_library.timeseries,tsim) ;
13993 }
13994 EXRETURN ;
13995 }
13996
13997 /*-----------------------------------------------------------------------*/
13998 /* N.B.: The input time series structure is destroyed!
13999 Never refer to it again, even to free() it!
14000 *//*---------------------------------------------------------------------*/
14001
14002 void AFNI_replace_timeseries( MRI_IMAGE *tsim )
14003 {
14004 int its ; MRI_IMAGE *qsim ;
14005
14006 ENTRY("AFNI_replace_timeseries") ;
14007
14008 if( tsim == NULL ) EXRETURN ;
14009
14010 its = AFNI_tsname_in_library( tsim->name ) ;
14011 if( its < 0 ){
14012 AFNI_add_timeseries(tsim); EXRETURN;
14013 }
14014
14015 POPDOWN_timeseries_chooser ;
14016 qsim = IMARR_SUBIMAGE(GLOBAL_library.timeseries,its) ;
14017 mri_move_guts( qsim , tsim ) ;
14018 mri_free(tsim) ;
14019 EXRETURN ;
14020 }
14021
14022 /*------------------------------------------------------------------------*/
14023 /*** New fix for scale size problem
14024 - via a timeout, to avoid excessive flashing of the scale widget
14025 - 03 Jun 2019 [RWC in Lucca]
14026 - 05 Jun 2019 - modified to a fixed timeout every so often
14027 ***/
14028 /*------------------------------------------------------------------------*/
14029
14030 void AFNI_fix_scale_size_direct( Three_D_View *im3d )
14031 {
14032 int iqqq = AFNI_controller_index(im3d) ;
14033 int sel_height,sel_actual ; XtPointer sel_ptr=NULL ;
14034 Dimension sel_aaa ;
14035
14036 if( iqqq < 0 || ! IM3D_OPEN(im3d) ) return ; /* not valid */
14037
14038 if( AFNI_yesenv("AFNI_DONT_FIX_SCALE_SIZE") ) return ; /* obey orders */
14039
14040 /* check if height is correct */
14041
14042 XtVaGetValues( im3d->vwid->func->thr_scale ,
14043 XmNuserData , &sel_ptr , NULL ) ;
14044 sel_height = PTOI(sel_ptr) ; /* stored in a pointer, convert to int */
14045
14046 XtVaGetValues( im3d->vwid->func->thr_scale ,
14047 XmNheight , &sel_aaa , NULL ) ;
14048 sel_actual = (int)sel_aaa ;
14049
14050 /**** INFO_message("actual = %d nominal = %d",sel_actual,sel_height) ; ****/
14051
14052 if( sel_actual == sel_height ) return ; /* it's OK */
14053
14054 /* do the work */
14055
14056 XtUnmanageChild(im3d->vwid->func->thr_scale) ; AFNI_sleep(1) ;
14057
14058 XtVaSetValues( im3d->vwid->func->thr_scale ,
14059 XmNheight , sel_height , NULL ) ;
14060
14061 XtManageChild(im3d->vwid->func->thr_scale) ;
14062
14063 return ;
14064 }
14065
14066 #undef FIX_TIME
14067 #define FIX_TIME 1357 /* ms between calls */
14068
14069 void AFNI_fix_scale_size_timer_CB( XtPointer client_data , XtIntervalId *id )
14070 {
14071 Three_D_View *im3d ;
14072 int iqqq ;
14073 int sel_height,sel_actual ; XtPointer sel_ptr=NULL ;
14074
14075 for( iqqq=0 ; iqqq < MAX_CONTROLLERS ; iqqq++ ){
14076 AFNI_fix_scale_size_direct(GLOBAL_library.controllers[iqqq]) ;
14077 }
14078
14079 (void) XtAppAddTimeOut( MAIN_app , FIX_TIME ,
14080 AFNI_fix_scale_size_timer_CB , NULL ) ;
14081
14082 return ;
14083 }
14084
14085 /* 04/06/2020 discoraj */
14086 int AFNI_find_session( char *dname ) {
14087
14088 int ic ;
14089 /* find session name in list of sessions (sloppy compare) */
14090 for( ic=0 ; ic < GLOBAL_library.sslist->num_sess ; ic++ )
14091 if( strstr(GLOBAL_library.sslist->ssar[ic]->sessname,dname) != NULL )
14092 break;
14093
14094 if( ic == GLOBAL_library.sslist->num_sess ) RETURN(-1) ;
14095
14096 return ic ;
14097 }
14098