1 /* This should always run even when compiled WITHOUT SUMA_COMPILED */
2 
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <assert.h>
6 #include <string.h>
7 #include <sys/time.h>
8 #include <math.h>
9 #include "mrilib.h"
10 #include "niml.h"
11 #include "../niml/niml_private.h"
12 #include "xutil.h"
13 
14 
15 #include "SUMA_suma.h"
16 
usage_Test_DSET_IO()17 void usage_Test_DSET_IO ()
18 
19   {/*Usage*/
20           char *sb=NULL;
21           sb = SUMA_help_basics();
22           printf ("\n"
23                   "Usage:  \n"
24                   "%s"
25                   "\n", sb);
26           SUMA_free(sb);
27           exit (0);
28   }/*Usage*/
29 
30 /* Create a toy CIFTI dataset that is made up of two surfaces isotopic with the surface named in sdomain and the volume grid in vdomain */
SUMA_Create_Fake_CIFTI(char * sdomain0,char * sdomain1,char * vdomain)31 SUMA_DSET *SUMA_Create_Fake_CIFTI(char *sdomain0, char *sdomain1, char *vdomain)
32 {
33    static char FuncName[]={"SUMA_Create_Fake_CIFTI"};
34    SUMA_DSET *sdset = NULL;
35    SUMA_SurfaceObject *SO0 = NULL, *SO1 = NULL;
36    THD_3dim_dataset *vdset = NULL;
37    byte *mask;
38    int N_mask, i, k, *dind=NULL, *dmaxind, *ind=NULL, *IndOffset=NULL;
39    float *v1=NULL, *v2=NULL, *fv=NULL;
40    SUMA_DO_Types *dtp=NULL;
41    char **dsstr=NULL;
42    SUMA_Boolean LocalHead = YUP;
43 
44    /*
45       Define indices for which there is some data on ld3, assume for left hemi
46       For convenience, the data values at these nodes will be generated to be
47       some silly version of the indices themselves.
48    */
49    int indLeft[] = {57, 58, 40, 39, 52, 53, 59, 81, 45, 47, 48, 49, 21};
50    int N_indLeft = 13;
51    /* Ditto for the right hemisphere.*/
52    int indRight[] = {30, 30, 32, 80, 88, 11, 90, 35, 36, 29 };
53    int N_indRight = 10;
54    int N_Alloc;
55 
56    SUMA_ENTRY;
57 
58    /* Hard code the domains, no time to get fancy here */
59    if (!sdomain0) sdomain0 = "lh:MNI_N27:ld20:smoothwm";
60    if (!sdomain1) sdomain1 = "rh:MNI_N27:ld20:smoothwm";
61    if (!vdomain) vdomain = "ciftivolmsk+tlrc.HEAD";
62 
63    /* Load the domains */
64 
65    if (!(SO0 = SUMA_Load_Surface_Object_Wrapper(sdomain0, NULL, NULL,
66                                          SUMA_PREDEFINED, SUMA_FF_NOT_SPECIFIED,
67                                          NULL, 2))) {
68       SUMA_S_Err("Failed to load SO0 %s", sdomain0);
69       SUMA_RETURN(NULL);
70    }
71 
72    if (!(SO1 = SUMA_Load_Surface_Object_Wrapper(sdomain1, NULL, NULL,
73                                          SUMA_PREDEFINED, SUMA_FF_NOT_SPECIFIED,
74                                          NULL, 2))) {
75       SUMA_S_Err("Failed to load SO1 %s", sdomain1);
76       SUMA_RETURN(NULL);
77    }
78 
79    if (!(vdset = THD_open_dataset(vdomain))) {
80       SUMA_S_Err("Failed to load vdset %s", vdomain);
81       SUMA_Free_Surface_Object(SO0); SO0 = NULL;
82       SUMA_Free_Surface_Object(SO1); SO1 = NULL;
83       SUMA_RETURN(NULL);
84    }
85    mask = THD_makemask( vdset , 0 , 1.0, -1.0 );
86    N_mask = THD_countmask(DSET_NVOX(vdset), mask);
87    fv = THD_extract_to_float ( 0, vdset);
88 
89    /* Number of entries, we assume this is not a full dataset */
90    N_Alloc = N_indLeft + N_indRight + N_mask;
91 
92 
93    /* Create the index column and some data */
94    SUMA_S_Warn("Check what is to be preserved in output dset and free the rest");
95    IndOffset = (int *)SUMA_calloc(3+1,sizeof(int));
96    dmaxind = (int *)SUMA_calloc(3,sizeof(int));
97    dsstr = (char **)SUMA_calloc(3, sizeof(char *));
98    dtp = (SUMA_DO_Types *)SUMA_calloc(3,sizeof(SUMA_DO_Types));
99    /* This is the domain index vector: dind[k] is the datum index of row k on
100    domain(k). This means that you could have duplicate indices whereby
101    dind[k1] == dind[k2], but only if domain(k1) != domain(k2).
102    For surface-only datasets, you could not have duplicate indices because
103    the dataset was defined over one domain only. To make sure the distinction
104    is clear in the code, I will create a new with MD in the name for
105    Multi Domain*/
106    dind = (int *)SUMA_calloc(N_Alloc, sizeof(int));
107    v1 = (float *)SUMA_calloc(N_Alloc, sizeof(float));
108    v2 = (float *)SUMA_calloc(N_Alloc, sizeof(float));
109 
110    IndOffset[0] = 0;
111    dmaxind[0] = SO0->N_Node;
112    dsstr[0] = SUMA_copy_string(sdomain0);
113    dtp[0] = SO_type;
114    k = 0;
115    i = 0;
116    while (i < N_indLeft) { /* Think of this as CIFTI brain model */
117       dind[k] = indLeft[i];
118       v1[k] = cos(i/300.0);
119       v2[k] = sin(i/300.0);
120       ++k; ++i;
121    }
122    IndOffset[1] = IndOffset[0]+N_indLeft;
123    dmaxind[1] = SO1->N_Node;
124    dsstr[1] = SUMA_copy_string(sdomain1);
125    dtp[1] = SO_type;
126    i = 0;
127    while (i < N_indRight) {
128       dind[k] = indRight[i];
129       v1[k] = sin(i/300.0);
130       v2[k] = cos(i/300.0);
131       ++k; ++i;
132    }
133    IndOffset[2] = IndOffset[1]+N_indRight;
134    dmaxind[2] = DSET_NVOX(vdset);
135    dsstr[2] = SUMA_copy_string(vdomain);
136    dtp[2] = VO_type;
137    i = 0;
138    while (i < DSET_NVOX(vdset)) {
139       if (mask[i]) {
140          dind[k] = i;
141          v1[k] = fv[i];
142          v2[k] = k-IndOffset[2];
143          ++k;
144       }
145       ++i;
146    }
147    IndOffset[3] = IndOffset[2]+N_mask; /* for convenience, always create the final unreachable index */
148 
149 
150    /* Put the dataset together */
151    sdset = SUMA_CreateDsetPointer( "cifti_toy",
152                                   SUMA_CIFTI_BUCKET,
153                                   NULL,
154                                   NULL,       /* no domain str specified */
155                                   N_Alloc    /* Number of nodes allocated for */
156                                     );
157    /* Setup the CIFTI domains */
158    SUMA_CIFTI_Set_Domains(sdset, 3, dind, IndOffset, dmaxind, dtp, dsstr);
159 
160    if (!SUMA_AddDsetNelCol (sdset, "Need",
161                                   SUMA_NODE_FLOAT, (void *)v1, NULL ,1)) {
162       SUMA_S_Err("Failed in SUMA_AddDsetNelCol");
163    }
164 
165    if (!SUMA_AddDsetNelCol (sdset, "Coffee",
166                                   SUMA_NODE_FLOAT, (void *)v2, NULL ,1)) {
167       SUMA_S_Err("Failed in SUMA_AddDsetNelCol");
168    }
169 
170    SUMA_Free_Surface_Object(SO0); SO0 = NULL;
171    SUMA_Free_Surface_Object(SO1); SO1 = NULL;
172    DSET_delete(vdset);
173    SUMA_ifree(v1); SUMA_ifree(v2); SUMA_ifree(dind);
174    SUMA_ifree(IndOffset); SUMA_ifree(dmaxind); SUMA_ifree(dtp);
175    for (i=0; i<3; ++i) SUMA_ifree(dsstr[i]);
176    SUMA_ifree(dsstr);
177    SUMA_ifree(mask);
178    SUMA_ifree(fv);
179 
180    SUMA_RETURN(sdset);
181 }
182 
183 
main(int argc,char * argv[])184 int main (int argc,char *argv[])
185 {/* Main */
186    static char FuncName[]={"SUMA_TestDsetIO"};
187    int *NodeDef=NULL;
188    byte *maskrow, *maskcol;
189    int i, i3, N_NodeDef, N_Alloc, flg;
190    float *r=NULL, *g=NULL, *b=NULL, *rgb=NULL;
191    char stmp[500], idcode[50], **s, *si, *OutName = NULL;
192    NI_element *nel=NULL;
193    NI_stream ns;
194    int found = 0, NoStride = 0;
195    byte *bt=NULL;
196    SUMA_DSET * dset = NULL, *ndset=NULL, *cdset = NULL;
197    SUMA_Boolean LocalHead = NOPE;
198 
199    SUMA_STANDALONE_INIT;
200    SUMA_mainENTRY;
201 
202 
203    SUMA_LH("Creating CIFTI toy");
204    if (!(cdset = SUMA_Create_Fake_CIFTI(NULL, NULL, NULL))) {
205       SUMA_S_Err("Failed to create fake CIFTI");
206       exit(1);
207    }
208    SUMA_WriteDset_eng("ToyCifti.niml.dset", cdset, SUMA_ASCII_NIML, 1, 1, 1);
209    SUMA_FreeDset(cdset); cdset = NULL;
210 
211    SUMA_LH("Creating Surface Data ...");
212    /* Create some sample data*/
213       /* let us create some colors to go on each node */
214       N_Alloc = 50;
215       NodeDef = (int *)SUMA_malloc(N_Alloc * sizeof(int));
216       r = (float *)SUMA_malloc(N_Alloc * sizeof(float));
217       g = (float *)SUMA_malloc(N_Alloc * sizeof(float));
218       b = (float *)SUMA_malloc(N_Alloc * sizeof(float));
219       bt = (byte *)SUMA_malloc(N_Alloc * sizeof(byte));
220       s = (char **)SUMA_malloc(N_Alloc * sizeof(char *));
221       maskrow = (byte *)SUMA_malloc(N_Alloc * sizeof(byte));
222       maskcol = (byte *)SUMA_malloc(10*sizeof(byte));
223       for (i=0; i<10; ++i) {
224          if (i==1 || i == 3) maskcol[i]=0;
225          else maskcol[i] = 1;
226       }
227       N_NodeDef = N_Alloc;
228       for (i=0; i<N_NodeDef; ++i) {
229          NodeDef[i] = i;
230          r[i] = sin((float)i/N_NodeDef*5);
231          g[i] = sin((float)i/N_NodeDef*10);
232          b[i] = cos((float)i/N_NodeDef*7);
233          bt[i] = (byte)(4*b[i]);
234          sprintf(stmp,"teststr_%d", i);
235          s[i] = SUMA_copy_string(stmp);
236          if (i==3 || i== 7 || i==33) maskrow[i] = 1; else maskrow[i]=0;
237       }
238       /* what if you had a vector of say, triplets */
239       rgb = (float *)SUMA_malloc(3 * N_Alloc * sizeof(float));
240       for (i=0; i<N_NodeDef; ++i) {
241          i3 = 3*i;
242          rgb[i3] = r[i];
243          rgb[i3+1] = g[i];
244          rgb[i3+2] = b[i];
245       }
246 
247   {
248       float *xc, *de, *amp;
249       int dof;
250       float par[3];
251       /* store some statistics */
252       xc = (float *)SUMA_malloc(N_Alloc * sizeof(float));
253       de = (float *)SUMA_malloc(N_Alloc * sizeof(float));
254       amp = (float *)SUMA_malloc(N_Alloc * sizeof(float));
255       for (i=0; i<N_NodeDef; ++i) {
256          xc[i] = rand()%1000/1000.0 * 1.0;
257          de[i] = rand()%1000/1000.0 * 30;
258          amp[i] = rand()%1000/1000.0 * 5.0;
259       }
260 
261       SUMA_LH("Creating dset pointer");
262       dset = SUMA_CreateDsetPointer(
263                                     "ExpandingRing_ResponseDelay",         /* some label */
264                                     SUMA_NODE_BUCKET,                /* mix and match */
265                                     NULL,    /* no idcode, let the function create one from the filename*/
266                                     NULL,       /* no domain str specified */
267                                     N_Alloc    /* Number of nodes allocated for */
268                                     ); /* DO NOT free dset, if it is stored in DsetList */
269       #ifdef SUMA_COMPILED
270       SUMA_LH("inserting dset pointer into list");
271       if (!SUMA_InsertDsetPointer(&dset, SUMAg_CF->DsetList,0)) {
272          SUMA_SL_Err("Failed to insert dset into list");
273          exit(1);
274       }
275       #endif
276          /* form the dataset */
277    SUMA_LH("Adding stat NodeDef column ...");
278    if (!SUMA_AddDsetNelCol (   dset, /* the famed nel */
279                            "Node Indices",
280                            SUMA_NODE_INDEX, /* the column's type (description),
281                                                one of SUMA_COL_TYPE */
282                            (void *)NodeDef, /* column pointer p, here it is
283                                              the list of node indices */
284                            NULL  /* that's an optional structure containing
285                                     attributes of the added column.
286                                     Not used at the moment */
287                            ,1 /* stride, useful when you need to copy a column
288                                  from a multiplexed vector. Say you have in p
289                                  [rgb rgb rgb rgb], to set the g column you
290                                  send in p+1 for the column pointer and a stride
291                                  of 3 */
292                            )) {
293          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
294          exit(1);
295       }
296 
297       SUMA_LH("Adding stat other columns...");
298          par[0] = 120; par[1] = 2; par[2] = 2;
299          if (!SUMA_AddDsetNelCol (dset, "XcorrCoef",
300                                   SUMA_NODE_XCORR, (void *)xc, (void *)par ,1)) {
301             fprintf (stderr,
302                      "Error  %s:\nFailed in SUMA_AddDsetNelCol", FuncName);
303             exit(1);
304          }
305 
306          if (!SUMA_AddDsetNelCol (dset, "Delay",
307                                   SUMA_NODE_FLOAT, (void *)de, NULL ,1)) {
308             fprintf (stderr,
309                      "Error  %s:\nFailed in SUMA_AddDsetNelCol", FuncName);
310             exit(1);
311          }
312 
313          if (!SUMA_AddDsetNelCol (dset, "Amplitude", SUMA_NODE_FLOAT, (void *)amp, NULL ,1)) {
314             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddDsetNelCol", FuncName);
315             exit(1);
316          }
317       SUMA_LH("History note");
318       if (!SUMA_AddNgrHist(dset->ngr, FuncName, argc, argv)) {
319          SUMA_SL_Err("History addition failed.");
320          exit(1);
321       }
322       #ifdef SUMA_COMPILED
323       OutName = SUMA_WriteDset_s ("SampleDset", dset, SUMA_ASCII_NIML, 1, 1);
324       #else
325       OutName = SUMA_WriteDset_ns ("SampleDset", dset, SUMA_ASCII_NIML, 1, 1);
326       #endif
327       if (!OutName) {
328          SUMA_SL_Err("Write Failed.");
329       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
330          SUMA_free(OutName); OutName = NULL;
331       }
332 
333       #ifdef SUMA_COMPILED
334       /* Now create a new dataset nel
335       no need to worry about loosing previous dset because it is in
336       SUMAg_CF->DsetList*/
337       #else
338       /* free dset by hand */
339       SUMA_LH("Freeing datasets ...");
340       if (dset) SUMA_FreeDset((void *)dset);
341       dset = NULL;
342       #endif
343 
344    }
345    SUMA_LH("Creating dset pointer");
346    dset = SUMA_CreateDsetPointer(
347                                  "SomethingLikeFileName",         /* usually the filename */
348                                  SUMA_NODE_BUCKET,                /* mix and match */
349                                  NULL,    /* no idcode, let the function create one from the filename*/
350                                  NULL,       /* no domain str specified */
351                                  N_Alloc    /* Number of nodes allocated for */
352                                  ); /* DO NOT free dset, it is store in DsetList */
353    #ifdef SUMA_COMPILED
354    SUMA_LH("inserting dset pointer into list");
355    if (!SUMA_InsertDsetPointer(&dset, SUMAg_CF->DsetList,0)) {
356       SUMA_SL_Err("Failed to insert dset into list");
357       exit(1);
358    }
359    #endif
360 
361    /* form the dataset */
362    SUMA_LH("Adding NodeDef column ...");
363    if (!SUMA_AddDsetNelCol (   dset, /* the famed nel */
364                            "le Node Def",
365                            SUMA_NODE_INDEX, /* the column's type (description),
366                                                one of SUMA_COL_TYPE */
367                            (void *)NodeDef, /* column pointer p, here it is
368                                              the list of node indices */
369                            NULL  /* that's an optional structure containing
370                                     attributes of the added column.
371                                     Not used at the moment */
372                            ,1 /* stride, useful when you need to copy a column
373                                  from a multiplexed vector. Say you have in p
374                                  [rgb rgb rgb rgb], to set the g column you
375                                  send in p+1 for the column pointer and a stride
376                                  of 3 */
377                            )) {
378          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
379          exit(1);
380       }
381 
382       SUMA_LH("Adding other columns...");
383       NoStride = 0;
384       if (NoStride) {
385          /* insert separate r, g and b column */
386          if (!SUMA_AddDsetNelCol (dset, "Le R", SUMA_NODE_R, (void *)r, NULL ,1)) {
387             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
388             exit(1);
389          }
390 
391          if (!SUMA_AddDsetNelCol (dset, "Le G", SUMA_NODE_G, (void *)g, NULL ,1)) {
392             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
393             exit(1);
394          }
395 
396          if (!SUMA_AddDsetNelCol (dset, "Le B", SUMA_NODE_B, (void *)b, NULL ,1)) {
397             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
398             exit(1);
399          }
400       } else {
401          /* insert from multiplexed rgb vector */
402          if (!SUMA_AddDsetNelCol (dset, "le R", SUMA_NODE_R, (void *)rgb, NULL ,3 )) {
403             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
404             exit(1);
405          }
406 
407          if (!SUMA_AddDsetNelCol (dset, "Le G", SUMA_NODE_G, (void *)(rgb+1), NULL ,3)) {
408             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
409             exit(1);
410          }
411 
412          if (!SUMA_AddDsetNelCol (dset, "Le B", SUMA_NODE_B, (void *)(rgb+2), NULL ,3)) {
413             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
414             exit(1);
415          }
416          #if 0
417          SUMA_LH("Testing insert column ...");
418          /* Test NI_inset_column_stride here please */
419          if (!SUMA_InsertDsetNelCol (dset, "Le G2", SUMA_NODE_G, (void *)(rgb+1), NULL ,3, 0)) {
420             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
421             exit(1);
422          }
423          #endif
424       }
425       { int suc; SUMA_LH("Where are the attributes?"); NEL_WRITE_TX(dset->ngr,"fd:1",suc); }
426       /* add the byte column, just to check multi type nightmares */
427       if (!SUMA_AddDsetNelCol (dset, "Le byte moi", SUMA_NODE_BYTE, (void *)bt, NULL ,1)) {
428             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
429             exit(1);
430       }
431 
432 
433       SUMA_LH("Testing write ops before adding string columns ...");
434       /* before adding a string column ... */
435       #ifdef SUMA_COMPILED
436       OutName = SUMA_WriteDset_s ("Test_write_all_num", dset, SUMA_1D, 1, 1);
437       #else
438       OutName = SUMA_WriteDset_ns ("Test_write_all_num", dset, SUMA_1D, 1, 1);
439       #endif
440 
441       if (!OutName) {
442          SUMA_SL_Err("Write Failed.");
443       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
444          SUMA_free(OutName); OutName = NULL;
445       }
446 
447       #ifdef SUMA_COMPILED
448       OutName = SUMA_WriteDset_s ("Test_writebi_all_num", dset, SUMA_BINARY_NIML, 1, 1);
449       #else
450       OutName = SUMA_WriteDset_ns ("Test_writebi_all_num", dset, SUMA_BINARY_NIML, 1, 1);
451       #endif
452       if (!OutName) {
453          SUMA_SL_Err("Write Failed.");
454       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
455          SUMA_free(OutName); OutName = NULL;
456       }
457 
458       #ifdef SUMA_COMPILED
459       OutName = SUMA_WriteDset_s ("Test_writeas_all_num", dset, SUMA_ASCII_NIML, 1, 1);
460       #else
461       OutName = SUMA_WriteDset_ns ("Test_writeas_all_num", dset, SUMA_ASCII_NIML, 1, 1);
462       #endif
463       if (!OutName) {
464          SUMA_SL_Err("Write Failed.");
465       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
466          SUMA_free(OutName); OutName = NULL;
467       }
468 
469       /* Now shuffle some columns (then put them back) */
470       SUMA_S_Note("NOTE THAT SHUFFLING here does not take care of attributes inside dset, but only dnel");
471       NI_move_column(dset->dnel, -1, 2);
472       SUMA_ShowNel(dset->dnel);
473       #ifdef SUMA_COMPILED
474       OutName = SUMA_WriteDset_s ("Test_writeas_all_shuff_num", dset, SUMA_ASCII_NIML, 1, 1);
475       #else
476       OutName = SUMA_WriteDset_ns ("Test_writeas_all_shuff_num", dset, SUMA_ASCII_NIML, 1, 1);
477       #endif
478       NI_move_column(dset->dnel, 2, -1);
479       SUMA_ShowNel(dset->dnel);
480 
481       /* zero out some columns and test operations */
482       SUMA_LH("Trying masking operations");
483       ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 1, 0);
484       SUMA_LH("Done");
485       /* try also:
486          ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 0, 1);
487          ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 0, 0);
488          ndset = SUMA_MaskedCopyofDset(dset, maskrow, NULL, 1, 0);
489          ndset = SUMA_MaskedCopyofDset(dset, NULL, NULL, 1, 0);
490          ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 1, 0);
491       */
492       if (!ndset) {
493          SUMA_SL_Err("Failed in SUMA_MaskedCopyofDset");
494       } else {
495          #ifdef SUMA_COMPILED
496          OutName = SUMA_WriteDset_s ("Test_writeas_MaskedCopy_num", ndset, SUMA_ASCII_NIML, 1, 1);
497          #else
498          OutName = SUMA_WriteDset_ns ("Test_writeas_MaskedCopy_num", ndset, SUMA_ASCII_NIML, 1, 1);
499          #endif
500          if (!OutName) {
501             SUMA_SL_Err("Write Failed.");
502          } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
503             SUMA_free(OutName); OutName = NULL;
504          }
505          SUMA_free(ndset); ndset = NULL;
506       }
507 
508       SUMA_LH("Adding a string column");
509       /* add a string column, just for kicks ..*/
510       if (!SUMA_AddDsetNelCol (dset, "la string", SUMA_NODE_STRING, (void *)s, NULL, 1)) {
511          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
512          exit(1);
513       }
514 
515       /* now try to create a masked copy, this should fail */
516       fprintf (stderr,"%s: Attempting to mask a not all numeric dset, this should fail\n", FuncName);
517       ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 1, 0);
518       if (ndset) {
519          fprintf (stderr,"Error  %s:\nWhat the hell? This should not be supported.", FuncName);
520          exit(1);
521       }else{
522          fprintf (stderr,"%s: Good, failed.\n", FuncName);
523       }
524       /* after adding a string column ... */
525       SUMA_LH("Writing datasets ...");
526       #ifdef SUMA_COMPILED
527       OutName = SUMA_WriteDset_s ("Test_writeas", dset, SUMA_ASCII_NIML, 1, 1);
528       #else
529       OutName = SUMA_WriteDset_ns ("Test_writeas", dset, SUMA_ASCII_NIML, 1, 1);
530       #endif
531       if (!OutName) {
532          SUMA_SL_Err("Write Failed.");
533       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
534          SUMA_free(OutName); OutName = NULL;
535       }
536 
537       #ifdef SUMA_COMPILED
538       OutName = SUMA_WriteDset_s ("Test_writebi", dset, SUMA_BINARY_NIML, 1, 1);
539       #else
540       OutName = SUMA_WriteDset_ns ("Test_writebi", dset, SUMA_BINARY_NIML, 1, 1);
541       #endif
542 
543       if (!OutName) {
544          SUMA_SL_Err("Write Failed.");
545       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
546          SUMA_free(OutName); OutName = NULL;
547       }
548 
549       SUMA_LH("Writing to 1D a dataset that is not all numbers.\nThis should fail.\n");
550       #ifdef SUMA_COMPILED
551       OutName = SUMA_WriteDset_s ("Test_write", dset, SUMA_1D, 1, 1);
552       #else
553       OutName = SUMA_WriteDset_ns ("Test_write", dset, SUMA_1D, 1, 1);
554       #endif
555       if (!OutName) {
556          SUMA_SL_Err("Write Failed.");
557       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName);
558          SUMA_free(OutName); OutName = NULL;
559       }
560 
561 
562 
563 
564       /* How about loading some data */
565       #ifdef SUMA_COMPILED
566       /* Now create a new dataset nel
567       no need to worry about loosing previous dset because it is in
568       SUMAg_CF->DsetList*/
569       #else
570       /* free dset by hand */
571       SUMA_LH("Freeing datasets ...");
572       if (dset) SUMA_FreeDset((void *)dset);
573       dset = NULL;
574       #endif
575 
576       SUMA_LH("Fresh dataset ...");
577       dset = SUMA_NewDsetPointer();
578       SUMA_LH("Reading dataset ...");
579       DSET_READ(dset, "file:Test_writebi.niml.dset"); if (!dset->ngr) exit(1);
580       /* insert the baby into the list */
581 
582       #ifdef SUMA_COMPILED
583       SUMA_LH("Inserting newly read element into list\n");
584       if (!SUMA_InsertDsetPointer(&dset, SUMAg_CF->DsetList, 0)) {
585          char *newid = NULL;
586          SUMA_SL_Err("Failed to insert dset into list");
587          /* Now change the idcode of that baby */
588          newid = UNIQ_hashcode(SDSET_ID(dset));
589          NI_set_attribute(dset->dnel, "self_idcode", newid); SUMA_free(newid);
590          SUMA_LH("Trying to insert dset with a new id ");
591          if (!SUMA_InsertDsetPointer(&dset, SUMAg_CF->DsetList, 0)) {
592             SUMA_SL_Err("Failed to insert dset into list\nI failed to succeed, snif.");
593             exit(1);
594          }
595          SUMA_LH("Lovely, that worked...");
596       }
597       #endif
598 
599       /* show me the whole thing. Don't do this for an enormous nel */
600          /* SUMA_ShowNel((void*)dset->nel); */
601 
602 
603       /* I want the pointer to the green column but do not know its index */
604          {
605             int j, *iv, N_i;
606             float *fp;
607             fprintf (stderr,"---Looking for green column ---\n");
608             iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_G, &N_i);
609             if (!iv) {
610                fprintf (stderr,"Error %s: Failed to find column.\n"
611                            , FuncName);
612             } else {
613                fprintf (stderr,"\t%d columns of type SUMA_NODE_G found.\n",
614                            N_i);
615                if (N_i) {
616                   fprintf (stderr,"\tReporting values at index %d\n", iv[0]);
617                   fp = (float *)dset->dnel->vec[iv[0]]; /* I know we only have one
618                                                    such col. here */
619                   for (j=0; j < SDSET_VECLEN(dset); ++j) {
620                      fprintf (stderr,"%f, ", fp[j]);
621                   }
622                   SUMA_free(iv); iv = NULL;
623                }
624             }
625 
626 
627          }
628 
629 
630    /* Now show me that baby,*/
631    SUMA_LH("I wanna Show You Some Info");
632    si = SUMA_DsetInfo (dset, 0);
633    fprintf (SUMA_STDERR,"Output of DsetInfo:\n%s\n", si); SUMA_free(si); si=NULL;
634 
635    if (LocalHead) fprintf(stderr," %s:-\nFrenching ...\n", FuncName);
636 
637    /* free other stuff */
638    if (r) SUMA_free(r); r = NULL;
639    if (g) SUMA_free(g); g = NULL;
640    if (b) SUMA_free(b); b = NULL;
641    if (rgb) SUMA_free(rgb); rgb = NULL;
642    if (maskrow) SUMA_free(maskrow); maskrow = NULL;
643    if (maskcol) SUMA_free(maskcol); maskcol = NULL;
644    if (NodeDef) SUMA_free(NodeDef); NodeDef = NULL;
645    if (s) {
646       for (i=0; i<N_NodeDef; ++i) {
647          if (s[i]) SUMA_free(s[i]);
648       }
649       SUMA_free(s);
650    }
651 
652    #ifdef SUMA_COMPILED
653    /* dset and its contents are freed in SUMA_Free_CommonFields */
654    if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
655    #else
656    /* free dset by hand */
657    if (dset) SUMA_FreeDset((void *)dset);
658    #endif
659 
660    SUMA_RETURN (0);
661 }/* Main */
662 
663