1 #include "SUMA_suma.h"
2
usage_SUMA_quickspec(SUMA_GENERIC_ARGV_PARSE * ps)3 void usage_SUMA_quickspec(SUMA_GENERIC_ARGV_PARSE *ps)
4 {
5 static char FuncName[]={"usage_SUMA_quickspec"};
6 char * s = NULL, *sio=NULL;
7 sio = SUMA_help_IO_Args(ps);
8
9 printf (
10 "\nUsage: quickspec \n"
11 " <-tn TYPE NAME> ...\n"
12 " <-tsn TYPE STATE NAME> ...\n"
13 " [<-spec specfile>] [-h/-help]\n"
14 " Use this spec file for quick and dirty way of \n"
15 " loading a surface into SUMA or the command line programs.\n"
16 "\n"
17 "Options:\n"
18 "%s\n"
19 " -tsnad TYPE STATE NAME ANATFLAG LDP: \n"
20 " specify surface type, state, name, anatomical correctness, \n"
21 " and its Local Domain Parent.\n"
22 " ANATFLAG: 'Y' if surface is anatomically correct (default).\n"
23 " 'N' if it is not anatomically correct.\n"
24 " LDP: Name of Local Domain Parent surface.\n"
25 " Use SAME (default) if surface is its own LDP.\n"
26 " -tsnadm TYPE STATE NAME ANATFLAG LDP MARKER: \n"
27 " specify surface type, state, name, anatomical correctness, \n"
28 " Local Domain Parent, and node marker file.\n"
29 " MARKER: A niml.do Displayable Object (DO) to put at every\n"
30 " node of the surface. See @DO.examples for information\n"
31 " about displayable objects\n"
32 " -tsnadl TYPE STATE NAME ANATFLAG LDP LABELDSET: \n"
33 " specify surface type, state, name, anatomical correctness, \n"
34 " Local Domain Parent, and a label dataset file.\n"
35 " LABELDSET: A surface dataset containing node labels.\n"
36 " -spec specfile: Name of spec file output.\n"
37 " Default is quick.spec\n"
38 " The program will only overwrite \n"
39 " quick.spec (the default) spec file.\n"
40 " -h or -help: This message here.\n"
41 "\n"
42 " You can use any combinaton of -tn and -tsn options.\n"
43 " Fields in the spec file that are (or cannot) be specified\n"
44 " by this program are set to default values.\n"
45 "\n This program was written to ward off righteous whiners and is\n"
46 " not meant to replace the venerable @SUMA_Make_Spec_XX scripts.\n"
47 "\n"
48 , sio); SUMA_free(sio); sio = NULL;
49 s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
50 printf(" Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \n\t\t Tue Dec 30\n"
51 "\n");
52 return;
53 }
54
main(int argc,char * argv[])55 int main (int argc,char *argv[])
56 {/* Main */
57 static char FuncName[]={"quickspec"};
58 int detail, kar, i, j, N_surf, N_name, idefstate;
59 FILE *fid = NULL;
60 char *spec_name, stmp[500], *Unique_st;
61 SUMA_SO_File_Type TypeC[SUMA_MAX_N_SURFACE_SPEC];
62 static char
63 *State[SUMA_MAX_N_SURFACE_SPEC],
64 *Name_coord[SUMA_MAX_N_SURFACE_SPEC],
65 *Name_topo[SUMA_MAX_N_SURFACE_SPEC],
66 Anat[SUMA_MAX_N_SURFACE_SPEC],
67 *LDP[SUMA_MAX_N_SURFACE_SPEC],
68 *MARK[SUMA_MAX_N_SURFACE_SPEC],
69 *LABEL[SUMA_MAX_N_SURFACE_SPEC];
70 SUMA_GENERIC_ARGV_PARSE *ps;
71 SUMA_Boolean brk;
72
73 SUMA_mainENTRY;
74
75 /* allocate space for CommonFields structure */
76 SUMAg_CF = SUMA_Create_CommonFields ();
77 if (SUMAg_CF == NULL) {
78 fprintf( SUMA_STDERR,
79 "Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
80 exit(1);
81 }
82
83 ps = SUMA_Parse_IO_Args(argc, argv, "-t;");
84
85 if (argc < 3)
86 {
87 usage_SUMA_quickspec (ps);
88 exit (0); /* status 0 on -help 18 Sep 2018 [rickr] */
89 }
90
91 kar = 1;
92 brk = NOPE;
93 detail = 1;
94 N_surf = 0;
95 N_name = 0;
96 spec_name = NULL;
97 while (kar < argc) { /* loop accross command ine options */
98 /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
99 if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
100 usage_SUMA_quickspec(ps);
101 exit (0); /* status 0 on -help 18 Sep 2018 [rickr] */
102 }
103 if (!brk && (strcmp(argv[kar], "-spec") == 0)) {
104 kar ++;
105 if (kar >= argc) {
106 fprintf (SUMA_STDERR, "need argument after -spec \n");
107 exit (1);
108 }
109 spec_name = argv[kar];
110 if (!THD_ok_overwrite() && SUMA_filexists(spec_name)) {
111 fprintf (SUMA_STDERR,
112 "File %s exists, choose another one.\n", spec_name);
113 exit(1);
114 }
115 brk = YUP;
116 }
117 if (!brk && (strcmp(argv[kar], "-tn") == 0)) {
118 if (N_surf >= SUMA_MAX_N_SURFACE_SPEC) {
119 SUMA_SL_Err("Exceeding maximum number of allowed surfaces...");
120 exit(1);
121 }
122 /* get the type */
123 kar ++;
124 if (kar >= argc) {
125 fprintf (SUMA_STDERR, "Type argument must follow -tn \n");
126 exit (1);
127 }
128 TypeC[N_surf] = SUMA_SurfaceTypeCode(argv[kar]);
129 if (TypeC[N_surf] == SUMA_FT_ERROR ||
130 TypeC[N_surf] == SUMA_FT_NOT_SPECIFIED) {
131 fprintf (SUMA_STDERR, "%s is a bad file type.\n", argv[kar]);
132 exit(1);
133 }
134 /* get the name */
135 if (TypeC[N_surf] == SUMA_SUREFIT || TypeC[N_surf] == SUMA_VEC)
136 N_name = 2;
137 else N_name = 1;
138 if (kar+N_name >= argc) {
139 fprintf (SUMA_STDERR, "need %d elements for NAME \n", N_name);
140 exit (1);
141 }
142 kar ++; Name_coord[N_surf] = argv[kar];
143 if (N_name == 2) {
144 kar ++; Name_topo[N_surf] = argv[kar];
145 } else {
146 Name_topo[N_surf] = NULL;
147 }
148 State[N_surf] = NULL;
149 Anat[N_surf] = 'Y';
150 LDP[N_surf] = NULL;
151 ++N_surf;
152 brk = YUP;
153 }
154 if (!brk && (strcmp(argv[kar], "-tsn") == 0)) {
155 if (N_surf >= SUMA_MAX_N_SURFACE_SPEC) {
156 SUMA_SL_Err("Exceeding maximum number of allowed surfaces...");
157 exit(1);
158 }
159 /* get the type */
160 kar ++;
161 if (kar >= argc) {
162 fprintf (SUMA_STDERR, "TYPE argument must follow -tsn \n");
163 exit (1);
164 }
165 TypeC[N_surf] = SUMA_SurfaceTypeCode(argv[kar]);
166 if ( TypeC[N_surf] == SUMA_FT_ERROR ||
167 TypeC[N_surf] == SUMA_FT_NOT_SPECIFIED) {
168 fprintf (SUMA_STDERR, "%s is a bad file TYPE.\n", argv[kar]);
169 exit(1);
170 }
171 /* get the state */
172 kar ++;
173 if (kar >= argc) {
174 fprintf (SUMA_STDERR,
175 "STATE argument must follow TYPE with -tsn \n");
176 exit (1);
177 }
178 State[N_surf] = argv[kar];
179
180 /* get the name */
181 if ( TypeC[N_surf] == SUMA_SUREFIT ||
182 TypeC[N_surf] == SUMA_VEC) N_name = 2;
183 else N_name = 1;
184 if (kar+N_name >= argc) {
185 fprintf (SUMA_STDERR, "need %d elements for NAME \n", N_name);
186 exit (1);
187 }
188 kar ++; Name_coord[N_surf] = argv[kar];
189 if (N_name == 2) {
190 kar ++; Name_topo[N_surf] = argv[kar];
191 } else {
192 Name_topo[N_surf] = NULL;
193 }
194
195 Anat[N_surf] = 'Y';
196 LDP[N_surf] = NULL;
197 ++N_surf;
198 brk = YUP;
199 }
200
201 if (!brk && (strcmp(argv[kar], "-tsnad") == 0)) {
202 if (N_surf >= SUMA_MAX_N_SURFACE_SPEC) {
203 SUMA_SL_Err("Exceeding maximum number of allowed surfaces...");
204 exit(1);
205 }
206 /* get the type */
207 kar ++;
208 if (kar >= argc) {
209 fprintf (SUMA_STDERR, "TYPE argument must follow -tsnad \n");
210 exit (1);
211 }
212 TypeC[N_surf] = SUMA_SurfaceTypeCode(argv[kar]);
213 if ( TypeC[N_surf] == SUMA_FT_ERROR ||
214 TypeC[N_surf] == SUMA_FT_NOT_SPECIFIED) {
215 fprintf (SUMA_STDERR, "%s is a bad file TYPE.\n", argv[kar]);
216 exit(1);
217 }
218 /* get the state */
219 kar ++;
220 if (kar >= argc) {
221 fprintf (SUMA_STDERR,
222 "STATE argument must follow TYPE with -tsnad \n");
223 exit (1);
224 }
225 State[N_surf] = argv[kar];
226
227 /* get the name */
228 if ( TypeC[N_surf] == SUMA_SUREFIT ||
229 TypeC[N_surf] == SUMA_VEC) N_name = 2;
230 else N_name = 1;
231 if (kar+N_name >= argc) {
232 fprintf (SUMA_STDERR, "need %d elements for NAME \n", N_name);
233 exit (1);
234 }
235 kar ++; Name_coord[N_surf] = argv[kar];
236 if (N_name == 2) {
237 kar ++; Name_topo[N_surf] = argv[kar];
238 } else {
239 Name_topo[N_surf] = NULL;
240 }
241
242
243 /* get the anatomical flag */
244 kar ++;
245 if (kar >= argc) {
246 fprintf (SUMA_STDERR,
247 "Anatomical flag must follow NAME with -tsnad \n");
248 exit (1);
249 }
250 Anat[N_surf] = SUMA_TO_UPPER_C(argv[kar][0]);
251 if (Anat[N_surf] != 'Y' && Anat[N_surf] != 'N') {
252 SUMA_S_Err("Anatomical flag must be either 'y' or 'n'");
253 exit (1);
254 }
255 /* get the LDP */
256 kar ++;
257 if (kar >= argc) {
258 fprintf (SUMA_STDERR,
259 "LocalDomainParent must follow Anatomical flag with -tsnad \n");
260 exit (1);
261 }
262 LDP[N_surf] = argv[kar];
263
264 ++N_surf;
265 brk = YUP;
266 }
267
268 if (!brk && (strcmp(argv[kar], "-tsnadm") == 0)) {
269 if (N_surf >= SUMA_MAX_N_SURFACE_SPEC) {
270 SUMA_SL_Err("Exceeding maximum number of allowed surfaces...");
271 exit(1);
272 }
273 /* get the type */
274 kar ++;
275 if (kar >= argc) {
276 fprintf (SUMA_STDERR, "TYPE argument must follow -tsnad \n");
277 exit (1);
278 }
279 TypeC[N_surf] = SUMA_SurfaceTypeCode(argv[kar]);
280 if ( TypeC[N_surf] == SUMA_FT_ERROR ||
281 TypeC[N_surf] == SUMA_FT_NOT_SPECIFIED) {
282 fprintf (SUMA_STDERR, "%s is a bad file TYPE.\n", argv[kar]);
283 exit(1);
284 }
285 /* get the state */
286 kar ++;
287 if (kar >= argc) {
288 fprintf (SUMA_STDERR,
289 "STATE argument must follow TYPE with -tsnad \n");
290 exit (1);
291 }
292 State[N_surf] = argv[kar];
293
294 /* get the name */
295 if ( TypeC[N_surf] == SUMA_SUREFIT ||
296 TypeC[N_surf] == SUMA_VEC) N_name = 2;
297 else N_name = 1;
298 if (kar+N_name >= argc) {
299 fprintf (SUMA_STDERR, "need %d elements for NAME \n", N_name);
300 exit (1);
301 }
302 kar ++; Name_coord[N_surf] = argv[kar];
303 if (N_name == 2) {
304 kar ++; Name_topo[N_surf] = argv[kar];
305 } else {
306 Name_topo[N_surf] = NULL;
307 }
308
309
310 /* get the anatomical flag */
311 kar ++;
312 if (kar >= argc) {
313 fprintf (SUMA_STDERR,
314 "Anatomical flag must follow NAME with -tsnad \n");
315 exit (1);
316 }
317 Anat[N_surf] = SUMA_TO_UPPER_C(argv[kar][0]);
318 if (Anat[N_surf] != 'Y' && Anat[N_surf] != 'N') {
319 SUMA_S_Err("Anatomical flag must be either 'y' or 'n'");
320 exit (1);
321 }
322 /* get the LDP */
323 kar ++;
324 if (kar >= argc) {
325 fprintf (SUMA_STDERR,
326 "LocalDomainParent must follow Anatomical flag with -tsnad \n");
327 exit (1);
328 }
329 LDP[N_surf] = argv[kar];
330
331 /* get the nodeMarker */
332 kar ++;
333 if (kar >= argc) {
334 fprintf (SUMA_STDERR,
335 "LocalDomainParent must follow Anatomical flag with -tsnad \n");
336 exit (1);
337 }
338 MARK[N_surf] = argv[kar];
339 ++N_surf;
340 brk = YUP;
341 }
342
343 if (!brk && (strcmp(argv[kar], "-tsnadl") == 0)) {
344 if (N_surf >= SUMA_MAX_N_SURFACE_SPEC) {
345 SUMA_SL_Err("Exceeding maximum number of allowed surfaces...");
346 exit(1);
347 }
348 /* get the type */
349 kar ++;
350 if (kar >= argc) {
351 fprintf (SUMA_STDERR, "TYPE argument must follow -tsnad \n");
352 exit (1);
353 }
354 TypeC[N_surf] = SUMA_SurfaceTypeCode(argv[kar]);
355 if ( TypeC[N_surf] == SUMA_FT_ERROR ||
356 TypeC[N_surf] == SUMA_FT_NOT_SPECIFIED) {
357 fprintf (SUMA_STDERR, "%s is a bad file TYPE.\n", argv[kar]);
358 exit(1);
359 }
360 /* get the state */
361 kar ++;
362 if (kar >= argc) {
363 fprintf (SUMA_STDERR,
364 "STATE argument must follow TYPE with -tsnad \n");
365 exit (1);
366 }
367 State[N_surf] = argv[kar];
368
369 /* get the name */
370 if ( TypeC[N_surf] == SUMA_SUREFIT ||
371 TypeC[N_surf] == SUMA_VEC) N_name = 2;
372 else N_name = 1;
373 if (kar+N_name >= argc) {
374 fprintf (SUMA_STDERR, "need %d elements for NAME \n", N_name);
375 exit (1);
376 }
377 kar ++; Name_coord[N_surf] = argv[kar];
378 if (N_name == 2) {
379 kar ++; Name_topo[N_surf] = argv[kar];
380 } else {
381 Name_topo[N_surf] = NULL;
382 }
383
384
385 /* get the anatomical flag */
386 kar ++;
387 if (kar >= argc) {
388 fprintf (SUMA_STDERR,
389 "Anatomical flag must follow NAME with -tsnad \n");
390 exit (1);
391 }
392 Anat[N_surf] = SUMA_TO_UPPER_C(argv[kar][0]);
393 if (Anat[N_surf] != 'Y' && Anat[N_surf] != 'N') {
394 SUMA_S_Err("Anatomical flag must be either 'y' or 'n'");
395 exit (1);
396 }
397 /* get the LDP */
398 kar ++;
399 if (kar >= argc) {
400 fprintf (SUMA_STDERR,
401 "LocalDomainParent must follow Anatomical flag with -tsnad \n");
402 exit (1);
403 }
404 LDP[N_surf] = argv[kar];
405
406 /* get the nodeMarker */
407 kar ++;
408 if (kar >= argc) {
409 fprintf (SUMA_STDERR,
410 "LocalDomainParent must follow Anatomical flag with -tsnad \n");
411 exit (1);
412 }
413 LABEL[N_surf] = argv[kar];
414 ++N_surf;
415 brk = YUP;
416 }
417
418 if (!brk) {
419 fprintf (SUMA_STDERR,
420 "Error %s: Option %s not understood. Try -help for usage\n",
421 FuncName, argv[kar]);
422 exit (1);
423 } else {
424 brk = NOPE;
425 kar ++;
426 }
427 }
428
429 /* write out the comments */
430 if (!spec_name) {
431 fid = fopen("quick.spec", "w");
432 } else {
433 fid = fopen(spec_name,"w");
434 }
435 if (!fid){
436 SUMA_SL_Err("Failed to open file for output");
437 exit(1);
438 }
439 fprintf(fid,"# define the group\n");
440 fprintf(fid,"\tGroup = QuickSpec\n");
441
442
443 /* now create a list of unique states */
444 idefstate = 0;
445 if (!State[0]) {
446 Unique_st = SUMA_copy_string ("\tStateDef = S_1\n");
447 idefstate = 1;
448 } else {
449 sprintf(stmp, "\tStateDef = %s\n", State[0]);
450 Unique_st = SUMA_copy_string (stmp);
451 }
452 for (i=1; i < N_surf; ++i) {
453 if (!State[i]) {
454 ++idefstate;
455 sprintf(stmp,"\tStateDef = S_%d\n", idefstate);
456 Unique_st = SUMA_append_replace_string (Unique_st, stmp, "", 1);
457 } else {
458 if (SUMA_iswordin(Unique_st, State[i]) != 1) {
459 sprintf(stmp, "\tStateDef = %s\n", State[i]);
460 Unique_st = SUMA_append_replace_string(Unique_st, stmp, "", 1);
461 }
462 }
463 }
464 fprintf (fid, "# define the various States\n");
465 fprintf (fid, "%s\n", Unique_st);
466
467 /* check on LDP correctness */
468 for (i=0; i < N_surf; ++i) {
469 if (LDP[i]) {
470 if (!strcmp(LDP[i],"same") || !strcmp(LDP[i],"Same"))
471 SUMA_TO_UPPER(LDP[i]);
472 if (strcmp(LDP[i],"SAME")) {
473 j= 0;
474 while (j<N_surf && strcmp(LDP[i], Name_coord[j])) ++j;
475 if (j == N_surf) {
476 SUMA_S_Errv("Could not find a surface named %s\n"
477 "to be the local domain parent of %s\n",
478 LDP[i], Name_coord[i]);
479 exit(1);
480 }
481 if (!strcmp(LDP[i], Name_coord[i])) {/* reset to SAME*/
482 LDP[i] = NULL; /* this results is SAME below */
483 }
484 }
485 }
486 }
487 /* now loop accross surfaces and write out the results */
488 idefstate = 0;
489 for (i=0; i < N_surf; ++i) {
490 fprintf(fid, "\nNewSurface\n");
491 fprintf(fid, "\tSurfaceType = %s\n", SUMA_SurfaceTypeString(TypeC[i]));
492 if (!State[i]) {
493 ++idefstate;
494 fprintf(fid, "\tSurfaceState = S_%d\n", idefstate);
495 } else fprintf(fid, "\tSurfaceState = %s\n", State[i]);
496 if (Name_topo[i]) {
497 fprintf(fid, "\tCoordFile = %s\n", Name_coord[i]);
498 fprintf(fid, "\tTopoFile = %s\n", Name_topo[i]);
499 } else {
500 fprintf(fid, "\tSurfaceName = %s\n", Name_coord[i]);
501 }
502 /* add LocalDomainParent */
503 if (LDP[i]) fprintf(fid, "\tLocalDomainParent = %s\n", LDP[i]);
504 else fprintf(fid, "\tLocalDomainParent = SAME\n");
505 /* add Anatomical */
506 if (Anat[i]) fprintf(fid, "\tAnatomical = %c\n", Anat[i]);
507 else fprintf(fid, "\tAnatomical = Y\n");
508 /* add nodeMarker */
509 if (MARK[i]) fprintf(fid, "\tNodeMarker = %s\n", MARK[i]);
510 if (LABEL[i]) fprintf(fid, "\tLabelDset = %s\n", LABEL[i]);
511
512 /* binary ? */
513 switch (TypeC[i]) {
514 case SUMA_FREE_SURFER:
515 if (!SUMA_isExtension(Name_coord[i], ".asc")) {
516 fprintf(fid, "\tSurfaceFormat = BINARY\n");
517 }
518 break;
519 default:
520 break;
521 }
522 }
523
524 fclose(fid); fid = NULL;
525
526 if (Unique_st) SUMA_free(Unique_st); Unique_st = NULL;
527
528 if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
529 if (!SUMA_Free_CommonFields(SUMAg_CF)) {
530 fprintf(SUMA_STDERR,"Error %s: SUMAg_CF Cleanup Failed!\n", FuncName);
531 exit(1);
532 }
533
534 SUMA_RETURN(0);
535
536 }/* main quickspec */
537