1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <sys/time.h>
6 #include <math.h>
7 #include "mrilib.h"
8 #include "niml.h"
9 #include "../niml/niml_private.h"
10 #include "xutil.h"
11 
12 
13 #include "SUMA_suma.h"
14 
usage_ConverDset(SUMA_GENERIC_ARGV_PARSE * ps,int detail)15 void usage_ConverDset(SUMA_GENERIC_ARGV_PARSE *ps, int detail)
16 {
17    static char FuncName[]={"usage_ConverDset"};
18    char *s = NULL, *sd=NULL, *sm=NULL;
19    s = SUMA_help_basics();
20    sd = SUMA_help_dset();
21    sm = SUMA_help_mask();
22    printf (
23 "Usage: \n"
24 "  ConvertDset -o_TYPE -input DSET [-i_TYPE] [-prefix OUT_PREF]\n"
25 "  Converts a surface dataset from one format to another.\n"
26 "\n%s", detail ? "":"use -h or -help for more help detail.\n");
27    if (detail) {
28       printf (
29 "  Mandatory parameters:\n"
30 "     -o_TYPE: TYPE of output datasets\n"
31 "              where TYPE is one of:\n"
32 "           niml_asc (or niml): for ASCII niml format.\n"
33 "           niml_bi:            for BINARY niml format.\n"
34 "           1D:                 for AFNI's 1D ascii format.\n"
35 "           1Dp:                like 1D but with no comments\n"
36 "                               or other 1D formatting gimmicks.\n"
37 "           1Dpt:               like 1Dp but transpose the output.\n"
38 "           gii:                GIFTI format default .\n"
39 "           gii_asc:            GIFTI format with ascii DataArrays.\n"
40 "           gii_b64:            GIFTI format with Base 64 encoded DataArrays.\n"
41 "           gii_b64gz:          GIFTI format with B64 enconding and gzipping.\n"
42 "         For stderr and stdout output use one of:\n"
43 "           1D_stderr, 1D_stdout, niml_stderr, or niml_stdout, \n"
44 "           1Dp_stdout, 1Dp_stderr, 1Dpt_stdout, 1Dpt_stderr\n"
45 "         Actually, this parameter is not that mandatory, the program\n"
46 "         can look at extensions on the prefix to guess the output\n"
47 "         format. If the prefix has no extension and o_TYPE is not\n"
48 "         specified, then the output format is the same as that of the\n"
49 "         input.\n"
50 "     -input DSET: Input dataset to be converted.\n"
51 "                  See more on input datasets below.\n"
52 "     -dset_labels 'SB_LABEL_0 SB_LABEL_1 ...'\n"
53 "                  Label the columns (sub-bricks) of the output dataset\n"
54 "                  You must have as many labels as you have sub-bricks in\n"
55 "                  the output dataset."
56 "  Optional parameters:\n"
57 "     -add_node_index: Add a node index element if one does not exist\n"
58 "                      in the input dset. With this option, the indexing\n"
59 "                      is assumed to be implicit (0,1,2,3.... for rows 0,1\n"
60 "                      2,3,...). If that is not the case, use -node_index_1D\n"
61 "                      option below. \n"
62 "             ** NOTE: It is highly recommended you use one of -node_index_1D\n"
63 "                       or -add_node_index when going from 1D format to NIML \n"
64 "                       GIFTI formats.\n"
65 "     -node_index_1D INDEX.1D: Specify file containing node indices\n"
66 "                              Use this to provide node indices with \n"
67 "                              a .1D dset. In many cases for .1D data\n"
68 "                              this option is DSET.1D'[0]'\n"
69 "     -node_select_1D MASK.1D: Specify the nodes you want to keep in the\n"
70 "                              output. \n"
71 "                              The order of the rows in the output dataset \n"
72 "                              reflects the order of the nodes in MASK.1D.\n"
73 "                              Note that the presence of duplicate nodes in\n"
74 "                              MASK.1D is not allowed, so if MASK.1D came\n"
75 "                              from ROI2dataset's -nodelist, recreate it with\n"
76 "                              option -nodelist.nodups instead. \n"
77 "                              Also, node indices that do not have data in the\n"
78 "                              input dataset will be ignored.\n"
79 "                              When in doubt, use the 1D output format along \n"
80 "                              with -prepend_node_index_1D and spot check your\n"
81 "                              results.\n"
82 "     -prepend_node_index_1D: Add a node index column to the data, rather\n"
83 "                             than keep it as part of the metadata.\n"
84 "     -pad_to_node MAX_INDEX: Output a full dset from node 0 \n"
85 "                            to node MAX_INDEX (a total of \n"
86 "                            MAX_INDEX + 1 nodes). Nodes that\n"
87 "                            get no value from input DSET are\n"
88 "                            assigned a value of 0\n"
89 "                            If MAX_INDEX is set to 0 it means you want\n"
90 "                            to pad the maximum node in the input dataset.\n"
91 "             ** Notice that padding gets done at the very end.\n"
92 "             ** Instead of directly setting MAX_INDEX to an integer you \n"
93 "                can set MAX_INDEX to something like:\n"
94 "             ld120 (or rd17) which sets MAX_INDEX to be the maximum \n"
95 "                node index on an Icosahedron with -ld 120. See \n"
96 "                CreateIcosahedron for details.\n"
97 "             d:DSET.niml.dset which sets MAX_INDEX to the maximum node found\n"
98 "                      in dataset DSET.niml.dset.\n"
99 "\n"
100 "     -labelize CMAP: Turn the dataset into a labeled set per the colormap in\n"
101 "                     CMAP. A CMAP can easily be generated with MakeColorMap's\n"
102 "                     options -usercolorlutfile and -suma_cmap.\n"
103 "\n"
104 "     -graphize: Turn the dataset into a SUMA graph dataset.\n"
105 "                See input format constraints under -onegraph and -multigraph\n"
106 "     -graph_nodelist_1D NODEINDLIST.1D NODELIST.1D: Two files specifying the \n"
107 "                                  indices and the coordinates of the graph's\n"
108 "                                  nodes. In sum you need I X Y Z (RAI mm).\n"
109 "                                  but the I comes from NODEINDLIST.1D and the\n"
110 "                                  X Y Z coordinates from NODELIST.1D\n"
111 "                                  If you have everything in one file, use\n"
112 "                                  the same filename twice with proper column\n"
113 "                                  selectors.\n"
114 "     -graph_full_nodelist_1D NODELIST.1D: Same as above, but without the need\n"
115 "                                  for NODEINDLIST.1D. In that case, indices\n"
116 "                                  will implicitly go from 0 to N-1, with N\n"
117 "                                  being the number of nodes.\n"
118 "     -graph_named_nodelist_txt NODENAMES.txt NODELIST.1D: Two files used to \n"
119 "                                  specify graph node indices, string labels, \n"
120 "                                  and their coordinates.\n"
121 "                                  In sum you need I LABEL X Y Z (RAI mm).\n"
122 "                                  The I and LABEL come from NODENAMES.txt and\n"
123 "                                  the X Y Z coordinates from NODELIST.1D\n"
124 "                          Also, you can assign to each graph node a group ID\n"
125 "                                  and nodes with the same group ID can be \n"
126 "                                  displayed with the same color in SUMA.\n"
127 "                                  To do so, add a third column to \n"
128 "                                  NODENAMES.txt so that you have: I LABEL GID\n"
129 "                                  with GID being the integer group ID.\n"
130 "                                  Color selection for the different group IDs\n"
131 "                                  is done automatically with ConvertDset, but\n"
132 "                                  you can set your own by appending three \n"
133 "                                  more columns to NODENAMES.txt to have:\n"
134 "                                     I LABEL GID R G B\n"
135 "                                  with R, G, and B values between 0 and 1.0\n"
136 "     -graph_XYZ_LPI: Coords in NodeList.1D are in LPI instead of RAI \n"
137 "     -graph_edgelist_1D EDGELIST.1D: i j indices of graph nodes defining edge\n"
138 "                                   with each row matching the input dset row.\n"
139 "                                   This option only works with -multigraph\n"
140 "                                   This option also marks the graph as being\n"
141 "                                   a sparse matrix, even if a square matrix \n"
142 "                                   is provided.\n"
143 "     -onegraph: Expect input dataset to be one square matrix defining the\n"
144 "                graph (default).\n"
145 "     -multigraph: Expect each column in input dataset to define an entire\n"
146 "                  graph. Each column in this case should be a column-stacked\n"
147 "                  square matrix.\n"
148 "\n"
149 "     -i_TYPE: TYPE of input datasets\n"
150 "              where TYPE is one of:\n"
151 "           niml: for niml data sets.\n"
152 "           1D:   for AFNI's 1D ascii format.\n"
153 "           dx: OpenDX format, expects to work on 1st\n"
154 "               object only.\n"
155 "           If no format is specified, the program will \n"
156 "           guess using the extension first and the file\n"
157 "           content next. However the latter operation might \n"
158 "           slow operations down considerably.\n"
159 "     -prefix OUT_PREF: Output prefix for data set.\n"
160 "                       Default is something based\n"
161 "                       on the input prefix.\n"
162 "     -split N: Split a multi-column dataset into about N output datasets\n"
163 "               with all having the same number of columns, except perhaps\n"
164 "               for the last one. Confused? try:\n"
165 "               ConvertDset -i v2s.lh.TS.niml.dset -split 3 \\\n"
166 "                           -prefix Split3\n"
167 "               3dinfo -n4 -label Split3.000* v2s.lh.TS.niml.dset\\\n"
168 "     -no_history: Do not include a history element in the output\n"
169 "  Notes:\n"
170 "     -This program will not overwrite pre-existing files.\n"
171 "     -The new data set is given a new idcode.\n"
172 "\n"
173 "%s"
174 "\n"
175 "%s"
176 "\n"
177 "%s"
178 "\n"
179 "Examples:\n"
180 "1-   Plot a node's time series from a niml dataset:\n"
181 "     ConvertDset -input DemoSubj_EccCntavir.niml.dset'#5779#' \\\n"
182 "                 -o_1D_stdout | 1dplot -nopush -stdin \n"
183 "\n"
184 "2-   Change a dataset to a labeled dataset using the colormap generated \n"
185 "     in Example 5 of MakeColorMap's help\n"
186 "        ConvertDset -i you_look_marvellous.niml.dset \\\n"
187 "                    -o you_look_labeled.niml.dset -labelize toylut.niml.cmap\n"
188 "     The advantage of having a labeled dataset is that you can see the label \n"
189 "     of a node when you click on it in SUMA, and you can extract\n"
190 "     regions based on their labels. For example, with the dataset created\n"
191 "     above you can run the following command to extract a mask of the  \n"
192 "     nodes labeled 'Small_Face' with something like:\n"
193 "        3dcalc -a you_look_labeled.niml.dset'<Small_Face>' \\\n"
194 "               -expr 'a' -prefix Small_Face.only\n"
195 "     This assumes of course that your colormap toylut.niml.cmap does have \n"
196 "     an entry labeled 'Small_Face'\n"
197 "\n"
198 "\n"
199 "\n",(detail > 1) ? sd : "Use -help for more detail.",
200      (detail > 1) ? sm : "",
201      (detail > 1) ? s : "");
202       }
203    SUMA_free(s); s = NULL; SUMA_free(sd); sd = NULL; SUMA_free(sm); sm = NULL;
204    if (detail) {
205       #ifdef SUMA_COMPILED
206       s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
207       #endif
208       fprintf (SUMA_STDOUT,
209          "    Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov\n\n");
210    }
211    return;
212 }
main(int argc,char * argv[])213 int main (int argc,char *argv[])
214 {/* Main */
215    static char FuncName[]={"ConvertDset"};
216    int   kar, brk, i_input, i, j, *Ti=NULL,
217          *indexmap = NULL, add_node_index, prepend_node_index,
218          no_hist ;
219    byte *Tb=NULL, *auto_nmask=NULL;
220    float *fv = NULL, *cols=NULL;
221    SUMA_DSET_FORMAT iform, oform;
222    SUMA_DSET *dset = NULL, *dseti=NULL, *dset_m = NULL;
223    char *NameOut, *prfx = NULL, *prefix = NULL, *cmapfile,
224          *graph_nodelist_1D=NULL, *graph_nodeindlist_1D=NULL,
225          *graph_edgelist_1D=NULL, *graph_nodeindlist_txt=NULL, **names=NULL;
226    char *ooo=NULL, *node_index_1d = NULL, *node_mask = NULL;
227    int overwrite = 0, exists = 0, N_inmask=-1, pad_to_node = -1, *ivec=NULL;
228    SUMA_GENERIC_ARGV_PARSE *ps=NULL;
229    int orderednodelist = 1, split=0, toGDSET=0, OneMat, *clan=NULL;
230    float fv5[5];
231    int nv, mxgrp, RAI;
232    char *stmp=NULL, colnm[32];
233    SUMA_COLOR_MAP *SM=NULL;
234    NI_str_array *dlabs=NULL;
235    SUMA_Boolean LocalHead = NOPE;
236 
237    SUMA_STANDALONE_INIT;
238    SUMA_mainENTRY;
239 
240    ps = SUMA_Parse_IO_Args(argc, argv, "-mask;");
241 
242    pad_to_node = -1;
243    add_node_index = 0;
244    prepend_node_index=0;
245    iform = SUMA_NO_DSET_FORMAT;
246    oform = SUMA_NO_DSET_FORMAT;
247    overwrite = 0;
248    i_input = -1;
249    prfx = NULL;
250    node_index_1d = NULL;
251    node_mask = NULL;
252    exists = 0;
253    split = 0;
254    no_hist = 0;
255    cmapfile=NULL;
256    toGDSET=0;
257    OneMat=1;
258    RAI = 1;
259    kar = 1;
260    brk = NOPE;
261    while (kar < argc) { /* loop accross command ine options */
262       if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
263          usage_ConverDset  (ps, strlen(argv[kar]) > 3 ? 2:1);
264          exit (0);
265       }
266 
267       SUMA_SKIP_COMMON_OPTIONS(brk, kar);
268 
269       SUMA_TO_LOWER(argv[kar]);
270 
271       if (SUMA_isOutputFormatFromArg(argv[kar], &oform)) {
272          brk = YUP;
273       }
274 
275 
276       if (!brk && (strcmp(argv[kar], "-i_1d") == 0))
277       {
278          if (iform != SUMA_NO_DSET_FORMAT) {
279             SUMA_SL_Err("input type already specified.");
280             exit(1);
281          }
282          iform = SUMA_1D;
283          brk = YUP;
284       }
285 
286       if (!brk && (strcmp(argv[kar], "-no_history") == 0))
287       {
288          no_hist = 1;
289          brk = YUP;
290       }
291 
292       if (!brk && (strcmp(argv[kar], "-graph_xyz_lpi") == 0))
293       {
294          RAI = 0;
295          brk = YUP;
296       }
297 
298 
299       if (!brk && (strcmp(argv[kar], "-graphize") == 0))
300       {
301          toGDSET = 1;
302          brk = YUP;
303       }
304 
305       if (!brk && (strcmp(argv[kar], "-onegraph") == 0))
306       {
307          OneMat = 1;
308          brk = YUP;
309       }
310       if (!brk && (strcmp(argv[kar], "-multigraph") == 0))
311       {
312          OneMat = 0;
313          brk = YUP;
314       }
315       if (!brk && (strcmp(argv[kar], "-i_niml") == 0))
316       {
317          if (iform != SUMA_NO_DSET_FORMAT) {
318             SUMA_SL_Err("input type already specified.");
319             exit(1);
320          }
321          iform = SUMA_NIML;
322          brk = YUP;
323       }
324 
325       if (!brk && (strcmp(argv[kar], "-i_dx") == 0))
326       {
327          if (iform != SUMA_NO_DSET_FORMAT) {
328             SUMA_SL_Err("input type already specified.");
329             exit(1);
330          }
331          iform = SUMA_ASCII_OPEN_DX_DSET;
332          brk = YUP;
333       }
334 
335 
336       if (  !brk &&
337             (  strcmp(argv[kar], "-input") == 0 ||
338                strcmp(argv[kar], "-i") == 0 ||
339                strcmp(argv[kar], "-i_") == 0)   )
340       {
341          if (kar+1 >= argc) {
342             SUMA_SL_Err("Need argument after -input");
343             exit(1);
344          }
345          if (i_input >= 0) {
346             SUMA_SL_Err("-input already specified.");
347             exit(1);
348          }
349          i_input = kar+1;
350          ++kar;
351          brk = YUP;
352       }
353 
354       if (!brk && (strcmp(argv[kar], "-labelize") == 0))
355       {
356          if (kar+1 >= argc) {
357             SUMA_SL_Err("Need colrmap after -labelize");
358             exit(1);
359          }
360          ++kar;
361          cmapfile = argv[kar];
362          if (!(SM = SUMA_LoadCmapFile_eng(cmapfile))) {
363             SUMA_S_Errv("Failed to load cmap file %s\n", cmapfile);
364             exit(1);
365          }
366          brk = YUP;
367       }
368 
369       if (!brk && (strcmp(argv[kar], "-graph_nodelist_1d") == 0))
370       {
371          if (kar+2 >= argc) {
372             SUMA_SL_Err("Need 2 arguments after -graph_nodelist_1D");
373             exit(1);
374          }
375          ++kar;
376          graph_nodeindlist_1D = argv[kar];
377          ++kar;
378          graph_nodelist_1D = argv[kar];
379          brk = YUP;
380       }
381 
382       if (!brk && (strcmp(argv[kar], "-graph_full_nodelist_1d") == 0))
383       {
384          if (kar+1 >= argc) {
385             SUMA_SL_Err("Need 1 arguments after -graph_full_nodelist_1D");
386             exit(1);
387          }
388          graph_nodeindlist_1D = NULL;
389          ++kar;
390          graph_nodelist_1D = argv[kar];
391          brk = YUP;
392       }
393 
394       if (!brk && (strcmp(argv[kar], "-graph_named_nodelist_txt") == 0))
395       {
396          if (kar+2 >= argc) {
397             SUMA_SL_Err("Need 2 arguments after -graph_named_nodelist_txt");
398             exit(1);
399          }
400          ++kar;
401          graph_nodeindlist_txt = argv[kar];
402          ++kar;
403          graph_nodelist_1D = argv[kar];
404          brk = YUP;
405       }
406 
407       if (!brk && (strcmp(argv[kar], "-graph_edgelist_1d") == 0))
408       {
409          if (kar+1 >= argc) {
410             SUMA_SL_Err("Need argument after -graph_edgelist_1D");
411             exit(1);
412          }
413          ++kar;
414          graph_edgelist_1D = argv[kar];
415          brk = YUP;
416       }
417 
418       if (!brk && (strcmp(argv[kar], "-node_index_1d") == 0))
419       {
420          if (kar+1 >= argc) {
421             SUMA_SL_Err("Need argument after -node_index_1D");
422             exit(1);
423          }
424          ++kar;
425          node_index_1d = argv[kar];
426          brk = YUP;
427       }
428 
429       if (!brk && (strcmp(argv[kar], "-node_select_1d") == 0))
430       {
431          if (kar+1 >= argc) {
432             SUMA_SL_Err("Need argument after -node_select_1D");
433             exit(1);
434          }
435          ++kar;
436          node_mask = argv[kar];
437          brk = YUP;
438       }
439 
440       if (!brk && (strcmp(argv[kar], "-add_node_index") == 0))
441       {
442 
443          add_node_index = 1;
444          brk = YUP;
445       }
446       if (!brk && (strcmp(argv[kar], "-prepend_node_index_1d") == 0))
447       {
448 
449          prepend_node_index = 1;
450          brk = YUP;
451       }
452       if (  !brk &&
453             (  strcmp(argv[kar], "-prefix") == 0 ||
454                strcmp(argv[kar], "-o") == 0 ||
455                strcmp(argv[kar], "-o_") == 0 ) )
456       {
457          if (kar+1 >= argc) {
458             SUMA_SL_Err("Need argument after -prefix/-o* options");
459             exit(1);
460          }
461          ++kar;
462          prfx = argv[kar];
463          brk = YUP;
464       }
465 
466       if (!brk && (strcmp(argv[kar], "-split") == 0))
467       {
468          if (kar+1 >= argc) {
469             SUMA_SL_Err("Need positive integer after -split");
470             exit(1);
471          }
472          ++kar;
473          split = atoi(argv[kar]);
474          brk = YUP;
475       }
476 
477       if (!brk && (strcmp(argv[kar], "-dset_labels") == 0)) {
478          kar ++;
479 			if (kar >= argc)  {
480 		  		fprintf (stderr, "need argument after -dset_labels \n");
481 				exit (1);
482 			}
483 			dlabs = NI_strict_decode_string_list(argv[kar] ,";, ");
484          brk = 1;
485 		}
486 
487       if (!brk && !ps->arg_checked[kar]) {
488          fprintf (SUMA_STDERR,
489             "Error %s: Option %s not understood. Try -help for usage\n",
490                FuncName, argv[kar]);
491          suggest_best_prog_option(argv[0], argv[kar]);
492          exit (1);
493       } else {
494          brk = NOPE;
495          kar ++;
496       }
497 
498    }/* loop accross command ine options */
499    if (argc < 3) {
500       usage_ConverDset  (ps, 0);
501       exit (1);
502    }
503 
504 
505    if (!prfx) {
506       prfx = "you_look_marvellous.niml.dset";
507       overwrite = 1;
508    } else {
509       overwrite = THD_ok_overwrite();
510    }
511    pad_to_node = MRILIB_DomainMaxNodeIndex;
512 
513    if (oform == SUMA_NO_DSET_FORMAT) {
514       if (prfx) {
515          /* try to guess */
516          oform = SUMA_GuessFormatFromExtension(prfx, argv[i_input]);
517          SUMA_LHv("Guessing output format to be: %s\n",
518                   SUMA_Dset_Format_Name(oform));
519          if (oform == SUMA_NO_DSET_FORMAT) {
520             SUMA_SL_Err("Output format MUST be specified, or should be\n"
521                         "obvious from prefix or the first input file.\n");
522             exit(1);
523          }
524       } else {
525          SUMA_S_Err("You need to specify either -o_TYPE or -prefix\n");
526          exit(1);
527       }
528    }
529 
530    exists = SUMA_WriteDset_NameCheck_s (prfx, NULL, oform, 0, &ooo);
531    if (exists != 0 && !overwrite) {
532       SUMA_S_Errv("Output dataset %s exists.\n", ooo);
533       SUMA_free(ooo); ooo=NULL;
534       exit(1);
535    }
536 
537    for (i=i_input; i<i_input + 1; ++i) {
538       if (LocalHead)
539          fprintf(SUMA_STDERR,"%s:\n Reading %s...\n", FuncName, argv[i]);
540       dset = SUMA_LoadDset_s (argv[i], &iform, 0);
541       if (!dset) { SUMA_SL_Err(  "Failed to load dataset.\n"
542                                  "Make sure file exists\n"
543                                  "and is of the specified\n"
544                                  "format."); exit(1); }
545       if (LocalHead) {
546          fprintf(SUMA_STDERR,"%s:\n Read dset of format %s\n",
547             FuncName, SUMA_Dset_Format_Name(iform));
548          SUMA_ShowDset(dset, 0, NULL);
549       }
550 
551       if (dlabs) {
552          if (dlabs->num != SDSET_VECNUM(dset)) {
553             SUMA_S_Err("You have %d labels but %d sub-bricks in dset %s",
554                         dlabs->num, SDSET_VECNUM(dset), SDSET_LABEL(dset));
555          } else {
556             int ii;
557             for (ii=0; ii<SDSET_VECNUM(dset); ++ii) {
558                SUMA_UpdateDsetColLabel(dset, ii, dlabs->str[ii]);
559             }
560          }
561          NI_delete_str_array(dlabs); dlabs = NULL;
562       }
563 
564       if (toGDSET) {
565          SUMA_LH("Going to graph format");
566          if (graph_edgelist_1D) {
567             int *ie=NULL;
568             SUMA_DSET *dsetc=NULL;
569             iform = SUMA_1D;
570             if (!(dseti = SUMA_LoadDset_s (graph_edgelist_1D, &iform, 0))) {
571                SUMA_S_Err("Failed to load nodelist ");
572                exit(1);
573             }
574             if (SDSET_VECNUM(dseti) != 3 && SDSET_VECNUM(dseti) != 2 ) {
575                SUMA_S_Err("Bad edgelist source, only 2or 3 columns allowed");
576                exit(1);
577             }
578             if (!(dsetc = SUMA_CoercedCopyofDset(dseti, SUMA_int, NULL))) {
579                SUMA_S_Err("Failed to copy to ints?");
580                exit(1);
581             }
582             SUMA_FreeDset(dseti); dseti = dsetc; dsetc = NULL;
583             switch (SDSET_VECNUM(dseti)){
584                case 2:
585                   if (!(SUMA_Dset_to_GDSET(&dset, NULL, OneMat,
586                                            NULL,
587                                            (int *)SDSET_VEC(dseti,0),
588                                            (int *)SDSET_VEC(dseti,1)))) {
589                      SUMA_S_Err("Failed to graphize");
590                   }
591                   break;
592                case 3:
593                   if (!(SUMA_Dset_to_GDSET(&dset, NULL, OneMat,
594                                            (int *)SDSET_VEC(dseti,0),
595                                            (int *)SDSET_VEC(dseti,1),
596                                            (int *)SDSET_VEC(dseti,2)))) {
597                      SUMA_S_Err("Failed to graphize");
598                   }
599                   break;
600                default:
601                   SUMA_S_Err("More infidel than an infidel!");
602                   break;
603             }
604             SUMA_FreeDset(dseti); dseti = NULL;
605          } else {
606             if (!(SUMA_Dset_to_GDSET(&dset, NULL, OneMat, NULL, NULL, NULL))) {
607                SUMA_S_Err("Failed to graphize");
608             }
609          }
610 
611          if (graph_nodelist_1D) {
612             SUMA_DSET *dsetind=NULL;
613             SUMA_LH("Set Aux shape");
614             if (!SUMA_GDSET_Set_Aux_matrix_shape(dset)) {
615                SUMA_S_Err("Need my matrix params");
616                exit(1);
617             }
618 
619             SUMA_LH("Now the nodelist");
620             iform = SUMA_1D;
621             if (!(dseti = SUMA_LoadDset_s (graph_nodelist_1D, &iform, 0))) {
622                SUMA_S_Err("Failed to load nodelist %s", graph_nodelist_1D);
623                exit(1);
624             }
625             if (SDSET_VECNUM(dseti) != 3) {
626                SUMA_S_Err("Bad nodelist source\n"
627                           "Only 3 column allowed, have %d of them in %s",
628                           SDSET_VECNUM(dseti), graph_nodelist_1D);
629                exit(1);
630             }
631             if (graph_nodeindlist_1D) {
632                if (!(dsetind =
633                         SUMA_LoadDset_s (graph_nodeindlist_1D, &iform, 0))) {
634                   SUMA_S_Err("Failed to load node index list %s",
635                              graph_nodeindlist_1D);
636                   exit(1);
637                }
638                if (SDSET_VECNUM(dsetind) != 1) {
639                   SUMA_S_Err("Bad nodelist index source\n"
640                              "Only 1 column allowed, have %d of them in %s",
641                              SDSET_VECNUM(dsetind), graph_nodeindlist_1D);
642                   exit(1);
643                }
644                if (SDSET_VECFILLED(dseti) != SDSET_VECFILLED(dsetind)) {
645                   SUMA_S_Errv(
646                      "mismatch in number of values between %s and %s\n",
647                      graph_nodelist_1D, graph_nodeindlist_1D);
648                   exit(1);
649                }
650                /* coerce index input to int */
651                {
652                   SUMA_DSET *dsetc=NULL;
653                   if (!(dsetc = SUMA_CoercedCopyofDset(dsetind,
654                                                        SUMA_int, NULL))) {
655                      SUMA_S_Err("Failed coerce");
656                      exit(1);
657                   }
658                   SUMA_FreeDset(dsetind); dsetind = dsetc; dsetc = NULL;
659                }
660                ivec = SDSET_VEC(dsetind,0);
661                dsetind->dnel->vec[0] = NULL;
662                SUMA_FreeDset(dsetind); dsetind = NULL;
663             } else if (graph_nodeindlist_txt) {
664                char *fl=NULL, *fle=NULL, *fl2=NULL;
665                int ok=0, cnt=0, mxcol=0, nalloc=0, nchar, ans;
666                float dum;
667 
668                /* Load file that has node indices and labels */
669                if (!(fl = SUMA_file_suck(graph_nodeindlist_txt, &nchar))) {
670                   SUMA_S_Errv("Faile to read %s\n", graph_nodeindlist_txt);
671                   exit(1);
672                }
673                fle = fl+nchar;
674                ok = 1;
675                cnt = 0; mxcol = 0, nalloc=0;
676                while (ok && fl < fle) {
677                   SUMA_SKIP_BLANK(fl, fle);
678                   do {
679                      /* skip comment, if any */
680                      SUMA_IS_COMMENT_LINE(fl, fle, '#', ans);
681                      if (ans) {
682                         SUMA_LH("Skipping comment...");
683                         SUMA_SKIP_LINE(fl, fle);
684                      }
685                   } while (ans);
686                   SUMA_SKIP_BLANK(fl, fle); if (fl == fle) break;
687                   SUMA_LHv("Now at >>%s<<\n", fl);
688                   /* read first number */
689                   SUMA_ADVANCE_PAST_NUM(fl, dum, ok);
690                   if (!ok && fl!=fle) {
691                      SUMA_S_Errv("Failed to read i, stuck at >>%s<<\n",
692                                  fl); exit(1);
693                   }
694                   if (cnt >= nalloc) {
695                      nalloc = nalloc+256;
696                      ivec = (int *)SUMA_realloc(ivec, nalloc*sizeof(int));
697                      names = (char **)SUMA_realloc(names, nalloc*sizeof(char *));
698                      clan = (int *)SUMA_realloc(clan, nalloc*sizeof(int));
699                      cols = (float *)SUMA_realloc(cols, 3*nalloc*sizeof(int));
700                   }
701                   SUMA_LHv("index[%d] %f\n", cnt, dum);
702                   ivec[cnt] = (int)dum;
703                   /* Now get the label */
704                   SUMA_GET_BETWEEN_BLANKS(fl, fle, fl2);
705                   if (fl2 > fl) {
706                      names[cnt]=NULL;
707                      SUMA_COPY_TO_STRING(fl, fl2, names[cnt]);
708                      SUMA_LHv("  Name[%d] %s, fl2[0] is >%c<\n",
709                                  cnt, names[cnt], fl2[0]);
710                      fl = fl2;
711                   } else {
712                      SUMA_S_Errv("Failed to get label associated with index %d\n"
713                                  ,ivec[cnt]);
714                      exit(1);
715                   }
716                   /* And lastly, do we have numbers left? */
717                   SUMA_SKIP_PURE_BLANK(fl, fle);
718                   SUMA_GET_TO_EOL(fl, fle, fl2);
719                   if (fl2 > fl) {
720                      SUMA_COPY_TO_STRING(fl, fl2, stmp);
721                      SUMA_LH("Parsing %s", stmp);
722                      /* colors anyone? */
723                      nv = SUMA_StringToNum(stmp, (void *)fv5, 4, 1);
724                      switch (nv) {
725                         case 0:
726                            clan[cnt] = -2;
727                         case 1:
728                            clan[cnt] = (int)fv5[0];
729                            cols[3*cnt  ] = -1.0;
730                            cols[3*cnt+1] = -1.0;
731                            cols[3*cnt+2] = -1.0;
732                            break;
733                         case 4:
734                            clan[cnt] = (int)fv5[0];
735                            cols[3*cnt  ] = fv5[1];
736                            cols[3*cnt+1] = fv5[2];
737                            cols[3*cnt+2] = fv5[3];
738                            break;
739                         default:
740                            SUMA_S_Err(
741                               "Expected 1 or 4  values after name %s, got %d"
742                               "Replacing with special group",
743                               names[cnt], nv);
744                            clan[cnt] = -1;
745                            cols[3*cnt  ] = -1.0;
746                            cols[3*cnt+1] = -1.0;
747                            cols[3*cnt+2] = -1.0;
748                            break;
749                      }
750                      fl = fl2;
751                   } else {
752                      clan[cnt] = -2;
753                   }
754                   SUMA_ifree(stmp);
755                   ++cnt;
756                }
757                if (cnt != SDSET_VECFILLED(dseti)) {
758                   SUMA_S_Errv("Have %d entries in %s but %d enties in %s\n",
759                            cnt, graph_nodeindlist_txt,
760                            SDSET_VECFILLED(dseti), graph_nodelist_1D);
761                   exit(1);
762                }
763                /* check on colors and grouping */
764                if (clan[0] == -2) {/* No grouping, no colors */
765                   SUMA_ifree(clan); SUMA_ifree(cols);
766                } else {
767                   mxgrp = -1;
768                   for (cnt=0; cnt <SDSET_VECFILLED(dseti); ++cnt) {
769                      if (clan[cnt] > mxgrp) mxgrp = clan[cnt];
770                   }
771                   for (cnt=0; cnt <SDSET_VECFILLED(dseti); ++cnt) {
772                      if (clan[cnt] < 0) clan[cnt] = mxgrp + 1;
773                   }
774                   sprintf(colnm, "%d", SUMA_MIN_PAIR(mxgrp+2,255));
775                   for (cnt=0; cnt <SDSET_VECFILLED(dseti); ++cnt) {
776                      if (cols[3*cnt] < 0) {
777                         SUMA_a_good_col(colnm, clan[cnt], fv5);
778                         cols[3*cnt  ] = fv5[0];
779                         cols[3*cnt+1] = fv5[1];
780                         cols[3*cnt+2] = fv5[1];
781                      }
782                   }
783                }
784             }  else {
785                ivec = NULL; /* SUMA_AddGDsetNodeListElement will generate one */
786             }
787 
788             SUMA_LH( "Have %d node indices %d .. %d in %s\n"
789                      "Graph %s has %ld segment nodes, %ld nodes defined.\n",
790                     SDSET_VECFILLED(dseti), ivec[0],
791                     ivec[SDSET_VECFILLED(dseti)-1], SDSET_LABEL(dseti),
792                     SDSET_LABEL(dset), GDSET_N_SEG_POINTS(dset),
793                     GDSET_N_ALL_POINTS(dset));
794             if (!RAI) {
795                int cnt;
796                float *fvx = (float *)SDSET_VEC(dseti,0);
797                float *fvy = (float *)SDSET_VEC(dseti,1);
798                SUMA_LH("Flipping to LPI");
799                for (cnt=0; cnt <SDSET_VECFILLED(dseti); ++cnt) {
800                   fvx[cnt] = -fvx[cnt];
801                   fvy[cnt] = -fvy[cnt];
802                }
803             }
804             if (!(SUMA_AddGDsetNodeListElement(dset, ivec,
805                                                      SDSET_VEC(dseti,0),
806                                                      SDSET_VEC(dseti,1),
807                                                      SDSET_VEC(dseti,2),
808                                                      names,
809                                                      clan,
810                                                      cols,
811                                                      SDSET_VECFILLED(dseti)))) {
812                SUMA_S_Err("Failed to add node list");
813                exit(1);
814             }
815             SUMA_FreeDset(dseti); dseti = NULL;
816             if (ivec) free(ivec); ivec=NULL;
817             if (names) SUMA_free(names); names = NULL;
818             SUMA_ifree(cols); SUMA_ifree(clan);
819          }
820          if (LocalHead) SUMA_ShowDset(dset,0, NULL);
821       }
822 
823       SUMA_LH("Checking on inel...");
824       /* make sure inel is initialized*/
825       if (!dset->inel || !SDSET_NODEINDLEN(dset)) {
826          SUMA_SL_Err("Bad dset->inel\nOld niml dset?");
827          SUMA_ShowDset(dset,0, NULL);
828          SUMA_DUMP_TRACE("Bad dset->inel, dumping trace for debug:");
829          SUMA_FreeDset(dset); dset = NULL;
830          SUMA_RETURN(1);
831       }
832 
833       SUMA_LH("On to node index stuff...");
834       if (node_index_1d) { /* add a node index column */
835          iform = SUMA_1D;
836          if (!(dseti = SUMA_LoadDset_s (node_index_1d, &iform, 0))) {
837             SUMA_S_Err("Failed to load node index dset");
838             exit(1);
839          }
840          if (SDSET_VECNUM(dseti) != 1) {
841             SUMA_S_Err("Bad node index source, only one column allowed");
842             exit(1);
843          }
844          if (SDSET_VECFILLED(dseti) != SDSET_VECFILLED(dset)) {
845             SUMA_S_Err(
846                "mismatch in number of values in index source and dataset");
847             exit(1);
848          }
849          Ti = (int *) SUMA_calloc(SDSET_VECFILLED(dseti), sizeof(int));
850          fv = (float *)dseti->dnel->vec[0];
851          for (j=0; j<SDSET_VECFILLED(dseti); ++j) {
852             Ti[j] = (int)fv[j];
853          }
854          if (!SUMA_AddDsetNelCol (  dset, "Node Index",
855                                     SUMA_NODE_INDEX, (void *)Ti, NULL, 1)) {
856             SUMA_SL_Err("Failed to add column");
857             if (Ti) SUMA_free(Ti); Ti = NULL;
858             exit(1);
859          }
860          SUMA_free(Ti); Ti = NULL;
861          SUMA_FreeDset(dseti); dseti = NULL;
862       }
863 
864 
865       if (add_node_index) {
866          if (!SUMA_PopulateDsetNodeIndexNel(dset, 1)) {
867             SUMA_S_Err("Failed to add node index column");
868             exit(1);
869          }
870       }
871 
872       if (pad_to_node == 0) {
873          DSET_MAX_NODE_INDEX(dset, pad_to_node);
874          if (pad_to_node < 0) {
875             SUMA_S_Err( "Failed to get max node index in input dset.\n"
876                   "Cannot set pad_to_node automatically\n");
877             exit(1);
878          }
879       }
880       if (pad_to_node > 0) {
881          SUMA_S_Notev("Padding output dset until node %d\n", pad_to_node);
882       }
883 
884       SUMA_LHv("On to auto_nmask ...%p %p %p\n",
885                ps->bmaskname,ps->nmaskname,ps->cmask);
886       if (!(auto_nmask =
887                SUMA_load_all_command_masks(  ps->bmaskname,
888                                              ps->nmaskname,
889                                              ps->cmask,
890                                              SDSET_VECFILLED(dset),
891                                              &N_inmask))
892             && N_inmask < 0) {
893             SUMA_S_Err("Failed loading mask");
894             exit(1);
895       }
896       if (auto_nmask) { /* mask input here */
897          SUMA_LH("Masking here ...");
898          if (!(dset_m = SUMA_MaskedCopyofDset(dset, auto_nmask, NULL, 1, 0))){
899             SUMA_S_Err("Failed to mask dset by mask options\n");
900             exit(1);
901          }
902          SUMA_FreeDset(dset); dset = NULL;
903          dset = dset_m;  dset_m = NULL;
904       }
905 
906       SUMA_LH("On to node_mask ...");
907       if (node_mask) { /* mask dataset */
908          iform = SUMA_1D;
909          if (!(dseti = SUMA_LoadDset_s (node_mask, &iform, 0))) {
910             SUMA_S_Err("Failed to load node_selection dset");
911             exit(1);
912          }
913          if (SDSET_VECNUM(dseti) != 1) {
914             SUMA_S_Err("Bad node index source, only one column allowed");
915             exit(1);
916          }
917 
918          Ti = (int *) SUMA_calloc(SDSET_VECFILLED(dseti), sizeof(int));
919          fv = (float *)dseti->dnel->vec[0];
920          for (j=0; j<SDSET_VECFILLED(dseti); ++j) Ti[j] = (int)fv[j];
921 
922          if (orderednodelist) {
923             int *inlu=NULL, N_inlu=0;
924             /* make sure indexlist is unique */
925             inlu = SUMA_UniqueInt(Ti, SDSET_VECFILLED(dseti),
926                                   &N_inlu, 0);
927             SUMA_free(inlu); inlu = NULL;
928             if (N_inlu != SDSET_VECFILLED(dseti)) {
929                SUMA_S_Err( "Indexlist contains duplicate entries.\n"
930                            "This is not supported.");
931                exit(1);
932             }
933 
934 
935             if (!(dset_m = SUMA_MaskedByOrderedNodeIndexCopyofDset(
936                      dset, Ti, SDSET_VECFILLED(dseti),  NULL, 1, 0))) {
937                SUMA_S_Err("Failed to mask dset by node indices\n");
938                SUMA_S_Note("If your input dataset did not have a node index \n"
939                            "explicitly defined, use -add_node_index or\n"
940                            "-node_index_1D options to specify node indices.\n" )
941                exit(1);
942             }
943          } else {
944             if (!(dset_m = SUMA_MaskedByNodeIndexCopyofDset(
945                      dset, Ti, SDSET_VECFILLED(dseti),  NULL, 1, 0))) {
946                SUMA_S_Err("Failed to mask dset by node indices\n");
947                SUMA_S_Note("If your input dataset did not have a node index \n"
948                            "explicitly defined, use -add_node_index or\n"
949                            "-node_index_1D options to specify node indices.\n" )
950                exit(1);
951             }
952          }
953 
954          SUMA_free(Ti); Ti = NULL;
955          SUMA_free(indexmap); indexmap = NULL;
956          SUMA_FreeDset(dseti); dseti = NULL;
957          SUMA_FreeDset(dset); dset = NULL;
958          dset = dset_m;  dset_m = NULL;
959       }
960 
961 
962       if (pad_to_node >= 0) {
963          dset_m = SUMA_PaddedCopyofDset ( dset, pad_to_node );
964          SUMA_FreeDset(dset); dset = NULL;
965          dset = dset_m; dset_m = NULL;
966       }
967 
968       SUMA_LH("On to prefix ...");
969 
970       if (!prfx) {
971          /* don't use iform because some 1Ds are NIML compatible and they get
972          read-in as such unless you specifically order otherwise. */
973          prefix = SUMA_RemoveDsetExtension_s(argv[i], SUMA_NO_DSET_FORMAT);
974       } else {
975          prefix = SUMA_copy_string(prfx);
976       }
977 
978       /* set a new ID for the dset */
979       SUMA_NEWDSET_ID_LABEL_HIST(dset, prefix) ;
980 
981 
982       if (no_hist) {
983          SUMA_RemoveDsetHist(dset);
984       }
985 
986       if (prepend_node_index) {/* prepend node index? */
987          if (!SUMA_InsertDsetNelCol (  dset, "Node Index Copy",
988                                        SUMA_NODE_INT,
989                                        (void *)(dset->inel->vec[0]),
990                                        NULL ,1, 0)) {
991             SUMA_S_Err("Failed to insert column");
992          }
993          if (LocalHead) SUMA_ShowDset(dset,0, NULL);
994       }
995 
996       if (cmapfile && SM) { /* labelize */
997          SUMA_DSET *idset;
998          if (!SUMA_is_AllConsistentCastType_dset(dset, SUMA_int)) {
999             idset = SUMA_CoercedCopyofDset(dset, SUMA_int, NULL);
1000          } else {
1001             idset = dset;
1002          }
1003          if (!(SUMA_dset_to_Label_dset_cmap(idset, SM))) {
1004             SUMA_S_Err("Failed to make change");
1005             exit(1);
1006          }
1007 
1008          if (idset != dset) {
1009             SUMA_FreeDset(dset); dset = idset; idset=NULL;
1010          }
1011       }
1012 
1013       SUMA_LHv("About to write dset to %s\n", prefix);
1014       if (!split) {
1015          NameOut = SUMA_WriteDset_s (prefix, dset, oform, overwrite, 0);
1016          if (!NameOut && !SUMA_IS_DSET_STDXXX_FORMAT(oform)) {
1017             SUMA_SL_Err("Failed to write dataset."); exit(1);
1018          } else {
1019             if (NameOut) SUMA_free(NameOut); NameOut = NULL;
1020          }
1021       } else {
1022          int ksp, ikp, ikps, nsplits=(int)ceil((float)SDSET_VECNUM(dset)/split);
1023          SUMA_DSET *ds=NULL;
1024          char cbuf[12]={""}, *prefs = NULL;
1025          byte *colmask=NULL;
1026          colmask=(byte*)SUMA_malloc(sizeof(byte)*SDSET_VECNUM(dset));
1027          for (ksp=0; ksp<split; ++ksp) {
1028             sprintf(cbuf,"%04d",ksp);
1029             memset(colmask, 0, sizeof(byte)*SDSET_VECNUM(dset));
1030             ikp = ksp*nsplits;
1031             ikps = SUMA_MIN_PAIR(SDSET_VECNUM(dset), (ksp+1)*nsplits);
1032             if (ikp == ikps) continue; /* all one */
1033             while (ikp < ikps) colmask[ikp++]=1;
1034             prefs = SUMA_RemoveDsetExtension_s(prefix,SUMA_NO_DSET_FORMAT);
1035             prefs = SUMA_append_replace_string(prefs,cbuf,".", 1);
1036             if (!(ds = SUMA_MaskedCopyofDset(dset, NULL, colmask, 1, 1))) {
1037                SUMA_S_Err("Failed to get masked copy");
1038                exit(1);
1039             }
1040             NameOut = SUMA_WriteDset_s (prefs, ds, oform, overwrite, 0);
1041             if (!NameOut && !SUMA_IS_DSET_STDXXX_FORMAT(oform)) {
1042                SUMA_SL_Err("Failed to write dataset."); exit(1);
1043             } else {
1044                if (NameOut) SUMA_free(NameOut); NameOut = NULL;
1045             }
1046             if (prefs) SUMA_free(prefs);
1047             SUMA_FreeDset(ds); ds=NULL;
1048          }
1049          SUMA_free(colmask); colmask=NULL;
1050       }
1051 
1052       if (SM) SUMA_Free_ColorMap(SM); SM = NULL;
1053       if (prefix) SUMA_free(prefix); prefix = NULL;
1054       if (dset) SUMA_FreeDset((void *)dset); dset = NULL;
1055       if (NameOut) SUMA_free(NameOut); NameOut = NULL;
1056    }
1057 
1058 	SUMA_RETURN(0);
1059 }
1060