1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 /*! \file
8    This file contains the definition of the structs, macros, etc. for AFNI datasets.
9 */
10 
11 #ifndef _MCW_3DDATASET_
12 #define _MCW_3DDATASET_
13 
14 /**                                  yyyy-mm-dd  **/
15 #define DSET_VERSION_LATEST         "1996-07-10"
16 #define DSET_VERSION_COMPARE(v1,v2) strcmp(v1,v2)
17 
18 /** #include <dirent.h> **/
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <time.h>
27 #include <sys/types.h>
28 
29 #include "replaceXt.h"  /* 09 Nov 2018 */
30 
31 /*----------------------------------------------------------------------------*/
32 
33 #include "mcw_malloc.h"
34 
35 #include "killer.h"
36 #include "vecmat.h"
37 #include "machdep.h"
38 #include "mrilib.h"
39 #include "tagset.h"
40 
41 #include "thd_compress.h"
42 
43 #include "nifti2_io.h"   /* 06 Dec 2005 */
44 
45 /* cast int to pointer and vice-versa without warning messages */
46 
47 #ifndef SOLARIS_OLD
48 #include <stdint.h>
49 #endif
50 #undef  ITOP
51 #define ITOP(qw) ((void *)(intptr_t)(qw))
52 #undef  PTOI
53 #define PTOI(qw) ((int)(intptr_t)(qw))
54 
55 struct THD_3dim_dataset ;  /* incomplete definition */
56 
57 #include "niml.h"          /* NIML */
58 #include "afni_suma.h"     /* SUrface MApper */
59 
60 #ifdef  __cplusplus
61 extern "C" {
62 #endif
63 
64 /*! Macro to check if string ss ends in string suf. */
65 
66 #define STRING_HAS_SUFFIX(ss,suf)              \
67   ((ss != NULL) && (suf != NULL) &&            \
68    (strlen(ss) >= strlen(suf))   &&            \
69    (strcmp(ss+strlen(ss)-strlen(suf),suf) == 0))
70 
71 #define STRING_HAS_SUFFIX_CASE(ss,suf)         \
72   ((ss != NULL) && (suf != NULL) &&            \
73    (strlen(ss) >= strlen(suf))   &&            \
74    (strcasecmp(ss+strlen(ss)-strlen(suf),suf) == 0))
75 
76 #define PREFIX_IS_NIFTI(ss) ( STRING_HAS_SUFFIX(ss,".nii")    ||  \
77                               STRING_HAS_SUFFIX(ss,".nii.gz") ||  \
78                               STRING_HAS_SUFFIX(ss,".hdr")      )
79 
80 /***************************** dimensions ***************************/
81 
82 /*! Max length of a dataset label. */
83 
84 #define THD_MAX_LABEL     38
85 
86 /*! Max length of a dataset sub-brick label. */
87 
88 #define THD_MAX_SBLABEL     64     /* added 11/03/2011 drg */
89 
90 /*! Max length of a dataset prefix. [increased to 999 by RWCox 17 Oct 2016] */
91 
92 #define THD_MAX_PREFIX     (999+1)  /* must be more than THD_MAX_LABEL
93                                     (  ZSS Jan 07 need room for path specified
94                                        with prefix on command line    ) */
95 
96 /*! Max length of a "name" of a file, or stuff like that. */
97 
98 #define THD_MAX_NAME      (4096+THD_MAX_PREFIX)     /* (ZSS Jan 07)*/
99 
100 /*! Max length of a dataset view code (+orig, etc). */
101 
102 #define THD_MAX_VIEWCODE   (4+1)
103 
104 /*! Max length of a dataset suffix (BRIK, etc). */
105 
106 #define THD_MAX_SUFFIX     (4+1)
107 
108 /*! Max length of a dataset filecode (prefix+view). */
109 
110 #define THD_MAX_FILECODE   (THD_MAX_PREFIX+THD_MAX_VIEWCODE)
111 
112 /*! Default label for a dataset.
113 
114     Labels aren't really used anymore, since the stupid users didn't like them
115 */
116 #define THD_DEFAULT_LABEL "Viggo!"
117 
118 /*! Max num datasets per session. */
119 
120 #define THD_MAX_SESSION_SIZE  8192
121 
122 /*! Max number of directories. */
123 
124 #define THD_MAX_NUM_SESSION   199
125 
126 #define THD_MAX_CHOICES THD_MAX_SESSION_SIZE
127 
128 #define THD_MAX_MARKSET       5
129 
130 #define FAIL    -1
131 #define SUCCESS  1
132 
133 /*! General "type code" for invalid data.
134 
135     Various things are labeled with non-negative type codes (e.g., statistics types).
136     Negative type codes indicate something is not valid.
137 */
138 
139 #define ILLEGAL_TYPE -666
140 
141 /* define the max length of a string input to realpath() */
142 
143 #undef  RPMAX
144 #define RPMAX 4096
145 #if defined(PATH_MAX) && PATH_MAX > RPMAX
146 # undef  RPMAX
147 # define RPMAX PATH_MAX
148 #endif
149 #if defined(MAXPATHLEN) && MAXPATHLEN > RPMAX
150 # undef  RPMAX
151 # define RPMAX MAXPATHLEN
152 #endif
153 
154 #undef  isnumeric
155 #define isnumeric(c) (isdigit(c) || (c) == '-' || (c) == '+' || (c) == '.')
156 
157 /* define what angular difference constitues a "real" difference
158  * (allow for truncation artifacts)          22 May 2015 [rickr] */
159 #undef OBLIQ_ANGLE_THRESH
160 #define OBLIQ_ANGLE_THRESH 0.01
161 
162 /***************  generic function with no return value  **********************/
163 
164 /*! Generic function type returning void. */
165 
166 typedef void generic_func() ;
167 
168 /*! Generic function type returning float. */
169 
170 typedef float float_func() ;
171 
172 /*! Stores a list of "registered" functions (e.g., "Transforms") */
173 
174 typedef struct {
175    int num ;                     /*!< number of functions */
176    int * flags ;                 /*!< flags[i] = bitmask flag for function #i */
177    char ** labels ;              /*!< labels[i] = string name for function #i */
178    generic_func ** funcs ;       /*!< funcs[i] = function #i */
179 
180    void ** func_data ;           /*!< 30 Jan 2000 */
181    int *   func_code ;
182 
183    generic_func ** func_init ;   /*!< 21 Jul 2003 */
184 } MCW_function_list ;
185 
186 /*! MCW_function_list possible bitmask flag */
187 #define RETURNS_STRING    1
188 
189 /*! MCW_function_list possible bitmask flag */
190 #define NEEDS_DSET_INDEX  2
191 
192 /*! MCW_function_list possible bitmask flag */
193 #define PROCESS_MRI_IMAGE 4
194 
195 /*! MCW_function_list possible bitmask flag */
196 #define SET_DPLOT_OVERLAY 8
197 
198 /*! MCW_function_list possible func_code */
199 #define FUNC_0D   0
200 /*! MCW_function_list possible func_code */
201 #define FUNC_1D   1
202 /*! MCW_function_list possible func_code */
203 #define FUNC_2D   2
204 /*! MCW_function_list possible func_code */
205 #define FUNC_3D   3
206 
207 /*! MCW_function_list possible func_code */
208 #define FUNC_FIM  71
209 
210 /******************************** macros ******************************/
211 
212 /*! First part of TWO_TWO macro. */
213 
214 #define TWO_ONE(x,y) x ## y
215 
216 /*! Combine two interpreted tokens into one using TWO_TWO. */
217 
218 #define TWO_TWO(x,y) TWO_ONE(x,y)
219 
220 /*! Zero out a variable */
221 
222 #undef  ZZME
223 #define ZZME(x) memset(&(x),0,sizeof(x))
224 
225 /*! Copy n units of the given type "type * ptr", into a structure "str",
226      starting at byte offset "off";
227    N.B.: str is the structure itself, not a pointer to it
228          off is most easily computed with RwcOffsetOf       */
229 
230 #define COPY_INTO_STRUCT(str,off,type,ptr,n) \
231    AAmemcpy( (char *)(&(str))+(off), (char *)(ptr), (n)*sizeof(type) )
232 
233 /*! Copy n units of the given type "type * ptr", from a structure "str",
234      starting at byte offset "off";
235    N.B.: str is the structure itself, not a pointer to it
236          off is most easily computed with RwcOffsetOf       */
237 
238 #define COPY_FROM_STRUCT(str,off,type,ptr,n) \
239    AAmemcpy( (char *)(ptr), (char *)(&(str))+(off), (n)*sizeof(type) )
240 
241 /*! Safe version of strncpy, which always leaves a NUL at the end.
242 
243     The standard stupid strncpy(dest,src,n) might not leave a NUL character
244     at the end if the src string is too long.  This criminal behavior is
245     reformed by this macro.
246 */
247 
248 #ifndef MCW_strncpy
249 #define MCW_strncpy(dest,src,n) \
250    ( (void) strncpy( (dest) , (src) , (n)-1 ) , (dest)[(n)-1] = '\0' )
251 #endif
252 
253 /*********************** dynamic array of RwcPointers **********************/
254 
255 #define IC_DSET 44301
256 #define IC_FLIM 55402
257 
258 /*! Dynamically extendable array of RwcPointer. */
259 
260 typedef struct {
261       int num ;         /*!< Number currently in use */
262       int nall ;        /*!< Number currently allocated */
263       RwcPointer *ar ;   /*!< Array of pointers: [0..num-1] are valid */
264       int *ic ;         /*!< added 26 Mar 2001 */
265 } RwcPointer_array ;
266 
267 /*! Increment for extending RwcPointer_array allocation */
268 
269 #define INC_XTARR 8
270 
271 /*! Initialize dynamic RwcPointer array named "name".
272 
273     You must declare "RwcPointer_array *name;".
274 */
275 #define INIT_XTARR(name)               \
276    ( (name) = RwcNew(RwcPointer_array) , \
277      (name)->num = (name)->nall = 0 ,  \
278      (name)->ar  = NULL ,              \
279      (name)->ic  = NULL   )
280 
281 /*! Add a pointer to a dynamic RwcPointer array. */
282 
283 #define ADDTO_XTARR(name,bblk)                                 \
284  do{ if( (name)->num == (name)->nall ){                        \
285       (name)->nall += INC_XTARR + (name)->nall/8 ;             \
286       (name)->ar    = (RwcPointer *)                            \
287                        RwcRealloc( (char *) (name)->ar ,        \
288                           sizeof(RwcPointer) * (name)->nall ) ; \
289       (name)->ic    = (int *) RwcRealloc( (char *) (name)->ic , \
290                           sizeof(int) * (name)->nall ) ;       \
291      }                                                         \
292      (name)->ar[(name)->num] = (RwcPointer)(bblk) ;             \
293      (name)->ic[(name)->num] = 0 ;                             \
294      ((name)->num)++ ;                                         \
295    } while(0)
296 
297 /*! Number of good entries in a dynamic RwcPointer array. */
298 
299 #define XTARR_NUM(name)  ((name)->num)
300 
301 /*! i-th entry in a dynamic RwcPointer array. */
302 
303 #define XTARR_XT(name,i) ((name)->ar[i])
304 
305 #define XTARR_IC(name,i) ((name)->ic[i])
306 
307 /*! Free a dynamic RwcPointer array.
308     But not what the pointers point to - that is a completely separate matter.
309 */
310 
311 #define FREE_XTARR(name)      \
312    if( (name) != NULL ){      \
313      myRwcFree( (name)->ar ) ; \
314      myRwcFree( (name)->ic ) ; \
315      myRwcFree( (name) ) ;     \
316      (name) = NULL ; }
317 
318 /*! Duplicate definition for FREE_XTARR */
319 #define DESTROY_XTARR  FREE_XTARR
320 
321 /*************************  help utilities    *************************/
322 
323 /* Flags & macros for shpinx string formatting */
324 typedef enum { TFORM_NOT_SET, NO_FORMAT, TXT, SPX , ASPX, WEB } TFORM;
325 
326 #define CHECK_HELP(opt,fun) {\
327    if( strcmp(argv[iarg],"-h_spx") == 0 ){   \
328          fun(SPX, 2); RETURN(0);}   \
329    else if( strcmp(argv[iarg],"-h_raw") == 0 ){ \
330          fun(NO_FORMAT,2); RETURN(0);} \
331    else if( strcmp(argv[iarg],"-help") == 0 ){  \
332          fun(TXT,1); RETURN(0);} \
333    else if( strcmp(argv[iarg],"-h") == 0 ){  \
334          fun(TXT,0); RETURN(0);} \
335 }
336 
337 #define  sphinx_printf(targ, ...) (sphinx_offprintf( targ, 0, NULL, __VA_ARGS__))
338 #define sphinx_fprintf(targ, fout, ...) \
339                                   (sphinx_offprintf( targ, 0, fout, __VA_ARGS__))
340 #include "suma_string_manip.h"
341 
342 /************************* string array stuff *************************/
343 
344 /*! Dynamic array of character strings. */
345 
346 typedef struct {
347       int num ;      /*!< Number of strings currently stored */
348       int nall ;     /*!< Number of strings space is set aside for */
349       char ** ar ;   /*!< Array of pointers to strings */
350       KILL_list kl ; /*!< For semi-automatic memory cleanup */
351 } THD_string_array ;
352 
353 /*! Return pointer to qq-th string in dynamic string array ss. */
354 
355 #define SARR_STRING(ss,qq) ((ss)->ar[(qq)])
356 
357 /*! Return number of strings stored in dynamic string array ss. */
358 
359 #define SARR_NUM(ss)       ((ss)->num)
360 
361 #define INC_SARR 64
362 
363 /*! Initialize an empty dynamic string array named "name".
364 
365     You must declare "THD_string_array *name;".
366 */
367 
368 #define INIT_SARR(name)                 \
369    ( (name) = RwcNew(THD_string_array) , \
370      (name)->num = (name)->nall = 0 ,   \
371      (name)->ar  = NULL ,               \
372      INIT_KILL((name)->kl) )
373 
374 /*! Add string str to dynamic string array "name". */
375 
376 #define ADDTO_SARR(name,str)                                          \
377  do{ if( (name)->num == (name)->nall ){                               \
378       (name)->nall += INC_SARR + (name)->nall/8 ;                     \
379       (name)->ar    = (char **) RwcRealloc( (char *) (name)->ar ,      \
380                                  sizeof(char *) * (name)->nall ) ;    \
381      }                                                                \
382      if( (str) != NULL ){                                             \
383       (name)->ar[(name)->num] = (char *) RwcMalloc( strlen((str))+1 ); \
384       strcpy( (name)->ar[(name)->num] , (str) ) ;                     \
385       ADDTO_KILL((name)->kl,(name)->ar[(name)->num]) ;                \
386       ((name)->num)++ ;                                               \
387      } } while(0)
388 
389 /*! Add string str to dynamic string array "name" if str is not in there yet. */
390 #define ADDUTO_SARR(name,str)                                          \
391  do{ if (SARR_find_string(name, str, 0)<0) ADDTO_SARR(name,str);   \
392    } while(0)
393 
394 /*! Remove the ijk-th string from dynamic string array "name". */
395 
396 #define REMOVEFROM_SARR(name,ijk)                \
397  do{ SINGLE_KILL((name)->kl,(name)->ar[(ijk)]) ; \
398      (name)->ar[(ijk)] = NULL ; } while(0)
399 
400 /*! Kill all entries in the dynamic string array "name". */
401 
402 #define DESTROY_SARR(name)    \
403  do{ if( (name) != NULL ){    \
404      KILL_KILL((name)->kl) ;  \
405      myRwcFree( (name)->ar ) ; \
406      myRwcFree( (name) ) ; } } while(0)
407 
408 /*! Print all entries in a dynamic string array */
409 
410 #define PRINTF_SARR(name,lll)                                            \
411  do{ int qq ; printf("%s:",(lll)) ;                                      \
412      for( qq=0; qq < (name)->num; qq++ ) printf(" '%s'",(name)->ar[qq]); \
413      printf("\n") ; } while(0)
414 
415 extern int SARR_find_string( THD_string_array * sar , char * str , byte ci) ;
416 extern int SARR_find_substring( THD_string_array * sar , char * sub , byte ci) ;
417 
418 extern int SARR_lookfor_string   ( THD_string_array * sar , char * str , int nstart , byte ci) ;
419 extern int SARR_lookfor_substring( THD_string_array * sar , char * sub , int nstart , byte ci) ;
420 
421 /*! Concatenate strings p1 and p2 into string pout, making them a filesystem path.
422 
423     If p1 doesn't end in a '/', the '/' between p1/p2 will be added.
424     The pout array must be previously allocated.
425 */
426 
427 #define PATH_CONCAT(pout,p1,p2)                            \
428   do{ int zq ; strcpy((pout),(p1)) ; zq = strlen((pout)) ; \
429       if( (pout)[zq-1] != '/' ) strcat((pout),"/") ;       \
430       strcat((pout),(p2)) ; } while(0)
431 
432 /*************** dynamic array of sorted (x,y,z) points *************/
433 
434 #undef  ALLOW_DATASET_VLIST
435 #ifdef  ALLOW_DATASET_VLIST
436 
437 /*! Dynamic array of xyz and ijk points. */
438 
439 typedef struct {
440       int num ;                         /*!< Number of points currently in use */
441       int nall ;                        /*!< Number of points currently allocated */
442       THD_fvec3 *xyz ;                  /*!< Array of xyz coordinates in parent */
443       THD_ivec3 *ijk ;                  /*!< Array of ijk indexes in parent */
444       struct THD_3dim_dataset *parent ; /*!< Dataset these things come from */
445 } THD_vector_list ;
446 
447 #define INC_VLIST 64
448 
449 /*! Initialize a dynamic array of xyz points, attached to datset ddd. */
450 
451 #define INIT_VLIST(name,ddd) \
452    ( (name) = RwcNew(THD_vector_list) ,  \
453      (name)->num = (name)->nall = 0 ,   \
454      (name)->xyz = NULL , (name)->ijk = NULL , \
455      (name)->parent = (ddd) )
456 
457 /*! Add 1 xyz-vector to the array of xyz points.
458 
459     The ijk-vector will be converted from the xyz coordinates,
460     using the parent dataset for this array.
461 */
462 
463 #define ADD_FVEC_TO_VLIST(name,vec) \
464    { if( (name)->num == (name)->nall ){                                    \
465       (name)->nall += INC_VLIST ;                                          \
466       (name)->xyz   = (THD_fvec3 * ) RwcRealloc( (char *) (name)->xyz ,     \
467                                       sizeof(THD_fvec3) * (name)->nall ) ; \
468       (name)->ijk   = (THD_ivec3 * ) RwcRealloc( (char *) (name)->ijk ,     \
469                                       sizeof(THD_ivec3) * (name)->nall ) ; \
470      }                                                                     \
471      (name)->xyz[(name)->num] = (vec);                                     \
472      (name)->ijk[(name)->num] = THD_3dmm_to_3dind((name)->parent,(vec)) ;  \
473      ((name)->num)++; }
474 
475 /*! Add one ijk-vector to the array of xyz points.
476 
477     The xyz-vector will be converted from the ijk indexes, using
478     the parent dataset for this array.
479 */
480 
481 #define ADD_IVEC_TO_VLIST(name,vec) \
482    { if( (name)->num == (name)->nall ){                                    \
483       (name)->nall += INC_VLIST ;                                          \
484       (name)->xyz   = (THD_fvec3 * ) RwcRealloc( (char *) (name)->xyz ,     \
485                                       sizeof(THD_fvec3) * (name)->nall ) ; \
486       (name)->ijk   = (THD_ivec3 * ) RwcRealloc( (char *) (name)->ijk ,     \
487                                       sizeof(THD_ivec3) * (name)->nall ) ; \
488      }                                                                     \
489      (name)->ijk[(name)->num] = (vec);                                     \
490      (name)->xyz[(name)->num] = THD_3dind_to_3dmm((name)->parent,(vec)) ;  \
491      ((name)->num)++; }
492 
493 /*! Destroy an array of xyz points. */
494 
495 #define DESTROY_VLIST(name)      \
496    { if( (name) != NULL ){       \
497        myRwcFree( (name)->xyz ) ; \
498        myRwcFree( (name)->ijk ) ; \
499        myRwcFree( (name) ) ; } }
500 
501 #endif /* ALLOW_DATASET_VLIST */
502 
503 /**************************** typedefs ******************************/
504 
505 /*---------- structure to hold attributes from disk files ----------*/
506 
507 #define ATR_STRING_TYPE   0
508 #define ATR_FLOAT_TYPE    1
509 #define ATR_INT_TYPE      2
510 
511 #define FIRST_ATR_TYPE 0
512 #define LAST_ATR_TYPE  2
513 
514 /*! Things to look for in the .HEAD file; these define start of an attribute. */
515 
516 static char * ATR_typestr[] = {
517    "string-attribute" , "float-attribute" , "integer-attribute"
518 } ;
519 
520 /*! Stores an integer-attribute (array of ints). */
521 
522 typedef struct {
523       int    type ;   /*!< should be ATR_INT_TYPE */
524       char * name ;   /*!< name of attribute, read from HEAD file */
525       int    nin ;    /*!< number of ints stored here */
526       int  * in ;     /*!< array of ints stored here */
527 } ATR_int ;
528 
529 /*! Stores a float-attribute (array of floats). */
530 
531 typedef struct {
532       int     type ;  /*!< should be ATR_FLOAT_TYPE */
533       char *  name ;  /*!< name of attribute, read from HEAD file */
534       int     nfl ;   /*!< number of floats stored here */
535       float * fl ;    /*!< array of floats stored here */
536 } ATR_float ;
537 
538 /*! Stores a string-attribute (array of strings). */
539 
540 typedef struct {
541       int    type ;   /*!< should be ATR_STRING_TYPE */
542       char * name ;   /*!< name of attribute, read from HEAD file */
543       int    nch ;    /*!< number of characters in string */
544       char * ch ;     /*!< array of characters (may not be NUL terminated) */
545 } ATR_string ;
546 
547 #define ZBLOCK 126
548 #define ZSBLOCK 59  /* kurukuru pa */
549 extern void THD_zblock(int,char *) ;   /* replace zeros with ZBLOCKs */
550 extern void THD_unzblock(int,char *) ; /* undo the above */
551 extern void THD_zblock_ch(int,char *,char) ;   /* 12 Jul 2006 [rickr] */
552 extern void THD_unzblock_ch(int,char *,char) ; /* undo the above      */
553 
554 /*! Union type to hold an arbitrary attribute. */
555 
556 typedef union {
557       int          type ;      /*!< Determines type of data here */
558       ATR_string   str_atr ;
559       ATR_float    flo_atr ;
560       ATR_int      int_atr ;
561 } ATR_any ;
562 
563 #undef  ATR_COUNT
564 #define ATR_COUNT(aap)                                                  \
565           ( ((aap)==NULL) ? 0                                           \
566            :((aap)->type==ATR_FLOAT_TYPE)  ? ((ATR_float  *)(aap))->nfl \
567            :((aap)->type==ATR_STRING_TYPE) ? ((ATR_string *)(aap))->nch \
568            :((aap)->type==ATR_INT_TYPE)    ? ((ATR_int    *)(aap))->nin \
569            :0 )
570 
571 /*---------------------------------------------------------------------*/
572 /*-------------------- structure for linear mapping -------------------*/
573 
574 #define MAPPING_LINEAR_TYPE 0
575 #define MAPPING_LINEAR_STR  "LINEAR_MAPPING"
576 
577 #define FIRST_MAPPING_TYPE 0
578 #define LAST_MAPPING_TYPE  0
579 
580 static char * MAPPING_typestr[] = {
581    MAPPING_LINEAR_STR
582 } ;
583 
584 /*! Structure to hold a linear mapping between coordinate systems. */
585 
586 typedef struct {
587       int type ;            /*!< type code: only type now is MAPPING_LINEAR_TYPE */
588 
589       THD_mat33 mfor ;      /*!< x_map = [mfor] * x_in  - bvec  */
590       THD_mat33 mbac ;      /*!< x_in  = [mbac] * x_map - svec  */
591 
592       THD_fvec3 bvec;       /* x_map = [mfor] * x_in  - bvec  */
593       THD_fvec3 svec;       /* svec = - [mbac] * bvec */
594       THD_fvec3 bot ;       /* lower bound for transformation use */
595       THD_fvec3 top ;       /* upper bound for transformation use */
596 } THD_linear_mapping ;
597 
598 /*! Copy the .bot and .top bounds between two THD_linear_mapping structs. */
599 
600 #define COPY_LMAP_BOUNDS(m1,m2) ( (m1).bot=(m2).bot , (m1).top=(m2).top )
601 
602 /*! Use the matrix operations to define a macro
603     to load the inverse to a THD_linear_mapping once the forward is done. */
604 
605 #define LOAD_INVERSE_LMAP(map) \
606    ( (map).mbac = MAT_INV((map).mfor) ,          \
607      (map).svec = MATVEC((map).mbac,(map).bvec) ,\
608      NEGATE_FVEC3((map).svec) )
609 
610 #define MAPPING_LINEAR_FSTART RwcOffsetOf(THD_linear_mapping,mfor)
611 #define MAPPING_LINEAR_FEND   (RwcOffsetOf(THD_linear_mapping,top)+sizeof(THD_fvec3))
612 #define MAPPING_LINEAR_FSIZE  ((MAPPING_LINEAR_FEND-MAPPING_LINEAR_FSTART)/sizeof(float))
613 
614 /*! Debugging printout of a THD_linear_mapping struct. */
615 
616 #define DUMP_LMAP(m) \
617 ( printf("THD_linear_mapping:\n") ,                                     \
618   printf("   mfor = %8.4f %8.4f %8.4f\n",                               \
619          (m).mfor.mat[0][0], (m).mfor.mat[0][1], (m).mfor.mat[0][2] ) , \
620   printf("          %8.4f %8.4f %8.4f\n",                               \
621          (m).mfor.mat[1][0], (m).mfor.mat[1][1], (m).mfor.mat[1][2] ) , \
622   printf("          %8.4f %8.4f %8.4f\n",                               \
623          (m).mfor.mat[2][0], (m).mfor.mat[2][1], (m).mfor.mat[2][2] ) , \
624   printf("   mbac = %8.4f %8.4f %8.4f\n",                               \
625          (m).mbac.mat[0][0], (m).mbac.mat[0][1], (m).mbac.mat[0][2] ) , \
626   printf("          %8.4f %8.4f %8.4f\n",                               \
627          (m).mbac.mat[1][0], (m).mbac.mat[1][1], (m).mbac.mat[1][2] ) , \
628   printf("          %8.4f %8.4f %8.4f\n",                               \
629          (m).mbac.mat[2][0], (m).mbac.mat[2][1], (m).mbac.mat[2][2] ) , \
630   printf("   bvec = %8.4f %8.4f %8.4f\n",                               \
631          (m).bvec.xyz[0] , (m).bvec.xyz[1] , (m).bvec.xyz[2] ) ,        \
632   printf("   svec = %8.4f %8.4f %8.4f\n",                               \
633          (m).svec.xyz[0] , (m).svec.xyz[1] , (m).svec.xyz[2] ) ,        \
634   printf("   bot  = %8.4f %8.4f %8.4f\n",                               \
635          (m).bot.xyz[0]  , (m).bot.xyz[1]  , (m).bot.xyz[2] )  ,        \
636   printf("   top  = %8.4f %8.4f %8.4f\n\n",                             \
637          (m).top.xyz[0]  , (m).top.xyz[1]  , (m).top.xyz[2] ) )
638 
639 /*-----------------------------------------------------------------*/
640 /*--------------- structure for user placed markers ---------------*/
641 
642 #define MARKS_MAXNUM  10
643 #define MARKS_MAXLAB  20
644 #define MARKS_MAXHELP 256
645 #define MARKS_MAXFLAG 8
646 
647 /*! Structure for user placed markers. */
648 
649 typedef struct {
650      int numdef ;                             /*!< Number of markers defined */
651      int numset ;                             /*!< Number of markers now set */
652 
653      char label[MARKS_MAXNUM][MARKS_MAXLAB] ; /*!< Names for these marks */
654 
655      char help[MARKS_MAXNUM][MARKS_MAXHELP] ; /*!< Help for these marks */
656 
657      int ovcolor[MARKS_MAXNUM] ;              /*!< Overlay color index; -1 --> use defaults */
658 
659      RwcBoolean valid[MARKS_MAXNUM] ;            /*!< True if actually set */
660 
661      float xyz[MARKS_MAXNUM][3] ;             /*!< Coordinates (3dmm, not DICOM) */
662 
663      int aflags[MARKS_MAXFLAG] ;              /*!< Action flags */
664 
665      int type ;                               /*!< Type of markers (same as aflags[0]) */
666      char name[MARKS_MAXLAB] ;                /*!< Name of this type of markers */
667 } THD_marker_set ;
668 
669 #define MARKS_FSIZE  (MARKS_MAXNUM*3)
670 #define MARKS_FSTART RwcOffsetOf(THD_marker_set,xyz)
671 
672 #define MARKS_LSIZE  (MARKS_MAXNUM*MARKS_MAXLAB)
673 #define MARKS_LSTART RwcOffsetOf(THD_marker_set,label)
674 
675 #define MARKS_HSIZE  (MARKS_MAXNUM*MARKS_MAXHELP)
676 #define MARKS_HSTART RwcOffsetOf(THD_marker_set,help)
677 
678 #define MARKS_ASIZE  MARKS_MAXFLAG
679 #define MARKS_ASTART RwcOffsetOf(THD_marker_set,aflags)
680 
681 /*--------------- definitions for markers I know about now ---------------*/
682 
683 #define MARKSET_ALIGN    1  /* types of marker sets */
684 #define MARKSET_BOUNDING 2
685 
686 #define MARKACTION_NONE     0  /* action codes for marker sets */
687 #define MARKACTION_WARP     1
688 #define MARKACTION_REGISTER 2  /* not used at present */
689 
690 /*........................................................................*/
691 
692 /*! Number of orig->acpc markers. */
693 
694 #define NMARK_ALIGN 5
695 
696 static int THD_align_aflags[MARKS_MAXFLAG] = {
697   MARKSET_ALIGN , MARKACTION_WARP
698 } ;
699 
700 #define IMARK_ACSE 0
701 #define IMARK_ACPM 1
702 #define IMARK_PCIE 2
703 #define IMARK_MSA1 3
704 #define IMARK_MSA2 4
705 
706 /*! Labels for orig->acpc markers. */
707 
708 static char * THD_align_label[NMARK_ALIGN] = {
709    "AC superior edge"     ,
710    "AC posterior margin"  ,
711    "PC inferior edge"     ,
712    "First mid-sag pt"     ,
713    "Another mid-sag pt"
714 } ;
715 
716 /*! Help for orig->acpc markers. */
717 
718 static char * THD_align_help[NMARK_ALIGN] = {
719    "This is the uppermost point\n"
720    "on the anterior commisure,\n"
721    "in the mid-sagittal plane." ,
722 
723    "This is the rearmost point\n"
724    "on the anterior commisure,\n"
725    "in the mid-sagittal plane.\n"
726    "[Just a couple mm behind and\n"
727    " below the AC superior edge.]" ,
728 
729    "This is the bottommost point\n"
730    "on the posterior commissure,\n"
731    "in the mid-sagittal plane." ,
732 
733    "You must also specify two other points in the\n"
734    "mid-sagittal plane, ABOVE the corpus callosum\n"
735    "(i.e., in the longitudinal fissure).  These\n"
736    "points are needed to define the vertical plane." ,
737 
738    "You must also specify two other points in the\n"
739    "mid-sagittal plane, ABOVE the corpus callosum\n"
740    "(i.e., in the longitudinal fissure).  These\n"
741    "points are needed to define the vertical plane." ,
742 
743 } ;
744 
745 /*.....................................................................*/
746 
747 /*! Number of acpc->tlrc markers. */
748 
749 #define NMARK_BOUNDING 6
750 
751 static int THD_bounding_aflags[MARKS_MAXFLAG] = {
752    MARKSET_BOUNDING , MARKACTION_WARP
753 } ;
754 
755 #define IMARK_MANT 0
756 #define IMARK_MPOS 1
757 #define IMARK_MSUP 2
758 #define IMARK_MINF 3
759 #define IMARK_MLEF 4
760 #define IMARK_MRIG 5
761 
762 /*! Atlas distances for acpc->tlrc markers.
763     If you change these, change the helps below too */
764 
765 #define ATLAS_FRONT_TO_AC 70.0
766 #define ATLAS_AC_TO_PC    23.0
767 #define ATLAS_PC_TO_BACK  79.0
768 
769 #define ATLAS_BOT_TO_AC   42.0
770 #define ATLAS_AC_TO_TOP   74.0
771 #define ATLAS_AC_TO_LAT   68.0
772 
773 #define ATLAS_BBOX_LAT    80.0    /* dimensions used for         */
774 #define ATLAS_BBOX_ANT    80.0    /* Talairach view clipping box */
775 #define ATLAS_BBOX_POS   110.0
776 #define ATLAS_BBOX_INF    55.0
777 #define ATLAS_BBOX_SUP    85.0
778 
779 #define ATLAS_BBOX_INF_NEW 65.0   /* 3/06/96: extra 10 mm for cerebellum */
780 
781 #define ATLAS_ALIGNBOX_LAT  95.0  /* dimensions used for AC-PC */
782 #define ATLAS_ALIGNBOX_ANT  95.0  /* aligned view clipping box */
783 #define ATLAS_ALIGNBOX_POS 140.0  /* (3/25/95)                 */
784 #define ATLAS_ALIGNBOX_SUP 100.0
785 #define ATLAS_ALIGNBOX_INF  70.0
786 
787 #define MAX_ALLOWED_DEVIATION 2.0
788 #define MIN_ALLOWED_DEVIATION 0.5
789 
790 /*! Labels for acpc->tlrc markers. */
791 
792 static char * THD_bounding_label[NMARK_BOUNDING] = {
793    "Most anterior point"  ,
794    "Most posterior point" ,
795    "Most superior point"  ,
796    "Most inferior point"  ,
797    "Most left point"      ,
798    "Most right point"
799 } ;
800 
801 /*! Help for acpc->tlrc markers. */
802 
803 static char * THD_bounding_help[NMARK_BOUNDING] = {
804 "The frontmost point of the frontal cortex;\n"
805 "needed for brain length [atlas y = -70 mm]" ,
806 
807 "The hindmost point of the occipital cortex;\n"
808 "needed for brain length [atlas y = +102 mm]" ,
809 
810 "The topmost point of the parietal cortex;\n"
811 "needed for brain height [atlas z = +74 mm]" ,
812 
813 "The lowest point of the temporal cortex;\n"
814 "needed for brain height [atlas z = -42 mm]" ,
815 
816 "The most lateral (left) point of the parietotemporal cortex;\n"
817 "needed for brain width [atlas x = +68 mm]" ,
818 
819 "The most lateral (right) point of the parietotemporal cortex;\n"
820 "needed for brain width [atlas x = -68 mm]"
821 
822 } ;
823 
824 /*---------------------------------------------------------------------*/
825 /*---------------------- structures to hold warps ---------------------*/
826 
827 #define WARP_AFFINE_TYPE   0
828 #define WARP_AFFINE_STR    "WARP_AFFINE"
829 
830 #define WARP_TALAIRACH_12_TYPE 1
831 #define WARP_TALAIRACH_12_STR  "WARP_TALAIRACH_12"
832 
833 #define FIRST_WARP_TYPE 0
834 #define LAST_WARP_TYPE  1
835 
836 static char * WARP_typestr[] = {
837    WARP_AFFINE_STR , WARP_TALAIRACH_12_STR
838 } ;
839 
840 /*----------------------- resample types -----------------------*/
841 
842 #define RESAM_NN_TYPE      0
843 #define RESAM_NN_STR      "Nearest Neighbor"
844 
845 #define RESAM_LINEAR_TYPE  1
846 #define RESAM_LINEAR_STR  "Linear Interpolation"
847 
848 #define RESAM_CUBIC_TYPE   2
849 #define RESAM_CUBIC_STR   "Cubic Interpolation"
850 
851 #define RESAM_BLOCK_TYPE   3
852 #define RESAM_BLOCK_STR   "Blocky Interpolation"
853 
854 #define FIRST_RESAM_TYPE 0
855 #define LAST_RESAM_TYPE  3
856 
857 static char * RESAM_typestr[] = {
858    RESAM_NN_STR , RESAM_LINEAR_STR , RESAM_CUBIC_STR , RESAM_BLOCK_STR
859 } ;
860 
861 #define NSTR_SHORT_RESAM 2
862 static char * RESAM_shortstr[] = { "NN" , "Li" , "Cu" , "Bk" } ;
863 
864 /*! 12-piece Warp struct for orig/acpc -> tlrc coordinates. */
865 
866 typedef struct {
867       int type ;       /*!< type code: WARP_TALAIRACH_12_TYPE */
868       int resam_type ; /*!< Resampling method */
869 
870       THD_linear_mapping warp[12] ; /* The 12 pieces of the transformation */
871 } THD_talairach_12_warp ;
872 
873 #define W_RAS  0  /* right-anterior -superior mapping index */
874 #define W_LAS  1  /* left -anterior -superior */
875 #define W_RMS  2  /* right-medial   -superior */
876 #define W_LMS  3  /* left -medial   -superior */
877 #define W_RPS  4  /* right-posterior-superior */
878 #define W_LPS  5  /* left -posterior-superior */
879 #define W_RAI  6  /* right-anterior -inferior */
880 #define W_LAI  7  /* left -anterior -inferior */
881 #define W_RMI  8  /* right-medial   -inferior */
882 #define W_LMI  9  /* left -medial   -inferior */
883 #define W_RPI 10  /* right-posterior-inferior */
884 #define W_LPI 11  /* left -posterior-inferior */
885 
886 #define WARP_TALAIRACH_12_SIZE (12*MAPPING_LINEAR_FSIZE)
887 
888 /*! Debug printout for 1 piece of a Talairach warp. */
889 
890 #define DUMP_T12_MAP(t12,xx,yy,zz) \
891  (  printf("\n--- submap " # xx # yy # zz "\n" ) , \
892     DUMP_LMAP( (t12).warp[W_ ## xx ## yy ## zz] )    )
893 
894 /*! Debug printout for all 12 pieces of a Talairach warp. */
895 
896 #define DUMP_T12_WARP(t12) \
897  ( printf("\n12 region Talairach warp:") ,                 \
898    DUMP_T12_MAP((t12),R,A,S) , DUMP_T12_MAP((t12),L,A,S) , \
899    DUMP_T12_MAP((t12),R,M,S) , DUMP_T12_MAP((t12),L,M,S) , \
900    DUMP_T12_MAP((t12),R,P,S) , DUMP_T12_MAP((t12),L,P,S) , \
901    DUMP_T12_MAP((t12),R,A,I) , DUMP_T12_MAP((t12),L,A,I) , \
902    DUMP_T12_MAP((t12),R,M,I) , DUMP_T12_MAP((t12),L,M,I) , \
903    DUMP_T12_MAP((t12),R,P,I) , DUMP_T12_MAP((t12),L,P,I)    )
904 
905 /*! Struct to hold a simple affine warp (orig -> acpc). */
906 
907 typedef struct {
908       int type ;         /*!< type code: WARP_AFFINE_TYPE */
909       int resam_type ;   /*!< Resampling method */
910 
911       THD_linear_mapping warp ; /*!< The single affine mapping */
912 } THD_affine_warp ;
913 
914 #define WARP_AFFINE_SIZE (MAPPING_LINEAR_FSIZE)
915 
916 /*! Union type to hold all possible warp types. */
917 
918 typedef union {
919       int type ;                      /*!< WARP_AFFINE_TYPE or WARP_TALAIRACH_12_TYPE */
920       THD_affine_warp       rig_bod ;
921       THD_talairach_12_warp tal_12 ;
922 } THD_warp ;
923 
924 /*! Check if ww is a good warp. */
925 
926 #define ISVALID_WARP(ww) ( (ww) != NULL &&                  \
927                            (ww)->type >= FIRST_WARP_TYPE && \
928                            (ww)->type <= LAST_WARP_TYPE )
929 
930 /*! Temporary warp. */
931 
932 static THD_warp tempA_warp ;
933 
934 /*! Return value is an affine warp set to the identity transformation. */
935 
936 #define IDENTITY_WARP                                                   \
937    ( tempA_warp.rig_bod.type       = WARP_AFFINE_TYPE ,                 \
938      tempA_warp.rig_bod.resam_type = RESAM_NN_TYPE ,                    \
939      tempA_warp.rig_bod.warp.type  = MAPPING_LINEAR_TYPE ,              \
940      LOAD_DIAG_MAT( tempA_warp.rig_bod.warp.mfor ,     1,    1,    1 ) ,\
941      LOAD_DIAG_MAT( tempA_warp.rig_bod.warp.mbac ,     1,    1,    1 ) ,\
942      LOAD_FVEC3(    tempA_warp.rig_bod.warp.bvec ,     0,    0,    0 ) ,\
943      LOAD_FVEC3(    tempA_warp.rig_bod.warp.svec ,     0,    0,    0 ) ,\
944      LOAD_FVEC3(    tempA_warp.rig_bod.warp.bot  , -9999,-9999,-9999 ) ,\
945      LOAD_FVEC3(    tempA_warp.rig_bod.warp.top  ,  9999, 9999, 9999 ) ,\
946      tempA_warp )
947 
948 /*! Return values is a warp of angle th about axis ff, in aa-bb plane. */
949 
950 #define ROTGEN_WARP(th,ff,aa,bb)                                        \
951    ( tempA_warp.rig_bod.type       = WARP_AFFINE_TYPE ,                 \
952      tempA_warp.rig_bod.resam_type = RESAM_NN_TYPE ,                    \
953      tempA_warp.rig_bod.warp.type  = MAPPING_LINEAR_TYPE ,              \
954      LOAD_ROTGEN_MAT(tempA_warp.rig_bod.warp.mfor, th,ff,aa,bb) ,       \
955      LOAD_ROTGEN_MAT(tempA_warp.rig_bod.warp.mbac,-th,ff,aa,bb) ,       \
956      LOAD_FVEC3(     tempA_warp.rig_bod.warp.bvec,     0,    0,    0 ) ,\
957      LOAD_FVEC3(     tempA_warp.rig_bod.warp.svec,     0,    0,    0 ) ,\
958      LOAD_FVEC3(     tempA_warp.rig_bod.warp.bot , -9999,-9999,-9999 ) ,\
959      LOAD_FVEC3(     tempA_warp.rig_bod.warp.top ,  9999, 9999, 9999 ) ,\
960      tempA_warp )
961 
962 #define ROTX_WARP(th) ROTGEN_WARP(th,0,1,2)
963 #define ROTY_WARP(th) ROTGEN_WARP(th,1,2,0)
964 #define ROTZ_WARP(th) ROTGEN_WARP(th,2,0,1)
965 
966 /*! Make the affine warp map point (xin,yin,zin) to (xout,yout,zout). */
967 
968 #define CEN_WARP(ww,xin,yin,zin,xout,yout,zout)                  \
969   do{ THD_fvec3 tv , uv ;                                        \
970       LOAD_FVEC3(tv,xin,yin,zin) ;                               \
971       uv = MATVEC((ww).rig_bod.warp.mfor,tv) ;                   \
972       LOAD_FVEC3(tv,xout,yout,zout) ;                            \
973       (ww).rig_bod.warp.bvec = SUB_FVEC3(uv,tv) ;                \
974       (ww).rig_bod.warp.svec =                                   \
975          MATVEC((ww).rig_bod.warp.mbac,(ww).rig_bod.warp.bvec) ; \
976       NEGATE_FVEC3((ww).rig_bod.warp.svec) ;                     \
977   } while(0)
978 
979 extern THD_fvec3 AFNI_backward_warp_vector( THD_warp * , THD_fvec3 ) ;
980 extern THD_fvec3 AFNI_forward_warp_vector ( THD_warp * , THD_fvec3 ) ;
981 
982 /*---------------------------------------------------------------------*/
983 /*----------- structure to hold pointer to data on disk ---------------*/
984 
985 #define DISKPTR_TYPE  47
986 
987 #define THD_MAX_RANK       3
988 #define THD_MIN_RANK       3
989 #define THD_MAX_RANK_EVER  5
990 
991 /* none of these should be over 4 characters! */
992 
993 #define DATASET_HEADER_SUFFIX "HEAD"
994 #define DATASET_BRICK_SUFFIX  "BRIK"
995 #define DATASET_NOTES_SUFFIX  "NOTE"
996 
997 /* for strstr searches, include the '.'  17 Jun 2016 [rickr,DRG] */
998 #define DATASET_DOT_HEADER_SUFFIX ".HEAD"
999 #define DATASET_DOT_BRICK_SUFFIX  ".BRIK"
1000 
1001 /***
1002   The following codes define how the data is stored on disk.
1003   At one time, I started to support more than one storage
1004   type, but that is history.  Data either isn't stored
1005   (i.e., is warped-on-demand), or is stored in one big
1006   brick file.
1007 
1008   Later: OK, now we have more than one type.  However, type #1
1009          was never implemented (the ill-fated STORAGE_BY_SLICES).
1010 
1011   see also: thd_opendset.c: storage_mode_from_filename()
1012 ***/
1013 
1014 #define STORAGE_UNDEFINED         0
1015 #define STORAGE_BY_BRICK          2
1016 #define STORAGE_BY_MINC           3
1017 #define STORAGE_BY_VOLUMES        4  /* 20 Jun 2002 */
1018 #define STORAGE_BY_ANALYZE        5
1019 #define STORAGE_BY_CTFMRI         6  /* 04 Dec 2002 */
1020 #define STORAGE_BY_CTFSAM         7
1021 #define STORAGE_BY_1D             8  /* 04 Mar 2003 */
1022 #define STORAGE_BY_3D             9  /* 21 Mar 2003 */
1023 #define STORAGE_BY_NIFTI         10  /* 28 Aug 2003 */
1024 #define STORAGE_BY_MPEG          11  /* 03 Dec 2003 */
1025 #define STORAGE_BY_NIML          12  /* NIML AFNI dset   25 May 2006 [rickr] */
1026 #define STORAGE_BY_NI_SURF_DSET  13  /* NIML surface dset */
1027 #define STORAGE_BY_GIFTI         14  /* GIFTI surface dset */
1028 #define STORAGE_BY_NI_TRACT      15  /* NIML tract dset */
1029 #define STORAGE_BY_IMAGE_FILE    16  /* 06 Jul 2016 */
1030 
1031 #define LAST_STORAGE_MODE        16
1032 
1033 /*! Contains information about where/how dataset is stored on disk.
1034 
1035      The filenames in this structure are really path names
1036      (that is, they have the directory name prependend).
1037 */
1038 
1039 typedef struct {
1040       int type ;                           /*!< must be DISKPTR_TYPE */
1041       int rank ;                           /*!< must be 3 */
1042       int nvals ;                          /*!< number of 3D volumes; must agree with THD_datablock */
1043       int dimsizes[THD_MAX_RANK] ;         /*!< size of each dimension of 3D array */
1044       int storage_mode ;                   /*!< one of the STORAGE_ codes  */
1045 
1046       int byte_order ;                     /*!< LSB_FIRST or MSB_FIRST [25 Apr 1998] */
1047 
1048       char prefix[THD_MAX_PREFIX] ;        /*!< prefix part of filename */
1049       char viewcode[THD_MAX_VIEWCODE] ;    /*!< viewcode part of filename */
1050       char filecode[THD_MAX_FILECODE] ;    /*!< filecode = prefix+viewcode */
1051 
1052       char directory_name[THD_MAX_NAME] ;  /*!< contain all files for this dataset */
1053       char header_name[THD_MAX_NAME] ;     /*!< contains attributes */
1054       char brick_name[THD_MAX_NAME] ;      /*!< THIS contains actual data volumes */
1055 
1056       int  allow_directwrite ;             /* 08 May 2009 -- Star Trek Day! */
1057 } THD_diskptr ;
1058 
1059 #define ATRNAME_BYTEORDER "BYTEORDER_STRING"
1060 
1061 extern void THD_delete_diskptr( THD_diskptr * ) ;
1062 
1063 /*! Determine if THD_diskptr dk is valid. */
1064 
1065 #define ISVALID_DISKPTR(dk) ( (dk)!=NULL && (dk)->type==DISKPTR_TYPE )
1066 
1067 /*! Convert a file prefix and viewcode into a filecode (prefix+view). */
1068 
1069 #define PREFIX_VIEW_TO_FILECODE(pr,vv,fc) sprintf( (fc),"%s+%s",(pr),(vv) )
1070 
1071 /*! Extract the prefix from a filecode (prefix+view).
1072 
1073     - If there is no '+', puts an empty string into pr
1074     - Otherwise, scans backward from end to find last '+'; everything before that is the prefix
1075     - Space for pr must be allocated beforehand
1076 
1077     Made strstr check for +orig, +acpc, and +tlrc instead of just
1078       "+". Names like aseg+aparc.nii were getting butchered
1079       ZSS: Dec 2011
1080 */
1081 
1082 #define FILECODE_TO_PREFIX(fc,pr)                                     \
1083   do{ char *qq , *ff , *pp ;                                          \
1084       if( strstr((fc),"+orig") == NULL &&\
1085           strstr((fc),"+acpc") == NULL &&\
1086           strstr((fc),"+tlrc") == NULL ){                             \
1087          (pr)[0] = '\0' ;                                             \
1088       } else {                                                        \
1089          for( qq=fc+strlen((fc)) ; *qq != '+' ; qq-- ) ;              \
1090          for( ff=(fc) , (pp)=(pr) ; ff < qq ; ff++,pp++ ) *pp = *ff ; \
1091          *pp = '\0' ; } break ; } while(1)
1092 
1093 #if 0
1094 #define FILECODE_TO_PREFIX(fc,pr) \
1095   do{ char *qq , *ff , *pp ;               \
1096       if( (qq=strstr((fc),"+")) == NULL ){ \
1097          (pr)[0] = '\0' ;                  \
1098       } else {                             \
1099          for( ff=(fc) , (pp)=(pr) ; ff < qq ; ff++,pp++ ) *pp = *ff ; \
1100          *pp = '\0' ; } break ; } while(1)
1101 #endif
1102 
1103 /*! Extract the prefix from a filename. */
1104 
1105 #define FILENAME_TO_PREFIX(fn,pr)             \
1106   do{ int ii ;                                \
1107       for( ii=strlen((fn)) ; ii >= 0 ; ii-- ) \
1108          if( (fn)[ii] == '/' ) break ;        \
1109       FILECODE_TO_PREFIX( (fn)+(ii+1) , (pr) ) ; break ; } while(1)
1110 
1111 /*---------------------------------------------------------------------*/
1112 /*------- structure to hold actual 3D data, or pointers thereto -------*/
1113 
1114 #define DATABLOCK_TYPE 37
1115 
1116 #define DATABLOCK_MEM_UNDEFINED  1
1117 #define DATABLOCK_MEM_MALLOC     2
1118 #define DATABLOCK_MEM_MMAP       4
1119 #define DATABLOCK_MEM_ANY        (DATABLOCK_MEM_MALLOC | DATABLOCK_MEM_MMAP)
1120 #define DATABLOCK_MEM_SHARED     8    /* 02 May 2003 */
1121 
1122 /*! Determine if mm is a valid memory allocation code. */
1123 
1124 #define ISVALID_MEM_CODE(mm) \
1125   ( (mm) == DATABLOCK_MEM_MALLOC || (mm) == DATABLOCK_MEM_MMAP \
1126                                  || (mm) == DATABLOCK_MEM_ANY  \
1127                                  || (mm) == DATABLOCK_MEM_SHARED )
1128 
1129 #ifndef MMAP_THRESHOLD           /* if not previously defined in machdep.h */
1130 /*! A brick file should have this many bytes before we try to use mmap */
1131 #  define MMAP_THRESHOLD 999999
1132 #endif
1133 
1134 /*------------------------------------------------------------------*/
1135 /* Stuff for volume-editing on demand.  [05 Sep 2006] */
1136 
1137 #define VEDIT_NPARAM 9
1138 typedef struct {
1139   int code , ival , flags ;
1140   float param[VEDIT_NPARAM] ;
1141   void *exinfo ;
1142 } VEDIT_settings ;
1143 
1144 #define VEDIT_CLUST    1   /* param= ithr,thr,rmm,vmul  exinfo=NULL */
1145 #define VEDIT_LASTCODE 1   /* no other options besides clustering!? */
1146 
1147 #define VEDIT_IVAL(vv)      ((vv).ival)
1148 #define DBLK_VEDIT_IVAL(db) VEDIT_IVAL((db)->vedset)
1149 #define DSET_VEDIT_IVAL(ds) DBLK_VEDIT_IVAL((ds)->dblk)
1150 
1151 #define VEDIT_CODE(vv)      ((vv).code)
1152 #define DBLK_VEDIT_CODE(db) VEDIT_CODE((db)->vedset)
1153 #define DSET_VEDIT_CODE(ds) DBLK_VEDIT_CODE((ds)->dblk)
1154 
1155 #define VEDIT_FLAGS(vv)      ((vv).flags)
1156 #define DBLK_VEDIT_FLAGS(db) VEDIT_FLAGS((db)->vedset)
1157 #define DSET_VEDIT_FLAGS(db) DBLK_VEDIT_FLAGS((ds)->dblk)
1158 
1159 #define VEDIT_good(vv)                                            \
1160    ( (vv).code > 0 && (vv).code <= VEDIT_LASTCODE )
1161 #define DBLK_VEDIT_good(db)                                       \
1162    ( VEDIT_good((db)->vedset) && (db)->vedset.ival >= 0 &&        \
1163                                  (db)->vedset.ival < (db)->nvals )
1164 #define DSET_VEDIT_good(ds) DBLK_VEDIT_good((ds)->dblk)
1165 /*------------------------------------------------------------------*/
1166 
1167 /*!  All subvolumes are stored in an array of MRI_IMAGE (the "brick").
1168      - If mmap is used, then the whole external file is mmap()-ed in one
1169        block and the data pointers for each image computed from this base.
1170      - If malloc() is used, then each image is separately allocated and input.
1171      - Each datablock has a brick, even if it doesn't actually contain
1172        data (is only warp-on-demand).
1173      - Whether or not a datablock contains actual voxel data can be
1174        determined by examining the "malloc_type".
1175     \date Feb 1996
1176 */
1177 
1178 typedef struct {
1179       int type ;              /*!< type code: DATABLOCK_TYPE */
1180 
1181       int nvals ;             /*!< number of 3D bricks */
1182 
1183       MRI_IMARR * brick  ;    /*!< array of pointers to each 3D brick */
1184       float * brick_fac  ;    /*!< array of scale factors to convert sub-bricks to floats */
1185       int64_t *brick_bytes ;  /*!< array of data size of each sub-brick */
1186 
1187                                 /* These fields added for "bucket" datasets: */
1188 
1189       char **  brick_lab  ;     /*!< labels for all sub-bricks                 */
1190       char **  brick_keywords ; /*!< keywords strings for all sub-bricks       */
1191       int *    brick_statcode ; /*!< a FUNC_*_TYPE ==> kind of statistic here  */
1192       float ** brick_stataux ;  /*!< stat_aux parameters for each sub-brick with brick_statcode[iv] > 0 */
1193 
1194       int64_t total_bytes ;   /*!< totality of data storage needed */
1195       int     malloc_type ;   /*!< memory allocation method */
1196       int     locked ;        /*!< Feb 1998: locked in memory (un-purgeable) */
1197 
1198                                 /* Jan 1999: for datasets that are extracted from a master dataset */
1199       int    master_nvals ;   /*!< Number of nvals in master dataset */
1200       int *  master_ival ;    /*!< master_ival[i] = sub-brick index in master of sub-brick #i here */
1201       int64_t *master_bytes ; /*!< master_bytes[i] = size of sub-brick #i in master */
1202 
1203       float master_bot ;      /*!< range of data values to keep from master - bottom */
1204       float master_top ;      /*!< range of data values to keep from master - top */
1205 
1206       /* for angle bracket selectors - input restricted to an integer list of */
1207       /* CSV (comma separated values) - akin to master_bot and master_top,    */
1208       /* but a list, not a range                          21 Nov 2016 [rickr] */
1209       /* --> of course, this will probably change to a list of float ranges...*/
1210       int    master_ncsv ;    /*!< Number of values in master_csv             */
1211       int *  master_csv  ;    /*!< list of non-zero values that can be stored */
1212 
1213       THD_diskptr * diskptr ; /*!< where the data is on disk (if anywhere!) */
1214 
1215       int       natr ;        /*!< number of attributes read from disk (or to write to disk) */
1216       int       natr_alloc ;  /*!< number of attributes allocated in atr below */
1217       ATR_any * atr ;         /*!< array of attributes (from the header) */
1218 
1219       int       nnodes ;      /*!< number of node indices [25 May 2006 rickr] */
1220       int     * node_list ;   /*!< index array for STORAGE_BY_NI_SURF_DSET    */
1221 
1222    /* pointers to other stuff */
1223 
1224       KILL_list kl ;          /*!< Stuff to delete if this struct is deleted */
1225       RwcPointer parent ;      /*!< Somebody who "owns" me */
1226 
1227       char shm_idcode[32] ;   /*!< Idcode for shared memory buffer, if any [02 May 2003]. */
1228       int  shm_idint ;        /*!< Integer id for shared memory buffer. */
1229 
1230       VEDIT_settings vedset ; /*!< Volume edit-on-the-fly settings */
1231       MRI_IMAGE *vedim ;      /*!< Volume edit-on-the-fly result */
1232 
1233       floatvec **brick_fdrcurve ; /*!< FDR z(q) as a function of statistic */
1234       floatvec **brick_mdfcurve ; /*!< FDR mdf as a function of log10(p) */
1235 
1236 } THD_datablock ;
1237 
1238 /*! Force bricks to be allocated with malloc(). */
1239 
1240 #define DBLK_mallocize(db) THD_force_malloc_type((db),DATABLOCK_MEM_MALLOC)
1241 
1242 /*! Force bricks to be allocated with mmap(). */
1243 
1244 #define DBLK_mmapize(db)   THD_force_malloc_type((db),DATABLOCK_MEM_MMAP)
1245 
1246 /*! Don't care how bricks are allocated. */
1247 
1248 #define DBLK_anyize(db)    THD_force_malloc_type((db),DATABLOCK_MEM_ANY)
1249 
1250 /*! Test if brick is set to be malloc()-ed. */
1251 
1252 #define DBLK_IS_MALLOC(db)  ((db)->malloc_type == DATABLOCK_MEM_MALLOC)
1253 
1254 /*! Test if brick is set to be mmap()-ed. */
1255 
1256 #define DBLK_IS_MMAP(db)    ((db)->malloc_type == DATABLOCK_MEM_MMAP)
1257 
1258 /*! Test if brick is set to be shared. */
1259 
1260 #define DBLK_IS_SHARED(db)  ((db)->malloc_type == DATABLOCK_MEM_SHARED)
1261 
1262 /*! Force bricks to be allocated in shared memory.  */
1263 
1264 #define DBLK_shareize(db) THD_force_malloc_type((db),DATABLOCK_MEM_SHARED)
1265 
1266 /*! Lock bricks in memory. */
1267 
1268 #define DBLK_lock(db)   ((db)->locked = 1)
1269 
1270 /*! Unlock bricks from memory, if they aren't "superlocked". */
1271 
1272 #define DBLK_unlock(db) ((db)->locked = ((db)->locked<2) ? 0 : 2)
1273 
1274 /*! Test if brick is locked into memory. */
1275 
1276 #define DBLK_LOCKED(db) ((db)->locked)
1277 
1278 /*! Superlock brick in memory.  Can only be undone by explicit access to db->locked. */
1279 #define DBLK_superlock(db) ((db)->locked = 2)
1280 
1281 /*! Check if brick is mastered from another dataset. */
1282 
1283 #define DBLK_IS_MASTERED(db) \
1284   ((db)->master_nvals > 0 && (db)->master_ival != NULL && (db)->master_bytes != NULL)
1285 
1286 /*! Check if brick is mastered and has subranges to be applied */
1287 
1288 #define DBLK_IS_MASTER_SUBRANGED(db)                    \
1289    (DBLK_IS_MASTERED(db) &&                             \
1290       ( ((db)->master_bot <= (db)->master_top) ||       \
1291         ((db)->master_ncsv > 0 && (db)->master_csv != NULL) ))
1292 
1293 extern void THD_delete_datablock         ( THD_datablock * ) ;
1294 extern void THD_init_datablock_brick     ( THD_datablock * , int , void * ) ;
1295 extern void THD_init_datablock_labels    ( THD_datablock * ) ;
1296 extern void THD_init_datablock_keywords  ( THD_datablock * ) ;
1297 extern void THD_copy_datablock_auxdata   ( THD_datablock * , THD_datablock * ) ;
1298 extern void THD_init_datablock_stataux   ( THD_datablock * ) ;
1299 extern void THD_store_datablock_stataux  ( THD_datablock *,int,int,int,float * );
1300 extern void THD_store_datablock_label    ( THD_datablock * , int , char * ) ;
1301 extern void THD_store_datablock_keywords ( THD_datablock * , int , char * ) ;
1302 extern void THD_append_datablock_keywords( THD_datablock * , int , char * ) ;
1303 extern int  THD_datablock_from_atr       ( THD_datablock *, char *, char * ) ;
1304 extern void atr_print( ATR_any * atr, char *ssep , char *spsep, char quote, int do_name) ;
1305 
1306 /*! Initialize all sub-bricks auxiliary data to nothing. */
1307 
1308 #define THD_null_datablock_auxdata(blk) ( (blk)->brick_lab      = NULL , \
1309                                           (blk)->brick_keywords = NULL , \
1310                                           (blk)->brick_statcode = NULL , \
1311                                           (blk)->brick_stataux  = NULL  )
1312 
1313 extern int  THD_string_has( char * , char * ) ;
1314 
1315 /*! Check if datablock is OK. */
1316 
1317 #define ISVALID_DATABLOCK(bk) ( (bk) != NULL && (bk)->type == DATABLOCK_TYPE )
1318 
1319 /*! Synonym for ISVALID_DATABLOCK. */
1320 
1321 #define ISVALID_DBLK           ISVALID_DATABLOCK  /* 26 Mar 2001 */
1322 
1323 /*------------- a dynamic array type for datablocks --------------*/
1324 
1325 /*! A dynamic array type for datablocks - used when assembling datasets. */
1326 
1327 typedef struct {
1328       int num ;               /*!< Number of datablocks stored */
1329       int nall ;              /*!< Number of datablocks space allocated for */
1330       THD_datablock **ar ;    /*!< Array of datablocks */
1331 } THD_datablock_array ;
1332 
1333 #define INC_DBARR 8
1334 
1335 /*! Initialize a THD_datablock_array. */
1336 
1337 #define INIT_DBARR(name)                  \
1338    ( (name) = RwcNew(THD_datablock_array) ,\
1339      (name)->num = (name)->nall = 0 ,     \
1340      (name)->ar  = NULL )
1341 
1342 /*! Add a datablock to a THD_datablock_array. */
1343 
1344 #define ADDTO_DBARR(name,bblk)                                     \
1345    { if( (name)->num == (name)->nall ){                            \
1346       (name)->nall += INC_DBARR + (name)->nall/8 ;                 \
1347       (name)->ar    = (THD_datablock **)                           \
1348                        RwcRealloc( (char *) (name)->ar ,            \
1349                         sizeof(THD_datablock *) * (name)->nall ) ; \
1350      }                                                             \
1351      if( (bblk) != NULL ){               \
1352       (name)->ar[(name)->num] = (bblk) ; \
1353       ((name)->num)++ ;                  \
1354      } }
1355 
1356 /*! Free the space used by a THD_datablock_array (but not the datablocks themselves). */
1357 
1358 #define FREE_DBARR(name)      \
1359    if( (name) != NULL ){      \
1360      myRwcFree( (name)->ar ) ; \
1361      myRwcFree( (name) ) ; }
1362 
1363 /*--------------------------------------------------------------------*/
1364 /*---------- stuff to hold axes information for 3D dataset -----------*/
1365 
1366 #define DATAXES_TYPE 27
1367 
1368 /*! Default resampling grid size (in mm). */
1369 
1370 #define DEFAULT_RESAMPLE_VOX 1.0
1371 
1372 /*--- orientation types ---*/
1373 
1374 #define ORI_R2L_TYPE  0
1375 #define ORI_R2L_STR  "Right-to-Left"
1376 
1377 #define ORI_L2R_TYPE  1
1378 #define ORI_L2R_STR  "Left-to-Right"
1379 
1380 #define ORI_P2A_TYPE  2
1381 #define ORI_P2A_STR  "Posterior-to-Anterior"
1382 
1383 #define ORI_A2P_TYPE  3
1384 #define ORI_A2P_STR  "Anterior-to-Posterior"
1385 
1386 #define ORI_I2S_TYPE  4
1387 #define ORI_I2S_STR  "Inferior-to-Superior"
1388 
1389 #define ORI_S2I_TYPE  5
1390 #define ORI_S2I_STR  "Superior-to-Inferior"
1391 
1392 #define ORI_GEN_TYPE  6
1393 #define ORI_GEN_STR  "General"  /* not used at present */
1394 
1395 #define FIRST_ORIENT_TYPE 0
1396 #define LAST_ORIENT_TYPE  5
1397 
1398 #define LONGEST_ORIENT_TYPESTR strlen(ORI_P2A_STR)
1399 
1400 static char * ORIENT_typestr[] = {
1401    ORI_R2L_STR , ORI_L2R_STR , ORI_P2A_STR ,
1402    ORI_A2P_STR , ORI_I2S_STR , ORI_S2I_STR , ORI_GEN_STR
1403 } ;
1404 
1405 static char * ORIENT_shortstr[] = {
1406    "R-L" , "L-R" , "P-A" , "A-P" , "I-S" , "S-I" , "GEN"
1407 } ;
1408 
1409 static char * ORIENT_tinystr[] = {
1410    "RL" , "LR" , "PA" , "AP" , "IS" , "SI" , "??"
1411 } ;
1412 
1413 static char ORIENT_xyz[]   = "xxyyzzg" ;  /* DICOM directions are
1414                                              x = R->L , y = A->P , z = I->S */
1415 
1416 /*! Determines if orientation code (0..5) is DICOM positive or negative. */
1417 
1418 static char ORIENT_sign[]  = "+--++-" ;
1419 
1420 static char ORIENT_first[] = "RLPAIS" ;
1421 
1422 static int  ORIENT_xyzint[] = { 1,1 , 2,2 , 3,3 , 666 } ;
1423 
1424 #define ORIENT_OPPOSITE(orc) \
1425   ( ((orc) % 2 == 0) ? ((orc)+1) : ((orc)-1) )
1426 
1427 /*! Struct to hold information about 3D brick grid in space.
1428     Voxel center x[i] is at xxorg + i * xxdel, et cetera.
1429 */
1430 
1431 typedef struct {
1432       int type ;     /*!< type code: DATAXES_TYPE */
1433 
1434       int nxx ;      /*!< Number of points in grid in x direction */
1435       int nyy ;      /*!< Number of points in grid in y direction */
1436       int nzz ;      /*!< Number of points in grid in z direction */
1437 
1438       float xxorg ;  /*!< Center of (0,0,0) voxel */
1439       float yyorg ;  /*!< Center of (0,0,0) voxel */
1440       float zzorg ;  /*!< center of (0,0,0) voxel */
1441       float xxdel ;  /*!< Spacings between voxel centers (mm) - may be negative */
1442       float yydel ;  /*!< Spacings between voxel centers (mm) - may be negative */
1443       float zzdel ;  /*!< Spacings between voxel centers (mm) - may be negative */
1444 
1445       float xxmin ;  /*!< Bounding box for grid [cf THD_set_daxes_bbox()] */
1446       float xxmax ;  /*!< Bounding box for grid */
1447       float yymin ;  /*!< Bounding box for grid */
1448       float yymax ;  /*!< Bounding box for grid */
1449       float zzmin ;  /*!< Bounding box for grid */
1450       float zzmax ;  /*!< Bounding box for grid */
1451 
1452       int xxorient ;  /*!< Orientation code */
1453       int yyorient ;  /*!< Orientation code */
1454       int zzorient ;  /*!< Orientation code */
1455 
1456       THD_mat33 to_dicomm ; /*!< Orthogonal matrix transforming from
1457                                 dataset coordinates to DICOM coordinates */
1458 
1459       /*** 06 Dec 2005: extensions to allow arbitrarily oriented volumes [cf thd_matdaxes.c] ***/
1460 
1461       mat44 ijk_to_dicom ;  /* matrix taking ijk indexes to DICOM xyz coords */
1462       mat44 dicom_to_ijk ;  /* inverse of above */
1463       float dicom_xxmin , dicom_yymin , dicom_zzmin ;
1464       float dicom_xxmax , dicom_yymax , dicom_zzmax ;
1465       /*** 18 May 2007: obliquity */
1466       mat44 ijk_to_dicom_real ;  /* matrix to convert ijk to DICOM for obliquity*/
1467    /* pointers to other stuff */
1468 
1469       RwcPointer parent ;    /*!< Dataset that "owns" this struct */
1470 } THD_dataxes ;
1471 
1472 #define DAXES_CMAT(dax,rrr)                               \
1473    ( ( rrr && ISVALID_MAT44((dax)->ijk_to_dicom_real) )   \
1474      ? (dax)->ijk_to_dicom_real                           \
1475      : (dax)->ijk_to_dicom      )
1476 
1477 #define DSET_CMAT(ds,rrr)  DAXES_CMAT( (ds)->daxes , (rrr) )
1478 
1479 #define DAXES_COPYOVER_REAL(dax)                  \
1480   (dax)->ijk_to_dicom_real = (dax)->ijk_to_dicom  /* 27 Jun 2014 */
1481 
1482 #define DSET_COPYOVER_REAL(ds)                               \
1483   do{ if( ISVALID_DSET(ds) && ISVALID_DATAXES((ds)->daxes) ) \
1484         DAXES_COPYOVER_REAL((ds)->daxes) ;                   \
1485   } while(0)
1486 
1487 #define DSET_CHECKAXES_REAL(ds)                                                               \
1488   do{ if( ISVALID_DSET(ds) && ISVALID_DATAXES((ds)->daxes) ){                                 \
1489         float dif = MAT44_FLDIF((ds)->daxes->ijk_to_dicom,(ds)->daxes->ijk_to_dicom_real);    \
1490         if( dif > 0.001f )                                                                    \
1491           WARNING_message("-*-*-*- ijk_to_dicom and ijk_to_dicom_real differ for dataset %s", \
1492                           DSET_HEADNAME(ds) ) ;                                               \
1493       } } while(0)
1494 
1495 /*! Center of grid in x-direction. */
1496 #define DAXES_XCEN(dax) ((dax)->xxorg + 0.5*((dax)->nxx - 1) * (dax)->xxdel)
1497 
1498 /*! Center of grid in y-direction. */
1499 #define DAXES_YCEN(dax) ((dax)->yyorg + 0.5*((dax)->nyy - 1) * (dax)->yydel)
1500 
1501 /*! Center of grid in z-direction. */
1502 #define DAXES_ZCEN(dax) ((dax)->zzorg + 0.5*((dax)->nzz - 1) * (dax)->zzdel)
1503 
1504 #define DSET_XCEN(ds) DAXES_XCEN((ds)->daxes)
1505 #define DSET_YCEN(ds) DAXES_YCEN((ds)->daxes)
1506 #define DSET_ZCEN(ds) DAXES_ZCEN((ds)->daxes)
1507 
1508 #if 1
1509 #define DAXES_NUM(dax,ori) \
1510    ( (ORIENT_xyzint[(ori)] == ORIENT_xyzint[(dax)->xxorient]) ? (dax)->nxx : \
1511      (ORIENT_xyzint[(ori)] == ORIENT_xyzint[(dax)->yyorient]) ? (dax)->nyy : \
1512      (ORIENT_xyzint[(ori)] == ORIENT_xyzint[(dax)->zzorient]) ? (dax)->nzz : 0 )
1513 #else
1514 #define DAXES_NUM(dax,ori) ( ( ORIENT_xyzint[(ori)] == 1 ) ? (dax)->nxx : \
1515                              ( ORIENT_xyzint[(ori)] == 2 ) ? (dax)->nyy : \
1516                              ( ORIENT_xyzint[(ori)] == 3 ) ? (dax)->nzz : 0 )
1517 #endif
1518 
1519 /*!  WARNING:  If you perform surgery on a dataset and change its
1520                dimensions in the dataxes, you must also reflect
1521                this in the diskptr.  Otherwise, the .HEAD file
1522                will not have the correct dimensions!  The macro
1523                just below will do this for you.
1524 */
1525 
1526 #define DATAXES_TO_DISKPTR(ds)                             \
1527   ( (ds)->dblk->diskptr->dimsizes[0] = (ds)->daxes->nxx ,  \
1528     (ds)->dblk->diskptr->dimsizes[1] = (ds)->daxes->nyy ,  \
1529     (ds)->dblk->diskptr->dimsizes[2] = (ds)->daxes->nzz  )
1530 
1531 /*! Check if dax is a valid THD_dataxes struct. */
1532 
1533 #define ISVALID_DATAXES(dax) ( (dax) != NULL && (dax)->type == DATAXES_TYPE )
1534 
1535 /*! Check if two THD_dataxes are essential equivalent.
1536     ***** SEE ALSO ********
1537     THD_dataset_mismatch ()               */
1538 
1539 #define EQUIV_DATAXES(cax,dax)                     \
1540   ( ISVALID_DATAXES((cax))                      && \
1541     ISVALID_DATAXES((dax))                      && \
1542     (cax)->nxx == (dax)->nxx                    && \
1543     (cax)->nyy == (dax)->nyy                    && \
1544     (cax)->nzz == (dax)->nzz                    && \
1545     fabs( (cax)->xxorg - (dax)->xxorg ) < 0.01  && \
1546     fabs( (cax)->yyorg - (dax)->yyorg ) < 0.01  && \
1547     fabs( (cax)->zzorg - (dax)->zzorg ) < 0.01  && \
1548     fabs( (cax)->xxdel - (dax)->xxdel ) < 0.001 && \
1549     fabs( (cax)->yydel - (dax)->yydel ) < 0.001 && \
1550     fabs( (cax)->zzdel - (dax)->zzdel ) < 0.001 && \
1551     (cax)->xxorient == (dax)->xxorient          && \
1552     (cax)->yyorient == (dax)->yyorient          && \
1553     (cax)->zzorient == (dax)->zzorient    )
1554 
1555 #define EQUIV_DATAXYZ(cax,dax)                     \
1556   ( ISVALID_DATAXES((cax))                      && \
1557     ISVALID_DATAXES((dax))                      && \
1558     (cax)->nxx == (dax)->nxx                    && \
1559     (cax)->nyy == (dax)->nyy                    && \
1560     (cax)->nzz == (dax)->nzz                    && \
1561     fabs( (cax)->xxdel - (dax)->xxdel ) < 0.001 && \
1562     fabs( (cax)->yydel - (dax)->yydel ) < 0.001 && \
1563     fabs( (cax)->zzdel - (dax)->zzdel ) < 0.001 && \
1564     (cax)->xxorient == (dax)->xxorient          && \
1565     (cax)->yyorient == (dax)->yyorient          && \
1566     (cax)->zzorient == (dax)->zzorient    )
1567 
1568 #define EQUIV_DATADELTAXYZ(cax,dax)                \
1569   ( ISVALID_DATAXES((cax))                      && \
1570     ISVALID_DATAXES((dax))                      && \
1571     fabs( (cax)->xxdel - (dax)->xxdel ) < 0.001 && \
1572     fabs( (cax)->yydel - (dax)->yydel ) < 0.001 && \
1573     fabs( (cax)->zzdel - (dax)->zzdel ) < 0.001 && \
1574     (cax)->xxorient == (dax)->xxorient          && \
1575     (cax)->yyorient == (dax)->yyorient          && \
1576     (cax)->zzorient == (dax)->zzorient    )
1577 
1578 #define EQUIV_GRIDS(d1,d2) \
1579  ( ISVALID_DSET(d1) && ISVALID_DSET(d2) && EQUIV_DATAXES((d1)->daxes,(d2)->daxes) )
1580 
1581 #define EQUIV_GRIDXYZ(d1,d2) \
1582  ( ISVALID_DSET(d1) && ISVALID_DSET(d2) && EQUIV_DATAXYZ((d1)->daxes,(d2)->daxes) )
1583 
1584 #define EQUIV_DELTAXYZ(d1,d2) \
1585  ( ISVALID_DSET(d1) && ISVALID_DSET(d2) && EQUIV_DATADELTAXYZ((d1)->daxes,(d2)->daxes) )
1586 
1587 #define EQUIV_DATA_NXYZ(cax,dax)    \
1588  ( ISVALID_DATAXES((cax))        && \
1589    ISVALID_DATAXES((dax))        && \
1590    (cax)->nxx == (dax)->nxx      && \
1591    (cax)->nyy == (dax)->nyy      && \
1592    (cax)->nzz == (dax)->nzz  )
1593 
1594 #define EQUIV_GRIDS_NXYZ(d1,d2) \
1595  ( ISVALID_DSET(d1) && ISVALID_DSET(d2) && EQUIV_DATA_NXYZ((d1)->daxes,(d2)->daxes) )
1596 
1597 extern void THD_edit_dataxes( float , THD_dataxes * , THD_dataxes * ) ;
1598 
1599 extern void THD_set_daxes_bbox     ( THD_dataxes * ) ; /* 20 Dec 2005 */
1600 extern void THD_set_daxes_to_dicomm( THD_dataxes * ) ;
1601 
1602 int THD_get_axis_direction( THD_dataxes *, int ) ; /* 19 Mar 2003 */
1603 int THD_fill_orient_int_3_rlpais( THD_dataxes *, int [3] ); // [PT: Nov 2, 2020]
1604 int THD_fill_orient_str_3( THD_dataxes *, char [4] );/* 23 Jan 2013 [rickr] */
1605 int THD_fill_orient_str_6( THD_dataxes *, char [7] );/* 23 Jan 2013 [rickr] */
1606 
1607 
1608 extern int  THD_daxes_to_mat44  ( THD_dataxes *dax ) ; /* 07 Dec 2005 */
1609 extern int  THD_daxes_from_mat44( THD_dataxes *dax ) ;
1610 extern void THD_set_dicom_box   ( THD_dataxes *dax ) ; /* 15 Dec 2005 */
1611 extern mat44 THD_resample_mat44( mat44 , int,int,int ,
1612                                  float,float,float , int *,int *,int *) ;
1613 
1614 /*---------------------------------------------------------------------*/
1615 /* Macros and functions for dealing with mat44 structs. */
1616 
1617 /*******
1618    Useful mat33 and mat44 functions in nifti1_io.c:
1619       mat44 nifti_mat44_inverse( mat44 R ) ;           == matrix inverse
1620       mat33 nifti_mat33_inverse( mat33 R ) ;           == matrix inverse
1621       mat33 nifti_mat33_polar  ( mat33 A ) ;           == polar decomp
1622       float nifti_mat33_rownorm( mat33 A ) ;           == max row sum
1623       float nifti_mat33_colnorm( mat33 A ) ;           == max col sum
1624       float nifti_mat33_determ ( mat33 R ) ;           == determinant
1625       mat33 nifti_mat33_mul    ( mat33 A, mat33 B ) ;  == matrix multiply
1626 *******/
1627 
1628 /******* Function below is not in nifti1_io.c, due to some oversight ******/
1629 
1630 extern mat44 THD_mat44_mul( mat44 A , mat44 B ) ;      /* matrix multiply */
1631 
1632 static mat44 tempA_mat44 ;                   /* temp storage for matrices */
1633 static mat33 tempZ_mat33 ;
1634 
1635 extern mat44 THD_mat44_sqrt( mat44 A ) ;  /* matrix square root [30 Jul 2007] */
1636 
1637 /* function to return rotation matrix of angle
1638    theta (radians) about unit vector (ax,ay,az) [05 Nov 2020] */
1639 
1640 extern mat33 THD_mat33_generic_rotation( float theta, float ax, float ay, float az ) ;
1641 
1642 typedef struct {  /* holds a matrix plus 3D grid dimensions */
1643   mat44 mat ;
1644   int nx,ny,nz ;
1645 } mat44_nxyz ;
1646 
1647 extern float MAT44_angle( mat44 amat , mat44 bmat ) ;
1648 extern mat44 MAT44_to_rotation( mat44 amat ) ;
1649 
1650 #undef  MAT44_MUL
1651 #define MAT44_MUL THD_mat44_mul
1652 
1653 #undef  MAT33_MUL
1654 #define MAT33_MUL nifti_mat33_mul
1655 
1656 #undef  MAT44_SQRT
1657 #define MAT44_SQRT THD_mat44_sqrt
1658 
1659 #undef  MAT44_INV
1660 #define MAT44_INV nifti_mat44_inverse
1661 
1662 #undef  MAT33_INV
1663 #define MAT33_INV nifti_mat33_inverse
1664 
1665 #undef  ISVALID_MAT44
1666 #define ISVALID_MAT44(AA) ((AA).m[3][3] != 0.0f)
1667 
1668 #undef  INVALIDATE_MAT44
1669 #define INVALIDATE_MAT44(AA) ((AA).m[3][3] = 0.0f)
1670 
1671 #undef  ISZERO_MAT44
1672 #define ISZERO_MAT44(AA)  \
1673  ((AA.m[0][0] == 0.0f) && \
1674   (AA.m[0][1] == 0.0f) && \
1675   (AA.m[0][2] == 0.0f) && \
1676   (AA.m[0][3] == 0.0f) && \
1677   (AA.m[1][0] == 0.0f) && \
1678   (AA.m[1][1] == 0.0f) && \
1679   (AA.m[1][2] == 0.0f) && \
1680   (AA.m[1][3] == 0.0f) && \
1681   (AA.m[2][0] == 0.0f) && \
1682   (AA.m[2][1] == 0.0f) && \
1683   (AA.m[2][2] == 0.0f) && \
1684   (AA.m[2][3] == 0.0f)   )
1685 
1686 #undef  ISZERO_MAT33
1687 #define ISZERO_MAT33(AA)  \
1688  ((AA.m[0][0] == 0.0f) && \
1689   (AA.m[0][1] == 0.0f) && \
1690   (AA.m[0][2] == 0.0f) && \
1691   (AA.m[1][0] == 0.0f) && \
1692   (AA.m[1][1] == 0.0f) && \
1693   (AA.m[1][2] == 0.0f) && \
1694   (AA.m[2][0] == 0.0f) && \
1695   (AA.m[2][1] == 0.0f) && \
1696   (AA.m[2][2] == 0.0f)     )
1697 
1698 #undef  NORM_MAT33
1699 #define NORM_MAT33(MM) (fabsf(MM.m[0][0])+fabsf(MM.m[0][1])+fabsf(MM.m[0][2]) \
1700                        +fabsf(MM.m[1][0])+fabsf(MM.m[1][1])+fabsf(MM.m[1][2]) \
1701                        +fabsf(MM.m[2][0])+fabsf(MM.m[2][1])+fabsf(MM.m[2][2]) )
1702 
1703 #undef  ISIDENT_MAT44
1704 #define ISIDENT_MAT44(AA) \
1705  ((AA.m[0][0] == 1.0f) && \
1706   (AA.m[0][1] == 0.0f) && \
1707   (AA.m[0][2] == 0.0f) && \
1708   (AA.m[0][3] == 0.0f) && \
1709   (AA.m[1][0] == 0.0f) && \
1710   (AA.m[1][1] == 1.0f) && \
1711   (AA.m[1][2] == 0.0f) && \
1712   (AA.m[1][3] == 0.0f) && \
1713   (AA.m[2][0] == 0.0f) && \
1714   (AA.m[2][1] == 0.0f) && \
1715   (AA.m[2][2] == 1.0f) && \
1716   (AA.m[2][3] == 0.0f)   )
1717 
1718 #undef  ISIDENT_MAT33
1719 #define ISIDENT_MAT33(AA) \
1720  ((AA.m[0][0] == 1.0f) && \
1721   (AA.m[0][1] == 0.0f) && \
1722   (AA.m[0][2] == 0.0f) && \
1723   (AA.m[1][0] == 0.0f) && \
1724   (AA.m[1][1] == 1.0f) && \
1725   (AA.m[1][2] == 0.0f) && \
1726   (AA.m[2][0] == 0.0f) && \
1727   (AA.m[2][1] == 0.0f) && \
1728   (AA.m[2][2] == 1.0f)     )
1729 
1730 /* check if 2 mat44 matrices are equal-ish */
1731 
1732 #undef  FLEQ
1733 #define FLEQ(a,b) (fabsf((a)-(b)) < 0.0001f)
1734 
1735 #undef  MAT44_FLEQ
1736 #define MAT44_FLEQ(AA,BB)                                        \
1737  ( FLEQ(AA.m[0][0],BB.m[0][0]) && FLEQ(AA.m[0][1],BB.m[0][1]) && \
1738    FLEQ(AA.m[0][2],BB.m[0][2]) && FLEQ(AA.m[0][3],BB.m[0][3]) && \
1739    FLEQ(AA.m[1][0],BB.m[1][0]) && FLEQ(AA.m[1][1],BB.m[1][1]) && \
1740    FLEQ(AA.m[1][2],BB.m[1][2]) && FLEQ(AA.m[1][3],BB.m[1][3]) && \
1741    FLEQ(AA.m[2][0],BB.m[2][0]) && FLEQ(AA.m[2][1],BB.m[2][1]) && \
1742    FLEQ(AA.m[2][2],BB.m[2][2]) && FLEQ(AA.m[2][3],BB.m[2][3]) && \
1743    FLEQ(AA.m[3][0],BB.m[3][0]) && FLEQ(AA.m[3][1],BB.m[3][1]) && \
1744    FLEQ(AA.m[3][2],BB.m[3][2]) && FLEQ(AA.m[3][3],BB.m[3][3])   )
1745 
1746 /* compute sum of diffs of 2 mat44 matrices */
1747 
1748 #undef  FLDIF
1749 #define FLDIF(a,b) fabsf((a)-(b))
1750 
1751 #undef  MAT44_FLDIF
1752 #define MAT44_FLDIF(AA,BB)                                       \
1753  ( FLDIF(AA.m[0][0],BB.m[0][0]) + FLDIF(AA.m[0][1],BB.m[0][1]) + \
1754    FLDIF(AA.m[0][2],BB.m[0][2]) + FLDIF(AA.m[0][3],BB.m[0][3]) + \
1755    FLDIF(AA.m[1][0],BB.m[1][0]) + FLDIF(AA.m[1][1],BB.m[1][1]) + \
1756    FLDIF(AA.m[1][2],BB.m[1][2]) + FLDIF(AA.m[1][3],BB.m[1][3]) + \
1757    FLDIF(AA.m[2][0],BB.m[2][0]) + FLDIF(AA.m[2][1],BB.m[2][1]) + \
1758    FLDIF(AA.m[2][2],BB.m[2][2]) + FLDIF(AA.m[2][3],BB.m[2][3]) + \
1759    FLDIF(AA.m[3][0],BB.m[3][0]) + FLDIF(AA.m[3][1],BB.m[3][1]) + \
1760    FLDIF(AA.m[3][2],BB.m[3][2]) + FLDIF(AA.m[3][3],BB.m[3][3])    )
1761 
1762 /* load the top 3 rows of a mat44 matrix,
1763    and set the 4th row to [ 0 0 0 1], as required */
1764 
1765 #undef  LOAD_MAT44
1766 #define LOAD_MAT44(AA,a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34)    \
1767   ( AA.m[0][0]=a11 , AA.m[0][1]=a12 , AA.m[0][2]=a13 , AA.m[0][3]=a14 ,   \
1768     AA.m[1][0]=a21 , AA.m[1][1]=a22 , AA.m[1][2]=a23 , AA.m[1][3]=a24 ,   \
1769     AA.m[2][0]=a31 , AA.m[2][1]=a32 , AA.m[2][2]=a33 , AA.m[2][3]=a34 ,   \
1770     AA.m[3][0]=AA.m[3][1]=AA.m[3][2]=0.0f , AA.m[3][3]=1.0f            )
1771 
1772 #undef  LOAD_DIAG_MAT44
1773 #define LOAD_DIAG_MAT44(AA,a,b,c)                                         \
1774   LOAD_MAT44( AA , (a),0,0,0 , 0,(b),0,0 , 0,0,(c),0 )
1775 
1776 #undef  LOAD_IDENT_MAT44
1777 #define LOAD_IDENT_MAT44(AA)                                              \
1778   LOAD_MAT44( AA , 1,0,0,0 , 0,1,0,0 , 0,0,1,0 )
1779 
1780 #undef  ZERO_MAT44
1781 #define ZERO_MAT44(AA)  LOAD_DIAG_MAT44(AA,0.0,0.0,0.0)
1782 #undef  LOAD_ZERO_MAT44
1783 #define LOAD_ZERO_MAT44 ZERO_MAT44
1784 
1785 #undef  LOAD_MAT44_VEC
1786 #define LOAD_MAT44_VEC(AA,x,y,z) ( AA.m[0][3]=(x) , AA.m[1][3]=(y) , AA.m[2][3]=(z) )
1787 
1788 #undef  UNLOAD_MAT44_VEC
1789 #define UNLOAD_MAT44_VEC(AA,x,y,z) ( (x)=AA.m[0][3] , (y)=AA.m[1][3] , (z)=AA.m[2][3] )
1790 
1791 #undef  UNLOAD_MAT44
1792 #define UNLOAD_MAT44(AA,a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34)  \
1793   ( a11=AA.m[0][0] , a12=AA.m[0][1] , a13=AA.m[0][2] , a14=AA.m[0][3] ,   \
1794     a21=AA.m[1][0] , a22=AA.m[1][1] , a23=AA.m[1][2] , a24=AA.m[1][3] ,   \
1795     a31=AA.m[2][0] , a32=AA.m[2][1] , a33=AA.m[2][2] , a34=AA.m[2][3]  )
1796 
1797 #undef  UNLOAD_MAT44_AR
1798 #define UNLOAD_MAT44_AR(AA,vv)                                       \
1799  UNLOAD_MAT44(AA,(vv)[0],(vv)[1],(vv)[2],(vv)[3],(vv)[4 ],(vv)[5 ],  \
1800                  (vv)[6],(vv)[7],(vv)[8],(vv)[9],(vv)[10],(vv)[11] )
1801 
1802 #undef  LOAD_MAT44_AR
1803 #define LOAD_MAT44_AR(AA,vv)                                       \
1804  LOAD_MAT44(AA,(vv)[0],(vv)[1],(vv)[2],(vv)[3],(vv)[4 ],(vv)[5 ],  \
1805                (vv)[6],(vv)[7],(vv)[8],(vv)[9],(vv)[10],(vv)[11] )
1806 
1807 #undef  UNLOAD_MAT33
1808 #define UNLOAD_MAT33(AA,a11,a12,a13,a21,a22,a23,a31,a32,a33) \
1809   ( a11=AA.m[0][0] , a12=AA.m[0][1] , a13=AA.m[0][2] ,       \
1810     a21=AA.m[1][0] , a22=AA.m[1][1] , a23=AA.m[1][2] ,       \
1811     a31=AA.m[2][0] , a32=AA.m[2][1] , a33=AA.m[2][2]  )
1812 
1813 #undef  UNLOAD_MAT33_AR
1814 #define UNLOAD_MAT33_AR(AA,vv)                               \
1815  UNLOAD_MAT33(AA,(vv)[0],(vv)[1],(vv)[2],(vv)[3],            \
1816                  (vv)[4],(vv)[5],(vv)[6],(vv)[7],(vv)[8] )
1817 
1818 /* negate the top 2 rows of a mat44 matrix
1819    (for transforming between NIfTI-1 and DICOM coord systems) */
1820 
1821 #undef  XYINVERT_MAT44
1822 #define XYINVERT_MAT44(AA)                                  \
1823   ( AA.m[0][0] = -AA.m[0][0] , AA.m[0][1] = -AA.m[0][1] ,   \
1824      AA.m[0][2] = -AA.m[0][2] , AA.m[0][3] = -AA.m[0][3] ,  \
1825     AA.m[1][0] = -AA.m[1][0] , AA.m[1][1] = -AA.m[1][1] ,   \
1826      AA.m[1][2] = -AA.m[1][2] , AA.m[1][3] = -AA.m[1][3] )
1827 
1828 #undef MAT44_SUB
1829 #define MAT44_SUB(AA,BB)                                       \
1830  ( tempA_mat44.m[0][0] = (AA).m[0][0] - (BB).m[0][0] , \
1831    tempA_mat44.m[1][0] = (AA).m[1][0] - (BB).m[1][0] , \
1832    tempA_mat44.m[2][0] = (AA).m[2][0] - (BB).m[2][0] , \
1833    tempA_mat44.m[3][0] = (AA).m[3][0] - (BB).m[3][0] , \
1834    tempA_mat44.m[0][1] = (AA).m[0][1] - (BB).m[0][1] , \
1835    tempA_mat44.m[1][1] = (AA).m[1][1] - (BB).m[1][1] , \
1836    tempA_mat44.m[2][1] = (AA).m[2][1] - (BB).m[2][1] , \
1837    tempA_mat44.m[3][1] = (AA).m[3][1] - (BB).m[3][1] , \
1838    tempA_mat44.m[0][2] = (AA).m[0][2] - (BB).m[0][2] , \
1839    tempA_mat44.m[1][2] = (AA).m[1][2] - (BB).m[1][2] , \
1840    tempA_mat44.m[2][2] = (AA).m[2][2] - (BB).m[2][2] , \
1841    tempA_mat44.m[3][2] = (AA).m[3][2] - (BB).m[3][2] , \
1842    tempA_mat44.m[0][3] = (AA).m[0][3] - (BB).m[0][3] , \
1843    tempA_mat44.m[1][3] = (AA).m[1][3] - (BB).m[1][3] , \
1844    tempA_mat44.m[2][3] = (AA).m[2][3] - (BB).m[2][3] , \
1845    tempA_mat44.m[3][3] = (AA).m[3][3] - (BB).m[3][3] , tempA_mat44 )
1846 
1847 #undef  MAT44_NORM
1848 #define MAT44_NORM(AA)             \
1849  sqrt( (AA).m[0][0]*(AA).m[0][0] + \
1850        (AA).m[0][1]*(AA).m[0][1] + \
1851        (AA).m[0][2]*(AA).m[0][2] + \
1852        (AA).m[0][3]*(AA).m[0][3] + \
1853        (AA).m[1][0]*(AA).m[1][0] + \
1854        (AA).m[1][1]*(AA).m[1][1] + \
1855        (AA).m[1][2]*(AA).m[1][2] + \
1856        (AA).m[1][3]*(AA).m[1][3] + \
1857        (AA).m[2][0]*(AA).m[2][0] + \
1858        (AA).m[2][1]*(AA).m[2][1] + \
1859        (AA).m[2][2]*(AA).m[2][2] + \
1860        (AA).m[2][3]*(AA).m[2][3] + \
1861        (AA).m[3][0]*(AA).m[3][0] + \
1862        (AA).m[3][1]*(AA).m[3][1] + \
1863        (AA).m[3][2]*(AA).m[3][2] + \
1864        (AA).m[3][3]*(AA).m[3][3]  )
1865 
1866 #undef  MAT44_COLNORM
1867 #define MAT44_COLNORM(AA,j)            \
1868  sqrt( (AA).m[0][(j)]*(AA).m[0][(j)] + \
1869        (AA).m[1][(j)]*(AA).m[1][(j)] + \
1870        (AA).m[2][(j)]*(AA).m[2][(j)]  )
1871 
1872 #undef  MAT44_ROWNORM
1873 #define MAT44_ROWNORM(i)               \
1874  sqrt( (AA).m[(i)][0]*(AA).m[(i)][0] + \
1875        (AA).m[(i)][1]*(AA).m[(i)][1] + \
1876        (AA).m[(i)][2]*(AA).m[(i)][2]  )
1877 
1878 /* load a mat33 matrix */
1879 
1880 #undef  LOAD_MAT33
1881 #define LOAD_MAT33(AA,a11,a12,a13,a21,a22,a23,a31,a32,a33)  \
1882   ( AA.m[0][0]=a11 , AA.m[0][1]=a12 , AA.m[0][2]=a13 ,      \
1883     AA.m[1][0]=a21 , AA.m[1][1]=a22 , AA.m[1][2]=a23 ,      \
1884     AA.m[2][0]=a31 , AA.m[2][1]=a32 , AA.m[2][2]=a33  )
1885 
1886 /* fill a mat33 with zeros */
1887 
1888 #undef  LOAD_ZERO_MAT33
1889 #define LOAD_ZERO_MAT33(AA) LOAD_MAT33(AA,0,0,0,0,0,0,0,0,0)
1890 
1891 /* fill a mat33 with the identity matrix */
1892 
1893 #undef  LOAD_IDENT_MAT33
1894 #define LOAD_IDENT_MAT33(AA)               \
1895   LOAD_MAT33( AA , 1,0,0, 0,1,0 , 0,0,1 )
1896 
1897 /* copy the upper left corner of a mat44 struct into a mat33 struct */
1898 
1899 #undef  MAT44_TO_MAT33
1900 #define MAT44_TO_MAT33(AA,BB)                      \
1901   LOAD_MAT33(BB,AA.m[0][0],AA.m[0][1],AA.m[0][2],  \
1902                 AA.m[1][0],AA.m[1][1],AA.m[1][2],  \
1903                 AA.m[2][0],AA.m[2][1],AA.m[2][2] )
1904 
1905 /* the reverse: copy mat33 to mat44 upper left corner */
1906 
1907 #undef  MAT33_TO_MAT44
1908 #define MAT33_TO_MAT44(AA,BB)                            \
1909    LOAD_MAT44(BB,AA.m[0][0],AA.m[0][1],AA.m[0][2],0.0f,  \
1910                  AA.m[1][0],AA.m[1][1],AA.m[1][2],0.0f,  \
1911                  AA.m[2][0],AA.m[2][1],AA.m[2][2],0.0f )
1912 
1913 /* cf. vecmat.h */
1914 
1915 #undef  VECMAT_TO_MAT44
1916 #define VECMAT_TO_MAT44(vm,AA)                                                \
1917  LOAD_MAT44(AA,vm.mm.mat[0][0],vm.mm.mat[0][1],vm.mm.mat[0][2],vm.vv.xyz[0],  \
1918                vm.mm.mat[1][0],vm.mm.mat[1][1],vm.mm.mat[1][2],vm.vv.xyz[1],  \
1919                vm.mm.mat[2][0],vm.mm.mat[2][1],vm.mm.mat[2][2],vm.vv.xyz[2] )
1920 
1921 #undef  MAT44_TO_VECMAT
1922 #define MAT44_TO_VECMAT(AA,vm)                                                  \
1923  UNLOAD_MAT44(AA,vm.mm.mat[0][0],vm.mm.mat[0][1],vm.mm.mat[0][2],vm.vv.xyz[0],  \
1924                  vm.mm.mat[1][0],vm.mm.mat[1][1],vm.mm.mat[1][2],vm.vv.xyz[1],  \
1925                  vm.mm.mat[2][0],vm.mm.mat[2][1],vm.mm.mat[2][2],vm.vv.xyz[2] )
1926 
1927 /* apply a mat44 matrix to a 3 vector (x,y,z) to produce (a,b,c) */
1928 
1929 #undef  MAT44_VEC
1930 #define MAT44_VEC(AA,x,y,z,a,b,c)                                        \
1931  ( (a) = AA.m[0][0]*(x) + AA.m[0][1]*(y) + AA.m[0][2]*(z) + AA.m[0][3] , \
1932    (b) = AA.m[1][0]*(x) + AA.m[1][1]*(y) + AA.m[1][2]*(z) + AA.m[1][3] , \
1933    (c) = AA.m[2][0]*(x) + AA.m[2][1]*(y) + AA.m[2][2]*(z) + AA.m[2][3]  )
1934 
1935 /* apply a mat33 matrix to a 3 vector (x,y,z) to produce (a,b,c);
1936    could also be used to apply the upper left 3x3
1937    corner of a mat44 matrix to (x,y,z), if you insist */
1938 
1939 #undef  MAT33_VEC
1940 #define MAT33_VEC(AA,x,y,z,a,b,c)                           \
1941  ( (a) = AA.m[0][0]*(x) + AA.m[0][1]*(y) + AA.m[0][2]*(z) , \
1942    (b) = AA.m[1][0]*(x) + AA.m[1][1]*(y) + AA.m[1][2]*(z) , \
1943    (c) = AA.m[2][0]*(x) + AA.m[2][1]*(y) + AA.m[2][2]*(z)  )
1944 
1945 /* L2 norm of i-th column of a matrix (3x3 or 4x4) */
1946 
1947 #undef  MAT33_CLEN
1948 #define MAT33_CLEN(AA,i)  \
1949  sqrt(AA.m[0][i]*AA.m[0][i]+AA.m[1][i]*AA.m[1][i]+AA.m[2][i]*AA.m[2][i])
1950 
1951 #undef  MAT44_CLEN
1952 #define MAT44_CLEN MAT33_CLEN
1953 
1954 /* print a mat44 struct to stdout (with a string) */
1955 
1956 #undef  DUMP_MAT44
1957 #define DUMP_MAT44(SS,AA)                              \
1958      printf("# mat44 %s:\n"                            \
1959             " %13.6f %13.6f %13.6f  %13.6f\n"          \
1960             " %13.6f %13.6f %13.6f  %13.6f\n"          \
1961             " %13.6f %13.6f %13.6f  %13.6f\n" ,        \
1962   SS, AA.m[0][0], AA.m[0][1], AA.m[0][2], AA.m[0][3],  \
1963       AA.m[1][0], AA.m[1][1], AA.m[1][2], AA.m[1][3],  \
1964       AA.m[2][0], AA.m[2][1], AA.m[2][2], AA.m[2][3] )
1965 
1966 // vecmat.h oddly already contains a DUMP_MAT33, but I want one with
1967 // less formatting.
1968 #undef  DUMP_MAT33b
1969 #define DUMP_MAT33b(SS,AA)                              \
1970      printf("# mat33 %s:\n"                            \
1971             " %13.6f %13.6f %13.6f\n"                  \
1972             " %13.6f %13.6f %13.6f\n"                  \
1973             " %13.6f %13.6f %13.6f\n" ,                \
1974   SS, AA.m[0][0], AA.m[0][1], AA.m[0][2],              \
1975       AA.m[1][0], AA.m[1][1], AA.m[1][2],              \
1976       AA.m[2][0], AA.m[2][1], AA.m[2][2] )
1977 
1978 #undef  DUMP_MAT44_ONELINE
1979 #define DUMP_MAT44_ONELINE(AA)                         \
1980      printf(" %13.6f %13.6f %13.6f  %13.6f"            \
1981             " %13.6f %13.6f %13.6f  %13.6f"            \
1982             " %13.6f %13.6f %13.6f  %13.6f " ,         \
1983             AA.m[0][0], AA.m[0][1], AA.m[0][2], AA.m[0][3], \
1984             AA.m[1][0], AA.m[1][1], AA.m[1][2], AA.m[1][3], \
1985             AA.m[2][0], AA.m[2][1], AA.m[2][2], AA.m[2][3] )
1986 
1987 /* modify the last column of a mat44 struct so that the
1988    same spatial coords apply to an image with pp,qq,rr
1989    elements added at the lower edges [01 Sep 2006 - RWCox] */
1990 
1991 #undef  MAT44_EXTEND_IJK
1992 #define MAT44_EXTEND_IJK(AA,pp,qq,rr)                              \
1993  ( AA.m[0][3] -= AA.m[0][0]*(pp)+AA.m[0][1]*(qq)+AA.m[0][2]*(rr) , \
1994    AA.m[1][3] -= AA.m[1][0]*(pp)+AA.m[1][1]*(qq)+AA.m[1][2]*(rr) , \
1995    AA.m[2][3] -= AA.m[2][0]*(pp)+AA.m[2][1]*(qq)+AA.m[2][2]*(rr)  )
1996 
1997 /* elementary rotation matrices:
1998    rotate about axis #ff, from axis #aa toward #bb,
1999    where ff, aa, and bb are a permutation of {0,1,2} */
2000 
2001 #undef  LOAD_ROTGEN_MAT44
2002 #define LOAD_ROTGEN_MAT44(AA,th,ff,aa,bb)                             \
2003  ( AA.m[aa][aa] = AA.m[bb][bb] = cos((th)) ,                          \
2004    AA.m[aa][bb] = sin((th)) ,                                         \
2005    AA.m[bb][aa] = -AA.m[aa][bb] ,                                     \
2006    AA.m[ff][ff] = 1.0f ,                                              \
2007    AA.m[aa][ff] = AA.m[bb][ff] = AA.m[ff][aa] = AA.m[ff][bb] = 0.0f , \
2008    AA.m[0][3]   = AA.m[1][3]   = AA.m[2][3]   =                       \
2009    AA.m[3][0]   = AA.m[3][1]   = AA.m[3][2]   = 0.0f , AA.m[3][3]=1.0f  )
2010 
2011 
2012 /* rotations about x,y,z axes, respectively */
2013 
2014 #undef  LOAD_ROTX_MAT44
2015 #undef  LOAD_ROTY_MAT44
2016 #undef  LOAD_ROTZ_MAT44
2017 #define LOAD_ROTX_MAT44(A,th) LOAD_ROTGEN_MAT44(A,th,0,1,2)
2018 #define LOAD_ROTY_MAT44(A,th) LOAD_ROTGEN_MAT44(A,th,1,2,0)
2019 #define LOAD_ROTZ_MAT44(A,th) LOAD_ROTGEN_MAT44(A,th,2,0,1)
2020 
2021 /* rotation about axis #i, for i=0,1,2 (x,y,z) */
2022 
2023 #undef  LOAD_ROT_MAT44
2024 #define LOAD_ROT_MAT44(A,th,i)                    \
2025   do{ switch( (i) ){                              \
2026         case 0: LOAD_ROTX_MAT44(A,th)   ; break ; \
2027         case 1: LOAD_ROTY_MAT44(A,th)   ; break ; \
2028         case 2: LOAD_ROTZ_MAT44(A,th)   ; break ; \
2029        default: LOAD_DIAG_MAT44(A,1,1,1); break ; \
2030       } } while(0)
2031 
2032 /* determinant (could be used on a mat44 or mat33 struct) */
2033 
2034 #undef  MAT44_DET
2035 #define MAT44_DET(AA)                                                   \
2036  (  AA.m[0][0]*AA.m[1][1]*AA.m[2][2] - AA.m[0][0]*AA.m[1][2]*AA.m[2][1] \
2037   - AA.m[1][0]*AA.m[0][1]*AA.m[2][2] + AA.m[1][0]*AA.m[0][2]*AA.m[2][1] \
2038   + AA.m[2][0]*AA.m[0][1]*AA.m[1][2] - AA.m[2][0]*AA.m[0][2]*AA.m[1][1]   )
2039 
2040 /* trace */
2041 
2042 #undef  MAT44_TRACE
2043 #define MAT44_TRACE(AA) ( AA.m[0][0] + AA.m[1][1] + AA.m[2][2] )
2044 
2045 /* scale */
2046 
2047 #undef  MAT44_SCALE
2048 #define MAT44_SCALE(AA,ff)                                                                 \
2049  ( (AA).m[0][0] *= (ff), (AA).m[0][1] *= (ff), (AA).m[0][2] *= (ff), (AA).m[0][3] *= (ff), \
2050    (AA).m[1][0] *= (ff), (AA).m[1][1] *= (ff), (AA).m[1][2] *= (ff), (AA).m[1][3] *= (ff), \
2051    (AA).m[2][0] *= (ff), (AA).m[2][1] *= (ff), (AA).m[2][2] *= (ff), (AA).m[2][3] *= (ff)   )
2052 
2053 /* scale */
2054 
2055 #undef  MAT33_SCALE
2056 #define MAT33_SCALE(AA,ff)                                           \
2057  ( (AA).m[0][0] *= (ff), (AA).m[0][1] *= (ff), (AA).m[0][2] *= (ff), \
2058    (AA).m[1][0] *= (ff), (AA).m[1][1] *= (ff), (AA).m[1][2] *= (ff), \
2059    (AA).m[2][0] *= (ff), (AA).m[2][1] *= (ff), (AA).m[2][2] *= (ff)    )
2060 
2061 /* add */
2062 
2063 #undef  MAT44_SUM
2064 #define MAT44_SUM(AA,ff,BB,gg)                                    \
2065   ( tempA_mat44.m[0][0] = (AA).m[0][0]*(ff) + (BB).m[0][0]*(gg) , \
2066     tempA_mat44.m[0][1] = (AA).m[0][1]*(ff) + (BB).m[0][1]*(gg) , \
2067     tempA_mat44.m[0][2] = (AA).m[0][2]*(ff) + (BB).m[0][2]*(gg) , \
2068     tempA_mat44.m[0][3] = (AA).m[0][3]*(ff) + (BB).m[0][3]*(gg) , \
2069     tempA_mat44.m[1][0] = (AA).m[1][0]*(ff) + (BB).m[1][0]*(gg) , \
2070     tempA_mat44.m[1][1] = (AA).m[1][1]*(ff) + (BB).m[1][1]*(gg) , \
2071     tempA_mat44.m[1][2] = (AA).m[1][2]*(ff) + (BB).m[1][2]*(gg) , \
2072     tempA_mat44.m[1][3] = (AA).m[1][3]*(ff) + (BB).m[1][3]*(gg) , \
2073     tempA_mat44.m[2][0] = (AA).m[2][0]*(ff) + (BB).m[2][0]*(gg) , \
2074     tempA_mat44.m[2][1] = (AA).m[2][1]*(ff) + (BB).m[2][1]*(gg) , \
2075     tempA_mat44.m[2][2] = (AA).m[2][2]*(ff) + (BB).m[2][2]*(gg) , \
2076     tempA_mat44.m[2][3] = (AA).m[2][3]*(ff) + (BB).m[2][3]*(gg) , tempA_mat44 )
2077 
2078 /* add */
2079 
2080 #undef  MAT33_SUM
2081 #define MAT33_SUM(AA,ff,BB,gg)                                    \
2082   ( tempZ_mat33.m[0][0] = (AA).m[0][0]*(ff) + (BB).m[0][0]*(gg) , \
2083     tempZ_mat33.m[0][1] = (AA).m[0][1]*(ff) + (BB).m[0][1]*(gg) , \
2084     tempZ_mat33.m[0][2] = (AA).m[0][2]*(ff) + (BB).m[0][2]*(gg) , \
2085     tempZ_mat33.m[1][0] = (AA).m[1][0]*(ff) + (BB).m[1][0]*(gg) , \
2086     tempZ_mat33.m[1][1] = (AA).m[1][1]*(ff) + (BB).m[1][1]*(gg) , \
2087     tempZ_mat33.m[1][2] = (AA).m[1][2]*(ff) + (BB).m[1][2]*(gg) , \
2088     tempZ_mat33.m[2][0] = (AA).m[2][0]*(ff) + (BB).m[2][0]*(gg) , \
2089     tempZ_mat33.m[2][1] = (AA).m[2][1]*(ff) + (BB).m[2][1]*(gg) , \
2090     tempZ_mat33.m[2][2] = (AA).m[2][2]*(ff) + (BB).m[2][2]*(gg) , tempZ_mat33 )
2091 
2092 /*---------------------------------------------------------------------*/
2093 /*--- Macros to work on augmented ([4][4]) affine transforms       ----*/
2094 #undef AFF44_IDENT
2095 #define AFF44_IDENT( M ) {\
2096    M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1.0; \
2097    M[0][1] = M[0][2] = M[0][3] = \
2098    M[1][0] = M[1][2] = M[1][3] = \
2099    M[2][0] = M[2][1] = M[2][3] = \
2100    M[3][0] = M[3][1] = M[3][2] = 0.0;\
2101 }
2102 
2103 #undef AFF44_ZERO
2104 #define AFF44_ZERO( M ) {\
2105    M[0][0] = M[1][1] = M[2][2] = M[3][3] =  \
2106    M[0][1] = M[0][2] = M[0][3] = \
2107    M[1][0] = M[1][2] = M[1][3] = \
2108    M[2][0] = M[2][1] = M[2][3] = \
2109    M[3][0] = M[3][1] = M[3][2] = 0.0;\
2110 }
2111 
2112 #undef AFF44_CARD_LOAD
2113 #define AFF44_CARD_LOAD( M , d0, d1, d2) {\
2114    M[0][0] = d0; M[1][1] = d1; M[2][2] = d2; M[3][3] = 1.0;\
2115    M[0][1] = M[0][2] = M[0][3] = \
2116    M[1][0] = M[1][2] = M[1][3] = \
2117    M[2][0] = M[2][1] = M[2][3] = \
2118    M[3][0] = M[3][1] = M[3][2] = 0.0;\
2119 }
2120 
2121 #undef AFF44_TO_V12
2122 #define AFF44_TO_V12( V, M ) { \
2123    V[0] = M[0][0]; V[1] = M[0][1]; V[2]  = M[0][2]; V[3]  = M[0][3];   \
2124    V[4] = M[1][0]; V[5] = M[1][1]; V[6]  = M[1][2]; V[7]  = M[1][3];   \
2125    V[8] = M[2][0]; V[9] = M[2][1]; V[10] = M[2][2]; V[11] = M[2][3];   \
2126 }
2127 
2128 #undef V12_TO_AFF44
2129 #define V12_TO_AFF44( M, V) { \
2130    M[0][0] = V[0]; M[0][1] = V[1]; M[0][2] = V[2];  M[0][3] = V[3];   \
2131    M[1][0] = V[4]; M[1][1] = V[5]; M[1][2] = V[6];  M[1][3] = V[7];   \
2132    M[2][0] = V[8]; M[2][1] = V[9]; M[2][2] = V[10]; M[2][3] = V[11];  \
2133    M[3][0] = 0.0;  M[3][1] = 0.0;  M[3][2] = 0.0;   M[3][3] = 1.0;    \
2134 }
2135 
2136 #undef AFF44_MULT_I
2137 #define AFF44_MULT_I( X, M, I ) { \
2138    X[0] = M[0][0]*I[0] + M[0][1]*I[1] + M[0][2]*I[2] + M[0][3]; \
2139    X[1] = M[1][0]*I[0] + M[1][1]*I[1] + M[1][2]*I[2] + M[1][3]; \
2140    X[2] = M[2][0]*I[0] + M[2][1]*I[1] + M[2][2]*I[2] + M[2][3]; \
2141 }
2142 
2143 /* This macro is for transforming a direction D, rather than
2144    a point in I */
2145 #undef AFF44_MULT_D
2146 #define AFF44_MULT_D( X, M, D ) { \
2147    X[0] = M[0][0]*D[0] + M[0][1]*D[1] + M[0][2]*D[2]; \
2148    X[1] = M[1][0]*D[0] + M[1][1]*D[1] + M[1][2]*D[2]; \
2149    X[2] = M[2][0]*D[0] + M[2][1]*D[1] + M[2][2]*D[2]; \
2150 }
2151 
2152 #undef  AFF44_MULT
2153 #define AFF44_MULT( M, A, B ) {\
2154    int i,j ;   \
2155    for( i=0 ; i < 3 ; i++ )   \
2156     for( j=0 ; j < 4 ; j++ )  \
2157      M[i][j] =    A[i][0] * B[0][j] + A[i][1] * B[1][j]   \
2158                 + A[i][2] * B[2][j] + A[i][3] * B[3][j] ; \
2159    M[3][0] = M[3][1] = M[3][2] = 0.0 ; M[3][3] = 1.0 ;  \
2160 }
2161 
2162 #undef MAT44_COPY
2163 #define MAT44_COPY( C, A ) {\
2164    int i,j ;   \
2165    for( i=0 ; i < 4 ; i++ )   \
2166     for( j=0 ; j < 4 ; j++ )  \
2167      C.m[i][j] =    A.m[i][j] ; \
2168 }
2169 
2170 #undef AFF44_COPY
2171 #define AFF44_COPY( C, A ) {\
2172    int i,j ;   \
2173    for( i=0 ; i < 4 ; i++ )   \
2174     for( j=0 ; j < 4 ; j++ )  \
2175      C[i][j] =    A[i][j] ; \
2176 }
2177 
2178 #undef MAT44_TO_AFF44
2179 #define MAT44_TO_AFF44( A, M ) {\
2180    int i,j ;   \
2181    for( i=0 ; i < 4 ; i++ )   \
2182     for( j=0 ; j < 4 ; j++ )  \
2183      A[i][j] =    M.m[i][j] ; \
2184 }
2185 
2186 #undef AFF44_TO_MAT44
2187 #define AFF44_TO_MAT44( M, A ) {\
2188    int i,j ;   \
2189    for( i=0 ; i < 4 ; i++ )   \
2190     for( j=0 ; j < 4 ; j++ )  \
2191      M.m[i][j] =    A[i][j] ; \
2192 }
2193 
2194 #undef AFF44_INV
2195 #define AFF44_INV( Ai, A ) {\
2196    mat44 M, Mi;                  \
2197    AFF44_TO_MAT44( M, A );  \
2198    Mi = MAT44_INV( M ); \
2199    MAT44_TO_AFF44 ( Ai, Mi ); \
2200 }
2201 
2202 
2203 #undef AFF44_LOAD
2204 #define AFF44_LOAD( C, a,b,c,d, e,f,g,h, i,j,k,l ) {\
2205    C[0][0]=a; C[0][1]=b; C[0][2]=c; C[0][3]=d;  \
2206    C[1][0]=e; C[1][1]=f; C[1][2]=g; C[1][3]=h;  \
2207    C[2][0]=i; C[2][1]=j; C[2][2]=k; C[2][3]=l;  \
2208    C[3][0]=0; C[3][1]=0; C[3][2]=0; C[3][3]=1;  \
2209 }
2210 
2211 /* Change transform matrix so that it applies to RAI space
2212    rather than LPI or vice versa.                             */
2213 #undef  AFF44_LPI_RAI_FLIP
2214 #define AFF44_LPI_RAI_FLIP( M , A )   {              \
2215    double F[4][4], T[4][4];                           \
2216    AFF44_LOAD( F , -1,0,0,0 , 0,-1,0,0 , 0,0,1,0 );   \
2217    AFF44_MULT( T , F , A );                           \
2218    AFF44_MULT( M , T , F );                             \
2219 }
2220 
2221 /* Show the matrix */
2222 #undef  AFF44_SHOW
2223 #define AFF44_SHOW( A , str)   {              \
2224    if (str) fprintf(stderr,"%s\n", str);   \
2225    fprintf(stderr,"%f\t%f\t%f\t%f\n"   \
2226                   "%f\t%f\t%f\t%f\n"   \
2227                   "%f\t%f\t%f\t%f\n"   \
2228                   "%f\t%f\t%f\t%f\n",  \
2229             A[0][0], A[0][1], A[0][2], A[0][3],  \
2230             A[1][0], A[1][1], A[1][2], A[1][3],  \
2231             A[2][0], A[2][1], A[2][2], A[2][3],  \
2232             A[3][0], A[3][1], A[3][2], A[3][3]); \
2233 }
2234 
2235 /*---------------------------------------------------------------------*/
2236 /*--- data structure for information about time axis of 3D dataset ----*/
2237 
2238 #define TIMEAXIS_TYPE 907
2239 
2240 #define UNITS_MSEC_TYPE  77001
2241 #define UNITS_SEC_TYPE   77002
2242 #define UNITS_HZ_TYPE    77003
2243 
2244 static char * UNITS_TYPE_labelstring[] = { "ms" , "s" , "Hz" } ;
2245 
2246 /*! Return a string for the units of the uu-th time unit type. */
2247 
2248 #define UNITS_TYPE_LABEL(uu) ( ((uu)<UNITS_MSEC_TYPE || (uu)>UNITS_HZ_TYPE) ? \
2249                                  "none" : \
2250                                  UNITS_TYPE_labelstring[(uu)-UNITS_MSEC_TYPE] )
2251 
2252 /*! Struct to hold information about the time axis of a 3D+time datset.
2253 
2254     For 3D+t datasets, there are ntt 3D times; the i-th one is centered
2255     at ttorg + ttdel*ii seconds, for ii=0..ntt-1.
2256     Also, ttdur = duration of each sample in time.
2257 
2258     If ( nsl > 0 && toff_sl != NULL), then the data was acquired as
2259     slices, not as a 3D block.  The slicing direction must be the
2260     dataset (not DICOM) z-axis.  The extra offset for the data at
2261     z is given by computing isl = (z - zorg_sl) / dz_sl + 0.5; the
2262     extra offset is then toff_sl[isl].  Note that dz_sl might be
2263     different from the dataxes zzdel because the dataset might actually
2264     be made up of duplicated slices (see program abut.c).
2265 
2266     All this is computed using the routine THD_timeof().
2267 
2268     When transformed, all the slice stuff will be ignored.  That's
2269     because the warped dataset z-direction will not be the same as the
2270     original dataset's z-direction.
2271 */
2272 
2273 typedef struct {
2274    int   type ;     /*!< TIMEAXIS_TYPE */
2275    int   ntt ;      /*!< Number of time points */
2276    float ttorg ;    /*!< Time origin (usually 0) */
2277    float ttdel ;    /*!< Fondly known as TR */
2278    float ttdur ;    /*!< Duration of image acquisition (usually not known) */
2279 
2280    int units_type ;  /*!< one of the UNITS_ codes */
2281 
2282    int     nsl ;      /*!< Number of slice-dependent time offsets */
2283    float * toff_sl ;  /*!< toff_sl[i] is time offset for slice #1 */
2284    float   zorg_sl ;  /*!< z-coordinate origin for slice offsets */
2285    float   dz_sl ;    /*!< z-coordinate spacing for slice offsets */
2286 } THD_timeaxis ;
2287 
2288 /*! Check if tax points to a valid THD_timeaxis struct. */
2289 
2290 #define ISVALID_TIMEAXIS(tax) ((tax) != NULL && (tax)->type == TIMEAXIS_TYPE)
2291 
2292 /*---------------------------------------------------------------------*/
2293 /*--------- data structure for statistics about a 3D dataset ----------*/
2294 
2295 #define STATISTICS_TYPE 17
2296 
2297 /*! Statistics about data in a sub-brick.
2298     (e.g., Used in the Define Function control panel in AFNI.)
2299 */
2300 
2301 typedef struct {
2302    float min ;      /*!< Smallest value in sub-brick */
2303    float max ;      /*!< Largest value in sub-brick */
2304 } THD_brick_stats ;
2305 
2306 /*! Collection of statistics about all sub-bricks. */
2307 
2308 typedef struct {
2309    int type ;                    /*!< STATISTICS_TYPE */
2310    int             nbstat ;      /*!< Number of entries below */
2311    THD_brick_stats *bstat ;      /*!< Array of entries for all sub-bricks */
2312    RwcPointer parent ;            /*!< Owner of this object */
2313 } THD_statistics ;
2314 
2315 /*! Check if st is a valid THD_statistics struct. */
2316 
2317 #define ISVALID_STATISTIC(st) ( (st) != NULL && (st)->type == STATISTICS_TYPE )
2318 
2319 /*! Check if bst is a valid sub-brick statistic. */
2320 
2321 #define ISVALID_BSTAT(bst) ( (bst).min <= (bst).max )
2322 
2323 /*! Make bst have invalid data. */
2324 
2325 #define INVALIDATE_BSTAT(bst) ( (bst).min = 1.0 , (bst).max = -1.0 )
2326 
2327 /*! Destroy a THD_statistics struct. */
2328 
2329 #define KILL_STATISTIC(st)          \
2330   do{ if( ISVALID_STATISTIC(st) ){  \
2331         RwcFree((char *)(st)->bstat) ; RwcFree((char *)(st)) ; } } while(0)
2332 
2333 /*--------------------------------------------------------------------*/
2334 
2335 typedef struct {
2336   float hbot , htop , hdel ; int nbin ;
2337   int *hist ;
2338 } THD_histogram ;
2339 
2340 #define HISTOGRAM_SET_TYPE 1743
2341 
2342 typedef struct {
2343   int type ;
2344   int           nbhist ;
2345   THD_histogram *bhist ;
2346   RwcPointer parent ;
2347 } THD_histogram_set ;
2348 
2349 /*--------------------------------------------------------------------*/
2350 /*--------------------  Unique ID code for a 3D dataset  -------------*/
2351 
2352 #ifndef IDCODE_PREFIX
2353 #  define MCW_IDPREFIX "NIH_"
2354 #else
2355 #  define MCW_IDPREFIX IDCODE_PREFIX
2356 #endif
2357 
2358 /*! Size of ID code string. 27 Sep 2001: increased from 16 to 32. */
2359 #define MCW_IDSIZE 32
2360 
2361 /*! Size of ID date string. */
2362 #define MCW_IDDATE 48
2363 
2364 /*! Struct to hold ID code for a dataset. */
2365 
2366 typedef struct {
2367   char str[MCW_IDSIZE] ;    /*!< Unique ID code string */
2368   char date[MCW_IDDATE] ;   /*!< Date string was generated */
2369 } MCW_idcode ;
2370 
2371 extern MCW_idcode MCW_new_idcode (void) ;
2372 extern void       MCW_hash_idcode( char *, struct THD_3dim_dataset * ) ;
2373 
2374 /*! Check if 2 ID code strings are equal. */
2375 
2376 #define EQUIV_IDCODES(id,ie) (strncmp((id).str,(ie).str,MCW_IDSIZE) == 0)
2377 
2378 /*! Check if 2 AFNI dataset pointers point to the same dataset struct. */
2379 
2380 #define EQUIV_DSETS(ds,es) \
2381    ( (ds)==(es) ||         \
2382      ((ds)!=NULL && (es)!=NULL && EQUIV_IDCODES((ds)->idcode,(es)->idcode)) )
2383 
2384 /*! Check if 2 AFNI dataset pointers are different but have the same ID codes. */
2385 
2386 #define DUPLICATE_DSETS(ds,es)   \
2387    ( (ds) != (es) &&             \
2388      (ds) != NULL &&             \
2389      (es) != NULL && EQUIV_IDCODES((ds)->idcode,(es)->idcode) )
2390 
2391 /*! Zero out the ID code. */
2392 
2393 #define ZERO_IDCODE(id)   ((id).str[0] = (id).date[0] = '\0')
2394 
2395 /*! Check if the ID code is zero. */
2396 
2397 #define ISZERO_IDCODE(id) ((id).str[0] == '\0')
2398 
2399 #define ATRNAME_IDSTRING  "IDCODE_STRING"
2400 #define ATRNAME_IDDATE    "IDCODE_DATE"
2401 #define ATRNAME_IDANATPAR "IDCODE_ANAT_PARENT"
2402 #define ATRNAME_IDWARPPAR "IDCODE_WARP_PARENT"
2403 
2404 /*----------------------------------------------------------------------*/
2405 /*------------------- how to present the coordinates -------------------*/
2406 
2407 /*! How to present coordinates to the user (vs. the internal RAI/DICOM order). */
2408 
2409 typedef struct {
2410    int xxsign , yysign , zzsign ,
2411        first  , second , third  ,
2412        xxor   , yyor   , zzor    ;
2413    char orcode[4] ;
2414 } THD_coorder ;
2415 
2416 extern void THD_coorder_fill( char * , THD_coorder * ) ;
2417 extern void THD_dicom_to_coorder( THD_coorder *, float *, float *, float * ) ;
2418 extern void THD_coorder_to_dicom( THD_coorder *, float *, float *, float * ) ;
2419 
2420 /*----------------------------------------------------------------------*/
2421 /*-------------- internal data structure for a 3D dataset --------------*/
2422 
2423 /* dataset type codes and string */
2424 
2425 #define HEAD_ANAT_TYPE 0
2426 #define HEAD_ANAT_STR  "3DIM_HEAD_ANAT"
2427 
2428 #define HEAD_FUNC_TYPE 1
2429 #define HEAD_FUNC_STR  "3DIM_HEAD_FUNC"
2430 
2431 #define GEN_ANAT_TYPE  2
2432 #define GEN_ANAT_STR   "3DIM_GEN_ANAT"
2433 
2434 #define GEN_FUNC_TYPE  3
2435 #define GEN_FUNC_STR   "3DIM_GEN_FUNC"
2436 
2437 #define FIRST_3DIM_TYPE 0
2438 #define LAST_3DIM_TYPE  3
2439 
2440 #define LONGEST_3DIM_TYPESTR strlen(HEAD_ANAT_STR)
2441 
2442 static char * DATASET_typestr[] = {
2443    HEAD_ANAT_STR , HEAD_FUNC_STR , GEN_ANAT_STR , GEN_FUNC_STR
2444 } ;
2445 
2446 /* view type codes, string, and viewcodes */
2447 
2448 #define VIEW_ORIGINAL_TYPE    0
2449 #define VIEW_ORIGINAL_STR     "Original View"
2450 #define VIEW_ORIGINAL_CODE    "orig"
2451 
2452 #define VIEW_ACPCALIGNED_TYPE 1
2453 #define VIEW_ACPCALIGNED_STR  "AC-PC Aligned"
2454 #define VIEW_ACPCALIGNED_CODE "acpc"
2455 
2456 #define VIEW_TALAIRACH_TYPE   2
2457 #define VIEW_TALAIRACH_STR    "Talairach View"
2458 #define VIEW_TALAIRACH_CODE   "tlrc"
2459 
2460 #define VIEW_REGISTERED_TYPE  3
2461 #define VIEW_REGISTERED_STR   "Registered View"
2462 #define VIEW_REGISTERED_CODE  "rgst"
2463 
2464 /*#define oldsessions 1*/
2465 #undef oldsessions
2466 #ifdef oldsessions
2467    #define FIRST_VIEW_TYPE 0
2468    #define LAST_VIEW_TYPE  2
2469    #define MAX_LAST_VIEW_TYPE 2
2470 #else
2471    #define FIRST_VIEW_TYPE 0
2472    #define LAST_VIEW_TYPE \
2473      (int)((int)get_nspaces()-1)
2474    #define MAX_LAST_VIEW_TYPE 10
2475 #endif
2476 #define LONGEST_VIEW_TYPESTR strlen(VIEW_REGISTERED_STR)
2477 
2478 static char * VIEW_typestr[] = {
2479    VIEW_ORIGINAL_STR  , VIEW_ACPCALIGNED_STR ,
2480    VIEW_TALAIRACH_STR , VIEW_REGISTERED_STR
2481 } ;
2482 
2483 static char * VIEW_codestr[] = {
2484    VIEW_ORIGINAL_CODE  , VIEW_ACPCALIGNED_CODE ,
2485    VIEW_TALAIRACH_CODE , VIEW_REGISTERED_CODE
2486 } ;
2487 
2488 /* function type codes, string, and prefixes */
2489 
2490 #define FUNC_FIM_TYPE       0
2491 #define FUNC_FIM_STR        "Intensity"
2492 #define FUNC_FIM_PREFIX     "fim"
2493 #define FUNC_FIM_LABEL      "fim"
2494 #define FUNC_FIM_DESCRIPTOR "Functional Intensity"
2495 #define FUNC_FIM_MASK       (1 << FUNC_FIM_TYPE)
2496 
2497 /** old PAIR type retained for compatibility **/
2498 
2499 #define FUNC_PAIR_TYPE   1
2500 #define FUNC_PAIR_STR    "Inten+Thr"
2501 #define FUNC_PAIR_PREFIX "fith"
2502 
2503 #define FUNC_THR_TYPE          FUNC_PAIR_TYPE
2504 #define FUNC_THR_STR           FUNC_PAIR_STR
2505 #define FUNC_THR_PREFIX        FUNC_PAIR_PREFIX
2506 #define FUNC_THR_TOP           1.0        /* maximum true value               */
2507 #define FUNC_THR_SCALE_SHORT   10000      /* stored short = this * true value */
2508 #define FUNC_THR_SCALE_BYTE    100        /* stored byte  = this * true value */
2509 #define FUNC_THR_LABEL         "Thr "     /* <= 4 characters!                 */
2510 #define FUNC_THR_DESCRIPTOR    "Old style threshold"
2511 #define FUNC_THR_MASK          (1 << FUNC_PAIR_TYPE)
2512 
2513 #define FUNC_COR_TYPE          2
2514 #define FUNC_COR_STR           "Inten+Cor"
2515 #define FUNC_COR_PREFIX        "fico"
2516 #define FUNC_COR_TOP           1.0
2517 #define FUNC_COR_SCALE_SHORT   10000
2518 #define FUNC_COR_SCALE_BYTE    100
2519 #define FUNC_COR_LABEL         "Corr"
2520 #define FUNC_COR_DESCRIPTOR    "Correlation Coefficient"
2521 #define FUNC_COR_MASK          (1 << FUNC_COR_TYPE)
2522 
2523 #define FUNC_TT_TYPE           3
2524 #define FUNC_TT_STR            "Inten+Ttest"
2525 #define FUNC_TT_PREFIX         "fitt"
2526 #define FUNC_TT_TOP           10.0
2527 #define FUNC_TT_SCALE_SHORT   1000
2528 #define FUNC_TT_SCALE_BYTE    10
2529 #define FUNC_TT_LABEL         "T-t "
2530 #define FUNC_TT_DESCRIPTOR    "Student t-statistic"
2531 #define FUNC_TT_MASK          (1 << FUNC_TT_TYPE)
2532 
2533                                                     /* 30 Oct 1996 */
2534 #define FUNC_FT_TYPE           4
2535 #define FUNC_FT_STR            "Inten+Ftest"
2536 #define FUNC_FT_PREFIX         "fift"
2537 #define FUNC_FT_TOP           100.0
2538 #define FUNC_FT_SCALE_SHORT   100
2539 #define FUNC_FT_SCALE_BYTE    1
2540 #define FUNC_FT_LABEL         "F-t "
2541 #define FUNC_FT_DESCRIPTOR    "Fisher F-statistic"
2542 #define FUNC_FT_MASK          (1 << FUNC_FT_TYPE)
2543 
2544                                                     /* 22 Jul 1997 */
2545 #define FUNC_ZT_TYPE           5
2546 #define FUNC_ZT_STR            "Inten+Ztest"
2547 #define FUNC_ZT_PREFIX         "fizt"
2548 #define FUNC_ZT_TOP           10.0
2549 #define FUNC_ZT_SCALE_SHORT   1000
2550 #define FUNC_ZT_SCALE_BYTE    10
2551 #define FUNC_ZT_LABEL         "Z-t "
2552 #define FUNC_ZT_DESCRIPTOR    "Normal (Gaussian) Z"
2553 #define FUNC_ZT_MASK          (1 << FUNC_ZT_TYPE)
2554 
2555                                                     /* 22 Jul 1997 */
2556 #define FUNC_CT_TYPE           6
2557 #define FUNC_CT_STR            "Inten+ChiSq"
2558 #define FUNC_CT_PREFIX         "fict"
2559 #define FUNC_CT_TOP           100.0
2560 #define FUNC_CT_SCALE_SHORT   100
2561 #define FUNC_CT_SCALE_BYTE    1
2562 #define FUNC_CT_LABEL         "ChiS"
2563 #define FUNC_CT_DESCRIPTOR    "Chi-Squared statistic"
2564 #define FUNC_CT_MASK          (1 << FUNC_CT_TYPE)
2565 
2566                                                     /* 22 Jul 1997 */
2567 #define FUNC_BT_TYPE           7
2568 #define FUNC_BT_STR            "Inten+Beta"
2569 #define FUNC_BT_PREFIX         "fibt"
2570 #define FUNC_BT_TOP           1.0
2571 #define FUNC_BT_SCALE_SHORT   10000
2572 #define FUNC_BT_SCALE_BYTE    100
2573 #define FUNC_BT_LABEL         "Beta"
2574 #define FUNC_BT_DESCRIPTOR    "Beta Distribution"
2575 #define FUNC_BT_MASK          (1 << FUNC_BT_TYPE)
2576 
2577                                                     /* 22 Jul 1997 */
2578 #define FUNC_BN_TYPE           8
2579 #define FUNC_BN_STR            "Inten+Binom"
2580 #define FUNC_BN_PREFIX         "fibn"
2581 #define FUNC_BN_TOP           100.0
2582 #define FUNC_BN_SCALE_SHORT   100
2583 #define FUNC_BN_SCALE_BYTE    1
2584 #define FUNC_BN_LABEL         "Bino"
2585 #define FUNC_BN_DESCRIPTOR    "Binomial Distribution"
2586 #define FUNC_BN_MASK          (1 << FUNC_BN_TYPE)
2587 
2588                                                     /* 22 Jul 1997 */
2589 #define FUNC_GT_TYPE           9
2590 #define FUNC_GT_STR            "Inten+Gamma"
2591 #define FUNC_GT_PREFIX         "figt"
2592 #define FUNC_GT_TOP           10.0
2593 #define FUNC_GT_SCALE_SHORT   1000
2594 #define FUNC_GT_SCALE_BYTE    10
2595 #define FUNC_GT_LABEL         "Gam "
2596 #define FUNC_GT_DESCRIPTOR    "Gamma Distribution"
2597 #define FUNC_GT_MASK          (1 << FUNC_GT_TYPE)
2598 
2599                                                     /* 22 Jul 1997 */
2600 #define FUNC_PT_TYPE          10
2601 #define FUNC_PT_STR            "Inten+Poisson"
2602 #define FUNC_PT_PREFIX         "fipt"
2603 #define FUNC_PT_TOP           100.0
2604 #define FUNC_PT_SCALE_SHORT   100
2605 #define FUNC_PT_SCALE_BYTE    1
2606 #define FUNC_PT_LABEL         "Pois"
2607 #define FUNC_PT_DESCRIPTOR    "Poisson Distribution"
2608 #define FUNC_PT_MASK          (1 << FUNC_PT_TYPE)
2609 
2610                                                    /* 30 Nov 1997 */
2611 #define FUNC_BUCK_TYPE          11
2612 #define FUNC_BUCK_STR           "Func-Bucket"
2613 #define FUNC_BUCK_PREFIX        "fbuc"
2614 #define FUNC_BUCK_TOP           1.0
2615 #define FUNC_BUCK_SCALE_SHORT   1
2616 #define FUNC_BUCK_SCALE_BYTE    1
2617 #define FUNC_BUCK_LABEL         "Buck"
2618 #define FUNC_BUCK_DESCRIPTOR    "Function Bucket"
2619 #define FUNC_BUCK_MASK          (1 << FUNC_BUCK_TYPE)
2620 
2621 #define FIRST_FUNC_TYPE  0
2622 #define LAST_FUNC_TYPE  11
2623 
2624 #define FIRST_STAT_TYPE  2
2625 #define LAST_STAT_TYPE  10
2626 
2627 #define FUNC_ALL_MASK (FUNC_FIM_MASK | FUNC_THR_MASK |                \
2628                        FUNC_COR_MASK | FUNC_TT_MASK  | FUNC_FT_MASK | \
2629                        FUNC_ZT_MASK  | FUNC_CT_MASK  | FUNC_BT_MASK | \
2630                        FUNC_BN_MASK  | FUNC_GT_MASK  | FUNC_PT_MASK | \
2631                        FUNC_BUCK_MASK                                    )
2632 
2633 #define LONGEST_FUNC_TYPESTR strlen(FUNC_PT_STR)
2634 
2635 static char * FUNC_typestr[] = {
2636    FUNC_FIM_STR , FUNC_THR_STR , FUNC_COR_STR , FUNC_TT_STR , FUNC_FT_STR ,
2637    FUNC_ZT_STR  , FUNC_CT_STR  , FUNC_BT_STR  ,
2638    FUNC_BN_STR  , FUNC_GT_STR  , FUNC_PT_STR  , FUNC_BUCK_STR
2639 } ;
2640 
2641 static char * FUNC_prefixstr[] = {
2642    FUNC_FIM_PREFIX , FUNC_THR_PREFIX , FUNC_COR_PREFIX ,
2643    FUNC_TT_PREFIX  , FUNC_FT_PREFIX  ,
2644    FUNC_ZT_PREFIX  , FUNC_CT_PREFIX  , FUNC_BT_PREFIX  ,
2645    FUNC_BN_PREFIX  , FUNC_GT_PREFIX  , FUNC_PT_PREFIX  , FUNC_BUCK_PREFIX
2646 } ;
2647 
2648 static float FUNC_topval[] = {
2649   1.0 , FUNC_THR_TOP , FUNC_COR_TOP , FUNC_TT_TOP , FUNC_FT_TOP ,
2650         FUNC_ZT_TOP  , FUNC_CT_TOP  , FUNC_BT_TOP ,
2651         FUNC_BN_TOP  , FUNC_GT_TOP  , FUNC_PT_TOP , FUNC_BUCK_TOP
2652 } ;
2653 
2654 static int FUNC_scale_short[] = {
2655   1 , FUNC_THR_SCALE_SHORT , FUNC_COR_SCALE_SHORT ,
2656       FUNC_TT_SCALE_SHORT  , FUNC_FT_SCALE_SHORT  ,
2657       FUNC_ZT_SCALE_SHORT  , FUNC_CT_SCALE_SHORT  , FUNC_BT_SCALE_SHORT ,
2658       FUNC_BN_SCALE_SHORT  , FUNC_GT_SCALE_SHORT  , FUNC_PT_SCALE_SHORT ,
2659       FUNC_BUCK_SCALE_SHORT
2660 } ;
2661 
2662 static int FUNC_scale_byte[] = {
2663   1 , FUNC_THR_SCALE_BYTE , FUNC_COR_SCALE_BYTE ,
2664       FUNC_TT_SCALE_BYTE  , FUNC_FT_SCALE_BYTE  ,
2665       FUNC_ZT_SCALE_BYTE  , FUNC_CT_SCALE_BYTE  , FUNC_BT_SCALE_BYTE ,
2666       FUNC_BN_SCALE_BYTE  , FUNC_GT_SCALE_BYTE  , FUNC_PT_SCALE_BYTE ,
2667       FUNC_BUCK_SCALE_BYTE
2668 } ;
2669 
2670 static char * FUNC_label[] = {
2671   FUNC_FIM_LABEL , FUNC_THR_LABEL , FUNC_COR_LABEL , FUNC_TT_LABEL , FUNC_FT_LABEL ,
2672   FUNC_ZT_LABEL  , FUNC_CT_LABEL  , FUNC_BT_LABEL ,
2673   FUNC_BN_LABEL  , FUNC_GT_LABEL  , FUNC_PT_LABEL , FUNC_BUCK_LABEL
2674 } ;
2675 
2676 static char * FUNC_descriptor[] = {
2677   FUNC_FIM_DESCRIPTOR , FUNC_THR_DESCRIPTOR ,
2678   FUNC_COR_DESCRIPTOR , FUNC_TT_DESCRIPTOR  , FUNC_FT_DESCRIPTOR ,
2679   FUNC_ZT_DESCRIPTOR  , FUNC_CT_DESCRIPTOR  , FUNC_BT_DESCRIPTOR ,
2680   FUNC_BN_DESCRIPTOR  , FUNC_GT_DESCRIPTOR  , FUNC_PT_DESCRIPTOR ,
2681   FUNC_BUCK_DESCRIPTOR
2682 } ;
2683 
2684 #define AFNI_FIRST_STATCODE FUNC_COR_TYPE
2685 #define AFNI_LAST_STATCODE  FUNC_PT_TYPE
2686 
2687 static int FUNC_nvals[]    = {  1, 2,2,2,2,2,2,2,2,2,2, 1 } ; /* # in each dataset */
2688 static int FUNC_ival_fim[] = {  0, 0,0,0,0,0,0,0,0,0,0, 0 } ; /* index of fim      */
2689 
2690 #define FIMTHR 0   /* set = -1 to disable thresholding for FIM type - 06 Feb 2003 */
2691 
2692 static int FUNC_ival_thr[] = { FIMTHR, 1,1,1,1,1,1,1,1,1,1, 0 } ; /* index of thresh */
2693 
2694 #define FUNC_HAVE_FIM(ftyp)  ((ftyp) >= 0 && \
2695                               (ftyp) <= LAST_FUNC_TYPE && FUNC_ival_fim[(ftyp)] >= 0)
2696 
2697 #define FUNC_HAVE_THR(ftyp)  ((ftyp) >= 0 && \
2698                               (ftyp) <= LAST_FUNC_TYPE && FUNC_ival_thr[(ftyp)] >= 0)
2699 
2700 #define FUNC_IS_STAT(ftyp)   ((ftyp) >= FIRST_STAT_TYPE && (ftyp) <= LAST_STAT_TYPE)
2701 #define FUNC_HAVE_PVAL       FUNC_IS_STAT
2702 
2703 #define STAT_SIDES(fcod)     \
2704  ( !FUNC_IS_STAT(fcod) ? 0   \
2705   : ((fcod)==FUNC_COR_TYPE || (fcod)==FUNC_TT_TYPE || (fcod)==FUNC_ZT_TYPE) ? 2 : 1 )
2706 
2707 /******* dimension of auxiliary array for functional statistics *******/
2708 
2709 #define MAX_STAT_AUX 64
2710 
2711 /*! Number of statistical parameters needed for each statistic code. */
2712 
2713 static int FUNC_need_stat_aux[] = { 0 , 0 , 3 , 1 , 2 ,
2714                                     0 , 1 , 2 , 2 , 2 , 1 ,
2715                                     0 } ; /* # aux data needed */
2716 
2717 /*! Labels describing the parameters needed for each statistic code. */
2718 
2719 static char * FUNC_label_stat_aux[] = {
2720    "N/A" , "N/A" ,                                      /* fim, fith */
2721    "SAMPLES  FIT-PARAMETERS  ORT-PARAMETERS" ,          /* fico */
2722    "DEGREES-of-FREEDOM" ,                               /* fitt */
2723    "NUMERATOR and DENOMINATOR DEGREES-of-FREEDOM" ,     /* fift */
2724    "N/A" ,                                              /* fizt */
2725    "DEGREES-of-FREEDOM" ,                               /* fict */
2726    "A (numerator) and B (denominator)" ,                /* fibt */
2727    "NUMBER-of-TRIALS and PROBABILITY-per-TRIAL" ,       /* fibn */
2728    "SHAPE and SCALE" ,                                  /* figt */
2729    "MEAN" ,                                             /* fipt */
2730    "N/A"                                                /* fbuc */
2731 } ;
2732 
2733 /***  stat_aux values:
2734         FUNC_FIM_TYPE = not used
2735         FUNC_THR_TYPE = not used
2736         FUNC_COR_TYPE = # samples, # fit parameters, # ort parameters
2737         FUNC_TT_TYPE  = # degrees of freedom
2738         FUNC_FT_TYPE  = DOF for numerator and denominator
2739         FUNC_ZT_TYPE  = not used
2740         FUNC_CT_TYPE  = DOF
2741         FUNC_BT_TYPE  = a and b parameters
2742         FUNC_BN_TYPE  = number of trials, and probability per trial
2743         FUNC_GT_TYPE  = shape and scale parameters
2744         FUNC_PT_TYPE  = mean of Poisson distribution
2745       FUNC_BUCK_TYPE  = not used
2746 ***********************************************************************/
2747 
2748 /****   anatomy type codes, strings, and prefixes        ****/
2749 /* (these are not used much at present, but may be someday) */
2750 
2751 #define ANAT_SPGR_TYPE   0
2752 #define ANAT_SPGR_STR    "Spoiled GRASS"
2753 #define ANAT_SPGR_PREFIX "spgr"
2754 #define ANAT_SPGR_MASK   (1 << ANAT_SPGR_TYPE)
2755 
2756 #define ANAT_FSE_TYPE    1
2757 #define ANAT_FSE_STR     "Fast Spin Echo"
2758 #define ANAT_FSE_PREFIX  "fse"
2759 #define ANAT_FSE_MASK    (1 << ANAT_FSE_TYPE)
2760 
2761 #define ANAT_EPI_TYPE    2
2762 #define ANAT_EPI_STR     "Echo Planar"
2763 #define ANAT_EPI_PREFIX  "epan"
2764 #define ANAT_EPI_MASK    (1 << ANAT_EPI_TYPE)
2765 
2766 #define ANAT_MRAN_TYPE   3
2767 #define ANAT_MRAN_STR    "MRI Anatomy"
2768 #define ANAT_MRAN_PREFIX "anat"
2769 #define ANAT_MRAN_MASK   (1 << ANAT_MRAN_TYPE)
2770 
2771 #define ANAT_CT_TYPE     4
2772 #define ANAT_CT_STR      "CT Scan"
2773 #define ANAT_CT_PREFIX   "ct"
2774 #define ANAT_CT_MASK     (1 << ANAT_CT_TYPE)
2775 
2776 #define ANAT_SPECT_TYPE   5
2777 #define ANAT_SPECT_STR    "SPECT Anatomy"
2778 #define ANAT_SPECT_PREFIX "spct"
2779 #define ANAT_SPECT_MASK   (1 << ANAT_SPECT_TYPE)
2780 
2781 #define ANAT_PET_TYPE     6
2782 #define ANAT_PET_STR      "PET Anatomy"
2783 #define ANAT_PET_PREFIX   "pet"
2784 #define ANAT_PET_MASK     (1 << ANAT_PET_TYPE)
2785 
2786 #define ANAT_MRA_TYPE    7
2787 #define ANAT_MRA_STR     "MR Angiography"
2788 #define ANAT_MRA_PREFIX  "mra"
2789 #define ANAT_MRA_MASK    (1 << ANAT_MRA_TYPE)
2790 
2791 #define ANAT_BMAP_TYPE   8
2792 #define ANAT_BMAP_STR    "B-field Map"
2793 #define ANAT_BMAP_PREFIX "bmap"
2794 #define ANAT_BMAP_MASK   (1 << ANAT_BMAP_TYPE)
2795 
2796 #define ANAT_DIFF_TYPE   9
2797 #define ANAT_DIFF_STR    "Diffusion Map"
2798 #define ANAT_DIFF_PREFIX "diff"
2799 #define ANAT_DIFF_MASK   (1 << ANAT_DIFF_TYPE)
2800 
2801 #define ANAT_OMRI_TYPE   10
2802 #define ANAT_OMRI_STR    "Other MRI"
2803 #define ANAT_OMRI_PREFIX "omri"
2804 #define ANAT_OMRI_MASK   (1 << ANAT_OMRI_TYPE)
2805 
2806 #define ANAT_BUCK_TYPE   11
2807 #define ANAT_BUCK_STR    "Anat Bucket"
2808 #define ANAT_BUCK_PREFIX "abuc"
2809 #define ANAT_BUCK_MASK   (1 << ANAT_BUCK_TYPE)
2810 
2811 #define ANAT_MAPC_TYPE   12
2812 #define ANAT_MAPC_STR    "Mapped Color"
2813 #define ANAT_MAPC_PREFIX "mapc"
2814 #define ANAT_MAPC_MASK   (1 << ANAT_MAPC_TYPE)
2815 
2816 #define FIRST_ANAT_TYPE  0
2817 #define LAST_ANAT_TYPE   11
2818 
2819 #define ANAT_ALL_MASK ( ANAT_SPGR_MASK | ANAT_FSE_MASK | ANAT_EPI_MASK   | \
2820                         ANAT_MRAN_MASK | ANAT_CT_MASK  | ANAT_SPECT_MASK | \
2821                         ANAT_PET_MASK  | ANAT_MRA_MASK | ANAT_BMAP_MASK  | \
2822                         ANAT_DIFF_MASK | ANAT_OMRI_MASK| ANAT_BUCK_MASK  | \
2823                         ANAT_MAPC_MASK )
2824 
2825 #define NUM_DSET_TYPES (LAST_FUNC_TYPE + LAST_ANAT_TYPE + 2)
2826 
2827 #define LONGEST_ANAT_TYPESTR strlen(ANAT_MRA_STR)
2828 
2829 static char * ANAT_typestr[] = {
2830  ANAT_SPGR_STR , ANAT_FSE_STR   , ANAT_EPI_STR  , ANAT_MRAN_STR ,
2831  ANAT_CT_STR   , ANAT_SPECT_STR , ANAT_PET_STR  ,
2832  ANAT_MRA_STR  , ANAT_BMAP_STR  , ANAT_DIFF_STR , ANAT_OMRI_STR ,
2833  ANAT_BUCK_STR , ANAT_MAPC_STR
2834 } ;
2835 
2836 static char * ANAT_prefixstr[] = {
2837  ANAT_SPGR_PREFIX , ANAT_FSE_PREFIX   , ANAT_EPI_PREFIX  , ANAT_MRAN_PREFIX ,
2838  ANAT_CT_PREFIX   , ANAT_SPECT_PREFIX , ANAT_PET_PREFIX  ,
2839  ANAT_MRA_PREFIX  , ANAT_BMAP_PREFIX  , ANAT_DIFF_PREFIX , ANAT_OMRI_PREFIX ,
2840  ANAT_BUCK_PREFIX , ANAT_MAPC_PREFIX
2841 } ;
2842 
2843 /* Feb 1998: put all together */
2844 
2845 static char * DSET_prefixstr[NUM_DSET_TYPES] = {
2846    FUNC_FIM_PREFIX , FUNC_THR_PREFIX , FUNC_COR_PREFIX ,
2847    FUNC_TT_PREFIX  , FUNC_FT_PREFIX  ,
2848    FUNC_ZT_PREFIX  , FUNC_CT_PREFIX  , FUNC_BT_PREFIX  ,
2849    FUNC_BN_PREFIX  , FUNC_GT_PREFIX  , FUNC_PT_PREFIX  , FUNC_BUCK_PREFIX ,
2850    ANAT_SPGR_PREFIX , ANAT_FSE_PREFIX   , ANAT_EPI_PREFIX  , ANAT_MRAN_PREFIX ,
2851    ANAT_CT_PREFIX   , ANAT_SPECT_PREFIX , ANAT_PET_PREFIX  ,
2852    ANAT_MRA_PREFIX  , ANAT_BMAP_PREFIX  , ANAT_DIFF_PREFIX , ANAT_OMRI_PREFIX ,
2853    ANAT_BUCK_PREFIX
2854 } ;
2855 
2856 #define DSET_PREFIXSTR(ds) ( ISFUNC(ds) ? FUNC_prefixstr[(ds)->func_type]  \
2857                                         : ANAT_prefixstr[(ds)->func_type] )
2858 
2859 #define DSET_FUNCLABEL(ds) ( ISFUNC(ds) ? FUNC_label[(ds)->func_type]      \
2860                                         : ANAT_prefixstr[(ds)->func_type] )
2861 
2862 #define DSET_TYPESTR(ds)   ( ISFUNC(ds) ? FUNC_typestr[(ds)->func_type]     \
2863                                         : ANAT_typestr[(ds)->func_type] )
2864 
2865 static int ANAT_nvals[]     = { 1,1,1,1,1,1,1,1,1,1,1,1 , 1 } ;
2866 static int ANAT_ival_zero[] = { 0,0,0,0,0,0,0,0,0,0,0,0 , 0 } ;
2867 
2868 /* the data structure itself */
2869 
2870 /*! One AFNI dataset structure.
2871     Most elements are accessed via macros, and should only be changed via EDIT_dset_items(). */
2872 
2873 typedef struct THD_3dim_dataset {
2874       int type ;        /*!< type code: HEAD_ANAT_TYPE or HEAD_FUNC_TYPE or GEN_ANAT_TYPE or GEN_FUNC_TYPE */
2875 
2876       int view_type ;   /*!< view code: VIEW_ORIGINAL_TYPE or VIEW_ACPCALIGNED_TYPE or VIEW_TALAIRACH_TYPE */
2877       int func_type ;   /*!< dataset type: one of FUNC_*_TYPE or ANAT_*_TYPE codes */
2878 
2879       char label1[THD_MAX_LABEL] ;  /*!< short label #1: not used for anything anymore */
2880       char label2[THD_MAX_LABEL] ;  /*!< short label #2: even more obsolete */
2881 
2882       THD_datablock   * dblk ;      /*!< pointer to actual data */
2883       THD_dataxes     * daxes ;     /*!< info about axes (where dataset is) */
2884       THD_dataxes     * wod_daxes ; /*!< warp-on-demand axes (for viewing interpolated dataset) */
2885       int               wod_flag ;  /*!< if true, use wod_daxes, otherwise use daxes */
2886 
2887       THD_timeaxis    * taxis ;     /*!< non-NULL --> this is a 3D+t dataset */
2888 
2889       THD_marker_set  * markers ;   /*!< user set mark points (if non-NULL) */
2890 
2891       struct THD_3dim_dataset * warp_parent ; /*!< non-NULL --> this dataset is warped from that one */
2892       THD_warp                * warp ;        /*!< this is the coordinate-to-coordinate warp */
2893       THD_warp                * vox_warp ;    /*!< this is the index-to-index warp */
2894 
2895       struct THD_3dim_dataset * anat_parent ;   /*!< non-NULL --> linked to this as anatomical ref */
2896 
2897       THD_statistics          * stats ;      /*!< statistics about the sub-brick data */
2898 
2899       float stat_aux[MAX_STAT_AUX] ;         /*!< global auxiliary statistics info */
2900 
2901       char warp_parent_name[THD_MAX_NAME] ;  /*!< "name" of warp_parent dataset (no longer used) */
2902       char anat_parent_name[THD_MAX_NAME] ;  /*!< "name" of anat_parent dataset (no longer used) */
2903       char self_name[THD_MAX_NAME]        ;  /*!< my own "name" (no longer used) */
2904 
2905 #ifdef ALLOW_DATASET_VLIST
2906       THD_vector_list * pts ;     /*!< in dataset coords (not DICOM order!) - for Ted Deyoe */
2907       RwcBoolean pts_original ;      /*!< true if was read from disk directly */
2908 #endif
2909 
2910       int death_mark ;            /*!< dataset is marked for destruction */
2911 
2912       MCW_idcode idcode ;              /*!< globally unique (I hope) ID code for this dataset */
2913       MCW_idcode anat_parent_idcode ;  /*!< ID code for warp_parent dataset */
2914       MCW_idcode warp_parent_idcode ;  /*!< ID code for anat_parent dataset */
2915 
2916       char * keywords ;           /*!< 30 Nov 1997: keyword list for dataset */
2917 
2918       THD_usertaglist * tagset ;  /*!< 23 Oct 1998: see plug_tag.c */
2919 
2920    /* pointers to other stuff */
2921 
2922       KILL_list kl ;              /*!< Stuff to delete if this dataset is deleted (see killer.h) */
2923       RwcPointer parent ;          /*!< Somebody that "owns" this dataset */
2924 
2925    /* 26 Aug 2002: self warp (for w-o-d) */
2926 
2927       THD_warp *self_warp ;
2928 
2929    /* 03 Aug 2004: list of filenames to cat together (cf. THD_open_tcat) */
2930 
2931       char *tcat_list ;
2932       int   tcat_num ;
2933       int  *tcat_len ;
2934 
2935    /* 26 Feb 2010: Pointer to VALUE_LABEL_DTABLE for ROI drawing labels*/
2936       void *Label_Dtable;
2937    /* 13 Mar 2009: atlas space */
2938       char atlas_space[THD_MAX_NAME] ;
2939    /* 18 Nov 2010: Pointer to ATLAS_LABEL_TABLE for atlas segmentation */
2940 /*      atlas_point_list *atlas_label_table;*/
2941 
2942    /* 31 Mar 2009: integer colormap for ROIs and atlases */
2943       int int_cmap ;
2944    /* 04 Jul 2010: temporary index to say which space the dataset is in */
2945       int space_index;
2946 
2947 } THD_3dim_dataset ;
2948 
2949 /*! A marker that defines a dataset that is about to be killed. */
2950 
2951 #define DOOMED 665
2952 
2953 /*! Mark a dataset to be eliminated by AFNI_mark_for_death() and AFNI_andersonville(). */
2954 
2955 #define DSET_MARK_FOR_DEATH(ds)                                         \
2956  do{ if( ISVALID_DSET(ds) && ds->death_mark >= 0 ) ds->death_mark = DOOMED ; } while(0)
2957 
2958 /*! Mark a dataset to be ineligible for elimination during AFNI_rescan_session(). */
2959 
2960 #define DSET_MARK_FOR_IMMORTALITY(ds)                                   \
2961  do{ if( ISVALID_DSET(ds) ) ds->death_mark = -1 ; } while(0)
2962 
2963 /*! Mark a dataset to be eligible for elimination if the need arises. */
2964 
2965 #define DSET_MARK_FOR_NORMAL(ds)                                        \
2966  do{ if( ISVALID_DSET(ds) ) ds->death_mark = 0 ; } while(0)
2967 
2968 /*! Dataset is tcat-ed? */
2969 
2970 #define DSET_IS_TCAT(ds) (ISVALID_DSET(ds) && (ds)->tcat_list != NULL && (ds)->tcat_num > 0)
2971 
2972 /*! Return pointer to current dataset axes (warp-on-demand or permanent). */
2973 
2974 #define CURRENT_DAXES(ds) (((ds)->wod_flag) ? ((ds)->wod_daxes) : ((ds)->daxes))
2975 
2976 /*! Determine if ds is a pointer to a valid dataset. */
2977 
2978 #define ISVALID_3DIM_DATASET(ds)                       \
2979    ( (ds) != NULL && (ds)->type >= FIRST_3DIM_TYPE  && \
2980                      (ds)->type <= LAST_3DIM_TYPE   && \
2981                 (ds)->view_type >= FIRST_VIEW_TYPE  && \
2982                 (ds)->view_type <= LAST_VIEW_TYPE   && \
2983       ISVALID_DATABLOCK((ds)->dblk)                     )
2984 
2985 /*! Determine if ds is a pointer to a valid dataset. */
2986 
2987 #define ISVALID_DSET ISVALID_3DIM_DATASET
2988 
2989 /*! Determine if nn is a functional dataset type code. */
2990 
2991 #define ISFUNCTYPE(nn) ( (nn) == HEAD_FUNC_TYPE || (nn) == GEN_FUNC_TYPE )
2992 
2993 /*! Determine if dset is a functional dataset. */
2994 
2995 #define ISFUNC(dset) ( ISVALID_DSET(dset) && ISFUNCTYPE((dset)->type) )
2996 
2997 /*! Determine if nn is an anatomical dataset type code. */
2998 
2999 #define ISANATTYPE(nn) ( (nn) == HEAD_ANAT_TYPE || (nn) == GEN_ANAT_TYPE )
3000 
3001 /*! Determine if dset is an anatomical dataset. */
3002 
3003 #define ISANAT(dset) ( ISVALID_DSET(dset) && ISANATTYPE((dset)->type) )
3004 
3005 /*! Determine if nn is a head dataset type code. */
3006 
3007 #define ISHEADTYPE(nn) ( (nn) == HEAD_ANAT_TYPE || (nn) == HEAD_FUNC_TYPE )  /* 09 Sep 2002: ==ugh */
3008 
3009 /*! Determine if dset is a head dataset (vs. non-head). */
3010 
3011 #define ISHEAD(dset) ( ISVALID_DSET(dset) && ISHEADTYPE((dset)->type) )
3012 
3013 /*! Determine if dset is an anatomical bucket dataset */
3014 
3015 #define ISANATBUCKET(dset) ( ISANAT(dset) && (dset)->func_type == ANAT_BUCK_TYPE )
3016 
3017 /*! Determine if dset is a functional bucket dataset */
3018 
3019 #define ISFUNCBUCKET(dset) ( ISFUNC(dset) && (dset)->func_type == FUNC_BUCK_TYPE )
3020 
3021 /*! Determine if dset is a bucket dataset (functional or anatomical) */
3022 
3023 #define ISBUCKET(dset) ( ISANATBUCKET(dset) || ISFUNCBUCKET(dset) )
3024 
3025 /*! Determine if dataset ds is actually stored on disk */
3026 
3027 #define DSET_ONDISK(ds) ( ISVALID_DSET(ds) && (ds)->dblk!=NULL && \
3028                           (ds)->dblk->diskptr->storage_mode!=STORAGE_UNDEFINED )
3029 
3030 /*! Determine if dataset ds is stored in a BRIK file on disk */
3031 
3032 #define DSET_IS_BRIK(ds) ( ISVALID_DSET(ds) && (ds)->dblk!=NULL && \
3033                            (ds)->dblk->diskptr->storage_mode == STORAGE_BY_BRICK )
3034 
3035 /*! Determine if datablock db is stored in a MINC file on disk */
3036 
3037 #define DBLK_IS_MINC(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) && \
3038                            (db)->diskptr->storage_mode == STORAGE_BY_MINC )
3039 
3040 /*! Determine if dataset ds is stored in a MINC file on disk */
3041 
3042 #define DSET_IS_MINC(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&       \
3043                            ISVALID_DISKPTR((ds)->dblk->diskptr) &&               \
3044                            (ds)->dblk->diskptr->storage_mode == STORAGE_BY_MINC )
3045 
3046 /*! Determine if datablock db is stored in a ANALYZE file on disk */
3047 
3048 #define DBLK_IS_ANALYZE(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) && \
3049                               (db)->diskptr->storage_mode == STORAGE_BY_ANALYZE )
3050 
3051 /*! Determine if dataset ds is stored in a ANALYZE file on disk */
3052 
3053 #define DSET_IS_ANALYZE(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&       \
3054                               ISVALID_DISKPTR((ds)->dblk->diskptr) &&               \
3055                               (ds)->dblk->diskptr->storage_mode == STORAGE_BY_ANALYZE )
3056 
3057 /*! Determine if datablock db is stored in a CTFMRI file on disk */
3058 
3059 #define DBLK_IS_CTFMRI(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) && \
3060                              (db)->diskptr->storage_mode == STORAGE_BY_CTFMRI )
3061 
3062 /*! Determine if dataset ds is stored in a CTFMRI file on disk */
3063 
3064 #define DSET_IS_CTFMRI(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&       \
3065                              ISVALID_DISKPTR((ds)->dblk->diskptr) &&               \
3066                              (ds)->dblk->diskptr->storage_mode == STORAGE_BY_CTFMRI )
3067 
3068 /*! Determine if datablock db is stored in a CTFSAM file on disk */
3069 
3070 #define DBLK_IS_CTFSAM(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) && \
3071                              (db)->diskptr->storage_mode == STORAGE_BY_CTFSAM )
3072 
3073 /*! Determine if dataset ds is stored in a CTFSAM file on disk */
3074 
3075 #define DSET_IS_CTFSAM(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&       \
3076                              ISVALID_DISKPTR((ds)->dblk->diskptr) &&               \
3077                              (ds)->dblk->diskptr->storage_mode == STORAGE_BY_CTFSAM )
3078 
3079 /*! Determine if datablock db is stored in a 1D file on disk */
3080 
3081 #define DBLK_IS_1D(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) &&     \
3082                          (db)->diskptr->storage_mode == STORAGE_BY_1D )
3083 
3084 /*! Determine if datablock db is stored in a 3D file on disk */
3085 
3086 #define DBLK_IS_3D(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) &&     \
3087                          (db)->diskptr->storage_mode == STORAGE_BY_3D )
3088 
3089 /*! Determine if datablock db is stored in a NIFTI file on disk */
3090 
3091 #define DBLK_IS_NIFTI(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) &&  \
3092                            (db)->diskptr->storage_mode == STORAGE_BY_NIFTI )
3093 
3094 /*! Determine if datablock db is stored in a NIML file on disk  26 May 2006 */
3095 
3096 #define DBLK_IS_NIML(db) ( ISVALID_DBLK(db)               &&  \
3097                            ISVALID_DISKPTR((db)->diskptr) &&  \
3098                            (db)->diskptr->storage_mode == STORAGE_BY_NIML )
3099 
3100 /*! Determine if datablock db is stored in a NI_SURF_DSET file on disk */
3101 
3102 #define DBLK_IS_NI_SURF_DSET(db) ( ISVALID_DBLK(db)   &&  \
3103                        ISVALID_DISKPTR((db)->diskptr) &&  \
3104                        (db)->diskptr->storage_mode == STORAGE_BY_NI_SURF_DSET )
3105 
3106 /*! Determine if datablock db is stored in a NI_SURF_DSET file on disk */
3107 
3108 #define DBLK_IS_GIFTI(db) ( ISVALID_DBLK(db)   &&  \
3109                        ISVALID_DISKPTR((db)->diskptr) &&  \
3110                        (db)->diskptr->storage_mode == STORAGE_BY_GIFTI )
3111 
3112 /*! Determine if dataset ds is stored in a 1D file on disk */
3113 
3114 #define DSET_IS_1D(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&           \
3115                          ISVALID_DISKPTR((ds)->dblk->diskptr) &&                   \
3116                          (ds)->dblk->diskptr->storage_mode == STORAGE_BY_1D )
3117 
3118 /*! Determine if dataset ds is stored in a 3D file on disk */
3119 
3120 #define DSET_IS_3D(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&           \
3121                          ISVALID_DISKPTR((ds)->dblk->diskptr) &&                   \
3122                          (ds)->dblk->diskptr->storage_mode == STORAGE_BY_3D )
3123 
3124 /*! Determine if dataset ds is stored in a NIFTI file on disk */
3125 
3126 #define DSET_IS_NIFTI(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&        \
3127                             ISVALID_DISKPTR((ds)->dblk->diskptr) &&                \
3128                             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NIFTI )
3129 
3130 /*! Determine if dataset ds is stored in a NIML file on disk  26 May 2006 */
3131 
3132 #define DSET_IS_NIML(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&  \
3133                            ISVALID_DISKPTR((ds)->dblk->diskptr)         &&  \
3134                          (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NIML )
3135 
3136 /*! Determine if dataset ds is stored in a NI_SURF_DSET file on disk */
3137 
3138 #define DSET_IS_NI_SURF_DSET(ds) (ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) \
3139                  && ISVALID_DISKPTR((ds)->dblk->diskptr) &&                    \
3140                  (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NI_SURF_DSET )
3141 
3142 /*! Determine if dataset ds is stored in a GIFTI file on disk */
3143 
3144 #define DSET_IS_GIFTI(ds) (ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) \
3145                  && ISVALID_DISKPTR((ds)->dblk->diskptr) &&                    \
3146                  (ds)->dblk->diskptr->storage_mode == STORAGE_BY_GIFTI )
3147 
3148 /*! Determine if datablock db is stored by volume files rather than 1 big BRIK */
3149 
3150 #define DBLK_IS_VOLUMES(db) ( ISVALID_DBLK(db) &&                                \
3151                               ISVALID_DISKPTR((db)->diskptr) &&                  \
3152                               (db)->diskptr->storage_mode == STORAGE_BY_VOLUMES )
3153 
3154 /*! Determine if dataset ds is stored in volumes files rather than 1 big BRIK */
3155 
3156 #define DSET_IS_VOLUMES(ds) ( ISVALID_DSET(ds) &&                                    \
3157                               ISVALID_DBLK((ds)->dblk) &&                            \
3158                               ISVALID_DISKPTR((ds)->dblk->diskptr) &&                \
3159                               (ds)->dblk->diskptr->storage_mode == STORAGE_BY_VOLUMES )
3160 
3161 /*! Determine if datablock db is stored in a MPEG file on disk */
3162 
3163 #define DBLK_IS_MPEG(db) ( ISVALID_DBLK(db) && ISVALID_DISKPTR((db)->diskptr) && \
3164                            (db)->diskptr->storage_mode == STORAGE_BY_MPEG )
3165 
3166 /*! Determine if dataset ds is stored in a MPEG file on disk */
3167 
3168 #define DSET_IS_MPEG(ds) ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&       \
3169                            ISVALID_DISKPTR((ds)->dblk->diskptr) &&               \
3170                            (ds)->dblk->diskptr->storage_mode == STORAGE_BY_MPEG )
3171 
3172 /*! Determine if dataset is valid, but has a non-AFNI storage mode */
3173 
3174 #define IS_VALID_NON_AFNI_DSET(ds)                                           \
3175         ( ISVALID_DSET(ds) && ISVALID_DBLK((ds)->dblk) &&                    \
3176           ISVALID_DISKPTR((ds)->dblk->diskptr) &&                            \
3177           ( (ds)->dblk->diskptr->storage_mode == STORAGE_BY_MINC         ||  \
3178             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_ANALYZE      ||  \
3179             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_CTFMRI       ||  \
3180             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_CTFSAM       ||  \
3181             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_1D           ||  \
3182             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_3D           ||  \
3183             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NIFTI        ||  \
3184             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_MPEG         ||  \
3185             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NIML         ||  \
3186             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NI_SURF_DSET ||  \
3187             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_NI_TRACT     ||  \
3188             (ds)->dblk->diskptr->storage_mode == STORAGE_BY_GIFTI            \
3189           ) )
3190 
3191 /*! Determine if AFNI is allowed to over-write dataset ds */
3192 
3193 #define DSET_WRITEABLE(ds)       \
3194  ( ISVALID_DSET(ds)          &&  \
3195    ISVALID_DBLK((ds)->dblk)  &&  \
3196    !DSET_IS_MINC(ds)         &&  \
3197    !DSET_IS_ANALYZE(ds)      &&  \
3198    ( (ds)->warp_parent != NULL || (ds)->dblk->diskptr->allow_directwrite==1 ) )
3199 
3200 /*! Determine if dataset ds is stored in a compressed format */
3201 
3202 #define DSET_COMPRESSED(ds)                  \
3203    ( ISVALID_DSET(ds) && (ds)->dblk!=NULL && \
3204      (ds)->dblk->diskptr != NULL          && \
3205      COMPRESS_filecode((ds)->dblk->diskptr->brick_name) >= 0 )
3206 
3207 /*! Purge the data of dataset ds from memory (you can reload it later) */
3208 
3209 #define PURGE_DSET(ds)                                                  \
3210   do{ if( ISVALID_3DIM_DATASET(ds) && DSET_ONDISK(ds) )                 \
3211          (void) THD_purge_datablock( (ds)->dblk , DATABLOCK_MEM_ANY ) ; \
3212   } while(0)
3213 
3214 /*! Determine if dataset ds is loadable into memory */
3215 
3216 #define DSET_INMEMORY(ds)                                                        \
3217   ( ISVALID_DSET(ds) && (ds)->dblk!=NULL &&                                      \
3218     (ds)->dblk->malloc_type!=DATABLOCK_MEM_UNDEFINED &&                          \
3219     ( (ds)->dblk->diskptr->storage_mode!=STORAGE_UNDEFINED || DSET_LOADED(ds) ) )
3220 
3221 #define DBLK_BRICK(db,iv) ((db)->brick->imarr[(iv)])
3222 
3223 /*! Return the MRI_IMAGE * that is the iv-th volume of dataset ds */
3224 
3225 #define DSET_BRICK(ds,iv) DBLK_BRICK((ds)->dblk,(iv))
3226 
3227 /*! See if the iv-th volume is purged to disk at this moment */
3228 
3229 #define DSET_BRICK_IS_PURGED(ds,iv) MRI_IS_PURGED(DSET_BRICK((ds),(iv)))
3230 
3231 #define DBLK_BRICK_TYPE(db,iv) (DBLK_BRICK((db),(iv))->kind)
3232 
3233 /*! Return the datum code (MRI_short, etc.) of the iv-th volume of dataset ds */
3234 
3235 #define DSET_BRICK_TYPE(ds,iv) DBLK_BRICK_TYPE((ds)->dblk,(iv))
3236 
3237 /*! Return the number of voxels in the iv-th volume of dataset ds */
3238 
3239 #define DBLK_BRICK_NVOX(db,iv) (DBLK_BRICK((db),(iv))->nvox)
3240 
3241 #define DBLK_ARRAY(db,iv) mri_data_pointer( DBLK_BRICK((db),(iv)) )
3242 
3243 /*! Return the pointer to the actual data in the iv-th volume of dataset ds */
3244 
3245 #define DSET_ARRAY(ds,iv) DBLK_ARRAY((ds)->dblk,(iv))
3246 
3247 /* set a sub-brick pointer to null              ZSS May 08 2012 */
3248 #define DSET_NULL_ARRAY(ds,iv) \
3249    mri_clear_data_pointer(DBLK_BRICK((ds)->dblk,(iv)))
3250 /* free then set a sub-brick pointer to null    ZSS May 08 2012 */
3251 #define DSET_FREE_ARRAY(ds,iv) { \
3252    if (DSET_ARRAY((ds),(iv))) {\
3253       free(DSET_ARRAY((ds),(iv))); \
3254       mri_clear_data_pointer(DBLK_BRICK((ds)->dblk,(iv)));  \
3255    }  \
3256 }
3257 
3258 #define DSET_BRICK_ARRAY DSET_ARRAY  /* Because I sometimes forget the  */
3259 #define DBLK_BRICK_ARRAY DBLK_ARRAY  /* correct names given above - RWC */
3260 
3261 #define DBLK_BRICK_FACTOR(db,iv) ((db)->brick_fac[(iv)])
3262 
3263 /*! Return the brick scaling factor of the iv-th volume of dataset ds.
3264 
3265     If the scale factor is 0, then the brick is used "as-is"; that is,
3266     the effective scale factor is 1.  You can assign to this macro
3267     as in "DSET_BRICK_FACTOR(ds,iv)=3.2;" but I don't recommend this.
3268     Instead, do something like "EDIT_BRICK_FACTOR(ds,iv,3.2);" (see editvol.h).
3269 */
3270 
3271 #define DSET_BRICK_FACTOR(ds,iv) DBLK_BRICK_FACTOR((ds)->dblk,(iv))
3272 
3273 extern int THD_need_brick_factor( THD_3dim_dataset * ) ;
3274 
3275 #define DBLK_BRICK_BYTES(db,iv) ((db)->brick_bytes[iv])
3276 
3277 /*! Return number of bytes stored in the iv-th volume of dataset ds */
3278 
3279 #define DSET_BRICK_BYTES(ds,iv) DBLK_BRICK_BYTES((ds)->dblk,(iv))
3280 
3281 /*! Return the volume index of the "most important" sub-brick in dataset ds.
3282 
3283     This is still used in places, but is fairly obsolete
3284 */
3285 #define DSET_PRINCIPAL_VALUE(ds) ( ISANAT(ds) ? ANAT_ival_zero[(ds)->func_type] \
3286                                               : FUNC_ival_fim[(ds)->func_type] )
3287 
3288 /*! Synonym for DSET_PRINCIPAL_VALUE */
3289 
3290 #define DSET_PRINCIPAL_INDEX DSET_PRINCIPAL_VALUE
3291 
3292 /*! Return the volume index of the "threshold" sub-brick in dataset ds.
3293 
3294     This is analogous to DSET_PRINCIPAL_VALUE, and is also sort-of-obsolete.
3295 */
3296 #define DSET_THRESH_VALUE(ds) (ISANAT((ds)) ? -1 : FUNC_ival_thr[(ds)->func_type])
3297 
3298 #define DSET_THRESH_INDEX DSET_THRESH_VALUE
3299 
3300 /*! Return a pointer to the prefix of dataset ds */
3301 #define DSET_PREFIX(ds) (((ds)->dblk!=NULL && (ds)->dblk->diskptr!=NULL) \
3302                        ? ((ds)->dblk->diskptr->prefix) : "\0" )
3303 extern char *DSET_prefix_noext(THD_3dim_dataset *dset);
3304 
3305 extern char * THD_newprefix(THD_3dim_dataset * dset, char * suffix); /* 16 Feb 2001 */
3306 extern char * THD_deplus_prefix( char *prefix ) ;                    /* 22 Nov 2002 */
3307 extern int    THD_deconflict_prefix( THD_3dim_dataset * ) ;          /* 23 Mar 2007 */
3308 
3309 /*! Return a pointer to the filecode of dataset ds (prefix+view) */
3310 
3311 #define DSET_FILECODE(ds) (((ds)->dblk!=NULL && (ds)->dblk->diskptr!=NULL) \
3312                          ? ((ds)->dblk->diskptr->filecode) : "\0" )
3313 
3314 /*! Return a pointer to the .HEAD filename of dataset ds */
3315 
3316 #define DSET_HEADNAME(ds) ( ((ds)->tcat_list != NULL) ? (ds)->tcat_list     \
3317                           : ((ds)->dblk!=NULL && (ds)->dblk->diskptr!=NULL) \
3318                           ? ((ds)->dblk->diskptr->header_name) : "\0" )
3319 
3320 /*! Return a pointer to the .BRIK filename of dataset ds */
3321 
3322 #define DSET_BRIKNAME(ds) (((ds)->dblk!=NULL && (ds)->dblk->diskptr!=NULL) \
3323                          ? ((ds)->dblk->diskptr->brick_name) : "\0" )
3324 #define DSET_BRICKNAME DSET_BRIKNAME
3325 
3326 /*! Return a pointer to the directory name of dataset ds */
3327 
3328 #define DSET_DIRNAME(ds) (((ds)->dblk!=NULL && (ds)->dblk->diskptr!=NULL) \
3329                          ? ((ds)->dblk->diskptr->directory_name) : "\0" )
3330 
3331 #define DSET_SESSNAME DSET_DIRNAME
3332 
3333 /*! Return a pointer to the ID code of dataset ds */
3334 
3335 #define DSET_IDCODE(ds) (&((ds)->idcode))
3336 
3337 /*! Return the ID code string */
3338 
3339 #define DSET_IDCODE_STR(ds) ((ds)->idcode.str)
3340 
3341 /*! Return the storage mode     5 Mar 2012 [rickr] */
3342 #define DSET_STORAGE_MODE(ds) ( ((ds) && (ds)->dblk && (ds)->dblk->diskptr)\
3343    ? (ds)->dblk->diskptr->storage_mode:STORAGE_UNDEFINED )
3344 
3345 /*! Return the storage mode string */
3346 #define DSET_STORAGE_MODE_STR(ds) ( ((ds) && (ds)->dblk && (ds)->dblk->diskptr)\
3347    ? storage_mode_str((ds)->dblk->diskptr->storage_mode):"NULL" )
3348 
3349 /* 25 April 1998 */
3350 
3351 #define DBLK_BYTEORDER(db)  ((db)->diskptr->byte_order)
3352 
3353 /*! Return LSB_FIRST or MSB_FIRST for dataset ds */
3354 
3355 #define DSET_BYTEORDER(ds)  DBLK_BYTEORDER((ds)->dblk)
3356 
3357 /** macros for time-dependent datasets **/
3358 
3359 /*! Return number of time points in dataset ds.
3360 
3361     If value is 1, dataset is not time-dependent, but it still may have
3362     multiple sub-bricks (if it is a bucket dataset, for example)
3363 */
3364 #define DSET_NUM_TIMES(ds)       ( ((ds)->taxis == NULL) ? 1 : (ds)->taxis->ntt )
3365 
3366 /*! Check if have a 3D+time dataset. */
3367 
3368 #define HAS_TIMEAXIS(ds)         ( DSET_NUM_TIMES(ds) > 1 )
3369 #define DSET_HAS_TIMEAXIS HAS_TIMEAXIS
3370 
3371 /*! Return number of values stored at each time point for dataset ds.
3372 
3373     Will always be 1 in the current version of AFNI!
3374     (Except for bucket datasets, that is, damn it.)
3375 */
3376 #define DSET_NVALS_PER_TIME(ds)  ( (ds)->dblk->nvals / DSET_NUM_TIMES(ds) )
3377 
3378 /*! Return number of sub-bricks in dataset ds */
3379 
3380 #define DSET_NVALS(ds)           ( (ds)->dblk->nvals )
3381 
3382 /*! Return number of voxels in each sub-brick of dataset ds */
3383 
3384 #define DSET_NVOX(ds) ( (ds)->daxes->nxx * (ds)->daxes->nyy * (ds)->daxes->nzz )
3385 
3386 /*! Find the largest node index in dset (for surface-based dsets) */
3387 #define DSET_MAX_NODE(ds, MM) {\
3388    int i; \
3389    MM = -1; \
3390    if ((ds) && (ds)->dblk && (ds)->dblk->node_list) {\
3391       for (i=0; i<(ds)->dblk->nnodes; ++i) {\
3392          if ((ds)->dblk->node_list[i]>MM) MM = (ds)->dblk->node_list[i];\
3393       }  \
3394    }  \
3395 }
3396 
3397 /*! Return total size of dataset in bytes. */
3398 
3399 #define DSET_TOTALBYTES(ds) ((ds)->dblk->total_bytes)
3400 
3401 /*! Return number of voxels along x-axis of dataset ds */
3402 
3403 #define DSET_NX(ds) ((ds)->daxes->nxx)
3404 
3405 /*! Return number of voxels along y-axis of dataset ds */
3406 
3407 #define DSET_NY(ds) ((ds)->daxes->nyy)
3408 
3409 /*! Return number of voxels along z-axis of dataset ds */
3410 
3411 #define DSET_NZ(ds) ((ds)->daxes->nzz)
3412 
3413 /*! Return number of voxels in a slice of dataset ds */
3414 
3415 #define DSET_NXY(ds) ((ds)->daxes->nxx * (ds)->daxes->nyy)
3416 
3417 /*! Is dataset 3D? [12 May 2020] */
3418 
3419 #define DSET_HAS_3D(ds) \
3420   ( (ds)->daxes->nxx > 1 && (ds)->daxes->nyy > 1 && (ds)->daxes->nzz > 1 )
3421 
3422 /*! Is dataset 2D? [12 May 2020] */
3423 
3424 #define DSET_HAS_2D(ds) \
3425   ( (ds)->daxes->nxx > 1 && (ds)->daxes->nyy > 1 && (ds)->daxes->nzz == 1 )
3426 
3427 /*! Is dataset 1D? [12 May 2020] */
3428 
3429 #define DSET_HAS_1D(ds) \
3430   ( (ds)->daxes->nxx > 1 && (ds)->daxes->nyy == 1 && (ds)->daxes->nzz == 1 )
3431 
3432 /*! Return grid spacing (voxel size) along x-axis of dataset ds */
3433 
3434 #define DSET_DX(ds) ((ds)->daxes->xxdel)  /* added 17 Aug 1998 */
3435 
3436 /*! Return grid spacing (voxel size) along y-axis of dataset ds */
3437 
3438 #define DSET_DY(ds) ((ds)->daxes->yydel)
3439 
3440 /*! Return grid spacing (voxel size) along z-axis of dataset ds */
3441 
3442 #define DSET_DZ(ds) ((ds)->daxes->zzdel)
3443 
3444 /*! Return 1 if dset is on a volume grid, as opposed to 1D or surface-based */
3445 
3446 #define DSET_IS_VOL(ds) (((ds)->daxes->nzz == 1 && (ds)->daxes->nyy == 1) ? 0:1)
3447 
3448 /*! Return volume of a voxel */
3449 
3450 #define DSET_VOXVOL(ds) \
3451   fabsf((ds)->daxes->xxdel*(ds)->daxes->yydel*(ds)->daxes->zzdel)
3452 
3453 /*! Return minimum grid spacing in 2 dimensions for dataset ds */
3454 #define DSET_MIN_DELXY(ds) ((fabs(DSET_DX(ds)) < (fabs(DSET_DY(ds))) ) ?  \
3455      fabs(DSET_DX(ds)) : fabs(DSET_DY(ds)) )
3456 
3457 /*! Return minimum grid spacing in 3 dimensions for dataset ds */
3458 #define DSET_MIN_DEL(ds) ((DSET_MIN_DELXY(ds)<fabs(DSET_DZ(ds))) ? \
3459      DSET_MIN_DELXY(ds) : fabs(DSET_DZ(ds)))
3460 
3461 /*! Return grid origin along x-axis of dataset ds */
3462 
3463 #define DSET_XORG(ds) ((ds)->daxes->xxorg)  /* 29 Aug 2001 */
3464 
3465 /*! Return grid origin along y-axis of dataset ds */
3466 
3467 #define DSET_YORG(ds) ((ds)->daxes->yyorg)
3468 
3469 /*! Return grid origin along y-axis of dataset ds */
3470 
3471 #define DSET_ZORG(ds) ((ds)->daxes->zzorg)
3472 
3473 /*! Return smallest x-coordinate of grid for dataset ds */
3474 
3475 #define DSET_XXMIN(ds) ((ds)->daxes->xxmin) /* 11 Sep 2001 */
3476 
3477 /*! Return largest x-coordinate of grid for dataset ds */
3478 
3479 #define DSET_XXMAX(ds) ((ds)->daxes->xxmax)
3480 
3481 /*! Return smallest y-coordinate of grid for dataset ds */
3482 
3483 #define DSET_YYMIN(ds) ((ds)->daxes->yymin)
3484 
3485 /*! Return largest y-coordinate of grid for dataset ds */
3486 
3487 #define DSET_YYMAX(ds) ((ds)->daxes->yymax)
3488 
3489 /*! Return smallest z-coordinate of grid for dataset ds */
3490 
3491 #define DSET_ZZMIN(ds) ((ds)->daxes->zzmin)
3492 
3493 /*! Return largest z-coordinate of grid for dataset ds */
3494 
3495 #define DSET_ZZMAX(ds) ((ds)->daxes->zzmax)
3496 
3497   /* these next 4 added 19 Aug 1999 */
3498 
3499 /*! Find the x-axis index of a 3D array index in dataset ds */
3500 
3501 #define DSET_index_to_ix(ds,ii)         (  (ii) % (ds)->daxes->nxx)
3502 
3503 /*! Find the y-axis index of a 3D array index in dataset ds */
3504 
3505 #define DSET_index_to_jy(ds,ii)         ( ((ii) / (ds)->daxes->nxx) % (ds)->daxes->nyy )
3506 
3507 /*! Find the z-axis index of a 3D array index in dataset ds */
3508 
3509 #define DSET_index_to_kz(ds,ii)         (  (ii) /((ds)->daxes->nxx * (ds)->daxes->nyy ))
3510 
3511 /*! Convert a triple-index (ix,jy,kz) to a single 3D index for dataset ds */
3512 
3513 #define DSET_ixyz_to_index(ds,ix,jy,kz) ((ix)+((jy)+(kz)*(ds)->daxes->nyy)*(ds)->daxes->nxx)
3514 
3515 #define DAXES_index_to_ix(da,ii)         (  (ii) % (da)->nxx)
3516 #define DAXES_index_to_jy(da,ii)         ( ((ii) / (da)->nxx) % (da)->nyy )
3517 #define DAXES_index_to_kz(da,ii)         (  (ii) /((da)->nxx * (da)->nyy ))
3518 #define DAXES_ixyz_to_index(da,ix,jy,kz) ((ix)+((jy)+(kz)*(da)->nyy)*(da)->nxx)
3519 
3520 /*! Determine if dataset ds has cubical voxels */
3521 
3522 #define DSET_CUBICAL(ds) ( fabs((ds)->daxes->xxdel) == fabs((ds)->daxes->yydel) && \
3523                            fabs((ds)->daxes->xxdel) == fabs((ds)->daxes->zzdel)   )
3524 
3525 /*! Determine if a graph window can be opened for dataset ds.
3526     Cannot graph warp-on-demand datasets.
3527 */
3528 #define DSET_GRAPHABLE(ds) ( ISVALID_3DIM_DATASET(ds) && DSET_INMEMORY(ds)      && \
3529                              (ds)->wod_flag == False                            && \
3530                              ( DSET_ONDISK(ds) || DSET_LOADED(ds) || DSET_LOCKED(ds) ) )
3531 
3532 /*! Return the TR for dataset ts; will be 0 if not time-dependent. */
3533 
3534 #define DSET_TIMESTEP(ds)        ( ((ds)->taxis == NULL) ? 0.0 : (ds)->taxis->ttdel )
3535 
3536 #define DSET_TR                  DSET_TIMESTEP
3537 
3538 #define DSET_TR_SEC(ds) ( \
3539             (DSET_TIMEUNITS(ds) == UNITS_SEC_TYPE) ? DSET_TR(ds) : \
3540            ((DSET_TIMEUNITS(ds) == UNITS_MSEC_TYPE) ? DSET_TR(ds)*0.001 : 0.0 ) )
3541 
3542 /*! Return the time origin for dataset ds.
3543 
3544     Is always 0 in current version of AFNI.
3545 */
3546 #define DSET_TIMEORIGIN(ds)      ( ((ds)->taxis == NULL) ? 0.0 : (ds)->taxis->ttorg )
3547 
3548 /*! Return the time duration of image acquisition for dataset ds.
3549 
3550     Is always 0 in current version of AFNI (was intended for true 3D echo-volume imaging).
3551 */
3552 #define DSET_TIMEDURATION(ds)    ( ((ds)->taxis == NULL) ? 0.0 : (ds)->taxis->ttdur )
3553 
3554 /*! Return the time-step units code for dataset ds.
3555 
3556     Will be one of
3557       - UNITS_MSEC_TYPE  milliseconds
3558       - UNITS_SEC_TYPE   seconds
3559       - UNITS_HZ_TYPE    Hertz
3560       - ILLEGAL_TYPE     not a time-dependent dataset (d'oh)
3561 */
3562 #define DSET_TIMEUNITS(ds)       ( ((ds)->taxis == NULL) ? ILLEGAL_TYPE             \
3563                                                          : (ds)->taxis->units_type )
3564 
3565 /*! Alter a dataset's time units from MSEC to SEC, if need be. */
3566 
3567 #define DSET_UNMSEC(ds)                                                               \
3568  do{ int zz ;                                                                         \
3569    if( (ds)!=NULL && (ds)->taxis!=NULL && (ds)->taxis->units_type==UNITS_MSEC_TYPE ){ \
3570      (ds)->taxis->units_type = UNITS_SEC_TYPE ;                                       \
3571      (ds)->taxis->ttdel     *= 0.001 ;                                                \
3572      (ds)->taxis->ttorg     *= 0.001 ;                                                \
3573      (ds)->taxis->ttdur     *= 0.001 ;                                                \
3574      if( (ds)->taxis->toff_sl != NULL )                                               \
3575       for( zz=0 ; zz < (ds)->taxis->nsl ; zz++ ) (ds)->taxis->toff_sl[zz] *= 0.001 ;  \
3576    } } while(0)
3577 
3578 /*! Return number of time-axis slice offsets for datsaet ds.
3579 
3580     Will be zero for non-time-dependent datasets, and may be zero or positive
3581     for time-dependent datasets
3582 */
3583 #define DSET_NUM_TTOFF(ds)    ( ((ds)->taxis == NULL) ? 0 : (ds)->taxis->nsl )
3584 /*! Return whether the dataset has slice timing.    6 May 2013 [rickr] */
3585 #define DSET_HAS_SLICE_TIMING(ds) \
3586  (((ds) != NULL) && (DSET_NUM_TTOFF(ds) > 0) && ((ds)->taxis->toff_sl != NULL))
3587 
3588 /** 30 Nov 1997 **/
3589 
3590 #define NO_LAB_FLAG "?"
3591 #define DBLK_BRICK_LAB(db,iv) ( ((db)->brick_lab != NULL) ? ((db)->brick_lab[iv]) \
3592                                                           : NO_LAB_FLAG )
3593 
3594 /*! Return the label string for sub-brick iv of dataset ds.
3595 
3596     This label is used on chooser menus, for example
3597 */
3598 #define DSET_BRICK_LAB(ds,iv) DBLK_BRICK_LAB((ds)->dblk,(iv))
3599 
3600 /*! Synonym for DSET_BRICK_LAB */
3601 
3602 #define DSET_BRICK_LABEL      DSET_BRICK_LAB
3603 
3604 /*! Check if sub-brick has label March 2010 ZSS */
3605 #define DSET_HAS_LABEL(ds,iv) ( strcmp (DSET_BRICK_LABEL(ds,iv), NO_LAB_FLAG) )
3606 
3607 #define DBLK_BRICK_STATCODE(db,iv)  \
3608  ( ((db)->brick_statcode != NULL) ? (db)->brick_statcode[iv] : ILLEGAL_TYPE )
3609 
3610 /*! Return the statistical type code for the iv-th volume of dataset ds.
3611 
3612     Will be -1 if this sub-brick is not tagged as being an SPM.
3613 */
3614 #if 1  /* 18 Dec 2017 */
3615 
3616 #define DSET_BRICK_STATCODE(ds,iv)                                        \
3617       ( (((ds)->dblk->brick_statcode != NULL) && (iv >= 0))          \
3618       ? (ds)->dblk->brick_statcode[iv]                                         \
3619       : (ISFUNC(ds) && (iv)==FUNC_ival_thr[(ds)->func_type])        \
3620         ? (ds)->func_type : -1                               )
3621 
3622 #else  /* Ye Olde Waye */
3623 
3624 #define DSET_BRICK_STATCODE(ds,iv)                                         \
3625    ( ISBUCKET((ds)) ? DBLK_BRICK_STATCODE((ds)->dblk,(iv))                 \
3626                     : (ISFUNC(ds) && (iv)==FUNC_ival_thr[(ds)->func_type]) \
3627                       ? (ds)->func_type : -1 )
3628 
3629 #endif
3630 
3631 #define DBLK_BRICK_STATAUX(db,iv)  \
3632  ( ((db)->brick_stataux != NULL) ? (db)->brick_stataux[iv] : NULL )
3633 
3634 /*! Return float * pointer to statistical parameters for sub-brick iv in dataset ds.
3635 
3636     If return is NULL, there aren't any parameters for this sub-brick,
3637     otherwise the number of parameters is given by FUNC_need_stat_aux[code],
3638     where code = DSET_BRICK_STATCODE(ds,iv).
3639 */
3640 
3641 #if 1
3642 
3643 #define DSET_BRICK_STATAUX(ds,iv)                                          \
3644   ( ((ds)->dblk->brick_stataux != NULL)                                    \
3645      ? (ds)->dblk->brick_stataux[iv]                                       \
3646      : (ISFUNC(ds) && (iv)==FUNC_ival_thr[(ds)->func_type])                \
3647        ? (ds)->stat_aux : NULL                             )
3648 
3649 # else /* Ye Olde Waye */
3650 
3651 #define DSET_BRICK_STATAUX(ds,iv)                                          \
3652    ( ISBUCKET((ds)) ? DBLK_BRICK_STATAUX((ds)->dblk,(iv))                  \
3653                     : (ISFUNC(ds) && (iv)==FUNC_ival_thr[(ds)->func_type]) \
3654                       ? (ds)->stat_aux : NULL )
3655 
3656 #endif
3657 
3658 #define DBLK_BRICK_STATPAR(db,iv,jj) \
3659  ( ((db)->brick_stataux != NULL) ? (db)->brick_stataux[iv][jj] : 0.0 )
3660 
3661 /*! Return the jj-th statistical parameter for the iv-th volume of dataset ds. */
3662 
3663 #if 1 /* 18 Dec 2017 */
3664 
3665 #define DSET_BRICK_STATPAR(ds,iv,jj)                                       \
3666   ( ((ds)->dblk->brick_stataux != NULL)                                    \
3667      ? (ds)->dblk->brick_stataux[iv][jj]                                   \
3668      : (ISFUNC(ds) && (iv)==FUNC_ival_thr[(ds)->func_type])                \
3669        ? (ds)->stat_aux[jj] : 0.0                          )
3670 
3671 #else /* Ye Olde Waye */
3672 
3673 #define DSET_BRICK_STATPAR(ds,iv,jj)                                       \
3674    ( ISBUCKET((ds)) ? DBLK_BRICK_STATPAR((ds)->dblk,(iv),(jj))             \
3675                     : (ISFUNC(ds) && (iv)==FUNC_ival_thr[(ds)->func_type]) \
3676                       ? (ds)->stat_aux[jj] : 0.0 )
3677 
3678 #endif
3679 
3680 #define DBLK_BRICK_KEYWORDS(db,iv) \
3681   ( ((db)->brick_keywords != NULL) ? ((db)->brick_keywords[iv]) : NULL )
3682 
3683 #define DSET_BRICK_KEYWORDS(ds,iv) DBLK_BRICK_KEYWORDS((ds)->dblk,(iv))
3684 
3685 #define DSET_KEYWORDS(ds) ((ds)->keywords)
3686 
3687 #define DSET_BRICK_KEYWORDS_HAS(ds,iv,ss) \
3688    THD_string_has( DSET_BRICK_KEYWORDS((ds),(iv)) , (ss) )
3689 
3690 #define DSET_KEYWORDS_HAS(ds,ss) \
3691    THD_string_has( DSET_KEYWORDS((ds)) , (ss) )
3692 
3693 /*---- macros to get the FDR curve for a sub-brick (if any) [23 Jan 2008] ----*/
3694 
3695 #define DBLK_BRICK_FDRCURVE(db,ii) \
3696  ( ((db)->brick_fdrcurve==NULL) ? NULL : (db)->brick_fdrcurve[ii] )
3697 
3698 #define DSET_BRICK_FDRCURVE(ds,ii) DBLK_BRICK_FDRCURVE((ds)->dblk,(ii))
3699 
3700 /* smallest FDR q in the curve for sub-brick #ii [09 Dec 2015] */
3701 
3702 #define DSET_BRICK_FDRMIN(ds,ii)                                                \
3703  ( ( (ds)->dblk->brick_fdrcurve==NULL || (ds)->dblk->brick_fdrcurve[ii]==NULL ) \
3704   ? 0.0                                                                         \
3705   : 2.0*qg((ds)->dblk->brick_fdrcurve[ii]->ar[(ds)->dblk->brick_fdrcurve[ii]->nar-1]) )
3706 
3707 #define DBLK_BRICK_FDRCURVE_KILL(db,ii)                                      \
3708  do{ if( (db)->brick_fdrcurve != NULL ){                                     \
3709        floatvec *fv = (db)->brick_fdrcurve[ii] ;                             \
3710        if( fv != NULL ){ KILL_floatvec(fv); (db)->brick_fdrcurve[ii]=NULL; } \
3711  }} while(0)
3712 
3713 #define DSET_BRICK_FDRCURVE_KILL(ds,ii) DBLK_BRICK_FDRCURVE_KILL((ds)->dblk,(ii))
3714 
3715 #define DBLK_BRICK_FDRCURVE_ALLKILL(db)                                    \
3716  do{ if( (db)->brick_fdrcurve != NULL ){                                   \
3717       int qq;                                                              \
3718       for( qq=0; qq < (db)->nvals; qq++ ) DBLK_BRICK_FDRCURVE_KILL(db,qq); \
3719       free((db)->brick_fdrcurve) ; (db)->brick_fdrcurve = NULL ;           \
3720  }} while(0)
3721 
3722 #define DSET_BRICK_FDRCURVE_ALLKILL(ds) DBLK_BRICK_FDRCURVE_ALLKILL((ds)->dblk)
3723 
3724 /*---- same for MDF curves [22 Oct 2008] -----*/
3725 
3726 #define DBLK_BRICK_MDFCURVE(db,ii) \
3727  ( ((db)->brick_mdfcurve==NULL) ? NULL : (db)->brick_mdfcurve[ii] )
3728 
3729 #define DSET_BRICK_MDFCURVE(ds,ii) DBLK_BRICK_MDFCURVE((ds)->dblk,(ii))
3730 
3731 #define DBLK_BRICK_MDFCURVE_KILL(db,ii)                                      \
3732  do{ if( (db)->brick_mdfcurve != NULL ){                                     \
3733        floatvec *fv = (db)->brick_mdfcurve[ii] ;                             \
3734        if( fv != NULL ){ KILL_floatvec(fv); (db)->brick_mdfcurve[ii]=NULL; } \
3735  }} while(0)
3736 
3737 #define DSET_BRICK_MDFCURVE_KILL(ds,ii) DBLK_BRICK_MDFCURVE_KILL((ds)->dblk,(ii))
3738 
3739 #define DBLK_BRICK_MDFCURVE_ALLKILL(db)                                    \
3740  do{ if( (db)->brick_mdfcurve != NULL ){                                   \
3741       int qq;                                                              \
3742       for( qq=0; qq < (db)->nvals; qq++ ) DBLK_BRICK_MDFCURVE_KILL(db,qq); \
3743       free((db)->brick_mdfcurve) ; (db)->brick_mdfcurve = NULL ;           \
3744  }} while(0)
3745 
3746 #define DSET_BRICK_MDFCURVE_ALLKILL(ds) DBLK_BRICK_MDFCURVE_ALLKILL((ds)->dblk)
3747 
3748 extern int   THD_create_one_fdrcurve( THD_3dim_dataset *, int ) ;
3749 extern int   THD_create_all_fdrcurves( THD_3dim_dataset * ) ;
3750 extern float THD_fdrcurve_zval( THD_3dim_dataset *, int, float ) ;
3751 extern float THD_mdfcurve_mval( THD_3dim_dataset *, int, float ) ;
3752 extern int THD_count_fdrwork( THD_3dim_dataset *dset ) ; /* 12 Nov 2008 */
3753 extern float THD_fdrcurve_zqtot( THD_3dim_dataset *dset , int iv , float zval ) ;
3754 
3755 /*! Macro to load the self_name and labels of a dataset
3756     with values computed from the filenames;
3757     replaces user control/input of these values in to3d
3758 */
3759 
3760 #define DSET_FIX_NAMES(ds)                                       \
3761   ( strcpy((ds)->self_name,(ds)->dblk->diskptr->directory_name), \
3762     strcat((ds)->self_name,(ds)->dblk->diskptr->filecode)      , \
3763     strncpy((ds)->label1   ,(ds)->dblk->diskptr->filecode, THD_MAX_LABEL-1)      , \
3764     strcpy((ds)->label2   ,THD_DEFAULT_LABEL) )
3765 
3766 /*! Macro to load brick statistics of a dataset if it
3767       - doesn't have statistics already, OR
3768       - has bad statistics from the (very very very) old to3d bug
3769 */
3770 
3771 #define RELOAD_STATS(dset)                                                  \
3772   if( ISVALID_3DIM_DATASET((dset)) &&                                       \
3773       ( !ISVALID_STATISTIC((dset)->stats) ||                                \
3774         ( (dset)->dblk->nvals > 1 &&                                        \
3775           (dset)->stats->bstat[1].min > (dset)->stats->bstat[1].max ) ) ){  \
3776      THD_load_statistics((dset)) ; }
3777 
3778 /*! Determine if the ii-th volume of dataset dset has a valid brick statistic.
3779     Brick statistics are just the min and max values in the volume.
3780 */
3781 
3782 #define DSET_VALID_BSTAT(dset,ii)                 \
3783   ( ISVALID_3DIM_DATASET((dset))     &&           \
3784     ISVALID_STATISTIC((dset)->stats) &&           \
3785     (ii) < (dset)->stats->nbstat     &&           \
3786     ISVALID_BSTAT( (dset)->stats->bstat[(ii)] ) )
3787 
3788 /*! Mark the ii-th volume's brick statistics to be invalid in dataset dset. */
3789 
3790 #define DSET_CRUSH_BSTAT(dset,ii)                                 \
3791   do{ if( DSET_VALID_BSTAT(dset,ii) )                             \
3792          INVALIDATE_BSTAT((dset)->stats->bstat[(ii)]) ; } while(0)
3793 
3794 /*! Return the ii-th volume's min value from bstat, if present */
3795 
3796 #define DSET_BSTAT_MIN(dset,ii)  \
3797   ( DSET_VALID_BSTAT(dset,ii) ? (dset)->stats->bstat[(ii)].min : 0.0f )
3798 
3799 /*! Return the ii-th volume's max value from bstat, if present */
3800 
3801 #define DSET_BSTAT_MAX(dset,ii)  \
3802   ( DSET_VALID_BSTAT(dset,ii) ? (dset)->stats->bstat[(ii)].max : 0.0f )
3803 
3804 /*! Return the ii-th volume's max abs value from bstat, if present */
3805 
3806 #define DSET_BSTAT_MAXABS(dset,ii)  \
3807   ( DSET_VALID_BSTAT(dset,ii) ?     \
3808       MAX(fabsf((dset)->stats->bstat[(ii)].max),fabsf((dset)->stats->bstat[(ii)].min)) : 0.0f )
3809 
3810 /*! Delete all the sub-brick statistics for dataset ds. */
3811 
3812 #define DSET_KILL_STATS(ds)                                \
3813   do{ if( (ds)->stats != NULL ){                           \
3814          REMOVEFROM_KILL( (ds)->kl, (ds)->stats->bstat ) ; \
3815          REMOVEFROM_KILL( (ds)->kl, (ds)->stats ) ;        \
3816          KILL_STATISTIC( (ds)->stats ) ;                   \
3817          (ds)->stats = NULL ; } } while(0)
3818 
3819 /*! Macro to initialize the global stat_aux data in a dataset.
3820 
3821     Note that each sub-brick now has its own stat_aux data, and this
3822     global data is only used for the older (non-bucket) functional
3823     dataset types such as "fico".
3824 */
3825 
3826 #define INIT_STAT_AUX(ds,nf,ff)               \
3827   do{ int is ;                                \
3828       for( is=0 ; is < MAX_STAT_AUX ; is++ )  \
3829          (ds)->stat_aux[is] = (is < (nf)) ? (ff)[is] : 0.0 ; } while(0)
3830 
3831 /*! Clear the global stat_aux data in a dataset. */
3832 
3833 #define ZERO_STAT_AUX(ds)                              \
3834   do{ int is ; for( is=0 ; is < MAX_STAT_AUX ; is++ )  \
3835                  (ds)->stat_aux[is] = 0.0 ; } while(0)
3836 
3837 /** macros to load and unload a dataset from memory **/
3838 
3839 /*! Load dataset ds's sub-bricks into memory.
3840 
3841     If it is already loaded, does nothing (so you can call this without much penalty).
3842 */
3843 #define DSET_load(ds)   THD_load_datablock( (ds)->dblk )
3844 
3845 /*! Unload dataset ds's sub-bricks from memory.
3846 
3847     Won't do anything if the dataset is locked into memory
3848 */
3849 #define DSET_unload(ds) THD_purge_datablock( (ds)?(ds)->dblk:NULL , DATABLOCK_MEM_ANY )
3850 
3851 /*! Unload sub-brick iv in dataset ds from memory.
3852 
3853     Only does something if the dataset is malloc()-ed,
3854     not mmap()-ed, and not locked in memory
3855 */
3856 #define DSET_unload_one(ds,iv) THD_purge_one_brick( (ds)->dblk , (iv) )
3857 
3858 /*! Delete dataset ds's volumes and struct from memory.
3859     Does not delete from disk
3860 */
3861 #define DSET_delete(ds) THD_delete_3dim_dataset((ds),False)
3862 
3863 #define DSET_deletepp(ds) \
3864   do{ THD_delete_3dim_dataset((ds),False); myRwcFree((ds)); } while(0)
3865 
3866 /*! Write dataset ds to disk.
3867     Also loads the sub-brick statistics
3868 */
3869 #define DSET_write(ds)  ( THD_load_statistics( (ds) ) ,                    \
3870                           THD_write_3dim_dataset( NULL,NULL , (ds),True ) )
3871 
3872 /*! Write dataset to disk, fer shur this time, Cletus. [07 Jan 2008] */
3873 
3874 #define DSET_overwrite(ds)      \
3875  do{ THD_force_ok_overwrite(1); \
3876      DSET_write(ds); THD_force_ok_overwrite(0); } while(0)
3877 
3878 #define DSET_quiet_overwrite(ds)      \
3879  do{ int m_q = THD_get_quiet_overwrite();  \
3880      THD_force_ok_overwrite(1); THD_set_quiet_overwrite(1);\
3881      DSET_write(ds); THD_force_ok_overwrite(0); \
3882      THD_set_quiet_overwrite(m_q);} while(0)
3883 
3884 extern int THD_deathcon(void) ;             /* 06 Jun 2007 */
3885 extern int THD_ok_overwrite(void) ;         /* Jan 2008 */
3886 extern void THD_force_ok_overwrite( int ) ; /* 07 Jan 2008 */
3887 extern void THD_set_image_globalrange(int ii); /* 27 Jan 2014 */
3888 extern int THD_get_image_globalrange(void);
3889 extern char *THD_get_image_globalrange_str(void);
3890 extern void THD_cycle_image_globalrange(void);
3891 extern void THD_set_image_globalrange_env(int ig);
3892 
3893 /*! Write only the dataset header to disk, for dataset ds */
3894 
3895 #define DSET_write_header(ds)  THD_write_3dim_dataset( NULL,NULL , (ds),False )
3896 
3897 #define DSET_overwrite_header(ds)  \
3898  do{ THD_force_ok_overwrite(1);    \
3899      DSET_write_header(ds); THD_force_ok_overwrite(0); } while(0)
3900 
3901 /*! Check if dataset ds if fully loaded into memory.
3902 
3903     If return is 0 (false), you could try DSET_load(ds)
3904 */
3905 #define DSET_LOADED(ds) ( THD_count_databricks((ds)->dblk) == DSET_NVALS(ds) )
3906 
3907 /*! Check if a given brick is loaded [14 Sep 2007] */
3908 
3909 #define DSET_BRICK_LOADED(ds,iq) \
3910  ( DSET_BRICK(ds,iq) != NULL && DSET_ARRAY(ds,iq) != NULL )
3911 
3912 /*! Lock dataset ds into memory */
3913 
3914 #define DSET_lock(ds)      DBLK_lock((ds)->dblk)       /* Feb 1998 */
3915 
3916 /*! Unlock dataset ds (so it can be purged) */
3917 
3918 #define DSET_unlock(ds)    DBLK_unlock((ds)->dblk)
3919 
3920 /*! Check if dataset ds is locked into memory */
3921 
3922 #define DSET_LOCKED(ds)    DBLK_LOCKED((ds)->dblk)
3923 
3924 /*! Force this dataset to be loaded into memory using malloc().
3925 
3926     If you are altering the dataset contents, this is required,
3927     since a mmap()-ed dataset is readonly.
3928 */
3929 #define DSET_mallocize(ds) DBLK_mallocize((ds)->dblk)
3930 
3931 /*! Force this dataset to be loaded into memory using mmap()
3932     You cannot alter any sub-brick data, since mmap() is done in
3933     readonly mode.
3934 */
3935 #define DSET_mmapize(ds)   DBLK_mmapize((ds)->dblk)
3936 
3937 /*! Force this dataset to be loaded into shared memory.
3938     You cannot alter any sub-brick data, since is done in
3939     readonly mode.
3940 */
3941 #define DSET_shareize(ds)  DBLK_shareize((ds)->dblk)
3942 
3943 /*! Let AFNI decide how to load a dataset into memory.
3944 
3945     May choose mmap() or malloc()
3946 */
3947 #define DSET_anyize(ds)    DBLK_anyize((ds)->dblk)
3948 
3949 /*! Super-lock dataset ds into memory.
3950 
3951     Super-locked datasets will not be unlocked by DSET_unlock
3952 */
3953 #define DSET_superlock(ds) DBLK_superlock((ds)->dblk)  /* 22 Mar 2001 */
3954 
3955 /*! Check if dataset ds is loaded into memory using malloc() */
3956 
3957 #define DSET_IS_MALLOC(ds)  DBLK_IS_MALLOC((ds)->dblk)
3958 
3959 /*! Check if dataset ds is loaded into memory using mmap() */
3960 
3961 #define DSET_IS_MMAP(ds)    DBLK_IS_MMAP((ds)->dblk)
3962 
3963 /*! Check if dataset ds is loaded into shared memory */
3964 
3965 #define DSET_IS_SHARED(ds)  DBLK_IS_SHARED((ds)->dblk)
3966 
3967 /*! Check if dataset ds is "mastered": gets its data from someone else.
3968 
3969     Mastered datasets are specified on the command line with the [a..b] syntax, etc.
3970 */
3971 #define DSET_IS_MASTERED(ds) DBLK_IS_MASTERED((ds)->dblk)
3972  /*! Swap dset for a fully copy of itself if it is mastered
3973     This is useful when you want to modify a loaded dset that
3974     has been mastered */
3975 #define DSET_NEW_IF_MASTERED(dset) {\
3976    if ((dset) && DSET_IS_MASTERED((dset))) {\
3977       THD_3dim_dataset *dsetc=EDIT_full_copy((dset), "THE_MASTER"); \
3978       if (dsetc) { DSET_delete((dset)); (dset)=dsetc; }   \
3979       else { ERROR_message("Failed to copy mastered dset. Nothing done."); }  \
3980    }  \
3981 }
3982 /*! Prepare a dset that has been loaded from disk to be modified
3983    and rewritten */
3984 #define PREP_LOADED_DSET_4_REWRITE(dset, prefix) {\
3985    DSET_NEW_IF_MASTERED((dset)); \
3986    ZERO_IDCODE((dset)->idcode); \
3987    (dset)->idcode = MCW_new_idcode() ; \
3988    EDIT_dset_items( (dset) , ADN_prefix , \
3989                     (prefix) ? (prefix) : "HUMBUG", ADN_none ) ;  \
3990 }
3991 
3992 /*-------------------------------------------------------------------*/
3993 #undef  TWOGIG
3994 #define TWOGIG 2100000000   /* 2 gigabytes, aboot */
3995 
3996 /* Modified 31 May 2011 to allow mmap() for big files on a 64-bit system */
3997 
3998 #define DBLK_mmapfix(db)                                      \
3999   do{ if( (db)->malloc_type == DATABLOCK_MEM_MMAP &&          \
4000           (db)->total_bytes >  TWOGIG             &&          \
4001           sizeof(size_t)    <  8                     )        \
4002        (db)->malloc_type = DATABLOCK_MEM_MALLOC ; } while(0)
4003 
4004 /*---------------------------------------------------------------------------*/
4005 
4006 extern void THD_patch_dxyz_all( THD_3dim_dataset * ) ;       /* 05 Jun 2007 */
4007 extern void THD_patch_dxyz_one( THD_3dim_dataset * , int ) ;
4008 
4009 /*------------- a dynamic array type for 3D datasets ---------------*/
4010 
4011 /*! A dynamic array type for AFNI datasets.
4012 
4013     This is used when collecting all the datasets in a directory into a THD_session.
4014 */
4015 
4016 typedef struct THD_3dim_dataset_array {
4017       int num ;                 /*!< Number of datasets stored */
4018       int nall ;                /*!< Number of datasets slots allocated */
4019       THD_3dim_dataset**ar ;    /*!< Array of datasets: [0..num-1] are in use */
4020 } THD_3dim_dataset_array ;
4021 
4022 #define INC_3DARR 8
4023 
4024 /*! Initialize a new AFNI dataset array into variable "name".
4025 
4026     You should declare "THD_3dim_dataset_array *name;".
4027 */
4028 #define INIT_3DARR(name)                  \
4029    ( (name) = RwcNew(THD_3dim_dataset_array) ,\
4030      (name)->num = (name)->nall = 0 ,     \
4031      (name)->ar  = NULL )
4032 
4033 /*! Add dataset ddset to AFNI dataset array "name" */
4034 
4035 #define ADDTO_3DARR(name,ddset)                                       \
4036    { if( (name)->num == (name)->nall ){                               \
4037       (name)->nall += INC_3DARR + (name)->nall/8 ;                    \
4038       (name)->ar    = (THD_3dim_dataset **)                           \
4039                        RwcRealloc( (char *) (name)->ar ,               \
4040                         sizeof(THD_3dim_dataset *) * (name)->nall ) ; \
4041      }                                                             \
4042      if( (ddset) != NULL ){               \
4043       (name)->ar[(name)->num] = (ddset) ; \
4044       ((name)->num)++ ;                  \
4045      } }
4046 
4047 /*! Free the AFNI dataset array (but don't kill the datasets).
4048 
4049     This would be used after the dataset pointers have been moved
4050     someplace else (e.g., into the THD_session structure).
4051 */
4052 
4053 #define FREE_3DARR(name)      \
4054    if( (name) != NULL ){      \
4055      myRwcFree( (name)->ar ) ; \
4056      myRwcFree( (name) ) ; }
4057 
4058 /*! Macro to access the nn-th dataset in AFNI dataset array name */
4059 
4060 #define DSET_IN_3DARR(name,nn) ((name)->ar[(nn)])
4061 
4062 /*! Determine if two datasets are properly ordered */
4063 
4064 #define DSET_ORDERED(d1,d2)                  \
4065   ( ( (d1)->view_type < (d2)->view_type ) || \
4066     ( (d1)->view_type==(d2)->view_type && (d1)->func_type<(d2)->func_type ) )
4067 
4068 /*! Swap 2 dataset pointers (thru pointer dt) */
4069 
4070 #define DSET_SWAP(d1,d2) (dt=(d1),(d1)=(d2),(d2)=dt)
4071 
4072 /*! Sort an AFNI dataset array */
4073 
4074 #define SORT_3DARR(name)                                               \
4075    if( (name) != NULL && (name)->num > 1 ){                            \
4076       int iid , jjd ; THD_3dim_dataset * dt ;                          \
4077       for( iid=0 ; iid < (name)->num ; iid++ ){                        \
4078          for( jjd=1 ; jjd < (name)->num ; jjd++ ){                     \
4079             if( !DSET_ORDERED( (name)->ar[jjd-1] , (name)->ar[jjd] ) ) \
4080                DSET_SWAP( (name)->ar[jjd-1] , (name)->ar[jjd] ) ;      \
4081    }}}
4082 
4083 /*-------------------------------------------------------------------*/
4084 /*--------        holds all data from a session!          -----------*/
4085 
4086 #define SESSION_TYPE 97
4087 
4088 /*! Holds all the datasets from a directory (session).
4089     [28 Jul 2003: modified to put elide distinction between anat and func]
4090     [20 Jan 2004: modified to put surfaces into here as well]
4091 */
4092 
4093 
4094 /* each session can contain a list of dataset in different views */
4095 /* each row can be represented by this structure showing different
4096    spaces or views for each dataset - orig, acpc, tlrc, mni,...*/
4097 /* the dataset may be on the disk or an on-the-fly transformed
4098    version of another dataset */
4099 typedef struct {
4100   int nds;               /* the number of dataset spaces for this row */
4101   THD_3dim_dataset **ds; /* the datasets for that "row" of spaces */
4102 } THD_dsarr;
4103 
4104 typedef struct {
4105       int type     ;                  /*!< code indicating this is a THD_session */
4106       int num_dsset ;                 /*!< Number of datasets. */
4107       char sessname[THD_MAX_NAME] ;   /*!< Name of directory datasets were read from */
4108       char lastname[THD_MAX_NAME] ;   /*!< Just/the/last/name of the directory */
4109 #ifdef oldsessions
4110       THD_3dim_dataset *xdsset[THD_MAX_SESSION_SIZE][LAST_VIEW_TYPE+1] ;
4111                                       /*!< array of datasets */
4112 #endif
4113       THD_dsarr **dsrow;               /* list of pointers for dataset
4114                                          in different spaces */
4115       int ndsets;                      /* number of datasets */
4116       Htable *warptable ;       /*!< Table of inter-dataset warps [27 Aug 2002] */
4117 
4118       /* 20 Jan 2004: put surfaces here, rather than in the datasets */
4119 
4120       int su_num ;              /*!< Number of surfaces */
4121       SUMA_surface **su_surf ;  /*!< Surface array */
4122 
4123       int su_numgroup ;                  /*!< Number of surface groups */
4124       SUMA_surfacegroup **su_surfgroup ; /*!< Surface group array */
4125 
4126       int su_nummask ;          /*!< Number of SUMA masks (moveable surfaces) */
4127       SUMA_mask **su_mask ;     /*!< array of pointers to SUMA masks */
4128 
4129       int is_collection ;       /*!< If a collection rather than a directory */
4130 
4131       RwcPointer parent ;        /*!< generic pointer to "owner" of session */
4132 } THD_session ;
4133 
4134 extern char * THD_get_space(THD_3dim_dataset *dset);
4135 extern int THD_space_code(char *space);
4136 extern int space_to_NIFTI_code(THD_3dim_dataset *dset);
4137 
4138 
4139 extern int is_surface_storage_mode( int smode ) ;
4140 
4141 extern THD_3dim_dataset *
4142         get_session_dset_id(THD_session *sess, MCW_idcode idcode, int space_index);
4143 extern THD_3dim_dataset *
4144         get_session_dset(THD_session *sess, int index, int space_index);
4145 extern int
4146         set_session_dset(THD_3dim_dataset *dset, THD_session *sess,
4147                            int index, int space_index);
4148 extern void set_nspaces(int n);
4149 extern void set_atlas_nspaces(void);
4150 extern int get_nspaces(void);
4151 
4152 #ifdef oldsessions
4153    #define GET_SESSION_DSET(session, index, space) \
4154         session->xdsset[index][space]
4155    #define SET_SESSION_DSET(sdset, session, index, space) \
4156         session->xdsset[index][space] = sdset
4157 #else
4158    #define GET_SESSION_DSET(session, index, space) \
4159         (THD_3dim_dataset *) get_session_dset(session, index, space)
4160    #define SET_SESSION_DSET(sdset, session, index, space) \
4161         set_session_dset(sdset, session, index, space)
4162 #endif
4163 
4164 /*! Determine if ss points to a valid THD_session. */
4165 
4166 #define ISVALID_SESSION(ss) ( (ss) != NULL && (ss)->type == SESSION_TYPE )
4167 
4168 #define IS_COLLECTION(ss) ( ISVALID_SESSION(ss) && (ss)->is_collection != 0 )
4169 
4170 /*! Initialize THD_session ss to hold nothing at all. */
4171 
4172 #define BLANK_SESSION(ss)                                                     \
4173   if( ISVALID_SESSION((ss)) ){                                                \
4174       int id , vv ;                                                           \
4175       (ss)->num_dsset = 0 ;                                                   \
4176       (ss)->su_num    = 0 ; (ss)->su_surf = NULL ;                            \
4177       (ss)->su_nummask= 0 ; (ss)->su_mask = NULL ;                            \
4178       (ss)->su_numgroup = 0 ; (ss)->su_surfgroup = NULL ;                     \
4179       (ss)->is_collection = 0 ;                                               \
4180       (ss)->warptable = NULL ; (ss)->dsrow = NULL;                            \
4181       for( id=0 ; id < THD_MAX_SESSION_SIZE ; id++ )                          \
4182         for( vv=0 ; vv < get_nspaces() ; vv++ )                               \
4183            SET_SESSION_DSET(NULL, ss, id, vv);                                \
4184   }
4185 
4186 /*! Determine if session has SUMA surface data attached. */
4187 
4188 #define SESSION_HAS_SUMA(ss) ( (ss) != NULL &&                                         \
4189                                ( ( (ss)->su_surf != NULL && (ss)->su_num     > 0 ) ||  \
4190                                  ( (ss)->su_mask != NULL && (ss)->su_nummask > 0 )   ) \
4191                              )
4192 
4193 #define SESSIONLIST_TYPE 107
4194 
4195 /*! Array of THD_sessions.
4196 
4197     Holds all the datasets read into AFNI from all directories.
4198 */
4199 
4200 typedef struct {
4201       int type , num_sess ;
4202       THD_session *ssar[THD_MAX_NUM_SESSION] ;
4203       RwcPointer parent ;
4204 } THD_sessionlist ;
4205 
4206 /*! Determine if sl is a valid THD_sessionlist */
4207 
4208 #define ISVALID_SESSIONLIST(sl) ( (sl)!=NULL && (sl)->type==SESSIONLIST_TYPE )
4209 
4210 /*! Initialize a THD_sessionlist to contain nothing. */
4211 
4212 #define BLANK_SESSIONLIST(sl) \
4213    if( ISVALID_SESSIONLIST((sl)) ){ \
4214       int is ; \
4215       for( is=0 ; is < THD_MAX_NUM_SESSION ; is++ ) (sl)->ssar[is] = NULL ; \
4216       (sl)->num_sess = 0 ; }
4217 
4218 /*! Return type for THD_sessionlist searching (see THD_dset_in_*).
4219 
4220     There are different ways to search for a dataset in THD_sessionlist
4221       - FIND_NAME    to find by the name field (is now obsolete)
4222       - FIND_IDCODE  to find by the dataset ID code (the best way)
4223       - FIND_PREFIX  to find by the dataset prefix (an OK way)
4224 */
4225 
4226 typedef struct {
4227    int sess_index ;            /*!< Session it was found in */
4228    int dset_index ;            /*!< Index it was found at (if >= 0) */
4229    int view_index ;            /*!< View index it was found at (if >= 0) */
4230    THD_3dim_dataset * dset ;   /*!< Pointer to found dataset itself */
4231 } THD_slist_find ;
4232 
4233 /*! Set the find codes to indicate a bad result */
4234 
4235 #define BADFIND(ff)                                       \
4236    ( (ff).sess_index=(ff).dset_index=(ff).view_index=-1 , \
4237      (ff).dset = NULL )
4238 
4239 #define FIND_NAME   1
4240 #define FIND_IDCODE 2
4241 #define FIND_PREFIX 3
4242 
4243 /*******************************************************************/
4244 /********************** attribute names ****************************/
4245 
4246 #define ATRNAME_DATANAME "DATASET_NAME"
4247 #define ATRNAME_LABEL1   "LABEL_1"
4248 #define ATRNAME_LABEL2   "LABEL_2"
4249 
4250 #define ATRNAME_ANATOMY_PARENT "ANATOMY_PARENTNAME"
4251 
4252 #define ATRNAME_ORIENT_SPECIFIC "ORIENT_SPECIFIC"
4253 #define ATRTYPE_ORIENT_SPECIFIC ATR_INT_TYPE
4254 #define ATRSIZE_ORIENT_SPECIFIC 3
4255 
4256 #define ATRNAME_ORIENT_GENERAL "ORIENT_GENERAL"   /*** not used yet  ***/
4257 #define ATRTYPE_ORIENT_GENERAL ATR_FLOAT_TYPE     /* (will someday be  */
4258 #define ATRSIZE_ORIENT_GENERAL 9                  /*  rotation matrix) */
4259 
4260 #define ATRNAME_ORIGIN "ORIGIN"
4261 #define ATRTYPE_ORIGIN ATR_FLOAT_TYPE
4262 #define ATRSIZE_ORIGIN 3
4263 
4264 #define ATRNAME_DELTA  "DELTA"
4265 #define ATRTYPE_DELTA  ATR_FLOAT_TYPE
4266 #define ATRSIZE_DELTA  3
4267 
4268 #define ATRNAME_SKIP   "SKIP"
4269 #define ATRTYPE_SKIP   ATR_FLOAT_TYPE
4270 #define ATRSIZE_SKIP   3
4271 
4272 #define ATRNAME_MARKSXYZ  "MARKS_XYZ"
4273 #define ATRTYPE_MARKSXYZ  ATR_FLOAT_TYPE
4274 #define ATRSIZE_MARKSXYZ  MARKS_FSIZE
4275 
4276 #define ATRNAME_MARKSLAB  "MARKS_LAB"
4277 #define ATRTYPE_MARKSLAB  ATR_STRING_TYPE
4278 #define ATRSIZE_MARKSLAB  MARKS_LSIZE
4279 
4280 #define ATRNAME_MARKSHELP "MARKS_HELP"
4281 #define ATRTYPE_MARKSHELP  ATR_STRING_TYPE
4282 #define ATRSIZE_MARKSHELP  MARKS_HSIZE
4283 
4284 #define ATRNAME_MARKSFLAG "MARKS_FLAGS"
4285 #define ATRTYPE_MARKSFLAG  ATR_INT_TYPE
4286 #define ATRSIZE_MARKSFLAG  MARKS_MAXFLAG
4287 
4288 #define ATRNAME_TYPESTRING "TYPESTRING"
4289 #define ATRTYPE_TYPESTRING ATR_STRING_TYPE
4290 #define ATRSIZE_TYPESTRING 0                /* 0 size means variable */
4291 
4292 #define ATRNAME_WARP_TYPE  "WARP_TYPE"
4293 #define ATRTYPE_WARP_TYPE  ATR_INT_TYPE
4294 #define ATRSIZE_WARP_TYPE  8           /* warp, resample (6 expansions) */
4295 
4296 #define ATRNAME_WARP_DATA  "WARP_DATA"
4297 #define ATRTYPE_WARP_DATA  ATR_FLOAT_TYPE
4298 #define ATRSIZE_WARP_DATA  0
4299 
4300 #define ATRNAME_WARP_DATA_3DWD_AF  "WARPDRIVE_MATVEC_INV_000000"  /* Talairach warp via 3dWarpDrive */
4301 #define ATRTYPE_WARP_DATA_3DWD_AF  ATR_FLOAT_TYPE
4302 #define ATRSIZE_WARP_DATA_3DWD_AF  0         /* not using this one. Calv. Cool. June 24 */
4303 
4304 #define ATRNAME_WARP_PARENT "WARP_PARENTNAME"
4305 #define ATRTYPE_WARP_PARENT ATR_STRING_TYPE
4306 #define ATRSIZE_WARP_PARENT 0
4307 
4308 #define ATRNAME_SCENE_TYPE "SCENE_DATA"
4309 #define ATRTYPE_SCENE_TYPE ATR_INT_TYPE
4310 #define ATRSIZE_SCENE_TYPE 8           /* view, func, type (+5) */
4311 
4312 #define ATRNAME_DATASET_RANK "DATASET_RANK"
4313 #define ATRTYPE_DATASET_RANK ATR_INT_TYPE
4314 #define ATRSIZE_DATASET_RANK 8         /* # dims, # vals (+6) */
4315 
4316 #define ATRNAME_DATASET_DIMENSIONS "DATASET_DIMENSIONS"
4317 #define ATRTYPE_DATASET_DIMENSIONS ATR_INT_TYPE
4318 #define ATRSIZE_DATASET_DIMENSIONS THD_MAX_RANK_EVER
4319 
4320 #define ATRNAME_MINMAX "MINMAX"
4321 #define ATRTYPE_MINMAX ATR_INT_TYPE
4322 
4323 #if 0
4324 #   define ATRNAME_DATASET_PREFIX  "DATASET_PREFIX"
4325 #   define ATRTYPE_DATASET_PREFIX  ATR_STRING_TYPE
4326 #   define ATRSIZE_DATASET_PREFIX  THD_MAX_PREFIX
4327 
4328 #   define ATRNAME_DATASET_VIEWCODE  "DATASET_VIEWCODE"
4329 #   define ATRTYPE_DATASET_VIEWCODE  ATR_STRING_TYPE
4330 #   define ATRSIZE_DATASET_VIEWCODE  THD_MAX_VIEWCODE
4331 #endif
4332 
4333 /** additions 1995 Nov 15, for variable brick data types **/
4334 
4335 #define ATRNAME_BRICK_TYPES    "BRICK_TYPES"
4336 #define ATRTYPE_BRICK_TYPES    ATR_INT_TYPE
4337 #define ATRSIZE_BRICK_TYPES    0
4338 
4339 #define ATRNAME_BRICK_STATS    "BRICK_STATS"
4340 #define ATRTYPE_BRICK_STATS    ATR_FLOAT_TYPE
4341 #define ATRSIZE_BRICK_STATS    0
4342 
4343 #define ATRNAME_BRICK_FLTFAC   "BRICK_FLOAT_FACS"
4344 #define ATRTYPE_BRICK_FLTFAC   ATR_FLOAT_TYPE
4345 #define ATRSIZE_BRICK_FLTFAC   0
4346 
4347 /** 1996 Mar 26 **/
4348 
4349 #define ATRNAME_STAT_AUX       "STAT_AUX"
4350 #define ATRTYPE_STAT_AUX       ATR_FLOAT_TYPE
4351 #define ATRSIZE_STAT_AUX       0
4352 
4353 /** 1996 May 14 **/
4354 
4355 #define ATRNAME_TAXIS_NUMS     "TAXIS_NUMS"
4356 #define ATRSIZE_TAXIS_NUMS     8
4357 
4358 #define ATRNAME_TAXIS_FLOATS   "TAXIS_FLOATS"
4359 #define ATRSIZE_TAXIS_FLOATS   8
4360 
4361 #define ATRNAME_TAXIS_OFFSETS  "TAXIS_OFFSETS"
4362 #define ATRSIZE_TAXIS_OFFSETS  0
4363 
4364 /** 30 Nov 1997 **/
4365 
4366 #define ATRNAME_BRICK_LABS     "BRICK_LABS"
4367 #define ATRNAME_BRICK_STATAUX  "BRICK_STATAUX"
4368 #define ATRNAME_BRICK_KEYWORDS "BRICK_KEYWORDS"
4369 
4370 #define ATRNAME_KEYWORDS       "DATASET_KEYWORDS"
4371 
4372 #ifdef  __cplusplus
4373 }
4374 #endif
4375 
4376 /************************************************************************/
4377 /******************* rest of prototypes *********************************/
4378 
4379 /** #include <stdarg.h> **/
4380 #ifdef  __cplusplus
4381 extern "C" {
4382 #endif
4383 
4384 #ifndef DONT_USE_SCANDIR
4385 #ifdef SCANDIR_WANTS_CONST
4386    extern int THD_select_dirent( const struct dirent * dp ) ;
4387 #else
4388    extern int THD_select_dirent( struct dirent * dp ) ;
4389 #endif
4390 #endif
4391 
4392 char * ig_strstr( char *, char *, char * ) ; /* 08 Aug 2002 */
4393 void freeup_strings( int n , char **sar ) ;
4394 int breakup_string( char *sin , char ***stok ) ;
4395 
4396 extern THD_string_array * THD_get_all_filenames( char * ) ;
4397 extern THD_string_array * THD_extract_regular_files( THD_string_array * ) ;
4398 extern THD_string_array * THD_extract_directories( THD_string_array * ) ;
4399 extern int THD_is_file     ( char * ) ;
4400 extern int THD_is_fifo     ( char * ) ;  /* 27 Aug 2019 */
4401 extern int THD_is_symlink  ( char * ) ;  /* 03 Mar 1999 */
4402 extern int THD_is_directory( char * ) ;
4403 extern int THD_forbidden_directory( char *) ; /* 18 Sep 2020 */
4404 
4405 #define THD_is_good_directory(ddd) \
4406   ( THD_is_directory(ddd) && !THD_forbidden_directory(ddd) )
4407 
4408 extern int THD_is_ondisk   ( char * ) ;  /* 19 Dec 2002 */
4409 extern int THD_is_prefix_ondisk( char *pathname, int stripsels ) ; /* Dec 2011 */
4410 extern int THD_mkdir       ( char * ) ;  /* 19 Dec 2002 */
4411 extern int THD_cwd         ( char * ) ;  /* 19 Dec 2002 */
4412 extern int THD_equiv_files ( char * , char * ) ;
4413 extern long long THD_filesize( char * pathname ) ;
4414 extern int THD_filetime_diff( char *pathname,
4415                               int year, int month, int day);
4416 extern char *THD_filetime( char *pathname );
4417 extern char *THD_homedir(byte withslash);
4418 extern char *THD_custom_atlas_dir(byte withslash);
4419 extern char *THD_get_custom_atlas_dir(byte withslash);
4420 extern char *THD_afnirc(void);
4421 extern char *THD_custom_atlas_file(char *name);
4422 extern char *THD_helpdir(byte withslash);
4423 extern char *THD_get_helpdir(byte withslash);
4424 extern char *THD_datadir(byte withslash);
4425 extern char *THD_get_datadir(byte withslash);
4426 extern char *THD_abindir(byte withslash);
4427 extern char * THD_facedir(byte withslash);
4428 extern char *find_afni_file(char * nimlname, int niname, char *altpath);
4429 char *THD_helpsearchlog(int createpath);
4430 
4431 extern THD_string_array * THD_get_all_subdirs( int , char * ) ;
4432 extern THD_string_array * THD_normalize_flist( THD_string_array * ) ;
4433 extern THD_string_array * THD_get_wildcard_filenames( char * ) ;
4434 
4435 extern int THD_check_for_duplicates( int, char **, int ) ; /* 31 May 2007 */
4436 
4437 extern time_t THD_file_mtime( char * ) ; /* 05 Dec 2001 */
4438 extern char *af_strnstr(char *s1, char *s2, size_t n);
4439 extern char *TrimString(char *lbl, int mxlen);
4440 extern THD_string_array * THD_get_all_files( char *, char ) ; /* 08 Jun 2011 */
4441 extern THD_string_array * THD_getpathprogs( THD_string_array *, char );
4442 extern THD_string_array * THD_get_all_afni_executables(void );
4443 extern THD_string_array * THD_get_all_afni_readmes(void);
4444 extern int list_afni_programs(int withpath, int withnum);
4445 extern int list_afni_readmes(int withpath, int withnum);
4446 extern int list_afni_dsets(int withpath, int withnum);
4447 extern int THD_is_executable( char * pathname ) ;
4448 int progopt_C_array(FILE *fout, int verb, char *thisprog, int appendmode);
4449 char *form_C_progopt_string(char *prog, char **ws, int N_ws);
4450 char *phelp(char *prog, TFORM targ, int verb);
4451 char *sphelp(char *prog, char **str, TFORM targ, int verb);
4452 int phelp_cmd(char *prog, TFORM targ, char cmd[512], char fout[128], int verb );
4453 int program_supports(char *prog, char *opt, char *oval, int verb);
4454 char *find_popt(char *sh, char *opt, int *nb);
4455 int prog_complete_command (char *prog, char *ofile, int shtp);
4456 void view_prog_help(char *prog);
4457 void web_prog_help(char *prog, int style);
4458 char *web_prog_help_link(char *prog, int style);
4459 void web_class_docs(char *prog);
4460 int view_web_link(char *link, char *browser);
4461 int view_text_file(char *progname) ;
4462 extern char * THD_find_executable( char * ) ;
4463 extern char * THD_find_regular_file( char * , char *) ;
4464 extern THD_string_array *get_elist(void);
4465 char *find_readme_file(char *str);
4466 
4467 extern int THD_is_dataset( char * , char * , int ) ; /* 17 Mar 2000 */
4468 extern char * THD_dataset_headname( char * , char * , int ) ;
4469 
4470 /*--------------------- functions for reading tables -------------------------*/
4471 
4472 extern NI_element * THD_simple_table_read( char *fname ) ; /* 19 May 2010 */
4473 extern NI_element * THD_mixed_table_read ( char *fname ) ; /* 26 Jul 2010 */
4474 extern NI_element * THD_string_table_read( char *fname , int flags ) ;
4475 
4476 /*--------------------- functions for TSV (.tsv) files -----------------------*/
4477 
4478 extern NI_element * THD_read_tsv(char *fname) ;            /* 12 Sep 2018 */
4479 extern void THD_write_tsv( char *fname , NI_element *nel ) ;
4480 extern void THD_set_tsv_column_labels( NI_element *fnel , char **clab ) ;
4481 extern NI_element * THD_mri_to_tsv_element( MRI_IMAGE *imin , char **clab ) ;
4482 extern MRI_IMAGE * THD_niml_to_mri( NI_element *nel ) ;
4483 
4484 extern NI_element * THD_read_csv(char *fname) ;            /* 15 Apr 2019 */
4485 extern void THD_write_csv( char *fname , NI_element *nel ) ;
4486 extern void THD_set_csv_column_labels( NI_element *fnel , char **clab ) ;
4487 extern NI_element * THD_mri_to_csv_element( MRI_IMAGE *imin , char **clab ) ;
4488 
4489 extern NI_ELARR * THD_get_many_tcsv( THD_string_array * dlist ) ; /* 16 Jun 2020 */
4490 extern NI_ELARR * THD_get_all_tcsv( char * dname ) ;
4491 
4492 /*---------------------------------------------------------------------------*/
4493 
4494 extern MRI_IMARR * THD_get_all_timeseries( char * ) ;
4495 extern MRI_IMARR * THD_get_many_timeseries( THD_string_array * ) ;
4496 extern char * THD_trailname( char * fname , int lev ) ;
4497 extern char * THD_filepath( char *fname );
4498 extern int THD_filehaspath ( char *fname);
4499 extern int THD_linecount( char * ) ;
4500 
4501 extern void THD_read_all_atr ( char * , THD_datablock * ) ;
4502 extern void THD_erase_all_atr( THD_datablock * ) ;
4503 extern void THD_erase_one_atr( THD_datablock * , char * ) ;
4504 extern void THD_read_niml_atr( char * , THD_datablock * ) ; /* 01 Jun 2005 */
4505 
4506 extern void THD_anonymize_dset ( THD_3dim_dataset * ) ;  /* 08 Jul 2005 */
4507 extern void THD_anonymize_write( int ) ;
4508 
4509 extern ATR_any    * THD_find_atr       ( THD_datablock * , char * ) ;
4510 extern ATR_float  * THD_find_float_atr ( THD_datablock * , char * ) ;
4511 extern ATR_int    * THD_find_int_atr   ( THD_datablock * , char * ) ;
4512 extern ATR_string * THD_find_string_atr( THD_datablock * , char * ) ;
4513 
4514 extern void THD_set_atr( THD_datablock * , char * , int,int, void * ) ;
4515 
4516 extern ATR_any * THD_copy_atr( ATR_any *atr ) ;  /* 03 Aug 2005 */
4517 extern void THD_insert_atr( THD_datablock *blk , ATR_any *atr ) ;
4518 extern int THD_copy_labeltable_atr( THD_datablock *d1,  THD_datablock *d2);
4519 
4520 extern void THD_store_dataset_keywords ( THD_3dim_dataset * , char * ) ;
4521 extern void THD_append_dataset_keywords( THD_3dim_dataset * , char * ) ;
4522 extern char * THD_dataset_info( THD_3dim_dataset * , int ) ;
4523 extern char * THD_dset_subbrick_info( THD_3dim_dataset * , int );
4524 
4525 extern int THD_subbrick_minmax( THD_3dim_dataset *dset, int isb, int scl,
4526                                  float *min, float *max);
4527 extern float THD_subbrick_max(THD_3dim_dataset *dset, int isb, int scl);
4528 extern float THD_subbrick_min(THD_3dim_dataset *dset, int isb, int scl);
4529 extern int THD_dset_minmax( THD_3dim_dataset *dset, int scl,
4530                                  float *min, float *max);
4531 extern int THD_slow_minmax_dset(THD_3dim_dataset *dset,
4532                 float *dmin, float *dmax, int iv_bot, int iv_top);
4533 extern float THD_dset_max(THD_3dim_dataset *dset, int scl);
4534 extern float THD_dset_min(THD_3dim_dataset *dset, int scl);
4535 extern float THD_dset_extent(THD_3dim_dataset *dset, char ret,float *RL_AP_IS);
4536 extern float THD_dset_extent_rlpais(THD_3dim_dataset *dset, char ret,
4537                                     float *RL_PA_IS);
4538 
4539 extern void THD_show_dataset_names( THD_3dim_dataset *dset,
4540                                     char *head, FILE *out);
4541 extern const char * storage_mode_str(int);
4542 extern int dset_obliquity(THD_3dim_dataset *dset , float *anglep);
4543 double dset_obliquity_angle_diff(THD_3dim_dataset *dset1,
4544                                  THD_3dim_dataset *dset2,
4545                                  double tol);
4546 double daxes_obliquity_angle_diff(THD_dataxes *ax1, THD_dataxes *ax2,
4547                                   double tol);
4548 extern void THD_set_float_atr( THD_datablock * , char * , int , float * ) ;
4549 extern void THD_set_int_atr  ( THD_datablock * , char * , int , int   * ) ;
4550 extern void THD_set_char_atr ( THD_datablock * , char * , int , char  * ) ;
4551 
4552 /*! Macro to set a string attribute from a C string (vs. a char array). */
4553 
4554 #define THD_set_string_atr(blk,name,str) \
4555    THD_set_char_atr( (blk) , (name) , strlen(str)+1 , (str) )
4556 
4557 extern void THD_init_diskptr_names( THD_diskptr *, char *,char *,char * ,
4558                                     int, RwcBoolean ) ;
4559 
4560 extern THD_datablock *       THD_init_one_datablock( char *,char * ) ;
4561 extern THD_datablock_array * THD_init_prefix_datablocks( char *, THD_string_array * ) ;
4562 
4563 extern RwcPointer_array * THD_init_alldir_datablocks( char * ) ;
4564 
4565 extern THD_session * THD_init_session( char * ) ;
4566 extern void          THD_order_session( THD_session * ) ;   /* 29 Jul 2003 */
4567 extern void THD_append_sessions( THD_session *, THD_session *); /* 20 Dec 2001 */
4568 
4569 extern char * THD_suck_pipe( char *cmd ) ;                  /* 01 Feb 2018 */
4570 extern NI_str_array * THD_get_subdirs_bysub( char *dirname , char *subid ) ;
4571 extern THD_session * THD_init_session_bysub( char *dirname , char *subid ) ;
4572 extern THD_session * THD_init_session_recursive( char *dirname ) ;
4573 
4574 extern char * Add_plausible_path(char *fname);              /* ZSS:Aug. 08 */
4575 extern THD_3dim_dataset * THD_open_one_dataset( char * ) ;
4576 extern THD_3dim_dataset * THD_open_dataset( char * ) ;      /* 11 Jan 1999 */
4577 extern THD_3dim_dataset * THD_open_analyze( char * ) ;      /* 27 Aug 2002 */
4578 extern THD_3dim_dataset * THD_open_ctfmri( char * ) ;       /* 04 Dec 2002 */
4579 extern THD_3dim_dataset * THD_open_ctfsam( char * ) ;       /* 04 Dec 2002 */
4580 extern THD_3dim_dataset * THD_open_1D( char * ) ;           /* 04 Mar 2003 */
4581 extern THD_3dim_dataset * THD_open_3D( char * ) ;           /* 21 Mar 2003 */
4582 extern THD_3dim_dataset * THD_open_nifti( char * ) ;        /* 28 Aug 2003 */
4583 extern THD_3dim_dataset * THD_open_mpeg( char * ) ;         /* 03 Dec 2003 */
4584 extern THD_3dim_dataset * THD_open_tcat( char * ) ;         /* 04 Aug 2004 */
4585 extern THD_3dim_dataset * THD_open_niml( char * ) ;         /* 01 Jun 2006 */
4586 extern THD_3dim_dataset * THD_open_gifti( char * ) ;        /* 13 Feb 2008 */
4587 
4588 extern THD_3dim_dataset * THD_open_image( char *fname ) ;   /* 06 Jul 2016 */
4589 extern THD_3dim_dataset * THD_image_to_dset( MRI_IMAGE *im , char *prefix ) ;
4590 
4591 extern THD_string_array * THD_multiplex_dataset( char * ) ; /* 19 Jul 2007 */
4592 
4593 extern THD_3dim_dataset * THD_niml_3D_to_dataset( NI_element *, char * ) ;
4594 extern THD_3dim_dataset * THD_ni_surf_dset_to_afni( NI_group *, int ) ;
4595 extern void * read_niml_file( char *, int ) ;
4596 extern int    storage_mode_from_niml( void * ) ;
4597 extern int    niml_get_major_label_order( char * ) ;        /* 28 Jul 2009 */
4598 
4599 
4600 extern int        NI_write_gifti( NI_group *, char * , int);
4601 extern NI_group * NI_read_gifti( char * , int ) ;
4602 
4603 extern int storage_mode_from_filename( char * fname );      /* 20 Apr 2006 */
4604 int storage_mode_from_prefix( char * fname );
4605 extern char *storage_mode_name(int mode);
4606 extern int has_known_non_afni_extension( char * fname ) ;   /*     [rickr] */
4607 extern int is_writable_storage_mode( int smode ) ;          /* 05 Mar 2012 */
4608 extern char * find_filename_extension( char * fname );
4609 extern char * modify_afni_prefix( char * fname , char *pref, char *suf);
4610 extern char * without_afni_filename_extension( char *fname);
4611 char * without_afni_filename_view_and_extension( char * fname );
4612 
4613 extern void THD_datablock_apply_atr( THD_3dim_dataset * ) ; /* 09 May 2005 */
4614 
4615 extern THD_3dim_dataset * THD_fetch_dataset      (char *) ; /* 23 Mar 2001 */
4616 extern RwcPointer_array *  THD_fetch_many_datasets(char *) ;
4617 extern MRI_IMAGE *        THD_fetch_1D           (char *) ; /* 26 Mar 2001 */
4618 
4619 extern void THD_set_storage_mode( THD_3dim_dataset *,int ); /* 21 Mar 2003 */
4620 
4621 extern int * get_count_intlist    (char *str, int *nret, int maxval );
4622 extern int * get_count_intlist_eng(char *str, int *nret, int maxval, int ok_neg);
4623 /* get_1dcat_intlist: May 15 2012 ZSS    ; added maxval 4 Jan 2016 [rickr] */
4624 int * get_1dcat_intlist    ( char *str , int *nret, int maxval);
4625 int * get_1dcat_intlist_eng( char *str , int *nret, int maxval, int ok_neg);
4626 
4627 extern int * MCW_get_intlist( int , char * ) ;
4628 extern int * MCW_get_labels_intlist( char ** , int,  char * ); /* ZSS Dec 09 */
4629 extern int * MCW_get_thd_intlist( THD_3dim_dataset * , char * ); /* ZSS Dec 09 */
4630 extern void MCW_intlist_allow_negative( int ) ;             /* 22 Nov 1999 */
4631 extern int  MCW_get_angle_range(THD_3dim_dataset *, char *, float *, float *);
4632 extern int  thd_check_angle_selector(THD_3dim_dataset *, char *); /* 21 Nov 2016 */
4633 
4634 
4635 /* copy a dataset, given a list of sub-bricks          [rickr] 26 Jul 2004 */
4636 extern THD_3dim_dataset * THD_copy_dset_subs( THD_3dim_dataset * , int * ) ;
4637 extern THD_3dim_dataset * THD_copy_one_sub  ( THD_3dim_dataset * , int ) ;
4638 
4639 /*! Help string to explain dataset "mastering" briefly. */
4640 
4641 #define MASTER_SHORTHELP_STRING                                                \
4642  "INPUT DATASET NAMES\n"                                                       \
4643  "-------------------\n"                                                       \
4644  "This program accepts datasets that are modified on input according to the\n" \
4645  "following schemes:\n"                                                        \
4646  "  'r1+orig[3..5]'                                    {sub-brick selector}\n" \
4647  "  'r1+orig<100..200>'                                {sub-range selector}\n" \
4648  "  'r1+orig[3..5]<100..200>'                          {both selectors}\n"     \
4649  "  '3dcalc( -a r1+orig -b r2+orig -expr 0.5*(a+b) )'  {calculation}\n"        \
4650  "For the gruesome details, see the output of 'afni -help'.\n"
4651 
4652 /*! Help string to explain dataset "mastering" at length. */
4653 
4654 #define MASTER_HELP_STRING                                                    \
4655     "INPUT DATASET NAMES\n"                                                   \
4656     "-------------------\n"                                                   \
4657     " An input dataset is specified using one of these forms:\n"              \
4658     "    'prefix+view', 'prefix+view.HEAD', or 'prefix+view.BRIK'.\n"         \
4659     " You can also add a sub-brick selection list after the end of the\n"     \
4660     " dataset name.  This allows only a subset of the sub-bricks to be\n"     \
4661     " read in (by default, all of a dataset's sub-bricks are input).\n"       \
4662     " A sub-brick selection list looks like one of the following forms:\n"    \
4663     "   fred+orig[5]                     ==> use only sub-brick #5\n"         \
4664     "   fred+orig[5,9,17]                ==> use #5, #9, and #17\n"           \
4665     "   fred+orig[5..8]     or [5-8]     ==> use #5, #6, #7, and #8\n"        \
4666     "   fred+orig[5..13(2)] or [5-13(2)] ==> use #5, #7, #9, #11, and #13\n"  \
4667     " Sub-brick indexes start at 0.  You can use the character '$'\n"         \
4668     " to indicate the last sub-brick in a dataset; for example, you\n"        \
4669     " can select every third sub-brick by using the selection list\n"         \
4670     "   fred+orig[0..$(3)]\n"                                                 \
4671     "\n"                                                                      \
4672     " N.B.: The sub-bricks are read in the order specified, which may\n"      \
4673     " not be the order in the original dataset.  For example, using\n"        \
4674     "   fred+orig[0..$(2),1..$(2)]\n"                                         \
4675     " will cause the sub-bricks in fred+orig to be input into memory\n"       \
4676     " in an interleaved fashion.  Using\n"                                    \
4677     "   fred+orig[$..0]\n"                                                    \
4678     " will reverse the order of the sub-bricks.\n"                            \
4679     "\n"                                                                      \
4680     " N.B.: You may also use the syntax <a..b> after the name of an input \n" \
4681     " dataset to restrict the range of values read in to the numerical\n"     \
4682     " values in a..b, inclusive.  For example,\n"                             \
4683     "    fred+orig[5..7]<100..200>\n"                                         \
4684     " creates a 3 sub-brick dataset with values less than 100 or\n"           \
4685     " greater than 200 from the original set to zero.\n"                      \
4686     " If you use the <> sub-range selection without the [] sub-brick\n"       \
4687     " selection, it is the same as if you had put [0..$] in front of\n"       \
4688     " the sub-range selection.\n"                                             \
4689     "\n"                                                                      \
4690     " N.B.: Datasets using sub-brick/sub-range selectors are treated as:\n"   \
4691     "  - 3D+time if the dataset is 3D+time and more than 1 brick is chosen\n" \
4692     "  - otherwise, as bucket datasets (-abuc or -fbuc)\n"                    \
4693     "    (in particular, fico, fitt, etc datasets are converted to fbuc!)\n"  \
4694     "\n"                                                                      \
4695     " N.B.: The characters '$ ( ) [ ] < >'  are special to the shell,\n"      \
4696     " so you will have to escape them.  This is most easily done by\n"        \
4697     " putting the entire dataset plus selection list inside forward\n"        \
4698     " single quotes, as in 'fred+orig[5..7,9]', or double quotes \"x\".\n"
4699 
4700 
4701 /*! Help string to explain catenated datasets. */
4702 
4703 #define CATENATE_HELP_STRING                                                  \
4704     "CATENATED AND WILDCARD DATASET NAMES\n"                                  \
4705     "------------------------------------\n"                                  \
4706     " Datasets may also be catenated or combined in memory, as if one first\n"\
4707     " ran 3dTcat or 3dbucket.\n"                                              \
4708     " \n"                                                                     \
4709     " An input with space-separated elements will be read as a concatenated\n"\
4710     " dataset, as with 'dset1+tlrc dset2+tlrc dset3+tlrc', or with paths,\n"  \
4711     " 'dir/dset1+tlrc dir/dset2+tlrc dir/dset3+tlrc'.\n"                      \
4712     " The datasets will be combined (as if by 3dTcat) and then treated as a\n"\
4713     " single input dataset.  Note that the quotes are required to specify\n"\
4714     " them as a single argument.\n"                                           \
4715     " \n"                                                                     \
4716     " Sub-brick selection using '[]' works with space separated dataset\n"    \
4717     " names.  If the selector is at the end, it is considered global and\n"   \
4718     " applies to all inputs.  Otherwise, it applies to the adjacent input.\n" \
4719     " For example:\n"                                                         \
4720     "    local:  'dset1+tlrc[2,3] dset2+tlrc[7,0,1] dset3+tlrc[5,0,$]'\n"     \
4721     "    global: 'dset1+tlrc dset2+tlrc dset3+tlrc[5,6]'\n"                   \
4722     " \n"                                                                     \
4723     " N.B. If AFNI_PATH_SPACES_OK is set to Yes, will be considered as part\n"\
4724     " of the dataset name, and not as a separator between them.\n"            \
4725     " \n"                                                                     \
4726     " Similar treatment applies when specifying datasets using a wildcard\n"  \
4727     " pattern, using '*' or '?', as in: 'dset*+tlrc.HEAD'.  Any sub-brick\n"  \
4728     " selectors would apply to all matching datasets, as with:\n"             \
4729     "    'dset*+tlrc.HEAD[2,5,3]'\n"                                          \
4730     " \n"                                                                     \
4731     " N.B.: complete filenames are required when using wildcard matching,\n"\
4732     " or no files will exist to match, e.g. 'dset*+tlrc' would not work.\n" \
4733     " \n"                                                                     \
4734     " N.B.: '[]' are processed as sub-brick or time point selectors.  They\n" \
4735     " are therefore not allowed as wildcard characters in this context.\n"    \
4736     " \n"                                                                     \
4737     " Space and wildcard catenation can be put together.  In such a case,\n"  \
4738     " spaces divide the input into wildcard pieces, which are processed\n"    \
4739     " individually.\n"                                                        \
4740     " \n"                                                                     \
4741     " Examples (each is processed as a single, combined dataset):\n"          \
4742     " \n"                                                                     \
4743     "    'dset1+tlrc dset2+tlrc dset3+tlrc'\n"                                \
4744     "    'dset1+tlrc dset2+tlrc dset3+tlrc[2,5,3]'\n"                         \
4745     "    'dset1+tlrc[3] dset2+tlrc[0,1] dset3+tlrc[3,0,1]'\n"                 \
4746     " \n"                                                                     \
4747     "    'dset*+tlrc.HEAD'\n"                                                 \
4748     "    'dset*+tlrc.HEAD[2,5,3]'\n"                                          \
4749     "    'dset1*+tlrc.HEAD[0,1] dset2*+tlrc.HEAD[7,8]'\n"                     \
4750     " \n"                                                                     \
4751     "    'group.*/subj.*/stats*+tlrc.HEAD[7]'\n"
4752 
4753 /*! Help string to explain calculated datasets. */
4754 
4755 #define CALC_HELP_STRING                                                   \
4756    "CALCULATED DATASETS\n"                                                 \
4757    "-------------------\n"                                                 \
4758    " Datasets may also be specified as runtime-generated results from\n"   \
4759    " program 3dcalc.  This type of dataset specifier is enclosed in\n"     \
4760    " quotes, and starts with the string '3dcalc(':\n"                      \
4761    "    '3dcalc( opt opt ... opt )'\n"                                     \
4762    " where each 'opt' is an option to program 3dcalc; this program\n"      \
4763    " is run to generate a dataset in the directory given by environment\n" \
4764    " variable TMPDIR (default=/tmp).  This dataset is then read into\n"    \
4765    " memory, locked in place, and deleted from disk.  For example\n"       \
4766    "    afni -dset '3dcalc( -a r1+orig -b r2+orig -expr 0.5*(a+b) )'\n"    \
4767    " will let you look at the average of datasets r1+orig and r2+orig.\n"  \
4768    " N.B.: using this dataset input method will use lots of memory!\n"
4769 
4770 /*! Help string to explain 1D column and row selection. [01 May 2003] */
4771 
4772 #define TS_HELP_STRING                                                        \
4773    "TIMESERIES (1D) INPUT\n"                                                  \
4774    "---------------------\n"                                                  \
4775    "A timeseries file is in the form of a 1D or 2D table of ASCII numbers;\n" \
4776    "for example:   3 5 7\n"                                                   \
4777    "               2 4 6\n"                                                   \
4778    "               0 3 3\n"                                                   \
4779    "               7 2 9\n"                                                   \
4780    "This example has 4 rows and 3 columns.  Each column is considered as\n"   \
4781    "a timeseries in AFNI.  The convention is to store this type of data\n"    \
4782    "in a filename ending in '.1D'.\n"                                         \
4783    "\n"                                                                       \
4784    "** COLUMN SELECTION WITH [] **\n"                                         \
4785    "When specifying a timeseries file to an command-line AFNI program, you\n" \
4786    "can select a subset of columns using the '[...]' notation:\n"             \
4787    "  'fred.1D[5]'            ==> use only column #5\n"                       \
4788    "  'fred.1D[5,9,17]'       ==> use columns #5, #9, and #17\n"              \
4789    "  'fred.1D[5..8]'         ==> use columns #5, #6, #7, and #8\n"           \
4790    "  'fred.1D[5..13(2)]'     ==> use columns #5, #7, #9, #11, and #13\n"     \
4791    "Column indices start at 0.  You can use the character '$'\n"              \
4792    "to indicate the last column in a 1D file; for example, you\n"             \
4793    "can select every third column in a 1D file by using the selection list\n" \
4794    "  'fred.1D[0..$(3)]'      ==> use columns #0, #3, #6, #9, ....\n"         \
4795    "\n"                                                                       \
4796    "** ROW SELECTION WITH {} **\n"                                            \
4797    "Similarly, you select a subset of the rows using the '{...}' notation:\n" \
4798    "  'fred.1D{0..$(2)}'      ==> use rows #0, #2, #4, ....\n"                \
4799    "You can also use both notations together, as in\n"                        \
4800    "  'fred.1D[1,3]{1..$(2)}' ==> columns #1 and #3; rows #1, #3, #5, ....\n" \
4801    "\n"                                                                       \
4802    "** DIRECT INPUT OF DATA ON THE COMMAND LINE WITH 1D: **\n"                \
4803    "You can also input a 1D time series 'dataset' directly on the command\n"  \
4804    "line, without an external file. The 'filename' for such input has the\n"  \
4805    "general format\n"                                                         \
4806    "  '1D:n_1@val_1,n_2@val_2,n_3@val_3,...'\n"                               \
4807    "where each 'n_i' is an integer and each 'val_i' is a float.  For\n"       \
4808    "example\n"                                                                \
4809    "   -a '1D:5@0,10@1,5@0,10@1,5@0'\n"                                       \
4810    "specifies that variable 'a' be assigned to a 1D time series of 35,\n"     \
4811    "alternating in blocks between values 0 and value 1.\n"                    \
4812    " * Spaces or commas can be used to separate values.\n"                    \
4813    " * A '|' character can be used to start a new input \"line\":\n"          \
4814    "   Try 1dplot '1D: 3 4 3 5 | 3 5 4 3'\n"                                  \
4815    "\n"                                                                       \
4816    "** TRANSPOSITION WITH \\' **\n"                                           \
4817    "Finally, you can force most AFNI programs to transpose a 1D file on\n"    \
4818    "input by appending a single ' character at the end of the filename.\n"    \
4819    "N.B.: Since the ' character is also special to the shell, you'll\n"       \
4820    "      probably have to put a \\ character before it. Examples:\n"         \
4821    "       1dplot '1D: 3 2 3 4 | 2 3 4 3'   and\n"                            \
4822    "       1dplot '1D: 3 2 3 4 | 2 3 4 3'\\'\n"                               \
4823    "When you have reached this level of understanding, you are ready to\n"    \
4824    "take the AFNI Jedi Master test.  I won't insult you by telling you\n"     \
4825    "where to find this examination.\n"
4826 
4827 /*---------------------------- TSV (.tsv) file help  -------------------------*/
4828 
4829 #undef  TSV_HELP_STRING
4830 #define TSV_HELP_STRING                                                          \
4831    "TAB SEPARATED VALUE (.tsv) FILES [Sep 2018]\n"                               \
4832    "-------------------------------------------\n"                               \
4833    "These files are used in BIDS http://bids.neuroimaging.io and AFNI\n"         \
4834    "programs can read these in a few places.\n"                                  \
4835    "\n"                                                                          \
4836    "The format of a .tsv file is a set of columns, where the values in\n"        \
4837    "each row are separated by tab characters -- spaces are NOT separators.\n"    \
4838    "Each element is string, some of which are numeric (e.g. 3.1416).\n"          \
4839    "The first row of a .tsv file is a set of strings which are column\n"         \
4840    "desciptors (separated by tabs, of course). For the most part, the\n"         \
4841    "following data in each column are exclusively numeric or exclusively\n"      \
4842    "strings. Strings can contain blanks/spaces since only tabs are used\n"       \
4843    "to separate values.\n"                                                       \
4844    "\n"                                                                          \
4845    "A .tsv file can be read in most places where a .1D file is read.\n"          \
4846    "However, columns (after the header row) that are not purely numeric\n"       \
4847    "will be ignored, since the internal usage of .1D data in AFNI is numeric.\n" \
4848    "Thus, you can do something like\n"                                           \
4849    "  1dplot -nopush -sepscl sub-10506_task-pamenc_events.tsv\n"                 \
4850    "and you will get a plot of all the numeric columns in this BIDS file.\n"     \
4851    "Column selection '[]' can be done, using numbers to specify columns\n"       \
4852    "or using the column labels in the .tsv file.\n"                              \
4853    "\n"                                                                          \
4854    "N.B.: The string 'N/A' or 'n/a' in a column that is otherwise numeric\n"     \
4855    "      will be considered to be a number, and will be replaced on input\n"    \
4856    "      with the mean of the \"true\" numbers in the column -- there is\n"     \
4857    "      no concept of missing data in an AFNI .1D file.\n"                     \
4858    "    ++ If you don't like this, well ... too bad for you.\n"                  \
4859    "\n"                                                                          \
4860    "Program 1dcat has special knowledge of .tsv files, and will cat\n"           \
4861    "(sideways - along rows) .tsv and .1D files together. It also has an\n"       \
4862    "option to write the output in .tsv format.\n"                                \
4863    "\n"                                                                          \
4864    "For example, to get the 'onset', 'duration', and 'trial_type' columns\n"     \
4865    "out of a BIDS task .tsv file, a command like this could be used:\n"          \
4866    "  1dcat sub-10506_task-pamenc_events.tsv'[onset,duration,trial_type]'\n"     \
4867    "Note that the column headers are lost in this output, but could be kept\n"   \
4868    "if the 1dcat '-tsvout' option were used. In reverse, a numeric .1D file\n"   \
4869    "can be converted to .tsv format by a command like:\n"                        \
4870    "  1dcat -tsvout Fred.1D\n"                                                   \
4871    "In this case, since a the data for .1D file doesn't have headers for its\n"  \
4872    "columns, 1dcat will invent some column names.\n"                             \
4873    "\n"                                                                          \
4874    "At this time, other programs don't 'know' much about .tsv files, and will\n" \
4875    "ignore the header row and non-numeric columns when reading a .tsv file.\n"   \
4876    "in place of a .1D file.\n"
4877 
4878 /*----------------------------------------------------------------------------*/
4879 
4880 extern void THD_delete_3dim_dataset( THD_3dim_dataset * , RwcBoolean ) ;
4881 extern void *DSET_Label_Dtable(THD_3dim_dataset *dset);
4882 extern THD_3dim_dataset * THD_3dim_from_block( THD_datablock * ) ;
4883 extern void THD_allow_empty_dataset( int ) ; /* 23 Mar 2001 */
4884 extern THD_3dim_dataset_array *
4885    THD_array_3dim_from_block( THD_datablock_array * blk_arr ) ;
4886 
4887 extern RwcBoolean THD_write_3dim_dataset( char *,char * ,
4888                                        THD_3dim_dataset * , RwcBoolean );
4889 
4890 extern int THD_get_write_error_count(void) ;     /* 23 Sep 2013 */
4891 extern void THD_reset_write_error_count(void) ;
4892 
4893 extern void THD_use_3D_format   ( int ) ;  /* 21 Mar 2003 */
4894 extern void THD_use_NIFTI_format( int ) ;  /* 06 Apr 2005 */
4895 extern void THD_set_quiet_overwrite ( int ) ;  /* 31 Jan 2011 */
4896 extern int THD_get_quiet_overwrite (void );/* 31 Jan 2011 */
4897 extern RwcBoolean THD_write_datablock( THD_datablock * , RwcBoolean ) ;
4898 extern RwcBoolean THD_write_atr( THD_datablock * ) ;
4899 extern RwcBoolean THD_write_nimlatr( THD_datablock * ) ;  /* 01 Jun 2005 */
4900 extern void THD_set_write_compression( int mm ) ;
4901 extern int THD_enviro_write_compression(void) ;
4902 extern int THD_get_write_compression(void) ;
4903 
4904 extern void THD_set_write_order( int ) ;
4905 extern void THD_enviro_write_order(void) ;
4906 extern int THD_get_write_order(void) ;
4907 
4908 extern int TRUST_host(char *) ;
4909 #define OKHOST(hh) TRUST_host(hh) ;
4910 extern void TRUST_addhost(char *) ;      /* 21 Feb 2001 */
4911 
4912 extern RwcBoolean THD_load_datablock( THD_datablock * ) ;
4913 extern void    THD_load_no_mmap(void) ;                         /* Apr 2013 */
4914 extern void    THD_load_datablock_verbose(int) ;             /* 21 Aug 2002 */
4915 extern void    THD_set_freeup( generic_func * ) ;            /* 18 Oct 2001 */
4916 extern RwcBoolean THD_purge_datablock( THD_datablock * , int ) ;
4917 extern RwcBoolean THD_purge_one_brick( THD_datablock * , int ) ;
4918 extern void    THD_force_malloc_type( THD_datablock * , int ) ;
4919 extern int     THD_count_databricks( THD_datablock * ) ;
4920 extern int     THD_subset_loaded( THD_3dim_dataset *, int, int * ) ;
4921 extern void    THD_load_analyze( THD_datablock * ) ;         /* 27 Aug 2002 */
4922 extern void    THD_load_ctfmri ( THD_datablock * ) ;         /* 04 Dec 2002 */
4923 extern void    THD_load_ctfsam ( THD_datablock * ) ;         /* 04 Dec 2002 */
4924 extern void    THD_load_1D     ( THD_datablock * ) ;         /* 04 Mar 2003 */
4925 extern void    THD_load_3D     ( THD_datablock * ) ;         /* 21 Mar 2003 */
4926 extern void    THD_load_nifti  ( THD_datablock * ) ;         /* 28 Aug 2003 */
4927 extern void    THD_load_mpeg   ( THD_datablock * ) ;         /* 03 Dec 2003 */
4928 extern void    THD_load_tcat   ( THD_datablock * ) ;         /* 04 Aug 2004 */
4929 extern int     THD_load_niml   ( THD_datablock * ) ;         /* 12 Jun 2006 */
4930 extern int     THD_load_gifti  ( THD_datablock * ) ;         /* 13 Feb 2008 */
4931 
4932 extern int     THD_count_potential_databricks( THD_datablock *dblk );
4933 
4934 extern THD_3dim_dataset * THD_mean_dataset( int nds, THD_3dim_dataset **dsin, int ivbot, int ivtop, int verb ) ;
4935 
4936 extern void    THD_zerofill_dataset( THD_3dim_dataset * ) ;  /* 18 Mar 2005 */
4937 extern int     THD_apply_master_subrange( THD_datablock * ); /* 14 Apr 2006 */
4938 extern int     THD_apply_master_subrange_list(THD_datablock *);/* 30 Nov 2016 */
4939 extern void    THD_patch_brickim( THD_3dim_dataset * ) ;     /* 20 Oct 2006 */
4940 
4941 extern int THD_datum_constant( THD_datablock * ) ;           /* 30 Aug 2002 */
4942 #define DSET_datum_constant(ds) THD_datum_constant((ds)->dblk)
4943 
4944 #define ALLOW_FSL_FEAT  /* 27 Aug 2002 */
4945 
4946 #define MINC_FLOATIZE_MASK 1
4947 #define MINC_SWAPIZE_MASK 1<<1
4948 
4949 extern void THD_write_1D( char *, char *, THD_3dim_dataset *); /* 04 Mar 2003 */
4950 extern void THD_write_3D( char *, char *, THD_3dim_dataset *); /* 21 Mar 2003 */
4951 extern RwcBoolean THD_write_niml( THD_3dim_dataset *, int);
4952 extern RwcBoolean THD_write_niml_to_stream( THD_3dim_dataset *, char *, int);
4953 extern RwcBoolean THD_write_gifti( THD_3dim_dataset *, int, int);
4954 
4955 extern int  write_niml_file( char *, NI_group *);      /* 12 Jun 2006 [rickr] */
4956 extern int  write_niml_stream( char *, NI_group *);    /* 10 Oct 2019 [rickr] */
4957 
4958 extern void THD_reconcile_parents( THD_sessionlist * ) ;
4959 extern THD_slist_find THD_dset_in_sessionlist( int,void *, THD_sessionlist *, int ) ;
4960 extern THD_slist_find THD_dset_in_session( int,void * , THD_session * ) ;
4961 extern int AFNI_append_dset_to_session( char *fname, int sss ) ;
4962 
4963 extern void THD_check_idcodes( THD_sessionlist * ) ; /* 08 Jun 1999 */
4964 
4965 extern void THD_load_statistics( THD_3dim_dataset * ) ;
4966 extern void THD_update_statistics( THD_3dim_dataset * ) ;
4967 extern THD_brick_stats THD_get_brick_stats( MRI_IMAGE * ) ;
4968 extern void THD_update_one_bstat( THD_3dim_dataset * , int ) ;  /* 29 Mar 2005 */
4969 extern int THD_dset_scale(THD_3dim_dataset *aset, float fac);   /* 31 Jan 2015 */
4970 extern int THD_count_nonzero_bricks( THD_3dim_dataset *dset ) ; /* 17 Jan 2017 */
4971 
4972 extern THD_fvec3 THD_3dind_to_3dmm( THD_3dim_dataset * , THD_ivec3 ) ;
4973 extern THD_fvec3 THD_3dind_to_3dmm_no_wod( THD_3dim_dataset * , THD_ivec3 ) ;
4974 extern THD_ivec3 THD_3dmm_to_3dind( THD_3dim_dataset * , THD_fvec3 ) ;
4975 extern THD_ivec3 THD_3dmm_to_3dind_warn( THD_3dim_dataset * , THD_fvec3, int * ) ;
4976 extern THD_ivec3 THD_3dmm_to_3dind_no_wod( THD_3dim_dataset * , THD_fvec3 ) ;
4977                                                    /* 28 Sep 2004  [rickr] */
4978 extern THD_fvec3 THD_3dind_to_dicomm_no_wod( THD_3dim_dataset *dset, THD_ivec3 iv ) ;
4979 
4980 extern THD_fvec3 THD_3dfind_to_3dmm( THD_3dim_dataset * , THD_fvec3 ) ;
4981 extern THD_fvec3 THD_3dmm_to_3dfind( THD_3dim_dataset * , THD_fvec3 ) ;
4982 
4983 extern THD_fvec3 THD_3dmm_to_dicomm( THD_3dim_dataset * , THD_fvec3 ) ;
4984 extern THD_fvec3 THD_dicomm_to_3dmm( THD_3dim_dataset * , THD_fvec3 ) ;
4985 #define AFNI_3D_to_1D_index(i, j, k, ni, nij) \
4986       ( (int)(i) + (int)(j) * (ni) + (int)(k) * (nij) )
4987 
4988 #define AFNI_1D_to_3D_index(ijk, i, j, k, ni, nij){  \
4989    k = ((ijk) / (nij)); \
4990    j = ((ijk) % (nij));   \
4991    i = ((j) % (ni));  \
4992    j = ((j) / (ni)); \
4993 }
4994 
4995 
4996 extern THD_fvec3 THD_tta_to_mni( THD_fvec3 ) ;  /* 29 Apr 2002 */
4997 extern THD_fvec3 THD_mni_to_tta( THD_fvec3 ) ;
4998 extern void THD_3mni_to_3tta( float *, float *, float *) ;
4999 extern void THD_3tta_to_3mni( float *, float *, float *) ;
5000 
5001 extern float THD_timeof      ( int , float , THD_timeaxis * ) ;
5002 extern float THD_timeof_vox  ( int , int , THD_3dim_dataset * ) ;
5003 extern float THD_timeof_slice( int , int , THD_3dim_dataset * ) ;  /* BDW */
5004 
5005 extern float * TS_parse_tpattern( int, float, char * ) ;  /* 11 Dec 2007 */
5006 
5007 extern THD_fvec3 THD_dataset_center( THD_3dim_dataset * ) ;  /* 01 Feb 2001 */
5008 extern THD_fvec3 THD_cmass( THD_3dim_dataset *xset , int iv , byte *mmm,
5009                                int cmode);
5010 extern float *THD_roi_cmass(THD_3dim_dataset *xset , int iv ,
5011                             int *rois, int N_rois, int cmode);
5012 extern THD_fvec3 THD_Icent( THD_3dim_dataset *xset , int iv , byte *mmm,
5013                      int cmode, THD_fvec3 cmxyz);
5014 THD_fvec3 THD_Dcent( THD_3dim_dataset *xset , int iv , byte *mmm,
5015                      int cmode, THD_fvec3 cmxyz);
5016 double THD_xyz_distance( THD_3dim_dataset *xset , MRI_IMAGE *im ,
5017    double xcm, double ycm, double zcm);
5018 
5019 extern int THD_dataset_mismatch(THD_3dim_dataset *, THD_3dim_dataset *) ;
5020 extern double THD_diff_vol_vals(THD_3dim_dataset *d1, THD_3dim_dataset *d2,
5021                                 int scl);
5022 extern int THD_dataset_tshift( THD_3dim_dataset * , int ) ; /* 15 Feb 2001 */
5023 
5024 #define MISMATCH_CENTER  (1<<0)  /* within 0.2 voxel */
5025 #define MISMATCH_DELTA   (1<<1)  /* within 0.001 voxel */
5026 #define MISMATCH_ORIENT  (1<<2)
5027 #define MISMATCH_DIMEN   (1<<3)
5028 #define MISMATCH_OBLIQ   (1<<4)
5029 
5030 /*----------------------------------------------------------------*/
5031 /*--------  FD_brick type: for rapid extraction of slices --------*/
5032 
5033 /*! This type is to hold information needed for the rapid extraction
5034            of slices from an AFNI dataset (THD_3dim_dataset struct).
5035 
5036     It exists primarily as a historical artifact.  The earliest version
5037     of AFNI was to be called FD3, as a successor to FD2.  The FD_brick
5038     was conceived as part of FD3.  However, FD3 morphed into AFNI within
5039     a few weeks, but by then I didn't want to throw away the code that
5040     had already been structured around this (primarily the imseq.c stuff).
5041 */
5042 
5043 typedef struct FD_brick {
5044 
5045    THD_ivec3 nxyz ;     /*!< actual dimensions as read in */
5046    THD_ivec3 sxyz ;     /*!< starting indices in each dataset dimen */
5047    THD_ivec3 a123 ;     /*!< axis codes as supplied in THD_3dim_dataset_to_brick */
5048 
5049    int n1 ;             /*!< ni = length in direction i */
5050    int d1 ;             /*!< di = stride in direction i */
5051    int e1 ;             /*!< ei = last index in direc i */
5052    int n2 ;             /*!< ni = length in direction i */
5053    int d2 ;             /*!< di = stride in direction i */
5054    int e2 ;             /*!< ei = last index in direc i */
5055    int n3 ;             /*!< ni = length in direction i */
5056    int d3 ;             /*!< di = stride in direction i */
5057    int start ;          /*!< start = offset of 1st elem */
5058 
5059    float del1 ;         /*!< voxel dimensions */
5060    float del2 ;         /*!< voxel dimensions */
5061    float del3 ;         /*!< voxel dimensions */
5062 
5063    THD_3dim_dataset *dset ;     /*!< pointer to parent dataset */
5064    int resam_code ;             /*!< how to resample normal sub-bricks */
5065    int thr_resam_code ;         /*!< how to resample statistical sub-bricks */
5066    int deltival ;               /*!< how much to shift the sub-brick index */
5067 
5068    char namecode[32] ;          /*!< June 1997 */
5069 
5070    int       ntmask ;           /*!< Mar 2013 */
5071    MRI_IMAGE *tmask ;           /*!< Mar 2013 */
5072 
5073    RwcPointer parent ;           /*!< struct owner */
5074    RwcPointer brother;
5075 } FD_brick ;
5076 
5077 #define TMASK_INDEX(fdb) ((fdb)->ntmask)
5078 
5079 #define CLEAR_TMASK(fdb)                                        \
5080  do{ if( fdb != NULL && fdb->tmask != NULL ){                   \
5081        mri_free(fdb->tmask); fdb->tmask=NULL; fdb->ntmask=-666; \
5082      } } while(0)
5083 
5084 #define STATUS_TMASK(sss,fdb)                                   \
5085  do{ if( fdb != NULL ) STATUSp(sss,fdb->tmask) ; } while(0)
5086 
5087 #define DESTROY_FD_BRICK(fdb)       \
5088  do{ FD_brick *_jj=(FD_brick *)fdb; \
5089      if( _jj != NULL ){ mri_free(_jj->tmask); myRwcFree(_jj); fdb=NULL; } } while(0)
5090 
5091 /*! rotate the three numbers (a,b,c) to (b,c,a) into (na,nb,nc) */
5092 
5093 #define ROT3(a,b,c,na,nb,nc) ((na)=(b),(nb)=(c),(nc)=(a))
5094 
5095 /*! Determine if this FD_brick can be drawn (in an image or graph) */
5096 
5097 #define BRICK_DRAWABLE(br)  ((br)->n1 >  1 && (br)->n2 >  1)
5098 #define BRICK_GRAPHABLE(br) ((br)->n1 >= 1 && (br)->n2 >= 1)
5099 
5100 extern FD_brick * THD_3dim_dataset_to_brick( THD_3dim_dataset * ,
5101                                              int,int,int ) ;
5102 
5103 extern MRI_IMAGE * FD_brick_to_mri( int,int , FD_brick * br ) ;
5104 extern MRI_IMAGE * FD_brick_to_series( int , FD_brick * br ) ;
5105 
5106 extern float THD_get_voxel( THD_3dim_dataset *dset , int ijk , int ival ) ;
5107 extern float THD_get_voxel_dicom( THD_3dim_dataset *dset, float x,float y,float z, int ival ) ;
5108 
5109 extern MRI_IMAGE * THD_extract_series( int , THD_3dim_dataset * , int ) ;
5110 extern MRI_IMARR * THD_extract_many_series( int, int *, THD_3dim_dataset * );
5111 extern MRI_IMAGE * THD_dset_to_1Dmri( THD_3dim_dataset *dset ) ;
5112 
5113 extern void THD_extract_many_arrays( int ns , int *ind ,
5114                                      THD_3dim_dataset *dset , float *dsar ) ;
5115 
5116 /*---------------------------------------------------------------------------*/
5117 
5118 typedef struct {
5119   int    nvec , nvals , ignore ;
5120   int   *ivec ;
5121   float *fvec ;
5122   int    nx,ny,nz ;
5123   float  dx,dy,dz , dt ;
5124 } MRI_vectim ;
5125 
5126 #undef  MAKE_VECTIM
5127 #define MAKE_VECTIM(nam,nvc,nvl)                                  \
5128  do{ (nam) = (MRI_vectim *)calloc(sizeof(MRI_vectim),1) ;         \
5129      (nam)->nvec  = (nvc) ;                                       \
5130      (nam)->nvals = (nvl) ;                                       \
5131      (nam)->ivec  = (int *)  calloc(sizeof(int)  ,(nvc)) ;        \
5132      (nam)->fvec  = (float *)calloc(sizeof(float)*(nvc),(nvl)) ;  \
5133  } while(0)
5134 
5135 #undef  ISVALID_VECTIM
5136 #define ISVALID_VECTIM(mv)                                        \
5137  ( (mv) != NULL && (mv)->ivec != NULL && (mv)->fvec != NULL )
5138 
5139 #undef  VECTIM_PTR
5140 #define VECTIM_PTR(mv,j) ((mv)->fvec + (size_t)(j)*(size_t)(mv)->nvals)
5141 
5142 #undef  VECTIM_extract
5143 #define VECTIM_extract(mv,j,aa) \
5144   AAmemcpy( (aa) , VECTIM_PTR((mv),(j)) , sizeof(float)*(mv)->nvals )
5145 
5146 #undef  VECTIM_insert
5147 #define VECTIM_insert(mv,j,aa) \
5148   AAmemcpy( VECTIM_PTR((mv),(j)) , (aa) , sizeof(float)*(mv)->nvals )
5149 
5150 #undef  VECTIM_destroy
5151 #define VECTIM_destroy(mv)                       \
5152  do{ if( (mv)->fvec != NULL ) free((mv)->fvec);  \
5153      if( (mv)->ivec != NULL ) free((mv)->ivec);  \
5154      free((mv)); (mv) = NULL;                    \
5155  } while(0)
5156 
5157 extern MRI_vectim * THD_dset_to_vectim( THD_3dim_dataset *dset, byte *mask, int ignore );
5158 extern MRI_vectim * THD_dset_to_vectim_stend( THD_3dim_dataset *dset, byte *mask , int start, int end ) ;
5159 
5160 extern MRI_vectim * THD_dset_censored_to_vectim( THD_3dim_dataset *dset,
5161                                                  byte *mask , int nkeep , int *keep ) ;
5162 
5163 extern MRI_vectim * THD_dset_list_censored_to_vectim( int nds, THD_3dim_dataset **ds,
5164                                                       byte *mask, int nkeep, int *keep ) ;
5165 
5166 MRI_vectim * THD_2dset_to_vectim( THD_3dim_dataset *dset1, byte *mask1 ,
5167                                   THD_3dim_dataset *dset2, byte *mask2 ,
5168                                   int ignore );
5169 extern int64_t THD_vectim_size( THD_3dim_dataset *dset , byte *mask ) ;
5170 extern int THD_vectim_ifind( int iv , MRI_vectim *mrv ) ;
5171 extern int bsearch_int( int tt , int nar , int *ar ) ;
5172 extern void THD_vectim_to_dset( MRI_vectim *mrv , THD_3dim_dataset *dset ) ;
5173 extern void THD_vectim_to_dset_indexed( MRI_vectim *mrv ,
5174                                         THD_3dim_dataset *dset , int *tlist ) ; /* 06 Aug 2013 */
5175 extern void THD_vectim_indexed_to_dset( MRI_vectim *mrv, int nlist, int *ilist,
5176                                         THD_3dim_dataset *dset ) ;              /* 06 Feb 2014 */
5177 
5178 extern int THD_vectim_data_tofile( MRI_vectim *mrv , char *fnam ) ;
5179 extern int THD_vectim_reload_fromfile( MRI_vectim *mrv , char *fname ) ;
5180 extern void THD_vector_fromfile( int nvals , int iv , float *vv , FILE *fp ) ;
5181 
5182 void THD_check_vectim( MRI_vectim *mv , char *fname ) ;                         /* 13 Mar 2017 */
5183 
5184 extern void mri_blur3D_vectim( MRI_vectim *vim , float fwhm ) ;
5185 extern void THD_vectim_normalize( MRI_vectim *mrv ) ;
5186 extern void THD_vectim_dotprod  ( MRI_vectim *mrv, float *vec, float *dp, int ata ) ;
5187 extern void THD_vectim_spearman ( MRI_vectim *mrv, float *vec, float *dp ) ; /* 01 Mar 2010 */
5188 extern void THD_vectim_quantile ( MRI_vectim *mrv, float *vec, float *dp ) ; /* 11 May 2012 */
5189 extern void THD_vectim_quadrant ( MRI_vectim *mrv, float *vec, float *dp ) ; /* 01 Mar 2010 */
5190 extern void THD_vectim_ktaub    ( MRI_vectim *mrv, float *vec, float *dp ) ; /* 29 Apr 2010 */
5191 extern void THD_vectim_tictactoe( MRI_vectim *mrv, float *vec, float *dp ) ; /* 30 Mar 2011 */
5192 
5193 extern void THD_vectim_pearson_section( MRI_vectim *mrv, float *vec,
5194                                         float *dp, int ibot , int itop ) ; /* 07 Oct 0214 */
5195 
5196 extern void THD_vectim_applyfunc( MRI_vectim *mrv , void *vp ) ;        /* 10 May 2012 */
5197 
5198 extern void THD_vectim_pearsonBC( MRI_vectim *mrv, float srad, int sijk, int pv, float *par ) ;
5199 
5200 extern void THD_vectim_distance( MRI_vectim *mrv , float *vec ,
5201                                  float *dp, int abs, char *xform) ;
5202 
5203 extern float kendallNlogN ( float *arr1, float *arr2, int len ) ;  /* in ktaub.c */
5204 extern float kendallSmallN( float *arr1, float *arr2, int len ) ;
5205 
5206 extern int THD_vectim_subset_average( MRI_vectim *mrv, int nind, int *ind, float *ar );
5207 
5208 extern void THD_vectim_vectim_dot( MRI_vectim *arv, MRI_vectim *brv, float *dp ) ;
5209 
5210 extern MRI_vectim * THD_vectim_copy( MRI_vectim *mrv ) ;      /* 08 Apr 2010 */
5211 extern MRI_vectim * THD_tcat_vectims( int , MRI_vectim ** ) ; /* 26 Jul 2010 */
5212 extern MRI_vectim * THD_dset_list_to_vectim( int, THD_3dim_dataset **, byte * );
5213 
5214 extern MRI_vectim * THD_xyzcat_vectims( int nvim , MRI_vectim **vim ) ; /* 09 Apr 2018 */
5215 
5216 extern MRI_IMAGE * THD_temp_subim_from_vectim( MRI_vectim *vim ,
5217                                                int istart , int numi ) ; /* 19 Nov 2021 */
5218 
5219 #define VECTIM_TEMP_IMAGE(vvv) THD_temp_subim_from_vectim( (vvv) , 0 , 0 )
5220 
5221 
5222 #define ICOR_MAX_FTOP 99999  /* 26 Feb 2010 */
5223 
5224 typedef struct {
5225   THD_3dim_dataset *dset , *mset ;
5226   byte *mmm ;
5227   MRI_IMAGE *gortim ; int gortnpc ;
5228   int start,end , automask , mindex ;
5229   int clen,cnum,cstep ;
5230   float fbot , ftop , blur , sblur ;
5231   int polort , cmeth , despike , change ;
5232   MRI_vectim *mv ;
5233   char *prefix ; int ndet ;
5234   float *tseed ;
5235   int   iter_count ;  /* 05 Feb 2015 */
5236   float iter_thresh ;
5237 
5238   THD_3dim_dataset *eset ; MRI_vectim *ev ;
5239 } ICOR_setup ;
5240 
5241 #undef  INIT_ICOR_setup
5242 #define INIT_ICOR_setup(is) (is) = (ICOR_setup *)calloc(1,sizeof(ICOR_setup))
5243 
5244 #undef  ISVALID_ICOR_setup
5245 #define ISVALID_ICOR_setup(is) ( (is) != NULL && (is)->mv != NULL )
5246 
5247 #undef  DESTROY_ICOR_setup
5248 #define DESTROY_ICOR_setup(is)                               \
5249  do{ if( (is) != NULL ){                                     \
5250        if( (is)->mmm    != NULL ) free((is)->mmm) ;          \
5251        if( (is)->gortim != NULL ) mri_free((is)->gortim) ;   \
5252        if( (is)->mv     != NULL ) VECTIM_destroy((is)->mv) ; \
5253        if( (is)->ev     != NULL ) VECTIM_destroy((is)->ev) ; \
5254        if( (is)->prefix != NULL ) free((is)->prefix) ;       \
5255        if( (is)->tseed  != NULL ) free((is)->tseed) ;        \
5256        free((is)) ; (is) = NULL ;                            \
5257  }} while(0)
5258 
5259 extern int         THD_instacorr_prepare( ICOR_setup *iset ) ;
5260 extern MRI_IMAGE * THD_instacorr        ( ICOR_setup *iset, int ijk ) ;
5261 extern int         THD_instacorr_cmeth_needs_normalize( int cmeth );
5262 extern MRI_IMARR * THD_instacorr_collection( ICOR_setup *iset, int ijk ) ;
5263 
5264 extern int THD_instacorr_cmeth_needs_norm(int cmeth) ;
5265 /*---------------------------------------------------------------------------*/
5266 
5267 extern int THD_extract_array      ( int, THD_3dim_dataset *, int, void * ) ;
5268 extern int THD_extract_float_array( int, THD_3dim_dataset *, float * ) ;
5269 extern float THD_get_float_value( int, int, THD_3dim_dataset * ) ;
5270 
5271 extern MRI_IMAGE * THD_extract_float_brick( int , THD_3dim_dataset * ) ;
5272 extern MRI_IMAGE * THD_extract_double_brick( int , THD_3dim_dataset * ) ;
5273 extern MRI_IMAGE * THD_extract_int_brick( int , THD_3dim_dataset * ) ;
5274 extern float * THD_extract_to_float( int , THD_3dim_dataset * ) ;
5275 extern double * THD_extract_to_double( int , THD_3dim_dataset * ) ;
5276 extern int * THD_extract_to_int( int , THD_3dim_dataset * ) ;
5277 
5278 extern void THD_insert_series( int, THD_3dim_dataset *, int, int, void *, int );
5279 
5280 extern int THD_voxel_is_constant( int ind , THD_3dim_dataset *dset ) ;
5281 
5282 extern floatvec * THD_fitter( int npt , float *far  ,
5283                               int nref, float *ref[], int meth, float *ccon ) ;
5284 
5285 extern floatvec * THD_deconvolve( int npt    , float *far   ,
5286                                   int minlag , int maxlag   , float *kern,
5287                                   int nbase  , float *base[],
5288                                   int meth   , float *ccon  , int dcon   ,
5289                                   int pencode, float penpar               ) ;
5290 
5291 extern floatvec * THD_fitter_fitts( int npt, floatvec *fv,
5292                                     int nref, float *ref[], float *far ) ;
5293 
5294 extern void       THD_fitter_do_fitts(int qq) ;
5295 extern floatvec * THD_retrieve_fitts(void) ;
5296 extern void       THD_fitter_voxid( int i ) ;       /* 10 Sep 2008 */
5297 extern void       THD_fitter_set_vthresh( float ) ; /* 18 May 2010 */
5298 
5299 /* 11 Mar 2011: LASSO regression stuff (thd_lasso.c) */
5300 
5301 extern floatvec * THD_lasso_L2fit( int npt    , float *far   ,
5302                                    int nref   , float *ref[] ,
5303                                    float *lam , float *ccon   ) ;
5304 extern void THD_lasso_fixlam( float x ) ;
5305 extern void THD_lasso_setlamvec( int nref , float *lam ) ;
5306 extern void THD_lasso_dopost( int x ) ;
5307 extern void THD_lasso_dosigest( int x ) ;
5308 extern void THD_lasso_setdeps( float x ) ;
5309 extern floatvec * THD_lasso( int meth   ,
5310                              int npt    , float *far   ,
5311                              int nref   , float *ref[] ,
5312                              float *lam , float *ccon   ) ;
5313 extern floatvec * THD_sqrtlasso_L2fit( int npt    , float *far   ,
5314                                        int nref   , float *ref[] ,
5315                                        float *lam , float *ccon   ) ;
5316 
5317 extern void THD_lasso_add_centro_block( intvec *mb ) ; /* 06 Aug 2021 */
5318 
5319 /*--------------- routines that are in thd_detrend.c ---------------*/
5320 
5321 extern void get_linear_trend     ( int, float *, float *, float * ) ;
5322 extern void THD_linear_detrend   ( int, float *, float *, float * ) ;
5323 extern void get_quadratic_trend  ( int, float *, float *, float *, float * ) ;
5324 extern void THD_quadratic_detrend( int, float *, float *, float *, float * ) ;
5325 extern float THD_normalize       ( int, float * ) ;
5326 extern void THD_normRMS          ( int, float * ) ;  /* 06 Jun 2008 */
5327 extern void THD_normmax          ( int, float * ) ;  /* 26 Mar 2008 */
5328 extern void THD_normL1           ( int, float * ) ;  /* 26 Mar 2008 */
5329 extern void THD_cubic_detrend    ( int, float * ) ;  /* 15 Nov 1999 */
5330 
5331 extern void THD_const_detrend    ( int, float *, float * ); /* 24 Aug 2001 */
5332 extern void THD_linear_detrend_complex  ( int, complex * ); /* 05 Mar 2007 */
5333 extern int  THD_is_constant      ( int , float * );         /* 11 May 2011 */
5334 extern int  THD_is_zero          ( int , float * );         /* 20 Feb 2014 */
5335 
5336 extern void THD_generic_detrend_LSQ( int, float *, int, int, float **, float *) ;
5337 extern void THD_generic_detrend_L1 ( int, float *, int, int, float **, float *) ;
5338 extern void THD_generic_retrend    ( int, float *, int, int, float **, float *) ;
5339 
5340 extern MRI_IMARR * THD_time_fit_dataset( THD_3dim_dataset *, int, float **, int, byte *);
5341 extern void THD_extract_detrended_array( THD_3dim_dataset * ,
5342                                          int, float **, MRI_IMARR *,
5343                                          int, int, float * ) ;
5344 
5345 extern THD_3dim_dataset * THD_detrend_dataset( THD_3dim_dataset *dset ,
5346                                                int nref , float **ref ,
5347                                                int meth , int scl ,
5348                                                byte *mask , MRI_IMARR **imar ) ;
5349 
5350 extern int THD_retrend_dataset( THD_3dim_dataset *dset ,
5351                                 int nref , float **ref ,
5352                                 int scl , byte *mask , MRI_IMARR *imar ) ;
5353 
5354 extern float ** THD_build_trigref( int corder , int nvals ) ;
5355 extern float ** THD_build_polyref( int nref   , int nvals ) ; /* 20 Sep 2007 */
5356 
5357 #define DETREND_linear(n,f)    THD_linear_detrend(n,f,NULL,NULL)
5358 #define DETREND_quadratic(n,f) THD_quadratic_detrend(n,f,NULL,NULL,NULL)
5359 #define DETREND_cubic(n,f)     THD_cubic_detrend(n,f)
5360 #define DETREND_const(n,f)     THD_const_detrend(n,f,NULL)
5361 
5362 /*! Macro to detrend a time series array in to various polynomial orders. */
5363 
5364 #define DETREND_polort(p,n,f)                            \
5365  do{ switch(p){ default:                         break;  \
5366                  case 0: DETREND_const(n,f)    ; break;  \
5367                  case 1: DETREND_linear(n,f)   ; break;  \
5368                  case 2: DETREND_quadratic(n,f); break;  \
5369                  case 3: DETREND_cubic(n,f)    ; break; } } while(0)
5370 
5371 /*------------------------------------------------------------------*/
5372 
5373 extern THD_ivec3 THD_fdind_to_3dind( FD_brick * , THD_ivec3 ) ;
5374 extern THD_ivec3 THD_3dind_to_fdind( FD_brick * , THD_ivec3 ) ;
5375 
5376 extern THD_fvec3 THD_fdfind_to_3dfind( FD_brick *, THD_fvec3) ; /* 30 Aug 2001 */
5377 extern THD_fvec3 THD_3dfind_to_fdfind( FD_brick *, THD_fvec3) ;
5378 
5379 extern FD_brick ** THD_setup_bricks( THD_3dim_dataset * ) ;
5380 
5381 extern FD_brick * THD_oriented_brick( THD_3dim_dataset *, char *) ; /* 07 Dec 2001 */
5382 
5383 extern size_t thd_floatscan  ( size_t , float *   ) ; /* 30 Jul 1999 */
5384 extern size_t thd_complexscan( size_t , complex * ) ; /* 14 Sep 1999 */
5385 
5386 #undef  MRI_floatscan
5387 #define MRI_floatscan(imm)                                                                       \
5388  do{ if( (imm) != NULL ){                                                                        \
5389            if( (imm)->kind== MRI_float   ) thd_floatscan  ((imm)->nvox,MRI_FLOAT_PTR  ((imm))) ; \
5390       else if( (imm)->kind== MRI_complex ) thd_complexscan((imm)->nvox,MRI_COMPLEX_PTR((imm))) ; \
5391    }} while(0)
5392 
5393 #undef floatfix
5394 #ifdef isfinite
5395 # define floatfix(x) if( !isfinite(x) ) (x) = 0.0f ; else
5396 #else
5397 # define floatfix(x) if( !finite(x) ) (x) = 0.0f ; else
5398 # define isfinite    finite
5399 #endif
5400 
5401 extern size_t mri_floatscan  ( MRI_IMAGE * ) ;     /* 22 Feb 2007 */
5402 extern size_t imarr_floatscan( MRI_IMARR * ) ;
5403 extern size_t dblk_floatscan ( THD_datablock * ) ;
5404 extern size_t dset_floatscan ( THD_3dim_dataset * ) ;
5405 
5406 #undef  BAD_FLOAT
5407 #define BAD_FLOAT(xx) thd_floatscan(1,&(xx))    /* 31 Dec 2008 */
5408 
5409 #define BOXLEN    7  /* number of values to define a box */
5410 #define BOX_XYZ   1
5411 #define BOX_DIC   2
5412 #define BOX_NEU   3
5413 #define BOX_IJK   4
5414 #define BALL_XYZ 11
5415 #define BALL_DIC 12
5416 #define BALL_NEU 13
5417 
5418 extern int THD_parse_boxball( int *, float **, char **) ;
5419 extern byte * THD_boxballmask( THD_3dim_dataset *, int, float * ) ;
5420 
5421 extern byte * THD_makemask( THD_3dim_dataset *, int,float,float) ;
5422 extern int    THD_makedsetmask( THD_3dim_dataset *, int,float,float, byte* ) ;
5423 extern int    THD_dset_to_mask(THD_3dim_dataset *, float, float);
5424 extern int THD_applydsetmask( THD_3dim_dataset *dset , byte *cmask );
5425 extern int *THD_unique_vals( THD_3dim_dataset *mask_dset, int miv,
5426                               int *n_unique, byte*cmask );
5427 extern int *THD_unique_rank( THD_3dim_dataset *mask_dset ,
5428                         int miv,
5429                         byte *cmask,
5430                         char *mapname,
5431                         int **unqp, int *N_unq);
5432 extern int THD_unique_rank_edit( THD_3dim_dataset *mask_dset ,
5433                            int miv,
5434                            byte *cmask,
5435                            char *mapname, int **unqp, int *N_unq) ;
5436 int is_integral_dset ( THD_3dim_dataset *dset, int check_data);
5437 int is_integral_sub_brick ( THD_3dim_dataset *dset, int isb, int check_data);
5438 extern int THD_mask_remove_isolas( int nx, int ny, int nz , byte *mmm ) ;
5439 
5440 extern int    THD_countmask( int , byte * ) ;
5441 extern byte * THD_automask( THD_3dim_dataset * ) ;         /* 13 Aug 2001 */
5442 extern void   THD_automask_verbose( int ) ;                /* 28 Oct 2003 */
5443 extern void   THD_automask_extclip( int ) ;
5444 extern void   THD_automask_set_onlypos( int ) ;            /* 09 Nov 2020 */
5445 extern byte * mri_automask_image( MRI_IMAGE * ) ;          /* 05 Mar 2003 */
5446 extern byte * mri_automask_imarr( MRI_IMARR * ) ;          /* 18 Nov 2004 */
5447 extern int    mask_intersect_count( int, byte *, byte * ); /* 30 Mar 2009 */
5448 extern int    mask_union_count    ( int, byte *, byte * ); /* 30 Mar 2009 */
5449 extern int    mask_count          ( int, byte * ) ;
5450 extern float_triple mask_rgyrate( int nx, int ny, int nz , byte *mmm ) ;
5451 extern byte * mri_automask_image2D( MRI_IMAGE *im ) ;      /* 12 Mar 2010 */
5452 /* 26 Dec 2021, migrated */
5453 extern THD_3dim_dataset *thd_apply_mask( THD_3dim_dataset *dset,
5454                                          byte *mask,
5455                                          char *prefix );
5456 
5457 extern THD_3dim_dataset * THD_remove_allzero(THD_3dim_dataset *); /* 25 Jul 2017 */
5458 
5459 
5460                                                    /* 13 Nov 2006 [rickr] */
5461 extern int    thd_mask_from_brick(THD_3dim_dataset *, int, float, byte **, int);
5462 extern int    thd_multi_mask_from_brick(THD_3dim_dataset *, int, byte **);
5463 
5464 
5465 extern THD_3dim_dataset * THD_autobbox( THD_3dim_dataset * ,  /* 06 Jun 2002 */
5466                           int *, int * , int *, int * , int *, int *, char *) ;
5467 extern void MRI_autobbox( MRI_IMAGE * ,
5468                           int *, int * , int *, int * , int *, int * ) ;
5469 extern void MRI_autobbox_clust( int ) ;                    /* 20 Sep 2006 */
5470 extern void THD_autobbox_clip( int ) ;                     /* 06 Aug 2007 */
5471 extern void THD_autobbox_npad(int) ;
5472 extern void THD_autobbox_noexpand(int) ;                   /* 08 Jan 2019 */
5473 
5474 void MRI_autobbox_byte( MRI_IMAGE *qim ,                   /* 18 Mar 2021 */
5475                         int *xm, int *xp , int *ym, int *yp , int *zm, int *zp ) ;
5476 
5477 extern void THD_automask_set_clipfrac( float f ) ;         /* 20 Mar 2006 */
5478 extern void THD_automask_set_peelcounts( int,int ) ;       /* 24 Oct 2006 */
5479 extern void THD_automask_set_gradualize( int ) ;
5480 extern void THD_automask_set_cheapo( int n ) ;             /* 13 Aug 2007 */
5481 
5482 extern int THD_mask_fillin_completely( int,int,int, byte *, int ) ; /* 19 Apr 2002 */
5483 extern int THD_mask_fillin_once      ( int,int,int, byte *, int ) ;
5484 
5485 extern int THD_mask_clip_neighbors( int,int,int, byte *, float,float,float *) ; /* 28 Oct 2003 */
5486 extern int THD_mask_fill_holes( int,int,int, byte *, THD_ivec3 *, int);
5487 
5488 
5489 extern void THD_mask_clust( int nx, int ny, int nz, byte *mmm ) ;
5490 extern void THD_mask_erode( int nx, int ny, int nz, byte *mmm, int redilate, byte nn ) ;
5491 extern void THD_mask_erode_sym(int nx,int ny,int nz, byte *mmm, int nerode,
5492                                int NN); /* NN: 19 May 2020 [rickr] */
5493 
5494 extern void THD_mask_erodemany( int nx, int ny, int nz, byte *mmm, int npeel ) ; /* 24 Oct 2006 */
5495 
5496 extern int THD_peel_mask( int nx, int ny, int nz , byte *mmm, int pdepth ) ;
5497 
5498 extern int THD_mask_dilate( int, int, int, byte *, int, byte ) ;   /* 30 Aug 2002 */
5499 extern short *THD_mask_depth (int nx, int ny, int nz, byte *mask,
5500                               byte preservemask,
5501                               short *usethisdepth, byte nn); /* ZSS March 02 2010 */
5502                                                              /* DRG Dec 23 2019 */
5503 
5504 extern float THD_cliplevel( MRI_IMAGE * , float ) ;          /* 12 Aug 2001 */
5505 extern float THD_cliplevel_abs( MRI_IMAGE * , float ) ;      /* 05 Mar 2007 */
5506 extern float mri_topclip( MRI_IMAGE * ) ;                    /* 28 Sep 2006 */
5507 extern float THD_cliplevel_search( MRI_IMAGE *im ) ;         /* 17 May 2017 */
5508 extern MRI_IMAGE * THD_median_brick( THD_3dim_dataset * ) ;  /* 12 Aug 2001 */
5509 extern MRI_IMAGE * THD_mad_brick   ( THD_3dim_dataset * ) ;  /* 07 Dec 2006 */
5510 extern MRI_IMAGE * THD_mean_brick  ( THD_3dim_dataset * ) ;  /* 15 Apr 2005 */
5511 extern MRI_IMAGE * THD_rms_brick   ( THD_3dim_dataset * ) ;  /* 15 Apr 2005 */
5512 extern MRI_IMAGE * THD_aveabs_brick( THD_3dim_dataset * ) ;  /* 11 May 2009 */
5513 extern MRI_IMAGE * THD_maxabs_brick( THD_3dim_dataset * ) ;  /* 08 Jan 2019 */
5514 extern MRI_IMAGE * THD_avepos_brick( THD_3dim_dataset * ) ;  /* 09 Nov 2020 */
5515 
5516 extern MRI_IMARR * THD_medmad_bricks   (THD_3dim_dataset *); /* 07 Dec 2006 */
5517 extern MRI_IMARR * THD_meansigma_bricks(THD_3dim_dataset *); /* 07 Dec 2006 */
5518 extern MRI_IMARR * IMARR_medmad_bricks ( MRI_IMARR * )     ; /* 11 Dec 2006 */
5519 
5520 extern float THD_cliplevel_partial( MRI_IMAGE *im , float mfrac ,
5521                                     int xa,int xb, int ya,int yb, int za,int zb ) ;
5522 extern MRI_IMAGE * THD_cliplevel_gradual( MRI_IMAGE *im , float mfrac ) ;
5523 
5524  /* 08 Mar 2001 - functions for dealing with rows */
5525 
5526 extern int THD_get_dset_rowcount( THD_3dim_dataset *, int ) ;
5527 extern void * THD_get_dset_row( THD_3dim_dataset *, int, int, int,int,int ) ;
5528 extern void THD_put_dset_row( THD_3dim_dataset *, int,
5529                               int, int,int,int, void * row ) ;
5530 extern int THD_dataset_rowfillin( THD_3dim_dataset *, int, int, int ) ;
5531 extern int THD_dataset_zfillin( THD_3dim_dataset *, int, int, int ) ; /* 03 Jul 2001 */
5532 
5533 extern MRI_IMAGE * mri_get_dset_row( THD_3dim_dataset *, int , int,int,int,int ) ;
5534 
5535 /*------------------------------------------------------------------*/
5536 /*-- October 1998: routines for 3D volume rotation and alignment. --*/
5537 
5538 #define DELTA_AFTER  1
5539 #define DELTA_BEFORE 2
5540 #define DELTA_FIXED  3
5541 
5542   /*-- see thd_rotangles.c --*/
5543 
5544 extern void THD_rotangle_user_to_dset( THD_3dim_dataset * ,
5545                                        float,char, float,char, float,char,
5546                                        float*,int* , float*,int* , float*,int* );
5547 
5548 extern int THD_axcode( THD_3dim_dataset * , char ) ; /* promoted from static */
5549 extern int THD_handedness( THD_3dim_dataset * ) ;    /* on 06 Feb 2001 - RWCox */
5550 
5551 extern THD_dmat33 DBLE_mat_to_dicomm( THD_3dim_dataset * ) ; /* 14 Feb 2001 */
5552 extern THD_mat33  SNGL_mat_to_dicomm( THD_3dim_dataset * ) ; /* 28 Aug 2002 */
5553 
5554 extern THD_dvecmat THD_rotcom_to_matvec( THD_3dim_dataset * , char * ) ;
5555 
5556 extern THD_dvecmat invert_dvecmat( THD_dvecmat avm ) ; /* 24 Jul 2007 */
5557 extern THD_dvecmat sqrt_dvecmat( THD_dvecmat avm ) ;   /* 30 Jul 2007 */
5558 
5559   /*-- see thd_rot3d.c for these routines --*/
5560 
5561 extern void THD_rota_method( int ) ;
5562 
5563 extern void THD_rota_setpad( int,int,int ) ; /* 02 Feb 2001 */
5564 extern void THD_rota_clearpad(void) ;
5565 
5566 extern void THD_rota_vol( int, int, int, float, float, float, float *,
5567                           int,float, int,float, int,float,
5568                           int,float,float,float ) ;
5569 
5570 extern MRI_IMAGE * THD_rota3D( MRI_IMAGE * ,
5571                                int,float, int,float, int,float,
5572                                int,float,float,float ) ;
5573 
5574 extern MRI_IMAGE * THD_rota3D_matvec( MRI_IMAGE *, THD_dmat33,THD_dfvec3 ) ;
5575 
5576   /* routines below added to thd_rot3d.c on 16 Jul 2000 */
5577 
5578 extern void THD_rota_vol_matvec( int, int, int, float, float, float, float *,
5579                                  THD_dmat33 , THD_dfvec3 ) ;
5580 
5581 extern THD_dvecmat DLSQ_rot_trans( int, THD_dfvec3 *, THD_dfvec3 *, double * );
5582 extern THD_dvecmat DLSQ_affine   ( int, THD_dfvec3 *, THD_dfvec3 *           );
5583 extern THD_dvecmat DLSQ_rotscl   ( int, THD_dfvec3 *, THD_dfvec3 *, int      );
5584 
5585 extern THD_dvecmat THD_read_dvecmat( char * , int ) ;  /* THD_read_vecmat.c */
5586 
5587    /* cf. thd_coords.c for cardinal transformation matrix */
5588 extern void THD_dicom_card_xform (THD_3dim_dataset * dset ,
5589                                   THD_dmat33 *tmat, THD_dfvec3 *dics );
5590 extern void THD_dicom_real_xform (THD_3dim_dataset * dset ,
5591                                   THD_dmat33 *tmat, THD_dfvec3 *dics );
5592 extern int  THD_dicom_real_to_card(THD_3dim_dataset *dset, /* 23 Mar 2020 */
5593                                    THD_fvec3 * coords, int rnd);
5594 extern float THD_compute_oblique_angle(mat44 ijk_to_dicom44, int verbose);
5595 
5596 /* coordinate converters - moved from afni.h  17 Feb 2021 [rickr] */
5597 extern void AFNI_ijk_to_xyz( THD_3dim_dataset * ,
5598                              int,int,int, float *,float *,float *) ;
5599 extern void AFNI_xyz_to_ijk( THD_3dim_dataset * ,
5600                              float,float,float , int *,int *,int *) ;
5601 extern void AFNI_xyz_to_dicomm( THD_3dim_dataset * ,
5602                                 float,float,float , float *,float *,float *) ;
5603 extern void AFNI_dicomm_to_xyz( THD_3dim_dataset * ,
5604                                 float,float,float , float *,float *,float *) ;
5605 
5606 /* [PT: Nov 4, 2020] functions for reorienting dset via
5607    ijk_to_dicom_real */
5608 extern int   is_valid_orient_char( char ochar[3] );
5609 extern int   is_valid_orient_int( int oint[3] );
5610 extern void  THD_orient_to_int_rlpais( char ochar[4], int oint[3] );
5611 extern void  THD_int_to_orient_rlpais( int oint[3], char ochar[4] );
5612 extern mat33 THD_char_reorient_perm_mat33( char *ocharA, char *ocharB );
5613 extern mat33 THD_int_reorient_perm_mat33( int *ointA, int *ointB );
5614 extern mat33 THD_dset_reorient_perm_mat33( THD_3dim_dataset *dsetA,
5615                                            char *ocharB );
5616 extern mat44 THD_refit_orient_ijk_to_dicom_real( THD_3dim_dataset *dsetA,
5617                                                  char *ocharB );
5618 extern mat44 nifti_orthogonalize_mat44( mat44 Min);
5619 extern int is_mat44_orthogonal(mat44 A);
5620 
5621 
5622 extern void THD_report_obliquity(THD_3dim_dataset *dset);
5623 extern void set_obliquity_report(int v);
5624 
5625 extern void THD_set_oblique_report(int n1, int n2);
5626 
5627 extern int THD_get_oblique_report(void);
5628 
5629 extern void THD_reset_oblique_report_index(void);
5630 
5631 extern void THD_check_oblique_field(THD_3dim_dataset *dset);
5632 extern void THD_make_cardinal(THD_3dim_dataset *dset);
5633 extern void THD_updating_obliquity(int update);
5634 extern int THD_update_obliquity_status(void);
5635 extern void THD_set_dset_atr_status(int st);
5636 extern int THD_update_dset_atr_status(void);
5637 
5638   /* cf. thd_tmask.c */
5639 
5640 #define TM_IXY 2  /* fixdir-1 for each plane */
5641 #define TM_IYZ 0
5642 #define TM_IZX 1
5643 
5644 /*! Struct used in cox_render.c to indicate which lines in a volume are all zero. */
5645 
5646 typedef struct {
5647    int   nmask[3] ;
5648    byte * mask[3] ;
5649 } Tmask ;
5650 
5651 extern void free_Tmask( Tmask * ) ;
5652 extern Tmask * create_Tmask_byte( int, int, int, byte * ) ;
5653 extern Tmask * create_Tmask_rgba( int, int, int, rgba * ) ;
5654 
5655 #define TM_ZLINE(tm,i) (tm==NULL || tm->mask[TM_IXY][i])
5656 #define TM_YLINE(tm,i) (tm==NULL || tm->mask[TM_IZX][i])
5657 #define TM_XLINE(tm,i) (tm==NULL || tm->mask[TM_IYZ][i])
5658 
5659   /* routines below created in thd_rot3d_byte.c on 23 Oct 2000 */
5660 
5661 extern void THD_rota_vol_byte( int, int, int, float, float, float, byte *,
5662                                int,float, int,float, int,float,
5663                                int,float,float,float , Tmask * ) ;
5664 
5665 extern void THD_rota_byte_mode( int ) ; /* 07 Nov 2000 */
5666 
5667 extern void THD_rota_vol_matvec_byte( int, int, int, float, float, float, byte *,
5668                                       THD_mat33 , THD_fvec3 , Tmask * ) ;
5669 
5670   /*-- see thd_shift2.c for these routines --*/
5671 
5672 extern void SHIFT_set_method( int ) ;
5673 extern int  SHIFT_get_method( void ) ;
5674 extern void SHIFT_two_rows( int , int , float , float *, float , float *) ;
5675 
5676 extern void fft_shift2  ( int , int , float , float *, float , float *) ;
5677 extern void hept_shift2 ( int , int , float , float *, float , float *) ;
5678 extern void quint_shift2( int , int , float , float *, float , float *) ;
5679 extern void cub_shift2  ( int , int , float , float *, float , float *) ;
5680 extern void lin_shift2  ( int , int , float , float *, float , float *) ;
5681 extern void nn_shift2   ( int , int , float , float *, float , float *) ;
5682 extern void ts_shift2   ( int , int , float , float *, float , float *) ;
5683 
5684 extern void hept_shift ( int , float , float *) ;
5685 extern void nn_shift   ( int , float , float *) ;
5686 extern void lin_shift  ( int , float , float *) ;
5687 extern void cub_shift  ( int , float , float *) ;
5688 extern void quint_shift( int , float , float *) ;
5689 
5690 extern void wsinc5_shift( int , float , float *) ; /* Aug 2019 */
5691 extern void wsinc5_shift2( int , int , float , float *, float , float *) ;
5692 extern void wsinc9_shift( int , float , float *) ; /* Aug 2019 */
5693 extern void wsinc9_shift2( int , int , float , float *, float , float *) ;
5694 
5695 extern void THD_fftshift( THD_3dim_dataset *, float,float,float, int ) ;
5696 
5697 extern int THD_bandpass_vectors( int nlen, int nvec, float **vec, /* 30 Apr 2009 */
5698                                  float dt, float fbot, float ftop,
5699                                  int qdet, int nort, float **ort ) ;
5700 extern int THD_bandpass_OK( int nx, float dt, float fbot, float ftop, int verb ) ;
5701 extern int THD_bandpass_remain_dim(int nx, float dt, float fbot, float ftop, int verb) ;  /* 18 Mar 2015 [rickr] */
5702 
5703 extern int THD_bandpass_set_nfft( int n ) ;
5704 
5705 extern int THD_bandpass_vectim( MRI_vectim *mrv ,
5706                                 float dt , float fbot , float ftop  ,
5707                                 int qdet , int nort   , float **ort  ) ;
5708 
5709 extern int      THD_despike9       ( int, float *) ; /* 08 Oct 2010 */
5710 extern int_pair THD_vectim_despike9( MRI_vectim *) ;
5711 
5712 extern void THD_vectim_despike_L1( MRI_vectim *mrv , int localedit ) ; /* 02 Aug 2013 */
5713 
5714 extern THD_3dim_dataset * THD_despike9_dataset( THD_3dim_dataset *, byte * ) ;
5715 
5716   /*-- see mri_3dalign.c for these routines --*/
5717 
5718 /*! Struct that holds information used during 3D registration. */
5719 
5720 typedef struct {
5721    MRI_IMARR * fitim ;    /*!< Regression basis images */
5722    double * chol_fitim ;  /*!< Choleski decomposition of the normal equations */
5723    int xa,xb , ya,yb , za,zb ; /* trim box */
5724 } MRI_3dalign_basis ;
5725 
5726 extern void mri_3dalign_edging( int , int , int ) ;
5727 extern void mri_3dalign_edging_default( int , int , int ) ;
5728 extern void mri_3dalign_force_edging( int ) ;
5729 extern void mri_3dalign_wtrimming( int ) ;
5730 extern void mri_3dalign_wproccing( int ) ;
5731 extern void mri_3dalign_scaleinit( float ) ;  /* 22 Mar 2004 */
5732 
5733 extern void mri_3dalign_params( int , float , float , float ,
5734                                 int , int , int , int ) ;
5735 
5736 extern void mri_3dalign_method( int , int , int , int ) ;
5737 
5738 extern void mri_3dalign_final_regmode( int ) ;
5739 
5740 extern MRI_3dalign_basis * mri_3dalign_setup( MRI_IMAGE * , MRI_IMAGE * ) ;
5741 extern MRI_IMAGE * mri_3dalign_one( MRI_3dalign_basis * , MRI_IMAGE * ,
5742                                     float *, float *, float *,
5743                                     float *, float *, float * ) ;
5744 extern MRI_IMARR * mri_3dalign_many( MRI_IMAGE *, MRI_IMAGE * , MRI_IMARR *,
5745                                     float *, float *, float *,
5746                                     float *, float *, float * ) ;
5747 extern void mri_3dalign_cleanup( MRI_3dalign_basis * ) ;
5748 
5749 extern void mri_3dalign_initvals( float,float,float,float,float,float ) ;
5750 
5751 extern MRI_IMARR * mri_3dalign_oneplus( MRI_3dalign_basis * , MRI_IMARR * ,
5752                                         float *, float *, float *,
5753                                         float *, float *, float * ) ;
5754 extern MRI_IMARR * mri_3dalign_apply( MRI_3dalign_basis * , MRI_IMARR * ,
5755                                         float, float, float,
5756                                         float, float, float, int ) ;
5757 
5758 /*---------------------------------------------------------------------*/
5759 
5760   /*-- see mri_warp3D_align.c for these routines --*/
5761 
5762 #undef  PARAM_MAXTRIAL
5763 #define PARAM_MAXTRIAL 29
5764 typedef struct {
5765   float min, max, siz, ident, delta, toler ;
5766   float val_init , val_out , val_fixed , val_pinit ;
5767   int fixed ;
5768   float val_trial[PARAM_MAXTRIAL] ;
5769   int   idx_trial[PARAM_MAXTRIAL] ; /* 24 Jun 2021 */
5770   char name[32] ;
5771 } MRI_warp3D_param_def ;
5772 
5773   /*! Struct that holds information used during warp3D registration. */
5774 
5775 typedef struct {
5776 
5777    /*- this stuff is to be set by the user -*/
5778 
5779    int nparam ;
5780    MRI_warp3D_param_def *param ;
5781    float scale_init , scale_out ;
5782    float delfac , tolfac ;
5783    float twoblur ;
5784 
5785    int regmode , verb , max_iter , num_iter , wtproc ;
5786    int xedge , yedge , zedge ;
5787    int regfinal ;
5788 
5789    MRI_IMAGE *imbase , *imwt ;
5790 
5791    void (*vwfor)(float,float,float,float *,float *,float *) ;
5792    void (*vwinv)(float,float,float,float *,float *,float *) ;
5793    void (*vwset)(int,float *) ;
5794    float (*vwdet)(float,float,float) ;
5795 
5796    /*- below here is not to be touched by the user! -*/
5797 
5798    int        nfree ;
5799    MRI_IMAGE *imww ;
5800    MRI_IMAGE *imap ;
5801    MRI_IMAGE *imps ;
5802    MRI_IMAGE *imsk ;
5803    MRI_IMAGE *imps_blur ;
5804 
5805 } MRI_warp3D_align_basis ;
5806 
5807 extern int         mri_warp3D_align_setup  ( MRI_warp3D_align_basis * ) ;
5808 extern MRI_IMAGE * mri_warp3D_align_one    ( MRI_warp3D_align_basis *, MRI_IMAGE * );
5809 extern void        mri_warp3D_align_cleanup( MRI_warp3D_align_basis * ) ;
5810 
5811 extern void THD_check_AFNI_version(char *) ;  /* 26 Aug 2005 */
5812 extern void THD_death_setup( int msec ) ;     /* 14 Sep 2009 */
5813 
5814 extern float THD_saturation_check( THD_3dim_dataset *, byte * , int,int ) ;       /* 08 Feb 2010 */
5815 extern float THD_saturation_check_multi( THD_3dim_dataset *, byte *, int,int *) ; /* 23 Dec 2011 */
5816 
5817 
5818 extern THD_3dim_dataset * THD_dummy_N27  (void) ;  /* 12 Feb 2010 */
5819 extern THD_3dim_dataset * THD_dummy_RWCOX(void) ;  /* 12 Feb 2010 */
5820 
5821 /*---------------------------------------------------------------------*/
5822 
5823 #if 0
5824 extern float THD_thresh_to_pval( float thr , THD_3dim_dataset * dset ) ;
5825 #endif
5826 
5827 extern float THD_stat_to_pval  ( float thr , int statcode , float * stataux ) ;
5828 extern float THD_pval_to_stat  ( float pval, int statcode , float * stataux ) ;
5829 extern float THD_stat_to_zscore( float thr , int statcode , float * stataux ) ;
5830 extern int   THD_stat_is_2sided( int statcode , int thrsign ) ;  /* Jan 2015 */
5831 
5832 extern int THD_filename_ok( char * ) ;   /* 24 Apr 1997 */
5833 extern int THD_filename_pure( char * ) ; /* 28 Feb 2001 */
5834 extern int THD_freemegabytes( char * ) ; /* 28 Mar 2005 */
5835 extern int THD_character_ok( char ) ;    /* 04 Feb 2010 */
5836 extern int THD_filename_fix( char * ) ;  /* 04 Feb 2010 */
5837 
5838 #undef  HAS_WILDCARD                     /* 19 Jun 2012 */
5839 #define HAS_WILDCARD(sss) ( strchr((sss),'*') != NULL || strchr((sss),'?') != NULL )
5840 
5841 extern THD_warp * AFNI_make_voxwarp( THD_warp * , THD_3dim_dataset * ,
5842                                                   THD_3dim_dataset *  ) ;
5843 
5844 extern THD_linear_mapping * AFNI_make_voxmap( THD_linear_mapping * ,
5845                                               THD_dataxes * , THD_dataxes * ) ;
5846 
5847 extern void AFNI_concatenate_warp( THD_warp * , THD_warp * ) ;
5848 
5849 extern THD_linear_mapping * AFNI_concatenate_lmap( THD_linear_mapping * ,
5850                                                    THD_linear_mapping *  ) ;
5851 
5852 extern THD_warp * AFNI_make_affwarp_12(float,float,float,float,
5853                                        float,float,float,float,
5854                                        float,float,float,float ); /* 27 Aug 2002 */
5855 
5856 extern THD_warp * AFNI_make_affwarp_mat   ( THD_mat33 ) ;         /* 28 Aug 2002 */
5857 extern THD_warp * AFNI_make_affwarp_matvec( THD_mat33 , THD_fvec3 ) ;
5858 
5859 extern THD_ivec3 THD_matrix_to_orientation( THD_mat33 R ) ;       /* 27 Aug 2003 */
5860 
5861 extern THD_3dim_dataset * WINsorize( THD_3dim_dataset * ,
5862                                      int,int,int, float, char *, int,int,byte * );
5863 
5864 #define ZPAD_EMPTY (1<<0)
5865 #define ZPAD_PURGE (1<<1)
5866 #define ZPAD_MM    (1<<2)
5867 #define ZPAD_IJK   (1<<3)     /* ZSS Dec 23 05 pad values are in voxel coords */
5868 
5869 extern THD_3dim_dataset * THD_zeropad( THD_3dim_dataset * ,
5870                                        int,int,int,int,int,int, char *, int );
5871 
5872 THD_3dim_dataset * THD_volume_to_dataset( THD_3dim_dataset *mset  ,
5873                                           MRI_IMAGE *imin         ,
5874                                           char *prefix            ,
5875                                           int pad_xm , int pad_xp ,
5876                                           int pad_ym , int pad_yp ,
5877                                           int pad_zm , int pad_zp  ) ; /* 25 Jan 2021 */
5878 
5879 THD_3dim_dataset * THD_imarr_to_dataset( MRI_IMARR *imar, char *prefix ) ; /* 05 Mar 2021 */
5880 THD_3dim_dataset * THD_image_to_dataset( MRI_IMAGE *imin, char *prefix ) ;
5881 
5882 extern THD_3dim_dataset * THD_warp3D(    /* cf. mri_warp3D.c - 18 May 2003 */
5883                      THD_3dim_dataset *,
5884                      void w_in2out(float,float,float,float *,float *,float *),
5885                      void w_out2in(float,float,float,float *,float *,float *),
5886                      void * , char *, int , int ) ;
5887 
5888 extern THD_3dim_dataset * THD_warp3D_affine(
5889                      THD_3dim_dataset *, THD_vecmat, void *, char *, int, int );
5890 
5891 extern THD_3dim_dataset * THD_warp3D_mni2tta( THD_3dim_dataset *, void *,
5892                                               char *, int, int );
5893 extern THD_3dim_dataset * THD_warp3D_tta2mni( THD_3dim_dataset *, void *,
5894                                               char *, int, int );
5895 
5896 #define WARP3D_NEWGRID  1
5897 #define WARP3D_NEWDSET  2
5898 #define WARP3D_GRIDMASK 7
5899 
5900 /*-- 02 Mar 2001: thd_entropy16.c --*/
5901 
5902 extern void   ENTROPY_setup     (void) ;
5903 extern void   ENTROPY_setdown   (void) ;
5904 extern void   ENTROPY_accumulate(int64_t , void *) ;
5905 extern double ENTROPY_compute   (void) ;
5906 extern double ENTROPY_dataset   (THD_3dim_dataset *) ;
5907 extern double ENTROPY_datablock (THD_datablock *) ;
5908 
5909 extern int  AFNI_vedit( THD_3dim_dataset *dset , VEDIT_settings vednew , byte *mask ) ;
5910 extern void AFNI_vedit_clear( THD_3dim_dataset *dset ) ;
5911 
5912 /*--------------------------------------------------------------------------*/
5913 
5914 /*--- Stuff for Tom Ross's NOTES ---*/
5915 
5916 #define MAX_DSET_NOTES 999
5917 #define MAX_NOTE_SIZE  4000
5918 
5919 extern void   tross_Add_Note   (THD_3dim_dataset *, char *) ;
5920 extern void   tross_Delete_Note(THD_3dim_dataset *, int   ) ;
5921 
5922 extern char * tross_Expand_String( char * ) ;
5923 extern char * tross_Encode_String( char * ) ;
5924 extern void tross_Dont_Encode_Slash( int ) ;  /* 13 Mar 2003 */
5925 
5926 extern void   tross_Store_Note   ( THD_3dim_dataset * , int , char * ) ;
5927 extern char * tross_Get_Note     ( THD_3dim_dataset * , int ) ;
5928 extern char * tross_Get_Notedate ( THD_3dim_dataset * , int ) ;
5929 extern int    tross_Get_Notecount( THD_3dim_dataset * ) ;
5930 
5931 extern void tross_Addto_History( THD_3dim_dataset *, THD_3dim_dataset *) ;
5932 
5933 extern char * tross_datetime(void) ;
5934 extern char * tross_username(void) ;
5935 extern char * tross_hostname(void) ;
5936 extern char * tross_commandline( char * , int , char ** ) ;
5937 
5938 extern int AFNI_logger( char * , int , char ** ) ; /* 13 Aug 2001 */
5939 extern void AFNI_sleep( int ) ;
5940 #define AFNI_log_string(ss) AFNI_logger(ss,0,NULL)
5941 extern long long AFNI_logfilesize(void) ;          /* 17 Oct 2007 */
5942 
5943 extern void AFNI_serverlog( char * ) ;             /* 24 Mar 2005 */
5944 
5945 void THD_outlier_count( THD_3dim_dataset *, float, int **, int * ) ; /* 15 Aug 2001 */
5946 
5947 extern void   tross_Append_History ( THD_3dim_dataset * , char * ) ;
5948 extern char * tross_Get_History    ( THD_3dim_dataset * ) ;
5949 extern void   tross_Make_History   ( char *, int, char **, THD_3dim_dataset * ) ;
5950 extern void   tross_Copy_History   ( THD_3dim_dataset *, THD_3dim_dataset * ) ;
5951 extern void   tross_Replace_History( THD_3dim_dataset * , char * ) ;
5952 
5953 #define tross_Erase_History(ds) THD_erase_one_atr((ds)->dblk,"HISTORY_NOTE")
5954 
5955 extern char * tross_breakup_string( char *, int , int ) ;
5956 
5957 void tross_multi_Append_History( THD_3dim_dataset * , ... ) ;
5958 
5959 #define ATLAS_CMAX    64   /* If you change this parameter,edit constant in
5960                               CA_EZ_Prep.m (MaxLbl* checks), thd_ttatlas_query.h TTO_FORMAT */
5961 
5962 typedef enum { UNKNOWN_SPC=0, /*!< Dunno */
5963                AFNI_TLRC_SPC, /*!< The Classic */
5964                MNI_SPC,       /*!< A la Canadienne */
5965                MNI_ANAT_SPC,  /*!< Mit viele liebe */
5966 
5967                NUMBER_OF_SPC  /*!< A flag for the number of spaces,
5968                                     leave for last */
5969                } AFNI_STD_SPACES;
5970 
5971 typedef struct {
5972    /* tdval and tdlev stand for "Talairach Daemon" value and level */
5973    /* these are kept for historical purposes  */
5974    /* perhaps one day making an unusally boring PBS special */
5975    short tdval;         /* Leave this one to be the very first element */
5976    char name[ATLAS_CMAX] ;  /* Leave this one to be the second element */
5977    float xx,yy,zz;     /* xx,yy,zz - RAI position of region  - now in float */
5978    short tdlev,okey ;          /* tdlev = unknown, gyrus or area code */
5979                                /* okey = original value in atlas */
5980                                /*  this value was converted for TT daemon */
5981                                /*  atlas values because left and right */
5982                                /*  ROIs shared the same value */
5983    char sblabel[ATLAS_CMAX];   /* This is the sub-brick label
5984                                   of a dataset related to this point.
5985                                   The only time this is used is for
5986                                   linking an atlas point to the probability
5987                                   map volume. */
5988    char longname[ATLAS_CMAX] ;  /* Leave this one to be the second element */
5989 } ATLAS_POINT ;
5990 
5991 
5992 extern int atlas_n_points(char *atname);
5993 extern ATLAS_POINT *atlas_points(char *atname);
5994 
5995 extern char * TT_whereami( float , float , float,
5996                            char *, void *) ;
5997 extern char * TT_whereami_old( float , float , float ) ;
5998 extern int  TT_load_atlas_old (void);
5999 extern void TT_purge_atlas(void);
6000 extern THD_3dim_dataset * TT_retrieve_atlas_old(void) ;
6001 extern THD_3dim_dataset * TT_retrieve_atlas_dset(char *aname, int szflag);
6002 extern void TT_setup_popup_func( void (*pf)(char *) ) ; /* 26 May 2006 */
6003 
6004 extern THD_3dim_dataset * TT_retrieve_atlas_big_old(void) ; /* 01 Aug 2001 */
6005 extern void TT_purge_atlas_big(void);
6006 
6007 extern THD_3dim_dataset * TT_retrieve_atlas_either_old(void); /* 22 Aug 2001 */
6008 extern char **atlas_chooser_formatted_labels(char *atname,int flipxy);
6009 
6010 #define TT_ATLAS_NZ_SMALL 141 /* 01 Aug 2001 */
6011 #define TT_ATLAS_NZ_BIG   151
6012 
6013 #define TT_retrieve_atlas_dset_nz(nz)                                \
6014  ( ((nz)==TT_ATLAS_NZ_SMALL)                                    \
6015     ? TT_retrieve_atlas_dset("TT_Daemon",-1)                          \
6016     : ((nz)==TT_ATLAS_NZ_BIG) ? TT_retrieve_atlas_dset("TT_Daemon",1) : NULL )
6017 
6018 /*------------------------------------------------------------------------*/
6019 
6020 extern float THD_spearman_corr( int,float *,float *) ;  /* 23 Aug 2001 */
6021 extern float THD_quadrant_corr( int,float *,float *) ;
6022 extern float THD_pearson_corr ( int,float *,float *) ;
6023 extern float THD_pearson_partial_corr( int, float *, float *, float *);
6024 extern double THD_pearson_corrd ( int, double *, double *) ;
6025 extern float THD_covariance( int n, float *x , float *y );
6026 extern float THD_ktaub_corr   ( int,float *,float *) ;  /* 29 Apr 2010 */
6027 extern float THD_eta_squared  ( int,float *,float *) ;  /* 25 Jun 2010 */
6028 extern double THD_eta_squared_masked(int,float *,float *,byte *);/* 16 Jun'11 */
6029 extern float THD_dice_coef_f_masked(int,float *,float *,byte *);/* 28 Jul'15 */
6030 // orig- Apr. 2014;  updated- Jan. 2017, as part of some attempted saBobtage:
6031 extern THD_3dim_dataset * THD_Tcorr1D(THD_3dim_dataset *xset,
6032                byte *mask, int nmask, MRI_IMAGE *ysim,
6033                char *smethod, char *prefix,int do_short,int do_atanh);
6034 
6035 extern float THD_quantile_corr( int,float *,float *) ;  /* 10 May 2012 */
6036 extern float quantile_corr( int n , float *x , float rv , float *r ) ;
6037 extern void THD_quantile_corr_setup( int ) ;
6038 extern float quantile_prepare( int n , float *a ) ;
6039 
6040 extern float THD_tictactoe_corr( int,float *,float *) ;  /* 19 Jul 2011 */
6041 
6042 extern float THD_pearson_corr_wt(int,float *,float *,float *); /* 13 Sep 2006 */
6043 
6044 extern void THD_pearson_corr_boot( int n, float *x, float *y,
6045                             float_triple *rrr ,
6046                             float_triple *aaa ,
6047                             float_triple *bbb  ) ;         /* 01 Mar 2011 */
6048 extern float_triple THD_pearson_indexed( int nix, int *ix, float *x, float *y );
6049 extern float_triple THD_bootstrap_confinv( float estim , float alpha ,
6050                                            int nboot   , float *eboot ) ;
6051 extern float THD_bootstrap_biascorr( float estim , int nboot , float *eboot ) ;
6052 
6053 extern void THD_spearman_corr_boot( int n , float *x , float *y , float_triple *rrr ) ;
6054 
6055 extern float_pair THD_l1_fit_to_line( int n , float *x , float *y ) ;
6056 
6057 extern float THD_bootstrap_vectcorr( int nlen, int nboot, int use_pv, int xtyp,
6058                                      int xnum, void *xp , int ynum  , void *yp );
6059 
6060 extern float THD_spearman_corr_nd( int,float *,float *) ;  /* 23 Aug 2006 */
6061 extern float THD_quadrant_corr_nd( int,float *,float *) ;
6062 extern float THD_distance( int, float *, float *, int ); /* 04 May 2012 */
6063 #define THD_pearson_corr_nd THD_pearson_corr
6064 
6065 double THD_spearman_corr_dble( int n , double *x , double *y ) ;
6066 
6067 extern void  rank_order_float     ( int , float * );
6068 extern float spearman_rank_prepare( int , float * );
6069 extern float quadrant_corr_prepare( int , float * );
6070 extern float spearman_rank_corr   ( int , float * , float , float * );
6071 extern float quadrant_corr        ( int , float * , float , float * );
6072 
6073 extern float tictactoe_corr_prepare( int , float * );
6074 extern float tictactoe_corr        ( int , float * , float , float * );
6075 extern void  tictactoe_set_thresh  ( float bb , float tt ) ;
6076 
6077 extern void rank_order_float_arrays( int , int * , float ** ); /* 10 Nov 2010 */
6078 extern void rank_order_2floats( int , float * , int , float * ) ;
6079 
6080 extern float THD_mutual_info_scl( int, float,float,float *,    /* 16 Aug 2006 */
6081                                        float,float,float *, float * ) ;
6082 extern float THD_mutual_info( int , float *, float * ) ;
6083 
6084 extern void THD_correlate_ignore_zerozero(int) ;
6085 
6086 extern float THD_corr_ratio_scl( int, float,float,float *,     /* 23 Aug 2006 */
6087                                       float,float,float *, float * ) ;
6088 extern float THD_corr_ratio( int , float *, float * ) ;
6089 extern void  THD_corr_ratio_mode( int ) ;                      /* 11 Oct 2006 */
6090 #define THD_corr_ratio_sym_not THD_corr_ratio_mode(0)  /* unsymm   */
6091 #define THD_corr_ratio_sym_mul THD_corr_ratio_mode(1)  /* sym by * */
6092 #define THD_corr_ratio_sym_add THD_corr_ratio_mode(2)  /* sym by + */
6093 
6094 extern float THD_norm_mutinf_scl( int, float,float,float *,    /* 25 Sep 2006 */
6095                                        float,float,float *, float * ) ;
6096 extern float THD_norm_mutinf( int , float *, float * ) ;
6097 
6098 extern float THD_jointentrop_scl( int, float,float,float *,    /* 25 Sep 2006 */
6099                                        float,float,float *, float * ) ;
6100 extern float THD_jointentrop( int , float *, float * ) ;
6101 
6102 extern float THD_hellinger_scl( int, float,float,float *,      /* 26 Sep 2006 */
6103                                      float,float,float *, float * ) ;
6104 extern float THD_hellinger( int , float *, float * ) ;
6105 
6106 extern float_quad THD_helmicra_scl( int, float,float,float *,
6107                                     float,float,float *, float * ) ;
6108 extern float_quad THD_helmicra( int , float *, float * ) ;
6109 
6110 extern float_pair THD_binary_mutinfo( int n0, float *y0, int n1, float *y1 ) ;
6111 
6112 extern int retrieve_2Dhist   ( float **xyhist ) ;     /* 28 Sep 2006 */
6113 extern int retrieve_2Dhist1  ( float **, float ** ) ; /* 07 May 2007 */
6114 extern void set_2Dhist_hpower( double ) ;             /* 03 Oct 2006 */
6115 extern void set_2Dhist_hbin  ( int  ) ;
6116 extern int  get_2Dhist_hbin  ( void ) ;
6117 extern void clear_2Dhist     ( void ) ;
6118 extern void build_2Dhist( int n , float xbot,float xtop,float *x ,
6119                           float ybot,float ytop,float *y , float *w ) ;
6120 extern void addto_2Dhist( int n , float xbot,float xtop,float *x ,
6121                           float ybot,float ytop,float *y , float *w ) ;
6122 extern void normalize_2Dhist(void) ;
6123 
6124 extern void set_2Dhist_xybin( int nb, float *xb, float *yb ) ; /* 07 May 2007 */
6125 extern int get_2Dhist_xybin( float **xb , float **yb ) ;
6126 extern void set_2Dhist_xybin_eqwide( int,float,float,float,float ) ;
6127 extern void set_2Dhist_xybin_eqhigh( int,int,float *,float * ) ;
6128 extern void set_2Dhist_xyclip      ( int, float *, float * ) ;
6129 extern int  get_2Dhist_xyclip      ( float *, float *, float *, float * ) ;
6130 
6131 extern MRI_IMAGE *build_byteized_vectors( int n ,              /* 02 Mar 2009 */
6132                                           float xbot,float xtop,float *x ,
6133                                           float ybot,float ytop,float *y  ) ;
6134 
6135 extern double ljung_box_uneven( int nval, int hh, double *val, int *tau ) ; /* 21 Jan 2020 */
6136 extern double ljung_box_zcens ( int nval, int hh, double *val ) ;
6137 extern MRI_IMAGE * mri_vec_to_ljmap( MRI_IMAGE *inim ) ;                    /* 05 Feb 2020 */
6138 
6139 /*------------------------------------------------------------------------*/
6140 /* Stuff for compression via zlib - see zfun.c - 02 Mar 2009 == snow day! */
6141 
6142 extern void zz_compress_dosave( int ii );
6143 extern void zz_compress_dlev( int ii );
6144 extern int zz_compress_some( int nsrc, void *ptr );
6145 extern int zz_compress_all( int nsrc , char *src , char **dest );
6146 extern int zz_uncompress_some( int nsrc, char *src, int ndest, char *dest );
6147 extern int zz_uncompress_all( int nsrc , byte *src , char **dest );
6148 extern MRI_IMAGE * zz_ncd_many( int nar , int *nsrc , char **src );
6149 extern float zz_ncd_pair( int n1 , char *s1 , int n2 , char *s2 );
6150 extern float THD_ncdfloat( int n , float *x , float *y );
6151 extern float THD_ncdfloat_scl( int n , float xbot,float xtop,float *x ,
6152                                        float ybot,float ytop,float *y  );
6153 
6154 /* stuff below, for masks, created Jul 2010 */
6155 
6156 extern char * array_to_zzb64( int nsrc , char *src , int linelen ) ;
6157 extern int    zzb64_to_array( char *zb , char **dest ) ;
6158 
6159 extern byte * mask_binarize( int , byte * ) ;
6160 extern byte * mask_unbinarize( int , byte * ) ;
6161 
6162 extern char * mask_to_b64string  ( int nvox  , byte *mful ) ;
6163 extern byte * mask_from_b64string( char *str , int *nvox  ) ;
6164 extern int    mask_b64string_nvox( char *str ) ;
6165 
6166 extern bytevec * THD_create_mask_from_string( char *str ) ;
6167 
6168 /*------------------------------------------------------------------------*/
6169 
6170 extern THD_fvec3 THD_autonudge( THD_3dim_dataset *dsepi, int ivepi,
6171                                 THD_3dim_dataset *dsant, int ivant,
6172                                 float step,
6173                                 int xstep, int ystep, int zstep, int code ) ;
6174 
6175 extern MRI_IMAGE * mri_brainormalize( MRI_IMAGE *, int,int,int , MRI_IMAGE **, MRI_IMAGE **) ; /* 05 Apr 2004 */
6176 extern void mri_brainormalize_verbose( int ) ;
6177 extern void brainnormalize_coord( float  ispat, float  jspat, float  kspat ,
6178                 float *iorig, float *jorig, float *korig ,
6179                 THD_3dim_dataset *origset,
6180                 float *xrai_orig, float *yrai_orig, float *zrai_orig); /* ZSS */
6181 extern MRI_IMAGE * mri_watershedize( MRI_IMAGE * , float ) ;
6182 extern void mri_speciebusiness( int ) ;
6183 extern void mri_brain_normalize_cuts ( char * );
6184 extern void mri_brainormalize_initialize(float dx, float dy, float dz);
6185 extern float THD_BN_dxyz(void);
6186 extern int THD_BN_nx(void);
6187 extern int THD_BN_ny(void);
6188 extern int THD_BN_nz(void);
6189 extern float THD_BN_xorg(void);
6190 extern float THD_BN_yorg(void);
6191 extern float THD_BN_zorg(void);
6192 extern float THD_BN_zheight(void);
6193 extern float THD_BN_xcm (void);
6194 extern float THD_BN_ycm (void);
6195 extern float THD_BN_zcm (void);
6196 extern float THD_BN_rat (void);
6197 /*------------------------------------------------------------------------*/
6198 /* 09 May 2005: stuff for converting a dataset to from a NIML group.      */
6199 
6200 extern NI_group   * THD_nimlize_dsetatr( THD_3dim_dataset *) ;
6201 extern NI_group   * THD_dset_to_ni_surf_dset( THD_3dim_dataset * , int ) ;
6202 extern NI_element * NI_find_element_by_aname(NI_group *,char *,char *,char *);
6203 
6204 extern void       THD_dblkatr_from_niml( NI_group *, THD_datablock * ) ;
6205 extern void       THD_set_dataset_attributes( THD_3dim_dataset * ) ;
6206 
6207 extern char     * THD_make_statsym_string(THD_3dim_dataset *, int);
6208 extern char     * unescape_unix_str(const char *);
6209 
6210 extern THD_3dim_dataset * THD_niml_to_dataset( NI_group * , int ) ;
6211 extern int THD_add_bricks( THD_3dim_dataset * , void *, THD_3dim_dataset * ) ;
6212 extern int THD_add_sparse_data( THD_3dim_dataset * , NI_group * ) ;
6213 extern int THD_add_sparse_bricks( THD_3dim_dataset *, NI_element *) ;
6214 
6215 extern int  NI_get_byte_order(NI_element *) ;    /* 29 Aug 2006 [rickr] */
6216 extern int  dtype_nifti_to_niml(int dtype);      /* 19 Feb 2008 [rickr] */
6217 extern int  dtype_niml_to_nifti(int dtype);      /* 20 Feb 2008 [rickr] */
6218 extern int  nsd_string_atr_to_slist(char ***, int, ATR_string *);
6219 
6220 
6221 extern int  get_gni_debug(void) ;                /*  3 Aug 2006 [rickr] */
6222 extern int  get_gni_to_float(void) ;
6223 extern int  get_gni_write_mode(void) ;
6224 extern void set_gni_debug(int) ;
6225 extern void set_gni_to_float(int) ;
6226 extern void set_gni_write_mode(int) ;
6227 extern int  set_ni_globs_from_env(void) ;
6228 extern int  set_sparse_data_attribs(NI_element *, THD_3dim_dataset *, int) ;
6229 
6230 /*------------------------------------------------------------------------*/
6231 /* for converting between NIFTI-1 and NIFTI-2   10 Jul, 2015 [rickr]      */
6232 int64_t * copy_ints_as_i64    (int * ivals, int nvals);
6233 int       nifti_mat44_2_dmat44(mat44 * fm, nifti_dmat44 * dm);
6234 int       nifti_dmat44_2_mat44(nifti_dmat44 * dm, mat44 * fm);
6235 
6236 
6237 
6238 #define SBFLAG_INDEX    (1<<0)
6239 #define SBFLAG_FACTOR   (1<<1)
6240 #define SBFLAG_STATCODE (1<<2)
6241 
6242 extern NI_element * THD_subbrick_to_niml( THD_3dim_dataset *, int , int ) ;
6243 extern NI_group * THD_dataset_to_niml( THD_3dim_dataset * ) ;
6244 
6245 extern MRI_IMAGE  * niml_to_mri( NI_element * ) ;
6246 extern NI_element * mri_to_niml( MRI_IMAGE *  ) ;
6247 
6248 /* a random-ish seed for a random number generator */
6249 
6250 #undef  GSEED
6251 #define GSEED (time(NULL) + 701*getpid())
6252 
6253 #ifdef  __cplusplus
6254 }
6255 #endif
6256 
6257 typedef struct {
6258   int npthr , nathr ;
6259   float *pthr , *athr ;
6260   float **cluthr ;
6261 } CLU_threshtable ;   /* from 3dClustSim [Jul 2010] */
6262 
6263 extern char * THD_clustsim_atr_mask_dset_idcode( THD_3dim_dataset *dset ) ;
6264 extern float_triple THD_clustsim_atr_fwhmxyz( THD_3dim_dataset *dset ) ;
6265 
6266 /*------ Moved here from afni.h [13 Jan 2020] ------*/
6267 extern void AFNI_store_dset_index(int,int) ;  /* 18 May 2000 */
6268 extern int  AFNI_needs_dset_ijk(void) ;
6269 extern int  AFNI_needs_dset_tin(void) ;
6270 
6271 #endif /* _MCW_3DDATASET_ */
6272