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