1 #ifndef SUMA_DATASETS_INCLUDED
2 #define SUMA_DATASETS_INCLUDED
3 
4 #include "replaceXt.h"  /* 09 Nov 2018 */
5 
6 #include "suma_objs.h"
7 #include "matrix.h"
8 #include "suma_afni_surface.h"
9 
10 #define MAX_ERRLOG_MSG 1000
11 #define MAX_ERRLOG_FUNCNAME 200
12 #define TMP_NAME_SEP "_LDPID_"
13 
14 /*! macro to avoid typecasting warnings when going from
15     void * pointers (or XtPointer) to int and vice versa */
16    /* I use INT_MAX and LONG_MAX
17    to guess whether or not we have 64 bit pointers.
18    I need to guess with #if to do proper type casting and
19    avoid compiler warnings */
20 #if INT_MAX < LONG_MAX
21    #define INT_CAST  int)(long int
22    #define VOID_CAST  void *)(long int
23    #define CVOID_CAST  const void *)(long int
24    #define XTP_CAST  XtPointer)(long int
25    #define NIGRP_CAST NI_group *)(long int
26 #else
27    #define INT_CAST int
28    #define VOID_CAST void *
29    #define CVOID_CAST const void *
30    #define XTP_CAST  XtPointer
31    #define NIGRP_CAST NI_group *
32 #endif
33 
34 
35 #define SUMA_free(a) mcw_free(a,__FILE__,__LINE__)
36 #define SUMA_ifree(p)  { if ((p)) {SUMA_free((p));} (p)=NULL; }
37 
38 #ifdef USE_TRACING
39 #define SUMA_DUMP_TRACE( ... ) { /* taken from dbtrace.h */\
40    int m_ii;  \
41    SUMA_S_Note( __VA_ARGS__ );\
42    if( DBG_num >= 0 ){  \
43       for( m_ii=DBG_num-1; m_ii >= 0 ; m_ii-- ) \
44          fprintf(stderr,"%*.*s%s\n",m_ii+1,m_ii+1," ",DBG_rout[m_ii]) ; \
45    } else { \
46       fprintf(stderr,"[No debug tracing stack: DBG_num=%d]\n",DBG_num) ;   \
47    }  \
48 }
49 #define SUMA_EDUMP_TRACE( ... ) { /* taken from dbtrace.h */\
50    int m_ii;  \
51    SUMA_S_Err( __VA_ARGS__ ); \
52    if( DBG_num >= 0 ){  \
53       for( m_ii=DBG_num-1; m_ii >= 0 ; m_ii-- ) \
54          fprintf(stderr,"%*.*s%s\n",m_ii+1,m_ii+1," ",DBG_rout[m_ii]) ; \
55    } else { \
56       fprintf(stderr,"[No debug tracing stack: DBG_num=%d]\n",DBG_num) ;   \
57    }  \
58 }
59 #else
60 #define SUMA_DUMP_TRACE(...) /* nada */
61 #define SUMA_EDUMP_TRACE( ... ) /* nada */
62 #endif
63 #define SUMA_T_Err SUMA_EDUMP_TRACE
64 
65 typedef struct {
66     char macroname[100];
67     char msg[MAX_ERRLOG_MSG];
68     char FuncName[MAX_ERRLOG_FUNCNAME];
69 } SUMA_ERRLOG;
70 
71 
72 typedef enum { SUMA_SIDE_ERROR=-1, SUMA_NO_SIDE, SUMA_LR, SUMA_LEFT, SUMA_RIGHT } SUMA_SO_SIDE;
73 
74 typedef enum { SUMA_NO_NUM_UNITS = 0,
75                SUMA_MM_UNITS,
76                SUMA_P_VALUE_UNITS,
77                SUMA_Q_VALUE_UNITS,
78                SUMA_PERC_VALUE_UNITS,
79 
80                SUMA_N_NUMERICAL_UNITS
81                } SUMA_NUMERICAL_UNITS;
82 
83 
84 /*! simple vectors */
85 typedef struct {
86    int n;
87    int *v;
88 } SUMA_IVEC;
89 
90 typedef struct {
91    int n;
92    float *v;
93 } SUMA_FVEC;
94 
95 typedef struct {
96    int n;
97    double *v;
98 } SUMA_DVEC;
99 
100 
101 
102 typedef enum {
103    SUMA_ERROR_DSET_TYPE = -1,
104    SUMA_NO_DSET_TYPE,
105    SUMA_NODE_BUCKET,
106    SUMA_VOXEL_BUCKET,
107    SUMA_AFNI_NODE_BUCKET,
108    SUMA_NODE_ROI, /*!< Col0: Node ID, Col1: ROI label (int) */
109    SUMA_NODE_RGB,
110    SUMA_NODE_RGBb,
111    SUMA_NODE_RGBA,
112    SUMA_NODE_RGBAb,
113    SUMA_NODE_LABEL,
114    SUMA_NODE_XYZ,
115    SUMA_NEW_NODE_XYZ,
116    SUMA_NODE_CONVEXITY,
117    SUMA_NEW_MESH_IJK,
118    SUMA_MESH_IJK,
119    SUMA_PREP_NEW_SURFACE,
120    SUMA_VIEWER_SETTING,
121    SUMA_SURFACE_VOLUME_PARENT,
122    SUMA_SURFACE_OBJECT,
123    SUMA_ENGINE_INSTRUCTION,
124    SUMA_SEGMENT_OBJECT,
125    SUMA_LABEL_TABLE_OBJECT,
126    SUMA_GRAPH_BUCKET,
127    SUMA_TRACT_BUCKET,
128    SUMA_CIFTI_BUCKET,
129    SUMA_N_DSET_TYPES
130 } SUMA_DSET_TYPE; /*!<  Type of data set ( should be called Object, not DSET )
131                         When you add a new element, modify functions
132                         SUMA_Dset_Type_Name
133                         SUMA_Dset_Type */
134 
135 typedef enum {
136    SUMA_ERROR_DSET_FORMAT = -1,
137    SUMA_NO_DSET_FORMAT,       /* 0 */
138    SUMA_ASCII_NIML,           /* 1 */
139    SUMA_BINARY_NIML,          /* 2 */
140    SUMA_NIML,                 /* 3 */
141    SUMA_1D,                   /* 4 */
142    SUMA_1D_PURE,              /* 5 */
143    SUMA_ASCII_OPEN_DX_DSET,   /* 6 */
144    SUMA_1D_PURE_TRANSPOSE,    /* 7 */
145    SUMA_1D_STDOUT,            /* THIS ONE IS USED AS A MARKER TOO   */   /*8 */
146    SUMA_1D_STDERR,            /* 9 */
147    SUMA_NIML_STDOUT,          /* 10 */
148    SUMA_NIML_STDERR,          /* 11 */
149    SUMA_1D_PURE_STDOUT,       /* 12 */
150    SUMA_1D_PURE_STDERR,       /* 13 */
151    SUMA_1D_PURE_STDOUT_TRANSPOSE,       /* 14 */
152    SUMA_1D_PURE_STDERR_TRANSPOSE,/* THIS ONE IS USED AS A MARKER TOO*/  /* 15 */
153    SUMA_XML_DSET,                  /* 16 */
154    SUMA_XML_ASCII_DSET,            /* 17 */
155    SUMA_XML_B64_DSET,              /* 18 */
156    SUMA_XML_B64GZ_DSET,             /* 19 */
157 
158    SUMA_N_DSET_FORMATS           /* leave at the end */
159 } SUMA_DSET_FORMAT; /*!<  Format of data set
160                           When you add a new element, modify functions
161                           SUMA_Dset_Format_Name
162                           SUMA_Dset_Format */
163 #define SUMA_IS_DSET_1D_FORMAT(d) ( (d)==SUMA_1D || (d)==SUMA_1D_PURE || (d)==SUMA_1D_STDOUT || (d)==SUMA_1D_STDERR ) ? 1:0
164 
165 #define SUMA_IS_DSET_STDXXX_FORMAT(d) ( (d)>=SUMA_1D_STDOUT && (d)<= SUMA_1D_PURE_STDERR_TRANSPOSE) ? 1:0
166 
167 typedef enum {
168    SUMA_ERROR_COL_TYPE = -1,
169    SUMA_NO_COL_TYPE,
170    SUMA_NODE_INT,    /*!< Generic integer */
171    SUMA_NODE_INDEX,  /*!< index of a node OR edge to locate it in its domain */
172    SUMA_NODE_ILABEL, /*!< An integer coding for an integer label */
173    SUMA_NODE_SLABEL, /*!< An string label */
174    SUMA_GNODE_IGROUP, /*!< An integer coding for a group integer label of
175                            a graph node*/
176    SUMA_NODE_FLOAT,  /*!< Generic float */
177    SUMA_NODE_CX,     /*!< Node convexity */
178    SUMA_NODE_X,      /*!< Node X coordinate */
179    SUMA_NODE_Y,      /*!< Node Y coordinate */
180    SUMA_NODE_Z,      /*!< Node Z coordinate */
181    SUMA_NODE_3C,     /*!<  Node XYZ triplets */
182    SUMA_NODE_R,      /*!< Node R color */
183    SUMA_NODE_G,      /*!< Node G color */
184    SUMA_NODE_B,      /*!< Node B color */
185    SUMA_NODE_A,      /*!< Node A value */
186    SUMA_NODE_BYTE,   /*!< Generic byte */
187    SUMA_NODE_Rb,      /*!< Node R color in bytes*/
188    SUMA_NODE_Gb,      /*!< Node G color in bytes*/
189    SUMA_NODE_Bb,      /*!< Node B color in bytes*/
190    SUMA_NODE_Ab,      /*!< Node A value in bytes*/
191    SUMA_NODE_STRING,   /*!< Generic String */
192    SUMA_NODE_SHORT,      /*!< Generic short */
193    SUMA_NODE_DOUBLE,     /*!< Generic double */
194    SUMA_NODE_COMPLEX,     /*!< Generic complex */
195    SUMA_NODE_XCORR,      /*!< Cross Correlation Coefficient */
196    SUMA_NODE_ZSCORE,      /*!< Zscore */
197    SUMA_NODE_VFR,       /* Visual Field Ration */
198    SUMA_NODE_PHASE,     /* Phase of some sort */
199    SUMA_NODE_AREA,      /* Area associated with node*/
200    SUMA_NODE_VOLUME,    /* Volume associated with node */
201    SUMA_NODE_THICKNESS,  /* Thickness (distance between isotopic nodes) */
202    SUMA_GNODE_INDEX,     /*!< index of a graph's node/point,
203                               not to be confused with SUMA_NODE_INDEX which
204                               really should be named SUMA_DATUM_INDEX if it were
205                               not for all the other _NODE_ which would also
206                               need changing*/
207    SUMA_EDGE_P1_INDEX,        /* First point (Graph Node) defining an edge */
208    SUMA_EDGE_P2_INDEX,        /* Second point defining an edge */
209 
210    SUMA_MD_NODE_INDEX, /*!< Index col. into a Multiple Domain object a la CIFTI*/
211 
212    SUMA_N_COL_TYPES           /* MAX number of col types */
213 }  SUMA_COL_TYPE; /*!<  Column types.
214                         When you add a new element, you need to modify
215                         SUMA_AddColAttr
216                         SUMA_Col_Type
217                         SUMA_Col_Type_Name
218                         SUMA_ColType2TypeCast
219                         */
220 #define SUMA_IS_GNODE_IXYZ_COL(ctp) (((ctp)==SUMA_NODE_X || \
221                                  (ctp)==SUMA_NODE_Y || \
222                                  (ctp)==SUMA_NODE_Z || \
223                                  (ctp)==SUMA_GNODE_INDEX || \
224                                  (ctp)==SUMA_GNODE_IGROUP || \
225                                  (ctp)==SUMA_NODE_R || \
226                                  (ctp)==SUMA_NODE_G || \
227                                  (ctp)==SUMA_NODE_B || \
228                                  (ctp)==SUMA_NODE_SLABEL) ? 1:0)
229 
230 #define SUMA_GNODE_IXYZ_CTP2COL(ctp) ( (ctp)==SUMA_NODE_X ? 1 : \
231                                        ( (ctp)==SUMA_NODE_Y ? 2: \
232                                        ( (ctp)==SUMA_NODE_Z ? 3: \
233                                        ( (ctp)==SUMA_NODE_SLABEL ? 4: \
234                                        ( (ctp)==SUMA_GNODE_IGROUP ? 5: \
235                                        ( (ctp)==SUMA_NODE_R ? 6: \
236                                        ( (ctp)==SUMA_NODE_G ? 7: \
237                                        ( (ctp)==SUMA_NODE_B ? 8: \
238                                        ( (ctp)==SUMA_GNODE_INDEX ? 0: \
239                                                          -1 ) ) ) ) ) ) ) ) )
240 
241 #define SUMA_IS_DATUM_INDEX_COL(ctp) (((ctp)==SUMA_NODE_INDEX || \
242                                  (ctp)==SUMA_EDGE_P1_INDEX || \
243                                  (ctp)==SUMA_EDGE_P2_INDEX ) ? 1:0)
244 #define SUMA_IS_MD_DATUM_INDEX_COL(ctp) (((ctp)==SUMA_NODE_INDEX) ? 1 : 0)
245 #define SUMA_DATUM_INDEX_CTP2COL(ctp) ( ((ctp)==SUMA_NODE_INDEX || \
246                                          (ctp)==SUMA_MD_NODE_INDEX) ? 0 : \
247                                     ( (ctp)==SUMA_EDGE_P1_INDEX ? 1: \
248                                        ( (ctp)==SUMA_EDGE_P2_INDEX ? 2:-1 ) )  )
249 
250 /*!< Displayable Object Types
251                                                                                     S: surface, A: axis, G: grid,
252                                                                                     ROId: Region of interest drawn type,
253                                                                                     LS_type: line segment
254                                                                                     NBLS_type: Node-based line segment
255 
256   OLS_type: oriented line segment
257                                                                                     NBOLS_type: Node-based oriented line segment
258                                                                                     NBV_type: Node-Based vector (displayed as a line from node)
259                                                                                     ONBV_type: NBV with a ball on the bottom (slower to render)
260                                                                                     SP_type: spherical markers
261                                                                                     NBSP_type: Node-Based spherical markers
262                                                                                     PL_type: planes
263                                                                                     NBT_type: Node-based text
264                                                                                     SBT_type: Screen-based text
265                                                                                     DBT_type: Dicom-based text
266                                                                                     DIR_type: Directions
267                                                                                     ODIR_type: Oriented Directions (not in use yet)
268 
269   PNT_type: Cloud of points
270 
271   */
272 typedef enum { NOT_SET_type = -1,
273                not_DO_type, SO_type, AO_type, ROIdO_type, ROIO_type,
274                GO_type, LS_type, NBLS_type, OLS_type, NBOLS_type,
275                NBV_type, ONBV_type, SP_type,
276                NBSP_type, PL_type, VO_type,
277                NBT_type, SBT_type, DBT_type, /*!< Those three will
278                                                    likely not be used */
279                NIDO_type, ANY_DSET_type, GDSET_type, MD_DSET_type, TRACT_type,
280                GRAPH_LINK_type, MASK_type, DIR_type, ODIR_type,
281                PNT_type,
282                CDOM_type, /* The domain of a CIFTI beast */
283                N_DO_TYPES } SUMA_DO_Types;
284 
285 #define iDO_isSO(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? 0: \
286                       ( SUMAg_DOv[(i)].ObjectType == SO_type ? 1:0) )
287 #define iDO_isGLDO(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? 0: \
288                       ( SUMAg_DOv[(i)].ObjectType == GRAPH_LINK_type ? 1:0) )
289 #define iDO_isTDO(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? 0: \
290                       ( SUMAg_DOv[(i)].ObjectType == TRACT_type ? 1:0) )
291 #define iDO_isMDO(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? 0: \
292                       ( SUMAg_DOv[(i)].ObjectType == MASK_type ? 1:0) )
293 #define iDO_isVO(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? 0: \
294                       ( SUMAg_DOv[(i)].ObjectType == VO_type ? 1:0) )
295 #define iDO_type(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? NOT_SET_type: \
296                       ( SUMAg_DOv[(i)].ObjectType ) )
297 #define iDO_typename(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? \
298                               "NO OBJECT!": \
299                       ( SUMA_ObjectTypeCode2ObjectTypeName(\
300                                     SUMAg_DOv[(i)].ObjectType) ) )
301 #define iDO_ADO(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? NULL : \
302                               (SUMA_ALL_DO *)SUMAg_DOv[(i)].OP)
303 #define ADO_iDO(ado) ( (ado) ? SUMA_whichDO(SUMA_ADO_idcode((ado)), \
304                                             SUMAg_DOv, SUMAg_N_DOv):-1 )
305 #define iDO_state SUMA_iDO_state
306 #define iDO_group SUMA_iDO_group
307 
308 #define ADO_TNAME(ado) (!(ado) ? \
309                               "NULL ADO!": \
310                       ( SUMA_ObjectTypeCode2ObjectTypeName(\
311                                     (ado)->do_type) ) )
312 #define ADO_ID(ado) SUMA_ADO_idcode(ado)
313 #define ADO_LABEL(ado) SUMA_ADO_sLabel(ado)
314 #define ADO_STATE(ado) SUMA_iDO_state(ADO_iDO(ado))
315 #define ADO_GROUP(ado) SUMA_iDO_group(ADO_iDO(ado))
316 
317 #define iDO_label(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? \
318                               "NO OBJECT!": \
319                       ( (SUMA_ADO_Label((SUMA_ALL_DO *)SUMAg_DOv[(i)].OP) ) ) )
320 #define iDO_variant(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? \
321                               "NO OBJECT!": \
322                       ( (SUMA_ADO_variant((SUMA_ALL_DO *)SUMAg_DOv[(i)].OP) ) ) )
323 
324 #define iDO_GSaux(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? \
325                               NULL: \
326                       ( (SUMA_ADO_GSaux((SUMA_ALL_DO *)SUMAg_DOv[(i)].OP) ) ) )
327 #define iDO_idcode(i) ( ((i)<0 || (i)>=SUMAg_N_DOv) ? \
328                               NULL: \
329                       ( (SUMA_ADO_idcode((SUMA_ALL_DO *)SUMAg_DOv[(i)].OP) ) ) )
330 #define iDO_is_variant(i,var) ( (var) ? !strcmp(iDO_variant(i),(var)):0 )
331 #define  DO_label(DO) ( !(DO) ? "NO OBJECT!": \
332                         ((SUMA_ADO_Label((SUMA_ALL_DO *)(DO)) ) ) )
333 
334 #define SUMA_IS_GOOD_STATE(mm) ( ((mm)&&strncmp(mm,"TheShadow",9))?1:0 )
335 #define SUMA_IS_REAL_VARIANT(mm) ( ((mm)&&strncmp(mm,"TheShadow",9))?1:0 )
336 
337 /*!
338 I do not think we can have both nodes and triangles in this struct.
339 I guess I can make this be a Node Datum then create a similar struct
340 for triangle Datum and add them to SUMA_NIML_DRAWN_ROI.
341 If you do something like this rename:
342 SUMA_NIML_ROI_DATUM to SUMA_NIML_NODE_ROI_DATUM
343 */
344 typedef struct {
345    int action; /*!< action taken with this datum,
346                      see same field in SUMA_ROI_DATUM */
347    int Type; /*!< describes the type of the DrawnROI datum
348                   (see SUMA_ROI_TYPE) */
349    int N_n;
350    int *nPath;
351 /* int Type;
352    int N_t;
353    int *tPath; */
354 } SUMA_NIML_ROI_DATUM; /*!< a version of SUMA_ROI_DATUM struct
355                            that can be used by niml. */
356 
357 typedef struct {
358    int Type;         /*!< The final type of the DrawnROI,
359                            see SUMA_ROI_DRAWING_TYPE*/
360    char *idcode_str;
361    char *Parent_idcode_str;
362    int Parent_side;
363    char *Label;
364    char *ColPlaneName;
365    float FillColor[4];  /*!< RGB fill color */
366    float EdgeColor[4];  /*!< RGB edge color */
367    int EdgeThickness;   /*!< thickness of edge */
368    int iLabel;
369    SUMA_NIML_ROI_DATUM *ROI_datum; /*!< a vector of ROI data
370                                        (a multitude of ROI datum) */
371    int N_ROI_datum;
372 } SUMA_NIML_DRAWN_ROI; /*!< a version of SUMA_DRAWN_ROI struct that
373                            can be used by niml. Fields are a reflection
374                            of those in SUMA_DRAWN_ROI*/
375 
376 typedef struct { /* A structure to contain information about a domain
377                     over which a subset of a dataset is defined.
378                     This structure was introduced to support CIFTI data */
379    /* The following variables are named after those in CIFTI's documentation for
380       BrainModel Element */
381       int IndexOffset; /* The number of the first row in dset corresponding to
382                        the first datum over this domain  */
383       int IndexCount; /* How many consecutive rows in dset correspond to this
384                       domain*/
385       int Max_N_Data; /* Maximum number of data points in domain
386                          SO->N_Node, DSET_NVOX(dset) */
387       SUMA_DO_Types ModelType; /* Is this a surface, volume, etc...*/
388       SUMA_SO_SIDE  ModelSide; /* Which hemisphere? ...*/
389       int Range[4];  /* min , max , imin, imax
390                      min, and max are the minimum and maximum node indices
391                      present in the full index list for this domain.
392                      imin and imax are the rows into the full index list
393                      where these min and max indices are found */
394       char *Source;
395       char *edset_id; /* ID to elementary dataset defining that part of
396       	             the parent multi domain dataset that is
397       	             defined over this one domain only.
398 		     'edset' is an elementary (single domain) dataset. */
399 } SUMA_DSET_DOMAIN;
400 /* Get the pointer to the beginning of the data indices for domain dom */
401 
402 #define SUMA_DOMAIN_INDICES(dset,dom) ((( (dset) && \
403                                  (dset)->inel && \
404                                  (dset)->inel->vec[0] && \
405                                  IndexOffset >= 0)) ? \
406                                 dset->inel->vec[0]+IndexOffset:NULL)
407 
408 typedef enum { SUMA_NO_PTR_TYPE,
409                SUMA_LINKED_DSET_TYPE, /*!< For pointers to SUMA_DSET */
410                SUMA_LINKED_OVERLAY_TYPE, /*!< For pointers to SUMA_OVERLAYS */
411                SUMA_LINKED_ND_FRST_NEI_TYPE,
412                                  /*!< For pointers to SUMA_NODE_FIRST_NEIGHB*/
413                SUMA_LINKED_MEMB_FACE_TYPE,
414                                  /*!< For pointers to SUMA_MEMBER_FACE_SETS*/
415                SUMA_LINKED_SURFCONT_TYPE, /*!< For pointers to SUMA_X_SurfCont*/
416                SUMA_LINKED_COLORLIST_TYPE,/* pointers to SUMA_COLORLIST_STRUCT */
417                SUMA_LINKED_DRAW_MASKS_TYPE, /*!< Pointers to SUMA_DRAW_MASKS */
418                SUMA_N_LINKED_PTR_TYPES } SUMA_LINKED_PTR_TYPES;
419 
420 typedef enum { MAT_UNKNOWN=-2, MAT_NA = -1, MAT_HEEHAW = 0 /* not set */,
421                MAT_FULL = 1, MAT_TRI, MAT_TRI_DIAG, MAT_SPARSE
422               } SUMA_SQ_MATRIX_SHAPES;
423 
424 typedef enum { SURF_DSET, GRAPH_DSET, TRACT_DSET, VOLUME_DSET,
425       	       CIFTI_DSET, MD_DSET} SUMA_DSET_FLAVORS;
426 typedef enum { SUMA_ELEM_DAT=0, /* Nodes of surface, points of tracts,
427                                  edges of graph */
428                SUMA_LEV1_DAT, /* data at the tract level*/
429                SUMA_LEV2_DAT, /* data at the bundle level */
430                SUMA_N_LEV_DAT} SUMA_DATUM_LEVEL;
431 
432 typedef struct { /* Something to hold auxiliary datasets structs */
433       /* The Saux kids are not always set, they should be
434          reached by accessor functions and macros, not
435          fished directly from here
436          Where Saux lies depends on the flavor of dset at hand */
437    void *Saux; /* A pointer to a structure for SUMA's use */
438    void (*FreeSaux)(void *Saux); /* Function to free Saux */
439 
440    /* Some fields that make queries faster, WARNING, they
441       are duplicates of fields in the NI_group* so you
442       should not set these values explicitly */
443    SUMA_SQ_MATRIX_SHAPES matrix_shape;
444    long int matrix_max_index;    /* max number of edges */
445    long int matrix_size[2];
446    long int matrix_2M;
447    long int range_edge_index[2]; /* min, max, edge index */
448    long int range_node_index[2]; /* min, max, node index
449                                    (points defining edges)*/
450    long int N_seg_nodes; /* Number of node indices making up segments*/
451    long int N_all_nodes; /* Total number of nodes stored in nodelist of the
452                             graph dataset */
453    SUMA_DSET_FLAVORS isGraph;
454 
455    SUMA_DSET_DOMAIN **doms; /* domains over which the dataset
456                                (only CIFTI for now) is defined */
457    int N_doms;              /* Number of domains          */
458 } SUMA_DSET_AUX;
459 
460 /*!
461    Structure to track copies of a certain pointer.
462    DO NOT CHANGE THE ORDER OF THE STRUCTURE's FIELDS
463 */
464 
465 typedef struct {
466    SUMA_DO_Types do_type;  /*!< To check if this is a displayable object
467                               Leave on top for SUMA_ALL_DO and SUMA_DSET */
468    int LinkedPtrType; /*!< Indicates the type of linked pointer */
469    int N_links;   /*!< Number of links to this pointer */
470    char owner_id[SUMA_IDCODE_LENGTH];   /*!< The id of whoever created
471                               that pointer. Might never get used.... */
472 } SUMA_LinkedPtr;
473 
474 /*! Structure to contain a dataset defined on the surface */
475 
476 typedef struct {
477    /* *** DO NOT ADD ANYTHING BEFORE THESE FIELDS
478           DO NOT CHANGE THE ORDER OF THESE FIELDS
479           These fields are use for tracking copies
480           (links) to a pointer.
481           ANY CHANGES HERE SHOULD BE REFLECTED IN
482           SUMA_LinkedPtr structure
483    */
484    SUMA_DO_Types do_type;  /*!< To check if this is a displayable object
485                                 This is to remain on top, to fit with
486                                 SUMA_ALL_DO */
487    int LinkedPtrType; /*!< Indicates the type of linked pointer */
488    int N_links;   /*!< Number of links to this pointer */
489    char owner_id[SUMA_IDCODE_LENGTH];   /*!< The id of whoever created
490                                  that pointer. Might never get used.... */
491 
492    #ifdef OLD_DSET
493    NI_element *nel;  /*!< The whole deal
494       nel is a NIML data element which is briefly
495       defined by a set of attributes, and a collection
496       of data columns.
497       nel contains the following string attributes:
498          filename: The filename
499          label: A short text label identifying the data set.
500                 Typically, a short version of the filename
501          idcode_str: Unique identifier for the data set
502          MeshParent_idcode: Unique identifier of the surface containing the mesh
503                             over which this set is defined
504          geometry_parent_idcode: Unique identifier of the surface containing the
505                             coordinates of the nodes whose attributes
506                             (values) are in this set.
507          sorted_node_def: flag indicating that nodes in NodeDef are sorted
508                           see NodeDef below.
509          LabelCol_'i': Label of column i
510          RangeCol_'i': Range of values in column i.
511                        See function:
512                         SUMA_GetColRange.
513          TypeCol_'i': Type of data in column i.
514                       See functions:
515                         SUMA_Col_Type
516                         SUMA_Col_Type_Name
517                         SUMA_ColType2TypeCast
518                       and typedef:
519                         SUMA_COL_TYPE
520          AttrCol_'i': Attributes specific to that column type.
521                       At the moment, I don't use it much. But
522                       think attributes to store with an f-stat
523                       column for example and so on.
524          RangeCol_, TypeCol_ and AttrCol_: are automatically
525                                            generated, see:
526                                              SUMA_AddColAttr
527                                              SUMA_AddGenColAttr
528 
529       nel structure contains the following fields:
530          name: A string for the type of dataset.
531                See functions:
532                   SUMA_Dset_Type_Name
533                   SUMA_Dset_Type
534                and typedef:
535                   SUMA_DSET_TYPE
536          vec: A vector of pointers to the data columns.
537          vec_num: Number of columns in vec. So your columns
538                   are vec[0] .. vec[vec_num - 1]
539                   THINK SUB-BRICKS
540          vec_len: Total number of rows in the dset. Think total
541                   number of voxels.
542          vec_filled: Number of rows (node data) filled in the dset.
543                      You'd think this should be equal to vec_len,
544                      but in instances where you may be receiving data for a
545                      varying number of nodes, it's a pain to have to destroy
546                      and recreate dsets. The trouble is not one of allocation
547                      but of multiple links and associated structures created
548                      for each new dset. So, while the juice is only up to
549                      vec_filled, the allocation is for vec_len
550          NodeDef: A vector containing an explicit list of the node index
551                   associated with each row of data.
552                   ACTUALLY this is not a field of nel, but it is a column of
553                   data of the type SUMA_NODE_INDEX or "Node_Index". This
554                   column may or may not exist. If it exist then NodeDef is
555                   (int *)nel->vec[i_node_index] where i_node_index is the
556                   index of the column containing node definitions. To
557                   find i_node_index, see function:
558                      SUMA_GetColIndex
559 
560          Functions to read and write dsets:
561             SUMA_LoadDset
562             SUMA_Load1DDset
563             SUMA_LoadNimlDset
564             SUMA_WriteDset
565             SUMA_RemoveDsetExtension
566          Functions to form/access dsets and contents:
567             SUMA_NewNel
568             SUMA_AddNelCol
569             SUMA_FillNelCol
570             SUMA_GetColIndex
571             SUMA_Col2Float
572             SUMA_GetNodeDef
573             SUMA_FreeDset
574          Functions for debugging:
575             SUMA_ShowNel
576             SUMA_NI_nel_Info
577             SUMA_DsetInfo
578             SUMA_ShowMeSome
579          Miscellaneous functions/tools:
580             SUMA_Dset_Format
581             SUMA_Dset_Format_Name
582             SUMA_AddNelHist
583 
584          */
585    #else   /* the post april 06 05 way */
586    /* *** You can go crazy below */
587    NI_group *ngr; /*!< This is now April 06 05, the container of the dataset,
588                        as opposed to the olde days where nel
589                        contained everything. The reason that was done is to
590                        accomodate large sized attibutes that
591                        do not fit nicely in ASCII forms tucked inside the header.
592                        What used to be called nel, is now called dnel (for
593                        data-part nel) and is nothing but a copy
594                        of the pointer under ngr to the nel that contains the
595                        tabular dataset.
596 
597       ngr contains two types of attributes:
598          STRING attributes:
599             filename: The filename
600             label: A short text label identifying the data set.
601                    Typically, a short version of the filename
602             idcode_str: Unique identifier for the data set
603             MeshParent_idcode: Unique identifier of the surface containing
604                                the mesh over which this set is defined
605             geometry_parent_idcode: Unique identifier of the surface containing
606                                the coordinates of the nodes whose attributes
607                                (values) are in this set.
608             sorted_node_def: flag indicating that nodes in NodeDef are sorted
609                              see NodeDef below.
610 
611          ELEMENT (data) attributes
612             ColumnRange
613             ColumnType
614             ColumnLabel
615             ColumnAttribute
616             History
617 
618          Sample Code: SUMA_TestDSETIO.c
619          */
620    NI_element *dnel; /*!< a copy of the NI_element pointer that contains
621                          the tabular data inside ngr. Do not free this
622                          element separately, and make sure its value is changed
623                          in syncrony with the one in ngr. */
624    NI_element *inel; /*!< a copy of the NI_element pointer that contains the
625                           node (or edge for graph dsets) index column inside ngr.
626                           Do not free this
627                           element separately, and make sure its value is
628                           changed in syncrony with the one in ngr. */
629    NI_element *pdnel; /*!< a copy of the NI_element pointer that contains the
630                          tabular graph point data inside ngr. Do not free this
631                          element separately, and make sure its value is changed
632                          in syncrony with the one in ngr. */
633    NI_element *pinel; /*!< a copy of the NI_element pointer that contains the
634                           point index column inside ngr. Do not free this
635                           element separately, and make sure its value is
636                           changed in syncrony with the one in ngr. */
637    SUMA_DSET_AUX *Aux;
638    #endif
639 } SUMA_DSET;
640 
641 /*!
642    Structure containing NIML formatted displayable objects
643 */
644 typedef struct {
645       /* FIRST VARIABLES MUST RETAIN THEIR ORDER and follow SUMA_ALL_DO */
646    SUMA_DO_Types do_type;
647    char *idcode_str;    /*!< unique idcode for DO */
648    char *Label; /*!< ascii label for DO */
649 
650       /* Begin specific fields */
651    NI_group *ngr;
652 } SUMA_NIDO;
653 
654 typedef struct {
655    float x;
656    float y;
657    float z;
658 } SUMA_XYZ;
659 
660 typedef struct {
661    int N_vals; /* Number of values in each array below.
662                   Each array can be NULL, a singleton,
663                   or N_vals long.
664                   a singleton is marked by setting (ptr+1)
665                   to NULL */
666    SUMA_NIDO **nido; /* Display DOs, perhaps */
667    char **lab;
668    float *val;
669    SUMA_XYZ *loc;
670 } SUMA_G_DATUM;
671 
672 /*! structure for holding graph nodes */
673 typedef struct {
674    int id;
675 
676    SUMA_G_DATUM *gd;
677 } SUMA_G_NODE;
678 
679 /*! structure for holding graph edges */
680 typedef struct {
681    int id;
682    int n0id; /* id of starting node */
683    int n1id; /* id of ending node */
684 
685    SUMA_G_DATUM *gd;
686 } SUMA_G_EDGE;
687 
688 typedef struct {
689    SUMA_G_NODE **gn; /* vector of nodes */
690    int N_gn;
691    int N_alloc;
692 }  SUMA_G_NODES;
693 
694 typedef struct {
695    SUMA_G_EDGE **ge; /* vector of edges */
696    int N_ge;
697    int N_alloc;
698 }  SUMA_G_EDGES;
699 
700 typedef struct {
701    SUMA_G_NODES *nodes;
702    SUMA_G_EDGES *edges;
703    int O_nodes; /* order of number of nodes, used to increment allocation */
704    int O_edges;
705 } SUMA_GRAPH;
706 
707 #define SUMA_COUNTER_SUFFIX(ic)  ( ((ic) == 1) ? "st" : ((ic) == 2) ? "nd" : ((ic) == 3) ? "rd" : "th" )
708 #define SUMA_COUNTER_PLURAL(ic)  ( ((ic) == 1) ? "" : "s" )
709 
710 #define SUMA_ECHO_EDU(brk, kar) {   \
711    if (!brk && (strcmp(argv[kar], "-echo_edu") == 0)) {  \
712       int m_jj;  \
713       fprintf(SUMA_STDOUT,"\n+++ Now running:\n   "); \
714       for (m_jj=0; m_jj<argc; ++m_jj) {   \
715          if (m_jj != kar) {   \
716             fprintf(SUMA_STDOUT,"%s ", argv[m_jj]);   \
717          }  \
718       }  \
719       fprintf(SUMA_STDOUT,"\n+++\n");  \
720       brk = YUP;   \
721    }  \
722 }
723 
724 
725 
726 #define SUMA_SKIP_COMMON_OPTIONS(m_brk, m_kar) {\
727    SUMA_ECHO_EDU(m_brk, m_kar);  \
728    if (!m_brk &&                                     \
729        ( (strcmp(argv[m_kar], "-memdbg") == 0) ||    \
730          (strcmp(argv[m_kar], "-iodbg") == 0)  ||    \
731          (strcmp(argv[m_kar], "-nomall") == 0) ||    \
732          (strcmp(argv[m_kar], "-yesmall") == 0) ||   \
733          (strcmp(argv[m_kar], "-trace") == 0) ||     \
734          (strcmp(argv[m_kar], "-novolreg") == 0) ||   \
735          (strcmp(argv[m_kar], "-noxform") == 0) ||   \
736          (strcmp(argv[m_kar], "-TRACE") == 0)) ) {   \
737 		/* valid options, but already taken care of */  \
738 		m_brk = YUP;                                   \
739 	}                                               \
740 }
741 
742 /*!
743    set a to 1 if vector values are sorted in increasing order
744             0 if not
745 */
746 #define SUMA_IS_SORTED_UP(v, n_v, a) {\
747    int m_i, m_nv = n_v-1; \
748    if (v) { \
749       a = 1;   \
750       for (m_i =0; m_i <m_nv; ++m_i) {  \
751          if (v[m_i] > v[m_i+1]) { a = 0; break; }  \
752       }  \
753    } else {\
754       SUMA_S_Warn("NULL vector in SUMA_IS_SORTED_UP\nReturning 0 for ans.\n");   \
755       a = 0;   \
756    }\
757 }/*!
758    set a to 1 if vector values are sorted in decreasing order
759             0 if not
760 */
761 #define SUMA_IS_SORTED_DOWN(v, n_v, a) {\
762    int m_i, m_nv = n_v-1; \
763    if (v) { \
764       a = 1;   \
765       for (m_i =0; m_i <m_nv; ++m_i) {  \
766          if (v[m_i] < v[m_i+1]) { a = 0; break; }  \
767       }  \
768    } else {\
769       SUMA_S_Warn("NULL vector in SUMA_IS_SORTED_DOWN\nReturning 0 for ans.\n");   \
770       a = 0;   \
771    }\
772 }
773 
774 /*!
775    Convenience function for SUMA_StringAppend cleanup
776 */
777 #define SUMA_SS2S(SS, stmp)  {\
778    if (SS)  {  \
779       SS = SUMA_StringAppend(SS, NULL);   \
780       stmp = SS->s;  \
781       SUMA_free(SS); SS = NULL;   } \
782 }
783 /*!
784    Frees so, if not NULL
785    copies sn into so, takes care of so's allocation
786    Does not free sn
787 */
788 #define SUMA_STRING_REPLACE(so, sn) {  \
789    if (so) SUMA_free(so);  \
790    so = SUMA_copy_string(sn); \
791 }
792 
793 #define SUMA_TO_LOWER_C(c) ( (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A'): c )
794 #define SUMA_IS_UPPER_C(c) ( (c >= 'A' && c <= 'Z') )
795 #define SUMA_IS_LOWER_C(c) ( (c >= 'a' && c <= 'z') )
796 
797 #define SUMA_TO_LOWER(s) { \
798    int m_i, m_d; \
799    if (s) { \
800       m_d = 'a' - 'A';  \
801       for (m_i=0; m_i < strlen(s); ++m_i) { \
802          if (s[m_i] >= 'A' && s[m_i] <= 'Z') s[m_i] = s[m_i] + m_d;  \
803       }   \
804    }  \
805 }
806 
807 #define SUMA_TO_UPPER_C(c) ( (c >= 'a' && c <= 'z') ? (c - 'a' + 'A'): c )
808 
809 #define SUMA_TO_UPPER(s) { \
810    int m_i, m_d; \
811    if (s) { \
812       m_d = 'a' - 'A';  \
813       for (m_i=0; m_i < strlen(s); ++m_i) { \
814          if (s[m_i] >= 'a' && s[m_i] <= 'z') s[m_i] = s[m_i] - m_d;  \
815       }   \
816    }  \
817 }
818 
819 
820 
821 /*!
822    Is this attribute string empty ?
823 */
824 #define SUMA_IS_EMPTY_STR_ATTR(str)  ( (!(str) || !strcmp((str),SUMA_EMPTY_ATTR)) ? 1 : 0 )
825 
826 
827 /*!
828    \brief Macros to access dataset elements
829    Almost all of them involve a function call
830    so don't use them in loops where the returned
831    value is not expected to change
832 */
833 #ifdef OLD_DSET
834    #define SDSET_FILENAME(dset) NI_get_attribute(dset->nel,"filename")
835    #define SDSET_LABEL(dset) NI_get_attribute(dset->nel,"label")
836    #define SDSET_ID(dset) SUMA_sdset_id(dset)
837    #define SDSET_IDGDOM(dset) NI_get_attribute(dset->nel,"geometry_parent_idcode")
838    #define SDSET_IDMDOM(dset) SUMA_sdset_idmdom(dset)
839    #define SDSET_SORTED(dset) NI_get_attribute(dset->nel,"sorted_node_def")
840    #define SDSET_TYPE_NAME(dset) dset->nel->name
841    #define SDSET_TYPE(dset) SUMA_Dset_Type(dset->nel->name)
842    #define SDSET_VECLEN(dset) dset->nel->vec_len
843    #define SDSET_VECNUM(dset) dset->nel->vec_num
844    #define SDSET_VECFILLED(dset) dset->nel->vec_filled
845 #else
846    #define SDSET_FILENAME(dset) NI_get_attribute(dset->ngr,"filename")
847       /* A safer version than SDSET_FILENAME */
848    #define SDSET_FILENAME_s(dset) SUMA_sdset_filename(dset)
849 
850    /* This macro can return NULL, use it wisely, or use the safer macro */
851    #define SDSET_LABEL(dset) NI_get_attribute(dset->ngr,"label")
852    #define SDSET_LABEL_s(dset) SUMA_sdset_label(dset)
853 
854    /* This macro can return NULL, can't change behavior of SUMA_sdset_id()
855    unless I check usage of SDSET_ID everywhere in the code... */
856    #define SDSET_ID(dset) SUMA_sdset_id(dset)
857    #define SDSET_IDGDOM(dset) \
858             NI_get_attribute(dset->ngr,"geometry_parent_idcode")
859    #define SDSET_IDMDOM(dset) SUMA_sdset_idmdom(dset)
860    #define SDSET_SORTED(dset) ( (!dset || !dset->inel) ? \
861                            NULL:NI_get_attribute(dset->inel,"sorted_node_def") )
862    #define SDSET_IS_SORTED(dset) ( (!dset || !dset->inel || \
863          !NI_get_attribute(dset->inel,"sorted_node_def") || \
864          strcmp(NI_get_attribute(dset->inel,"sorted_node_def"), "Yes") != 0) \
865                                                             ? 0 : 1 )
866    #define SDSET_TYPE_NAME(dset) NI_get_attribute(dset->ngr,"dset_type")
867    #define SDSET_TYPE(dset)   \
868       SUMA_Dset_Type(NI_get_attribute(dset->ngr,"dset_type"))
869    #define SDSET_DAT_LEVEL(dset) \
870       SUMA_sdset_datum_level(dset);
871    #define SDSET_COLCAST(dset, i)   \
872       SUMA_ColType2TypeCast(SUMA_TypeOfDsetColNumb(dset, i))
873    #define SDSET_COLTYPE(dset, i)   \
874       SUMA_TypeOfDsetColNumb(dset, i)
875    #define SDSET_VECLEN(dset) ( (!dset || !dset->dnel) ? -1:dset->dnel->vec_len )
876    #define SDSET_VECALLOC(dset) MAX(SDSET_VECLEN(dset),0)  /* 24 Sep 2021 - RWC */
877    #define SDSET_VEC(dset,iii) dset->dnel->vec[iii]
878    #define SDSET_NVOX SDSET_VECLEN
879    #define SDSET_IS_VOL SUMA_isVolDataset
880    #define SDSET_BRICK_FACTOR SUMA_GetBrickFactor
881    #define SDSET_BRICK_TYPE   SUMA_GetBrickType
882    #define SDSET_ARRAY SDSET_VEC
883    #define SDSET_NODEINDLEN(dset) dset->inel->vec_len
884    #define SDSET_VECNUM(dset) dset->dnel->vec_num
885    #define SDSET_NODEINDNUM(dset) dset->inel->vec_num
886    #define SDSET_VECFILLED(dset) dset->dnel->vec_filled
887    #define SDSET_NODEINDFILLED(dset) dset->inel->vec_filled
888    #define SDSET_NODE_INDEX_COL(dset) ( (!dset || !dset->inel ||  \
889                                          !dset->inel->vec) ?   \
890                                                 NULL:(int*)(dset->inel->vec[0]) )
891    #define SDSET_EDGE_INDEX_COL SDSET_NODE_INDEX_COL
892    #define SDSET_EDGE_P1_INDEX_COL(dset) ( (!dset || !dset->inel ||  \
893                                       !dset->inel->vec || \
894                                       dset->inel->vec_num != 3) ?   \
895                                                 NULL:(int*)(dset->inel->vec[1]) )
896    #define SDSET_EDGE_P2_INDEX_COL(dset) ( (!dset || !dset->inel ||  \
897                                       !dset->inel->vec || \
898                                       dset->inel->vec_num != 3) ?   \
899                                                 NULL:(int*)(dset->inel->vec[2]) )
900    #define SDSET_EDGE_NODE_INDEX_COLS(dset, PE, P1, P2) {\
901       (PE)=(P1)=(P2)=NULL;   \
902       if ( (dset) && (dset->inel) && (dset->inel->vec) && \
903             dset->inel->vec_num ==3 ) { \
904             (PE) = (int*)(dset->inel->vec[0]);  \
905             (P1) = (int*)(dset->inel->vec[1]);  \
906             (P2) = (int*)(dset->inel->vec[2]);  \
907       }  \
908    }
909 
910    #define SDSET_COL(dset, icol) ( (!dset || !dset->dnel || !dset->dnel->vec) \
911                                                  ? NULL:(dset->dnel->vec[icol]) )
912    #define SDSET_MATRIX_SZ0(dset) ( (!(dset) || !(dset)->Aux) ? \
913                                           -1: ((dset)->Aux->matrix_size[0]) )
914    #define SDSET_MATRIX_SZ1(dset) ( (!(dset) || !(dset)->Aux) ? \
915                                           -1: ((dset)->Aux->matrix_size[1]) )
916    #define GDSET_N_SEG_POINTS(dset) ( (!(dset) || !(dset)->Aux) ? \
917                                           -1: ((dset)->Aux->N_seg_nodes) )
918    #define GDSET_N_ALL_POINTS(dset) ( (!(dset) || !(dset)->Aux) ? \
919                                           -1: ((dset)->Aux->N_all_nodes) )
920 #endif
921 
922 #define DSET_MAX_NODE_INDEX(dset, MM) {\
923    double r[2]; int loc[2];   \
924    if (!SUMA_GetDsetNodeIndexColRange( dset, r, loc, 1)) {  \
925       MM = -1; \
926    } else { \
927       MM = (int)r[1];   \
928    }  \
929 }
930 
931 /* Edges are the 'nodes' of datasets */
932 #define GDSET_MAX_EDGE_INDEX DSET_MAX_NODE_INDEX
933 
934 /*!
935    \brief Macros to access commonly used colorplane parameters
936    DO NOT USE COLP_NODEDEF macro inside a loop where the returned
937    value is not to change because it involves a function call (SLOW)
938 */
939 /* Post March 29 04. You can't go frugal and use dset's fields
940 NodeDef might be dynamically changed in the overlay plane */
941 #define COLP_NODEDEF(cop) cop->NodeDef
942 #define COLP_N_NODEDEF(cop) cop->N_NodeDef
943 #ifdef OLD_DSET
944    #define COLP_N_ALLOC(cop) cop->dset_link->nel->vec_len
945 #else
946    #define COLP_N_ALLOC(cop) cop->dset_link->dnel->vec_len
947 #endif
948 /* #define DSET_(dset) NI_get_attribute(dset->nel,"") */
949 
950 static byte NI_GOT;
951 
952 #define NI_SET_STR(ngr, name, val)  {\
953    if (val && val[0] != '\0') NI_set_attribute(ngr, name, val);  \
954    else NI_set_attribute(ngr, name, SUMA_EMPTY_ATTR); \
955 }
956 #define NI_GET_STR(ngr, name, val)  {\
957    char *m_s = NI_get_attribute(ngr, name);  \
958    if (m_s) {  \
959       NI_GOT = 1; \
960       if (strcmp(m_s,SUMA_EMPTY_ATTR) == 0) val[0] = '\0'; else sprintf(val,"%s", m_s); \
961    }  else {   \
962       NI_GOT = 0; \
963       val[0] = '\0'; \
964    }  \
965 }
966 
967 #define NI_GET_STR_CP(ngr, name, val)  {\
968    char *m_s = NI_get_attribute(ngr, name);  \
969    if (m_s) {  \
970       NI_GOT = 1; \
971       if (strcmp(m_s,SUMA_EMPTY_ATTR) == 0) val = NULL; else val = SUMA_copy_string(m_s); \
972    } else { \
973       NI_GOT = 0; val = NULL; \
974    }  \
975 }
976 
977 #define NI_SET_INT(ngr, name, val)  {\
978    char m_stmp[100]; sprintf(m_stmp,"%d", val);   \
979    NI_set_attribute(ngr, name, m_stmp);  \
980 }
981 #define NI_GET_INT(ngr, name, val)  {\
982    char *m_s = NI_get_attribute(ngr, name);  \
983    if (m_s) { NI_GOT = 1; val = atoi(m_s); } else { NI_GOT = 0; val = 0; }\
984 }
985 #define NI_SET_INTv(ngr, name, valv, n) {\
986    char m_stmp[400]={""}; int m_i=0, m_s=0; m_stmp[0] = '\0';\
987    for (m_i=0; m_i<n && m_s < 350; ++m_i) { \
988       sprintf(m_stmp+m_s, " %d", valv[m_i]);   \
989       m_s = strlen(m_stmp);  \
990       if (m_s >= 350) { SUMA_S_Warn("Too long a vector, might get truncated"); }\
991    }\
992    NI_set_attribute(ngr, name, m_stmp);  \
993 }
994 
995 #define NI_GET_INTv(ngr, name, valv, n, verb) {\
996    char *m_s = NI_get_attribute(ngr, name);  \
997    int m_nr, m_i; int *m_iv;  \
998    for (m_i=0; m_i<n; ++m_i) valv[m_i] = 0.0;   \
999    if (m_s) {  \
1000       NI_GOT = 1; \
1001       m_iv = (int *)SUMA_strtol_vec(m_s, n, &m_nr, SUMA_int, NULL); \
1002       if (m_iv) {\
1003          if (!verb) { \
1004             if (m_nr < n) { \
1005                SUMA_S_Warn("Fewer values in field\nProceeding..."); }  \
1006             else  if (m_nr > n) { \
1007                SUMA_S_Warn("More values in field\nProceeding..."); }  \
1008          }  \
1009          for (m_i=0; m_i<SUMA_MIN_PAIR(n, m_nr);++m_i) valv[m_i] = m_iv[m_i];  \
1010          SUMA_free(m_iv);  \
1011       } else {    \
1012          NI_GOT = 1; \
1013          if (verb) SUMA_S_Warn("NULL vec, filling with zeros"); \
1014       }  \
1015    } else { NI_GOT = 0; }  \
1016 }
1017 
1018 #define NI_SET_FLOAT(ngr, name, val)  {\
1019    char m_stmp[100]; sprintf(m_stmp,"%f", val);   \
1020    NI_set_attribute(ngr, name, m_stmp);  \
1021 }
1022 
1023 #define NI_GET_FLOAT(ngr, name, val)  {\
1024    char *m_s = NI_get_attribute(ngr, name);  \
1025    if (m_s) { NI_GOT = 1; val = atof(m_s); } else { NI_GOT = 0; val = 0.0; }\
1026 }
1027 
1028 #define NI_SET_FLOATv(ngr, name, valv, n) {\
1029    char m_stmp[400]; int m_i=0, m_s=0;  m_stmp[0] = '\0';\
1030    for (m_i=0; m_i<n && m_s < 350; ++m_i) { \
1031       sprintf(m_stmp+m_s, " %f", valv[m_i]);   \
1032       m_s = strlen(m_stmp);  \
1033       if (m_s >= 350) { SUMA_S_Warn("Too long a vector, might get truncated"); }\
1034    }\
1035    NI_set_attribute(ngr, name, m_stmp);  \
1036 }
1037 
1038 #define NI_GET_FLOATv(ngr, name, valv, n, verb) {\
1039    char *m_s = NI_get_attribute(ngr, name);  \
1040    int m_nr, m_i; float *m_fv;  \
1041    for (m_i=0; m_i<n; ++m_i) valv[m_i] = 0.0;   \
1042    if (m_s) {  \
1043       NI_GOT = 1; \
1044       m_fv = (float *)SUMA_strtol_vec(m_s, n, &m_nr, SUMA_float, NULL); \
1045       if (m_fv) {\
1046          if (verb) {\
1047             if (m_nr < n) { \
1048                SUMA_S_Warn("Fewer values in field\nProceeding..."); }  \
1049             else if (m_nr > n) { \
1050                SUMA_S_Warn("More values in field\nProceeding..."); }  \
1051          }  \
1052          for (m_i=0; m_i<SUMA_MIN_PAIR(n, m_nr);++m_i) \
1053             valv[m_i] = m_fv[m_i];    \
1054          SUMA_free(m_fv);  \
1055       } else {    \
1056          NI_GOT = 1; \
1057          if (verb) SUMA_S_Warn("NULL vec, filling with zeros"); \
1058       }  \
1059    } else { NI_GOT = 0; }  \
1060 }
1061 
1062 #define NI_SET_DOUBLE(ngr, name, val)  {\
1063    char m_stmp[100]; sprintf(m_stmp,"%f", val);   \
1064    NI_set_attribute(ngr, name, m_stmp);  \
1065 }
1066 
1067 #define NI_GET_DOUBLE(ngr, name, val)  {\
1068    char *m_s = NI_get_attribute(ngr, name);  \
1069    if (m_s) { NI_GOT = 1; val = strtod(m_s,NULL); } else { NI_GOT = 0; val = 0.0; }\
1070 }
1071 
1072 #define NI_SET_DOUBLEv(ngr, name, valv, n) {\
1073    char m_stmp[400]; int m_i=0, m_s=0;  m_stmp[0] = '\0';\
1074    for (m_i=0; m_i<n && m_s < 350; ++m_i) { \
1075       sprintf(m_stmp+m_s, " %f", valv[m_i]);   \
1076       m_s = strlen(m_stmp);  \
1077       if (m_s >= 350) { SUMA_S_Warn("Too long a vector, might get truncated"); }\
1078    }\
1079    NI_set_attribute(ngr, name, m_stmp);  \
1080 }
1081 
1082 #define NI_GET_DOUBLEv(ngr, name, valv, n, verb) {\
1083    char *m_s = NI_get_attribute(ngr, name);  \
1084    int m_nr, m_i; double *m_fv;  \
1085    for (m_i=0; m_i<n; ++m_i) valv[m_i] = 0.0;   \
1086    if (m_s) {  \
1087       NI_GOT = 1; \
1088       m_fv = (double *)SUMA_strtol_vec(m_s, n, &m_nr, SUMA_double, NULL); \
1089       if (m_fv) {\
1090          if (verb) {\
1091             if (m_nr < n) { \
1092                SUMA_S_Warn("Fewer values in field\nProceeding..."); }  \
1093             else if (m_nr > n) { \
1094                SUMA_S_Warn("More values in field\nProceeding..."); }  \
1095          }  \
1096          for (m_i=0; m_i<SUMA_MIN_PAIR(n, m_nr);++m_i) \
1097             valv[m_i] = m_fv[m_i];    \
1098          SUMA_free(m_fv);  \
1099       } else {    \
1100          NI_GOT = 1; \
1101          if (verb) SUMA_S_Warn("NULL vec, filling with zeros"); \
1102       }  \
1103    } else { NI_GOT = 0; }  \
1104 }
1105 
1106 #define NI_SET_PTR(ngr, name, val) {   \
1107    char m_stmp[100]; sprintf(m_stmp,"%p",val);  \
1108    NI_set_attribute(ngr, name, m_stmp);  \
1109 }
1110 
1111 #define NI_GET_PTR(ngr, name, val) {   \
1112    char *m_s = NI_get_attribute(ngr, name);    \
1113    if (m_s) { NI_GOT = 1; sscanf(m_s,"%p", &val);  }\
1114 }
1115 
1116 #define NI_IS_STR_ATTR_EQUAL(ngr, name, stmp) ( (!name || !NI_get_attribute(ngr,name) || !stmp || strcmp(NI_get_attribute(ngr,name), stmp) ) ? 0:1 )
1117 #define NI_IS_STR_ATTR_EMPTY(ngr, name) ( (!name || !NI_get_attribute(ngr,name) || !strlen(NI_get_attribute(ngr,name))  ) ? 0:1 )
1118 
1119 #define NI_YES_ATTR(ngr, name) ( \
1120    (  !name || \
1121       !NI_get_attribute(ngr,name) ||   \
1122       strncmp(SUMA_to_lower(NI_get_attribute(ngr,name)), "y",1) )   \
1123       ? 0:1 )
1124 #define NI_NO_ATTR(ngr, name) ( (!name || !NI_get_attribute(ngr,name) || strncmp(SUMA_to_lower(NI_get_attribute(ngr,name)), "n",1) ) ? 0:1 )
1125 
1126 /*!
1127    NEL_READ macro for reading a NI element from strm
1128    nel (NI_element *) to contain the deed (if null then read failed)
1129    frm the source such as: "file:Test_niml_file"
1130 */
1131 #define NEL_READ(nel, frm) { \
1132    NI_stream m_ns = NULL;  \
1133    {   \
1134       nel = NULL; \
1135       m_ns = NI_stream_open( frm , "r" ) ;   \
1136       if( m_ns == NULL ) {    \
1137          SUMA_SL_Err ("Failed to open stream");  \
1138       } else { \
1139          /* read the element */   \
1140          if (!(nel = NI_read_element( m_ns , 1 )))  { \
1141             SUMA_SL_Err ("Failed to read element");  \
1142          }  \
1143       }  \
1144       /* close the stream */  \
1145       NI_stream_close( m_ns ) ; \
1146    }  \
1147 }
1148 
1149 #define DSET_READ(dset, frm) { \
1150    NI_stream m_ns = NULL;  \
1151    if (dset->ngr || dset->dnel) {   SUMA_SL_Err("dset elements not empty!\nNeed a clean dset"); }  \
1152    else {   \
1153       m_ns = NI_stream_open( frm , "r" ) ;   \
1154       if( m_ns == NULL ) {    \
1155          SUMA_SL_Err ("Failed to open stream");  \
1156       } else { \
1157          /* read the element */   \
1158          if (!(dset->ngr = NI_read_element( m_ns , 1 )))  { \
1159             SUMA_SL_Err ("Failed to read element");  \
1160          } else { \
1161             /* Look for the _data element */ \
1162             if (!(dset->dnel = SUMA_FindDsetDataElement(dset))) {  \
1163                SUMA_SL_Err("Cannot find data element!\nCleaning up.\n");   \
1164                NI_free_element (dset->ngr); dset->ngr = NULL;  \
1165             }  \
1166             dset->inel =  SUMA_FindDsetDatumIndexElement(dset); \
1167          }\
1168       }  \
1169       /* close the stream */  \
1170       NI_stream_close( m_ns ) ; \
1171    }  \
1172 }
1173 
1174 #define DSET_FIND(id) (SUMA_FindDset_s(id, SUMAg_CF->DsetList))
1175 
1176 /*! Write an array to a text file, mcol consecutive values per line.
1177 v is the array
1178 Nel is the total number of values
1179 m is the number of consecutive values to write per line
1180 If you want to have some index before the entries, use SUMA_WRITE_IND_ARRAY_1D*/
1181 #define SUMA_WRITE_ARRAY_1D(v,Nel,m,iname){  \
1182    int m_kkk; \
1183    char *name=(char*)iname;   \
1184    FILE * m_fp=NULL;\
1185    m_fp = (name) ? fopen((name),"w"): fopen("yougavemenoname","w");  \
1186    if (m_fp) { \
1187       fprintf(m_fp,"# Output from %s, %d values (%d per line).", FuncName, Nel, m);  \
1188       for (m_kkk=0; m_kkk<Nel; ++m_kkk) { if (!(m_kkk % m)) fprintf(m_fp,"\n"); fprintf(m_fp,"%f   ", (double)v[m_kkk]); }\
1189       fclose(m_fp); \
1190    }  \
1191 }
1192 #define SUMA_WRITE_INT_ARRAY_1D(v,Nel,m,name){  \
1193    int m_kkk; \
1194    FILE * m_fp=NULL;\
1195    m_fp = (name) ? fopen((name),"w"): fopen("yougavemenoname","w");  \
1196    if (m_fp) { \
1197       fprintf(m_fp,"# Output from %s, %d values (%d per line).", \
1198                      FuncName, Nel, m);  \
1199       for (m_kkk=0; m_kkk<Nel; ++m_kkk) { \
1200          if (!(m_kkk % m)) fprintf(m_fp,"\n"); \
1201          fprintf(m_fp,"%d   ", (int)v[m_kkk]); }\
1202       fclose(m_fp); \
1203    }  \
1204 }
1205 #define SUMA_WRITE_INT_ARRAY_AND_FLAG_1D(v,Nel,m,name,flg){  \
1206    int m_kkk; \
1207    FILE * m_fp=NULL;\
1208    m_fp = (name) ? fopen((name),"w"): fopen("yougavemenoname","w");  \
1209    if (m_fp) { \
1210       fprintf(m_fp,"# Output from %s, %d values (%d per line).", \
1211                      FuncName, Nel, m);  \
1212       for (m_kkk=0; m_kkk<Nel; ++m_kkk) { \
1213          if (!(m_kkk % m)) {  \
1214             if (m_kkk) fprintf(m_fp,"%d   ", flg); \
1215             fprintf(m_fp,"\n"); \
1216          }  \
1217          fprintf(m_fp,"%d   ", (int)v[m_kkk]); }\
1218          fprintf(m_fp,"%d   ", flg); \
1219       fclose(m_fp); \
1220    }  \
1221 }
1222 
1223 /* Just like SUMA_WRITE_ARRAY_1D but ind contains indices
1224 to add at the beginning of each line.
1225 If ind is NULL, then the index will be the line number.
1226 */
1227 #define SUMA_WRITE_IND_ARRAY_1D(v,m_ind,Nel,m,name){  \
1228    int m_kkk, *ind = (int *)m_ind;  \
1229    FILE * m_fp = (name) ? fopen((name),"w"): fopen("yougavemenoidly","w");  \
1230    if (m_fp) { \
1231       fprintf(m_fp,  "# Output from %s, index followed by %d values "\
1232                      "(%d per line).\n", FuncName, Nel, 1);  \
1233       if (!ind) {  \
1234          for (m_kkk=0; m_kkk<Nel; ++m_kkk) { \
1235             if (!(m_kkk % m)) fprintf(m_fp,"\n%d   ", m_kkk/m); \
1236             fprintf(m_fp,"%f   ", (double)v[m_kkk]); }\
1237       } else {\
1238          for (m_kkk=0; m_kkk<Nel; ++m_kkk) { \
1239             if (!(m_kkk % m)) fprintf(m_fp,"\n%d   ", ind[m_kkk/m]); \
1240             fprintf(m_fp,"%f   ", (double)v[m_kkk]); }\
1241       }  \
1242       fclose(m_fp); \
1243    }  \
1244 }
1245 
1246 /*!
1247    NEL_WRITE_TX(nel, strm, suc)
1248    NEL_WRITE_BI(nel, strm, suc)
1249    NEL_WRITE_1D(nel, strm, suc)
1250    NEL_WRITE_1D_PURE(nel, strm, suc)
1251    macros for writing a NI element in  NI_TEXT_MODE, NI_BINARY_MODE  or
1252                                        NI_TEXT_MODE | NI_HEADERSHARP_FLAG which is a la 1D
1253    nel is the NI element
1254    frm is someting like:  "file:Test_write_asc_1D" (for a file output)
1255                            "fd:1" (for stdout)
1256                            or "stderr:" or "stdout:"
1257    suc is a flag for success (1), failure (0)
1258 */
1259 #define NEL_WRITE_TX(nel, frm, suc) NEL_WRITE_TX_ENG(nel, frm, suc, NI_TEXT_MODE)
1260 #define NEL_WRITE_TXH(nel, frm, suc) NEL_WRITE_TX_ENG(nel, frm, suc, (NI_TEXT_MODE | NI_HEADERSHARP_FLAG))
1261 
1262 #define NEL_WRITE_TX_ENG(nel, frm, suc, form) { \
1263    NI_stream m_ns = NULL;  \
1264    suc = 1; \
1265    m_ns = NI_stream_open( frm , "w" ) ;   \
1266    if( m_ns == NULL ) {    \
1267       SUMA_S_Err ("Failed to open stream");  \
1268       suc = 0; \
1269    } else { \
1270       /* write out the element */   \
1271       if (NI_write_element( m_ns , nel , form ) < 0) { \
1272          SUMA_S_Err ("Failed to write element");  \
1273          suc = 0; \
1274       }  \
1275    }  \
1276    /* close the stream */  \
1277    NI_stream_close( m_ns ) ; \
1278 }
1279 
1280 
1281 
1282 #define DSET_WRITE_1D(dset, frm, suc, addindex) { \
1283    NI_stream m_ns = NULL;  \
1284    int m_allnum;  \
1285    suc = 1; \
1286    m_allnum = SUMA_is_AllNumeric_dset(dset);   \
1287    if (!m_allnum) { \
1288       SUMA_SL_Err ("Element cannont be written to 1D format");    \
1289       suc = 0; \
1290    } else {   \
1291       m_ns = NI_stream_open( frm , "w" ) ;   \
1292       if( m_ns == NULL ) {    \
1293          SUMA_SL_Err ("Failed to open stream");  \
1294          suc = 0; \
1295       } else { \
1296          /* write out the element */   \
1297          if (addindex) { \
1298             if (!dset->inel) { SUMA_SL_Err ("No inel in dset! No node indices written!\n"); addindex = 0;}   \
1299             else { NI_insert_column(dset->dnel, dset->inel->vec_typ[0], dset->inel->vec[0], 0);  } \
1300          }  \
1301          if (NI_write_element( m_ns , dset->dnel , NI_TEXT_MODE | NI_HEADERSHARP_FLAG) < 0) { \
1302             SUMA_SL_Err ("Failed to write element");  \
1303             suc = 0; \
1304          }  \
1305          if (addindex) { NI_remove_column(dset->dnel, 0); } \
1306       }  \
1307       /* close the stream */  \
1308       NI_stream_close( m_ns ) ; \
1309    }  \
1310 }
1311 #define DSET_WRITE_1D_PURE(dset, frm, suc, addindex) { \
1312    FILE *m_fid = NULL;  \
1313    int m_ind, m_ival;   \
1314    int m_allnum;  \
1315    suc = 1; \
1316    m_allnum = SUMA_is_AllNumeric_dset(dset);   \
1317    if (!m_allnum) { \
1318       SUMA_SL_Err ("Element cannont be written to 1D format");    \
1319       suc = 0; \
1320    } else {   \
1321       if (!strcmp(frm,"stdout")) m_fid = stdout;   \
1322       else if (!strcmp(frm,"stderr")) m_fid = stderr;   \
1323       else m_fid = fopen(frm,"w"); \
1324       if( m_fid == NULL ) {    \
1325          SUMA_SL_Err ("Failed to open file for output");  \
1326          suc = 0; \
1327       } else { \
1328          if (addindex) { \
1329             if (!dset->inel) { SUMA_SL_Err ("No inel in dset! No node indices written!\n"); addindex = 0;}   \
1330          }  \
1331          if (!addindex) {  \
1332             for (m_ival=0; m_ival<dset->dnel->vec_len; ++m_ival) { \
1333                for (m_ind=0; m_ind<dset->dnel->vec_num; ++m_ind) { \
1334                   fprintf(m_fid,"%f   ", SUMA_GetDsetValInCol2(dset, m_ind, m_ival));  \
1335                }  \
1336                fprintf(m_fid,"\n"); \
1337             }  \
1338          } else { \
1339             int *m_n=(int *)dset->inel->vec[0];  \
1340             for (m_ival=0; m_ival<dset->dnel->vec_len; ++m_ival) { \
1341                fprintf(m_fid,"%d   ", m_n[m_ival]); \
1342                for (m_ind=0; m_ind<dset->dnel->vec_num; ++m_ind) { \
1343                   fprintf(m_fid,"%f   ", SUMA_GetDsetValInCol2(dset, m_ind, m_ival));  \
1344                }  \
1345                fprintf(m_fid,"\n"); \
1346             }  \
1347          }  \
1348          fclose(m_fid); m_fid = NULL;  \
1349       }  \
1350    }\
1351 }
1352 
1353 #define DSET_WRITE_1D_PURE_TRANSPOSE(dset, frm, suc, addindex) { \
1354    FILE *m_fid = NULL;  \
1355    int m_ind, m_ival;   \
1356    int m_allnum;  \
1357    suc = 1; \
1358    m_allnum = SUMA_is_AllNumeric_dset(dset);   \
1359    if (!m_allnum) { \
1360       SUMA_SL_Err ("Element cannont be written to 1D format");    \
1361       suc = 0; \
1362    } else {   \
1363       if (!strcmp(frm,"stdout")) m_fid = stdout;   \
1364       else if (!strcmp(frm,"stderr")) m_fid = stderr;   \
1365       else m_fid = fopen(frm,"w"); \
1366       if( m_fid == NULL ) {    \
1367          SUMA_SL_Err ("Failed to open file for output");  \
1368          suc = 0; \
1369       } else { \
1370          if (addindex) { \
1371             if (!dset->inel) { SUMA_SL_Err ("No inel in dset! No node indices written!\n"); addindex = 0;}   \
1372          }  \
1373          if (!addindex) {  \
1374             for (m_ind=0; m_ind<dset->dnel->vec_num; ++m_ind) { \
1375                for (m_ival=0; m_ival<dset->dnel->vec_len; ++m_ival) { \
1376                   fprintf(m_fid,"%f   ", SUMA_GetDsetValInCol2(dset, m_ind, m_ival));  \
1377                }  \
1378                fprintf(m_fid,"\n"); \
1379             }  \
1380          } else { \
1381             int *m_n=(int *)dset->inel->vec[0];  \
1382             for (m_ind=0; m_ind<dset->dnel->vec_num; ++m_ind) { \
1383                for (m_ival=0; m_ival<dset->dnel->vec_len; ++m_ival) { \
1384                fprintf(m_fid,"%d   ", m_n[m_ival]); \
1385                   fprintf(m_fid,"%f   ", \
1386                            SUMA_GetDsetValInCol2(dset, m_ind, m_ival));  \
1387                }  \
1388                fprintf(m_fid,"\n"); \
1389             }  \
1390          }  \
1391          fclose(m_fid); m_fid = NULL;  \
1392       }  \
1393    }\
1394 }
1395 
1396 #define NEL_WRITE_1D(nel, frm, suc) { \
1397    NI_stream m_ns = NULL;  \
1398    int m_tt = NI_element_type((void*)nel) ; \
1399    int m_allnum;  \
1400    suc = 1; \
1401    if (m_tt == NI_GROUP_TYPE) { \
1402       m_allnum = 0; \
1403       SUMA_SL_Err ("Group, use DSET_WRITE_1D_PURE"); }/* USE DSET_WRITE_1D */   \
1404    else m_allnum = SUMA_is_AllNumeric_nel(nel);   \
1405    if (!m_allnum) { \
1406       SUMA_SL_Err ("Element cannont be written to 1D format");    \
1407       suc = 0; \
1408    } else {   \
1409       m_ns = NI_stream_open( frm , "w" ) ;   \
1410       if( m_ns == NULL ) {    \
1411          SUMA_SL_Err ("Failed to open stream");  \
1412          suc = 0; \
1413       } else { \
1414          /* write out the element */   \
1415          if (NI_write_element( m_ns , nel , \
1416                                NI_TEXT_MODE | NI_HEADERSHARP_FLAG) < 0) { \
1417             SUMA_SL_Err ("Failed to write element");  \
1418             suc = 0; \
1419          }  \
1420       }  \
1421       /* close the stream */  \
1422       NI_stream_close( m_ns ) ; \
1423    }  \
1424 }
1425 
1426 /*!
1427    NEL_WRITE* macros are left for the record, they should not be used
1428 */
1429 #define NEL_WRITE_1D_PURE(nel, frm, suc) { \
1430    FILE *m_fid = NULL;  \
1431    int m_ind, m_ival;   \
1432    int m_tt = NI_element_type((void*)nel) ; \
1433    int m_allnum;  \
1434    suc = 1; \
1435    if (m_tt == NI_GROUP_TYPE) { \
1436       m_allnum = 0;  \
1437       SUMA_SL_Err ("Group, use DSET_WRITE_1D_PURE"); } /* USE DSET_WRITE_1D */  \
1438    else m_allnum = SUMA_is_AllNumeric_nel(nel);   \
1439    if (!m_allnum) { \
1440       SUMA_SL_Err ("Element cannont be written to 1D format");    \
1441       suc = 0; \
1442    } else {   \
1443       m_fid = fopen(frm,"w"); \
1444       if( m_fid == NULL ) {    \
1445          SUMA_SL_Err ("Failed to open file for output");  \
1446          suc = 0; \
1447       } else { \
1448          for (m_ival=0; m_ival<nel->vec_len; ++m_ival) { \
1449             for (m_ind=0; m_ind<nel->vec_num; ++m_ind) { \
1450                fprintf(m_fid,"%f   ", SUMA_GetValInCol2(nel, m_ind, m_ival));  \
1451             }  \
1452             fprintf(m_fid,"\n"); \
1453          }  \
1454          fclose(m_fid); m_fid = NULL;  \
1455       }  \
1456    }\
1457 }
1458 
1459 #define NEL_WRITE_BI(nel, frm, suc) { \
1460    NI_stream m_ns = NULL;  \
1461    suc = 1; \
1462    m_ns = NI_stream_open( frm , "w" ) ;   \
1463    if( m_ns == NULL ) {    \
1464       SUMA_SL_Err ("Failed to open stream");  \
1465       suc = 0; \
1466    } else { \
1467       /* write out the element */   \
1468       if (NI_write_element( m_ns , nel , NI_BINARY_MODE) < 0) { \
1469          SUMA_SL_Err ("Failed to write element");  \
1470          suc = 0; \
1471       }  \
1472    }  \
1473    /* close the stream */  \
1474    NI_stream_close( m_ns ) ; \
1475 }
1476 
1477 /*!
1478    get a string positioned in column col, row row in NI_element * nel.
1479    str is a copy of the pointer to that string and must not be freed
1480 */
1481 #define SUMA_NEL_GET_STRING(nel, row, col, str) {\
1482    char **m_rc;   \
1483    m_rc = (char **)(nel)->vec[(col)]; \
1484    str = m_rc[(row)];\
1485 }
1486 /*!
1487    replace a string positioned in column col, row row in NI_element * nel.
1488 */
1489 #define SUMA_NEL_REPLACE_STRING(nel, row, col, str) {\
1490    char **m_rc;   \
1491    m_rc = (char **)(nel)->vec[(col)]; \
1492    if (m_rc[(row)]) NI_free(m_rc[(row)]); \
1493    m_rc[(row)] = NULL;\
1494    if (str) { \
1495       m_rc[(row)] = (char*)NI_malloc(char, (strlen((str))+1)*sizeof(char));\
1496       strcpy( m_rc[(row)], str );   \
1497    }  \
1498 }
1499 
1500 /*!
1501    \brief A macro to be run from main() before writing a dset.
1502    Changes a dset's ID, label (using prefix) and history
1503 */
1504 #define SUMA_NEWDSET_ID_LABEL(dset, prefix) {\
1505    if (dset) { \
1506       if (!SUMA_NewDsetID (dset))  { \
1507          SUMA_SL_Err("Failed in SUMA_NewDsetID, proceeding..."); }  \
1508       if (!SUMA_LabelDset(dset, prefix)) { \
1509          SUMA_SL_Err("Failed in SUMA_LabelDset, proceeding..."); }  \
1510    } else {\
1511       SUMA_SL_Err("NULL dset");  \
1512    }  \
1513 }
1514 
1515 #define SUMA_NEWDSET_ID_LABEL_HIST(dset, prefix) {\
1516    if (dset) { \
1517       SUMA_NEWDSET_ID_LABEL(dset, prefix);   \
1518       if (!SUMA_AddNgrHist (dset->ngr, FuncName, argc, argv)) { \
1519          SUMA_SL_Err("Failed in SUMA_AddNgrHist, proceeding..."); } \
1520    } else {\
1521       SUMA_SL_Err("NULL dset");  \
1522    }  \
1523 }
1524 
1525 /*! A macro to transport common attributes when
1526     copying columns from one dset to another.
1527     Do not include in ATR_LIST here, any of
1528     HISTORY_NOTE (this should be done by appending old history separately)
1529     COLMS_LABELS
1530     COLMS_TYPES
1531     COLMS_RANGE as these are handled at the moment of column creation
1532 */
1533 #define SUMA_COPY_DSET_COL_ATTRIBUTES(odset, ndset, io, in) {   \
1534    static char *m_ATR_LIST[64] = { \
1535       "COLMS_STATSYM", "FDRCURVE",  \
1536        NULL }; \
1537    if (!SUMA_CopyDsetAttributes (odset, ndset, m_ATR_LIST, io, in)) {   \
1538       SUMA_S_Err("Failed to copy dset attributes");   \
1539    }  \
1540 }
1541 #define SUMA_COPY_DSET_ALL_COL_ATTRIBUTES(odset, ndset) {   \
1542    int m_i=-1;\
1543    if (SDSET_VECNUM(odset) != SDSET_VECNUM(ndset)) {\
1544       SUMA_S_Err("Mismatch in number of columns");   \
1545    } \
1546    for (m_i=0; m_i<SDSET_VECNUM(dset); ++m_i) { \
1547       SUMA_COPY_DSET_COL_ATTRIBUTES(odset, ndset, m_i, m_i);   \
1548    }  \
1549 }
1550 
1551 #define SUMA_COPY_DSETWIDE_ATTRIBUTES(odset, ndset) {   \
1552    static char *m_ATR_LIST[64] = { \
1553       "TR",  \
1554       "AFNI_labeltable",   \
1555        NULL }; \
1556    if (!SUMA_CopyDsetAttributes (odset, ndset, m_ATR_LIST, -1, -1)) {   \
1557       SUMA_S_Err("Failed to copy dset attributes");   \
1558    }  \
1559 }
1560 
1561 /*!
1562    A typical check on the output status of a selected prefix for
1563    surface datasets
1564 */
1565 #define SUMA_CHECK_OUTPUT_SDSET_STATUS(Opref, InName, oform, pre, app, exists) {\
1566    char *ooo = SUMA_OutputDsetFileStatus(Opref, InName, \
1567                                           &(oform), pre, app, &(exists)); \
1568    if (exists && !THD_ok_overwrite()) {   \
1569       SUMA_S_Errv("Output file %s already exists.\n"  \
1570                   "Pick another prefix or add -overwrite\n", ooo);   \
1571       exit(1); \
1572    }  \
1573    if (ooo) SUMA_free(ooo); ooo=NULL;\
1574 }
1575 
1576 
1577 #define SUMA_MAX_OPEN_DX_FIELD_COMPONENTS 500
1578 #define SUMA_MAX_OPEN_DX_FIELD_ATTRIBUTES 500
1579 #define SUMA_MAX_OPEN_DX_OBJECTS  500
1580 
1581 typedef struct {
1582    int rank;
1583    int shape;
1584    int items;
1585    int bad_data;
1586    char *type;
1587    char *object;
1588    char *class;
1589    char *data;
1590    char *data_off;
1591    int data_format;
1592    void *datap;
1593    int n_comp;
1594    char *comp_name[SUMA_MAX_OPEN_DX_FIELD_COMPONENTS];
1595    char *comp_value[SUMA_MAX_OPEN_DX_FIELD_COMPONENTS];
1596    int n_attr;
1597    char *attr_name[SUMA_MAX_OPEN_DX_FIELD_ATTRIBUTES];
1598    char *attr_string[SUMA_MAX_OPEN_DX_FIELD_ATTRIBUTES];
1599    int *counts;
1600    int n_counts;
1601    float *delta;
1602    int n_delta;
1603    float *origin;
1604    int n_origin;
1605 } SUMA_OPEN_DX_STRUCT;
1606 
1607 #define SUMA_OK_OPENDX_DATA_TYPE(tp) ( (  tp == SUMA_int || \
1608                                           tp == SUMA_float ||  \
1609                                           tp == SUMA_double || \
1610                                           tp == SUMA_byte )   \
1611                                            ? 1 : 0 )
1612 
1613 #define SUMA_NCOL_OPENDX(dx) ( ( ( (dx)->shape == 0 ) ? 1 : ((dx)->shape) ) )
1614 char *SUMA_getcwd(void);
1615 void SUMA_FreeErrLog ( void *data);
1616 void SUMA_PushErrLog(char *macroname, char *msg, char *fname);
1617 DListElmt* SUMA_PopErrLog(DListElmt *eldone);
1618 void WorkErrLog_ns(void);
1619 
1620 NI_element *SUMA_FindDsetDataElement(SUMA_DSET *dset);
1621 NI_element *SUMA_FindGDsetNodeListElement(SUMA_DSET *dset);
1622 NI_element *SUMA_AddGDsetNodeListElement(SUMA_DSET *dset,
1623                                          int *I, float *X, float *Y, float *Z,
1624                                          char **names, int *cln, float *cols,
1625                                          int N_Node);
1626 NI_element *SUMA_FindDsetDatumIndexElement(SUMA_DSET *dset);
1627 NI_element *SUMA_FindSDsetNodeIndexElement(SUMA_DSET *dset);
1628 NI_element *SUMA_FindGDsetEdgeIndexElement(SUMA_DSET *dset);
1629 NI_element *SUMA_FindDsetAttributeElement(SUMA_DSET *dset, char *attname);
1630 NI_element *SUMA_FindNgrAttributeElement(NI_group *ngr, char *attname);
1631 NI_element *SUMA_FindNgrDataElement(NI_group *ngr, char *nelname,
1632                                     char *typename);
1633 float SUMA_LatestVersionNumber(void);
1634 int SUMA_IcoNums(int depth, byte bin, char what);
1635 char * SUMA_Dset_Type_Name (SUMA_DSET_TYPE tp);
1636 SUMA_DSET_TYPE SUMA_Dset_Type (char *Name);
1637 char * SUMA_Col_Type_Name (SUMA_COL_TYPE tp);
1638 SUMA_COL_TYPE SUMA_Col_Type (char *Name);
1639 char * SUMA_AttrOfDsetColNumb(SUMA_DSET *dset, int ind);
1640 SUMA_COL_TYPE SUMA_TypeOfDsetColNumb(SUMA_DSET *dset, int ind);
1641 SUMA_COL_TYPE SUMA_TypeOfColNumb(NI_element *nel, int ind) ;
1642 SUMA_VARTYPE SUMA_ColType2TypeCast (SUMA_COL_TYPE ctp);
1643 SUMA_Boolean SUMA_isSameDsetColTypes(SUMA_DSET *dset1, SUMA_DSET *dset2);
1644 int SUMA_ShowNel (void *nel);
1645 char *SUMA_NI_nel_Info (NI_element *nel, int detail);
1646 
1647 void SUMA_allow_nel_use(int al);
1648 int SUMA_AddDsetIndexCol(SUMA_DSET *dset, int *icolu, int *icolp1, int *icolp2);
1649 int SUMA_AddGDsetNelXYZCol ( SUMA_DSET *dset, char *col_label,
1650                                SUMA_COL_TYPE ctp, void *col,
1651                                void *col_attr, int stride);
1652 int SUMA_AddDsetNelIndexCol ( SUMA_DSET *dset, char *col_label,
1653                                SUMA_COL_TYPE ctp, void *col,
1654                                void *col_attr, int stride);
1655 int SUMA_AddDsetNelCol ( SUMA_DSET *dset, char *col_label,
1656                      SUMA_COL_TYPE ctp, void *col,
1657                      void *col_attr, int stride);
1658 int SUMA_InsertDsetNelCol ( SUMA_DSET *dset, char *col_label,
1659                      SUMA_COL_TYPE ctp, void *col,
1660                      void *col_attr, int stride, int icol);
1661 int SUMA_AddNelCol ( NI_element *nel, char *col_label,
1662                      SUMA_COL_TYPE ctp, void *col,
1663                      void *col_attr, int stride);
1664 int SUMA_AddDsetColAttr (SUMA_DSET *dset, char *col_label,
1665                      SUMA_COL_TYPE ctp, void *col_attr,
1666                      int col_index, int insert_mode);
1667 int SUMA_AddDsetNodeIndexColAttr (SUMA_DSET *dset, char *col_label,
1668                      SUMA_COL_TYPE ctp, void *col_attr );
1669 int SUMA_AddGDsetNodeXYZColAttr (SUMA_DSET *dset, char *col_label,
1670                                  SUMA_COL_TYPE ctp, void *col_attr);
1671 int SUMA_AddColAttr (NI_element *nel, char *col_label,
1672                      SUMA_COL_TYPE ctp, void *col_attr, int col_index);
1673 SUMA_Boolean SUMA_isMultiColumnAttr(NI_element *nel);
1674 SUMA_Boolean SUMA_isSingleColumnAttr(NI_element *nel, int *icolb, char *rtname);
1675 SUMA_Boolean SUMA_isDsetwideColumnAttr(NI_element *nel);
1676 SUMA_Boolean SUMA_isDsetNelAttr(NI_element *nel);
1677 char * SUMA_CreateDsetColRangeCompString( SUMA_DSET *dset, int col_index,
1678                                           SUMA_COL_TYPE ctp);
1679 int SUMA_UpdateDsetColRange(SUMA_DSET *dset, int icol);
1680 int SUMA_UpdateDsetColLabel(SUMA_DSET *dset, int icol, char *label);
1681 char * SUMA_GetDsetColStringAttr( SUMA_DSET *dset, int col_index,
1682                                     char *attrname);
1683 char * SUMA_GetNgrColStringAttr( NI_group *ngr, int col_index,
1684                                  char *attrname);
1685 SUMA_Boolean SUMA_ParseAttrName(NI_element *nel, int *tp,
1686                                  int *icol, char *rtname);
1687 SUMA_Boolean SUMA_CopyDsetAttributes ( SUMA_DSET *src, SUMA_DSET *dest,
1688                                        char **attrlist,
1689                                        int isrc, int idest );
1690 
1691 /* A quick way to check graphinity. Use SUMA_isGraphDset for safety */
1692 #define SUMA_isGraphDset_fast(dset) ( ((dset)->Aux->isGraph==GRAPH_DSET) )
1693 #define SUMA_isTractDset_fast(dset) ( ((dset)->Aux->isGraph==TRACT_DSET) )
1694 #define SUMA_isCIFTIDset_fast(dset) ( ((dset)->Aux->isGraph==CIFTI_DSET) )
1695 #define SUMA_isMD_Dset_fast(dset) ( ((dset)->Aux->isGraph==MD_DSET) )
1696 byte SUMA_isGraphDset(SUMA_DSET *dset);
1697 byte SUMA_isGraphDsetNgr(NI_group *ngr);
1698 byte SUMA_isTractDset(SUMA_DSET *dset);
1699 byte SUMA_isTractDsetNgr(NI_group *ngr);
1700 byte SUMA_isMD_Dset(SUMA_DSET *dset);
1701 byte SUMA_isCIFTIDset(SUMA_DSET *dset);
1702 byte SUMA_isCIFTIDsetNgr(NI_group *ngr);
1703 SUMA_Boolean SUMA_Add_Dset_Aux(SUMA_DSET *dset);
1704 SUMA_Boolean SUMA_NewDsetGrp (SUMA_DSET *dset, SUMA_DSET_TYPE dtp,
1705                            char* MeshParent_idcode,
1706                           char * geometry_parent_idcode,
1707                           int N_el, int N_eel,
1708                           char *filename, char *thisidcode);
1709 NI_element * SUMA_NewNel (SUMA_DSET_TYPE dtp, char* MeshParent_idcode,
1710                           char * geometry_parent_idcode, int N_el,
1711                           char *name, char *thisidcode);
1712 SUMA_DSET_FORMAT SUMA_Dset_Format (char *Name);
1713 long SUMA_sdset_dnel_size(SUMA_DSET *dset);
1714 char * SUMA_Dset_Format_Name (SUMA_DSET_FORMAT fr);
1715 char *SUMA_HistString (char *CallingFunc, int N_arg, char **arg, char *sold);
1716 char * SUMA_GetNgrHist(NI_group *ngr);
1717 int SUMA_AddNgrHist(NI_group *ngr, char *CallingFunc, int N_arg, char **arg);
1718 int SUMA_RemoveNgrHist(NI_group *ngr);
1719 int SUMA_RemoveDsetHist(SUMA_DSET *dset);
1720 int SUMA_AddNelHist(NI_element *nel, char *CallingFunc, int N_arg, char **arg);
1721 void SUMA_FreeDset(void *dset);
1722 SUMA_Boolean SUMA_FreeDsetContent (SUMA_DSET *dset);
1723 SUMA_DSET * SUMA_FindDset_ns (char *idcode_str, DList *DsetList);
1724 SUMA_DSET * SUMA_FindDset2_ns (char *idcode_str, DList *DsetList, char *itype);
1725 DListElmt * SUMA_FindDsetEl_ns (char *idcode, DList *DsetList);
1726 SUMA_DSET * SUMA_FindDset_eng (char *idcode_str, DList *DsetList,
1727                                  DListElmt **elp, char *itype);
1728 char *SUMA_DsetInfo (SUMA_DSET *dset, int detail);
1729 void SUMA_ShowDset (SUMA_DSET *dset, int detail, FILE *out);
1730 char *SUMA_ShowMeSome (void *dt, SUMA_VARTYPE tp, int N_dt,
1731                        int mxshow, char *title);
1732 SUMA_DSET * SUMA_NewDsetPointer(void);
1733 SUMA_DSET * SUMA_CreateDsetPointer (
1734                               char *name,
1735                               SUMA_DSET_TYPE tp,
1736                               char *idcode_str,
1737                               char *domain_idcode_str,
1738                               int N_Alloc);
1739 SUMA_DSET * SUMA_CreateFullDsetPointer (
1740                               char *filename, SUMA_DSET_TYPE tp,
1741                               char *idcode,
1742                               char *domain_idcode,
1743                               int N_Alloc);
1744 int SUMA_InsertDsetPointer (SUMA_DSET **dset, DList *DsetList, int replace);
1745 int SUMA_DeleteDsetPointer (SUMA_DSET **dsetp, DList *DsetList);
1746 void * SUMA_GetCx(char *idcode_str, DList *DsetList, int ReturnDsetPointer) ;
1747 #if 0
1748 SUMA_DSET *SUMA_LinkToDset(SUMA_DSET *dset);
1749 SUMA_DSET *SUMA_UnlinkFromDset(SUMA_DSET *dset);
1750 #endif
1751 void *SUMA_LinkToPointer(void *ptr);
1752 void *SUMA_UnlinkFromPointer(void *ptr);
1753 int * SUMA_GetNodeDef(SUMA_DSET *dset);
1754 int SUMA_GetNodeDefColIndex(SUMA_DSET *dset);
1755 int SUMA_FillDsetNelCol (SUMA_DSET *dset, char *col_label,
1756                      SUMA_COL_TYPE ctp, void *col,
1757                      void *col_attr, int stride);
1758 int SUMA_FillDsetNelNodeIndexCol (SUMA_DSET *dset, char *col_label,
1759                      SUMA_COL_TYPE ctp, void *col,
1760                      void *col_attr, int stride);
1761 SUMA_Boolean SUMA_PopulateDsetNodeIndexNel(SUMA_DSET *dset, int verb);
1762 int SUMA_FillNelCol (NI_element *nel, char *col_label,
1763                      SUMA_COL_TYPE ctp, void *col,
1764                      void *col_attr, int stride);
1765 int *SUMA_GetDsetColIndex (SUMA_DSET *dset, SUMA_COL_TYPE tp, int *N_i);
1766 int *SUMA_GetColIndex (NI_element *nel, SUMA_COL_TYPE tp, int *N_i);
1767 int SUMA_Float2DsetCol (SUMA_DSET *dset, int ind, float *V, int FilledOnly,
1768                         byte *replacemask);
1769 int SUMA_Vec2DsetCol (SUMA_DSET *dset, int ind,
1770                         void *V, SUMA_VARTYPE Vtp,
1771                         int FilledOnly,
1772                         byte *replacemask);
1773 int * SUMA_DsetCol2Int (SUMA_DSET *dset, int ind, int FilledOnly);
1774 float * SUMA_DsetCol2Float (SUMA_DSET *dset, int ind, int FilledOnly);
1775 double * SUMA_DsetCol2Double (SUMA_DSET *dset, int ind, int FilledOnly);
1776 float * SUMA_Col2Float (NI_element *nel, int ind, int FilledOnly);
1777 SUMA_Boolean SUMA_SetUniqueValsAttr(SUMA_DSET *dset, int icol, byte replace);
1778 NI_element * SUMA_GetUniqueValsAttr(SUMA_DSET *dset, int icol);
1779 NI_element * SUMA_GetUniqueIndicesAttr(SUMA_DSET *dset, int iindex);
1780 int * SUMA_GetUniqueIndicesVec(SUMA_DSET *dset, int iindex);
1781 int * SUMA_GetDatasetDimensions(SUMA_DSET *dset);
1782 float * SUMA_GetDatasetFactors(SUMA_DSET *dset);
1783 MRI_TYPE SUMA_GetBrickType(SUMA_DSET *dset, int ii);
1784 float SUMA_GetBrickFactor(SUMA_DSET *dset, int ii);
1785 float * SUMA_GetDatasetI2X(SUMA_DSET *dset, float M[4][4]);
1786 int SUMA_isVolDataset(SUMA_DSET *dset);
1787 NI_element * SUMA_GetAtlasLabelTable(SUMA_DSET *dset);
1788 NI_element * SUMA_GetValueLabelTable(SUMA_DSET *dset);
1789 SUMA_Boolean SUMA_SetUniqueIndicesAttr(SUMA_DSET *dset, byte replace);
1790 int SUMA_GetDsetColRange(SUMA_DSET *dset, int col_index,
1791                          double range[2], int loc[2]);
1792 int SUMA_GetDsetNodeIndexColRange(SUMA_DSET *dset,
1793                                   double range[2], int loc[2], int addifmissing);
1794 int SUMA_GetColRange(NI_element *nel, int col_index,
1795                      double range[2], int loc[2]);
1796 int SUMA_AddGenDsetColAttr (SUMA_DSET *dset, SUMA_COL_TYPE ctp, void *col,
1797                             int stride, int col_index, int insert_mode);
1798 int SUMA_AddGenDsetNodeIndexColAttr (SUMA_DSET *dset, SUMA_COL_TYPE ctp,
1799                                      void *col, int stride) ;
1800 int SUMA_AddGenGDsetNodeXYZColAttr (SUMA_DSET *dset, SUMA_COL_TYPE ctp,
1801                                      void *col, int stride) ;
1802 int SUMA_AddGenColAttr (NI_element *nel, SUMA_COL_TYPE ctp, void *col,
1803                         int stride, int col_index);
1804 SUMA_DSET *SUMA_LoadNimlDset (char *Name, int verb);
1805 SUMA_DSET *SUMA_LoadGIFTIDset (char *Name, int verb);
1806 SUMA_DSET *SUMA_LoadDset_eng (char *Name, SUMA_DSET_FORMAT *form, int verb);
1807 SUMA_DSET *SUMA_LoadDset_ns (char *Name, SUMA_DSET_FORMAT *form, int verb);
1808 SUMA_DSET *SUMA_Load1DDset_eng (char *Name, int verb);
1809 SUMA_DSET *SUMA_Load1DDset_ns (char *Name, int verb);
1810 SUMA_DSET *SUMA_LoadDXDset_eng (char *Name, int verb);
1811 SUMA_DSET *SUMA_LoadDXDset_ns (char *Name, int verb);
1812 char *SUMA_RemoveDsetExtension_ns (char*Name, SUMA_DSET_FORMAT form);
1813 char *SUMA_RemoveDsetExtension_eng (char*Name, SUMA_DSET_FORMAT *form);
1814 char * SUMA_WriteDset_ns (char *Name, SUMA_DSET *dset, SUMA_DSET_FORMAT form,
1815                           int overwrite, int verb);
1816 int SUMA_WriteDset_NameCheck_ns (char *Name, SUMA_DSET *dset,
1817                                  SUMA_DSET_FORMAT form, int verb,
1818                                  char **NameOutp);
1819 int SUMA_WriteDset_NameCheck_eng (char *Name, SUMA_DSET *dset,
1820                                   SUMA_DSET_FORMAT form, int verb,
1821                                   char **NameOutp);
1822 char * SUMA_WriteDset_eng (char *Name, SUMA_DSET *dset, SUMA_DSET_FORMAT form,
1823                            int overwrite, int verb, int rename_autoid);
1824 SUMA_DSET * SUMA_far2dset_eng( char *FullName, char *dset_id, char *dom_id,
1825                                  float **farp, int vec_len, int vec_num,
1826                                  int ptr_cpy);
1827 SUMA_DSET * SUMA_far2dset_ns( char *FullName, char *dset_id, char *dom_id,
1828                                  float **farp, int vec_len, int vec_num,
1829                                  int ptr_cpy);
1830 SUMA_DSET * SUMA_iar2dset_eng( char *FullName, char *dset_id, char *dom_id,
1831                                  int **farp, int vec_len, int vec_num,
1832                                  int ptr_cpy);
1833 SUMA_DSET * SUMA_iar2dset_ns( char *FullName, char *dset_id, char *dom_id,
1834                                  int **farp, int vec_len, int vec_num,
1835                                  int ptr_cpy);
1836 int SUMA_is_AllNumeric_dset(SUMA_DSET *dset);
1837 int SUMA_dset_to_Label_dset(SUMA_DSET *dset);
1838 int SUMA_is_Label_dset(SUMA_DSET *dset, NI_group **NIcmap);
1839 int SUMA_is_Label_dset_col(SUMA_DSET *dset, int icol);
1840 int SUMA_is_Phase_dset(SUMA_DSET *dset);
1841 int SUMA_is_RetinoAngle_dset(SUMA_DSET *dset);
1842 int SUMA_is_VFR_dset(SUMA_DSET *dset);
1843 NI_group *SUMA_NICmapToNICmap(NI_group *NIcmap);
1844 int * SUMA_UniqueValuesInLabelDset(SUMA_DSET *dset, int *N_unq);
1845 int SUMA_is_AllConsistentNumeric_dset(SUMA_DSET *dset, SUMA_VARTYPE *vtpp);
1846 int SUMA_GetConsistentColType_dset(SUMA_DSET *dset);
1847 int SUMA_is_AllConsistentColType_dset(SUMA_DSET *dset, SUMA_COL_TYPE ctpi);
1848 int SUMA_is_AllConsistentCastType_dset(SUMA_DSET *dset, int typecast);
1849 int SUMA_is_AllNumeric_ngr(NI_group *ngr) ;
1850 int SUMA_is_AllNumeric_nel(NI_element *nel);
1851 int SUMA_is_TimeSeries_dset(SUMA_DSET *dset, double *TRp);
1852 SUMA_Boolean SUMA_SetDsetTR(SUMA_DSET *dset, double TR);
1853 SUMA_Boolean SUMA_NewDsetID (SUMA_DSET *dset);
1854 SUMA_Boolean SUMA_NewDsetID2 (SUMA_DSET *dset, char *str);
1855 char *SUMA_DsetColStringAttrCopy(SUMA_DSET *dset, int i,
1856                                  int addcolnum, char *attrname);
1857 char *SUMA_DsetColLabel(SUMA_DSET *dset, int i);
1858 char *SUMA_DsetColLabelCopy(SUMA_DSET *dset, int i, int addcolnum);
1859 int SUMA_FindDsetColLabeled(SUMA_DSET *dset, char *label);
1860 int SUMA_FindNelColLabeled(NI_element *nelb, char *label);
1861 char **SUMA_AllDsetColLabels(SUMA_DSET *dset);
1862 char **SUMA_FreeAllDsetColLabels(char **);
1863 char *SUMA_ColLabelCopy(NI_element *nel, int i, int addcolnum);
1864 int SUMA_FloatScanDset ( SUMA_DSET *odset, int doNan, int doInf,
1865                          int zeroout, int fixrange);
1866 SUMA_Boolean SUMA_Reset_NodeIndex_Element(SUMA_DSET *dset, NI_element **inel);
1867 SUMA_DSET * SUMA_PaddedCopyofDset ( SUMA_DSET *odset, int MaxNodeIndex );
1868 SUMA_DSET * SUMA_MaskedCopyofDset(SUMA_DSET *odset,
1869                                   byte *rowmask, byte *colmask,
1870                                   int masked_only, int keep_node_index);
1871 SUMA_DSET *SUMA_CoercedCopyofDset( SUMA_DSET *odset, SUMA_VARTYPE vtp,
1872                                    byte *colmask);
1873 SUMA_DSET * SUMA_MaskedByOrderedNodeIndexCopyofDset(
1874       SUMA_DSET *odset, int *indexlist,
1875       int N_indexlist, byte *colmask,
1876       int masked_only, int keep_node_index);
1877 SUMA_DSET * SUMA_MaskedByNodeIndexCopyofDset(SUMA_DSET *odset, int *indexlist,
1878                      int N_indexlist, byte *colmask,
1879                      int masked_only, int keep_node_index);
1880 SUMA_DSET * SUMA_VcatDset(SUMA_DSET *odset,
1881                            byte *rowmask, byte *colmask,
1882                            int masked_only, int keep_node_index);
1883 SUMA_Boolean SUMA_Append_Copy_Part_Column(void *col, NI_rowtype *rt, int N_col,
1884                                  byte *rowmask, int masked_only,
1885                                  void **appendhere, int *append_rowtype_code,
1886                                  int *n_inappendhere);
1887 void *SUMA_Copy_Part_Column(void *col,  NI_rowtype *rt, int N_col,
1888                             byte *rowmask, int masked_only, int *n_incopy);
1889 char* SUMA_sdset_id(SUMA_DSET *dset);
1890 char *SUMA_sdset_label(SUMA_DSET *dset);
1891 char *SUMA_sdset_filename(SUMA_DSET *dset);
1892 char* SUMA_sdset_idmdom(SUMA_DSET *dset);
1893 char *SUMA_Dset_orcode(SUMA_DSET *dset);
1894 SUMA_DATUM_LEVEL SUMA_sdset_datum_level(SUMA_DSET *dset);
1895 SUMA_Boolean SUMA_sdset_set_datum_level(SUMA_DSET *dset, SUMA_DATUM_LEVEL lvl);
1896 NI_group *SUMA_oDsetNel2nDsetNgr(NI_element *nel);
1897 void SUMA_SetParent_DsetToLoad(char *parent);
1898 float *SUMA_Load1D_eng (char *oName, int *ncol, int *nrow, int RowMajor, int verb);
1899 double *SUMA_LoadDouble1D_eng (char *oName, int *ncol, int *nrow, int RowMajor, int verb);
1900 complex *SUMA_LoadComplex1D_eng (char *oName, int *ncol, int *nrow, int RowMajor, int verb);
1901 float *SUMA_Load1D_ns (char *oName, int *ncol, int *nrow, int RowMajor, int verb);
1902 SUMA_OPEN_DX_STRUCT **SUMA_OpenDX_Read(char *fname, int *nobj);
1903 void SUMA_Show_OpenDX_Struct(SUMA_OPEN_DX_STRUCT **dxv, int N_dxv, FILE *out);
1904 SUMA_OPEN_DX_STRUCT *SUMA_Free_OpenDX_Struct(SUMA_OPEN_DX_STRUCT *dx);
1905 SUMA_OPEN_DX_STRUCT *SUMA_Alloc_OpenDX_Struct(void);
1906 void * SUMA_OpenDx_Object_Header_Field(char *op, int nchar, const char *attr,
1907                                        char **op_end);
1908 SUMA_Boolean SUMA_OpenDx_Object_Data(char *op, int nchar,
1909                                      SUMA_OPEN_DX_STRUCT *dx);
1910 int * SUMA_FindNumericDataDsetCols(SUMA_DSET *dset, int *N_icols);
1911 float * SUMA_DsetCol2FloatFullSortedColumn(
1912             SUMA_DSET *dset, int ico, byte **nmaskp, float fillval,
1913             int N_Node, int *N_inmask, SUMA_Boolean MergeMask);
1914 double * SUMA_DsetCol2DoubleFullSortedColumn(
1915             SUMA_DSET *dset, int ico, byte **nmaskp, double fillval,
1916             int N_Node, int *N_inmask, SUMA_Boolean MergeMask);
1917 SUMA_Boolean SUMA_MakeSparseColumnFullSorted(float **vp, int N_v, float mask_val, byte **bmp, SUMA_DSET *dset, int N_Node);
1918 SUMA_Boolean SUMA_MakeSparseDoubleColumnFullSorted (
1919       double **vp, int N_v,
1920       double mask_val, byte **bmp,
1921       SUMA_DSET *dset, int N_Node);
1922 SUMA_Boolean SUMA_AddNodeIndexColumn(SUMA_DSET *dset, int N_Node);
1923 int *SUMA_CreateNodeIndexToRowIndexMap(SUMA_DSET *dset, int maxind,
1924                                        double *range);
1925 SUMA_DSET * SUMA_ngr_2_dset(NI_group *nini, int warn);
1926 SUMA_Boolean SUMA_LabelDset(SUMA_DSET *dset, char *lbl);
1927 SUMA_Boolean SUMA_RenameDset(SUMA_DSET *dset, char *filename, int autoid);
1928 byte *SUMA_load_1D_n_mask(char *name, int N_Node, byte *omask,
1929                            const char *oper, int *N_inmask);
1930 byte * SUMA_indexlist_2_bytemask(int *ind_list, int N_ind_list,
1931                                  int N_mask, int *N_inmask);
1932 byte * SUMA_Meshbmask_2_IndexListbmask(byte *Mbmask, int N_Mbmask,
1933                                  int *ind_list, int N_ind_list, int *N_ILbmask);
1934 byte *SUMA_load_1D_b_mask(char *name, int N_Node, byte *omask,
1935                           const char *oper, int *N_inmask);
1936 byte *SUMA_get_c_mask(char *mask, int N_Node, byte *omask,
1937                       const char *oper, int *N_inmask);
1938 byte * SUMA_load_all_command_masks(char *bmaskname, char *nmaskname,
1939                                    char *cmask, int N_Node, int *N_inmask);
1940 void SUMA_SetAddIndex_1D(int);
1941 int SUMA_GetAddIndex_1D(void);
1942 THD_3dim_dataset *SUMA_sumadset2afnidset(SUMA_DSET **dsetp, int copy_data,
1943                                          int cleardset);
1944 SUMA_DSET *SUMA_afnidset2sumadset(THD_3dim_dataset **dsetp, int copy_data,
1945                                   int cleardset, int floatize);
1946 int SUMA_GetDsetColStatAttr(  SUMA_DSET *dset, int col_index,
1947                               int *statcode,
1948                               float *p1, float *p2, float *p3);
1949 float SUMA_fdrcurve_zval( SUMA_DSET *dset , int iv , float thresh );
1950 NI_group *SUMA_NI_Cmap_of_Dset(SUMA_DSET *dset);
1951 
1952 
1953 /*********************** BEGIN Miscellaneous support functions **************************** */
1954    #define SUMA_STANDALONE_INIT {   \
1955       /* install signal handler, shamelessly copied from AFNI) */ \
1956       signal(SIGINT ,SUMA_sigfunc) ;      \
1957       signal(SIGBUS ,SUMA_sigfunc) ;   \
1958       signal(SIGSEGV,SUMA_sigfunc) ;   \
1959       signal(SIGTERM,SUMA_sigfunc) ;   \
1960       SUMA_process_environ(); \
1961       SUMA_ParseInput_basics_ns (argv, argc);   \
1962    }
1963 
1964 #define SUMA_DSET_NAME_CHECK(prefix) { \
1965    char *NameOut=NULL; SUMA_DSET_FORMAT form=SUMA_NO_DSET_FORMAT; \
1966    if (!THD_ok_overwrite()) { \
1967       form = SUMA_GuessFormatFromExtension(prefix, "jeveux.niml.dset" );  \
1968       if (SUMA_WriteDset_NameCheck_s (prefix, NULL, form,  \
1969                                   0, &NameOut)) {   \
1970          SUMA_S_Errv("Dset %s already exists\n", NameOut); \
1971          SUMA_free(NameOut); \
1972          exit(1);  \
1973       }  \
1974    } if (NameOut) SUMA_free(NameOut); \
1975 }
1976 
1977 SUMA_DSET_FORMAT SUMA_FormatFromFormString(char *arg);
1978 SUMA_DSET_FORMAT SUMA_GuessFormatFromExtension(char *Name, char *fallbackname);
1979 const char *SUMA_ExtensionOfDsetFormat (SUMA_DSET_FORMAT form);
1980 char *SUMA_OutputDsetFileStatus(char *prefix, char *inname,
1981                             SUMA_DSET_FORMAT *oform,
1982                             char *pre, char *app, int *exists);
1983 char * SUMA_GetDsetValInCol(SUMA_DSET *dset, int ind, int ival, double *dval) ;
1984 char * SUMA_GetValInCol(NI_element *nel, int ind, int ival, double *dval);
1985 void **SUMA_Dset2VecArray(SUMA_DSET *dset,
1986                         int *ind, int nind,
1987                         int *node, int N_Node,
1988                         int iNodeMax,
1989                         int *N_ret,
1990                         SUMA_VARTYPE tp);
1991 SUMA_DSET *SUMA_VecArray2Dset(void **resv,
1992                         SUMA_DSET *usethisdset,
1993                         int *ind, int nind,
1994                         int *node, int N_Node,
1995                         int iNodeMax,
1996                         SUMA_VARTYPE tp);
1997 void * SUMA_GetDsetAllNodeValsInCols2(SUMA_DSET *dset,
1998                                        int *ind, int nind,
1999                                        int node, int N_Node,
2000                                        int *N_ret,
2001                                        SUMA_VARTYPE tp);
2002 double SUMA_GetDsetValInCol2(SUMA_DSET *dset, int ind, int ival) ;
2003 double SUMA_GetValInCol2(NI_element *nel, int ind, int ival);
2004 int SUMA_GetNodeRow_FromNodeIndex_ns(SUMA_DSET *dset, int node, int N_Node);
2005 int SUMA_GetNodeRow_FromNodeIndex_eng(SUMA_DSET *dset, int node, int N_Node);
2006 int SUMA_GetNodeIndex_FromNodeRow_ns(SUMA_DSET *dset, int row, int N_Node);
2007 int SUMA_GetNodeIndex_FromNodeRow_eng(SUMA_DSET *dset, int row, int N_Node);
2008 double SUMA_GetDsetNodeValInCol2(SUMA_DSET *dset, int ind,
2009                                  int node, int N_Node);
2010 SUMA_VARTYPE SUMA_CTypeName2VarType (char *vt);
2011 const char *SUMA_VarType2CTypeName (SUMA_VARTYPE vt);
2012 SUMA_COL_TYPE SUMA_VarType2ColType (char *vt);
2013 int SUMA_SizeOf(SUMA_VARTYPE vt);
2014 void *SUMA_BinarySuck(char *fname, SUMA_VARTYPE data_type, int endian, int start, int end, int *nvals_read);
2015 void SUMA_swap_2(void *ppp);
2016 void SUMA_swap_4(void *ppp);
2017 void SUMA_swap_8(void *ppp);
2018 int SUMA_suck_file( char *fname , char **fbuf );
2019 char * SUMA_file_suck( char *fname , int *nread );
2020 
2021 
2022 /******** BEGIN functions for surface structure  ******************** */
2023 SUMA_SO_SIDE SUMA_giiStringToNumSide(char *cc);
2024 void SUMA_ShowAfniSurfaceObject(NI_group *aSO, FILE *out,
2025                               int detail, char *title);
2026 char *SUMA_AfniSurfaceObject_Info(NI_group *aSO,
2027                                   int detail, char *title);
2028 NI_group * afni_open_gifti_surf(char * fname, int read_data);
2029 int afni_write_gifti_surf( NI_group *aSO, char * fname,
2030                            int write_data, int encoding);
2031 
2032 
2033 /******** END functions for surface structure  ******************** */
2034 int SUMA_init_GISET_setup(NI_stream nsg , NI_element *nel, GICOR_setup *giset,
2035                           int bmode);   /* 17 Aug 2012 [rickr] */
2036 int SUMA_PopulateDsetsFromGICORnel(NI_element *nel, GICOR_setup *giset,
2037                                    SUMA_DSET **sdsetv);
2038 const char *SUMA_ObjectTypeCode2ObjectTypeName(SUMA_DO_Types dd);
2039 SUMA_DO_Types SUMA_ObjectTypeName2ObjectTypeCode(char *cc);
2040 #define SUMA_otn2otc SUMA_ObjectTypeName2ObjectTypeCode
2041 #define SUMA_otc2otn SUMA_ObjectTypeCode2ObjectTypeName
2042 
2043 /************************ GRAPH Dset functions  ******************** */
2044 
2045 /*! Return the 1D (p) index corresponding to the compact
2046     columnwise storage of a triangular matrix
2047     Use the R test function ij2p in CompactIndexing.R
2048     for details and tests.
2049     Note, we pass two_n instead of n, the dimension of the matrix
2050     for speed.
2051     i and j, must be integers or floor operation will fail
2052 */
2053 #define SUMA_CItri_ij2p_diag(i, j, two_n) ((i+(two_n-(j)-1)*(j))/2)
2054 #define SUMA_CItri_ij2p(i, j, two_n)      ((i-1+(two_n-(j)-3)*(j))/2)
2055 #define SUMA_CItri_pmax_diag(n) (((n)*((n)+1))/2-1)
2056 #define SUMA_CItri_pmax(n)      (((n)*((n)-1))/2-1)
2057 
2058 SUMA_DSET *SUMA_FloatVec_to_GDSET(float **vec, int vec_num, int vec_len,
2059                                   char *mtype,
2060                                   char **vec_labs, int *ie, int *i0, int *i1);
2061 SUMA_Boolean SUMA_Dset_to_GDSET(SUMA_DSET **dset, char *mtype,
2062                                 int ok_verticalize, int *ie, int *i0, int *i1);
2063 byte SUMA_CItri_p2ij(int p, int n, int two_n, byte withdiag, int *i, int *j);
2064 SUMA_Boolean SUMA_GDSET_Set_Aux_matrix_shape(SUMA_DSET *dset);
2065 byte SUMA_GDSET_SegIndexToPoints(SUMA_DSET *dset, int si,
2066                                  int *i1, int *i2, int *row);
2067 byte SUMA_GDSET_PointsToSegIndex(SUMA_DSET *dset, int i1, int i2, int *si);
2068 byte SUMA_GDSET_SegRowToPoints(SUMA_DSET *dset, int ri,
2069                                  int *i1, int *i2, int *index);
2070 byte SUMA_GDSET_PointsToSegRow(SUMA_DSET *dset, int i1, int i2, int *ri);
2071 byte SUMA_GDSET_PointToDiagSegRowIndex(SUMA_DSET *dset,int i1, int *ri, int *si);
2072 byte SUMA_GDSET_PointToDiagSegIndex(SUMA_DSET *dset, int i1, int *si);
2073 byte SUMA_GDSET_PointToDiagSegRow(SUMA_DSET *dset, int i1, int *ri);
2074 SUMA_SQ_MATRIX_SHAPES SUMA_matrix_shape_name_to_matrix_shape(char *name);
2075 char * SUMA_matrix_shape_to_matrix_shape_name(SUMA_SQ_MATRIX_SHAPES sq);
2076 int *SUMA_GDSET_GetPointIndexColumn(SUMA_DSET *dset, int *N_vals, NI_element **);
2077 char **SUMA_GDSET_GetPointNamesColumn(SUMA_DSET *dset, int *N_vals,
2078                                     NI_element **nelxyzr);
2079 float *SUMA_GDSET_GetPointColumn_f(SUMA_DSET *dset, int *N_vals,
2080                                       NI_element **nelxyzr, char *label);
2081 int *SUMA_GDSET_GetPointGroupColumn(SUMA_DSET *dset, int *N_vals,
2082                                       NI_element **nelxyzr);
2083 int SUMA_GDSET_Index_To_NodeIndex(SUMA_DSET *dset, int cinode);
2084 int SUMA_GDSET_NodeIndex_To_Index(SUMA_DSET *dset, int node);
2085 int SUMA_GDSET_EdgeIndex_To_Row(SUMA_DSET *dset, int ei);
2086 int SUMA_GDSET_EdgeRow_To_Index(SUMA_DSET *dset, int ri);
2087 int SUMA_GDSET_Max_Edge_Index(SUMA_DSET *dset);
2088 char *SUMA_GDSET_Node_Label(SUMA_DSET *dset, int psel);
2089 char *SUMA_GDSET_Edge_Label(SUMA_DSET *dset, int isel, char *pref, char *sep);
2090 
2091 /************************ CIFTI Dset functions ******************** */
2092 SUMA_Boolean SUMA_CIFTI_Set_Domains(SUMA_DSET *dset, int N_doms,
2093                                     int *dind, int *dindoff, int *dn,
2094                                     SUMA_DO_Types *dtp, char **dsrcs);
2095 SUMA_DSET *SUMA_CIFTI_2_edset(SUMA_DSET *dset, int i, byte *colmask,
2096       	             	      DList *DsetList, int allowreplace);
2097 SUMA_Boolean SUMA_CIFTI_NgrFromDomains(SUMA_DSET *dset);
2098 SUMA_Boolean SUMA_CIFTI_DomainsFromNgr(SUMA_DSET *dset, DList *DsetList,
2099       	             	      	       int allowreplace, SUMA_DSET **ret_edset);
2100 SUMA_Boolean SUMA_CIFTI_free_MD_data(SUMA_DSET *dset);
2101 SUMA_Boolean SUMA_CIFTI_Free_Doms(SUMA_DSET *dset);
2102 #endif
2103