1 /* It should be possible to compile this file without
2 the SUMA_COMPILED being defined
3 Without SUMA_COMPILED,  SUMA_DataSets_NS.o can be linked
4 from AFNI without trouble.
5 See SUMA_Makefile_NoDev
6 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <math.h>
13 #include "mrilib.h"
14 #include "niml.h"
15 #include "../niml/niml_private.h"
16 
17 #include "suma_objs.h" /* 21 Apr 2020 */
18 /*------------------------------------------------------------*/
19 
20 extern int selenium_close(void) ;
21 
22 int SUMA_AddDsetNelIndexCol ( SUMA_DSET *dset, char *col_label,
23                                SUMA_COL_TYPE ctp, void *col,
24                                void *col_attr, int stride) ;
25 
26 
27 #if defined SUMA_COMPILED
28    extern SUMA_CommonFields *SUMAg_CF;
29    extern int SUMAg_N_DOv;
30    extern SUMA_DO *SUMAg_DOv;
31 #endif
32 
33 extern int * UniqueInt (int *y, int ysz, int *kunq, int Sorted );
34 
35 static int verv[] = { SUMA_VERSION_VECTOR };
SUMA_LatestVersionNumber(void)36 float SUMA_LatestVersionNumber(void)
37 {
38    return((float)verv[0]/10000.0);
39 }
40 
41 #define NEL_DSET_TYPE(a) (NI_get_attribute((a), "dset_type"))
42 #define NEL_DATA_TYPE(a) (NI_get_attribute((a), "data_type"))
43 
44 /* A bunch of functions to track errors from non-suma and suma programs */
45 static DList *list=NULL;
46 
SUMA_FreeErrLog(void * data)47 void SUMA_FreeErrLog ( void *data)
48 {
49    SUMA_ERRLOG *el=NULL;
50    if (!data) return;
51    el = (SUMA_ERRLOG *)data;
52    SUMA_free(el);
53    return;
54 }
55 
SUMA_PushErrLog(char * macroname,char * msg,char * fname)56 void SUMA_PushErrLog(char *macroname, char *msg, char *fname)
57 {
58    SUMA_ERRLOG *el=NULL;
59    if (!list) {
60       list = (DList *)SUMA_calloc(1,sizeof(DList));
61       dlist_init(list, SUMA_FreeErrLog);
62    }
63    el = (SUMA_ERRLOG*)SUMA_calloc(1,sizeof(SUMA_ERRLOG));
64    snprintf(el->macroname, 39*sizeof(char),"%s", macroname);
65    snprintf(el->msg, (MAX_ERRLOG_MSG-1)*sizeof(char), "%s", msg);
66    snprintf(el->FuncName, (MAX_ERRLOG_FUNCNAME-1)*sizeof(char), "%s", fname);
67    dlist_ins_next(list, dlist_tail(list), (void *)el);
68    return;
69 }
70 
SUMA_PopErrLog(DListElmt * eldone)71 DListElmt* SUMA_PopErrLog(DListElmt *eldone)
72 {
73    static char FuncName[]={"SUMA_PopErrLog"};
74    if (!list) return(NULL);
75    if (!eldone) return(dlist_head(list));
76    else {
77       if (eldone == dlist_tail(list)) { /* all done, get out completely*/
78          dlist_destroy(list);
79          SUMA_free(list); list = NULL;
80          return(NULL);
81       } else {
82          return(dlist_next(eldone));
83       }
84    }
85    SUMA_S_Err("should not be here !");
86    return(NULL);
87 }
88 
89 /* A function to executes the proper macros for message generation. This one here is for non-suma programs */
WorkErrLog_ns(void)90 void WorkErrLog_ns(void)
91 {
92    static char FuncName[MAX_ERRLOG_FUNCNAME]={"WorkErrLog_ns"};
93    int LocalHead = 0;
94    DListElmt *del=NULL;
95    SUMA_ERRLOG *el=NULL;
96    char mmm[256];
97    del = SUMA_PopErrLog(NULL);
98    while (del) {
99       el = (SUMA_ERRLOG *)del->data;
100       sprintf(FuncName, "%s", el->FuncName);
101            if (!strcmp(el->macroname,"L_Err")) { SUMA_L_Err("%s", el->msg); }
102       else if (!strcmp(el->macroname,"SL_Err")) { SUMA_SL_Err("%s", el->msg); }
103       else if (!strcmp(el->macroname,"SLP_Err")) { SUMA_SLP_Err("%s", el->msg); }
104       else if (!strcmp(el->macroname,"L_Warn")) { SUMA_L_Warn("%s", el->msg); }
105       else if (!strcmp(el->macroname,"SL_Warn")) { SUMA_SL_Warn("%s", el->msg); }
106       else if (!strcmp(el->macroname,"SLP_Warn")){SUMA_SLP_Warn("%s", el->msg); }
107       else if (!strcmp(el->macroname,"L_Note")) { SUMA_L_Note("%s", el->msg); }
108       else if (!strcmp(el->macroname,"SL_Note")) { SUMA_L_Note("%s", el->msg); }
109       else if (!strcmp(el->macroname,"SLP_Note")){SUMA_SLP_Note("%s", el->msg); }
110       else if (!strcmp(el->macroname,"L_Crit")) { SUMA_L_Crit("%s", el->msg); }
111       else if (!strcmp(el->macroname,"SL_Crit")) { SUMA_SL_Crit("%s", el->msg); }
112       else if (!strcmp(el->macroname,"SLP_Crit")){SUMA_SLP_Crit("%s", el->msg); }
113       else {
114          snprintf(mmm, 255*sizeof(char), "Bad macroname %s", el->macroname);
115          sprintf(FuncName, "%s", "WorkErrLog_ns"); SUMA_S_Err("%s",mmm);
116       }
117       del = SUMA_PopErrLog(del);
118    }
119 }
120 
121 
122 /*!
123    Creates a NI group to store surface data
124    N_el is the number of data elements stored in each column
125    N_el can be the number of nodes for example.
126    N_eel is the number of edges for graph type datasets
127 */
SUMA_NewDsetGrp(SUMA_DSET * dset,SUMA_DSET_TYPE dtp,char * MeshParent_idcode,char * geometry_parent_idcode,int N_el,int N_eel,char * filename,char * thisidcode)128 SUMA_Boolean SUMA_NewDsetGrp (SUMA_DSET *dset, SUMA_DSET_TYPE dtp,
129                            char* MeshParent_idcode,
130                           char * geometry_parent_idcode,
131                           int N_el, int N_eel,
132                           char *filename, char *thisidcode)
133 {
134    static char FuncName[]={"SUMA_NewDsetGrp"};
135    char idcode[SUMA_IDCODE_LENGTH], *namecode, *dname;
136 
137    SUMA_ENTRY;
138 
139    if (!dset) { SUMA_SL_Err("NULL dset"); SUMA_RETURN(NOPE); }
140    if (dset->N_links != 0) {
141       SUMA_SL_Err("Not expected here, N_links != 0");
142       SUMA_RETURN(NOPE);
143    }
144 
145    dset->ngr = NI_new_group_element();
146    if (0) {
147       NI_rename_group(dset->ngr, SUMA_Dset_Type_Name(dtp));
148    } else { /* trying to go the AFNI route */
149       NI_rename_group(dset->ngr, "AFNI_dataset");
150       NI_set_attribute (dset->ngr, "dset_type", SUMA_Dset_Type_Name(dtp));
151    }
152 
153    /* assign an idcode */
154    if (!thisidcode) {
155       if (!filename) {
156          UNIQ_idcode_fill(idcode);
157          NI_set_attribute (dset->ngr, "self_idcode", idcode);
158                   /* create one *//* changed from idcode March 31 */
159       } else {
160          namecode = UNIQ_hashcode(filename);  /* from filename */
161          NI_set_attribute (dset->ngr, "self_idcode", namecode);
162                SUMA_free(namecode);
163       }
164    } else {
165       NI_set_attribute (dset->ngr, "self_idcode", thisidcode);
166    }
167 
168    /* set the idcodes of the parents */
169    if (MeshParent_idcode) {
170       NI_set_attribute (dset->ngr, "domain_parent_idcode", MeshParent_idcode);
171    } else {
172       NI_set_attribute (dset->ngr, "domain_parent_idcode", NULL);
173                /* don't use SUMA_EMPTY_ATTR unless you must NULL is nice*/
174    }
175    if (geometry_parent_idcode) {
176       NI_set_attribute (dset->ngr, "geometry_parent_idcode",
177                         geometry_parent_idcode);
178    } else {
179       NI_set_attribute (dset->ngr, "geometry_parent_idcode", NULL);
180    }
181 
182    if (filename) NI_set_attribute (dset->ngr, "filename", filename);
183 
184    /* add the data element */
185    dname = SUMA_append_string(SUMA_Dset_Type_Name(dtp), "_data");
186    dset->dnel = NI_new_data_element("SPARSE_DATA", N_el);
187    NI_set_attribute (dset->dnel, "data_type", dname);
188    SUMA_free(dname); dname = NULL;
189    NI_add_to_group(dset->ngr, dset->dnel);
190 
191    /* Now add the node/edge  index element */
192    if (SUMA_isGraphDset(dset))
193          dname = SUMA_append_string(SUMA_Dset_Type_Name(dtp), "_edge_indices");
194    else  dname = SUMA_append_string(SUMA_Dset_Type_Name(dtp), "_node_indices");
195    dset->inel = NI_new_data_element("INDEX_LIST", N_el);
196    NI_set_attribute (dset->inel, "data_type", dname);
197    SUMA_free(dname); dname = NULL;
198    NI_add_to_group(dset->ngr, dset->inel);
199 
200    if (SUMA_isGraphDset(dset)) {
201       SUMA_S_Warn("Not bothering with point data yet. "
202                   "If you don't end up adding this here, get rid of N_eel"
203                   "Also not sure if I want to add data only or data and "
204                   "indices. Consider also initializing to 0 N_eel, then"
205                   "use NI_alter_veclen");
206       if (0) {
207          /* point (just to distinguish from node) data */
208       dname = SUMA_append_string(SUMA_Dset_Type_Name(dtp), "_pdata");
209       dset->pdnel = NI_new_data_element("P_SPARSE_DATA", N_eel);
210       NI_set_attribute (dset->pdnel, "data_type", dname);
211       SUMA_free(dname); dname = NULL;
212       NI_add_to_group(dset->ngr, dset->pdnel);
213       }
214    }
215 
216    /* SUMA_ShowNel((void*)dset->inel); */
217    SUMA_RETURN(YUP);
218 }
219 
220 
221 static byte SUMA_ALLOW_NEL_USE;
SUMA_allow_nel_use(int al)222 void SUMA_allow_nel_use(int al)
223 {
224    if (al) SUMA_ALLOW_NEL_USE = 1;
225    else SUMA_ALLOW_NEL_USE = 0;
226 
227    return;
228 }
229 
230 /*!
231    Creates a NI elem. to store surface data
232    N_el is the number of data elements stored in each column
233    N_el can be the number of nodes for example
234    Do not use this function to create dsets anymore, use
235    SUMA_NewDsetGrp
236 */
SUMA_NewNel(SUMA_DSET_TYPE dtp,char * MeshParent_idcode,char * geometry_parent_idcode,int N_el,char * filename,char * thisidcode)237 NI_element * SUMA_NewNel (SUMA_DSET_TYPE dtp, char* MeshParent_idcode,
238                           char * geometry_parent_idcode, int N_el,
239                           char *filename, char *thisidcode)
240 {
241    static char FuncName[]={"SUMA_NewNel"};
242    NI_element *nel=NULL;
243    char idcode[SUMA_IDCODE_LENGTH], *namecode;
244 
245    SUMA_ENTRY;
246 
247    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, perhaps. Check on caller.");
248 
249    if (!(nel = NI_new_data_element(SUMA_Dset_Type_Name(dtp), N_el))) {
250       SUMA_S_Err("Failed to create nel");
251       fprintf(SUMA_STDERR,"Had N_el = %d\n", N_el);
252    }
253 
254    /* assign an idcode */
255    if (!thisidcode) {
256       if (!filename) {
257          UNIQ_idcode_fill(idcode);
258          NI_set_attribute (nel, "self_idcode", idcode); /* create one */
259       } else {
260          namecode = UNIQ_hashcode(filename);  /* from filename */
261          NI_set_attribute (nel, "self_idcode", namecode); SUMA_free(namecode);
262       }
263    } else {
264       NI_set_attribute (nel, "self_idcode", thisidcode);
265    }
266 
267 
268    /* set the idcodes of the parents */
269    if (MeshParent_idcode) {
270       NI_set_attribute (nel, "domain_parent_idcode", MeshParent_idcode);
271    } else {
272       NI_set_attribute (nel, "domain_parent_idcode", SUMA_EMPTY_ATTR);
273    }
274    if (geometry_parent_idcode) {
275       NI_set_attribute (nel, "geometry_parent_idcode", geometry_parent_idcode);
276    } else {
277       NI_set_attribute (nel, "geometry_parent_idcode", SUMA_EMPTY_ATTR);
278    }
279 
280    if (filename) NI_set_attribute (nel, "filename", filename);
281 
282    SUMA_allow_nel_use(0);
283    SUMA_RETURN(nel);
284 }
285 /*!
286    \brief Returns a copy of a string attribute for
287    one column. Yours to free when done with it.
288 */
SUMA_DsetColStringAttrCopy(SUMA_DSET * dset,int i,int addcolnum,char * attrname)289 char *SUMA_DsetColStringAttrCopy(SUMA_DSET *dset, int i,
290                                  int addcolnum, char *attrname)
291 {
292    static char FuncName[]={"SUMA_DsetColStringAttrCopy"};
293    char Name[500], *lbl = NULL, **sc=NULL, *s=NULL;
294    NI_element *nelb=NULL;
295 
296    SUMA_ENTRY;
297 
298    if (!dset || !dset->dnel || !attrname) { SUMA_RETURN(NULL); }
299    if (i < 0 || i >= SDSET_VECNUM(dset)) { SUMA_RETURN(NULL); }
300 
301    if (!(nelb = SUMA_FindDsetAttributeElement(dset, attrname))) {
302       SUMA_RETURN(NULL);
303    }
304    SUMA_NEL_GET_STRING(nelb, 0, 0, lbl);
305       /* sc is a pointer copy here, do not free */
306    lbl = SUMA_Get_Sub_String(lbl, SUMA_NI_CSS, i);
307    sprintf(Name, "%d: ", i);
308    if (lbl) {
309       if (addcolnum) s = SUMA_append_string(Name, lbl);
310       else s = SUMA_copy_string(lbl);
311       SUMA_free(lbl); lbl = NULL;
312    }
313 
314    SUMA_RETURN(s);
315 }
316 
317 /* A conveninence function to get a column's label.
318    Do not free what you get back. Labels are truncated at 64 chars.
319  */
SUMA_DsetColLabel(SUMA_DSET * dset,int i)320 char *SUMA_DsetColLabel(SUMA_DSET *dset, int i)
321 {
322    static char ans[5][65]={""};
323    static int n=0;
324    char *ss=NULL;
325 
326    ++n; if (n>4) n=0;
327    ans[n][0]='\0';
328 
329    if (!(ss = SUMA_DsetColLabelCopy(dset, i,0))) {
330       return(ans[n]);
331    }
332    snprintf(ans[n],64*sizeof(char),"%s",ss);
333    SUMA_free(ss);
334    return(ans[n]);
335 }
336 
337 /*!
338    \brief Returns A COPY of the label of a column in a NI_element
339    NULL in case of error
340    YOU SHOULD FREE THIS POINTER when you're done with it
341 */
SUMA_DsetColLabelCopy(SUMA_DSET * dset,int i,int addcolnum)342 char *SUMA_DsetColLabelCopy(SUMA_DSET *dset, int i, int addcolnum)
343 {
344    static char FuncName[]={"SUMA_DsetColLabelCopy"};
345    char Name[500], *lbl = NULL, **sc=NULL, *s=NULL;
346    NI_element *nelb=NULL;
347 
348    SUMA_ENTRY;
349 
350    if (!dset || !dset->dnel) { SUMA_RETURN(NULL); }
351    if (i < 0 || i >= SDSET_VECNUM(dset)) { SUMA_RETURN(NULL); }
352 
353    if (!(nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_LABS"))) {
354       if (!addcolnum) {
355          SUMA_RETURN(SUMA_copy_string("no_label"));
356       } else {
357          sprintf(Name, "%d: ", i);
358          SUMA_RETURN(SUMA_append_string(Name,"no_label"));
359       }
360    }
361    SUMA_NEL_GET_STRING(nelb, 0, 0, lbl);
362                      /* lbl is a pointer copy here, do not free */
363    lbl = SUMA_Get_Sub_String(lbl, SUMA_NI_CSS, i);
364    sprintf(Name, "%d: ", i);
365    if (lbl) {
366       if (addcolnum) s = SUMA_append_string(Name, lbl);
367       else s = SUMA_copy_string(lbl);
368       SUMA_free(lbl); lbl = NULL;
369       SUMA_RETURN(s);
370    }
371 
372    /* no label, try the name of the nel */
373    lbl = NI_get_attribute(dset->ngr, "label");
374    if (lbl) {
375       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
376       else SUMA_RETURN(SUMA_copy_string(lbl));
377    }
378    lbl = NI_get_attribute(dset->ngr, "filename");
379    if (lbl) {
380       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
381       else SUMA_RETURN(SUMA_copy_string(lbl));
382    }
383 
384    if (NEL_DSET_TYPE(dset->ngr)) {
385       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, NEL_DSET_TYPE(dset->ngr)));
386       else SUMA_RETURN(SUMA_copy_string(NEL_DSET_TYPE(dset->ngr)));
387    }
388 
389    /* give me a bone */
390    if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, "bone"));
391    else  SUMA_RETURN(SUMA_copy_string("bone"));
392 }
393 
SUMA_FindDsetColLabeled(SUMA_DSET * dset,char * label)394 int SUMA_FindDsetColLabeled(SUMA_DSET *dset, char *label)
395 {
396    static char FuncName[]={"SUMA_FindDsetColLabeled"};
397    int ind=-1;
398    NI_element *nelb=NULL;
399    char *lbl=NULL, *str=NULL;
400 
401    SUMA_ENTRY;
402 
403    if (!label || !dset ||
404        !(nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_LABS"))) {
405       SUMA_S_Err("NULL input");
406       SUMA_RETURN(-1);
407    }
408    SUMA_NEL_GET_STRING(nelb, 0, 0, lbl);
409 
410    if (strstr(lbl,label)) {/* have something */
411       for (ind=0; ind<SDSET_VECNUM(dset); ++ind) {
412          if ((str = SUMA_DsetColLabelCopy(dset, ind, 0))) {
413             if (!strcmp(str,label)) {
414                SUMA_free(str); SUMA_RETURN(ind);
415             } else SUMA_free(str);
416          }
417       }
418    }
419 
420    SUMA_RETURN(-1);
421 }
422 
423 /*!
424    Return a NULL terminated vector of strings containing a copy
425    of all labels
426    free with SUMA_FreeAllDsetColLabels
427 */
SUMA_AllDsetColLabels(SUMA_DSET * dset)428 char **SUMA_AllDsetColLabels(SUMA_DSET *dset)
429 {
430    static char FuncName[]={"SUMA_AllDsetColLabels"};
431    char ** AllLabels=NULL;
432    int ii;
433 
434    if (!dset) return(NULL);
435 
436    AllLabels = (char **)SUMA_calloc(SDSET_VECNUM(dset)+1,sizeof(char*));
437 
438    for (ii=0; ii<SDSET_VECNUM(dset); ++ii)
439       AllLabels[ii] = SUMA_DsetColLabelCopy(dset, ii, 0);
440 
441    AllLabels[SDSET_VECNUM(dset)] = NULL;
442 
443    return(AllLabels);
444 }
445 
SUMA_FreeAllDsetColLabels(char ** AllLabels)446 char **SUMA_FreeAllDsetColLabels(char **AllLabels)
447 {
448    static char FuncName[]={"SUMA_FreeAllDsetColLabels"};
449    int ii=0;
450 
451    if (!AllLabels) return(NULL);
452 
453    while (AllLabels[ii]) {
454       SUMA_free(AllLabels[ii]);
455       ++ii;
456    }
457    SUMA_free(AllLabels);
458    return(NULL);
459 }
460 
461 /*!
462    \brief Returns A COPY of the label of a column in a NI_element
463    NULL in case of error
464    YOU SHOULD FREE THIS POINTER when you're done with it
465 
466 */
SUMA_ColLabelCopy(NI_element * nel,int i,int addcolnum)467 char *SUMA_ColLabelCopy(NI_element *nel, int i, int addcolnum)
468 {
469    static char FuncName[]={"SUMA_ColLabelCopy"};
470    char Name[500], *lbl;
471 
472    SUMA_ENTRY;
473 
474    /* SUMA_SL_Warn("Obsolete, use new version."); it is still used for converting old types to new one */
475 
476    if (i < 0) { SUMA_RETURN(NULL); }
477    if (!nel) { SUMA_RETURN(NULL); }
478 
479    sprintf(Name, "LabelCol_%d", i);
480    lbl = NI_get_attribute(nel, Name);
481    sprintf(Name, "%d: ", i);
482    if (lbl) {
483       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
484       else SUMA_RETURN(SUMA_copy_string(lbl));
485    }
486    /* no label, try the name of the nel */
487    lbl = NI_get_attribute(nel, "label");
488    if (lbl) {
489       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
490       else SUMA_RETURN(SUMA_copy_string(lbl));
491    }
492    lbl = NI_get_attribute(nel, "filename");
493    if (lbl) {
494       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
495       else SUMA_RETURN(SUMA_copy_string(lbl));
496    }
497 
498    if (nel->name) {
499       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, nel->name));
500       else SUMA_RETURN(SUMA_copy_string(nel->name));
501    }
502 
503    /* give me a bone */
504    if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, "bone"));
505    else  SUMA_RETURN(SUMA_copy_string("bone"));
506 }
507 
SUMA_FindDsetDataElement(SUMA_DSET * dset)508 NI_element *SUMA_FindDsetDataElement(SUMA_DSET *dset)
509 {
510    static char FuncName[]={"SUMA_FindDsetDataElement"};
511    char *attname=NULL;
512    NI_element *nel=NULL;
513 
514    SUMA_ENTRY;
515 
516    if (!dset || !dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
517    attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_data");
518 
519    nel = SUMA_FindNgrDataElement(dset->ngr, "SPARSE_DATA", attname);
520    SUMA_free(attname);
521    SUMA_RETURN(nel);
522 }
523 
524 
SUMA_FindDsetDatumIndexElement(SUMA_DSET * dset)525 NI_element *SUMA_FindDsetDatumIndexElement(SUMA_DSET *dset)
526 {
527    static char FuncName[]={"SUMA_FindDsetDatumIndexElement"};
528    char *attname=NULL;
529    NI_element *nel=NULL;
530 
531    SUMA_ENTRY;
532 
533    if (!dset || !dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
534    if (SUMA_isGraphDset(dset))
535         attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_edge_indices");
536    else attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_node_indices");
537 
538    nel = SUMA_FindNgrDataElement(dset->ngr, "INDEX_LIST", attname);
539    SUMA_free(attname);
540    SUMA_RETURN(nel);
541 }
542 
SUMA_FindSDsetNodeIndexElement(SUMA_DSET * dset)543 NI_element *SUMA_FindSDsetNodeIndexElement(SUMA_DSET *dset)
544 {
545    static char FuncName[]={"SUMA_FindSDsetNodeIndexElement"};
546    char *attname=NULL;
547    NI_element *nel=NULL;
548 
549    SUMA_ENTRY;
550 
551    if (!dset || !dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
552    attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_node_indices");
553 
554    nel = SUMA_FindNgrDataElement(dset->ngr, "INDEX_LIST", attname);
555    SUMA_free(attname);
556    SUMA_RETURN(nel);
557 }
558 
SUMA_FindGDsetEdgeIndexElement(SUMA_DSET * dset)559 NI_element *SUMA_FindGDsetEdgeIndexElement(SUMA_DSET *dset)
560 {
561    static char FuncName[]={"SUMA_FindGDsetEdgeIndexElement"};
562    char *attname=NULL;
563    NI_element *nel=NULL;
564 
565    SUMA_ENTRY;
566 
567    if (!dset || !dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
568    attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_edge_indices");
569 
570    nel = SUMA_FindNgrDataElement(dset->ngr, "INDEX_LIST", attname);
571    SUMA_free(attname);
572    SUMA_RETURN(nel);
573 }
574 
575 
SUMA_FindNgrDataElement(NI_group * ngr,char * nelname,char * typename)576 NI_element *SUMA_FindNgrDataElement(
577          NI_group *ngr, char *nelname, char *typename)
578 {
579    static char FuncName[]={"SUMA_FindNgrDataElement"};
580    NI_element *nel = NULL;
581    char *rs=NULL;
582    static int nwarn = 0;
583    int ip;
584    SUMA_Boolean LocalHead = NOPE;
585 
586    SUMA_ENTRY;
587 
588    if (!ngr || !typename || !nelname) {
589       SUMA_SL_Err("NUll input "); SUMA_RETURN(nel);
590    }
591 
592    /* search for an element of type nelname
593       that is also of data_type typename */
594    for( ip=0 ; ip < ngr->part_num ; ip++ ){
595       /* nel = (NI_element *)ngr->part[ip] ;
596          SUMA_LHv("Working part %d/%d, name %s\n",
597                   ip, ngr->part_num, nel->name); */
598       switch( ngr->part_typ[ip] ){
599          /*-- a sub-group ==> recursion! --*/
600          case NI_GROUP_TYPE:
601             break ;
602          case NI_ELEMENT_TYPE:
603             nel = (NI_element *)ngr->part[ip] ;
604             if (LocalHead)  {
605                fprintf(SUMA_STDERR,
606                         "%s:  Looking for %s,%s   name=%s vec_len=%d "
607                         "vec_filled=%d, vec_num=%d\n",
608                         FuncName,
609                         nelname, typename, nel->name, nel->vec_len,
610                         nel->vec_filled, nel->vec_num );
611             }
612             if (!strcmp(nelname, nel->name)) {/* now in keeping with AFNI */
613                rs = NI_get_attribute(nel, "data_type");
614                if (rs) {
615                   if (!strcmp(typename, rs)) SUMA_RETURN(nel);
616                } else {
617                   if ( 0 && !(nwarn % 25)) {
618                      fprintf(SUMA_STDERR,
619                      "Notice %s:\n"
620                      "  NIML Dset's index column named %s \n"
621                      "  is without any data_type attribute.\n"
622                      "  Could not verify that element's \n"
623                      "     data_type = %s .\n"
624                      "  Ignore notice for dsets created by AFNI.\n"
625                      "  Notice is shown intermittently in \n"
626                      "  SUMA GUI mode.\n", FuncName, nel->name, typename);
627                      nwarn = 0;
628                   }
629                   ++nwarn;
630                   SUMA_RETURN(nel);
631                }
632             }
633             /* cancel plans if you get here */
634             nel = NULL;
635             break;
636          default:
637             SUMA_SL_Err("Don't know what to make of this "
638                         "group element, ignoring.");
639             break;
640       }
641    }
642 
643    SUMA_RETURN(nel);
644 }
645 
646 /*!
647    Check if this is an attribute for all columns
648    It has to be of type string and its name must begin with COLMS_
649 */
SUMA_isMultiColumnAttr(NI_element * nel)650 SUMA_Boolean SUMA_isMultiColumnAttr(NI_element *nel)
651 {
652    static char FuncName[]={"SUMA_isMultiColumnAttr"};
653    NI_rowtype *rti=NULL;
654    char *mm=NULL;
655 
656    SUMA_ENTRY;
657 
658    if (strcmp("AFNI_atr", nel->name)) SUMA_RETURN(NOPE);
659 
660    rti = NI_rowtype_find_code(nel->vec_typ[0]) ;
661    if (rti->code != NI_STRING) SUMA_RETURN(NOPE);
662 
663    /* now check the name */
664    mm = NI_get_attribute(nel, "atr_name");
665    if (!mm || strncmp("COLMS_",mm, 6)) SUMA_RETURN(NOPE);
666 
667    SUMA_RETURN(YUP);
668 }
669 
670 /* Check to see if this an attribute for just one column
671 like FDRCURVE_000002
672 */
SUMA_isSingleColumnAttr(NI_element * nel,int * icolb,char * rtname)673 SUMA_Boolean SUMA_isSingleColumnAttr(NI_element *nel, int *icolb, char *rtname)
674 {
675    static char FuncName[]={"SUMA_isSingleColumnAttr"};
676    NI_rowtype *rti=NULL;
677    char *mm, mbuf[128], mbuf2[128];
678    int ic=-1, found = -1, icol=-1;
679    SUMA_Boolean LocalHead = NOPE;
680 
681    SUMA_ENTRY;
682 
683    if (icolb) *icolb = icol;
684    if (rtname) rtname[0] = '\0';
685 
686    if (strcmp("AFNI_atr", nel->name)) SUMA_RETURN(NOPE);
687 
688    mm = NI_get_attribute(nel, "atr_name");
689    if (!mm ) SUMA_RETURN(NOPE);
690 
691    /* search backwards for the first _ */
692    ic = strlen(mm)-1;
693    found = 0;
694    while (!found && ic >=0) {
695       if (mm[ic]=='_') found = ic+1;
696       else --ic;
697    }
698    if (!found) SUMA_RETURN(NOPE);   /* no numbers here */
699    /* make sure all is numbers past found */
700    ic = found;
701    while (SUMA_IS_DIGIT(*(mm+ic))) ++ic;
702    if (LocalHead) {
703       fprintf(SUMA_STDERR,"%s: ic = %d, strlen = %d\n",
704                FuncName, ic, (int)strlen(mm));
705    }
706    if (ic != strlen(mm)) SUMA_RETURN(NOPE);   /* not all digits after _ */
707 
708    /* now turn that potential number to int and then do comparison again*/
709 
710    icol = (int)atof((&(mm[found])));
711    for (ic=0; ic<found-1; ++ic) mbuf2[ic] = mm[ic];
712    mbuf2[ic] = '\0';
713    sprintf(mbuf, "%s_%06d", mbuf2, icol);
714    if (LocalHead) {
715       fprintf(SUMA_STDERR, "%s:\n"
716                            "  >%s<\n"
717                            "  >%s<\n"
718                            "  >%s<\n",
719                FuncName, (&(mm[found])), mbuf,mm);
720    }
721    if (strcmp(mbuf,mm)) SUMA_RETURN(NOPE);
722 
723    if (icolb) *icolb = icol;
724    if (rtname) sprintf(rtname, "%s", mbuf2);
725 
726    SUMA_RETURN(YUP);
727 }
728 
729 /*!
730    Check to see if this is an attribute for no column in particular
731    like HISTORY
732 */
SUMA_isDsetwideColumnAttr(NI_element * nel)733 SUMA_Boolean SUMA_isDsetwideColumnAttr(NI_element *nel) {
734    static char FuncName[]={"SUMA_isDsetwideColumnAttr"};
735    int icol=-1;
736 
737    SUMA_ENTRY;
738 
739    if (strcmp("AFNI_atr", nel->name)) SUMA_RETURN(NOPE);
740 
741    if (SUMA_isMultiColumnAttr(nel)) {
742       SUMA_RETURN(NOPE);
743    }
744    if (SUMA_isSingleColumnAttr(nel, NULL, NULL)) {
745       SUMA_RETURN(NOPE);
746    }
747 
748    SUMA_RETURN(YUP);
749 }
750 
751 /*!
752    A stupid check to be sure this is an AFNI_atr
753 */
SUMA_isDsetNelAttr(NI_element * nel)754 SUMA_Boolean SUMA_isDsetNelAttr(NI_element *nel) {
755    static char FuncName[]={"SUMA_isDsetNelAttr"};
756 
757    SUMA_ENTRY;
758 
759    if (!nel || !nel->name) SUMA_RETURN(NOPE);
760    if (!strcmp("AFNI_atr", nel->name)) SUMA_RETURN(YUP);
761 
762    SUMA_RETURN(NOPE);
763 }
764 /*!
765    Parses an attribute name and fills the following:
766    tp --> 0 not an attribute
767          1 SingleColumn
768          2 MultiColumn
769          3 Dsetwide
770    icol --> the column number in case of tp = 1
771    rtname --> the attribute name for tp != 1
772                the attribute name's root for tp = 1
773          */
SUMA_ParseAttrName(NI_element * nel,int * tp,int * icol,char * rtname)774 SUMA_Boolean SUMA_ParseAttrName(NI_element *nel, int *tp,
775                                  int *icol, char *rtname)
776 {
777    static char FuncName[]={"SUMA_ParseAttrName"};
778    int ltp = -1, licol = -1;
779    char lrtname[128]={"error"};
780 
781    SUMA_ENTRY;
782 
783    if (!nel || (!tp && !icol && !rtname)) {
784       SUMA_RETURN(NOPE);
785    }
786 
787    if (SUMA_isDsetwideColumnAttr(nel)) {
788       ltp = 3;
789       strcpy(lrtname,NI_get_attribute(nel,"atr_name"));
790    } else if (SUMA_isMultiColumnAttr(nel)) {
791       ltp = 2;
792       strcpy(lrtname,NI_get_attribute(nel,"atr_name"));
793    } else if (SUMA_isSingleColumnAttr(nel, &licol, lrtname)) {
794       ltp = 1;
795    } else {
796       ltp = 0;
797       lrtname[0] = '\0';
798    }
799 
800    if (tp) *tp = ltp;
801    if (icol) *icol = licol;
802    if (rtname) strcpy(rtname, lrtname);
803 
804    SUMA_RETURN(YUP);
805 }
806 
SUMA_FindInAttrList(char ** attrlist,char * attr,int icol,int * imatch)807 SUMA_Boolean SUMA_FindInAttrList(char **attrlist, char *attr,
808                                  int icol, int *imatch)
809 {
810    static char FuncName[]={"SUMA_FindInAttrList"};
811    char nmbuf[128]={""};
812    int iattrlist = -1;
813 
814    SUMA_ENTRY;
815 
816 
817    if (!attrlist || !attr) SUMA_RETURN(NOPE);
818 
819    iattrlist = 0;
820    while (attrlist[iattrlist] && iattrlist >= 0) {
821       if (!strcmp(attrlist[iattrlist],attr)) {
822          if (imatch) *imatch = iattrlist;
823          iattrlist = -1; /* a sign to quit */
824       } else {
825          ++iattrlist;
826       }
827    }
828    if (iattrlist >= 0 && icol >= 0) {
829       /* try for single-column attribute match */
830       iattrlist = 0;
831       while (attrlist[iattrlist] && iattrlist >= 0) {
832          sprintf(nmbuf,"%s_%06d",attrlist[iattrlist],icol) ;
833          if (!strcmp(nmbuf,attr)) {
834             /* a name match */
835             if (imatch) *imatch = iattrlist;
836             iattrlist = -1; /* a sign to quit */
837          } else {
838             ++iattrlist;
839          }
840       }
841    }
842 
843    if (iattrlist == -1) SUMA_RETURN(YUP);
844    else SUMA_RETURN(NOPE);
845 }
846 
847 /*!
848    Makes a copy of a NI colormap */
SUMA_NICmapToNICmap(NI_group * ngr)849 NI_group *SUMA_NICmapToNICmap(NI_group *ngr)
850 {
851    static char FuncName[]={"SUMA_NICmapToNICmap"};
852    int i;
853    char *colname=NULL;
854    NI_group *ngro=NULL;
855    SUMA_DSET dset, *odset=NULL;
856    SUMA_Boolean LocalHead = NOPE;
857 
858    SUMA_ENTRY;
859 
860    SUMA_LH("In");
861    if (!ngr) SUMA_RETURN(ngro);
862 
863    /* shoehorn into dset struct */
864    dset.ngr = ngr;
865    dset.inel = dset.dnel = NULL;
866    dset.dnel = SUMA_FindDsetDataElement(&dset);
867 
868    if (SDSET_TYPE((&dset)) != SUMA_LABEL_TABLE_OBJECT) {
869       SUMA_S_Err("Not a colormap object");
870       SUMA_RETURN(ngro);
871    }
872 
873    /* make a copy of the meat */
874    odset = SUMA_CreateDsetPointer(NI_get_attribute(ngr,"Name"),
875                                  SUMA_LABEL_TABLE_OBJECT,
876                                  NULL, NULL, SDSET_VECLEN((&dset)));
877 
878    /* Go for it */
879    for (i=0; i<SDSET_VECNUM((&dset)); ++i) {
880       colname = SUMA_DsetColLabelCopy(&dset, i, 0);
881       if (!SUMA_AddDsetNelCol(odset, colname, SDSET_COLTYPE((&dset),i),
882                               SDSET_VEC((&dset),i), NULL, 1)){
883             SUMA_S_Err("Failed to add R");
884             SUMA_FreeDset(odset); odset = NULL;
885             SUMA_RETURN(ngro);
886       }
887       if (colname) SUMA_free(colname); colname=NULL;
888    }
889 
890    /* the little people */
891    NI_set_attribute(odset->ngr,"Name",
892                     NI_get_attribute(dset.ngr,"Name"));
893    NI_set_attribute(odset->ngr,"flipped",
894                     NI_get_attribute(dset.ngr,"flipped"));
895    NI_set_attribute(odset->ngr,"Sgn",
896                     NI_get_attribute(dset.ngr,"Sgn"));
897    NI_set_attribute(odset->ngr,"top_frac",
898                     NI_get_attribute(dset.ngr,"top_frac"));
899    NI_set_attribute(odset->ngr,"M0",
900                     NI_get_attribute(dset.ngr,"M0"));
901 
902    /* So this is not really a dset, but it was nice to make use of
903    dset utility functions. Now cleanup a little */
904    /* remove ugly inel */
905    NI_remove_from_group(odset->ngr, odset->inel);
906 
907    /* grab ngr from dset, it is all we need */
908    ngro = odset->ngr; odset->ngr = NULL;
909 
910    /* change name from AFNI_dataset to AFNI_labeltable */
911    NI_rename_group(ngro, "AFNI_labeltable");
912    /* get rid of dset */
913    odset->dnel = NULL; SUMA_FreeDset(odset); odset=NULL;
914 
915    SUMA_RETURN(ngro);
916 }
917 
918 /*!
919    Copies attributes from one dset to another
920    src: Source dset
921    dest: destination dset
922    attrlist: NULL terminated list of attribute names to copy
923    isrc: Column from which attributes should be copied.
924          This is useful for string type attributes
925    idest: Column into which attributes are going
926 
927    Usually you run this function separately for Dsetwide attributes,
928    setting both of isrc and idest to -1
929    Or you run it for SingleColumn or MultiColumn attributes with both
930    isrc and idest properly set.
931 
932 */
SUMA_CopyDsetAttributes(SUMA_DSET * src,SUMA_DSET * dest,char ** attrlist,int isrc,int idest)933 SUMA_Boolean SUMA_CopyDsetAttributes ( SUMA_DSET *src, SUMA_DSET *dest,
934                                        char **attrlist,
935                                        int isrc, int idest )
936 {
937    static char FuncName[]={"SUMA_CopyDsetAttributes"};
938    NI_element *nel=NULL, **nelcp=NULL, *nelt=NULL;
939    NI_group *ngri=NULL, *ngro=NULL, *nicmap=NULL;
940    char *rs=NULL, nmbuf[256], nmbuf2[256],*nm=NULL, *src_string=NULL;
941    int ip=0, iattrlist=-1, inelcp=-1, N_ip=-1, tp=-1, icolsrc=-1, ic=-1;
942    SUMA_Boolean ans = NOPE;
943    SUMA_Boolean LocalHead = NOPE;
944 
945    SUMA_ENTRY;
946 
947    if (!src || !src->ngr || !dest || !dest->ngr) SUMA_RETURN(NOPE);
948 
949    /* now read the elements in this group */
950    ngri = src->ngr;
951    /* allocate for enough attributes to copy */
952    nelcp = (NI_element **)SUMA_calloc(ngri->part_num, sizeof(NI_element *));
953    inelcp = 0;
954    for( ip=0 ; ip < ngri->part_num ; ip++ ){
955       switch( ngri->part_typ[ip] ){
956          /*-- a sub-group ==> recursion! --*/
957          case NI_GROUP_TYPE: /* not quite attributes, but oh well...*/
958             nicmap = (NI_group *)ngri->part[ip] ;
959             SUMA_LH("Have group named %s",nicmap->name);
960             if (  !attrlist ||
961                   SUMA_FindInAttrList(attrlist,nicmap->name, isrc, &iattrlist)) {
962                SUMA_LH("Will copy it");
963                /* make a copy */
964                nicmap = SUMA_NICmapToNICmap(nicmap);
965                if (LocalHead) {
966                   SUMA_ShowNel(nicmap);
967                }
968                NI_add_to_group(dest->ngr, nicmap);
969             }
970             break ;
971          case NI_ELEMENT_TYPE:
972             nel = (NI_element *)ngri->part[ip] ;
973             nm = NI_get_attribute(nel, "atr_name");
974             if (LocalHead > 1)  {
975                fprintf(SUMA_STDERR,
976                         "%s:  src Col %d\n"
977                         "     nel_name:atr_name =%s:%s\n"
978                         "     vec_len=%6d vec_filled=%6d, vec_num=%4d",
979                         FuncName, isrc,
980                         nel->name ? nel->name : "NULL",
981                         nm ? nm : "NULL ",
982                         nel->vec_len, nel->vec_filled, nel->vec_num );
983             }
984             if (SUMA_isDsetNelAttr(nel)) {
985                if( (rs = NI_get_attribute(nel, "atr_name")) ) {
986                   #if 0
987                   if (!attrlist) {
988                      /* No list, copy everything */
989                      nelcp[inelcp] = nel; ++inelcp;
990                      if (LocalHead > 1)  {
991                         fprintf( SUMA_STDERR,
992                                  "      +++++ Added %s (indiscriminate)\n",
993                                  rs);
994                      }
995                   } else {
996                      /* do we have a perfect name match? */
997                      iattrlist = 0;
998                      while (attrlist[iattrlist] && iattrlist >= 0) {
999                         if (!strcmp(attrlist[iattrlist],rs)) {
1000                            /* have a perfect name match */
1001                            nelcp[inelcp] = nel; ++inelcp;
1002                            iattrlist = -1; /* a sign to quit */
1003                         } else {
1004                            ++iattrlist;
1005                         }
1006                      }
1007 
1008                      /* if we do not have a perfect match,
1009                         try the number padded ones */
1010                      if (iattrlist >= 0) {
1011                         iattrlist = 0;
1012                         while (attrlist[iattrlist] && iattrlist >= 0) {
1013                            sprintf(nmbuf,"%s_%06d",attrlist[iattrlist],isrc) ;
1014                            if (!strcmp(nmbuf,rs)) {
1015                               /* have a perfect name match */
1016                               nelcp[inelcp] = nel; ++inelcp;
1017                               iattrlist = -1; /* a sign to quit */
1018                            } else {
1019                               ++iattrlist;
1020                            }
1021                         }
1022                      }
1023                      if (iattrlist < 0) {
1024                         if (LocalHead > 1)  {
1025                            fprintf( SUMA_STDERR,
1026                                     "          +++++ Added %s \n",
1027                                     rs);
1028                         }
1029                      }
1030                   }
1031                   #else
1032                   if (  !attrlist ||
1033                         SUMA_FindInAttrList(attrlist,rs, isrc, &iattrlist)) {
1034                      nelcp[inelcp] = nel; ++inelcp;
1035                      if (LocalHead > 1) {
1036                         if (!attrlist) {
1037                            fprintf( SUMA_STDERR,
1038                                     "  +++++ Added %s (indiscriminate)\n",
1039                                     rs);
1040                         } else {
1041                            fprintf( SUMA_STDERR,
1042                                     "  +++++ Added %s \n",
1043                                     rs);
1044                         }
1045                      }
1046                   }  else {
1047                       if (LocalHead > 1) {
1048                            fprintf( SUMA_STDERR,
1049                                     "  ----- Not added\n"
1050                                     );
1051                       }
1052                   }
1053                   #endif
1054                }
1055             } else if (nel == src->dnel) {
1056                if (  !attrlist ||
1057                      SUMA_FindInAttrList(attrlist,"TR",isrc, &iattrlist)) {
1058                   double TR=-1.0;
1059                   /* check on ni_timetep */
1060                   if (SUMA_is_TimeSeries_dset(src, &TR)) {
1061                      if (LocalHead > 1) {
1062                         fprintf( SUMA_STDERR,
1063                                  "  +++++ Added TR of %f\n",
1064                                  TR);
1065                      }
1066                      if (!SUMA_SetDsetTR(dest, TR)) {
1067                         SUMA_S_Warn("Could not set TR for output");
1068                      }
1069                   }
1070                } else {
1071                   if (LocalHead > 1) {
1072                         fprintf( SUMA_STDERR,
1073                                  "  ooooo Has no attributes\n"
1074                                  );
1075                   }
1076                }
1077             } else {
1078                if (LocalHead > 1) {
1079                         fprintf( SUMA_STDERR,
1080                                  "  ooooo Not an attribute\n"
1081                                  );
1082                }
1083             }
1084             break;
1085          default:
1086             SUMA_SL_Err("Don't know what to make of this\n"
1087                         " group element, ignoring.");
1088             goto OUT;
1089             break;
1090       }
1091    }
1092    if (LocalHead)  {
1093       fprintf( SUMA_STDERR,
1094                "\n"
1095                "%s: Src Col %d\n"
1096                "  Have %d NEL attributes to add to new dset Col %d.\n"
1097                , FuncName, isrc, inelcp, idest);
1098    }
1099 
1100    /* Now you go through the different attributes and add them */
1101    N_ip = inelcp;
1102    for (ip=0; ip<N_ip; ++ip) {
1103       nel = nelcp[ip];
1104       if (!SUMA_ParseAttrName(nel, &tp, &icolsrc, nmbuf)) {
1105          SUMA_S_Err("Should not happen!");
1106          goto OUT;
1107       }
1108       if (icolsrc >= 0 && icolsrc != isrc) {
1109          SUMA_S_Err("Weird index mismatch"); /* This should not be */
1110          goto OUT;
1111       }
1112       /* name of nel in new dset */
1113       if (tp == 1) { sprintf(nmbuf2,"%s_%06d", nmbuf, idest); }
1114       else strcpy(nmbuf2, nmbuf);
1115       if (LocalHead) {
1116          fprintf(SUMA_STDERR,
1117                   "%s:\n"
1118                   "  Have to add %s, type %d, col %d(old) to col %d (new):\n"
1119                   "  Attr name in destination dset: %s\n"
1120                   "  (isMulti %d) (isSingle %d) (isDsetwide %d)\n"
1121                   , FuncName, nmbuf, tp, isrc, idest
1122                   , nmbuf2
1123                   , SUMA_isMultiColumnAttr(nel)
1124                   , SUMA_isSingleColumnAttr(nel, NULL, NULL)
1125                   , SUMA_isDsetwideColumnAttr(nel) );
1126       }
1127       if (tp == 3 && isrc != -1) {
1128          SUMA_S_Err("Cannot add Dsetwide attributes with source column != -1");
1129          goto OUT;
1130       }
1131       /* Do we have this nel in target?*/
1132       nelt = SUMA_FindNgrAttributeElement(dest->ngr,
1133                                           nmbuf2);
1134       if (nelt) {
1135          if (tp == 1 || tp == 3) {
1136             /* single-column or Dsetwide
1137                pre-existing attribute, kill it*/
1138             if (LocalHead) {
1139                fprintf(SUMA_STDERR,
1140                         "%s:\n"
1141                         "  Killing pre-existing %s attribute\n"
1142                         , FuncName, nmbuf2);
1143             }
1144             NI_remove_from_group(dest->ngr, (void *)nelt);
1145             NI_free_element(nelt); nelt = NULL;
1146          } else {
1147             if (LocalHead) {
1148                fprintf(SUMA_STDERR,
1149                         "%s:\n"
1150                         "  Keeping multi-column %s attribute\n"
1151                         , FuncName, nmbuf2);
1152             }
1153          }
1154       }
1155 
1156       if (!nelt) {/* make new one, just like in src dset*/
1157          nelt = NI_new_data_element("AFNI_atr", nel->vec_len);
1158          NI_set_attribute(nelt, "atr_name", nmbuf2);
1159          for (ic=0; ic<nel->vec_num; ++ic) {
1160             NI_add_column_stride (nelt, nel->vec_typ[0], NULL, 1);
1161             NI_add_to_group(dest->ngr, nelt);
1162          }
1163       }
1164 
1165       /* Now nelt exists, need put the data in there */
1166       if (tp == 2) { /* here we have a MultiColumn string type */
1167          if (isrc < 0 || idest < 0) {
1168             SUMA_S_Err("Should not be here!"); goto OUT;
1169          }
1170          src_string =
1171             SUMA_GetDsetColStringAttr( src, isrc,
1172                                        NI_get_attribute(nel, "atr_name"));
1173 
1174          if (LocalHead) {
1175                fprintf(SUMA_STDERR,
1176                         "%s:\n"
1177                         "  Inserting string %s at col %d in target's %s\n"
1178                         , FuncName, src_string, idest, nmbuf2);
1179          }
1180          SUMA_AddColAtt_CompString( nelt, idest,
1181                                     src_string,
1182                                     SUMA_NI_CSS, 0);
1183          if (src_string) SUMA_free(src_string); src_string = NULL;
1184       } else { /* just copy the whole thing */
1185          /* Obviously not a valid operation for something like
1186          HISTORY_NOTE where appending rather than
1187          overwriting is needed */
1188          if (LocalHead) {
1189                fprintf(SUMA_STDERR,
1190                         "%s:\n"
1191                         "  Copy source attribute contents\n"
1192                         , FuncName);
1193          }
1194          for (ic=0; ic<nel->vec_num; ++ic) {
1195             NI_fill_column_stride(nelt, nel->vec_typ[ic],
1196                                   nel->vec[ic], ic, 1);
1197          }
1198       }
1199    }
1200 
1201    ans = YUP;
1202 
1203    OUT:
1204    SUMA_free(nelcp); nelcp = NULL;
1205    SUMA_RETURN(YUP);
1206 }
1207 
SUMA_FindDsetAttributeElement(SUMA_DSET * dset,char * attname)1208 NI_element *SUMA_FindDsetAttributeElement(SUMA_DSET *dset, char *attname)
1209 {
1210    static char FuncName[]={"SUMA_FindDsetAttributeElement"};
1211    int ip;
1212    SUMA_Boolean LocalHead = NOPE;
1213 
1214    SUMA_ENTRY;
1215 
1216    if (!dset || !attname) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
1217    if (!dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
1218 
1219 
1220    SUMA_RETURN(SUMA_FindNgrAttributeElement(dset->ngr, attname));
1221 }
1222 
SUMA_FindNgrAttributeElement(NI_group * ngr,char * attname)1223 NI_element *SUMA_FindNgrAttributeElement(NI_group *ngr, char *attname)
1224 {
1225    static char FuncName[]={"SUMA_FindNgrAttributeElement"};
1226    NI_element *nel = NULL;
1227    char *rs=NULL;
1228    int ip;
1229    SUMA_Boolean LocalHead = NOPE;
1230 
1231    SUMA_ENTRY;
1232 
1233    if (!ngr || !attname) { SUMA_SL_Err("NUll input "); SUMA_RETURN(nel); }
1234 
1235   /* now read the elements in this group */
1236    for( ip=0 ; ip < ngr->part_num ; ip++ ){
1237       if (LocalHead)  {
1238          fprintf( SUMA_STDERR,
1239                   "%s: %d/%d = %d\n",
1240                   FuncName, ip, ngr->part_num, ngr->part_typ[ip]);
1241       }
1242       switch( ngr->part_typ[ip] ){
1243          /*-- a sub-group ==> recursion! --*/
1244          case NI_GROUP_TYPE:
1245             break ;
1246          case NI_ELEMENT_TYPE:
1247             nel = (NI_element *)ngr->part[ip] ;
1248             if (LocalHead)  {
1249                fprintf(SUMA_STDERR,
1250                         "%s:  Looking for %s   name=%s (%d/%d)\n"
1251                         "vec_len=%d vec_filled=%d, vec_num=%d\n",
1252                         FuncName,
1253                         attname, nel->name, ip, ngr->part_num-1,
1254                         nel->vec_len, nel->vec_filled, nel->vec_num );
1255             }
1256             if (!strcmp("AFNI_atr", nel->name)) {/* now in keeping with AFNI */
1257                rs = NI_get_attribute(nel, "atr_name");
1258                if (rs) {
1259                   if (!strcmp(attname, rs)) {
1260                      SUMA_RETURN(nel);
1261                   }
1262                }
1263             }
1264             /* cancel plans if you get here */
1265             nel = NULL;
1266             break;
1267          default:
1268             SUMA_SL_Err(
1269                "Don't know what to make of this group element, ignoring.");
1270             if (LocalHead) {
1271                fprintf(SUMA_STDERR,"%s: type = %d (know of %d and %d only)!\n",
1272                                     FuncName, ngr->part_typ[ip],
1273                                     NI_GROUP_TYPE, NI_ELEMENT_TYPE);
1274             }
1275             break;
1276       }
1277    }
1278 
1279    SUMA_RETURN(nel);
1280 }
1281 
1282 /*! \brief Return the attribute that contains the set of unique values
1283             in a column
1284 */
SUMA_GetUniqueValsAttr(SUMA_DSET * dset,int icol)1285 NI_element * SUMA_GetUniqueValsAttr(SUMA_DSET *dset, int icol)
1286 {
1287    static char FuncName[]={"SUMA_GetUniqueValsAttr"};
1288    char aname[256];
1289    NI_element *nel=NULL;
1290    SUMA_Boolean LocalHead = NOPE;
1291 
1292    SUMA_ENTRY;
1293 
1294    if (!dset || !dset->ngr) SUMA_RETURN(nel);
1295 
1296    sprintf(aname, "UNIQUE_VALS_%06d", icol);
1297    nel = SUMA_FindDsetAttributeElement (dset, aname);
1298 
1299    SUMA_RETURN(nel);
1300 }
1301 
SUMA_GetUniqueIndicesAttr(SUMA_DSET * dset,int iindex)1302 NI_element * SUMA_GetUniqueIndicesAttr(SUMA_DSET *dset, int iindex)
1303 {
1304    static char FuncName[]={"SUMA_GetUniqueIndicesAttr"};
1305    char aname[256];
1306    NI_element *nel=NULL;
1307    SUMA_Boolean LocalHead = NOPE;
1308 
1309    SUMA_ENTRY;
1310 
1311    if (!dset || !dset->ngr) SUMA_RETURN(nel);
1312 
1313    sprintf(aname, "UNIQUE_INDICES_%06d", iindex);
1314    nel = SUMA_FindDsetAttributeElement (dset, aname);
1315 
1316    SUMA_RETURN(nel);
1317 }
1318 
SUMA_GetUniqueIndicesVec(SUMA_DSET * dset,int iindex)1319 int * SUMA_GetUniqueIndicesVec(SUMA_DSET *dset, int iindex)
1320 {
1321    static char FuncName[]={"SUMA_GetUniqueIndicesVec"};
1322    NI_element *nel=NULL;
1323    SUMA_Boolean LocalHead = NOPE;
1324 
1325    SUMA_ENTRY;
1326 
1327    if (!(nel = SUMA_GetUniqueIndicesAttr(dset, iindex))) SUMA_RETURN(NULL);
1328 
1329    SUMA_RETURN((int *)nel->vec[0]);
1330 }
1331 
SUMA_GetDatasetDimensions(SUMA_DSET * dset)1332 int * SUMA_GetDatasetDimensions(SUMA_DSET *dset)
1333 {
1334    static char FuncName[]={"SUMA_GetDatasetDimensions"};
1335    NI_element *nel=NULL;
1336    static int v[10][5];
1337    static int ncall = 0;
1338 
1339    SUMA_ENTRY;
1340 
1341    ++ncall; if (ncall > 9) ncall = 0;
1342 
1343    if (!dset) {
1344       v[ncall][0] = -1; SUMA_RETURN(v[ncall]);
1345    }
1346 
1347    if (!(nel = SUMA_FindDsetAttributeElement (dset, "DATASET_DIMENSIONS"))) {
1348       v[ncall][0] = SDSET_VECLEN(dset);
1349       v[ncall][1] = 0; v[ncall][2] = 0; v[ncall][3] = 0; v[ncall][4] = 0;
1350       SUMA_RETURN(v[ncall]);
1351    }
1352 
1353    SUMA_RETURN((int *)nel->vec[0]);
1354 }
1355 
SUMA_GetDatasetFactors(SUMA_DSET * dset)1356 float * SUMA_GetDatasetFactors(SUMA_DSET *dset)
1357 {
1358    static char FuncName[]={"SUMA_GetDatasetFactors"};
1359    NI_element *nel=NULL;
1360 
1361    SUMA_ENTRY;
1362 
1363 
1364    if (!dset) {
1365       SUMA_RETURN(NULL);
1366    }
1367 
1368    if (!(nel = SUMA_FindDsetAttributeElement (dset, "BRICK_FLOAT_FACS"))) {
1369       SUMA_RETURN(NULL);
1370    }
1371    SUMA_RETURN((float *)nel->vec[0]);
1372 }
1373 
SUMA_GetBrickFactor(SUMA_DSET * dset,int ii)1374 float SUMA_GetBrickFactor(SUMA_DSET *dset, int ii)
1375 {
1376    static char FuncName[]={"SUMA_GetBrickFactor"};
1377    float *vv = NULL;
1378 
1379    SUMA_ENTRY;
1380 
1381    if (!dset || ii < 0 || ii >= SDSET_VECNUM(dset)) SUMA_RETURN(0.0);
1382 
1383    if (!(vv = SUMA_GetDatasetFactors(dset))) SUMA_RETURN(0.0);
1384 
1385    SUMA_RETURN(vv[ii]);
1386 }
1387 
SUMA_GetBrickType(SUMA_DSET * dset,int ii)1388 MRI_TYPE SUMA_GetBrickType(SUMA_DSET *dset, int ii)
1389 {
1390    static char FuncName[]={"SUMA_GetBrickType"};
1391    SUMA_COL_TYPE ctp;
1392    SUMA_VARTYPE vtp;
1393 
1394    SUMA_ENTRY;
1395 
1396    if (!dset || ii < 0 || ii >= SDSET_VECNUM(dset)) SUMA_RETURN(0.0);
1397 
1398    ctp = SUMA_TypeOfDsetColNumb(dset, ii);
1399    vtp = SUMA_ColType2TypeCast(ctp) ;
1400    switch (vtp) {
1401       case SUMA_short:
1402          SUMA_RETURN(MRI_short);
1403       case SUMA_byte:
1404          SUMA_RETURN(MRI_byte);
1405       case SUMA_float:
1406          SUMA_RETURN(MRI_float);
1407       case SUMA_complex:
1408          SUMA_RETURN(MRI_complex);
1409       case SUMA_double:
1410          SUMA_RETURN(MRI_double);
1411       default:
1412          SUMA_RETURN(-1);
1413    }
1414 
1415    SUMA_RETURN(-1);
1416 }
1417 
SUMA_GetDatasetI2X(SUMA_DSET * dset,float M[4][4])1418 float * SUMA_GetDatasetI2X(SUMA_DSET *dset, float M[4][4])
1419 {
1420    static char FuncName[]={"SUMA_GetDatasetI2X"};
1421    NI_element *nel=NULL;
1422    float *v;
1423 
1424    SUMA_ENTRY;
1425 
1426 
1427    if (!dset) {
1428       SUMA_RETURN(NULL);
1429    }
1430 
1431    if (!(nel = SUMA_FindDsetAttributeElement (dset, "IJK_TO_DICOM_REAL"))) {
1432       SUMA_RETURN(NULL);
1433    }
1434 
1435    if ((v = (float *)nel->vec[0])) {
1436       V12_TO_AFF44(M, v);
1437    }
1438    SUMA_RETURN(v);
1439 }
1440 
SUMA_isVolDataset(SUMA_DSET * dset)1441 int SUMA_isVolDataset(SUMA_DSET *dset)
1442 {
1443    int *dims = 0;
1444 
1445    if (!dset) return(0);
1446    if ((dims = SUMA_GetDatasetDimensions(dset))) {
1447       if (dims[1]>1) return(1);
1448    }
1449    return(0);
1450 }
1451 
SUMA_GetAtlasLabelTable(SUMA_DSET * dset)1452 NI_element * SUMA_GetAtlasLabelTable(SUMA_DSET *dset)
1453 {
1454    static char FuncName[]={"SUMA_GetAtlasLabelTable"};
1455    NI_element *nel=NULL;
1456    SUMA_Boolean LocalHead = NOPE;
1457    SUMA_ENTRY;
1458    /* This is for volumes only */
1459    nel = SUMA_FindDsetAttributeElement (dset, "ATLAS_LABEL_TABLE");
1460    SUMA_LH("ATLAS_LABEL_TABLE  nel:%p", nel);
1461    SUMA_RETURN(nel);
1462 }
1463 
SUMA_GetValueLabelTable(SUMA_DSET * dset)1464 NI_element * SUMA_GetValueLabelTable(SUMA_DSET *dset)
1465 {
1466    static char FuncName[]={"SUMA_GetValueLabelTable"};
1467    NI_element *nel=NULL;
1468    SUMA_Boolean LocalHead = NOPE;
1469    SUMA_ENTRY;
1470    /* This is for volumes only */
1471    nel = SUMA_FindDsetAttributeElement (dset, "VALUE_LABEL_DTABLE");
1472    SUMA_LH("VALUE_LABEL_DTABLE  nel:%p", nel);
1473    SUMA_RETURN(nel);
1474 }
1475 
1476 
1477 /*! \brief Add an attribute that contains the set of unique values
1478             in a column
1479 */
1480 
SUMA_SetUniqueValsAttr(SUMA_DSET * dset,int icol,byte replace)1481 SUMA_Boolean SUMA_SetUniqueValsAttr(SUMA_DSET *dset, int icol, byte replace)
1482 {
1483    static char FuncName[]={"SUMA_SetUniqueValsAttr"};
1484    int *unq=NULL, N_unq=0, i=0;
1485    char aname[256];
1486    NI_element *nel=NULL;
1487    SUMA_Boolean LocalHead = NOPE;
1488 
1489    SUMA_ENTRY;
1490 
1491    if (!dset || !dset->ngr) SUMA_RETURN(NOPE);
1492 
1493    sprintf(aname, "UNIQUE_VALS_%06d", icol);
1494    nel = SUMA_FindDsetAttributeElement (dset, aname);
1495    if (nel) {
1496       if (!replace) SUMA_RETURN(YUP);
1497       else {
1498          /* adios */
1499          NI_remove_from_group(dset->ngr, nel); NI_free_element(nel); nel=NULL;
1500       }
1501    }
1502    if (nel) {
1503       SUMA_S_Err("Should not be here");
1504       SUMA_RETURN(NOPE);
1505    }
1506 
1507    switch(SUMA_ColType2TypeCast(SUMA_TypeOfDsetColNumb(dset, icol))) {
1508       case  SUMA_byte: {
1509          byte *bunq=NULL;
1510          if (!(bunq =  UniqueByte ( SDSET_VEC(dset, icol), SDSET_VECLEN(dset),
1511                                        &N_unq, 0))) {
1512             SUMA_S_Err("Failed to get unique values");
1513             SUMA_RETURN(NOPE);
1514          }
1515          unq = (int *)SUMA_malloc(N_unq*sizeof(int));
1516          for (i=0; i<N_unq; ++i) unq[i] = bunq[i];
1517          SUMA_ifree(bunq);
1518          break; }
1519       case SUMA_int:
1520          if (!(unq =  UniqueInt ( SDSET_VEC(dset, icol), SDSET_VECLEN(dset),
1521                                        &N_unq, 0))) {
1522             SUMA_S_Err("Failed to get unique values");
1523             SUMA_RETURN(NOPE);
1524          }
1525          break;
1526       case SUMA_short: {
1527          short *sunq=NULL;
1528          if (!(sunq =  UniqueShort ( SDSET_VEC(dset, icol), SDSET_VECLEN(dset),
1529                                      &N_unq, 0))) {
1530             SUMA_S_Err("Failed to get unique values");
1531             SUMA_RETURN(NOPE);
1532          }
1533          unq = (int *)SUMA_malloc(N_unq*sizeof(int));
1534          for (i=0; i<N_unq; ++i) unq[i] = sunq[i];
1535          SUMA_ifree(sunq);
1536          break; }
1537       default:
1538          SUMA_S_Err("Bad column type %d for unique values",
1539                   SUMA_TypeOfDsetColNumb(dset, icol));
1540          SUMA_RETURN(NOPE);
1541          break;
1542    }
1543    nel = NI_new_data_element("AFNI_atr", N_unq);
1544    NI_set_attribute(nel, "atr_name", aname);
1545    NI_add_column_stride(nel, NI_INT, (void *)unq, 1);
1546    free(unq); unq=NULL;
1547 
1548    NI_add_to_group(dset->ngr, nel);
1549 
1550    SUMA_RETURN(YUP);
1551 }
1552 
SUMA_SetUniqueIndicesAttr(SUMA_DSET * dset,byte replace)1553 SUMA_Boolean SUMA_SetUniqueIndicesAttr(SUMA_DSET *dset, byte replace)
1554 {
1555    static char FuncName[]={"SUMA_SetUniqueIndicesAttr"};
1556    int *unq=NULL, N_unq=0, icol=0;
1557    char aname[256];
1558    NI_element *nel=NULL;
1559    SUMA_Boolean LocalHead = NOPE;
1560 
1561    SUMA_ENTRY;
1562 
1563    if (!dset || !dset->ngr || !dset->inel) SUMA_RETURN(NOPE);
1564 
1565    for (icol = 0; icol < dset->inel->vec_num; ++icol) {
1566       SUMA_LHv("Working col %d\n", icol);
1567       sprintf(aname, "UNIQUE_INDICES_%06d", icol);
1568       nel = SUMA_FindDsetAttributeElement (dset, aname);
1569       if (nel) {
1570          if (!replace) SUMA_RETURN(YUP);
1571          else {
1572             /* adios */
1573             NI_remove_from_group(dset->ngr, nel); NI_free_element(nel); nel=NULL;
1574          }
1575       }
1576       if (nel) {
1577          SUMA_S_Err("Should not be here");
1578          SUMA_RETURN(NOPE);
1579       }
1580       if (!(unq =  UniqueInt ( dset->inel->vec[icol], dset->inel->vec_len,
1581                                     &N_unq, 0))) {
1582          SUMA_S_Err("Failed to get unique values");
1583          SUMA_RETURN(NOPE);
1584       }
1585 
1586       SUMA_LHv("%d unique values for col %d\n", N_unq, icol);
1587       nel = NI_new_data_element("AFNI_atr", N_unq);
1588       NI_set_attribute(nel, "atr_name", aname);
1589       NI_add_column_stride(nel, NI_INT, (void *)unq, 1);
1590       free(unq); unq=NULL;
1591 
1592       NI_add_to_group(dset->ngr, nel);
1593    }
1594    SUMA_RETURN(YUP);
1595 }
1596 
1597 /*!
1598    Add an attribute element to a data set, to be called after adding a column to the data element
1599    The old version of this is SUMA_AddColAttr
1600    \sa SUMA_AddDsetNodeIndexColAttr for special SUMA_NODE_INDEX ctp
1601 */
SUMA_AddDsetColAttr(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col_attr,int col_index,int insert_mode)1602 int SUMA_AddDsetColAttr (  SUMA_DSET *dset, char *col_label,
1603                            SUMA_COL_TYPE ctp, void *col_attr,
1604                            int col_index, int insert_mode)
1605 {
1606    static char FuncName[]={"SUMA_AddDsetColAttr"};
1607    NI_element *nelb = NULL;
1608    char Name[500], Attr[500], *attrstr=NULL;
1609    SUMA_Boolean LocalHead = NOPE;
1610 
1611    SUMA_ENTRY;
1612 
1613    if (SUMA_IS_DATUM_INDEX_COL(ctp) || SUMA_IS_MD_DATUM_INDEX_COL(ctp)) {
1614       SUMA_RETURN(
1615          SUMA_AddDsetNodeIndexColAttr (dset, col_label, ctp, col_attr));
1616    }
1617 
1618    if (SUMA_isGraphDset(dset) && SUMA_IS_GNODE_IXYZ_COL(ctp)) {
1619       SUMA_RETURN(SUMA_AddGDsetNodeXYZColAttr (dset, col_label, ctp, col_attr));
1620    }
1621 
1622    if (!dset) SUMA_RETURN(0);
1623    if (col_index < 0) col_index = SDSET_VECNUM(dset)-1;
1624    if (col_index < 0 || !SDSET_VECNUM(dset) ) {
1625       SUMA_SL_Err("No columns in data set's data element!"); SUMA_RETURN(0); }
1626    if (SDSET_VECNUM(dset) <= col_index) {
1627       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
1628 
1629    /* has the column label element been added yet ?*/
1630    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_LABS");
1631    if (!nelb) { /* need to form this element */
1632       nelb = NI_new_data_element("AFNI_atr", 1);
1633       NI_set_attribute(nelb,"atr_name", "COLMS_LABS");
1634       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
1635       NI_add_to_group(dset->ngr, nelb);
1636    }
1637    SUMA_AddColAtt_CompString( nelb, col_index, col_label,
1638                               SUMA_NI_CSS, insert_mode);
1639 
1640    /* has the column type element been added yet ? */
1641    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_TYPE");
1642    if (!nelb) { /* need to form this element */
1643       nelb = NI_new_data_element("AFNI_atr", 1);
1644       NI_set_attribute(nelb,"atr_name", "COLMS_TYPE");
1645       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
1646       NI_add_to_group(dset->ngr, nelb);
1647    }
1648    /* set the type */
1649    SUMA_AddColAtt_CompString( nelb, col_index, SUMA_Col_Type_Name(ctp),
1650                               SUMA_NI_CSS, insert_mode);
1651 
1652    /* set the Col_STATSYM
1653       (SPECIAL CASE: USE THE ; rather than the ~ . The story is complicated) */
1654    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_STATSYM");
1655    if (!nelb) { /* need to form this element */
1656       nelb = NI_new_data_element("AFNI_atr", 1);
1657       NI_set_attribute(nelb,"atr_name", "COLMS_STATSYM");
1658       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
1659       NI_add_to_group(dset->ngr, nelb);
1660    }
1661    /* set the attribute string */
1662    switch (ctp) {
1663       default:
1664          attrstr = SUMA_copy_string("none");
1665          break;
1666 
1667       case SUMA_NODE_XCORR:
1668          if (col_attr){
1669             float *pars = (float *)col_attr;
1670             SUMA_LH("%s",
1671                NI_stat_encode(NI_STAT_CORREL, pars[0], pars[1], pars[2]));
1672             attrstr = SUMA_copy_string(
1673                         NI_stat_encode(NI_STAT_CORREL,
1674                                        pars[0], pars[1], pars[2]));
1675          } else {
1676             attrstr = SUMA_copy_string("none");
1677          }
1678          break;
1679 
1680       case SUMA_NODE_ZSCORE:
1681          attrstr = SUMA_copy_string(
1682                         NI_stat_encode(NI_STAT_ZSCORE, 0.0 , 0.0, 0.0));
1683 
1684          break;
1685    }
1686 
1687    SUMA_AddColAtt_CompString( nelb, col_index, attrstr,
1688                               SUMA_NI_CSS, insert_mode);
1689             /* See confusing note following AFNI_NI_CSS in SUMA_DataSets.h */
1690    if (attrstr) SUMA_free(attrstr); attrstr = NULL;
1691 
1692    SUMA_RETURN(1);
1693 }
1694 
1695 /*!
1696    \brief a special version of SUMA_AddDsetColAttr for node index column
1697 */
SUMA_AddDsetNodeIndexColAttr(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col_attr)1698 int SUMA_AddDsetNodeIndexColAttr (SUMA_DSET *dset, char *col_label,
1699                                   SUMA_COL_TYPE ctp, void *col_attr)
1700 {
1701    static char FuncName[]={"SUMA_AddDsetNodeIndexColAttr"};
1702    NI_element *nelb = NULL;
1703    char *attrstr=NULL, *stmp=NULL;
1704    SUMA_Boolean LocalHead = NOPE;
1705 
1706    SUMA_ENTRY;
1707 
1708    if (!SUMA_IS_DATUM_INDEX_COL(ctp) && !SUMA_IS_MD_DATUM_INDEX_COL(ctp)) {
1709       SUMA_S_Err("Don't call me like that");
1710       SUMA_RETURN(0);
1711    }
1712 
1713    if (!dset || !dset->inel || !SDSET_NODEINDLEN(dset)) SUMA_RETURN(0);
1714 
1715    stmp = SUMA_copy_string(NI_get_attribute(dset->inel,"COLMS_LABS"));
1716    if (!SUMA_Set_Sub_String(&stmp, SUMA_NI_CSS,
1717                             SUMA_DATUM_INDEX_CTP2COL(ctp), col_label)) {
1718       SUMA_S_Warnv("Failed to set substring for COLMS_LABS at %d\n",
1719                    SUMA_DATUM_INDEX_CTP2COL(ctp));
1720    }
1721    if (stmp) {
1722       NI_set_attribute(dset->inel, "COLMS_LABS", stmp);
1723       SUMA_free(stmp); stmp=NULL;
1724    }
1725 
1726    stmp = SUMA_copy_string(NI_get_attribute(dset->inel,"COLMS_TYPE"));
1727    if (!SUMA_Set_Sub_String(&stmp, SUMA_NI_CSS, SUMA_DATUM_INDEX_CTP2COL(ctp),
1728                             SUMA_Col_Type_Name(ctp))) {
1729       SUMA_S_Warnv("Failed to set substring for COLMS_TYPE at %d\n",
1730                    SUMA_DATUM_INDEX_CTP2COL(ctp));
1731    }
1732    if (stmp) {
1733       NI_set_attribute(dset->inel, "COLMS_TYPE", stmp);
1734       SUMA_free(stmp); stmp=NULL;
1735    }
1736 
1737    SUMA_RETURN(1);
1738 }
1739 
SUMA_AddGDsetNodeXYZColAttr(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col_attr)1740 int SUMA_AddGDsetNodeXYZColAttr (SUMA_DSET *dset, char *col_label,
1741                                 SUMA_COL_TYPE ctp, void *col_attr)
1742 {
1743    static char FuncName[]={"SUMA_AddGDsetNodeXYZColAttr"};
1744    NI_element *xyznel = NULL;
1745    char *attrstr=NULL, *stmp=NULL;
1746    SUMA_Boolean LocalHead = NOPE;
1747 
1748    SUMA_ENTRY;
1749 
1750    if (!SUMA_IS_GNODE_IXYZ_COL(ctp)) {
1751       SUMA_S_Err("Don't call me like that");
1752       SUMA_RETURN(0);
1753    }
1754 
1755    if (!dset || !SDSET_NODEINDLEN(dset)) SUMA_RETURN(0);
1756 
1757    if (!SUMA_isGraphDset(dset)) {
1758       SUMA_SL_Err("Null or bad input");
1759       SUMA_RETURN(0);
1760    }
1761 
1762    if (!(xyznel = SUMA_FindGDsetNodeListElement(dset))) {
1763       SUMA_S_Err("No nodelist element");
1764       SUMA_RETURN(0);
1765    }
1766 
1767    stmp = SUMA_copy_string(NI_get_attribute(xyznel,"COLMS_LABS"));
1768    if (!SUMA_Set_Sub_String(&stmp, SUMA_NI_CSS,
1769                             SUMA_GNODE_IXYZ_CTP2COL(ctp), col_label)) {
1770       SUMA_S_Warnv("Failed to set substring for COLMS_LABS at %d\n",
1771                    SUMA_IS_GNODE_IXYZ_COL(ctp));
1772    }
1773    if (stmp) {
1774       NI_set_attribute(xyznel, "COLMS_LABS", stmp);
1775       SUMA_free(stmp); stmp=NULL;
1776    }
1777 
1778    stmp = SUMA_copy_string(NI_get_attribute(xyznel,"COLMS_TYPE"));
1779    if (!SUMA_Set_Sub_String(&stmp, SUMA_NI_CSS, SUMA_GNODE_IXYZ_CTP2COL(ctp),
1780                             SUMA_Col_Type_Name(ctp))) {
1781       SUMA_S_Warnv("Failed to set substring for COLMS_TYPE at %d\n",
1782                    SUMA_IS_GNODE_IXYZ_COL(ctp));
1783    }
1784    if (stmp) {
1785       NI_set_attribute(xyznel, "COLMS_TYPE", stmp);
1786       SUMA_free(stmp); stmp=NULL;
1787    }
1788 
1789    SUMA_RETURN(1);
1790 }
1791 
1792 /*!
1793 
1794    Adds an attribute to nel for that explains the last added column's
1795    contents. You should call this function after each SUMA_AddNelCol call
1796    col_attr (void *) is a pointer to a structure containing special
1797    attributes of the data in the last column added. At the moment,
1798    this pointer is not being used, but you can imagine needing it if
1799    you have to store certain stats or parameters that go with each column.
1800 
1801 */
SUMA_AddColAttr(NI_element * nel,char * col_label,SUMA_COL_TYPE ctp,void * col_attr,int col_index)1802 int SUMA_AddColAttr (NI_element *nel, char *col_label, SUMA_COL_TYPE ctp,
1803                      void *col_attr, int col_index)
1804 {
1805    static char FuncName[]={"SUMA_AddColAttr"};
1806    char Name[500], Attr[500];
1807 
1808    SUMA_ENTRY;
1809 
1810    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
1811 
1812    if (!nel) SUMA_RETURN(0);
1813    if (col_index < 0) col_index = nel->vec_num-1;
1814    if (col_index < 0 || !nel->vec_num ) {
1815       SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0);
1816    }
1817    if (nel->vec_num <= col_index) {
1818       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0);
1819    }
1820 
1821    /* if a label is specified, set it */
1822    if (col_label) {
1823       sprintf(Name, "LabelCol_%d", col_index);
1824       NI_set_attribute ( nel, Name, col_label);
1825    }
1826    /* save the type of the column */
1827    sprintf(Name, "TypeCol_%d", col_index);
1828    NI_set_attribute ( nel, Name, SUMA_Col_Type_Name(ctp));
1829 
1830    sprintf(Attr, "AttrCol_%d", col_index);
1831    switch (ctp) {
1832       case SUMA_NODE_BYTE:
1833          NI_set_attribute ( nel, Attr, NULL);
1834          break;
1835 
1836       case SUMA_NODE_DOUBLE:
1837          NI_set_attribute ( nel, Attr, NULL);
1838          break;
1839 
1840       case SUMA_NODE_COMPLEX:
1841          NI_set_attribute ( nel, Attr, NULL);
1842          break;
1843 
1844       case SUMA_NODE_INDEX:
1845          /* form the string of attributes for this column */
1846          NI_set_attribute ( nel, Attr, NULL);
1847          break;
1848 
1849       case SUMA_MD_NODE_INDEX:
1850          /* form the string of attributes for this column */
1851          NI_set_attribute ( nel, Attr, NULL);
1852          break;
1853 
1854       case SUMA_NODE_INT:
1855          NI_set_attribute ( nel, Attr, NULL);
1856          break;
1857 
1858       case SUMA_NODE_SHORT:
1859          NI_set_attribute ( nel, Attr, NULL);
1860          break;
1861 
1862       case SUMA_NODE_ILABEL:
1863          NI_set_attribute ( nel, Attr, NULL);
1864          break;
1865 
1866       case SUMA_GNODE_IGROUP:
1867          NI_set_attribute ( nel, Attr, NULL);
1868          break;
1869 
1870       case SUMA_NODE_SLABEL:
1871          NI_set_attribute ( nel, Attr, NULL);
1872          break;
1873 
1874       case SUMA_NODE_X:
1875          NI_set_attribute ( nel, Attr, NULL);
1876          break;
1877 
1878       case SUMA_NODE_Y:
1879          NI_set_attribute ( nel, Attr, NULL);
1880          break;
1881 
1882       case SUMA_NODE_Z:
1883          NI_set_attribute ( nel, Attr, NULL);
1884          break;
1885 
1886       case SUMA_NODE_R:
1887          NI_set_attribute ( nel, Attr, NULL);
1888          break;
1889 
1890       case SUMA_NODE_G:
1891          NI_set_attribute ( nel, Attr, NULL);
1892          break;
1893 
1894       case SUMA_NODE_B:
1895          NI_set_attribute ( nel, Attr, NULL);
1896          break;
1897 
1898       case SUMA_NODE_A:
1899          NI_set_attribute ( nel, Attr, NULL);
1900          break;
1901 
1902       case SUMA_NODE_Rb:
1903          NI_set_attribute ( nel, Attr, NULL);
1904          break;
1905 
1906       case SUMA_NODE_Gb:
1907          NI_set_attribute ( nel, Attr, NULL);
1908          break;
1909 
1910       case SUMA_NODE_Bb:
1911          NI_set_attribute ( nel, Attr, NULL);
1912          break;
1913 
1914       case SUMA_NODE_Ab:
1915          NI_set_attribute ( nel, Attr, NULL);
1916          break;
1917 
1918       case SUMA_NODE_FLOAT:
1919          NI_set_attribute ( nel, Attr, NULL);
1920          break;
1921 
1922       case SUMA_NODE_3C:
1923          NI_set_attribute ( nel, Attr, NULL);
1924          break;
1925 
1926       case SUMA_NODE_STRING:
1927          NI_set_attribute ( nel, Attr, NULL);
1928          break;
1929 
1930       case SUMA_NODE_CX:
1931          NI_set_attribute ( nel, Attr, NULL);
1932          break;
1933 
1934       case SUMA_NODE_VFR:
1935          NI_set_attribute ( nel, Attr, NULL);
1936          break;
1937 
1938       case SUMA_NODE_PHASE:
1939          NI_set_attribute ( nel, Attr, NULL);
1940          break;
1941 
1942       case SUMA_NODE_AREA:
1943          NI_set_attribute ( nel, Attr, NULL);
1944          break;
1945 
1946       case SUMA_NODE_VOLUME:
1947          NI_set_attribute ( nel, Attr, NULL);
1948          break;
1949 
1950       case SUMA_NODE_THICKNESS:
1951          NI_set_attribute ( nel, Attr, NULL);
1952          break;
1953 
1954       default:
1955          NI_set_attribute ( nel, Attr, NULL);
1956          break;
1957    }
1958 
1959    SUMA_allow_nel_use(0);
1960 
1961    SUMA_RETURN(1);
1962 }
1963 
1964 /*!
1965    Adds some generic attributes.
1966    For the moment, the range is added for numeric columns
1967    if col_index is -1, then it is assumed that the attributes are
1968       for the latest column added (vec_num -1)
1969    \sa SUMA_AddGenDsetNodeIndexColAttr for the special case of the
1970       node index column
1971 */
SUMA_AddGenDsetColAttr(SUMA_DSET * dset,SUMA_COL_TYPE ctp,void * col,int stride,int col_index,int insert_mode)1972 int SUMA_AddGenDsetColAttr (  SUMA_DSET *dset, SUMA_COL_TYPE ctp,
1973                               void *col, int stride, int col_index,
1974                               int insert_mode)
1975 {
1976    static char FuncName[]={"SUMA_AddGenDsetColAttr"};
1977    char **junk, *stmp, *curstring = NULL;
1978    NI_element *nelb = NULL;
1979    SUMA_Boolean LocalHead = NOPE;
1980 
1981    SUMA_ENTRY;
1982 
1983    if (SUMA_IS_DATUM_INDEX_COL(ctp) || SUMA_IS_MD_DATUM_INDEX_COL(ctp)) {
1984       SUMA_RETURN(SUMA_AddGenDsetNodeIndexColAttr (dset, ctp, col, stride) );
1985    }
1986 
1987    if (SUMA_isGraphDset(dset) && SUMA_IS_GNODE_IXYZ_COL(ctp)) {
1988       SUMA_RETURN(SUMA_AddGenGDsetNodeXYZColAttr (dset, ctp, col, stride));
1989    }
1990 
1991    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
1992    if (col_index < 0) col_index = SDSET_VECNUM(dset)-1;
1993    if (col_index < 0 || !SDSET_VECNUM(dset) ) {
1994       SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
1995    if (SDSET_VECNUM(dset) <= col_index) {
1996       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
1997 
1998    /* does the range attribute element exist ? */
1999    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_RANGE");
2000    if (!nelb) { /* need to form this element */
2001       SUMA_LH("Need to create ranges element");
2002       nelb = NI_new_data_element("AFNI_atr", 1); /* one long string */
2003       NI_set_attribute(nelb, "atr_name", "COLMS_RANGE");
2004       NI_add_to_group(dset->ngr, nelb);
2005       #if 0 /* trying to work with NI_insert */
2006       { int i ; junk = (char **)SUMA_calloc(300,sizeof(char*));
2007          for (i=0; i< 300; ++i)
2008             junk[i] = (char *)SUMA_calloc(300, sizeof(char));
2009          for (i=0; i<50; ++i) sprintf(junk[i], "Hello Baby Joannne ro"); }
2010       NI_add_column_stride ( nelb, NI_STRING, junk, 1 );
2011       #else
2012          NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
2013       #endif
2014       if (LocalHead) SUMA_ShowNel((void*)nelb);
2015       curstring = NULL;
2016    } else {
2017       SUMA_LH("Ranges element found, getting previous string");
2018       SUMA_NEL_GET_STRING(nelb, 0, 0, curstring);
2019    }
2020    if (!col) {
2021       SUMA_LH("No data");
2022       /* Do not complain, that is not a bad thing.
2023       People can use this to allocate for a column
2024       without filling it up */
2025       stmp = SUMA_copy_string("0 0 -1 -1");
2026    } else {
2027       SUMA_LH("Calculating range");
2028       if (!(stmp = SUMA_CreateDsetColRangeCompString(dset, col_index, ctp))) {
2029          SUMA_S_Err("Failed to calculate range");
2030          SUMA_RETURN(0);
2031       }
2032    }
2033 
2034 
2035    SUMA_AddColAtt_CompString(nelb, col_index, stmp, SUMA_NI_CSS, insert_mode);
2036    if (LocalHead) SUMA_ShowNel((void*)nelb);
2037    SUMA_free(stmp); stmp = NULL;
2038    SUMA_RETURN(1);
2039 }
2040 
SUMA_UpdateDsetColRange(SUMA_DSET * dset,int icol)2041 int SUMA_UpdateDsetColRange(SUMA_DSET *dset, int icol)
2042 {
2043    static char FuncName[]={"SUMA_UpdateDsetColRange"};
2044    int ic=0, istrt=0, iend=0;
2045    char *sbuf=NULL;
2046    SUMA_Boolean LocalHead=NOPE;
2047 
2048    SUMA_ENTRY;
2049 
2050    if (!dset) SUMA_RETURN(0);
2051    if (icol < 0) { istrt=0; iend=SDSET_VECNUM(dset); }
2052    else { istrt = icol; iend=icol+1; }
2053    if (istrt < 0 || istrt > SDSET_VECNUM(dset)) SUMA_RETURN(0);
2054    if (iend  < 0 || iend > SDSET_VECNUM(dset)) SUMA_RETURN(0);
2055 
2056    for (ic=istrt; ic<iend; ++ic) {
2057       if(!(sbuf = SUMA_CreateDsetColRangeCompString(dset, ic,
2058                               SUMA_TypeOfDsetColNumb(dset,ic)))) {
2059          SUMA_S_Err("Failed to calculate range");
2060          SUMA_RETURN(0);
2061       }else {
2062          NI_element *nelb =
2063             SUMA_FindDsetAttributeElement(dset, "COLMS_RANGE");
2064          SUMA_LH("%s", sbuf);
2065          SUMA_AddColAtt_CompString(nelb, ic, sbuf, SUMA_NI_CSS,0);
2066          SUMA_free(sbuf); sbuf=NULL;
2067       }
2068    }
2069    SUMA_RETURN(1);
2070 }
2071 
SUMA_UpdateDsetColLabel(SUMA_DSET * dset,int icol,char * label)2072 int SUMA_UpdateDsetColLabel(SUMA_DSET *dset, int icol, char *label)
2073 {
2074    static char FuncName[]={"SUMA_UpdateDsetColLabel"};
2075    int ic=0, istrt=0, iend=0;
2076    char *sbuf=NULL;
2077    SUMA_Boolean LocalHead=NOPE;
2078 
2079    SUMA_ENTRY;
2080 
2081    if (!dset || !label) SUMA_RETURN(0);
2082    if (icol < 0) { istrt=0; iend=SDSET_VECNUM(dset); }
2083    else { istrt = icol; iend=icol+1; }
2084    if (istrt < 0 || istrt > SDSET_VECNUM(dset)) SUMA_RETURN(0);
2085    if (iend  < 0 || iend > SDSET_VECNUM(dset)) SUMA_RETURN(0);
2086 
2087    for (ic=istrt; ic<iend; ++ic) {
2088       {
2089          NI_element *nelb =
2090             SUMA_FindDsetAttributeElement(dset, "COLMS_LABS");
2091          SUMA_LH("%d: %s", ic, label);
2092          SUMA_AddColAtt_CompString(nelb, ic, label, SUMA_NI_CSS,0);
2093       }
2094    }
2095    SUMA_RETURN(1);
2096 }
2097 
2098 /*!
2099    \brief A special case of  SUMA_AddGenDsetColAttr for node indices
2100 
2101    Now OK with Graph Dsets
2102 */
SUMA_AddGenDsetNodeIndexColAttr(SUMA_DSET * dset,SUMA_COL_TYPE ctp,void * col,int stride)2103 int SUMA_AddGenDsetNodeIndexColAttr (SUMA_DSET *dset, SUMA_COL_TYPE ctp,
2104                                      void *col, int stride)
2105 {
2106    static char FuncName[]={"SUMA_AddGenDsetNodeIndexColAttr"};
2107    char Name[500], **junk, *stmp=NULL;
2108    float amin = 0.0, amax = 0.0, *fv;
2109    int aminloc = -1, amaxloc = -1, *iv, icol=0, N_col;
2110    byte *bv;
2111    complex *cv = NULL;
2112    SUMA_Boolean LocalHead = NOPE;
2113 
2114    SUMA_ENTRY;
2115 
2116    if (!dset || !dset->inel || SDSET_NODEINDLEN(dset) < 1) {
2117       SUMA_SL_Err("Null input");
2118       SUMA_ShowNel(dset->inel);
2119       SUMA_DUMP_TRACE("Bad dset->inel, dumping trace for debug:");
2120       SUMA_RETURN(0);
2121    }
2122 
2123    if (!col) {
2124       SUMA_LH("No data");
2125       /* Do not complain, that is not a bad thing.
2126       People can use this to allocate for a column
2127       without filling it up */
2128       if (SUMA_isGraphDset(dset)) {
2129          snprintf(Name, 500*sizeof(char),"0 0 -1 -1%s0 0 -1 -1%s0 0 -1 -1",
2130                   SUMA_NI_CSS, SUMA_NI_CSS);
2131          stmp = SUMA_copy_string(Name);
2132       } if (SUMA_isCIFTIDset(dset)) {
2133          SUMA_S_Err("This needs to be done per domain also, "
2134                     "so we're not there yet. ");
2135          SUMA_RETURN(0);
2136       } else {
2137          stmp = SUMA_copy_string("0 0 -1 -1");
2138       }
2139    } else {
2140       if (LocalHead && SUMA_isCIFTIDset(dset)) {
2141          SUMA_S_Warn("Caution, needs verification for ciftination");
2142       }
2143       SUMA_LH("Calculating indrange");
2144       icol = SUMA_DATUM_INDEX_CTP2COL(ctp);
2145       N_col = stride*SDSET_VECFILLED(dset);
2146       stmp = SUMA_copy_string(NI_get_attribute(dset->inel,"COLMS_RANGE"));
2147       switch (SUMA_ColType2TypeCast(ctp)) {
2148          case SUMA_int:
2149             iv = (int *)col;
2150             SUMA_MIN_MAX_VEC_STRIDE(iv, N_col, amin, amax,
2151                                     aminloc, amaxloc, stride);
2152             snprintf(Name, 500*sizeof(char),"%d %d %d %d",
2153                      (int)amin, (int)amax, aminloc, amaxloc);
2154             break;
2155          case SUMA_float:
2156             fv = (float *)col;
2157             SUMA_MIN_MAX_VEC_STRIDE(fv , N_col, amin, amax,
2158                                     aminloc, amaxloc, stride);
2159             snprintf(Name, 500*sizeof(char),"%f %f %d %d",
2160                            amin, amax, aminloc, amaxloc);
2161             break;
2162          case SUMA_byte:
2163             bv = (byte *)col;
2164             SUMA_MIN_MAX_VEC_STRIDE(bv , N_col, amin, amax,
2165                                     aminloc, amaxloc, stride);
2166             snprintf(Name, 500*sizeof(char),"%d %d %d %d",
2167                            (int)amin, (int)amax, aminloc, amaxloc);
2168             break;
2169          case SUMA_string:
2170             Name[0] = '\0';
2171             break;
2172          case SUMA_complex:
2173             cv = (complex *)col;
2174             SUMA_MIN_MAX_CVEC_STRIDE(cv , N_col, amin, amax,
2175                                     aminloc, amaxloc, stride, 0);
2176             snprintf(Name, 500*sizeof(char),"%d %d %d %d",
2177                            (int)amin, (int)amax, aminloc, amaxloc);
2178             break;
2179          default:
2180             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
2181             SUMA_RETURN(0);
2182             break;
2183       }
2184       if (!SUMA_Set_Sub_String(&stmp, SUMA_NI_CSS, icol,Name)) {
2185          fprintf (stderr,"Error %s: Failed to set substring to %s\n",
2186                         FuncName, Name);
2187          SUMA_RETURN(0);
2188       }
2189 
2190    }
2191 
2192    NI_set_attribute(dset->inel, "COLMS_RANGE", stmp);
2193 
2194    if (stmp) SUMA_free(stmp); stmp = NULL;
2195    SUMA_RETURN(1);
2196 }
2197 
SUMA_AddGenGDsetNodeXYZColAttr(SUMA_DSET * dset,SUMA_COL_TYPE ctp,void * col,int stride)2198 int SUMA_AddGenGDsetNodeXYZColAttr (SUMA_DSET *dset, SUMA_COL_TYPE ctp,
2199                                      void *col, int stride)
2200 {
2201    static char FuncName[]={"SUMA_AddGenGDsetNodeXYZColAttr"};
2202    char Name[500], **junk, *stmp=NULL;
2203    float amin = 0.0, amax = 0.0, *fv;
2204    int aminloc = -1, amaxloc = -1, *iv, icol=0, N_col=0;
2205    byte *bv;
2206    complex *cv = NULL;
2207    NI_element *xyznel=NULL;
2208    SUMA_Boolean LocalHead = NOPE;
2209 
2210    SUMA_ENTRY;
2211 
2212    if (!dset || SDSET_NODEINDLEN(dset) < 1) {
2213       SUMA_SL_Err("Null input");
2214       SUMA_ShowNel(dset->inel);
2215       SUMA_DUMP_TRACE("Bad dset->inel, dumping trace for debug:");
2216       SUMA_RETURN(0);
2217    }
2218 
2219    if (!SUMA_isGraphDset(dset)) {
2220       SUMA_SL_Err("Null or bad input");
2221       SUMA_RETURN(0);
2222    }
2223 
2224    if (!(xyznel = SUMA_FindGDsetNodeListElement(dset))) {
2225       SUMA_S_Err("No nodelist element");
2226       SUMA_RETURN(0);
2227    }
2228 
2229    if (dset->Aux->matrix_shape == MAT_HEEHAW) {
2230       SUMA_GDSET_Set_Aux_matrix_shape(dset);
2231    }
2232 
2233    if (!col) {
2234       SUMA_LH("No data");
2235       /* Do not complain, that is not a bad thing.
2236       People can use this to allocate for a column
2237       without filling it up */
2238       if (SUMA_isGraphDset(dset)) {
2239          snprintf(Name, 500*sizeof(char),
2240                   "0 0 -1 -1%s0 0 -1 -1%s0 0 -1 -1", SUMA_NI_CSS, SUMA_NI_CSS);
2241          stmp = SUMA_copy_string(Name);
2242       } else {
2243          stmp = SUMA_copy_string("0 0 -1 -1");
2244       }
2245    } else {
2246       SUMA_LH("Calculating XYZrange");
2247       icol = SUMA_GNODE_IXYZ_CTP2COL(ctp);
2248       N_col = GDSET_N_SEG_POINTS(dset)*stride;
2249       stmp = SUMA_copy_string(NI_get_attribute(xyznel,"COLMS_RANGE"));
2250       switch (SUMA_ColType2TypeCast(ctp)) {
2251          case SUMA_int:
2252             iv = (int *)col;
2253             SUMA_MIN_MAX_VEC_STRIDE(iv ,N_col, amin, amax,
2254                                     aminloc, amaxloc, stride);
2255             snprintf(Name, 500*sizeof(char),"%d %d %d %d",
2256                      (int)amin, (int)amax, aminloc, amaxloc);
2257             break;
2258          case SUMA_float:
2259             fv = (float *)col;
2260             SUMA_MIN_MAX_VEC_STRIDE(fv ,N_col, amin, amax,
2261                                     aminloc, amaxloc, stride);
2262             snprintf(Name, 500*sizeof(char),"%f %f %d %d",
2263                            amin, amax, aminloc, amaxloc);
2264             break;
2265          case SUMA_byte:
2266             bv = (byte *)col;
2267             SUMA_MIN_MAX_VEC_STRIDE(bv ,N_col, amin, amax,
2268                                     aminloc, amaxloc, stride);
2269             snprintf(Name, 500*sizeof(char),"%d %d %d %d",
2270                            (int)amin, (int)amax, aminloc, amaxloc);
2271             break;
2272          case SUMA_string:
2273             Name[0] = '\0';
2274             break;
2275          case SUMA_complex:
2276             cv = (complex *)col;
2277             SUMA_MIN_MAX_CVEC_STRIDE(cv ,N_col, amin, amax,
2278                                     aminloc, amaxloc, stride, 0);
2279             snprintf(Name, 500*sizeof(char),"%d %d %d %d",
2280                            (int)amin, (int)amax, aminloc, amaxloc);
2281             break;
2282          default:
2283             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
2284             SUMA_RETURN(0);
2285             break;
2286       }
2287       if (!SUMA_Set_Sub_String(&stmp, SUMA_NI_CSS, icol,Name)) {
2288          fprintf (stderr,"Error %s: Failed to set substring to %s\n",
2289             FuncName, Name);
2290          SUMA_RETURN(0);
2291       }
2292 
2293    }
2294 
2295    NI_set_attribute(xyznel, "COLMS_RANGE", stmp);
2296 
2297    if (stmp) SUMA_free(stmp); stmp = NULL;
2298    SUMA_RETURN(1);
2299 }
2300 
2301 
2302 
2303 /*!
2304    Adds some generic attributes.
2305    For the moment, the range is added for numeric columns
2306    if col_index is -1, then it is assumed that the attributes are for the latest     column added (vec_num -1)
2307 */
SUMA_AddGenColAttr(NI_element * nel,SUMA_COL_TYPE ctp,void * col,int stride,int col_index)2308 int SUMA_AddGenColAttr (NI_element *nel, SUMA_COL_TYPE ctp, void *col,
2309                         int stride, int col_index)
2310 {
2311    static char FuncName[]={"SUMA_AddGenColAttr"};
2312    static char stmp[500], Name[500];
2313    float amin = 0.0, amax = 0.0, *fv;
2314    int aminloc = -1, amaxloc = -1, *iv, N_col=0;
2315    complex *cv = NULL;
2316    byte *bv;
2317 
2318    SUMA_ENTRY;
2319 
2320    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
2321 
2322    if (!nel) { SUMA_SL_Err("Null Nel"); SUMA_RETURN(0); }
2323    if (col_index < 0) col_index = nel->vec_num-1;
2324    if (col_index < 0 || !nel->vec_num ) {
2325       SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
2326    if (nel->vec_num <= col_index) {
2327       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
2328 
2329    sprintf(Name, "RangeCol_%d", col_index);
2330 
2331    if (!col) {
2332       /* Do not complain, that is not a bad thing.
2333          People can use this to allocate for a column
2334          without filling it up */
2335       sprintf(stmp, "0 0 -1 -1");
2336    } else {
2337       N_col = stride*nel->vec_filled;
2338       switch (SUMA_ColType2TypeCast(ctp)) {
2339          case SUMA_int:
2340             iv = (int *)col;
2341             SUMA_MIN_MAX_VEC_STRIDE(iv ,N_col, amin, amax,
2342                                     aminloc, amaxloc, stride);
2343             snprintf(stmp, 500*sizeof(char),"%d %d %d %d",
2344                            (int)amin, (int)amax, aminloc, amaxloc);
2345             break;
2346          case SUMA_float:
2347             fv = (float *)col;
2348             SUMA_MIN_MAX_VEC_STRIDE(fv ,N_col, amin, amax,
2349                                     aminloc, amaxloc, stride);
2350             snprintf(stmp, 500*sizeof(char),"%f %f %d %d",
2351                            amin, amax, aminloc, amaxloc);
2352             break;
2353          case SUMA_byte:
2354             bv = (byte *)col;
2355             SUMA_MIN_MAX_VEC_STRIDE(bv ,N_col, amin, amax,
2356                                     aminloc, amaxloc, stride);
2357             snprintf(stmp, 500*sizeof(char),"%d %d %d %d",
2358                            (int)amin, (int)amax, aminloc, amaxloc);
2359             break;
2360          case SUMA_string:
2361             stmp[0] = '\0';
2362             break;
2363          case SUMA_complex:
2364             cv = (complex *)col;
2365             SUMA_MIN_MAX_CVEC_STRIDE(cv ,N_col, amin, amax,
2366                                     aminloc, amaxloc, stride, 0);
2367             snprintf(stmp, 500*sizeof(char),"%d %d %d %d",
2368                            (int)amin, (int)amax, aminloc, amaxloc);
2369             break;
2370          default:
2371             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
2372             SUMA_RETURN(0);
2373             break;
2374       }
2375    }
2376 
2377    NI_set_attribute ( nel, Name, stmp);
2378 
2379    SUMA_allow_nel_use(0);
2380    SUMA_RETURN(1);
2381 }
2382 
2383 
2384 /*!
2385    \brief Gets the column range values
2386    col_index can be -1 if you want the attributes of the last column
2387 */
SUMA_GetDsetColRange(SUMA_DSET * dset,int col_index,double range[2],int loc[2])2388 int SUMA_GetDsetColRange(  SUMA_DSET *dset, int col_index,
2389                            double range[2], int loc[2])
2390 {
2391    static char FuncName[]={"SUMA_GetDsetColRange"};
2392    char *rs = NULL, **sc=NULL, Name[500];
2393    double nums[4];
2394    NI_element *nelb = NULL;
2395 
2396    SUMA_ENTRY;
2397 
2398    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
2399    if (col_index < 0) col_index = SDSET_VECNUM(dset)-1;
2400    if (col_index < 0 || !SDSET_VECNUM(dset) ) {
2401       SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
2402    if (SDSET_VECNUM(dset) <= col_index) {
2403       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
2404 
2405    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_RANGE");
2406    if (!nelb) {
2407       SUMA_SL_Err("Failed to find column range attribute"); SUMA_RETURN(0); }
2408 
2409    SUMA_NEL_GET_STRING(nelb, 0, 0, rs);
2410          /* rs is a pointer copy here, do not free */
2411    rs = SUMA_Get_Sub_String(rs, SUMA_NI_CSS, col_index);
2412    if (!rs) { SUMA_SL_Err("No range field."); SUMA_RETURN(0); }
2413    if (SUMA_StringToNum(rs, (void *)nums, 4, 2) != 4) {
2414       SUMA_SL_Err("Failed to read 4 nums from range."); SUMA_RETURN(0); }
2415    range[0] = nums[0]; range[1] = nums[1];
2416    loc[0] = (int)nums[2]; loc[1] = (int)nums[3];
2417    SUMA_free(rs); rs = NULL;
2418    SUMA_RETURN(1);
2419 }
2420 
SUMA_CreateDsetColRangeCompString(SUMA_DSET * dset,int col_index,SUMA_COL_TYPE ctp)2421 char * SUMA_CreateDsetColRangeCompString( SUMA_DSET *dset, int col_index,
2422                                           SUMA_COL_TYPE ctp)
2423 {
2424    static char FuncName[]={"SUMA_CreateDsetColRangeCompString"};
2425    char Name[500]={""};
2426    char *stmp=NULL;
2427    float *fv=NULL;
2428    double *dv = NULL, amin = 0.0, amax = 0.0;
2429    complex *cv = NULL;
2430    int aminloc = -1, amaxloc = -1, *iv, kk;
2431    byte *bv;
2432    NI_element *nelb = NULL;
2433    void *col=NULL;
2434 
2435    SUMA_ENTRY;
2436 
2437    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
2438    if (col_index < 0) col_index = SDSET_VECNUM(dset)-1;
2439    if (col_index < 0 || !SDSET_VECNUM(dset) ) {
2440       SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
2441    if (SDSET_VECNUM(dset) <= col_index) {
2442       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
2443    if (ctp <= SUMA_NO_COL_TYPE) {
2444       /* sometimes this function is called after a dset is created
2445       and the type is set already in dset but the user does not want to
2446       bother sending the type in. Since dset is fully
2447       formed by then, ctp can be recovered from dset */
2448       if (  (ctp = SUMA_TypeOfDsetColNumb(dset, col_index)) ==
2449             SUMA_ERROR_COL_TYPE ){
2450          SUMA_SL_Err("ctp not set and cannot be obtained.\n"
2451                      "You must specify column type if dset\n"
2452                      "not fully formed yet"); SUMA_RETURN(0);
2453       }
2454    }
2455    col = dset->dnel->vec[col_index];
2456 
2457    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_RANGE");
2458    if (!nelb) {
2459       SUMA_SL_Err("Failed to find column range attribute"); SUMA_RETURN(0); }
2460 
2461       switch (SUMA_ColType2TypeCast(ctp)) {
2462          case SUMA_int:
2463             iv = (int *)col;
2464             SUMA_MIN_MAX_VEC_STRIDE(iv ,SDSET_VECFILLED(dset), amin, amax,
2465                                     aminloc, amaxloc, 1);
2466             snprintf(Name, 500*sizeof(char),
2467                      "%d %d %d %d", (int)amin, (int)amax, aminloc, amaxloc);
2468             break;
2469          case SUMA_float:
2470             fv = (float *)col;
2471             SUMA_MIN_MAX_VEC_STRIDE(fv ,SDSET_VECFILLED(dset), amin, amax,
2472                                     aminloc, amaxloc, 1);
2473             snprintf(Name, 500*sizeof(char),
2474                            "%f %f %d %d", amin, amax, aminloc, amaxloc);
2475             break;
2476          case SUMA_byte:
2477             bv = (byte *)col;
2478             SUMA_MIN_MAX_VEC_STRIDE(bv ,SDSET_VECFILLED(dset), amin, amax,
2479                                     aminloc, amaxloc, 1);
2480             snprintf(Name, 500*sizeof(char),
2481                            "%d %d %d %d",
2482                            (int)amin, (int)amax, aminloc, amaxloc);
2483             break;
2484          case SUMA_double:
2485             dv = (double *)col;
2486             SUMA_MIN_MAX_VEC_STRIDE(dv ,SDSET_VECFILLED(dset), amin, amax,
2487                                     aminloc, amaxloc, 1);
2488             snprintf(Name, 500*sizeof(char),
2489                            "%f %f %d %d", amin, amax, aminloc, amaxloc);
2490             break;
2491          case SUMA_string:
2492             snprintf(Name, 500*sizeof(char),
2493                            "0 0 -1 -1");
2494             break;
2495          case SUMA_complex:
2496             cv = (complex *)col;
2497             SUMA_MIN_MAX_CVEC_STRIDE(cv ,SDSET_VECFILLED(dset), amin, amax,
2498                                     aminloc, amaxloc, 1, 0);
2499             snprintf(Name, 500*sizeof(char),
2500                            "%f %f %d %d", amin, amax, aminloc, amaxloc);
2501             break;
2502          default:
2503             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
2504             SUMA_RETURN(0);
2505             break;
2506       }
2507       stmp = SUMA_copy_string(Name);
2508 
2509    SUMA_RETURN(stmp);
2510 }
2511 
2512 /*!
2513    Upon returning, sets the statistical parameters from a
2514    certain dset column
2515 */
SUMA_GetDsetColStatAttr(SUMA_DSET * dset,int col_index,int * statcode,float * p1,float * p2,float * p3)2516 int SUMA_GetDsetColStatAttr(  SUMA_DSET *dset, int col_index,
2517                               int *statcode,
2518                               float *p1, float *p2, float *p3)
2519 {
2520    static char FuncName[]={"SUMA_GetDsetColStatAttr"};
2521    char *rs = NULL, **sc=NULL, Name[500];
2522    float nums[4];
2523    NI_element *nelb = NULL;
2524    SUMA_Boolean LocalHead = NOPE;
2525 
2526    SUMA_ENTRY;
2527 
2528    *statcode = -1;
2529    *p1 = *p2 = *p3 = -1.0;
2530 
2531    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
2532    if (col_index < 0) col_index = SDSET_VECNUM(dset)-1;
2533    if (col_index < 0 || !SDSET_VECNUM(dset) ) {
2534       SUMA_SL_Err("No columns in data set!");
2535       SUMA_RETURN(0);
2536    }
2537    if (SDSET_VECNUM(dset) <= col_index) {
2538       SUMA_SL_Err("col_index >= nel->vec_num!");
2539       SUMA_RETURN(0);
2540    }
2541 
2542    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_STATSYM");
2543    if (!nelb) {
2544       if (LocalHead) {
2545          SUMA_S_Warn("Failed to find column range attribute");
2546       }
2547       SUMA_RETURN(0);
2548    }
2549 
2550    SUMA_NEL_GET_STRING(nelb, 0, 0, rs); /* rs is a pointer copy here */
2551 
2552    rs = SUMA_Get_Sub_String(rs, SUMA_NI_CSS, col_index);
2553    if (!rs) { SUMA_SL_Err("No stat field."); SUMA_RETURN(0); }
2554    NI_stat_decode(rs, statcode, p1, p2, p3);
2555    SUMA_free(rs); rs = NULL;
2556 
2557    SUMA_RETURN(1);
2558 }
2559 
SUMA_GetDsetColStringAttr(SUMA_DSET * dset,int col_index,char * attrname)2560 char * SUMA_GetDsetColStringAttr( SUMA_DSET *dset, int col_index,
2561                                     char *attrname)
2562 {
2563    static char FuncName[]={"SUMA_GetDsetColStringAttr"};
2564    char *rs = NULL;
2565    NI_element *nelb = NULL;
2566    SUMA_ENTRY;
2567 
2568    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
2569    if (col_index < 0) col_index = SDSET_VECNUM(dset)-1;
2570    if (col_index < 0 || !SDSET_VECNUM(dset) ) {
2571       SUMA_SL_Err("No columns in data set!");
2572       SUMA_RETURN(NULL);
2573    }
2574    if (SDSET_VECNUM(dset) <= col_index) {
2575       SUMA_SL_Err("col_index >= nel->vec_num!");
2576       SUMA_RETURN(NULL);
2577    }
2578 
2579    nelb = SUMA_FindDsetAttributeElement(dset, attrname);
2580    if (!nelb) {
2581       SUMA_SL_Err("Failed to find  attribute");
2582       SUMA_RETURN(NULL);
2583    }
2584    SUMA_NEL_GET_STRING(nelb, 0, 0, rs); /* rs is a pointer copy here */
2585 
2586    rs = SUMA_Get_Sub_String(rs, SUMA_NI_CSS, col_index);
2587 
2588    SUMA_RETURN(rs);
2589 }
2590 
SUMA_GetNgrColStringAttr(NI_group * ngr,int col_index,char * attrname)2591 char * SUMA_GetNgrColStringAttr( NI_group *ngr, int col_index,
2592                                  char *attrname)
2593 {
2594    static char FuncName[]={"SUMA_GetNgrColStringAttr"};
2595    char *rs = NULL;
2596    NI_element *nelb = NULL;
2597    SUMA_ENTRY;
2598 
2599    if (!ngr) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
2600    if (col_index < 0 ) {
2601       SUMA_SL_Err("Bad Col Index");
2602       SUMA_RETURN(NULL);
2603    }
2604 
2605    nelb = SUMA_FindNgrAttributeElement(ngr, attrname);
2606    if (!nelb) {
2607       SUMA_SL_Err("Failed to find  attribute");
2608       SUMA_RETURN(NULL);
2609    }
2610    SUMA_NEL_GET_STRING(nelb, 0, 0, rs); /* rs is a pointer copy here */
2611 
2612    rs = SUMA_Get_Sub_String(rs, SUMA_NI_CSS, col_index);
2613 
2614    SUMA_RETURN(rs);
2615 }
2616 
SUMA_GetDsetNodeIndexColRange_eng(SUMA_DSET * dset,double range[2],int loc[2],int addifmissing,int ii)2617 int SUMA_GetDsetNodeIndexColRange_eng(  SUMA_DSET *dset,
2618                                     double range[2], int loc[2],
2619                                     int addifmissing, int ii)
2620 {
2621    static char FuncName[]={"SUMA_GetDsetNodeIndexColRange_eng"};
2622    char *rs = NULL, Name[500];
2623    double nums[4];
2624    char *ctmp=NULL;
2625    SUMA_Boolean LocalHead = NOPE;
2626 
2627    SUMA_ENTRY;
2628 
2629    range[0] = 0; range[1] = 0;
2630    loc[0] = -1; loc[1] = -1;
2631 
2632    if (!dset || !dset->inel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
2633    if (SUMA_isCIFTIDset(dset)) {
2634       SUMA_SL_Err("Cannot answer this question without adding domain as"
2635                   "an extra parameter");
2636       SUMA_RETURN(0);
2637    }
2638    if (ii != 0) {
2639       if (!SUMA_isGraphDset(dset)) {
2640          SUMA_S_Errv("Should not ask for %d unless with graph dset",ii);
2641          SUMA_RETURN(0);
2642       }
2643       if (ii>2 || ii<0) {
2644          SUMA_S_Errv("What is %d for?",ii);
2645          SUMA_RETURN(0);
2646       }
2647    }
2648 
2649    if (SUMA_isGraphDset(dset) && dset->inel->vec_num == 0) {
2650       SUMA_LH("Here is hoping we're standard");
2651       switch (dset->Aux->matrix_shape) {
2652          case MAT_HEEHAW:
2653          default:
2654             SUMA_S_Err("Should not happen here");
2655             SUMA_RETURN(NOPE);
2656          case MAT_TRI:
2657          case MAT_TRI_DIAG:
2658          case MAT_FULL:
2659             if (ii==0) {
2660                range[0]=loc[0]=0; range[1]=loc[1]=SDSET_VECLEN(dset)-1;
2661             } else if (ii==1 || ii==2) {
2662                range[0]=loc[0]=0; range[1]=loc[1]=SDSET_MATRIX_SZ0(dset)-1;
2663             }
2664             break;
2665          case MAT_SPARSE:
2666             SUMA_S_Err("Sparse matrix and no inel?");
2667             SUMA_RETURN(0);
2668       }
2669       SUMA_RETURN(1);
2670    }
2671 
2672    rs = NI_get_attribute(dset->inel, "COLMS_RANGE");
2673    if (!rs) {
2674       if (!addifmissing) {
2675          SUMA_SL_Err("No range field."); SUMA_RETURN(0);
2676       }else {
2677          if (SUMA_isGraphDset(dset)) {
2678             if (!SUMA_AddGenDsetNodeIndexColAttr (dset, SUMA_EDGE_P1_INDEX,
2679                                              SDSET_EDGE_P1_INDEX_COL(dset), 1)) {
2680                SUMA_SL_Err("Could not add range field for P1."); SUMA_RETURN(0);
2681             }
2682             if (!SUMA_AddGenDsetNodeIndexColAttr (dset, SUMA_EDGE_P2_INDEX,
2683                                              SDSET_EDGE_P2_INDEX_COL(dset), 1)) {
2684                SUMA_SL_Err("Could not add range field for P2."); SUMA_RETURN(0);
2685             }
2686          }
2687          if (!SUMA_AddGenDsetNodeIndexColAttr (dset, SUMA_NODE_INDEX,
2688                                              SDSET_NODE_INDEX_COL(dset), 1)) {
2689             SUMA_SL_Err("Could not add range field."); SUMA_RETURN(0);
2690          }
2691          rs = NI_get_attribute(dset->inel, "COLMS_RANGE");
2692       }
2693    }
2694    if (!SUMA_isGraphDset(dset)){
2695       if (SUMA_StringToNum(rs, (void *)nums, 4, 2) != 4) {
2696          SUMA_SL_Err("Failed to read 4 nums from range.");
2697          SUMA_RETURN(0);
2698       }
2699    } else {
2700       ctmp = SUMA_Get_Sub_String(rs, SUMA_NI_CSS, ii);
2701       if (SUMA_StringToNum(ctmp, (void *)nums, 4, 2) != 4) {
2702          SUMA_SL_Err("Failed to read 4 nums from range.");
2703          SUMA_RETURN(0);
2704       }
2705    }
2706    range[0] = nums[0]; range[1] = nums[1];
2707    loc[0] = (int)nums[2]; loc[1] = (int)nums[3];
2708    SUMA_RETURN(1);
2709 }
2710 
SUMA_GetDsetNodeIndexColRange(SUMA_DSET * dset,double range[2],int loc[2],int addifmissing)2711 int SUMA_GetDsetNodeIndexColRange(  SUMA_DSET *dset,
2712                                     double range[2], int loc[2],
2713                                     int addifmissing)
2714 {
2715    return(SUMA_GetDsetNodeIndexColRange_eng(
2716             dset, range, loc, addifmissing,0));
2717 }
2718 
2719 
2720 /*!
2721    \brief Gets the column range values
2722    col_index can be -1 if you want the attributes of the last column
2723 */
SUMA_GetColRange(NI_element * nel,int col_index,double range[2],int loc[2])2724 int SUMA_GetColRange(NI_element *nel, int col_index, double range[2], int loc[2])
2725 {
2726    static char FuncName[]={"SUMA_GetColRange"};
2727    char *rs = NULL, Name[500];
2728    double nums[4];
2729 
2730    SUMA_ENTRY;
2731 
2732    SUMA_SL_Warn("Obsolete, use new version.");
2733 
2734    if (!nel) { SUMA_SL_Err("Null Nel"); SUMA_RETURN(0); }
2735    if (col_index < 0) col_index = nel->vec_num-1;
2736    if (col_index < 0 || !nel->vec_num ) {
2737       SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
2738    if (nel->vec_num <= col_index) {
2739       SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
2740 
2741 
2742    sprintf(Name, "RangeCol_%d", col_index);
2743    rs = NI_get_attribute(nel, Name);
2744 
2745    if (!rs) { SUMA_SL_Err("No range field."); SUMA_RETURN(0); }
2746    if (SUMA_StringToNum(rs, (void *)nums, 4, 2) != 4) {
2747       SUMA_SL_Err("Failed to read 4 nums from range."); SUMA_RETURN(0); }
2748    range[0] = nums[0]; range[1] = nums[1];
2749    loc[0] = (int)nums[2]; loc[1] = (int)nums[3];
2750 
2751    SUMA_RETURN(1);
2752 }
2753 /*!
2754    Adds a column to dset->dnel (new version of SUMA_AddNelCol)
2755    The vectors added are nel->vec_len long so col should contain at least
2756    nel->vec_len * stride elements.
2757 
2758    What to do when filling up to nel->vec_filled only ? Does one need to
2759    write another version of NI_add_column_stride ? (see file niml/niml_element)
2760    Is the use of vec_filled what I think it is ?
2761 
2762    Mar 23 04: Made modifications to NI_add_column and _stride
2763    so that data are copied up to nel->vec_filled instead of
2764    nel->vec_len if nel->vec_filled is > 0 and < vec_len
2765 
2766    Tue Aug 29 10:42:26 EDT 2006: SUMA_NODE_INDEX is handled separately, it is
2767    an element in the group
2768 
2769    If you wish to allocate space for a column (nel->vec_len long)
2770    then pass NULL for col
2771 
2772    Can also use SUMA_InsertDsetNelCol, tiz more flexible.
2773 */
SUMA_AddDsetNelCol(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)2774 int SUMA_AddDsetNelCol (   SUMA_DSET *dset, char *col_label,
2775                            SUMA_COL_TYPE ctp, void *col,
2776                            void *col_attr, int stride)
2777 {
2778    static char FuncName[]={"SUMA_AddDsetNelCol"};
2779    SUMA_Boolean LocalHead = NOPE;
2780 
2781    SUMA_ENTRY;
2782 
2783    SUMA_RETURN(SUMA_InsertDsetNelCol(  dset, col_label, ctp,
2784                                        col, col_attr, stride, -1));
2785 }
2786 
SUMA_InsertDsetNelCol(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride,int icol)2787 int SUMA_InsertDsetNelCol ( SUMA_DSET *dset, char *col_label,
2788                             SUMA_COL_TYPE ctp, void *col,
2789                             void *col_attr, int stride, int icol)
2790 {
2791    static char FuncName[]={"SUMA_InsertDsetNelCol"};
2792    int *iv, is_sorted;
2793    NI_element *nelb=NULL;
2794    SUMA_Boolean LocalHead = NOPE;
2795 
2796    SUMA_ENTRY;
2797 
2798    if (SUMA_IS_DATUM_INDEX_COL(ctp)) {
2799       SUMA_RETURN(SUMA_AddDsetNelIndexCol (  dset, col_label, ctp,
2800                                              col, col_attr, stride));
2801    }
2802    if (SUMA_isGraphDset(dset) && SUMA_IS_GNODE_IXYZ_COL(ctp)) {
2803       SUMA_RETURN(SUMA_AddGDsetNelXYZCol (dset, col_label, ctp, col,
2804                                           col_attr, stride));
2805    }
2806    if (icol != -1) {
2807       /*
2808       SUMA_S_Err("Function not ready to deal with attribute insertion yet."
2809                  " See bottom of function");
2810       SUMA_RETURN(0);
2811       */
2812       SUMA_LH("insertion mode");
2813    }
2814 
2815    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
2816    if (!col) {
2817       /* Do not complain, that is not a bad thing.
2818       People can use this to allocate for a column
2819       without filling it up */
2820       /* SUMA_SL_Err("Null Col"); SUMA_RETURN(0); */
2821    }
2822 
2823    SUMA_LH("Checking Type");
2824    if (LocalHead && !col) {
2825       SUMA_ShowNel((void*)dset->dnel);
2826    }
2827    switch (SUMA_ColType2TypeCast(ctp)) {
2828       case SUMA_int:
2829          NI_insert_column_stride (  dset->dnel, NI_INT,
2830                                     (int *)col, stride, icol);
2831          break;
2832       case SUMA_float:
2833          NI_insert_column_stride (  dset->dnel, NI_FLOAT,
2834                                     (float *)col, stride, icol );
2835          break;
2836       case SUMA_byte:
2837          NI_insert_column_stride (  dset->dnel, NI_BYTE,
2838                                     (byte *)col, stride, icol );
2839          break;
2840       case SUMA_double:
2841          NI_insert_column_stride (  dset->dnel, NI_DOUBLE,
2842                                     (double *)col, stride, icol );
2843          break;
2844       case SUMA_string:
2845          NI_insert_column_stride (  dset->dnel, NI_STRING,
2846                                     (char **)col, stride, icol );
2847          break;
2848       case SUMA_complex:
2849          NI_insert_column_stride (  dset->dnel, NI_COMPLEX,
2850                                     (complex *)col, stride, icol );
2851          break;
2852       default:
2853          fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
2854          SUMA_RETURN(0);
2855          break;
2856    }
2857    if (LocalHead && !col) {
2858       SUMA_ShowNel((void*)dset->dnel);
2859    }
2860 
2861    SUMA_LH("Cheking generic attributes");
2862 
2863    /* set some generic attributes.
2864    You must redo it for all columns from icol
2865    to the very end but that is not a pleasant task
2866    because the functions below cannot insert. Only append (icol = -1)
2867    or replace. You'll need to find a solution for inserts before
2868    allowing column insertion.
2869    That is now fixed, Oct 07 */
2870    SUMA_LH("Before SUMA_AddGenDsetColAttr");
2871    SUMA_AddGenDsetColAttr (dset, ctp, col, stride, icol, 1);
2872    /* add the attributes of that column */
2873    SUMA_LH("Before SUMA_AddDsetColAttr");
2874    SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, icol, 1);
2875    SUMA_LH("Before Returning");
2876 
2877    SUMA_RETURN(1);
2878 }
2879 
2880 /*!
2881    A convenient form of adding a default node index column
2882 */
SUMA_AddDsetIndexCol(SUMA_DSET * dset,int * icolu,int * icolp1,int * icolp2)2883 int SUMA_AddDsetIndexCol(SUMA_DSET *dset, int *icolu, int *icolp1, int *icolp2)
2884 {
2885    static char FuncName[]={"SUMA_AddDsetIndexCol"};
2886    int ii=0, *icol=NULL;
2887 
2888    SUMA_ENTRY;
2889 
2890    if (!dset) SUMA_RETURN(NOPE);
2891    if (SDSET_VECLEN(dset) <= 0) SUMA_RETURN(NOPE);
2892    if (!icolu) {
2893       if (SUMA_isGraphDset(dset)) { /* sorry no guessing */
2894          SUMA_RETURN(YUP);
2895       }
2896       if (SUMA_isCIFTIDset(dset)) { /* no guessing either */
2897          SUMA_RETURN(YUP);
2898       }
2899       if (!(icol = (int *)SUMA_malloc(sizeof(int)*SDSET_VECALLOC(dset)))) {
2900          SUMA_S_Err("Failed to icolate");
2901          SUMA_RETURN(NOPE);
2902       }
2903       for (ii=0; ii<SDSET_VECLEN(dset); ++ii) icol[ii]=ii;
2904    } else {
2905       if (SUMA_isGraphDset(dset) && (!icolp1 || !icolp2)) {
2906          SUMA_S_Err("Uncool for a graph");
2907          SUMA_RETURN(NOPE);
2908       }
2909       icol = icolu;
2910    }
2911    if (SUMA_isCIFTIDset(dset)) {
2912       if (!SUMA_AddDsetNelIndexCol (dset, "MD node index",
2913                                     SUMA_MD_NODE_INDEX, (void *)icol,
2914                                     NULL, 1)) {
2915          SUMA_S_Err("Failed to add default multi domain index col");
2916          SUMA_RETURN(NOPE);
2917       }
2918    } else {
2919       if (!SUMA_AddDsetNelIndexCol (dset, "node index",
2920                                     SUMA_NODE_INDEX, (void *)icol,
2921                                     NULL, 1)) {
2922          SUMA_S_Err("Failed to add default index col");
2923          SUMA_RETURN(NOPE);
2924       }
2925    }
2926    if (icolp1) {
2927       if (!SUMA_AddDsetNelIndexCol (dset, "P1 index",
2928                                     SUMA_EDGE_P1_INDEX, (void *)icolp1,
2929                                     NULL, 1)) {
2930          SUMA_S_Err("Failed to add p1 index col");
2931          SUMA_RETURN(NOPE);
2932       }
2933    }
2934    if (icolp2) {
2935       if (!SUMA_AddDsetNelIndexCol (dset, "P2 index",
2936                                     SUMA_EDGE_P2_INDEX, (void *)icolp2,
2937                                     NULL, 1)) {
2938          SUMA_S_Err("Failed to add p2 index col");
2939          SUMA_RETURN(NOPE);
2940       }
2941    }
2942    if (!icolu) SUMA_free(icol);
2943 
2944    SUMA_RETURN(YUP);
2945 }
2946 /*!
2947    \brief A version of SUMA_AddDsetNelCol that is specific for adding node indices
2948    \sa SUMA_AddDsetIndexCol();
2949 */
SUMA_AddDsetNelIndexCol(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)2950 int SUMA_AddDsetNelIndexCol ( SUMA_DSET *dset, char *col_label,
2951                                SUMA_COL_TYPE ctp, void *col,
2952                                void *col_attr, int stride)
2953 {
2954    static char FuncName[]={"SUMA_AddDsetNelIndexCol"};
2955    int *iv, is_sorted;
2956    NI_element *nelb=NULL;
2957    SUMA_Boolean LocalHead = NOPE;
2958 
2959    SUMA_ENTRY;
2960 
2961    if (LocalHead) {
2962       SUMA_DUMP_TRACE("Trace at entry");
2963    }
2964    if (ctp == SUMA_MD_NODE_INDEX) {
2965       SUMA_S_Err("This function cannot handle multiple domain indices\n"
2966                  "You might want to call SUMA_CIFTI_Set_Domains()\n");
2967       SUMA_RETURN(0);
2968    }
2969    if (!dset || !dset->inel || !SDSET_NODEINDLEN(dset)) {
2970       SUMA_SL_Err("Null input");
2971       SUMA_DUMP_TRACE("Bad dset->inel, dumping trace for debug:");
2972       SUMA_RETURN(0);
2973    }
2974    if (!col) {
2975       /* Do not complain, that is not a bad thing.
2976       People can use this to allocate for a column
2977       without filling it up */
2978       SUMA_LH("Null Col");
2979    }else {
2980       SUMA_LH("Non NuLL Col");
2981    }
2982 
2983    SUMA_LH("Checking Type");
2984 
2985    switch (SUMA_ColType2TypeCast(ctp)) { /* overkill, all we use is int here,
2986                                             but keeping the code anyway ...*/
2987       case SUMA_int:
2988          NI_add_column_stride ( dset->inel, NI_INT, col, stride);
2989          break;
2990       case SUMA_float:
2991          NI_add_column_stride ( dset->inel, NI_FLOAT, col, stride );
2992          break;
2993       case SUMA_byte:
2994          NI_add_column_stride ( dset->inel, NI_BYTE, col, stride );
2995          break;
2996       case SUMA_double:
2997          NI_add_column_stride ( dset->inel, NI_DOUBLE, col, stride );
2998          break;
2999       case SUMA_string:
3000          NI_add_column_stride ( dset->inel, NI_STRING, col, stride );
3001          break;
3002       case SUMA_complex:
3003          NI_add_column_stride ( dset->inel, NI_COMPLEX, col, stride );
3004          break;
3005       default:
3006          fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
3007          SUMA_RETURN(0);
3008          break;
3009    }
3010 
3011    if (ctp == SUMA_NODE_INDEX) { /* Can also be SUMA_EDGE_P[12]_INDEX*/
3012       if (col) {
3013          SUMA_LH("Check sortedness");
3014          /* need to check for sortedness of list */
3015          iv = (int *)col;
3016          SUMA_IS_SORTED_UP(iv, SDSET_VECFILLED(dset), is_sorted);
3017          iv = NULL;
3018          if (is_sorted) {
3019             NI_set_attribute(dset->inel, "sorted_node_def", "Yes");
3020          } else {
3021             NI_set_attribute(dset->inel, "sorted_node_def", "No");
3022          }
3023       } else {
3024          NI_set_attribute(dset->inel, "sorted_node_def", "Unknown");
3025       }
3026    }
3027 
3028 
3029 
3030    SUMA_LH("Setting index attributes");
3031    /* set some generic attributes */
3032    SUMA_AddGenDsetColAttr (dset, ctp, col, stride, -1, 0);
3033    /* add the attributes of that column */
3034    SUMA_AddDsetColAttr (dset, col_label?col_label:"node index",
3035                         ctp, col_attr, -1, 0);
3036    if (LocalHead) SUMA_ShowNel((void*)dset->inel);
3037 
3038 
3039    SUMA_RETURN(1);
3040 }
3041 
SUMA_AddGDsetNelXYZCol(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)3042 int SUMA_AddGDsetNelXYZCol ( SUMA_DSET *dset, char *col_label,
3043                                SUMA_COL_TYPE ctp, void *col,
3044                                void *col_attr, int stride)
3045 {
3046    static char FuncName[]={"SUMA_AddGDsetNelXYZCol"};
3047    int *iv, is_sorted;
3048    NI_element *xyznel=NULL;
3049    SUMA_Boolean LocalHead = NOPE;
3050 
3051    SUMA_ENTRY;
3052 
3053    if (LocalHead) {
3054       SUMA_DUMP_TRACE("Trace at entry");
3055    }
3056    if (!SUMA_isGraphDset(dset)) {
3057       SUMA_SL_Err("Null or bad input");
3058       SUMA_RETURN(0);
3059    }
3060 
3061    if (!(xyznel = SUMA_FindGDsetNodeListElement(dset))) {
3062       SUMA_S_Err("No nodelist element");
3063       SUMA_RETURN(0);
3064    }
3065 
3066    if (!col) {
3067       /* Do not complain, that is not a bad thing.
3068       People can use this to allocate for a column
3069       without filling it up */
3070       SUMA_LH("Null Col");
3071    }else {
3072       SUMA_LH("Non NuLL Col");
3073    }
3074 
3075    SUMA_LHv("Checking Type %s, stride %d\n",
3076             SUMA_Col_Type_Name(ctp), stride);
3077 
3078    switch (SUMA_ColType2TypeCast(ctp)) { /* overkill, all we use is int here,
3079                                             but keeping the code anyway ...*/
3080       case SUMA_int:
3081          NI_add_column_stride (xyznel, NI_INT, col, stride);
3082          break;
3083       case SUMA_float:
3084          NI_add_column_stride (xyznel, NI_FLOAT, col, stride );
3085          break;
3086       case SUMA_byte:
3087          NI_add_column_stride (xyznel, NI_BYTE, col, stride );
3088          break;
3089       case SUMA_double:
3090          NI_add_column_stride (xyznel, NI_DOUBLE, col, stride );
3091          break;
3092       case SUMA_string:
3093          NI_add_column_stride (xyznel, NI_STRING, col, stride );
3094          break;
3095       case SUMA_complex:
3096          NI_add_column_stride (xyznel, NI_COMPLEX, col, stride );
3097          break;
3098       default:
3099          fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
3100          SUMA_RETURN(0);
3101          break;
3102    }
3103 
3104 
3105    SUMA_LH("Cheking generic attributes");
3106    /* set some generic attributes */
3107    SUMA_AddGenDsetColAttr (dset, ctp, col, stride, -1, 0);
3108    /* add the attributes of that column */
3109    SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, -1, 0);
3110 
3111    if (LocalHead) SUMA_ShowNel((void*)xyznel);
3112 
3113 
3114    SUMA_RETURN(1);
3115 }
3116 
3117 
3118 /*!
3119    Adds a column to Nel
3120    The vectors added are nel->vec_len long so col should contain at least
3121    nel->vec_len * stride elements.
3122 
3123    What to do when filling up to nel->vec_filled only ? Does one need to
3124    write another version of NI_add_column_stride ? (see file niml/niml_element)
3125    Is the use of vec_filled what I think it is ?
3126 
3127    Mar 23 04: Made modifications to NI_add_column and _stride
3128    so that data are copied up to nel->vec_filled instead of
3129    nel->vec_len if nel->vec_filled is > 0 and < vec_len
3130 
3131    If you wish to allocate space for a column (nel->vec_len long)
3132    then pass NULL for col
3133 */
3134 
SUMA_AddNelCol(NI_element * nel,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)3135 int SUMA_AddNelCol ( NI_element *nel, char *col_label, SUMA_COL_TYPE ctp,
3136                      void *col,
3137                      void *col_attr, int stride)
3138 {
3139    static char FuncName[]={"SUMA_AddNelCol"};
3140    int *iv, is_sorted;
3141    SUMA_ENTRY;
3142 
3143    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
3144    if (!nel) { SUMA_SL_Err("Null Nel"); SUMA_RETURN(0); }
3145    if (!col) {
3146       /* Do not complain, that is not a bad thing.
3147       People can use this to allocate for a column
3148       without filling it up */
3149       /* SUMA_SL_Err("Null Col"); SUMA_RETURN(0); */
3150    }
3151 
3152    switch (SUMA_ColType2TypeCast(ctp)) {
3153       case SUMA_int:
3154          NI_add_column_stride ( nel, NI_INT, (int *)col, stride);
3155          break;
3156       case SUMA_float:
3157          NI_add_column_stride ( nel, NI_FLOAT, (float *)col, stride );
3158          break;
3159       case SUMA_byte:
3160          NI_add_column_stride ( nel, NI_BYTE, (byte *)col, stride );
3161          break;
3162       case SUMA_double:
3163          NI_add_column_stride ( nel, NI_DOUBLE, (double *)col, stride );
3164          break;
3165       case SUMA_string:
3166          NI_add_column_stride ( nel, NI_STRING, (char **)col, stride );
3167          break;
3168       case SUMA_complex:
3169          NI_add_column_stride ( nel, NI_COMPLEX, (complex *)col, stride );
3170          break;
3171       default:
3172          fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
3173          SUMA_RETURN(0);
3174          break;
3175    }
3176 
3177    if (ctp == SUMA_NODE_INDEX) { /* No need to woryy about sorting for SUMA_EDGE_P[12]_INDEX */
3178       if (col) {
3179          /* need to check for sortedness of list */
3180          iv = (int *)col;
3181          SUMA_IS_SORTED_UP(iv, nel->vec_filled, is_sorted)
3182          iv = NULL;
3183          if (is_sorted) {
3184             NI_set_attribute(nel, "sorted_node_def", "Yes");
3185          } else {
3186             NI_set_attribute(nel, "sorted_node_def", "No");
3187          }
3188       } else {
3189          NI_set_attribute(nel, "sorted_node_def", "Unknown");
3190       }
3191    }
3192 
3193    /* set some generic attributes */
3194    SUMA_allow_nel_use(1);
3195    SUMA_AddGenColAttr (nel, ctp, col, stride, -1);
3196    /* add the attributes of that column */
3197    SUMA_allow_nel_use(1);
3198    SUMA_AddColAttr (nel, col_label, ctp, col_attr, -1);
3199 
3200    SUMA_allow_nel_use(0);
3201    SUMA_RETURN(1);
3202 }
3203 
3204 /*!
3205    \brief See SUMA_MaskedCopyofDset, for all parameters not listed here.
3206    SUMA_DSET * SUMA_MaskedByNodeIndexCopyofDset(SUMA_DSET *odset,
3207                                                 int *indexlist, int N_indexlist,
3208                                                 byte *colmask, int masked_only, int keep_node_index)
3209 
3210    \param indexlist (int *) a list of N_indexlist node indices to retain in output dset.
3211    \param N_indexlist (int)
3212    These two params are used instead of rowmask in SUMA_MaskedCopyofDset
3213 */
SUMA_MaskedByNodeIndexCopyofDset(SUMA_DSET * odset,int * indexlist,int N_indexlist,byte * colmask,int masked_only,int keep_node_index)3214 SUMA_DSET * SUMA_MaskedByNodeIndexCopyofDset(
3215       SUMA_DSET *odset, int *indexlist,
3216       int N_indexlist, byte *colmask,
3217       int masked_only, int keep_node_index)
3218 {
3219    static char FuncName[]={"SUMA_MaskedByNodeIndexCopyofDset"};
3220    SUMA_DSET *dset_m = NULL;
3221    byte *Tb = NULL;
3222    int *indexmap = NULL, j=0;
3223    double range[2];
3224    int loc[2];
3225    SUMA_Boolean LocalHead = NOPE;
3226 
3227    SUMA_ENTRY;
3228 
3229    if (!(indexmap = SUMA_CreateNodeIndexToRowIndexMap(odset, -1, range))) {
3230       SUMA_S_Err("Failed to get indexmap");
3231       SUMA_RETURN(NULL);
3232    }
3233 
3234    Tb = (byte *) SUMA_calloc(SDSET_VECALLOC(odset), sizeof(byte));
3235    for (j=0; j<N_indexlist; ++j) {
3236       if (  indexmap[indexlist[j]] >=0 &&
3237             indexmap[indexlist[j]] < SDSET_VECFILLED(odset) &&
3238             indexlist[j] <= (int) range[1]) {
3239          Tb[indexmap[indexlist[j]]] = 1;
3240       } else {
3241          SUMA_S_Warn("Nodes in indexlist exceed odset->dnel->vec_filled\n"
3242                      "Such nodes will be ignored but may indicate \n"
3243                      "more serious trouble.\n"
3244                      "Warning will not be repeated in this call.");
3245       }
3246    }
3247    if (LocalHead) {
3248       for (j=0; j<N_indexlist; ++j) {
3249          fprintf(stderr,"indexlist[%d]=%d\n", j,indexlist[j]);
3250       }
3251       for (j=0; j<SDSET_VECLEN(odset); ++j) {
3252          if (Tb[j]) fprintf(stderr,"Tb[%d/%d]=%d\n",
3253                             j, SDSET_VECLEN(odset), Tb[j]);
3254       }
3255    }
3256    SUMA_free(indexmap); indexmap = NULL;
3257 
3258    if (!(dset_m = SUMA_MaskedCopyofDset(  odset, Tb, colmask,
3259                                           masked_only, keep_node_index ))) {
3260       SUMA_S_Err("Failed to mask dset by node indices");
3261       SUMA_free(Tb); Tb = NULL;
3262       SUMA_RETURN(NULL);
3263    }
3264 
3265    SUMA_RETURN(dset_m);
3266 }
3267 
SUMA_MaskedByOrderedNodeIndexCopyofDset(SUMA_DSET * odset,int * indexlist_orig,int N_indexlist_orig,byte * colmask,int masked_only,int keep_node_index)3268 SUMA_DSET * SUMA_MaskedByOrderedNodeIndexCopyofDset(
3269       SUMA_DSET *odset, int *indexlist_orig,
3270       int N_indexlist_orig, byte *colmask,
3271       int masked_only, int keep_node_index)
3272 {
3273    static char FuncName[]={"SUMA_MaskedByOrderedNodeIndexCopyofDset"};
3274    SUMA_DSET *dset_uo = NULL;
3275    int *rowofnode = NULL, i=0, c=0, nn=0,rownodebuf=0, *nl=NULL, nlbuf=0;
3276    NI_rowtype *rt = NULL;
3277    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
3278    void *vcol=NULL;
3279    byte bbuf=0, *bcol=NULL;
3280    short sbuf=0, *scol=NULL;
3281    int ibuf=0, *icol=NULL;
3282    float fbuf=0, *fcol=NULL;
3283    double dbuf=0, *dcol=NULL, range[2];
3284    int *indexlist=NULL, N_indexlist=-1;
3285    SUMA_Boolean LocalHead = NOPE;
3286 
3287    SUMA_ENTRY;
3288 
3289    dset_uo = SUMA_MaskedByNodeIndexCopyofDset(
3290                odset, indexlist_orig, N_indexlist_orig,
3291                colmask, masked_only,keep_node_index);
3292 
3293    /* now we have the dset we want, but the oder is shuffled. */
3294    if (!(rowofnode = SUMA_CreateNodeIndexToRowIndexMap(dset_uo, -1, range))) {
3295       SUMA_S_Err("Failed to create map");
3296       SUMA_RETURN(NULL);
3297    }
3298    if (!(nl = SDSET_NODE_INDEX_COL(dset_uo))) {
3299       SUMA_S_Err("Need a node index to do this");
3300       SUMA_RETURN(NULL);
3301    }
3302    /* trim index list of bad indices */
3303    if (SDSET_VECLEN(dset_uo) < N_indexlist_orig) {
3304       indexlist = (int *)SUMA_calloc(SDSET_VECALLOC(dset_uo), sizeof(int));
3305       N_indexlist = 0;
3306       while (i < N_indexlist_orig) {
3307          if (  indexlist_orig[i] >= (int)range[0] &&
3308                indexlist_orig[i] <= (int)range[1]) {
3309             if (N_indexlist < SDSET_VECLEN(dset_uo)) {
3310                indexlist[N_indexlist] = indexlist_orig[i]; ++N_indexlist;
3311             } else {
3312                SUMA_S_Err("Unexpected N_indexlist > SDSET_VECLEN");
3313                SUMA_RETURN(NULL);
3314             }
3315          }
3316          ++i;
3317       }
3318    } else {
3319       indexlist = indexlist_orig;
3320       N_indexlist = N_indexlist_orig;
3321    }
3322 
3323    /* get a buffer dset that has one row only. */
3324    for (i=0; i<N_indexlist; ++i) {
3325       nn = indexlist[i];
3326       if (rowofnode[nn] == i) { /* all is good */
3327       } else {
3328          for (c=0; c<SDSET_VECNUM(dset_uo); ++c) {
3329             bcol=NULL; bbuf=0;
3330             scol=NULL; sbuf=0;
3331             icol=NULL; ibuf=0;
3332             fcol=NULL; fbuf=0.0;
3333             dcol=NULL; dbuf=0.0;
3334             vcol = SDSET_VEC(dset_uo, c);
3335             ctp = SUMA_TypeOfDsetColNumb(dset_uo, c);
3336             rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ;
3337             /* need to put data from node nn in row i */
3338             switch(rt->code) {
3339                case NI_BYTE:
3340                   bcol = (byte*)vcol;
3341                   bbuf = bcol[i];
3342                   bcol[i] = bcol[rowofnode[nn]];
3343                   bcol[rowofnode[nn]] = bbuf;
3344                   break;
3345                case NI_SHORT:
3346                   scol = (short*)vcol;
3347                   sbuf = scol[i];
3348                   scol[i] = scol[rowofnode[nn]];
3349                   scol[rowofnode[nn]] = sbuf;
3350                   break;
3351                case NI_INT:
3352                   icol = (int*)vcol;
3353                   ibuf = icol[i];
3354                   icol[i] = icol[rowofnode[nn]];
3355                   icol[rowofnode[nn]] = ibuf;
3356                   break;
3357                case NI_FLOAT:
3358                   fcol = (float*)vcol;
3359                   fbuf = fcol[i];
3360                   fcol[i] = fcol[rowofnode[nn]];
3361                   fcol[rowofnode[nn]] = fbuf;
3362                   break;
3363                case NI_DOUBLE:
3364                   dcol = (double*)vcol;
3365                   dbuf = dcol[i];
3366                   dcol[i] = dcol[rowofnode[nn]];
3367                   dcol[rowofnode[nn]] = dbuf;
3368                   break;
3369                default:
3370                SUMA_SL_Warn(
3371                   "Type not allowed for padding operation, skipping");
3372                break;
3373             }
3374          }/* for each column c */
3375          rownodebuf = rowofnode[nn];
3376          rowofnode[nn] = i;
3377          rowofnode[nl[i]] = rownodebuf;
3378          nlbuf = nl[i];
3379          nl[i] = nn;
3380          nl[rownodebuf] = nlbuf;
3381       }
3382    }
3383    if (indexlist_orig !=  indexlist) SUMA_free(indexlist); indexlist = NULL;
3384    if (rowofnode) SUMA_free(rowofnode); rowofnode=NULL;
3385    SUMA_RETURN(dset_uo);
3386 }
3387 
3388 /*!
3389    \brief creates a new dataset that has a copy of each row in odset
3390    wherever rowmask[irow] is not zero.
3391    \param odset (SUMA_DSET *) input dataset
3392    \param rowmask (byte *) [nel->vec_len x 1]
3393                vector specifying which rows to preserve
3394                If rowmask[irow] is 1 then this row is copied
3395                into ndset.
3396                If rowmask[irow] = 0 then the row is either
3397                skipped (see masked_only) or set to 0 in its entirety
3398                (see keep_node_index for exception).
3399                If rowmask == NULL then all rows are copied
3400    \param colmask (byte *) [nel->vec_num x 1]
3401                vector specifying which volumns to operate on.
3402                If colmask[icol] is 1 then values in this column
3403                are copied.
3404                If colmask == NULL then all columns are copied
3405    \param masked_only (int)   If 1 then the output dataset is only to contain
3406                those rows where rowmask[irow] = 1
3407                If 0 then all rows are output but with column entries set to 0
3408                for all rows where rowmask[irow] = 0. One column might be
3409                exempt from nulling if it meets the requirements on
3410                Schedule B form suma654.233
3411                or if it is of the type SUMA_NODE_INDEX and keep_node_index
3412                is set to 1.
3413 
3414    \param keep_node_index (int)
3415                If 1, then preserves the node index column (SUMA_NODE_INDEX)
3416                from being masked.
3417                Makes sense to use it when masked_only == 0.
3418    \param ndset (SUMA_DSET *) Copy of dataset with masking applied.
3419 
3420    - You might want to have a version that replaces columns in odset with
3421    the masked data
3422    as opposed to copying them.
3423    I think I do something like this with the drawn ROI dataset...
3424 
3425    This function should now work with Graph Dsets
3426 
3427    \sa SUMA_Copy_Part_Column, SUMA_MaskedByNodeIndexCopyofDset
3428 */
SUMA_EmptyCopyofDset(SUMA_DSET * odset,byte * rowmask,int masked_only,int keep_node_index)3429 SUMA_DSET * SUMA_EmptyCopyofDset (  SUMA_DSET *odset,
3430                                     byte *rowmask,
3431                                     int masked_only, int keep_node_index)
3432 {
3433    static char FuncName[]={"SUMA_EmptyCopyofDset"};
3434    SUMA_DSET *ndset=NULL;
3435    int i, n_incopy=-1;
3436    NI_rowtype *rti=NULL;
3437    void *ind=NULL, *indp1=NULL, *indp2=NULL, *ncoli = NULL,
3438         *ncolp1=NULL, *ncolp2=NULL;
3439    char *new_name=NULL, idcode[SUMA_IDCODE_LENGTH], *lblcp=NULL;
3440    SUMA_Boolean LocalHead = NOPE;
3441 
3442    SUMA_ENTRY;
3443 
3444    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
3445    if (LocalHead && SUMA_isCIFTIDset(odset)) {
3446       SUMA_S_Warn("Not fully tested for CIFTI dsets. Returned dataset is"
3447       	          "a single domain one.");
3448    }
3449    ind = SDSET_NODE_INDEX_COL(odset);
3450    if (rowmask && !ind) {
3451       SUMA_S_Note("Will force population of node index element");
3452       SUMA_PopulateDsetNodeIndexNel(odset,0);
3453    }
3454    /* deal with node index element */
3455    if ((ind = SDSET_NODE_INDEX_COL(odset))) {
3456       rti = NI_rowtype_find_code(SUMA_ColType2TypeCast(SUMA_NODE_INDEX)) ;
3457       if (SUMA_isGraphDset(odset)) {
3458           indp1 = SDSET_EDGE_P1_INDEX_COL(odset);
3459           indp2 = SDSET_EDGE_P2_INDEX_COL(odset);
3460           if (!indp1 || !indp2) {
3461             SUMA_S_Err("This should not happen here, bad index element?");
3462             SUMA_RETURN(ndset);
3463           }
3464       }
3465       if (0 && LocalHead) {
3466          char *ss=NULL;
3467          SUMA_LH("Pre copy");
3468          SUMA_ShowNel((void*)odset->inel);
3469          ss = SUMA_ShowMeSome(ind, SUMA_int, SDSET_VECLEN(odset), -1, NULL);
3470          SUMA_S_Note("%s",ss); if (ss) SUMA_free(ss); ss = NULL;
3471       }
3472       if (keep_node_index && !masked_only) {
3473          /* preserve all rows */
3474          ncoli = SUMA_Copy_Part_Column(
3475                   ind, rti, SDSET_VECLEN(odset),
3476                   NULL, masked_only, &n_incopy);
3477          if (SUMA_isGraphDset(odset)) {
3478             ncolp1 = SUMA_Copy_Part_Column(
3479                   indp1, rti, SDSET_VECLEN(odset),
3480                   NULL, masked_only, &n_incopy);
3481             ncolp2 = SUMA_Copy_Part_Column(
3482                   indp2, rti, SDSET_VECLEN(odset),
3483                   NULL, masked_only, &n_incopy);
3484          }
3485       } else {
3486          ncoli = SUMA_Copy_Part_Column(
3487                   ind, rti, SDSET_VECLEN(odset),
3488                   rowmask, masked_only, &n_incopy);
3489          if (SUMA_isGraphDset(odset)) {
3490             ncolp1 = SUMA_Copy_Part_Column(
3491                   indp1, rti, SDSET_VECLEN(odset),
3492                   rowmask, masked_only, &n_incopy);
3493             ncolp2 = SUMA_Copy_Part_Column(
3494                   indp2, rti, SDSET_VECLEN(odset),
3495                   rowmask, masked_only, &n_incopy);
3496          }
3497       }
3498       if (!ncoli) {
3499          SUMA_SL_Err("No index data got copied.");
3500          SUMA_RETURN(ndset);
3501       }
3502       if (SUMA_isGraphDset(odset) && (!ncolp1 || !ncolp2)) {
3503          SUMA_SL_Err("No point index data got copied.");
3504          SUMA_RETURN(ndset);
3505       }
3506       if (0 && LocalHead) {
3507          char *ss=NULL;
3508          SUMA_LH("Post copy");
3509          SUMA_ShowNel((void*)odset->inel);
3510          ss = SUMA_ShowMeSome(ncoli, SUMA_int, n_incopy, -1, NULL);
3511          SUMA_S_Note("%s",ss); if (ss) SUMA_free(ss); ss = NULL;
3512       }
3513    } else { /* no node index to work with */
3514       if (keep_node_index && !masked_only) {
3515          n_incopy = SDSET_VECLEN(odset);
3516       } else {
3517          if (rowmask) {
3518             n_incopy = 0;
3519             for (i=0; i<SDSET_VECLEN(odset); ++i) if (rowmask[i]) ++n_incopy;
3520          } else {
3521             n_incopy = SDSET_VECLEN(odset);
3522          }
3523       }
3524    }
3525    SUMA_LH("Forming new dset");
3526 
3527    /* Now create a new dset */
3528    new_name = SUMA_append_string( NI_get_attribute(odset->ngr,"filename"),
3529                                   "copy");
3530    UNIQ_idcode_fill(idcode);
3531    ndset =  SUMA_CreateDsetPointer(
3532                               new_name,
3533                               SUMA_Dset_Type(NEL_DSET_TYPE(odset->ngr)),
3534                               idcode,
3535                               NI_get_attribute(odset->ngr,
3536                               "domain_parent_idcode"),
3537                               n_incopy );
3538    SUMA_free(new_name); new_name = NULL;
3539    if (ncoli) {
3540       SUMA_LH("Adding ncoli");
3541       if (!SUMA_AddDsetNelCol (ndset,
3542                      "node index",
3543                      SUMA_NODE_INDEX, ncoli, NULL ,1)) {
3544          SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
3545          SUMA_FreeDset((void*)ndset); ndset = NULL;
3546          SUMA_RETURN(ndset);
3547       }
3548       SUMA_free(ncoli); ncoli=NULL;
3549       if (ncolp1 && ncolp2) {
3550          if (!SUMA_AddDsetNelCol (ndset,
3551                      "P1 index",
3552                      SUMA_EDGE_P1_INDEX, ncolp1, NULL ,1)) {
3553             SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
3554             SUMA_FreeDset((void*)ndset); ndset = NULL;
3555             SUMA_RETURN(ndset);
3556          }
3557          if (!SUMA_AddDsetNelCol (ndset,
3558                      "P2 index",
3559                      SUMA_EDGE_P2_INDEX, ncolp2, NULL ,1)) {
3560             SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
3561             SUMA_FreeDset((void*)ndset); ndset = NULL;
3562             SUMA_RETURN(ndset);
3563          }
3564          SUMA_free(ncolp1); ncolp1=NULL;
3565          SUMA_free(ncolp2); ncolp2=NULL;
3566       }
3567    }
3568 
3569 
3570    /* Here you would use SUMA_CopyDsetAttributes
3571    with attr_list consisting of attributes that
3572    are Dsetwide. To do so, set isrc and idest to -1
3573    For now, there is no such attributes that need to
3574    be copied. */
3575 
3576    SUMA_RETURN(ndset);
3577 }
3578 /*
3579    Scan dataset for nans/infs and replace them with 0
3580 */
SUMA_FloatScanDset(SUMA_DSET * odset,int doNan,int doInf,int zerout,int fixrange)3581 int SUMA_FloatScanDset ( SUMA_DSET *odset, int doNan, int doInf, int zerout,
3582                          int fixrange )
3583 {
3584    static char FuncName[]={"SUMA_FloatScanDset"};
3585    int i, j, nfixed=0, nfixed_total = 0, nwarn=0;
3586    NI_rowtype *rt = NULL;
3587    void *ndat=NULL;
3588    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
3589    SUMA_Boolean LocalHead = NOPE;
3590 
3591    SUMA_ENTRY;
3592    SUMA_LH("IN");
3593    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(nfixed_total); }
3594    if (!doNan && !doInf) {
3595       SUMA_SL_Err("Nothing to do"); SUMA_RETURN(nfixed_total);
3596    }
3597    if (fixrange) zerout = 1; /* no point in fixing range without zeroing out */
3598 
3599    /* scan each column in dset, get a full copy back */
3600    nfixed_total = 0;
3601    for (i=0; i < SDSET_VECNUM(odset); ++i) {
3602          nfixed = 0;
3603          ctp = SUMA_TypeOfDsetColNumb(odset, i);
3604          rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ;
3605          if( rt == NULL || ROWTYPE_is_varsize(rt)) {
3606             SUMA_S_Warn("Could not recognize rowtype, or rowtype is of "
3607                         "variable size. Column will be skipped.");
3608             continue;
3609          }
3610 
3611          /* scan */
3612          switch (rt->code) {
3613             case NI_BYTE:
3614             case NI_SHORT:
3615             case NI_INT:
3616                /* No illegal bits */
3617                break;
3618             case NI_FLOAT:
3619                {
3620                   float *fv=(float *)odset->dnel->vec[i];
3621                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3622                      if (doNan && isnan(fv[j])) {
3623                         ++nfixed;
3624                         if (zerout) fv[j]=0.0;
3625                      } else if (doInf && isinf(fv[j])) {
3626                         ++nfixed;
3627                         if (zerout) fv[j]=0.0;
3628                      }
3629                }
3630                break;
3631             case NI_DOUBLE:
3632                {
3633                   double *dv=(double *)odset->dnel->vec[i];
3634                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3635                      if (doNan && isnan(dv[j])) {
3636                         ++nfixed;
3637                         if (zerout) dv[j]=0.0;
3638                      } else if (doInf && isinf(dv[j])) {
3639                         ++nfixed;
3640                         if (zerout) dv[j]=0.0;
3641                      }
3642                }
3643                break;
3644             case NI_COMPLEX:
3645                {
3646                   complex *cxv=(complex *)odset->dnel->vec[i];
3647                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3648                      if (doNan && (isnan(cxv[j].r) || isnan(cxv[j].i))) {
3649                         ++nfixed;
3650                         if (zerout) { cxv[j].r=0.0; cxv[j].i=0.0; }
3651                      } else if (doInf && (isinf(cxv[j].r) || isinf(cxv[j].i))) {
3652                         ++nfixed;
3653                         if (zerout) { cxv[j].r=0.0; cxv[j].i=0.0; }
3654                      }
3655                }
3656                break;
3657             default:
3658                /* nothing to check here either */
3659                break;
3660          }
3661          if (nfixed && fixrange) {
3662             if (!nwarn) {
3663                SUMA_S_Note("Recomputing range for column with inf or nans\n"
3664                         "Message muted for other columns");
3665             }
3666             ++nwarn;
3667             SUMA_UpdateDsetColRange(odset, i);
3668          }
3669          nfixed_total += nfixed;
3670    }
3671    SUMA_LH("OUT");
3672    SUMA_RETURN(nfixed_total);
3673 }
3674 
3675 /* Return a full and node_index-sorted version of the input dataset.
3676 */
SUMA_PaddedCopyofDset(SUMA_DSET * odset,int MaxNodeIndex)3677 SUMA_DSET * SUMA_PaddedCopyofDset ( SUMA_DSET *odset, int MaxNodeIndex )
3678 {
3679    static char FuncName[]={"SUMA_PaddedCopyofDset"};
3680    SUMA_DSET *ndset=NULL;
3681    int i, n_incopy=-1, j, *indold = NULL, *indnew = NULL, N_inmask;
3682    NI_rowtype *rti=NULL, *rt = NULL;
3683    char *new_name=NULL, idcode[SUMA_IDCODE_LENGTH], *lblcp=NULL;
3684    void *ndat=NULL;
3685    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
3686    SUMA_Boolean LocalHead = NOPE;
3687 
3688    SUMA_ENTRY;
3689 
3690    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
3691    if (SUMA_isCIFTIDset(odset)) {
3692       SUMA_SL_Err("Not ready for CIFTI"); SUMA_RETURN(NULL);
3693    }
3694    /* deal with node index element */
3695    if ((indold = SDSET_NODE_INDEX_COL(odset))) {
3696       rti = NI_rowtype_find_code(SUMA_ColType2TypeCast(SUMA_NODE_INDEX)) ;
3697    } else { /* no node index to work with */
3698       SUMA_S_Err("No node index element!");
3699       SUMA_RETURN(NULL);
3700    }
3701 
3702    DSET_MAX_NODE_INDEX(odset, i);
3703    if (MaxNodeIndex < i) {
3704       SUMA_S_Errv("MaxNodeIndex =%d but dset has nodes up to %d\n",
3705                   MaxNodeIndex, i);
3706       SUMA_RETURN(NULL);
3707    }
3708 
3709    /* form new indices */
3710    if (!(indnew = (int *)SUMA_calloc(MaxNodeIndex+1, sizeof(int)))) {
3711       SUMA_S_Crit("Failed to allocate for indnew!");
3712       SUMA_RETURN(NULL);
3713    }
3714    for (i=0; i<MaxNodeIndex+1; ++i) indnew[i] = i;
3715    SUMA_LH("Forming new dset");
3716 
3717    /* Now create a new dset */
3718    new_name = SUMA_append_string( NI_get_attribute(odset->ngr,"filename"),
3719                                   "padded");
3720    UNIQ_idcode_fill(idcode);
3721    ndset =  SUMA_CreateDsetPointer(
3722                               new_name,
3723                               SUMA_Dset_Type(NEL_DSET_TYPE(odset->ngr)),
3724                               idcode,
3725                               NI_get_attribute(odset->ngr,
3726                               "domain_parent_idcode"),
3727                               MaxNodeIndex+1);
3728    SUMA_free(new_name); new_name = NULL;
3729 
3730 
3731    SUMA_COPY_DSETWIDE_ATTRIBUTES(odset, ndset);
3732 
3733    SUMA_LH("Adding indnew");
3734    if (!SUMA_AddDsetNelCol (ndset,
3735                   NI_get_attribute(ndset->inel,"COLMS_LABS"),
3736                   SUMA_NODE_INDEX, (void *)indnew, NULL ,1)) {
3737       SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
3738       SUMA_FreeDset((void*)ndset); ndset = NULL;
3739       SUMA_RETURN(ndset);
3740    }
3741 
3742    /* for each column in dset, get a full copy back */
3743    for (i=0; i < SDSET_VECNUM(odset); ++i) {
3744          ctp = SUMA_TypeOfDsetColNumb(odset, i);
3745          rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ;
3746          if( rt == NULL || ROWTYPE_is_varsize(rt)) {
3747             SUMA_S_Warn("Could not recognize rowtype, or rowtype is of "
3748                         "variable size. Column will be skipped.");
3749             continue;
3750          }
3751          /* Allocate */
3752          switch (rt->code) {
3753             case NI_BYTE:
3754                ndat = SUMA_calloc(MaxNodeIndex+1, sizeof(byte));
3755                break;
3756              case NI_SHORT:
3757                ndat = SUMA_calloc(MaxNodeIndex+1, sizeof(short));
3758                break;
3759              case NI_INT:
3760                ndat = SUMA_calloc(MaxNodeIndex+1, sizeof(int));
3761                break;
3762              case NI_FLOAT:
3763                ndat = SUMA_calloc(MaxNodeIndex+1, sizeof(float));
3764                break;
3765              case NI_DOUBLE:
3766                ndat = SUMA_calloc(MaxNodeIndex+1, sizeof(double));
3767                break;
3768              case NI_COMPLEX:
3769                ndat = SUMA_calloc(MaxNodeIndex+1, sizeof(complex));
3770                break;
3771              default:
3772                SUMA_SL_Warn(
3773                   "Type not allowed for padding operation, skipping");
3774                break;
3775          }
3776          /* fill up */
3777          SUMA_LH("Preserving rows in mask only");
3778          switch (rt->code) {
3779             case NI_BYTE:
3780                {
3781                   byte *bv=(byte *)odset->dnel->vec[i];
3782                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3783                      if (indold[j] <= MaxNodeIndex){
3784                         SUMA_ASSIGN_VALUE_IN_VEC ( ndat, indold[j],
3785                                                    byte, bv[j]);
3786                      }
3787                }
3788                break;
3789             case NI_SHORT:
3790                {
3791                   short *sv=(short *)odset->dnel->vec[i];
3792                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3793                      if (indold[j] <= MaxNodeIndex) {
3794                         SUMA_ASSIGN_VALUE_IN_VEC ( ndat, indold[j],
3795                                                    short, sv[j]);
3796                      }
3797                }
3798                break;
3799             case NI_INT:
3800                {
3801                   int *iv=(int *)odset->dnel->vec[i];
3802                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3803                      if (indold[j] <= MaxNodeIndex) {
3804                         SUMA_ASSIGN_VALUE_IN_VEC ( ndat, indold[j],
3805                                                 int, iv[j]);
3806                      }
3807                }
3808                break;
3809             case NI_FLOAT:
3810                {
3811                   float *fv=(float *)odset->dnel->vec[i];
3812                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3813                      if (indold[j] <= MaxNodeIndex) {
3814                         SUMA_ASSIGN_VALUE_IN_VEC ( ndat, indold[j],
3815                                                    float, fv[j]);
3816                      }
3817                }
3818                break;
3819             case NI_DOUBLE:
3820                {
3821                   double *dv=(double *)odset->dnel->vec[i];
3822                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3823                      if (indold[j] <= MaxNodeIndex) {
3824                         SUMA_ASSIGN_VALUE_IN_VEC ( ndat, indold[j],
3825                                                    double, dv[j]);
3826                      }
3827                }
3828                break;
3829             case NI_COMPLEX:
3830                {
3831                   complex *cxx=NULL, *cxv=(complex *)odset->dnel->vec[i];
3832                   for (j=0; j<SDSET_VECFILLED(odset); ++j)
3833                      if (indold[j] <= MaxNodeIndex) {
3834                         cxx = (complex *)ndat;
3835                         cxx[indold[j]].r = cxv[j].r;
3836                         cxx[indold[j]].i = cxv[j].i;
3837                      }
3838                }
3839                break;
3840             default:
3841                SUMA_SL_Warn(
3842                   "Type not allowed for masking operation, skipping.");
3843                break;
3844          }
3845 
3846          switch (rt->code) {
3847             case NI_BYTE:
3848             case NI_SHORT:
3849             case NI_INT:
3850             case NI_FLOAT:
3851             case NI_DOUBLE:
3852             case NI_COMPLEX:
3853                /* add the column */
3854                SUMA_LH("Getting the label");
3855                lblcp = SUMA_DsetColLabelCopy(odset, i, 0);
3856                SUMA_LH("Inserting the column");
3857                if (!SUMA_AddDsetNelCol (  ndset, lblcp, ctp,
3858                                           ndat, NULL ,1)) {
3859                   SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
3860                   SUMA_FreeDset((void*)ndset); ndset = NULL;
3861                   SUMA_RETURN(ndset);
3862                }
3863                if (lblcp) SUMA_free(lblcp); lblcp = NULL;
3864                /* Adding other columnar attributes */
3865                SUMA_COPY_DSET_COL_ATTRIBUTES(odset, ndset,
3866                                              i, SDSET_VECNUM(ndset)-1);
3867 
3868                break;
3869             default:
3870                SUMA_SL_Warn(
3871                   "Type not allowed for masking operation, skipping.");
3872                break;
3873          }
3874    }
3875 
3876    SUMA_RETURN(ndset);
3877 }
3878 
3879 /* Make a new copy of a dataset forcing all the columns to of type vtp */
SUMA_CoercedCopyofDset(SUMA_DSET * odset,SUMA_VARTYPE vtp,byte * colmask)3880 SUMA_DSET *SUMA_CoercedCopyofDset( SUMA_DSET *odset, SUMA_VARTYPE vtp,
3881                                    byte *colmask)
3882 {
3883    static char FuncName[]={"SUMA_CoercedCopyofDset"};
3884    int i = -1;
3885    int *coli=NULL;
3886    float *colf=NULL;
3887    void *colv=NULL;
3888    char *lblcp=NULL;
3889    SUMA_DSET *ndset=NULL;
3890    NI_rowtype *rt=NULL;
3891    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
3892    int DoThisCol=0;
3893    SUMA_Boolean LocalHead = NOPE;
3894 
3895    SUMA_ENTRY;
3896 
3897    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
3898    if (!odset->dnel) { SUMA_SL_Err("Null dnel"); SUMA_RETURN(NULL); }
3899    if (!SUMA_is_AllNumeric_dset(odset)) {
3900       SUMA_SL_Err("Function does not deal with data sets containing "
3901                   "non-numeric columns");
3902       SUMA_RETURN(NULL);
3903    }
3904    if (vtp != SUMA_int && vtp != SUMA_float) {
3905       SUMA_S_Err("Only SUMA_int and SUMA_float supported");
3906       SUMA_RETURN(NULL);
3907    }
3908    if (0 && LocalHead) {
3909       SUMA_ShowNel((void*)odset->dnel);
3910    }
3911 
3912    if (!ndset) {
3913       ndset = SUMA_EmptyCopyofDset( odset, NULL,
3914                                     0, 1);
3915 
3916       SUMA_COPY_DSETWIDE_ATTRIBUTES(odset, ndset);
3917    }
3918    for (i=0; i < SDSET_VECNUM(odset); ++i) {
3919       if (!colmask) DoThisCol = 1;
3920       else DoThisCol = colmask[i];
3921       if (DoThisCol) {
3922          if (LocalHead) fprintf(SUMA_STDERR,"%s:\nProcessing column %d\n",
3923                                  FuncName, i);
3924          ctp = SUMA_TypeOfDsetColNumb(odset, i);
3925          rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ;
3926          if( rt == NULL || ROWTYPE_is_varsize(rt)) {
3927             SUMA_SL_Err("Could not recognize rowtype, or rowtype is of "
3928                         "variable size."); SUMA_RETURN(NULL);
3929          }
3930          coli=NULL;
3931          colf=NULL;
3932          if (SUMA_IS_DATUM_INDEX_COL(ctp)) {
3933             SUMA_S_Err("This should not be anymore. Skipping...");
3934          } else {
3935              switch(vtp) {
3936                case SUMA_int:
3937                   if (!(coli = SUMA_DsetCol2Int (odset, i, 1))) {
3938                      SUMA_S_Errv("Failed to convert col. %d to int (%d) type",
3939                                  i, vtp);
3940                      SUMA_FreeDset(ndset); SUMA_RETURN(NULL);
3941                   }
3942                   ctp = SUMA_NODE_INT;
3943                   colv = (void *)coli;
3944                   break;
3945                case SUMA_float:
3946                   if (!(colf = SUMA_DsetCol2Float (odset, i, 1))) {
3947                      SUMA_S_Errv("Failed to convert col. %d to float (%d) type",
3948                                  i, vtp);
3949                      SUMA_FreeDset(ndset); SUMA_RETURN(NULL);
3950                   }
3951                   ctp = SUMA_NODE_FLOAT;
3952                   colv = (void *)colf;
3953                   break;
3954                default:
3955                   SUMA_S_Errv("Not ready for type %d\n", vtp);
3956                   SUMA_FreeDset(ndset); SUMA_RETURN(NULL);
3957                   break;
3958             }
3959          }
3960          if (!colv) {
3961             SUMA_SL_Err("No data got copied.");
3962             SUMA_FreeDset(ndset); SUMA_RETURN(NULL);
3963          }
3964          /* add the column */
3965          SUMA_LH("Getting the label");
3966          lblcp = SUMA_DsetColLabelCopy(odset, i, 0);
3967          SUMA_LH("Inserting the column");
3968          if (!SUMA_AddDsetNelCol (ndset, lblcp, ctp, colv, NULL ,1)) {
3969             SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
3970             SUMA_FreeDset((void*)ndset); ndset = NULL;
3971             SUMA_RETURN(ndset);
3972          }
3973          SUMA_LH("Insertion finished");
3974          if (lblcp) SUMA_free(lblcp); lblcp = NULL;
3975          /* Adding other columnar attributes */
3976          SUMA_COPY_DSET_COL_ATTRIBUTES(odset, ndset,
3977                                        i, SDSET_VECNUM(ndset)-1);
3978       } else {
3979          if (LocalHead)
3980             fprintf(SUMA_STDERR,"%s:\nSkipping column %d\n", FuncName, i);
3981       }
3982    }
3983 
3984    SUMA_RETURN(ndset);
3985 }
3986 
SUMA_MaskedCopyofDset(SUMA_DSET * odset,byte * rowmask,byte * colmask,int masked_only,int keep_node_index)3987 SUMA_DSET * SUMA_MaskedCopyofDset(  SUMA_DSET *odset,
3988                                     byte *rowmask, byte *colmask,
3989                                     int masked_only, int keep_node_index)
3990 {
3991    static char FuncName[]={"SUMA_MaskedCopyofDset"};
3992    int n_incopy = -1, i=-1;
3993    char *lblcp=NULL;
3994    SUMA_DSET *ndset=NULL;
3995    NI_rowtype *rt=NULL;
3996    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
3997    void *ncol=NULL;
3998    int DoThisCol=0;
3999    SUMA_Boolean LocalHead = NOPE;
4000 
4001    SUMA_ENTRY;
4002 
4003    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
4004    if (!odset->dnel) { SUMA_SL_Err("Null dnel"); SUMA_RETURN(NULL); }
4005    if (!SUMA_is_AllNumeric_dset(odset)) {
4006       SUMA_SL_Err("Function does not deal with data sets containing "
4007                   "non-numeric columns");
4008       SUMA_RETURN(NULL);
4009    }
4010    if (0 && LocalHead) {
4011       SUMA_ShowNel((void*)odset->dnel);
4012    }
4013 
4014    for (i=0; i < SDSET_VECNUM(odset); ++i) {
4015       if (!colmask) DoThisCol = 1;
4016       else DoThisCol = colmask[i];
4017       if (DoThisCol) {
4018          if (LocalHead) fprintf(SUMA_STDERR,"%s:\nProcessing column %d\n",
4019                                  FuncName, i);
4020          ctp = SUMA_TypeOfDsetColNumb(odset, i);
4021          rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ;
4022          if( rt == NULL || ROWTYPE_is_varsize(rt)) {
4023             SUMA_SL_Err("Could not recognize rowtype, or rowtype is of "
4024                         "variable size."); SUMA_RETURN(NULL);
4025          }
4026          if (SUMA_IS_DATUM_INDEX_COL(ctp) && keep_node_index && !masked_only) {
4027             SUMA_S_Err("This should not be anymore. Skipping...");
4028             /* preserve all rows */
4029             /* ncol = SUMA_Copy_Part_Column(odset->dnel->vec[i], rt,
4030                      SDSET_VECLEN(odset), NULL, masked_only, &n_incopy); */
4031          } else {
4032             SUMA_LH("Preserving rows in mask only");
4033             ncol = SUMA_Copy_Part_Column(
4034                                  odset->dnel->vec[i], rt,
4035                                  SDSET_VECLEN(odset), rowmask,
4036                                  masked_only, &n_incopy);
4037          }
4038          if (!ncol) {
4039             SUMA_SL_Err("No data got copied.");
4040             SUMA_RETURN(ndset);
4041          }
4042          if (!ndset) {
4043             ndset = SUMA_EmptyCopyofDset( odset, rowmask,
4044                                           masked_only, keep_node_index);
4045 
4046             SUMA_COPY_DSETWIDE_ATTRIBUTES(odset, ndset);
4047          }
4048          /* add the column */
4049          SUMA_LH("Getting the label");
4050          lblcp = SUMA_DsetColLabelCopy(odset, i, 0);
4051          SUMA_LH("Inserting the column");
4052          if (!SUMA_AddDsetNelCol (ndset, lblcp, ctp, ncol, NULL ,1)) {
4053             SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
4054             SUMA_FreeDset((void*)ndset); ndset = NULL;
4055             SUMA_RETURN(ndset);
4056          }
4057          SUMA_LH("Insertion finished");
4058          if (lblcp) SUMA_free(lblcp); lblcp = NULL;
4059          /* Adding other columnar attributes */
4060          SUMA_COPY_DSET_COL_ATTRIBUTES(odset, ndset,
4061                                        i, SDSET_VECNUM(ndset)-1);
4062          /* Free ncol, was not done before Apr. 29 2013*/
4063          SUMA_free(ncol); ncol=NULL;
4064       } else {
4065          if (LocalHead)
4066             fprintf(SUMA_STDERR,"%s:\nSkipping column %d\n", FuncName, i);
4067       }
4068    }
4069 
4070    SUMA_RETURN(ndset);
4071 }
4072 
4073 /* vertically catenate columns, creating a new dataset*/
SUMA_VcatDset(SUMA_DSET * odset,byte * rowmask,byte * colmask,int masked_only,int keep_node_index)4074 SUMA_DSET * SUMA_VcatDset(SUMA_DSET *odset,
4075                            byte *rowmask, byte *colmask,
4076                            int masked_only, int keep_node_index)
4077 {
4078    static char FuncName[]={"SUMA_VcatDset"};
4079    int n_incopy = -1, i=-1;
4080    char *lblcp=NULL, *new_name, idcode[SUMA_IDCODE_LENGTH];
4081    SUMA_DSET *ndset=NULL;
4082    NI_rowtype *rt=NULL;
4083    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
4084    void *ncol=NULL;
4085    int DoThisCol=0, rt_ncol=-1;
4086    SUMA_Boolean LocalHead = NOPE;
4087 
4088    SUMA_ENTRY;
4089 
4090    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
4091    if (!odset->dnel) { SUMA_SL_Err("Null dnel"); SUMA_RETURN(NULL); }
4092    if (!SUMA_is_AllNumeric_dset(odset)) {
4093       SUMA_SL_Err("Function does not deal with data sets containing "
4094                   "non-numeric columns");
4095       SUMA_RETURN(NULL);
4096    }
4097    if (!SUMA_is_AllConsistentColType_dset(odset, SUMA_ERROR_COL_TYPE)) {
4098       SUMA_S_Err("Must have same column types");
4099       SUMA_RETURN(NULL);
4100    }
4101    if (0 && LocalHead) {
4102       SUMA_ShowNel((void*)odset->dnel);
4103    }
4104 
4105    for (i=0; i < SDSET_VECNUM(odset); ++i) {
4106       if (!colmask) DoThisCol = 1;
4107       else DoThisCol = colmask[i];
4108       if (DoThisCol) {
4109          if (LocalHead) fprintf(SUMA_STDERR,"%s:\nProcessing column %d\n",
4110                                  FuncName, i);
4111          ctp = SUMA_TypeOfDsetColNumb(odset, i);
4112          rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ;
4113          if( rt == NULL || ROWTYPE_is_varsize(rt)) {
4114             SUMA_SL_Err("Could not recognize rowtype, or rowtype is of "
4115                         "variable size."); SUMA_RETURN(NULL);
4116          }
4117          if (SUMA_IS_DATUM_INDEX_COL(ctp) && keep_node_index && !masked_only) {
4118             SUMA_S_Err("This should not be anymore. Skipping...");
4119             /* preserve all rows */
4120             /* ncol = SUMA_Copy_Part_Column(odset->dnel->vec[i], rt,
4121                      SDSET_VECLEN(odset), NULL, masked_only, &n_incopy); */
4122          } else {
4123             SUMA_LH("Preserving rows in mask only");
4124             if (!SUMA_Append_Copy_Part_Column(odset->dnel->vec[i], rt,
4125                                  SDSET_VECLEN(odset), rowmask,
4126                                  masked_only,
4127                                  &ncol, &rt_ncol, &n_incopy)) {
4128                SUMA_SL_Err("Failed in vertical catenation");
4129                SUMA_RETURN(NULL);
4130             }
4131             if (!ncol) {
4132                SUMA_SL_Err("No data got catenated.");
4133                SUMA_RETURN(ndset);
4134             }
4135          }
4136       } else {
4137          if (LocalHead)
4138             fprintf(SUMA_STDERR,"%s:\nSkipping column %d\n", FuncName, i);
4139       }
4140    }
4141 
4142    /* Put the catenated results in here */
4143    /* Now create a new dset */
4144    new_name = SUMA_append_string( NI_get_attribute(odset->ngr,"filename"),
4145                                   "copy");
4146    UNIQ_idcode_fill(idcode);
4147    ndset =  SUMA_CreateDsetPointer(
4148                               new_name,
4149                               SUMA_Dset_Type(NEL_DSET_TYPE(odset->ngr)),
4150                               idcode,
4151                               NI_get_attribute(odset->ngr,
4152                               "domain_parent_idcode"),
4153                               n_incopy );
4154    SUMA_free(new_name); new_name = NULL;
4155 
4156 
4157    /* That's for TR and LabelTable, should be irrelevant for vertical catenation
4158       SUMA_COPY_DSETWIDE_ATTRIBUTES(odset, ndset); */
4159 
4160    /* add the catenated monster*/
4161    lblcp = SUMA_append_replace_string(
4162                      SUMA_DsetColLabelCopy(odset, 0, 0),"...","",1);
4163    if (!SUMA_AddDsetNelCol (ndset, lblcp, ctp, ncol, NULL ,1)) {
4164       SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
4165       SUMA_FreeDset((void*)ndset); ndset = NULL;
4166       SUMA_RETURN(ndset);
4167    }
4168    if (lblcp) SUMA_free(lblcp); lblcp = NULL;
4169    SUMA_free(ncol); ncol = NULL;
4170 
4171    /* copy stat sym (see SUMA_COPY_DSET_COL_ATTRIBUTES but don't go with
4172       all that the macro copies */
4173    {
4174       char *ATR_LIST[64] = {  "COLMS_STATSYM",  NULL };
4175       if (!SUMA_CopyDsetAttributes (odset, ndset, ATR_LIST, 0, 0)) {
4176          SUMA_S_Err("Failed to copy dset attributes");
4177       }
4178    }
4179 
4180    SUMA_RETURN(ndset);
4181 }
4182 
4183 /* A vertically catenating version of SUMA_Copy_Part_Column */
SUMA_Append_Copy_Part_Column(void * col,NI_rowtype * rt,int N_col,byte * rowmask,int masked_only,void ** appendhere,int * append_rowtype_code,int * n_inappendhere)4184 SUMA_Boolean SUMA_Append_Copy_Part_Column(void *col, NI_rowtype *rt, int N_col,
4185                                     byte *rowmask, int masked_only,
4186                                     void **appendhere, int *append_rowtype_code,
4187                                     int *n_inappendhere)
4188 {
4189    static char FuncName[]={"SUMA_Append_Copy_Part_Column"};
4190    SUMA_Boolean LocalHead = NOPE;
4191    int n_incopy=0;
4192    char *ndat=NULL;
4193    void *vv=NULL;
4194    SUMA_ENTRY;
4195 
4196    if (!appendhere || !append_rowtype_code || !n_inappendhere) {
4197       /* foul input */
4198       SUMA_S_Err("NULL return carriers.");
4199       SUMA_RETURN(NOPE);
4200    }
4201    if (!ROWTYPE_is_basic_code(rt->code)) {
4202        SUMA_S_Err("Not good for non-basic codes");
4203        SUMA_RETURN(NOPE);
4204    }
4205    if (!*appendhere) { /* first time */
4206       *appendhere = SUMA_Copy_Part_Column(col, rt, N_col, rowmask,
4207                                           masked_only, &n_incopy);
4208       *append_rowtype_code = rt->code;
4209       *n_inappendhere = n_incopy;
4210       SUMA_RETURN(YUP);
4211    }
4212 
4213    /* second time around */
4214    if (!ROWTYPE_is_basic_code(*append_rowtype_code)) {
4215       SUMA_S_Err("Bad type on second call, what is this?");
4216       SUMA_RETURN(NOPE);
4217    }
4218 
4219    if ( *append_rowtype_code != rt->code ) {
4220       SUMA_S_Err("Type mismatch");
4221       SUMA_RETURN(NOPE);
4222    }
4223 
4224    ndat = (char *)SUMA_Copy_Part_Column(col, rt, N_col, rowmask,
4225                                         masked_only, &n_incopy);
4226    /* OK, now realloc. be careful incrementing (*appendhere),
4227       that vector can store variables that are of different size than char */
4228    *appendhere = (char *)SUMA_realloc(*appendhere,
4229                            rt->size * (n_incopy+*n_inappendhere) *sizeof(char));
4230    memcpy((char*)(*appendhere)+(*n_inappendhere*rt->size/sizeof(char)),
4231           ndat, n_incopy*rt->size*sizeof(char));
4232    SUMA_free(ndat); ndat=NULL;
4233    *n_inappendhere = *n_inappendhere+n_incopy;
4234 
4235    SUMA_RETURN(YUP);
4236 }
4237 
4238 /*!
4239    see help for SUMA_MaskedCopyofDset
4240 
4241 */
SUMA_Copy_Part_Column(void * col,NI_rowtype * rt,int N_col,byte * rowmask,int masked_only,int * n_incopy)4242 void *SUMA_Copy_Part_Column(void *col, NI_rowtype *rt, int N_col,
4243                             byte *rowmask, int masked_only, int *n_incopy)
4244 {
4245    static char FuncName[]={"SUMA_Copy_Part_Column"};
4246    int n_alloc = -1, i, j, cnt;
4247    char *ndat = NULL;
4248    SUMA_Boolean LocalHead = NOPE;
4249    SUMA_ENTRY;
4250 
4251    *n_incopy = -1;
4252    n_alloc = 0;
4253    if (masked_only) {
4254       if (rowmask) {
4255          for (i=0; i<N_col; ++i) {
4256             if (rowmask[i]) ++n_alloc;
4257          }
4258       } else { /* copy entire column ... */
4259          n_alloc = N_col;
4260       }
4261    } else {
4262       n_alloc = N_col;
4263    }
4264 
4265    if (!n_alloc) {
4266       SUMA_SL_Err("No values to go in column...");
4267       SUMA_RETURN(NULL);
4268    }
4269 
4270    /* allocate for result */
4271          ndat = (char *)SUMA_calloc(rt->size * n_alloc ,sizeof(char)  ) ;
4272          if (!ndat) {
4273             SUMA_SL_Crit("Failed to allocate for ndat");
4274             SUMA_RETURN(NULL);
4275          }
4276          /* Now to copy the proper values */
4277          if (!masked_only) {
4278             SUMA_LH("All copy");
4279             memcpy( ndat , (char *)col , rt->size * n_alloc ) ;
4280             if (LocalHead && rt->code == NI_FLOAT) {
4281                float *fv=(float*)ndat, *cv=(float *)col;
4282                fprintf(SUMA_STDERR, "i=0; %f, %f\ni=1; %f, %f\n", fv[0], cv[0], fv[1], cv[1]);
4283             }
4284             /* reset values that are not in mask */
4285             if (rowmask) {
4286                switch(rt->code) {
4287                   case NI_BYTE:
4288                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, byte, 0);}
4289                      break;
4290                   case NI_SHORT:
4291                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, short, 0);}
4292                      break;
4293                   case NI_INT:
4294                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, int, 0);}
4295                      break;
4296                   case NI_FLOAT:
4297                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, float, 0);}
4298                      break;
4299                   case NI_DOUBLE:
4300                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, double, 0);}
4301                      break;
4302                   default:
4303                      SUMA_SL_Warn("Type not allowed for masking operation, skipping.");
4304                      break;
4305                }
4306             }
4307          } else {
4308             if (rowmask) {
4309                /* copy good values, one at a time */
4310                SUMA_LH("Masked only copy");
4311                cnt = 0;
4312                switch(rt->code) {
4313                   case NI_BYTE:
4314                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, byte, byte); ++cnt;}
4315                      break;
4316                   case NI_SHORT:
4317                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, short, short); ++cnt;}
4318                      break;
4319                   case NI_INT:
4320                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, int, int); ++cnt;}
4321                      break;
4322                   case NI_FLOAT:
4323                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, float, float); ++cnt;}
4324                      break;
4325                   case NI_DOUBLE:
4326                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, double, double); ++cnt;}
4327                      break;
4328                   default:
4329                      SUMA_SL_Warn("Type not allowed for masking operation, skipping.");
4330                      break;
4331                }
4332             } else {
4333                /* wants a copy of everything */
4334                memcpy( ndat , (char *)col , rt->size * n_alloc ) ;
4335             }
4336 
4337          }
4338    *n_incopy = n_alloc;
4339    SUMA_LH("Returning");
4340    SUMA_RETURN((void *)ndat);
4341 }
4342 /*!
4343    \brief Function to fill the contents of a pre-existing column
4344    created with SUMA_AddDsetNelCol.
4345    if vec_filled > 0 && vec_filled <= vec_len, filling is done
4346    up to vec_filled.
4347    vec_filled must be set BEFORE YOU CALL THIS FUNCTION
4348    New version of SUMA_FillNelCol
4349 
4350    Now OK for Graph Dsets
4351 */
SUMA_FillDsetNelCol(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)4352 int SUMA_FillDsetNelCol (SUMA_DSET *dset, char *col_label,
4353                      SUMA_COL_TYPE ctp, void *col,
4354                      void *col_attr, int stride)
4355 {
4356    static char FuncName[]={"SUMA_FillDsetNelCol"};
4357    int icol = -1, is_sorted;
4358    int *iv, N_i;
4359 
4360    SUMA_ENTRY;
4361 
4362    if (SUMA_IS_DATUM_INDEX_COL(ctp)) {
4363       SUMA_RETURN(SUMA_FillDsetNelNodeIndexCol (dset, col_label, ctp,
4364                                                 col, col_attr, stride));
4365    }
4366 
4367    /* find the index into vec of the column of type ctp,
4368       complain if you find more than 1 */
4369    iv = SUMA_GetDsetColIndex (dset, ctp, &N_i);
4370    if (N_i != 1) {
4371       SUMA_SL_Err("Found more than one column.\n");
4372       SUMA_RETURN(-1);
4373    }
4374    icol = iv[0];
4375    SUMA_free(iv); iv = NULL;
4376 
4377    /* Now use the function NI_fill_column_stride
4378    that I have yet to write in nim_element.c
4379    (a modification of NI_add_column_stride) and
4380    you're all set */
4381    switch (SUMA_ColType2TypeCast(ctp)) {
4382       case SUMA_int:
4383          NI_fill_column_stride ( dset->dnel, NI_INT, (int *)col, icol, stride);
4384          break;
4385       case SUMA_float:
4386          NI_fill_column_stride ( dset->dnel, NI_FLOAT, (float *)col,
4387                                  icol, stride );
4388          break;
4389       case SUMA_byte:
4390          NI_fill_column_stride ( dset->dnel, NI_BYTE, (byte *)col,
4391                                  icol, stride );
4392          break;
4393       case SUMA_string:
4394          NI_fill_column_stride ( dset->dnel, NI_STRING, (char **)col,
4395                                  icol, stride );
4396          break;
4397       case SUMA_double:
4398          NI_fill_column_stride ( dset->dnel, NI_DOUBLE, (double *)col,
4399                                  icol, stride );
4400          break;
4401       case SUMA_complex:
4402          NI_fill_column_stride ( dset->dnel, NI_COMPLEX, (complex *)col,
4403                                  icol, stride );
4404          break;
4405       default:
4406          fprintf  (stderr,"Error %s: Bad column type.\n", FuncName);
4407          SUMA_RETURN(0);
4408          break;
4409    }
4410 
4411    /* set some generic attributes */
4412    SUMA_AddGenDsetColAttr (dset, ctp, col, stride, icol, 0);
4413    /* add the attributes of that column */
4414    SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, icol, 0 );
4415 
4416    SUMA_RETURN(1);
4417 }
4418 
4419 /* Function now OK for Graph Dsets */
SUMA_FillDsetNelNodeIndexCol(SUMA_DSET * dset,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)4420 int SUMA_FillDsetNelNodeIndexCol (SUMA_DSET *dset, char *col_label,
4421                                   SUMA_COL_TYPE ctp, void *col,
4422                                   void *col_attr, int stride)
4423 {
4424    static char FuncName[]={"SUMA_FillDsetNelNodeIndexCol"};
4425    int is_sorted, *iv=NULL;
4426 
4427    SUMA_ENTRY;
4428 
4429    if (!dset || !dset->inel) {
4430       SUMA_S_Err("NULL input");
4431       SUMA_RETURN(0);
4432    }
4433 
4434    if (!SUMA_IS_DATUM_INDEX_COL(ctp) && !SUMA_IS_MD_DATUM_INDEX_COL(ctp)) {
4435       SUMA_S_Err("Not for you!");
4436       SUMA_RETURN(0);
4437    }
4438 
4439    /* Now use the function NI_fill_column_stride
4440    that I have yet to write in nim_element.c
4441    (a modification of NI_add_column_stride) and
4442    you're all set */
4443    switch (SUMA_ColType2TypeCast(ctp)) {
4444       case SUMA_int:
4445          NI_fill_column_stride ( dset->inel, NI_INT, col, 0, stride);
4446          break;
4447       case SUMA_float:
4448          NI_fill_column_stride ( dset->inel, NI_FLOAT, col, 0, stride );
4449          break;
4450       case SUMA_byte:
4451          NI_fill_column_stride ( dset->inel, NI_BYTE, col, 0, stride );
4452          break;
4453       case SUMA_string:
4454          NI_fill_column_stride ( dset->inel, NI_STRING, col, 0, stride );
4455          break;
4456       case SUMA_double:
4457          NI_fill_column_stride ( dset->inel, NI_DOUBLE, col, 0, stride );
4458          break;
4459       case SUMA_complex:
4460          NI_fill_column_stride ( dset->inel, NI_COMPLEX, col, 0, stride );
4461          break;
4462       default:
4463          fprintf  (stderr,"Error %s: Bad column type.\n", FuncName);
4464          SUMA_RETURN(0);
4465          break;
4466    }
4467 
4468    if (ctp == SUMA_NODE_INDEX) { /* Nothing to do if SUMA_EDGE_P[12]_INDEX */
4469       if (col) {
4470          /* need to check for sortedness of list */
4471          iv = (int *)col;
4472          SUMA_IS_SORTED_UP(iv, SDSET_VECFILLED(dset), is_sorted)
4473          iv = NULL;
4474          if (is_sorted) {
4475             NI_set_attribute(dset->inel, "sorted_node_def", "Yes");
4476          } else {
4477             NI_set_attribute(dset->inel, "sorted_node_def", "No");
4478          }
4479          /* set some generic attributes */
4480          SUMA_AddGenDsetColAttr (dset, ctp, col, stride, -1, 0);
4481          /* add the attributes of that column */
4482          SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, -1, 0);
4483       } else {
4484          NI_set_attribute(dset->inel, "sorted_node_def", "Unknown");
4485       }
4486    } else if (ctp == SUMA_MD_NODE_INDEX) {
4487       if (col) {
4488          SUMA_S_Warn("Not ready to determine sorting for MD indices");
4489          NI_set_attribute(dset->inel, "sorted_node_def", "No");
4490 
4491          /* set some generic attributes */
4492          SUMA_AddGenDsetColAttr (dset, ctp, col, stride, -1, 0);
4493          /* add the attributes of that column */
4494          SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, -1, 0);
4495       } else {
4496          NI_set_attribute(dset->inel, "sorted_node_def", "Unknown");
4497       }
4498    }
4499 
4500 
4501    SUMA_RETURN(1);
4502 }
4503 /*!
4504    \brief Function to fill the contents of a pre-existing column
4505    created with SUMA_AddNelCol.
4506    if vec_filled > 0 && vec_filled <= vec_len, filling is done
4507    up to vec_filled.
4508    vec_filled must be set BEFORE YOU CALL THIS FUNCTION
4509 */
SUMA_FillNelCol(NI_element * nel,char * col_label,SUMA_COL_TYPE ctp,void * col,void * col_attr,int stride)4510 int SUMA_FillNelCol (NI_element *nel, char *col_label, SUMA_COL_TYPE ctp,
4511                      void *col,
4512                      void *col_attr, int stride)
4513 {
4514    static char FuncName[]={"SUMA_FillNelCol"};
4515    int icol = -1;
4516    int *iv, N_i, is_sorted;
4517 
4518    SUMA_ENTRY;
4519 
4520    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
4521 
4522    /* find the index into vec of the column of type ctp,
4523       complain if you find more than 1 */
4524    iv = SUMA_GetColIndex (nel, ctp, &N_i);
4525    if (N_i != 1) {
4526       SUMA_SL_Err("Found more than one column.\n");
4527       SUMA_RETURN(-1);
4528    }
4529    icol = iv[0];
4530    SUMA_free(iv); iv = NULL;
4531 
4532    /* Now use the function NI_fill_column_stride
4533    that I have yet to write in nim_element.c
4534    (a modification of NI_add_column_stride) and
4535    you're all set */
4536    switch (SUMA_ColType2TypeCast(ctp)) {
4537       case SUMA_int:
4538          NI_fill_column_stride ( nel, NI_INT, (int *)col, icol, stride);
4539          break;
4540       case SUMA_float:
4541          NI_fill_column_stride ( nel, NI_FLOAT, (float *)col, icol, stride );
4542          break;
4543       case SUMA_byte:
4544          NI_fill_column_stride ( nel, NI_BYTE, (byte *)col, icol, stride );
4545          break;
4546       case SUMA_string:
4547          NI_fill_column_stride ( nel, NI_STRING, (char **)col, icol, stride );
4548          break;
4549       case SUMA_double:
4550          NI_fill_column_stride ( nel, NI_DOUBLE, (double *)col, icol, stride );
4551          break;
4552       case SUMA_complex:
4553          NI_fill_column_stride ( nel, NI_COMPLEX, (complex *)col, icol, stride );
4554          break;
4555       default:
4556          fprintf  (stderr,"Error %s: Bad column type.\n", FuncName);
4557          SUMA_RETURN(0);
4558          break;
4559    }
4560 
4561    if (ctp == SUMA_NODE_INDEX) { /* No need for sorting flag for SUMA_EDGE_P[12]_INDEX */
4562       if (col) {
4563          /* need to check for sortedness of list */
4564          iv = (int *)col;
4565          SUMA_IS_SORTED_UP(iv, nel->vec_filled, is_sorted)
4566          iv = NULL;
4567          if (is_sorted) {
4568             NI_set_attribute(nel, "sorted_node_def", "Yes");
4569          } else {
4570             NI_set_attribute(nel, "sorted_node_def", "No");
4571          }
4572       } else {
4573          NI_set_attribute(nel, "sorted_node_def", "Unknown");
4574       }
4575    }
4576 
4577    /* set some generic attributes */
4578    SUMA_AddGenColAttr (nel, ctp, col, stride, icol);
4579    /* add the attributes of that column */
4580    SUMA_AddColAttr (nel, col_label, ctp, col_attr, icol);
4581 
4582    SUMA_allow_nel_use(0);
4583    SUMA_RETURN(1);
4584 }
4585 
SUMA_CTypeName2VarType(char * vt)4586 SUMA_VARTYPE SUMA_CTypeName2VarType (char *vt)
4587 {
4588    static char FuncName[]={"SUMA_CTypeName2VarType"};
4589 
4590    SUMA_ENTRY;
4591 
4592    if (!vt) SUMA_RETURN(SUMA_notypeset);
4593 
4594    if (strstr(vt,"int")) SUMA_RETURN(SUMA_int);
4595    if (strstr(vt,"float")) SUMA_RETURN(SUMA_float);
4596    if (strstr(vt,"byte")) SUMA_RETURN(SUMA_byte);
4597    if (strstr(vt,"double")) SUMA_RETURN(SUMA_double);
4598    if (strstr(vt,"short")) SUMA_RETURN(SUMA_short);
4599    if (strstr(vt,"complex")) SUMA_RETURN(SUMA_complex);
4600 
4601    SUMA_RETURN(SUMA_notypeset);
4602 }
4603 
SUMA_VarType2CTypeName(SUMA_VARTYPE vt)4604 const char *SUMA_VarType2CTypeName (SUMA_VARTYPE vt)
4605 {
4606    static char FuncName[]={"SUMA_VarType2CTypeName"};
4607 
4608    SUMA_ENTRY;
4609 
4610    switch (vt) {
4611       case SUMA_int:
4612          SUMA_RETURN("int");
4613          break;
4614       case SUMA_float:
4615          SUMA_RETURN("float");
4616          break;
4617       case SUMA_byte:
4618          SUMA_RETURN("byte");
4619          break;
4620       case SUMA_double:
4621          SUMA_RETURN("double");
4622          break;
4623       case SUMA_short:
4624          SUMA_RETURN("short");
4625          break;
4626       case SUMA_complex:
4627          SUMA_RETURN("complex");
4628          break;
4629       default:
4630          SUMA_RETURN("dunno");
4631    }
4632 
4633 }
4634 
SUMA_SizeOf(SUMA_VARTYPE vt)4635 int SUMA_SizeOf(SUMA_VARTYPE vt)
4636 {
4637    static char FuncName[]={"SUMA_SizeOf"};
4638 
4639    SUMA_ENTRY;
4640 
4641    switch (vt) {
4642       case SUMA_int:
4643          SUMA_RETURN(sizeof(int));
4644          break;
4645       case SUMA_float:
4646          SUMA_RETURN(sizeof(float));
4647          break;
4648       case SUMA_byte:
4649          SUMA_RETURN(sizeof(byte));
4650          break;
4651       case SUMA_double:
4652          SUMA_RETURN(sizeof(double));
4653          break;
4654       case SUMA_short:
4655          SUMA_RETURN(sizeof(short));
4656          break;
4657       case SUMA_complex:
4658          SUMA_RETURN(sizeof(complex));
4659          break;
4660       default:
4661          SUMA_RETURN(-1);
4662    }
4663 
4664 }
4665 
SUMA_VarType2ColType(char * vt)4666 SUMA_COL_TYPE SUMA_VarType2ColType (char *vt)
4667 {
4668    static char FuncName[]={"SUMA_VarType2ColType"};
4669 
4670    SUMA_ENTRY;
4671 
4672    if (!vt) SUMA_RETURN(((SUMA_COL_TYPE)SUMA_notypeset));
4673 
4674    if (strstr(vt,"int")) SUMA_RETURN(SUMA_NODE_INT);
4675    if (strstr(vt,"float")) SUMA_RETURN(SUMA_NODE_FLOAT);
4676    if (strstr(vt,"byte")) SUMA_RETURN(SUMA_NODE_BYTE);
4677    if (strstr(vt,"double")) SUMA_RETURN(SUMA_NODE_DOUBLE);
4678    if (strstr(vt,"short")) SUMA_RETURN(SUMA_NODE_SHORT);
4679    if (strstr(vt,"complex")) SUMA_RETURN(SUMA_NODE_COMPLEX);
4680 
4681    SUMA_RETURN(SUMA_ERROR_COL_TYPE);
4682 }
4683 
SUMA_ColType2TypeCast(SUMA_COL_TYPE ctp)4684 SUMA_VARTYPE SUMA_ColType2TypeCast (SUMA_COL_TYPE ctp)
4685 {
4686    static char FuncName[]={"SUMA_ColType2TypeCast"};
4687 
4688    SUMA_ENTRY;
4689 
4690    switch (ctp) {
4691       case SUMA_NODE_INT:
4692       case SUMA_NODE_ILABEL:
4693       case SUMA_EDGE_P1_INDEX:
4694       case SUMA_EDGE_P2_INDEX:
4695       case SUMA_GNODE_INDEX:
4696       case SUMA_GNODE_IGROUP:
4697       case SUMA_MD_NODE_INDEX:
4698       case SUMA_NODE_INDEX:
4699          SUMA_RETURN(SUMA_int);
4700          break;
4701       case SUMA_NODE_FLOAT:
4702       case SUMA_NODE_CX:
4703       case SUMA_NODE_X:
4704       case SUMA_NODE_Y:
4705       case SUMA_NODE_Z:
4706       case SUMA_NODE_R:
4707       case SUMA_NODE_G:
4708       case SUMA_NODE_B:
4709       case SUMA_NODE_A:
4710       case SUMA_NODE_XCORR:
4711       case SUMA_NODE_ZSCORE:
4712       case SUMA_NODE_3C:
4713       case SUMA_NODE_VFR:
4714       case SUMA_NODE_PHASE:
4715       case SUMA_NODE_AREA:
4716       case SUMA_NODE_VOLUME:
4717       case SUMA_NODE_THICKNESS:
4718          SUMA_RETURN(SUMA_float);
4719          break;
4720       case SUMA_NODE_BYTE:
4721       case SUMA_NODE_Rb:
4722       case SUMA_NODE_Gb:
4723       case SUMA_NODE_Bb:
4724       case SUMA_NODE_Ab:
4725          SUMA_RETURN(SUMA_byte);
4726          break;
4727       case SUMA_NODE_DOUBLE:
4728          SUMA_RETURN(SUMA_double);
4729          break;
4730       case SUMA_NODE_COMPLEX:
4731          SUMA_RETURN(SUMA_complex);
4732          break;
4733       case SUMA_NODE_SLABEL:
4734       case SUMA_NODE_STRING:
4735          SUMA_RETURN(SUMA_string);
4736          break;
4737       case SUMA_NODE_SHORT:
4738          SUMA_RETURN(SUMA_short);
4739          break;
4740       default:
4741          fprintf  (stderr,"Error %s: Bad column type %d (Max allowed %d)\n",
4742                      FuncName, ctp, SUMA_N_COL_TYPES-1);
4743          SUMA_RETURN(SUMA_notypeset);
4744          break;
4745    }
4746 
4747    SUMA_RETURN(SUMA_notypeset);
4748 }
SUMA_Dset_Format_Name(SUMA_DSET_FORMAT fr)4749 char * SUMA_Dset_Format_Name (SUMA_DSET_FORMAT fr)
4750 {
4751    static char FuncName[]={"SUMA_Dset_Format_Name"};
4752 
4753    SUMA_ENTRY;
4754 
4755    switch(fr) {
4756       case SUMA_ERROR_DSET_FORMAT:
4757          SUMA_RETURN ("Error_Dset_Format");
4758          break;
4759       case SUMA_NO_DSET_FORMAT:
4760          SUMA_RETURN ("Dset_Format_Undefined");
4761          break;
4762       case SUMA_ASCII_NIML:
4763          SUMA_RETURN ("Ascii_Niml");
4764          break;
4765       case SUMA_BINARY_NIML:
4766          SUMA_RETURN ("Binary_Niml");
4767          break;
4768       case SUMA_NIML:
4769          SUMA_RETURN ("Niml");
4770          break;
4771       case SUMA_1D:
4772          SUMA_RETURN ("Afni_1D");
4773          break;
4774       case SUMA_XML_DSET:
4775          SUMA_RETURN ("GIFTI");
4776          break;
4777       case SUMA_XML_B64_DSET:
4778          SUMA_RETURN ("GIFTI_Base64");
4779          break;
4780       case SUMA_XML_B64GZ_DSET:
4781          SUMA_RETURN ("GIFTI_Base64_GZIPPED");
4782          break;
4783       case SUMA_XML_ASCII_DSET:
4784          SUMA_RETURN ("GIFTI_ASCII");
4785          break;
4786       case SUMA_ASCII_OPEN_DX_DSET:
4787          SUMA_RETURN ("Ascii_OpenDX_dset");
4788          break;
4789       case SUMA_N_DSET_FORMATS:
4790          SUMA_RETURN("Number_of_formats");
4791       default:
4792          SUMA_RETURN("Cowabonga-gimlauron");
4793          break;
4794    }
4795 
4796 }
4797 
SUMA_Dset_Format(char * Name)4798 SUMA_DSET_FORMAT SUMA_Dset_Format (char *Name)
4799 {
4800    static char FuncName[]={"SUMA_Dset_Format"};
4801 
4802    SUMA_ENTRY;
4803 
4804    if (!strcmp(Name,"Error_Dset_Format")) SUMA_RETURN (SUMA_ERROR_DSET_FORMAT);
4805    if (!strcmp(Name,"Dset_Format_Undefined")) SUMA_RETURN (SUMA_NO_DSET_FORMAT);
4806    if (!strcmp(Name,"Ascii_Niml")) SUMA_RETURN (SUMA_ASCII_NIML);
4807    if (!strcmp(Name,"Binary_Niml")) SUMA_RETURN (SUMA_BINARY_NIML);
4808    if (!strcmp(Name,"Niml")) SUMA_RETURN (SUMA_NIML);
4809    if (!strcmp(Name,"Afni_1D")) SUMA_RETURN (SUMA_1D);
4810    if (!strcmp(Name,"Ascii_OpenDX_dset")) SUMA_RETURN (SUMA_ASCII_OPEN_DX_DSET);
4811    if (!strcmp(Name,"GIFTI")) SUMA_RETURN (SUMA_XML_DSET);
4812    if (!strcmp(Name,"GIFTI_Base64_GZIPPED")) SUMA_RETURN (SUMA_XML_B64GZ_DSET);
4813    if (!strcmp(Name,"GIFTI_Base64")) SUMA_RETURN (SUMA_XML_B64_DSET);
4814    if (!strcmp(Name,"GIFTI_ASCII")) SUMA_RETURN (SUMA_XML_ASCII_DSET);
4815    if (!strcmp(Name,"Number_of_formats")) SUMA_RETURN (SUMA_N_DSET_FORMATS);
4816    SUMA_RETURN(SUMA_ERROR_DSET_FORMAT);
4817 }
4818 
SUMA_Dset_Type_Name(SUMA_DSET_TYPE tp)4819 char * SUMA_Dset_Type_Name (SUMA_DSET_TYPE tp)
4820 {
4821    static char FuncName[]={"SUMA_Dset_Type_Name"};
4822 
4823    SUMA_ENTRY;
4824 
4825    switch (tp) {
4826       case SUMA_NO_DSET_TYPE:
4827          SUMA_RETURN("Dset_Type_Undefined");
4828          break;
4829       case SUMA_ERROR_DSET_TYPE:
4830          SUMA_RETURN("Error_Dset_Type");
4831          break;
4832       case SUMA_NODE_BUCKET:
4833          SUMA_RETURN("Node_Bucket");
4834          break;
4835       case SUMA_VOXEL_BUCKET:
4836          SUMA_RETURN("Voxel_Bucket");
4837          break;
4838       case SUMA_AFNI_NODE_BUCKET:
4839          SUMA_RETURN("AFNI_3D_dataset");
4840          break;
4841       case SUMA_NODE_ROI:
4842          SUMA_RETURN("Node_ROI");
4843          break;
4844       case SUMA_NODE_RGB:
4845          SUMA_RETURN("Node_RGB");
4846          break;
4847       case SUMA_NODE_RGBA:
4848          SUMA_RETURN("Node_RGBA");
4849          break;
4850       case SUMA_NODE_RGBb:
4851          SUMA_RETURN("Node_RGBb");
4852          break;
4853       case SUMA_NODE_RGBAb:
4854          SUMA_RETURN("Node_RGBAb");
4855          break;
4856       case SUMA_NODE_XYZ:
4857          SUMA_RETURN("Node_XYZ");
4858          break;
4859       case SUMA_NEW_NODE_XYZ:
4860          SUMA_RETURN("NewNode_XYZ");
4861          break;
4862       case SUMA_VIEWER_SETTING:
4863          SUMA_RETURN("Viewer_Visual_Setting");
4864          break;
4865       case SUMA_NODE_CONVEXITY:
4866          SUMA_RETURN("Node_Convexity");
4867          break;
4868       case SUMA_NEW_MESH_IJK:
4869          SUMA_RETURN("NewMesh_IJK");
4870          break;
4871       case SUMA_MESH_IJK:
4872          SUMA_RETURN("Mesh_IJK");
4873          break;
4874       case SUMA_PREP_NEW_SURFACE:
4875          SUMA_RETURN("PrepNewSurface");
4876          break;
4877       case SUMA_SURFACE_VOLUME_PARENT:
4878          SUMA_RETURN("SurfaceVolumeParent");
4879          break;
4880       case SUMA_SURFACE_OBJECT:
4881          SUMA_RETURN("SurfaceObject");
4882          break;
4883       case SUMA_ENGINE_INSTRUCTION:
4884          SUMA_RETURN("EngineInstruction");
4885          break;
4886       case SUMA_SEGMENT_OBJECT:
4887          SUMA_RETURN("SegmentObject");
4888          break;
4889       case SUMA_LABEL_TABLE_OBJECT:
4890          SUMA_RETURN("LabelTableObject");
4891          break;
4892       case SUMA_NODE_LABEL:
4893          SUMA_RETURN("Node_Label");
4894          break;
4895       case SUMA_GRAPH_BUCKET:
4896          SUMA_RETURN("Graph_Bucket");
4897          break;
4898       case SUMA_TRACT_BUCKET:
4899          SUMA_RETURN("Tract_Bucket");
4900          break;
4901       case SUMA_CIFTI_BUCKET:
4902          SUMA_RETURN("CIFTI_Bucket");
4903          break;
4904       default:
4905          SUMA_RETURN("Cowabonga-gothdo");
4906          break;
4907    }
4908 }
4909 
SUMA_Dset_Type(char * Name)4910 SUMA_DSET_TYPE SUMA_Dset_Type (char *Name)
4911 {
4912    static char FuncName[]={"SUMA_Dset_Type"};
4913 
4914    SUMA_ENTRY;
4915    if (!Name) { SUMA_S_Err("Null Name"); SUMA_RETURN(SUMA_NO_DSET_TYPE); }
4916    if (!strcmp(Name,"Dset_Type_Undefined")) SUMA_RETURN (SUMA_NO_DSET_TYPE);
4917    if (!strcmp(Name,"Error_Dset_Type")) SUMA_RETURN (SUMA_ERROR_DSET_TYPE);
4918    if (!strcmp(Name,"Node_Bucket")) SUMA_RETURN (SUMA_NODE_BUCKET);
4919    if (!strcmp(Name,"Voxel_Bucket")) SUMA_RETURN (SUMA_VOXEL_BUCKET);
4920    if (!strcmp(Name,"Node_ROI")) SUMA_RETURN (SUMA_NODE_ROI);
4921    if (!strcmp(Name,"Node_RGB")) SUMA_RETURN (SUMA_NODE_RGB);
4922    if (!strcmp(Name,"Node_RGBA")) SUMA_RETURN (SUMA_NODE_RGBA);
4923    if (!strcmp(Name,"Node_RGBb")) SUMA_RETURN (SUMA_NODE_RGBb);
4924    if (!strcmp(Name,"Node_RGBAb")) SUMA_RETURN (SUMA_NODE_RGBAb);
4925    if (!strcmp(Name,"Node_XYZ")) SUMA_RETURN (SUMA_NODE_XYZ);
4926    if (!strcmp(Name,"NewNode_XYZ")) SUMA_RETURN (SUMA_NEW_NODE_XYZ);
4927    if (!strcmp(Name,"Viewer_Visual_Setting")) SUMA_RETURN (SUMA_VIEWER_SETTING);
4928    if (!strcmp(Name,"Cowabonga")) SUMA_RETURN (SUMA_ERROR_DSET_TYPE);
4929    if (!strcmp(Name,"Node_Convexity")) SUMA_RETURN (SUMA_NODE_CONVEXITY);
4930    if (!strcmp(Name,"AFNI_3D_dataset")) SUMA_RETURN (SUMA_AFNI_NODE_BUCKET);
4931    if (!strcmp(Name,"NewMesh_IJK")) SUMA_RETURN (SUMA_NEW_MESH_IJK);
4932    if (!strcmp(Name,"Mesh_IJK")) SUMA_RETURN (SUMA_MESH_IJK);
4933    if (!strcmp(Name,"PrepNewSurface")) SUMA_RETURN (SUMA_PREP_NEW_SURFACE);
4934    if (!strcmp(Name,"SurfaceVolumeParent"))
4935       SUMA_RETURN (SUMA_SURFACE_VOLUME_PARENT);
4936    if (!strcmp(Name,"SurfaceObject")) SUMA_RETURN (SUMA_SURFACE_OBJECT);
4937    if (!strcmp(Name,"EngineInstruction")) SUMA_RETURN (SUMA_ENGINE_INSTRUCTION);
4938    if (!strcmp(Name,"SegmentObject")) SUMA_RETURN (SUMA_SEGMENT_OBJECT);
4939    if (!strcmp(Name,"LabelTableObject")) SUMA_RETURN (SUMA_LABEL_TABLE_OBJECT);
4940    if (!strcmp(Name,"Node_Label")) SUMA_RETURN (SUMA_NODE_LABEL);
4941    if (!strcmp(Name,"Tract_Bucket")) SUMA_RETURN (SUMA_TRACT_BUCKET);
4942    if (!strcmp(Name,"Graph_Bucket")) SUMA_RETURN (SUMA_GRAPH_BUCKET);
4943    if (!strcmp(Name,"CIFTI_Bucket")) SUMA_RETURN (SUMA_CIFTI_BUCKET);
4944 
4945    SUMA_RETURN (SUMA_ERROR_DSET_TYPE);
4946 }
4947 
SUMA_Col_Type_Name(SUMA_COL_TYPE tp)4948 char * SUMA_Col_Type_Name (SUMA_COL_TYPE tp)
4949 {
4950    static char FuncName[]={"SUMA_Col_Type_Name"};
4951 
4952    SUMA_ENTRY;
4953 
4954    switch (tp) {
4955       case SUMA_NO_COL_TYPE:
4956          SUMA_RETURN("Col_Type_Undefined");
4957          break;
4958       case SUMA_ERROR_COL_TYPE:
4959          SUMA_RETURN ("Error_Col_Type");
4960          break;
4961       case SUMA_NODE_INT:
4962          SUMA_RETURN("Generic_Int");
4963          break;
4964       case SUMA_NODE_INDEX:
4965          SUMA_RETURN("Node_Index");
4966          break;
4967       case SUMA_MD_NODE_INDEX:
4968          SUMA_RETURN("MD_Node_Index");
4969          break;
4970       case SUMA_GNODE_INDEX:
4971          SUMA_RETURN("GNode_Index");
4972          break;
4973       case SUMA_GNODE_IGROUP:
4974          SUMA_RETURN("GNode_Group");
4975          break;
4976       case SUMA_EDGE_P1_INDEX:
4977          SUMA_RETURN("Edge_P1_Index");
4978          break;
4979       case SUMA_EDGE_P2_INDEX:
4980          SUMA_RETURN("Edge_P2_Index");
4981          break;
4982       case SUMA_NODE_ILABEL:
4983          SUMA_RETURN("Node_Index_Label");
4984          break;
4985       case SUMA_NODE_FLOAT:
4986          SUMA_RETURN("Generic_Float");
4987          break;
4988       case SUMA_NODE_SHORT:
4989          SUMA_RETURN("Generic_Short");
4990          break;
4991       case SUMA_NODE_3C:
4992          SUMA_RETURN("XYZ_triplets");
4993          break;
4994       case SUMA_NODE_X:
4995          SUMA_RETURN("X_coord");
4996          break;
4997       case SUMA_NODE_Y:
4998          SUMA_RETURN("Y_coord");
4999          break;
5000       case SUMA_NODE_Z:
5001          SUMA_RETURN("Z_coord");
5002          break;
5003       case SUMA_NODE_R:
5004          SUMA_RETURN("R_col");
5005          break;
5006       case SUMA_NODE_G:
5007          SUMA_RETURN("G_col");
5008          break;
5009       case SUMA_NODE_B:
5010          SUMA_RETURN("B_col");
5011          break;
5012       case SUMA_NODE_A:
5013          SUMA_RETURN("A_col");
5014          break;
5015       case SUMA_NODE_Rb:
5016          SUMA_RETURN("Rb_col");
5017          break;
5018       case SUMA_NODE_Gb:
5019          SUMA_RETURN("Gb_col");
5020          break;
5021       case SUMA_NODE_Bb:
5022          SUMA_RETURN("Bb_col");
5023          break;
5024       case SUMA_NODE_Ab:
5025          SUMA_RETURN("Ab_col");
5026          break;
5027       case SUMA_NODE_SLABEL:
5028          SUMA_RETURN("Node_String_Label");
5029          break;
5030       case SUMA_NODE_STRING:
5031          SUMA_RETURN("Generic_String");
5032          break;
5033       case SUMA_NODE_COMPLEX:
5034          SUMA_RETURN("Generic_Complex");
5035          break;
5036       case SUMA_NODE_CX:
5037          SUMA_RETURN("Convexity");
5038          break;
5039       case SUMA_NODE_BYTE:
5040          SUMA_RETURN("Generic_Byte");
5041          break;
5042       case SUMA_NODE_DOUBLE:
5043          SUMA_RETURN("Generic_Double");
5044          break;
5045       case SUMA_NODE_XCORR:
5046          SUMA_RETURN("Cross_Corr_Coeff");
5047          break;
5048       case SUMA_NODE_ZSCORE:
5049          SUMA_RETURN("Z_score");
5050          break;
5051       case SUMA_NODE_VFR:
5052          SUMA_RETURN("VFR");
5053          break;
5054       case SUMA_NODE_PHASE:
5055          SUMA_RETURN("Phase");
5056          break;
5057       case SUMA_NODE_AREA:
5058          SUMA_RETURN("Area");
5059          break;
5060       case SUMA_NODE_VOLUME:
5061          SUMA_RETURN("Volume");
5062          break;
5063       case SUMA_NODE_THICKNESS:
5064          SUMA_RETURN("Thickness");
5065          break;
5066       default:
5067          SUMA_RETURN("Cowabonga-Jo");
5068          break;
5069    }
5070 
5071 }
5072 
5073 /*!
5074    For daily use, call       ctp = SUMA_TypeOfColNumb(nel, i);
5075 
5076 */
SUMA_Col_Type(char * Name)5077 SUMA_COL_TYPE SUMA_Col_Type (char *Name)
5078 {
5079    static char FuncName[]={"SUMA_Col_Type"};
5080 
5081    SUMA_ENTRY;
5082    if (!Name)  { SUMA_SL_Err("NULL Name");  SUMA_RETURN (SUMA_ERROR_COL_TYPE); }
5083    if (!strcmp(Name,"Col_Type_Undefined")) SUMA_RETURN (SUMA_NO_COL_TYPE);
5084    if (!strcmp(Name,"Error_Col_Type")) SUMA_RETURN (SUMA_ERROR_COL_TYPE);
5085    if (!strcmp(Name,"Generic_Int")) SUMA_RETURN (SUMA_NODE_INT);
5086    if (!strcmp(Name,"Generic_Short")) SUMA_RETURN (SUMA_NODE_SHORT);
5087    if (!strcmp(Name,"Node_Index")) SUMA_RETURN (SUMA_NODE_INDEX);
5088    if (!strcmp(Name,"MD_Node_Index")) SUMA_RETURN (SUMA_MD_NODE_INDEX);
5089    if (!strcmp(Name,"GNode_Index")) SUMA_RETURN (SUMA_GNODE_INDEX);
5090    if (!strcmp(Name,"GNode_Group")) SUMA_RETURN (SUMA_GNODE_IGROUP);
5091    if (!strcmp(Name,"Edge_P1_Index")) SUMA_RETURN (SUMA_EDGE_P1_INDEX);
5092    if (!strcmp(Name,"Edge_P2_Index")) SUMA_RETURN (SUMA_EDGE_P2_INDEX);
5093    if (!strcmp(Name,"Node_Index_Label")) SUMA_RETURN (SUMA_NODE_ILABEL);
5094    if (!strcmp(Name,"Node_String_Label")) SUMA_RETURN (SUMA_NODE_SLABEL);
5095    if (!strcmp(Name,"Generic_Float")) SUMA_RETURN (SUMA_NODE_FLOAT);
5096    if (!strcmp(Name,"XYZ_triplets")) SUMA_RETURN (SUMA_NODE_3C);
5097    if (!strcmp(Name,"X_coord")) SUMA_RETURN (SUMA_NODE_X);
5098    if (!strcmp(Name,"Y_coord")) SUMA_RETURN (SUMA_NODE_Y);
5099    if (!strcmp(Name,"Z_coord")) SUMA_RETURN (SUMA_NODE_Z);
5100    if (!strcmp(Name,"R_col")) SUMA_RETURN (SUMA_NODE_R);
5101    if (!strcmp(Name,"G_col")) SUMA_RETURN (SUMA_NODE_G);
5102    if (!strcmp(Name,"B_col")) SUMA_RETURN (SUMA_NODE_B);
5103    if (!strcmp(Name,"A_col")) SUMA_RETURN (SUMA_NODE_A);
5104    if (!strcmp(Name,"Rb_col")) SUMA_RETURN (SUMA_NODE_Rb);
5105    if (!strcmp(Name,"Gb_col")) SUMA_RETURN (SUMA_NODE_Gb);
5106    if (!strcmp(Name,"Bb_col")) SUMA_RETURN (SUMA_NODE_Bb);
5107    if (!strcmp(Name,"Ab_col")) SUMA_RETURN (SUMA_NODE_Ab);
5108    if (!strcmp(Name,"Generic_String")) SUMA_RETURN (SUMA_NODE_STRING);
5109    if (!strcmp(Name,"Generic_Byte")) SUMA_RETURN (SUMA_NODE_BYTE);
5110    if (!strcmp(Name,"Generic_Double")) SUMA_RETURN (SUMA_NODE_DOUBLE);
5111    if (!strcmp(Name,"Generic_Complex")) SUMA_RETURN (SUMA_NODE_COMPLEX);
5112    if (!strcmp(Name,"Convexity")) SUMA_RETURN (SUMA_NODE_CX);
5113    if (!strcmp(Name,"Cross_Corr_Coeff")) SUMA_RETURN (SUMA_NODE_XCORR);
5114    if (!strcmp(Name,"Z_score")) SUMA_RETURN (SUMA_NODE_ZSCORE);
5115    if (!strcmp(Name,"VFR")) SUMA_RETURN (SUMA_NODE_VFR);
5116    if (!strcmp(Name,"Phase")) SUMA_RETURN (SUMA_NODE_PHASE);
5117    if (!strcmp(Name,"Area")) SUMA_RETURN (SUMA_NODE_AREA);
5118    if (!strcmp(Name,"Volume")) SUMA_RETURN (SUMA_NODE_VOLUME);
5119    if (!strcmp(Name,"Thickness")) SUMA_RETURN (SUMA_NODE_THICKNESS);
5120    /* if (!strcmp(Name,"")) SUMA_RETURN (); */
5121    SUMA_RETURN (SUMA_ERROR_COL_TYPE);
5122 
5123 }
5124 
5125 
SUMA_ShowNel(void * nel)5126 int SUMA_ShowNel (void *nel)
5127 {
5128    static char FuncName[]={"SUMA_ShowNel"};
5129    NI_stream nstdout;
5130    NI_element *el=NULL;
5131    SUMA_Boolean LocalHead = NOPE;
5132 
5133    SUMA_ENTRY;
5134 
5135    if (LocalHead) SUMA_DUMP_TRACE("Who just called ShowNel?");
5136 
5137    nstdout = NI_stream_open( "fd:1","w");
5138    if( nstdout == NULL ){
5139       fprintf(stderr,"%s: Can't open fd:1\n", FuncName);
5140       SUMA_RETURN(0);
5141    }
5142    if (!nel) {
5143       fprintf (stdout, "\n***********NULL nel  ************\n");
5144       SUMA_RETURN(0);
5145    }
5146    fprintf (stdout, "\n***********nel extra info ************\n");
5147    el = (NI_element *)nel;
5148    if (el->type == NI_ELEMENT_TYPE) {
5149       fprintf (stdout,  "\n    Element type.\n"
5150                         "      vec_len   = %d\n"
5151                         "      vec_num   = %d\n"
5152                         "      vec_filled= %d\n",
5153                         el->vec_len, el->vec_num, el->vec_filled);
5154    } else {
5155       fprintf (stdout,  "\n    Group type.\n");
5156    }
5157    fprintf (stdout, "\n***********nel stdout begin***********\n");
5158    NI_write_element( nstdout , nel , NI_TEXT_MODE ) ;
5159    fprintf (stdout, "\n***********nel stdout end  ***********\n");
5160    NI_stream_close(nstdout);
5161 
5162    SUMA_RETURN(1);
5163 }
5164 
5165 /* A generic function to write a nel to a string */
SUMA_NI_nel_Info(NI_element * nel,int detail)5166 char *SUMA_NI_nel_Info (NI_element *nel, int detail)
5167 {
5168    static char FuncName[]={"SUMA_NI_nel_Info"};
5169    NI_stream ns=NULL;
5170    char *s=NULL;
5171 
5172    SUMA_ENTRY;
5173 
5174    if (!nel) s = SUMA_copy_string("NULL nel");
5175    else {
5176       ns = NI_stream_open( "str:" , "w" ) ;
5177       (void) NI_write_element( ns , nel , NI_TEXT_MODE&NI_HEADERONLY_FLAG) ;
5178       s = SUMA_copy_string( NI_stream_getbuf(ns) ) ;
5179       NI_stream_close( ns ) ;
5180    }
5181 
5182    SUMA_RETURN(s);
5183 }
5184 
5185 
5186 
SUMA_GetDsetColIndex(SUMA_DSET * dset,SUMA_COL_TYPE tp,int * N_i)5187 int *SUMA_GetDsetColIndex (SUMA_DSET *dset, SUMA_COL_TYPE tp, int *N_i)
5188 {
5189    static char FuncName[]={"SUMA_GetDsetColIndex"};
5190    int *iv=NULL, i=0;
5191    char stmp[500], *atr;
5192    int ctp;
5193    SUMA_Boolean LocalHead = NOPE;
5194 
5195    SUMA_ENTRY;
5196 
5197    if (SUMA_IS_DATUM_INDEX_COL(tp)) {
5198       SUMA_S_Err("Function cannot be called for column type SUMA_NODE_INDEX");
5199       SUMA_RETURN(NULL);
5200    }
5201 
5202    if (!dset || !dset->dnel) { SUMA_SL_Err ("NULL input"); SUMA_RETURN(NULL); }
5203    *N_i = -1;
5204    iv = (int *)SUMA_calloc(SDSET_VECNUM(dset), sizeof(int));
5205    if (!iv) {
5206       SUMA_RETURN(NULL);
5207    }
5208 
5209    *N_i = 0;
5210    for (i=0; i < SDSET_VECNUM(dset); ++i) {
5211       ctp = SUMA_TypeOfDsetColNumb(dset, i);
5212       if (ctp == tp) {
5213          iv[*N_i] = i;
5214          *N_i = *N_i + 1;
5215       }
5216    }
5217 
5218    if (!*N_i) { SUMA_free(iv); iv = NULL; }
5219    SUMA_RETURN(iv);
5220 }
5221 
SUMA_GetColIndex(NI_element * nel,SUMA_COL_TYPE tp,int * N_i)5222 int *SUMA_GetColIndex (NI_element *nel, SUMA_COL_TYPE tp, int *N_i)
5223 {
5224    static char FuncName[]={"SUMA_GetColIndex"};
5225    int *iv=NULL, i=0;
5226    char stmp[500], *atr;
5227    int ctp;
5228    SUMA_Boolean LocalHead = NOPE;
5229 
5230    SUMA_ENTRY;
5231 
5232    SUMA_SL_Warn("Obsolete, use new version.");
5233 
5234    if (!nel) { SUMA_SL_Err ("NULL nel"); SUMA_RETURN(NULL); }
5235    *N_i = -1;
5236    iv = (int *)SUMA_calloc(nel->vec_num, sizeof(int));
5237    if (!iv) {
5238       SUMA_RETURN(NULL);
5239    }
5240 
5241    *N_i = 0;
5242    for (i=0; i < nel->vec_num; ++i) {
5243       ctp = SUMA_TypeOfColNumb(nel, i);
5244       if (ctp == tp) {
5245          iv[*N_i] = i;
5246          *N_i = *N_i + 1;
5247       }
5248    }
5249 
5250    if (!*N_i) { SUMA_free(iv); iv = NULL; }
5251    SUMA_RETURN(iv);
5252 }
5253 
5254 /*!
5255    \brief returns a string with a history note
5256    \param CallingFunc (char *) name of function / program calling
5257    \param N_arg (int) number of arguments in arg
5258    \param arg (char **) vector of strings
5259    \param sold (char *) old history note
5260    \return histoire (char *)
5261 */
5262 
SUMA_HistString(char * CallingFunc,int N_arg,char ** arg,char * sold)5263 char *SUMA_HistString (char *CallingFunc, int N_arg, char **arg, char *sold)
5264 {
5265    static char FuncName[]={"SUMA_HistString"};
5266    char  *stmp=NULL, *ch=NULL, *chold = NULL,
5267          *cdate=NULL, *cname=NULL, *cuser=NULL, *cn = NULL;
5268    int idate , iname , iuser ;
5269    int N_tot, i;
5270    SUMA_Boolean LocalHead = NOPE;
5271 
5272    SUMA_ENTRY;
5273 
5274    if (!arg) SUMA_RETURN(NULL);
5275    if (!arg[0]) SUMA_RETURN(NULL);
5276    if (!N_arg) SUMA_RETURN(NULL);
5277 
5278       /* Based on tross_Make_History and tross_Append_History */
5279       if (LocalHead)
5280          fprintf(SUMA_STDERR,"CF: %s, N_arg=%d\n", CallingFunc, N_arg);
5281       cn = tross_commandline( CallingFunc, N_arg, arg);
5282       if (LocalHead) fprintf(SUMA_STDERR,"cn: %s\n", cn);
5283       cdate = tross_datetime() ; idate = strlen(cdate) ;
5284       cname = tross_hostname() ; iname = strlen(cname) ;
5285       cuser = tross_username() ; iuser = strlen(cuser) ;
5286       if (sold) { /* sold is already trossized */
5287          chold = tross_Expand_String(sold) ;
5288          if( chold == NULL ) SUMA_RETURN(NULL) ;
5289          chold = AFREALL( chold, char,
5290 		               strlen(chold)+idate+iuser+iname+strlen(cn)+12 ) ;
5291 
5292          strcat(chold,"\n") ;
5293          strcat(chold,"[") ;  strcat(chold,cuser) ; strcat(chold,"@") ;
5294                               strcat(chold,cname) ; strcat(chold,": ") ;
5295                               strcat(chold,cdate) ;
5296          strcat(chold,"] ") ;
5297          strcat(chold,cn) ;
5298          SUMA_LH("%s",chold);
5299          ch = tross_Encode_String(chold) ;
5300          if( ch == NULL ){ free(chold); SUMA_RETURN(NULL); }
5301          stmp = SUMA_copy_string(ch);
5302          free(chold) ; free(ch);
5303       } else {
5304          chold = AFMALL(char, idate+iuser+iname+strlen(cn)+12 ) ;
5305          sprintf(chold,"[%s@%s: %s] %s",cuser,cname,cdate,cn) ;
5306          SUMA_LH("%s",chold);
5307          ch = tross_Encode_String(chold) ;
5308          if( ch == NULL ){ free(chold); SUMA_RETURN(NULL); }
5309          stmp = SUMA_copy_string(ch);
5310          free(chold) ;  free(ch);
5311          free(cuser); free(cname); free(cdate);
5312       }
5313 
5314    SUMA_RETURN(stmp);
5315 }
5316 
5317 /*!
5318    \brief returns pointer to history string.
5319    DO NOT FREE THIS POINTER, it is a copy
5320    of the pointer in one of ngr's elements.
5321    NULL if no history or no history elements
5322    were found
5323 */
SUMA_GetNgrHist(NI_group * ngr)5324 char * SUMA_GetNgrHist(NI_group *ngr)
5325 {
5326    static char FuncName[]={"SUMA_GetNgrHist"};
5327    char **sv, *shist = NULL;
5328    NI_element *nelb = NULL;
5329    SUMA_Boolean LocalHead = NOPE;
5330 
5331    SUMA_ENTRY;
5332 
5333    nelb = SUMA_FindNgrAttributeElement(ngr, "HISTORY_NOTE");
5334    if (nelb) {
5335       sv = (char **)nelb->vec[0];
5336       shist = (char *)sv[0];
5337    } else {
5338       shist = NULL;
5339    }
5340    SUMA_RETURN(shist);
5341 }
5342 
5343 /*!
5344    \brief adds a history element note to the ni-group
5345 
5346    \param dset (NI_group *)
5347    \param CallingFunc (char *) name of function / program calling
5348    \param N_arg (int) number of arguments in arg
5349    \param arg (char **) vector of strings
5350    \return ans (int) 0 Failed
5351                      1 OK
5352 */
SUMA_AddNgrHist(NI_group * ngr,char * CallingFunc,int N_arg,char ** arg)5353 int SUMA_AddNgrHist(NI_group *ngr, char *CallingFunc, int N_arg, char **arg)
5354 {
5355    static char FuncName[]={"SUMA_AddNgrHist"};
5356    char *stmp=NULL, *sold=NULL, **sv=NULL;
5357    int N_tot, i;
5358    NI_element *nelb = NULL;
5359    SUMA_Boolean LocalHead = NOPE;
5360 
5361    SUMA_ENTRY;
5362 
5363    if (!arg) SUMA_RETURN(0);
5364    if (!arg[0]) SUMA_RETURN(0);
5365    if (!ngr) SUMA_RETURN(0);
5366    if (!N_arg) SUMA_RETURN(0);
5367 
5368    /* get former history element, if any and old string */
5369    nelb = SUMA_FindNgrAttributeElement(ngr, "HISTORY_NOTE");
5370    if (nelb) {
5371       sv = (char **)nelb->vec[0];
5372       sold = (char *)sv[0];
5373    } else {
5374       sold = NULL;
5375    }
5376 
5377    /* form the new string */
5378    stmp = SUMA_HistString (CallingFunc, N_arg, arg, sold);
5379 
5380 
5381    if (stmp) {
5382       if (nelb) { /* element existed */
5383          /* now need to replace the old string with the new one */
5384          if (sold) { /* clean the old pos */
5385             NI_free(sold); sold = sv[0] = NULL;
5386          }
5387       } else { /* element never existed */
5388          nelb = NI_new_data_element("AFNI_atr", 1);
5389          NI_set_attribute(nelb, "atr_name", "HISTORY_NOTE");
5390          NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
5391          NI_add_to_group(ngr, nelb);
5392       }
5393       /* now add the new string */
5394       SUMA_NEL_REPLACE_STRING(nelb, 0, 0, (void*)stmp);
5395       SUMA_free(stmp); stmp = NULL;
5396    } else {
5397       SUMA_SL_Err("Failed to create string!");
5398       SUMA_RETURN(0);
5399    }
5400 
5401    SUMA_RETURN(1);
5402 }
5403 
SUMA_RemoveDsetHist(SUMA_DSET * dset)5404 int SUMA_RemoveDsetHist(SUMA_DSET *dset) {
5405    if (!dset||!dset->ngr) return(0);
5406    return(SUMA_RemoveNgrHist(dset->ngr));
5407 }
5408 
SUMA_RemoveNgrHist(NI_group * ngr)5409 int SUMA_RemoveNgrHist(NI_group *ngr)
5410 {
5411    static char FuncName[]={"SUMA_RemoveNgrHist"};
5412    NI_element *nelb = NULL;
5413 
5414    SUMA_ENTRY;
5415 
5416    if (!ngr) SUMA_RETURN(0);
5417 
5418    /* get former history element, if any and old string */
5419    nelb = SUMA_FindNgrAttributeElement(ngr, "HISTORY_NOTE");
5420    if (nelb) {
5421       NI_remove_from_group(ngr, nelb);
5422    }
5423    SUMA_RETURN(1);
5424 }
5425 
5426 /*!
5427    \brief adds a history note to the ni-element
5428 
5429    \param nel (NI_element *)
5430    \param CallingFunc (char *) name of function / program calling
5431    \param N_arg (int) number of arguments in arg
5432    \param arg (char **) vector of strings
5433    \return ans (int) 0 Failed
5434                      1 OK
5435 */
SUMA_AddNelHist(NI_element * nel,char * CallingFunc,int N_arg,char ** arg)5436 int SUMA_AddNelHist(NI_element *nel, char *CallingFunc, int N_arg, char **arg)
5437 {
5438    static char FuncName[]={"SUMA_AddNelHist"};
5439    char *stmp=NULL, *sold=NULL;
5440    int N_tot, i;
5441 
5442    SUMA_ENTRY;
5443 
5444    SUMA_SL_Warn("Obsolete, use new version.");
5445 
5446    if (!arg) SUMA_RETURN(0);
5447    if (!arg[0]) SUMA_RETURN(0);
5448    if (!nel) SUMA_RETURN(0);
5449    if (!N_arg) SUMA_RETURN(0);
5450 
5451    sold = NI_get_attribute(nel, "HISTORY_NOTE");
5452    stmp = SUMA_HistString (CallingFunc, N_arg, arg, sold);
5453 
5454   if (stmp) {
5455       NI_set_attribute ( nel, "HISTORY_NOTE", stmp);
5456       SUMA_free(stmp);
5457    }
5458 
5459    SUMA_RETURN(1);
5460 }
5461 
5462 
5463 
5464 
5465 /***
5466    Functions to deal with SUMA's datasets
5467    They don't quite belong in SUMA_DataSets.c because
5468    they are specific to SUMA
5469 ***/
5470 
5471 /*!
5472    \brief look for a dataset with a particular idcode
5473 */
SUMA_FindDset_ns(char * idcode,DList * DsetList)5474 SUMA_DSET * SUMA_FindDset_ns (char *idcode, DList *DsetList)
5475 {
5476    SUMA_DSET *dset = SUMA_FindDset_eng (idcode, DsetList, NULL, NULL);
5477    WorkErrLog_ns();
5478    return(dset);
5479 }
SUMA_FindDset2_ns(char * idcode,DList * DsetList,char * itype)5480 SUMA_DSET * SUMA_FindDset2_ns (char *idcode, DList *DsetList, char *itype)
5481 {
5482    SUMA_DSET *dset = SUMA_FindDset_eng (idcode, DsetList, NULL, itype);
5483    WorkErrLog_ns();
5484    return(dset);
5485 }
5486 
SUMA_FindDsetEl_ns(char * idcode,DList * DsetList)5487 DListElmt * SUMA_FindDsetEl_ns (char *idcode, DList *DsetList)
5488 {
5489    DListElmt *el=NULL;
5490    SUMA_DSET *dset = SUMA_FindDset_eng (idcode, DsetList, &el, NULL);
5491    WorkErrLog_ns();
5492    return(el);
5493 }
5494 
SUMA_FindDset_eng(char * idcode,DList * DsetList,DListElmt ** elp,char * idtype)5495 SUMA_DSET * SUMA_FindDset_eng (char *idcode, DList *DsetList,
5496                                DListElmt **elp, char *idtype)
5497 {
5498    static char FuncName[]={"SUMA_FindDset_eng"};
5499    SUMA_DSET *dset = NULL, *dsetf = NULL;
5500    char *dsetid;
5501    DListElmt *el=NULL;
5502    SUMA_Boolean LocalHead = NOPE;
5503 
5504    SUMA_ENTRY;
5505 
5506 
5507    dsetf = NULL;
5508    if (!DsetList) { SUMA_SL_Err("NULL DsetList"); SUMA_RETURN(dsetf); }
5509    if (!DsetList->size) { SUMA_RETURN(dsetf); }
5510    if (!idcode) { SUMA_SL_Err("NULL idcode"); SUMA_RETURN(dsetf); }
5511    if (elp) *elp=NULL;
5512    el = NULL;
5513    do {
5514       if (LocalHead)
5515          fprintf(SUMA_STDOUT,
5516                "%s: \n      checking element out of %d for %s, idtype =%s\n",
5517                FuncName, dlist_size(DsetList), idcode, idtype?idtype:"NULL");
5518       if (!el) el = dlist_head(DsetList);
5519       else el = dlist_next(el);
5520       dset = (SUMA_DSET *)el->data;
5521       if (!dset) {
5522         SUMA_LH("no dset in el->data!");
5523         SUMA_PushErrLog("SLP_Err",
5524                         "Unexpected NULL dset element in list!\n"
5525                         "Please report this occurrence to saadz@mail.nih.gov.",
5526                         FuncName);
5527       } else {
5528          SUMA_LH("Have dset in el->data, checking");
5529          #ifdef OLD_DSET      /* before dsets were NI_groups */
5530          if (idtype) {
5531             SUMA_S_Err("non-null idtype search not supported with old dsets");
5532             SUMA_RETURN(dsetf);
5533          }
5534          if (dset->nel) {
5535             SUMA_LH("dset is nel type");
5536             dsetid = NI_get_attribute(dset->nel, "idcode"); /* obsolete */
5537             if (!dsetid) dsetid = NI_get_attribute(dset->nel, "self_idcode");
5538             if (dsetid) {
5539                if (!strcmp(dsetid, idcode))  {/* match */
5540                   dsetf = dset;
5541                   if (elp) *elp=el;
5542                }
5543             }
5544          }
5545          #else
5546          if (dset->ngr) {
5547             SUMA_LH("dset is ngr type, ID=%s, Label=%s, user idtype is %s",
5548 	            SDSET_ID(dset), SDSET_LABEL(dset), CNS(idtype));
5549             if (!idtype || !strcmp(idtype,"self_idcode")) {
5550                dsetid = NI_get_attribute(dset->ngr, "idcode"); /* obsolete */
5551                if (!dsetid) dsetid = NI_get_attribute(dset->ngr, "self_idcode");
5552                if (dsetid) {
5553                   if (!strcmp(dsetid, idcode))  { /* match */
5554                      dsetf = dset;
5555                      if (elp) *elp=el;
5556                   }
5557                }
5558             } else if (idtype) {
5559                if (!strcmp(idtype,"filename")) {
5560                   if (!strcmp(CHECK_NULL_STR(SDSET_FILENAME(dset)), idcode))  {
5561                         dsetf = dset;
5562                         if (elp) *elp=el;
5563                   }
5564                } else if (!strcmp(idtype,"label")) {
5565                   if (!strcmp(CHECK_NULL_STR(SDSET_LABEL(dset)), idcode))  {
5566                         dsetf = dset;
5567                         if (elp) *elp=el;
5568                   }
5569                } else if (!strcmp(idtype,"isGraphDset")) {
5570                   if (SUMA_isGraphDset(dset)) {
5571                      dsetf = dset;
5572                      if (elp) *elp=el;
5573                   }
5574                }
5575             }
5576          }
5577          #endif
5578       }
5579       if (LocalHead) fprintf(SUMA_STDOUT,"%s: About to loopback:\n"
5580                                           "el=%p, tail=%p, dsetf=%p, idtype=%s\n"
5581                                           , FuncName, el, dlist_tail(DsetList),
5582                                           dsetf, idtype?idtype:"NULL");
5583    } while ( (el != dlist_tail(DsetList)) && !dsetf );
5584 
5585    SUMA_LHv("dsetf = %p, returning.\n\n", dsetf);
5586 
5587    SUMA_RETURN(dsetf);
5588 }
5589 
5590 #define CHECK_DUPS {\
5591    if (dsetf && dsetf != dset) { \
5592       fprintf (SUMA_STDERR,"Error %s:\n"  \
5593                            "More than one dataset found satisfying"  \
5594                            "criteria: %s\n",    \
5595                             FuncName, criteria);   \
5596       SUMA_ShowDset(dset, 0, NULL); \
5597       SUMA_ShowDset(dsetf, 0, NULL);   \
5598       SUMA_RETURN(NULL);   \
5599    }  \
5600                   }\
5601 
SUMA_FindDsetLoose(SUMA_DSET * dsetin,DList * DsetList,char * criteria)5602 SUMA_DSET * SUMA_FindDsetLoose (
5603                SUMA_DSET *dsetin,
5604                DList *DsetList,
5605                char *criteria)
5606 {
5607    static char FuncName[]={"SUMA_FindDsetLoose"};
5608    SUMA_DSET *dsetf = NULL, *dset= NULL;
5609    int ifound=0, newmatch, totmatch, icrit;
5610    char *dsetid=NULL, *s=NULL;
5611    DListElmt *el=NULL;
5612    SUMA_Boolean LocalHead = NOPE;
5613 
5614    SUMA_ENTRY;
5615 
5616 
5617    dsetf = NULL;
5618    if (!DsetList) { SUMA_SL_Err("NULL DsetList"); SUMA_RETURN(dsetf); }
5619    if (!DsetList->size) { SUMA_RETURN(dsetf); }
5620    if (!dsetin) { SUMA_SL_Err("NULL dset"); SUMA_RETURN(dsetf); }
5621    totmatch = 0;
5622    do {
5623       if (LocalHead) fprintf( SUMA_STDOUT,
5624                               "%s: \n      checking element out of %d\n",
5625                               FuncName, dlist_size(DsetList));
5626       if (!el) el = dlist_head(DsetList);
5627       else el = dlist_next(el);
5628       dset = (SUMA_DSET *)el->data;
5629       if (!dset) {
5630         SUMA_LH("dset not found");
5631         SUMA_SL_Err( "Unexpected NULL dset element in list!\n"
5632                      "Please report this occurrence to saadz@mail.nih.gov." );
5633       } else {
5634          SUMA_LH("dset found");
5635 
5636          newmatch = 0; icrit = 0;
5637          while (  !newmatch &&
5638                   (s = SUMA_NI_get_ith_string( criteria , "|", icrit ))) {
5639             if (!strcmp(s,"self_idcode")) {
5640                #ifdef OLD_DSET      /* before dsets were NI_groups */
5641                if (dset->nel) {
5642                   SUMA_LH("dset is nel type");
5643                   dsetid = NI_get_attribute(dset->nel, "idcode"); /* obsolete */
5644                   if (!dsetid)
5645                      dsetid = NI_get_attribute(dset->nel, "self_idcode");
5646                   if (dsetid) {
5647                      if (!strcmp(dsetid, SDSET_ID(dsetin)))  {/* match */
5648                         CHECK_DUPS;
5649                         dsetf = dset;
5650                         newmatch = 1; ++totmatch;
5651                      }
5652                   }
5653                }
5654                #else
5655                if (dset->ngr) {
5656                   SUMA_LH("dset is ngr type");
5657                   dsetid = NI_get_attribute(dset->ngr, "idcode"); /* obsolete */
5658                   if (!dsetid)
5659                      dsetid = NI_get_attribute(dset->ngr, "self_idcode");
5660                   if (dsetid) {
5661                      if (!strcmp(dsetid, SDSET_ID(dsetin)))  { /* match */
5662                         CHECK_DUPS;
5663                         dsetf = dset;
5664                         newmatch = 1; ++totmatch;
5665                      }
5666                   }
5667                }
5668                #endif
5669             } else if (!strcmp(s,"filename")) {
5670                #ifdef OLD_DSET      /* before dsets were NI_groups */
5671                if (dset->nel) {
5672                   SUMA_LH("dset is nel type");
5673                   dsetid = SDSET_FILENAME(dset);
5674                   if (dsetid) {
5675                      if (!strcmp(dsetid, SDSET_FILENAME(dsetin)))  { /* match */
5676                         CHECK_DUPS;
5677                         dsetf = dset;
5678                         newmatch = 1; ++totmatch;
5679                      }
5680                   }
5681                }
5682                #else
5683                if (dset->ngr) {
5684                   SUMA_LH("dset is ngr type");
5685                   dsetid = SDSET_FILENAME(dset);
5686                   if (dsetid) {
5687                      if (!strcmp(   dsetid,
5688                                     CHECK_NULL_STR(SDSET_FILENAME(dsetin))))  {
5689                                     /* match */
5690                         CHECK_DUPS;
5691                         dsetf = dset;
5692                         newmatch = 1; ++totmatch;
5693                      }
5694                   }
5695                }
5696                #endif
5697             }else if (!strcmp(s,"label")) {
5698                #ifdef OLD_DSET      /* before dsets were NI_groups */
5699                SUMA_S_Err("Search by label not supported for old dsets");
5700                #else
5701                if (dset->ngr) {
5702                   SUMA_LH("dset is ngr type");
5703                   dsetid = SDSET_LABEL(dset);
5704                   if (dsetid) {
5705                      if (!strcmp(   dsetid,
5706                                     CHECK_NULL_STR(SDSET_LABEL(dsetin))))  {
5707                                     /* match */
5708                         CHECK_DUPS;
5709                         dsetf = dset;
5710                         newmatch = 1; ++totmatch;
5711                      }
5712                   }
5713                }
5714                #endif
5715             }  else {
5716                SUMA_S_Err("Bad Aux.");
5717             }
5718             ++icrit;
5719          }
5720       }
5721       if (LocalHead) fprintf(SUMA_STDOUT,"%s: About to loopback:\n"
5722                                           "el=%p, tail=%p, dsetf=%p\n"
5723                                           , FuncName, el,
5724                                           dlist_tail(DsetList), dsetf);
5725    } while ( (el != dlist_tail(DsetList)));
5726    SUMA_RETURN(dsetf);
5727 }
5728 
5729 /*!
5730    \brief Function to free a Dset
5731 
5732    - YOU SHOULD NOT FREE individual dsets yourself if they are inserted
5733    into DsetList, that is done by the dlist_destroy function
5734 */
SUMA_FreeDset(void * vp)5735 void SUMA_FreeDset(void *vp)
5736 {
5737    static char FuncName[]={"SUMA_FreeDset"};
5738    SUMA_DSET *dset;
5739    SUMA_Boolean LocalHead = NOPE;
5740 
5741    SUMA_ENTRY;
5742 
5743    dset = (SUMA_DSET *)vp;
5744 
5745    if (!dset) SUMA_RETURNe;
5746    SUMA_LH("Check Link");
5747    if (dset->N_links) {
5748       SUMA_SL_Err("dset structure has links to it.\n"
5749                   "structure not freed.\n"
5750                   "That is a now a memory leak.\n");
5751       SUMA_ShowDset (dset, 0, NULL);
5752       SUMA_RETURNe;
5753    }
5754 
5755    if (SUMA_isCIFTIDset(dset)) {
5756       SUMA_S_Warn("Note that objects defining domain of the dataset\n"
5757                   "being deleted are not being freed\n");
5758    }
5759    if (!SUMA_FreeDsetContent(dset)) {
5760       SUMA_S_Err("Failed to free content, proceeding, "
5761                  "but danger danger Will Robinson!");
5762    }
5763 
5764    SUMA_LH("The last straw");
5765    SUMA_free(dset); dset = NULL;
5766 
5767    SUMA_RETURNe;
5768 }
5769 
SUMA_FreeDsetContent(SUMA_DSET * dset)5770 SUMA_Boolean SUMA_FreeDsetContent (SUMA_DSET *dset)
5771 {
5772    static char FuncName[]={"SUMA_FreeDsetContent"};
5773    SUMA_Boolean LocalHead = NOPE;
5774 
5775    SUMA_ENTRY;
5776 
5777    #ifdef OLD_DSET /* before ngr was used */
5778    SUMA_LH("Old dset");
5779    if (dset->nel)
5780       NI_free_element(dset->nel); dset->nel = NULL;
5781          /* you can keep ni_free from freeing a nel->vec[i]
5782          vector by copying nel->vec[i] to a pointer then
5783          setting nel->vec[i] = NULL */
5784    #else
5785    SUMA_LH("New Treatment");
5786    dset->dnel = NULL; /* this one was a pointer copy to an element inside ngr */
5787    dset->inel = NULL;
5788    dset->pdnel = dset->pinel = NULL;
5789    if (dset->ngr)
5790       SUMA_LH("Freeing NGR");
5791       NI_free_element(dset->ngr); dset->ngr = NULL;
5792          /* you can keep ni_free from freeing a nel->vec[i]
5793          vector by copying nel->vec[i] to a pointer then
5794          setting nel->vec[i] = NULL */
5795    #endif
5796 
5797    if (dset->Aux) { /* free auxiliary data */
5798       if (dset->Aux->Saux) {
5799          if (!dset->Aux->FreeSaux) {
5800             SUMA_S_Err("You're leaky, you're leaky");
5801          } else dset->Aux->FreeSaux(dset->Aux->Saux);
5802          dset->Aux->Saux =NULL; /* pointer freed in freeing function */
5803       }
5804       SUMA_CIFTI_Free_Doms(dset);
5805       SUMA_ifree(dset->Aux);
5806    }
5807 
5808    SUMA_RETURN(YUP);
5809 }
5810 
5811 /*!
5812    \brief Pointer linking and unliking functions.
5813    They are to be used for all pointer linking
5814    in SUMA. For now they are just used for the datasets
5815    but I plan to move all "inode" stuff in here.
5816 
5817    These functions are generalized versions of SUMA_LinkToDset
5818    and SUMA_UnlinkFromDset
5819 */
SUMA_LinkToPointer(void * ptr)5820 void *SUMA_LinkToPointer(void *ptr)
5821 {
5822    static char FuncName[]={"SUMA_LinkToPointer"};
5823    SUMA_LinkedPtr *dset=NULL;
5824    SUMA_Boolean LocalHead = NOPE;
5825 
5826    SUMA_ENTRY;
5827 
5828    if (!ptr) {
5829       SUMA_SL_Err("NULL pointer");
5830       SUMA_RETURN(NULL);
5831    }
5832    dset = (SUMA_LinkedPtr *)ptr;
5833    if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Link Requested to pointer %p. \n"
5834                              "LinkedPtrType = %d, owner_id = %s, do_type = %d\n"
5835                                       "N_links was %d\n",
5836                                       FuncName, dset,
5837                              dset->LinkedPtrType, dset->owner_id, dset->do_type,
5838                                       dset->N_links);
5839    dset->N_links = dset->N_links + 1;
5840 
5841    SUMA_RETURN((void *)dset);
5842 }
SUMA_UnlinkFromPointer(void * ptr)5843 void *SUMA_UnlinkFromPointer(void *ptr)
5844 {
5845    static char FuncName[]={"SUMA_UnlinkFromPointer"};
5846    SUMA_LinkedPtr *dset=NULL;
5847    SUMA_Boolean LocalHead = NOPE;
5848 
5849    SUMA_ENTRY;
5850 
5851    if (!ptr) {
5852       SUMA_SL_Err("NULL pointer");
5853       SUMA_RETURN(NULL);
5854    }
5855    dset = (SUMA_LinkedPtr *)ptr;
5856    if (LocalHead)
5857       fprintf(SUMA_STDERR, "%s:\n Unlink Requested from pointer %p.\n"
5858                            "LinkedPtrType = %d, owner_id = %s, do_type = %d\n"
5859                            "N_links was %d\n",
5860                            FuncName, dset,
5861                            dset->LinkedPtrType, dset->owner_id, dset->do_type,
5862                            dset->N_links);
5863    if (dset->N_links > 0) dset->N_links = dset->N_links - 1;
5864    else if (dset->N_links == 0) {
5865       SUMA_SL_Err("N_links ==0\nThis should not happen here.\n");
5866       SUMA_RETURN(NULL);
5867    }
5868 
5869    SUMA_RETURN(NULL);
5870 }
5871 
SUMA_NewDsetPointer(void)5872 SUMA_DSET * SUMA_NewDsetPointer(void)
5873 {
5874    static char FuncName[]={"SUMA_NewDsetPointer"};
5875    SUMA_DSET *dset = NULL;
5876    SUMA_Boolean LocalHead = NOPE;
5877    SUMA_ENTRY;
5878 
5879    dset = (SUMA_DSET *)SUMA_calloc(1,sizeof(SUMA_DSET));
5880    if (!dset) {
5881       SUMA_SL_Err("Failed to allocate for dset");
5882       SUMA_RETURN(dset);
5883    }
5884    if (LocalHead)
5885       fprintf(SUMA_STDERR,"%s:\n dset %p allocated.\n", FuncName, dset);
5886    /* initialize */
5887    #ifdef OLD_DSET
5888    dset->nel = NULL;
5889    #else
5890    dset->inel = NULL;
5891    dset->dnel = NULL;
5892    dset->pdnel = dset->pinel = NULL;
5893    dset->ngr = NULL;
5894    #endif
5895    dset->N_links = 0;
5896    dset->owner_id[0] = '\0';
5897    dset->LinkedPtrType = SUMA_LINKED_DSET_TYPE;
5898    dset->Aux = NULL;
5899    dset->do_type = ANY_DSET_type;
5900    SUMA_RETURN(dset);
5901 }
5902 
5903 /* Change a dataset with one integer valued column to a
5904   Label type dset. Note that dset itself is modified.
5905 */
SUMA_dset_to_Label_dset(SUMA_DSET * dset)5906 int SUMA_dset_to_Label_dset(SUMA_DSET *dset)
5907 {
5908    static char FuncName[]={"SUMA_dset_to_Label_dset"};
5909    int ctp, vtp, i, *unq=NULL, N_unq=0;
5910    NI_group *NIcmap=NULL, *ngr=NULL;
5911    char stmp[256], *lbli=NULL, *attname=NULL;
5912    SUMA_Boolean LocalHead = NOPE;
5913 
5914    SUMA_ENTRY;
5915 
5916    if (!dset || !dset->dnel || !dset->inel) SUMA_RETURN(0);
5917 
5918    if (!SUMA_is_AllConsistentCastType_dset(dset, SUMA_int)) {
5919       SUMA_LH("Not all columns are type castable to SUMA_int");
5920       SUMA_RETURN(0);
5921    }
5922 
5923    if (SUMA_is_Label_dset(dset, NULL)) {
5924       SUMA_LH("is label already");
5925    } else {
5926       /* Must have one column that is an integer value */
5927       for (i=0; i<1; ++i) {
5928          ctp = SUMA_TypeOfDsetColNumb(dset, i);
5929          if (LocalHead) {
5930             fprintf(SUMA_STDERR,"%s: ctp(%d) = %d (%d)\n",
5931                   FuncName, i, ctp, SUMA_NODE_ILABEL);
5932          }
5933          if (ctp != SUMA_NODE_ILABEL) {
5934             if (SUMA_ColType2TypeCast(ctp) != SUMA_int) {
5935                SUMA_S_Err( "Cannot make the change. "
5936                            "Only integer columns supported");
5937                SUMA_RETURN(0);
5938             }
5939             /* change the column type */
5940             lbli = SUMA_DsetColLabelCopy(dset, i, 0);
5941             if (!SUMA_AddDsetColAttr ( dset, lbli ,
5942                                  SUMA_NODE_ILABEL, NULL,
5943                                  i, 1)) {
5944                SUMA_S_Err("Failed chaning attribute");
5945                SUMA_RETURN(0);
5946             }
5947             if (lbli) SUMA_free(lbli); lbli = NULL;
5948          }
5949       }
5950       /* and dset_type */
5951       NI_set_attribute( dset->ngr,"dset_type",
5952                         SUMA_Dset_Type_Name(SUMA_NODE_LABEL));
5953       attname = SUMA_append_string(SDSET_TYPE_NAME(dset),"_data");
5954       NI_set_attribute( dset->dnel,"data_type",
5955                         attname);
5956       SUMA_free(attname); attname = NULL;
5957       attname = SUMA_append_string(SDSET_TYPE_NAME(dset),"_node_indices");
5958       NI_set_attribute( dset->inel,"data_type",
5959                         attname);
5960       SUMA_free(attname); attname = NULL;
5961    }
5962 
5963    SUMA_RETURN(1);
5964 }
5965 
SUMA_Reset_NodeIndex_Element(SUMA_DSET * dset,NI_element ** inel)5966 SUMA_Boolean SUMA_Reset_NodeIndex_Element(SUMA_DSET *dset, NI_element **inel)
5967 {
5968    static char FuncName[]={"SUMA_Reset_NodeIndex_Element"};
5969    char *dname=NULL;
5970 
5971    SUMA_ENTRY;
5972 
5973 
5974    if (!dset) SUMA_RETURN(NOPE);
5975 
5976    if (SUMA_isGraphDset(dset)) {
5977       if (inel && *inel) {
5978          if ((*inel)->vec_num != 3) {
5979             SUMA_S_Errv("You failed the basic test of 3, "
5980                         "bad inel with %d cols\n",
5981                      (*inel)->vec_num);
5982             SUMA_RETURN(NOPE);
5983          }
5984       }
5985       dname = SUMA_append_string(
5986             NEL_DSET_TYPE(dset->ngr), "_edge_indices");
5987    } else {
5988       if (inel && *inel) {
5989          if ((*inel)->vec_num != 1) {
5990             SUMA_S_Errv("You failed the basic test of 1, "
5991                         "bad inel with %d cols\n",
5992                      (*inel)->vec_num);
5993             SUMA_RETURN(NOPE);
5994          }
5995       }
5996       dname = SUMA_append_string(
5997             NEL_DSET_TYPE(dset->ngr), "_node_indices");
5998    }
5999    if (dset->inel) {
6000       NI_remove_from_group(dset->ngr, dset->inel);
6001       NI_free_element(dset->inel); dset->inel = NULL;
6002    }
6003 
6004    if (!inel || !*inel) {
6005       dset->inel = NI_new_data_element("INDEX_LIST", SDSET_VECLEN(dset));
6006    } else {
6007       dset->inel = *inel; *inel = NULL;
6008    }
6009 
6010    NI_set_attribute (dset->inel, "data_type", dname);
6011    SUMA_free(dname); dname = NULL;
6012    NI_add_to_group(dset->ngr, dset->inel);
6013 
6014    SUMA_RETURN(YUP);
6015 
6016 }
6017 
6018 /* Create/initialize Auxiliary structure */
SUMA_Add_Dset_Aux(SUMA_DSET * dset)6019 SUMA_Boolean SUMA_Add_Dset_Aux(SUMA_DSET *dset)
6020 {
6021    static char FuncName[]={"SUMA_Add_Dset_Aux"};
6022    SUMA_Boolean LocalHead = NOPE;
6023 
6024    SUMA_ENTRY;
6025 
6026    if (!dset || !dset->ngr) {
6027       SUMA_S_Err("Have nothing to work with");
6028       SUMA_RETURN(NOPE);
6029    }
6030 
6031    /* SUMA_DUMP_TRACE("Auxing\n"); */
6032 
6033    if (dset->Aux) {
6034       SUMA_LH("Have Aux already, nothing done");
6035       SUMA_RETURN(YUP);
6036    }
6037    /* Is this a gaph dset? */
6038    if (SUMA_isGraphDsetNgr(dset->ngr)) {
6039       dset->Aux = (SUMA_DSET_AUX *)SUMA_calloc(1,sizeof(SUMA_DSET_AUX));
6040       dset->Aux->matrix_shape = MAT_HEEHAW;
6041       dset->Aux->isGraph = GRAPH_DSET;
6042    } else if (SUMA_isTractDsetNgr(dset->ngr)) {
6043       dset->Aux = (SUMA_DSET_AUX *)SUMA_calloc(1,sizeof(SUMA_DSET_AUX));
6044       dset->Aux->matrix_shape = MAT_NA;
6045       dset->Aux->isGraph = TRACT_DSET;
6046    } else if (SUMA_isCIFTIDsetNgr(dset->ngr)) {
6047       dset->Aux = (SUMA_DSET_AUX *)SUMA_calloc(1,sizeof(SUMA_DSET_AUX));
6048       dset->Aux->matrix_shape = MAT_NA;
6049       dset->Aux->isGraph = CIFTI_DSET;
6050    } else { /* you should always have Aux allocated, default to surf_dset...*/
6051       dset->Aux = (SUMA_DSET_AUX *)SUMA_calloc(1,sizeof(SUMA_DSET_AUX));
6052       dset->Aux->isGraph = SURF_DSET;
6053       dset->Aux->matrix_shape = MAT_NA;
6054    }
6055 
6056    SUMA_RETURN(YUP);
6057 }
6058 
6059 /*!
6060    \brief a function to put a ni_group (ngr) element into a SUMA_DSET pointer
6061    To free dset along with the ngr in it use SUMA_FreeDset.
6062    To preserve ngr:
6063       ngr_keep = dset->ngr; dset->ngr = NULL; SUMA_Free(dset);
6064 */
SUMA_ngr_2_dset(NI_group * nini,int warn)6065 SUMA_DSET * SUMA_ngr_2_dset(NI_group *nini, int warn)
6066 {
6067    static char FuncName[]={"SUMA_ngr_2_dset"};
6068    SUMA_DSET *dset=NULL;
6069    char *dname = NULL;
6070 
6071    SUMA_ENTRY;
6072 
6073    if (!(dset = SUMA_NewDsetPointer())) {
6074       SUMA_SL_Err("Failed to create dset pointer");
6075       SUMA_RETURN(NULL);
6076    }
6077 
6078    dset->ngr = (NI_group *)nini; nini = NULL;
6079    dset->dnel = SUMA_FindDsetDataElement(dset);
6080    dset->inel = SUMA_FindDsetDatumIndexElement(dset);
6081    if (!dset->dnel) {
6082       SUMA_SL_Warn("Failed to find dset data element");
6083    }
6084    if (!dset->inel || !SDSET_NODEINDNUM(dset)) {
6085       /* If a dset had an empty node index holder at write time,
6086       the inel is written with vecnum set to 0. This would make
6087       any attempt to add columns later on fail.
6088       */
6089       if (warn && !SUMA_isGraphDsetNgr(dset->ngr)) {
6090          SUMA_S_Note("NIML dset with no valid node index element");
6091       }
6092       NI_remove_from_group(dset->ngr, dset->inel);
6093       NI_free_element(dset->inel); dset->inel = NULL;
6094       /* Now add the new and proper node index element holder*/
6095       if (dset->dnel) {
6096          if (warn && !SUMA_isGraphDsetNgr(dset->ngr)) {
6097             SUMA_S_Note("Adding empty holder\n");
6098          }
6099          SUMA_Reset_NodeIndex_Element(dset, NULL);
6100       }
6101    }
6102 
6103    /* Got a label table ? */
6104    if (SUMA_NI_Cmap_of_Dset(dset)) { /* make sure it is a label dset then */
6105       if (!SUMA_dset_to_Label_dset(dset)) {
6106          SUMA_S_Err("Failed to turn dset into a labeled one.");
6107       }
6108    }
6109 
6110    /* Set Aux (could have been set already with earlier calls
6111       via SUMA_isGraphDset() ) */
6112    if (!dset->Aux && !SUMA_Add_Dset_Aux(dset)) {
6113       SUMA_S_Err("Failed to add Aux");
6114    }
6115 
6116    SUMA_RETURN(dset);
6117 }
6118 
6119 /*!
6120    \brief assign a label to a dset
6121    pass NULL for lbl if you want the function to guess at creating one
6122 
6123    Note: Label Length is truncated to 20 chars
6124 */
SUMA_LabelDset(SUMA_DSET * dset,char * lbl)6125 SUMA_Boolean SUMA_LabelDset(SUMA_DSET *dset, char *lbl)
6126 {
6127    static char FuncName[]={"SUMA_LabelDset"};
6128    char *Label=NULL, *tmp=NULL;
6129    SUMA_PARSED_NAME *pn=NULL;
6130    SUMA_Boolean ok;
6131 
6132    SUMA_ENTRY;
6133 
6134    if (!dset) {
6135       SUMA_S_Err("NULL Input");
6136       SUMA_RETURN(NOPE);
6137    }
6138    ok = YUP;
6139    if (lbl) {
6140       Label = SUMA_truncate_string(lbl, 20);
6141       NI_set_attribute(dset->ngr, "label", Label);
6142    } else if ( (tmp = NI_get_attribute(dset->ngr,"filename")) ) {
6143       pn = SUMA_ParseFname(tmp, NULL);
6144       if (pn) {
6145          Label = SUMA_truncate_string(pn->FileName_NoExt, 20);
6146          SUMA_Free_Parsed_Name(pn); pn = NULL;
6147          NI_set_attribute(dset->ngr, "label", Label);
6148       } else {
6149          NI_set_attribute(dset->ngr, "label", "Bad No label");
6150          ok = NOPE;
6151       }
6152    } else {
6153       NI_set_attribute(dset->ngr, "label", "No label");
6154       ok = NOPE;
6155    }
6156    if (Label) SUMA_free(Label); Label = NULL;
6157 
6158    SUMA_RETURN(ok);
6159 }
6160 
6161 /*!
6162    Rename a dataset and take care of idcode and relabeling, if necessary
6163 */
SUMA_RenameDset(SUMA_DSET * dset,char * filename,int autoid)6164 SUMA_Boolean SUMA_RenameDset(SUMA_DSET *dset, char *filename, int autoid)
6165 {
6166    static char FuncName[]={"SUMA_RenameDset"};
6167    char *ofname=NULL, *ofnameid = NULL, *olabel = NULL;
6168    char  *fnameid=NULL, *label=NULL;
6169    SUMA_Boolean LocalHead = NOPE;
6170 
6171    SUMA_ENTRY;
6172 
6173    if (!filename) {
6174       SUMA_S_Err("No filename");
6175       SUMA_RETURN(NOPE);
6176    }
6177 
6178    /* Do we have file name already ? */
6179    if (!(ofname = SUMA_copy_string(NI_get_attribute(dset->ngr,"filename")))) {
6180       ofname = SUMA_copy_string(filename); /* old is new */
6181    }
6182 
6183    /* put the new name in */
6184    NI_set_attribute(dset->ngr, "filename", filename);
6185 
6186    if (autoid) {
6187       /* what would the new id be based on the new name? */
6188       SUMA_NEW_ID(fnameid, filename);
6189       /* what would the old id be based on the olde name? */
6190       SUMA_NEW_ID(ofnameid, ofname);
6191       if (LocalHead) {
6192          fprintf(SUMA_STDERR,"Old: %s, %s\n"
6193                              "New: %s, %s\n",
6194                              ofnameid, ofname,
6195                              fnameid, filename);
6196       }
6197       /* was the olde id based on the old fname? */
6198       if (SDSET_ID(dset)) {
6199          if (strcmp(SDSET_ID(dset), ofnameid) == 0) {
6200             SUMA_LH("Id based on old name");
6201             /* need to recreate id based on new name*/
6202             NI_set_attribute (dset->ngr, "self_idcode", fnameid);
6203          } else { /* id was not based on name, do nothing */
6204             SUMA_LH("Id not based on old name");
6205          }
6206       } else {
6207          SUMA_S_Warn("dset with no id, what gives?");
6208       }
6209    }
6210 
6211    /* what about the label ? */
6212    if ((olabel = SDSET_LABEL(dset))) {
6213       /* have label already */
6214       if (strstr(ofname, olabel)) {
6215          /* old label was based on old file name, relabel with new filename */
6216          SUMA_LabelDset(dset, filename);
6217       }
6218    } else { /* no label, put new one in */
6219       SUMA_LabelDset(dset, filename);
6220    }
6221 
6222    if (fnameid) SUMA_free(fnameid); fnameid = NULL;
6223    if (ofnameid) SUMA_free(ofnameid); ofnameid = NULL;
6224    if (ofname) SUMA_free(ofname); ofname = NULL;
6225 
6226    SUMA_RETURN(YUP);
6227 }
6228 
6229 /*!
6230    \brief Function to allocate and initialize a dataset and add
6231    it to the list of data sets .
6232 
6233    dset = SUMA_CreateDsetPointer (
6234                               char *filename, char *idcode,
6235                               char *domain_idcode, int N_Alloc
6236                               ) ;
6237    \param filename (char *): Name of dset, typically, filename with path
6238    \param idcode (char *): identifier to use for dset.
6239                                If idcode is NULL then a new one is
6240                                generated from filename.
6241    \param domain_idcode(char *): idcode of domain. (used for both MeshDomain
6242                               and geometry domain)
6243    \return dset (SUMA_DSET *): Element of DsetList containing dataset that
6244                               was created by the function.
6245 
6246    -  This function does the following:
6247       xxxxxxx
6248 
6249    \sa SUMA_AddNelCol
6250    \sa SUMA_InsertDsetPointer
6251    \sa SUMA_NewDsetPointer
6252    \sa SUMA_CreateFullDsetPointer
6253 */
SUMA_CreateDsetPointer(char * filename,SUMA_DSET_TYPE tp,char * idcode,char * domain_idcode,int N_Alloc)6254 SUMA_DSET * SUMA_CreateDsetPointer (
6255                               char *filename, SUMA_DSET_TYPE tp,
6256                               char *idcode,
6257                               char *domain_idcode,
6258                               int N_Alloc
6259                               )
6260 {
6261    static char FuncName[]={"SUMA_CreateDsetPointer"};
6262    int ilist = -1, i = -1;
6263    char  *locid=NULL;
6264    SUMA_DSET *dset=NULL;
6265    DListElmt *Elm = NULL;
6266    SUMA_Boolean LocalHead = NOPE;
6267 
6268    SUMA_ENTRY;
6269 
6270    if (!idcode) { /* No id is given yet */
6271       if (filename) {
6272          SUMA_NEW_ID(locid, filename);   /* form one from the filename */
6273          if (LocalHead)
6274             fprintf(SUMA_STDERR,
6275                "%s: Using filename %s to create IDcode %s.\n",
6276                FuncName, filename, locid);
6277       } else {
6278          SUMA_NEW_ID(locid, NULL);
6279       }
6280    }else {
6281       locid = SUMA_copy_string(idcode);
6282    }
6283 
6284    dset = SUMA_NewDsetPointer();
6285    if (!SUMA_NewDsetGrp (dset, tp, domain_idcode, domain_idcode,
6286                          N_Alloc, 0, filename, locid)) {
6287       SUMA_SL_Crit("Failed to create dset.\n");
6288       SUMA_RETURN(0);
6289    }
6290 
6291    SUMA_LabelDset(dset, filename);
6292 
6293    if (locid) SUMA_free(locid); locid = NULL;
6294    SUMA_RETURN(dset);
6295 }
6296 
6297 /*!
6298    An easier way to create a full dset, complete with node index column
6299 */
SUMA_CreateFullDsetPointer(char * filename,SUMA_DSET_TYPE tp,char * idcode,char * domain_idcode,int N_Alloc)6300 SUMA_DSET * SUMA_CreateFullDsetPointer (
6301                               char *filename, SUMA_DSET_TYPE tp,
6302                               char *idcode,
6303                               char *domain_idcode,
6304                               int N_Alloc )
6305 {
6306    static char FuncName[]={"SUMA_CreateFullDsetPointer"};
6307    SUMA_DSET *dset=NULL;
6308    int ii, *col=NULL;
6309 
6310    SUMA_ENTRY;
6311 
6312    dset = SUMA_CreateDsetPointer (filename, tp, idcode, domain_idcode,N_Alloc);
6313    if (!dset) SUMA_RETURN(dset);
6314    if (!N_Alloc) SUMA_RETURN(dset);
6315 
6316    if (!(col = (int*)SUMA_malloc(sizeof(int)*N_Alloc))) {
6317       SUMA_S_Err("Failed to allocate node index column");
6318       SUMA_FreeDset(dset); dset=NULL;
6319    } else {
6320       for (ii=0; ii<N_Alloc; ++ii) col[ii]=ii;
6321       if (tp == SUMA_CIFTI_BUCKET) {
6322          if (!SUMA_AddDsetNelCol ( dset, "MD Node Index",
6323                                    SUMA_MD_NODE_INDEX, (void *)col, NULL, 1)) {
6324             SUMA_S_Err("Failed to add MD node index column");
6325             SUMA_FreeDset(dset); dset=NULL;
6326          }
6327       } else {
6328          if (!SUMA_AddDsetNelCol ( dset, "Node Index",
6329                                    SUMA_NODE_INDEX, (void *)col, NULL, 1)) {
6330             SUMA_S_Err("Failed to add node index column");
6331             SUMA_FreeDset(dset); dset=NULL;
6332          }
6333       }
6334    }
6335 
6336    if (col) SUMA_free(col); col = NULL;
6337    SUMA_RETURN(dset);
6338 }
6339 
6340 
6341 /*!
6342    \brief inserts a dataset pointer into the DsetList,
6343    if *dset to be inserted has the same ID as a pre-existing one (old_dset) and replace is 1, then:
6344       the contents of old_dset are freed
6345       the contents of dset are copied into old_dset
6346       the pointers of dset are set to null
6347       *dset is freed
6348       *dset is set to old_dset
6349    with those of the new one. The value of dsetp is set to the one found in the list.
6350 
6351    \param dset (SUMA_DSET **)
6352    \param DsetList (DList *): List of dset objects.
6353 */
SUMA_InsertDsetPointer(SUMA_DSET ** dsetp,DList * DsetList,int replace)6354 int SUMA_InsertDsetPointer (SUMA_DSET **dsetp, DList *DsetList, int replace)
6355 {
6356    static char FuncName[]={"SUMA_InsertDsetPointer"};
6357    char *s=NULL, stmp[200]={"uninitialized"};
6358    SUMA_DSET *dprev=NULL, *dset=NULL;
6359    SUMA_Boolean LocalHead = NOPE;
6360 
6361    SUMA_ENTRY;
6362 
6363    SUMA_LH("About to insert dset pointer %p", dsetp ? *dsetp:NULL);
6364    if (!DsetList)  { SUMA_SL_Err("Need Dset List"); SUMA_RETURN(0); }
6365    if (!dsetp) { SUMA_SL_Err("dsetp is NULL"); SUMA_RETURN(0); }
6366    else dset = *dsetp;  /* dset is the new pointer */
6367 
6368    if (SUMA_isCIFTIDset(dset) && !dset->dnel) {
6369       SUMA_S_Warn("As things stand, dset->dnel, and other goodies might be NULL"
6370       	          "and would cause an error in this function below.\n"
6371 		  "For now I will do nothing and return a positive result\n"
6372 		  "depite having done nothing.\n"
6373 		  "I am pretty sure we will want the MD dset present in the\n"
6374 		  "DsetList however.");
6375       SUMA_RETURN(1);
6376    }
6377    if (!dset->dnel) {
6378       SUMA_SL_Err("dset->nel is NULL\nNothing to do");
6379       SUMA_RETURN(0);
6380    }
6381 
6382    if (!(s= SDSET_ID(dset))) {
6383       SUMA_SL_Err("dset has no idcode.\n");
6384       SUMA_RETURN(0);
6385    }
6386 
6387    /* check if surface read was unique
6388    it's inefficient to check after the surface is read,
6389    but idcode is generated in the read routine
6390    and users should not be making this mistake too often
6391    Search for similar comment elsewhere in the code once
6392    a better remedy is found*/
6393    if ((dprev = SUMA_FindDset_ns (s,  DsetList))) {
6394       /* Check the filename match, to get around ID collision
6395          This modification is no guarantee that collisions
6396          won't occur but it is a start until I figure out
6397          the problem with hashcode */
6398       char *name=NULL, *mname=NULL;
6399       SUMA_LH("Hash code collision of (%s) with dset %p (%s)",
6400                SDSET_LABEL(dset), dprev, SDSET_LABEL(dprev));
6401       if (!(mname = SDSET_FILENAME(dprev))) mname = "NULLITY";
6402       if (!(name = SDSET_FILENAME(dset))) name = "NULLITY";
6403       if (name && mname && strcmp(name, mname)) {
6404          char *stimpy;
6405          /* give dset a new ID */
6406          stimpy = SUMA_append_replace_string(name, SDSET_ID(dset),"_",0);
6407          SUMA_NewDsetID2(dset, stimpy);
6408          SUMA_ifree(stimpy);
6409          s= SDSET_ID(dset);
6410       }
6411       dprev=NULL;
6412    }
6413 
6414    if ((dprev = SUMA_FindDset_ns (s,  DsetList))) {
6415       snprintf(stmp, 198, "Dset %s has similar idcode (%s) in list as \n"
6416                      "dset %s. Trying replacement.\n",
6417                      SUMA_sdset_filename(dset), s, SUMA_sdset_filename(dprev));
6418    } else if (!dprev && replace) { /* try a looser search */
6419       SUMA_LH("ID match not found, trying filename match");
6420       dprev = SUMA_FindDsetLoose(dset, DsetList,"filename");
6421       if (dprev) {
6422          if (!AFNI_yesenv("SUMA_AllowFilenameDsetMatch")) {
6423             SUMA_S_Warn("Attempting to load a new dataset with a unique ID\n"
6424                         "and a pre-existing name in the list.\n"
6425                         "This causes trouble unless you are willing to \n"
6426                         "replace pre-existing dataset of the same name.\n"
6427                         "If so, you need to set the environment variable: \n"
6428                         "SUMA_AllowFilenameDsetMatch = YES\n"
6429                         "in your ~/.sumarc or ~/.afnirc files.\n");
6430              SUMA_RETURN(0);
6431          } else {
6432             snprintf(stmp, 198,
6433                   "Dset match based on filename, although IDs did not match.\n"
6434                   "Allowing replacement per SUMA_AllowFilenameDsetMatch\n"
6435                   "environment variable setting.\n");
6436          }
6437       }
6438    }
6439 
6440 
6441 
6442    if (dprev) {
6443       SUMA_LH("Dset exists");
6444       if (replace || AFNI_yesenv("SUMA_AllowFilenameDsetMatch")) {
6445          SUMA_LH("Replacing");
6446          SUMA_SL_Note("%s",stmp);
6447          #ifdef OLD_DSET /* before ngr was used */
6448          if (dprev->nel) NI_free_element(dprev->nel); dprev->nel = NULL;
6449          dprev->nel = dset->nel;
6450          dset->nel = NULL;
6451          #else
6452          dprev->inel = NULL;
6453          dprev->dnel = NULL;
6454          if (dprev->ngr) NI_free_element(dprev->ngr); dprev->ngr = NULL;
6455          dprev->ngr = dset->ngr;
6456          dprev->dnel = dset->dnel;
6457          dprev->inel = dset->inel;
6458          /* set dset's pointers to null */
6459          dset->ngr = NULL;
6460          dset->dnel = NULL;
6461          dset->inel = NULL;
6462          #endif
6463          SUMA_free(dset);
6464          /* Put a flag up to state that all overlays of this dataset need
6465             to have column copied refreshed */
6466          NI_set_attribute(dprev->dnel,"ResetOverlay_Vecs", "yes");
6467          /*make the switch so that on return, dset becomes the previous dset*/
6468          *dsetp = dprev;
6469       } else {
6470          SUMA_LH("Not Replacing");
6471          snprintf(stmp, 198, "Dset with similar idcode (%s)\n"
6472                         "found in list. \n"
6473                         "Replacement option is turned off.\n"
6474                         "Set 'SUMA_AllowDsetReplacement = YES'\n"
6475                         "in ~/.sumarc to allow replacement.\n", s);
6476          SUMA_SL_Err("%s",stmp);
6477          SUMA_RETURN(0);
6478       }
6479    } else {
6480       SUMA_LH("New dset, inserting");
6481       /* insert into list */
6482       if (dlist_ins_next(DsetList, dlist_tail(DsetList), (void *)dset) < 0) {
6483          SUMA_SL_Err("Failed to insert dset into list");
6484          SUMA_FreeDset(dset); dset = NULL; *dsetp = NULL;
6485          SUMA_RETURN(0);
6486       }
6487    }
6488 
6489    SUMA_RETURN(1);
6490 }
6491 
SUMA_DeleteDsetPointer(SUMA_DSET ** dsetp,DList * DsetList)6492 int SUMA_DeleteDsetPointer (SUMA_DSET **dsetp, DList *DsetList)
6493 {
6494    static char FuncName[]={"SUMA_DeleteDsetPointer"};
6495    char *s=NULL, stmp[200];
6496    SUMA_DSET *dprev=NULL, *dset=NULL;
6497    DListElmt *el=NULL;
6498    SUMA_Boolean LocalHead = NOPE;
6499 
6500    SUMA_ENTRY;
6501 
6502    if (!DsetList)  { SUMA_SL_Err("Need Dset List"); SUMA_RETURN(0); }
6503    if (!dsetp) { SUMA_SL_Err("dsetp is NULL"); SUMA_RETURN(0); }
6504    else dset = *dsetp;  /* dset is the new pointer */
6505 
6506    if (!dset->dnel) { SUMA_SL_Err("dset->nel is NULL\nNothing to do"); SUMA_RETURN(0); }
6507 
6508    s= SDSET_ID(dset); if (!s) { SUMA_SL_Err("dset has no idcode.\n"); SUMA_RETURN(0); }
6509    if ((el = SUMA_FindDsetEl_ns (s,  DsetList))) {
6510       SUMA_LH("Dset exists, removing element");
6511       dlist_remove(DsetList, el, (void *)&dprev);
6512       if (dset != dprev) { SUMA_S_Crit("This is confusing..."); SUMA_RETURN(0);}
6513 
6514       SUMA_LH("   and freeing dset");
6515       SUMA_FreeDset(dset); dset = NULL;
6516       *dsetp = NULL;
6517    } else {
6518       SUMA_LH("Dset not in list, no action taken");
6519    }
6520 
6521    SUMA_RETURN(1);
6522 }
6523 
SUMA_ShowMeSome(void * dt,SUMA_VARTYPE tp,int N_dt,int mxshow,char * title)6524 char *SUMA_ShowMeSome ( void *dt, SUMA_VARTYPE tp, int N_dt,
6525                         int mxshow, char *title)
6526 {
6527    static char FuncName[]={"SUMA_ShowMeSome"};
6528    int i, imx, firsthalf, secondhalf;
6529    double *dtd;
6530    int *dti;
6531    short *dth;
6532    byte *dtb;
6533    char **dts;
6534    float *dtf;
6535    char *s=NULL;
6536    complex *dtc = NULL;
6537    SUMA_STRING *SS=NULL;
6538    SUMA_Boolean LocalHead = NOPE;
6539 
6540    SUMA_ENTRY;
6541 
6542    if (mxshow > N_dt) mxshow = N_dt;
6543 
6544    if (mxshow < 0) mxshow = N_dt;
6545    if (mxshow < 0) SUMA_RETURN(s);
6546 
6547    SS = SUMA_StringAppend(NULL, NULL);
6548 
6549    if (title) {
6550       SS = SUMA_StringAppend_va(SS, "%s", title);
6551    }
6552 
6553 
6554    firsthalf = mxshow / 2;
6555    secondhalf = mxshow - firsthalf;
6556    if (LocalHead)
6557       fprintf(SUMA_STDERR,
6558                "%s: tp=%d, SUMA_complex = %d, SUMA_double=%d, SUMA_float=%d, "
6559                "SUMA_int=%d, SUMA_byte=%d, SUMA_short=%d\n",
6560                FuncName, tp, SUMA_complex, SUMA_double, SUMA_float,
6561                SUMA_int, SUMA_byte, SUMA_short);
6562    if (mxshow && dt) {
6563       switch (tp) {
6564          case SUMA_double:
6565             dtd = (double*)dt;
6566             for (i=0; i < firsthalf; ++i)
6567                   SS = SUMA_StringAppend_va(SS, "%lf, ", dtd[i]);
6568             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6569             if (secondhalf > 1) {
6570                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6571                      SS = SUMA_StringAppend_va(SS, "%lf, ", dtd[i]);
6572             }
6573             SS = SUMA_StringAppend_va(SS, "%lf", dtd[N_dt-1]);
6574             break;
6575          case SUMA_float:
6576             dtf = (float*)dt;
6577             for (i=0; i < firsthalf; ++i)
6578                SS = SUMA_StringAppend_va(SS, "%f, ", dtf[i]);
6579             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6580             if (secondhalf > 1) {
6581                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6582                   SS = SUMA_StringAppend_va(SS, "%f, ", dtf[i]);
6583             }
6584             SS = SUMA_StringAppend_va(SS, "%f", dtf[N_dt-1]);
6585             break;
6586          case SUMA_int:
6587             dti = (int*)dt;
6588             for (i=0; i < firsthalf; ++i)
6589                SS = SUMA_StringAppend_va(SS, "%d, ", dti[i]);
6590             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6591             if (secondhalf > 1) {
6592                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6593                   SS = SUMA_StringAppend_va(SS, "%d, ", dti[i]);
6594             }
6595             SS = SUMA_StringAppend_va(SS, "%d", dti[N_dt-1]);
6596             break;
6597          case SUMA_byte:
6598             dtb = (byte*)dt;
6599             for (i=0; i < firsthalf; ++i)
6600                SS = SUMA_StringAppend_va(SS, "%d, ", dtb[i]);
6601             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6602             if (secondhalf > 1) {
6603                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6604                   SS = SUMA_StringAppend_va(SS, "%d, ", dtb[i]);
6605             }
6606             SS = SUMA_StringAppend_va(SS, "%d", dtb[N_dt-1]);
6607             break;
6608          case SUMA_short:
6609             dth = (short*)dt;
6610             for (i=0; i < firsthalf; ++i)
6611                SS = SUMA_StringAppend_va(SS, "%d, ", dth[i]);
6612             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6613             if (secondhalf > 1) {
6614                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6615                   SS = SUMA_StringAppend_va(SS, "%d, ", dth[i]);
6616             }
6617             SS = SUMA_StringAppend_va(SS, "%d", dth[N_dt-1]);
6618             break;
6619          case SUMA_string:
6620             dts = (char **)dt;
6621             for (i=0; i < firsthalf; ++i)
6622                SS = SUMA_StringAppend_va(SS, "%s, ", dts[i]);
6623             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6624             if (secondhalf > 1) {
6625                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6626                   SS = SUMA_StringAppend_va(SS, "%s, ", dts[i]);
6627             }
6628             SS = SUMA_StringAppend_va(SS, "%s", dts[N_dt-1]);
6629             break;
6630          case SUMA_complex:
6631             dtc = (complex *)dt;
6632             for (i=0; i < firsthalf; ++i)
6633                SS = SUMA_StringAppend_va(SS, "(%f %+fi), ", dtc[i].r, dtc[i].i);
6634             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
6635             if (secondhalf > 1) {
6636                for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i)
6637                   SS = SUMA_StringAppend_va(SS, "(%f %+fi), ",
6638                                                 dtc[i].r, dtc[i].i);
6639             }
6640             SS = SUMA_StringAppend_va( SS, "(%f %+fi)",
6641                                        dtc[N_dt-1].r, dtc[N_dt-1].i);
6642             break;
6643          default:
6644             SS = SUMA_StringAppend_va(SS, "Column type not supported.");
6645       }
6646    } else {
6647       if (!dt) {
6648         SUMA_StringAppend(SS,"NULL vector.");
6649       } else {
6650          SS = SUMA_StringAppend_va(SS, "Empty vector.");
6651       }
6652    }
6653 
6654    SUMA_SS2S(SS,s);
6655 
6656    SUMA_RETURN(s);
6657 }
6658 
SUMA_ShowDset(SUMA_DSET * dset,int detail,FILE * out)6659 void SUMA_ShowDset (SUMA_DSET *dset, int detail, FILE *out)
6660 {
6661    static char FuncName[]={"SUMA_ShowDset"};
6662    char *si = NULL;
6663 
6664    SUMA_ENTRY;
6665 
6666    if (!out) out = SUMA_STDERR;
6667 
6668    si = SUMA_DsetInfo(dset, detail);
6669 
6670    fprintf(out,"%s\n", si);
6671 
6672    if (si) SUMA_free(si); si = NULL;
6673 
6674    SUMA_RETURNe;
6675 
6676 }
6677 /*!
6678    \brief Function to return info on SUMA_DSET
6679 
6680    - You must free the returned string on your own
6681    \sa SUMA_ShowDset
6682 */
SUMA_DsetInfo(SUMA_DSET * dset,int detail)6683 char *SUMA_DsetInfo (SUMA_DSET *dset, int detail)
6684 {
6685    static char FuncName[]={"SUMA_DsetInfo"};
6686    int i;
6687    SUMA_COL_TYPE ctp;
6688    char *s=NULL, stmp[200];
6689    SUMA_STRING *SS=NULL;
6690    NI_group *ngr=NULL;
6691 
6692    SUMA_ENTRY;
6693 
6694    SS = SUMA_StringAppend(NULL, NULL);
6695 
6696    if (dset) {
6697       SS = SUMA_StringAppend_va(SS, "Dset %p, datum level %d (0..%d possible)\n",
6698                                  dset,  SUMA_sdset_datum_level(dset),
6699                                  SUMA_N_LEV_DAT);
6700       SS = SUMA_StringAppend_va(SS, "Number of Links: %d\n", dset->N_links);
6701       if (dset->dnel) {
6702          SS = SUMA_StringAppend_va(SS,
6703             "Dset Name: %s (%d), isGraph %d, isCIFTI (MultiDomain)%d\n",
6704             dset->dnel->name, SUMA_Dset_Type(dset->dnel->name),
6705             SUMA_isGraphDset(dset), SUMA_isCIFTIDset(dset));
6706          if ((s = NI_get_attribute(dset->ngr,"MD_parent_ID"))) {
6707 	    SS = SUMA_StringAppend_va(SS,
6708 	          "Elemantary dataset created from multi domain parent:\n"
6709 		  "   ID: %s\n"
6710 		  "   Label: %s\n"
6711 		  "   Domain Index: %s",
6712 		  s, NI_get_attribute(dset->ngr,"MD_parent_label"),
6713 		  NI_get_attribute(dset->ngr,"MD_parent_subdomain_index"));
6714 	    s = NULL;
6715 	 }
6716 	 if (SDSET_FILENAME(dset))
6717             SS = SUMA_StringAppend_va( SS, "filename: %s\n",
6718                                        SDSET_FILENAME(dset));
6719          else SS = SUMA_StringAppend_va(SS, "filename: NULL\n");
6720          if (SDSET_LABEL(dset))
6721             SS = SUMA_StringAppend_va(SS, "label: %s\n", SDSET_LABEL(dset));
6722          else SS = SUMA_StringAppend_va(SS, "label: NULL\n");
6723          if (SDSET_ID(dset))
6724             SS = SUMA_StringAppend_va( SS, "self_idcode (idcode): %s\n",
6725                                        SDSET_ID(dset));
6726          else SS = SUMA_StringAppend_va(SS, "self_idcode (idcode): NULL\n");
6727          if (SDSET_IDGDOM(dset))
6728             SS = SUMA_StringAppend_va( SS, "geometry_parent_idcode: %s\n",
6729                                        SDSET_IDGDOM(dset));
6730          else SS = SUMA_StringAppend_va(SS, "geometry_parent_idcode: NULL\n");
6731          if (SDSET_IDMDOM(dset))
6732             SS = SUMA_StringAppend_va(SS,
6733                         "domain_parent_idcode (MeshParent_idcode): %s\n",
6734                         SDSET_IDMDOM(dset));
6735          else SS = SUMA_StringAppend_va(SS,
6736                         "domain_parent_idcode ( MeshParent_idcode): NULL\n");
6737 
6738 
6739          /* where is the node index (NodeDef) column ? */
6740          SS = SUMA_StringAppend_va(SS, "Node Index (NodeDef) Element:\n");
6741          if (!dset->inel) {
6742             SS = SUMA_StringAppend_va(SS, "NULL inel\n");
6743          } else {
6744             SS = SUMA_StringAppend_va(SS, "\tinel->vec_len = %d\n"
6745                                           "\tinel->vec_num = %d\n"
6746                                           "\tinel->vec_filled = %d\n",
6747                                           dset->inel->vec_len,
6748                                           dset->inel->vec_num,
6749                                           dset->inel->vec_filled);
6750          }
6751          {  int *ind;
6752             ind = SUMA_GetNodeDef (dset);
6753             if (!ind) {
6754                SS = SUMA_StringAppend_va(SS,
6755                            "\tNode Index Column pointer is NULL.\n");
6756             } else {
6757                SS = SUMA_StringAppend_va(SS, "\tNode Index Column found.\n");
6758                if (SDSET_SORTED(dset))
6759                   SS = SUMA_StringAppend_va(SS,
6760                      "\tsorted_node_def: %s\n", SDSET_SORTED(dset));
6761                else SS = SUMA_StringAppend_va(SS, "\tsorted_node_def: NULL\n");
6762                s = SUMA_ShowMeSome((void*)(  ind),
6763                                    SUMA_ColType2TypeCast (SUMA_NODE_INDEX)
6764                                   , SDSET_VECLEN(dset), 5, NULL);
6765                SS = SUMA_StringAppend_va(SS, "         %s\n", s);
6766                                     SUMA_free(s); s = NULL;
6767             }
6768          }
6769 
6770          if (!dset->Aux) SS = SUMA_StringAppend_va(SS, "Aux struct is NULL");
6771          else {
6772             SS = SUMA_StringAppend_va(SS, "Saux: %p\n",
6773                            dset->Aux->Saux?dset->Aux->Saux:NULL);
6774             SS = SUMA_StringAppend_va(SS, "matrix_shape: %d",
6775                                        dset->Aux->matrix_shape);
6776             SS = SUMA_StringAppend_va(SS,
6777                "matrix_max_index: %ld, matrix_size: %ld %ld, matrix_2M: %ld\b",
6778                   dset->Aux->matrix_max_index,
6779                   dset->Aux->matrix_size[0], dset->Aux->matrix_size[1],
6780                   dset->Aux->matrix_2M);
6781             SS = SUMA_StringAppend_va(SS,
6782                "range_edge_index: %ld %ld, range_node_index: %ld %ld\n"
6783                "N_seg_nodes: %ld, N_all_nodes: %ld\n",
6784                dset->Aux->range_edge_index[0], dset->Aux->range_edge_index[1],
6785                dset->Aux->range_node_index[0], dset->Aux->range_node_index[1],
6786                dset->Aux->N_seg_nodes, dset->Aux->N_all_nodes);
6787             SS = SUMA_StringAppend_va(SS, "%d domains:\n", dset->Aux->N_doms);
6788             if (dset->Aux->doms) {
6789                for (i=0; i<dset->Aux->N_doms; ++i) {
6790                   if (dset->Aux->doms[i]) {
6791 
6792 		     SS = SUMA_StringAppend_va(SS,
6793                            "   dom[%d]:\n"
6794 			   "      edset_id %s\n"
6795                            "      Source: %s\n"
6796                            "      IndexOffset: %d\n"
6797                            "      IndexCount: %d\n"
6798                            "      Max_N_Data: %d\n"
6799                            "      ModelType: %d %s\n"
6800                            "      Range: %d %d %d %d\n",
6801                      i, CNS(dset->Aux->doms[i]->edset_id),
6802 		     SUMA_CHECK_NULL_STR(dset->Aux->doms[i]->Source),
6803                      dset->Aux->doms[i]->IndexOffset,
6804                      dset->Aux->doms[i]->IndexCount,
6805                      dset->Aux->doms[i]->Max_N_Data,
6806                      dset->Aux->doms[i]->ModelType,
6807             SUMA_ObjectTypeCode2ObjectTypeName(dset->Aux->doms[i]->ModelType),
6808                      dset->Aux->doms[i]->Range[0], dset->Aux->doms[i]->Range[1],
6809                      dset->Aux->doms[i]->Range[2], dset->Aux->doms[i]->Range[3]);
6810                   } else {
6811                      SS = SUMA_StringAppend_va(SS, "   dom[%d]=NULL\n", i);
6812                   }
6813                }
6814             } else {
6815                SS = SUMA_StringAppend_va(SS, "dset->Aux->doms is NULL");
6816             }
6817          }
6818          SS = SUMA_StringAppend_va(SS, "Data Element:\n");
6819          SS = SUMA_StringAppend_va(SS,
6820                   "dnel->vec_num (N_subsets): %d\n", SDSET_VECNUM(dset));
6821          SS = SUMA_StringAppend_va(SS,
6822                   "dnel->vec_filled (N_NodeDef): %d\n", SDSET_VECFILLED(dset));
6823          SS = SUMA_StringAppend_va(SS,
6824                   "dnel->vec_len (N_Alloc): %d\n", SDSET_VECLEN(dset));
6825          for (i=0; i < SDSET_VECNUM(dset); ++i) {
6826             SS = SUMA_StringAppend_va(SS, "vec[%d]:\n", i);
6827             sprintf (stmp,"TypeCol_%d", i);
6828             ctp = SUMA_TypeOfDsetColNumb(dset, i);
6829             SS = SUMA_StringAppend_va(SS, "\tColumn %d's type: %s\n",
6830                                        i, SUMA_Col_Type_Name(ctp));
6831             #if 1
6832             sprintf(stmp,"attrCol_%d", i);
6833             s = SUMA_AttrOfDsetColNumb(dset, i);
6834             if (s && s[0] != '\0') {
6835                SS = SUMA_StringAppend_va(SS,
6836                                      "\tColumn %d's attribute: %s\n",
6837                                        i, s );
6838             } else {
6839                SS = SUMA_StringAppend_va(SS,
6840                                     "\tColumn %d's attribute does not exist.\n",
6841                                        i );
6842             }
6843             if (s) SUMA_free(s); s = NULL;
6844             s = SUMA_DsetColLabelCopy(dset, i, 0);
6845             if (s && s[0] != '\0') {
6846                SS = SUMA_StringAppend_va(SS,
6847                                        "\tColumn %d's label: %s\n",
6848                                        i, s );
6849             } else {
6850                SS = SUMA_StringAppend_va(SS,
6851                                        "\tColumn %d's label does not exist.\n",
6852                                        i );
6853             }
6854             if (s) SUMA_free(s); s = NULL;
6855             if (dset->dnel->vec[i]) {
6856                s = SUMA_ShowMeSome((void*)(  dset->dnel->vec[i]),
6857                                              SUMA_ColType2TypeCast (ctp)
6858                                              , SDSET_VECLEN(dset), 5, NULL);
6859                SS = SUMA_StringAppend_va(SS, "         %s\n", s);
6860                SUMA_free(s); s = NULL;
6861             } else SS = SUMA_StringAppend_va(SS, "         NULL\n");
6862             #endif
6863          }
6864 
6865          if (detail) { /* write the entire element to SS */
6866             NI_stream ns = NI_stream_open("str:", "w");
6867             NI_write_element(ns, dset->ngr, NI_TEXT_MODE);
6868             SS = SUMA_StringAppend(SS, "\n Full NI group in text mode:\n");
6869             SS = SUMA_StringAppend(SS, NI_stream_getbuf(ns));
6870                /* don't use StringAppend_va because it does not
6871                   allow very long strings. */
6872             SS = SUMA_StringAppend(SS, "\n");
6873             NI_stream_close(ns);
6874          }
6875       } else {
6876          SS = SUMA_StringAppend(SS, "NULL dset->dnel.");
6877       }
6878       /* got cmap? */
6879       if ((ngr = SUMA_NI_Cmap_of_Dset(dset))) {
6880             NI_stream ns = NI_stream_open("str:", "w");
6881             NI_write_element(ns, ngr, NI_TEXT_MODE);
6882             SS = SUMA_StringAppend(SS, "\n Internal colormap info:\n");
6883             SS = SUMA_StringAppend(SS, NI_stream_getbuf(ns));
6884             SS = SUMA_StringAppend(SS, "\n");
6885             NI_stream_close(ns);
6886       } else {
6887          SS = SUMA_StringAppend(SS, "No internal colormap.");
6888       }
6889    } else {
6890       SS = SUMA_StringAppend(SS, "NULL dset.");
6891    }
6892 
6893    SUMA_SS2S(SS, s);
6894 
6895    SUMA_RETURN(s);
6896 }
6897 
6898 
6899 
6900 /*!
6901    \brief Returns a pointer to the column containing NodeDef
6902    (if it exists, in dset). Do not free this pointer!
6903 */
SUMA_GetNodeDef(SUMA_DSET * dset)6904 int * SUMA_GetNodeDef(SUMA_DSET *dset)
6905 {
6906    static char FuncName[]={"SUMA_GetNodeDef"};
6907    int *ind = NULL;
6908    SUMA_Boolean LocalHead=NOPE;
6909 
6910    SUMA_ENTRY;
6911 
6912    ind = SDSET_NODE_INDEX_COL(dset);
6913 
6914    if (!ind) {
6915       SUMA_LH("No Node Def found.");
6916       SUMA_RETURN(NULL);
6917    } else {
6918       SUMA_LH("Node Def Column found.");
6919       /* a healthy check */
6920                /* The SDSET_VECFILLED(dset) < SDSET_NODEINDFILLED(dset) */
6921                /* can occur when drawing ROI as the node index column */
6922                /* is created to be as large as the number of nodes in the */
6923                /* surface but the number of columns for the RGB data grows */
6924                /* with each drawing stroke. */
6925       if (  SDSET_VECLEN(dset) > SDSET_NODEINDLEN(dset) ||
6926             SDSET_VECFILLED(dset) > SDSET_NODEINDFILLED(dset) ) {
6927          SUMA_SL_Err(   "Veclen and/or vecfilled for\n"
6928                         "node indices is less \n"
6929                         "than that of dset data!");
6930          SUMA_DUMP_TRACE("Discrepancy in veclen, dumping trace:\n");
6931       }
6932    }
6933 
6934    SUMA_RETURN(ind);
6935 }
6936 
6937 /*!
6938    \brief Returns index (i) of the column containing NodeDef
6939    (if it exists, in dset).
6940    To get the NodeDef pointer use:
6941    if (i>=0) NodeDef = (int *)(dset->dnel->vec[i]);
6942 
6943 */
SUMA_GetNodeDefColIndex(SUMA_DSET * dset)6944 int SUMA_GetNodeDefColIndex(SUMA_DSET *dset)
6945 {
6946    static char FuncName[]={"SUMA_GetNodeDefColIndex"};
6947    int *iv, N_i, i = -1;
6948    SUMA_Boolean LocalHead=NOPE;
6949 
6950    SUMA_ENTRY;
6951 
6952    SUMA_S_Err("Function is obsolete. Make do with SUMA_GetNodeDef.\n");
6953    SUMA_RETURN(-1);
6954 
6955    i = -1;
6956 
6957    iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_INDEX, &N_i);
6958    if (!iv) {
6959       SUMA_LH("No such column found.");
6960       SUMA_RETURN(-1);
6961    } else {
6962       SUMA_LH("Column found.");
6963       i = iv[0];
6964 
6965       if (N_i > 1) {
6966          SUMA_SL_Warn("Found more than one node index vector.\n"
6967                       "Returning first one found.\n");
6968       }
6969       SUMA_free(iv); iv = NULL;
6970    }
6971 
6972    SUMA_RETURN(i);
6973 }
6974 
6975 /*!
6976    \brief Look for datasets satisfying the following:
6977       type SUMA_NODE_CONVEXITY
6978       idcode_str for a geometry domain and a mesh domain
6979    \param ReturnDsetPointer if 1 then return pointer is to
6980                                        dset element (SUMA_DSET *)
6981                             if 0 then return pointer is to Cx (float *)
6982    \return A POINTER copy to Cx (float *)
6983 */
SUMA_GetCx(char * idcode_str,DList * DsetList,int ReturnDsetPointer)6984 void * SUMA_GetCx(char *idcode_str, DList *DsetList, int ReturnDsetPointer)
6985 {
6986    static char FuncName[]={"SUMA_GetCx"};
6987    float *Cx = NULL;
6988    char *tp_name, *idg, *idm;
6989    int *iv = NULL, N_i=-1, N_found = -1;
6990    DListElmt *el;
6991    SUMA_DSET *dset=NULL;
6992 
6993    SUMA_ENTRY;
6994 
6995    if (!dlist_size(DsetList)) SUMA_RETURN(Cx);
6996    if (!idcode_str)  SUMA_RETURN(Cx);
6997    tp_name = SUMA_Dset_Type_Name(SUMA_NODE_CONVEXITY);
6998 
6999    el = NULL;
7000    Cx = NULL;
7001    N_found = 0;
7002    do {
7003       if (!el) el = dlist_head(DsetList);
7004       else el = el->next;
7005       dset = (SUMA_DSET *)el->data;
7006       if (dset->dnel) {
7007          if (strcmp(SDSET_TYPE_NAME(dset), tp_name) == 0) {
7008             /* matched type, now look for matching domain */
7009             idg = SDSET_IDGDOM(dset); idm = SDSET_IDMDOM(dset);
7010             if (idg && idm) {
7011                if (!strcmp(SDSET_IDGDOM(dset), idcode_str)) {
7012                   if (!N_found) {
7013                      /* find the column of type SUMA_NODE_CX */
7014                      iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_CX, &N_i);
7015                      if (!iv) {
7016                         SUMA_SL_Err("SUMA_NODE_CX not found.");
7017                         SUMA_RETURN(NULL); }
7018                      if (N_i != 1) {
7019                         SUMA_SL_Err("more than 1 SUMA_NODE_CX found.");
7020                         SUMA_RETURN(NULL); }
7021                      Cx = (float *)dset->dnel->vec[iv[0]];
7022                      SUMA_free(iv); iv = NULL;
7023                   }
7024                   ++ N_found;
7025                }
7026             }
7027          }
7028       }
7029 
7030    }  while (el != dlist_tail(DsetList));
7031 
7032    if (N_found > 1) {
7033       SUMA_SL_Warn ( "More than one convexity dataset found.\n"
7034                      "Returning first one encountered.");
7035    }
7036 
7037    if (ReturnDsetPointer) {SUMA_RETURN((void*)dset);}
7038    else {SUMA_RETURN((void *)Cx);}
7039 }
7040 
7041 /*!
7042    \brief Returns the index of the node for which
7043    data exists in row row of  Dset.
7044    Set N_Node to SO->N_Node in the function call whenever
7045    appropriate, it helps the function go faster
7046    in certain instances. You can't get SO inside this
7047    function from MeshParent_idcode of nel because this file
7048    is not to know about surface objects.
7049    Set N_Node to -1 if you don't want to use it
7050 */
SUMA_GetNodeIndex_FromNodeRow_ns(SUMA_DSET * dset,int row,int N_Node)7051 int SUMA_GetNodeIndex_FromNodeRow_ns(SUMA_DSET *dset, int row, int N_Node)
7052 {
7053    int i=SUMA_GetNodeIndex_FromNodeRow_eng(dset, row, N_Node);
7054    WorkErrLog_ns();
7055    return(i);
7056 }
7057 
SUMA_GetNodeIndex_FromNodeRow_eng(SUMA_DSET * dset,int row,int N_Node)7058 int SUMA_GetNodeIndex_FromNodeRow_eng(SUMA_DSET *dset, int row, int N_Node)
7059 {
7060    static char FuncName[]={"SUMA_GetNodeIndex_FromNodeRow_eng"};
7061    static int WarnCount;
7062    int Found = -1, i, *NodeDef=NULL;
7063    double dval=0.0;
7064    char *str=NULL;
7065    NI_element *nel = dset->dnel;
7066    SUMA_Boolean LocalHead = NOPE;
7067 
7068    SUMA_ENTRY;
7069 
7070    if (row < 0) SUMA_RETURN(-1);
7071 
7072    if (N_Node >= 0  && row >= N_Node) {
7073       SUMA_PushErrLog(  "SL_Err",
7074                         "row index >= N_Node\n"
7075                         "Will somebody please think of the children!",
7076                         FuncName);
7077       SUMA_RETURN(-1);
7078    }
7079    if (row >= nel->vec_len) {
7080       SUMA_PushErrLog(  "SL_Err",
7081                         "row index >= nel->vec_len\n"
7082                         "Bad logic!",
7083                         FuncName);
7084       SUMA_RETURN(-1);
7085    }
7086 
7087    #if 0
7088    /*(DO NOT DELETE)*/
7089    /* This would fail if data are not ordered such that row(i)
7090       is the data for node i */
7091    /* try the fast one */
7092    SUMA_LH( "Trying the fast one");
7093    if (nel->vec_len == nel->vec_filled && nel->vec_len == N_Node) {
7094       SUMA_RETURN(row);
7095    }
7096    #endif
7097 
7098    SUMA_LH( "Trying the slow mo");
7099    /* does this dset have a column index ? */
7100    NodeDef = SUMA_GetNodeDef (dset);
7101 
7102    if (NodeDef) {
7103       SUMA_LH( "Col. Index found");
7104       if (row >= nel->vec_filled) {
7105          SUMA_PushErrLog(  "SL_Err", "row >= nel->vec_filled.\n", FuncName);
7106          SUMA_RETURN(-1);
7107       } else {
7108          SUMA_RETURN(NodeDef[row]);
7109       }
7110    }
7111 
7112    /* last resort, assume that data are ordered properly
7113       (see commented out section above)*/
7114    if ((nel->vec_len == nel->vec_filled &&
7115        (nel->vec_len == N_Node || N_Node == -1))) {
7116                /* N_Node can be set to -1 when function is called on
7117                   non-SOs . In that case the N_Node match should not
7118                   be enforced */
7119       if (0 && !(WarnCount % 25 - 1)) {
7120          SUMA_PushErrLog(  "SLP_Warn", "Assuming ith row of data\n"
7121                      "corresponds to node i.\n"
7122                      "You'll get trash if this is not true.\n"
7123                      "This warning is shown intermittently.", FuncName);
7124       } ++ WarnCount;
7125       SUMA_RETURN(row);
7126    }
7127 
7128    fprintf(stderr,"row %d vec_len %d vec_filled %d N_Node %d\n",
7129                 row, nel->vec_len, nel->vec_filled, N_Node);
7130    SUMA_DUMP_TRACE("???");
7131    SUMA_PushErrLog(  "SL_Err", "No way to get column index.", FuncName);
7132 
7133    /* bad news lews, this node is not in this Dset */
7134    SUMA_RETURN(-1);
7135 }
7136 
7137 
7138 /*!
7139    \brief j = SUMA_GetNodeRow_FromNodeIndex( dset, i);
7140    Returns the row index of a node in the columns
7141    of a data set. In other terms, node i's data are in
7142    row j of the columns in nel
7143    for N_Node, see comments in  SUMA_GetNodeIndex_FromNodeRow
7144    \sa SUMA_GetNodeIndex_FromNodeRow
7145 */
SUMA_GetNodeRow_FromNodeIndex_ns(SUMA_DSET * dset,int node,int N_Node)7146 int SUMA_GetNodeRow_FromNodeIndex_ns(SUMA_DSET *dset, int node, int N_Node)
7147 {
7148    int i = SUMA_GetNodeRow_FromNodeIndex_eng(dset,  node,  N_Node);
7149    WorkErrLog_ns();
7150    return(i);
7151 }
SUMA_GetNodeRow_FromNodeIndex_eng(SUMA_DSET * dset,int node,int Max_Node_Index)7152 int SUMA_GetNodeRow_FromNodeIndex_eng(SUMA_DSET *dset, int node,
7153                                       int Max_Node_Index)
7154 {
7155    static char FuncName[]={"SUMA_GetNodeRow_FromNodeIndex_eng"};
7156    static int WarnCount;
7157    int Found = -1, i, *NodeDef=NULL;
7158    double dval=0.0;
7159    char *str=NULL;
7160    char mmm[256];
7161    NI_element *nel = NULL;
7162    SUMA_Boolean LocalHead = NOPE;
7163 
7164    SUMA_ENTRY;
7165 
7166 
7167    if (!dset || node < 0 || (Max_Node_Index >=0 && node > Max_Node_Index)) {
7168       /* turn this warning off once you confirm that Shane's bug is gone */
7169       /* Note that -1 is a flag for an unitialized node, so it is benign */
7170       if (LocalHead) {
7171          snprintf(mmm,
7172                  255*sizeof(char),
7173             "Strange input, dset %p, node %d, Max Node Index %d. returning -1.",
7174                  dset, node, Max_Node_Index);
7175 
7176          SUMA_PushErrLog("SL_Warn", mmm, FuncName);
7177          SUMA_DUMP_TRACE("At the strange input");
7178       }
7179       SUMA_RETURN(-1);
7180    }
7181 
7182    nel = dset->dnel;
7183    if (!nel) {
7184       SUMA_PushErrLog("SL_Err", "Nasty dset", FuncName);
7185       SUMA_RETURN(-1);
7186    }
7187    #if 0
7188    /* DO NOT DELETE, SEE BELOW */
7189    /* try the fast one */
7190    /* This would fail if data are not ordered such that row(i) is
7191       the data for node i */
7192    SUMA_LH( "Trying the fast one");
7193    if (nel->vec_len == nel->vec_filled && nel->vec_len == (Max_Node_Index+1)) {
7194       SUMA_RETURN(node);
7195    }
7196    #endif
7197 
7198    SUMA_LH("Trying the slow mo");
7199    /* does this dset have a column index ? */
7200    NodeDef = SUMA_GetNodeDef (dset);
7201 
7202    if (NodeDef) {
7203       SUMA_LH("Col. Index found, node %d, vec_filled %d", node, nel->vec_filled);
7204       if (nel->vec_filled > node) {
7205          /* bug here (used to be < !) discovered thanks to Rosanna and Shane */
7206          if (node == NodeDef[node]) {
7207             SUMA_LH("Got lucky");
7208             SUMA_RETURN(node);
7209          }
7210       }
7211       /* explicit search */
7212       SUMA_LH("Explicit");
7213       if (Max_Node_Index >= 0 && nel->vec_filled > (Max_Node_Index+1)) {
7214                                  /* Sometimes Max_Node_Index is not set (-1)*/
7215          if (LocalHead) {
7216             fprintf( SUMA_STDERR,
7217                   "Error %s: nel->vec_filled (%d) > (%d) Max_Node_Index+1\n",
7218                   FuncName, nel->vec_filled, Max_Node_Index+1);
7219          }
7220          SUMA_PushErrLog("SL_Err",
7221                          "Unexpected error nel->vec_filled > Max_Node_Index+1",
7222                          FuncName);
7223          SUMA_RETURN(-1);
7224       }
7225 
7226       if (SDSET_IS_SORTED(dset)) {
7227          SUMA_LH("A sorted beast");
7228          SUMA_RETURN(SUMA_ibinFind(NodeDef, nel->vec_filled, node));
7229       } else {
7230          SUMA_LH("A long slow search through %d data\n",nel->vec_filled);
7231          for (i=0; i<nel->vec_filled; ++i) {
7232             if (NodeDef[i] == node) {
7233                SUMA_RETURN(i);
7234             }
7235          }
7236       }
7237    } else {
7238       SUMA_LH("No Col. Index found");
7239    }
7240 
7241    /* last resort, assume that data are ordered properly
7242       (see commented out section above)*/
7243    if (Max_Node_Index < 0 && SUMA_isVolDataset(dset)) {
7244       /* By now, we know we do not have explicit node indices */
7245       Max_Node_Index = nel->vec_len -1;
7246    }
7247    if (nel->vec_len == nel->vec_filled && nel->vec_len == Max_Node_Index+1) {
7248       SUMA_LH("Off the deep end");
7249       if (0 && !(WarnCount % 25 - 1)) {
7250          SUMA_PushErrLog("SLP_Err", "Assuming ith row of data\n"
7251                      "corresponds to node i.\n"
7252                      "You'll get trash if this is not true.\n"
7253                      "This warning is shown intermittently.", FuncName);
7254       } ++ WarnCount;
7255       SUMA_RETURN(node);
7256    } else {
7257       if (LocalHead) {
7258          SUMA_LH("Govt Shutdown");
7259          SUMA_ShowDset(dset, 0, NULL);
7260       }
7261    }
7262 
7263    /* bad news lews, this node is not in this Dset */
7264    SUMA_RETURN(-1);
7265 }
7266 
7267 /*!
7268    returns indexmap, such that indexmap[node] = row which means that
7269    data for node 'node' is in row 'row' of the dset
7270    if indexmap[node] = -1 then the node does not exist in the dset
7271    indexmap is as large as the MAX(largest index in the node list in dset ,
7272                                    maxind, SDSET_VECLEN(dset))
7273    free indexmap with SUMA_free
7274 
7275    This function should be OK for Graph Dsets.
7276 */
SUMA_CreateNodeIndexToRowIndexMap(SUMA_DSET * dset,int maxind,double * range)7277 int *SUMA_CreateNodeIndexToRowIndexMap(SUMA_DSET *dset, int maxind,
7278                                        double *range)
7279 {
7280    static char FuncName[]={"SUMA_CreateNodeIndexToRowIndexMap"};
7281    int *indexmap=NULL, j=0, *nip=NULL;
7282    int maxn = -1, loc[2];
7283    double rangel[2];
7284    SUMA_Boolean LocalHead = NOPE;
7285 
7286    SUMA_ENTRY;
7287 
7288    if (!range) range = rangel;
7289 
7290    if (!(nip = SUMA_GetNodeDef(dset))) {
7291       SUMA_S_Err("Failed to find node index column in dset");
7292       SUMA_RETURN(indexmap);
7293    }
7294 
7295    /* get the range of valid nodes */
7296    if (!SUMA_GetDsetNodeIndexColRange(dset, range, loc, 1)) {
7297       SUMA_S_Err("Failed to get node range!");
7298       SUMA_RETURN(NULL);
7299    }
7300 
7301    maxn = SUMA_MAX_PAIR(maxind+1, SDSET_VECLEN(dset));
7302    maxn = SUMA_MAX_PAIR(maxn, range[1]+1);
7303 
7304    /* find the mapping of a node index to a row */
7305    indexmap = (int *)SUMA_calloc(maxn, sizeof(int));
7306    if (!indexmap) {
7307       SUMA_S_Crit("Failed to allocate");
7308       SUMA_RETURN(NULL);
7309    }
7310    for (j=0; j<maxn; ++j)  indexmap[j] = -1;
7311 
7312    for (j=0; j<SDSET_VECFILLED(dset); ++j)
7313       indexmap[nip[j]] = j; /* indexmap[node] hold the
7314                               row in the dset that contains
7315                               data for node */
7316    if (LocalHead) {
7317       for (j=0; j<SDSET_VECFILLED(dset); ++j) {
7318           fprintf(stderr,"node %d is in row %d\n",
7319                      nip[j],
7320                      indexmap[nip[j]]);
7321       }
7322    }
7323    SUMA_RETURN(indexmap);
7324 }
7325 /*!
7326    \brief Returns the value from column ind, row ival
7327    The value is stored in a double variable 0.0  in case of error.
7328    \sa SUMA_GetValInCol
7329 */
SUMA_GetValInCol2(NI_element * nel,int ind,int ival)7330 double SUMA_GetValInCol2(NI_element *nel, int ind, int ival)
7331 {
7332    static char FuncName[]={"SUMA_GetValInCol2"};
7333    SUMA_COL_TYPE ctp;
7334    SUMA_VARTYPE vtp;
7335    byte *bv = NULL;
7336    double *dv = NULL, dval = 0.0;
7337    float *fv=NULL;
7338    int *iv = NULL;
7339    char **cv = NULL;
7340    complex *cmv = NULL;
7341    SUMA_Boolean LocalHead = NOPE;
7342 
7343    SUMA_ENTRY;
7344 
7345    SUMA_SL_Warn("Obsolete, check caller");
7346    if (!nel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(0.0); }
7347 
7348    if (ind < 0 || ind > nel->vec_num - 1) {
7349       SUMA_SL_Err("Bad index");
7350       SUMA_RETURN(0.0);
7351    }
7352 
7353    if (ival >= nel->vec_len) {
7354       SUMA_SL_Err("ival too large");
7355       SUMA_RETURN(0.0);
7356    }
7357 
7358    ctp = SUMA_TypeOfColNumb(nel, ind);
7359 
7360    vtp = SUMA_ColType2TypeCast (ctp) ;
7361    switch (vtp) {
7362       case SUMA_byte:
7363          bv = (byte *)nel->vec[ind];
7364          dval = (double)bv[ival];
7365          break;
7366       case SUMA_int:
7367          iv = (int *)nel->vec[ind];
7368          dval = (double)iv[ival];
7369          break;
7370       case SUMA_float:
7371          fv = (float *)nel->vec[ind];
7372          dval = (double)fv[ival];
7373          break;
7374       case SUMA_double:
7375          dv = (double *)nel->vec[ind];
7376          dval = (double)dv[ival];
7377          break;
7378       case SUMA_complex: /* Should be a flag for what to return here, someday*/
7379          cmv = (complex *)nel->vec[ind];
7380          dval = (double)CABS(cmv[ival]);
7381          break;
7382       default:
7383          SUMA_SL_Err("This type is not supported.\n");
7384          SUMA_RETURN(0.0);
7385          break;
7386    }
7387 
7388    SUMA_RETURN(dval);
7389 }
7390 
7391 /*!
7392    \brief Returns the value from column ind, row ival
7393    The value is stored in a double variable and a string
7394    version is returned. NULL in case of error. You are to free
7395    the returned string.
7396    \sa SUMA_GetValInCol2
7397 */
SUMA_GetValInCol(NI_element * nel,int ind,int ival,double * dval)7398 char * SUMA_GetValInCol(NI_element *nel, int ind, int ival, double *dval)
7399 {
7400    static char FuncName[]={"SUMA_GetValInCol"};
7401    SUMA_COL_TYPE ctp;
7402    SUMA_VARTYPE vtp;
7403    byte *bv = NULL;
7404    double *dv = NULL;
7405    float *fv=NULL;
7406    int *iv = NULL;
7407    char  *str=NULL, **cv = NULL;
7408    complex *cmv=NULL;
7409    SUMA_Boolean LocalHead = NOPE;
7410 
7411    SUMA_ENTRY;
7412 
7413    SUMA_SL_Warn("Obsolete, check caller");
7414    if (!nel || !dval) { SUMA_SL_Err("NULL input"); SUMA_RETURN(NULL); }
7415 
7416    if (ind < 0 || ind > nel->vec_num - 1) {
7417       SUMA_SL_Err("Bad index");
7418       SUMA_RETURN(NULL);
7419    }
7420 
7421    if (ival >= nel->vec_len) {
7422       SUMA_SL_Err("ival too large");
7423       SUMA_RETURN(NULL);
7424    }
7425 
7426    ctp = SUMA_TypeOfColNumb(nel, ind);
7427 
7428    vtp = SUMA_ColType2TypeCast (ctp) ;
7429    switch (vtp) {
7430       case SUMA_byte:
7431          str = (char *)SUMA_malloc(50*sizeof(char));
7432          bv = (byte *)nel->vec[ind];
7433          sprintf(str,"%d",bv[ival]);
7434          *dval = (double)bv[ival];
7435          break;
7436       case SUMA_int:
7437          str = (char *)SUMA_malloc(50*sizeof(char));
7438          iv = (int *)nel->vec[ind];
7439          sprintf(str,"%d",iv[ival]);
7440          *dval = (double)iv[ival];
7441          break;
7442       case SUMA_float:
7443          str = (char *)SUMA_malloc(50*sizeof(char));
7444          fv = (float *)nel->vec[ind];
7445          sprintf(str,"%f",fv[ival]);
7446          *dval = (double)fv[ival];
7447          break;
7448       case SUMA_double:
7449          str = (char *)SUMA_malloc(50*sizeof(char));
7450          dv = (double *)nel->vec[ind];
7451          sprintf(str,"%f",dv[ival]);
7452          *dval = (double)dv[ival];
7453          break;
7454       case SUMA_string:
7455          cv = (char **)nel->vec[ind];
7456          *dval = 0.0;
7457          str = SUMA_copy_string((char*)cv[ival]);
7458          break;
7459       case SUMA_complex:
7460          str = (char *)SUMA_malloc(100*sizeof(char));
7461          cmv = (complex *)nel->vec[ind];
7462          *dval = CABS(cmv[ival]);
7463          sprintf(str,"%f i%f",cmv[ival].r, cmv[ival].i);
7464          break;
7465       default:
7466          SUMA_SL_Err("This type is not supported yet.\n");
7467          SUMA_RETURN(NULL);
7468          break;
7469    }
7470 
7471    SUMA_LH("%s",str);
7472    SUMA_RETURN(str);
7473 }
7474 
7475 /*
7476    returns a vector of values at a particular node index in a dset
7477    dset: is the dset in question
7478    ind (int *): An optional vector of columns to use.
7479                Default is NULL = all columns
7480    nind (int): Number of values in ind.
7481                Not useful when ind = NULL
7482    node (int): Index of node in question
7483    iNodeMax (int): If you know the maximum number of nodes forming the domain
7484                   of the dset, typically SO->iNodeMax then pass it for speed.
7485                   Otherwise, pass -1
7486    N_ret (int *): Pointer to int to contain the number of values in result
7487                   vector
7488    Returns:
7489       result (double*) a vector of N_ret values at node node
7490 
7491    \sa SUMA_GetDsetAllNodeValsInCols
7492    \sa SUMA_Dset2VecArray
7493 */
SUMA_GetDsetAllNodeValsInCols2(SUMA_DSET * dset,int * ind,int nind,int node,int iNodeMax,int * N_ret,SUMA_VARTYPE tp)7494 void *SUMA_GetDsetAllNodeValsInCols2(SUMA_DSET *dset,
7495                                        int *ind, int nind,
7496                                        int node, int iNodeMax,
7497                                        int *N_ret,
7498                                        SUMA_VARTYPE tp)
7499 {
7500    static char FuncName[]={"SUMA_GetDsetAllNodeValsInCols2"};
7501    double *resd = NULL;
7502    float *resf = NULL;
7503    int *resi=NULL;
7504    void *resv=NULL;
7505    int noderow=-1, i=-1;
7506    SUMA_Boolean LocalHead = NOPE;
7507 
7508    SUMA_ENTRY;
7509 
7510    if (!dset || !dset->dnel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(resv); }
7511    noderow = SUMA_GetNodeRow_FromNodeIndex_eng (dset, node, iNodeMax);
7512    if (noderow < 0) {   SUMA_LH("Could not get node row\n"
7513                                 " This can happen in benign cases");
7514                         SUMA_RETURN(resv); }
7515    if ( tp != SUMA_float &&
7516         tp != SUMA_double &&
7517         tp != SUMA_int) { SUMA_SL_Err("Bad otype"); SUMA_RETURN(resv); }
7518    if (ind) {
7519       if (nind <= 0) {
7520          SUMA_SL_Err("no columns selected"); SUMA_RETURN(resv);
7521       }
7522       if (nind > SDSET_VECNUM(dset)) {
7523          SUMA_SL_Err("More columns than in dset"); SUMA_RETURN(resv);
7524       }
7525       switch (tp) {
7526          case SUMA_double:
7527             if (!(resd = (double*)SUMA_calloc(nind, sizeof(double)))) {
7528                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7529             }
7530             for (i=0; i<nind; ++i) {
7531                if (ind[i] >= 0 && ind[i]<SDSET_VECNUM(dset)) {
7532                   resd[i] = SUMA_GetDsetValInCol2(dset, ind[i], noderow);
7533                } else {
7534                   resd[i] = 0.0;
7535                }
7536             }
7537             resv = (void *)resd;
7538             break;
7539          case SUMA_float:
7540             if (!(resf = (float*)SUMA_calloc(nind, sizeof(float)))) {
7541                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7542             }
7543             for (i=0; i<nind; ++i) {
7544                if (ind[i] >= 0 && ind[i]<SDSET_VECNUM(dset)) {
7545                   resf[i] = (float)SUMA_GetDsetValInCol2(dset, ind[i], noderow);
7546                } else {
7547                   resf[i] = 0.0;
7548                }
7549             }
7550             resv = (void *)resf;
7551             break;
7552          case SUMA_int:
7553             if (!(resi = (int*)SUMA_calloc(nind, sizeof(int)))) {
7554                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7555             }
7556             for (i=0; i<nind; ++i) {
7557                if (ind[i] >= 0 && ind[i]<SDSET_VECNUM(dset)) {
7558                   resi[i] = (int)SUMA_GetDsetValInCol2(dset, ind[i], noderow);
7559                } else {
7560                   resi[i] = 0;
7561                }
7562             }
7563             resv = (void *)resi;
7564             break;
7565          default:
7566             SUMA_SL_Err("Bad otype, why here?"); SUMA_RETURN(resv);
7567             break;
7568       }
7569       *N_ret =  nind;
7570    } else {
7571       switch (tp) {
7572          case SUMA_double:
7573             if (!(resd = (double*)SUMA_calloc(SDSET_VECNUM(dset),
7574                                                 sizeof(double)))) {
7575                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7576             }
7577             for (i=0; i<SDSET_VECNUM(dset); ++i) {
7578                resd[i] = SUMA_GetDsetValInCol2(dset, i, noderow);
7579             }
7580             resv = (void *)resd;
7581             break;
7582          case SUMA_float:
7583             if (!(resf = (float*)SUMA_calloc(SDSET_VECNUM(dset),
7584                                                 sizeof(float)))) {
7585                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7586             }
7587             for (i=0; i<SDSET_VECNUM(dset); ++i) {
7588                resf[i] = (float)SUMA_GetDsetValInCol2(dset, i, noderow);
7589             }
7590             resv = (void *)resf;
7591             break;
7592          case SUMA_int:
7593             if (!(resi = (int*)SUMA_calloc(SDSET_VECNUM(dset),
7594                                                 sizeof(int)))) {
7595                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7596             }
7597             for (i=0; i<SDSET_VECNUM(dset); ++i) {
7598                resi[i] = (int)SUMA_GetDsetValInCol2(dset, i, noderow);
7599             }
7600             resv = (void *)resi;
7601             break;
7602          default:
7603             SUMA_SL_Err("Bad otype, why here too?"); SUMA_RETURN(resv);
7604             break;
7605       }
7606       *N_ret = SDSET_VECNUM(dset);
7607    }
7608 
7609    SUMA_RETURN(resv);
7610 }
7611 
7612 /*
7613 This function is very similar to SUMA_GetDsetAllNodeValsInCols2
7614 Except it operates on multiple nodes.
7615 What you get back is is a double pointer of VARTYPE with N_ret values
7616 in each row and N_Node rows
7617 
7618 \sa SUMA_VecArray2Dset
7619 */
7620 
SUMA_Dset2VecArray(SUMA_DSET * dset,int * ind,int nind,int * node,int N_Node,int iNodeMax,int * N_ret,SUMA_VARTYPE tp)7621 void **SUMA_Dset2VecArray(SUMA_DSET *dset,
7622                         int *ind, int nind,
7623                         int *node, int N_Node,
7624                         int iNodeMax,
7625                         int *N_ret,
7626                         SUMA_VARTYPE tp)
7627 {
7628    static char FuncName[]={"SUMA_Dset2VecArray"};
7629    double **resd = NULL, *dc=NULL;
7630    float **resf = NULL, *fc=NULL;
7631    int **resi=NULL, icol=0, i, c, *ic=NULL;
7632    short **ress=NULL, *sc=NULL;
7633    byte **resb=NULL, *bc=NULL;
7634    void **resv=NULL;
7635    int *rowofnode=NULL;
7636    double range[2];
7637 
7638    SUMA_Boolean LocalHead = NOPE;
7639 
7640    SUMA_ENTRY;
7641 
7642    if (!dset || !dset->dnel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(resv); }
7643    rowofnode = SUMA_CreateNodeIndexToRowIndexMap(dset, iNodeMax, range);
7644 
7645    if (!node) {
7646       node = SDSET_NODE_INDEX_COL(dset);
7647       N_Node = SDSET_VECLEN(dset);
7648    } else {
7649       /* make sure node indices do not exceed dset range */
7650       for (i=0; i<N_Node; ++i) {
7651          if (ind[i] > (int)range[1] || ind[i] < (int)range[0]) {
7652             SUMA_S_Err("Node indices out or range");
7653             SUMA_RETURN(resv);
7654          }
7655       }
7656    }
7657    if (!node) {
7658       SUMA_S_Err("Nothing to work with");
7659       SUMA_RETURN(resv);
7660    }
7661    if (!ind) {
7662       nind = SDSET_VECNUM(dset);
7663    }
7664    if ( tp == SUMA_complex) {
7665       SUMA_S_Err("No support for complex types yet");
7666       SUMA_RETURN(resv);
7667    }
7668    if ( tp != SUMA_float &&
7669         tp != SUMA_double &&
7670         tp != SUMA_int&&
7671         tp != SUMA_short &&
7672         tp != SUMA_byte ) { SUMA_SL_Err("Bad otype"); SUMA_RETURN(resv); }
7673 
7674    if (nind <= 0) {
7675       SUMA_SL_Err("no columns selected"); SUMA_RETURN(resv);
7676    }
7677    if (nind > SDSET_VECNUM(dset)) {
7678       SUMA_SL_Err("More columns than in dset"); SUMA_RETURN(resv);
7679    }
7680    switch (tp) {
7681       case SUMA_double:
7682          resd=NULL; resf=NULL; resi=NULL; ress=NULL; resb=NULL;
7683          resd = (double**)SUMA_calloc(N_Node, sizeof(double*));
7684          for (i=0; i<N_Node; ++i) {
7685             if (!(resd[i] = (double*)SUMA_calloc(nind, sizeof(double)))) {
7686                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7687             }
7688          }
7689          for (c=0; c<nind; ++c) { /* for each column */
7690             if (ind) icol = ind[c];
7691             else icol = c;
7692             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
7693             switch (SUMA_ColType2TypeCast(
7694                            SUMA_TypeOfDsetColNumb(dset, icol))) {
7695                case SUMA_double:
7696                   dc = (double *)SDSET_VEC(dset,icol);
7697                   for (i=0; i<N_Node; ++i) {
7698                      resd[i][c] = (double)dc[rowofnode[node[i]]];
7699                   }
7700                   break;
7701                case SUMA_float:
7702                   fc = (float *)SDSET_VEC(dset,icol);
7703                   for (i=0; i<N_Node; ++i) {
7704                      resd[i][c] = (double)fc[rowofnode[node[i]]];
7705                   }
7706                   break;
7707                case SUMA_int:
7708                   ic = (int *)SDSET_VEC(dset,icol);
7709                   for (i=0; i<N_Node; ++i) {
7710                      resd[i][c] = (double)ic[rowofnode[node[i]]];
7711                   }
7712                   break;
7713                case SUMA_short:
7714                   sc = (short *)SDSET_VEC(dset,icol);
7715                   for (i=0; i<N_Node; ++i) {
7716                      resd[i][c] = (double)sc[rowofnode[node[i]]];
7717                   }
7718                   break;
7719                case SUMA_byte:
7720                   bc = (byte *)SDSET_VEC(dset,icol);
7721                   for (i=0; i<N_Node; ++i) {
7722                      resd[i][c] = (double)bc[rowofnode[node[i]]];
7723                   }
7724                   break;
7725                default:
7726                   SUMA_S_Err("Var Type not supported."
7727                              "Memory leak now present");
7728                   SUMA_RETURN(NULL);
7729             }
7730          } /* for each column */
7731          resv = (void **)resd;
7732          break;
7733 
7734       case SUMA_float:
7735          resd=NULL; resf=NULL; resi=NULL; ress=NULL; resb=NULL;
7736          resf = (float**)SUMA_calloc(N_Node, sizeof(float*));
7737          for (i=0; i<N_Node; ++i) {
7738             if (!(resf[i] = (float*)SUMA_calloc(nind, sizeof(float)))) {
7739                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7740             }
7741          }
7742          for (c=0; c<nind; ++c) { /* for each column */
7743             if (ind) icol = ind[c];
7744             else icol = c;
7745             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
7746             switch (SUMA_ColType2TypeCast(
7747                            SUMA_TypeOfDsetColNumb(dset, icol))) {
7748                case SUMA_double:
7749                   dc = (double *)SDSET_VEC(dset,icol);
7750                   for (i=0; i<N_Node; ++i) {
7751                      resf[i][c] = (float)dc[rowofnode[node[i]]];
7752                   }
7753                   break;
7754                case SUMA_float:
7755                   fc = (float *)SDSET_VEC(dset,icol);
7756                   for (i=0; i<N_Node; ++i) {
7757                      resf[i][c] = (float)fc[rowofnode[node[i]]];
7758                   }
7759                   break;
7760                case SUMA_int:
7761                   ic = (int *)SDSET_VEC(dset,icol);
7762                   for (i=0; i<N_Node; ++i) {
7763                      resf[i][c] = (float)ic[rowofnode[node[i]]];
7764                   }
7765                   break;
7766                case SUMA_short:
7767                   sc = (short *)SDSET_VEC(dset,icol);
7768                   for (i=0; i<N_Node; ++i) {
7769                      resf[i][c] = (float)sc[rowofnode[node[i]]];
7770                   }
7771                   break;
7772                case SUMA_byte:
7773                   bc = (byte *)SDSET_VEC(dset,icol);
7774                   for (i=0; i<N_Node; ++i) {
7775                      resf[i][c] = (float)bc[rowofnode[node[i]]];
7776                   }
7777                   break;
7778                default:
7779                   SUMA_S_Err("Type not supported."
7780                              "Memory leak now present");
7781                   SUMA_RETURN(NULL);
7782             }
7783          } /* for each column */
7784          resv = (void **)resf;
7785          break;
7786       case SUMA_int:
7787          resd=NULL; resi=NULL; resi=NULL; ress=NULL; resb=NULL;
7788          resi = (int**)SUMA_calloc(N_Node, sizeof(int*));
7789          for (i=0; i<N_Node; ++i) {
7790             if (!(resi[i] = (int*)SUMA_calloc(nind, sizeof(int)))) {
7791                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7792             }
7793          }
7794          for (c=0; c<nind; ++c) { /* for each column */
7795             if (ind) icol = ind[c];
7796             else icol = c;
7797             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
7798             switch (SUMA_ColType2TypeCast(
7799                            SUMA_TypeOfDsetColNumb(dset, icol))) {
7800                case SUMA_double:
7801                   dc = (double *)SDSET_VEC(dset,icol);
7802                   for (i=0; i<N_Node; ++i) {
7803                      resi[i][c] = (int)dc[rowofnode[node[i]]];
7804                   }
7805                   break;
7806                case SUMA_float:
7807                   fc = (float *)SDSET_VEC(dset,icol);
7808                   for (i=0; i<N_Node; ++i) {
7809                      resi[i][c] = (int)fc[rowofnode[node[i]]];
7810                   }
7811                   break;
7812                case SUMA_int:
7813                   ic = (int *)SDSET_VEC(dset,icol);
7814                   for (i=0; i<N_Node; ++i) {
7815                      resi[i][c] = (int)ic[rowofnode[node[i]]];
7816                   }
7817                   break;
7818                case SUMA_short:
7819                   sc = (short *)SDSET_VEC(dset,icol);
7820                   for (i=0; i<N_Node; ++i) {
7821                      resi[i][c] = (int)sc[rowofnode[node[i]]];
7822                   }
7823                   break;
7824                case SUMA_byte:
7825                   bc = (byte *)SDSET_VEC(dset,icol);
7826                   for (i=0; i<N_Node; ++i) {
7827                      resi[i][c] = (int)bc[rowofnode[node[i]]];
7828                   }
7829                   break;
7830                default:
7831                   SUMA_S_Err("Type not supported."
7832                              "Memory leak now present");
7833                   SUMA_RETURN(NULL);
7834             }
7835          } /* for each column */
7836          resv = (void **)resi;
7837          break;
7838       case SUMA_short:
7839          resd=NULL; ress=NULL; ress=NULL; ress=NULL; resb=NULL;
7840          ress = (short**)SUMA_calloc(N_Node, sizeof(short*));
7841          for (i=0; i<N_Node; ++i) {
7842             if (!(ress[i] = (short*)SUMA_calloc(nind, sizeof(short)))) {
7843                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7844             }
7845          }
7846          for (c=0; c<nind; ++c) { /* for each column */
7847             if (ind) icol = ind[c];
7848             else icol = c;
7849             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
7850             switch (SUMA_ColType2TypeCast(
7851                            SUMA_TypeOfDsetColNumb(dset, icol))) {
7852                case SUMA_double:
7853                   dc = (double *)SDSET_VEC(dset,icol);
7854                   for (i=0; i<N_Node; ++i) {
7855                      ress[i][c] = (short)dc[rowofnode[node[i]]];
7856                   }
7857                   break;
7858                case SUMA_float:
7859                   fc = (float *)SDSET_VEC(dset,icol);
7860                   for (i=0; i<N_Node; ++i) {
7861                      ress[i][c] = (short)fc[rowofnode[node[i]]];
7862                   }
7863                   break;
7864                case SUMA_int:
7865                   ic = (int *)SDSET_VEC(dset,icol);
7866                   for (i=0; i<N_Node; ++i) {
7867                      ress[i][c] = (short)ic[rowofnode[node[i]]];
7868                   }
7869                   break;
7870                case SUMA_short:
7871                   sc = (short *)SDSET_VEC(dset,icol);
7872                   for (i=0; i<N_Node; ++i) {
7873                      ress[i][c] = (short)sc[rowofnode[node[i]]];
7874                   }
7875                   break;
7876                case SUMA_byte:
7877                   bc = (byte *)SDSET_VEC(dset,icol);
7878                   for (i=0; i<N_Node; ++i) {
7879                      ress[i][c] = (short)bc[rowofnode[node[i]]];
7880                   }
7881                   break;
7882                default:
7883                   SUMA_S_Err("Type not supported."
7884                              "Memory leak now present");
7885                   SUMA_RETURN(NULL);
7886             }
7887          } /* for each column */
7888          resv = (void **)ress;
7889          break;
7890       case SUMA_byte:
7891          resd=NULL; resb=NULL; resb=NULL; resb=NULL; resb=NULL;
7892          resb = (byte**)SUMA_calloc(N_Node, sizeof(byte*));
7893          for (i=0; i<N_Node; ++i) {
7894             if (!(resb[i] = (byte*)SUMA_calloc(nind, sizeof(byte)))) {
7895                SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(resv);
7896             }
7897          }
7898          for (c=0; c<nind; ++c) { /* for each column */
7899             if (ind) icol = ind[c];
7900             else icol = c;
7901             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
7902             switch (SUMA_ColType2TypeCast(
7903                            SUMA_TypeOfDsetColNumb(dset, icol))) {
7904                case SUMA_double:
7905                   dc = (double *)SDSET_VEC(dset,icol);
7906                   for (i=0; i<N_Node; ++i) {
7907                      resb[i][c] = (byte)dc[rowofnode[node[i]]];
7908                   }
7909                   break;
7910                case SUMA_float:
7911                   fc = (float *)SDSET_VEC(dset,icol);
7912                   for (i=0; i<N_Node; ++i) {
7913                      resb[i][c] = (byte)fc[rowofnode[node[i]]];
7914                   }
7915                   break;
7916                case SUMA_int:
7917                   ic = (int *)SDSET_VEC(dset,icol);
7918                   for (i=0; i<N_Node; ++i) {
7919                      resb[i][c] = (byte)ic[rowofnode[node[i]]];
7920                   }
7921                   break;
7922                case SUMA_short:
7923                   sc = (short *)SDSET_VEC(dset,icol);
7924                   for (i=0; i<N_Node; ++i) {
7925                      resb[i][c] = (byte)sc[rowofnode[node[i]]];
7926                   }
7927                   break;
7928                case SUMA_byte:
7929                   bc = (byte *)SDSET_VEC(dset,icol);
7930                   for (i=0; i<N_Node; ++i) {
7931                      resb[i][c] = (byte)bc[rowofnode[node[i]]];
7932                   }
7933                   break;
7934                default:
7935                   SUMA_S_Err("Type not supported."
7936                              "Memory leak now present");
7937                   SUMA_RETURN(NULL);
7938             }
7939          } /* for each column */
7940          resv = (void **)resb;
7941          break;
7942       default:
7943          SUMA_SL_Err("Bad otype, why here?"); SUMA_RETURN(resv);
7944          break;
7945    } /* switch on type of output */
7946 
7947    *N_ret =  nind;
7948    if (rowofnode) SUMA_free(rowofnode); rowofnode = NULL;
7949 
7950    SUMA_RETURN(resv);
7951 }
7952 
7953 /*!
7954    Reverse of   SUMA_Dset2VecArray
7955 */
SUMA_VecArray2Dset(void ** resv,SUMA_DSET * usethisdset,int * ind,int nind,int * node,int N_Node,int iNodeMax,SUMA_VARTYPE tp)7956 SUMA_DSET *SUMA_VecArray2Dset(void **resv,
7957                         SUMA_DSET *usethisdset,
7958                         int *ind, int nind,
7959                         int *node, int N_Node,
7960                         int iNodeMax,
7961                         SUMA_VARTYPE tp)
7962 {
7963    static char FuncName[]={"SUMA_VecArray2Dset"};
7964    double **resd = NULL, *dc=NULL;
7965    float **resf = NULL, *fc=NULL;
7966    int **resi=NULL, icol=0, i, c, *ic=NULL;
7967    short **ress=NULL, *sc=NULL;
7968    byte **resb=NULL, *bc=NULL;
7969    int *rowofnode=NULL;
7970    double range[2];
7971    SUMA_DSET *dset=NULL;
7972 
7973    SUMA_Boolean LocalHead = NOPE;
7974 
7975    SUMA_ENTRY;
7976 
7977    if (!usethisdset) {
7978       SUMA_S_Err("Not ready to create a new dset from scratch");
7979    } else {
7980       dset = usethisdset;  /* put the stuff in here */
7981    }
7982 
7983    if (!dset || !dset->dnel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(dset); }
7984    rowofnode = SUMA_CreateNodeIndexToRowIndexMap(dset, iNodeMax, range);
7985 
7986    if (!node) {
7987       node = SDSET_NODE_INDEX_COL(dset);
7988       N_Node = SDSET_VECLEN(dset);
7989    } else {
7990       /* make sure node indices do not exceed dset range */
7991       for (i=0; i<N_Node; ++i) {
7992          if (ind[i] > (int)range[1] || ind[i] < (int)range[0]) {
7993             SUMA_S_Err("Node indices out or range");
7994             SUMA_RETURN(dset);
7995          }
7996       }
7997    }
7998    if (!node) {
7999       SUMA_S_Err("Nothing to work with");
8000       SUMA_RETURN(dset);
8001    }
8002    if (!ind) {
8003       nind = SDSET_VECNUM(dset);
8004    }
8005    if (tp == SUMA_complex) {
8006       SUMA_S_Err("Complex type not supported");
8007       SUMA_RETURN(dset);
8008    }
8009    if ( tp != SUMA_float &&
8010         tp != SUMA_double &&
8011         tp != SUMA_int &&
8012         tp != SUMA_short &&
8013         tp != SUMA_byte ) { SUMA_SL_Err("Bad otype"); SUMA_RETURN(dset); }
8014 
8015    if (nind <= 0) {
8016       SUMA_SL_Err("no columns selected"); SUMA_RETURN(dset);
8017    }
8018    if (nind > SDSET_VECNUM(dset)) {
8019       SUMA_SL_Err("More columns than in dset"); SUMA_RETURN(dset);
8020    }
8021    switch (tp) {
8022       case SUMA_double:
8023          resd=NULL; resf=NULL; resi=NULL; ress=NULL; resb=NULL;
8024          resd = (double**)resv;
8025          for (c=0; c<nind; ++c) { /* for each column */
8026             if (ind) icol = ind[c];
8027             else icol = c;
8028             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
8029             switch (SUMA_ColType2TypeCast(
8030                            SUMA_TypeOfDsetColNumb(dset, icol))) {
8031                case SUMA_double:
8032                   dc = (double *)SDSET_VEC(dset,icol);
8033                   for (i=0; i<N_Node; ++i) {
8034                      dc[rowofnode[node[i]]] = (double)resd[i][c];
8035                   }
8036                   break;
8037                case SUMA_float:
8038                   fc = (float *)SDSET_VEC(dset,icol);
8039                   for (i=0; i<N_Node; ++i) {
8040                      fc[rowofnode[node[i]]] = (float)resd[i][c];
8041                   }
8042                   break;
8043                case SUMA_int:
8044                   ic = (int *)SDSET_VEC(dset,icol);
8045                   for (i=0; i<N_Node; ++i) {
8046                      ic[rowofnode[node[i]]] = (int)resd[i][c];
8047                   }
8048                   break;
8049                case SUMA_short:
8050                   sc = (short *)SDSET_VEC(dset,icol);
8051                   for (i=0; i<N_Node; ++i) {
8052                      sc[rowofnode[node[i]]] = (short)resd[i][c];
8053                   }
8054                   break;
8055                case SUMA_byte:
8056                   bc = (byte *)SDSET_VEC(dset,icol);
8057                   for (i=0; i<N_Node; ++i) {
8058                      bc[rowofnode[node[i]]] = (byte)resd[i][c];
8059                   }
8060                   break;
8061                default:
8062                   SUMA_S_Err("Type not supported."
8063                              "Memory leak now present");
8064                   SUMA_RETURN(NULL);
8065             }
8066          } /* for each column */
8067          break;
8068 
8069       case SUMA_float:
8070          resd=NULL; resf=NULL; resi=NULL; ress=NULL; resb=NULL;
8071          resf = (float**)resv;
8072          for (c=0; c<nind; ++c) { /* for each column */
8073             if (ind) icol = ind[c];
8074             else icol = c;
8075             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
8076             switch (SUMA_ColType2TypeCast(
8077                            SUMA_TypeOfDsetColNumb(dset, icol))) {
8078                case SUMA_double:
8079                   dc = (double *)SDSET_VEC(dset,icol);
8080                   for (i=0; i<N_Node; ++i) {
8081                      dc[rowofnode[node[i]]] = (double)resf[i][c];
8082                   }
8083                   break;
8084                case SUMA_float:
8085                   fc = (float *)SDSET_VEC(dset,icol);
8086                   for (i=0; i<N_Node; ++i) {
8087                      fc[rowofnode[node[i]]] = (float)resf[i][c];
8088                   }
8089                   break;
8090                case SUMA_int:
8091                   ic = (int *)SDSET_VEC(dset,icol);
8092                   for (i=0; i<N_Node; ++i) {
8093                      ic[rowofnode[node[i]]] = (int)resf[i][c];
8094                   }
8095                   break;
8096                case SUMA_short:
8097                   sc = (short *)SDSET_VEC(dset,icol);
8098                   for (i=0; i<N_Node; ++i) {
8099                      sc[rowofnode[node[i]]] = (short)resf[i][c];
8100                   }
8101                   break;
8102                case SUMA_byte:
8103                   bc = (byte *)SDSET_VEC(dset,icol);
8104                   for (i=0; i<N_Node; ++i) {
8105                      bc[rowofnode[node[i]]] = (byte)resf[i][c];
8106                   }
8107                   break;
8108                default:
8109                   SUMA_S_Err("Type not supported."
8110                              "Memory leak now present");
8111                   SUMA_RETURN(NULL);
8112             }
8113          } /* for each column */
8114          break;
8115       case SUMA_int:
8116          resd=NULL; resi=NULL; resi=NULL; ress=NULL; resb=NULL;
8117          resi = (int **)resv;
8118          for (c=0; c<nind; ++c) { /* for each column */
8119             if (ind) icol = ind[c];
8120             else icol = c;
8121             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
8122             switch (SUMA_ColType2TypeCast(
8123                            SUMA_TypeOfDsetColNumb(dset, icol))) {
8124                case SUMA_double:
8125                   dc = (double *)SDSET_VEC(dset,icol);
8126                   for (i=0; i<N_Node; ++i) {
8127                      dc[rowofnode[node[i]]] = (double)resi[i][c];
8128                   }
8129                   break;
8130                case SUMA_float:
8131                   fc = (float *)SDSET_VEC(dset,icol);
8132                   for (i=0; i<N_Node; ++i) {
8133                      fc[rowofnode[node[i]]] = (float)resi[i][c];
8134                   }
8135                   break;
8136                case SUMA_int:
8137                   ic = (int *)SDSET_VEC(dset,icol);
8138                   for (i=0; i<N_Node; ++i) {
8139                      ic[rowofnode[node[i]]] = (int)resi[i][c];
8140                   }
8141                   break;
8142                case SUMA_short:
8143                   sc = (short *)SDSET_VEC(dset,icol);
8144                   for (i=0; i<N_Node; ++i) {
8145                      sc[rowofnode[node[i]]] = (short)resi[i][c];
8146                   }
8147                   break;
8148                case SUMA_byte:
8149                   bc = (byte *)SDSET_VEC(dset,icol);
8150                   for (i=0; i<N_Node; ++i) {
8151                      bc[rowofnode[node[i]]] = (byte)resi[i][c];
8152                   }
8153                   break;
8154                default:
8155                   SUMA_S_Err("Type not supported."
8156                              "Memory leak now present");
8157                   SUMA_RETURN(NULL);
8158             }
8159          } /* for each column */
8160          break;
8161       case SUMA_short:
8162          resd=NULL; ress=NULL; ress=NULL; ress=NULL; resb=NULL;
8163          ress = (short **)resv;
8164          for (c=0; c<nind; ++c) { /* for each column */
8165             if (ind) icol = ind[c];
8166             else icol = c;
8167             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
8168             switch (SUMA_ColType2TypeCast(
8169                            SUMA_TypeOfDsetColNumb(dset, icol))) {
8170                case SUMA_double:
8171                   dc = (double *)SDSET_VEC(dset,icol);
8172                   for (i=0; i<N_Node; ++i) {
8173                      dc[rowofnode[node[i]]] = (double)ress[i][c];
8174                   }
8175                   break;
8176                case SUMA_float:
8177                   fc = (float *)SDSET_VEC(dset,icol);
8178                   for (i=0; i<N_Node; ++i) {
8179                      fc[rowofnode[node[i]]] = (float)ress[i][c];
8180                   }
8181                   break;
8182                case SUMA_int:
8183                   ic = (int *)SDSET_VEC(dset,icol);
8184                   for (i=0; i<N_Node; ++i) {
8185                      ic[rowofnode[node[i]]] = (int)ress[i][c];
8186                   }
8187                   break;
8188                case SUMA_short:
8189                   sc = (short *)SDSET_VEC(dset,icol);
8190                   for (i=0; i<N_Node; ++i) {
8191                      sc[rowofnode[node[i]]] = (short)ress[i][c];
8192                   }
8193                   break;
8194                case SUMA_byte:
8195                   bc = (byte *)SDSET_VEC(dset,icol);
8196                   for (i=0; i<N_Node; ++i) {
8197                      bc[rowofnode[node[i]]] = (byte)ress[i][c];
8198                   }
8199                   break;
8200                default:
8201                   SUMA_S_Err("Type not supported."
8202                              "Memory leak now present");
8203                   SUMA_RETURN(NULL);
8204             }
8205          } /* for each column */
8206          break;
8207       case SUMA_byte:
8208          resd=NULL; resb=NULL; resb=NULL; resb=NULL; resb=NULL;
8209          resb = (byte**)resv;
8210          for (c=0; c<nind; ++c) { /* for each column */
8211             if (ind) icol = ind[c];
8212             else icol = c;
8213             dc=NULL; fc=NULL; ic=NULL; sc=NULL; bc=NULL;
8214             switch (SUMA_ColType2TypeCast(
8215                            SUMA_TypeOfDsetColNumb(dset, icol))) {
8216                case SUMA_double:
8217                   dc = (double *)SDSET_VEC(dset,icol);
8218                   for (i=0; i<N_Node; ++i) {
8219                      dc[rowofnode[node[i]]] = (double)resb[i][c];
8220                   }
8221                   break;
8222                case SUMA_float:
8223                   fc = (float *)SDSET_VEC(dset,icol);
8224                   for (i=0; i<N_Node; ++i) {
8225                      fc[rowofnode[node[i]]] = (float)resb[i][c];
8226                   }
8227                   break;
8228                case SUMA_int:
8229                   ic = (int *)SDSET_VEC(dset,icol);
8230                   for (i=0; i<N_Node; ++i) {
8231                      ic[rowofnode[node[i]]] = (int)resb[i][c];
8232                   }
8233                   break;
8234                case SUMA_short:
8235                   sc = (short *)SDSET_VEC(dset,icol);
8236                   for (i=0; i<N_Node; ++i) {
8237                      sc[rowofnode[node[i]]] = (short)resb[i][c];
8238                   }
8239                   break;
8240                case SUMA_byte:
8241                   bc = (byte *)SDSET_VEC(dset,icol);
8242                   for (i=0; i<N_Node; ++i) {
8243                      bc[rowofnode[node[i]]] = (byte)resb[i][c];
8244                   }
8245                   break;
8246                default:
8247                   SUMA_S_Err("Type not supported."
8248                              "Memory leak now present");
8249                   SUMA_RETURN(NULL);
8250             }
8251          } /* for each column */
8252          break;
8253       default:
8254          SUMA_SL_Err("Bad otype, why here?"); SUMA_RETURN(dset);
8255          break;
8256    } /* switch on type of output */
8257 
8258    if (rowofnode) SUMA_free(rowofnode); rowofnode = NULL;
8259 
8260    SUMA_RETURN(dset);
8261 }
8262 
8263 /* returns the value at a paricular column and particular
8264    node in double format.
8265    If you know the maximum number of nodes forming the domain
8266    of the dset, typically SO->N_Node then pass it for speed.
8267    Otherwise, pass -1 for last param.
8268 */
SUMA_GetDsetNodeValInCol2(SUMA_DSET * dset,int ind,int node,int Max_Node_Index)8269 double SUMA_GetDsetNodeValInCol2(SUMA_DSET *dset, int ind,
8270                                  int node, int Max_Node_Index)
8271 {
8272    int ival = SUMA_GetNodeRow_FromNodeIndex_eng (dset, node, Max_Node_Index);
8273    if (ival < 0) return(0.0);
8274    else return( SUMA_GetDsetValInCol2( dset, ind, ival ) );
8275 }
8276 /*!
8277    \brief Returns the value from column ind, row ival
8278    The value is stored in a double variable
8279    0.0  in case of error.
8280    \sa SUMA_GetDsetValInCol and SUMA_GetDsetNodeValInCol2
8281 */
SUMA_GetDsetValInCol2(SUMA_DSET * dset,int ind,int ival)8282 double SUMA_GetDsetValInCol2(SUMA_DSET *dset, int ind, int ival)
8283 {
8284    static char FuncName[]={"SUMA_GetDsetValInCol2"};
8285    SUMA_COL_TYPE ctp;
8286    SUMA_VARTYPE vtp;
8287    byte *bv = NULL;
8288    double *dv = NULL, dval = 0.0;
8289    float *fv=NULL;
8290    int *iv = NULL;
8291    char **cv = NULL;
8292    complex *cmv=NULL;
8293    SUMA_Boolean LocalHead = NOPE;
8294 
8295    SUMA_ENTRY;
8296 
8297    if (!dset || !dset->dnel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(0.0); }
8298 
8299    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
8300       SUMA_SL_Err("Bad column index");
8301       SUMA_RETURN(0.0);
8302    }
8303 
8304    if (ival < 0) {
8305       SUMA_SL_Err("ival < 0");
8306       SUMA_RETURN(0.0);
8307    }
8308    if (ival >= SDSET_VECLEN(dset)) {
8309       SUMA_SL_Err("ival too large");
8310       SUMA_RETURN(0.0);
8311    }
8312 
8313    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
8314 
8315    vtp = SUMA_ColType2TypeCast (ctp) ;
8316    switch (vtp) {
8317       case SUMA_byte:
8318          bv = (byte *)dset->dnel->vec[ind];
8319          dval = (double)bv[ival];
8320          break;
8321       case SUMA_int:
8322          iv = (int *)dset->dnel->vec[ind];
8323          dval = (double)iv[ival];
8324          break;
8325       case SUMA_float:
8326          fv = (float *)dset->dnel->vec[ind];
8327          dval = (double)fv[ival];
8328          break;
8329       case SUMA_double:
8330          dv = (double *)dset->dnel->vec[ind];
8331          dval = (double)dv[ival];
8332          break;
8333       case SUMA_complex:
8334          cmv = (complex *)dset->dnel->vec[ind];
8335          dval = CABS(cmv[ival]);
8336          break;
8337       default:
8338          SUMA_SL_Err("This type is not supported.\n");
8339          SUMA_RETURN(0.0);
8340          break;
8341    }
8342 
8343    SUMA_RETURN(dval);
8344 }
8345 
8346 /*!
8347    \brief Returns the value from column ind, row ival
8348    The value is stored in a double variable and a string
8349    version is returned. NULL in case of error. You are to free
8350    the returned string.
8351    \sa SUMA_GetDsetValInCol2
8352 */
SUMA_GetDsetValInCol(SUMA_DSET * dset,int ind,int ival,double * dval)8353 char * SUMA_GetDsetValInCol(SUMA_DSET *dset, int ind, int ival, double *dval)
8354 {
8355    static char FuncName[]={"SUMA_GetDsetValInCol"};
8356    SUMA_COL_TYPE ctp;
8357    SUMA_VARTYPE vtp;
8358    byte *bv = NULL;
8359    short *shv=NULL;
8360    double *dv = NULL;
8361    float *fv=NULL;
8362    int *iv = NULL;
8363    char  *str=NULL, **cv = NULL;
8364    complex *cmv=NULL;
8365    SUMA_Boolean LocalHead = NOPE;
8366 
8367    SUMA_ENTRY;
8368 
8369    if (!dset->dnel || !dval) { SUMA_SL_Err("NULL input"); SUMA_RETURN(NULL); }
8370 
8371    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
8372       SUMA_SL_Err("Bad index");
8373       SUMA_RETURN(NULL);
8374    }
8375 
8376    if (ival >= SDSET_VECLEN(dset)) {
8377       SUMA_SL_Err("ival too large");
8378       SUMA_RETURN(NULL);
8379    }
8380 
8381    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
8382 
8383    vtp = SUMA_ColType2TypeCast (ctp) ;
8384    if (LocalHead) {
8385       char stmp[1000]={""};
8386       snprintf(stmp, 998,
8387             "%s:\n"
8388             "dset %p, label %s, filen %s\n"
8389             "ind %d, ival %d\n"
8390             "ctp %d, vtp %d (b %d, i %d, f %d, d %d)\n",
8391             FuncName,
8392             dset, SDSET_LABEL(dset), SDSET_FILENAME(dset),
8393             ind, ival,
8394             ctp, vtp, SUMA_byte, SUMA_int, SUMA_float, SUMA_double);
8395       SUMA_LH("%s", stmp);
8396    }
8397    switch (vtp) {
8398       case SUMA_byte:
8399          str = (char *)SUMA_malloc(50*sizeof(char));
8400          bv = (byte *)dset->dnel->vec[ind];
8401          sprintf(str,"%d",bv[ival]);
8402          *dval = (double)bv[ival];
8403          break;
8404       case SUMA_short:
8405          str = (char *)SUMA_malloc(50*sizeof(char));
8406          shv = (short *)dset->dnel->vec[ind];
8407          sprintf(str,"%d",shv[ival]);
8408          *dval = (double)shv[ival];
8409          break;
8410       case SUMA_int:
8411          str = (char *)SUMA_malloc(50*sizeof(char));
8412          iv = (int *)dset->dnel->vec[ind];
8413          sprintf(str,"%d",iv[ival]);
8414          *dval = (double)iv[ival];
8415          break;
8416       case SUMA_float:
8417          str = (char *)SUMA_malloc(50*sizeof(char));
8418          fv = (float *)dset->dnel->vec[ind];
8419          sprintf(str,"%f",fv[ival]);
8420          *dval = (double)fv[ival];
8421          break;
8422       case SUMA_double:
8423          str = (char *)SUMA_malloc(50*sizeof(char));
8424          dv = (double *)dset->dnel->vec[ind];
8425          sprintf(str,"%f",dv[ival]);
8426          *dval = (double)dv[ival];
8427          break;
8428       case SUMA_string:
8429          cv = (char **)dset->dnel->vec[ind];
8430          *dval = 0.0;
8431          str = SUMA_copy_string((char*)cv[ival]);
8432          break;
8433       case SUMA_complex:
8434          str = (char *)SUMA_malloc(100*sizeof(char));
8435          cmv = (complex *)dset->dnel->vec[ind];
8436          sprintf(str,"%f i%f",cmv[ival].r, cmv[ival].i);
8437          *dval = CABS(cmv[ival]);
8438          break;
8439       default:
8440          SUMA_SL_Err("This type is not supported yet.\n");
8441          SUMA_RETURN(NULL);
8442          break;
8443    }
8444 
8445    SUMA_LH("%s",str);
8446    SUMA_RETURN(str);
8447 }
8448 
8449 /*!
8450    \brief Copies the contents of a NI_element column into
8451    a new float vector
8452    V = SUMA_Col2Float (nel,  ind,  FilledOnly);
8453 
8454    \param nel (NI_element *)
8455    \param ind (int) index of column to be copied
8456    \param FilledOnly (int) 0 = allocate for and read all of the column
8457                               (up to nel->vec_len)
8458                            1 = allocate for and read the filled portion
8459                                of the column (up to nel->vec_filled)
8460    \return V (float *) vector (allocated by the function) containing
8461                      the column's contents.
8462  */
SUMA_Col2Float(NI_element * nel,int ind,int FilledOnly)8463 float * SUMA_Col2Float (NI_element *nel, int ind, int FilledOnly)
8464 {
8465    static char FuncName[]={"SUMA_Col2Float"};
8466    int i = -1, N_read = -1, *iv = NULL;
8467    float *V=NULL, *fv = NULL;
8468    SUMA_COL_TYPE ctp;
8469    SUMA_VARTYPE vtp;
8470 
8471    SUMA_ENTRY;
8472 
8473    SUMA_SL_Err("Obsolete, check caller");
8474    SUMA_RETURN(NULL);
8475 
8476    if (!nel) { SUMA_RETURN(NULL); }
8477 
8478    if (ind < 0 || ind > nel->vec_num - 1) {
8479       SUMA_SL_Err("Bad index");
8480       SUMA_RETURN(NULL);
8481    }
8482 
8483    if (FilledOnly) {
8484       N_read = nel->vec_filled;
8485    } else {
8486       N_read = nel->vec_len;
8487    }
8488 
8489    ctp = SUMA_TypeOfColNumb(nel, ind);
8490 
8491    V = (float *)SUMA_calloc(N_read,sizeof(float));
8492    if (!V) { SUMA_SL_Crit("Failed to allocate for V."); SUMA_RETURN(NULL); }
8493    vtp = SUMA_ColType2TypeCast (ctp) ;
8494    switch (vtp) {
8495       case SUMA_int:
8496          iv = (int *)nel->vec[ind];
8497          for (i=0; i<N_read; ++i) V[i] = (float)iv[i];
8498          break;
8499       case SUMA_float:
8500          fv = (float *)nel->vec[ind];
8501          for (i=0; i<N_read; ++i) V[i] = fv[i];
8502          break;
8503       default:
8504          SUMA_SL_Err("This type is not supported.\n");
8505          SUMA_free(V);
8506          SUMA_RETURN(NULL);
8507          break;
8508    }
8509 
8510    SUMA_RETURN(V);
8511 }
8512 
8513 /*
8514 given a 1D filename with one column of node indices, create a binary mask for
8515 a surface of N_Node nodes.
8516 if omask is specified, then omask is modified and returned per the operator "oper"
8517 oper can be "or" (or "") or "and"
8518 */
SUMA_load_1D_n_mask(char * name,int N_Node,byte * omask,const char * oper,int * N_inmask)8519 byte *SUMA_load_1D_n_mask(char *name, int N_Node, byte *omask,
8520                           const char *oper, int *N_inmask)
8521 {
8522    static char FuncName[]={"SUMA_load_1D_n_mask"};
8523    int kk;
8524    float *far=NULL;
8525    MRI_IMAGE * im=NULL;
8526    byte *out=NULL;
8527 
8528    SUMA_ENTRY;
8529 
8530    if (N_inmask) *N_inmask = -1;
8531    if (!name) {
8532       SUMA_S_Err("NULL input");
8533       SUMA_RETURN(NULL);
8534    }
8535 
8536    im = mri_read_1D (name);
8537    if (!im) {
8538       SUMA_S_Err("Failed to read mask file");
8539       SUMA_RETURN(NULL);
8540    }
8541    far = MRI_FLOAT_PTR(im);
8542 
8543    if (!im->nx) {
8544       SUMA_S_Err("Empty file");
8545       goto CLEANUP;
8546    }
8547 
8548    if (im->ny != 1 ) {
8549       SUMA_S_Err("nmask file must have\n"
8550                   " 1 column.");
8551       fprintf(SUMA_STDERR,"Have %d columns!\n", im->ny);
8552       goto CLEANUP;
8553    }
8554    if (!omask) {
8555       out = (byte *)SUMA_calloc(N_Node, sizeof(byte));
8556       if (!out) {
8557          SUMA_S_Crit("Failed to allocate"); goto CLEANUP;
8558       }
8559    } else {
8560       out = omask;
8561    }
8562    if (omask) {
8563       if (!oper || oper[0] == '\0' || (oper && strstr(oper, "or"))) {
8564          for (kk=0; kk<im->nx; ++kk) {
8565             if (far[kk] < 0 || far[kk] >= N_Node) {
8566                SUMA_S_Err( "Bad indices in mask file.\n"
8567                            "Values either < 0 or >= number\n"
8568                            "of nodes in surface.");
8569                if (out && out != omask) SUMA_free(out); out = NULL;
8570                goto CLEANUP;
8571             }
8572             out[(int)far[kk]] = 1;
8573          }
8574       } else if (oper && strstr(oper, "and")) {
8575          for (kk=0; kk<im->nx; ++kk) {
8576             if (far[kk] < 0 || far[kk] >= N_Node) {
8577                SUMA_S_Err( "Bad indices in mask file.\n"
8578                            "Values either < 0 or >= number\n"
8579                            "of nodes in surface.");
8580                if (out && out != omask) SUMA_free(out); out = NULL;
8581                goto CLEANUP;
8582             }
8583             out[(int)far[kk]] += 1;
8584             if (out[(int)far[kk]] > 2) {
8585                SUMA_S_Err("input mask is not binary!\n");
8586                if (out && out != omask) SUMA_free(out); out = NULL;
8587                goto CLEANUP;
8588             }
8589          }
8590          for (kk=0; kk < N_Node; ++kk) {
8591             if (out[kk] > 1) out[kk] = 1;
8592             else out[kk] = 0;
8593          }
8594       } else {
8595          SUMA_S_Err("Bad operator\n");
8596          if (out && out != omask) SUMA_free(out); out = NULL;
8597          goto CLEANUP;
8598 
8599       }
8600    } else {
8601       for (kk=0; kk<im->nx; ++kk) {
8602          if (far[kk] < 0 || far[kk] >= N_Node) {
8603             SUMA_S_Err( "Bad indices in mask file.\n"
8604                         "Values either < 0 or >= number\n"
8605                         "of nodes in surface.");
8606             if (out && out != omask) SUMA_free(out); out = NULL;
8607             goto CLEANUP;
8608          }
8609          out[(int)far[kk]] = 1;
8610       }
8611    }
8612 
8613    if (N_inmask) {
8614       *N_inmask = 0;
8615       for (kk=0; kk<N_Node; ++kk) if (out[kk]) ++(*N_inmask);
8616    }
8617 
8618    CLEANUP:
8619    mri_free(im); im = NULL;
8620    SUMA_RETURN(out);
8621 }
8622 
8623 /*
8624 given a 1D filename with one column of 0s and non zeros, create a binary mask for
8625 a surface of N_Node nodes.
8626 if omask is specified, then omask is modified and returned per the operator "oper"
8627 oper can be "or" (or "") or "and"
8628 */
SUMA_load_1D_b_mask(char * name,int N_Node,byte * omask,const char * oper,int * N_inmask)8629 byte *SUMA_load_1D_b_mask(char *name, int N_Node, byte *omask,
8630                           const char *oper, int *N_inmask)
8631 {
8632    static char FuncName[]={"SUMA_load_1D_b_mask"};
8633    int kk;
8634    float *far=NULL;
8635    MRI_IMAGE * im=NULL;
8636    byte *out=NULL;
8637 
8638    SUMA_ENTRY;
8639 
8640    if (N_inmask) *N_inmask = -1;
8641 
8642    if (!name) {
8643       SUMA_S_Err("NULL input");
8644       SUMA_RETURN(NULL);
8645    }
8646 
8647    im = mri_read_1D (name);
8648    if (!im) {
8649       SUMA_S_Err("Failed to read mask file");
8650       SUMA_RETURN(NULL);
8651    }
8652    far = MRI_FLOAT_PTR(im);
8653 
8654    if (!im->nx) {
8655       SUMA_S_Err("Empty file");
8656       goto CLEANUP;
8657    }
8658    if (im->ny != 1 ) {
8659       SUMA_S_Err("nmask file must have\n"
8660                   " 1 column.");
8661       fprintf(SUMA_STDERR,"Have %d columns!\n", im->ny);
8662       goto CLEANUP;
8663    }
8664 
8665    if (im->nx != N_Node) {
8666       SUMA_S_Err( "Number of rows in mask file is not \n"
8667                   "equal to number of nodes in surface.\n");
8668       goto CLEANUP;
8669    }
8670 
8671    if (!omask) {
8672       out = (byte *)SUMA_calloc(N_Node, sizeof(byte));
8673       if (!out) {
8674          SUMA_S_Crit("Failed to allocate"); goto CLEANUP;
8675       }
8676    } else {
8677       out = omask;
8678    }
8679 
8680    if (omask) {
8681       if (!oper || oper[0] == '\0' || (oper && strstr(oper, "or"))) {
8682          for (kk=0; kk<im->nx; ++kk) {
8683             if ((int)far[kk]) {
8684                out[kk] = 1;
8685                /* fprintf (SUMA_STDERR,"%d   ", kk);  */
8686             }
8687          }
8688       } else if (oper && strstr(oper, "and")) {
8689          for (kk=0; kk<im->nx; ++kk) {
8690             if ((int)far[kk]&&out[kk]) out[kk] = 1;
8691             else out[kk] = 0;
8692          }
8693       } else {
8694          SUMA_S_Err("Bad operator\n");
8695          if (out && out != omask) SUMA_free(out); out = NULL;
8696          goto CLEANUP;
8697 
8698       }
8699    } else {
8700       for (kk=0; kk<im->nx; ++kk) {
8701          if ((int)far[kk]) { out[kk] = 1; }
8702       }
8703    }
8704 
8705    if (N_inmask) {
8706       *N_inmask = 0;
8707       for (kk=0; kk<N_Node; ++kk) if (out[kk]) ++(*N_inmask);
8708    }
8709    CLEANUP:
8710    mri_free(im); im = NULL;
8711    SUMA_RETURN(out);
8712 }
8713 
SUMA_get_c_mask(char * mask,int N_Node,byte * omask,const char * oper,int * N_inmask)8714 byte *SUMA_get_c_mask(char *mask, int N_Node, byte *omask,
8715                       const char *oper, int *N_inmask)
8716 {
8717    static char FuncName[]={"SUMA_get_c_mask"};
8718    int    clen, ninmask, i, kk;
8719 	char * cmd;
8720    byte *bmask=NULL, *out=NULL;
8721 
8722    SUMA_ENTRY;
8723 
8724    if (N_inmask) *N_inmask = -1;
8725    if (!mask) {
8726       SUMA_S_Err("NULL input");
8727       SUMA_RETURN(bmask);
8728    }
8729 
8730    clen = strlen( mask );
8731 	/* save original cmask command, as EDT_calcmask() is destructive */
8732 	cmd = (char *)calloc((clen + 1), sizeof(char));
8733 	strcpy( cmd,  mask);
8734 
8735 
8736    bmask = EDT_calcmask( cmd, &ninmask, N_Node );
8737 
8738 	free( cmd );		cmd = NULL;	   /* free EDT_calcmask() string */
8739 
8740 	if ( bmask == NULL ) {
8741 	   SUMA_S_Err("Failed to compute mask from -cmask option");
8742       SUMA_RETURN(NULL);
8743 	}
8744 
8745    #if 0 /* a little check */
8746    for (kk=0; kk<ninmask; ++kk) {
8747       if (bmask[kk]) fprintf(stderr," %d/%d %d\n", kk, ninmask, bmask[kk]);
8748    }
8749    #endif
8750 
8751 	if ( ninmask != N_Node ) {
8752 	   SUMA_S_Err("Input and cmask datasets do not have "
8753 		            "the same dimensions\n" );
8754 	   fprintf(SUMA_STDERR,"Have %d in mask and %d nodes\n", ninmask, N_Node);
8755       SUMA_free(bmask); bmask=NULL;
8756 	   SUMA_RETURN(NULL);
8757 	}
8758    if (!omask) {
8759       out = bmask;
8760    } else {
8761       out = omask;
8762       if (!oper || oper[0] == '\0' || (oper && strstr(oper, "or"))) {
8763          for (kk=0; kk<ninmask; ++kk) {
8764             if (bmask[kk]) {
8765                out[kk] = 1;
8766                /* fprintf (SUMA_STDERR,"%d   ", kk);  */
8767             }
8768          }
8769       } else if (oper && strstr(oper, "and")) {
8770          for (kk=0; kk<ninmask; ++kk) {
8771             if (bmask[kk]&&out[kk]) out[kk] = 1;
8772             else out[kk] = 0;
8773          }
8774       } else {
8775          SUMA_S_Err("Bad operator\n");
8776          if (out && out != omask) { SUMA_free(out); out = NULL; }
8777          else { if (out) SUMA_free(out); out = NULL; }
8778          goto CLEANUP;
8779       }
8780    }
8781 
8782    if (N_inmask) {
8783       *N_inmask = 0;
8784       for (kk=0; kk<N_Node; ++kk) if (out[kk]) ++(*N_inmask);
8785    }
8786 
8787    CLEANUP:
8788    if (bmask && out != bmask) free(bmask); bmask=NULL;
8789 
8790    SUMA_RETURN(out);
8791 }
8792 
8793 /*!
8794    \brief Load and combine all masks on command line
8795    mask = SUMA_load_all_command_masks(char *bmaskname, char *nmaskname, char *cmask, int N_Node, int *N_inmask);
8796    N_Node is the number of nodes on the recipient surface
8797    N_inmask will contain the number of nodes in the mask (if it is -1 then an error occurred)
8798    mask is a vector (N_Node) of 1 for nodes in the mask (N_inmask of them) and 0 for nodes not in mask.
8799 */
SUMA_load_all_command_masks(char * bmaskname,char * nmaskname,char * cmask,int N_Node,int * N_inmask)8800 byte * SUMA_load_all_command_masks(
8801    char *bmaskname, char *nmaskname,
8802    char *cmask, int N_Node, int *N_inmask)
8803 {
8804    static char FuncName[]={"SUMA_load_all_command_masks"};
8805    byte *nmask=NULL;
8806 
8807    SUMA_ENTRY;
8808 
8809    *N_inmask = -1;   /* indicates an error */
8810 
8811    if (bmaskname) {
8812       if (!(nmask = SUMA_load_1D_b_mask(
8813                         bmaskname, N_Node, nmask, "and", N_inmask))) {
8814          SUMA_S_Err("Failed loading mask");
8815          if (nmask) SUMA_free(nmask); nmask=NULL; SUMA_RETURN(nmask);
8816       }
8817    }
8818    if (cmask) {
8819       if (!(nmask = SUMA_get_c_mask(
8820                         cmask, N_Node, nmask, "and", N_inmask))) {
8821          SUMA_S_Err("Failed loading mask");
8822          if (nmask) SUMA_free(nmask); nmask=NULL; SUMA_RETURN(nmask);
8823       }
8824    }
8825    if (nmaskname) {
8826       if (!(nmask = SUMA_load_1D_n_mask(
8827                         nmaskname, N_Node, nmask, "and", N_inmask))) {
8828          SUMA_S_Err("Failed loading mask");
8829          if (nmask) SUMA_free(nmask); nmask=NULL; SUMA_RETURN(nmask);
8830       }
8831    }
8832 
8833 
8834    if (*N_inmask < 0)
8835       *N_inmask = 0; /* Remove error flag,
8836                         even if nmask is NULL (no mask to speak of) */
8837 
8838    SUMA_RETURN(nmask);
8839 }
8840 
8841 /*!
8842    \brief Create a byte * mask of indices in ind_list
8843    \param ind_list (int *) Pointer to vector of n_ind_list (node) indices
8844    \param N_ind_list (int)
8845    \param N_mask (int) length of returned byte mask. Values in ind_list >= N_mask will
8846                        generate a warning and will be ignored
8847    \param N_inmask (int *) Pointer to integer that will contain number of 1 values in bmask
8848                            that would be a number equal to N_ind_list if all values in ind_list are < N_mask
8849    \return bmask (byte *) the byte mask with bmask[j] = 1 where j is an int found in ind_list.
8850 */
SUMA_indexlist_2_bytemask(int * ind_list,int N_ind_list,int N_mask,int * N_inmask)8851 byte * SUMA_indexlist_2_bytemask(
8852       int *ind_list, int N_ind_list,
8853       int N_mask, int *N_inmask)
8854 {
8855    static char FuncName[]={"SUMA_indexlist_2_bytemask"};
8856    int i = 0, cnt, ign = 0;
8857    byte *bmask = NULL;
8858 
8859    SUMA_ENTRY;
8860 
8861    cnt = -1;
8862    if (!ind_list) {
8863       SUMA_S_Err("NULL ind_list");
8864       goto BYE;
8865    }
8866 
8867    if (!(bmask = (byte *)SUMA_calloc(N_mask, sizeof(byte)))) {
8868       SUMA_SL_Crit("Failed to allocate (macro)");
8869       goto BYE;
8870    }
8871 
8872    cnt = 0;
8873    for (i=0; i<N_ind_list; ++i) {
8874       if (ind_list[i] < N_mask) {
8875          bmask[ind_list[i]] = 1;
8876          ++cnt;
8877       } else {
8878          if (!ign) {
8879             SUMA_S_Warn("Values in ind_list exceed N_mask!\n");
8880          }
8881          ++ign;
8882       }
8883    }
8884 
8885    if (ign) {
8886       fprintf(SUMA_STDERR,
8887    "%s:   %d values in indexlist ignored because they are >= N_mask of %d\n",
8888          FuncName, ign, N_mask);
8889    }
8890 
8891    BYE:
8892    if (N_inmask) *N_inmask = cnt;
8893    SUMA_RETURN(bmask);
8894 }
8895 
SUMA_Meshbmask_2_IndexListbmask(byte * Mbmask,int N_Mbmask,int * ind_list,int N_ind_list,int * N_ILbmask)8896 byte * SUMA_Meshbmask_2_IndexListbmask(
8897    byte *Mbmask, int N_Mbmask, int *ind_list, int N_ind_list, int *N_ILbmask)
8898 {
8899    static char FuncName[]={"SUMA_Meshbmask_2_IndexListbmask"};
8900    int i = 0, cnt, ign = 0;
8901    byte *ILbmask = NULL;
8902 
8903    SUMA_ENTRY;
8904 
8905    cnt = -1;
8906    if (!ind_list) {
8907       SUMA_S_Err("NULL ind_list");
8908       goto BYE;
8909    }
8910 
8911    if (!(ILbmask = (byte *)SUMA_calloc(N_ind_list, sizeof(byte)))) {
8912       SUMA_SL_Crit("Failed to allocate (macro)");
8913       goto BYE;
8914    }
8915 
8916    if (!Mbmask) { /* default, take whole thing */
8917       memset(ILbmask, 1, sizeof(byte)*N_ind_list);
8918       cnt = N_ind_list;
8919       goto BYE;
8920    }
8921 
8922    for (i=0; i<N_ind_list; ++i) {
8923       if (ind_list[i] < N_Mbmask) {
8924          if (Mbmask[ind_list[i]]) {
8925             ILbmask[i]=1; ++cnt;
8926          }
8927       } else {
8928          if (!ign) {
8929             SUMA_S_Warn("Values in ind_list exceed N_mask!\n");
8930          }
8931          ++ign;
8932       }
8933    }
8934 
8935    if (ign) {
8936       fprintf(SUMA_STDERR,
8937    "%s:   %d values in indexlist ignored because they are >= N_mask of %d\n",
8938          FuncName, ign, N_Mbmask);
8939    }
8940 
8941    BYE:
8942    if (N_ILbmask) *N_ILbmask = cnt;
8943    SUMA_RETURN(ILbmask);
8944 }
8945 
8946 /*!
8947    \brief c = SUMA_DsetCol2FloatFullSortedColumn (
8948                         dset, ico, nmaskp, fillval,
8949                         N_Node, N_inmaskp, MergeMask);
8950            Returns a float copy 'c' column 'ico' in a dset
8951            If 'dset' is sparse, the copy is filled such that
8952            c[i] has the value for node i.
8953    \param dset (SUMA_DSET *) Dataset pointer
8954    \param ico (int) column desired from dset
8955    \param nmaskp (byte **) pointer to node mask vector.
8956 
8957                  If you have a node mask nmask (byte *) that
8958                  you want applied to 'c' then pass &nmask to
8959                  this function. nmask is internally modified
8960                  so that nmask[i] is set to 0 if node 'i' does
8961                  have entries in dset.
8962 
8963                  If you do not have a node mask (i.e. you want
8964                  to use all nodes) then you can set nmask = NULL
8965                  and pass &nmask to this function nonetheless.
8966                  When the function returns, it will have set
8967                  nmask to reflect the nodes present in dset.
8968 
8969                  The previous two conditions apply the first time
8970                  you are calling this function with a particular
8971                  sparse dset. For subsequent calls, your nmask
8972                  will not change, so you can pass NULL for nmaskp.
8973 
8974                  Note that if you specify no mask to begin with
8975                  and dset is not sparse, then  *nmaskp will
8976                  be NULL on return
8977    \param  fillval (float) value to put in c[i] where i is a node
8978                  not present in the dset.
8979    \param  N_Node (int) Total number of nodes in surface where dset
8980                         is defined
8981    \param  N_inmask (int *) To contain the total number of nodes in
8982                             *nmaskp. If nmaskp was set to NULL then
8983                             *N_inmask = -1
8984    \param MergeMask (SUMA_Boolean) A flag to indicate that node mask
8985                                    merger is needed. Set to YUP the
8986                                    first time you call this function
8987                                    for a particular dataset.
8988    \sa   SUMA_MakeSparseColumnFullSorted and   SUMA_DsetCol2Float
8989    \sa   SUMA_DsetCol2DoubleFullSortedColumn
8990 
8991    MAKE SURE YOU ALSO MODIFY Double version of this function when you make
8992    changes here
8993 */
SUMA_DsetCol2FloatFullSortedColumn(SUMA_DSET * dset,int ico,byte ** nmaskp,float fillval,int N_Node,int * N_inmask,SUMA_Boolean MergeMask)8994 float * SUMA_DsetCol2FloatFullSortedColumn(
8995             SUMA_DSET *dset, int ico, byte **nmaskp,
8996             float fillval, int N_Node, int *N_inmask,
8997             SUMA_Boolean MergeMask)
8998 {
8999    static char FuncName[]={"SUMA_DsetCol2FloatFullSortedColumn"};
9000    float *fin_orig = NULL;
9001    byte *locmask = NULL;
9002    byte *nmask = NULL;
9003    int n=0, N_nmask=0, jj=0;
9004    SUMA_Boolean LocalHead = NOPE;
9005 
9006    SUMA_ENTRY;
9007 
9008    if (nmaskp) nmask = *nmaskp;
9009    if (N_inmask) *N_inmask =  -1;
9010 
9011    /* get a float copy of the data column */
9012    fin_orig = SUMA_DsetCol2Float (dset, ico , 1);
9013    if (!fin_orig) {
9014       SUMA_SL_Crit("Failed to get copy of column. Woe to thee!");
9015       SUMA_RETURN(NULL);
9016    }
9017 
9018    /* make sure column is not sparse, one value per node */
9019    if (MergeMask) { /* masks may need merging */
9020       SUMA_LH( "Mask merger");
9021       locmask = NULL;
9022       if (!SUMA_MakeSparseColumnFullSorted(
9023                &fin_orig, SDSET_VECFILLED(dset), fillval,
9024                &locmask, dset, N_Node)) {
9025          SUMA_S_Err("Failed to get full column vector");
9026          SUMA_RETURN(NULL);
9027       }
9028       if (locmask) {
9029          SUMA_LH( "Something was filled in SUMA_MakeSparseColumnFullSorted\n" );
9030          /* something was filled in good old SUMA_MakeSparseColumnFullSorted */
9031          if (nmask) {   /* combine locmask with nmask */
9032             SUMA_LH( "Merging masks\n" );
9033             for (jj=0; jj < N_Node; ++jj) {
9034                if (nmask[jj] && !locmask[jj]) nmask[jj] = 0;
9035             }
9036          } else { nmask = locmask; }
9037       }
9038       if (nmask) {
9039          N_nmask = 0;
9040          for (n=0; n<N_Node; ++n) { if (nmask[n]) ++ N_nmask; }
9041          if (LocalHead)
9042             fprintf( SUMA_STDERR,
9043                      "%s: Node mask has %d nodes in mask)\n",
9044                      FuncName, N_nmask);
9045          if (!N_nmask) {
9046             SUMA_S_Warn("Empty mask, nothing to do");
9047          }
9048       } else {
9049          N_nmask = N_Node;
9050       }
9051       if (nmaskp) { /* return the mask that we have created or modified*/
9052          *nmaskp = nmask;
9053          if (locmask && nmask != locmask) { /* free locally created mask */
9054             SUMA_free(locmask);
9055          }
9056          locmask = NULL;
9057       }
9058       if (N_inmask) *N_inmask = N_nmask;
9059    } else {
9060       SUMA_LH( "going to SUMA_MakeSparseColumnFullSorted");
9061       if (!SUMA_MakeSparseColumnFullSorted(
9062                &fin_orig, SDSET_VECFILLED(dset),
9063                fillval, NULL, dset, N_Node)) {
9064          SUMA_S_Err("Failed to get full column vector");
9065          SUMA_RETURN(NULL);
9066       }
9067       /* no need for reworking nmask and locmask on this pass...*/
9068       if (N_inmask) *N_inmask =  -1; /* nothing to do */
9069    }
9070 
9071 
9072    SUMA_RETURN(fin_orig);
9073 }
9074 /*! double precision version of SUMA_DsetCol2FloatFullSortedColumn */
SUMA_DsetCol2DoubleFullSortedColumn(SUMA_DSET * dset,int ico,byte ** nmaskp,double fillval,int N_Node,int * N_inmask,SUMA_Boolean MergeMask)9075 double * SUMA_DsetCol2DoubleFullSortedColumn(
9076             SUMA_DSET *dset, int ico, byte **nmaskp,
9077             double fillval, int N_Node, int *N_inmask,
9078             SUMA_Boolean MergeMask)
9079 {
9080    static char FuncName[]={"SUMA_DsetCol2DoubleFullSortedColumn"};
9081    double *fin_orig = NULL;
9082    byte *locmask = NULL;
9083    byte *nmask = NULL;
9084    int n=0, N_nmask=0, jj=0;
9085    SUMA_Boolean LocalHead = NOPE;
9086 
9087    SUMA_ENTRY;
9088 
9089    if (nmaskp) nmask = *nmaskp;
9090    *N_inmask =  -1;
9091 
9092    /* get a double copy of the data column */
9093    fin_orig = SUMA_DsetCol2Double (dset, ico , 1);
9094    if (!fin_orig) {
9095       SUMA_SL_Crit("Failed to get copy of column. Woe to thee!");
9096       SUMA_RETURN(NULL);
9097    }
9098 
9099    /* make sure column is not sparse, one value per node */
9100    if (MergeMask) { /* masks may need merging */
9101       SUMA_LH( "Mask merger");
9102       locmask = NULL;
9103       if (!SUMA_MakeSparseDoubleColumnFullSorted(
9104                &fin_orig, SDSET_VECFILLED(dset), fillval,
9105                &locmask, dset, N_Node)) {
9106          SUMA_S_Err("Failed to get full column vector");
9107          SUMA_RETURN(NULL);
9108       }
9109       if (locmask) {
9110          SUMA_LH( "Something was filled in"
9111                   "SUMA_MakeSparseDoubleColumnFullSorted\n" );
9112          /* something was filled in good old
9113             SUMA_MakeSparseDoubleColumnFullSorted */
9114          if (nmask) {   /* combine locmask with nmask */
9115             SUMA_LH( "Merging masks\n" );
9116             for (jj=0; jj < N_Node; ++jj) {
9117                if (nmask[jj] && !locmask[jj]) nmask[jj] = 0;
9118             }
9119          } else { nmask = locmask; }
9120       }
9121       if (nmask) {
9122          N_nmask = 0;
9123          for (n=0; n<N_Node; ++n) { if (nmask[n]) ++ N_nmask; }
9124          if (LocalHead)
9125             fprintf( SUMA_STDERR,
9126                      "%s: Node mask has %d nodes in mask)\n",
9127                      FuncName, N_nmask);
9128          if (!N_nmask) {
9129             SUMA_S_Warn("Empty mask, nothing to do");
9130          }
9131       } else {
9132          N_nmask = N_Node;
9133       }
9134       if (nmaskp) { /* return the mask that we have created or modified*/
9135          *nmaskp = nmask;
9136          if (locmask && nmask != locmask) { /* free locally created mask */
9137             SUMA_free(locmask);
9138          }
9139          locmask = NULL;
9140       }
9141       *N_inmask = N_nmask;
9142    } else {
9143       SUMA_LH( "going to SUMA_MakeSparseDoubleColumnFullSorted");
9144       if (!SUMA_MakeSparseDoubleColumnFullSorted(
9145                &fin_orig, SDSET_VECFILLED(dset),
9146                fillval, NULL, dset, N_Node)) {
9147          SUMA_S_Err("Failed to get full column vector");
9148          SUMA_RETURN(NULL);
9149       }
9150       /* no need for reworking nmask and locmask on this pass...*/
9151       *N_inmask =  -1; /* nothing to do */
9152    }
9153 
9154 
9155    SUMA_RETURN(fin_orig);
9156 }
9157 
9158 /*!
9159    \brief Make the contents of a sparse node-based data column (vector)
9160    into a full column.
9161    \param vp (float **) pointer to the vector (v=*vp) containing values.
9162                         when the function returns, v would be a full column,
9163                         possibly a new vector altogether. Old sparse v
9164                         would get freed inside this function.
9165    \param N_v (int) number of values in v
9166    \param mask_val (float) value to assign in full vector for empty locations
9167    \param bmp (byte **) if bmp != NULL then a mask is returned in *bmp that
9168                         indicates which locations in returned v have values in them.
9169    \return  YUP: OK
9170             NOPE: NOK
9171 
9172    \sa SUMA_DsetCol2FloatFullSortedColumn
9173    MAKE SURE YOU ALSO MODIFY Double version of this function when you make
9174    changes here
9175 */
SUMA_MakeSparseColumnFullSorted(float ** vp,int N_v,float mask_val,byte ** bmp,SUMA_DSET * dset,int N_Node)9176 SUMA_Boolean SUMA_MakeSparseColumnFullSorted (
9177       float **vp, int N_v,
9178       float mask_val, byte **bmp,
9179       SUMA_DSET *dset, int N_Node)
9180 {
9181    static char FuncName[]={"SUMA_MakeSparseColumnFullSorted"};
9182    double range[2];
9183    float *vc=NULL, *vr=NULL;
9184    byte *bm = NULL;
9185    int  loc[2], *nip=NULL, i;
9186    SUMA_Boolean LocalHead = NOPE;
9187 
9188    SUMA_ENTRY;
9189 
9190    if ((!vp || !*vp) && !bmp) { /* OK to come in with no data, just to get bmp */
9191       SUMA_S_Err("Too NULL an input, need at least bmp or vp!");
9192       SUMA_RETURN(NOPE);
9193    }
9194 
9195    /* the column vector */
9196    if (vp) vc = *vp;
9197 
9198    /* get the node index column */
9199    if (!(nip = SUMA_GetNodeDef(dset))) {
9200       /* No node index column, check based on number of values */
9201       if (N_v == N_Node) {
9202          SUMA_LH( "Fullness established based on \n"
9203                   "number of nodes and values in v");
9204          SUMA_RETURN(YUP);
9205       } else {
9206          SUMA_S_Err("Not full and cannot fill it");
9207          SUMA_RETURN(NOPE);
9208       }
9209    } else {
9210       /* make sure column range does not exceed N_Node */
9211       if (!SUMA_GetDsetNodeIndexColRange(dset, range, loc, 1)) {
9212          SUMA_S_Err("Failed to get nodedef range");
9213          SUMA_RETURN(NOPE);
9214       }
9215 
9216       if (range[0] < 0 || range[1] >= N_Node) {
9217          SUMA_S_Err("Node index range is outside [0, N_Node[");
9218          SUMA_RETURN(NOPE);
9219       }
9220 
9221       /* have node index */
9222       if (N_v != SDSET_VECFILLED(dset)) {   /* oops, not good */
9223          SUMA_S_Err( "Number of values in v not equal to vec_filled.\n"
9224                      "Cannot proceed.");
9225          SUMA_RETURN(NOPE);
9226       }
9227 
9228       /* number of values is same as filled values, good, now proceed */
9229       if (  SDSET_VECFILLED(dset) == N_Node &&
9230             nip[SDSET_VECFILLED(dset)-1] == N_Node -1 &&
9231             nip[SDSET_VECFILLED(dset)-1-SDSET_VECFILLED(dset)/2] ==
9232                   N_Node -1 -SDSET_VECFILLED(dset)/2 &&
9233             nip[SDSET_VECFILLED(dset)-1-SDSET_VECFILLED(dset)/3] ==
9234                   N_Node -1 -SDSET_VECFILLED(dset)/3 &&
9235             SDSET_IS_SORTED(dset)) {   /* likely a full column */
9236          SUMA_LH( "Fullness established by loose examination \n"
9237                   "of node defintion column.");
9238          SUMA_RETURN(YUP);
9239       }
9240       /* if you get here then you do not have a
9241          full list or the list is not sorted*/
9242       SUMA_LH("Creating vr");
9243       if (vc) vr = (float *)SUMA_calloc(N_Node, sizeof(float));
9244       if (bmp) {
9245          if (*bmp) {
9246             SUMA_S_Err("*bmp must be NULL");
9247             SUMA_RETURN(NOPE);
9248          }
9249          bm = (byte *)SUMA_calloc(N_Node, sizeof(byte));
9250       } else bm = NULL;
9251 
9252       if ((vc && !vr) || (bmp && !bm)) {
9253          SUMA_S_Crit("Failed to allocate");
9254          SUMA_RETURN(NOPE);
9255       }
9256       if (vr) {
9257          for (i=0; i<N_Node; ++i) {
9258             vr[i] = mask_val; /* if (bm) bm[i] = 0; */
9259          }
9260       }
9261       for (i=0; i<SDSET_VECFILLED(dset); ++i) {
9262          if (vc) vr[nip[i]] = vc[i];
9263          if (bm) bm[nip[i]] = 1;
9264       }
9265 
9266 
9267       /* Now free old v */
9268       if (vc) SUMA_free(vc); vc = NULL;
9269 
9270       /* stow away for return */
9271       if (bmp) { *bmp = bm; bm = NULL; }
9272       if (vp) *vp = vr; vr = NULL;
9273 
9274       SUMA_RETURN(YUP);
9275    }
9276 
9277    /* Should not get here */
9278    SUMA_RETURN(NOPE);
9279 }
9280 
9281 /*! double precision version of SUMA_MakeSparseColumnFullSorted */
SUMA_MakeSparseDoubleColumnFullSorted(double ** vp,int N_v,double mask_val,byte ** bmp,SUMA_DSET * dset,int N_Node)9282 SUMA_Boolean SUMA_MakeSparseDoubleColumnFullSorted (
9283       double **vp, int N_v,
9284       double mask_val, byte **bmp,
9285       SUMA_DSET *dset, int N_Node)
9286 {
9287    static char FuncName[]={"SUMA_MakeSparseDoubleColumnFullSorted"};
9288    double *vc=NULL, *vr=NULL;
9289    byte *bm = NULL;
9290    double range[2];
9291    int  loc[2], *nip=NULL, i;
9292    SUMA_Boolean LocalHead = NOPE;
9293 
9294    SUMA_ENTRY;
9295 
9296    if ((!vp || !*vp) && !bmp) { /* OK if user just wants update of bmp */
9297       SUMA_S_Err("Too NULL an input, need at least bmp or vp!");
9298       SUMA_RETURN(NOPE);
9299    }
9300 
9301    /* the column vector */
9302    if (vp) vc = *vp;
9303 
9304    /* get the node index column */
9305    if (!(nip = SUMA_GetNodeDef(dset))) {
9306       /* No node index column, check based on number of values */
9307       if (N_v == N_Node) {
9308          SUMA_LH( "Fullness established based on \n"
9309                   "number of nodes and values in v");
9310          SUMA_RETURN(YUP);
9311       } else {
9312          SUMA_S_Err("Not full and cannot fill it");
9313          SUMA_RETURN(NOPE);
9314       }
9315    } else {
9316       /* make sure column range does not exceed N_Node */
9317       if (!SUMA_GetDsetNodeIndexColRange(dset, range, loc, 1)) {
9318          SUMA_S_Err("Failed to get nodedef range");
9319          SUMA_RETURN(NOPE);
9320       }
9321 
9322       if (range[0] < 0 || range[1] >= N_Node) {
9323          SUMA_S_Err("Node index range is outside [0, N_Node[");
9324          SUMA_RETURN(NOPE);
9325       }
9326 
9327       /* have node index */
9328       if (N_v != SDSET_VECFILLED(dset)) {   /* oops, not good */
9329          SUMA_S_Err( "Number of values in v not equal to vec_filled.\n"
9330                      "Cannot proceed.");
9331          SUMA_RETURN(NOPE);
9332       }
9333 
9334       /* number of values is same as filled values, good, now proceed */
9335       if (  SDSET_VECFILLED(dset) == N_Node &&
9336             nip[SDSET_VECFILLED(dset)-1] == N_Node -1 &&
9337             nip[SDSET_VECFILLED(dset)-1-SDSET_VECFILLED(dset)/2] ==
9338                   N_Node -1 -SDSET_VECFILLED(dset)/2 &&
9339             nip[SDSET_VECFILLED(dset)-1-SDSET_VECFILLED(dset)/3] ==
9340                   N_Node -1 -SDSET_VECFILLED(dset)/3 &&
9341             SDSET_IS_SORTED(dset)) {   /* likely a full column */
9342          SUMA_LH( "Fullness established by loose examination \n"
9343                   "of node defintion column.");
9344          SUMA_RETURN(YUP);
9345       }
9346       /* if you get here then you do not have a
9347          full list or the list is not sorted*/
9348       SUMA_LH("Creating vr");
9349       if (vc) vr = (double *)SUMA_calloc(N_Node, sizeof(double));
9350       if (bmp) {
9351          if (*bmp) {
9352             SUMA_S_Err("*bmp must be NULL");
9353             SUMA_RETURN(NOPE);
9354          }
9355          bm = (byte *)SUMA_calloc(N_Node, sizeof(byte));
9356       } else bm = NULL;
9357 
9358       if ((vc && !vr) || (bmp && !bm)) {
9359          SUMA_S_Crit("Failed to allocate");
9360          SUMA_RETURN(NOPE);
9361       }
9362       if (vr) {
9363          for (i=0; i<N_Node; ++i) {
9364             vr[i] = mask_val; /* if (bm) bm[i] = 0; */
9365          }
9366       }
9367       for (i=0; i<SDSET_VECFILLED(dset); ++i) {
9368          if (vc) vr[nip[i]] = vc[i];
9369          if (bm) bm[nip[i]] = 1;
9370       }
9371 
9372 
9373       /* Now free old v */
9374       if (vc) SUMA_free(vc); vc = NULL;
9375 
9376       /* stow away for return */
9377       if (bmp) { *bmp = bm; bm = NULL; }
9378       if (vp) *vp = vr; vr = NULL;
9379 
9380       SUMA_RETURN(YUP);
9381    }
9382 
9383    /* Should not get here */
9384    SUMA_RETURN(NOPE);
9385 }
9386 
9387 /*!
9388    \brief Copies the contents of a float vector into a NI_element column
9389    SUMA_Float2DsetCol (dset,  ind,  V, FilledOnly, replacemask);
9390 
9391    \param nel (NI_element *)
9392    \param ind (int) index of column to be filled with values in V
9393    \param V (float *) vector containing the column's contents (see number of values copied below).
9394    \param FilledOnly (int) 0 = copy from index 0 to dset->dnel->vec_len or SDSET_VECLEN(dset)
9395                            1 = copy from index 0 to dset->dnel->vec_filled or SDSET_VECFILLED(dset)
9396    \param replacemask (byte *) if not null, then copy value in index i only IF replacemask[i] == 1
9397                                if null, copy all indices i
9398    The values in V replace those in nel!
9399    No new columns in nel are created.
9400 
9401    \sa SUMA_DsetCol2Float , SUMA_Vec2DsetCol
9402 */
SUMA_BadOptimizerBadBad(void)9403 void SUMA_BadOptimizerBadBad(void){ return; }
9404 
9405 #define SUMA_COL_FILL(vv, VV, tp){\
9406    if (!replacemask) {\
9407       if (nip) { \
9408          for (i=0; i<N_read; ++i) { vv[i] = (tp)VV[nip[i]]; } \
9409       } else { \
9410          for (i=0; i<N_read; ++i) { vv[i] = (tp)VV[i]; } \
9411       }\
9412    } else { \
9413      if (nip) { \
9414          for (i=0; i<N_read; ++i)  { \
9415             if (replacemask[nip[i]]) { \
9416                vv[i] = (tp)VV[nip[i]]; \
9417                 /* That call was turned off again because
9418                   this macro misbehaved again Jan. 2011.
9419                   Putting brackets at all spots seems to have
9420                   fixed the problem, and that call below seems
9421                   unnecessary for now.    ZSS Jan 04 2011 */   \
9422                /* SUMA_BadOptimizerBadBad();  Dec. 03 07 */ \
9423             }  \
9424          }  \
9425      } else {  \
9426          for (i=0; i<N_read; ++i) { \
9427             if (replacemask[i]) { \
9428                vv[i] = (tp)VV[i];  /* (int) --> (tp) ZSS Jan 04 2011 */ \
9429             } \
9430          }  \
9431      }   \
9432    }  \
9433 }
9434 
SUMA_Float2DsetCol(SUMA_DSET * dset,int ind,float * V,int FilledOnly,byte * replacemask)9435 int SUMA_Float2DsetCol (SUMA_DSET *dset, int ind,
9436                         float *V, int FilledOnly,
9437                         byte *replacemask)
9438 {
9439    static char FuncName[]={"SUMA_Float2DsetCol"};
9440    int i = -1, N_read = -1, *iv = NULL, *nip=NULL, nnn=-1, NodeDBG=0;
9441    float *fv = NULL;
9442    SUMA_COL_TYPE ctp;
9443    SUMA_VARTYPE vtp;
9444    SUMA_Boolean LocalHead = NOPE;
9445 
9446    SUMA_ENTRY;
9447 
9448    if (!dset) { SUMA_RETURN(0); }
9449 
9450    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
9451       SUMA_S_Errv("Bad col index (%d/%d)\n", ind, SDSET_VECNUM(dset) - 1);
9452       SUMA_RETURN(0);
9453    }
9454 
9455    if (FilledOnly) {
9456       N_read = SDSET_VECFILLED(dset);
9457    } else {
9458       N_read = SDSET_VECLEN(dset);
9459    }
9460 
9461    if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
9462 
9463    #if 0
9464       /* MACROS below have given me hell with optimizer related troubles
9465          Code left here for sanity checks */
9466    NodeDBG =  136029;
9467    if (LocalHead) fprintf(stderr,"%s: Pre replacement, node %d=%f\n"
9468                      "New value %f, mask = %d\n",
9469                FuncName, NodeDBG,
9470                SUMA_GetDsetNodeValInCol2(dset,ind,
9471                                           NodeDBG, -1),
9472                V[NodeDBG], replacemask ? replacemask[NodeDBG]:1);
9473    #endif
9474 
9475    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
9476    vtp = SUMA_ColType2TypeCast (ctp) ;
9477    nip = SUMA_GetNodeDef(dset);
9478    switch (vtp) {
9479       case SUMA_int:
9480          iv = (int *)dset->dnel->vec[ind];
9481          SUMA_COL_FILL(iv, V, int);
9482          break;
9483       case SUMA_float:
9484          fv = (float *)dset->dnel->vec[ind];
9485          #if 1 /* Assuming MACRO is not causing trouble */
9486             SUMA_COL_FILL(fv, V, float);
9487          #else /* Try this block to test optimizer bug */
9488    if (!replacemask) {
9489       if (nip) { for (i=0; i<N_read; ++i) { fv[i] = (float)V[nip[i]]; } }
9490       else { for (i=0; i<N_read; ++i) { fv[i] = (float)V[i]; } }
9491    } else {
9492      if (nip) {
9493          for (i=0; i<N_read; ++i)  {
9494             if (replacemask[nip[i]]) {
9495                fv[i] = (float)V[nip[i]];
9496                 /* That call was turned off again because
9497                   this macro misbehaved again Jan. 2011.
9498                   Putting brackets at all spots seems to have
9499                   fixed the problem, and that call below seems
9500                   unnecessary for now.    ZSS Jan 04 2011 */
9501                /* SUMA_BadOptimizerBadBad();  Dec. 03 07 */
9502             }
9503          }
9504      } else {
9505          for (i=0; i<N_read; ++i) {
9506             if (replacemask[i]) {
9507                fv[i] = (float)V[i];  /* (int) --> (float) ZSS Jan 04 2011 */
9508             }
9509          }
9510      }
9511    }
9512          #endif
9513          break;
9514       default:
9515          SUMA_SL_Err("This type is not supported.\n");
9516          SUMA_RETURN(0);
9517          break;
9518    }
9519 
9520    #if 0
9521    if (LocalHead) fprintf(stderr,"%s: Post replacement, node %d=%f\n"
9522                      "New value %f, mask = %d\n",
9523                FuncName, NodeDBG,
9524                SUMA_GetDsetNodeValInCol2(dset,ind,
9525                                           NodeDBG, -1),
9526                V[NodeDBG], replacemask ? replacemask[NodeDBG]:1);
9527    #endif
9528    /* reset generic attributes */
9529    SUMA_AddGenDsetColAttr (dset, ctp, dset->dnel->vec[ind], 1, ind, 0);
9530 
9531    SUMA_RETURN(1);
9532 }
9533 /*!
9534    \brief Copies the contents of a vector into a NI_element column
9535    SUMA_Vec2DsetCol (dset,  ind,  V, Vtp, FilledOnly, replacemask);
9536 
9537    \param nel (NI_element *)
9538    \param ind (int) index of column to be filled with values in V
9539    \param V (void *) vector containing the column's contents
9540                (see number of values copied below).
9541    \param Vtp (SUMA_VARTYPE) type of data in V
9542    \param FilledOnly (int) 0 = copy from index 0 to dset->dnel->vec_len
9543                                                  or SDSET_VECLEN(dset)
9544                            1 = copy from index 0 to dset->dnel->vec_filled
9545                                                  or SDSET_VECFILLED(dset)
9546    \param replacemask (byte *) if not null, then copy value in index i
9547                                              only IF replacemask[i] == 1
9548                                if null, copy all indices i
9549    The values in V replace those in nel!
9550    No new columns in nel are created.
9551 
9552    \sa SUMA_DsetCol2Float
9553 */
SUMA_Vec2DsetCol(SUMA_DSET * dset,int ind,void * V,SUMA_VARTYPE Vtp,int FilledOnly,byte * replacemask)9554 int SUMA_Vec2DsetCol (SUMA_DSET *dset, int ind,
9555                         void *V, SUMA_VARTYPE Vtp,
9556                         int FilledOnly,
9557                         byte *replacemask)
9558 {
9559    static char FuncName[]={"SUMA_Vec2DsetCol"};
9560    int i = -1, N_read = -1, *iv = NULL, *iV=NULL, *nip=NULL, nnn=-1;
9561    float *fv = NULL, *fV=NULL;
9562    double *dV=NULL;
9563    SUMA_COL_TYPE ctp;
9564    SUMA_VARTYPE vtp;
9565    SUMA_Boolean LocalHead = NOPE;
9566 
9567    SUMA_ENTRY;
9568 
9569    if (!dset) { SUMA_RETURN(0); }
9570    if (!V) {
9571       SUMA_S_Err("NULL V");
9572       SUMA_RETURN(0);
9573    }
9574    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
9575       SUMA_SL_Err("Bad col index");
9576       SUMA_RETURN(0);
9577    }
9578 
9579    if (FilledOnly) {
9580       N_read = SDSET_VECFILLED(dset);
9581    } else {
9582       N_read = SDSET_VECLEN(dset);
9583    }
9584 
9585    if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
9586    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
9587    vtp = SUMA_ColType2TypeCast (ctp) ;
9588    nip = SUMA_GetNodeDef(dset);
9589    switch (Vtp) {
9590      case SUMA_int:
9591          iV = (int *)V;
9592          switch (vtp) {
9593             case SUMA_int:
9594                iv = (int *)dset->dnel->vec[ind];
9595                SUMA_COL_FILL(iv, iV, int);
9596                break;
9597             case SUMA_float:
9598                fv = (float *)dset->dnel->vec[ind];
9599                SUMA_COL_FILL(fv, iV, float);
9600                break;
9601             default:
9602                SUMA_SL_Err("This type is not supported.\n");
9603                SUMA_RETURN(0);
9604                break;
9605          }
9606          break;
9607       case SUMA_float:
9608          fV = (float *)V;
9609          switch (vtp) {
9610             case SUMA_int:
9611                iv = (int *)dset->dnel->vec[ind];
9612                SUMA_COL_FILL(iv, fV, int);
9613                break;
9614             case SUMA_float:
9615                fv = (float *)dset->dnel->vec[ind];
9616                SUMA_COL_FILL(fv, fV, float);
9617                break;
9618             default:
9619                SUMA_SL_Err("This type is not supported.\n");
9620                SUMA_RETURN(0);
9621                break;
9622          }
9623          break;
9624       case SUMA_double:
9625          dV = (double *)V;
9626          switch (vtp) {
9627             case SUMA_int:
9628                iv = (int *)dset->dnel->vec[ind];
9629                SUMA_COL_FILL(iv, dV, int);
9630                break;
9631             case SUMA_float:
9632                fv = (float *)dset->dnel->vec[ind];
9633                SUMA_COL_FILL(fv, dV, float);
9634                break;
9635             default:
9636                SUMA_SL_Err("This type is not supported.\n");
9637                SUMA_RETURN(0);
9638                break;
9639          }
9640          break;
9641 
9642       default:
9643          SUMA_SL_Err("This type is not supported.\n");
9644          SUMA_RETURN(0);
9645          break;
9646    }
9647 
9648    /* reset generic attributes */
9649    SUMA_AddGenDsetColAttr (dset, ctp, dset->dnel->vec[ind], 1, ind, 0);
9650    if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
9651    SUMA_RETURN(1);
9652 }
9653 
9654 /*!
9655    \brief Copies the contents of a NI_element column into
9656    a new float vector
9657    V = SUMA_DsetCol2Float (dset,  ind,  FilledOnly);
9658 
9659    \param nel (NI_element *)
9660    \param ind (int) index of column to be copied
9661    \param FilledOnly (int) 0 = allocate for and read all of the column
9662                               (up to nel->vec_len)
9663                            1 = allocate for and read the filled portion
9664                                of the column (up to nel->vec_filled)
9665    \return V (float *) vector (allocated by the function) containing
9666                      the column's contents.
9667    \sa SUMA_Float2DsetCol
9668  */
SUMA_DsetCol2Float(SUMA_DSET * dset,int ind,int FilledOnly)9669 float * SUMA_DsetCol2Float (SUMA_DSET *dset, int ind, int FilledOnly)
9670 {
9671    static char FuncName[]={"SUMA_DsetCol2Float"};
9672    int i = -1, N_read = -1, *iv = NULL;
9673    float *V=NULL, *fv = NULL, fac;
9674    byte *bv=NULL;
9675    double *dv=NULL;
9676    short *sv=NULL;
9677    complex *cmv=NULL;
9678    SUMA_COL_TYPE ctp;
9679    SUMA_VARTYPE vtp;
9680    SUMA_Boolean LocalHead = NOPE;
9681 
9682    SUMA_ENTRY;
9683 
9684    if (!dset) { SUMA_RETURN(NULL); }
9685 
9686    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
9687       SUMA_SL_Err("Bad index");
9688       SUMA_RETURN(NULL);
9689    }
9690 
9691    if (FilledOnly) {
9692       N_read = SDSET_VECFILLED(dset);
9693    } else {
9694       N_read = SDSET_VECLEN(dset);
9695    }
9696 
9697    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
9698    fac = SUMA_GetBrickFactor(dset, ind); if (fac == 0.0f) fac = 1.0;
9699    SUMA_LH("Col fac (if any) %f\n", fac);
9700    V = (float *)SUMA_calloc(N_read, sizeof(float));
9701    if (!V) { SUMA_SL_Crit("Failed to allocate for V."); SUMA_RETURN(NULL); }
9702    vtp = SUMA_ColType2TypeCast (ctp) ;
9703    switch (vtp) {
9704       case SUMA_byte:
9705          bv = (byte *)dset->dnel->vec[ind];
9706          for (i=0; i<N_read; ++i) V[i] = (float)(bv[i]*fac);
9707          break;
9708       case SUMA_int:
9709          iv = (int *)dset->dnel->vec[ind];
9710          for (i=0; i<N_read; ++i) V[i] = (float)iv[i];
9711          break;
9712       case SUMA_short:
9713          sv = (short *)dset->dnel->vec[ind];
9714          for (i=0; i<N_read; ++i) V[i] = (float)(sv[i]*fac);
9715          break;
9716       case SUMA_float:
9717          fv = (float *)dset->dnel->vec[ind];
9718          for (i=0; i<N_read; ++i) V[i] = fv[i];
9719          break;
9720       case SUMA_double:
9721          dv = (double *)dset->dnel->vec[ind];
9722          for (i=0; i<N_read; ++i) V[i] = (float)dv[i];
9723          break;
9724       case SUMA_complex:
9725          cmv = (complex *)dset->dnel->vec[ind];
9726          for (i=0; i<N_read; ++i) V[i] = (float)CABS(cmv[i]);
9727          break;
9728       default:
9729          SUMA_SL_Err("This type is not supported.\n");
9730          SUMA_free(V);
9731          SUMA_RETURN(NULL);
9732          break;
9733    }
9734 
9735    SUMA_RETURN(V);
9736 }
SUMA_DsetCol2Int(SUMA_DSET * dset,int ind,int FilledOnly)9737 int * SUMA_DsetCol2Int (SUMA_DSET *dset, int ind, int FilledOnly)
9738 {
9739    static char FuncName[]={"SUMA_DsetCol2Int"};
9740    int i = -1, *V=NULL, N_read = -1, *iv = NULL;
9741    float *fv = NULL;
9742    SUMA_COL_TYPE ctp;
9743    SUMA_VARTYPE vtp;
9744    SUMA_Boolean LocalHead = NOPE;
9745 
9746    SUMA_ENTRY;
9747 
9748    if (!dset) { SUMA_RETURN(NULL); }
9749 
9750    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
9751       SUMA_SL_Err("Bad index");
9752       SUMA_RETURN(NULL);
9753    }
9754 
9755    if (FilledOnly) {
9756       N_read = SDSET_VECFILLED(dset);
9757    } else {
9758       N_read = SDSET_VECLEN(dset);
9759    }
9760 
9761    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
9762 
9763    V = (int *)SUMA_calloc(N_read, sizeof(int));
9764    if (!V) { SUMA_SL_Crit("Failed to allocate for V."); SUMA_RETURN(NULL); }
9765    vtp = SUMA_ColType2TypeCast (ctp) ;
9766    switch (vtp) {
9767       case SUMA_int:
9768          iv = (int *)dset->dnel->vec[ind];
9769          for (i=0; i<N_read; ++i) V[i] = (int)iv[i];
9770          break;
9771       case SUMA_float:
9772          fv = (float *)dset->dnel->vec[ind];
9773          for (i=0; i<N_read; ++i) V[i] = (int)fv[i];
9774          break;
9775       default:
9776          SUMA_SL_Err("This type is not supported.\n");
9777          SUMA_free(V);
9778          SUMA_RETURN(NULL);
9779          break;
9780    }
9781 
9782    SUMA_RETURN(V);
9783 }
SUMA_DsetCol2Double(SUMA_DSET * dset,int ind,int FilledOnly)9784 double * SUMA_DsetCol2Double (SUMA_DSET *dset, int ind, int FilledOnly)
9785 {
9786    static char FuncName[]={"SUMA_DsetCol2Double"};
9787    int i = -1, N_read = -1, *iv = NULL;
9788    double *V=NULL;
9789    float *fv = NULL;
9790    double *dv=NULL;
9791    byte *bv=NULL;
9792    complex *cv=NULL;
9793    SUMA_COL_TYPE ctp;
9794    SUMA_VARTYPE vtp;
9795    SUMA_Boolean LocalHead = NOPE;
9796 
9797    SUMA_ENTRY;
9798 
9799    if (!dset) { SUMA_RETURN(NULL); }
9800 
9801    if (ind < 0 || ind > SDSET_VECNUM(dset) - 1) {
9802       SUMA_SL_Err("Bad index");
9803       SUMA_RETURN(NULL);
9804    }
9805 
9806    if (FilledOnly) {
9807       N_read = SDSET_VECFILLED(dset);
9808    } else {
9809       N_read = SDSET_VECLEN(dset);
9810    }
9811 
9812    ctp = SUMA_TypeOfDsetColNumb(dset, ind);
9813 
9814    V = (double *)SUMA_calloc(N_read, sizeof(double));
9815    if (!V) { SUMA_SL_Crit("Failed to allocate for V."); SUMA_RETURN(NULL); }
9816    vtp = SUMA_ColType2TypeCast (ctp) ;
9817    switch (vtp) {
9818       case SUMA_byte:
9819          bv = (byte *)dset->dnel->vec[ind];
9820          for (i=0; i<N_read; ++i) V[i] = (float)bv[i];
9821          break;
9822       case SUMA_int:
9823          iv = (int *)dset->dnel->vec[ind];
9824          for (i=0; i<N_read; ++i) V[i] = (float)iv[i];
9825          break;
9826       case SUMA_float:
9827          fv = (float *)dset->dnel->vec[ind];
9828          for (i=0; i<N_read; ++i) V[i] = fv[i];
9829          break;
9830       case SUMA_double:
9831          dv = (double *)dset->dnel->vec[ind];
9832          for (i=0; i<N_read; ++i) V[i] = (float)dv[i];
9833          break;
9834       case SUMA_complex:
9835          cv = (complex *)dset->dnel->vec[ind];
9836          for (i=0; i<N_read; ++i) V[i] = (float)CABS(cv[i]);
9837          break;
9838       default:
9839          SUMA_SL_Err("This type is not supported.\n");
9840          SUMA_free(V);
9841          SUMA_RETURN(NULL);
9842          break;
9843    }
9844 
9845    SUMA_RETURN(V);
9846 }
9847 
9848 /*!
9849    a function to return the string attribute of a column
9850    Free with SUMA_free
9851 */
SUMA_AttrOfDsetColNumb(SUMA_DSET * dset,int ind)9852 char * SUMA_AttrOfDsetColNumb(SUMA_DSET *dset, int ind)
9853 {
9854    static char FuncName[]={"SUMA_AttrOfDsetColNumb"};
9855    char *cnm = NULL;
9856    NI_element *nelb=NULL;
9857    SUMA_Boolean LocalHead = NOPE;
9858 
9859    SUMA_ENTRY;
9860 
9861    if (!dset) {
9862       SUMA_SL_Err("NULL NI element");
9863       SUMA_RETURN(cnm);
9864    }
9865    if (ind < 0 || ind > (SDSET_VECNUM(dset) - 1)) {
9866       SUMA_SL_Err("Bad index");
9867       SUMA_RETURN(cnm);
9868    }
9869 
9870    /* try SUMA's */
9871    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsAttributes");
9872    if (nelb) {
9873       SUMA_NEL_GET_STRING(nelb, 0, 0, cnm); /* cnm is a pointer copy here, do not free */
9874       cnm = SUMA_Get_Sub_String(cnm, SUMA_NI_CSS, ind);
9875       SUMA_RETURN(cnm);
9876    }
9877 
9878 
9879 
9880    if (LocalHead) { SUMA_SL_Warn("Failed to find attribute"); }
9881    SUMA_RETURN(NULL);
9882 }
9883 
9884 /*!
9885    a wrapper to faciliate getting column types from
9886    both SUMA and AFNI formatted niml elements
9887    \sa SUMA_Col_Type
9888    NOTE, this function will repeatedly parse the entire string
9889    for column types. That's both stupid and inefficient.
9890    Write an efficient version called  SUMA_TypesOfDsetColNumb next ...
9891 */
SUMA_TypeOfDsetColNumb(SUMA_DSET * dset,int ind)9892 SUMA_COL_TYPE SUMA_TypeOfDsetColNumb(SUMA_DSET *dset, int ind)
9893 {
9894    static char FuncName[]={"SUMA_TypeOfDsetColNumb"};
9895    int *ctpv = NULL;
9896    char *cnm = NULL, **sc = NULL;
9897    int_array *iar = NULL;
9898    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
9899    char stmp[100];
9900    NI_element *nelb=NULL;
9901    SUMA_Boolean LocalHead = NOPE;
9902 
9903    SUMA_ENTRY;
9904 
9905    if (!dset) {
9906       SUMA_SL_Err("NULL NI element");
9907       SUMA_RETURN(ctp);
9908    }
9909    if (ind < 0 || ind > (SDSET_VECNUM(dset) - 1)) {
9910       SUMA_SL_Err("Bad index");
9911       SUMA_RETURN(ctp);
9912    }
9913 
9914    /* try SUMA's */
9915    nelb = SUMA_FindDsetAttributeElement(dset, "COLMS_TYPE");
9916    if (nelb) {
9917       SUMA_LH("Fetching Type a la suma");
9918       SUMA_NEL_GET_STRING(nelb, 0, 0, cnm);
9919          /* cnm is a pointer copy here, do not free */
9920       cnm = SUMA_Get_Sub_String(cnm, SUMA_NI_CSS, ind);
9921       /* SUMA_LH(cnm); */
9922    }
9923    if (cnm) {
9924       ctp = SUMA_Col_Type(cnm); SUMA_free(cnm); cnm = NULL;
9925       SUMA_RETURN(ctp);
9926    }
9927 
9928    /* try AFNI's */
9929    SUMA_LH("Fetching Type a la afni");
9930    cnm = NI_get_attribute(dset->dnel, "ni_type");
9931    if (cnm) {
9932       SUMA_LH("%s",cnm);
9933       iar = decode_type_string( cnm );
9934       if (iar) {
9935          ctp = iar->ar[ind];
9936             /* this is not the same as SUMA's column type,
9937                it is just data type */
9938          NI_free(iar->ar); NI_free(iar); iar = NULL;
9939          switch(ctp) {
9940             case SUMA_int:
9941                ctp = SUMA_NODE_INT;
9942                break;
9943             case SUMA_float:
9944                ctp = SUMA_NODE_FLOAT;
9945                break;
9946             case SUMA_byte:
9947                ctp = SUMA_NODE_BYTE;
9948                break;
9949             case SUMA_short:
9950                ctp = SUMA_NODE_SHORT;
9951                break;
9952             case SUMA_complex:
9953                ctp = SUMA_NODE_COMPLEX;
9954                break;
9955             default:
9956                SUMA_SL_Err("AFNI column type not supported at the moment.\n");
9957                ctp = SUMA_ERROR_COL_TYPE;
9958                break;
9959          }
9960          SUMA_RETURN(ctp);
9961       }
9962    }
9963 
9964    SUMA_SL_Err("Failed to determine type");
9965    SUMA_RETURN(ctp);
9966 }
9967 
SUMA_isSameDsetColTypes(SUMA_DSET * dset1,SUMA_DSET * dset2)9968 SUMA_Boolean SUMA_isSameDsetColTypes(SUMA_DSET *dset1, SUMA_DSET *dset2)
9969 {
9970    static char FuncName[]={"SUMA_isSameDsetColTypes"};
9971    int *ctpv = NULL, ind = 0;
9972    char *cnm1 = NULL, *cnm2=NULL, **sc = NULL;
9973    int_array *iar1 = NULL, *iar2 = NULL;
9974    char stmp[100];
9975    NI_element *nelb1=NULL;
9976    NI_element *nelb2=NULL;
9977    SUMA_Boolean LocalHead = NOPE;
9978 
9979    SUMA_ENTRY;
9980 
9981    if (!dset1 || !dset2) {
9982       SUMA_SL_Err("NULL Dsets");
9983       SUMA_RETURN(NOPE);
9984    }
9985    SUMA_LHv("Checking sb numbers %d vs %d\n",
9986          SDSET_VECNUM(dset1), SDSET_VECNUM(dset2));
9987    if (SDSET_VECNUM(dset1) != SDSET_VECNUM(dset2)) {
9988       SUMA_RETURN(NOPE);
9989    }
9990 
9991    /* try SUMA's */
9992    nelb1 = SUMA_FindDsetAttributeElement(dset1, "COLMS_TYPE");
9993    nelb2 = SUMA_FindDsetAttributeElement(dset2, "COLMS_TYPE");
9994    if (nelb1 && nelb2) {
9995       SUMA_NEL_GET_STRING(nelb1, 0, 0, cnm1);
9996       SUMA_NEL_GET_STRING(nelb2, 0, 0, cnm2);
9997          /* cnm is a pointer copy here, do not free */
9998    }
9999 
10000    if (cnm1 && cnm2) {
10001       SUMA_LHv("Types a la SUMA\n%s\nvs.\n%s\n",
10002          cnm1,cnm2);
10003       if (strcmp(cnm1,cnm2)) {/* wholesale comparison */
10004          SUMA_RETURN(NOPE);
10005       } else {
10006          SUMA_RETURN(YUP);
10007       }
10008    }
10009 
10010    /* try AFNI's */
10011    SUMA_LH("Fetching Type a la afni");
10012    cnm1 = NI_get_attribute(dset1->dnel, "ni_type");
10013    cnm2 = NI_get_attribute(dset2->dnel, "ni_type");
10014    if (cnm1 && cnm2) {
10015       SUMA_LH("%s %s", cnm1, cnm2);
10016       iar1 = decode_type_string( cnm1 );
10017       iar2 = decode_type_string( cnm1 );
10018       if (iar1 && iar2) {
10019          for (ind=0; ind<SDSET_VECNUM(dset1); ++ind) {
10020             if (iar1->ar[ind] != iar2->ar[ind])  SUMA_RETURN(NOPE);
10021             NI_free(iar1->ar); NI_free(iar1); iar1 = NULL;
10022             NI_free(iar2->ar); NI_free(iar2); iar2 = NULL;
10023          }
10024          SUMA_RETURN(YUP); /* all columns matched */
10025       } else {
10026          SUMA_RETURN(NOPE);
10027       }
10028    }
10029 
10030    SUMA_SL_Err("Failed to determine types");
10031    SUMA_RETURN(NOPE);
10032 }
10033 
SUMA_AddNodeIndexColumn(SUMA_DSET * dset,int N_Node)10034 SUMA_Boolean SUMA_AddNodeIndexColumn(SUMA_DSET *dset, int N_Node)
10035 {
10036    static char FuncName[]={"SUMA_AddNodeIndexColumn"};
10037    double range[2];
10038    int *ind=NULL, i, N_i;
10039    float *T = NULL;
10040    int *Ti = NULL;
10041    byte *vis=NULL;
10042    SUMA_Boolean OKfirstCol = NOPE;
10043    SUMA_Boolean LocalHead = NOPE;
10044 
10045    SUMA_ENTRY;
10046 
10047    if (!dset) SUMA_RETURN(NOPE);
10048    if (SUMA_isCIFTIDset(dset)) {
10049       SUMA_S_Err("Have yet to work out the logic for this type");
10050       SUMA_RETURN(NOPE);
10051    }
10052    /* check for obvious insult */
10053    if (SDSET_VECLEN(dset) > N_Node) {
10054       SUMA_SL_Err("more values in dset than nodes in surface.");
10055       SUMA_RETURN(NOPE);
10056    }
10057    /* Check for Col Index*/
10058    ind = SUMA_GetNodeDef (dset);
10059    if (!ind) {
10060       SUMA_LH("No node index column");
10061       if (SUMA_isGraphDset(dset)) {
10062          if (dset->Aux->matrix_shape == MAT_SPARSE) {
10063             SUMA_S_Err("No gessing possible");
10064             SUMA_RETURN(NOPE);
10065          }
10066          SUMA_LH("Graph dset with explicit indexing possible, nothing to do."
10067                  "You can if you insist add an explicit indexing element, but"
10068                  "that strikes me as a waste. "
10069                  "You would do it as with the Populate function");
10070          SUMA_RETURN(YUP);
10071       }
10072       /* would the first column work ? */
10073       T = SUMA_DsetCol2Float (dset, 0, 0);
10074       OKfirstCol = NOPE;
10075       if (!T) { SUMA_LH("First column does not cut it"); OKfirstCol = NOPE;}
10076       else {
10077          Ti = (int *)SUMA_malloc(sizeof(int)*SDSET_VECALLOC(dset));
10078          vis = (byte *)SUMA_calloc(N_Node, sizeof(byte));
10079          SUMA_LH("Testing if node indices can be in 1st column...");
10080          /* check if all values are ints and if they are within 0 and N_Node -1
10081             and that there are no duplicate entries */
10082          i=0;
10083          OKfirstCol = YUP;
10084          while (i <SDSET_VECLEN(dset) && OKfirstCol) {
10085             Ti[i] = (int)T[i];
10086             if (  (T[i] != Ti[i]) || (T[i] < 0) ||
10087                    (Ti[i] >= N_Node) || vis[Ti[i]] ) OKfirstCol = NOPE;
10088             else if ( Ti[i] < N_Node ) vis[Ti[i]] = 1;
10089             ++i;
10090          }
10091          SUMA_free(vis); vis = NULL;
10092 
10093          if (!OKfirstCol) {
10094             SUMA_SLP_Note( "Assuming node indexing\n"
10095                            "is explicit. \n"
10096                            "1st row is for node 0\n"
10097                            "2nd is for node 1, etc.\n" );
10098             for (i=0; i <SDSET_VECLEN(dset); ++i) Ti[i]=i;
10099             OKfirstCol = YUP;
10100          }else{
10101             char Name[500], Attr[500];
10102             SUMA_SL_Note("Used column 0 as node indices.\n"
10103                          "Added a node index column nonetheless.");
10104             /* You can't just change the label and the type
10105             of the 0th column to be SUMA_NODE_INDEX because
10106             this column is float, not ints. Duplicate ahead...*/
10107          }
10108 
10109       }
10110 
10111       if (!OKfirstCol) {
10112          SUMA_LH("No node index could be created");
10113          if (Ti) SUMA_free(Ti); Ti = NULL;
10114          SUMA_RETURN(NOPE);
10115       }
10116 
10117       /* Now add Ti to the dataset as a node index column ... */
10118       /* if you change the column label's string ("Node Index (inferred)")
10119       make sure you change SUMA_isColumn_inferred accordingly */
10120       if (!SUMA_AddDsetNelCol (dset, "Node Index (inferred)",
10121                                 SUMA_NODE_INDEX, (void *)Ti, NULL, 1)) {
10122          SUMA_SL_Err("Failed to add column");
10123          if (Ti) SUMA_free(Ti); Ti = NULL;
10124          SUMA_RETURN(NOPE);
10125       }
10126 
10127       /* all done */
10128       SUMA_LH("Added the index column, ciao");
10129       if (Ti) SUMA_free(Ti); Ti = NULL;
10130       SUMA_RETURN(YUP);
10131    } else {
10132       SUMA_LH( "Node index column found, element might be empty however.\n"
10133                "Use SUMA_PopulateDsetNodeIndexNel to fill it.");
10134       /* Nothing to do, return on a positive note */
10135       SUMA_RETURN(YUP);
10136    }
10137 
10138    SUMA_SL_Err("why are you here ?");
10139    SUMA_RETURN(NOPE);
10140 }
10141 
10142 /* Function now OK with Graph Datasets */
SUMA_PopulateDsetNodeIndexNel(SUMA_DSET * dset,int verb)10143 SUMA_Boolean SUMA_PopulateDsetNodeIndexNel(SUMA_DSET *dset, int verb)
10144 {
10145    static char FuncName[]={"SUMA_PopulateDsetNodeIndexNel"};
10146    int *Ti = NULL, *P1=NULL, *P2=NULL;
10147    int i, j, n;
10148 
10149    SUMA_ENTRY;
10150 
10151    if (!dset ) {
10152       SUMA_S_Err("NULL input dset");
10153    }
10154    if (SUMA_isCIFTIDset(dset)) {
10155       SUMA_S_Err("Have yet to work out the logic for this type");
10156       SUMA_RETURN(NOPE);
10157    }
10158    if (!dset->inel) {
10159       SUMA_S_Err("NULL dset->inel");
10160    }
10161 
10162    if (dset->inel && dset->inel->vec_num) {
10163       if (verb > 1) SUMA_S_Note("Dset has node indices. Will not alter list.\n");
10164    } else {
10165       if (SUMA_isGraphDset(dset)) {
10166          if (verb > 1)
10167             SUMA_S_Notev("Graph Dset matrix %ldx%ld, shape %d, veclen %d\n",
10168                           dset->Aux->matrix_size[0], dset->Aux->matrix_size[1],
10169                           dset->Aux->matrix_shape, SDSET_VECLEN(dset));
10170          if (dset->Aux->matrix_shape == MAT_HEEHAW ||
10171              dset->Aux->matrix_shape == MAT_NA ) {
10172             if (verb > 2) SUMA_S_Notev("Going for a setting (%s)\n",
10173                               NI_get_attribute(dset->dnel,"matrix_shape"));
10174             if (!SUMA_GDSET_Set_Aux_matrix_shape(dset)) {
10175                SUMA_S_Err("Failed to set matrix shape");
10176                SUMA_RETURN(NOPE);
10177             }
10178             if (verb > 2)
10179                SUMA_S_Notev("Now have Graph Dset matrix %ldx%ld "
10180                             "for %d elements, shape now %d\n",
10181                             dset->Aux->matrix_size[0], dset->Aux->matrix_size[1],
10182                             SDSET_VECLEN(dset),dset->Aux->matrix_shape);
10183          }
10184          Ti = (int *) SUMA_calloc(SDSET_VECALLOC(dset), sizeof(int));
10185          P1 = (int *) SUMA_calloc(SDSET_VECALLOC(dset), sizeof(int));
10186          P2 = (int *) SUMA_calloc(SDSET_VECALLOC(dset), sizeof(int));
10187          for (i=0; i <SDSET_VECLEN(dset); ++i) Ti[i]=i;
10188          switch (dset->Aux->matrix_shape) {
10189             case MAT_HEEHAW:
10190             default:
10191                SUMA_S_Err("Should not happen");
10192                SUMA_RETURN(NOPE);
10193             case MAT_TRI:
10194                for (j=0, n=0; j <dset->Aux->matrix_size[0]; ++j) {
10195                for (i=j+1; i <dset->Aux->matrix_size[0]; ++i) {
10196                   P1[n]=i;
10197                   P2[n]=j;
10198                   ++n;
10199                } }
10200                break;
10201             case MAT_TRI_DIAG:
10202                for (j=0, n=0; j <dset->Aux->matrix_size[0]; ++j) {
10203                for (i=j; i <dset->Aux->matrix_size[0]; ++i) {
10204                   P1[n]=i;
10205                   P2[n]=j;
10206                   ++n;
10207                } }
10208                break;
10209             case MAT_FULL:
10210                for (j=0, n=0; j <dset->Aux->matrix_size[0]; ++j) {
10211                for (i=0; i <dset->Aux->matrix_size[0]; ++i) {
10212                   P1[n]=i;
10213                   P2[n]=j;
10214                   ++n;
10215                } }
10216                break;
10217             case MAT_SPARSE:
10218                SUMA_S_Err("Should not have entered parent else");
10219                SUMA_RETURN(NOPE);
10220          }
10221 
10222          if (!SUMA_AddDsetNelCol (  dset, "Edge Index (inferred)",
10223                                     SUMA_NODE_INDEX, (void *)Ti, NULL, 1)) {
10224             SUMA_S_Err("Failed to add column");
10225             SUMA_RETURN(NOPE);
10226          }
10227          SUMA_free(Ti); Ti = NULL;
10228          if (!SUMA_AddDsetNelCol (  dset, "P1 Index (inferred)",
10229                                     SUMA_EDGE_P1_INDEX, (void *)P1, NULL, 1)) {
10230             SUMA_S_Err("Failed to add column");
10231             SUMA_RETURN(NOPE);
10232          }
10233          SUMA_free(P1); P1 = NULL;
10234          if (!SUMA_AddDsetNelCol (  dset, "P2 Index (inferred)",
10235                                     SUMA_EDGE_P2_INDEX, (void *)P2, NULL, 1)) {
10236             SUMA_S_Err("Failed to add column");
10237             SUMA_RETURN(NOPE);
10238          }
10239          SUMA_free(P2); P2 = NULL;
10240       } else {
10241          if (verb) SUMA_S_Note( "Assuming node indexing\n"
10242                         "is explicit. \n"
10243                         "1st row is for node 0\n"
10244                         "2nd is for node 1, etc.\n" );
10245          Ti = (int *) SUMA_calloc(SDSET_VECALLOC(dset), sizeof(int));
10246          for (i=0; i <SDSET_VECLEN(dset); ++i) Ti[i]=i;
10247          if (!SUMA_AddDsetNelCol (  dset, "Node Index (inferred)",
10248                                     SUMA_NODE_INDEX, (void *)Ti, NULL, 1)) {
10249             SUMA_S_Err("Failed to add column");
10250             SUMA_RETURN(NOPE);
10251          }
10252          SUMA_free(Ti); Ti = NULL;
10253       }
10254    }
10255 
10256    SUMA_RETURN(YUP);
10257 }
10258 
10259 
10260 /*!
10261    a wrapper to faciliate getting column types from
10262    both SUMA and AFNI formatted niml elements
10263    \sa SUMA_Col_Type
10264 */
SUMA_TypeOfColNumb(NI_element * nel,int ind)10265 SUMA_COL_TYPE SUMA_TypeOfColNumb(NI_element *nel, int ind)
10266 {
10267    static char FuncName[]={"SUMA_TypeOfColNumb"};
10268    int *ctpv = NULL;
10269    char *cnm = NULL;
10270    int_array *iar = NULL;
10271    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
10272    char stmp[100];
10273    SUMA_Boolean LocalHead = NOPE;
10274 
10275    SUMA_ENTRY;
10276 
10277    /* SUMA_SL_Warn("Obsolete, use new version.");
10278          still needed to convert old format to new one */
10279 
10280    if (!nel) {
10281       SUMA_SL_Err("NULL NI element");
10282       SUMA_RETURN(ctp);
10283    }
10284    if (ind < 0 || ind > (nel->vec_num - 1)) {
10285       SUMA_SL_Err("Bad index");
10286       SUMA_RETURN(ctp);
10287    }
10288 
10289    /* try SUMA's */
10290    snprintf (stmp,50*sizeof(char),"TypeCol_%d", ind);
10291    cnm = NI_get_attribute(nel, stmp);
10292    if (cnm) {
10293       SUMA_RETURN(SUMA_Col_Type(cnm));
10294    }
10295 
10296    /* try AFNI's */
10297    cnm = NI_get_attribute(nel, "ni_type");
10298    if (!cnm) NI_set_ni_type_atr(nel);
10299    cnm = NI_get_attribute(nel, "ni_type");
10300 
10301    if (cnm) {
10302       iar = decode_type_string( cnm );
10303       if (iar) {
10304          ctp = iar->ar[ind];   /* this is not the same as SUMA's column type, it is just data type */
10305          NI_free(iar->ar); NI_free(iar); iar = NULL;
10306          switch(ctp) {
10307             case SUMA_int:
10308                ctp = SUMA_NODE_INT;
10309                break;
10310             case SUMA_float:
10311                ctp = SUMA_NODE_FLOAT;
10312                break;
10313             case SUMA_byte:
10314                ctp = SUMA_NODE_BYTE;
10315                break;
10316             case SUMA_short:
10317                ctp = SUMA_NODE_SHORT;
10318                break;
10319             case SUMA_complex:
10320                ctp = SUMA_NODE_COMPLEX;
10321                break;
10322             default:
10323                SUMA_SL_Err("AFNI column type not supported at the moment.\n");
10324                ctp = SUMA_ERROR_COL_TYPE;
10325                break;
10326          }
10327          SUMA_RETURN(ctp);
10328       }
10329    }
10330 
10331    SUMA_SL_Err("Failed to determine type");
10332    SUMA_RETURN(ctp);
10333 }
10334 
10335 /*!
10336    \brief Load a surface-based dataset from disk
10337 
10338    \param Name (char *) THe name of the file
10339    \param form (SUMA_DSET_FORMAT *) The format of the file
10340                                   can choose SUMA_NO_DSET_FORMAT
10341                                   and have the function attempt
10342                                   to guess. In that case the function
10343                                   will set the value of form
10344    \return (SUMA_DSET *) dset
10345    The datset does not get associated with a surface (owner_id[0] = '\0')
10346    You'll have to do this manually later on if you wish
10347    You typically want to insert that dataset into SUMA's DsetList list...
10348 */
SUMA_LoadDset_ns(char * Name,SUMA_DSET_FORMAT * form,int verb)10349 SUMA_DSET *SUMA_LoadDset_ns (char *Name, SUMA_DSET_FORMAT *form, int verb)
10350 {
10351    SUMA_DSET *dset = SUMA_LoadDset_eng (Name, form,  verb);
10352    WorkErrLog_ns();
10353    return(dset);
10354 }
10355 
SUMA_LoadDset_eng(char * iName,SUMA_DSET_FORMAT * form,int verb)10356 SUMA_DSET *SUMA_LoadDset_eng (char *iName, SUMA_DSET_FORMAT *form, int verb)
10357 {
10358    static char FuncName[]={"SUMA_LoadDset_eng"};
10359    SUMA_DSET *dset = NULL, *dset_c = NULL;
10360    int *RowSel=NULL, *ColSel=NULL, *NodeSel=NULL, i, nfixed=0;
10361    char *Name=NULL;
10362    double range[2];
10363    int loc[2];
10364    byte *b_ColSel = NULL, *b_RowSel = NULL;
10365    SUMA_DSET_FORMAT fform = SUMA_NO_DSET_FORMAT;
10366    SUMA_PARSED_NAME *pn=NULL;
10367 
10368    SUMA_Boolean LocalHead = NOPE;
10369 
10370    SUMA_ENTRY;
10371 
10372    if (!iName) { SUMA_SL_Err("NULL Name"); goto GOODBYE; }
10373    if (!form) form = &fform;
10374 
10375    if (LocalHead) {
10376       fprintf(stderr,"%s: Have %s to work with\n", FuncName, iName);
10377    }
10378    /* parse the name please. */
10379    RowSel = ColSel = NodeSel = NULL;
10380    if (!(pn = SUMA_ParseFname(iName, NULL))) {
10381       SUMA_SL_Err("Failed to parse name"); goto GOODBYE;
10382    }
10383 
10384    if (pn->NodeSelect[0]!= '\0' && pn->RowSelect[0] != '\0') {
10385       SUMA_SL_Err("Cannot use Node and Row selectors simultaneously");
10386       goto GOODBYE;
10387    }
10388 
10389    /* Form the name */
10390    Name = SUMA_append_string(pn->Path, pn->FileName);
10391 
10392    if (*form == SUMA_NO_DSET_FORMAT) {  /* attempt to guess from extension */
10393       SUMA_LH("Attempting to guess dset format from extension\n");
10394       *form = SUMA_GuessFormatFromExtension(Name, NULL);
10395    }
10396 
10397 
10398    switch (*form) {
10399       case SUMA_NIML:
10400       case SUMA_ASCII_NIML:
10401       case SUMA_BINARY_NIML:
10402          SUMA_LH("Loading NIML Dset");
10403          dset = SUMA_LoadNimlDset(Name, verb);
10404          break;
10405       case SUMA_1D:
10406          SUMA_LH("Loading 1D Dset");
10407          dset = SUMA_Load1DDset_ns(Name, verb);
10408          break;
10409       case SUMA_ASCII_OPEN_DX_DSET:
10410          SUMA_LH("Loading DX Dset");
10411          dset = SUMA_LoadDXDset_ns(Name, verb);
10412          break;
10413       case SUMA_XML_DSET:
10414       case SUMA_XML_ASCII_DSET:
10415       case SUMA_XML_B64_DSET:
10416       case SUMA_XML_B64GZ_DSET:
10417          SUMA_LH("Loading GIFTI Dset");
10418          dset = SUMA_LoadGIFTIDset(Name, verb);
10419          break;
10420       case SUMA_NO_DSET_FORMAT:
10421          if (!dset) {
10422             SUMA_LH("Trying NIML Dset");
10423             dset = SUMA_LoadNimlDset(Name, 0); *form = SUMA_NIML;
10424          }
10425          if (!dset) {
10426             SUMA_LH("Trying 1D Dset");
10427             dset = SUMA_Load1DDset_ns(Name, 0); *form = SUMA_1D;
10428          }
10429          if (!dset) {
10430             SUMA_LH("Trying DX Dset");
10431             dset = SUMA_LoadDXDset_ns(Name, 0); *form = SUMA_ASCII_OPEN_DX_DSET;
10432          }
10433          break;
10434       default:
10435          if (verb)
10436             SUMA_PushErrLog("SLP_Err", "Bad format specification", FuncName);
10437          goto GOODBYE;
10438    }
10439 
10440    if (!dset) {
10441       if (verb) SUMA_PushErrLog("SL_Err","Failed to read dset", FuncName);
10442       goto GOODBYE;
10443    }
10444 
10445    if (LocalHead) {
10446       SUMA_ShowParsedFname(pn, NULL);
10447       SUMA_ShowDset(dset, 0, NULL);
10448    }
10449    /* Update filename field in dset */
10450    NI_set_attribute(dset->ngr, "filename", Name);
10451 
10452    /* repair floats */
10453    if (!SUMA_isEnv("AFNI_FLOATSCAN","NO")) {
10454       if (nfixed = SUMA_FloatScanDset(dset, 1, 1, 1, 0)) {
10455          if (verb) fprintf(SUMA_STDOUT,
10456              "++    Notice %s: %d NAN or INF values were set to 0 in dset\n\n",
10457                         FuncName,  nfixed);
10458       }
10459    }
10460 
10461    /* do we need to substitute with node indices only? */
10462    if (pn->only_index) {
10463       SUMA_DSET *ndset=NULL;
10464       void *ind=NULL;
10465       if (!(ind = SDSET_NODE_INDEX_COL(dset))) {
10466          SUMA_FreeDset(dset); dset = NULL;
10467          SUMA_SL_Err( "No node index column to work with.\n"
10468                      "This feature is meaningless with .1D\n"
10469                      "datasets. You can use the node\n"
10470                      "column's index directly for that.\n");
10471          goto GOODBYE;
10472       }
10473       ndset =  SUMA_EmptyCopyofDset( dset,
10474                                      NULL, 1, 0 );
10475       if (!SUMA_InsertDsetNelCol (  ndset, "Node Index Copy",
10476                                     SUMA_NODE_INT, ind,
10477                                     NULL ,1, 0)) {
10478             SUMA_S_Err("Failed to insert column");
10479       }
10480       if (SUMA_isGraphDset(dset)) {
10481          if (!(ind = SDSET_EDGE_P1_INDEX_COL(dset))){
10482             SUMA_FreeDset(dset); dset = NULL;
10483             SUMA_SL_Err( "This should not happen in ind above was OK.\n");
10484             goto GOODBYE;
10485          }
10486          if (!SUMA_InsertDsetNelCol (  ndset, "Edge P1 Index Copy",
10487                                     SUMA_NODE_INT, ind,
10488                                     NULL ,1, 0)) {
10489             SUMA_S_Err("Failed to insert column");
10490          }
10491          if (!(ind = SDSET_EDGE_P2_INDEX_COL(dset))){
10492             SUMA_FreeDset(dset); dset = NULL;
10493             SUMA_SL_Err( "This really should not happen in ind above was OK.\n");
10494             goto GOODBYE;
10495          }
10496          if (!SUMA_InsertDsetNelCol (  ndset, "Edge P2 Index Copy",
10497                                     SUMA_NODE_INT, ind,
10498                                     NULL ,1, 0)) {
10499             SUMA_S_Err("Failed to insert column");
10500          }
10501       }
10502       SUMA_FreeDset(dset); dset = ndset; ndset = NULL;
10503    }
10504 
10505    /* do we have column, row, or node selectors? */
10506    if (pn->NodeSelect[0]!= '\0') {
10507       /* go get the selector lists */
10508       if (!SUMA_GetDsetNodeIndexColRange(dset, range, loc, 1)) {
10509          SUMA_SL_Err("Can't get node index column range!");
10510          goto GOODBYE;
10511       }
10512       NodeSel = MCW_get_intlist( (int)range[1] ,
10513                                   pn->NodeSelect ) ;
10514       if (!NodeSel || !NodeSel[0]) {
10515          SUMA_SL_Err("Failed to get node selection");
10516          SUMA_FreeDset(dset); dset = NULL;
10517          goto GOODBYE;
10518       }
10519       if (LocalHead) {
10520          SUMA_LH("NodeSelection");
10521          fprintf(SUMA_STDERR,"   %d:", NodeSel[0]);
10522          for (i=1; i<=NodeSel[0]; ++i) fprintf(SUMA_STDERR,"   %d", NodeSel[i]);
10523          fprintf(SUMA_STDERR,"\n");
10524       }
10525    }
10526    if (pn->ColSelect[0]!= '\0') {
10527       char **AllLabels=NULL;
10528       if (pn->only_index) {
10529          SUMA_S_Err("Only index selection not allowed with column selection.");
10530          goto GOODBYE;
10531       }
10532       /* go get the selector lists */
10533       AllLabels = SUMA_AllDsetColLabels(dset);
10534       ColSel = MCW_get_labels_intlist( AllLabels, SDSET_VECNUM(dset) ,
10535                                        pn->ColSelect ) ;
10536       AllLabels = SUMA_FreeAllDsetColLabels(AllLabels);
10537 
10538       if (!ColSel || !ColSel[0]) {
10539          SUMA_SL_Err("Failed to get column selection");
10540          SUMA_FreeDset(dset); dset = NULL;
10541          goto GOODBYE;
10542       }
10543       if (LocalHead) {
10544          SUMA_LH("ColSelection");
10545          fprintf(SUMA_STDERR,"   %d:", ColSel[0]);
10546          for (i=1; i<=ColSel[0]; ++i) fprintf(SUMA_STDERR,"   %d", ColSel[i]);
10547          fprintf(SUMA_STDERR,"\n");
10548       }
10549    }
10550    if (pn->RowSelect[0]!= '\0') {
10551       /* go get the selector lists */
10552       RowSel = MCW_get_intlist( SDSET_VECFILLED(dset) , pn->RowSelect ) ;
10553       if (!RowSel || !RowSel[0]) {
10554          SUMA_SL_Err("Failed to get row selection");
10555          SUMA_FreeDset(dset); dset = NULL;
10556          goto GOODBYE;
10557       }
10558       if (LocalHead) {
10559          SUMA_LH("RowSelection");
10560          fprintf(SUMA_STDERR,"   %d:", RowSel[0]);
10561          for (i=1; i<=RowSel[0]; ++i) fprintf(SUMA_STDERR,"   %d", RowSel[i]);
10562          fprintf(SUMA_STDERR,"\n");
10563       }
10564    }
10565 
10566    if (pn->RangeSelect[0]!= '\0') {
10567       SUMA_SL_Err("Range selection not allowed with SUMA dsets.");
10568       SUMA_FreeDset(dset); dset = NULL;
10569       goto GOODBYE;
10570    }
10571 
10572    if (ColSel) {
10573       if (!(b_ColSel =
10574          SUMA_indexlist_2_bytemask((ColSel+1), ColSel[0],
10575                                     SDSET_VECNUM(dset), NULL))) {
10576          SUMA_SL_Err("Failed in creating byte mask");
10577          SUMA_FreeDset(dset); dset = NULL;
10578          goto GOODBYE;
10579       }
10580    } else b_ColSel = NULL;
10581 
10582    if (RowSel) {
10583       if (!(b_RowSel =  SUMA_indexlist_2_bytemask((RowSel+1), RowSel[0],
10584                                                    SDSET_VECFILLED(dset),
10585                                                    NULL))) {
10586          SUMA_SL_Err("Failed in creating byte mask");
10587          SUMA_FreeDset(dset); dset = NULL;
10588          goto GOODBYE;
10589       }
10590    } else b_RowSel = NULL;
10591 
10592    if (NodeSel) {
10593       if (!(dset_c = SUMA_MaskedByNodeIndexCopyofDset(dset, (NodeSel+1),
10594                                                       NodeSel[0], b_ColSel, 1,
10595                                                       0))) {
10596          SUMA_SL_Err("Failed in creating masked dset");
10597          SUMA_FreeDset(dset); dset = NULL;
10598          goto GOODBYE;
10599       }
10600       SUMA_FreeDset(dset); dset = dset_c; dset_c = NULL;
10601    }else if (RowSel || ColSel) {
10602       if (!(dset_c = SUMA_MaskedCopyofDset(dset, b_RowSel, b_ColSel, 1, 0))) {
10603          SUMA_SL_Err("Failed in creating masked dset");
10604          SUMA_FreeDset(dset); dset = NULL;
10605          goto GOODBYE;
10606       }
10607       SUMA_FreeDset(dset); dset = dset_c; dset_c = NULL;
10608    }
10609 
10610    /* set do_type */
10611    if (SUMA_isGraphDset(dset)) dset->do_type = GDSET_type;
10612    else if (SUMA_isCIFTIDset(dset)) {
10613       SUMA_LH("Found no need to flag CIFTI dset as anything other\n"
10614               "than generic dataset");
10615    }
10616    GOODBYE:
10617    if (b_ColSel) SUMA_free(b_ColSel); b_ColSel = NULL;
10618    if (b_RowSel) SUMA_free(b_RowSel); b_RowSel = NULL;
10619    if (ColSel) free(ColSel); ColSel = NULL;
10620    if (NodeSel) free (NodeSel); NodeSel = NULL;
10621    if (RowSel)   free(RowSel); RowSel = NULL;
10622    if (pn) SUMA_Free_Parsed_Name(pn); pn = NULL;
10623 
10624    SUMA_RETURN(dset);
10625 }
10626 
10627 static int AddIndex_1D = 0;
SUMA_SetAddIndex_1D(int v)10628 void SUMA_SetAddIndex_1D(int v) { AddIndex_1D=v; return; }
SUMA_GetAddIndex_1D(void)10629 int SUMA_GetAddIndex_1D(void) { return(AddIndex_1D); }
10630 
SUMA_WriteDset_NameCheck_ns(char * Name,SUMA_DSET * dset,SUMA_DSET_FORMAT form,int verb,char ** NameOutp)10631 int SUMA_WriteDset_NameCheck_ns (
10632             char *Name, SUMA_DSET *dset,
10633             SUMA_DSET_FORMAT form, int verb, char **NameOutp)
10634 {
10635    int exists = SUMA_WriteDset_NameCheck_eng(Name, dset, form, verb, NameOutp);
10636    WorkErrLog_ns();
10637    return(exists);
10638 }
10639 
SUMA_WriteDset_NameCheck_eng(char * Name,SUMA_DSET * dset,SUMA_DSET_FORMAT form,int verb,char ** NameOutp)10640 int SUMA_WriteDset_NameCheck_eng (  char *Name, SUMA_DSET *dset,
10641                                     SUMA_DSET_FORMAT form,
10642                                     int verb, char **NameOutp)
10643 {
10644    static char FuncName[]={"SUMA_WriteDset_NameCheck_eng"};
10645    int exists = 0;
10646    char *PrefOut=NULL, *NameOut=NULL;
10647    SUMA_Boolean LocalHead = NOPE;
10648 
10649    SUMA_ENTRY;
10650 
10651    if (!Name && dset && dset->ngr && !SUMA_IS_DSET_STDXXX_FORMAT(form)) {
10652       if (!(Name=NI_get_attribute(dset->ngr, "filename"))) {
10653       SUMA_PushErrLog("SL_Err","NULL Name", FuncName); SUMA_RETURN(-1);
10654       }
10655    }
10656 
10657    if (!SUMA_IS_DSET_STDXXX_FORMAT(form)) {
10658       PrefOut = SUMA_RemoveDsetExtension_ns(Name, form);
10659       if (!PrefOut) {
10660          SUMA_PushErrLog(  "SL_Err",
10661                            "Failed clean dset name", FuncName);
10662          SUMA_RETURN(-1);
10663       }
10664       SUMA_LH("%s", PrefOut);
10665    }
10666 
10667    if (form == SUMA_NO_DSET_FORMAT) {
10668       form = SUMA_GuessFormatFromExtension(Name, NULL);
10669    }
10670    switch (form) {
10671       case SUMA_XML_DSET:
10672       case SUMA_XML_ASCII_DSET:
10673       case SUMA_XML_B64_DSET:
10674       case SUMA_XML_B64GZ_DSET:
10675          if (SUMA_isExtension(Name,".gii")) { /* allow .gii only */
10676             NameOut = SUMA_Extension(PrefOut, ".gii", NOPE);
10677          } else {
10678             NameOut = SUMA_Extension(PrefOut, ".gii.dset", NOPE);
10679          }
10680          if (SUMA_filexists(NameOut)) {
10681             exists = 1;
10682          }
10683          break;
10684       case SUMA_NIML:
10685       case SUMA_ASCII_NIML:
10686       case SUMA_BINARY_NIML:
10687          NameOut = SUMA_Extension(PrefOut, ".niml.dset", NOPE);
10688          if (SUMA_filexists(NameOut)) {
10689             exists = 1;
10690          }
10691          break;
10692       case SUMA_1D:
10693          NameOut = SUMA_Extension(PrefOut, ".1D.dset", NOPE);
10694          if (SUMA_filexists(NameOut)) {
10695             exists = 1;
10696          }
10697          break;
10698       case SUMA_1D_PURE:
10699          NameOut = SUMA_Extension(PrefOut, ".1D.dset", NOPE);
10700          if (SUMA_filexists(NameOut)) {
10701             exists = 1;
10702          }
10703          break;
10704       case SUMA_1D_PURE_TRANSPOSE:
10705          NameOut = SUMA_Extension(PrefOut, ".1D.dset", NOPE);
10706          if (SUMA_filexists(NameOut)) {
10707             exists = 1;
10708          }
10709          break;
10710       case SUMA_NIML_STDERR:
10711       case SUMA_NIML_STDOUT:
10712       case SUMA_1D_PURE_STDOUT:
10713       case SUMA_1D_PURE_STDERR:
10714       case SUMA_1D_PURE_STDOUT_TRANSPOSE:
10715       case SUMA_1D_PURE_STDERR_TRANSPOSE:
10716       case SUMA_1D_STDOUT:
10717       case SUMA_1D_STDERR:
10718          break;
10719       case SUMA_NO_DSET_FORMAT:
10720          /* try them all */
10721          exists = -1;
10722          {
10723             SUMA_DSET_FORMAT zform=SUMA_NO_DSET_FORMAT+1;
10724             while (exists != 1 && zform < SUMA_N_DSET_FORMATS) {
10725                exists = SUMA_WriteDset_NameCheck_eng(
10726                            Name, dset, zform, verb, &NameOut);
10727                if (exists == 1) form=zform;
10728                ++zform;
10729             }
10730          }
10731          break;
10732       default:
10733          SUMA_PushErrLog("SLP_Err","Bad format specification", FuncName);
10734          exists = -1;
10735          break;
10736    }
10737 
10738 
10739 
10740    if (NameOutp && !SUMA_IS_DSET_STDXXX_FORMAT(form)) {
10741       SUMA_LH("%s", NameOut);
10742       *NameOutp = NameOut; NameOut = NULL;
10743    } else {
10744       if (NameOut) SUMA_free(NameOut); NameOut = NULL;
10745    }
10746    if (PrefOut) SUMA_free(PrefOut); PrefOut = NULL;
10747    SUMA_RETURN(exists);
10748 }
10749 
10750 /*!
10751    \brief writes a dataset to disk
10752    \param Name (char *) Name of output file.
10753    \param dset (SUMA_DSET *) Le dataset
10754    \param form (SUMA_DSET_FORMAT ) Le format
10755    \return OutName (char *)The name used for the output file
10756                            (you have to free that one yourself)
10757                            NULL if things went bad.
10758    - Be careful, this function will not change the idcode of the
10759    dataset being written. You'll have to do that manually.
10760 */
SUMA_WriteDset_ns(char * Name,SUMA_DSET * dset,SUMA_DSET_FORMAT form,int overwrite,int verb)10761 char * SUMA_WriteDset_ns ( char *Name, SUMA_DSET *dset,
10762                            SUMA_DSET_FORMAT form,
10763                            int overwrite, int verb)
10764 {
10765    char *c=SUMA_WriteDset_eng (Name, dset, form, overwrite, verb, 1);
10766    WorkErrLog_ns();
10767    return(c);
10768 }
10769 
10770 
SUMA_WriteDset_eng(char * Name,SUMA_DSET * dset,SUMA_DSET_FORMAT form,int overwrite,int verb,int rename_autoid)10771 char * SUMA_WriteDset_eng (char *Name, SUMA_DSET *dset,
10772                            SUMA_DSET_FORMAT form,
10773                            int overwrite, int verb,
10774                            int rename_autoid)
10775 {
10776    static char FuncName[]={"SUMA_WriteDset_eng"};
10777    char *NameOut = NULL, *strmname=NULL, stmp[500], *eee=NULL, *oName=NULL;
10778    int flg = 0, exists = 0, goutmode=-1, eoutmode = -1;
10779    SUMA_Boolean LocalHead = NOPE;
10780 
10781    SUMA_ENTRY;
10782 
10783    if (LocalHead) verb = 3;
10784    if (!dset) {
10785       SUMA_PushErrLog("SL_Err", "NULL dset", FuncName);
10786       SUMA_RETURN(NameOut);
10787    }
10788    if (LocalHead) {
10789       SUMA_LH("About to write dset to %s", Name);
10790       SUMA_ShowDset(dset, 0, NULL);
10791    }
10792    if (!dset->ngr) {
10793       SUMA_PushErrLog("SL_Err","NULL dset->ngr", FuncName);
10794       SUMA_RETURN(NameOut);
10795    }
10796 
10797    if (!Name) {
10798       if (!(Name=SDSET_FILENAME(dset))) {
10799          SUMA_PushErrLog("SL_Err","NULL Name and no filename",
10800                          FuncName); SUMA_RETURN(NameOut);
10801       }
10802    } else if (Name != SDSET_FILENAME(dset)) /* yes, a pointer comparison */{
10803       /* call rename dset, unless they passed SDSET_FILENAME(dset) for name!*/
10804       if (!SUMA_RenameDset(dset, Name, rename_autoid)) {
10805          SUMA_PushErrLog(  "SL_Err",
10806                            "Failed to rename dset",
10807                            FuncName);
10808          SUMA_RETURN(NameOut);
10809       }
10810    }
10811 
10812    if (form == SUMA_NO_DSET_FORMAT) {
10813       form = SUMA_GuessFormatFromExtension (Name, "lazybum.niml.dset");
10814    }
10815 
10816    if (( exists =
10817          SUMA_WriteDset_NameCheck_ns (Name, dset, form, verb, &NameOut) ) < 0) {
10818       SUMA_PushErrLog("SLP_Err","Failed to check name", FuncName);
10819       SUMA_RETURN(NameOut);
10820    }
10821 
10822    /* take care of ambiguous NIML form */
10823    if (form == SUMA_NIML) {
10824       if (AFNI_yesenv("AFNI_NIML_TEXT_DATA")) {
10825          form = SUMA_ASCII_NIML;
10826       } else {
10827          form = SUMA_BINARY_NIML;
10828       }
10829    }
10830 
10831    /* turn off outmode, me no use it */
10832    if (dset->ngr->outmode >= 0) {
10833       goutmode = dset->ngr->outmode;
10834       dset->ngr->outmode = -1;
10835    }
10836    if (dset->dnel->outmode >= 0) {
10837       eoutmode = dset->dnel->outmode;
10838       dset->dnel->outmode = -1;
10839    }
10840 
10841 
10842    if (exists && overwrite) {
10843       exists = 0;
10844       if (verb)
10845          fprintf( SUMA_STDOUT,
10846                   "Notice %s: Overwriting existing file %s ...\n",
10847                   FuncName, NameOut);
10848    }
10849 
10850    if (!exists) {
10851       switch (form) {
10852          case SUMA_XML_DSET:
10853          case SUMA_XML_ASCII_DSET:
10854          case SUMA_XML_B64_DSET:
10855          case SUMA_XML_B64GZ_DSET:
10856             {
10857                int aaa;
10858                if (form == SUMA_XML_B64GZ_DSET)
10859                   aaa = NI_write_gifti(dset->ngr, NameOut,3);
10860                         /* GIFTI_ENCODING_B64GZ */
10861                else if (form == SUMA_XML_B64_DSET)
10862                   aaa = NI_write_gifti(dset->ngr, NameOut,2);
10863                         /* GIFTI_ENCODING_B64 */
10864                else if (form == SUMA_XML_ASCII_DSET)
10865                   aaa = NI_write_gifti(dset->ngr, NameOut,1);
10866                         /* GIFTI_ENCODING_ASCII */
10867                else aaa = NI_write_gifti(dset->ngr, NameOut, 0);
10868                if (aaa){
10869                   SUMA_PushErrLog(  "SL_Err",
10870                                     "Failed to write GIFTI dset", FuncName);
10871                   flg = 0;
10872                } else flg = 1;
10873             }
10874             break;
10875          case SUMA_NIML:
10876          case SUMA_ASCII_NIML:
10877          case SUMA_BINARY_NIML:
10878             {
10879                strmname = SUMA_append_string("file:",NameOut);
10880                NI_set_attribute(dset->ngr,"filename", NameOut);
10881                if (form == SUMA_ASCII_NIML) {
10882                  SUMA_LH("Writing NIML, ASCII...%s",strmname);
10883                  NEL_WRITE_TX (dset->ngr, strmname, flg);
10884                  SUMA_LH("DONE.");
10885                } else {
10886                  SUMA_LH("Writing NIML, BINARY...%s",strmname);
10887                  NEL_WRITE_BI (dset->ngr, strmname, flg);
10888                  SUMA_LH("DONE.");
10889                }
10890                if (!flg) {
10891                   SUMA_PushErrLog(  "SL_Err",
10892                                     "Failed to write niml element", FuncName);
10893                } else {
10894                   SUMA_LH("DONE.");
10895                }
10896             }
10897             break;
10898          case SUMA_NIML_STDERR:
10899          case SUMA_NIML_STDOUT:
10900             if (form == SUMA_NIML_STDOUT) {
10901               SUMA_LH("Writing NIML, STDOUT...%s", strmname);
10902               NEL_WRITE_TX (dset->ngr, "stdout:", flg);
10903               SUMA_LH("DONE.");
10904             } else {
10905               SUMA_LH("Writing NIML, STDERR...%s", strmname);
10906               NEL_WRITE_TX (dset->ngr, "stderr:", flg);
10907               SUMA_LH("DONE.");
10908             }
10909             if (!flg) {
10910                SUMA_PushErrLog("SL_Err","Failed to write element", FuncName);
10911             } else {
10912                SUMA_LH("DONE.");
10913             }
10914             break;
10915          case SUMA_1D:
10916             {
10917                NI_set_attribute(dset->ngr,"filename", NameOut);
10918                strmname = SUMA_append_string("file:",NameOut);
10919 	            SUMA_LH("Writing 1D...%s", strmname);
10920                DSET_WRITE_1D (dset, strmname, flg, AddIndex_1D);
10921                if (!flg) {
10922                   SUMA_PushErrLog("SL_Err","Output file not written", FuncName);
10923                } else {
10924                   SUMA_LH("DONE.");
10925                }
10926             }
10927             break;
10928          case SUMA_1D_PURE:
10929             {
10930                NI_set_attribute(dset->ngr,"filename", NameOut);
10931                strmname = SUMA_copy_string(NameOut);
10932 	            SUMA_LH("Writing 1D pure...%s", strmname);
10933                DSET_WRITE_1D_PURE (dset, strmname, flg, AddIndex_1D);
10934                if (!flg) {
10935                   SUMA_PushErrLog("SL_Err","Output file not written", FuncName);
10936                } else {
10937                   SUMA_LH("DONE.");
10938                }
10939             }
10940             break;
10941          case SUMA_1D_PURE_TRANSPOSE:
10942             {
10943                NI_set_attribute(dset->ngr,"filename", NameOut);
10944                strmname = SUMA_copy_string(NameOut);
10945 	            SUMA_LH("Writing 1D pure transpose...%s", strmname);
10946                DSET_WRITE_1D_PURE_TRANSPOSE (dset, strmname, flg, AddIndex_1D);
10947                if (!flg) {
10948                   SUMA_PushErrLog("SL_Err","Output file not written", FuncName);
10949                } else {
10950                   SUMA_LH("DONE.");
10951                }
10952             }
10953             break;
10954          case SUMA_1D_PURE_STDOUT:
10955             {
10956                NI_set_attribute(dset->ngr,"filename", "stdout");
10957 	            SUMA_LH("Writing 1D pure...%s", strmname);
10958                DSET_WRITE_1D_PURE (dset, "stdout", flg, AddIndex_1D);
10959                {
10960                   SUMA_LH("DONE.");
10961                }
10962             }
10963             break;
10964          case SUMA_1D_PURE_STDERR:
10965             {
10966                NI_set_attribute(dset->ngr,"filename", "stderr");
10967 	            SUMA_LH("Writing 1D pure...%s", strmname);
10968                DSET_WRITE_1D_PURE (dset, "stderr", flg, AddIndex_1D);
10969                {
10970                   SUMA_LH("DONE.");
10971                }
10972             }
10973             break;
10974          case SUMA_1D_PURE_STDOUT_TRANSPOSE:
10975             {
10976                NI_set_attribute(dset->ngr,"filename","stdout");
10977 	            SUMA_LH("Writing 1D pure transpose...%s", strmname)
10978                DSET_WRITE_1D_PURE_TRANSPOSE (dset, "stdout", flg, AddIndex_1D);
10979                {
10980                   SUMA_LH("DONE.");
10981                }
10982             }
10983             break;
10984          case SUMA_1D_PURE_STDERR_TRANSPOSE:
10985             {
10986                NI_set_attribute(dset->ngr,"filename","stderr");
10987 	            SUMA_LH("Writing 1D pure transpose...%s", strmname);
10988                DSET_WRITE_1D_PURE_TRANSPOSE (dset, "stderr", flg, AddIndex_1D);
10989                {
10990                   SUMA_LH("DONE.");
10991                }
10992             }
10993             break;
10994          case SUMA_1D_STDOUT:
10995             DSET_WRITE_1D (dset, "stdout:", flg, AddIndex_1D);
10996             if (!flg) {
10997                SUMA_PushErrLog("SL_Err","Output file not written", FuncName);
10998             } else {
10999                SUMA_LH("DONE.");
11000             }
11001             break;
11002          case SUMA_1D_STDERR:
11003             DSET_WRITE_1D (dset, "stderr:", flg, AddIndex_1D);
11004             if (!flg) {
11005                SUMA_PushErrLog("SL_Err","Output file not written", FuncName);
11006             } else {
11007                SUMA_LH("DONE.");
11008             }
11009             break;
11010          case SUMA_NO_DSET_FORMAT:
11011             SUMA_PushErrLog("SLP_Err","Must specify output format", FuncName);
11012             break;
11013          default:
11014             SUMA_PushErrLog("SLP_Err","Bad format specification", FuncName);
11015             break;
11016       }
11017 
11018       if (!NameOut || !flg) {
11019          if (verb)
11020             SUMA_PushErrLog("SLP_Err","Failed writing dataset.", FuncName);
11021          if (NameOut) SUMA_free(NameOut); NameOut = NULL;
11022       }
11023    } else {
11024       snprintf(stmp, 500*sizeof(char),
11025                "Output file %s exists.\n Will not overwrite.", NameOut);
11026       SUMA_PushErrLog("SLP_Err",stmp, FuncName);
11027       if (NameOut) SUMA_free(NameOut); NameOut = NULL;
11028    }
11029 
11030    if (strmname) SUMA_free(strmname); strmname = NULL;
11031 
11032    if (goutmode >= 0) { dset->ngr->outmode = goutmode ; }
11033    if (eoutmode >= 0) { dset->dnel->outmode = eoutmode ; }
11034 
11035    SUMA_RETURN(NameOut);
11036 }
11037 
11038 /*!
11039    \brief Guess file format from extension
11040    \param Name (char *) name
11041    \return form SUMA_DSET_FORMAT
11042 */
SUMA_GuessFormatFromExtension_core(char * Name)11043 SUMA_DSET_FORMAT SUMA_GuessFormatFromExtension_core(char *Name)
11044 {
11045    static char FuncName[]={"SUMA_GuessFormatFromExtension_core"};
11046    SUMA_DSET_FORMAT form = SUMA_NO_DSET_FORMAT;
11047    SUMA_PARSED_NAME *fn=NULL;
11048    SUMA_Boolean LocalHead = NOPE;
11049 
11050    SUMA_ENTRY;
11051 
11052    if (!Name) { SUMA_RETURN(form); }
11053 
11054    fn=SUMA_ParseFname (Name, NULL);
11055    if (LocalHead) SUMA_ShowParsedFname(fn, NULL);
11056 
11057    if (SUMA_isExtension(fn->FileName, ".niml.dset") ||
11058        SUMA_isExtension(fn->FileName, ".niml.do") ||
11059        SUMA_isExtension(fn->FileName, ".niml.mo") ||
11060        SUMA_isExtension(fn->FileName, ".niml.tract") )
11061       form = SUMA_NIML;
11062    else if (  SUMA_isExtension(fn->FileName, ".gii.dset") ||
11063          SUMA_isExtension(fn->FileName, ".gii") )
11064       form = SUMA_XML_DSET;
11065    else if (SUMA_isExtension(fn->FileName, ".1D.dset"))
11066       form = SUMA_1D;
11067    else if (SUMA_isExtension(fn->FileName, ".niml.cmap"))
11068       form = SUMA_NIML;
11069    else if (SUMA_isExtension(fn->FileName, ".1D.cmap"))
11070       form = SUMA_1D;
11071    else if (SUMA_isExtension(fn->FileName, ".dx.dset"))
11072       form = SUMA_ASCII_OPEN_DX_DSET;
11073    else if (SUMA_isExtension(fn->FileName, ".dx"))
11074       form = SUMA_ASCII_OPEN_DX_DSET;
11075    else if (SUMA_isExtension(fn->FileName, ".1D"))
11076       form = SUMA_1D;
11077 
11078    SUMA_Free_Parsed_Name(fn); fn = NULL;
11079 
11080    SUMA_RETURN(form);
11081 }
11082 
SUMA_GuessFormatFromExtension(char * Name,char * fallbackname)11083 SUMA_DSET_FORMAT SUMA_GuessFormatFromExtension(char *Name, char *fallbackname)
11084 {
11085    static char FuncName[]={"SUMA_GuessFormatFromExtension"};
11086    SUMA_DSET_FORMAT form = SUMA_NO_DSET_FORMAT;
11087 
11088    SUMA_ENTRY;
11089 
11090    if (!Name && fallbackname) {Name = fallbackname;}
11091 
11092    form = SUMA_GuessFormatFromExtension_core(Name);
11093    if (form <= SUMA_NO_DSET_FORMAT && fallbackname && Name != fallbackname ) { /* try with fallback */
11094       form = SUMA_GuessFormatFromExtension_core(fallbackname);
11095    }
11096 
11097    SUMA_RETURN(form);
11098 }
11099 
11100 
SUMA_ExtensionOfDsetFormat(SUMA_DSET_FORMAT form)11101 const char *SUMA_ExtensionOfDsetFormat (SUMA_DSET_FORMAT form)
11102 {
11103    static char FuncName[]={"SUMA_ExtensionOfDsetFormat"};
11104 
11105    SUMA_ENTRY;
11106 
11107    switch (form) {
11108       case SUMA_NIML:
11109       case SUMA_ASCII_NIML:
11110       case SUMA_BINARY_NIML:
11111          SUMA_RETURN(".niml.dset");
11112       case SUMA_1D:
11113          SUMA_RETURN(".1D.dset");
11114       case SUMA_ASCII_OPEN_DX_DSET:
11115          SUMA_RETURN(".dx.dset");
11116       case SUMA_XML_DSET:
11117       case SUMA_XML_ASCII_DSET:
11118       case SUMA_XML_B64_DSET:
11119       case SUMA_XML_B64GZ_DSET:
11120          SUMA_RETURN(".gii.dset");
11121       default:
11122          SUMA_RETURN("");
11123    }
11124 
11125    SUMA_RETURN("huh");
11126 }
11127 
11128 /*!
11129    \brief Removes the standard extension from a dataset filename
11130    \param Name (char *) name
11131    \param form SUMA_DSET_FORMAT
11132    \return (char *) no_extension (you have to free that one with SUMA_free)
11133 */
SUMA_RemoveDsetExtension_ns(char * Name,SUMA_DSET_FORMAT form)11134 char *SUMA_RemoveDsetExtension_ns (char*Name, SUMA_DSET_FORMAT form)
11135 {
11136    char *c=SUMA_RemoveDsetExtension_eng (Name,  &form);
11137    WorkErrLog_ns();
11138    return(c);
11139 }
11140 
11141 /* Removes the standard extension && sets the format upon return
11142    if the format was SUMA_NO_DSET_FORMAT */
SUMA_RemoveDsetExtension_eng(char * Name,SUMA_DSET_FORMAT * form)11143 char *SUMA_RemoveDsetExtension_eng (char*Name, SUMA_DSET_FORMAT *form)
11144 {
11145    static char FuncName[]={"SUMA_RemoveDsetExtension_eng"};
11146    char *noex = NULL, *tmp = NULL;
11147    SUMA_DSET_FORMAT formo=*form;
11148 
11149    SUMA_ENTRY;
11150 
11151    if (!Name) { SUMA_SL_Err("NULL Name"); SUMA_RETURN(NULL); }
11152 
11153    switch (*form) {
11154       case SUMA_NIML:
11155       case SUMA_ASCII_NIML:
11156       case SUMA_BINARY_NIML:
11157          noex  =  SUMA_Extension(Name, ".niml.dset", YUP);
11158          break;
11159       case SUMA_1D:
11160       case SUMA_1D_PURE:
11161       case SUMA_1D_PURE_TRANSPOSE:
11162          tmp  =  SUMA_Extension(Name, ".1D", YUP);
11163          noex  =  SUMA_Extension(tmp, ".1D.dset", YUP);
11164             SUMA_free(tmp); tmp = NULL;
11165          break;
11166       case SUMA_ASCII_OPEN_DX_DSET:
11167          tmp  =  SUMA_Extension(Name, ".dx", YUP);
11168          noex  =  SUMA_Extension(tmp, ".dx.dset", YUP);
11169             SUMA_free(tmp); tmp = NULL;
11170          break;
11171       case SUMA_NO_DSET_FORMAT:
11172          tmp  =  SUMA_Extension(Name, ".1D", YUP);
11173             if (strcmp(tmp,Name)) formo=SUMA_1D;
11174          noex = SUMA_Extension(tmp, ".1D.dset", YUP);
11175             if (strcmp(noex,tmp)) formo=SUMA_1D;
11176             SUMA_free(tmp); tmp = NULL; tmp = noex;
11177          noex = SUMA_Extension(tmp, ".niml.dset", YUP);
11178             if (strcmp(noex,tmp)) formo=SUMA_NIML;
11179             SUMA_free(tmp); tmp = NULL; tmp = noex;
11180          noex  =  SUMA_Extension(tmp, ".gii", YUP);
11181             if (strcmp(noex,tmp)) formo=SUMA_XML_DSET;
11182             SUMA_free(tmp); tmp = NULL; tmp = noex;
11183          noex  =  SUMA_Extension(tmp, ".gii.dset", YUP);
11184             if (strcmp(noex,tmp)) formo=SUMA_XML_DSET;
11185             SUMA_free(tmp); tmp = NULL; tmp = noex;
11186          noex  =  SUMA_Extension(tmp, ".dx", YUP);
11187             if (strcmp(noex,tmp)) formo=SUMA_ASCII_OPEN_DX_DSET;
11188             SUMA_free(tmp); tmp = NULL; tmp = noex;
11189          noex  =  SUMA_Extension(tmp, ".dx.dset", YUP);
11190             if (strcmp(noex,tmp)) formo=SUMA_ASCII_OPEN_DX_DSET;
11191             SUMA_free(tmp); tmp = NULL;
11192          break;
11193       case SUMA_XML_DSET:
11194       case SUMA_XML_ASCII_DSET:
11195       case SUMA_XML_B64_DSET:
11196       case SUMA_XML_B64GZ_DSET:
11197          tmp  =  SUMA_Extension(Name, ".gii", YUP);
11198          noex  =  SUMA_Extension(tmp, ".gii.dset", YUP);
11199             SUMA_free(tmp); tmp = NULL;
11200          break;
11201       case SUMA_NIML_STDOUT:
11202       case SUMA_NIML_STDERR:
11203       case SUMA_1D_STDOUT:
11204       case SUMA_1D_STDERR:
11205       case SUMA_1D_PURE_STDOUT:
11206       case SUMA_1D_PURE_STDERR:
11207       case SUMA_1D_PURE_STDOUT_TRANSPOSE:
11208       case SUMA_1D_PURE_STDERR_TRANSPOSE:
11209          noex = SUMA_copy_string(Name);
11210          break;
11211       default:
11212          SUMA_PushErrLog("SLP_Err","Bad format specification", FuncName);
11213          break;
11214    }
11215 
11216    *form=formo;
11217    SUMA_RETURN(noex);
11218 }
11219 
11220 /*!
11221    \brief a function to turn the old dataset NI_element to the new
11222    dataset NI_group structure. Only essentials are preserved. Some
11223    of the attributes will remain empty in the data element, no simple
11224    way at the moment to remove attributes from a nel
11225 */
SUMA_oDsetNel2nDsetNgr(NI_element * nel)11226 NI_group *SUMA_oDsetNel2nDsetNgr(NI_element *nel)
11227 {
11228    static char FuncName[]={"SUMA_oDsetNel2nDsetNgr"};
11229    NI_group *ngr = NULL;
11230    NI_element *nelb = NULL;
11231    char *idcode=NULL, *dname=NULL, *col_label = NULL, *stmp=NULL;
11232    int ctp, i, iiidata=0, iiinel = 0;
11233    NI_element *dnel = NULL, *inel = NULL;
11234    SUMA_DSET dset; /* dummy */
11235    SUMA_Boolean LocalHead = NOPE;
11236 
11237    SUMA_ENTRY;
11238 
11239    ngr = NI_new_group_element();
11240    NI_rename_group(ngr, nel->name);
11241 
11242    /* copy the ID */
11243    idcode = NI_get_attribute(nel,"idcode");
11244    if (!idcode) idcode = NI_get_attribute(nel,"ni_idcode");
11245    if (idcode) {
11246       NI_set_attribute(ngr, "self_idcode", idcode);
11247    } else {
11248       SUMA_NEW_ID(idcode, NULL);
11249       NI_set_attribute(ngr, "self_idcode", idcode);
11250       SUMA_free(idcode); idcode = NULL;
11251    }
11252    /* the domain parent */
11253    idcode = NI_get_attribute(nel,"DomParent_idcode");
11254    if (idcode) {
11255       NI_set_attribute(ngr, "domain_parent_idcode", idcode);
11256    } else {
11257       NI_set_attribute(ngr, "domain_parent_idcode", NULL);
11258    }
11259 
11260    /* the geometry domain parent */
11261    idcode = NI_get_attribute(nel,"geometry_parent_idcode");
11262    if (idcode) {
11263       NI_set_attribute(ngr, "geometry_parent_idcode", idcode);
11264    } else {
11265       NI_set_attribute(ngr, "geometry_parent_idcode", NULL);
11266    }
11267 
11268    /* form the data nel */
11269    SUMA_LH("Doing dnel");
11270    dname = SUMA_append_string(NEL_DSET_TYPE(ngr), "_data");
11271    dnel = NI_new_data_element("SPARSE_DATA", nel->vec_len);
11272    NI_set_attribute (dnel, "data_type", dname);
11273    SUMA_free(dname); dname = NULL;
11274    NI_add_to_group(ngr, dnel);
11275 
11276    /* Now add the node index element */
11277    SUMA_LH("Doing inel");
11278    dname = SUMA_append_string(NEL_DSET_TYPE(ngr), "_node_indices");
11279    inel = NI_new_data_element("INDEX_LIST", nel->vec_len);
11280    NI_set_attribute (inel, "data_type", dname);
11281    SUMA_free(dname); dname = NULL;
11282    NI_add_to_group(ngr, inel);
11283 
11284    /* now, manually add the columns' spots */
11285    for (i=0; i<nel->vec_num; ++ i) {
11286       SUMA_LH("Adding cols");
11287       ctp = SUMA_TypeOfColNumb(nel, i);
11288       if (ctp != SUMA_NODE_INDEX) {
11289          switch (SUMA_ColType2TypeCast(ctp)) {
11290             /* MUST use the old function SUMA_TypeOfColNumb here ! */
11291             case SUMA_int:
11292                SUMA_LH("int");
11293                NI_add_column_stride ( dnel, NI_INT, NULL, 1);
11294                break;
11295             case SUMA_float:
11296                SUMA_LH("float");
11297                NI_add_column_stride ( dnel, NI_FLOAT, NULL, 1 );
11298                break;
11299             case SUMA_byte:
11300                SUMA_LH("byte");
11301                NI_add_column_stride ( dnel, NI_BYTE, NULL, 1 );
11302                break;
11303             case SUMA_double:
11304                SUMA_LH("double");
11305                NI_add_column_stride ( dnel, NI_DOUBLE, NULL, 1 );
11306                break;
11307             case SUMA_string:
11308                SUMA_LH("String");
11309                NI_add_column_stride ( dnel, NI_STRING, NULL, 1 );
11310                break;
11311             case SUMA_complex:
11312                SUMA_LH("Complex");
11313                NI_add_column_stride ( dnel, NI_COMPLEX, NULL, 1 );
11314                break;
11315             default:
11316                fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
11317                NI_free_element(ngr);
11318                SUMA_RETURN(NULL);
11319                break;
11320          }
11321          /* copy the vector's pointer */
11322          dnel->vec[iiidata] = nel->vec[i]; nel->vec[i] = NULL;
11323          /* set some generic attributes */
11324          dset.dnel = dnel; dset.ngr = ngr; dset.inel = inel;
11325          SUMA_AddGenDsetColAttr (&dset, ctp, dnel->vec[iiidata], 1, -1, 0);
11326          /* add the attributes of that column */
11327          col_label = SUMA_ColLabelCopy(nel, i, 0);
11328          SUMA_AddDsetColAttr (&dset, col_label, ctp, NULL, -1, 0);
11329          if (col_label) SUMA_free(col_label); col_label = NULL;
11330          ++iiidata;
11331       } else {
11332          if (iiinel > 0) {
11333             SUMA_S_Err("Have inel column already...");
11334             NI_free_element(ngr); ngr = NULL;
11335             SUMA_RETURN(NULL);
11336          }
11337          SUMA_LH("In the else");
11338          switch (SUMA_ColType2TypeCast(ctp)) {
11339             /* MUST use the old function SUMA_TypeOfColNumb here ! */
11340             case SUMA_int:
11341                SUMA_LH("int");
11342                NI_add_column_stride ( inel, NI_INT, NULL, 1);
11343                break;
11344             case SUMA_float:
11345                SUMA_LH("float");
11346                NI_add_column_stride ( inel, NI_FLOAT, NULL, 1 );
11347                break;
11348             case SUMA_byte:
11349                SUMA_LH("byte");
11350                NI_add_column_stride ( inel, NI_BYTE, NULL, 1 );
11351                break;
11352             case SUMA_double:
11353                SUMA_LH("doouble");
11354                NI_add_column_stride ( inel, NI_DOUBLE, NULL, 1 );
11355                break;
11356             case SUMA_string:
11357                NI_add_column_stride ( inel, NI_STRING, NULL, 1 );
11358                break;
11359             case SUMA_complex:
11360                NI_add_column_stride ( inel, NI_COMPLEX, NULL, 1 );
11361                break;
11362             default:
11363                fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
11364                NI_free_element(ngr);
11365                SUMA_RETURN(NULL);
11366                break;
11367          }
11368          inel->vec[0] = nel->vec[i]; nel->vec[i] = NULL;
11369          /* set some generic attributes */
11370          dset.inel = inel; dset.ngr = ngr; dset.dnel = dnel;
11371          SUMA_AddGenDsetColAttr (&dset, ctp, inel->vec[0], 1, -1, 0);
11372          ++iiinel;
11373       }
11374    }
11375 
11376 
11377    /* add the history note */
11378    SUMA_LH("History Note");
11379    stmp = NI_get_attribute(nel, "HISTORY_NOTE");
11380    if (stmp) {
11381       nelb = NI_new_data_element("AFNI_atr", 1);
11382       NI_set_attribute(nelb,"atr_name", "HISTORY_NOTE");
11383       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
11384       NI_add_to_group(ngr, nelb);
11385       /* now add the new string */
11386       SUMA_NEL_REPLACE_STRING(nelb, 0, 0, (void*)stmp);
11387    }
11388 
11389    SUMA_RETURN(ngr);
11390 }
11391 
SUMA_LoadGIFTIDset(char * Name,int verb)11392 SUMA_DSET *SUMA_LoadGIFTIDset (char *Name, int verb)
11393 {
11394    static char FuncName[]={"SUMA_LoadGIFTIDset"};
11395    char *FullName = NULL, *niname = NULL;
11396    SUMA_DSET *dset=NULL;
11397    NI_group *ngr = NULL;
11398    SUMA_Boolean LocalHead = NOPE;
11399 
11400    SUMA_ENTRY;
11401 
11402    if (!Name) { SUMA_SL_Err("Null Name"); SUMA_RETURN(dset); }
11403 
11404    /* work the name */
11405    if (!SUMA_filexists(Name)) {
11406       /* try the extension game */
11407       FullName = SUMA_Extension(Name, ".gii.dset", NOPE);
11408       if (!SUMA_filexists(FullName)) {
11409          if (verb)  { SUMA_SL_Err("Failed to find dset file."); }
11410          if (FullName) SUMA_free(FullName); FullName = NULL;
11411          SUMA_RETURN(dset);
11412       }
11413    }else {
11414       FullName = SUMA_copy_string(Name);
11415    }
11416 
11417    ngr = NI_read_gifti(Name, 1);
11418    if( !ngr ) {
11419       if (verb)  { SUMA_SL_Err("Failed to read dset file."); }
11420       SUMA_RETURN(dset);
11421    }
11422 
11423    /* add filename and label */
11424    if (!NI_get_attribute(ngr,"filename"))
11425       NI_set_attribute(ngr,"filename", FullName);
11426    if (!NI_get_attribute(ngr,"label"))
11427       NI_set_attribute(ngr,"label", SUMA_FnameGet(FullName,"fne", NULL));
11428 
11429    if (!(dset = SUMA_ngr_2_dset(ngr, 0))) {
11430       SUMA_SL_Err("Failed to go from ngr to dset");
11431       SUMA_RETURN(NULL);
11432    }
11433 
11434    /* make sure inel is initialized*/
11435    if (!dset->inel || !SDSET_NODEINDLEN(dset)) {
11436       SUMA_SL_Err("Bad dset->inel\nOld niml dset?");
11437       SUMA_ShowDset(dset,0, NULL);
11438       SUMA_DUMP_TRACE("Bad dset->inel, dumping trace for debug:");
11439       SUMA_FreeDset(dset); dset = NULL;
11440       SUMA_RETURN(dset);
11441    }
11442 
11443    /* done, clean up and out you go */
11444    if (FullName) SUMA_free(FullName); FullName = NULL;
11445    SUMA_RETURN(dset);
11446 }
11447 
11448 /*!
11449 
11450    \brief Load a surface-based data set of the niml format
11451    \param Name (char *) name or prefix of dataset
11452    \param verb (int) level of verbosity. 0 mute, 1 normal, 2 dramatic perhaps
11453    \return dset (SUMA_DSET *)
11454 
11455    - Reads one ni element only
11456 */
SUMA_LoadNimlDset(char * Name,int verb)11457 SUMA_DSET *SUMA_LoadNimlDset (char *Name, int verb)
11458 {
11459    static char FuncName[]={"SUMA_LoadNimlDset"};
11460    char *FullName = NULL, *niname = NULL;
11461    NI_stream ns = NULL;
11462    void *nini=NULL;
11463    SUMA_DSET *dset=NULL;
11464    int tt;
11465    SUMA_Boolean iselement = NOPE;
11466    SUMA_Boolean LocalHead = NOPE;
11467 
11468    SUMA_ENTRY;
11469 
11470 
11471    if (!Name) { SUMA_SL_Err("Null Name"); SUMA_RETURN(dset); }
11472 
11473    /* work the name */
11474    if (!SUMA_filexists(Name)) {
11475       /* try the extension game */
11476       FullName = SUMA_Extension(Name, ".niml.dset", NOPE);
11477       if (!SUMA_filexists(FullName)) {
11478          if (verb)  { SUMA_SL_Err("Failed to find dset file."); }
11479          if (FullName) SUMA_free(FullName); FullName = NULL;
11480          SUMA_RETURN(dset);
11481       }
11482    }else {
11483       FullName = SUMA_copy_string(Name);
11484    }
11485 
11486    /* got the name, now load it */
11487    niname = SUMA_append_string("file:", FullName);
11488 
11489    ns = NI_stream_open(niname, "r");
11490    if (!ns) {
11491       SUMA_SL_Crit("Failed to open NI stream for reading.");
11492       if (FullName) SUMA_free(FullName); FullName = NULL;
11493       SUMA_RETURN(dset);
11494    }
11495 
11496    nini = NI_read_element(ns, 1) ;
11497    NI_stream_close( ns ) ; ns = NULL;
11498    tt = NI_element_type(nini);
11499 
11500    SUMA_LH("Checking on nini type");
11501    /* check if group or element */
11502    if(tt == NI_GROUP_TYPE) {
11503       iselement = NOPE;
11504       SUMA_LH("Dealing with group");
11505    } else if (tt == NI_ELEMENT_TYPE) {
11506       iselement = YUP;
11507       SUMA_LH("Dealing with element");
11508    } else {
11509       fprintf(SUMA_STDERR, "Note %s: %s has no element and no group. \n"
11510                            "Perhaps it is a .1D read in as a niml dset.\n",
11511                             FuncName, Name);
11512       SUMA_RETURN(NULL);
11513    }
11514 
11515 
11516    if (iselement) {
11517       dset = SUMA_NewDsetPointer();
11518       dset->ngr = SUMA_oDsetNel2nDsetNgr((NI_element *)nini);
11519       dset->dnel = SUMA_FindDsetDataElement(dset);
11520       dset->inel = SUMA_FindDsetDatumIndexElement(dset);
11521       if (!dset->dnel) {
11522          SUMA_SL_Warn("Failed to find dset data element");
11523       }
11524       if (!dset->inel) {
11525          SUMA_SL_Warn("Failed to find dset node index element");
11526       }
11527       NI_free_element((NI_element *)nini);
11528       #ifdef OLD_DSET
11529       if (!nel) {
11530          if (verb) { SUMA_SL_Err("Failed to read dset."); }
11531       } else {
11532          /* Now store that baby in Dset */
11533          dset = SUMA_NewDsetPointer();
11534          dset->nel = (NI_element *)nel; nini = NULL;
11535       }
11536       #endif
11537    } else {
11538       if (!(dset = SUMA_ngr_2_dset((NI_group *)nini, verb))) {
11539          SUMA_SL_Err("Failed to go from ngr to dset");
11540          SUMA_RETURN(NULL);
11541       }
11542    }
11543 
11544    /* make sure inel is initialized*/
11545    if (!dset->inel || !SDSET_NODEINDLEN(dset)) {
11546       SUMA_SL_Err("Bad dset->inel\nOld niml dset?");
11547       SUMA_ShowDset(dset,0, NULL);
11548       SUMA_DUMP_TRACE("Bad dset->inel, dumping trace for debug:");
11549       SUMA_FreeDset(dset); dset = NULL;
11550       SUMA_RETURN(dset);
11551    }
11552 
11553    /* done, clean up and out you go */
11554    if (niname) SUMA_free(niname); niname = NULL;
11555    if (FullName) SUMA_free(FullName); FullName = NULL;
11556    SUMA_RETURN(dset);
11557 }
11558 
11559 /*!
11560    \brief get the data values
11561 */
SUMA_OpenDx_Object_Data(char * op,int nchar,SUMA_OPEN_DX_STRUCT * dx)11562 SUMA_Boolean SUMA_OpenDx_Object_Data(char *op, int nchar,
11563                                      SUMA_OPEN_DX_STRUCT *dx)
11564 {
11565    static char FuncName[]={"SUMA_OpenDx_Object_Data"};
11566    int i, Found = 0, ival;
11567    char *op_end, cend, *op2, *sval;
11568    char *op_orig;
11569    SUMA_Boolean LocalHead = NOPE;
11570 
11571    SUMA_ENTRY;
11572 
11573    /* get the data */
11574    op_orig = op; /* hide this pointer from the evils that will befall it */
11575    cend = op_orig[nchar-1]; op_orig[nchar-1] = '\0';
11576    op_end = op_orig + nchar - 1;
11577    if (LocalHead) { /* potential for huge dump if you set show to nchar! */
11578          int j, show;
11579          show = 500; /* could also use nchar */
11580          fprintf(SUMA_STDERR,"%s Object\n", FuncName);
11581          j=0; while (op[j] && j<500) { fprintf(SUMA_STDERR,"%c", op[j]); ++j; }
11582          fprintf(SUMA_STDERR,"\n");
11583    }
11584    SUMA_ADVANCE_PAST(op,op_end,"data",Found,1);
11585    sval = NULL;
11586    if (Found) {
11587       /* get the data's info */
11588       SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11589       if (op2 == op) {
11590          SUMA_LH("Empty data?");
11591          dx->data=NULL;
11592       } else {
11593          SUMA_COPY_TO_STRING(op, op2, sval);
11594          dx->data = sval; sval = NULL;
11595       }
11596       op = op2;
11597       /* now fill datap if possible*/
11598       if (dx->data && strstr(dx->data,"follows")){
11599          int nread=0;
11600          SUMA_LH("data inside");
11601          if (LocalHead) { /* potential for huge dump! */
11602             int j, show;
11603             show = 500; /* could also use nchar */
11604             fprintf(SUMA_STDERR,"%s Object\n", FuncName);
11605             j=0; while (op[j] && j<500) { fprintf(SUMA_STDERR,"%c", op[j]); ++j; }
11606             fprintf(SUMA_STDERR,"\n");
11607          }
11608          dx->datap = SUMA_strtol_vec(op, dx->items*SUMA_NCOL_OPENDX(dx), &nread, SUMA_CTypeName2VarType (dx->type), NULL);
11609          if (LocalHead) {
11610             fprintf(SUMA_STDERR,"%s: Read %d/%d values\n", FuncName, nread, dx->items*SUMA_NCOL_OPENDX(dx));
11611          }
11612          if (nread != dx->items*SUMA_NCOL_OPENDX(dx)) {
11613             fprintf(SUMA_STDERR,"Error %s: read in %d values, expected %d \n", FuncName, nread, dx->items*SUMA_NCOL_OPENDX(dx));
11614             op_orig[nchar-1] =  cend;
11615             SUMA_RETURN(NOPE);
11616          }
11617       }else {
11618          SUMA_LH("data does not follow");
11619          if (LocalHead) {
11620             for (i=0; i < 500; ++i) { fprintf(SUMA_STDERR,"%c", op[i]); } fprintf(SUMA_STDERR,"\n"); fflush(SUMA_STDERR);
11621          }
11622          /* ? have file name ? */
11623          if (strstr(dx->data,"file")) {
11624             SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11625             if (op2 > op) {
11626                SUMA_free(dx->data); /* free the "file" string */
11627                SUMA_COPY_TO_STRING(op, op2, sval);
11628                dx->data = sval; sval = NULL;
11629                /* search backwards for a comma */
11630                i=strlen(dx->data)-1; Found = -1;
11631                while(i>=0 && Found <0) { if (dx->data[i] == ',') Found = i; --i; }
11632                if (Found >= 0) {
11633                   dx->data_off = SUMA_copy_string(&(dx->data[Found+1]));
11634                   dx->data[Found]='\0';
11635                }
11636                /* see if you have some byte order or binary business */
11637                dx->data_format = 0; /* ascii, default*/
11638                op = op_orig; SUMA_ADVANCE_PAST(op,op_end,"binary",Found,1);
11639                if (Found) {
11640                   dx->data_format = MSB_FIRST; /* default */
11641                }
11642                /* endianness, regardless of what was above, "binary" might not occur */
11643                op = op_orig; SUMA_ADVANCE_PAST(op,op_end,"msb",Found,1);
11644                if (Found) { dx->data_format = MSB_FIRST; }
11645                else {
11646                   op = op_orig; SUMA_ADVANCE_PAST(op,op_end,"lsb",Found,1);
11647                   if (Found) { dx->data_format = LSB_FIRST; }
11648                }
11649             }
11650          }
11651       }
11652    } else {
11653       SUMA_LH("No data for this object");
11654    }
11655 
11656    op_orig[nchar-1] =  cend;
11657    SUMA_RETURN(YUP);
11658 }
11659 
11660 
11661 /*!
11662    \brief return values of an attribute from an OpenDX object string
11663 */
SUMA_OpenDx_Object_Attr(char * op,int nchar,SUMA_OPEN_DX_STRUCT * dx)11664 SUMA_Boolean SUMA_OpenDx_Object_Attr(char *op, int nchar, SUMA_OPEN_DX_STRUCT *dx)
11665 {
11666    static char FuncName[]={"SUMA_OpenDx_Object_Attr"};
11667    int i, Found, ival,imax;
11668    char *op_end, cend, *op2, *sval;
11669    char *op_orig;
11670    SUMA_Boolean LocalHead = NOPE;
11671 
11672    SUMA_ENTRY;
11673 
11674    /* get the attributes */
11675 
11676    op_orig = op; /* hide this pointer from the evils that will befall it */
11677    cend = op_orig[nchar-1]; op_orig[nchar-1] = '\0';
11678    op_end = op_orig + nchar - 1;
11679 
11680    SUMA_ADVANCE_PAST(op,op_end,"attribute",Found, 1);
11681    sval = NULL;
11682    while (Found) {
11683       /* get the attribute's name */
11684       SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11685       if (op2 == op) {
11686          SUMA_LH("Empty attribute?");
11687       } else {
11688          imax = op2 - op;
11689          if (imax > 5000) {
11690             SUMA_SL_Err("Unexpectedly large field!");
11691             op_orig[nchar-1] =  cend;
11692             SUMA_RETURN(NOPE);
11693          }else if (imax < 0) {
11694             SUMA_SL_Err("Negative imax!");
11695             op_orig[nchar-1] =  cend;
11696             SUMA_RETURN(NOPE);
11697          }
11698          sval = (char *)SUMA_calloc(imax + 2, sizeof(char));
11699 
11700          for (i=0; i < imax; ++i) sval[i] = op[i];
11701          sval[imax] = '\0';
11702          dx->attr_name[dx->n_attr] = sval;
11703       }
11704       op = op2;
11705       /* look for attribute string */
11706       SUMA_ADVANCE_PAST(op,op_end,"string",Found,1);
11707       if (Found) {
11708          SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11709          if (op2 == op) {
11710             SUMA_LH("Empty string?");
11711          } else {
11712             imax = op2 - op;
11713             if (imax > 5000) {
11714                SUMA_SL_Err("Unexpectedly large field!");
11715                op_orig[nchar-1] =  cend;
11716                SUMA_RETURN(NOPE);
11717             }else if (imax < 0) {
11718                SUMA_SL_Err("Negative imax!");
11719                op_orig[nchar-1] =  cend;
11720                SUMA_RETURN(NOPE);
11721             }
11722             sval = (char *)SUMA_calloc(imax + 2, sizeof(char));
11723 
11724             for (i=0; i < imax; ++i) sval[i] = op[i];
11725             sval[imax] = '\0';
11726             dx->attr_string[dx->n_attr] = sval;
11727          }
11728       }
11729       ++dx->n_attr;
11730       /* look for next attribute */
11731       op = op2;
11732       SUMA_ADVANCE_PAST(op,op_end,"attribute",Found,1);
11733    }
11734 
11735    op_orig[nchar-1] =  cend;
11736    SUMA_RETURN(YUP);
11737 }
11738 
11739 /*!
11740    \brief return values of a header field from an OpenDX object string
11741    If you expect an int back like when attr is "rank" or "shape"
11742       ans should be type cast to (int *) before use: int ival; ival = *((int *)ans);
11743    If you expect a bunch of numbers like for "counts" "origin" "delta"
11744       then ans is (SUMA_IVEC *) or (SUMA_FVEC*) or (SUMA_DVEC *)
11745       These are freed with SUMA_free(ans->v); SUMA_free(ans);
11746    else ans should be type cast to (char **) before use:
11747       char *sval; sval = *((char **)ans); then free sval with SUMA_free(sval);
11748 
11749 */
SUMA_OpenDx_Object_Header_Field(char * op,int nchar,const char * attr,char ** opeofield)11750 void * SUMA_OpenDx_Object_Header_Field(char *op, int nchar, const char *attr, char **opeofield)
11751 {
11752    static char FuncName[]={"SUMA_OpenDx_Object_Header_Field"};
11753    void *ans=NULL;
11754    int i, Found, ival, imax, nread;
11755    char *op_end = NULL, cend, *op2, *sval, *pp1, *pp2;
11756    char *op_orig;
11757    SUMA_Boolean LocalHead = NOPE;
11758 
11759    SUMA_ENTRY;
11760 
11761    if (opeofield) *opeofield = op;
11762 
11763    if (!attr) SUMA_RETURN(ans);
11764    op_orig = op; /* hide this pointer from the evils that will befall it */
11765    cend = op_orig[nchar-1]; op_orig[nchar-1] = '\0';
11766    /* do we have a data section to signal end of header? */
11767    op_end = NULL;
11768    pp1 = strstr(op, "data");
11769    if (pp1) {
11770       pp2 = strstr(op, "follows");
11771       if (pp2) op_end = pp2;
11772    }
11773    if (!op_end) op_end = op_orig + nchar - 1; /* op_end all the way at end */
11774 
11775    if (LocalHead) {
11776       fprintf(SUMA_STDERR,"%s: Object of %d chars, looking for >>>%s<<<\n", FuncName, nchar, attr );
11777    }
11778 
11779   /* get the header field's value name */
11780    SUMA_ADVANCE_PAST(op,op_end,attr,Found,1);
11781    if (Found) {
11782       SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11783       if (op2 == op) {
11784          SUMA_LH("No field");
11785       } else {
11786          /* get the numeric fields changed*/
11787          if (strstr(attr,"rank") || strstr(attr,"shape") || strstr(attr,"items")) { /* rank, shape (matrix's second dim) are integer vals */
11788             ival = (int)strtol(op, NULL , 10);
11789             ans = (void*)&ival;
11790          } else if (strstr(attr,"counts")) { /* are a series integer vals */
11791             ans = SUMA_AdvancePastNumbers(op, &op2, SUMA_int);
11792          } else if (strstr(attr,"origin") || strstr(attr,"delta")) { /* are integer vals */
11793             ans = SUMA_AdvancePastNumbers(op, &op2, SUMA_float);
11794          } else  { /* strings*/
11795             imax = op2 - op;
11796             if (imax > 5000) {
11797                SUMA_SL_Err("Unexpectedly large field!");
11798                op_orig[nchar-1] =  cend;
11799                SUMA_RETURN(ans);
11800             }else if (imax < 0) {
11801                SUMA_SL_Err("Negative imax!");
11802                op_orig[nchar-1] =  cend;
11803                SUMA_RETURN(ans);
11804             }
11805             sval = (char *)SUMA_calloc(imax + 2, sizeof(char));
11806 
11807             for (i=0; i < imax; ++i) sval[i] = op[i];
11808             sval[imax] = '\0';
11809             ans = (void*)&sval;
11810          }
11811          if (LocalHead) {
11812             fprintf(SUMA_STDERR,"%s: attribute >>>%s<<< is:\n", FuncName, attr);
11813             i = 0;
11814             while (op[i] && op+i != op2) {
11815                fprintf(SUMA_STDERR,"%c", op[i]);
11816                ++i;
11817             }
11818             fprintf(SUMA_STDERR,"\n");
11819          }
11820 
11821       }
11822       op = op2; /* advance op */
11823    } else {
11824       if (strstr(attr,"class")) {
11825          /* it looks like "class" is sometimes omitted, look for string field, which is a class */
11826          SUMA_ADVANCE_PAST(op,op_end,"field", Found,1);
11827          if (Found) sval = SUMA_copy_string("field");
11828          ans = (void*)&sval;
11829       } else {
11830          SUMA_LH("No such attribute");
11831       }
11832    }
11833 
11834    op_orig[nchar-1] =  cend;
11835    if (opeofield) *opeofield = op;
11836    SUMA_RETURN(ans);
11837 }
11838 
11839 /*!
11840    \brief return values of an attribute from an OpenDX object string
11841 */
SUMA_OpenDx_Object_Components(char * op,int nchar,SUMA_OPEN_DX_STRUCT * dx)11842 SUMA_Boolean SUMA_OpenDx_Object_Components(char *op, int nchar, SUMA_OPEN_DX_STRUCT *dx)
11843 {
11844    static char FuncName[]={"SUMA_OpenDx_Object_Components"};
11845    int i, Found, ival,imax;
11846    char *op_end, cend, *op2, *sval;
11847    char *op_orig;
11848    SUMA_Boolean LocalHead = NOPE;
11849 
11850    SUMA_ENTRY;
11851 
11852    /* get the attributes */
11853 
11854    op_orig = op; /* hide this pointer from the evils that will befall it */
11855    cend = op_orig[nchar-1]; op_orig[nchar-1] = '\0';
11856    op_end = op_orig + nchar - 1;
11857 
11858    SUMA_ADVANCE_PAST(op,op_end,"component",Found,1);
11859    while (Found) {
11860       /* get the attribute's name */
11861       SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11862       if (op2 == op) {
11863          SUMA_LH("Empty component?");
11864       } else {
11865          imax = op2 - op;
11866          if (imax > 5000) {
11867             SUMA_SL_Err("Unexpectedly large field!");
11868             op_orig[nchar-1] =  cend;
11869             SUMA_RETURN(NOPE);
11870          }else if (imax < 0) {
11871             SUMA_SL_Err("Negative imax!");
11872             op_orig[nchar-1] =  cend;
11873             SUMA_RETURN(NOPE);
11874          }
11875          sval = (char *)SUMA_calloc(imax + 2, sizeof(char));
11876 
11877          for (i=0; i < imax; ++i) sval[i] = op[i];
11878          sval[imax] = '\0';
11879          dx->comp_name[dx->n_comp] = sval;
11880       }
11881       op = op2;
11882       /* look for attribute string */
11883       SUMA_ADVANCE_PAST(op,op_end,"value",Found,1);
11884       if (Found) {
11885          SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11886          if (op2 == op) {
11887             SUMA_SL_Err("No value!");
11888          } else {
11889             imax = op2 - op;
11890             if (imax > 5000) {
11891                SUMA_SL_Err("Unexpectedly large field!");
11892                op_orig[nchar-1] =  cend;
11893                SUMA_RETURN(NOPE);
11894             }else if (imax < 0) {
11895                SUMA_SL_Err("Negative imax!");
11896                op_orig[nchar-1] =  cend;
11897                SUMA_RETURN(NOPE);
11898             }
11899             sval = (char *)SUMA_calloc(imax + 2, sizeof(char));
11900 
11901             for (i=0; i < imax; ++i) sval[i] = op[i];
11902             sval[imax] = '\0';
11903             dx->comp_value[dx->n_comp] = sval;
11904          }
11905       }else { /* try for non-existing "value" */
11906          SUMA_GET_BETWEEN_BLANKS(op, op_end, op2);
11907          if (op2 == op) {
11908             SUMA_SL_Err("No value at all");
11909          } else {
11910             imax = op2 - op;
11911             if (imax > 5000) {
11912                SUMA_SL_Err("Unexpectedly large field!");
11913                op_orig[nchar-1] =  cend;
11914                SUMA_RETURN(NOPE);
11915             }else if (imax < 0) {
11916                SUMA_SL_Err("Negative imax!");
11917                op_orig[nchar-1] =  cend;
11918                SUMA_RETURN(NOPE);
11919             }
11920             sval = (char *)SUMA_calloc(imax + 2, sizeof(char));
11921 
11922             for (i=0; i < imax; ++i) sval[i] = op[i];
11923             sval[imax] = '\0';
11924             dx->comp_value[dx->n_comp] = sval;
11925          }
11926       }
11927       ++dx->n_comp;
11928       /* look for next component */
11929       op = op2;
11930       SUMA_ADVANCE_PAST(op,op_end,"component",Found,1);
11931    }
11932 
11933    op_orig[nchar-1] =  cend;
11934    SUMA_RETURN(YUP);
11935 }
11936 
11937 /*!
11938    \brief A function to create a dataset out of an OpenDX object
11939    \param FullName (char *) the filename
11940    \param dset_id (char *) if null, SUMA_CreateDsetPointer will create one
11941    \param dom_id (char *) domain idcode null if you have none
11942    \param dx (SUMA_OPEN_DX_STRUCT *) pointer to OpenDX object
11943    \return dset (SUMA_DSET *) NULL if trouble, of course.
11944 */
SUMA_OpenDX2dset(char * FullName,char * dset_id,char * dom_id,SUMA_OPEN_DX_STRUCT * dx)11945 SUMA_DSET *SUMA_OpenDX2dset( char *FullName, char *dset_id, char *dom_id,
11946                                 SUMA_OPEN_DX_STRUCT *dx )
11947 {
11948    static char FuncName[]={"SUMA_OpenDX2dset"};
11949    SUMA_DSET *dset = NULL;
11950    int i = 0;
11951 
11952    SUMA_ENTRY;
11953 
11954    if (!FullName) { SUMA_SL_Err("Need a FullName"); SUMA_RETURN(dset); }
11955    if (!dx) { SUMA_SL_Err("NULL dx"); SUMA_RETURN(dset); }
11956 
11957    dset = SUMA_CreateDsetPointer( FullName, SUMA_NODE_BUCKET, dset_id, dom_id,  dx->items);
11958 
11959    /* now add the columns */
11960 
11961    for (i=0; i<SUMA_NCOL_OPENDX(dx); ++i) {
11962       if (!SUMA_AddDsetNelCol (dset, "dx_col",
11963                            SUMA_VarType2ColType (dx->type),
11964                            (char *)dx->datap+i, NULL , SUMA_NCOL_OPENDX(dx))) {
11965          SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
11966          SUMA_FreeDset((void*)dset); dset = NULL;
11967          SUMA_RETURN(dset);
11968       }
11969    }
11970 
11971 
11972    SUMA_RETURN(dset);
11973 }
11974 
11975 /*!
11976    \brief A function to create a dataset out of MRI_FLOAT_PTR(im)
11977          that is typically used to read in a 1D file
11978    \param FullName (char *) the filename
11979    \param dset_id (char *) if null, SUMA_CreateDsetPointer will create one
11980    \param dom_id (char *) domain idcode null if you have none
11981    \param farp (float **) pointer to float vector. If far = MRI_FLOAT_PTR(im);
11982                            then pass farp is &far . I want the pointer
11983                            so that I can set it to NULL if the pointer
11984                            is copied instead of the data (i.e. ptr_cpy ! = 0)
11985    \param vec_len (int) That would be im->nx
11986    \param vec_num (int) That would be im->ny
11987    \param ptr_cpy (int) 0 if you want to copy the values in *farp,
11988                         1 if you want to make a pointer copy. In that case
11989                         (not supported yet, *farp is set to NULL)
11990    \return dset (SUMA_DSET *) NULL if trouble, of course.
11991 */
SUMA_far2dset_ns(char * FullName,char * dset_id,char * dom_id,float ** farp,int vec_len,int vec_num,int ptr_cpy)11992 SUMA_DSET *SUMA_far2dset_ns( char *FullName, char *dset_id, char *dom_id,
11993                                  float **farp, int vec_len, int vec_num,
11994                                  int ptr_cpy)
11995 {
11996    SUMA_DSET *dset = SUMA_far2dset_eng( FullName, dset_id, dom_id,
11997                                  farp, vec_len, vec_num,
11998                                  ptr_cpy);
11999    WorkErrLog_ns();
12000    return(dset);
12001 }
SUMA_far2dset_eng(char * FullName,char * dset_id,char * dom_id,float ** farp,int vec_len,int vec_num,int ptr_cpy)12002 SUMA_DSET *SUMA_far2dset_eng( char *FullName, char *dset_id, char *dom_id,
12003                                  float **farp, int vec_len, int vec_num,
12004                                  int ptr_cpy)
12005 {
12006    static char FuncName[]={"SUMA_far2dset_eng"};
12007    SUMA_DSET *dset = NULL;
12008    int i = 0;
12009    float *far = NULL;
12010 
12011    SUMA_ENTRY;
12012 
12013    if (!FullName) {
12014       SUMA_PushErrLog("SL_Err", "Need a FullName", FuncName);
12015       SUMA_RETURN(dset);
12016    }
12017    if (!farp) {
12018       SUMA_PushErrLog("SL_Err", "NULL farp", FuncName); SUMA_RETURN(dset);
12019    }
12020    far = *farp;
12021    if (!far) {
12022       SUMA_PushErrLog("SL_Err", "NULL *farp", FuncName); SUMA_RETURN(dset);
12023    }
12024    if (vec_len < 0 || vec_num < 0) {
12025       SUMA_PushErrLog("SL_Err", "Negative vec_len or vec_num", FuncName);
12026       SUMA_RETURN(dset);
12027    }
12028    if (ptr_cpy) {
12029       SUMA_PushErrLog("SL_Err", "Pointer copy not supported yet", FuncName);
12030       SUMA_RETURN(dset);
12031    }
12032 
12033    if (vec_num > 200 * vec_len || vec_num > 50000){/* warning for MSB's mishap */
12034       char *eee = getenv("SUMA_1D_Transpose_Warn");
12035       int Warn = 1;
12036       static int nwarn = 0;
12037       Warn = 1;
12038       if (eee) {
12039          if (strcmp(eee,"NO") == 0) Warn = 0; /* stay out of this */
12040       }
12041       if (Warn) {
12042          if (!nwarn) {
12043             SUMA_PushErrLog("SLP_Warn", "Unusual 1D file dimensions.\n"
12044                         "Number of rows (nodes) much less\n"
12045                         "than number of columns (sub-bricks).\n"
12046                         "This warning is put up in case\n"
12047                         "you have the dataset incorrectly \n"
12048                         "transposed for some reason. Should\n"
12049                         "you need to transpose it again, use \n"
12050                         "the program 1dtranspose .\n"
12051                         "1D files where the number of columns\n"
12052                         "is much larger than the number of \n"
12053                         "rows will take a long time to load \n"
12054                         "and a longer time, much longer a times,\n"
12055                         "to have the X interface initialized.\n"
12056                         "The read operation was cancelled this\n"
12057                         "time, read the file again if you think\n"
12058                         "the file you are reading is properly \n"
12059                         "formatted. This warning will\n"
12060                         "no be shown again in this session.\n"
12061                         "Set the environment variable \n"
12062                         "SUMA_1D_Transpose_Warn = NO\n"
12063                         "in .sumarc if you do not want to see\n"
12064                         "this warning ever again.\n"
12065                         , FuncName);
12066             /* return the first time with NULL */
12067             ++nwarn; SUMA_RETURN(NULL);
12068          }
12069       }
12070    }
12071    dset = SUMA_CreateDsetPointer( FullName, SUMA_NODE_BUCKET,
12072                                   dset_id, dom_id,  vec_len  );
12073 
12074    /* now add the columns */
12075    for (i=0; i<vec_num; ++i) {
12076       if (!SUMA_AddDsetNelCol (dset, "numeric", SUMA_NODE_FLOAT,
12077                                (void *)(&(far[i*vec_len])), NULL ,1)) {
12078          SUMA_PushErrLog("SL_Crit", "Failed in SUMA_AddDsetNelCol", FuncName);
12079          SUMA_FreeDset((void*)dset); dset = NULL;
12080          SUMA_RETURN(dset);
12081       }
12082    }
12083 
12084    if (ptr_cpy) *farp = NULL;
12085 
12086    SUMA_RETURN(dset);
12087 }
12088 
SUMA_iar2dset_ns(char * FullName,char * dset_id,char * dom_id,int ** iarp,int vec_len,int vec_num,int ptr_cpy)12089 SUMA_DSET *SUMA_iar2dset_ns( char *FullName, char *dset_id, char *dom_id,
12090                               int **iarp, int vec_len, int vec_num,
12091                               int ptr_cpy)
12092 {
12093    SUMA_DSET *dset = SUMA_iar2dset_eng( FullName, dset_id, dom_id,
12094                                  iarp, vec_len, vec_num,
12095                                  ptr_cpy);
12096    WorkErrLog_ns();
12097    return(dset);
12098 }
SUMA_iar2dset_eng(char * FullName,char * dset_id,char * dom_id,int ** iarp,int vec_len,int vec_num,int ptr_cpy)12099 SUMA_DSET *SUMA_iar2dset_eng( char *FullName, char *dset_id, char *dom_id,
12100                                  int **iarp, int vec_len, int vec_num,
12101                                  int ptr_cpy)
12102 {
12103    static char FuncName[]={"SUMA_iar2dset_eng"};
12104    SUMA_DSET *dset = NULL;
12105    int i = 0;
12106    int *iar = NULL;
12107 
12108    SUMA_ENTRY;
12109 
12110    if (!FullName) {
12111       SUMA_PushErrLog("SL_Err", "Need a FullName", FuncName);
12112       SUMA_RETURN(dset);
12113    }
12114    if (!iarp) {
12115       SUMA_PushErrLog("SL_Err", "NULL iarp", FuncName); SUMA_RETURN(dset);
12116    }
12117    iar = *iarp;
12118    if (!iar) {
12119       SUMA_PushErrLog("SL_Err", "NULL *iarp", FuncName); SUMA_RETURN(dset);
12120    }
12121    if (vec_len < 0 || vec_num < 0) {
12122       SUMA_PushErrLog("SL_Err", "Negative vec_len or vec_num", FuncName);
12123       SUMA_RETURN(dset);
12124    }
12125    if (ptr_cpy) {
12126       SUMA_PushErrLog("SL_Err", "Pointer copy not supported yet", FuncName);
12127       SUMA_RETURN(dset);
12128    }
12129 
12130    dset = SUMA_CreateDsetPointer( FullName, SUMA_NODE_BUCKET, dset_id,
12131                                   dom_id,  vec_len  );
12132 
12133    /* now add the columns */
12134    for (i=0; i<vec_num; ++i) {
12135       if (!SUMA_AddDsetNelCol (dset, "numeric", SUMA_NODE_INT,
12136                                (void *)(&(iar[i*vec_len])), NULL ,1)) {
12137          SUMA_PushErrLog("SL_Crit", "Failed in SUMA_AddDsetNelCol", FuncName);
12138          SUMA_FreeDset((void*)dset); dset = NULL;
12139          SUMA_RETURN(dset);
12140       }
12141    }
12142 
12143    if (ptr_cpy) *iarp = NULL;
12144 
12145    SUMA_RETURN(dset);
12146 }
12147 
SUMA_is_AllConsistentNumeric_dset(SUMA_DSET * dset,SUMA_VARTYPE * vtpp)12148 int SUMA_is_AllConsistentNumeric_dset(SUMA_DSET *dset, SUMA_VARTYPE *vtpp)
12149 {
12150    static char FuncName[]={"SUMA_is_AllConsistentNumeric_dset"};
12151    int ctp, vtp, vtpc = SUMA_notypeset, i;
12152 
12153    SUMA_ENTRY;
12154 
12155    if (!dset) SUMA_RETURN(0);
12156 
12157    for (i=0; i<SDSET_VECNUM(dset); ++i) {
12158       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12159       vtp = SUMA_ColType2TypeCast(ctp) ;
12160       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
12161       if (i==0) { vtpc = vtp; }
12162       else if (vtp != vtpc) SUMA_RETURN(0);
12163    }
12164 
12165    if (vtpp) *vtpp = vtpc;
12166    SUMA_RETURN(1);
12167 }
12168 
12169 /*!
12170    Are all columns of the same column type ctpi
12171    If you just care for a consistency test, set ctpi to SUMA_ERROR_COL_TYPE
12172 */
SUMA_is_AllConsistentColType_dset(SUMA_DSET * dset,SUMA_COL_TYPE ctpi)12173 int SUMA_is_AllConsistentColType_dset(SUMA_DSET *dset, SUMA_COL_TYPE ctpi)
12174 {
12175    static char FuncName[]={"SUMA_is_AllConsistentColType_dset"};
12176    int ctp0 = SUMA_ERROR_COL_TYPE, ctp, i;
12177 
12178    SUMA_ENTRY;
12179 
12180    if (!dset) SUMA_RETURN(0);
12181 
12182    for (i=0; i<SDSET_VECNUM(dset); ++i) {
12183       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12184       /* SUMA_S_Note("Dset %s: Type of col %d = [%d, %s], target [%d %s]",
12185                   SDSET_LABEL(dset), i, ctp, SUMA_Col_Type_Name(ctp),
12186                   ctpi, SUMA_Col_Type_Name(ctpi)); */
12187       if (ctpi>SUMA_ERROR_COL_TYPE && ctp != ctpi) SUMA_RETURN(0);
12188       if (i==0) { ctp0 = ctp; }
12189       else if (ctp0 != ctp) SUMA_RETURN(0);
12190    }
12191    SUMA_RETURN(1);
12192 }
12193 
SUMA_GetConsistentColType_dset(SUMA_DSET * dset)12194 int SUMA_GetConsistentColType_dset(SUMA_DSET *dset)
12195 {
12196    static char FuncName[]={"SUMA_GetConsistentColType_dset"};
12197    int ctp0 = SUMA_ERROR_COL_TYPE, ctp, i;
12198 
12199    SUMA_ENTRY;
12200 
12201    if (!dset) SUMA_RETURN(SUMA_ERROR_COL_TYPE);
12202 
12203    for (i=0; i<SDSET_VECNUM(dset); ++i) {
12204       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12205       if (i==0) { ctp0 = ctp; }
12206       else if (ctp0 != ctp) SUMA_RETURN(SUMA_ERROR_COL_TYPE);
12207    }
12208    SUMA_RETURN(ctp0);
12209 }
12210 
SUMA_is_AllConsistentCastType_dset(SUMA_DSET * dset,int typecast)12211 int SUMA_is_AllConsistentCastType_dset(SUMA_DSET *dset, int typecast)
12212 {
12213    static char FuncName[]={"SUMA_is_AllConsistentCastType_dset"};
12214    int ctp, vtp, i;
12215 
12216    SUMA_ENTRY;
12217 
12218    if (!dset) SUMA_RETURN(0);
12219 
12220    for (i=0; i<SDSET_VECNUM(dset); ++i) {
12221       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12222       vtp = SUMA_ColType2TypeCast(ctp) ;
12223       if (vtp != typecast) SUMA_RETURN(0);
12224    }
12225 
12226    SUMA_RETURN(1);
12227 }
12228 
SUMA_is_AllNumeric_dset(SUMA_DSET * dset)12229 int SUMA_is_AllNumeric_dset(SUMA_DSET *dset)
12230 {
12231    static char FuncName[]={"SUMA_is_AllNumeric_dset"};
12232    int ctp, vtp, i;
12233 
12234    SUMA_ENTRY;
12235 
12236    if (!dset) SUMA_RETURN(0);
12237 
12238    for (i=0; i<SDSET_VECNUM(dset); ++i) {
12239       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12240       vtp = SUMA_ColType2TypeCast(ctp) ;
12241       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
12242    }
12243 
12244    SUMA_RETURN(1);
12245 }
12246 
12247 /*!
12248    \brief requirements to be a label dset:
12249    1- 1 column of data with type SUMA_NODE_ILABEL
12250    that is it for now.
12251 */
SUMA_is_Label_dset(SUMA_DSET * dset,NI_group ** NIcmap)12252 int SUMA_is_Label_dset(SUMA_DSET *dset, NI_group **NIcmap)
12253 {
12254    static char FuncName[]={"SUMA_is_Label_dset"};
12255    int ctp, vtp, i;
12256    NI_group *ngr=NULL;
12257    SUMA_Boolean LocalHead = NOPE;
12258 
12259    SUMA_ENTRY;
12260 
12261    if (!dset) SUMA_RETURN(0);
12262 
12263    if (SUMA_isVolDataset(dset)) {
12264       if(SUMA_GetAtlasLabelTable(dset) || SUMA_GetValueLabelTable(dset)) {
12265          SUMA_RETURN(1);
12266       }
12267    }
12268 
12269    SUMA_LH( "All Cons Type = %d : %d\n"
12270             "SDSET_TYPE (%s) = %d\n",
12271             SUMA_NODE_ILABEL,
12272             SUMA_is_AllConsistentColType_dset(dset, SUMA_NODE_ILABEL),
12273             SDSET_LABEL(dset),
12274             SDSET_TYPE (dset));
12275 
12276    if (!SUMA_is_AllConsistentColType_dset(dset, SUMA_NODE_ILABEL))
12277       SUMA_RETURN(0);
12278 
12279    /* Check on the dset_type attribute.
12280       This check is needed to tell the difference between
12281       NODE_ROI datasets that are treated as regular datasets,
12282       and NODE_LABEL which are rendered differently.
12283       Both types have a dset column that is of type
12284       SUMA_NODE_ILABEL*/
12285 
12286    if (SDSET_TYPE(dset) != SUMA_NODE_LABEL) { SUMA_RETURN(0); }
12287 
12288    /* Does the dset have a colormap ?*/
12289    if ((ngr = SUMA_NI_Cmap_of_Dset(dset))) {
12290       /* OK, have colormap */
12291       if (NIcmap) *NIcmap = ngr;
12292    } else {
12293       /* do not reject this yet */
12294       if (NIcmap) *NIcmap = NULL;
12295    }
12296 
12297    SUMA_LH("dset %s considered Label_dset", SDSET_LABEL(dset));
12298    SUMA_RETURN(1);
12299 }
12300 
12301 /* sort of like is_Label_dset, but here we just worry
12302 about one data column. We also require that there be
12303 a colormap in the dataset somewhere. This was added
12304 to handle GIFTI datasets that are labels but that seem
12305 to get translate to one column of labels and other columns
12306 of generic_ints. The dataset came from the HCP's Workbench
12307 and I am not sure if the problem is one of translation on our
12308 part or one of GIFTI formatting from Workbench.
12309 For now, this function would allow for the proper display of
12310 such a dataset.   ZSS Feb. 20 2014 */
SUMA_is_Label_dset_col(SUMA_DSET * dset,int icol)12311 int SUMA_is_Label_dset_col(SUMA_DSET *dset, int icol)
12312 {
12313    static char FuncName[]={"SUMA_is_Label_dset_col"};
12314    int ctp, vtp, i;
12315    NI_group *ngr=NULL;
12316    SUMA_Boolean LocalHead = NOPE;
12317 
12318    SUMA_ENTRY;
12319 
12320    if (!dset || icol < 0) SUMA_RETURN(0);
12321 
12322    if (SUMA_TypeOfDsetColNumb(dset, icol) != SUMA_NODE_ILABEL) SUMA_RETURN(0);
12323    if (SDSET_TYPE(dset) != SUMA_NODE_LABEL) { SUMA_RETURN(0); }
12324 
12325    /* Does the dset have a colormap ?*/
12326    if (!(ngr = SUMA_NI_Cmap_of_Dset(dset))) {
12327       /* reject out of caution */
12328       SUMA_RETURN(0);
12329    }
12330 
12331    SUMA_RETURN(1);
12332 }
12333 
12334 
12335 /*!
12336    \brief requirements to be a VFR dset:
12337    1- 1st column of data with type SUMA_NODE_VFR
12338 */
SUMA_is_VFR_dset(SUMA_DSET * dset)12339 int SUMA_is_VFR_dset(SUMA_DSET *dset)
12340 {
12341    static char FuncName[]={"SUMA_is_VFR_dset"};
12342    int ctp, vtp, i;
12343    NI_group *ngr=NULL;
12344    SUMA_Boolean LocalHead = NOPE;
12345 
12346    SUMA_ENTRY;
12347 
12348    if (!dset) SUMA_RETURN(0);
12349 
12350    i = 0;
12351    ctp = SUMA_TypeOfDsetColNumb(dset, i);
12352    if (LocalHead) {
12353          fprintf(SUMA_STDERR,"%s: ctp(%d) = %d (%d)\n",
12354                FuncName, i, ctp, SUMA_NODE_VFR);
12355    }
12356    if (ctp == SUMA_NODE_VFR) SUMA_RETURN(1);
12357 
12358 
12359    SUMA_RETURN(0);
12360 }
12361 
12362 /*!
12363    \brief requirements to be a phase dset:
12364    1- 1st column of data with type SUMA_NODE_PHASE
12365 */
SUMA_is_Phase_dset(SUMA_DSET * dset)12366 int SUMA_is_Phase_dset(SUMA_DSET *dset)
12367 {
12368    static char FuncName[]={"SUMA_is_Phase_dset"};
12369    int ctp, vtp, i;
12370    NI_group *ngr=NULL;
12371    SUMA_Boolean LocalHead = NOPE;
12372 
12373    SUMA_ENTRY;
12374 
12375    if (!dset) SUMA_RETURN(0);
12376 
12377    i = 0;
12378       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12379       if (LocalHead) {
12380          fprintf(SUMA_STDERR,"%s: ctp(%d) = %d (%d)\n",
12381                FuncName, i, ctp, SUMA_NODE_PHASE);
12382       }
12383       if (ctp == SUMA_NODE_PHASE) SUMA_RETURN(1);
12384 
12385    SUMA_RETURN(0);
12386 }
12387 
12388 /*!
12389    \brief requirements to be a retinotopically derived angle:
12390    Checks labels of columns
12391 */
SUMA_is_RetinoAngle_dset(SUMA_DSET * dset)12392 int SUMA_is_RetinoAngle_dset(SUMA_DSET *dset)
12393 {
12394    static char FuncName[]={"SUMA_is_RetinoAngle_dset"};
12395    int ctp, vtp, i;
12396    NI_group *ngr=NULL;
12397    char *lblcp=NULL;
12398    SUMA_Boolean LocalHead = NOPE;
12399 
12400    SUMA_ENTRY;
12401 
12402    if (!dset) SUMA_RETURN(0);
12403 
12404    /* check based on label, rather than column type.
12405    Dset is created with 3d program and it is a pain
12406    to add the column type there at the moment */
12407 
12408    i = 0;
12409    lblcp = SUMA_DsetColLabelCopy(dset, 0, 0);
12410    if (strstr(lblcp, "Polar Angle")) i = 1;
12411    else if (strstr(lblcp, "Eccentricity")) i = 1;
12412    else if (strncmp(lblcp, "Phz@", 4) == 0) i = 1;
12413    else if (strncmp(lblcp, "Phz_Delay", 5) == 0) i = 1;
12414 
12415    SUMA_free(lblcp);
12416    SUMA_RETURN(i);
12417 }
12418 
12419 
12420 
SUMA_NI_Cmap_of_Dset(SUMA_DSET * dset)12421 NI_group *SUMA_NI_Cmap_of_Dset(SUMA_DSET *dset)
12422 {
12423    static char FuncName[]={"SUMA_NI_Cmap_of_Dset"};
12424    NI_group *ngr=NULL;
12425    NI_element *nel=NULL;
12426    char *s=NULL;
12427    int ip=0;
12428    SUMA_Boolean LocalHead = NOPE;
12429 
12430    SUMA_ENTRY;
12431 
12432    if (!dset || !dset->ngr) SUMA_RETURN(NULL);
12433 
12434    for( ip=0 ; ip < dset->ngr->part_num ; ip++ ){
12435       switch( dset->ngr->part_typ[ip] ){
12436          case NI_GROUP_TYPE:
12437             ngr = (NI_group *)dset->ngr->part[ip];
12438             if (LocalHead)  {
12439                      fprintf( SUMA_STDERR,
12440                               "%s:  Looking for %s   in group %s \n",
12441                               FuncName, "AFNI_labeltable", ngr->name);
12442             }
12443             if (!strcmp("AFNI_labeltable", ngr->name)) {
12444                if (!NI_get_attribute(ngr,"Name")) {
12445                   s = SUMA_append_string("LT_", SDSET_LABEL(dset));
12446                   NI_set_attribute(ngr,"Name",s); SUMA_free(s); s= NULL;
12447                }
12448                SUMA_RETURN(ngr);
12449             }
12450             ngr=NULL; /* not good, keep looking */
12451             break ;
12452          case NI_ELEMENT_TYPE:
12453             nel = (NI_element *)dset->ngr->part[ip] ;
12454             break;
12455          default:
12456             SUMA_SL_Err("Don't know what to make of this group element\n"
12457                         "ignoring.");
12458             break;
12459       }
12460    }
12461 
12462    SUMA_RETURN(ngr);
12463 }
12464 
12465 /* Column of unique values, in Label dset DO NOT FREE */
SUMA_UniqueValuesInLabelDset(SUMA_DSET * dset,int * N_unq)12466 int * SUMA_UniqueValuesInLabelDset(SUMA_DSET *dset, int *N_unq)
12467 {
12468    static char FuncName[]={"SUMA_UniqueValuesInLabelDset"};
12469    NI_element *nel=NULL;
12470 
12471    SUMA_ENTRY;
12472 
12473    if (!dset || !N_unq) {
12474       SUMA_RETURN(NULL);
12475    }
12476    *N_unq = 0;
12477 
12478    if (!SUMA_is_Label_dset(dset, NULL)) {
12479       SUMA_RETURN(NULL);
12480    }
12481 
12482    nel = SUMA_GetUniqueValsAttr(dset, 0);
12483    if (!nel) {
12484       SUMA_SetUniqueValsAttr(dset, 0, 0);
12485    }
12486    nel = SUMA_GetUniqueValsAttr(dset, 0);
12487    if (!nel) {
12488       SUMA_RETURN(NULL);
12489    }
12490 
12491    *N_unq = nel->vec_len;
12492 
12493    SUMA_RETURN((int *)nel->vec[0]);
12494 }
12495 
SUMA_is_TimeSeries_dset(SUMA_DSET * dset,double * TRp)12496 int SUMA_is_TimeSeries_dset(SUMA_DSET *dset, double *TRp)
12497 {
12498    static char FuncName[]={"SUMA_is_TimeSeries_dset"};
12499    char *mm=NULL;
12500    double TR=-1.0;
12501 
12502    SUMA_ENTRY;
12503 
12504    if (TRp) *TRp = TR;
12505    if (!SUMA_is_AllNumeric_dset(dset)) SUMA_RETURN(0);
12506    if (!dset->dnel) SUMA_RETURN(0);
12507 
12508 
12509    mm = NI_get_attribute(dset->dnel, "ni_timestep");
12510    if ( !mm ) SUMA_RETURN(0);
12511    TR = strtod(mm, NULL);
12512    if (TR > 100) { /* likely a bug in dsets prior to Sep 19 09 */
12513       SUMA_S_Warn("ni_timestep may be incorrectly specified in msec.\n"
12514                   "Time units should be in sec.");
12515       if (TR > 360) { /* just cut the damned thing down */
12516          SUMA_S_Warn("TR > 360, reduced it by a factor of 1000.\n");
12517          TR *= 0.001;
12518       }
12519    }
12520    if (TRp) *TRp = TR;
12521    if ( mm && TR >= 0.0) SUMA_RETURN(1);
12522 
12523    SUMA_RETURN(0);
12524 }
12525 
SUMA_SetDsetTR(SUMA_DSET * dset,double TR)12526 SUMA_Boolean SUMA_SetDsetTR(SUMA_DSET *dset, double TR)
12527 {
12528    static char FuncName[]={"SUMA_SetDsetTR"};
12529    char ccc[32];
12530 
12531    SUMA_ENTRY;
12532 
12533    if (TR < 0 || !dset || !dset->dnel) SUMA_RETURN(NOPE);
12534    if (!SUMA_is_AllNumeric_dset(dset)) SUMA_RETURN(NOPE);
12535    sprintf(ccc,"%f", TR);
12536    NI_set_attribute(dset->dnel, "ni_timestep", ccc);
12537    SUMA_RETURN(YUP);
12538 }
12539 
12540 /*!
12541    \brief returns the indices of columns that are numeric
12542    and likely considered as data
12543    free returned pointer with SUMA_free
12544 */
SUMA_FindNumericDataDsetCols(SUMA_DSET * dset,int * N_icols)12545 int * SUMA_FindNumericDataDsetCols(SUMA_DSET *dset, int *N_icols)
12546 {
12547    static char FuncName[]={"SUMA_FindNumericDataDsetCols"};
12548    int *icols = NULL, i, ctp, vtp;
12549 
12550    SUMA_ENTRY;
12551 
12552    *N_icols = -1;
12553 
12554    if (!dset || !dset->dnel) SUMA_RETURN(NULL);
12555 
12556    icols = (int *)SUMA_calloc(SDSET_VECNUM(dset), sizeof(int));
12557    if (!icols) {
12558       SUMA_S_Err("Failed to allocate");
12559       SUMA_RETURN(NULL);
12560    }
12561 
12562    *N_icols = 0;
12563    for (i=0; i<SDSET_VECNUM(dset); ++i) {
12564       ctp = SUMA_TypeOfDsetColNumb(dset, i);
12565       if (  SUMA_IS_DATUM_INDEX_COL(ctp) ||
12566             ctp == SUMA_NODE_ILABEL ||
12567             ctp == SUMA_NODE_SLABEL ||
12568             ctp == SUMA_NODE_STRING ||
12569             ctp == SUMA_GNODE_IGROUP )
12570          continue;
12571       vtp = SUMA_ColType2TypeCast(ctp) ;
12572       if (vtp < SUMA_byte || vtp > SUMA_double) continue;
12573 
12574       icols[*N_icols] = i;
12575       ++(*N_icols);
12576    }
12577 
12578    SUMA_RETURN(icols);
12579 }
12580 
SUMA_is_AllNumeric_ngr(NI_group * ngr)12581 int SUMA_is_AllNumeric_ngr(NI_group *ngr)
12582 {
12583    static char FuncName[]={"SUMA_is_AllNumeric_ngr"};
12584    int ctp, vtp, i;
12585    NI_element *nelb;
12586    char *sname=NULL;
12587    SUMA_DSET dset;
12588 
12589    SUMA_ENTRY;
12590 
12591    if (!ngr) SUMA_RETURN(0);
12592 
12593    sname = SUMA_append_string(NEL_DSET_TYPE(ngr),"_data");
12594    nelb = SUMA_FindNgrDataElement(ngr, "SPARSE_DATA", sname);
12595    SUMA_free(sname); sname = NULL;
12596    dset.ngr = ngr;
12597    dset.dnel = nelb;
12598 
12599    /* this one's overkill perhaps ...*/
12600    if (SUMA_isGraphDsetNgr(ngr))
12601         sname = SUMA_append_string(NEL_DSET_TYPE(ngr),"_edge_indices");
12602    else sname = SUMA_append_string(NEL_DSET_TYPE(ngr),"_node_indices");
12603    nelb = SUMA_FindNgrDataElement(ngr, "INDEX_LIST", sname);
12604    SUMA_free(sname); sname = NULL;
12605    dset.inel = nelb;
12606 
12607    for (i=0; i<dset.dnel->vec_num; ++i) {
12608       ctp = SUMA_TypeOfDsetColNumb(&dset, i);
12609       vtp = SUMA_ColType2TypeCast(ctp) ;
12610       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
12611    }
12612 
12613    SUMA_RETURN(1);
12614 }
12615 
SUMA_is_AllNumeric_nel(NI_element * nel)12616 int SUMA_is_AllNumeric_nel(NI_element *nel)
12617 {
12618    static char FuncName[]={"SUMA_is_AllNumeric_nel"};
12619    int ctp, vtp, i;
12620 
12621    SUMA_ENTRY;
12622 
12623    /*
12624       Macro NEL_WRITE_1D still needs this ...
12625 
12626       SUMA_SL_Warn("Obsolete, perhaps. Check on caller.");
12627    */
12628 
12629    if (!nel) SUMA_RETURN(0);
12630 
12631    for (i=0; i<nel->vec_num; ++i) {
12632       ctp = SUMA_TypeOfColNumb(nel, i);
12633       vtp = SUMA_ColType2TypeCast(ctp) ;
12634       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
12635    }
12636 
12637    SUMA_RETURN(1);
12638 }
12639 
12640 static char *ParentOfDsetToLoad = NULL;
12641 
12642 /*! Used to provide an identifier for the surface on which a dset will
12643 be attached. Remember to reset this pointer to NULL after loading the dset
12644 This is not used (yet) for assigning a SO parent to the dset*/
SUMA_SetParent_DsetToLoad(char * parent)12645 void SUMA_SetParent_DsetToLoad(char *parent)
12646 {
12647    ParentOfDsetToLoad = parent;
12648    return;
12649 }
12650 
SUMA_Alloc_OpenDX_Struct(void)12651 SUMA_OPEN_DX_STRUCT *SUMA_Alloc_OpenDX_Struct(void)
12652 {
12653    static char FuncName[]={"SUMA_Alloc_OpenDX_Struct"};
12654    int i;
12655    SUMA_OPEN_DX_STRUCT *dx = NULL;
12656 
12657    SUMA_ENTRY;
12658 
12659    dx = (SUMA_OPEN_DX_STRUCT *)SUMA_calloc(1,sizeof(SUMA_OPEN_DX_STRUCT));
12660    dx->rank = 0;
12661    dx->shape = 0;
12662    dx->items = 0;
12663    dx->bad_data = 0;
12664    dx->object = NULL;
12665    dx->class = NULL;
12666    dx->type = NULL;
12667    dx->data = NULL;
12668    dx->data_format = 0;
12669    dx->data_off = NULL;
12670    dx->datap = NULL;
12671    dx->n_comp = 0;
12672    dx->counts = NULL;
12673    dx->n_counts = 0;
12674    dx->origin = NULL;
12675    dx->n_origin = 0;
12676    dx->delta = NULL;
12677    dx->n_delta = 0;
12678    for (i=0; i<SUMA_MAX_OPEN_DX_FIELD_COMPONENTS; ++i) {
12679       dx->comp_name[i] = dx->comp_value[i] =NULL; }
12680    dx->n_attr = 0;
12681    for (i=0; i<SUMA_MAX_OPEN_DX_FIELD_ATTRIBUTES; ++i) {
12682       dx->attr_name[i] = dx->attr_string[i] =NULL; }
12683    SUMA_RETURN(dx);
12684 }
12685 
SUMA_Free_OpenDX_Struct(SUMA_OPEN_DX_STRUCT * dx)12686 SUMA_OPEN_DX_STRUCT *SUMA_Free_OpenDX_Struct(SUMA_OPEN_DX_STRUCT *dx)
12687 {
12688    static char FuncName[]={"SUMA_Free_OpenDX_Struct"};
12689    int i;
12690 
12691    SUMA_ENTRY;
12692 
12693    if (!dx) SUMA_RETURN(dx);
12694    if (dx->object) SUMA_free(dx->object); dx->object = NULL;
12695    if (dx->class) SUMA_free(dx->class); dx->class = NULL;
12696    if (dx->data) SUMA_free(dx->data); dx->data = NULL;
12697    if (dx->data_off) SUMA_free(dx->data_off); dx->data_off = NULL;
12698    if (dx->datap) {
12699       if ( SUMA_OK_OPENDX_DATA_TYPE(SUMA_CTypeName2VarType (dx->type)) ) {
12700          SUMA_free(dx->datap); dx->datap = NULL;
12701       } else {
12702          SUMA_SL_Warn("Do not know how to free datap.\n"
12703                       "You now possibly have a leak on your hands.");
12704       }
12705    }
12706    if (dx->type) SUMA_free(dx->type); dx->type = NULL;
12707    for (i=0; i<SUMA_MAX_OPEN_DX_FIELD_COMPONENTS; ++i) {
12708       if (dx->comp_name[i]) SUMA_free(dx->comp_name[i]); dx->comp_name[i] = NULL;
12709       if (dx->comp_value[i]) SUMA_free(dx->comp_value[i]);
12710       dx->comp_value[i] =NULL;
12711    }
12712    for (i=0; i<SUMA_MAX_OPEN_DX_FIELD_ATTRIBUTES; ++i) {
12713       if (dx->attr_name[i]) SUMA_free(dx->attr_name[i]); dx->attr_name[i] = NULL;
12714       if (dx->attr_string[i]) SUMA_free(dx->attr_string[i]);
12715       dx->attr_string[i] =NULL;
12716    }
12717    if (dx->origin) SUMA_free(dx->origin);
12718    if (dx->delta) SUMA_free(dx->delta);
12719    if (dx->counts) SUMA_free(dx->counts);
12720    SUMA_free(dx); dx = NULL;
12721    SUMA_RETURN(dx);
12722 }
12723 
SUMA_Show_OpenDX_Struct(SUMA_OPEN_DX_STRUCT ** dxv,int N_dxv,FILE * out)12724 void SUMA_Show_OpenDX_Struct(SUMA_OPEN_DX_STRUCT **dxv, int N_dxv, FILE *out)
12725 {
12726    static char FuncName[]={"SUMA_Show_OpenDX_Struct"};
12727    int i, idx;
12728    SUMA_STRING *SS=NULL;
12729    char *s = NULL;
12730    SUMA_OPEN_DX_STRUCT *dx=NULL;
12731 
12732    SUMA_ENTRY;
12733 
12734    SS = SUMA_StringAppend(NULL, NULL);
12735    if (!dxv) SS = SUMA_StringAppend(SS, "NULL dxv\n");
12736    for (idx = 0; idx < N_dxv; ++idx) {
12737       dx = dxv[idx];
12738       SS = SUMA_StringAppend_va(SS, "Object Struct %d/%d\n", idx+1, N_dxv);
12739       if (!dx) SS = SUMA_StringAppend(SS, "NULL dx\n");
12740       else {
12741          if (dx->object)
12742             SS = SUMA_StringAppend_va(SS, "object: %s\n", dx->object);
12743          else SS = SUMA_StringAppend_va(SS, "object: NULL\n");
12744          if (dx->class) SS = SUMA_StringAppend_va(SS, "class: %s\n", dx->class);
12745          else SS = SUMA_StringAppend_va(SS, "class: NULL\n");
12746          if (dx->type) SS = SUMA_StringAppend_va(SS, "type: %s\n", dx->type);
12747          else SS = SUMA_StringAppend_va(SS, "type: NULL\n");
12748          if (dx->rank) SS = SUMA_StringAppend_va(SS, "rank: %d\n", dx->rank);
12749          else SS = SUMA_StringAppend_va(SS, "rank: 0\n");
12750          if (dx->shape) SS = SUMA_StringAppend_va(SS, "shape: %d\n", dx->shape);
12751          else SS = SUMA_StringAppend_va(SS, "shape: 0\n");
12752          if (dx->items) SS = SUMA_StringAppend_va(SS, "items: %d\n", dx->items);
12753          else SS = SUMA_StringAppend_va(SS, "items: 0\n");
12754          if (dx->counts) {
12755             SS = SUMA_StringAppend_va(SS, "counts: (%d vals)\n", dx->n_counts);
12756             s = SUMA_ShowMeSome(dx->counts, SUMA_int, dx->n_counts, 5, NULL);
12757             SS = SUMA_StringAppend_va(SS, "\t%s\n", s); SUMA_free(s); s = NULL;
12758          } else SS = SUMA_StringAppend_va(SS, "counts: NULL\n");
12759          if (dx->origin) {
12760             SS = SUMA_StringAppend_va(SS, "origin: (%d vals)\n", dx->n_origin);
12761             s = SUMA_ShowMeSome(dx->origin, SUMA_float, dx->n_origin, 5, NULL);
12762             SS = SUMA_StringAppend_va(SS, "\t%s\n", s); SUMA_free(s); s = NULL;
12763          } else SS = SUMA_StringAppend_va(SS, "origin: NULL\n");
12764          if (dx->delta) {
12765             SS = SUMA_StringAppend_va(SS, "delta: (%d vals)\n", dx->n_delta);
12766             s = SUMA_ShowMeSome(dx->delta, SUMA_float, dx->n_delta, 9, NULL);
12767             SS = SUMA_StringAppend_va(SS, "\t%s\n", s); SUMA_free(s); s = NULL;
12768          }else SS = SUMA_StringAppend_va(SS, "delta: NULL\n");
12769 
12770          if (dx->data) SS = SUMA_StringAppend_va(SS, "data: %s (Data load error %d)\n", dx->data, dx->bad_data);
12771          else SS = SUMA_StringAppend_va(SS, "data: NULL\n");
12772          if (dx->data_off) SS = SUMA_StringAppend_va(SS, "data_off: %s \n", dx->data_off);
12773          else SS = SUMA_StringAppend_va(SS, "data_off: NULL\n");
12774          SS = SUMA_StringAppend_va(SS, "data_format: %d \n", dx->data_format);
12775          if (dx->datap) {
12776             s = SUMA_ShowMeSome(dx->datap, SUMA_CTypeName2VarType(dx->type), dx->items * SUMA_NCOL_OPENDX(dx), 5, NULL);
12777             SS = SUMA_StringAppend_va(SS, "\t%s\n", s); SUMA_free(s); s = NULL;
12778          }
12779          if (dx->n_comp) {
12780             SS = SUMA_StringAppend_va(SS, "components: %d\n", dx->n_comp);
12781             for (i=0; i<dx->n_comp; ++i) {
12782                if (dx->comp_name[i]) SS = SUMA_StringAppend_va(SS, "\tname: %s\t", dx->comp_name[i]);
12783                else SS = SUMA_StringAppend_va(SS, "\tname: NULL\t");
12784                if (dx->comp_value[i]) SS = SUMA_StringAppend_va(SS, "\ttype: %s\n", dx->comp_value[i]);
12785                else SS = SUMA_StringAppend_va(SS, "\ttype: NULL\n");
12786             }
12787          } else {
12788             SS = SUMA_StringAppend_va(SS, "components: %d\n", dx->n_comp);
12789          }
12790          if (dx->n_attr) {
12791             SS = SUMA_StringAppend_va(SS, "attributes: %d\n", dx->n_attr);
12792             for (i=0; i<dx->n_attr; ++i) {
12793                if (dx->attr_name[i]) SS = SUMA_StringAppend_va(SS, "\tname: %s\t", dx->attr_name[i]);
12794                else SS = SUMA_StringAppend_va(SS, "\tname: NULL\t");
12795                if (dx->attr_string[i]) SS = SUMA_StringAppend_va(SS, "\tstring: %s\n", dx->attr_string[i]);
12796                else SS = SUMA_StringAppend_va(SS, "\tstring: NULL\n");
12797             }
12798          } else {
12799             SS = SUMA_StringAppend_va(SS, "attributes: %d\n", dx->n_attr);
12800          }
12801       }
12802    }
12803 
12804    SUMA_SS2S(SS,s);
12805    if (!out) fprintf(stdout, "%s", s);
12806    else fprintf(out, "%s", s);
12807 
12808    SUMA_free(s); s = NULL;
12809 
12810    SUMA_RETURNe;
12811 }
12812 /*!
12813    \sa http://opendx.npaci.edu/docs/html/pages/usrgu068.htm#Header_417
12814 */
SUMA_OpenDX_Read(char * fname,int * nobj)12815 SUMA_OPEN_DX_STRUCT **SUMA_OpenDX_Read(char *fname, int *nobj)
12816 {
12817    static char FuncName[]={"SUMA_OpenDX_Read"};
12818    int nread = 0, i = 0,  iop, *ivalp=NULL, shft=0;
12819    char *fl=NULL, **opv = NULL, *op = NULL,*sbuf=NULL, **svalp=NULL, *ope;
12820    int *nchar = NULL;
12821    SUMA_OPEN_DX_STRUCT **dxv=NULL;
12822    SUMA_FVEC *fvec=NULL;
12823    SUMA_IVEC *ivec=NULL;
12824    SUMA_Boolean LocalHead = NOPE;
12825 
12826    SUMA_ENTRY;
12827 
12828    *nobj = 0;
12829 
12830    SUMA_LH("Sucking file");
12831    nread = SUMA_suck_file( fname , &fl ) ;
12832    if (!fl) {
12833       SUMA_SL_Err("Failed to read file.");
12834       SUMA_RETURN(dxv);
12835    }
12836 
12837    if (LocalHead) fprintf(SUMA_STDERR,"%s: Read in %d chars\n", FuncName, nread);
12838 
12839    opv = (char **)SUMA_calloc(SUMA_MAX_OPEN_DX_OBJECTS, sizeof(char*));
12840    nchar = (int*)SUMA_calloc(SUMA_MAX_OPEN_DX_OBJECTS, sizeof(int));
12841    dxv = (SUMA_OPEN_DX_STRUCT **)SUMA_calloc(SUMA_MAX_OPEN_DX_OBJECTS, sizeof(SUMA_OPEN_DX_STRUCT *));
12842 
12843    /* now search for the first "object" */
12844    op = fl;
12845    iop = 0;
12846    shft = 0;
12847    do {
12848       op = strstr((op+shft), "object");
12849       if (op) {
12850          opv[iop] = op;
12851          if (iop) nchar[iop-1] = opv[iop] - opv[iop-1];
12852          if (LocalHead) {
12853             fprintf(SUMA_STDERR,"%s: Object found.\n", FuncName);
12854             i = 0;
12855             while (i<20 && op[i] !='\0') { fprintf(SUMA_STDERR,"%c",op[i]); ++i; } fprintf(SUMA_STDERR,"\n");
12856          }
12857 
12858          /* must skip beyond first "object" for next pass*/
12859          shft = strlen("object");
12860          ++iop;
12861       }
12862    } while (op && iop < SUMA_MAX_OPEN_DX_OBJECTS);
12863    if (iop >= SUMA_MAX_OPEN_DX_OBJECTS) {
12864       SUMA_SL_Warn("Too many objects, processing first SUMA_MAX_OPEN_DX_OBJECTS only");
12865    }
12866 
12867    if (iop) {/* find the length of the last object */
12868       op = opv[iop-1];
12869       while (*op !='\0') { ++op; }
12870       nchar[iop-1] = op - opv[iop-1];
12871    }
12872 
12873    if (LocalHead) {
12874       fprintf(SUMA_STDERR,"%s: %d Objects found.\n", FuncName, iop);
12875    }
12876 
12877    for (i=0; i<iop; ++i) { /* process each object's header field and data*/
12878       if ( 0 && LocalHead) { /* potentially huge dump if nmax is not controlled*/
12879          int j, nmax;
12880          nmax = 500; /* could also use nchar[i]*/
12881          fprintf(SUMA_STDERR,"%s Object %d\n", FuncName, i);
12882          op = opv[i]; for (j=0; j<nmax; ++j) fprintf(SUMA_STDERR,"%c", op[j]);
12883          fprintf(SUMA_STDERR,"\n");
12884       }
12885       /* get the class */
12886       dxv[i] = SUMA_Alloc_OpenDX_Struct();
12887       ivalp = (int *)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "rank", NULL);
12888       if (ivalp) dxv[i]->rank = *ivalp;
12889       ivalp = (int *)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "shape", NULL);
12890       if (ivalp) dxv[i]->shape = *ivalp;
12891       ivalp = (int *)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "items", NULL);
12892       if (ivalp) dxv[i]->items = *ivalp;
12893       svalp = (char **)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "object", NULL);
12894       if (svalp) dxv[i]->object = *svalp;
12895       svalp = (char **)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "class", NULL);
12896       if (svalp) dxv[i]->class = *svalp;
12897       svalp = (char **)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "type", NULL);
12898       if (svalp) dxv[i]->type = *svalp;
12899       ivec = (SUMA_IVEC*)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "counts", NULL);
12900       if (ivec) { dxv[i]->counts = ivec->v; dxv[i]->n_counts = ivec->n; SUMA_free(ivec); ivec = NULL;}
12901       fvec = (SUMA_FVEC*)SUMA_OpenDx_Object_Header_Field(opv[i], nchar[i], "origin", NULL);
12902       if (fvec) { dxv[i]->origin = fvec->v; dxv[i]->n_origin = fvec->n; SUMA_free(fvec); fvec = NULL;}
12903       { /* get the deltas */
12904          int j, k;
12905          char *rf=opv[i];
12906          j=0;
12907          while (j<dxv[i]->n_counts) {
12908             fvec = (SUMA_FVEC*)SUMA_OpenDx_Object_Header_Field(rf, nchar[i], "delta", &ope);
12909             if (fvec && fvec->v) {
12910                if (fvec->n < dxv[i]->n_counts) { SUMA_SL_Warn("Bad assumption about delta field.\nExpect disasters!"); }
12911                if (fvec->n > dxv[i]->n_counts) {
12912                   SUMA_SL_Err("More values in delta that counts! Limiting to counts.\nExpect tragedy.");
12913                   fvec->n = dxv[i]->n_counts;
12914                }
12915                if (j==0) { /* allocate */
12916                   dxv[i]->n_delta = dxv[i]->n_counts*dxv[i]->n_counts;
12917                   dxv[i]->delta = (float *)SUMA_calloc(dxv[i]->n_delta, sizeof(float));
12918                }
12919                for (k=0; k<fvec->n; ++k) {
12920                   dxv[i]->delta[(j*dxv[i]->n_counts) + k] = fvec->v[k];
12921                }
12922                SUMA_free(fvec->v); SUMA_free(fvec); fvec = NULL;
12923             } else { /* get out */
12924                if (j) {
12925                   SUMA_SL_Warn("Expect as many deltas as counts!\nThat was not the case.");
12926                } else { /* OK, no deltas at all */ }
12927                j = dxv[i]->n_counts;
12928             }
12929             ++j; rf = ope;
12930          }
12931       }
12932       /* now for the data */
12933       if (!SUMA_OpenDx_Object_Data(opv[i], nchar[i], dxv[i])) {
12934          SUMA_SL_Err("Failed to get data");
12935          dxv[i]->bad_data = 1;
12936       }
12937    }
12938 
12939    for (i=0; i<iop; ++i) { /* process each object's attributes*/
12940       if (!SUMA_OpenDx_Object_Attr(opv[i], nchar[i], dxv[i])) {
12941          SUMA_SL_Err("Failed in SUMA_OpenDx_Object_Attr");
12942       }
12943       if (!SUMA_OpenDx_Object_Components(opv[i], nchar[i], dxv[i])) {
12944          SUMA_SL_Err("Failed in SUMA_OpenDx_Object_Components");
12945       }
12946    }
12947 
12948    if (LocalHead) {
12949          SUMA_Show_OpenDX_Struct(dxv, iop, NULL); fflush(stdout);
12950    }
12951 
12952    if (opv) SUMA_free(opv); opv = NULL;
12953    if (nchar) SUMA_free(nchar); nchar = NULL;
12954    if (fl) SUMA_free(fl); fl = NULL; /* added Mon May 9 05, ZSS */
12955    *nobj = iop;
12956    SUMA_RETURN(dxv);
12957 }
12958 
12959 /*!
12960 
12961    \brief Load a surface-based data set of the DX format
12962    \param Name (char *) name or prefix of dataset
12963    \param verb (int) level of verbosity. 0 mute, 1 normal, 2 dramatic perhaps
12964    \return dset (SUMA_DSET *)
12965 
12966 */
SUMA_LoadDXDset_ns(char * Name,int verb)12967 SUMA_DSET *SUMA_LoadDXDset_ns (char *Name, int verb)
12968 {
12969    SUMA_DSET *dset=SUMA_LoadDXDset_eng (Name,  verb);
12970    WorkErrLog_ns();
12971    return(dset);
12972 }
SUMA_LoadDXDset_eng(char * Name,int verb)12973 SUMA_DSET *SUMA_LoadDXDset_eng (char *Name, int verb)
12974 {
12975    static char FuncName[]={"SUMA_LoadDXDset_eng"};
12976    char *FullName = NULL;
12977    MRI_IMAGE *im = NULL;
12978    float *far=NULL;
12979    int i, ndxv=0;
12980    char *idcode = NULL, *name=NULL;
12981    SUMA_DSET *dset=NULL;
12982    SUMA_OPEN_DX_STRUCT **dxv=NULL, *dx=NULL;
12983    SUMA_ENTRY;
12984 
12985    if (!Name) { SUMA_PushErrLog("SL_Err", "Null Name", FuncName); SUMA_RETURN(dset); }
12986 
12987    /* work the name */
12988    if (!SUMA_filexists(Name)) {
12989       /* try the extension game */
12990       FullName = SUMA_Extension(Name, ".dx.dset", NOPE);
12991       if (!SUMA_filexists(FullName)) {
12992          SUMA_free(FullName); FullName = NULL;
12993          FullName = SUMA_Extension(Name, ".dx", NOPE);
12994          if (!SUMA_filexists(FullName)) {
12995             if (verb)  { SUMA_PushErrLog("SL_Err", "Failed to find dset file.", FuncName); }
12996             goto CLEAN_EXIT;
12997          }
12998       }
12999    }else {
13000       FullName = SUMA_copy_string(Name);
13001    }
13002 
13003    /* load the objects */
13004    if (!(dxv = SUMA_OpenDX_Read(FullName, &ndxv))) {
13005       if (verb) SUMA_PushErrLog("SL_Err", "Failed to read OpenDx File", FuncName);
13006       goto CLEAN_EXIT;
13007    }
13008 
13009    /* if more than one, warn that only one is to be used */
13010    if (ndxv < 1) {
13011       SUMA_PushErrLog("SL_Err", "no objects in file", FuncName);
13012       goto CLEAN_EXIT;
13013    }else if (ndxv > 1) {
13014       SUMA_SL_Warn("More than one object found in file.\nUsing first applicable one.");
13015    }
13016    /* find the object that is appropriate */
13017    i=0; dx = NULL;
13018    while (i<ndxv && !dx) {
13019       if (dxv[i]->datap && dxv[i]->items) {
13020          dx = dxv[i];
13021       }
13022       ++i;
13023    }
13024    if (!dx) {
13025       SUMA_PushErrLog("SL_Err", "No appropriate objects found", FuncName);
13026       SUMA_Show_OpenDX_Struct(dxv, ndxv, NULL); fflush(stdout);
13027       goto CLEAN_EXIT;
13028    }
13029    /* transfer contents to dset */
13030    if (ParentOfDsetToLoad) name = SUMA_append_string(ParentOfDsetToLoad, FullName);
13031    else if (FullName) name = SUMA_copy_string(FullName);
13032    else name = SUMA_copy_string("wow");
13033    SUMA_NEW_ID(idcode, name);
13034    SUMA_free(name); name = NULL;
13035    dset = SUMA_OpenDX2dset(FullName, idcode, NULL, dx);
13036    if (idcode) SUMA_free(idcode); idcode = NULL;
13037    if (!dset) {
13038       SUMA_PushErrLog("SLP_Err", "Failed in SUMA_OpenDX2dset\n", FuncName);
13039       goto CLEAN_EXIT;
13040    }
13041 
13042 
13043    CLEAN_EXIT:
13044    if (FullName) SUMA_free(FullName); FullName = NULL;
13045    for (i=0; i<ndxv; ++i) {
13046       dxv[i] = SUMA_Free_OpenDX_Struct(dxv[i]);
13047    }
13048    if (dxv) SUMA_free(dxv); dxv = NULL;
13049    SUMA_RETURN(dset);
13050 }
13051 /*!
13052 
13053    \brief Load a surface-based data set of the 1D format
13054    \param Name (char *) name or prefix of dataset
13055    \param verb (int) level of verbosity. 0 mute, 1 normal, 2 dramatic perhaps
13056    \return dset (SUMA_DSET *)
13057 
13058 */
SUMA_Load1DDset_ns(char * oName,int verb)13059 SUMA_DSET *SUMA_Load1DDset_ns (char *oName, int verb)
13060 {
13061    SUMA_DSET *dset=SUMA_Load1DDset_eng (oName,  verb);
13062    WorkErrLog_ns();
13063    return(dset);
13064 }
SUMA_Load1DDset_eng(char * oName,int verb)13065 SUMA_DSET *SUMA_Load1DDset_eng (char *oName, int verb)
13066 {
13067    static char FuncName[]={"SUMA_Load1DDset_eng"};
13068    char *FullName = NULL;
13069    MRI_IMAGE *im = NULL;
13070    float *far=NULL;
13071    int i;
13072    char *idcode = NULL, *name=NULL, *nstrip = NULL;
13073    SUMA_DSET *dset=NULL;
13074 
13075    SUMA_ENTRY;
13076 
13077    if (!oName) {
13078       SUMA_PushErrLog("SL_Err", "Null Name", FuncName); SUMA_RETURN(dset); }
13079 
13080    /* SUMA_S_Note(oName); */
13081    /* remove [] if existing */
13082    nstrip = SUMA_copy_string(oName);
13083    for (i=0; i<strlen(nstrip); ++i)
13084       if (nstrip[i] == '[') { nstrip[i] = '\0'; break; }
13085 
13086    /* work the name */
13087    if (!SUMA_filexists(nstrip)) {
13088       /* try the extension game */
13089       FullName = SUMA_Extension(nstrip, ".1D.dset", NOPE);
13090       if (!SUMA_filexists(FullName)) {
13091          if (verb)  {
13092             SUMA_PushErrLog("SL_Err", "Failed to find dset file.", FuncName); }
13093          if (FullName) SUMA_free(FullName); FullName = NULL;
13094          SUMA_RETURN(dset);
13095       }
13096    }else {
13097       FullName = SUMA_copy_string(nstrip);
13098    }
13099    /* got the name, now read it */
13100    im = mri_read_1D (oName);
13101    if (!im) {
13102       if (verb) SUMA_PushErrLog("SLP_Err", "Failed to read file", FuncName);
13103       if (FullName) SUMA_free(FullName); FullName = NULL;
13104       SUMA_RETURN(NULL);
13105    }
13106 
13107    /* form a good id */
13108    if (ParentOfDsetToLoad)
13109       name = SUMA_append_string(ParentOfDsetToLoad, FullName);
13110    else if (FullName) name = SUMA_copy_string(FullName);
13111    else name = SUMA_copy_string("wow");
13112    SUMA_NEW_ID(idcode, name);
13113    SUMA_free(name); name = NULL;
13114    far = MRI_FLOAT_PTR(im);
13115    dset = SUMA_far2dset_ns(FullName, idcode, NULL, &far, im->nx, im->ny, 0);
13116    if (idcode) SUMA_free(idcode); idcode = NULL;
13117    if (!dset) {
13118       SUMA_PushErrLog("SLP_Err", "Failed in SUMA_far2dset\n", FuncName);
13119       if (im) mri_free(im); im = NULL;
13120       if (FullName) SUMA_free(FullName); FullName = NULL;
13121       SUMA_RETURN(NULL);
13122    }
13123 
13124    /* done, clean up and out you go */
13125    if (im) mri_free(im); im = NULL;
13126    if (FullName) SUMA_free(FullName); FullName = NULL;
13127    if (nstrip) SUMA_free(nstrip); nstrip = NULL;
13128    SUMA_RETURN(dset);
13129 }
13130 
13131 /*!
13132    \brief a convenience function to return a 1D file in a float array
13133    \param oName (char *) name of 1D file, can use '[]' if you like.
13134    \param ncol (int *) to hold the number of columns in the file.
13135    \param nrow (int *) to hold the number of rows in the file.
13136    \param RowMajor (int) 0 keep result in column major   xxxxxx yyyyyy zzzzzz
13137                         1 turn results to row major       xyz xyz xyz xyz
13138    \return far(float *), the float array. Should be freed with free but SUMA_free
13139    would work too.
13140 */
SUMA_Load1D_ns(char * oName,int * ncol,int * nrow,int RowMajor,int verb)13141 float *SUMA_Load1D_ns (char *oName, int *ncol, int *nrow, int RowMajor,
13142                        int verb)
13143 {
13144    float *far=SUMA_Load1D_eng (oName, ncol, nrow,  RowMajor,  verb);
13145    WorkErrLog_ns();
13146    return(far);
13147 }
SUMA_Load1D_eng(char * oName,int * ncol,int * nrow,int RowMajor,int verb)13148 float *SUMA_Load1D_eng (char *oName, int *ncol, int *nrow, int RowMajor,
13149                         int verb)
13150 {
13151    static char FuncName[]={"SUMA_Load1D_eng"};
13152    char *FullName = NULL;
13153    MRI_IMAGE *im = NULL, *imt = NULL;
13154    float *far=NULL;
13155    int i;
13156    SUMA_Boolean LocalHead = NOPE;
13157 
13158    SUMA_ENTRY;
13159 
13160    if (!oName) {
13161       SUMA_PushErrLog("SL_Err", "Null Name", FuncName); SUMA_RETURN(NULL); }
13162 
13163    /* got the name, now read it */
13164    im = mri_read_1D (oName);
13165    if (!im) {
13166       if (verb) SUMA_PushErrLog("SLP_Err","Failed to read file", FuncName);
13167       SUMA_RETURN(NULL);
13168    }
13169    *ncol = im->ny;
13170    *nrow = im->nx;
13171    if (LocalHead) fprintf(SUMA_STDERR,
13172                      "Read %s, found %d cols, %d rows\n", oName, *ncol, *nrow);
13173    if (RowMajor) {
13174       imt = mri_transpose(im); mri_free(im); im = imt; imt = NULL;
13175    }
13176 
13177    far = MRI_FLOAT_PTR(im);
13178    /* make sure that pointer is gone from im, or risk hell */
13179    mri_clear_data_pointer(im) ;
13180 
13181    /* done, clean up and out you go */
13182    if (im) mri_free(im); im = NULL;
13183 
13184    SUMA_RETURN(far);
13185 }
SUMA_LoadDouble1D_eng(char * oName,int * ncol,int * nrow,int RowMajor,int verb)13186 double *SUMA_LoadDouble1D_eng (char *oName, int *ncol, int *nrow, int RowMajor, int verb)
13187 {
13188    static char FuncName[]={"SUMA_LoadDouble1D_eng"};
13189    char *FullName = NULL;
13190    MRI_IMAGE *im = NULL, *imt = NULL;
13191    double *far=NULL;
13192    int i;
13193 
13194    SUMA_ENTRY;
13195 
13196    if (!oName) { SUMA_PushErrLog("SL_Err", "Null Name", FuncName); SUMA_RETURN(NULL); }
13197 
13198    /* got the name, now read it */
13199    im = mri_read_double_1D (oName);
13200    if (!im) {
13201       if (verb) SUMA_PushErrLog("SLP_Err","Failed to read file", FuncName);
13202       SUMA_RETURN(NULL);
13203    }
13204    *ncol = im->ny;
13205    *nrow = im->nx;
13206 
13207    if (RowMajor) {
13208       imt = mri_transpose(im); mri_free(im); im = imt; imt = NULL;
13209    }
13210 
13211    far = MRI_DOUBLE_PTR(im);
13212    /* make sure that pointer is gone from im, or risk hell */
13213    mri_clear_data_pointer(im) ;
13214 
13215    /* done, clean up and out you go */
13216    if (im) mri_free(im); im = NULL;
13217 
13218    SUMA_RETURN(far);
13219 }
13220 
SUMA_LoadComplex1D_eng(char * oName,int * ncol,int * nrow,int RowMajor,int verb)13221 complex *SUMA_LoadComplex1D_eng (char *oName, int *ncol, int *nrow, int RowMajor, int verb)
13222 {
13223    static char FuncName[]={"SUMA_LoadComplex1D_eng"};
13224    char *FullName = NULL;
13225    MRI_IMAGE *im = NULL, *imt = NULL;
13226    complex *far=NULL;
13227    int i;
13228 
13229    SUMA_ENTRY;
13230 
13231    if (!oName) { SUMA_PushErrLog("SL_Err", "Null Name", FuncName); SUMA_RETURN(NULL); }
13232 
13233    /* got the name, now read it */
13234    im = mri_read_complex_1D (oName);
13235    if (!im) {
13236       if (verb) SUMA_PushErrLog("SLP_Err","Failed to read file", FuncName);
13237       SUMA_RETURN(NULL);
13238    }
13239    *ncol = im->ny;
13240    *nrow = im->nx;
13241 
13242    if (RowMajor) {
13243       imt = mri_transpose(im); mri_free(im); im = imt; imt = NULL;
13244    }
13245 
13246    far = MRI_COMPLEX_PTR(im);
13247    /* make sure that pointer is gone from im, or risk hell */
13248    mri_clear_data_pointer(im) ;
13249 
13250    /* done, clean up and out you go */
13251    if (im) mri_free(im); im = NULL;
13252 
13253    SUMA_RETURN(far);
13254 }
13255 
13256 /*!
13257    \brief Return a dataset's data size
13258 */
SUMA_sdset_dnel_size(SUMA_DSET * dset)13259 long SUMA_sdset_dnel_size(SUMA_DSET *dset)
13260 {
13261    int ii=0;
13262    long jj=0;
13263 
13264    if (!dset || !dset->dnel) SUMA_RETURN(-1);
13265    for( jj=ii=0 ; ii < dset->dnel->vec_num ; ii++ )
13266       jj += NI_size_column( NI_rowtype_find_code(dset->dnel->vec_typ[ii]) ,
13267                             dset->dnel->vec_len , dset->dnel->vec[ii] ) ;
13268    return(jj);
13269 }
13270 
13271 /*!
13272    \brief Replaces a dataset's idcode with a new one
13273 */
SUMA_NewDsetID(SUMA_DSET * dset)13274 SUMA_Boolean SUMA_NewDsetID (SUMA_DSET *dset)
13275 {
13276    static char FuncName[]={"SUMA_NewDsetID"};
13277    char stmp[SUMA_IDCODE_LENGTH];
13278 
13279    SUMA_ENTRY;
13280 
13281    UNIQ_idcode_fill(stmp);
13282 
13283    if (!dset) SUMA_RETURN(NOPE);
13284    if (!dset->ngr) SUMA_RETURN(NOPE);
13285 
13286    NI_set_attribute(dset->ngr, "self_idcode", stmp);
13287 
13288    SUMA_RETURN(YUP);
13289 }
13290 
SUMA_NewDsetID2(SUMA_DSET * dset,char * str)13291 SUMA_Boolean SUMA_NewDsetID2 (SUMA_DSET *dset, char *str)
13292 {
13293    static char FuncName[]={"SUMA_NewDsetID2"};
13294    char *namecode;
13295 
13296    SUMA_ENTRY;
13297 
13298    if (!dset) SUMA_RETURN(NOPE);
13299    if (!dset->ngr) SUMA_RETURN(NOPE);
13300    if (str) {
13301       namecode = UNIQ_hashcode(str);  /* from str */
13302       NI_set_attribute (dset->ngr, "self_idcode", namecode);
13303       SUMA_free(namecode); namecode = NULL;
13304    } else if (NI_get_attribute(dset->ngr, "filename")) {
13305       namecode = UNIQ_hashcode(NI_get_attribute(dset->ngr, "filename"));
13306                /* from filename */
13307       NI_set_attribute (dset->ngr, "self_idcode", namecode);
13308       SUMA_free(namecode); namecode = NULL;
13309    } else {
13310       SUMA_NewDsetID (dset);
13311    }
13312 
13313 
13314    SUMA_RETURN(YUP);
13315 }
13316 
13317 /*!
13318    \brief return a niml dset's ID,
13319     substitute for macro  SDSET_ID
13320 */
SUMA_sdset_id(SUMA_DSET * dset)13321 char* SUMA_sdset_id(SUMA_DSET *dset)
13322 {
13323    static char FuncName[]={"SUMA_sdset_id"};
13324    char *id=NULL;
13325 
13326    SUMA_ENTRY;
13327 
13328    if (!dset) SUMA_RETURN(id);
13329    #ifdef OLD_DSET
13330    if (!dset->nel) SUMA_RETURN(id);
13331 
13332    id = NI_get_attribute(dset->nel,"self_idcode");
13333    if (!id) id = NI_get_attribute(dset->nel,"idcode"); /* the olde way */
13334    #else
13335    if (!dset->ngr) SUMA_RETURN(id);
13336 
13337    id = NI_get_attribute(dset->ngr,"self_idcode");
13338    if (!id) id = NI_get_attribute(dset->ngr,"idcode"); /* the olde way */
13339    #endif
13340    SUMA_RETURN(id);
13341 }
13342 
SUMA_sdset_label(SUMA_DSET * dset)13343 char *SUMA_sdset_label(SUMA_DSET *dset)
13344 {
13345    static char FuncName[]={"SUMA_sdset_label"};
13346    char *s;
13347 
13348    if (!dset || !dset->ngr || !(s=NI_get_attribute(dset->ngr,"label"))) {
13349       return("");
13350    }
13351    return(s);
13352 }
13353 
SUMA_sdset_filename(SUMA_DSET * dset)13354 char *SUMA_sdset_filename(SUMA_DSET *dset)
13355 {
13356    static char FuncName[]={"SUMA_sdset_filename"};
13357    char *s;
13358 
13359    if (!dset || !dset->ngr || !(s=NI_get_attribute(dset->ngr,"filename"))) {
13360       return("");
13361    }
13362    return(s);
13363 }
13364 
13365 
SUMA_sdset_datum_level(SUMA_DSET * dset)13366 SUMA_DATUM_LEVEL SUMA_sdset_datum_level(SUMA_DSET *dset)
13367 {
13368    static char FuncName[]={"SUMA_sdset_datum_level"};
13369    SUMA_DATUM_LEVEL dtlvl = SUMA_ELEM_DAT;
13370 
13371    if (!dset || !dset->ngr) return(dtlvl);
13372    NI_GET_INT(dset->ngr, "Datum_Level", dtlvl);
13373    if (!NI_GOT) dtlvl = SUMA_ELEM_DAT;
13374 
13375    return(dtlvl);
13376 }
13377 
SUMA_sdset_set_datum_level(SUMA_DSET * dset,SUMA_DATUM_LEVEL lvl)13378 SUMA_Boolean SUMA_sdset_set_datum_level(SUMA_DSET *dset, SUMA_DATUM_LEVEL lvl)
13379 {
13380    static char FuncName[]={"SUMA_sdset_set_datum_level"};
13381 
13382    if (!dset || !dset->ngr ||
13383          lvl < SUMA_ELEM_DAT || lvl >= SUMA_N_LEV_DAT) return(NOPE);
13384 
13385    NI_SET_INT(dset->ngr, "Datum_Level", (int)lvl);
13386    return(YUP);
13387 }
13388 
13389 /*!
13390    \brief return a niml dset's mesh parent ID , substitute for macro
13391    SDSET_IDMDOM
13392 */
SUMA_sdset_idmdom(SUMA_DSET * dset)13393 char* SUMA_sdset_idmdom(SUMA_DSET *dset)
13394 {
13395    static char FuncName[]={"SUMA_sdset_idmdom"};
13396    char *id=NULL;
13397 
13398    SUMA_ENTRY;
13399 
13400    if (!dset) SUMA_RETURN(id);
13401    #ifdef OLD_DSET
13402    if (!dset->nel) SUMA_RETURN(id);
13403 
13404    id = NI_get_attribute(dset->nel,"domain_parent_idcode");
13405    if (SUMA_IS_EMPTY_STR_ATTR(id)) id = NI_get_attribute(dset->nel,"MeshParent_idcode"); /* the olde way */
13406    #else
13407    if (!dset->ngr) SUMA_RETURN(SUMA_EMPTY_ATTR);
13408 
13409    id = NI_get_attribute(dset->ngr,"domain_parent_idcode");
13410    #endif
13411    SUMA_RETURN(id);
13412 }
13413 
13414 /* Return orientation code if available */
SUMA_Dset_orcode(SUMA_DSET * dset)13415 char *SUMA_Dset_orcode(SUMA_DSET *dset)
13416 {
13417    static char FuncName[]={"SUMA_Dset_orcode"};
13418    static int ncall = 0;
13419    int *iv=NULL;
13420    NI_element *nelb = NULL;
13421    static char ccc[10][3];
13422    char *orcode;
13423 
13424    SUMA_ENTRY;
13425 
13426    ++ncall; if (ncall > 9) ncall = 0;
13427    orcode = (char *)ccc[ncall];
13428    orcode[0] = orcode[1] = orcode[2] = 'X'; orcode[3] = '\0';
13429    if (!dset) SUMA_RETURN(orcode);
13430    if (!(nelb = SUMA_FindDsetAttributeElement(dset, "ORIENT_SPECIFIC"))) {
13431       SUMA_S_Err("No ORIENT SPECIFIC");
13432       SUMA_RETURN(orcode);
13433    }
13434    iv = (int *)nelb->vec[0];
13435    orcode[0] = ORIENT_typestr[iv[0]][0] ;
13436    orcode[1] = ORIENT_typestr[iv[1]][0] ;
13437    orcode[2] = ORIENT_typestr[iv[2]][0] ;
13438    orcode[3] = '\0';
13439 
13440    SUMA_RETURN(orcode);
13441 }
13442 
13443 
13444 /*! A function to change SUMA_DSET * to THD_3dim_dataset *
13445 This would work for float only dsets, function is in its
13446 infancy
13447    \param dsetp (SUMA_DSET **) Pointer to a dset pointer
13448                              *dsetp will be transformed to THD_3dim_dataset *
13449                              The contents of SPARSE_DATA inside dset will get
13450                              wiped out regardless of cleardset, once they are
13451                              copied into adset.
13452    \param copy_data  (int) if != 0 then the columns are populated.
13453                            Otherwise you get attributes and indices, no more.
13454    \param cleardset (int) Call SUMA_FreeDset on *dsetp and set *dsetp to NULL.
13455                           Only allowed if copy_data is set.
13456    \return adset (THD_3dim_dataset *) an AFNI dataset version of *dsetp
13457 
13458    \sa SUMA_afnidset2sumadset
13459 */
SUMA_sumadset2afnidset(SUMA_DSET ** dsetp,int copy_data,int cleardset)13460 THD_3dim_dataset *SUMA_sumadset2afnidset(
13461       SUMA_DSET **dsetp, int copy_data, int cleardset)
13462 {
13463    static char FuncName[]={"SUMA_sumadset2afnidset"};
13464    SUMA_DSET *dset = NULL;
13465    THD_3dim_dataset *newset=NULL;
13466    int rv = -1;
13467    SUMA_Boolean LocalHead = NOPE;
13468 
13469    SUMA_ENTRY;
13470 
13471    if (!dsetp) { SUMA_S_Err("Null of Null you are!"); SUMA_RETURN(newset); }
13472    dset = *dsetp;
13473    if (!dset) { SUMA_S_Err("NULL *dsetp."); SUMA_RETURN(newset); }
13474 
13475    if (!copy_data && cleardset) {
13476       SUMA_S_Err(
13477          "Requesting no datacopy and cleardset. \n"
13478          "That's a combo I can refuse.\n");
13479       SUMA_RETURN(newset);
13480    }
13481    if (!SUMA_is_AllNumeric_dset(dset)) {
13482       SUMA_S_Err("*dsetp is not all numeric");
13483       SUMA_RETURN(newset);
13484    }
13485    if (!dset->ngr || !dset->dnel) {
13486       fprintf( SUMA_STDERR,
13487                "Error %s: NULL dset contents: ngr=%p , dnel=%p\n",
13488                FuncName, dset->ngr, dset->dnel);
13489       SUMA_RETURN(newset);
13490    }
13491 
13492    if (!dset->inel || !dset->inel->vec_num) {
13493       if (!SUMA_PopulateDsetNodeIndexNel(dset,1)) {
13494             SUMA_S_Err("Failed to add node index column");
13495             exit(1);
13496       }
13497    }
13498    set_ni_globs_from_env();
13499    if (LocalHead) set_gni_debug(1);
13500    newset = THD_ni_surf_dset_to_afni(dset->ngr, 0);
13501    if (copy_data) {
13502       SUMA_LH("Copying data");
13503       rv = THD_add_sparse_data(newset->dblk->parent, dset->ngr);
13504       if( rv <= 0 ){
13505           fprintf(SUMA_STDERR,
13506                   "Error %s: add sdata returned %d for '%s'\n",
13507                   FuncName, rv, SDSET_LABEL(dset));
13508           DSET_delete(newset); newset=NULL;
13509           SUMA_RETURN(newset);
13510       }
13511       else if( rv < newset->dblk->nvals ){
13512           fprintf(SUMA_STDERR,
13513                   "Error %s: loaded only %d vols for '%s'\n",
13514                   FuncName, rv,SDSET_LABEL(dset));
13515           DSET_delete(newset); newset=NULL;
13516           SUMA_RETURN(newset);
13517       }
13518    }
13519    SUMA_LH("Clearification, perhaps");
13520    if (cleardset) { SUMA_FreeDset(dset); *dsetp = NULL; }
13521 
13522    SUMA_RETURN(newset);
13523 }
13524 
13525 /*! A function to change THD_3dim_dataset * to SUMA_DSET *
13526 This would work for float only dsets, function is in its
13527 infancy
13528    \param dsetp (THD_3dim_dataset **) Pointer to a dset pointer
13529                              *dsetp will be transformed to SUMA_DSET *
13530    \param copy_data  (int) if != 0 then the SPARSE_DATA element is populated.
13531                            Otherwise you get attributes and indices, no more.
13532    \param cleardset (int) Call DSET_delete on *dsetp and set *dsetp to NULL.
13533                           Only allowed if copy_data is set.
13534    \param floatize (int) if 1, floatize the input, unless it is complex.
13535                             0, leave as is.
13536                            -1, abide by the default (floatize is on),
13537                                and by the value of env var: AFNI_NSD_TO_FLOAT
13538                                which would be ignored otherwise.
13539    \return sdset (SUMA_DSET *) a SUMA dataset version of *dsetp
13540 
13541    \sa SUMA_sumadset2afnidset
13542 */
SUMA_afnidset2sumadset(THD_3dim_dataset ** dsetp,int copy_data,int cleardset,int floatize)13543 SUMA_DSET *SUMA_afnidset2sumadset(
13544       THD_3dim_dataset **dsetp,
13545       int copy_data, int cleardset, int floatize)
13546 {
13547    static char FuncName[]={"SUMA_afnidset2sumadset"};
13548    int ntf, vv;
13549    THD_3dim_dataset *dset = NULL;
13550    SUMA_DSET *newset=NULL;
13551    NI_group *ngr=NULL;
13552    SUMA_Boolean LocalHead = NOPE;
13553 
13554    SUMA_ENTRY;
13555 
13556    if (!dsetp) { SUMA_S_Err("Null of Null you are!"); SUMA_RETURN(newset); }
13557    if (!copy_data && cleardset) {
13558       SUMA_S_Err( "Requesting no datacopy and cleardset. \n"
13559                   "That's a combo I can refuse.\n");
13560       SUMA_RETURN(newset);
13561    }
13562    dset = *dsetp;
13563    if (!dset) { SUMA_S_Err("NULL *dsetp."); SUMA_RETURN(newset); }
13564 
13565    if (is_Dset_Atlasy(dset,NULL)) {
13566       SUMA_LH("This is an atlas");
13567    } else {
13568       SUMA_LH("No atlas");
13569    }
13570    if (floatize == -1) {
13571       set_ni_globs_from_env();
13572       ngr = THD_dset_to_ni_surf_dset(dset, copy_data);
13573    } else {
13574       ntf = get_gni_to_float(); set_gni_to_float(floatize);
13575       ngr = THD_dset_to_ni_surf_dset(dset, copy_data);
13576       set_gni_to_float(ntf);
13577    }
13578    if (!ngr) {
13579       SUMA_S_Err("Failed in THD_dset_to_ni_surf_dset");
13580       SUMA_RETURN(newset);
13581    }else {
13582       /* Keep track of HEADNAME of input */
13583       NI_set_attribute(ngr,"DSET_HEADNAME", DSET_HEADNAME(dset));
13584       if (!(newset = SUMA_ngr_2_dset(ngr, LocalHead))) {
13585          SUMA_S_Err("Failed to go from ngr to dset");
13586          SUMA_RETURN(newset);
13587       }
13588    }
13589 
13590    if (cleardset) {
13591       SUMA_LH("Clearing dset ...");
13592       DSET_delete(dset); *dsetp = NULL;
13593    }
13594 
13595    SUMA_RETURN(newset);
13596 }
13597 
13598 
SUMA_fdrcurve_zval(SUMA_DSET * dset,int iv,float thresh)13599 float SUMA_fdrcurve_zval( SUMA_DSET *dset , int iv , float thresh )
13600 {
13601    static char FuncName[]={"SUMA_fdrcurve_zval"};
13602    floatvec *fv = NULL ;
13603    float val =0.0, *v=NULL ;
13604    NI_element *nelb=NULL;
13605    int nv=-1;
13606    char name[100]={""};
13607 
13608    SUMA_ENTRY;
13609 
13610    if( !dset || iv < 0 || iv >= SDSET_VECNUM(dset) ) SUMA_RETURN(0.0f) ;
13611 
13612    sprintf(name,"FDRCURVE_%06d",iv) ;
13613    nelb = SUMA_FindNgrAttributeElement(dset->ngr, name);
13614    if (!nelb || !nelb->vec_num) SUMA_RETURN(0.0f) ;
13615 
13616    v = (float *)nelb->vec[0];
13617    nv = nelb->vec_len - 2 ;
13618    MAKE_floatvec(fv,nv) ;
13619    fv->x0 = v[0] ; fv->dx = v[1] ;
13620    memcpy( fv->ar , v + 2 , sizeof(float)*nv ) ;
13621    val = interp_floatvec(fv,thresh);
13622    KILL_floatvec(fv);
13623 
13624    SUMA_RETURN ( val ) ;
13625 }
13626 
13627 
SUMA_FormatFromFormString(char * arg)13628 SUMA_DSET_FORMAT SUMA_FormatFromFormString(char *arg) {
13629    static char FuncName[]={"SUMA_FormatFromFormString"};
13630 
13631    SUMA_DSET_FORMAT oform = SUMA_ERROR_DSET_FORMAT;
13632 
13633    SUMA_ENTRY;
13634 
13635    if (!arg) {
13636       SUMA_RETURN(oform);
13637    } else if ((strcmp(arg, "1d") == 0)) {
13638      oform = SUMA_1D;
13639    } else if ((strcmp(arg, "1dp") == 0)) {
13640       oform = SUMA_1D_PURE;
13641    } else if ((strcmp(arg, "1dpt") == 0)) {
13642       oform = SUMA_1D_PURE_TRANSPOSE;
13643    } else if ((strcmp(arg, "1d_stderr") == 0)) {
13644       oform = SUMA_1D_STDERR;
13645    } else if ((strcmp(arg, "1dp_stderr") == 0)) {
13646       oform = SUMA_1D_PURE_STDERR;
13647    } else if ((strcmp(arg, "1dpt_stderr") == 0)) {
13648       oform = SUMA_1D_PURE_STDERR_TRANSPOSE;
13649    } else if ((strcmp(arg, "1d_stdout") == 0)) {
13650       oform = SUMA_1D_STDOUT;
13651    } else if ((strcmp(arg, "1dp_stdout") == 0)) {
13652       oform = SUMA_1D_PURE_STDOUT;
13653    } else if ((strcmp(arg, "1dpt_stdout") == 0)) {
13654       oform = SUMA_1D_PURE_STDOUT_TRANSPOSE;
13655    } else if ((strcmp(arg, "niml_stderr") == 0)) {
13656       oform = SUMA_NIML_STDERR;
13657    } else if ((strcmp(arg, "niml_stdout") == 0)) {
13658       oform = SUMA_NIML_STDOUT;
13659    } else if (  (
13660          (strcmp(arg, "niml") == 0) ||
13661          (strcmp(arg, "nii") == 0) ) )  {
13662       oform = SUMA_NIML;
13663    } else if (  (
13664          (strncmp(arg, "niml_asc", 8) == 0)||
13665          (strncmp(arg, "nii_asc", 7) == 0) ||
13666          (strncmp(arg, "ni_as",5) == 0) ) ) {
13667       oform = SUMA_ASCII_NIML;
13668    } else if (  (
13669          (strncmp(arg, "niml_bi", 7) == 0)||
13670          (strncmp(arg, "nii_bi", 6) == 0) ||
13671          (strncmp(arg, "ni_bi", 5) == 0) ) ) {
13672       oform = SUMA_BINARY_NIML;
13673    } else if (  (
13674          (strncmp(arg, "gii", 3) == 0) ||
13675          (strncmp(arg, "gifti", 5) == 0) ) ) {
13676       if (AFNI_strcasestr(arg,"asc"))
13677          oform = SUMA_XML_ASCII_DSET;
13678       else if (AFNI_strcasestr(arg,"b64gz"))
13679          oform = SUMA_XML_B64GZ_DSET;
13680       else if (AFNI_strcasestr(arg,"b64"))
13681          oform = SUMA_XML_B64_DSET;
13682       else oform = SUMA_XML_DSET;
13683    }
13684 
13685    SUMA_RETURN(oform);
13686 }
13687 
13688 
13689 
13690 
13691 /*!
13692    Form the final output name from prefix.
13693    free returned full name
13694 */
SUMA_OutputDsetFileStatus(char * prefix,char * inname,SUMA_DSET_FORMAT * oformp,char * pre,char * app,int * exists)13695 char *SUMA_OutputDsetFileStatus(char *prefix, char *inname,
13696                             SUMA_DSET_FORMAT *oformp,
13697                             char *pre, char *app, int *exists)
13698 {
13699    static char FuncName[]={"SUMA_OutputDsetFileStatus"};
13700    SUMA_PARSED_NAME *Test=NULL;
13701    char *opref=NULL;
13702    SUMA_DSET_FORMAT oform = SUMA_NO_DSET_FORMAT;
13703 
13704    SUMA_ENTRY;
13705 
13706    if (oformp) oform = *oformp;
13707 
13708    /* settle on best oform */
13709    if (oform == SUMA_NO_DSET_FORMAT) {
13710       oform = SUMA_GuessFormatFromExtension(prefix, NULL);
13711       if (oform == SUMA_NO_DSET_FORMAT && inname) {
13712          Test = SUMA_ParseFname(inname, NULL);
13713          oform = SUMA_GuessFormatFromExtension(Test->HeadName, NULL);
13714          Test = SUMA_Free_Parsed_Name(Test);
13715       }
13716    }
13717    if (oform == SUMA_NO_DSET_FORMAT) oform = SUMA_NIML;
13718 
13719    /* remove possible extensions from prefix */
13720    opref = SUMA_RemoveDsetExtension_ns(prefix, oform);
13721 
13722    if (app) {
13723       Test = SUMA_ParseModifyName(opref, "append", app, NULL);
13724       SUMA_free(opref); opref = SUMA_copy_string(Test->HeadName);
13725       Test = SUMA_Free_Parsed_Name(Test);
13726    }
13727    if (pre) {
13728       Test = SUMA_ParseModifyName(opref, "prepend", pre, NULL);
13729       SUMA_free(opref); opref = SUMA_copy_string(Test->HeadName);
13730       Test = SUMA_Free_Parsed_Name(Test);
13731    }
13732    opref = SUMA_append_replace_string(opref,
13733                   (char *)SUMA_ExtensionOfDsetFormat(oform),"",1);
13734    if (exists) {
13735       if (THD_is_file(opref)) *exists = 1;
13736       else *exists = 0;
13737    }
13738 
13739    if (oformp) *oformp = oform;
13740 
13741    SUMA_RETURN(opref);
13742 }
13743 
13744 
13745 /* Note that this function is not getting called anymore.
13746 DBG_sigfunc() in debugtrace.h is being called instead */
SUMA_sigfunc(int sig)13747 void SUMA_sigfunc(int sig)   /** signal handler for fatal errors **/
13748 {
13749    char * sname ;
13750    static volatile int fff=0 ;
13751    if( fff ) _exit(1) ; else fff = 1 ;
13752    switch(sig){
13753       default:      sname = "unknown" ; break ;
13754       case SIGINT:  sname = "SIGINT(ctrl+c)"  ; break ;
13755       case SIGPIPE: sname = "SIGPIPE(broken pipe)" ; break ;
13756       case SIGSEGV: sname = "SIGSEGV(access outside limits)" ; break ;
13757       case SIGBUS:  sname = "SIGBUS(access violation)"  ; break ;
13758       case SIGTERM: sname = "SIGTERM(termination requested)" ; break ;
13759    }
13760    fprintf(stderr,"\nFatal Signal %d (%s) received\n",sig,sname); fflush(stderr);
13761    TRACEBACK ;
13762    fprintf(stderr,"*** SUMA Abort ***\nCompile Date: %s\n",
13763                           __DATE__) ; fflush(stderr) ;
13764    selenium_close(); /* close any selenium opened browser windows if open */
13765 
13766    if( sig != SIGINT && sig != SIGTERM ){  /* add crashlog [14 Apr 2015] */
13767      FILE *dfp ; char *home , fname[1024] ;
13768      home = THD_homedir(0) ;
13769      strcat(fname,"/.afni.crashlog") ;
13770      fprintf(stderr,"** If you report this crash to the AFNI message\n"
13771                     "** board, please copy the error messages EXACTLY.\n"
13772                     "** Crash log recorded in: %s\n",
13773                      fname ) ;
13774 
13775      dfp = fopen( fname , "a" ) ;
13776      if( dfp != NULL ){
13777        fprintf(dfp,
13778          "\n*********-----------------------------------------------*********") ;
13779        fprintf(dfp,"\nFatal Signal %d (%s) received\n",sig,sname);
13780        fflush(stderr);
13781 #ifdef USE_TRACING
13782        DBG_tfp = dfp ; DBG_traceback() ; DBG_tfp = stderr ;
13783 #endif
13784        fprintf(stderr,"*** SUMA Abort ***\nCompile Date: %s\n",
13785                           __DATE__) ; fflush(stderr) ;
13786 #ifdef SHSTRING
13787        fprintf(dfp,"** [[Precompiled binary " SHSTRING ": " __DATE__ "]]\n") ;
13788 #endif
13789        fprintf(dfp,"** SUMA Program Tragically Lost **\n") ;
13790        fclose(dfp) ;
13791      }
13792    }
13793    exit(sig) ;
13794 }
13795 
13796 
13797 
13798 /*!
13799    \brief replace the col th string attribute in a one-string nel
13800 
13801    Warning:
13802    This function gets non-linearly slower for dsets with very large numbers
13803    of columns. This is going to hurt some day.... The problem is that there
13804    are numerous instances of string allocating, copying, appending, freeing,
13805    over and over and over.
13806 
13807 */
SUMA_AddColAtt_CompString(NI_element * nel,int col,char * lbl,char * sep,int insertmode)13808 int SUMA_AddColAtt_CompString(NI_element *nel, int col,
13809                               char *lbl, char *sep, int insertmode)
13810 {
13811    static char FuncName[]={"SUMA_AddColAtt_CompString"};
13812    NI_str_array *nisa = NULL;
13813    char *cs=NULL, *ns=NULL;
13814    int i, num_string_components=0;
13815    SUMA_Boolean LocalHead = NOPE;
13816 
13817    SUMA_ENTRY;
13818 
13819    if (!nel) { SUMA_SL_Err("NULL element"); SUMA_RETURN(NOPE); }
13820    if (col < 0) { SUMA_SL_Err("Negative column index"); SUMA_RETURN(NOPE); }
13821 
13822    SUMA_NEL_GET_STRING(nel, 0, 0, cs); /* composite string */
13823 
13824    if (!cs) { /* first baby, put it in */
13825       if (LocalHead) fprintf(SUMA_STDERR,"%s: 1st string: %s\n", FuncName, lbl);
13826       SUMA_NEL_REPLACE_STRING(nel, 0, 0, lbl);
13827       SUMA_RETURN(YUP);
13828    }
13829 
13830    #if 0
13831    if (!(col % 1000)) {
13832       LocalHead=YUP;
13833       SUMA_LHv("%d\n", col);
13834    }
13835    #endif
13836    num_string_components = SUMA_NI_get_num_strings(cs, sep);
13837    SUMA_LHv("num_string_components=%d in cs=%s (sep=%s), col=%d, lbl=%s,"
13838             "insertmode=%d\n",
13839             num_string_components, cs, sep, col, lbl, insertmode);
13840 
13841    if (num_string_components < 0 || col != num_string_components) {
13842       nisa = SUMA_comp_str_2_NI_str_ar(cs, sep);
13843       if (!nisa) {
13844          SUMA_SL_Err("Failed in SUMA_comp_str_2_NI_str_ar"); SUMA_RETURN(NOPE); }
13845 
13846       if (LocalHead) {
13847          fprintf(SUMA_STDERR,
13848                   "%s: col = %d, num_string_components = %d nisa->num = %d\n",
13849                    FuncName, col, num_string_components, nisa->num);
13850       }
13851       if (col > nisa->num) {
13852          SUMA_SL_Err("col > nisa->num"); SUMA_DUMP_TRACE("nisa nisa");
13853          SUMA_RETURN(NOPE); }
13854       num_string_components = nisa->num;
13855    }
13856 
13857    if (col == num_string_components) { /* add at the end */
13858       if (LocalHead)
13859          fprintf(SUMA_STDERR,"%s: append %s to end of string, memcheck: %s\n",
13860                   FuncName, lbl, NI_malloc_status());
13861       #if 0 /* this gets real slow when adding column after column for
13862                dsets with a very large number of columns */
13863       ns = SUMA_append_replace_string(cs, lbl, sep, 0);
13864       SUMA_NEL_REPLACE_STRING(nel, 0, 0, ns);
13865       #else /* ZSS: Nov 26 08 modify the pointer directly
13866                (still slow, but less so...)*/
13867       {
13868       char **rc;
13869       int n0, n1, n2, nalloc;
13870       if (cs) n0 = strlen(cs); else n0 = 0;
13871       if (sep) n1 = strlen(sep); else n1 = 0;
13872       if (lbl) n2 = strlen(lbl); else n2 = 0;
13873       nalloc = SUMA_NI_get_int(nel,"alloc_max");
13874       SUMA_LHv("nalloc now %d versus %d with cs=%s and lbl=%s\n",
13875                nalloc, n0+n1+n2+1, CHECK_NULL_STR(cs), CHECK_NULL_STR(lbl));
13876       if (nalloc < (n0+n1+n2+1)) { /* and a little faster July 2012
13877                                     still need to go faster, but
13878                                     bottle neck may be elsewhere
13879                                     Note that if you add then readjust
13880                                     by editing the mid section, all this
13881                                     speed up effort becomes a real bad idea
13882                                     See what I do with alloc_max in the
13883                                     next blocs below.
13884                                     Need to get away from single composite
13885                                     strings, but that wouldstop being compatible
13886                                     with AFNI. Perhaps make the change at read,
13887                                     and undo it just before write.
13888                                     */
13889          nalloc += (n0+n1+n2+1)+8192;
13890          cs = (char *)NI_realloc(cs, char,
13891                   nalloc*sizeof(char));
13892          SUMA_NI_set_int(nel,"alloc_max", nalloc);
13893       }
13894 
13895       if (!SUMA_isExtension(cs, sep)) {
13896          i = 0; while(sep[i]) { cs[n0++] = sep[i]; ++i; }
13897       }
13898       if (n2) {
13899          i = 0; while(lbl[i]) { cs[n0++] = lbl[i]; ++i; }
13900       }
13901       cs[n0] = '\0';
13902       if (!(rc = (char **)(nel->vec[0]))) {
13903          SUMA_S_Err("Unexpected null nel->vec[0]");
13904          SUMA_RETURN(NOPE);
13905       }
13906       rc[0] = cs;
13907 
13908       if (0) {
13909          SUMA_LHv("cs (%d strings) now: %s\n",
13910                      SUMA_NI_get_num_strings(cs, sep), cs);
13911       } else {
13912          SUMA_LHv("cs (%d strings), memcheck:%s\n",
13913                      SUMA_NI_get_num_strings(cs, sep), NI_malloc_status());
13914       }
13915       }
13916       #endif
13917    } else if (!insertmode) { /* REPLACE! in middle */
13918       if (nisa->str[col]) NI_free(nisa->str[col]); nisa->str[col] = NULL;
13919       if (lbl) {
13920          nisa->str[col] = (char*)NI_malloc(char, (strlen(lbl)+1)*sizeof(char));
13921          strcpy( nisa->str[col],  lbl );
13922          if (LocalHead)
13923             fprintf( SUMA_STDERR,
13924                      "%s: replaced %s at location %d (%d)\n",
13925                      FuncName, lbl, col, nisa->num);
13926          ns = SUMA_NI_str_ar_2_comp_str(nisa, sep);
13927          if (LocalHead)
13928             fprintf(SUMA_STDERR,"%s: final string is %s\n", FuncName, ns);
13929          SUMA_NEL_REPLACE_STRING(nel, 0, 0, ns);
13930          /* Make sure alloc_max is reset, this is a new pointer and the
13931          pre-allocation done above is of no further use */
13932          SUMA_NI_set_int(nel,"alloc_max", strlen(ns));
13933          /* SUMA_DUMP_TRACE(NI_malloc_status()); */
13934       }
13935    } else { /* insert in middle */
13936       int n2;
13937       if (lbl) n2 = strlen(lbl); else n2 = 0;
13938       nisa->str = NI_realloc( nisa->str, char*, sizeof(char *)*(nisa->num+1) ) ;
13939       /* now move all above col to end */
13940       for (i=nisa->num-1; i >= col; --i) nisa->str[i+1] = nisa->str[i];
13941       nisa->str[col] = (char*)NI_malloc(char, (n2+1)*sizeof(char));
13942       if (lbl) strcpy( nisa->str[col],  lbl );
13943       else nisa->str[col][0] = '\0';
13944       ++nisa->num;
13945       if (LocalHead)
13946          fprintf( SUMA_STDERR,
13947                   "%s: inserted %s at location %d\n", FuncName, lbl, col);
13948       ns = SUMA_NI_str_ar_2_comp_str(nisa, sep);
13949       if (LocalHead)
13950          fprintf(SUMA_STDERR,"%s: final string is %s\n", FuncName, ns);
13951       SUMA_NEL_REPLACE_STRING(nel, 0, 0, ns);
13952       SUMA_NI_set_int(nel,"alloc_max", strlen(ns));
13953    }
13954    if (ns) SUMA_free(ns); ns = NULL;
13955    if (nisa) SUMA_free_NI_str_array(nisa); nisa = NULL;
13956 
13957    SUMA_RETURN(YUP);
13958 }
13959 
13960 
13961 /*! Swap the 4 bytes pointed to by ppp: abcd -> dcba. */
13962 
SUMA_swap_4(void * ppp)13963 void SUMA_swap_4(void *ppp)
13964 {
13965    unsigned char *pntr = (unsigned char *) ppp ;
13966    unsigned char b0, b1, b2, b3;
13967 
13968    b0 = *pntr; b1 = *(pntr+1); b2 = *(pntr+2); b3 = *(pntr+3);
13969    *pntr = b3; *(pntr+1) = b2; *(pntr+2) = b1; *(pntr+3) = b0;
13970 }
13971 
13972 /*---------------------------------------------------------------*/
13973 
13974 /*! Swap the 8 bytes pointed to by ppp: abcdefgh -> hgfedcba. */
13975 
SUMA_swap_8(void * ppp)13976 void SUMA_swap_8(void *ppp)
13977 {
13978    unsigned char *pntr = (unsigned char *) ppp ;
13979    unsigned char b0, b1, b2, b3;
13980    unsigned char b4, b5, b6, b7;
13981 
13982    b0 = *pntr    ; b1 = *(pntr+1); b2 = *(pntr+2); b3 = *(pntr+3);
13983    b4 = *(pntr+4); b5 = *(pntr+5); b6 = *(pntr+6); b7 = *(pntr+7);
13984 
13985    *pntr     = b7; *(pntr+1) = b6; *(pntr+2) = b5; *(pntr+3) = b4;
13986    *(pntr+4) = b3; *(pntr+5) = b2; *(pntr+6) = b1; *(pntr+7) = b0;
13987 }
13988 
13989 /*---------------------------------------------------------------*/
13990 
13991 /*! Swap the 2 bytes pointed to by ppp: ab -> ba. */
13992 
SUMA_swap_2(void * ppp)13993 void SUMA_swap_2(void *ppp)
13994 {
13995    unsigned char *pntr = (unsigned char *) ppp ;
13996    unsigned char b0, b1;
13997 
13998    b0 = *pntr; b1 = *(pntr+1);
13999    *pntr = b1; *(pntr+1) = b0;
14000 }
14001 
14002 /*!
14003    \brief
14004    \param endian (int)  0 : Don't know, do nothing
14005                         MSB_FIRST
14006                         LSB_FIRST
14007 */
SUMA_BinarySuck(char * fname,SUMA_VARTYPE data_type,int endian,int start,int end,int * nvals_read)14008 void *SUMA_BinarySuck(char *fname, SUMA_VARTYPE data_type, int endian,
14009                       int start, int end, int *nvals_read)
14010 {
14011    static char FuncName[]={"SUMA_BinarySuck"};
14012    int bs, End, chnk, read_n, N_alloc, ex;
14013    FILE *fp=NULL;
14014    void *ans = NULL;
14015    SUMA_Boolean LocalHead = NOPE;
14016 
14017    SUMA_ENTRY;
14018 
14019    *nvals_read = 0;
14020    ans = NULL;
14021 
14022    if (!SUMA_filexists(fname)) {
14023       SUMA_SL_Err("File not found or could not be read"); goto CLEAN_EXIT;
14024    }
14025    if (start < 0) { SUMA_SL_Err("Neg start val!"); goto CLEAN_EXIT; }
14026 
14027    /* byte swapping? */
14028    bs = 0;
14029    SUMA_WHAT_ENDIAN(End);
14030    if (endian && endian != End) bs = 1;
14031 
14032    /* open file */
14033    fp = fopen(fname,"r");
14034    if (!fp) { SUMA_SL_Err("Failed to open file for read op."); goto CLEAN_EXIT; }
14035 
14036    /* skip top, if need be */
14037    if (start) fseek(fp, start, SEEK_SET);
14038 
14039    /* size of each value */
14040    chnk = SUMA_SizeOf(data_type);
14041    if (chnk <= 0) {  SUMA_SL_Err("Bad data type"); goto CLEAN_EXIT; }
14042 
14043    /* how many values to read ? */
14044    read_n = -1;
14045    if (end > 0) {
14046       read_n = (end-start)/chnk;
14047       if (read_n < 0) { SUMA_SL_Err("Bad end, start values"); goto CLEAN_EXIT;  }
14048    }
14049 
14050    /* now start reading until you reach eof or end byte */
14051    if (read_n >= 0)  N_alloc = read_n;
14052    else N_alloc = ( THD_filesize( fname ) - start) / (unsigned long)chnk;
14053    if (LocalHead)
14054       fprintf(SUMA_STDERR,"%s: Expecting to read %d values\n",
14055                            FuncName, N_alloc);
14056 
14057    ex = 0;
14058    switch (data_type) {
14059       case SUMA_float:
14060          {
14061             float *vec = (float *)SUMA_malloc(N_alloc * sizeof(float));
14062             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
14063             SUMA_LH("Reading floats");
14064             ex = fread((void*)vec, chnk, N_alloc, fp);
14065             if (ex != N_alloc) {
14066                SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec);
14067                goto CLEAN_EXIT;
14068             }
14069             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
14070             ans = (void*)vec;
14071          }
14072          break;
14073       case SUMA_int:
14074          {
14075             int *vec = (int *)SUMA_malloc(N_alloc * sizeof(int));
14076             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
14077             SUMA_LH("Reading ints");
14078             ex = fread((void*)vec, chnk, N_alloc, fp);
14079             if (ex != N_alloc) {
14080                SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec);
14081                goto CLEAN_EXIT;
14082             }
14083             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
14084             ans = (void*)vec;
14085          }
14086          break;
14087       case SUMA_byte:
14088          {
14089             byte *vec = (byte *)SUMA_malloc(N_alloc * sizeof(byte));
14090             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
14091             SUMA_LH("Reading bytes");
14092             ex = fread((void*)vec, chnk, N_alloc, fp);
14093             if (ex != N_alloc) {
14094                SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec);
14095                goto CLEAN_EXIT;
14096             }
14097             if (bs) { SUMA_LH("swapping 1 byte numbers!?");  }
14098             ans = (void*)vec;
14099          }
14100          break;
14101       case SUMA_short:
14102          {
14103             short *vec = (short *)SUMA_malloc(N_alloc * sizeof(short));
14104             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
14105             SUMA_LH("Reading shorts");
14106             ex = fread((void*)vec, chnk, N_alloc, fp);
14107             if (ex != N_alloc) {
14108                SUMA_SL_Err("Failed to read all data!");
14109                SUMA_free(vec); goto CLEAN_EXIT;
14110             }
14111             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
14112             ans = (void*)vec;
14113          }
14114          break;
14115       case SUMA_complex:
14116          SUMA_SL_Err("Complex data type not supported");
14117          break;
14118       default:
14119          SUMA_SL_Err("data type not supported");
14120          break;
14121    }
14122 
14123    *nvals_read = ex;
14124 
14125    CLEAN_EXIT:
14126    if (fp) fclose(fp);
14127 
14128    SUMA_RETURN(ans);
14129 }
14130 
14131 /*!
14132    \brief A function to suck in an ascii file
14133    Shamelessly stolen from Bob's suck_file
14134    \sa SUMA_file_suck
14135 */
SUMA_suck_file(char * fname,char ** fbuf)14136 int SUMA_suck_file( char *fname , char **fbuf )
14137 {
14138    static char FuncName[]={"SUMA_suck_file"};
14139    int  fd , ii ;
14140    unsigned long len;
14141    char * buf ;
14142 
14143    SUMA_ENTRY;
14144 
14145    if( fname == NULL || fname[0] == '\0' || fbuf == NULL ) SUMA_RETURN(0) ;
14146 
14147    len = THD_filesize( fname ) ;
14148    if( len <= 0 ) SUMA_RETURN(0) ;
14149 
14150    buf = (char *) SUMA_malloc( sizeof(char) * (len+4) ) ;
14151    if( buf == NULL ) SUMA_RETURN(0) ;
14152 
14153    fd = open( fname , O_RDONLY ) ;
14154    if( fd < 0 ) SUMA_RETURN(0) ;
14155 
14156    ii = read( fd , buf , len ) ;
14157    close( fd ) ;
14158    if( ii <= 0 ){ SUMA_free(buf) ; SUMA_RETURN(0); }
14159    *fbuf = buf ;
14160    buf[ii] = '\0';
14161    SUMA_RETURN(ii) ;
14162 }
14163 
14164 /*!
14165    \brief Another version of SUMA_suck_file that hopes to
14166    avoid the silly error on OSX
14167    \sa SUMA_suck_file
14168 */
SUMA_file_suck(char * fname,int * nread)14169 char * SUMA_file_suck( char *fname , int *nread )
14170 {
14171    static char FuncName[]={"SUMA_file_suck"};
14172    int  fd , ii = 0;
14173    unsigned long len;
14174    char * buf = NULL;
14175 
14176    SUMA_ENTRY;
14177 
14178    *nread = 0;
14179    if( fname == NULL || fname[0] == '\0') SUMA_RETURN(NULL) ;
14180 
14181    len = THD_filesize( fname ) ;
14182    if( len <= 0 ) SUMA_RETURN(buf) ;
14183 
14184    buf = (char *) SUMA_malloc( sizeof(char) * (len+4) ) ;
14185    if( buf == NULL ) SUMA_RETURN(buf) ;
14186 
14187    fd = open( fname , O_RDONLY ) ;
14188    if( fd < 0 ) SUMA_RETURN(buf) ;
14189 
14190    ii = read( fd , buf , len ) ;
14191    close( fd ) ;
14192    if( ii <= 0 ){ SUMA_free(buf) ; buf = NULL; SUMA_RETURN(buf); }
14193    *nread = ii ; buf[ii]='\0'; SUMA_RETURN(buf) ;
14194 }
14195 
14196 
14197 /************** END Miscellaneous support function    ************** */
14198 
14199 /******** BEGIN functions for surface structure  ******************** */
SUMA_giiStringToNumSide(char * cc)14200 SUMA_SO_SIDE SUMA_giiStringToNumSide(char *cc)
14201 {
14202    static char FuncName[]={"SUMA_giiStringToNumSide"};
14203    char *hasright=NULL, *hasleft=NULL;
14204    SUMA_ENTRY;
14205 
14206    if (!cc) SUMA_RETURN(SUMA_NO_SIDE);
14207 
14208    deblank_name(cc);
14209    hasleft = AFNI_strcasestr(cc,"Left");
14210    hasright = AFNI_strcasestr(cc,"Right");
14211    if ( hasleft  && !hasright ) {
14212       SUMA_RETURN(SUMA_LEFT);
14213    } else if ( hasright && !hasleft ) {
14214       SUMA_RETURN(SUMA_RIGHT);
14215    } else if (    hasleft && hasright ) {
14216       SUMA_RETURN(SUMA_LR);
14217    }
14218 
14219    SUMA_RETURN(SUMA_NO_SIDE);
14220 }
14221 
14222       /* see some basic functions in suma_afni_surface.c */
SUMA_ShowAfniSurfaceObject(NI_group * aSO,FILE * out,int detail,char * title)14223 void SUMA_ShowAfniSurfaceObject( NI_group *aSO, FILE *out,
14224                                  int detail, char *title)
14225 {
14226    static char FuncName[]={"SUMA_ShowAfniSurfaceObject"};
14227    char *s=NULL;
14228    SUMA_ENTRY;
14229 
14230    if (!out) out = stdout;
14231 
14232    s = SUMA_AfniSurfaceObject_Info(aSO, detail, title);
14233    fprintf(out,"%s",s);
14234    SUMA_free(s); s = NULL;
14235    SUMA_RETURNe;
14236 }
14237 
SUMA_AfniSurfaceObject_Info(NI_group * aSO,int detail,char * title)14238 char *SUMA_AfniSurfaceObject_Info(NI_group *aSO,
14239                                   int detail, char *title)
14240 {
14241    static char FuncName[]={"SUMA_AfniSurfaceObject_Info"};
14242    int i=0, j=0, n=0;
14243    char *s=NULL, stmp[200];
14244    float *fv=NULL;
14245    int *iv=NULL;
14246    double xform[4][4];
14247    NI_element *nelxyz=NULL;
14248    NI_element *nelijk=NULL;
14249    NI_element *nelxform=NULL;
14250    NI_element *nelnormals=NULL;
14251    NI_element *nel=NULL;
14252    SUMA_STRING *SS=NULL;
14253    SUMA_Boolean LocalHead = NOPE;
14254 
14255    SUMA_ENTRY;
14256 
14257    SS = SUMA_StringAppend(NULL, NULL);
14258 
14259    if (title) SS = SUMA_StringAppend(SS, title);
14260    if (!aSO) {
14261       SS = SUMA_StringAppend(SS, "NULL Afni Surface Object\n");
14262    } else {
14263       nelxyz = SUMA_FindNgrNamedElement(aSO, "Node_XYZ");
14264       nelijk = SUMA_FindNgrNamedElement(aSO, "Mesh_IJK");
14265       nelnormals = SUMA_FindNgrNamedElement(aSO, "Node_Normals");
14266       nelxform = SUMA_FindNgrNamedElement(aSO, "Coord_System");
14267 
14268       if (!nelxyz) {
14269          SS = SUMA_StringAppend(SS, "NULL ps\n");
14270       } else {
14271          NI_GET_INT(nelxyz,"NodeDim",n);
14272          SS = SUMA_StringAppend_va(SS,   "Have %d (%dD) nodes:\n",
14273                            n > 0 ? nelxyz->vec_len/n:-1, n);
14274          if (!nelxyz->vec_num) {
14275             SS = SUMA_StringAppend(SS, "   NULL NodeList\n");
14276          } else {
14277             fv = (float *)nelxyz->vec[0];
14278             for (i=0; i<SUMA_MIN_PAIR(5,nelxyz->vec_len/n); ++i) {
14279                SS = SUMA_StringAppend_va(SS, "   %6d: ", i);
14280                for (j=0; j<n; ++j)
14281                   SS = SUMA_StringAppend_va(SS,
14282                            "%4.3f\t",
14283                            fv[n*i+j]);
14284                SS = SUMA_StringAppend(SS, "\n");
14285             }
14286          }
14287       }
14288       if (!nelijk) {
14289          SS = SUMA_StringAppend(SS, "NULL tr\n");
14290       } else {
14291          NI_GET_INT(nelijk,"FaceSetDim",n);
14292          SS = SUMA_StringAppend_va(SS,   "Have %d (%dD) polygons:\n",
14293                            n > 0 ? nelxyz->vec_len/n:-1, n);
14294          if (!nelijk->vec_num) {
14295             SS = SUMA_StringAppend(SS, "   NULL FaceSetList\n");
14296          } else {
14297             iv = (int *)nelijk->vec[0];
14298             for (i=0; i<SUMA_MIN_PAIR(5,nelxyz->vec_len/n); ++i) {
14299                SS = SUMA_StringAppend_va(SS, "   %6d: ", i);
14300                for (j=0; j<n; ++j)
14301                   SS = SUMA_StringAppend_va(SS,
14302                            "%6d\t",
14303                            iv[n*i+j]);
14304                SS = SUMA_StringAppend(SS, "\n");
14305             }
14306          }
14307       }
14308 
14309       if (!nelnormals) {
14310          SS = SUMA_StringAppend(SS, "No Node Normals\n");
14311       } else {
14312          if (nelxyz) {
14313             NI_GET_INT(nelxyz,"NodeDim",n);
14314             SS = SUMA_StringAppend_va(SS,   "Have %d (%dD) node normals:\n",
14315                                              n > 0 ? nelnormals->vec_len/n:-1,
14316                                              n);
14317          if (!nelnormals->vec_num) {
14318                SS = SUMA_StringAppend(SS, "NULL Node Normals Vector\n");
14319             } else {
14320                fv = (float *)nelnormals->vec[0];
14321                for (i=0; i<SUMA_MIN_PAIR(5,nelxyz->vec_len/n); ++i) {
14322                   SS = SUMA_StringAppend_va(SS, "   %6d: ", i);
14323                   for (j=0; j<n; ++j)
14324                      SS = SUMA_StringAppend_va(SS,
14325                               "%4.3f\t",
14326                               fv[n*i+j]);
14327                      SS = SUMA_StringAppend(SS, "\n");
14328                }
14329             }
14330          } else {
14331             SS = SUMA_StringAppend(SS,
14332                      "Freakish structure, no pointset to go with nornals\n");
14333          }
14334       }
14335 
14336       if (!nelxform) {
14337          SS = SUMA_StringAppend(SS, "No xform\n");
14338       } else {
14339          double *dv=NULL;
14340          int k;
14341          SS = SUMA_StringAppend_va(SS, "dataspace: %s\n"
14342                                        "xformspace: %s\n",
14343                   SUMA_CHECK_NULL_STR(NI_get_attribute(nelxform, "dataspace")),
14344                   SUMA_CHECK_NULL_STR(NI_get_attribute(nelxform, "xformspace")));
14345          dv = (double *)nelxform->vec[0];
14346          for (i=0; i<4;++i) {
14347             k = 4*i;
14348             SS = SUMA_StringAppend_va(SS, "  %.4f   %.4f   %.4f   %.4f\n",
14349                                      dv[k], dv[k+1], dv[k+2], dv[k+3]);
14350          }
14351       }
14352    }
14353 
14354    SUMA_SS2S(SS, s);
14355 
14356    SUMA_RETURN(s);
14357 }
14358 
14359 
14360 /******** END functions for surface structure  ******************** */
14361 
14362 /************************ BEGIN GICOR functions  ******************** */
14363 
14364 /* A function to initialize the setup structure for GroupInCorr     */
14365 /* bmode: a flag for batch mode to save dset    17 Aug 2012 [rickr] */
SUMA_init_GISET_setup(NI_stream nsg,NI_element * nel,GICOR_setup * giset,int bmode)14366 int SUMA_init_GISET_setup(NI_stream nsg , NI_element *nel, GICOR_setup *giset,
14367                           int bmode)
14368 {
14369    static char FuncName[]={"SUMA_init_GISET_setup"};
14370    char *atr=NULL , *pre=NULL, *s=NULL, sbuf[256];
14371    THD_3dim_dataset *tdset=NULL;
14372    SUMA_Boolean LocalHead = NOPE;
14373 
14374    SUMA_ENTRY;
14375 
14376    giset->ns    = nsg ;  /* save socket for I/O back to 3dGroupInCorr */
14377    giset->ready = 0 ;    /* not ready yet */
14378 
14379    /* set various parameters from the NIML header */
14380 
14381    atr = NI_get_attribute( nel , "ndset_A" ) ;
14382       if( atr == NULL )        SUMA_RETURN(NOPE);
14383    giset->ndset_A = (int)strtod(atr,NULL) ;
14384       if( giset->ndset_A < 2 ) SUMA_RETURN(NOPE);
14385 
14386    atr = NI_get_attribute( nel , "ndset_B" ) ;
14387       if( atr == NULL )        SUMA_RETURN(NOPE);
14388    giset->ndset_B = (int)strtod(atr,NULL) ;
14389 
14390    atr = NI_get_attribute( nel , "nvec" ) ;
14391       if( atr == NULL )        SUMA_RETURN(NOPE);
14392    giset->nvec = (int)strtod(atr,NULL) ;
14393       if( giset->nvec < 2 )    SUMA_RETURN(NOPE);
14394 
14395    atr = NI_get_attribute( nel , "geometry_string" );
14396       if( atr == NULL ) {
14397          SUMA_S_Err("No geometry string");
14398          SUMA_RETURN(NOPE);
14399       }
14400       pre = SUMA_copy_string(atr) ;
14401       tdset = EDIT_geometry_constructor( pre , "GrpInCorr" ) ;
14402       if( tdset == NULL ) {
14403          snprintf(sbuf, 256,
14404             "ERROR %s: Could not construct dset from %s\n",FuncName, pre);
14405          SUMA_S_Err("%s", sbuf);
14406          SUMA_RETURN(NOPE) ;
14407       }
14408       giset->nvox = DSET_NVOX(tdset) ;
14409       /* if batch mode, store dataset           17 Aug 2012 [rickr] */
14410       if( bmode ) giset->dset = tdset;
14411       else { DSET_delete(tdset); tdset=NULL; }
14412       SUMA_free(pre); pre=NULL;
14413 
14414    if( giset->nvox < 2 )    SUMA_RETURN(NOPE);
14415 
14416    atr = NI_get_attribute( nel , "seedrad" ) ;
14417    if( atr != NULL ) giset->seedrad = (float)strtod(atr,NULL) ;
14418 
14419    atr = NI_get_attribute( nel , "ttest_opcode" ) ;
14420    if( atr != NULL ) giset->ttest_opcode = (int)strtod(atr,NULL) ;
14421 
14422    /* How many dsets? */
14423    if (LocalHead) {
14424       snprintf(sbuf, 256,
14425             "LH %s: attr=%s\nval0=%s,val1=%s\n",
14426             FuncName, NI_get_attribute(nel,"LRpair_nnode"),
14427             SUMA_NI_get_ith_string(NI_get_attribute(nel,"LRpair_nnode"),",",0),
14428             SUMA_NI_get_ith_string(NI_get_attribute(nel,"LRpair_nnode"),",",1));
14429       SUMA_LH("%s",sbuf);
14430    }
14431    if ((s=SUMA_NI_get_ith_string(
14432                NI_get_attribute(nel,"LRpair_nnode"),",",0))) {
14433       giset->nnode_domain[0] = (int)strtol(s, NULL, 10);
14434       SUMA_free(s); s = NULL;
14435       if ((s=SUMA_NI_get_ith_string(
14436                NI_get_attribute(nel,"LRpair_nnode"),",",1))) {
14437          giset->nnode_domain[1] = (int)strtol(s, NULL, 10);
14438          SUMA_free(s); s = NULL;
14439       }
14440    } else {
14441       giset->nnode_domain[0] = giset->nvox;
14442       giset->nnode_domain[1] = 0;
14443    }
14444 
14445    if ((s=SUMA_NI_get_ith_string(
14446                NI_get_attribute(nel,"LRpair_ninmask"),",",0))) {
14447       giset->nnode_mask[0] = (int)strtol(s, NULL, 10);
14448       SUMA_free(s); s = NULL;
14449       if ((s=SUMA_NI_get_ith_string(
14450                NI_get_attribute(nel,"LRpair_ninmask"),",",1))) {
14451          giset->nnode_mask[1] = (int)strtol(s, NULL, 10);
14452          SUMA_free(s); s = NULL;
14453       }
14454    } else {
14455       giset->nnode_mask[0] = giset->nnode_domain[0];
14456       giset->nnode_mask[1] = giset->nnode_domain[1];
14457    }
14458 
14459    /* list of voxels to expect from each 3dGroupInCorr data */
14460    if( nel->vec_len == 0 || nel->vec_num == 0 || nel->vec == NULL ){  /* all */
14461      giset->ivec = NULL ; giset->nivec = 0 ;
14462       INFO_message("DEBUG: GICOR_setup_func has ivec=NULL") ;
14463    } else {                                     /* make index list of voxels */
14464      int ii , nn , *iv=(int *)nel->vec[0] ;
14465      giset->ivec = (int *)calloc(sizeof(int),giset->nvec) ;
14466      nn = MIN(giset->nvec,nel->vec_len) ; giset->nivec = nn ;
14467      for( ii=0 ; ii < nn ; ii++ ) giset->ivec[ii] = iv[ii] ;
14468      INFO_message("DEBUG: GICOR_setup_func has ivec=int[%d]",nn) ;
14469    }
14470 
14471    if (NI_get_attribute(nel, "target_labels")) {
14472       giset->brick_labels = strdup(NI_get_attribute(nel, "target_labels"));
14473    }
14474 
14475    atr = NI_get_attribute( nel , "target_nvals" ) ;
14476    if( atr != NULL ){
14477       giset->nvals = (int)strtod(atr,NULL);
14478       giset->nvals = SUMA_MAX_PAIR(1,giset->nvals);
14479    }
14480 
14481    SUMA_RETURN(YUP);
14482 }
14483 
SUMA_PopulateDsetsFromGICORnel(NI_element * nel,GICOR_setup * giset,SUMA_DSET ** sdsetv)14484 int SUMA_PopulateDsetsFromGICORnel(NI_element *nel, GICOR_setup *giset,
14485                                    SUMA_DSET **sdsetv)
14486 {
14487    static char FuncName[]={"SUMA_PopulateDsetsFromGICORnel"};
14488    char *sbuf=NULL;
14489    float *neldar , *nelzar , *dsdar , *dszar ;
14490    int nn , id=0, ipair=0, nvec=0;
14491    SUMA_Boolean LocalHead = NOPE;
14492 
14493    SUMA_ENTRY;
14494 
14495    if (!nel || !giset || !sdsetv) {
14496       SUMA_S_Err("NULL input");
14497       SUMA_RETURN(NOPE);
14498    }
14499 
14500    for (id=0; id < 2; ++id) {
14501       for (ipair=0; ipair < nel->vec_num/2; ++ipair) {
14502          neldar = (float *)nel->vec[2*ipair+0] ;  /* delta array */
14503          nelzar = (float *)nel->vec[2*ipair+1] ;  /* zscore array */
14504          nvec   = nel->vec_len ;
14505 
14506          if (giset->nnode_domain[id]) {
14507             dsdar = (float *)SDSET_VEC(sdsetv[id],(2*ipair+0)) ;
14508             dszar = (float *)SDSET_VEC(sdsetv[id],(2*ipair+1)) ;
14509             if (LocalHead) {
14510                sbuf=SUMA_ShowMeSome(dsdar,
14511                            SUMA_float, SDSET_VECLEN(sdsetv[id]),10,"dsdar:\n");
14512                SUMA_LHv("pre copy surf%d %s\n",id, sbuf);
14513                SUMA_free(sbuf); sbuf=NULL;
14514             }
14515 
14516             if( giset->ivec == NULL ){  /* all nodes */
14517                if (giset->nvox != nvec) {
14518                   SUMA_S_Errv( "nvox=%d, nvec=%d, ivec=NULL\n"
14519                               "Did not expect that.\n",
14520                               giset->nvox, nvec);
14521                   SUMA_RETURN(NOPE) ;
14522                }
14523                if (id == 0) {
14524                   nn = MAX(0, nvec-giset->nnode_domain[1]);
14525                   SUMA_LHv("Copying %d values from neldar, surf%d\n",
14526                            nn, id);
14527                   if (LocalHead) {
14528                      sbuf=SUMA_ShowMeSome(neldar,SUMA_float, nn,10,"neldar:\n");
14529                      SUMA_LHv("from the tube surf%d: %s\n", id, sbuf);
14530                      SUMA_free(sbuf); sbuf=NULL;
14531                   }
14532                   memcpy(dsdar,neldar,sizeof(float)*nn) ;
14533                   memcpy(dszar,nelzar,sizeof(float)*nn) ;
14534                } else {
14535                   nn = MAX(0, nvec-giset->nnode_domain[0]);
14536                   SUMA_LHv("Copying %d values from neldar+%d, surf%d\n",
14537                            nn, giset->nnode_domain[0], id);
14538                   if (LocalHead) {
14539                      sbuf=SUMA_ShowMeSome((neldar+giset->nnode_domain[0]),
14540                                           SUMA_float, nn, 10,"neldar:\n");
14541                      SUMA_LHv("from the tube surf%d: %s\n", id, sbuf);
14542                      SUMA_free(sbuf); sbuf=NULL;
14543                   }
14544                   memcpy(dsdar,(neldar+giset->nnode_domain[0]),
14545                            sizeof(float)*nn) ;
14546                   memcpy(dszar,(nelzar+giset->nnode_domain[0]),
14547                            sizeof(float)*nn) ;
14548                }
14549                if (LocalHead) {
14550                   sbuf=SUMA_ShowMeSome(dsdar,SUMA_float, nn, 10,"dsdar:\n");
14551                   SUMA_LHv("post copy surf%d %s\n", id, sbuf);
14552                   SUMA_free(sbuf); sbuf=NULL;
14553                }
14554             } else { /* Have index vector */
14555                int *ivec=giset->ivec , kk ;
14556                nn = MIN( giset->nnode_mask[id] , nvec ) ;
14557                if (id == 0) {
14558                   for( kk=0 ; kk < nn ; kk++ ){
14559                      dsdar[ivec[kk]] = neldar[kk] ;
14560                      dszar[ivec[kk]] = nelzar[kk] ;
14561                   }
14562                } else {
14563                   for( kk=0 ; kk < nn ; kk++ ){
14564                      dsdar[ivec[kk]-giset->nnode_domain[0]] = neldar[kk] ;
14565                      dszar[ivec[kk]-giset->nnode_domain[0]] = nelzar[kk] ;
14566                   }
14567                }
14568             }
14569             SUMA_LH("Updating range\n");
14570             if (!SUMA_UpdateDsetColRange(sdsetv[id],-1)) {
14571                SUMA_S_Err("Failed to update range");
14572                SUMA_RETURN(NOPE);
14573             }
14574             /* Put a flag up to state that all overlays of this dataset need
14575             to have column copied refreshed */
14576             if (sdsetv[id]->dnel) {
14577                NI_set_attribute(sdsetv[id]->dnel,"ResetOverlay_Vecs", "yes");
14578             }
14579          } /* if (giset->nnode_domain[id]) */
14580       } /* for (ipair ...) */
14581    }
14582 
14583    SUMA_RETURN(YUP);
14584 }
14585 
14586 /************************ END GICOR functions  ********************* */
14587 
14588 /************************ GRAPH Dset functions  ******************** */
14589 /* use macro: SUMA_isGraphDset_fast() for speed
14590    This one always goes back to the source */
SUMA_isGraphDset(SUMA_DSET * dset)14591 byte SUMA_isGraphDset(SUMA_DSET *dset)
14592 {
14593    static char FuncName[]={"SUMA_isGraphDset"};
14594 
14595    SUMA_ENTRY;
14596 
14597    if (!dset || !dset->ngr) SUMA_RETURN(NOPE);
14598 
14599    if (!dset->Aux) { /* create one, always good */
14600       if (!SUMA_Add_Dset_Aux(dset)) {
14601          SUMA_S_Err("Bad news, this should not fail");
14602          SUMA_RETURN(NOPE);
14603       }
14604    }
14605    if (SUMA_isGraphDsetNgr(dset->ngr)) {
14606       dset->Aux->isGraph = GRAPH_DSET;
14607    }
14608 
14609    SUMA_RETURN(dset->Aux->isGraph == GRAPH_DSET);
14610 }
14611 
SUMA_isGraphDsetNgr(NI_group * ngr)14612 byte SUMA_isGraphDsetNgr(NI_group *ngr)
14613 {
14614    if (!ngr) return(0);
14615    switch (SUMA_Dset_Type(NEL_DSET_TYPE(ngr))) {
14616       case SUMA_GRAPH_BUCKET:
14617          return(1);
14618       default:
14619          return(0);
14620    }
14621    return(0);
14622 }
14623 
14624 /*!
14625    Turn a bunch of matrices into a graph dataset.
14626    vec (float **) A collection of vec_num arrays with each array representing
14627                   a matrix of length vec_len.
14628                   Matrix k is stored in vec[k] and has a total of vec_len
14629                   elements. 4 types of matrices can be stored.
14630                   1- An MxM square matrix is stored in column major order
14631                      vec_len = M*M
14632                   2- A lower triangular matrix with diagonal is stored in
14633                      column major order, vec_len = M*(M+1)/2
14634                   3- A lower triangular matrix  is stored in column major
14635                      order with vec_len = M*(M-1)/2
14636                   4- A sparse M*M matrix of vec_len elements. For this you
14637                      will need to specify ie, i0, and i1 (see below)
14638    vec_num (int) : number of matrices
14639    vec_len (int) : number of elements in vec[k]
14640    mtype   (char *) : Choose from NULL (let function guess) or "full",
14641                       "lower_diag", "lower", or "sparse"
14642    vec_labs(char **) : labels of each matrix, vec_num of them. Send NULL for
14643                        default labeling
14644    The next three parameters are used when the matrices are sparse
14645    ie (int *): If not NULL, ie contains the 'edge/cell' index of the matrix
14646                where entries exist. If null, the edges are numbered from 0
14647                to vec_len-1
14648    i0 (int *): row indices
14649    i1 (int *): column indices
14650 */
14651 
SUMA_FloatVec_to_GDSET(float ** vec,int vec_num,int vec_len,char * mtype,char ** vec_labs,int * ie,int * i0,int * i1)14652 SUMA_DSET *SUMA_FloatVec_to_GDSET(float **vec, int vec_num, int vec_len,
14653                                   char *mtype,
14654                                   char **vec_labs, int *ie, int *i0, int *i1)
14655 {
14656    static char FuncName[]={"SUMA_FloatVec_to_GDSET"};
14657    SUMA_DSET *dset=NULL;
14658    char *lab=NULL, sbuf[32];
14659    int i;
14660 
14661    SUMA_ENTRY;
14662 
14663    if (!(dset =  SUMA_CreateDsetPointer( FuncName, SUMA_NODE_BUCKET,
14664                                          NULL, NULL, vec_len ))) {
14665       SUMA_S_Err("Failed to create dset");
14666       SUMA_RETURN(dset);
14667    }
14668 
14669    for (i=0; i<vec_num; ++i) {
14670       if (vec_labs) lab = vec_labs[i];
14671       else {
14672          sprintf(sbuf,"Mat%3d",i);
14673          lab = sbuf;
14674       }
14675       if (!SUMA_AddDsetNelCol(dset, lab,
14676                               SUMA_NODE_FLOAT, (void *)vec[i], NULL, 1)) {
14677          SUMA_S_Errv("Failed to add column %d %s\n", i, lab);
14678          SUMA_FreeDset(dset); dset=NULL;
14679          SUMA_RETURN(dset);
14680       }
14681    }
14682 
14683    /* Now turn dset to graph */
14684    if (!SUMA_Dset_to_GDSET(&dset, mtype, 0, ie, i0, i1)) {
14685       SUMA_S_Err("Failed to graphize");
14686       SUMA_FreeDset(dset); dset = NULL;
14687       SUMA_RETURN(dset);
14688    }
14689 
14690    SUMA_RETURN(dset);
14691 }
14692 
14693 /* Turn a node-based dset structure into a graph structure,
14694    cunningly still called SUMA_DSET                         */
SUMA_Dset_to_GDSET(SUMA_DSET ** pdset,char * mtype,int ok_verticalize,int * ie,int * i0,int * i1)14695 SUMA_Boolean SUMA_Dset_to_GDSET(SUMA_DSET **pdset, char *mtype,
14696                                 int ok_verticalize,
14697                                 int *ie, int *i0, int *i1)
14698 {
14699    static char FuncName[]={"SUMA_Dset_to_GDSET"};
14700    int npts = -1, nseg=0, msz[2];
14701    SUMA_DSET *tdset=NULL, *dset=NULL;
14702    float tt=-1.0;
14703    char *dname=NULL;
14704    SUMA_Boolean LocalHead = NOPE;
14705 
14706    SUMA_ENTRY;
14707 
14708    if (!pdset) SUMA_RETURN(NOPE);
14709    dset = *pdset;
14710    if (!dset || !dset->ngr || !dset->dnel) SUMA_RETURN(NOPE);
14711 
14712    SUMA_LH("Matrix type %s", mtype?mtype:"NULL");
14713 
14714    if (!SUMA_isGraphDset(dset)) {
14715       if (SDSET_VECNUM(dset) == SDSET_VECLEN(dset) &&
14716           ok_verticalize) {/* vertically catenate all columns.
14717                            Only recommended if going from
14718                            an MxM dataset that is just
14719                            one matrix as opposed to M square matrices
14720                            of dimension sqrt(M) */
14721          tdset = SUMA_VcatDset(dset, NULL, NULL, 0, 0);
14722          *pdset = tdset; SUMA_FreeDset(dset); dset=tdset; tdset=NULL;
14723       }
14724 
14725       /* label this thing as a graph */
14726       NI_set_attribute (dset->ngr, "dset_type",
14727                         SUMA_Dset_Type_Name(SUMA_GRAPH_BUCKET));
14728       /* Set type of dnel or it can't be located */
14729       dname = SUMA_append_string(SUMA_Dset_Type_Name(SUMA_GRAPH_BUCKET),
14730                                                                "_data");
14731       NI_set_attribute (dset->dnel, "data_type", dname);
14732       SUMA_free(dname); dname = NULL;
14733 
14734       /* get rid of old inel, if any, and put in a new one for graph dsets*/
14735       SUMA_Reset_NodeIndex_Element(dset, NULL);
14736 
14737       /* figure out the matrix size */
14738       npts = -1;
14739       if (mtype) {
14740          if (!strcmp(mtype,"lower")) {
14741             if (!((tt = (1+sqrt(1+8*nseg))/2.0) == (int)tt)) {
14742                SUMA_S_Errv("Can't get lower triangular matrix from %d values\n",
14743                            nseg);
14744                SUMA_RETURN(NOPE);
14745             }
14746             npts = tt;
14747          } else if (!strcmp(mtype,"lower_diag")) {
14748             if (!((tt = (-1+sqrt(1+8*nseg))/2.0) == (int)tt)) {
14749                SUMA_S_Errv("Can't get lower tri+diag matrix from %d values\n",
14750                            nseg);
14751                SUMA_RETURN(NOPE);
14752             }
14753             npts = tt;
14754          } else if (!strcmp(mtype,"full")) {
14755             if (!((tt = sqrt(SDSET_VECLEN(dset))) == (int)tt)) {
14756                SUMA_S_Errv("Can't get full square matrix from %d values\n",
14757                            nseg);
14758                SUMA_RETURN(NOPE);
14759             }
14760             npts = tt;
14761          } else if (!strcmp(mtype,"sparse")) {
14762             if (!i0 || !i1) {
14763                SUMA_S_Err("Must provide i0 and i1 for spare matrices");
14764                SUMA_RETURN(NOPE);
14765             }
14766          }
14767       }
14768       /* cases where the whole matrix is packed into 1 column */
14769       nseg = SDSET_VECLEN(dset);
14770       if (npts == 1) { /* singletons are full */
14771          msz[0]= msz[1] = npts;
14772          NI_SET_INTv(dset->dnel,"matrix_size", msz,2);
14773          NI_set_attribute(dset->dnel, "matrix_shape",
14774                           SUMA_matrix_shape_to_matrix_shape_name(MAT_FULL));
14775       } else if ((mtype && !strcmp(mtype,"lower")) ||
14776           ((!i0 && !i1) && (tt = (1+sqrt(1+8*nseg))/2.0) == (int)tt)) {
14777          if (npts < 0) npts = tt;
14778          SUMA_LHv("Me thinks it triangular Pa, %d %d\n",
14779                SDSET_VECNUM(dset), SDSET_VECLEN(dset));
14780          /* M*(M-1)/2, lower tri, without the diagonal */
14781          msz[0]= msz[1] = npts;
14782          NI_SET_INTv(dset->dnel,"matrix_size", msz,2);
14783          NI_set_attribute(dset->dnel, "matrix_shape",
14784                           SUMA_matrix_shape_to_matrix_shape_name(MAT_TRI));
14785          /* Edges are implicitly defined, example for a 3x3
14786             seg 0 --> 1,0
14787             seg 1 --> 2,0
14788             seg 2 --> 2,1
14789          */
14790       } else if ((mtype && !strcmp(mtype,"lower_diag")) ||
14791                  ((!i0 && !i1) && (tt = (-1+sqrt(1+8*nseg))/2.0) == (int)tt)) {
14792          if (npts < 0) npts = tt;
14793          SUMA_LHv("Me thinks it triangular Paps, %d %d\n",
14794                SDSET_VECNUM(dset), SDSET_VECLEN(dset));
14795          /* M*(M+1)/2, lower tri, with the diagonal */
14796          msz[0]= msz[1] = npts;
14797          NI_SET_INTv(dset->dnel,"matrix_size", msz,2);
14798          NI_set_attribute(dset->dnel, "matrix_shape",
14799                            SUMA_matrix_shape_to_matrix_shape_name(MAT_TRI_DIAG));
14800          /* Edges are implicitly defined, example for a 3x3
14801             seg 0 --> 0,0
14802             seg 1 --> 1,0
14803             seg 2 --> 2,0
14804             seg 3 --> 1,1
14805             seg 4 --> 2,1
14806             seg 5 --> 2,2
14807          */
14808       } else if ((mtype && !strcmp(mtype,"full")) ||
14809                  ((!i0 && !i1) && (tt = sqrt(SDSET_VECLEN(dset))) == (int)tt)) {
14810          if (npts < 0) npts = tt;
14811          SUMA_LHv("A wholesome stick, %d %d\n",
14812                SDSET_VECNUM(dset), SDSET_VECLEN(dset));
14813          /* full matrix, one column */
14814          msz[0]= msz[1] = npts;
14815          NI_SET_INTv(dset->dnel,"matrix_size", msz,2);
14816          NI_set_attribute(dset->dnel, "matrix_shape",
14817                           SUMA_matrix_shape_to_matrix_shape_name(MAT_FULL));
14818          /* Edges are implicitly defined, example for a 3x3
14819             seg 0 --> 0,0
14820             seg 1 --> 1,0
14821             seg 2 --> 2,0
14822             seg 3 --> 0,1
14823             seg 4 --> 1,1
14824             seg 5 --> 2,1
14825             seg 6 --> 0,2
14826             seg 7 --> 1,2
14827             seg 8 --> 2,2
14828          */
14829       } else if (i0 && i1) {
14830          NI_element *nn=NULL;
14831          int *ieu=NULL, i=0;
14832          if (!i0 || !i1) {
14833             SUMA_S_Err("Cannot convert without more information,"
14834                        "will need an element describing segments");
14835             SUMA_RETURN(NOPE);
14836          }
14837 
14838          if (!ie) {
14839             if (!(ieu = (int *)SUMA_calloc(SDSET_VECALLOC(dset), sizeof(int)))) {
14840                SUMA_S_Errv("Failed to allocate for %d elements\n",
14841                            SDSET_VECLEN(dset));
14842                SUMA_RETURN(NOPE);
14843             }
14844             for (i=0; i<SDSET_VECLEN(dset); ++i) ieu[i]=i;
14845             ie = ieu;
14846          }
14847          if (!SUMA_AddDsetIndexCol(dset, ie, i0, i1)) {
14848             SUMA_S_Err("Failed to add edge list");
14849             SUMA_ifree(ieu); SUMA_RETURN(NOPE);
14850          }
14851          if (ieu) {
14852             SUMA_free(ieu);
14853          }
14854 
14855          SUMA_LHv("A sparse business %d %d\n",
14856                SDSET_VECNUM(dset), SDSET_VECLEN(dset));
14857          if (!(SUMA_SetUniqueIndicesAttr(dset, 1))) {
14858             SUMA_S_Err("Failed to set unique index attributes");
14859             SUMA_RETURN(NOPE);
14860          }
14861 
14862          SUMA_LH("Get unique indices 1");
14863          if (!(nn = SUMA_GetUniqueIndicesAttr(dset,1))) {
14864             SUMA_S_Err("Failed to get unique indices");
14865             SUMA_RETURN(NOPE);
14866          }
14867 
14868          msz[0]= nn->vec_len;
14869          SUMA_LH("Get unique indices 2");
14870          if (!(nn = SUMA_GetUniqueIndicesAttr(dset,2))) {
14871             SUMA_S_Err("Failed to get unique indices");
14872             SUMA_RETURN(NOPE);
14873          }
14874 
14875          msz[1]= nn->vec_len;
14876          if ((tt=SDSET_VECLEN(dset)/(msz[0]*msz[1])) != (int)tt) {
14877             SUMA_S_Errv( "Number of entries per column (%d) is not an \n"
14878                          "integer number of unique edges %d x %d\n",
14879                          SDSET_VECLEN(dset), msz[0], msz[1]);
14880             SUMA_RETURN(NOPE);
14881          }
14882          NI_SET_INTv(dset->dnel,"matrix_size", msz,2);
14883          NI_set_attribute(dset->dnel, "matrix_shape",
14884                           SUMA_matrix_shape_to_matrix_shape_name(MAT_SPARSE));
14885       } else {
14886          SUMA_S_Err("Don't know how to graphize this set");
14887          SUMA_RETURN(NOPE);
14888       }
14889    } else {
14890       SUMA_LH("Nothing changed, odset already a graph");
14891    }
14892 
14893    /* set Aux info */
14894    if (!SUMA_GDSET_Set_Aux_matrix_shape(dset)) {
14895       SUMA_S_Err("Failed to set matrix shape");
14896       SUMA_RETURN(NOPE);
14897    }
14898    SUMA_LH("Done");
14899 
14900    SUMA_RETURN(YUP);
14901 }
14902 
SUMA_matrix_shape_name_to_matrix_shape(char * name)14903 SUMA_SQ_MATRIX_SHAPES SUMA_matrix_shape_name_to_matrix_shape(char *name)
14904 {
14905    if (!name) return(MAT_UNKNOWN);
14906 
14907    if (!strcmp(name,"full")) return(MAT_FULL);
14908    if (!strcmp(name,"square")) {
14909       fprintf(stderr,"square should be replaced by full\n"); return(MAT_FULL);
14910    }
14911    if (!strcmp(name,"tri")) return(MAT_TRI);
14912    if (!strcmp(name,"tri_diag")) return(MAT_TRI_DIAG);
14913    if (!strcmp(name,"sparse")) return(MAT_SPARSE);
14914    if (!strcmp(name,"festus")) return(MAT_HEEHAW); /* not set */
14915    if (!strcmp(name,"NA")) return(MAT_NA);
14916 
14917    return(MAT_UNKNOWN);
14918 }
14919 
SUMA_matrix_shape_to_matrix_shape_name(SUMA_SQ_MATRIX_SHAPES sq)14920 char * SUMA_matrix_shape_to_matrix_shape_name(SUMA_SQ_MATRIX_SHAPES sq)
14921 {
14922    switch (sq) {
14923       case MAT_FULL: return("full");
14924       case MAT_TRI: return("tri");
14925       case MAT_TRI_DIAG: return("tri_diag");
14926       case MAT_SPARSE: return("sparse");
14927       case MAT_HEEHAW: return("festus");
14928       case MAT_NA: return("NA");
14929       default:
14930          return("unknown");
14931    }
14932 }
14933 
14934 /*! Return the i,j, indices corresponding the to 1D index
14935     into the compact  columnwise storage of a triangular matrix.
14936     Use the R test function p2ij in CompactIndexing.R
14937     for details and tests.
14938 
14939     This function does not check if p is < 0 or exceeds the maximum
14940     index.
14941 
14942    \sa macros SUMA_CItri_ij2p_diag, SUMA_CItri_ij2p,
14943    SUMA_CItri_pmax_diag and SUMA_CItri_pmax
14944 */
SUMA_CItri_p2ij(int p,int n,int two_n,byte withdiag,int * i,int * j)14945 byte SUMA_CItri_p2ij(int p, int n, int two_n, byte withdiag, int *i, int *j)
14946 {
14947    int df;
14948    double b, D1;
14949 
14950    /* if (p<0) {*i=-1; *j=-1; return(0);} */
14951    if (withdiag) {
14952       if (p<n) {
14953          *j = 0;
14954          *i = p;
14955       } /* else if (p > SUMA_CItri_pmax_diag(two_n/2)) {
14956          *i=-1; *j=-1; return(0);
14957       } */ else {
14958          b = (two_n-1);
14959          D1 = b*b-8*p;
14960          if (D1 < 0) D1 = 0;
14961          else D1 = sqrt(D1);
14962          *j = (int)(b - D1)/2;
14963             *i = p- (int)(*j*(b-*j))/2;
14964          df = *j-*i;
14965          while (df > 0) { /* this should only loop once if at all*/
14966             *j = *j-1-df/2;
14967             *i = p- (int)(*j*(b-*j))/2;
14968             df = *j-*i;
14969          }
14970       }
14971    } else {
14972       if (p<n-1) {
14973          *j = 0;
14974          *i = p+1;
14975       } /* else if (p > SUMA_CItri_pmax(two_n/2)) {
14976          *i=-1; *j=-1; return(0);
14977       } */ else  {
14978          b = (two_n-3);
14979          D1 = b*b-8*(p-1);
14980          if (D1 < 0) D1 = 0;
14981          else D1 = sqrt(D1);
14982          *j = (int)(b - D1)/2;
14983             *i = p- (int)(*j*(b-*j))/2 +1;
14984          df = *j-*i;
14985          while (df>=0.0) { /* this should only loop once if at all*/
14986             *j = *j-1-df/2;
14987             *i = p- (int)(*j*(b-*j))/2 +1;
14988             df = *j-*i;
14989          }
14990       }
14991    }
14992 
14993    return(1);
14994 }
14995 
14996 /* Populate a few of the heavily used parameters from graph dset into Aux */
SUMA_GDSET_Set_Aux_matrix_shape(SUMA_DSET * dset)14997 SUMA_Boolean SUMA_GDSET_Set_Aux_matrix_shape(SUMA_DSET *dset)
14998 {
14999    static char FuncName[]={"SUMA_GDSET_Set_Aux_matrix_shape"};
15000    double range[2];
15001    int loc[2], buff=0;
15002    SUMA_Boolean LocalHead = NOPE;
15003    SUMA_ENTRY;
15004 
15005    if (!dset->dnel) {
15006       SUMA_S_Err("No data bro.");
15007       SUMA_RETURN(NOPE);
15008    }
15009    if (!dset->Aux) {
15010       SUMA_S_Err("I expect this to be allocated for already for a graph dset");
15011       SUMA_RETURN(NOPE);
15012    }
15013    if (!SUMA_isGraphDset(dset)) {
15014       SUMA_S_Err("I expect this function to be run on graph dsets only");
15015       SUMA_RETURN(NOPE);
15016    }
15017 
15018    dset->Aux->matrix_shape = MAT_HEEHAW;
15019    dset->Aux->matrix_shape = SUMA_matrix_shape_name_to_matrix_shape(
15020                               NI_get_attribute(dset->dnel,"matrix_shape"));
15021    SUMA_LHv("shape: %s (%d), sq=%d\n",
15022       NI_get_attribute(dset->dnel,"matrix_shape"),
15023       dset->Aux->matrix_shape, MAT_FULL);
15024 
15025    SUMA_LHv("size: %s\n", NI_get_attribute(dset->dnel,"matrix_size"));
15026    NI_GET_INTv(dset->dnel, "matrix_size", dset->Aux->matrix_size, 2, 0);
15027    if (!NI_GOT) {
15028       SUMA_S_Err("Missing essential attribute 'matrix_size'");
15029       SUMA_RETURN(NOPE);
15030    }
15031    dset->Aux->matrix_2M = 2*dset->Aux->matrix_size[0];
15032 
15033    switch (dset->Aux->matrix_shape) {
15034       case MAT_FULL:
15035          dset->Aux->matrix_max_index =
15036             dset->Aux->matrix_size[0]*dset->Aux->matrix_size[0]-1;
15037          dset->Aux->range_edge_index[0] = 0;
15038          dset->Aux->range_edge_index[1] = dset->Aux->matrix_max_index;
15039          dset->Aux->range_node_index[0] = 0;
15040          dset->Aux->range_node_index[1] = dset->Aux->matrix_size[0]-1;
15041          dset->Aux->N_seg_nodes = dset->Aux->matrix_size[0];
15042          if (!SUMA_GDSET_GetPointIndexColumn(dset,
15043                                        &buff, NULL)) {
15044             dset->Aux->N_all_nodes = dset->Aux->N_seg_nodes;
15045          } else dset->Aux->N_all_nodes = buff;
15046          break;
15047       case MAT_TRI:
15048          dset->Aux->matrix_max_index =
15049             (dset->Aux->matrix_size[0]*(dset->Aux->matrix_size[0]-1))/2;
15050          dset->Aux->range_edge_index[0] = 0;
15051          dset->Aux->range_edge_index[1] = dset->Aux->matrix_max_index;
15052          dset->Aux->range_node_index[0] = 0;
15053          dset->Aux->range_node_index[1] = dset->Aux->matrix_size[0]-1;
15054          dset->Aux->N_seg_nodes = dset->Aux->matrix_size[0];
15055          if (!SUMA_GDSET_GetPointIndexColumn(dset,
15056                                        &buff, NULL)) {
15057             dset->Aux->N_all_nodes = dset->Aux->N_seg_nodes;
15058          } else dset->Aux->N_all_nodes = buff;
15059          break;
15060       case MAT_TRI_DIAG:
15061          dset->Aux->matrix_max_index =
15062             (dset->Aux->matrix_size[0]*(dset->Aux->matrix_size[0]+1))/2;
15063          dset->Aux->range_edge_index[0] = 0;
15064          dset->Aux->range_edge_index[1] = dset->Aux->matrix_max_index;
15065          dset->Aux->range_node_index[0] = 0;
15066          dset->Aux->range_node_index[1] = dset->Aux->matrix_size[0]-1;
15067          dset->Aux->N_seg_nodes = dset->Aux->matrix_size[0];
15068          if (!SUMA_GDSET_GetPointIndexColumn(dset,
15069                                        &buff, NULL)){
15070             dset->Aux->N_all_nodes = dset->Aux->N_seg_nodes;
15071          } else dset->Aux->N_all_nodes = buff;
15072          break;
15073       case MAT_SPARSE:
15074          if (!dset->inel) {
15075             SUMA_S_Err("Don't have inel, badly shaped dataset");
15076             SUMA_RETURN(NOPE);
15077          }
15078          dset->Aux->matrix_max_index = dset->inel->vec_len;
15079 
15080          if (!SUMA_GetDsetNodeIndexColRange_eng(dset, range, loc, 0, 0)) {
15081             SUMA_LH("Failed to get erange?");
15082             dset->Aux->range_edge_index[0] = -2; /* error */
15083             dset->Aux->range_edge_index[1] = -2; /* error */
15084             SUMA_RETURN(NOPE);
15085          }
15086          dset->Aux->range_edge_index[0] = (long int)range[0];
15087          dset->Aux->range_edge_index[1] = (long int)range[1];
15088 
15089          if (!SUMA_GetDsetNodeIndexColRange_eng(dset, range, loc, 0, 1)) {
15090             SUMA_LH("Failed to get i0range?");
15091             dset->Aux->range_node_index[0] = -2; /* error */
15092             dset->Aux->range_node_index[1] = -2; /* error */
15093             SUMA_RETURN(NOPE);
15094          }
15095          dset->Aux->range_node_index[0] = (long int)range[0];
15096          dset->Aux->range_node_index[1] = (long int)range[1];
15097          if (!SUMA_GetDsetNodeIndexColRange_eng(dset, range, loc, 0, 2)) {
15098             SUMA_LH("Failed to get i1range?");
15099             dset->Aux->range_node_index[0] = -2; /* error */
15100             dset->Aux->range_node_index[1] = -2; /* error */
15101             SUMA_RETURN(NOPE);
15102          }
15103          if (dset->Aux->range_node_index[0] > (long int)range[0])
15104             dset->Aux->range_node_index[0] = (long int)range[0];
15105          if (dset->Aux->range_node_index[1] < (long int)range[1])
15106             dset->Aux->range_node_index[1] = (long int)range[1];
15107 
15108          /* get the unique set of nodes/points of graph */
15109          { int *ii=NULL, N_iu=-1, *iu=NULL;
15110          ii  = SDSET_EDGE_P1_INDEX_COL(dset);
15111          iu = UniqueInt(ii, SDSET_VECLEN(dset), &N_iu, 0 );
15112 
15113          /* catenate second column to unique of first */
15114          ii  = SDSET_EDGE_P2_INDEX_COL(dset);
15115          iu = (int *)realloc(iu, (SDSET_VECALLOC(dset)+N_iu)*sizeof(int));
15116          memcpy(iu+N_iu, ii, SDSET_VECALLOC(dset)*sizeof(int));
15117 
15118          /* find unique of both */
15119          ii = iu;
15120          iu = UniqueInt(ii, (SDSET_VECLEN(dset)+N_iu), &N_iu, 0);
15121          free(ii);
15122          free(iu);
15123          dset->Aux->N_seg_nodes = N_iu;
15124          }
15125 
15126          if (!SUMA_GDSET_GetPointIndexColumn(dset,
15127                                        &buff, NULL)){
15128             dset->Aux->N_all_nodes = dset->Aux->N_seg_nodes;
15129          } else dset->Aux->N_all_nodes = buff;
15130          SUMA_RETURN(YUP);
15131          break;
15132    }
15133    SUMA_RETURN(YUP);
15134 }
15135 
15136 /* this function should be fast, no messing around ,
15137 You should have a faster version, no need to bother with HEEHAW, that
15138 should be done before this first call also, no need to check on *i2
15139 if the index map is properly formed ...
15140 
15141 \param dset (SUMA_DSET *) a graph dset
15142 \param si (int) a segment/edge's index
15143 \param i1 (int *)to contain the index of the 1st node forming the edge
15144 \param i2 (int *)to contain the index of the 2nd node forming the edge
15145 \param row (int *) to contain the row in 'inel' where si was listed.
15146                    This parameter is only set for sparse matrices
15147 \sa SUMA_GDSET_SegRowToPoints
15148 */
SUMA_GDSET_SegIndexToPoints(SUMA_DSET * dset,int si,int * i1,int * i2,int * row)15149 byte SUMA_GDSET_SegIndexToPoints(SUMA_DSET *dset, int si,
15150                                  int *i1, int *i2, int *row)
15151 {
15152    static char FuncName[]={"SUMA_GDSET_SegIndexToPoints"};
15153    if (si < 0) return(0);
15154    *i1 = -1;
15155    switch (dset->Aux->matrix_shape) {
15156       case MAT_FULL:
15157          if (si > dset->Aux->matrix_max_index) return(0);
15158          *i2 = si / dset->Aux->matrix_size[0];
15159          if (*i2 >= dset->Aux->matrix_size[0]) return(0);
15160          *i1 = si % dset->Aux->matrix_size[0]; return(1);
15161          break;
15162       case MAT_TRI:
15163          if (si > dset->Aux->matrix_max_index) return(0);
15164          SUMA_CItri_p2ij(si, dset->Aux->matrix_size[0],
15165                          dset->Aux->matrix_2M, 0, i1, i2);
15166          return(1);
15167          break;
15168       case MAT_TRI_DIAG:
15169          SUMA_CItri_p2ij(si, dset->Aux->matrix_size[0],
15170                          dset->Aux->matrix_2M, 1, i1, i2);
15171          return(1);
15172          break;
15173       case MAT_SPARSE: { int r, *rp;
15174          /* Use index to figure out row */
15175          if ((r = SUMA_GetNodeRow_FromNodeIndex_eng(dset, si, -1))> -1) {
15176             rp = (int*)(dset->inel->vec[1]);
15177             *i1 = rp[r];
15178             rp = (int*)(dset->inel->vec[2]);
15179             *i2 = rp[r];
15180             if (row) *row = r;
15181             /* SUMA_S_Notev("Edge index %d, row %d, [%d %d]\n",
15182                             si, r, *i1, *i2); */
15183          }
15184          return(1);
15185          break; }
15186    }
15187 
15188    return(0);
15189 }
15190 
15191 /*! Go from segment row to points (and index)
15192 \sa SUMA_GDSET_SegIndexToPoints
15193 */
SUMA_GDSET_SegRowToPoints(SUMA_DSET * dset,int ri,int * i1,int * i2,int * index)15194 byte SUMA_GDSET_SegRowToPoints(SUMA_DSET *dset, int ri,
15195                                  int *i1, int *i2, int *index)
15196 {
15197    static char FuncName[]={"SUMA_GDSET_SegRowToPoints"};
15198    if (ri < 0) return(0);
15199    *i1 = -1;
15200    switch (dset->Aux->matrix_shape) {
15201       case MAT_FULL:
15202          if (ri > dset->Aux->matrix_max_index) return(0);
15203          *i2 = ri / dset->Aux->matrix_size[0];
15204          if (*i2 >= dset->Aux->matrix_size[0]) return(0);
15205          *i1 = ri % dset->Aux->matrix_size[0]; return(1);
15206          break;
15207       case MAT_TRI:
15208          if (ri > dset->Aux->matrix_max_index) return(0);
15209          SUMA_CItri_p2ij(ri, dset->Aux->matrix_size[0],
15210                          dset->Aux->matrix_2M, 0, i1, i2);
15211          return(1);
15212          break;
15213       case MAT_TRI_DIAG:
15214          SUMA_CItri_p2ij(ri, dset->Aux->matrix_size[0],
15215                          dset->Aux->matrix_2M, 1, i1, i2);
15216          return(1);
15217          break;
15218       case MAT_SPARSE: { int r, *rp;
15219          /* Use index to figure out row */
15220             rp = (int*)(dset->inel->vec[1]);
15221             *i1 = rp[ri];
15222             rp = (int*)(dset->inel->vec[2]);
15223             *i2 = rp[ri];
15224             if (index) {
15225                rp = (int*)(dset->inel->vec[0]);
15226                *index = rp[ri];
15227             }
15228             /* SUMA_S_Notev("Edge row %d, index %d, row %d, [%d %d]\n",
15229                             ri, index ? *index:-1, *i1, *i2); */
15230          return(1);
15231          break; }
15232    }
15233 
15234    return(0);
15235 }
15236 
15237 /* \sa SUMA_GDSET_PointsToSegRow */
SUMA_GDSET_PointsToSegIndex(SUMA_DSET * dset,int i1,int i2,int * si)15238 byte SUMA_GDSET_PointsToSegIndex(SUMA_DSET *dset, int i1, int i2, int *si)
15239 {
15240    static char FuncName[]={"SUMA_GDSET_PointsToSegIndex"};
15241 
15242    *si = -1;
15243    if (i1 < 0 || i2 < 0) return(0);
15244    switch (dset->Aux->matrix_shape) {
15245       case MAT_FULL:
15246          if (i1 >= dset->Aux->matrix_size[0] ||
15247              i2 >= dset->Aux->matrix_size[0]) return(0);
15248          *si = i1+i2*dset->Aux->matrix_size[0]; return(1);
15249          break;
15250       case MAT_TRI:
15251          if (i1 >= dset->Aux->matrix_size[0] ||
15252              i2 >= dset->Aux->matrix_size[0]) return(0);
15253          *si = SUMA_CItri_ij2p(i1,i2,dset->Aux->matrix_2M);
15254          return(1);
15255          break;
15256       case MAT_TRI_DIAG:
15257          if (i1 >= dset->Aux->matrix_size[0] ||
15258              i2 >= dset->Aux->matrix_size[0]) return(0);
15259          *si = SUMA_CItri_ij2p_diag(i1,i2,dset->Aux->matrix_2M);
15260          return(1);
15261          break;
15262       case MAT_SPARSE: { int is, *p1, *p2, *p0;
15263          /* This will be a slow slog unless I create a points to edge list */
15264          p1 = (int*)(dset->inel->vec[1]);
15265          p2 = (int*)(dset->inel->vec[2]);
15266          p0 = (int*)(dset->inel->vec[0]);
15267          for (is=0; is < dset->inel->vec_len; ++is) {
15268             if (p1[is]==i1 && p2[is]==i2) { *si = p0[is]; return(1); }
15269          }
15270          break; }
15271    }
15272 
15273    return(0);
15274 
15275 }
15276 
SUMA_GDSET_PointToDiagSegIndex(SUMA_DSET * dset,int i1,int * si)15277 byte SUMA_GDSET_PointToDiagSegIndex(SUMA_DSET *dset, int i1, int *si)
15278 {
15279    static char FuncName[]={"SUMA_GDSET_PointToDiagSegIndex"};
15280 
15281    *si = -1;
15282    if (i1 < 0) return(0);
15283    switch (dset->Aux->matrix_shape) {
15284       case MAT_FULL:
15285          if (i1 >= dset->Aux->matrix_size[0]) return(0);
15286          *si = i1+i1*dset->Aux->matrix_size[0]; return(1);
15287          break;
15288       case MAT_TRI:
15289          /* No diags elems here */
15290          return(0);
15291          break;
15292       case MAT_TRI_DIAG:
15293          if (i1 >= dset->Aux->matrix_size[0]) return(0);
15294          *si = SUMA_CItri_ij2p_diag(i1,i1,dset->Aux->matrix_2M);
15295          return(1);
15296          break;
15297       case MAT_SPARSE: { int is, *p1, *p2, *p0;
15298          /* This will be a slow slog unless I create a points to edge list */
15299          p1 = (int*)(dset->inel->vec[1]);
15300          p2 = (int*)(dset->inel->vec[2]);
15301          p0 = (int*)(dset->inel->vec[0]);
15302          for (is=0; is < dset->inel->vec_len; ++is) {
15303             if (p1[is]==i1 && p2[is]==i1) { *si = p0[is]; return(1); }
15304          }
15305          break; }
15306    }
15307 
15308    return(0);
15309 
15310 }
15311 
SUMA_GDSET_PointToDiagSegRowIndex(SUMA_DSET * dset,int i1,int * ri,int * si)15312 byte SUMA_GDSET_PointToDiagSegRowIndex(SUMA_DSET *dset, int i1, int *ri, int *si)
15313 {
15314    static char FuncName[]={"SUMA_GDSET_PointToDiagSegRowIndex"};
15315 
15316    *si = -1; *ri = -1;
15317    if (i1 < 0) return(0);
15318    switch (dset->Aux->matrix_shape) {
15319       case MAT_FULL:
15320          if (i1 >= dset->Aux->matrix_size[0]) return(0);
15321          *si = i1+i1*dset->Aux->matrix_size[0];
15322          *ri = *si; return(1);
15323          break;
15324       case MAT_TRI:
15325          /* No diags elems here */
15326          return(0);
15327          break;
15328       case MAT_TRI_DIAG:
15329          if (i1 >= dset->Aux->matrix_size[0]) return(0);
15330          *si = SUMA_CItri_ij2p_diag(i1,i1,dset->Aux->matrix_2M);
15331          *ri = *si;
15332          return(1);
15333          break;
15334       case MAT_SPARSE: { int is, *p1, *p2, *p0;
15335          /* This will be a slow slog unless I create a points to edge list */
15336          p1 = (int*)(dset->inel->vec[1]);
15337          p2 = (int*)(dset->inel->vec[2]);
15338          p0 = (int*)(dset->inel->vec[0]);
15339          for (is=0; is < dset->inel->vec_len; ++is) {
15340             if (p1[is]==i1 && p2[is]==i1) {
15341                *si = p0[is];
15342                *ri = is;
15343                return(1);
15344             }
15345          }
15346          break; }
15347    }
15348 
15349    return(0);
15350 
15351 }
15352 
15353 /*
15354 \sa SUMA_GDSET_PointsToSegIndex
15355 */
SUMA_GDSET_PointsToSegRow(SUMA_DSET * dset,int i1,int i2,int * ri)15356 byte SUMA_GDSET_PointsToSegRow(SUMA_DSET *dset, int i1, int i2, int *ri)
15357 {
15358    static char FuncName[]={"SUMA_GDSET_PointsToSegRow"};
15359 
15360    *ri = -1;
15361    if (i1 < 0 || i2 < 0) return(0);
15362    switch (dset->Aux->matrix_shape) {
15363       case MAT_FULL:
15364          if (i1 >= dset->Aux->matrix_size[0] ||
15365              i2 >= dset->Aux->matrix_size[0]) return(0);
15366          *ri = i1+i2*dset->Aux->matrix_size[0]; return(1);
15367          break;
15368       case MAT_TRI:
15369          if (i1 >= dset->Aux->matrix_size[0] ||
15370              i2 >= dset->Aux->matrix_size[0]) return(0);
15371          *ri = SUMA_CItri_ij2p(i1,i2,dset->Aux->matrix_2M);
15372          return(1);
15373          break;
15374       case MAT_TRI_DIAG:
15375          if (i1 >= dset->Aux->matrix_size[0] ||
15376              i2 >= dset->Aux->matrix_size[0]) return(0);
15377          *ri = SUMA_CItri_ij2p_diag(i1,i2,dset->Aux->matrix_2M);
15378          return(1);
15379          break;
15380       case MAT_SPARSE: { int is, *p1, *p2;
15381          /* This will be a slow slog unless I create a points to edge list */
15382          p1 = (int*)(dset->inel->vec[1]);
15383          p2 = (int*)(dset->inel->vec[2]);
15384          for (is=0; is < dset->inel->vec_len; ++is) {
15385             if (p1[is]==i1 && p2[is]==i2) { *ri = is; return(1); }
15386          }
15387          break; }
15388    }
15389 
15390    return(0);
15391 
15392 }
15393 
SUMA_GDSET_PointToDiagSegRow(SUMA_DSET * dset,int i1,int * ri)15394 byte SUMA_GDSET_PointToDiagSegRow(SUMA_DSET *dset, int i1, int *ri)
15395 {
15396    static char FuncName[]={"SUMA_GDSET_PointToDiagSegRow"};
15397 
15398    *ri = -1;
15399    if (i1 < 0) return(0);
15400    switch (dset->Aux->matrix_shape) {
15401       case MAT_FULL:
15402          if (i1 >= dset->Aux->matrix_size[0]) return(0);
15403          *ri = i1+i1*dset->Aux->matrix_size[0]; return(1);
15404          break;
15405       case MAT_TRI:
15406          /* No diagonal entries here */
15407          return(0);
15408          break;
15409       case MAT_TRI_DIAG:
15410          if (i1 >= dset->Aux->matrix_size[0]) return(0);
15411          *ri = SUMA_CItri_ij2p_diag(i1,i1,dset->Aux->matrix_2M);
15412          return(1);
15413          break;
15414       case MAT_SPARSE: { int is, *p1, *p2;
15415          /* This will be a slow slog unless I create a points to edge list */
15416          p1 = (int*)(dset->inel->vec[1]);
15417          p2 = (int*)(dset->inel->vec[2]);
15418          for (is=0; is < dset->inel->vec_len; ++is) {
15419             if (p1[is]==i1 && p2[is]==i1) { *ri = is; return(1); }
15420          }
15421          break; }
15422    }
15423 
15424    return(0);
15425 
15426 }
15427 
15428 /* From a node index, find the row where that node index is listed
15429 in the node list */
SUMA_GDSET_NodeIndex_To_Index(SUMA_DSET * dset,int node)15430 int SUMA_GDSET_NodeIndex_To_Index(SUMA_DSET *dset, int node)
15431 {
15432    static char FuncName[]={"SUMA_GDSET_NodeIndex_To_Index"};
15433    int N_vals, *I;
15434    if (node < 0) return(node);
15435    I = SUMA_GDSET_GetPointIndexColumn(dset, &N_vals, NULL);
15436    if (N_vals == -2) return(-1); /* error */
15437    if (N_vals == -1) return(node); /* implicit list ! */
15438    return(SUMA_NodeIndex_To_Index(I, N_vals, node));
15439 }
15440 
SUMA_GDSET_Index_To_NodeIndex(SUMA_DSET * dset,int cinode)15441 int SUMA_GDSET_Index_To_NodeIndex(SUMA_DSET *dset, int cinode)
15442 {
15443    static char FuncName[]={"SUMA_GDSET_Index_To_NodeIndex"};
15444    int *I=NULL, N_vals;
15445    if (cinode < 0) return(cinode);
15446    if ((I=SUMA_GDSET_GetPointIndexColumn(dset, &N_vals,NULL))) {
15447       if (cinode < N_vals) {
15448          return(I[cinode]);
15449       } else {
15450          SUMA_S_Errv("Bad news, index %d exceeds array length %d...\n",
15451                      cinode, N_vals);
15452          return(-1);
15453       }
15454    } else {
15455       if (N_vals == -2) {
15456          SUMA_S_Err("Badness");
15457          return(-1);
15458       } else return(cinode);
15459    }
15460 }
15461 
SUMA_GDSET_EdgeIndex_To_Row(SUMA_DSET * dset,int ei)15462 int SUMA_GDSET_EdgeIndex_To_Row(SUMA_DSET *dset, int ei)
15463 {
15464    static char FuncName[]={"SUMA_GDSET_EdgeIndex_To_Row"};
15465    if (ei < 0) return(ei);
15466    switch (dset->Aux->matrix_shape) {
15467       case MAT_SPARSE: { int *p0, N=SDSET_VECLEN(dset);
15468          p0 = (int*)(dset->inel->vec[0]);
15469          return(SUMA_NodeIndex_To_Index(p0, N, ei));
15470          break; }
15471       default:
15472          return(ei);
15473    }
15474    return(ei);
15475 }
15476 
SUMA_GDSET_EdgeRow_To_Index(SUMA_DSET * dset,int ri)15477 int SUMA_GDSET_EdgeRow_To_Index(SUMA_DSET *dset, int ri)
15478 {
15479    static char FuncName[]={"SUMA_GDSET_EdgeRow_To_Index"};
15480    if (ri < 0 || ri > SDSET_VECLEN(dset)) return(-1);
15481    switch (dset->Aux->matrix_shape) {
15482       case MAT_SPARSE: { int *p0;
15483          p0 = (int*)(dset->inel->vec[0]);
15484          return(p0[ri]);
15485          break; }
15486       default:
15487          return(ri);
15488    }
15489    return(ri);
15490 }
15491 
SUMA_GDSET_Max_Edge_Index(SUMA_DSET * dset)15492 int SUMA_GDSET_Max_Edge_Index(SUMA_DSET *dset)
15493 {
15494    static char FuncName[]={"SUMA_GDSET_Max_Edge_Index"};
15495    int mm;
15496    GDSET_MAX_EDGE_INDEX(dset, mm);
15497    return(mm);
15498 }
15499 
15500 /* Get the column containing the ids of points
15501 as they are listed in the coordinates list.
15502 
15503 If the list is implicit, N_vals is set to -1 and you get
15504 NULL back.
15505 
15506 If the xyz element is badly formed, N_vals is set to -2 as
15507 an error flag
15508 
15509 If there is an explicit indexing column, it is retured and
15510 N_vals set to the number of values in the column
15511 
15512 If nelxyr is not null, it will contain nelxyz on return.
15513 */
SUMA_GDSET_GetPointIndexColumn(SUMA_DSET * dset,int * N_vals,NI_element ** nelxyzr)15514 int *SUMA_GDSET_GetPointIndexColumn(SUMA_DSET *dset, int *N_vals,
15515                                     NI_element **nelxyzr)
15516 {
15517    static char FuncName[]={"SUMA_GDSET_GetPointIndexColumn"};
15518    NI_element *nelxyz=NULL;
15519    int *I=NULL, iicoord=-1;
15520    char *cs=NULL;
15521    SUMA_Boolean LocalHead = NOPE;
15522 
15523    SUMA_ENTRY;
15524 
15525    if (!N_vals) {
15526       SUMA_S_Err("You cheap date! I need N_vals to be not null");
15527       SUMA_RETURN(NULL);
15528    }
15529 
15530    *N_vals = -2; /*use as an error flag */
15531    if (nelxyzr) *nelxyzr = NULL;
15532 
15533    if (!(nelxyz = SUMA_FindGDsetNodeListElement(dset))) {
15534       /* Just fine if calling function knows what to do
15535          about this */
15536       SUMA_LHv("Failed to find Dset %s's NodeListElement.\n",
15537                 SDSET_LABEL(dset));
15538       if (LocalHead) SUMA_DUMP_TRACE("Who dun that?");
15539       SUMA_RETURN(NULL);
15540    }
15541    if (nelxyzr) *nelxyzr = nelxyz;
15542 
15543    /* The search by label is overkill since I enforce 'I'
15544       to be the 1st column ... Oh well. */
15545    if (!(cs = NI_get_attribute(nelxyz,"COLMS_LABS"))) {
15546       SUMA_S_Err("What can I say?");
15547       SUMA_RETURN(NULL);
15548    }
15549 
15550    if ((iicoord=SUMA_NI_find_in_cs_string(cs, SUMA_NI_CSS,
15551                                           "Gnode Index"))<0) {
15552       SUMA_LH("Failed to find I, assuming we have a full list");
15553       *N_vals = -1;
15554    } else {
15555       I = (int *)nelxyz->vec[iicoord];
15556       *N_vals = nelxyz->vec_len;
15557    }
15558 
15559    SUMA_RETURN(I);
15560 }
15561 
SUMA_GDSET_GetPointNamesColumn(SUMA_DSET * dset,int * N_vals,NI_element ** nelxyzr)15562 char **SUMA_GDSET_GetPointNamesColumn(SUMA_DSET *dset, int *N_vals,
15563                                     NI_element **nelxyzr)
15564 {
15565    static char FuncName[]={"SUMA_GDSET_GetPointNamesColumn"};
15566    NI_element *nelxyz=NULL;
15567    char  **I=NULL;
15568    int iicoord=-1;
15569    char *cs=NULL;
15570    SUMA_Boolean LocalHead = NOPE;
15571 
15572    SUMA_ENTRY;
15573 
15574    if (!N_vals) {
15575       SUMA_S_Err("You cheap skate! I need N_vals to be not null");
15576       SUMA_RETURN(NULL);
15577    }
15578    *N_vals = -2; /*use as an error flag */
15579    if (nelxyzr) *nelxyzr = NULL;
15580 
15581    if (!(nelxyz = SUMA_FindGDsetNodeListElement(dset))) {
15582       SUMA_S_Errv("Failed to find Dset %s's NodeListElement\n",
15583                         SDSET_LABEL(dset));
15584       SUMA_RETURN(NULL);
15585    }
15586    if (nelxyzr) *nelxyzr = nelxyz;
15587 
15588    /* The search by label is overkill since I enforce 'I'
15589       to be the 1st column ... Oh well. */
15590    if (!(cs = NI_get_attribute(nelxyz,"COLMS_LABS"))) {
15591       SUMA_S_Err("What can I say?");
15592       SUMA_RETURN(NULL);
15593    }
15594 
15595    if ((iicoord=SUMA_NI_find_in_cs_string(cs, SUMA_NI_CSS,
15596                                           "Gnode Label"))<0) {
15597       SUMA_LH("Failed to find I, assuming we have a full list");
15598       *N_vals = -1;
15599    } else {
15600       I = (char **)nelxyz->vec[iicoord];
15601       *N_vals = nelxyz->vec_len;
15602    }
15603 
15604    SUMA_RETURN(I);
15605 }
15606 
SUMA_GDSET_GetPointGroupColumn(SUMA_DSET * dset,int * N_vals,NI_element ** nelxyzr)15607 int *SUMA_GDSET_GetPointGroupColumn(SUMA_DSET *dset, int *N_vals,
15608                                       NI_element **nelxyzr)
15609 {
15610    static char FuncName[]={"SUMA_GDSET_GetPointGroupColumn"};
15611    NI_element *nelxyz=NULL;
15612    int *I=NULL;
15613    int iicoord=-1;
15614    char *cs=NULL;
15615    SUMA_Boolean LocalHead = NOPE;
15616 
15617    SUMA_ENTRY;
15618 
15619    if (!N_vals) {
15620       SUMA_S_Err("You cheap skate! I need N_vals to be not null");
15621       SUMA_RETURN(NULL);
15622    }
15623    *N_vals = -2; /*use as an error flag */
15624    if (nelxyzr) *nelxyzr = NULL;
15625 
15626    if (!(nelxyz = SUMA_FindGDsetNodeListElement(dset))) {
15627       SUMA_S_Errv("Failed to find Dset %s's NodeListElement\n",
15628                         SDSET_LABEL(dset));
15629       SUMA_RETURN(NULL);
15630    }
15631    if (nelxyzr) *nelxyzr = nelxyz;
15632 
15633    /* The search by label is overkill since I enforce 'I'
15634       to be the 1st column ... Oh well. */
15635    if (!(cs = NI_get_attribute(nelxyz,"COLMS_LABS"))) {
15636       SUMA_S_Err("What can I say?");
15637       SUMA_RETURN(NULL);
15638    }
15639 
15640    if ((iicoord=SUMA_NI_find_in_cs_string(cs, SUMA_NI_CSS,
15641                                           "Gnode Group"))<0) {
15642       SUMA_LH("Failed to find I, assuming we have a full list");
15643       *N_vals = -1;
15644    } else {
15645       I = (int *)nelxyz->vec[iicoord];
15646       *N_vals = nelxyz->vec_len;
15647    }
15648 
15649    SUMA_RETURN(I);
15650 }
15651 
SUMA_GDSET_GetPointColumn_f(SUMA_DSET * dset,int * N_vals,NI_element ** nelxyzr,char * label)15652 float *SUMA_GDSET_GetPointColumn_f(SUMA_DSET *dset, int *N_vals,
15653                                       NI_element **nelxyzr, char *label)
15654 {
15655    static char FuncName[]={"SUMA_GDSET_GetPointColumn_f"};
15656    NI_element *nelxyz=NULL;
15657    float *I=NULL;
15658    int iicoord=-1;
15659    char *cs=NULL;
15660    SUMA_Boolean LocalHead = NOPE;
15661 
15662    SUMA_ENTRY;
15663 
15664    if (!N_vals) {
15665       SUMA_S_Err("You cheap skate! I need N_vals to be not null");
15666       SUMA_RETURN(NULL);
15667    }
15668    *N_vals = -2; /*use as an error flag */
15669    if (nelxyzr) *nelxyzr = NULL;
15670 
15671    if (!(nelxyz = SUMA_FindGDsetNodeListElement(dset))) {
15672       SUMA_S_Errv("Failed to find Dset %s's NodeListElement\n",
15673                         SDSET_LABEL(dset));
15674       SUMA_RETURN(NULL);
15675    }
15676    if (nelxyzr) *nelxyzr = nelxyz;
15677 
15678    /* The search by label is overkill since I enforce 'I'
15679       to be the 1st column ... Oh well. */
15680    if (!(cs = NI_get_attribute(nelxyz,"COLMS_LABS"))) {
15681       SUMA_S_Err("What can I say?");
15682       SUMA_RETURN(NULL);
15683    }
15684 
15685    if ((iicoord=SUMA_NI_find_in_cs_string(cs, SUMA_NI_CSS, label))<0) {
15686       SUMA_LH("Failed to find I");
15687       *N_vals = -1;
15688    } else {
15689       I = (float *)nelxyz->vec[iicoord];
15690       *N_vals = nelxyz->vec_len;
15691    }
15692 
15693    SUMA_RETURN(I);
15694 }
15695 
15696 /* Get the name of an edge in a graph dset
15697    DO FREE the result */
SUMA_GDSET_Edge_Label(SUMA_DSET * dset,int isel,char * pref,char * sep)15698 char *SUMA_GDSET_Edge_Label(SUMA_DSET *dset, int isel, char *pref, char *sep)
15699 {
15700    static char FuncName[]={"SUMA_GDSET_Edge_Label"};
15701    int *inde, *ind0, *ind1, i1=0, i2=0;
15702    char *ans=NULL;
15703    SUMA_Boolean LocalHead = NOPE;
15704 
15705    SUMA_ENTRY;
15706 
15707    if (!dset || isel < 0) SUMA_RETURN(NULL);
15708    if (!sep) sep = ",";
15709 
15710    if (isel <= SUMA_GDSET_Max_Edge_Index(dset)) {
15711       SDSET_EDGE_NODE_INDEX_COLS(dset, inde, ind0, ind1);
15712       if (!ind0 || !ind1 || !inde) {
15713          SUMA_LH("No explicit node idexing information");
15714          SUMA_RETURN(NULL);
15715       }
15716       if (inde[isel] != isel) {
15717          SUMA_LHv("Hard way for segment index %d: i1=%d, i2 = %d\n",
15718                         isel, i1, i2);
15719          /* Fetch the indices of the nodes forming the edge */
15720          if (!SUMA_GDSET_SegIndexToPoints(dset, isel, &i1, &i2, NULL)) {
15721             SUMA_S_Errv("Failed to locate nodes of edge %d on dset %s\n",
15722                         isel, SDSET_LABEL(dset));
15723             SUMA_RETURN(NULL);
15724          }
15725       } else { /* the easy way */
15726          SUMA_LHv("Easy way: inde[%d]=%d [%d %d]\n",
15727                   isel, inde[isel], ind0[isel], ind1[isel]);
15728          i1 = ind0[isel];
15729          i2 = ind1[isel];
15730       }
15731 
15732       if (i1 < 0 || i2 < 0) SUMA_RETURN(NULL);
15733 
15734       if (!pref) {
15735          ans = SUMA_copy_string(SUMA_GDSET_Node_Label(dset, i1));
15736       } else {
15737          ans = SUMA_append_replace_string(pref,
15738                      SUMA_GDSET_Node_Label(dset, i1),"", 0);
15739       }
15740       ans = SUMA_append_replace_string(ans,
15741                         SUMA_GDSET_Node_Label(dset, i2), sep ,1);
15742 
15743       SUMA_LHv("label for edge %d [%d %d] on %s is: %s from (%s %s)\n",
15744                 isel, i1, i2, SDSET_LABEL(dset), ans?ans:"NULL",
15745              SUMA_GDSET_Node_Label(dset, i1), SUMA_GDSET_Node_Label(dset, i2));
15746    } else {
15747       SUMA_LHv("isel=%d, veclen=%d, max edge index %d\n",
15748                isel, SDSET_VECLEN(dset), SUMA_GDSET_Max_Edge_Index(dset));
15749    }
15750 
15751    SUMA_RETURN(ans);
15752 }
15753 
15754 /* Get the name label for a graph dset node
15755    Do not free returned string */
SUMA_GDSET_Node_Label(SUMA_DSET * dset,int psel)15756 char *SUMA_GDSET_Node_Label(SUMA_DSET *dset, int psel)
15757 {
15758    static char FuncName[]={"SUMA_GDSET_Node_Label"};
15759    int ii, iname;
15760    char **names= NULL;
15761 
15762    SUMA_ENTRY;
15763 
15764    if (!dset || psel < 0) SUMA_RETURN(NULL);
15765 
15766    if (!(names = SUMA_GDSET_GetPointNamesColumn(dset, &ii, NULL))) {
15767       if (ii == -2) SUMA_S_Err("No names!!");
15768       SUMA_RETURN(NULL);
15769    }
15770 
15771    iname = SUMA_GDSET_NodeIndex_To_Index(dset, psel);
15772    if (iname >= 0) SUMA_RETURN(names[iname]);
15773 
15774    SUMA_RETURN(NULL);
15775 }
15776 
SUMA_FindGDsetNodeListElement(SUMA_DSET * dset)15777 NI_element *SUMA_FindGDsetNodeListElement(SUMA_DSET *dset)
15778 {
15779    static char FuncName[]={"SUMA_FindGDsetNodeListElement"};
15780    char *attname=NULL;
15781    NI_element *nel=NULL;
15782    SUMA_Boolean LocalHead = NOPE;
15783 
15784    SUMA_ENTRY;
15785 
15786    if (!dset || !dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
15787    attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_node_coordinates");
15788    SUMA_LHv("Seeking NODE_COORDS with %s\n", attname);
15789    nel = SUMA_FindNgrDataElement(dset->ngr, "NODE_COORDS", attname);
15790    SUMA_free(attname);
15791    SUMA_RETURN(nel);
15792 }
15793 
15794 /* Add the indices and coordinates of nodes forming graph dataset
15795    Note that I may get reordered in this function */
SUMA_AddGDsetNodeListElement(SUMA_DSET * dset,int * I,float * X,float * Y,float * Z,char ** names,int * cln,float * cols,int N_Nodes)15796 NI_element *SUMA_AddGDsetNodeListElement(SUMA_DSET *dset,
15797                                         int *I, float *X, float *Y, float *Z,
15798                                         char **names, int *cln, float *cols,
15799                                         int N_Nodes)
15800 {
15801    static char FuncName[]={"SUMA_AddGDsetNodeListElement"};
15802    char *attname=NULL;
15803    NI_element *nel=NULL;
15804    int *isort = NULL, dosort = 0, ii, jump=0;
15805    float *fv=NULL, *fvxyz=NULL;
15806    SUMA_Boolean LocalHead = NOPE;
15807 
15808    SUMA_ENTRY;
15809 
15810    if (!dset || !dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
15811    if (cln && !cols) {
15812       SUMA_S_Err("If you specify node grouping, you must also send the colors");
15813       SUMA_RETURN(NULL);
15814    }
15815    if (!SUMA_isGraphDset(dset)) {
15816       SUMA_SL_Err("Non graph dset");
15817       SUMA_RETURN(NULL);
15818    }
15819    if (dset->Aux->matrix_shape == MAT_HEEHAW) {
15820       if (!SUMA_GDSET_Set_Aux_matrix_shape(dset)) {
15821          SUMA_S_Err("Failed to set matrix shape");
15822          SUMA_RETURN(NULL);
15823       }
15824    }
15825    if (!(nel=SUMA_FindGDsetNodeListElement(dset))) {
15826       attname = SUMA_append_string(NEL_DSET_TYPE(dset->ngr),"_node_coordinates");
15827       nel = NI_new_data_element("NODE_COORDS", N_Nodes);
15828       NI_set_attribute (nel, "data_type", attname);
15829       SUMA_free(attname); attname = NULL;
15830       NI_add_to_group(dset->ngr, nel);
15831    }
15832    /* Make sure I is sorted */
15833    if (I) {
15834       if (nel->vec_num != 0) {
15835          SUMA_S_Err("Attempting to add I out of order");
15836          SUMA_RETURN(nel);
15837       }
15838       for (ii=1; ii<N_Nodes; ++ii) {
15839          if (I[ii-1]>I[ii]) {
15840             dosort = 1;
15841             break;
15842          }
15843       }
15844       if (dosort) isort = z_dqsort (I, N_Nodes );
15845       if (!SUMA_AddDsetNelCol (  dset, "Gnode Index",
15846                                     SUMA_GNODE_INDEX, (void *)I, NULL, 1)) {
15847             SUMA_SL_Err("Failed to add column");
15848             SUMA_RETURN(nel);
15849        }
15850    } else {
15851       /* I want it, keep things clear and simple */
15852       if (nel->vec_num != 0) {
15853          SUMA_S_Err("Attempting to add I out of order");
15854          SUMA_RETURN(nel);
15855       }
15856       I = (int *)SUMA_calloc(nel->vec_len, sizeof(int));
15857       for (ii=0; ii<nel->vec_len; ++ii) I[ii]=ii;
15858       if (!SUMA_AddDsetNelCol (  dset, "Gnode Index",
15859                                     SUMA_GNODE_INDEX, (void *)I, NULL, 1)) {
15860             SUMA_SL_Err("Failed to add column");
15861             SUMA_RETURN(nel);
15862        }
15863        SUMA_ifree(I);
15864    }
15865 
15866    jump = 1;
15867    if (X && !Y && !Z) {  /* a trick to specify X Y Z with triplets */
15868       jump = 3;
15869       fvxyz  = NULL;
15870       if (isort) {
15871          fvxyz  = SUMA_freorder_triplets(X, isort, nel->vec_len);
15872          X = fvxyz;
15873          isort = 0; /* sorting now done */
15874       }
15875       Y = X + 1;
15876       Z = X + 2;
15877    }
15878 
15879    if (X) {
15880        if (nel->vec_num != 1) {
15881          SUMA_S_Err("Attempting to add X out of order");
15882          SUMA_RETURN(nel);
15883        }
15884        if (isort) {
15885          fv = SUMA_freorder(X, isort, nel->vec_len);
15886          if (!SUMA_AddDsetNelCol (  dset, "Gnode X",
15887                                        SUMA_NODE_X, (void *)fv, NULL, jump)) {
15888                SUMA_SL_Err("Failed to add column");
15889                SUMA_RETURN(nel);
15890           }
15891           SUMA_ifree(fv);
15892        } else {
15893           if (!SUMA_AddDsetNelCol (  dset, "Gnode X",
15894                                        SUMA_NODE_X, (void *)X, NULL, jump)) {
15895                SUMA_SL_Err("Failed to add column");
15896                SUMA_RETURN(nel);
15897           }
15898        }
15899    }
15900    if (Y) {
15901        if (nel->vec_num != 2) {
15902          SUMA_S_Err("Attempting to add Y out of order");
15903          SUMA_RETURN(nel);
15904        }
15905        if (isort) {
15906          fv = SUMA_freorder(Y, isort, nel->vec_len);
15907          if (!SUMA_AddDsetNelCol (  dset, "Gnode Y",
15908                                        SUMA_NODE_Y, (void *)fv, NULL, jump)) {
15909                SUMA_SL_Err("Failed to add column");
15910                SUMA_RETURN(nel);
15911           }
15912           SUMA_ifree(fv);
15913        } else {
15914           if (!SUMA_AddDsetNelCol (  dset, "Gnode Y",
15915                                        SUMA_NODE_Y, (void *)Y, NULL, jump)) {
15916                SUMA_SL_Err("Failed to add column");
15917                SUMA_RETURN(nel);
15918           }
15919        }
15920    }
15921    if (Z) {
15922        if (nel->vec_num != 3) {
15923          SUMA_S_Err("Attempting to add Z out of order");
15924          SUMA_RETURN(nel);
15925        }
15926        if (isort) {
15927          fv = SUMA_freorder(Z, isort, nel->vec_len);
15928          if (!SUMA_AddDsetNelCol (  dset, "Gnode Z",
15929                                        SUMA_NODE_Z, (void *)fv, NULL, jump)) {
15930                SUMA_SL_Err("Failed to add column");
15931                SUMA_RETURN(nel);
15932           }
15933           SUMA_ifree(fv);
15934        } else {
15935           if (!SUMA_AddDsetNelCol (  dset, "Gnode Z",
15936                                        SUMA_NODE_Z, (void *)Z, NULL, jump)) {
15937                SUMA_SL_Err("Failed to add column");
15938                SUMA_RETURN(nel);
15939           }
15940        }
15941    }
15942 
15943    if (!names) {/* Add dummy names */
15944       /* get I back */
15945       if ((ii=SUMA_NI_find_in_cs_string(
15946             NI_get_attribute(nel,"COLMS_LABS"), SUMA_NI_CSS, "Gnode Index"))<0) {
15947          SUMA_LH("Failed to find I?!");
15948       } else {
15949          I = (int *)nel->vec[ii];
15950          names = (char **)SUMA_calloc(nel->vec_len, sizeof(char*));
15951          for (ii=0; ii<nel->vec_len; ++ii) {
15952             names[ii] = (char *)SUMA_calloc(20, sizeof(char));
15953             sprintf(names[ii],"%d", I[ii]);
15954          }
15955       }
15956       SUMA_LH("Adding default gnode labels");
15957       if (!SUMA_AddDsetNelCol (  dset, "Gnode Label",
15958                                  SUMA_NODE_SLABEL, (void *)names, NULL, 1)) {
15959          SUMA_SL_Err("Failed to add names column");
15960          SUMA_RETURN(nel);
15961       }
15962       /* Left here for the lesson:
15963          Do not free names[ii] after adding names as a column
15964                   for (ii=0; ii<nel->vec_len; ++ii) SUMA_ifree(names[ii]); */
15965       SUMA_ifree(names);
15966    } else {  /* Caller's names */
15967       SUMA_LH("Adding gnode labels (%s ... %s)",
15968                names[0], names[nel->vec_len-1]);
15969       if (!SUMA_AddDsetNelCol (  dset, "Gnode Label",
15970                                  SUMA_NODE_SLABEL, (void *)names, NULL, 1)) {
15971          SUMA_SL_Err("Failed to add names column");
15972          SUMA_RETURN(nel);
15973       }
15974    }
15975 
15976 
15977    if (cln) { /* Add group belonging */
15978       SUMA_LH("Adding gnode groups");
15979       if (!SUMA_AddDsetNelCol (dset, "Gnode Group",
15980                                SUMA_GNODE_IGROUP, (void *)cln,NULL, 1)) {
15981          SUMA_SL_Err("Failed to add group column");
15982          SUMA_RETURN(nel);
15983       }
15984       SUMA_LH("Adding gnode group cols R %f..%f, G %f..%f, B %f..%f",
15985             cols[0], cols[3*(nel->vec_len-1)],
15986             cols[1], cols[3*(nel->vec_len-1)+1],
15987             cols[2], cols[3*(nel->vec_len-1)+2]);
15988       if (!SUMA_AddDsetNelCol (dset, "Gnode R",
15989                             SUMA_NODE_R, (void *)cols, NULL, 3)) {
15990          SUMA_SL_Err("Failed to add group column");
15991          SUMA_RETURN(nel);
15992       }
15993       if (!SUMA_AddDsetNelCol (dset, "Gnode G",
15994                             SUMA_NODE_G, (void *)(cols+1), NULL, 3)) {
15995          SUMA_SL_Err("Failed to add group column");
15996          SUMA_RETURN(nel);
15997       }
15998       if (!SUMA_AddDsetNelCol (dset, "Gnode B",
15999                             SUMA_NODE_B, (void *)(cols+2), NULL, 3)) {
16000          SUMA_SL_Err("Failed to add group column");
16001          SUMA_RETURN(nel);
16002       }
16003    }
16004    SUMA_ifree(fvxyz);
16005    SUMA_ifree(isort);
16006 
16007    SUMA_RETURN(nel);
16008 }
16009 
SUMA_ObjectTypeName2ObjectTypeCode(char * cc)16010 SUMA_DO_Types SUMA_ObjectTypeName2ObjectTypeCode(char *cc)
16011 {
16012    static char FuncName[]={"SUMA_ObjectTypeName2ObjectTypeCode"};
16013 
16014    if (!cc) SUMA_RETURN(NOT_SET_type);
16015    if (!strcmp(cc,"WhatTheWhat")) SUMA_RETURN(NOT_SET_type);
16016    if (!strcmp(cc,"NOT_SET_type")) SUMA_RETURN(NOT_SET_type);
16017    if (!strcmp(cc,"not_DO")) SUMA_RETURN(not_DO_type);
16018    if (!strcmp(cc,"Surface")) SUMA_RETURN(SO_type);
16019    if (!strcmp(cc,"Axis")) SUMA_RETURN(AO_type);
16020    if (!strcmp(cc,"ROI_drawn")) SUMA_RETURN(ROIdO_type);
16021    if (!strcmp(cc,"ROI")) SUMA_RETURN(ROIO_type);
16022    if (!strcmp(cc,"GO")) SUMA_RETURN(GO_type);
16023    if (!strcmp(cc,"Line_Segment")) SUMA_RETURN(LS_type);
16024    if (!strcmp(cc,"Node_Based_Line_Segment")) SUMA_RETURN(NBLS_type);
16025    if (!strcmp(cc,"Oriented_Line_Segment")) SUMA_RETURN(OLS_type);
16026    if (!strcmp(cc,"Oriented_Direction")) SUMA_RETURN(ODIR_type);
16027    if (!strcmp(cc,"Direction")) SUMA_RETURN(DIR_type);
16028    if (!strcmp(cc,"Point")) SUMA_RETURN(PNT_type);
16029    if (!strcmp(cc,"Oriented_Node_Based_Line_Segment")) SUMA_RETURN(NBOLS_type);
16030    if (!strcmp(cc,"Node_Based_Vector")) SUMA_RETURN(NBV_type);
16031    if (!strcmp(cc,"Oriented_Node_Based_Vector")) SUMA_RETURN(ONBV_type);
16032    if (!strcmp(cc,"Sphere")) SUMA_RETURN(SP_type);
16033    if (!strcmp(cc,"Node_Based_Sphere")) SUMA_RETURN(NBSP_type);
16034    if (!strcmp(cc,"Plane")) SUMA_RETURN(PL_type);
16035    if (!strcmp(cc,"VO")) SUMA_RETURN(VO_type);
16036    if (!strcmp(cc,"NBT")) SUMA_RETURN(NBT_type);
16037    if (!strcmp(cc,"SBT")) SUMA_RETURN(SBT_type);
16038    if (!strcmp(cc,"GDSET")) SUMA_RETURN(GDSET_type);
16039    if (!strcmp(cc,"CDOM")) SUMA_RETURN(CDOM_type);
16040    if (!strcmp(cc,"ANY_DSET")) SUMA_RETURN(ANY_DSET_type);
16041    if (!strcmp(cc,"MD_DSET")) SUMA_RETURN(MD_DSET_type);
16042    if (!strcmp(cc,"DBT")) SUMA_RETURN(DBT_type);
16043    if (!strcmp(cc,"NIDO")) SUMA_RETURN(NIDO_type);
16044    if (!strcmp(cc,"TRACT")) SUMA_RETURN(TRACT_type);
16045    if (!strcmp(cc,"MASK")) SUMA_RETURN(MASK_type);
16046    if (!strcmp(cc,"GRAPH_LINK")) SUMA_RETURN(GRAPH_LINK_type);
16047    if (!strcmp(cc,"Number_Of_DO_Types")) SUMA_RETURN(N_DO_TYPES);
16048 }
16049 
SUMA_ObjectTypeCode2ObjectTypeName(SUMA_DO_Types dd)16050 const char *SUMA_ObjectTypeCode2ObjectTypeName(SUMA_DO_Types dd)
16051 {
16052    static char FuncName[]={"SUMA_ObjectTypeCode2ObjectTypeName"};
16053    switch (dd) {
16054       case NOT_SET_type:
16055          return("NOT_SET_type");
16056          break;
16057       case not_DO_type:
16058          return("not_DO");
16059          break;
16060       case SO_type:
16061          return("Surface");
16062          break;
16063       case AO_type:
16064          return("Axis");
16065          break;
16066       case ROIdO_type:
16067          return("ROI_drawn");
16068          break;
16069       case ROIO_type:
16070          return("ROI");
16071          break;
16072       case GO_type:
16073          return("GO");
16074          break;
16075       case LS_type:
16076          return("Line_Segment");
16077          break;
16078       case NBLS_type:
16079          return("Node_Based_Line_Segment");
16080          break;
16081       case OLS_type:
16082          return("Oriented_Line_Segment");
16083          break;
16084       case ODIR_type:
16085          return("Oriented_Direction");
16086          break;
16087       case DIR_type:
16088          return("Direction");
16089          break;
16090       case PNT_type:
16091          return("Point");
16092          break;
16093       case NBOLS_type:
16094          return("Oriented_Node_Based_Line_Segment");
16095          break;
16096       case NBV_type:
16097          return("Node_Based_Vector");
16098          break;
16099       case ONBV_type:
16100          return("Oriented_Node_Based_Vector");
16101          break;
16102       case SP_type:
16103          return("Sphere");
16104          break;
16105       case NBSP_type:
16106          return("Node_Based_Sphere");
16107          break;
16108       case PL_type:
16109          return("Plane");
16110          break;
16111       case VO_type:
16112          return("VO");
16113          break;
16114       case NBT_type:
16115          return("NBT");
16116          break;
16117       case SBT_type:
16118          return("SBT");
16119          break;
16120       case GDSET_type:
16121          return("GDSET");
16122          break;
16123       case CDOM_type:
16124          return("CDOM");
16125          break;
16126       case ANY_DSET_type:
16127          return("ANY_DSET");
16128          break;
16129       case MD_DSET_type:
16130          return("MD_DSET");
16131          break;
16132       case DBT_type:
16133          return("DBT");
16134          break;
16135       case NIDO_type:
16136          return("NIDO");
16137          break;
16138       case TRACT_type:
16139          return("TRACT");
16140          break;
16141       case MASK_type:
16142          return("MASK");
16143          break;
16144       case GRAPH_LINK_type:
16145          return("GRAPH_LINK");
16146          break;
16147       case N_DO_TYPES:
16148          return("Number_Of_DO_Types");
16149          break;
16150       default:
16151          return("WhatTheWhat!");
16152    }
16153 }
16154 
16155 /**************** Tract dset functions *************************/
16156 
16157 /* This query goes back to the source all the time,
16158    use SUMA_isTractDset_fast for speed */
SUMA_isTractDset(SUMA_DSET * dset)16159 byte SUMA_isTractDset(SUMA_DSET *dset)
16160 {
16161    static char FuncName[]={"SUMA_isTractDset"};
16162 
16163    SUMA_ENTRY;
16164 
16165    if (!dset || !dset->ngr) SUMA_RETURN(NOPE);
16166 
16167    if (!dset->Aux) { /* create one, always good */
16168       if (!SUMA_Add_Dset_Aux(dset)) {
16169          SUMA_S_Err("Bad news, this should not fail");
16170          SUMA_RETURN(NOPE);
16171       }
16172    }
16173    if (SUMA_isTractDsetNgr(dset->ngr)) {
16174       dset->Aux->isGraph = TRACT_DSET;
16175    }
16176 
16177    SUMA_RETURN(dset->Aux->isGraph == TRACT_DSET);
16178 }
16179 
SUMA_isTractDsetNgr(NI_group * ngr)16180 byte SUMA_isTractDsetNgr(NI_group *ngr)
16181 {
16182    if (!ngr) return(0);
16183    switch (SUMA_Dset_Type(NEL_DSET_TYPE(ngr))) {
16184       case SUMA_TRACT_BUCKET:
16185          return(1);
16186       default:
16187          return(0);
16188    }
16189    return(0);
16190 }
16191 
16192 /**************** CIFTI dset functions *************************/
SUMA_isMD_Dset(SUMA_DSET * dset)16193 byte SUMA_isMD_Dset(SUMA_DSET *dset)
16194 {
16195    static char FuncName[]={"SUMA_isMD_Dset"};
16196 
16197    SUMA_ENTRY;
16198 
16199    if (!dset || !dset->Aux) SUMA_RETURN(NOPE);
16200 
16201    SUMA_RETURN(dset->Aux->isGraph == MD_DSET);  /* hopefully  16 Sep 2015 */
16202 }
16203 
16204 /* This query goes back to the source all the time,
16205    use SUMA_isCIFTIDset_fast for speed
16206    Logic might need revisiting at some point */
SUMA_isCIFTIDset(SUMA_DSET * dset)16207 byte SUMA_isCIFTIDset(SUMA_DSET *dset)
16208 {
16209    static char FuncName[]={"SUMA_isCIFTIDset"};
16210 
16211    SUMA_ENTRY;
16212 
16213    if (!dset) SUMA_RETURN(NOPE);
16214 
16215    if (!dset->Aux) { /* create one, always good */
16216       if (!SUMA_Add_Dset_Aux(dset)) {
16217          SUMA_S_Err("Bad news, this should not fail");
16218          SUMA_RETURN(NOPE);
16219       }
16220    }
16221 
16222    if (dset->Aux->N_doms > 0) { /* no need to to further
16223       	             	       with CIFTI dataset that
16224 			       are elementarized, there is
16225 			       no more ngr, etc.*/
16226       dset->Aux->isGraph = CIFTI_DSET;
16227       SUMA_RETURN(YUP);
16228    }
16229 
16230    if (dset->ngr && SUMA_isCIFTIDsetNgr(dset->ngr)) {
16231       dset->Aux->isGraph = CIFTI_DSET;
16232    }
16233 
16234    SUMA_RETURN(dset->Aux->isGraph == CIFTI_DSET);
16235 }
16236 
SUMA_isCIFTIDsetNgr(NI_group * ngr)16237 byte SUMA_isCIFTIDsetNgr(NI_group *ngr)
16238 {
16239    if (!ngr) return(0);
16240    switch (SUMA_Dset_Type(NEL_DSET_TYPE(ngr))) {
16241       case SUMA_CIFTI_BUCKET:
16242          return(1);
16243       default:
16244          return(0);
16245    }
16246    return(0);
16247 }
16248 
SUMA_CIFTI_Set_Domains(SUMA_DSET * dset,int N_doms,int * dind,int * dindoff,int * dn,SUMA_DO_Types * dtp,char ** dsrcs)16249 SUMA_Boolean SUMA_CIFTI_Set_Domains(SUMA_DSET *dset, int N_doms,
16250                                     int *dind, int *dindoff, int *dn,
16251                                     SUMA_DO_Types *dtp, char **dsrcs)
16252 {
16253    static char FuncName[]={"SUMA_CIFTI_Set_Domains"};
16254    char *str = NULL, buff[500]={""};
16255    int i, k, min, max, imin, imax, sorted, N, *ind=NULL;
16256    SUMA_Boolean LocalHead = NOPE;
16257 
16258    SUMA_ENTRY;
16259 
16260    if (!dset || !dset->inel) {
16261       SUMA_S_Err("dset or dset->inel is NULL");
16262       SUMA_RETURN(NOPE);
16263    }
16264 
16265    NI_SET_INT (dset->inel, "N_Domains", N_doms);
16266    NI_SET_INTv(dset->inel, "Index_Offsets", dindoff, N_doms+1);
16267    NI_SET_INTv(dset->inel, "Domain_N_Data", dn, N_doms); /* total number of
16268                                     nodes, voxels, etc possible in domain.*/
16269    str = NULL;
16270    for (i=0; i<N_doms; ++i) {
16271       str = SUMA_ar_string(
16272                str, (char *)SUMA_ObjectTypeCode2ObjectTypeName(dtp[i]),";",1);
16273    }
16274    NI_SET_STR(dset->inel, "Model_Types", str); SUMA_ifree(str);
16275 
16276 
16277    /* check the indices and set the ranges, location of min and max for
16278       each domain is relative to the full list */
16279    str = NULL;
16280    sorted = 1;
16281    for (i=0; i<N_doms; ++i) {
16282       ind = dind+dindoff[i]; N=dindoff[i+1]-dindoff[i];
16283       min = max = ind[0];
16284       imin = imax = 0;
16285       for (k=0; k<N; ++k) {
16286          if (sorted && k<N-1 && ind[k] >= ind[k+1]) sorted = 0;
16287          if (ind[k] < min) { min = ind[k]; imin = k+dindoff[i]; }
16288          if (ind[k] > max) { max = ind[k]; imax = k+dindoff[i]; }
16289       }
16290       snprintf(buff, 500*sizeof(char),"%d %d %d %d",
16291                      min, max, imin, imax);
16292       str = SUMA_ar_string(str, buff, SUMA_NI_CSS, 1);
16293    }
16294    NI_set_attribute(dset->inel, "COLMS_RANGE", str); SUMA_ifree(str);
16295 
16296    /* domain sources */
16297    str = NULL;
16298    for (i=0; i<N_doms; ++i) {
16299       str = SUMA_ar_string(str, dsrcs[i],";",1);
16300    }
16301    NI_SET_STR(dset->inel, "Domain_Sources", str); SUMA_ifree(str);
16302 
16303    /* Set the sorted flag */
16304    if (sorted) {
16305       NI_set_attribute(dset->inel, "sorted_node_def", "Yes");
16306    } else {
16307       NI_set_attribute(dset->inel, "sorted_node_def", "No");
16308    }
16309 
16310    /* You have yet to put in the indices */
16311    if (!SDSET_NODEINDNUM(dset)) {
16312       NI_add_column_stride ( dset->inel, NI_INT, dind, 1);
16313    } else {
16314       SUMA_LH("Have inel col of %d vals", dset->inel->vec_len);
16315       ind = (int *)(dset->inel->vec[0]);
16316       for (i=0; i<SDSET_VECLEN(dset); ++i) {
16317          ind[i] = dind[i];
16318       }
16319    }
16320 
16321    SUMA_RETURN(NOPE);
16322 }
16323 
SUMA_CIFTI_Free_Doms(SUMA_DSET * dset)16324 SUMA_Boolean SUMA_CIFTI_Free_Doms(SUMA_DSET *dset)
16325 {
16326    static char FuncName[]={"SUMA_CIFTI_Free_Doms"};
16327    int i;
16328    SUMA_DSET *edset = NULL;
16329 
16330    if (!dset || !dset->Aux) return(NOPE);
16331 
16332    if (dset->Aux->doms && dset->Aux->N_doms > 0) {
16333       for (i=0; i<dset->Aux->N_doms; ++i) {
16334          if (dset->Aux->doms[i]) {
16335             SUMA_ifree(dset->Aux->doms[i]->edset_id);
16336 	    SUMA_ifree(dset->Aux->doms[i]->Source);
16337             SUMA_ifree(dset->Aux->doms[i]);
16338          }
16339       }
16340       SUMA_ifree(dset->Aux->doms);
16341    }
16342    dset->Aux->N_doms = -1; dset->Aux->doms = NULL;
16343 
16344    return(YUP);
16345 }
16346 
16347 /* Take dset->ngr->inel domain information and write them into
16348    C-struct fields
16349    \sa  SUMA_CIFTI_NgrFromDomains */
SUMA_CIFTI_DomainsFromNgr(SUMA_DSET * dset,DList * DsetList,int allowreplace,SUMA_DSET ** ret_edset)16350 SUMA_Boolean SUMA_CIFTI_DomainsFromNgr(SUMA_DSET *dset, DList *DsetList,
16351       	             	      	       int allowreplace, SUMA_DSET **ret_edset)
16352 {
16353    static char FuncName[]={"SUMA_CIFTI_DomainsFromNgr"};
16354    double nums[4];
16355    int i, k, ibuff[51], jbuff[51];
16356    char *mtstr=NULL, *rnstr=NULL, *ss=NULL, *dsstr=NULL;
16357    SUMA_DSET *edset=NULL;
16358    SUMA_Boolean LocalHead = NOPE;
16359 
16360    SUMA_ENTRY;
16361 
16362    if (!SUMA_isCIFTIDset(dset) || !dset->Aux || !dset->inel) {
16363       SUMA_S_Err("I'm calling my lawyer");
16364       SUMA_RETURN(NOPE);
16365    }
16366    if (dset->Aux->doms) {
16367       SUMA_S_Note("Have doms already, freeing them but you might not like it"
16368       	          "if reloading a CIFTI in SUMA...");
16369       SUMA_CIFTI_Free_Doms(dset);
16370    }
16371    if (!DsetList && !ret_edset) {
16372       SUMA_S_Err("No way to preserve your edset!");
16373       SUMA_RETURN(NOPE);
16374    }
16375    if (ret_edset && *ret_edset) {
16376       SUMA_S_Err("*ret_edset must be NULL");
16377       SUMA_RETURN(NOPE);
16378    }
16379 
16380    NI_GET_INT(dset->inel, "N_Domains", dset->Aux->N_doms);
16381    if (dset->Aux->N_doms > 50) {
16382       SUMA_S_Err("No setup to deal with so many doms. Fix me");
16383       dset->Aux->N_doms = -1;
16384       SUMA_RETURN(NOPE);
16385    }
16386    SUMA_LH("%d Domains: %s", dset->Aux->N_doms,
16387       	    CNS(NI_get_attribute(dset->inel,"Index_Offsets")));
16388    NI_GET_INTv(dset->inel,"Index_Offsets", ibuff, dset->Aux->N_doms+1, 0);
16389    NI_GET_INTv(dset->inel,"Domain_N_Data", jbuff, dset->Aux->N_doms, 0);
16390 
16391    SUMA_LH("Getting strings");
16392    NI_GET_STR_CP(dset->inel, "Model_Types", mtstr);
16393    NI_GET_STR_CP(dset->inel, "Domain_Sources", dsstr);
16394    NI_GET_STR_CP(dset->inel, "COLMS_RANGE", rnstr);
16395    if (!mtstr || !rnstr || !dsstr) {
16396       SUMA_S_Err("Malformation suspected");
16397       SUMA_RETURN(NOPE);
16398    }
16399 
16400    SUMA_LH("Creating doms");
16401    dset->Aux->doms = (SUMA_DSET_DOMAIN **)SUMA_calloc(
16402                               dset->Aux->N_doms, sizeof(SUMA_DSET_DOMAIN *));
16403    if ((i = SUMA_StringToNum(rnstr, (void *)nums, 4, 2)) !=
16404                                                          4*dset->Aux->N_doms) {
16405       SUMA_SL_Err("Failed to read %d nums from range string %s. Got %d",
16406                   4*dset->Aux->N_doms, rnstr, i);
16407       for (i=0; i<4*dset->Aux->N_doms; ++i) nums[i]=-1;
16408    }
16409    for (i=0; i<dset->Aux->N_doms; ++i) {
16410       dset->Aux->doms[i] = (SUMA_DSET_DOMAIN *)
16411                                  SUMA_calloc(1,sizeof(SUMA_DSET_DOMAIN));
16412       dset->Aux->doms[i]->IndexOffset = ibuff[i];
16413       dset->Aux->doms[i]->IndexCount  = ibuff[i+1]-ibuff[i];
16414       dset->Aux->doms[i]->Max_N_Data  = jbuff[i];
16415       ss = SUMA_Get_Sub_String(mtstr,SUMA_NI_CSS, i);
16416       dset->Aux->doms[i]->ModelType   = SUMA_ObjectTypeName2ObjectTypeCode(ss);
16417       SUMA_ifree(ss);
16418       ss = SUMA_Get_Sub_String(dsstr,SUMA_NI_CSS, i);
16419       dset->Aux->doms[i]->Source = SUMA_copy_string(ss);
16420       SUMA_ifree(ss);
16421       for (k=0; k<4; ++k) dset->Aux->doms[i]->Range[k] = nums[4*i+k];
16422       /* aaaand the elementary dset */
16423       edset = SUMA_CIFTI_2_edset(dset, i, NULL, DsetList, allowreplace);
16424       dset->Aux->doms[i]->edset_id = SUMA_copy_string(SDSET_ID(edset));
16425       if (ret_edset) *ret_edset = edset;
16426       edset = NULL;
16427    }
16428 
16429    /* just empty the contents of dnel and inel to save space
16430       but keep the metadata to keep dataset somewhat viable,
16431       as we will be inserting the multi domain dataset into the
16432       dataset list */
16433    SUMA_CIFTI_free_MD_data(dset);
16434 
16435    SUMA_RETURN(YUP);
16436 }
16437 
16438 /* A function to free the bulk of data in a CIFTI multi domain
16439 dataset. Do this to save memory, after having created the elementary
16440 datasets */
SUMA_CIFTI_free_MD_data(SUMA_DSET * dset)16441 SUMA_Boolean SUMA_CIFTI_free_MD_data(SUMA_DSET *dset)
16442 {
16443    static char FuncName[]={"SUMA_CIFTI_free_MD_data"};
16444    int i, k;
16445    NI_element *nel=NULL;
16446 
16447    SUMA_ENTRY;
16448 
16449    /* assuming the bulk of content is in dnel, inel, etc */
16450    for (k=0; k<4; ++k) {
16451            if (k==0) nel = dset->dnel;
16452       else if (k==1) nel = dset->inel;
16453       else if (k==2) nel = dset->pdnel;
16454       else if (k==3) nel = dset->pinel;
16455       if (nel) {
16456       	 for (i=0; i<nel->vec_num; ++i) {
16457       	    NI_remove_column(nel,-1);
16458       	 }
16459       }
16460    }
16461 
16462    SUMA_RETURN(YUP);
16463 }
16464 
16465 /* Create a single domain (elementary) dataset from a multi domain (CIFTI) dataset.
16466 Will need something to go the other way around, from a collection of
16467 elementary dataset back to the MD dataset */
SUMA_CIFTI_2_edset(SUMA_DSET * dset,int i,byte * colmask,DList * DsetList,int allowreplace)16468 SUMA_DSET *SUMA_CIFTI_2_edset(SUMA_DSET *dset, int i, byte *colmask,
16469       	             	      DList *DsetList, int allowreplace)
16470 {
16471    static char FuncName[]={"SUMA_CIFTI_2_edset"};
16472    SUMA_DSET *edset = NULL;
16473    byte *rowmask = NULL;
16474    char *lbl=NULL, sbuf[64]={""};
16475    SUMA_Boolean LocalHead = NOPE;
16476 
16477    SUMA_ENTRY;
16478 
16479    if (!dset || !dset->Aux || !dset->Aux->doms ||
16480        dset->Aux->N_doms <= i) {
16481       SUMA_S_Err("Bad input to  SUMA_CIFTI_2_edset");
16482       SUMA_RETURN(edset);
16483    }
16484    if (!(rowmask = (byte *)SUMA_calloc(SDSET_VECALLOC(dset), sizeof(byte)))) {
16485       SUMA_S_Err("Failed to create rowmask");
16486       SUMA_RETURN(edset);
16487    }
16488    SUMA_LH("Setting mask for %d rows at offset %d",
16489       	   dset->Aux->doms[i]->IndexCount, dset->Aux->doms[i]->IndexOffset);
16490    memset(rowmask+dset->Aux->doms[i]->IndexOffset, 1,
16491       	  dset->Aux->doms[i]->IndexCount*sizeof(byte));
16492 
16493    if (!(edset = SUMA_MaskedCopyofDset( dset, rowmask, colmask, 1, 1))) {
16494       SUMA_S_Err("Failed to extract edset");
16495    } else {
16496       /* Label in peculiar fashion */
16497       sprintf(sbuf, "ED%02d:", i);
16498       /* change filename */
16499       lbl = SUMA_ModifyName(SUMA_sdset_filename(dset), "prepend", sbuf, NULL);
16500       SUMA_LH("Filename now %s", lbl);
16501       NI_set_attribute(edset->ngr, "filename", lbl);
16502       if (LocalHead) {
16503       	 SUMA_LH("(not) Writing out elementary dset %s for debugging", lbl);
16504          /* Use the 'no suma' version.  14 Aug 2015 [rickr] */
16505       	 SUMA_WriteDset_ns(lbl, edset, SUMA_ASCII_NIML, 1,1);
16506       }
16507       SUMA_ifree(lbl);
16508       /* recreate the ID to reflect the filename */
16509       lbl = UNIQ_hashcode(NI_get_attribute(edset->ngr, "filename"));
16510       NI_set_attribute(edset->ngr, "self_idcode", lbl); SUMA_ifree(lbl);
16511 
16512       /* and cute label */
16513       lbl = SUMA_ar_string(sbuf, SUMA_sdset_label(dset),"",0);
16514       SUMA_LabelDset(edset, lbl); SUMA_ifree(lbl);
16515 
16516       /* Put a reference to the multi-domain source */
16517       NI_set_attribute(edset->ngr,"MD_parent_ID", SDSET_ID(dset));
16518       NI_set_attribute(edset->ngr,"MD_parent_label", SDSET_LABEL(dset));
16519       NI_SET_INT(edset->ngr,"MD_parent_subdomain_index", i);
16520    }
16521    SUMA_ifree(rowmask);
16522 
16523    SUMA_LH("Elementary dset (%s, id %s) has pointer %p \n",
16524             SDSET_LABEL(edset), SDSET_ID(edset), edset);
16525 
16526    if (DsetList) {
16527       if (!SUMA_InsertDsetPointer(  &edset, DsetList, allowreplace)) {
16528 	 SUMA_SLP_Err("Failed to add new dset to list");
16529 	 /* is there not a function to replace a dset yet? */
16530 	 SUMA_FreeDset(edset); edset = NULL;
16531 	 SUMA_RETURN(NULL);
16532       }
16533       SUMA_LH("Now dset (%s, id %s) is  pointer %p\n",
16534       	       SDSET_LABEL(edset), SDSET_ID(edset), edset);
16535    }
16536 
16537    SUMA_RETURN(edset);
16538 }
16539 
16540 /* Take C-struct domain information and write them into
16541    dset->ngr->inel element
16542    \sa SUMA_CIFTI_DomainsFromNgr */
SUMA_CIFTI_NgrFromDomains(SUMA_DSET * dset)16543 SUMA_Boolean SUMA_CIFTI_NgrFromDomains(SUMA_DSET *dset)
16544 {
16545    static char FuncName[]={"SUMA_CIFTI_NgrFromDomains"};
16546    int dindoff[51], dn[51], i;
16547    char *dsrcs[51];
16548    SUMA_DO_Types dtp[51];
16549 
16550    if (!SUMA_isCIFTIDset(dset) || !dset->Aux || !dset->Aux->doms) {
16551       SUMA_S_Err("I'm calling my mom!");
16552       SUMA_RETURN(NOPE);
16553    }
16554    SUMA_S_Warn("Function not ready to take elementary datasets and recreate the"
16555       	       " multidomain version. See SUMA_CIFTI_2_Edset() ");
16556    if (dset->Aux->N_doms > 50) {
16557       SUMA_S_Err("No setup to deal with so many doms. Fix me");
16558       SUMA_RETURN(NOPE);
16559    }
16560    for (i=1; i<dset->Aux->N_doms; ++i) {
16561       dindoff[i] = dset->Aux->doms[i]->IndexOffset;
16562       dn[i] = dset->Aux->doms[i]->Max_N_Data;
16563       dtp[i] = dset->Aux->doms[i]->ModelType;
16564       dsrcs[i] = dset->Aux->doms[i]->Source;
16565    }
16566    SUMA_CIFTI_Set_Domains(dset, dset->Aux->N_doms, SDSET_NODE_INDEX_COL(dset),
16567                           dindoff, dn, dtp, dsrcs);
16568 
16569    SUMA_RETURN(YUP);
16570 }
16571 
16572