1 #include "SUMA_suma.h"
2
usage_ROI2dataset_Main(int detail)3 void usage_ROI2dataset_Main (int detail)
4
5 {/*Usage*/
6 static char FuncName[]={"usage_ROI2dataset_Main"};
7 char * s = NULL;
8 fprintf(SUMA_STDOUT,
9 "\n"
10 "Usage: \n"
11 " ROI2dataset <-prefix dsetname> [...] <-input ROI1 ROI2 ...>\n"
12 " [<-of ni_bi|ni_as|1D>] \n"
13 " [<-dom_par_id idcode>] \n"
14 " This program transforms a series of ROI files\n"
15 " to a node dataset. This data set will contain\n"
16 " the node indices in the first column and their\n"
17 " ROI values in the second column.\n"
18 " Duplicate node entries (nodes that are part of\n"
19 " multiple ROIs) will get ignored. You will be\n"
20 " notified when this occurs. \n"
21 "\n"
22 "Mandatory parameters:\n"
23 " -prefix dsetname: Prefix of output dataset.\n"
24 " Program will not overwrite existing\n"
25 " datasets.\n"
26 " See also -label_dset alternate below.\n"
27 " -keep_separate: Output one column (sub-brick) for each ROI value\n"
28 "\n"
29 " and/or\n"
30 " -nodelist NL: Prefix for a set of .1D files\n"
31 " -nodelist.nodups NL: that contain a list of node indices\n"
32 " in the order in which they appear in\n"
33 " an ROI. This way you can make use of the\n"
34 " directionality of an ROI line instead of just \n"
35 " treating it as a set of nodes. \n"
36 " For each integer label 'i' in the ROI files provided\n"
37 " with the -input option, you will get a file called\n"
38 " NL.i.1D listing the nodes in the order they were \n"
39 " encountered in an ROI file and across ROI files.\n"
40 " If you want duplicate node entries removed, then\n"
41 " use -nodelist.nodups instead.\n"
42 " For example, say you traced an ROI that consisted of some \n"
43 " arbitrary curved path and you want to get the nodes \n"
44 " forming the path in the order traversed while drawing.\n"
45 " First save the path drawn, say to trace.niml.roi, \n"
46 " then use the following command:\n"
47 " ROI2dataset -nodelist.nodups TRACE \\\n"
48 " -input trace.niml.roi\n"
49 " Note: You can use the output of -nodelist as input to \n"
50 " ConvertDset's -node_select_1D option. \n"
51 " This is not the case for -nodelist because\n"
52 " ConvertDset's -node_select_1D does not allow for \n"
53 " duplicate node entries. \n"
54 " -nodelist_with_ROIval: Also add the ROIval as a second column in .1D\n"
55 " files output by -nodelist.\n"
56 " -input ROI1 ROI2....: ROI files to turn into a \n"
57 " data set. This parameter MUST\n"
58 " be the last one on command line.\n"
59 "\n"
60 "Optional parameters:\n"
61 " All optional parameters must be specified before the -input parameters.\n"
62 "\n"
63 " -label_dset dsetname: Write a label dataset, instead of a simple dataset.\n"
64 " Labeled datasets are treated differently in SUMA.\n" " This option also sets the output format to NIML.\n"
65 " Note: Using -keep_separate with this option is legal, but\n"
66 " makes little sense. You can't view more than one \n"
67 " sub-brick in SUMA for Labeled datasets.\n"
68 " -h | -help: This help message\n"
69 " -of FORMAT: Output format of dataset. FORMAT is one of:\n"
70 " ni_bi: NIML binary\n"
71 " ni_as: NIML ascii (default)\n"
72 " 1D : 1D AFNI format.\n"
73 " -dom_par_id id: Idcode of domain parent.\n"
74 " When specified, only ROIs have the same\n"
75 " domain parent are included in the output.\n"
76 " If id is not specified then the first\n"
77 " domain parent encountered in the ROI list\n"
78 " is adopted as dom_par_id.\n"
79 " 1D roi files do not have domain parent \n"
80 " information. They will be added to the \n"
81 " output data under the chosen dom_par_id.\n"
82 " -pad_to_node max_index: Output a full dset from node 0 \n"
83 " to node max_index (a total of \n"
84 " max_index + 1 nodes). Nodes that\n"
85 " are not part of any ROI will get\n"
86 " a default label of 0 unless you\n"
87 " specify your own padding label.\n"
88 " -pad_label padding_label: Use padding_label (an integer) to\n"
89 " label nodes that do not belong\n"
90 " to any ROI. Default is 0.\n"
91 " This padding value is also used in the multi-column\n"
92 " format of option -keep_separate.\n"
93 "\n");
94 s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
95 fprintf(SUMA_STDOUT,
96 " Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \n");
97 exit (0);
98 }/*Usage*/
99
main(int argc,char * argv[])100 int main (int argc,char *argv[])
101 {/* Main */
102 static char FuncName[]={"ROI2dataset"};
103 char *prefix_name, **input_name_v=NULL, *out_name=NULL,
104 *Parent_idcode_str = NULL, *dummy_idcode_str = NULL,
105 *stmp=NULL, *sss=NULL, *nodelist=NULL, *outlist_name=NULL,
106 cbuf[50];
107 int kar, brk, N_input_name, cnt = 0, N_ROIv,
108 N_tROI, ii, i, nn, pad_to, pad_val;
109 SUMA_DSET *dset=NULL;
110 NI_stream ns;
111 SUMA_DSET_FORMAT Out_Format = SUMA_ASCII_NIML;
112 SUMA_DRAWN_ROI ** ROIv = NULL, **tROIv = NULL;
113 SUMA_Boolean AddThis = NOPE;
114 SUMA_ROI_EXTRACT *dd=NULL;
115 DList *ddl=NULL;
116 DListElmt *el=NULL;
117 int nodups=0, olabel = 0, withflag = 0, keepsep=0;
118 SUMA_COLOR_MAP *cmap=NULL;
119 SUMA_Boolean LocalHead = NOPE;
120
121 SUMA_STANDALONE_INIT;
122 SUMA_mainENTRY;
123
124 /* parse the command line */
125 kar = 1;
126 brk = NOPE;
127 prefix_name = NULL;
128 input_name_v = NULL;
129 N_input_name = 0;
130 Out_Format = SUMA_NO_DSET_FORMAT;
131 Parent_idcode_str = NULL;
132 pad_to = -1;
133 pad_val = 0;
134 nodelist=NULL;
135 withflag = 0;
136 olabel = 0;
137 keepsep = 0;
138 nodups = 0;
139 while (kar < argc) { /* loop accross command ine options */
140 /* SUMA_LH("Parsing command line..."); */
141
142 if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
143 usage_ROI2dataset_Main(strlen(argv[kar]) > 3 ? 2:1);
144 exit (1);
145 }
146
147 SUMA_SKIP_COMMON_OPTIONS(brk, kar);
148
149 if (!brk && (strcmp(argv[kar], "-prefix") == 0)) {
150 kar ++;
151 if (kar >= argc) {
152 fprintf (SUMA_STDERR, "need argument after -prefix ");
153 exit (1);
154 }
155 prefix_name = argv[kar];
156 brk = YUP;
157 }
158
159 if (!brk && (strcmp(argv[kar], "-label_dset") == 0)) {
160 kar ++;
161 if (kar >= argc) {
162 fprintf (SUMA_STDERR, "need argument after -label_dset ");
163 exit (1);
164 }
165 prefix_name = argv[kar];
166 if (Out_Format != SUMA_NO_DSET_FORMAT &&
167 Out_Format != SUMA_ASCII_NIML &&
168 Out_Format != SUMA_BINARY_NIML) {
169 SUMA_S_Warn("Overriding output format to accommodate -label_dset.\n"
170 "Format will be ni_as or ni_bi, depending on environment\n"
171 "variable AFNI_NIML_TEXT_DATA");
172 }
173 if (AFNI_yesenv("AFNI_NIML_TEXT_DATA")) Out_Format = SUMA_ASCII_NIML;
174 else Out_Format = SUMA_BINARY_NIML;
175 olabel = 1;
176 brk = YUP;
177 }
178
179 if ( !brk &&
180 (strcmp(argv[kar], "-keep_separate") == 0) ) {
181 keepsep = 1;
182 brk = YUP;
183 }
184
185
186 if ( !brk &&
187 (strcmp(argv[kar], "-nodelist") == 0 ||
188 strcmp(argv[kar], "-nodelist.nodups") == 0) ) {
189 if (strlen(argv[kar])> 10) nodups = 1;
190 else nodups = 0;
191 kar ++;
192 if (kar >= argc) {
193 fprintf (SUMA_STDERR, "need argument after -nodelist* options ");
194 exit (1);
195 }
196 nodelist = argv[kar];
197
198 brk = YUP;
199 }
200
201 if ( !brk &&
202 (strcmp(argv[kar], "-nodelist_with_ROIval") == 0) ) {
203 withflag = 1;
204 brk = YUP;
205 }
206
207 if (!brk && (strcmp(argv[kar], "-of") == 0)) {
208 kar ++;
209 if (kar >= argc) {
210 fprintf (SUMA_STDERR, "need argument after -of ");
211 exit (1);
212 }
213
214 Out_Format = SUMA_NO_DSET_FORMAT;
215 /* Can't use isOutputFormatFromArg because -of is not part
216 of the passed argument */
217 if (!SUMA_isFormatFromArg(argv[kar], &Out_Format)) {
218 fprintf (SUMA_STDERR,
219 "%s not a valid option with -of.\n", argv[kar]);
220 exit (1);
221 }
222 if (olabel &&
223 Out_Format != SUMA_ASCII_NIML &&
224 Out_Format != SUMA_BINARY_NIML) {
225 SUMA_S_Err("Cannot specify non-niml format with -label_dset");
226 exit(1);
227 }
228
229 brk = YUP;
230 }
231
232 if (!brk && (strcmp(argv[kar], "-dom_par_id") == 0)) {
233 kar ++;
234 if (kar >= argc) {
235 fprintf (SUMA_STDERR, "need argument after -dom_par_id");
236 exit (1);
237 }
238 Parent_idcode_str = SUMA_copy_string(argv[kar]);
239 brk = YUP;
240 }
241
242 if (!brk && (strcmp(argv[kar], "-input") == 0)) {
243 kar ++;
244 if (kar >= argc) {
245 fprintf (SUMA_STDERR, "need at least one argument after -input ");
246 exit (1);
247 }
248 input_name_v = (char **)SUMA_malloc((argc-kar+1)*sizeof(char *));
249
250 cnt = 0;
251 while (kar < argc) {
252 input_name_v[cnt] = argv[kar];
253 ++cnt; ++kar;
254 }
255 N_input_name = cnt;
256 brk = YUP;
257 }
258
259 if (!brk && ( (strcmp(argv[kar], "-pad_label") == 0) ||
260 (strcmp(argv[kar], "-pad_val") == 0) )) {
261 kar ++;
262 if (kar >= argc) {
263 fprintf (SUMA_STDERR, "need argument after -pad_label");
264 exit (1);
265 }
266 pad_val = atoi(argv[kar]);
267 brk = YUP;
268 }
269
270 if (!brk) {
271 fprintf (SUMA_STDERR,
272 "Error %s: Option %s not understood. Try -help for usage\n",
273 FuncName, argv[kar]);
274 suggest_best_prog_option(argv[0], argv[kar]);
275 exit (1);
276 } else {
277 brk = NOPE;
278 kar ++;
279 }
280 }
281
282 if (argc < 4) {
283 SUMA_S_Err("Too few options");
284 usage_ROI2dataset_Main (1);
285 }
286
287 if (MRILIB_DomainMaxNodeIndex >= 0) pad_to = MRILIB_DomainMaxNodeIndex;
288
289 if (!prefix_name && !nodelist) {
290 fprintf (SUMA_STDERR,
291 "Error %s: No output prefix or nodelist was specified.\n"
292 , FuncName);
293 exit(1);
294 }
295
296 if (prefix_name) {
297 if (Out_Format == SUMA_NO_DSET_FORMAT) {
298 Out_Format = SUMA_GuessFormatFromExtension(prefix_name,
299 "love.niml.dset");
300 }
301 /* form the output name and check for existence */
302 #if 1
303 out_name = SUMA_Extension( prefix_name,
304 (char *)SUMA_ExtensionOfDsetFormat(Out_Format),
305 NOPE);
306 #else
307 switch (Out_Format) {
308 case SUMA_ASCII_NIML:
309 case SUMA_BINARY_NIML:
310 out_name = SUMA_Extension(prefix_name, ".niml.dset", NOPE);
311 break;
312 case SUMA_1D:
313 out_name = SUMA_Extension(prefix_name, ".1D.dset", NOPE);
314 break;
315 default:
316 SUMA_S_Err("Output format not supported");
317 exit(1);
318 break;
319 }
320 #endif
321 SUMA_LH ("%s",out_name);
322
323 /* check for existence of out_name */
324 if (SUMA_filexists(out_name) && !THD_ok_overwrite()) {
325 fprintf(SUMA_STDERR,"Error %s:\n Output file %s exists.\n",
326 FuncName, out_name);
327 exit(1);
328 }
329 } else out_name = NULL;
330
331
332 /* check for input files */
333 if (N_input_name <= 0) {
334 fprintf(SUMA_STDERR,"Error %s:\n No ROI files specified.\n",
335 FuncName);
336 exit(1);
337 }
338
339 /* read in the data sets */
340 /* create a dummy idcode_str for potential 1D data sets */
341 N_ROIv = 0;
342 Parent_idcode_str = NULL;
343 dummy_idcode_str = UNIQ_hashcode("DummyNameNothingLikeIt");
344 for (i=0; i < N_input_name; ++i) {
345 if (SUMA_isExtension(input_name_v[i], ".niml.roi")) {
346 /* load niml ROI */
347 if (!( tROIv = SUMA_OpenDrawnROI_NIML (input_name_v[i],
348 &N_tROI, NOPE, NULL))) {
349 SUMA_S_Err("Failed to read NIML ROI.");
350 exit(1);
351 }
352 }else if (SUMA_isExtension(input_name_v[i], ".1D.roi")) {
353 /* load 1D ROI */
354 if (!( tROIv = SUMA_OpenDrawnROI_1D (input_name_v[i],
355 dummy_idcode_str, &N_tROI, NOPE))) {
356 SUMA_S_Err("Failed to read NIML ROI.");
357 exit(1);
358 }
359 }else {
360 SUMA_S_Errv( "Failed to recognize\n"
361 "ROI type from filename '%s'\n", input_name_v[i]);
362 exit(1);
363 }
364
365 SUMA_LH("Copying temporary ROIv into the main ROIv ");
366 /* copy temporary ROIv into the main ROIv */
367 ROIv = (SUMA_DRAWN_ROI **)
368 SUMA_realloc(ROIv, (N_ROIv + N_tROI) * sizeof(SUMA_DRAWN_ROI*));
369 if (!ROIv) {
370 SUMA_S_Err("Failed to allocate.");
371 exit(1);
372 }
373
374 /* Now go throught the ROIs and load them if possible into ROIv */
375 SUMA_LHv("Cycling over %d rois\n", N_tROI);
376 for (ii=0; ii < N_tROI; ++ii) {
377 if (!Parent_idcode_str) {
378 /* try to find out what the Parent_idcode_str is */
379 if (tROIv[ii]->Parent_idcode_str && dummy_idcode_str &&
380 strcmp(tROIv[ii]->Parent_idcode_str, dummy_idcode_str)) {
381 fprintf (SUMA_STDERR,
382 "%s: Adopting Parent_idcode_str (%s) in ROI %s\n",
383 FuncName, tROIv[ii]->Parent_idcode_str,
384 tROIv[ii]->Label);
385 /* good, use it as the Parent_idcode_str for all upcoming ROIs */
386 Parent_idcode_str =
387 SUMA_copy_string(tROIv[ii]->Parent_idcode_str);
388 }
389 }
390
391 AddThis = NOPE;
392 if (tROIv[ii]->Parent_idcode_str && dummy_idcode_str &&
393 !strcmp(tROIv[ii]->Parent_idcode_str, dummy_idcode_str)) {
394 AddThis = YUP;
395 } else {
396 if (tROIv[ii]->Parent_idcode_str && dummy_idcode_str &&
397 strcmp(tROIv[ii]->Parent_idcode_str, Parent_idcode_str)) {
398 fprintf (SUMA_STDERR,"Warning %s:\n Ignoring ROI labeled %s\n"
399 "because of Parent_idcode_str mismatch.\n",
400 FuncName, tROIv[ii]->Label);
401 AddThis = NOPE;
402 /* free structure of tROIv[ii] */
403 SUMA_freeDrawnROI (tROIv[ii]); tROIv[ii] = NULL;
404 }
405 else AddThis = YUP;
406
407 }
408 if (AddThis) {
409 if (LocalHead) fprintf (SUMA_STDERR,
410 "%s: Adding %dth ROI to ROIv...\n",
411 FuncName, N_ROIv);
412 ROIv[N_ROIv] = tROIv[ii];
413
414 ++N_ROIv;
415 }
416
417 }
418 /* now free tROIv vector */
419 if (tROIv) SUMA_free(tROIv); tROIv = NULL;
420 }
421
422 if (LocalHead) {
423 fprintf (SUMA_STDERR,"%s: Kept a total of %d ROIs with parent %s\n",
424 FuncName, N_ROIv, Parent_idcode_str);
425
426 }
427
428 if (nodelist) { /* output node list wanted */
429 ddl = SUMA_ROIv2NodeLists (ROIv, N_ROIv, nodups);
430 if (!ddl) {
431 SUMA_S_Err("Failed in SUMA_ROIv2NodeLists");
432 }
433 el = dlist_head(ddl);
434 while (el) {
435 dd = (SUMA_ROI_EXTRACT *)el->data;
436 sprintf(cbuf, ".%03d.1D", dd->label);
437 outlist_name = SUMA_append_string(nodelist, cbuf);
438 /* check for existence of outlist_name */
439 if (SUMA_filexists(outlist_name) && !THD_ok_overwrite()) {
440 fprintf(SUMA_STDERR,"Error %s:\n Output file %s exists.\n",
441 FuncName, outlist_name);
442 exit(1);
443 }
444
445 if (withflag) {
446 SUMA_WRITE_INT_ARRAY_AND_FLAG_1D(dd->vals, dd->N_vals, 1,
447 outlist_name, dd->label);
448 } else {
449 SUMA_WRITE_INT_ARRAY_1D(dd->vals, dd->N_vals, 1, outlist_name);
450 }
451 SUMA_free(outlist_name); outlist_name = NULL;
452 el = dlist_next(el);
453 }
454
455 }
456
457 if (out_name) { /* output dset required */
458 if (!keepsep) {
459 if (!(dset = SUMA_ROIv2Grpdataset ( ROIv, N_ROIv,
460 Parent_idcode_str,
461 pad_to, pad_val,
462 &cmap))) {
463 SUMA_SL_Err("Failed in SUMA_ROIv2Grpdataset");
464 exit(1);
465 }
466 } else {
467 if (!(dset = SUMA_ROIv2MultiDset ( ROIv, N_ROIv,
468 Parent_idcode_str,
469 pad_to, pad_val,
470 &cmap))) {
471 SUMA_SL_Err("Failed in SUMA_ROIv2MultiDset");
472 exit(1);
473 }
474 }
475 if (LocalHead) {
476 fprintf (SUMA_STDERR,"%s: Adding history\n",
477 FuncName);
478
479 }
480
481 /* Add the history line */
482 if (!SUMA_AddNgrHist (dset->ngr, FuncName, argc, argv)) {
483 SUMA_SL_Err("Failed in SUMA_AddNgrHist");
484 exit(1);
485 }
486
487
488 if (LocalHead) {
489 fprintf (SUMA_STDERR,"%s: preparing to write results\n",
490 FuncName);
491
492 }
493
494 if (olabel) {
495 if (!(SUMA_dset_to_Label_dset_cmap(dset, cmap))) {
496 SUMA_S_Err("Failed to make change");
497 exit(1);
498 }
499 }
500
501 /* write nel */
502 switch (Out_Format) {
503 case SUMA_ASCII_NIML:
504 case SUMA_BINARY_NIML:
505 /* open stream */
506 stmp = SUMA_append_string ("file:", out_name);
507 ns = NI_stream_open( stmp , "w" ) ;
508 if( ns == NULL ){
509 fprintf (stderr,"Error %s:\nCan't open %s!"
510 , FuncName, stmp);
511 exit(1);
512 }
513 if (Out_Format == SUMA_ASCII_NIML) {
514 nn = NI_write_element( ns , dset->ngr , NI_TEXT_MODE );
515 } else {
516 nn = NI_write_element( ns , dset->ngr , NI_BINARY_MODE );
517 }
518 if (nn < 0) {
519 SUMA_S_Err ("Failed in NI_write_element");
520 exit(1);
521 }
522
523 /* close the stream */
524 NI_stream_close( ns ) ;
525 break;
526 case SUMA_1D:
527 stmp = SUMA_append_string ("file:", out_name);
528 ns = NI_stream_open( stmp , "w" ) ;
529 if( ns == NULL ){
530 fprintf (stderr,"Error %s:\nCan't open %s!"
531 , FuncName, stmp);
532 exit(1);
533 }
534 if (LocalHead) SUMA_ShowNel(dset->dnel);
535 NI_insert_column(dset->dnel, dset->inel->vec_typ[0],
536 dset->inel->vec[0], 0);
537 if (LocalHead) SUMA_ShowNel(dset->dnel);
538 nn = NI_write_element( ns , dset->dnel ,
539 NI_TEXT_MODE | NI_HEADERSHARP_FLAG);
540 NI_remove_column(dset->dnel, 0);
541 if (nn < 0) {
542 SUMA_S_Err ("Failed in NI_write_element");
543 exit(1);
544 }
545
546 /* close the stream */
547 NI_stream_close( ns ) ;
548 break;
549 default:
550 nn = 1;
551 sss = SUMA_WriteDset_s( out_name, dset,
552 Out_Format, THD_ok_overwrite(),0);
553 if (sss) SUMA_free(sss); sss=NULL;
554 break;
555 }
556
557
558 /* free nel */
559 SUMA_FreeDset(dset); dset = NULL;
560 }
561
562 /* free others */
563 if (stmp) SUMA_free(stmp);
564 if (ROIv) SUMA_free (ROIv);
565 if (outlist_name) SUMA_free(outlist_name);
566 if (ddl) SUMA_free(ddl);
567 if (out_name) SUMA_free(out_name);
568 if (Parent_idcode_str) SUMA_free(Parent_idcode_str);
569 if (dummy_idcode_str) free(dummy_idcode_str); /* this one's allocated
570 by Bob's functions */
571 return(0);
572 }/* Main */
573