1
2 /*----------------------------------------------------------------------
3 * history:
4 *
5 * 11 Dec 2003 [rickr]
6 * - added functions:
7 * o SUMA_spec_select_surfs - restrict spec struct from name list
8 * o SUMA_swap_spec_entries - swap 2 entries in spec struct
9 * o SUMA_unique_name_ind - verify unique surf name in spec
10 * o SUMA_coord_file - get file name, based on surf type
11 * o swap_strings - swap 2 strings via 3rd
12 *----------------------------------------------------------------------
13 */
14
15 /* Header FILES */
16
17 #include "SUMA_suma.h"
18
19
20 /*#define DO_SCALE_RANGE *//*!< scale node coordinates to 0 <--> 100. DO NOT USE IT, OBSOLETE*/
21 #ifndef DO_SCALE_RANGE
22 #define DO_SCALE 319.7 /*!< scale node coordinates by specified factor. Useful for tesscon coordinate system in iv files*/
23 #endif
24
25 /* CODE */
26
27 /*!
28 SUMA_AllocSpecFields (SUMA_SurfSpecFile *Spec)
29 \brief Function to allocate space for the spec file fields.
30 Clumsy but does the work, needed to get around stack size limits of 8 Mb
31 \sa SUMA_FreeSpecFields
32 */
SUMA_AllocSpecFields(SUMA_SurfSpecFile * Spec)33 SUMA_Boolean SUMA_AllocSpecFields (SUMA_SurfSpecFile *Spec)
34 {
35 static char FuncName[]={"SUMA_AllocSpecFields"};
36 SUMA_Boolean LocalHead = NOPE;
37
38 SUMA_ENTRY;
39
40
41 if (!Spec) SUMA_RETURN(NOPE);
42
43 Spec->N_Surfs = -1; /* flag for initialization */
44 Spec->N_States = 0;
45 Spec->N_Groups = 0;
46
47 Spec->SurfaceType = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC ,
48 SUMA_MAX_LABEL_LENGTH, sizeof(char));
49 if (!Spec->SurfaceType) {
50 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
51 }
52 Spec->SurfaceFormat = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
53 SUMA_MAX_LABEL_LENGTH , sizeof(char));
54 if (!Spec->SurfaceFormat) {
55 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
56 }
57 Spec->TopoFile = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
58 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
59 if (!Spec->TopoFile) {
60 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
61 }
62 Spec->CoordFile = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
63 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
64 if (!Spec->CoordFile) {
65 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
66 }
67 Spec->MappingRef = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
68 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
69 if (!Spec->MappingRef) {
70 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
71 }
72 Spec->SureFitVolParam = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
73 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
74 if (!Spec->SureFitVolParam) {
75 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
76 }
77 Spec->SurfaceFile = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
78 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
79 if (!Spec->SurfaceFile) {
80 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
81 }
82 Spec->VolParName = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
83 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
84 if (!Spec->VolParName) {
85 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
86 }
87 Spec->IDcode = (char **)SUMA_calloc(SUMA_MAX_N_SURFACE_SPEC, sizeof(char*));
88 if (!Spec->IDcode) {
89 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
90 }
91 Spec->State = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
92 SUMA_MAX_LABEL_LENGTH, sizeof(char));
93 if (!Spec->State) {
94 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
95 }
96 Spec->Group = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
97 SUMA_MAX_LABEL_LENGTH, sizeof(char));
98 if (!Spec->Group) {
99 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
100 }
101 Spec->SurfaceLabel = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
102 SUMA_MAX_LABEL_LENGTH, sizeof(char));
103 if (!Spec->SurfaceLabel) {
104 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
105 }
106 Spec->EmbedDim = (int *)SUMA_calloc(SUMA_MAX_N_SURFACE_SPEC, sizeof(int));
107 if (!Spec->EmbedDim) {
108 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
109 }
110
111 /* modifications to the lame MappingRef field */
112 Spec->AnatCorrect = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
113 SUMA_MAX_LABEL_LENGTH, sizeof(char));
114 if (!Spec->AnatCorrect) {
115 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
116 }
117 Spec->Hemisphere = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
118 SUMA_MAX_LABEL_LENGTH, sizeof(char));
119 if (!Spec->Hemisphere) {
120 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
121 }
122 Spec->DomainGrandParentID = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
123 SUMA_MAX_LABEL_LENGTH, sizeof(char));
124 if (!Spec->DomainGrandParentID) {
125 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
126 }
127 Spec->OriginatorID = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
128 SUMA_MAX_LABEL_LENGTH, sizeof(char));
129 if (!Spec->OriginatorID) {
130 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
131 }
132 Spec->LocalCurvatureParent = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
133 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
134 if (!Spec->LocalCurvatureParent) {
135 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
136 }
137 Spec->LocalDomainParent = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
138 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
139 if (!Spec->LocalDomainParent) {
140 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
141 }
142 Spec->LabelDset = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
143 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
144 if (!Spec->LabelDset) {
145 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
146 }
147 Spec->NodeMarker = (char **)SUMA_allocate2D(SUMA_MAX_N_SURFACE_SPEC,
148 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
149 if (!Spec->NodeMarker) {
150 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
151 }
152
153 Spec->DO_name = (char **)SUMA_allocate2D(SUMA_MAX_N_DO_SPEC,
154 SUMA_MAX_FP_NAME_LENGTH , sizeof(char));
155 Spec->DO_type = (int *)SUMA_calloc(SUMA_MAX_N_DO_SPEC, sizeof(int));
156 Spec->N_DO = 0;
157
158 Spec->StateList = (char *)SUMA_calloc( SUMA_MAX_N_SURFACE_SPEC*100,
159 sizeof(char));
160 if (!Spec->StateList) {
161 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
162 }
163 Spec->SpecFilePath = (char *)SUMA_calloc(SUMA_MAX_DIR_LENGTH, sizeof(char));
164 if (!Spec->SpecFilePath) {
165 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
166 }
167 Spec->SpecFileName = (char *)SUMA_calloc(SUMA_MAX_NAME_LENGTH, sizeof(char));
168 if (!Spec->SpecFileName) {
169 SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NOPE);
170 }
171
172 SUMA_RETURN(YUP);
173 }
174
175
SUMA_FreeSpecFields(SUMA_SurfSpecFile * Spec)176 SUMA_Boolean SUMA_FreeSpecFields (SUMA_SurfSpecFile *Spec)
177 {
178 static char FuncName[]={"SUMA_FreeSpecFields"};
179
180 SUMA_ENTRY;
181
182 if (!Spec) SUMA_RETURN(YUP);
183 if ( (Spec->N_Surfs < 0 && Spec->N_Surfs != -1) ||
184 Spec->N_Surfs > SUMA_MAX_N_SURFACE_SPEC ) {
185 SUMA_S_Err("Suspicious values in Spec->N_Surfs, will not free fields");
186 SUMA_RETURN(NOPE);
187 }
188 if (Spec->SurfaceType) {
189 SUMA_free2D((char **)Spec->SurfaceType, SUMA_MAX_N_SURFACE_SPEC);
190 Spec->SurfaceType = NULL; }
191 if (Spec->SurfaceFormat) {
192 SUMA_free2D((char **)Spec->SurfaceFormat, SUMA_MAX_N_SURFACE_SPEC);
193 Spec->SurfaceFormat = NULL; }
194 if (Spec->TopoFile) {
195 SUMA_free2D((char **)Spec->TopoFile, SUMA_MAX_N_SURFACE_SPEC);
196 Spec->TopoFile = NULL; }
197 if (Spec->CoordFile) {
198 SUMA_free2D((char **)Spec->CoordFile, SUMA_MAX_N_SURFACE_SPEC);
199 Spec->CoordFile = NULL; }
200 if (Spec->MappingRef) {
201 SUMA_free2D((char **)Spec->MappingRef, SUMA_MAX_N_SURFACE_SPEC);
202 Spec->MappingRef = NULL; }
203 if (Spec->SureFitVolParam) {
204 SUMA_free2D((char **)Spec->SureFitVolParam, SUMA_MAX_N_SURFACE_SPEC);
205 Spec->SureFitVolParam = NULL; }
206
207 if (Spec->SurfaceFile) {
208 SUMA_free2D((char **)Spec->SurfaceFile, SUMA_MAX_N_SURFACE_SPEC);
209 Spec->SurfaceFile = NULL; }
210
211 if (Spec->DO_name) {
212 SUMA_free2D((char **)Spec->DO_name, SUMA_MAX_N_DO_SPEC);
213 Spec->DO_name = NULL; }
214 if (Spec->DO_type) SUMA_free(Spec->DO_type); Spec->DO_type=NULL;
215 Spec->N_DO = 0;
216
217 if (Spec->VolParName) {
218 SUMA_free2D((char **)Spec->VolParName, SUMA_MAX_N_SURFACE_SPEC);
219 Spec->VolParName = NULL; }
220 if (Spec->IDcode) { SUMA_free(Spec->IDcode);
221 Spec->IDcode = NULL; /* IDcode[i] = is a pointer copy */}
222 if (Spec->State) {
223 SUMA_free2D((char **)Spec->State, SUMA_MAX_N_SURFACE_SPEC);
224 Spec->State = NULL; }
225
226 if (Spec->Group) {
227 SUMA_free2D((char **)Spec->Group, SUMA_MAX_N_SURFACE_SPEC);
228 Spec->Group= NULL; }
229
230 if (Spec->SurfaceLabel) {
231 SUMA_free2D((char **)Spec->SurfaceLabel, SUMA_MAX_N_SURFACE_SPEC);
232 Spec->SurfaceLabel = NULL; }
233
234 if (Spec->EmbedDim) { SUMA_free(Spec->EmbedDim);
235 Spec->EmbedDim = NULL; }
236
237 /* modifications to the lame MappingRef field */
238 if (Spec->AnatCorrect) {
239 SUMA_free2D((char **)Spec->AnatCorrect, SUMA_MAX_N_SURFACE_SPEC);
240 Spec->AnatCorrect = NULL; }
241
242 if (Spec->Hemisphere) {
243 SUMA_free2D((char **)Spec->Hemisphere, SUMA_MAX_N_SURFACE_SPEC);
244 Spec->Hemisphere = NULL; }
245
246 if (Spec->DomainGrandParentID) {
247 SUMA_free2D((char **)Spec->DomainGrandParentID, SUMA_MAX_N_SURFACE_SPEC);
248 Spec->DomainGrandParentID = NULL; }
249
250 if (Spec->OriginatorID) {
251 SUMA_free2D((char **)Spec->OriginatorID, SUMA_MAX_N_SURFACE_SPEC);
252 Spec->OriginatorID = NULL; }
253
254 if (Spec->LocalCurvatureParent) {
255 SUMA_free2D((char **)Spec->LocalCurvatureParent, SUMA_MAX_N_SURFACE_SPEC);
256 Spec->LocalCurvatureParent = NULL; }
257
258 if (Spec->LocalDomainParent) {
259 SUMA_free2D((char **)Spec->LocalDomainParent, SUMA_MAX_N_SURFACE_SPEC);
260 Spec->LocalDomainParent = NULL; }
261
262 if (Spec->LabelDset) {
263 SUMA_free2D((char **)Spec->LabelDset, SUMA_MAX_N_SURFACE_SPEC);
264 Spec->LabelDset = NULL; }
265
266 if (Spec->NodeMarker) {
267 SUMA_free2D((char **)Spec->NodeMarker, SUMA_MAX_N_SURFACE_SPEC);
268 Spec->NodeMarker = NULL; }
269
270 Spec->N_Surfs = -2; /* flag for freeing */
271 Spec->N_States = 0;
272 Spec->N_Groups = 0;
273
274
275 if (Spec->StateList) { SUMA_free(Spec->StateList);
276 Spec->StateList = NULL; }
277 if (Spec->SpecFilePath) { SUMA_free(Spec->SpecFilePath);
278 Spec->SpecFilePath = NULL; }
279 if (Spec->SpecFileName) { SUMA_free(Spec->SpecFileName);
280 Spec->SpecFileName = NULL; }
281
282 SUMA_RETURN(YUP);
283 }
284
285 /*!
286 \brief Function to write surface objects to disk in various formats
287 ans = SUMA_Save_Surface_Object (void * F_name, SUMA_SurfaceObject *SO, SUMA_SO_File_Type SO_FT,
288 SUMA_SO_File_Format SO_FF, void *someparam);
289 \param F_name (void *)
290 For SUMA_INVENTOR_GENERIC F_name is (char *) containing path (if any) and filename of surface
291 For SUMA_SUREFIT F_name is (SUMA_SFname *) containing full topo and coord names, with path (if any)
292 For SUMA_FREE_SURFER F_name is (char *) name of .asc file (with path)
293 For SUMA_VEC (a dumb ascii format), F_name is (SUMA_SFname *) containing the nodelist file in name_coord
294 and facesetlist file in name_topo (path included).
295 For SUMA_PLY (char *) name of .ply file (with path)
296 For SUMA_OPENDX_MESH (char *) name of .dx file (with path)
297 \param SO_FT (SUMA_SO_File_Type) file type to be read (inventor, free surfer , Surefit )
298 \param SO_FF (SUMA_SO_File_Format) Ascii or Binary (only ascii at the moment, except for .ply files)
299 \param someparam (void *) a pointer used to pass extra parameters. At the moment, used for passing a parent
300 surface when writing FreeSurferPatches
301 \sa SUMA_Load_Surface_Object()
302
303 NOTE:
304 Vertex coordinates are written as in SO->NodeList
305 The Volume Parent transformation is not undone.
306 For SureFit surfaces, the volume param shift is not undone.
307 */
SUMA_Save_Surface_Object_Wrap(char * surf_name,char * topo_name,SUMA_SurfaceObject * SO,SUMA_SO_File_Type SO_FT,SUMA_SO_File_Format SO_FF,void * someparam)308 void * SUMA_Save_Surface_Object_Wrap (
309 char *surf_name, char *topo_name,
310 SUMA_SurfaceObject *SO,
311 SUMA_SO_File_Type SO_FT, SUMA_SO_File_Format SO_FF,
312 void *someparam)
313 {
314 static char FuncName[]={"SUMA_Save_Surface_Object_Wrap"};
315 void *SO_name=NULL;
316 SUMA_Boolean exists;
317
318 SUMA_ENTRY;
319
320 if (!surf_name || !SO) {
321 SUMA_S_Err("NULL input"); SUMA_RETURN(NULL);
322 }
323
324 if (SO_FT == SUMA_FT_NOT_SPECIFIED) {
325 SO_FT = SUMA_GuessSurfFormatFromExtension(surf_name, "usegifti.gii");
326 }
327
328 if (!(SO_name = SUMA_2Prefix2SurfaceName (surf_name, topo_name,
329 NULL, NULL, SO_FT, &exists))) {
330 SUMA_S_Err("Failed to form SO_name");
331 SUMA_RETURN(NULL);
332 }
333 if (!SUMA_Save_Surface_Object (SO_name, SO, SO_FT, SO_FF, someparam)) {
334 SUMA_S_Err("Failed to save surface");
335 SUMA_RETURN(NULL);
336 }
337
338 SUMA_RETURN(SO_name);
339 }
340
SUMA_Save_Surface_Object(void * F_name,SUMA_SurfaceObject * SO,SUMA_SO_File_Type SO_FT,SUMA_SO_File_Format SO_FF,void * someparam)341 SUMA_Boolean SUMA_Save_Surface_Object (void * F_name, SUMA_SurfaceObject *SO,
342 SUMA_SO_File_Type SO_FT,
343 SUMA_SO_File_Format SO_FF,
344 void *someparam)
345 {/*SUMA_Save_Surface_Object*/
346 static char FuncName[]={"SUMA_Save_Surface_Object"};
347
348 SUMA_ENTRY;
349
350 if (!F_name) {
351 SUMA_S_Err("Null filename!");
352 SUMA_RETURN(NOPE);
353 }
354 switch (SO_FT) {
355 case SUMA_OBJ_MESH:
356 SUMA_S_Err("Nothing for OBJ_MESH yet");
357 SUMA_RETURN(NOPE);
358 break;
359 case SUMA_OPENDX_MESH:
360 if (!SUMA_OpenDX_Write ((char *)F_name, SO)) {
361 fprintf (SUMA_STDERR,
362 "Error %s: Failed to write SUMA_OPENDX_MESH surface.\n"
363 , FuncName);
364 SUMA_RETURN (NOPE);
365 }
366 break;
367 case SUMA_PLY:
368 if (!SUMA_Ply_Write ((char *)F_name, SO)) {
369 fprintf (SUMA_STDERR,
370 "Error %s: Failed to write PLY surface.\n"
371 , FuncName);
372 SUMA_RETURN (NOPE);
373 }
374 break;
375 case SUMA_STL:
376 if (!SUMA_STL_Write ((char *)F_name, SO)) {
377 fprintf (SUMA_STDERR,
378 "Error %s: Failed to write STL surface.\n"
379 , FuncName);
380 SUMA_RETURN (NOPE);
381 }
382 break;
383 case SUMA_MNI_OBJ:
384 if (!SUMA_MNI_OBJ_Write ((char *)F_name, SO)) {
385 fprintf (SUMA_STDERR,
386 "Error %s: Failed to write MNI_OBJ surface.\n"
387 , FuncName);
388 SUMA_RETURN (NOPE);
389 }
390 break;
391 case SUMA_FREE_SURFER:
392 if (SO_FF == SUMA_FF_NOT_SPECIFIED) SO_FF = SUMA_ASCII;
393 if (SO_FF != SUMA_ASCII) {
394 fprintf (SUMA_STDERR,
395 "Warning %s: "
396 "Only ASCII supported for Free Surfer surfaces.\n"
397 , FuncName);
398 }
399 if (!SUMA_FS_Write ((char *)F_name, SO,
400 "!ascii version in FreeSurfer format (SUMA)")) {
401 fprintf (SUMA_STDERR,
402 "Error %s: Failed to write FreeSurfer surface.\n"
403 , FuncName);
404 SUMA_RETURN (NOPE);
405 }
406 break;
407 case SUMA_FREE_SURFER_PATCH:
408 if (SO_FF == SUMA_FF_NOT_SPECIFIED) SO_FF = SUMA_ASCII;
409 if (SO_FF != SUMA_ASCII) {
410 fprintf (SUMA_STDERR,
411 "Warning %s: "
412 "Only ASCII supported for Free Surfer surface patches.\n"
413 , FuncName);
414 }
415 if (!SUMA_FreeSurfer_WritePatch ((char *)F_name, SO, NULL,
416 (SUMA_SurfaceObject *)someparam)) {
417 fprintf (SUMA_STDERR,
418 "Error %s: Failed to write FreeSurfer surface.\n"
419 , FuncName);
420 SUMA_RETURN (NOPE);
421 }
422 break;
423 case SUMA_SUREFIT:
424 if (SO_FF == SUMA_FF_NOT_SPECIFIED) SO_FF = SUMA_ASCII;
425 if (SO_FF != SUMA_ASCII) {
426 fprintf (SUMA_STDERR,
427 "Warning %s: Only ASCII supported for SureFit surfaces.\n"
428 , FuncName);
429 }
430 if (!SUMA_SureFit_Write ((SUMA_SFname *)F_name, SO)) {
431 fprintf (SUMA_STDERR,
432 "Error %s: Failed to write SureFit surface.\n"
433 , FuncName);
434 SUMA_RETURN (NOPE);
435 }
436 break;
437 case SUMA_VEC:
438 if (SO_FF == SUMA_FF_NOT_SPECIFIED) SO_FF = SUMA_ASCII;
439 if (SO_FF != SUMA_ASCII) {
440 fprintf (SUMA_STDERR,
441 "Warning %s: Only ASCII supported for vec surfaces.\n"
442 , FuncName);
443 }
444 if (!SUMA_VEC_Write ((SUMA_SFname *)F_name, SO)) {
445 fprintf (SUMA_STDERR,
446 "Error %s: Failed to write vec surface.\n"
447 , FuncName);
448 SUMA_RETURN (NOPE);
449 }
450 break;
451 case SUMA_BYU:
452 if (SO_FF == SUMA_FF_NOT_SPECIFIED) SO_FF = SUMA_ASCII;
453 if (SO_FF != SUMA_ASCII) {
454 fprintf (SUMA_STDERR,
455 "Warning %s: Only ASCII supported for BYU surfaces.\n"
456 , FuncName);
457 }
458 if (!SUMA_BYU_Write ((char *)F_name, SO, 1)) {
459 fprintf (SUMA_STDERR,
460 "Error %s: Failed to write BYU surface.\n"
461 , FuncName);
462 SUMA_RETURN (NOPE);
463 }
464 break;
465 case SUMA_INVENTOR_GENERIC:
466 fprintf (SUMA_STDERR,
467 "Error %s: "
468 "Not ready to deal with inventor surface writing.\n"
469 , FuncName);
470 SUMA_RETURN (NOPE);
471 break;
472 case SUMA_BRAIN_VOYAGER:
473 fprintf (SUMA_STDERR,
474 "Error %s: "
475 "Not ready to deal with brain voyager surface writing.\n"
476 , FuncName);
477 SUMA_RETURN (NOPE);
478 break;
479 case SUMA_GIFTI:
480 if (!SUMA_GIFTI_Write ((char *)F_name, SO, SO_FF)) {
481 fprintf (SUMA_STDERR,
482 "Error %s: Failed to write GIFTI surface.\n"
483 , FuncName);
484 SUMA_RETURN (NOPE);
485 }
486 break;
487 case SUMA_PREDEFINED:
488 if (!SUMA_GIFTI_Write ((char *)F_name, SO, SUMA_ASCII)) {
489 fprintf (SUMA_STDERR,
490 "Error %s: Failed to write predefined GIFTI surface.\n"
491 , FuncName);
492 SUMA_RETURN (NOPE);
493 }
494 break;
495 case SUMA_FT_NOT_SPECIFIED:
496 default:
497 fprintf (SUMA_STDERR, "Error %s: Bad surface type.\n", FuncName);
498 SUMA_RETURN (NOPE);
499
500 }
501
502 SUMA_RETURN (YUP);
503 }
504
505 /*!
506 \brief for a new SO, calculate the following:
507 Normals, dimensions, SUMA's NodeMarker FaceSetMarker, etc.
508 */
SUMA_PrepSO_GeomProp_GL(SUMA_SurfaceObject * SO)509 SUMA_Boolean SUMA_PrepSO_GeomProp_GL(SUMA_SurfaceObject *SO)
510 {
511 static char FuncName[]={"SUMA_PrepSO_GeomProp_GL"};
512 static int iwarn=0;
513 int k, ND, id;
514 SUMA_SURF_NORM SN;
515 byte *PatchNodeMask=NULL;
516 SUMA_SurfaceViewer *sv=NULL;
517 SUMA_Boolean LocalHead = NOPE;
518
519 SUMA_ENTRY;
520
521 SUMA_LHv("Unleashed on surface %s\n", CHECK_NULL_STR(SO->Label));
522
523 /* Calculate Min, Max, Mean */
524
525 if (!SUMA_isSODimInitialized(SO)) {
526 if (!SUMA_SetSODims(SO)) {
527 SUMA_S_Err("Failed to set dims!");
528 SUMA_RETURN(NOPE);
529 }
530 } else {
531 SUMA_LH("SODim initialized already");
532 }
533
534 /* calculate the center and dimensions for the nodes in the patch only */
535 PatchNodeMask = SUMA_MaskOfNodesInPatch(SO, &(SO->N_patchNode));
536 if (!SO->N_patchNode || SO->N_patchNode == SO->N_Node) {
537 SUMA_LHv("Up here, isSphere = %d\n", SO->isSphere);
538 if (!PatchNodeMask ) {
539 SUMA_SL_Err("Failed in SUMA_MaskOfNodesInPatch.\n"
540 "Using values from all nodes.");
541 } else {
542 SUMA_LH("Using values from all nodes.");
543 }
544 if (!SUMA_IS_GEOM_SYMM(SO->isSphere)) {
545 SUMA_COPY_VEC(SO->Center, SO->patchCenter, 3, float, float);
546 } else {
547 SUMA_COPY_VEC(SO->SphereCenter, SO->patchCenter, 3, float, float);
548 }
549 SUMA_COPY_VEC(SO->MinDims, SO->patchMinDims, 3, float, float);
550 SUMA_COPY_VEC(SO->MaxDims, SO->patchMaxDims, 3, float, float);
551 SO->patchaMaxDims = SO->aMaxDims;
552 SO->patchaMinDims = SO->aMinDims;
553 }else {
554 SUMA_LH("Down there");
555 SUMA_MIN_MAX_SUM_VECMAT_MASK_COL (
556 SO->NodeList, SO->N_Node,
557 SO->NodeDim, PatchNodeMask,
558 SO->patchMinDims, SO->patchMaxDims,
559 SO->patchCenter);
560 SO->patchCenter[0] /= SO->N_patchNode;
561 SO->patchCenter[1] /= SO->N_patchNode;
562 SO->patchCenter[2] /= SO->N_patchNode;
563 SUMA_MIN_VEC (SO->patchMinDims, 3, SO->patchaMinDims );
564 SUMA_MAX_VEC (SO->patchMaxDims, 3, SO->patchaMaxDims);
565 }
566
567 if (SO->patchNodeMask) {
568 SUMA_S_Err( "Hmm, unexpected."
569 "This function is usually called once per surface, "
570 "it is OK to call it more than once, but be sure it is necessary"
571 "before you turn this error message off");
572 SUMA_free(SO->patchNodeMask);
573 }
574 SO->patchNodeMask = NULL;
575
576 if (PatchNodeMask) {
577 if (SO->N_patchNode != SO->N_Node) {
578 SO->patchNodeMask = PatchNodeMask; PatchNodeMask = NULL;
579 } else {
580 SUMA_free(PatchNodeMask) ; PatchNodeMask = NULL;
581 }
582 }
583 #ifdef DO_SCALE_RANGE
584 SUMA_LH("In scale range");
585 { float tmpfact;
586 /* Now do some scaling */
587 tmpfact = (SO->aMaxDims - SO->aMinDims)/100;
588 ND = SO->NodeDim;
589 for (k=0; k < SO->N_Node; k++)
590 {
591 id = NodeDim * k;
592 SO->NodeList[k] = (SO->NodeList[k] - SO->aMinDims)/tmpfact;
593 SO->NodeList[k+1] = (SO->NodeList[k+1] - SO->aMinDims)/tmpfact;
594 SO->NodeList[k+2] = (SO->NodeList[k+2] - SO->aMinDims)/tmpfact;
595 }
596
597 SO->Center[0] = (SO->Center[0] - SO->aMinDims)/tmpfact;
598 SO->Center[1] = (SO->Center[1] - SO->aMinDims)/tmpfact;
599 SO->Center[2] = (SO->Center[2] - SO->aMinDims)/tmpfact;
600
601 SO->MinDims[0] = (SO->MinDims[0] - SO->aMinDims)/tmpfact;
602 SO->MinDims[1] = (SO->MinDims[1] - SO->aMinDims)/tmpfact;
603 SO->MinDims[2] = (SO->MinDims[2] - SO->aMinDims)/tmpfact;
604
605 SO->MaxDims[0] = (SO->MaxDims[0] - SO->aMinDims)/tmpfact;
606 SO->MaxDims[1] = (SO->MaxDims[1] - SO->aMinDims)/tmpfact;
607 SO->MaxDims[2] = (SO->MaxDims[2] - SO->aMinDims)/tmpfact;
608
609 SO->aMinDims = 0.0;
610 SO->aMaxDims = 100.0;
611 }
612 #endif
613 #ifdef DO_SCALE
614
615 /* Now do some scaling */
616 SUMA_LH("In scale section");
617 if ( (SO->aMaxDims - SO->aMinDims) > SUMA_TESSCON_DIFF_FLAG) {
618 if (AFNI_yesenv("SUMA_TESSCON_AutoScale")) {
619 fprintf (stdout, "\n"
620 "\n"
621 "WARNING %s:\n"
622 " Assuming surface to be in tesscon units,\n"
623 " scaling down by %f.\n"
624 "\aYou might have abnormally large or small \n"
625 "freakish vertex coordinates.\n"
626 "Max/Min Dims = %f/%f\n"
627 "\n",
628 FuncName, SUMA_TESSCON_TO_MM,
629 SO->aMaxDims, SO->aMinDims);
630 ND = SO->NodeDim;
631 for (k=0; k < SO->N_Node; k++)
632 {
633 id = ND * k;
634 SO->NodeList[id] /= SUMA_TESSCON_TO_MM;
635 SO->NodeList[id+1] /= SUMA_TESSCON_TO_MM;
636 SO->NodeList[id+2] /= SUMA_TESSCON_TO_MM;
637 }
638
639 SO->Center[0] /= SUMA_TESSCON_TO_MM;
640 SO->Center[1] /= SUMA_TESSCON_TO_MM;
641 SO->Center[2] /= SUMA_TESSCON_TO_MM;
642
643 SO->MinDims[0] /= SUMA_TESSCON_TO_MM;
644 SO->MinDims[1] /= SUMA_TESSCON_TO_MM;
645 SO->MinDims[2] /= SUMA_TESSCON_TO_MM;
646
647 SO->MaxDims[0] /= SUMA_TESSCON_TO_MM;
648 SO->MaxDims[1] /= SUMA_TESSCON_TO_MM;
649 SO->MaxDims[2] /= SUMA_TESSCON_TO_MM;
650
651 SO->aMinDims /= SUMA_TESSCON_TO_MM;
652 SO->aMaxDims /= SUMA_TESSCON_TO_MM;
653 } else {
654 SUMA_S_Note("Surface dim range a little strange.\n"
655 "Make sure dimensions are OK.\n"
656 "Max/Min Dims = %f/%f\n",
657 SO->aMaxDims, SO->aMinDims);
658 }
659 }
660 #endif
661
662 SUMA_LHv("Checking too small a surface: %f\n", SO->MaxCentDist);
663 /* check for too small a surface */
664 if (SO->MaxCentDist < 10.0 && !iwarn) {
665 if (!(sv = SUMA_BestViewerForADO((SUMA_ALL_DO *)SO))) sv = SUMAg_SVv;
666 if (sv) { /* This can be null when surfaces are created on the fly,
667 No need to warn in that case though.*/
668 ; /* took out actual warning - mostly nuisance - 10 Oct 2017 DRG */
669 if (!iwarn) ++iwarn;
670 /* if (sv->GVS[sv->StdView].DimSclFac < 5 && !iwarn) {
671 ++iwarn;
672 SUMA_S_Note(
673 "Surface size is quite small, rendering errors might occur.\n"
674 "If your coordinate units are in cm, set SUMA_NodeCoordsUnits \n"
675 "In your ~/.sumarc to 'cm' instead of the default 'mm'\n"
676 "If you do not have a '~/.sumarc', just run 'suma -update_env'\n");
677 }*/
678 }
679 }
680 SUMA_LH("Computing normals");
681 /* Calculate SurfaceNormals */
682
683 if (SO->NodeNormList && SO->FaceNormList) {
684 SUMA_LH("Node normals already computed, skipping...");
685 } else {
686 SN = SUMA_SurfNorm( SO->NodeList, SO->N_Node,
687 SO->FaceSetList, SO->N_FaceSet );
688 SO->NodeNormList = SN.NodeNormList;
689 SO->FaceNormList = SN.FaceNormList;
690 }
691
692 /*create the structures for GL rendering */
693 /*The data is being duplicated at the moment and perhaps
694 I should just stick with the 1D stuf */
695 if (sizeof(GLfloat) != sizeof(float)) {
696 SUMA_SL_Crit("GLfloat and float have differing sizes!\n");
697 SUMA_RETURN(NOPE); }
698
699 if (sizeof(GLint) != sizeof(int)) {
700 SUMA_SL_Crit("GLint and int have differing sizes!\n");
701 SUMA_RETURN(NOPE); }
702
703 SO->glar_NodeList = (GLfloat *) SO->NodeList; /* copy pointer, not data */
704 SO->glar_FaceSetList = (GLint *) SO->FaceSetList; /* copy pointer, not data */
705 SO->glar_FaceNormList = (GLfloat *) SO->FaceNormList; /* copy pointer */
706 SO->glar_NodeNormList = (GLfloat *) SO->NodeNormList; /* copy pointer */
707
708 /* a surface object does contribute to the rotation
709 center of the viewer displaying it */
710 SO->RotationWeight = SO->N_Node;
711 SO->ViewCenterWeight = SO->N_Node;
712
713 /* No selections yet, but make the preps */
714 SUMA_SV_SetShowSelectedDatum(sv, YUP, NOPE);
715 SUMA_SV_SetShowSelectedFaceSet(sv, YUP, NOPE);
716 SO->SelectedFaceSet = -1;
717 SO->SelectedNode = -1;
718 /* create the ball object*/
719 if (SO->NodeMarker) {
720 SUMA_LH("NodeMarker already present. Skipping");
721 } else {
722 SO->NodeMarker = SUMA_Alloc_SphereMarker ();
723 }
724 if (SO->NodeMarker == NULL) {
725 fprintf( SUMA_STDERR,
726 "Error%s: Could not allocate for SO->NodeMarker\n", FuncName);
727 SUMA_Free_Surface_Object (SO);
728 SUMA_RETURN (NOPE);
729 }
730 /* create the FaceSetMarker object */
731 if (SO->FaceSetMarker) {
732 SUMA_LH("FaceSetMarker already present. Skipping");
733 } else {
734 SO->FaceSetMarker = SUMA_Alloc_FaceSetMarker();
735 }
736 if (SO->FaceSetMarker == NULL) {
737 fprintf( SUMA_STDERR,
738 "Error%s: Could not allocate for SO->FaceSetMarker\n",
739 FuncName);
740 SUMA_Free_Surface_Object (SO);
741 SUMA_RETURN (NOPE);
742 }
743
744 /* find normal directions, if possible.
745 Do not do this here, normally, I can guess well and
746 if certain about orientation
747 for a particular format, set at surface reading level.
748 No need to do more computations */
749 /* if (SO->normdir == 0) SO->normdir = SUMA_SurfNormDir(SO); */
750
751 SUMA_RETURN(YUP);
752 }
753
754
755 /*!
756 Call the function engine, with debug turned on. 20 Oct 2003 [rickr]
757 */
SUMA_Load_Surface_Object(void * SO_FileName_vp,SUMA_SO_File_Type SO_FT,SUMA_SO_File_Format SO_FF,char * VolParName)758 SUMA_SurfaceObject * SUMA_Load_Surface_Object (void *SO_FileName_vp, SUMA_SO_File_Type SO_FT, SUMA_SO_File_Format SO_FF, char *VolParName)
759 {/*SUMA_Load_Surface_Object*/
760 static char FuncName[]={"SUMA_Load_Surface_Object"};
761
762 SUMA_ENTRY;
763
764 SUMA_RETURN( SUMA_Load_Surface_Object_eng( SO_FileName_vp, SO_FT, SO_FF,
765 VolParName, 1) );
766 }/*SUMA_Load_Surface_Object*/
767
768
769 /* - appended _eng to engine function name 20 Oct 2003 [rickr]
770 * - added debug parmeter
771 * - only print non-error info when debug flag is set
772 */
773 /*!
774 \brief
775 SO = SUMA_Load_Surface_Object_eng ( SO_FileName, SO_FT, SO_FF, char *VolParName, int debug)
776
777
778 Input paramters :
779 \param (void *) SO_FileName
780 For SUMA_INVENTOR_GENERIC SO_FileName is (char *) containing path (if any) and filename of surface
781 For SUMA_SUREFIT SO_FileName is (SUMA_SFname *) containing full topo and coord names, with path (if any)
782 For SUMA_FREE_SURFER SO_FileName is (char *) name of .asc file (with path)
783 For SUMA_VEC (a dumb ascii format), SO_FileName is (SUMA_SFname *) containing the nodelist file in name_coord
784 and facesetlist file in name_topo (path included).
785 For SUMA_PLY (char *) name of .ply file (with path)
786 For SUMA_OPENDX_MESH (char *) name of .dx file (with path)
787 \param SO_FT (SUMA_SO_File_Type) file type to be read (inventor, free surfer , Surefit )
788 \param SO_FF (SUMA_SO_File_Format) Ascii or Binary (only ascii at the moment, except for .ply files)
789 \param VolParName (char *) filename (+path) of parent volume, pass NULL for none
790 If you pass NULL, no transformation is applied to the coordinates read.
791 \param debug (int) flag specifying whether to output surface object info
792
793 \return SO (SUMA_SurfaceObject *) Surface Object pointer
794 The following fields are set (or initialized):
795 SO->NodeDim
796 SO->FaceSetDim
797 SO->NodeList
798 SO->FaceSetList
799 SO->N_Node;
800 SO->N_FaceSet;
801 SO->Name;
802 SO->FileType;
803 SO->FileFormat
804 SO->idcode_str
805 SO->Center
806 SO->aMaxDims
807 SO->aMinDims
808 SO->NodeNormList
809 SO->FaceNormList
810 SO->glar_NodeList
811 SO->glar_FaceSetList
812 SO->glar_FaceNormList
813 SO->glar_NodeNormList
814 SO->RotationWeight
815 SO->ViewCenterWeight
816 SO->SelectedFaceSet
817 SO->SelectedNode
818 SO->NodeMarker
819 SO->FaceSetMarker
820 SO->VolPar
821 SO->SUMA_VolPar_Aligned
822
823 \sa SUMA_IV*
824 \sa SUMA_Save_Surface_Object()
825 \sa SUMA_Align_to_VolPar()
826
827 ***/
SUMA_Load_Surface_Object_eng(void * SO_FileName_vp,SUMA_SO_File_Type SO_FT,SUMA_SO_File_Format SO_FF,char * VolParName,int debug)828 SUMA_SurfaceObject * SUMA_Load_Surface_Object_eng (
829 void *SO_FileName_vp, SUMA_SO_File_Type SO_FT,
830 SUMA_SO_File_Format SO_FF, char *VolParName,
831 int debug)
832 {/*SUMA_Load_Surface_Object_eng*/
833 static char FuncName[]={"SUMA_Load_Surface_Object_eng"};
834 char stmp[1000], *SO_FileName=NULL;
835 SUMA_SFname *SF_FileName;
836 SUMA_SureFit_struct *SF;
837 SUMA_FreeSurfer_struct *FS;
838 SUMA_SO_File_Type gSO_FT;
839 char *tname=NULL, *psv=NULL, *pname=NULL;
840 int i1=0, par=0;
841 SUMA_SurfaceObject *SO;
842
843 SUMA_Boolean LocalHead = NOPE;
844
845 SUMA_ENTRY;
846
847 /* Allocate and initialize SUMA_SurfaceObject Pointer */
848 SO = SUMA_Alloc_SurfObject_Struct(1);
849
850 if (SO_FT == SUMA_SUREFIT || SO_FT == SUMA_VEC) {
851 tname = ((SUMA_SFname*)SO_FileName_vp)->name_coord;
852 } else {
853 tname = (char *)SO_FileName_vp;
854 /* A little ugly, but check if this is a template name */
855 i1 = SUMA_is_predefined_SO_name(tname, &par, NULL, &psv, &pname);
856 if (i1 == 4 ) {
857 tname = pname;
858 VolParName = psv;
859 } else {
860 SUMA_ifree(pname); SUMA_ifree(psv);
861 }
862 }
863 if (tname) {
864 gSO_FT = SUMA_GuessSurfFormatFromExtension(tname, NULL);
865 if (SO_FT <= SUMA_FT_NOT_SPECIFIED && gSO_FT > SO_FT) {
866 SUMA_S_Notev( "Surface type not specified.\n"
867 "Format appears to be %s\n"
868 "based on filename extension.\n",
869 SUMA_SurfaceTypeString(gSO_FT));
870 SO_FT = gSO_FT;
871 }
872 if (i1 == 4) { /* Have template surface, adopt format */
873 SO_FT = gSO_FT;
874 }
875 if ( gSO_FT > SUMA_FT_NOT_SPECIFIED &&
876 gSO_FT != SO_FT && !pname) {
877 SUMA_S_Warnv("Warning Warning MSB!!!\n"
878 "Surface file name's (%s) extension indcates a\n"
879 "surface of type %s and conflicts with specified\n"
880 "type of %s.\n"
881 "Function will attempt to proceed as if type is\n"
882 "%s.\n",
883 tname, SUMA_SurfaceTypeString(gSO_FT),
884 SUMA_SurfaceTypeString(SO_FT),
885 SUMA_SurfaceTypeString(SO_FT));
886 }
887 }
888 /* check if recognizable type */
889 switch (SO_FT) {
890 case SUMA_INVENTOR_GENERIC:
891 break;
892 case SUMA_SUREFIT:
893 break;
894 case SUMA_FREE_SURFER:
895 case SUMA_FREE_SURFER_PATCH:
896 break;
897 case SUMA_STL:
898 break;
899 case SUMA_PLY:
900 break;
901 case SUMA_OBJ_MESH:
902 break;
903 case SUMA_MNI_OBJ:
904 break;
905 case SUMA_OPENDX_MESH:
906 break;
907 case SUMA_VEC:
908 break;
909 case SUMA_BRAIN_VOYAGER:
910 break;
911 case SUMA_BYU:
912 break;
913 case SUMA_GIFTI:
914 break;
915 case SUMA_PREDEFINED:
916 break;
917 default:
918 SUMA_error_message(FuncName, "SO_FileType not supported", 0);
919 SUMA_ifree(pname); SUMA_ifree(psv);
920 SUMA_RETURN (NULL);
921 break;
922 } /* SO_FT*/
923
924
925 /* proceed for reading */
926 switch (SO_FT) {
927 case SUMA_CMAP_SO:
928 /* nothing to do here */
929 SUMA_SL_Err("Don't know how to read those from disk:");
930 SUMA_ifree(pname); SUMA_ifree(psv);
931 SUMA_RETURN(NULL);
932
933 case SUMA_FT_NOT_SPECIFIED:
934 fprintf (SUMA_STDERR,"Error %s: No File Type specified.\n", FuncName);
935 SUMA_ifree(pname); SUMA_ifree(psv);
936 SUMA_RETURN(NULL);
937
938 case SUMA_N_SO_FILE_TYPE:
939 fprintf (SUMA_STDERR,
940 "Error %s: This should not happen (SUMA_N_SO_FILE_TYPE)\n",
941 FuncName);
942 SUMA_ifree(pname); SUMA_ifree(psv);
943 SUMA_RETURN(NULL);
944
945 case SUMA_STL:
946 if (!SUMA_STL_Read (tname, SO)) {
947 fprintf (SUMA_STDERR,
948 "Error %s: Failed in SUMA_STL_Read.\n", FuncName);
949 SUMA_ifree(pname); SUMA_ifree(psv);
950 SUMA_RETURN(NULL);
951 }
952 SUMA_NEW_ID(SO->idcode_str,tname);
953
954 /* change coordinates to align them with volparent data set,
955 if possible */
956 if (VolParName != NULL) {
957 SO->VolPar = SUMA_VolPar_Attr (VolParName);
958 if (SO->VolPar == NULL) {
959 fprintf( SUMA_STDERR,
960 "Error %s: Failed to load parent volume attributes.\n",
961 FuncName);
962 } else {
963
964 if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
965 else {
966 SO->SUMA_VolPar_Aligned = YUP;
967 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
968 }
969 }
970 } else {
971 SO->SUMA_VolPar_Aligned = NOPE;
972 }
973 SO->normdir = 0; /* not set */
974 break;
975 case SUMA_PLY:
976 if (!SUMA_Ply_Read (tname, SO)) {
977 fprintf (SUMA_STDERR,
978 "Error %s: Failed in SUMA_Ply_Read.\n", FuncName);
979 SUMA_ifree(pname); SUMA_ifree(psv);
980 SUMA_RETURN(NULL);
981 }
982 SUMA_NEW_ID(SO->idcode_str,tname);
983
984 /* change coordinates to align them with volparent data set,
985 if possible */
986 if (VolParName != NULL) {
987 SO->VolPar = SUMA_VolPar_Attr (VolParName);
988 if (SO->VolPar == NULL) {
989 fprintf( SUMA_STDERR,
990 "Error %s: Failed to load parent volume attributes.\n",
991 FuncName);
992 } else {
993
994 if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
995 else {
996 SO->SUMA_VolPar_Aligned = YUP;
997 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
998 }
999 }
1000 } else {
1001 SO->SUMA_VolPar_Aligned = NOPE;
1002 }
1003 SO->normdir = 0; /* not set */
1004 break;
1005 case SUMA_MNI_OBJ:
1006 if (!SUMA_MNI_OBJ_Read (tname, SO)) {
1007 fprintf (SUMA_STDERR,
1008 "Error %s: Failed in SUMA_MNI_OBJ_Read.\n", FuncName);
1009 SUMA_ifree(pname); SUMA_ifree(psv);
1010 SUMA_RETURN(NULL);
1011 }
1012 SUMA_NEW_ID(SO->idcode_str,tname);
1013
1014 /* change coordinates to align them with
1015 volparent data set, if possible */
1016 if (VolParName != NULL) {
1017 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1018 if (SO->VolPar == NULL) {
1019 fprintf( SUMA_STDERR,
1020 "Error %s: Failed to load parent volume attributes.\n",
1021 FuncName);
1022 } else {
1023
1024 if (!SUMA_Align_to_VolPar (SO, NULL))
1025 SO->SUMA_VolPar_Aligned = NOPE;
1026 else {
1027 SO->SUMA_VolPar_Aligned = YUP;
1028 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1029 }
1030 }
1031 } else {
1032 SO->SUMA_VolPar_Aligned = NOPE;
1033 }
1034 SO->normdir = 0; /* not set */
1035 break;
1036 case SUMA_OPENDX_MESH:
1037 if (!SUMA_OpenDX_Read_SO (tname, SO)) {
1038 fprintf (SUMA_STDERR,
1039 "Error %s: Failed in SUMA_OpenDX_Read_SO.\n", FuncName);
1040 SUMA_ifree(pname); SUMA_ifree(psv);
1041 SUMA_RETURN(NULL);
1042 }
1043 SUMA_NEW_ID(SO->idcode_str,tname);
1044
1045 /* change coordinates to align them with volparent data set,
1046 if possible */
1047 if (VolParName != NULL) {
1048 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1049 if (SO->VolPar == NULL) {
1050 fprintf(SUMA_STDERR,
1051 "Error %s: Failed to load parent volume attributes.\n",
1052 FuncName);
1053 } else {
1054
1055 if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
1056 else {
1057 SO->SUMA_VolPar_Aligned = YUP;
1058 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1059 }
1060 }
1061 } else {
1062 SO->SUMA_VolPar_Aligned = NOPE;
1063 }
1064
1065 SO->normdir = -1; /* negative */
1066 break;
1067 case SUMA_OBJ_MESH:
1068 {
1069 if (!(SUMA_OBJ_Read_SO(tname, SO, NULL))) {
1070 SUMA_S_Err("Failed to read %s", tname);
1071 SUMA_ifree(pname); SUMA_ifree(psv);
1072 SUMA_RETURN(NULL);
1073 }
1074 /* Don't change ID here, that is done inside SUMA_OBJ_Read_SO */
1075 /* change coordinates to align them with volparent data set,
1076 if possible */
1077 if (VolParName != NULL) {
1078 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1079 if (SO->VolPar == NULL) {
1080 SUMA_S_Err("Failed to load parent volume attributes.\n");
1081 } else {
1082 if (!SUMA_Align_to_VolPar (SO, NULL))
1083 SO->SUMA_VolPar_Aligned = NOPE;
1084 else {
1085 SO->SUMA_VolPar_Aligned = YUP;
1086 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1087 }
1088 }
1089 } else {
1090 SO->SUMA_VolPar_Aligned = NOPE;
1091 }
1092
1093 SO->normdir = -1; /* negative */
1094 break;
1095
1096 }
1097 break;
1098 case SUMA_PREDEFINED:
1099 i1 = SUMA_is_predefined_SO_name(tname, &par,
1100 NULL, NULL, NULL);
1101 switch(i1) {
1102 case 1:
1103 SO = SUMA_CreateIcosahedron(30, par, NULL, "n", 1);
1104 break;
1105 case 2:
1106 SO = SUMA_CreateIcosahedron(30, par, NULL, "y", 1);
1107 break;
1108 case 0:
1109 break;
1110 default:
1111 SUMA_S_Errv("Not ready for typ %d on %s\n",
1112 i1, tname);
1113 SUMA_ifree(pname); SUMA_ifree(psv);
1114 SUMA_RETURN(NULL);
1115 break;
1116 }
1117 SO->Name = SUMA_StripPath(tname);
1118 SO->FileType = SUMA_PREDEFINED;
1119 /* change coordinates to align them with volparent data set,
1120 if possible */
1121 if (VolParName != NULL) {
1122 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1123 if (SO->VolPar == NULL) {
1124 fprintf(SUMA_STDERR,
1125 "Error %s: Failed to load parent volume attributes.\n",
1126 FuncName);
1127 } else {
1128
1129 if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
1130 else {
1131 SO->SUMA_VolPar_Aligned = YUP;
1132 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1133 }
1134 }
1135 } else {
1136 SO->SUMA_VolPar_Aligned = NOPE;
1137 }
1138
1139 SO->normdir = 1;
1140 break;
1141
1142 case SUMA_BRAIN_VOYAGER:
1143 if (0 && SUMA_GuessSurfFormatFromExtension(tname,
1144 NULL)==SUMA_GIFTI) {
1145 /* Allowing for cases where BrainVoyager.gii surfaces are in the same
1146 coordinate system as their native format and so will require
1147 the VolPar transform below. I did not think this should happen
1148 with GIFTI. The surface coords should correspond directly to those
1149 of the NIFTI volume
1150 Exception added for Adam Greenberg, surfaces are not well
1151 centered in the viewer. This will need fixing is this condition
1152 is to be allowed. Problem is that it appears BV's gifti surfaces
1153 might still be in their native coord system, not as set by
1154 the transform matrix in the gii file */
1155 SUMA_S_Warn("This should not be used regularly.\n"
1156 "Surfaces will not display in the proper place\n"
1157 "in SUMA.\n");
1158 if (!SUMA_GIFTI_Read (tname, SO, 1)) {
1159 fprintf (SUMA_STDERR,
1160 "Error %s: Failed in SUMA_GIFTI_Read.\n", FuncName);
1161 SUMA_ifree(pname); SUMA_ifree(psv);
1162 SUMA_RETURN(NULL);
1163 }
1164 SO->FileType = SUMA_BRAIN_VOYAGER;
1165 } else {
1166 if (!SUMA_BrainVoyager_Read (tname, SO, 1, 1)) {
1167 fprintf (SUMA_STDERR,
1168 "Error %s: Failed in SUMA_BrainVoyager_Read.\n",
1169 FuncName);
1170 SUMA_ifree(pname); SUMA_ifree(psv);
1171 SUMA_RETURN(NULL);
1172 }
1173 }
1174 SUMA_NEW_ID(SO->idcode_str,tname);
1175
1176 /* change coordinates to align them with volparent data set,
1177 if possible */
1178 if (VolParName != NULL) {
1179 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1180 if (SO->VolPar == NULL) {
1181 fprintf( SUMA_STDERR,
1182 "Error %s: Failed to load parent volume attributes.\n",
1183 FuncName);
1184 } else {
1185 if (!SUMA_Align_to_VolPar (SO, NULL))
1186 SO->SUMA_VolPar_Aligned = NOPE;
1187 else {
1188 SO->SUMA_VolPar_Aligned = YUP;
1189 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1190 }
1191 }
1192 } else {
1193 SO->SUMA_VolPar_Aligned = NOPE;
1194 }
1195
1196 if (SO->SUMA_VolPar_Aligned) SO->normdir = 1; /* positive */
1197 else SO->normdir = -1; /* negative */
1198 break;
1199
1200 case SUMA_BYU:
1201 if (!SUMA_BYU_Read (tname, SO, 1, 1)) {
1202 fprintf (SUMA_STDERR,
1203 "Error %s: Failed in SUMA_BYU_Read.\n", FuncName);
1204 SUMA_ifree(pname); SUMA_ifree(psv);
1205 SUMA_RETURN(NULL);
1206 }
1207 SUMA_NEW_ID(SO->idcode_str,tname);
1208
1209 /* change coordinates to align them with volparent data set,
1210 if possible */
1211 if (VolParName != NULL) {
1212 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1213 if (SO->VolPar == NULL) {
1214 fprintf( SUMA_STDERR,
1215 "Error %s: Failed to load parent volume attributes.\n",
1216 FuncName);
1217 } else {
1218
1219 if (!SUMA_Align_to_VolPar (SO, NULL))
1220 SO->SUMA_VolPar_Aligned = NOPE;
1221 else {
1222 SO->SUMA_VolPar_Aligned = YUP;
1223 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1224 }
1225 }
1226 } else {
1227 SO->SUMA_VolPar_Aligned = NOPE;
1228 }
1229
1230 SO->normdir = SUMA_SurfNormDir(SO); /* guess */
1231 break;
1232
1233 case SUMA_GIFTI:
1234 if (!SUMA_GIFTI_Read (tname, SO, 1)) {
1235 fprintf (SUMA_STDERR,
1236 "Error %s: Failed in SUMA_GIFTI_Read.\n", FuncName);
1237 SUMA_ifree(pname); SUMA_ifree(psv);
1238 SUMA_RETURN(NULL);
1239 }
1240 SUMA_NEW_ID(SO->idcode_str,tname);
1241
1242 /* change coordinates to align them with volparent data set,
1243 if possible */
1244 if (VolParName != NULL) {
1245 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1246 if (SO->VolPar == NULL) {
1247 fprintf( SUMA_STDERR,
1248 "Error %s: Failed to load parent volume attributes.\n",
1249 FuncName);
1250 } else {
1251
1252 if (!SUMA_Align_to_VolPar (SO, NULL))
1253 SO->SUMA_VolPar_Aligned = NOPE;
1254 else {
1255 SO->SUMA_VolPar_Aligned = YUP;
1256 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1257 }
1258 }
1259 } else {
1260 SO->SUMA_VolPar_Aligned = NOPE;
1261 }
1262
1263 SO->normdir = SUMA_SurfNormDir(SO); /* guess */
1264 break;
1265
1266 case SUMA_INVENTOR_GENERIC:
1267 SO_FileName = tname;
1268 /* You need to split name into path and name ... */
1269 if ( debug )
1270 fprintf(stdout,"%s\n", SO_FileName);
1271 SO->Name = SUMA_StripPath(SO_FileName);
1272 /* check for file existence */
1273 if (!SUMA_filexists(SO_FileName)) {
1274 snprintf(stmp,998,"File %s not found!", SO_FileName);
1275 SUMA_error_message(FuncName, stmp, 0);
1276 SUMA_RETURN (NULL);
1277 }
1278 SO->FileType = SO_FT;
1279 SO->FileFormat = SO_FF;
1280 SO->NodeDim = 3; /* This must be automated */
1281 SO->NodeList = SUMA_IV_XYZextract (SO_FileName, &(SO->N_Node), 0);
1282 if (SO->NodeList == NULL) {
1283 SUMA_error_message(FuncName,"SUMA_IV_XYZextract failed!",0);
1284 SUMA_ifree(pname); SUMA_ifree(psv);
1285 SUMA_RETURN(NULL);
1286 }
1287 SO->FaceSetList = SUMA_IV_FaceSetsextract (SO_FileName,
1288 &(SO->N_FaceSet));
1289 if (SO->FaceSetList == NULL) {
1290 SUMA_error_message(FuncName,"SUMA_IV_FaceSetsextract failed!",0);
1291 SUMA_ifree(pname); SUMA_ifree(psv);
1292 SUMA_RETURN(NULL);
1293 }
1294 SO->FaceSetDim = 3; /*This must also be automated */
1295 SUMA_NEW_ID(SO->idcode_str,SO_FileName);
1296
1297 SO->normdir = 0; /* not set */
1298 break;
1299
1300 case SUMA_FREE_SURFER:
1301 case SUMA_FREE_SURFER_PATCH:
1302 /* Allocate for FS */
1303 FS = (SUMA_FreeSurfer_struct *)
1304 SUMA_malloc(sizeof(SUMA_FreeSurfer_struct));
1305 if (FS == NULL) {
1306 fprintf( SUMA_STDERR,
1307 "Error %s: Failed to allocate for FS\n", FuncName);
1308 SUMA_ifree(pname); SUMA_ifree(psv);
1309 SUMA_RETURN (NULL);
1310 }
1311 /* add a couple of lines to appease the optimation gods... */
1312 /* (suma, v2s, SSmooth were crashing on FC7) 23 Jan 2008 [rickr] */
1313 memset(FS, 0, sizeof(SUMA_FreeSurfer_struct));
1314 if(debug > 1) fprintf(stderr,"-- optimization appeasement message\n");
1315 SO->Name = SUMA_StripPath((char*)SO_FileName_vp);
1316 SO->FileType = SO_FT;
1317 SO->FileFormat = SO_FF;
1318 SO->NodeDim = 3; /* This must be automated */
1319 /*read the surface file */
1320 if (SO->FileFormat == SUMA_ASCII) { // PDL: NB: This is where the ascii file,
1321 // containing the surface specifications, is read
1322 if (!SUMA_FreeSurfer_Read_eng((char*)SO_FileName_vp, FS, debug)) {
1323 fprintf( SUMA_STDERR,
1324 "Error %s: Failed in SUMA_FreeSurfer_Read.\n",
1325 FuncName);
1326 SUMA_ifree(pname); SUMA_ifree(psv);
1327 SUMA_RETURN (NULL);
1328 }
1329 } else if (SO->FileFormat == SUMA_BINARY_BE) {
1330 if (!SUMA_FreeSurfer_ReadBin_eng((char*)SO_FileName_vp, FS, debug)) {
1331 fprintf( SUMA_STDERR,
1332 "Error %s: Failed in SUMA_FreeSurfer_Read.\n",
1333 FuncName);
1334 SUMA_ifree(pname); SUMA_ifree(psv);
1335 SUMA_RETURN (NULL);
1336 }
1337 } else {
1338 SUMA_SL_Err("Format not supported.");
1339 SUMA_ifree(pname); SUMA_ifree(psv);
1340 SUMA_RETURN (NULL);
1341 }
1342 if ( debug > 1)
1343 SUMA_Show_FreeSurfer (FS, NULL);
1344 /* save the juice and clean up the rest */
1345 SO->N_Node = FS->N_Node;
1346 /* Save the pointers to NodeList and FaceSetList and
1347 clear what is left of FS structure at the end */
1348 SO->NodeList = FS->NodeList;
1349 FS->NodeList = NULL;
1350 SO->FaceSetList = FS->FaceSetList;
1351 SO->N_FaceSet = FS->N_FaceSet;
1352 FS->FaceSetList = NULL;
1353 SO->FaceSetDim = 3; /*This must also be automated */
1354
1355
1356 /* change coordinates to align them with volparent data set,
1357 if possible */
1358 if (VolParName != NULL) {
1359 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1360 if (SO->VolPar == NULL) {
1361 fprintf( SUMA_STDERR,
1362 "Error %s: Failed to load parent volume attributes.\n",
1363 FuncName);
1364 } else {
1365 if (!SUMA_Align_to_VolPar (SO, (void*)FS))
1366 SO->SUMA_VolPar_Aligned = NOPE;
1367 else {
1368 SO->SUMA_VolPar_Aligned = YUP;
1369 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1370 }
1371 }
1372 } else {
1373 SO->SUMA_VolPar_Aligned = NOPE;
1374 }
1375 SO->normdir = 1; /* normals point out */
1376 /* free FS */
1377 if (!SUMA_Free_FreeSurfer (FS)) {
1378 fprintf( SUMA_STDERR,
1379 "Error %s: Failed in SUMA_Free_FreeSurfer.\n", FuncName);
1380 SUMA_ifree(pname); SUMA_ifree(psv);
1381 SUMA_RETURN (NULL);
1382 }
1383
1384 /* create the IDcode */
1385 SUMA_NEW_ID(SO->idcode_str, tname);
1386 if (LocalHead)
1387 fprintf (SUMA_STDERR,
1388 "%s: Assigned idcode_str:%s:.\n", FuncName, SO->idcode_str);
1389
1390 SO->normdir = 1; /* positive */
1391 break;
1392
1393 case SUMA_VEC:
1394 /* naming is with two files, similar to SureFit */
1395 SF_FileName = (SUMA_SFname *)SO_FileName_vp;
1396 /* form the topo and the coord names */
1397 SO->Name_coord = SUMA_StripPath(SF_FileName->name_coord);
1398 SO->Name_topo = SUMA_StripPath(SF_FileName->name_topo);
1399 SO->FileType = SO_FT;
1400 SO->FileFormat = SO_FF;
1401 SO->NodeDim = 3; /* This must be automated */
1402 /* check for files */
1403 if (!SUMA_filexists(SF_FileName->name_coord)) {
1404 fprintf(SUMA_STDERR,"Error %s: Could not find %s\n",
1405 FuncName, SF_FileName->name_coord);
1406 SUMA_ifree(pname); SUMA_ifree(psv);
1407 SUMA_RETURN (NULL);
1408 }
1409 if (!SUMA_filexists(SF_FileName->name_topo)) {
1410 fprintf(SUMA_STDERR,"Error %s: Could not find %s\n",
1411 FuncName, SF_FileName->name_topo);
1412 SUMA_ifree(pname); SUMA_ifree(psv);
1413 SUMA_RETURN (NULL);
1414 }
1415
1416 if (!SUMA_VEC_Read(SF_FileName, SO)) {
1417 SUMA_SLP_Err("Failed to read 1D file");
1418 if (SO->NodeList) SUMA_free(SO->NodeList);
1419 if (SO->FaceSetList) SUMA_free(SO->FaceSetList);
1420 SUMA_ifree(pname); SUMA_ifree(psv);
1421 SUMA_RETURN (NULL);
1422 }
1423
1424 sprintf (stmp, "%s%s", SF_FileName->name_coord, SF_FileName->name_topo);
1425 SUMA_NEW_ID(SO->idcode_str, stmp);
1426
1427 /* change coordinates to align them with volparent data set,
1428 if possible */
1429 if (VolParName != NULL) {
1430 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1431 if (SO->VolPar == NULL) {
1432 fprintf( SUMA_STDERR,
1433 "Error %s: Failed to load parent volume attributes.\n",
1434 FuncName);
1435 } else {
1436
1437 if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
1438 else {
1439 SO->SUMA_VolPar_Aligned = YUP;
1440 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1441 }
1442 }
1443 } else {
1444 SO->SUMA_VolPar_Aligned = NOPE;
1445 }
1446
1447 SO->normdir = 0; /* not set */
1448 break;
1449
1450 case SUMA_FT_ERROR:
1451 SUMA_SL_Err("Error specifying file type.");
1452 break;
1453
1454 case SUMA_SUREFIT:
1455 /* Allocate for SF */
1456 SF = (SUMA_SureFit_struct *) SUMA_calloc(1,
1457 sizeof(SUMA_SureFit_struct));
1458 if (SF == NULL) {
1459 fprintf( SUMA_STDERR,
1460 "Error %s: Failed to allocate for SF\n", FuncName);
1461 SUMA_ifree(pname); SUMA_ifree(psv);
1462 SUMA_RETURN (NULL);
1463 }
1464 SF->NodeList= NULL;
1465 SF->NodeId = NULL;
1466 SF->allzerocoord = NULL;
1467 SF->Specs_mat = NULL;
1468 SF->FaceSetList = NULL;
1469 SF->FN.N_Neighb = NULL;
1470 SF->FN.FirstNeighb = NULL;
1471 SF->FN.NodeId = NULL;
1472 SF->caret_version = -1.0;
1473 SF_FileName = (SUMA_SFname *)SO_FileName_vp;
1474 /* form the topo and the coord names */
1475 SO->Name_coord = SUMA_StripPath(SF_FileName->name_coord);
1476 SO->Name_topo = SUMA_StripPath(SF_FileName->name_topo);
1477 SO->FileType = SO_FT;
1478 SO->FileFormat = SO_FF;
1479 SO->NodeDim = 3; /* This must be automated */
1480
1481 /*read the coordinate file */
1482 if (!SUMA_SureFit_Read_Coord (SF_FileName->name_coord,
1483 SF)) {
1484 fprintf( SUMA_STDERR,
1485 "Error %s: Failed in SUMA_SureFit_Read_Coord.\n", FuncName);
1486 SUMA_ifree(pname); SUMA_ifree(psv);
1487 SUMA_RETURN (NULL);
1488 }
1489 /* copy the pertinent data to SO */
1490 SO->N_Node = SF->N_Node;
1491 /* Save the pointers to NodeList and FaceSetList and
1492 clear what is left of SF structure at the end */
1493 SO->NodeList = SF->NodeList;
1494 SF->NodeList = NULL;
1495
1496
1497 /*read the topology file */
1498 if (!SUMA_SureFit_Read_Topo (SF_FileName->name_topo, SF)) {
1499 fprintf( SUMA_STDERR,
1500 "Error %s: Failed in SUMA_SureFit_Read_Topo.\n", FuncName);
1501 SUMA_ifree(pname); SUMA_ifree(psv);
1502 SUMA_RETURN (NULL);
1503 }
1504
1505
1506 /* read the param file */
1507 if (strlen(SF_FileName->name_param)){
1508 if (!SUMA_Read_SureFit_Param(SF_FileName->name_param, SF)) {
1509 fprintf( SUMA_STDERR,
1510 "Error %s: Failed in SUMA_Read_SureFit_Param.\n",
1511 FuncName);
1512 }
1513 } else {
1514 if (VolParName != NULL) {
1515 SUMA_S_Note("Volume Parent specified without .param file.\n"
1516 "Be sure surface and volume line up.");
1517 }
1518 }
1519
1520 /* copy the pertinent data to SO */
1521 SO->FaceSetList = SF->FaceSetList;
1522 SO->N_FaceSet = SF->N_FaceSet;
1523 SF->FaceSetList = NULL;
1524 SO->FaceSetDim = 3; /*This must also be automated */
1525
1526 /* change coordinates to align them with volparent data set,
1527 if possible */
1528 if (VolParName != NULL ) {
1529 SO->VolPar = SUMA_VolPar_Attr (VolParName);
1530 if (SO->VolPar == NULL) {
1531 fprintf( SUMA_STDERR,
1532 "Error %s: Failed to load parent volume attributes.\n",
1533 FuncName);
1534 } else {
1535 /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
1536
1537 if (!SUMA_Align_to_VolPar (SO, (void *)SF))
1538 SO->SUMA_VolPar_Aligned = NOPE;
1539 else
1540 SO->SUMA_VolPar_Aligned = YUP;
1541 }
1542 } else {
1543 /* OK to go there with new caret files */
1544 if (!SUMA_Align_to_VolPar (SO, (void *)SF))
1545 SO->SUMA_VolPar_Aligned = NOPE;
1546 else
1547 SO->SUMA_VolPar_Aligned = YUP;
1548 }
1549
1550 sprintf (stmp, "%s%s", SF_FileName->name_coord, SF_FileName->name_topo);
1551 SUMA_NEW_ID(SO->idcode_str, stmp);
1552
1553 if ((int) SF->tag_version == 1) { SO->normdir = 1; }
1554 else SO->normdir = -1;
1555
1556 /* SUMA_Show_SureFit(SF, SUMA_STDERR); */
1557
1558 /* free SF */
1559 if (!SUMA_Free_SureFit (SF)) {
1560 fprintf( SUMA_STDERR,
1561 "Error %s: Failed in SUMA_Free_SureFit.\n", FuncName);
1562 SUMA_ifree(pname); SUMA_ifree(psv);
1563 SUMA_RETURN (NULL);
1564 }
1565
1566 break;
1567 } /* SO_FileType*/
1568
1569 /* sanity check (this one's here for a reason) */
1570 if (SO->N_Node <=0 || SO->N_FaceSet<=0) {
1571 SUMA_SL_Crit("0 nodes or 0 facesets.\nProceed I will not.\n");
1572 SUMA_Free_Surface_Object (SO);
1573 SUMA_ifree(pname); SUMA_ifree(psv);
1574 SUMA_RETURN (NULL);
1575 }
1576
1577 /* A trick for Stephen Tyree, Pat Bellgowan, and other mad men */
1578 if (AFNI_yesenv("SUMA_FLIP_X_COORD")) {
1579 int i, id;
1580 for (i=0; i < SO->N_Node; ++i) {
1581 id = i * SO->NodeDim;
1582 SO->NodeList[id] = -SO->NodeList[id];
1583 }
1584 SO->normdir = -SO->normdir;
1585 }
1586 if (SO->isSphere == SUMA_GEOM_NOT_SET) {
1587 SUMA_SetSphereParams(SO, -0.1);
1588 } /* sets the spheriosity parameters */
1589
1590
1591
1592 if (!SUMA_PrepSO_GeomProp_GL (SO)) {
1593 SUMA_SL_Err("Failed to set surface's properties");
1594 SUMA_ifree(pname); SUMA_ifree(psv);
1595 SUMA_RETURN (NULL);
1596 }
1597
1598
1599 SUMA_ifree(pname); SUMA_ifree(psv);
1600 SUMA_RETURN (SO);
1601
1602 }/*SUMA_Load_Surface_Object_eng*/
1603
1604 /*!< Look for datasets names exactly like the surface but with
1605 a dataset extension and load them if found*/
SUMA_AutoLoad_SO_Dsets(SUMA_SurfaceObject * SO)1606 SUMA_Boolean SUMA_AutoLoad_SO_Dsets(SUMA_SurfaceObject *SO)
1607 {
1608 static char FuncName[]={"SUMA_AutoLoad_SO_Dsets"};
1609 char *ddd=NULL, *ddde=NULL, *soname=NULL;
1610 SUMA_Boolean LocalHead = NOPE;
1611
1612 SUMA_ENTRY;
1613
1614 soname = SUMA_SurfaceFileName(SO, 1);
1615 if (!soname) soname = SUMA_copy_string("No_SO_name.gii");
1616 ddd = SUMA_RemoveSurfNameExtension (soname, SO->FileType);
1617 SUMA_LH("Checking for %s dsets on root %s", soname, ddd);
1618 if (SUMA_filexists((ddde = SUMA_append_string(ddd,".niml.dset")))) {
1619 SUMA_S_Note("Auto Loading %s onto %s", ddde, soname);
1620 SUMA_LoadDsetOntoSO(ddde, (void *)SO);
1621 SUMA_ifree(ddde);
1622 }
1623 if (ddde) {/* try again */
1624 SUMA_ifree(ddde);
1625 if (SUMA_filexists((ddde = SUMA_append_string(ddd,".1D.dset")))) {
1626 SUMA_S_Note("Auto Loading %s onto %s", ddde, soname);
1627 SUMA_LoadDsetOntoSO(ddde, (void *)SO);
1628 SUMA_ifree(ddde);
1629 }
1630 }
1631 if (ddde) {/* try again */
1632 SUMA_ifree(ddde);
1633 if (SUMA_filexists((ddde = SUMA_append_string(ddd,".gii.dset")))) {
1634 SUMA_S_Note("Auto Loading %s onto %s", ddde, soname);
1635 SUMA_LoadDsetOntoSO(ddde, (void *)SO);
1636 SUMA_ifree(ddde);
1637 }
1638 }
1639 if (ddde) {/* try again */
1640 SUMA_ifree(ddde);
1641 if ( SO->FileType != SUMA_GIFTI &&
1642 SUMA_filexists((ddde = SUMA_append_string(ddd,".gii")))) {
1643 SUMA_S_Note("Auto Loading %s onto %s", ddde, soname);
1644 SUMA_LoadDsetOntoSO(ddde, (void *)SO);
1645 SUMA_ifree(ddde);
1646 }
1647 }
1648 SUMA_ifree(ddd);
1649 SUMA_ifree(soname);
1650 if (!ddde) SUMA_RETURN(YUP); /* got one */
1651
1652 SUMA_ifree(ddde);
1653 SUMA_RETURN(NOPE);
1654 }
1655
1656
1657
1658 /*!
1659 SUMA_Boolean SUMA_ParseLHS_RHS (char *s, char *lhs, char *rhs)
1660
1661 Parses S of the form "lhs = rhs"
1662 s, lhs and rhs must be allocated for
1663
1664 \param s (char *) "joe = fred"
1665 \param lhs (char *) "joe"
1666 if you send in lhs[0] = '\0'; it gets
1667 filled with joe for you.
1668 \param rhs (char *) returned "fred"
1669 \ret YUP/NOPE for goodness, badness
1670
1671 */
SUMA_ParseLHS_RHS(char * s,char * lhs,char * rhs)1672 SUMA_Boolean SUMA_ParseLHS_RHS (char *s, char *lhs, char *rhs)
1673 {
1674 static char FuncName[]={"SUMA_ParseLHS_RHS"};
1675 char *op=NULL, *op2=NULL;
1676 SUMA_Boolean LocalHead = NOPE;
1677
1678 SUMA_ENTRY;
1679
1680 if (s == NULL) {
1681 fprintf(SUMA_STDERR,"Error %s: NULL s\n", FuncName);
1682 SUMA_RETURN (NOPE);
1683 }
1684 rhs[0] = '\0';
1685
1686 /* skip first blank */
1687 SUMA_SKIP_BLANK(s, NULL);
1688
1689 /* seek first = */
1690 SUMA_LHv("Have >%s<\n", s);
1691 op=s;
1692 SUMA_SKIP_TO_NEXT_CHAR(s,NULL,'=');
1693 if (lhs[0] == '\0') { /* load left hand side */
1694 SUMA_FILL_STRING(op, s, lhs);
1695 SUMA_DEBLANK_RHS(lhs);
1696 SUMA_LHv("LHS now: >%s<\n", lhs);
1697 }
1698 if (*s != '=') {
1699 SUMA_LH("No equal, no right hand side\n");
1700 SUMA_RETURN (NOPE);
1701 }
1702 /* get all the rhs */
1703 ++s;
1704 SUMA_SKIP_BLANK(s, NULL);
1705 SUMA_FILL_STRING(s, NULL, rhs);
1706 /* deblank end of rhs */
1707 SUMA_DEBLANK_RHS(rhs);
1708
1709 SUMA_LHv("Have %s, lhs>%s<, rhs >%s<\n", s, lhs, rhs);
1710 SUMA_RETURN (YUP);
1711 }
1712
1713 /* Undo the separation of left/right deformed states
1714 the _lh and _rh are what @SUMA_Make_Spec_FS used
1715 to flag these special states */
1716 #define SUMA_LH_UNIFY_STATE_FIX(ss) { \
1717 SUMA_CropExtension((ss), "_lh_lh"); /* don't ask */\
1718 SUMA_CropExtension((ss), "_rh_rh"); /* don't ask */\
1719 SUMA_CropExtension((ss), "_lh"); \
1720 SUMA_CropExtension((ss), "_rh"); \
1721 }
1722
1723 /*!
1724 Function to read the surface specs file.
1725 \param fname (char *) name of the specs file
1726 \param Spec (SUMA_SurfSpecFile *) pre-allocated pointer to
1727 SUMA_SurfSpecFile structure. )
1728 \ret YUP, good, NOPE, not good
1729 */
SUMA_Read_SpecFile(char * f_name,SUMA_SurfSpecFile * Spec)1730 SUMA_Boolean SUMA_Read_SpecFile (
1731 char *f_name, SUMA_SurfSpecFile * Spec)
1732 {/* SUMA_Read_SpecFile */
1733 static char FuncName[]={"SUMA_Read_SpecFile"};
1734 char s[SUMA_MAX_DIR_LENGTH], stmp[SUMA_MAX_DIR_LENGTH],
1735 stmp2[SUMA_MAX_DIR_LENGTH], c;
1736 int ex, skp, evl, i, kkk, LHunify=0;
1737 FILE *sf_file;
1738 SUMA_FileName SpecName;
1739 SUMA_Boolean onGIFTIalert = NOPE;
1740 SUMA_Boolean OKread_SurfaceFormat, OKread_SurfaceType,
1741 OKread_TopoFile, OKread_CoordFile;
1742 SUMA_Boolean OKread_MappingRef, OKread_SureFitVolParam,
1743 OKread_FreeSurferSurface, OKread_InventorSurface;
1744 SUMA_Boolean OKread_Group, OKread_State, OKread_EmbedDim,
1745 OKread_SurfaceVolume, OKread_SurfaceLabel;
1746 SUMA_Boolean OKread_AnatCorrect, OKread_Hemisphere,
1747 OKread_DomainGrandParentID, OKread_OriginatorID;
1748 SUMA_Boolean OKread_LocalCurvatureParent, OKread_LocalDomainParent,
1749 OKread_LabelDset, OKread_NodeMarker;
1750 char DupWarn[]={ "Bad format in specfile "
1751 "(you may need a NewSurface line). "
1752 "Duplicate specification of"};
1753 char NewSurfWarn[]={ "Bad format in specfile. "
1754 "You must start with NewSurface line "
1755 "before any other field."};
1756 SUMA_Boolean LocalHead = NOPE;
1757
1758 SUMA_ENTRY;
1759
1760 if (SUMA_isEnv("SUMA_LHunify","YES")) LHunify = 1;
1761
1762 /*make sure file is there */
1763 if (!SUMA_filexists(f_name)) {
1764 fprintf(SUMA_STDERR,
1765 "Error %s: File %s does not exist or cannot be read.\n",
1766 FuncName, f_name);
1767 SUMA_RETURN (NOPE);
1768 }
1769
1770 if (Spec->N_Surfs != -1) {
1771 fprintf(SUMA_STDERR,
1772 "Error %s: Spec is not fresh after SUMA_AllocSpecFields.\n"
1773 "Perhaps you have redundant definitions of the input surface\n",
1774 FuncName);
1775 SUMA_RETURN (NOPE);
1776 }
1777
1778 Spec->N_Surfs = 0;
1779
1780 /* set the path for the spec file */
1781 SpecName = SUMA_StripPath (f_name);
1782 if (strlen(SpecName.Path) > SUMA_MAX_DIR_LENGTH-1) {
1783 fprintf( SUMA_STDERR,
1784 "Error %s: Path of specfile > %d charcters.\n",
1785 FuncName, SUMA_MAX_DIR_LENGTH-1);
1786 SUMA_RETURN (NOPE);
1787 }
1788 if (strlen(SpecName.FileName) > SUMA_MAX_NAME_LENGTH-1) {
1789 fprintf( SUMA_STDERR,
1790 "Error %s: Name of specfile > %d charcters.\n",
1791 FuncName, SUMA_MAX_NAME_LENGTH-1);
1792 SUMA_RETURN (NOPE);
1793 }
1794 snprintf(Spec->SpecFilePath,SUMA_MAX_DIR_LENGTH*sizeof(char),
1795 "%s", SpecName.Path);
1796 snprintf(Spec->SpecFileName,SUMA_MAX_NAME_LENGTH*sizeof(char),
1797 "%s", SpecName.FileName);
1798
1799 if (SUMA_iswordin(Spec->SpecFileName,"N27")) onGIFTIalert = 1;
1800
1801 /* free SpecName since it's not used elsewhere */
1802 if (SpecName.Path) SUMA_free(SpecName.Path);
1803 if (SpecName.FileName) SUMA_free(SpecName.FileName);
1804
1805 /*read the thing*/
1806 sf_file = fopen (f_name,"r");
1807 if (sf_file == NULL)
1808 {
1809 fprintf( SUMA_STDERR,
1810 "Error %s: Could not open file for read\n", FuncName);
1811 SUMA_RETURN (NOPE);
1812 }
1813
1814 /*read until you find not a comment */
1815
1816 /* read the first line, skipping leading space */
1817 do {
1818 ex = fscanf (sf_file,"%c",&c);
1819 } while (ex != EOF && isspace(c));
1820
1821 i=0;
1822 while (ex != EOF && c != '\n') {
1823 s[i] = c; ++i;
1824 ex = fscanf (sf_file,"%c",&c);
1825 }
1826 s[i] = '\0';
1827 if (LocalHead) fprintf(SUMA_STDERR,"Read %s\n", s);
1828 OKread_Group = YUP; /* it is OK to read a group before
1829 a new surface is declared */
1830 OKread_SurfaceFormat = OKread_SurfaceType =
1831 OKread_TopoFile = OKread_CoordFile = NOPE;
1832 OKread_MappingRef = OKread_SureFitVolParam =
1833 OKread_FreeSurferSurface = OKread_InventorSurface = NOPE;
1834 OKread_State = OKread_EmbedDim = OKread_SurfaceVolume =
1835 OKread_SurfaceLabel = NOPE ;
1836 OKread_AnatCorrect = OKread_Hemisphere = OKread_DomainGrandParentID =
1837 OKread_OriginatorID = NOPE;
1838 OKread_LocalCurvatureParent = OKread_LocalDomainParent =
1839 OKread_LabelDset = OKread_NodeMarker = NOPE;
1840
1841 Spec->StateList[0] = '\0';
1842 Spec->Group[0][0] = '\0';
1843 Spec->N_Surfs = Spec->N_States = Spec->N_Groups = 0;
1844 while (ex !=EOF) {
1845 evl = SUMA_iswordin (s,"#");
1846 if (evl != 1) { /* not a comment */
1847 if (LocalHead) fprintf(SUMA_STDERR,"Not a comment: %s\n", s);
1848 skp = 0;
1849 sprintf(stmp,"NewSurface");
1850 if (!skp && SUMA_iswordin (s, stmp) == 1) {
1851 if(Spec->N_Surfs >= SUMA_MAX_N_SURFACE_SPEC) {
1852 fprintf( SUMA_STDERR,
1853 "Error %s: Cannot read in more than %d new surfaces.\n",
1854 FuncName, SUMA_MAX_N_SURFACE_SPEC);
1855 SUMA_RETURN (NOPE);
1856 }
1857 Spec->N_Surfs += 1;
1858 if (LocalHead)
1859 fprintf( SUMA_STDERR,
1860 "Found New Surface, N = %d\n", Spec->N_Surfs);
1861 /* initialize some of the fields */
1862 if (Spec->N_Surfs == 1) { /* first surface, initialize to empty */
1863 sprintf(Spec->SurfaceFormat[Spec->N_Surfs-1],"ASCII");
1864 Spec->SurfaceType[Spec->N_Surfs-1][0] = '\0';
1865 Spec->TopoFile[Spec->N_Surfs-1][0] =
1866 Spec->CoordFile[Spec->N_Surfs-1][0] = '\0';
1867 Spec->MappingRef[Spec->N_Surfs-1][0] = '\0'; /* Should become
1868 obsolete,
1869 ZSS Jan 02 03 */
1870 Spec->SureFitVolParam[Spec->N_Surfs-1][0] = '\0';
1871 Spec->SurfaceFile[Spec->N_Surfs-1][0] = '\0';
1872 Spec->State[Spec->N_Surfs-1][0] = '\0';
1873 Spec->IDcode[Spec->N_Surfs-1] = NULL; /* this field is set in
1874 LoadSpec function */
1875 Spec->EmbedDim[Spec->N_Surfs-1] = 3;
1876 Spec->VolParName[Spec->N_Surfs-1][0] = '\0';
1877 Spec->SurfaceLabel[Spec->N_Surfs-1][0] = '\0';
1878 Spec->AnatCorrect[Spec->N_Surfs-1][0] = '\0';
1879 Spec->Hemisphere[Spec->N_Surfs-1][0] = '\0';
1880 Spec->DomainGrandParentID[Spec->N_Surfs-1][0] = '\0';
1881 Spec->OriginatorID[Spec->N_Surfs-1][0] = '\0';
1882 Spec->LocalCurvatureParent[Spec->N_Surfs-1][0] = '\0';
1883 Spec->LocalDomainParent[Spec->N_Surfs-1][0] = '\0';
1884 Spec->LabelDset[Spec->N_Surfs-1][0] = '\0';
1885 Spec->NodeMarker[Spec->N_Surfs-1][0] = '\0';
1886 } else {
1887 /* make sure important fields have been filled */
1888 if (Spec->SurfaceType[Spec->N_Surfs-2][0] == '\0') {
1889 fprintf(SUMA_STDERR,
1890 "Error %s: Failed to specify surface type "
1891 "for surface %d\n",
1892 FuncName, Spec->N_Surfs-2);
1893 SUMA_RETURN (NOPE);
1894 }
1895 /* initilize SOME of the fields to previous one */
1896 Spec->CoordFile[Spec->N_Surfs-1][0] = '\0'; /* *** BA, Dec 03 */
1897 Spec->SurfaceFile[Spec->N_Surfs-1][0] = '\0';/* *** BA, Dec 03 */
1898
1899 strcpy( Spec->SurfaceFormat[Spec->N_Surfs-1],
1900 Spec->SurfaceFormat[Spec->N_Surfs-2]);
1901 strcpy( Spec->SurfaceType[Spec->N_Surfs-1],
1902 Spec->SurfaceType[Spec->N_Surfs-2]);
1903 strcpy( Spec->TopoFile[Spec->N_Surfs-1],
1904 Spec->TopoFile[Spec->N_Surfs-2]);
1905 strcpy( Spec->MappingRef[Spec->N_Surfs-1],
1906 Spec->MappingRef[Spec->N_Surfs-2]);/* Should become
1907 obsolete,
1908 ZSS Jan 02 03 */
1909 strcpy( Spec->SureFitVolParam[Spec->N_Surfs-1],
1910 Spec->SureFitVolParam[Spec->N_Surfs-2]);
1911 Spec->VolParName[Spec->N_Surfs-1][0] = '\0';
1912 /* it is confusing to users to inherit
1913 this one from the pervious, keep it separate.*/
1914 Spec->IDcode[Spec->N_Surfs-1] = NULL; /* this field is set in
1915 LoadSpec function */
1916 Spec->SurfaceLabel[Spec->N_Surfs-1][0] = '\0';
1917 strcpy( Spec->Group[Spec->N_Surfs-1],
1918 Spec->Group[Spec->N_Surfs-2]);
1919 strcpy( Spec->State[Spec->N_Surfs-1],
1920 Spec->State[Spec->N_Surfs-2]);
1921 Spec->EmbedDim[Spec->N_Surfs-1] =
1922 Spec->EmbedDim[Spec->N_Surfs-2];
1923 /* perhaps make these inheritable from previous */
1924 Spec->AnatCorrect[Spec->N_Surfs-1][0] = '\0';
1925 Spec->Hemisphere[Spec->N_Surfs-1][0] = '\0';
1926 Spec->DomainGrandParentID[Spec->N_Surfs-1][0] = '\0';
1927 Spec->OriginatorID[Spec->N_Surfs-1][0] = '\0';
1928 Spec->LocalCurvatureParent[Spec->N_Surfs-1][0] = '\0';
1929 Spec->LocalDomainParent[Spec->N_Surfs-1][0] = '\0';
1930 Spec->LabelDset[Spec->N_Surfs-1][0] = '\0';
1931 Spec->NodeMarker[Spec->N_Surfs-1][0] = '\0';
1932 /* only Spec->CoordFile, Spec->SurfaceFile MUST be
1933 specified with a new surface */
1934 }
1935 OKread_SurfaceFormat = OKread_SurfaceType = OKread_TopoFile =
1936 OKread_CoordFile = YUP;
1937 OKread_MappingRef = OKread_SureFitVolParam =
1938 OKread_FreeSurferSurface = OKread_InventorSurface = YUP;
1939 OKread_Group = OKread_State = OKread_EmbedDim =
1940 OKread_SurfaceLabel = OKread_SurfaceVolume = YUP;
1941 OKread_AnatCorrect = OKread_Hemisphere =
1942 OKread_DomainGrandParentID = OKread_OriginatorID = YUP;
1943 OKread_LocalCurvatureParent = OKread_LocalDomainParent =
1944 OKread_LabelDset = OKread_NodeMarker = YUP;
1945 skp = 1;
1946 }
1947
1948 sprintf(stmp,"StateDef");
1949 if (!skp && SUMA_iswordin (s, stmp) == 1) {
1950 /* found a state definition, parse it
1951 Use Spec->State[0] as buffer, since SurfaceState comes later*/
1952 if (LocalHead)
1953 fprintf( SUMA_STDERR,
1954 "%s: Sending %p )\n",
1955 FuncName, Spec->State[0]);
1956 if (!SUMA_ParseLHS_RHS (
1957 s, stmp,
1958 Spec->State[0])) {
1959 fprintf( SUMA_STDERR,
1960 "Error %s: Error in SUMA_ParseLHS_RHS.\n",
1961 FuncName);
1962 SUMA_RETURN (NOPE);
1963 }
1964
1965 if (LHunify) { /* remove the separation of left/right deformed states
1966 the _lh and _rh are what @SUMA_Make_Spec_FS used
1967 to flag these special states */
1968 SUMA_LH_UNIFY_STATE_FIX(Spec->State[0]);
1969 }
1970 if (Spec->N_States == 0) {
1971 /* first state, add it to the list of states */
1972 sprintf(Spec->StateList, "%s|", Spec->State[0]);
1973 Spec->N_States += 1;
1974 } else {
1975 if (strcmp(Spec->StateList, Spec->State[0]) == 0) {
1976 /* it's a duplicate, complain and get outa here */
1977 fprintf( SUMA_STDERR,
1978 "Error %s: Duplicate StateDef (%s).\n",
1979 FuncName, Spec->State[0]);
1980 SUMA_RETURN (NOPE);
1981 } else {
1982 /* a new one, add it to the list and
1983 increment States counter */
1984 Spec->StateList =
1985 SUMA_append_replace_string(
1986 Spec->StateList, "|",
1987 Spec->State[0], 1);
1988 Spec->N_States += 1;
1989 }
1990 }
1991 Spec->State[0][0] = '\0';
1992 skp = 1;
1993 }
1994
1995 sprintf(stmp,"Group");
1996 if (!skp && SUMA_iswordin (s, stmp) == 1) {
1997 /* found a group definition, parse it */
1998 if (LocalHead)
1999 fprintf(SUMA_STDERR,"%s: Found %s.\n", FuncName, stmp);
2000 if (Spec->N_Surfs < 1) { /* no surfaces have been defined yet,
2001 group goes for all */
2002 if (!SUMA_ParseLHS_RHS (
2003 s, stmp,
2004 Spec->Group[0])) {
2005 fprintf( SUMA_STDERR,
2006 "Error %s: Error in SUMA_ParseLHS_RHS.\n",
2007 FuncName);
2008 SUMA_RETURN (NOPE);
2009 }
2010 } else {
2011 if (!SUMA_ParseLHS_RHS (
2012 s, stmp,
2013 Spec->Group[Spec->N_Surfs-1])) {
2014 fprintf( SUMA_STDERR,
2015 "Error %s: Error in SUMA_ParseLHS_RHS.\n",
2016 FuncName);
2017 SUMA_RETURN (NOPE);
2018 }
2019 }
2020
2021 if (Spec->N_Surfs < 1) Spec->N_Groups += 1;
2022 else { /* recount groups */
2023 Spec->N_Groups = 1;
2024 for (kkk=0; kkk< Spec->N_Surfs -1; ++kkk) {
2025 if (strcmp(Spec->Group[kkk], Spec->Group[0])) {
2026 Spec->N_Groups += 1; /* Have new group */
2027 break;
2028 }
2029 }
2030 }
2031
2032 if (!OKread_Group) {
2033 fprintf( SUMA_STDERR,"Error %s: %s %s\n",
2034 FuncName, DupWarn, stmp);
2035 SUMA_RETURN (NOPE);
2036 } else {
2037 OKread_Group = NOPE;
2038 }
2039 skp = 1;
2040 }
2041
2042 sprintf(stmp,"Anatomical");
2043 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2044 /* found Anatomically Correct field, parse it */
2045 if (!SUMA_ParseLHS_RHS (s, stmp,
2046 Spec->AnatCorrect[Spec->N_Surfs-1])) {
2047 fprintf( SUMA_STDERR,
2048 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2049 SUMA_RETURN (NOPE);
2050 }
2051 if ( strcmp(Spec->AnatCorrect[Spec->N_Surfs-1],"Y") &&
2052 strcmp(Spec->AnatCorrect[Spec->N_Surfs-1],"N")) {
2053 SUMA_SL_Err("Anatomical can only be Y ot N");
2054 SUMA_RETURN (NOPE);
2055 }
2056 if (!OKread_AnatCorrect) {
2057 fprintf( SUMA_STDERR,"Error %s: %s %s\n",
2058 FuncName, DupWarn, stmp);
2059 SUMA_RETURN (NOPE);
2060 } else {
2061 OKread_AnatCorrect = NOPE;
2062 }
2063 skp = 1;
2064 }
2065
2066 sprintf(stmp,"Hemisphere");
2067 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2068 /* found Hemisphere field, parse it */
2069 if (!SUMA_ParseLHS_RHS (
2070 s, stmp,
2071 Spec->Hemisphere[Spec->N_Surfs-1])) {
2072 fprintf(SUMA_STDERR,
2073 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2074 SUMA_RETURN (NOPE);
2075 }
2076 if ( strcmp(Spec->Hemisphere[Spec->N_Surfs-1],"L") &&
2077 strcmp(Spec->Hemisphere[Spec->N_Surfs-1],"R") &&
2078 strcmp(Spec->Hemisphere[Spec->N_Surfs-1],"B")) {
2079 SUMA_SL_Err("Hemisphere can only be L or R or B");
2080 SUMA_RETURN (NOPE);
2081 }
2082 if (!OKread_Hemisphere) {
2083 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2084 SUMA_RETURN (NOPE);
2085 } else {
2086 OKread_Hemisphere = NOPE;
2087 }
2088 skp = 1;
2089 }
2090
2091 sprintf(stmp,"DomainGrandParentID");
2092 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2093 /* found DomainGrandParentID field, parse it */
2094 if (!SUMA_ParseLHS_RHS (
2095 s, stmp,
2096 Spec->DomainGrandParentID[Spec->N_Surfs-1])) {
2097 fprintf( SUMA_STDERR,
2098 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2099 SUMA_RETURN (NOPE);
2100 }
2101
2102 if (!OKread_DomainGrandParentID) {
2103 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2104 SUMA_RETURN (NOPE);
2105 } else {
2106 OKread_DomainGrandParentID = NOPE;
2107 }
2108 skp = 1;
2109 }
2110
2111 sprintf(stmp,"OriginatorID");
2112 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2113 /* found OriginatorID field, parse it */
2114 if (!SUMA_ParseLHS_RHS (
2115 s, stmp,
2116 Spec->OriginatorID[Spec->N_Surfs-1])) {
2117 fprintf( SUMA_STDERR,
2118 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2119 SUMA_RETURN (NOPE);
2120 }
2121
2122 if (!OKread_OriginatorID) {
2123 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2124 SUMA_RETURN (NOPE);
2125 } else {
2126 OKread_OriginatorID = NOPE;
2127 }
2128 skp = 1;
2129 }
2130
2131 sprintf(stmp,"LocalCurvatureParent");
2132 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2133 /* found LocalCurvatureParent field, parse it */
2134 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2135 fprintf( SUMA_STDERR,
2136 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2137 SUMA_RETURN (NOPE);
2138 }
2139 snprintf (Spec->LocalCurvatureParent[Spec->N_Surfs-1],
2140 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2141 "%s%s", Spec->SpecFilePath, stmp2);
2142
2143 if (!OKread_LocalCurvatureParent) {
2144 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2145 SUMA_RETURN (NOPE);
2146 } else {
2147 OKread_LocalCurvatureParent = NOPE;
2148 }
2149 skp = 1;
2150 }
2151
2152 sprintf(stmp,"LocalDomainParent");
2153 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2154 /* found LocalDomainParent field, parse it */
2155 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2156 fprintf( SUMA_STDERR,
2157 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2158 SUMA_RETURN (NOPE);
2159 }
2160
2161 snprintf (Spec->LocalDomainParent[Spec->N_Surfs-1],
2162 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2163 "%s%s", Spec->SpecFilePath, stmp2);
2164
2165 if (!OKread_LocalDomainParent) {
2166 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2167 SUMA_RETURN (NOPE);
2168 } else {
2169 OKread_LocalDomainParent = NOPE;
2170 }
2171 skp = 1;
2172 }
2173
2174 sprintf(stmp,"LabelDset");
2175 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2176 /* found LabelDset field, parse it */
2177 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2178 fprintf( SUMA_STDERR,
2179 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2180 SUMA_RETURN (NOPE);
2181 }
2182
2183 snprintf (Spec->LabelDset[Spec->N_Surfs-1],
2184 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2185 "%s%s", Spec->SpecFilePath, stmp2);
2186
2187 if (!OKread_LabelDset) {
2188 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2189 SUMA_RETURN (NOPE);
2190 } else {
2191 OKread_LabelDset = NOPE;
2192 }
2193 skp = 1;
2194 }
2195
2196 sprintf(stmp,"NodeMarker");
2197 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2198 /* found NodeMarker field, parse it */
2199 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2200 fprintf( SUMA_STDERR,
2201 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2202 SUMA_RETURN (NOPE);
2203 }
2204
2205 snprintf (Spec->NodeMarker[Spec->N_Surfs-1],
2206 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2207 "%s%s", Spec->SpecFilePath, stmp2);
2208
2209 if (!OKread_NodeMarker) {
2210 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2211 SUMA_RETURN (NOPE);
2212 } else {
2213 OKread_NodeMarker = NOPE;
2214 }
2215 skp = 1;
2216 }
2217
2218
2219 sprintf(stmp,"EmbedDimension");
2220 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2221 /* found surface embedding dimension, parse it */
2222 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2223 fprintf( SUMA_STDERR,
2224 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2225 SUMA_RETURN (NOPE);
2226 }
2227 Spec->EmbedDim[Spec->N_Surfs-1] = atoi(stmp2);
2228 if ( Spec->EmbedDim[Spec->N_Surfs-1] < 2 ||
2229 Spec->EmbedDim[Spec->N_Surfs-1] > 3) {
2230 fprintf( SUMA_STDERR,
2231 "Error %s: Bad Embedding dimension %d.\n"
2232 "Only 2 and 3 allowed.\n",
2233 FuncName, Spec->EmbedDim[Spec->N_Surfs-1]);
2234 SUMA_RETURN (NOPE);
2235 }
2236 if (!OKread_EmbedDim) {
2237 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2238 SUMA_RETURN (NOPE);
2239 } else {
2240 OKread_EmbedDim = NOPE;
2241 }
2242 skp = 1;
2243 }
2244
2245 sprintf(stmp,"SurfaceState");
2246 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2247 /* found surface state, parse it */
2248 if (!SUMA_ParseLHS_RHS (
2249 s, stmp,
2250 Spec->State[Spec->N_Surfs-1])) {
2251 fprintf( SUMA_STDERR,
2252 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2253 SUMA_RETURN (NOPE);
2254 }
2255 if (LHunify) {
2256 SUMA_LH_UNIFY_STATE_FIX(Spec->State[Spec->N_Surfs-1]);
2257 }
2258
2259 /* make sure it is in the StateList */
2260 if (SUMA_iswordin (Spec->StateList, Spec->State[Spec->N_Surfs-1])
2261 != 1) {
2262 fprintf( SUMA_STDERR,
2263 "Error %s: State %s was not predefined in StateDef.\n"
2264 "StateDef List (| delimited) = %s \n",\
2265 FuncName, Spec->State[Spec->N_Surfs-1], Spec->StateList);
2266 SUMA_RETURN (NOPE);
2267 }
2268 if (!OKread_State) {
2269 fprintf( SUMA_STDERR,
2270 "Error %s: %s %s\n", FuncName, DupWarn, stmp);
2271 SUMA_RETURN (NOPE);
2272 } else {
2273 OKread_State = NOPE;
2274 }
2275 skp = 1;
2276 }
2277
2278 sprintf(stmp,"SurfaceFormat");
2279 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2280 if (Spec->N_Surfs < 1) {
2281 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2282 SUMA_RETURN (NOPE);
2283 }
2284 /*fprintf(SUMA_STDERR,"Found %s: ", stmp);*/
2285
2286 if (!SUMA_ParseLHS_RHS (
2287 s, stmp,
2288 Spec->SurfaceFormat[Spec->N_Surfs-1])) {
2289 fprintf( SUMA_STDERR,
2290 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2291 SUMA_RETURN (NOPE);
2292 }
2293
2294 if (!OKread_SurfaceFormat) {
2295 fprintf( SUMA_STDERR,
2296 "Error %s: %s %s\n", FuncName, DupWarn, stmp);
2297 SUMA_RETURN (NOPE);
2298 } else {
2299 OKread_SurfaceFormat = NOPE;
2300 }
2301 skp = 1;
2302 /*fprintf( SUMA_STDERR,"%s\n",
2303 Spec->SurfaceFormat[Spec->N_Surfs-1]);*/
2304 }
2305
2306 sprintf(stmp,"SurfaceType");
2307 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2308 if (Spec->N_Surfs < 1) {
2309 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2310 SUMA_RETURN (NOPE);
2311 }
2312 /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
2313 if (!SUMA_ParseLHS_RHS (
2314 s, stmp,
2315 Spec->SurfaceType[Spec->N_Surfs-1])) {
2316 fprintf( SUMA_STDERR,
2317 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2318 SUMA_RETURN (NOPE);
2319 }
2320 if (!OKread_SurfaceType) {
2321 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2322 SUMA_RETURN (NOPE);
2323 } else {
2324 OKread_SurfaceType = NOPE;
2325 }
2326 skp = 1;
2327 }
2328
2329 sprintf(stmp,"TopoFile");
2330 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2331 /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
2332 if (Spec->N_Surfs < 1) {
2333 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2334 SUMA_RETURN (NOPE);
2335 }
2336 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2337 fprintf( SUMA_STDERR,
2338 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2339 SUMA_RETURN (NOPE);
2340 }
2341 snprintf(Spec->TopoFile[Spec->N_Surfs-1],
2342 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2343 "%s%s", Spec->SpecFilePath, stmp2);
2344
2345 if (!OKread_TopoFile) {
2346 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2347 SUMA_RETURN (NOPE);
2348 } else {
2349 OKread_TopoFile = NOPE;
2350 }
2351 skp = 1;
2352 }
2353
2354 sprintf(stmp,"SureFitTopo");
2355 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2356 /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
2357 if (Spec->N_Surfs < 1) {
2358 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2359 SUMA_RETURN (NOPE);
2360 }
2361 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2362 fprintf( SUMA_STDERR,
2363 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2364 SUMA_RETURN (NOPE);
2365 }
2366 snprintf(Spec->TopoFile[Spec->N_Surfs-1],
2367 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),"%s%s",
2368 Spec->SpecFilePath, stmp2);
2369
2370 if (!OKread_TopoFile) {
2371 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2372 SUMA_RETURN (NOPE);
2373 } else {
2374 OKread_TopoFile = NOPE;
2375 }
2376 skp = 1;
2377 }
2378
2379 sprintf(stmp,"CoordFile");
2380 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2381 /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
2382 if (Spec->N_Surfs < 1) {
2383 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2384 SUMA_RETURN (NOPE);
2385 }
2386 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2387 fprintf( SUMA_STDERR,
2388 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2389 SUMA_RETURN (NOPE);
2390 }
2391 snprintf (Spec->CoordFile[Spec->N_Surfs-1],
2392 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2393 "%s%s", Spec->SpecFilePath, stmp2);
2394
2395 if (!OKread_CoordFile) {
2396 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2397 SUMA_RETURN (NOPE);
2398 } else {
2399 OKread_CoordFile = NOPE;
2400 }
2401 skp = 1;
2402 }
2403
2404 sprintf(stmp,"SureFitCoord");
2405 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2406 /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
2407 if (Spec->N_Surfs < 1) {
2408 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2409 SUMA_RETURN (NOPE);
2410 }
2411 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2412 fprintf( SUMA_STDERR,
2413 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2414 SUMA_RETURN (NOPE);
2415 }
2416 snprintf (Spec->CoordFile[Spec->N_Surfs-1],
2417 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2418 "%s%s", Spec->SpecFilePath, stmp2);
2419
2420 if (!OKread_CoordFile) {
2421 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2422 SUMA_RETURN (NOPE);
2423 } else {
2424 OKread_CoordFile = NOPE;
2425 }
2426 skp = 1;
2427 }
2428
2429 sprintf(stmp,"MappingRef");
2430 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2431 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2432 if (Spec->N_Surfs < 1) {
2433 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2434 SUMA_RETURN (NOPE);
2435 }
2436 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2437 fprintf( SUMA_STDERR,
2438 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2439 SUMA_RETURN (NOPE);
2440 }
2441 snprintf (Spec->MappingRef[Spec->N_Surfs-1],
2442 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2443 "%s%s", Spec->SpecFilePath, stmp2);
2444 if (!OKread_MappingRef) {
2445 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2446 SUMA_RETURN (NOPE);
2447 } else {
2448 OKread_MappingRef = NOPE;
2449 }
2450 skp = 1;
2451 }
2452 /* Should become obsolete, ZSS Jan 02 03 */
2453
2454 sprintf(stmp,"SureFitVolParam");
2455 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2456 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2457 if (Spec->N_Surfs < 1) {
2458 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2459 SUMA_RETURN (NOPE);
2460 }
2461 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2462 fprintf( SUMA_STDERR,
2463 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2464 SUMA_RETURN (NOPE);
2465 }
2466 snprintf (Spec->SureFitVolParam[Spec->N_Surfs-1],
2467 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2468 "%s%s", Spec->SpecFilePath, stmp2);
2469
2470 if (!OKread_SureFitVolParam) {
2471 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2472 SUMA_RETURN (NOPE);
2473 } else {
2474 OKread_SureFitVolParam = NOPE;
2475 }
2476 skp = 1;
2477 }
2478
2479 sprintf(stmp,"FreeSurferSurface");
2480 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2481 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2482 if (Spec->N_Surfs < 1) {
2483 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2484 SUMA_RETURN (NOPE);
2485 }
2486 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2487 fprintf(SUMA_STDERR,
2488 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2489 SUMA_RETURN (NOPE);
2490 }
2491 snprintf (Spec->SurfaceFile[Spec->N_Surfs-1],
2492 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2493 "%s%s", Spec->SpecFilePath, stmp2);
2494 if (!OKread_FreeSurferSurface) {
2495 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2496 SUMA_RETURN (NOPE);
2497 } else {
2498 OKread_FreeSurferSurface = NOPE;
2499 }
2500 skp = 1;
2501 }
2502
2503 sprintf(stmp,"SurfaceName");
2504 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2505 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2506 if (Spec->N_Surfs < 1) {
2507 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2508 SUMA_RETURN (NOPE);
2509 }
2510 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2511 fprintf( SUMA_STDERR,
2512 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2513 SUMA_RETURN (NOPE);
2514 }
2515 snprintf (Spec->SurfaceFile[Spec->N_Surfs-1],
2516 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2517 "%s%s", Spec->SpecFilePath, stmp2);
2518 if (!OKread_FreeSurferSurface) {
2519 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2520 SUMA_RETURN (NOPE);
2521 } else {
2522 OKread_FreeSurferSurface = NOPE;
2523 }
2524 if (onGIFTIalert) {
2525 if (SUMA_isExtension(Spec->SurfaceFile[Spec->N_Surfs-1],".gii")) {
2526 /* have gifti file with N27 spec, check gifti date */
2527 if (THD_filetime_diff(Spec->SurfaceFile[Spec->N_Surfs-1],
2528 2013, 8, 1) < 0) {
2529 SUMA_S_Warnv(
2530 "*******************************************************\n"
2531 "File %s is probably from SUMA's \n"
2532 "N27 GIFTI surfaces that are in RAI. With this new version\n"
2533 "of SUMA all GIFTI surfaces must be in LPI.\n"
2534 "\n"
2535 "You need to either correct these old surfaces or get\n"
2536 "a new copy of the template surface archives: \n"
2537 " https://afni.nimh.nih.gov/pub/dist/tgz/suma_MNI_N27.tgz\n"
2538 "or\n"
2539 " https://afni.nimh.nih.gov/pub/dist/tgz/suma_TT_N27.tgz\n"
2540 "or\n"
2541 " https://afni.nimh.nih.gov/pub/dist/tgz/suma_MNI152_2009.tgz\n"
2542 "\n"
2543 "If you choose to correct what you have, instead of a new\n"
2544 "download, see the help for option -nocor in @SUMA_Make_Spec_FS \n"
2545 "for suggestions.\n"
2546 "\n"
2547 "Results obtained with older versions of SUMA on old GIFTI\n"
2548 "surfaces are valid. You just can't mix old files with \n"
2549 "versions of SUMA postdating Aug. 1st 2013\n"
2550 "As usual, if you have concerns, open surfaces in SUMA \n"
2551 "and talk to AFNI. If contours line up, you're OK.\n"
2552 "*******************************************************\n"
2553 "*******************************************************\n"
2554 "\n",
2555 Spec->SurfaceFile[Spec->N_Surfs-1]);
2556
2557 }
2558 }
2559 }
2560 skp = 1;
2561 }
2562
2563 sprintf(stmp,"InventorSurface");
2564 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2565 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2566 if (Spec->N_Surfs < 1) {
2567 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2568 SUMA_RETURN (NOPE);
2569 }
2570 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2571 fprintf(SUMA_STDERR,
2572 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2573 SUMA_RETURN (NOPE);
2574 }
2575 snprintf(Spec->SurfaceFile[Spec->N_Surfs-1],
2576 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2577 "%s%s", Spec->SpecFilePath, stmp2);
2578
2579 if (!OKread_InventorSurface) {
2580 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2581 SUMA_RETURN (NOPE);
2582 } else {
2583 OKread_InventorSurface = NOPE;
2584 }
2585 skp = 1;
2586 }
2587
2588 sprintf(stmp,"SurfaceVolume");
2589 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2590 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2591 if (Spec->N_Surfs < 1) {
2592 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2593 SUMA_RETURN (NOPE);
2594 }
2595 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2596 fprintf(SUMA_STDERR,
2597 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2598 SUMA_RETURN (NOPE);
2599 }
2600
2601 fprintf(SUMA_STDOUT,
2602 "Note %s: Found SurfaceVolume in Spec File, "
2603 "Name must include path to volume.\n", FuncName);
2604
2605 sprintf(Spec->VolParName[Spec->N_Surfs-1], "%s", stmp2);
2606
2607 if (!OKread_SurfaceVolume) {
2608 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2609 SUMA_RETURN (NOPE);
2610 } else {
2611 OKread_SurfaceVolume = NOPE;
2612 }
2613 skp = 1;
2614 }
2615
2616 sprintf(stmp,"SurfaceLabel");
2617 if (!skp && SUMA_iswordin (s, stmp) == 1) {
2618 if (LocalHead) fprintf(SUMA_STDERR,"Found %s\n", stmp);
2619 if (Spec->N_Surfs < 1) {
2620 fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
2621 SUMA_RETURN (NOPE);
2622 }
2623 if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
2624 fprintf( SUMA_STDERR,
2625 "Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
2626 SUMA_RETURN (NOPE);
2627 }
2628
2629 sprintf(Spec->SurfaceLabel[Spec->N_Surfs-1], "%s", stmp2);
2630
2631 if (!OKread_SurfaceLabel) {
2632 fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
2633 SUMA_RETURN (NOPE);
2634 } else {
2635 OKread_SurfaceLabel = NOPE;
2636 }
2637 skp = 1;
2638 }
2639
2640 if (!skp) {
2641 fprintf(SUMA_STDERR,
2642 "Error %s: Your spec file contains uncommented gibberish:\n"
2643 " %s\n"
2644 "Please deal with it.\n",
2645 FuncName, s);
2646 SUMA_RETURN (NOPE);
2647 }
2648 } else {/* not not a comment */
2649 /*fprintf(SUMA_STDERR,"A comment: %s\n", s);*/
2650 }
2651
2652 /* read the next line */
2653 do {
2654 ex = fscanf (sf_file,"%c",&c);
2655 } while (ex!=EOF && isspace(c));
2656 i=0;
2657 while (ex != EOF && c != '\n') {
2658 s[i] = c; ++i;
2659 ex = fscanf (sf_file,"%c",&c);
2660 }
2661 s[i] = '\0';
2662 if (LocalHead) fprintf(SUMA_STDERR,"Read %s\n", s);
2663 }
2664 fclose (sf_file);
2665 /* make sure last entry was good */
2666 if (Spec->SurfaceType[Spec->N_Surfs-1][0] == '\0') {
2667 fprintf( SUMA_STDERR,
2668 "Error %s: Failed to specify surface type for surface %d\n",
2669 FuncName, Spec->N_Surfs-1);
2670 SUMA_RETURN (NOPE);
2671 }
2672
2673 if (!SUMA_CheckOnSpecFile (Spec)) {
2674 SUMA_SL_Err("Badness in the spec file.\n");
2675 SUMA_RETURN(NOPE);
2676 }
2677
2678 SUMA_RETURN (YUP);
2679 }/* SUMA_Read_SpecFile */
2680
2681
2682 /*!
2683 \brief merge left and right side specfiles in a manner that suits AFNI
2684 */
2685 #define SUMA_COPY_SPEC_FIELD(trgspec, cnt, srcspec, isurf, fld) { \
2686 if(srcspec->fld[isurf]) {\
2687 snprintf(trgspec->fld[cnt], \
2688 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),\
2689 "%s", srcspec->fld[isurf]); \
2690 } else { /* Should not happen */\
2691 fprintf(SUMA_STDERR, "** Error %s\n" \
2692 "This should not be\n", FuncName); \
2693 } \
2694 }
SUMA_Merge_SpecFiles(SUMA_SurfSpecFile * lhs,SUMA_SurfSpecFile * rhs,SUMA_SurfSpecFile * bhs,char * FileName)2695 SUMA_Boolean SUMA_Merge_SpecFiles( SUMA_SurfSpecFile *lhs,
2696 SUMA_SurfSpecFile *rhs,
2697 SUMA_SurfSpecFile *bhs,
2698 char *FileName)
2699 {
2700 static char FuncName[]={"SUMA_Merge_SpecFiles"};
2701 SUMA_SurfSpecFile *vs[20];
2702 char *ss[20], *ns=NULL;
2703 int i, c, k;
2704 SUMA_Boolean LocalHead=NOPE;
2705
2706 SUMA_ENTRY;
2707
2708 if (!lhs || !rhs || !bhs ||
2709 (!lhs->N_Surfs && !rhs->N_Surfs) ) SUMA_RETURN(NOPE);
2710
2711 SUMA_LH("Init");
2712 if (!SUMA_AllocSpecFields(bhs)) {
2713 SUMA_S_Err("Failed to init spec fields.");
2714 SUMA_RETURN(NOPE);
2715 }
2716
2717 vs[0] = lhs;
2718 ss[0] = "_lh";
2719 vs[1] = rhs;
2720 ss[1] = "_rh";
2721
2722 SUMA_LH("Check");
2723 /* checks */
2724 for (k=1; k<2; ++k) {
2725 if (strcmp(lhs->Group[0], rhs->Group[0])) {
2726 SUMA_S_Err("Not ready to merge different groups");
2727 SUMA_RETURN(NOPE);
2728 }
2729 }
2730
2731
2732 /* loop accross states and relabel non-anatomically correct states */
2733 c = 0;
2734 for (k=0; k<2; ++k) {
2735 for (i=0; i<vs[k]->N_Surfs; ++i) {
2736 SUMA_LHv("Copy vs[%d,%d]-->%d\n",k,i,c);
2737 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, SurfaceType);
2738 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, SurfaceFormat);
2739 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, TopoFile);
2740 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, CoordFile);
2741 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, MappingRef);
2742 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, SureFitVolParam);
2743 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, SurfaceFile);
2744 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, VolParName);
2745 bhs->IDcode[c] = vs[k]->IDcode[i];/* IDcode is a pointer copy */
2746 if (vs[k]->AnatCorrect[i][0] == 'N') {
2747 ns = SUMA_append_string(vs[k]->State[i],ss[k]);
2748 snprintf(bhs->State[c],
2749 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2750 "%s", ns); SUMA_free(ns); ns = NULL;
2751 } else {
2752 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, State);
2753 }
2754 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, LabelDset);
2755 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, NodeMarker);
2756 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, Group);
2757 if (strcmp(bhs->Group[0], vs[k]->Group[i])) {
2758 SUMA_S_Warn("Unexpected Group mismatch!\n"
2759 "Assumption was that all surfs\n"
2760 "in spec file are of the same group\n"
2761 "Proceeding, beware.\n");
2762 }
2763 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, SurfaceLabel);
2764 bhs->EmbedDim[c] = vs[k]->EmbedDim[i];
2765 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, AnatCorrect);
2766 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, Hemisphere);
2767 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, DomainGrandParentID);
2768 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, OriginatorID);
2769 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, LocalCurvatureParent);
2770 SUMA_COPY_SPEC_FIELD(bhs, c, vs[k], i, LocalDomainParent);
2771 ++c;
2772 }
2773 }
2774
2775 bhs->N_Surfs = c;
2776 bhs->N_Groups = 1;
2777
2778 SUMA_LH("States");
2779 /* do the states */
2780 sprintf(bhs->StateList, "%s|", bhs->State[0]);
2781 bhs->N_States = 1;
2782 for (c=1; c<bhs->N_Surfs; ++c) {
2783 SUMA_LHv("Is %s in %s\n", bhs->State[c], bhs->StateList);
2784 if (!strstr(bhs->StateList, bhs->State[c])) {/* new one */
2785 SUMA_LH(" No");
2786 bhs->StateList = SUMA_append_replace_string(bhs->StateList, "|",
2787 bhs->State[c], 1);
2788 bhs->N_States += 1;
2789 }
2790 }
2791
2792 snprintf(bhs->SpecFilePath,
2793 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2794 "%s", SUMA_FnameGet(FileName,"Pa", SUMAg_CF->cwd));
2795 snprintf(bhs->SpecFileName,
2796 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
2797 "%s", SUMA_FnameGet(FileName,"f", SUMAg_CF->cwd));
2798
2799
2800 SUMA_RETURN(YUP);
2801 }
2802
2803 /*!
2804 Remove surfaces of a certain state from the spec struct
2805 If ldp is not NULL, remove if both domain parent and the
2806 state match. ldp match is always partial.
2807
2808 Returns the number of surfaces remaining in the spec struct
2809 */
SUMA_RemoveSpecState(SUMA_SurfSpecFile * Spec,char * state_rm,int exact_match,char * ldp)2810 int SUMA_RemoveSpecState(SUMA_SurfSpecFile *Spec,
2811 char *state_rm, int exact_match,
2812 char *ldp)
2813 {
2814 static char FuncName[]={"SUMA_RemoveSpecState"};
2815 int i, k, copyit;
2816 SUMA_Boolean LocalHead = NOPE;
2817
2818 SUMA_ENTRY;
2819
2820 if (!Spec || !state_rm) SUMA_RETURN(0);
2821
2822 k = 0;
2823 for (i=0; i<Spec->N_Surfs; ++i) {
2824 copyit = 1;
2825 if ( (exact_match == 0 && strstr(Spec->State[i],state_rm)) ||
2826 (exact_match == 1 && !strcmp(Spec->State[i],state_rm))) {
2827 /* found state to remove */
2828 copyit = 0;
2829 SUMA_LHv("Will remove %s\n", Spec->State[i]);
2830 }
2831 /* don't use exact match for Spec->LocalDomainParent[i],
2832 unless you account for the paths. "SAME" ends up being
2833 "./SAME", for example. */
2834 if (!copyit && ldp && !strstr(Spec->LocalDomainParent[i], ldp)) {
2835 /* no match for ldp, cancel */
2836 copyit = 1;
2837 SUMA_LHv("Canceling removal ldp is %s\n", Spec->LocalDomainParent[i]);
2838 }
2839 if ( copyit ) {
2840 SUMA_LHv("Working to copy state %s for surface i=%d k=%d\n",
2841 Spec->State[i], i, k);
2842 if (k < i) {
2843 sprintf(Spec->State[k], "%s",Spec->State[i]);
2844 sprintf(Spec->SurfaceType[k], "%s",Spec->SurfaceType[i]);
2845 sprintf(Spec->SurfaceFormat[k], "%s",Spec->SurfaceFormat[i]);
2846 sprintf(Spec->TopoFile[k], "%s",Spec->TopoFile[i]);
2847 sprintf(Spec->CoordFile[k], "%s",Spec->CoordFile[i]);
2848 sprintf(Spec->MappingRef[k], "%s",Spec->MappingRef[i]);
2849 sprintf(Spec->SureFitVolParam[k], "%s",Spec->SureFitVolParam[i]);
2850 sprintf(Spec->SurfaceFile[k], "%s",Spec->SurfaceFile[i]);
2851 sprintf(Spec->VolParName[k], "%s",Spec->VolParName[i]);
2852 if (Spec->IDcode[i]) sprintf(Spec->IDcode[k], "%s",Spec->IDcode[i]);
2853 else Spec->IDcode[k]=NULL;
2854 sprintf(Spec->State[k], "%s",Spec->State[i]);
2855 sprintf(Spec->LabelDset[k], "%s",Spec->LabelDset[i]);
2856 sprintf(Spec->Group[k], "%s",Spec->Group[i]);
2857 sprintf(Spec->SurfaceLabel[k], "%s",Spec->SurfaceLabel[i]);
2858 Spec->EmbedDim[k] = Spec->EmbedDim[i];
2859 sprintf(Spec->AnatCorrect[k], "%s",Spec->AnatCorrect[i]);
2860 sprintf(Spec->Hemisphere[k], "%s",Spec->Hemisphere[i]);
2861 sprintf(Spec->DomainGrandParentID[k],
2862 "%s",Spec->DomainGrandParentID[i]);
2863 sprintf(Spec->OriginatorID[k], "%s",Spec->OriginatorID[i]);
2864 sprintf(Spec->LocalCurvatureParent[k],
2865 "%s",Spec->LocalCurvatureParent[i]);
2866 sprintf(Spec->LocalDomainParent[k], "%s",Spec->LocalDomainParent[i]);
2867 sprintf(Spec->NodeMarker[k], "%s",Spec->NodeMarker[i]);
2868 }
2869 ++k;
2870 }
2871 }
2872 if (k != Spec->N_Surfs) Spec->N_States = Spec->N_States-1;
2873 Spec->N_Surfs = k;
2874
2875 SUMA_RETURN(k);
2876 }
2877
2878 /*!
2879 \brief Write SUMA_SurfSpecFile structure to disk
2880 \param Spec: Structure containing specfile
2881 \param specFileNm: Name of specfile.
2882 If NULL, use
2883 name in Spec->SpecFileName
2884 \param program: name of program to put in comments if not NULL
2885 \param histnote: a history note to add as comment if not NULL
2886 */
SUMA_Write_SpecFile(SUMA_SurfSpecFile * Spec,char * specFileNmU,char * program,char * histnote)2887 SUMA_Boolean SUMA_Write_SpecFile ( SUMA_SurfSpecFile * Spec,
2888 char *specFileNmU,
2889 char *program,
2890 char *histnote) {
2891
2892 static char FuncName[]={"SUMA_Write_SpecFile"};
2893 FILE *outFile=NULL;
2894 int i=0, k=0, tag=0, ifSmwm=0, p=0;
2895 char writename[SUMA_MAX_FILENAME_LENGTH+3]={""};
2896 char *specFileNm=NULL;
2897
2898 SUMA_ENTRY;
2899
2900 if (!Spec) SUMA_RETURN(NOPE);
2901
2902
2903 if (specFileNmU && specFileNmU[0]) {
2904 specFileNm = SUMA_Extension(specFileNmU, ".spec", NOPE);
2905 sprintf(writename,"%s",specFileNm);
2906 } else {
2907 if (!Spec->SpecFileName) SUMA_RETURN(NOPE);
2908 specFileNm = SUMA_Extension(Spec->SpecFileName, ".spec", NOPE);
2909 if (Spec->SpecFilePath) {
2910 sprintf( writename,
2911 "%s/%s",
2912 Spec->SpecFilePath,
2913 specFileNm);
2914 } else {
2915 sprintf( writename,
2916 "%s",
2917 specFileNm);
2918 }
2919 }
2920 if (SUMA_filexists(writename) && !THD_ok_overwrite()) {
2921 SUMA_S_Errv("Spec file %s exists, will not overwrite\n", writename);
2922 SUMA_RETURN(NOPE);
2923 }
2924 if (specFileNm) SUMA_free(specFileNm); specFileNm = NULL;
2925
2926 outFile = fopen(writename, "w");
2927
2928 if (!outFile) {
2929 fprintf (SUMA_STDERR, "Failed in opening %s for writing.\n", writename);
2930 exit (1);
2931 }
2932 else {
2933 if (program && program[0])
2934 fprintf (outFile, "# %s generated spec file\n", program);
2935 if (histnote) fprintf (outFile, "#History: %s\n\n", histnote);
2936 else fprintf (outFile, "\n");
2937 fprintf (outFile, "#define the group\n\tGroup = %s\n\n", Spec->Group[0]);
2938 fprintf (outFile, "#define various States\n");
2939 for (i=0; i<Spec->N_Surfs; ++i) {
2940 tag = 0;
2941 for (k=0; k<i; ++k) {
2942 if ( strcmp( Spec->State[k], Spec->State[i] ) == 0 ) tag = -1;
2943 }
2944 if (tag==0) {
2945 fprintf( outFile, "\tStateDef = %s\n", Spec->State[i]);
2946 }
2947 }
2948
2949 for (i=0; i<Spec->N_Surfs; ++i) {
2950 fprintf (outFile,
2951 "\nNewSurface\n"
2952 "\tSurfaceFormat = %s\n"
2953 "\tSurfaceType = %s\n",
2954 Spec->SurfaceFormat[i],
2955 Spec->SurfaceType[i]);
2956 if (Spec->SurfaceFile[i][0]) {
2957 fprintf (outFile,
2958 "\tSurfaceName = %s\n",
2959 Spec->SurfaceFile[i] );
2960 } else {
2961 fprintf (outFile,
2962 "\tCoordFile = %s\n",
2963 Spec->CoordFile[i] );
2964 fprintf (outFile,
2965 "\tTopoFile = %s\n",
2966 Spec->TopoFile[i] );
2967 }
2968 if (Spec->SureFitVolParam[i][0]) {
2969 fprintf (outFile,
2970 "\tSureFitVolParam = %s\n",
2971 Spec->SureFitVolParam[i] );
2972 }
2973 if (Spec->LocalDomainParent[i][0]) {
2974 fprintf (outFile,
2975 "\tLocalDomainParent = %s\n",
2976 Spec->LocalDomainParent[i] );
2977 } else {
2978 fprintf (outFile,
2979 "\tLocalDomainParent = SAME\n" );
2980 }
2981 if (Spec->LabelDset[i][0]) {
2982 fprintf (outFile,
2983 "\tLabelDset = %s\n",
2984 Spec->LabelDset[i] );
2985 } else {
2986 }
2987 if (Spec->NodeMarker[i][0]) {
2988 fprintf (outFile,
2989 "\tNodeMarker = %s\n",
2990 Spec->NodeMarker[i] );
2991 } else {
2992 }
2993 fprintf (outFile, "\tSurfaceState = %s\n"
2994 "\tEmbedDimension = %d\n",
2995 Spec->State[i], Spec->EmbedDim[i]);
2996
2997 if (Spec->VolParName[i][0]) {
2998 fprintf (outFile,
2999 "\tSurfaceVolume = %s\n",
3000 Spec->VolParName[i] );
3001 }
3002 /* For now, only one group is allowed */
3003 if ( Spec->Group[i][0] && Spec->Group[0][0] &&
3004 strcmp(Spec->Group[i], Spec->Group[0])) {
3005 SUMA_S_Errv("SUMA does not read specfile with\n"
3006 "surfaces from multiple groups yet\n"
3007 "No point in trying to write that one.\n"
3008 "Group[%d]=%s and Group[0]=%s\n"
3009 , i, Spec->Group[i], Spec->Group[0]);
3010 SUMA_RETURN(NOPE);
3011 /* otherwise you just do:
3012 You can add this if all the groups are the same.
3013 SUMA will recognize that it is the same group and
3014 won't complain, but it might confuse the users*/
3015 if (Spec->Group[i][0]) {
3016 fprintf (outFile,
3017 "\tGroup = %s\n",
3018 Spec->Group[i] );
3019 }
3020 }
3021
3022 if (Spec->SurfaceLabel[i][0]) {
3023 fprintf (outFile,
3024 "\tSurfaceLabel = %s\n",
3025 Spec->SurfaceLabel[i] );
3026 }
3027 if (Spec->AnatCorrect[i][0]) {
3028 fprintf (outFile,
3029 "\tAnatomical = %s\n",
3030 Spec->AnatCorrect[i] );
3031 }
3032 if (Spec->Hemisphere[i][0]) {
3033 fprintf (outFile,
3034 "\tHemisphere = %s\n",
3035 Spec->Hemisphere[i] );
3036 }
3037 if (Spec->DomainGrandParentID[i][0]) {
3038 fprintf (outFile,
3039 "\tDomainGrandParentID = %s\n",
3040 Spec->DomainGrandParentID[i] );
3041 }
3042 if (Spec->OriginatorID[i][0]) {
3043 fprintf (outFile,
3044 "\tOriginatorID = %s\n",
3045 Spec->OriginatorID[i] );
3046 }
3047 if (Spec->LocalCurvatureParent[i][0]) {
3048 fprintf (outFile,
3049 "\tLocalCurvatureParent = %s\n",
3050 Spec->LocalCurvatureParent[i] );
3051 }
3052 /*
3053 if (Spec->xxx[i][0]) {
3054 fprintf (outFile,
3055 "\tyyy = %s\n",
3056 Spec->xxx[i] );
3057 }
3058 */
3059 }
3060
3061 fclose(outFile);
3062 }
3063 SUMA_RETURN(YUP);
3064 } /* SUMA_Write_SpecFile */
3065
3066 /*!
3067 \brief more checksums on the contents of the specfile
3068 */
SUMA_CheckOnSpecFile(SUMA_SurfSpecFile * Spec)3069 SUMA_Boolean SUMA_CheckOnSpecFile (SUMA_SurfSpecFile *Spec)
3070 {
3071 static char FuncName[]={"SUMA_CheckOnSpecFile"};
3072 static int ob_warn = 0;
3073 int i;
3074 SUMA_Boolean LocalHead = NOPE;
3075
3076 SUMA_ENTRY;
3077
3078 if (Spec->N_Surfs == -1) {
3079 SUMA_S_Err("Struct fresh out of SUMA_AllocSpecFields");
3080 SUMA_RETURN(NOPE);
3081 }
3082
3083 for (i=0; i<Spec->N_Surfs; ++i) {
3084 if ( Spec->MappingRef[i][0] &&
3085 (Spec->LocalDomainParent[i][0] ||
3086 Spec->LocalCurvatureParent[i][0] ||
3087 Spec->OriginatorID[i][0] ||
3088 Spec->DomainGrandParentID[i][0]) ) {
3089 SUMA_SL_Err("You cannont mix MappingRef with\n"
3090 "newer fields such as:\n"
3091 "LocalDomainParent, LocalCurvatureParent\n"
3092 "OriginatorID or DomainGrandParentID ");
3093 SUMA_RETURN(NOPE);
3094 }
3095 if ( Spec->MappingRef[i][0] ) {
3096
3097 if (LocalHead && !ob_warn) {
3098 fprintf(SUMA_STDERR, "Warning:\n"
3099 "The field MappingRef in the spec file \n"
3100 "is obsolete. Consider replacing: \n"
3101 " MappingRef = %s\n"
3102 " with\n"
3103 " LocalDomainParent = %s\n"
3104 "Similar warnings will be muted.\n",
3105 Spec->MappingRef[i], Spec->MappingRef[i]);
3106 }
3107 strcpy(Spec->LocalDomainParent[i], Spec->MappingRef[i]);
3108 strcpy(Spec->LocalCurvatureParent[i], Spec->MappingRef[i]);
3109 Spec->MappingRef[i][0] = '\0';
3110 ++ob_warn;
3111 }
3112 if ( strlen(Spec->LocalCurvatureParent[i]) ) {
3113 if ( ! strstr( Spec->LocalCurvatureParent[i],
3114 Spec->LocalDomainParent[i]) ) {
3115 SUMA_SL_Err("Fields LocalCurvatureParent and LocalDomainParent \n"
3116 "must be identical.\n");
3117 SUMA_RETURN(NOPE);
3118 }
3119 } else {
3120 sprintf( Spec->LocalCurvatureParent[i], "%s",
3121 Spec->LocalDomainParent[i]);
3122 }
3123
3124 if (strlen(Spec->LocalDomainParent[i]) &&
3125 SUMA_iswordsame(Spec->SurfaceFile[i],Spec->LocalDomainParent[i]) == 1){
3126 SUMA_LH("Make LDP be SAME");
3127 snprintf (Spec->LocalDomainParent[i],
3128 SUMA_MAX_FP_NAME_LENGTH * sizeof(char),
3129 "%s%s", Spec->SpecFilePath, "SAME");
3130 }
3131 }
3132
3133 SUMA_RETURN(YUP);
3134 }
3135
SUMA_ShowSpecStruct(SUMA_SurfSpecFile * Spec,FILE * Out,int detail)3136 SUMA_Boolean SUMA_ShowSpecStruct (SUMA_SurfSpecFile *Spec, FILE *Out, int detail)
3137 {
3138 static char FuncName[]={"SUMA_ShowSpecStruct"};
3139 FILE *Outp;
3140 char *s;
3141
3142 SUMA_ENTRY;
3143
3144 if (!Spec) {
3145 SUMA_SL_Err("NULL Spec");
3146 SUMA_RETURN(NOPE);
3147 }
3148
3149 if (Spec->N_Surfs == -1) {
3150 SUMA_S_Err("Struct fresh out of SUMA_AllocSpecFields");
3151 SUMA_RETURN(NOPE);
3152 }
3153
3154 if (!Out) Outp = stdout;
3155 else Outp = Out;
3156
3157 s = SUMA_SpecStructInfo (Spec, detail);
3158
3159 if (!s) {
3160 SUMA_SL_Err("Failed in SUMA_SpecStructInfo");
3161 SUMA_RETURN(NOPE);
3162 }
3163
3164 fprintf(Outp, "%s", s);
3165
3166 SUMA_free(s); s = NULL;
3167
3168 SUMA_RETURN(YUP);
3169 }
3170 /*!
3171 \brief show the contents of Spec structure
3172 ans = SUMA_ShowSpecStruct (Spec, Out, detail);
3173
3174 \param Spec (SUMA_SurfSpecFile *)
3175 \param Out (FILE *) Pointer to output file
3176 If NULL then output is to stdout
3177 \param detail (int) 1: only surface name or coord file
3178 name if surface file is split to coord.
3179 and topo. files
3180 2: surface name and BOTH coord and topo files
3181 whenever applicable
3182 3: The whole nine yards.
3183 \return ans (YUP = good, NOPE = bad)
3184 \sa SUMA_Read_SpecFile
3185 */
SUMA_SpecStructInfo(SUMA_SurfSpecFile * Spec,int detail)3186 char* SUMA_SpecStructInfo (SUMA_SurfSpecFile *Spec, int detail)
3187 {
3188 static char FuncName[]={"SUMA_ShowSpecStructInfo"};
3189 char name_coord[SUMA_MAX_LABEL_LENGTH];
3190 char name_topo[SUMA_MAX_LABEL_LENGTH], *s = NULL;
3191 SUMA_STRING *SS = NULL;
3192 char stmp[1000];
3193 int i;
3194 SUMA_Boolean ShowCoord, ShowTopo, ShowRest;
3195
3196 SUMA_ENTRY;
3197
3198 ShowCoord = ShowTopo = ShowRest = NOPE;
3199
3200 if (detail == 1) ShowCoord = YUP;
3201 else if (detail == 2) { ShowCoord = YUP; ShowTopo = YUP; }
3202 else if (detail == 3) { ShowCoord = YUP; ShowTopo = YUP; ShowRest = YUP; }
3203 else {
3204 SUMA_SL_Err("Bad value for detail, 0 < detail < 4");
3205 SUMA_RETURN(NULL);
3206 }
3207
3208 SS = SUMA_StringAppend (NULL, NULL);
3209 if (Spec->N_Surfs == -1)
3210 SS = SUMA_StringAppend_va (SS,"Spec fresh out of SUMA_AllocSpecFields");
3211
3212 if (Spec->SpecFilePath)
3213 SS = SUMA_StringAppend_va (SS,"SpecFilePath: %s\n", Spec->SpecFilePath);
3214 else SS = SUMA_StringAppend_va (SS,"SpecFilePath: NULL\n");
3215 if (Spec->SpecFileName)
3216 SS = SUMA_StringAppend_va (SS,"SpecFileName: %s\n", Spec->SpecFileName);
3217 else SS = SUMA_StringAppend_va (SS,"SpecFileName: NULL\n");
3218
3219 if (!Spec->N_Surfs) {
3220 SS = SUMA_StringAppend (SS,"No surfaces in Spec.\n");
3221 } else {
3222
3223 sprintf (stmp, "%d surfaces in Spec, %d defined states, %d groups\n",
3224 Spec->N_Surfs, Spec->N_States, Spec->N_Groups);
3225 SS = SUMA_StringAppend (SS, stmp);
3226
3227 for (i=0; i < Spec->N_Surfs; ++i) {
3228 name_coord[0] ='\0';
3229 name_topo[0] = '\0';
3230 if ( (SUMA_iswordin(Spec->SurfaceType[i], "SureFit") == 1) ||
3231 (SUMA_iswordin(Spec->SurfaceType[i], "1D") == 1) ) {
3232 sprintf(name_coord, "%s ", Spec->CoordFile[i]);
3233 sprintf(name_topo,"%s ", Spec->TopoFile[i]);
3234 } else if ( (SUMA_iswordin(Spec->SurfaceType[i], "FreeSurfer") == 1) ||
3235 (SUMA_iswordin(Spec->SurfaceType[i], "Ply") == 1) ||
3236 (SUMA_iswordin(Spec->SurfaceType[i], "GenericInventor") ==
3237 1) ||
3238 (SUMA_iswordin(Spec->SurfaceType[i], "OpenDX") == 1) ) {
3239 sprintf(name_coord, "%s ", Spec->SurfaceFile[i]);
3240 }
3241 SS = SUMA_StringAppend_va (SS, "%d) ", i);/* print the index */
3242
3243 if (ShowCoord) SS = SUMA_StringAppend (SS, name_coord);
3244 if (ShowTopo &&name_topo[0]) SS = SUMA_StringAppend (SS, name_topo);
3245 SS = SUMA_StringAppend (SS, "\n");
3246
3247 if (ShowRest) {
3248 SS = SUMA_StringAppend_va (SS, "\tMappingRef: %s\n",
3249 Spec->MappingRef[i]);
3250 /* Should become obsolete,
3251 ZSS Jan 02 03 */
3252 SS = SUMA_StringAppend_va (SS,
3253 "\tType: %s\n",
3254 Spec->SurfaceType[i]);
3255 SS = SUMA_StringAppend_va (SS,
3256 "\tFormat: %s\n",
3257 Spec->SurfaceFormat[i]);
3258 SS = SUMA_StringAppend_va (SS,
3259 "\tEmbedDim: %d\n",
3260 Spec->EmbedDim[i]);
3261 SS = SUMA_StringAppend_va (SS,
3262 "\tState: %s, Group %s\n",
3263 Spec->State[i], Spec->Group[i]);
3264
3265 if (strlen(Spec->SureFitVolParam[i])) {
3266 SS = SUMA_StringAppend_va (SS,
3267 "\tSureFitVolParam: %s\n",
3268 Spec->SureFitVolParam[i]);
3269 } else SS = SUMA_StringAppend_va (SS,
3270 "\tSureFitVolParam: (empty)\n");
3271
3272 if (strlen(Spec->VolParName[i])) {
3273 SS = SUMA_StringAppend_va (SS,
3274 "\tVolParName: %s\n",
3275 Spec->VolParName[i]);
3276 } else SS = SUMA_StringAppend_va (SS,
3277 "\tVolParName: (empty)\n");
3278
3279 if (Spec->IDcode[i]) {
3280 SS = SUMA_StringAppend_va (SS,
3281 "\tIDcode: %s\n",
3282 Spec->IDcode[i]);
3283 } else SS = SUMA_StringAppend_va (SS,
3284 "\tIDcode: (empty)\n");
3285
3286 if (strlen(Spec->AnatCorrect[i])) {
3287 SS = SUMA_StringAppend_va (SS,
3288 "\tAnatCorrect: %s\n",
3289 Spec->AnatCorrect[i]);
3290 } else SS = SUMA_StringAppend_va (SS,
3291 "\tAnatCorrect: (empty)\n");
3292
3293 if (strlen(Spec->Hemisphere[i])) {
3294 SS = SUMA_StringAppend_va (SS,
3295 "\tHemisphere: %s\n",
3296 Spec->Hemisphere[i]);
3297 } else SS = SUMA_StringAppend_va (SS,
3298 "\tHemisphere: (empty)\n");
3299
3300 if (strlen(Spec->DomainGrandParentID[i])) {
3301 SS = SUMA_StringAppend_va (SS,
3302 "\tDomainGrandParentID: %s\n",
3303 Spec->DomainGrandParentID[i]);
3304 } else SS = SUMA_StringAppend_va (SS,
3305 "\tDomainGrandParentID: (empty)\n");
3306
3307 if (strlen(Spec->OriginatorID[i])) {
3308 SS = SUMA_StringAppend_va (SS,
3309 "\tOriginatorID: %s\n",
3310 Spec->OriginatorID[i]);
3311 } else SS = SUMA_StringAppend_va (SS,
3312 "\tOriginatorID: (empty)\n");
3313
3314 if (strlen(Spec->LocalCurvatureParent[i])) {
3315 SS = SUMA_StringAppend_va (SS,
3316 "\tLocalCurvatureParent: %s\n",
3317 Spec->LocalCurvatureParent[i]);
3318 } else SS = SUMA_StringAppend_va (SS,
3319 "\tLocalCurvatureParent: (empty)\n");
3320
3321 if (strlen(Spec->LocalDomainParent[i])) {
3322 SS = SUMA_StringAppend_va (SS,
3323 "\tLocalDomainParent: %s\n",
3324 Spec->LocalDomainParent[i]);
3325 } else SS = SUMA_StringAppend_va (SS,
3326 "\tLocalDomainParent: (empty)\n");
3327
3328 if (strlen(Spec->LabelDset[i])) {
3329 SS = SUMA_StringAppend_va (SS,
3330 "\tLabelDset: %s\n",
3331 Spec->LabelDset[i]);
3332 } else SS = SUMA_StringAppend_va (SS,
3333 "\tLabelDset: (empty)\n");
3334
3335 if (strlen(Spec->NodeMarker[i])) {
3336 SS = SUMA_StringAppend_va (SS,
3337 "\tNodeMarker: %s\n",
3338 Spec->NodeMarker[i]);
3339 } else SS = SUMA_StringAppend_va (SS,
3340 "\tNodeMarker: (empty)\n");
3341 /*
3342 if (strlen(Spec->[i])) {
3343 SS = SUMA_StringAppend_va (SS,
3344 "\t: %s\n",
3345 Spec->[i]);
3346 } else SS = SUMA_StringAppend_va (SS, "\t: (empty)\n");
3347 */
3348 }
3349 }
3350 }
3351
3352 /* clean SS */
3353 SS = SUMA_StringAppend (SS, NULL);
3354 /* copy s pointer and free SS */
3355 s = SS->s;
3356 SUMA_free(SS);
3357
3358 SUMA_RETURN (s);
3359 }
3360
3361 /*!
3362 \brief loads a surface object specified in Spec[i]
3363
3364 - NOTABLE SO fields filled in this function are:
3365 SO->NodeList, SO->N_NodeList, SO->FaceSetList, SO->N_FaceSet
3366 SO->Group, SO->idcode_str,
3367 SO->State
3368 SO->EmbedDim
3369 SO->Side
3370 SO->OriginatorID
3371 SO->DomainGrandParentID
3372 SO->LocalCurvatureParent
3373 SO->LocalDomainParent
3374 SO->AnatCorrect
3375 SO->SpecFile
3376 \returns SO (SUMA_SurfaceObject *)
3377 */
SUMA_Load_Spec_Surf(SUMA_SurfSpecFile * Spec,int i,char * tmpVolParName,int debug)3378 SUMA_SurfaceObject * SUMA_Load_Spec_Surf(
3379 SUMA_SurfSpecFile *Spec,
3380 int i,
3381 char *tmpVolParName,
3382 int debug)
3383 { /* start SUMA_Load_Spec_Surf */
3384 static char FuncName[]={"SUMA_Load_Spec_Surf"};
3385 SUMA_SFname *SF_name;
3386 SUMA_SurfaceObject *SO=NULL;
3387 SUMA_Boolean brk, SurfIn=NOPE;
3388 SUMA_Boolean LocalHead = NOPE;
3389
3390 SUMA_ENTRY;
3391
3392 brk = NOPE;
3393
3394 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "SureFit") == 1) {
3395 /* load surefit surface */
3396 SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
3397 sprintf(SF_name->name_coord,"%s", Spec->CoordFile[i]);
3398 sprintf(SF_name->name_topo,"%s", Spec->TopoFile[i]);
3399 if (!strlen(Spec->SureFitVolParam[i])) { /* initialize to empty string */
3400 SF_name->name_param[0] = '\0';
3401 } else {
3402 sprintf(SF_name->name_param,"%s", Spec->SureFitVolParam[i]);
3403 }
3404
3405 /* Load The Surface */
3406 if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1) {
3407 SO = SUMA_Load_Surface_Object_eng ( (void *)SF_name, SUMA_SUREFIT,
3408 SUMA_ASCII, tmpVolParName, debug);
3409 } else {
3410 fprintf( SUMA_STDERR,
3411 "Error %s: Only ASCII surfaces can be read for now.\n",
3412 FuncName);
3413 SUMA_RETURN (NULL);
3414 }
3415 if (SO == NULL) {
3416 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3417 SUMA_RETURN(NULL);
3418 }
3419
3420 SUMA_free(SF_name);
3421
3422 SurfIn = YUP;
3423 brk = YUP;
3424 }/* load surefit surface */
3425
3426 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "1D") == 1) {
3427 /* load 1D surface */
3428 SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
3429 sprintf(SF_name->name_coord,"%s", Spec->CoordFile[i]); ;
3430 sprintf(SF_name->name_topo,"%s", Spec->TopoFile[i]);
3431 SF_name->name_param[0] = '\0';
3432
3433
3434 /* Load The Surface */
3435 if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1) {
3436 SO = SUMA_Load_Surface_Object_eng ((void *)SF_name, SUMA_VEC,
3437 SUMA_ASCII, tmpVolParName, debug);
3438 } else {
3439 fprintf( SUMA_STDERR,
3440 "Error %s: Only ASCII allowed for 1D files.\n", FuncName);
3441 SUMA_RETURN (NULL);
3442 }
3443 if (SO == NULL) {
3444 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3445 SUMA_RETURN(NULL);
3446 }
3447
3448 SUMA_free(SF_name);
3449
3450 SurfIn = YUP;
3451 brk = YUP;
3452 }/* load 1D surface */
3453
3454 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "FreeSurfer") == 1) {
3455 /* load FreeSurfer surface */
3456 if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1)
3457 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i],
3458 SUMA_FREE_SURFER, SUMA_ASCII,
3459 tmpVolParName, debug);
3460 else if (SUMA_iswordin(Spec->SurfaceFormat[i], "BINARY") == 1)
3461 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i],
3462 SUMA_FREE_SURFER, SUMA_BINARY_BE,
3463 tmpVolParName, debug);
3464 if (SO == NULL) {
3465 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3466 SUMA_RETURN(NULL);
3467 }
3468 SurfIn = YUP;
3469 brk = YUP;
3470 } /* load FreeSurfer surface */
3471
3472 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "Ply") == 1) {
3473 /* load Ply format surface */
3474 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i], SUMA_PLY,
3475 SUMA_FF_NOT_SPECIFIED, tmpVolParName, debug);
3476
3477 if (SO == NULL) {
3478 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3479 SUMA_RETURN(NULL);
3480 }
3481 SurfIn = YUP;
3482 brk = YUP;
3483 } /* load Ply format surface */
3484
3485 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "STL") == 1) {
3486 /* load STL format surface */
3487 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i], SUMA_STL, SUMA_FF_NOT_SPECIFIED, tmpVolParName,
3488 debug);
3489
3490 if (SO == NULL) {
3491 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3492 SUMA_RETURN(NULL);
3493 }
3494 SurfIn = YUP;
3495 brk = YUP;
3496 } /* load STL format surface */
3497
3498 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "MNI") == 1) {
3499 /* load MNI_OBJ format surface */
3500
3501 SO = SUMA_Load_Surface_Object_eng ((void *)Spec->SurfaceFile[i],
3502 SUMA_MNI_OBJ, SUMA_ASCII,
3503 tmpVolParName, debug);
3504
3505 if (SO == NULL) {
3506 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3507 SUMA_RETURN(NULL);
3508 }
3509 SurfIn = YUP;
3510 brk = YUP;
3511 } /* load MNI_OBJ format surface */
3512
3513 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "OpenDX") == 1) {
3514 SO = SUMA_Load_Surface_Object_eng ((void *)Spec->SurfaceFile[i],
3515 SUMA_OPENDX_MESH, SUMA_ASCII, tmpVolParName, debug);
3516
3517 if (SO == NULL) {
3518 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3519 SUMA_RETURN(NULL);
3520 }
3521 SurfIn = YUP;
3522 brk = YUP;
3523 } /* load OpenDX format surface */
3524
3525 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "OBJ") == 1) {
3526 SO = SUMA_Load_Surface_Object_eng ((void *)Spec->SurfaceFile[i],
3527 SUMA_OBJ_MESH, SUMA_ASCII, tmpVolParName, debug);
3528
3529 if (SO == NULL) {
3530 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3531 SUMA_RETURN(NULL);
3532 }
3533 SurfIn = YUP;
3534 brk = YUP;
3535 } /* load OBJ_MESH format surface */
3536
3537
3538 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "Predefined") == 1) {
3539
3540 SO = SUMA_Load_Surface_Object_eng ((void *)Spec->SurfaceFile[i],
3541 SUMA_PREDEFINED, SUMA_ASCII, tmpVolParName, debug);
3542 if (SO == NULL) {
3543 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3544 SUMA_RETURN(NULL);
3545 }
3546 SurfIn = YUP;
3547 brk = YUP;
3548 }
3549
3550 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "BrainVoyager") == 1) {
3551 /* load BrainVoyager format surface */
3552 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i],
3553 SUMA_BRAIN_VOYAGER,
3554 SUMA_FF_NOT_SPECIFIED, tmpVolParName,
3555 debug);
3556
3557 if (SO == NULL) {
3558 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3559 SUMA_RETURN(NULL);
3560 }
3561 SurfIn = YUP;
3562 brk = YUP;
3563 } /* load bv format surface */
3564
3565 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "BYU") == 1) {
3566 /* load BYU format surface */
3567 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i], SUMA_BYU,
3568 SUMA_FF_NOT_SPECIFIED, tmpVolParName,
3569 debug);
3570
3571 if (SO == NULL) {
3572 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3573 SUMA_RETURN(NULL);
3574 }
3575 SurfIn = YUP;
3576 brk = YUP;
3577 } /* load byu format surface */
3578
3579 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "GIFTI") == 1) {
3580 /* load GIFTI format surface */
3581 SO = SUMA_Load_Surface_Object_eng (
3582 (void *)Spec->SurfaceFile[i], SUMA_GIFTI,
3583 SUMA_FF_NOT_SPECIFIED, tmpVolParName, debug);
3584
3585 if (SO == NULL) {
3586 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3587 SUMA_RETURN(NULL);
3588 }
3589 SurfIn = YUP;
3590 brk = YUP;
3591 } /* load gifti format surface */
3592
3593 if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "GenericInventor") == 1) {
3594 /* load generic inventor format surface */
3595 if (tmpVolParName != NULL) {
3596 fprintf( SUMA_STDERR,
3597 "Error %s: Sorry, but Parent volumes "
3598 "are not supported for generic inventor surfaces.\n",
3599 FuncName);
3600 SUMA_RETURN (NULL);
3601 }
3602 if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1)
3603 SO = SUMA_Load_Surface_Object_eng ( (void *)Spec->SurfaceFile[i],
3604 SUMA_INVENTOR_GENERIC, SUMA_ASCII,
3605 NULL, debug);
3606 else {
3607 fprintf( SUMA_STDERR,
3608 "Error %s: Only ASCII surfaces can be read for now.\n",
3609 FuncName);
3610 SUMA_RETURN(NULL);
3611 }
3612 if (SO == NULL) {
3613 fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
3614 SUMA_RETURN(NULL);
3615 }
3616 SurfIn = YUP;
3617
3618 brk = YUP;
3619 }
3620
3621 if (!brk) {
3622 fprintf( SUMA_STDERR,
3623 "Error %s: Unknown SurfaceFormat %s.\n"
3624 "(Format syntax is case sensitive)\n",
3625 FuncName, Spec->SurfaceType[i]);
3626 SUMA_RETURN(NULL);
3627 }
3628
3629 if (!SurfIn) {
3630 fprintf(SUMA_STDERR,"Error %s: Failed to read input surface.\n", FuncName);
3631 SUMA_RETURN(NULL);
3632 }
3633
3634 /* assign its Group and State and Side*/
3635 SUMA_LHv("Assigning group %s , state %s, and EmbedDim %d\n",
3636 Spec->Group[i], Spec->State[i], Spec->EmbedDim[i]);
3637 SO->Group = (char *)SUMA_calloc(strlen(Spec->Group[i])+1, sizeof(char));
3638 SO->State = (char *)SUMA_calloc(strlen(Spec->State[i])+1, sizeof(char));
3639 if (Spec->SurfaceLabel[i][0] == '\0') {
3640 if (!(SO->Label = SUMA_SurfaceFileName (SO, NOPE))) {
3641 SO->Label = SUMA_copy_string("Who_Am_I");
3642 }
3643 } else {
3644 SO->Label = SUMA_copy_string(Spec->SurfaceLabel[i]);
3645 }
3646
3647 if (SO->isSphere == SUMA_GEOM_NOT_SET) {
3648 SUMA_SetSphereParams(SO, -0.1); /* sets the spheriosity parameters */
3649 }
3650
3651 if (!SO->Group || !SO->State || !SO->Label) {
3652 fprintf(SUMA_STDERR,"Error %s: Error allocating lameness.\n", FuncName);
3653 SUMA_RETURN (NULL);
3654 }
3655
3656 SO->Group = strcpy(SO->Group, Spec->Group[i]);
3657 SO->State = strcpy(SO->State, Spec->State[i]);
3658 SO->EmbedDim = Spec->EmbedDim[i];
3659 if (Spec->Hemisphere[i][0] == 'L') {
3660 SO->Side = SUMA_LEFT;
3661 } else if (Spec->Hemisphere[i][0] == 'R') {
3662 SO->Side = SUMA_RIGHT;
3663 } else if (Spec->Hemisphere[i][0] == 'B') {
3664 SO->Side = SUMA_LR;
3665 } else SO->Side = SUMA_GuessSide (SO);
3666
3667
3668 if (Spec->OriginatorID[i][0])
3669 SO->OriginatorID = SUMA_copy_string(Spec->OriginatorID[i]);
3670 if (Spec->DomainGrandParentID[i][0])
3671 SO->DomainGrandParentID = SUMA_copy_string(Spec->DomainGrandParentID[i]);
3672 if (Spec->LocalCurvatureParent[i][0])
3673 SO->LocalCurvatureParent = SUMA_copy_string(Spec->LocalCurvatureParent[i]);
3674 if (Spec->LocalDomainParent[i][0])
3675 SO->LocalDomainParent = SUMA_copy_string(Spec->LocalDomainParent[i]);
3676 if (Spec->AnatCorrect[i][0] == '\0')
3677 Spec->AnatCorrect[i][0] = SUMA_GuessAnatCorrect(SO);
3678 SO->AnatCorrect = NOPE;
3679 if (Spec->AnatCorrect[i][0] == 'Y') SO->AnatCorrect = YUP;
3680 else SO->AnatCorrect = NOPE;
3681
3682 if (Spec->SpecFilePath)
3683 SO->SpecFile.Path = SUMA_copy_string(Spec->SpecFilePath);
3684 if (Spec->SpecFileName)
3685 SO->SpecFile.FileName = SUMA_copy_string(Spec->SpecFileName);
3686
3687 SUMA_RETURN(SO);
3688
3689 } /* end SUMA_Load_Spec_Surf */
3690
SUMA_Load_Spec_Surf_with_Metrics(SUMA_SurfSpecFile * Spec,int i,char * tmpVolParName,int debug)3691 SUMA_SurfaceObject * SUMA_Load_Spec_Surf_with_Metrics(
3692 SUMA_SurfSpecFile *Spec,
3693 int i,
3694 char *tmpVolParName,
3695 int debug)
3696 {
3697 static char FuncName[]={"SUMA_Load_Spec_Surf_with_Metrics"};
3698 SUMA_SurfaceObject *SO=NULL;
3699
3700 SUMA_ENTRY;
3701
3702 if (!Spec) SUMA_RETURN(SO);
3703
3704 if (!(SO = SUMA_Load_Spec_Surf(Spec, i, tmpVolParName, debug))) {
3705 SUMA_S_Errv("Failed to find surface %s %s.\n",
3706 SPEC_NAME_DBG(Spec,i), SPEC_TOPO_DBG(Spec,i));
3707 SUMA_RETURN(SO);
3708 }
3709
3710 if (!SO->EL) SUMA_SurfaceMetrics_eng(SO, "EdgeList", NULL, debug,
3711 SUMAg_CF->DsetList);
3712 if (!SO->MF) SUMA_SurfaceMetrics_eng(SO, "MemberFace", NULL, debug,
3713 SUMAg_CF->DsetList);
3714 if (!SO->Label && !(SO->Label = SUMA_SurfaceFileName(SO, NOPE))) {
3715 SO->Label = SUMA_copy_string("A_Horse_With_No_Name");
3716 }
3717
3718 SUMA_RETURN(SO);
3719 }
3720
3721 /*!
3722 Take a mappable SO , loaded as it would be out of, say, SUMA_Load_Spec_Surf,
3723 find its metrics, initialize suma structures and add it to DOv
3724 */
SUMA_PrepAddmappableSO(SUMA_SurfaceObject * SO,SUMA_DO * dov,int * N_dov,int debug,DList * DsetList)3725 SUMA_Boolean SUMA_PrepAddmappableSO(SUMA_SurfaceObject *SO, SUMA_DO *dov,
3726 int *N_dov, int debug, DList *DsetList)
3727 { /* begin SUMA_PrepAddmappableSO */
3728 static char FuncName[]={"SUMA_PrepAddmappableSO"};
3729 SUMA_OVERLAYS *NewColPlane=NULL;
3730 SUMA_Boolean SurfIn = NOPE;
3731 char DoThis[100];
3732 SUMA_Boolean LocalHead = NOPE;
3733
3734 SUMA_ENTRY;
3735
3736 SurfIn = YUP;
3737
3738 /* set its MappingRef id to its own */
3739 SO->LocalDomainParentID = (char *)SUMA_calloc( strlen(SO->idcode_str)+1,
3740 sizeof(char));
3741 if (SO->LocalDomainParentID == NULL) {
3742 fprintf( SUMA_STDERR,
3743 "Error %s: Failed to allocate for SO->LocalDomainParentID. \n"
3744 "That is pretty bad.\n", FuncName);
3745 SUMA_RETURN (NOPE);
3746 }
3747 SO->LocalDomainParentID = strcpy(SO->LocalDomainParentID, SO->idcode_str);
3748
3749
3750 /* if the surface is loaded OK, and it has not been loaded
3751 previously, register it */
3752 if (SurfIn) {
3753 sprintf(DoThis,"Convexity");
3754 if (!SO->EL || !SO->FN) strcat(DoThis,", EdgeList");
3755 if (!SO->MF) strcat(DoThis,", MemberFace");
3756 if (!SUMA_SurfaceMetrics_eng (SO, DoThis, NULL, debug, DsetList)) {
3757 fprintf (SUMA_STDERR,
3758 "Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
3759 SUMA_RETURN (NOPE);
3760 }
3761
3762 #if SUMA_CHECK_WINDING
3763 /* if you have surfaces that are not consistent,
3764 you should fix them ahead of time
3765 because orientation affects calculations of normals,
3766 areas (signed), convexity
3767 etc.... */
3768 if (!SUMA_SurfaceMetrics_eng (SO, "CheckWind", NULL, debug, DsetList)) {
3769 fprintf (SUMA_STDERR,
3770 "Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
3771 SUMA_RETURN (NOPE);
3772 }
3773 #endif
3774
3775 /* Store it into dov, if not there already */
3776 if (SUMA_whichDO(SO->idcode_str, dov, *N_dov) < 0) {
3777 if (!SUMA_AddDO(dov, N_dov, (void *)SO, SO_type, SUMA_WORLD)) {
3778 fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
3779 SUMA_RETURN(NOPE);
3780 }
3781 }
3782
3783 /* create the surface controller */
3784 if (!SO->SurfCont) {
3785 SO->SurfCont = SUMA_CreateSurfContStruct(SO->idcode_str, SO_type);
3786 } else {
3787 SUMA_S_Note("Surface Controller Exists Already.");
3788 }
3789
3790 {
3791 SUMA_DSET *dset=NULL;/* create the color plane for Convexity*/
3792
3793 /* create an overlay plane */
3794 if (!(dset = (SUMA_DSET *)SUMA_GetCx(SO->idcode_str, DsetList, 1))) {
3795 SUMA_SL_Err("Failed to find dset!");
3796 SUMA_RETURN (NOPE);
3797 }
3798 NewColPlane = SUMA_CreateOverlayPointer ("Convexity", dset,
3799 SO->idcode_str, NULL);
3800 if (!NewColPlane) {
3801 fprintf (SUMA_STDERR,
3802 "Error %s: Failed in SUMA_CreateOverlayPointer.\n",
3803 FuncName);
3804 SUMA_RETURN (NOPE);
3805 }
3806 /* Add this plane to SO->Overlays */
3807 if (!SUMA_AddNewPlane ((SUMA_ALL_DO *)SO, NewColPlane, NULL, -1, 1)) {
3808 /* duplicate planes will be ignored! */
3809 SUMA_SL_Err("Failed in SUMA_AddNewPlane");
3810 SUMA_FreeOverlayPointer(NewColPlane);
3811 SUMA_RETURN (NOPE);
3812 }
3813 if (!SUMAg_CF->scm) {
3814 SUMAg_CF->scm = SUMA_Build_Color_maps();
3815 if (!SUMAg_CF->scm) {
3816 SUMA_SL_Err("Failed to build color maps.\n");
3817 SUMA_RETURN(NOPE);
3818 }
3819 }
3820
3821 if (!SUMA_SetConvexityPlaneDefaults(SO, DsetList)) {
3822 SUMA_SL_Err("Failed to set plane defaults."); SUMA_RETURN(NOPE);
3823 }
3824
3825 /* colorize the plane */
3826 SUMA_ColorizePlane(NewColPlane);
3827
3828 /* set current plane to it, if none are set */
3829 if (SO->SurfCont && !SO->SurfCont->curColPlane) {
3830 SO->SurfCont->curColPlane = NewColPlane;
3831 }
3832 }
3833
3834 /* Create a Mesh Axis for the surface */
3835 SO->MeshAxis = SUMA_Alloc_Axis ("Surface Mesh Axis", AO_type);
3836 if (SO->MeshAxis == NULL) {
3837 fprintf(SUMA_STDERR,"Error %s: Error Allocating axis\n", FuncName);
3838 SUMA_RETURN(NOPE);
3839 }
3840 /* Change the defaults of Mesh axis to fit standard */
3841 /* For the moment, use Box Axis */
3842 SO->MeshAxis->atype = SUMA_SCALE_BOX;
3843
3844 SUMA_MeshAxisStandard (SO->MeshAxis, (SUMA_ALL_DO *)SO);
3845 /*turn on the viewing for the axis */
3846
3847 SO->ShowMeshAxis = NOPE;
3848
3849
3850 }
3851
3852 SUMA_RETURN(YUP);
3853
3854 } /* end SUMA_PrepAddmappableSO */
3855
3856
SUMA_Load_SO_NodeMarker(SUMA_SurfaceObject * SO,char * NodeMarker)3857 SUMA_Boolean SUMA_Load_SO_NodeMarker(SUMA_SurfaceObject *SO,
3858 char *NodeMarker)
3859 {
3860 static char FuncName[]={"SUMA_Load_SO_NodeMarker"};
3861 SUMA_NIDO *nido=NULL;
3862 int i=0;
3863 SUMA_Boolean LocalHead = NOPE;
3864
3865 SUMA_ENTRY;
3866
3867 if (!SO || !NodeMarker) SUMA_RETURN(NOPE);
3868
3869 SUMA_LHv("Loading %s\n", NodeMarker);
3870 if (!(nido = SUMA_ReadNIDO (NodeMarker, SO->idcode_str))) {
3871 SUMA_S_Errv("Failed to load %s\n", NodeMarker);
3872 SUMA_RETURN(NOPE);
3873 }
3874 nido->do_type = NIDO_type;
3875
3876 if (SO->CommonNodeObject) {
3877 SUMA_Free_Displayable_Object_Vect(SO->CommonNodeObject,1);
3878 SO->CommonNodeObject = NULL;
3879 }
3880 SO->CommonNodeObject = (SUMA_DO *)SUMA_calloc(1,sizeof(SUMA_DO));
3881
3882 SO->CommonNodeObject->OP = (void *)nido;
3883 SO->CommonNodeObject->ObjectType = NIDO_type;
3884 SO->CommonNodeObject->CoordType = SUMA_WORLD;
3885 nido = NULL;
3886
3887 SUMA_LH( "Need to turn SO->CommonNodeObject to "
3888 "SO->NodeObjects, and SO->NodeNIDOObjects");
3889 #if 0
3890 /* this approach is less flexible, only one nel allowed in CommonNodeObject
3891 and it is not any faster than the second approach, wich allows for any NIDO
3892 to be propagated
3893 Just don't have both modes on, you'll be drawing similar objects twice */
3894 if (SO->NodeObjects) {
3895 SUMA_Free_Displayable_Object_Vect(SO->NodeObjects, 1);
3896 }
3897 SO->NodeObjects = SUMA_Multiply_NodeObjects( SO, SO->CommonNodeObject);
3898 #else
3899 if (SO->NodeNIDOObjects) {
3900 for (i=0; i<SO->N_Node; ++i)
3901 if (SO->NodeNIDOObjects[i]) SUMA_free_NIDO(SO->NodeNIDOObjects[i]);
3902 SUMA_free(SO->NodeNIDOObjects); SO->NodeNIDOObjects = NULL;
3903 }
3904 SO->NodeNIDOObjects =
3905 SUMA_Multiply_NodeNIDOObjects(SO, SO->CommonNodeObject, NULL, -1);
3906 #endif
3907
3908 SUMA_RETURN(YUP);
3909 }
3910
3911
3912 /*!
3913 Call the function engine, with debug turned on. 20 Oct 2003 [rickr]
3914 */
SUMA_LoadSpec(SUMA_SurfSpecFile * Spec,SUMA_DO * dov,int * N_dov,char * VolParName)3915 SUMA_Boolean SUMA_LoadSpec (SUMA_SurfSpecFile *Spec, SUMA_DO *dov,
3916 int *N_dov, char *VolParName)
3917 {/* SUMA_LoadSpec */
3918 static char FuncName[]={"SUMA_LoadSpec"};
3919
3920 SUMA_ENTRY;
3921
3922 SUMA_RETURN( SUMA_LoadSpec_eng(Spec, dov, N_dov, VolParName,
3923 1, SUMAg_CF->DsetList) );
3924
3925 }/* SUMA_LoadSpec */
3926
3927 /* - appended _eng to engine function name 20 Oct 2003 [rickr]
3928 * - added debug parameter
3929 * - only output non-error info when debug flag is set
3930 * - debug level 1, slight detail, level 2 more detail
3931 */
3932 /*!
3933 Loads the surfaces specified in Spec and stores them in DOv
3934 */
3935 static int LoadPacify = 0;
SetLoadPacify(int k)3936 void SetLoadPacify(int k) { LoadPacify = k; }
GetLoadPacify(void)3937 int GetLoadPacify(void) { return LoadPacify; }
3938
SUMA_LoadSpec_eng(SUMA_SurfSpecFile * Spec,SUMA_DO * dov,int * N_dov,char * VolParName,int debug,DList * DsetList)3939 SUMA_Boolean SUMA_LoadSpec_eng (
3940 SUMA_SurfSpecFile *Spec, SUMA_DO *dov, int *N_dov,
3941 char *VolParName, int debug, DList *DsetList)
3942 {/* SUMA_LoadSpec_eng */
3943 static char FuncName[]={"SUMA_LoadSpec_eng"};
3944 int i, k;
3945 char *tmpid, *tmpVolParName = NULL;
3946 SUMA_SurfaceObject *SO=NULL;
3947 SUMA_Axis *EyeAxis;
3948 SUMA_OVERLAYS *NewColPlane=NULL;
3949 SUMA_Boolean SurfIn = NOPE;
3950 SUMA_Boolean LocalHead = NOPE;
3951
3952 SUMA_ENTRY;
3953
3954 if (LocalHead) debug = 1;
3955
3956 if ( debug )
3957 SUMA_S_Notev("Expecting to read %d surfaces, %d DOs.\n",
3958 Spec->N_Surfs, Spec->N_DO);
3959 for (i=0; i<Spec->N_Surfs; ++i) { /* first loop across mappable surfaces */
3960 /*locate and load all Mappable surfaces */
3961 if (Spec->LocalDomainParent[i][0] == '\0') {
3962 /* assume surface is local domain parent, otherwise,
3963 surface controller would crash ZSS July 13 2010 */
3964 if (debug)
3965 SUMA_S_Warnv(
3966 "MappingRef field unavailable for %s in spec file, "
3967 "Assuming MappingRef = SAME\n"
3968 "You might have problems linking to volume.\n",
3969 SO->Label);
3970 sprintf(Spec->LocalDomainParent[i], "SAME");
3971 }
3972 if (SUMA_iswordin(Spec->LocalDomainParent[i],"SAME") == 1) {
3973 /* Mappable surfaces */
3974 if ( debug || LoadPacify) { /* turned this back on as a pacifier */
3975 fprintf (SUMA_STDERR,"\nvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
3976 fprintf (SUMA_STDERR,
3977 "Surface #%d/%d(Local Domain Parent), loading ...\n",
3978 i+1, Spec->N_Surfs );
3979 }
3980
3981 if (Spec->VolParName[i][0] != '\0') {
3982 SUMA_LH("Using Volume Parent Specified in Spec File.\n"
3983 "This overrides -sv option.");
3984 tmpVolParName = Spec->VolParName[i];
3985 }else {
3986 tmpVolParName = VolParName;
3987 }
3988
3989 SO = SUMA_Load_Spec_Surf(Spec, i, tmpVolParName, debug);
3990 if (SO) SurfIn = YUP;
3991 else {
3992 SurfIn = NOPE;
3993 SUMA_SL_Err("Failed to read surface.");
3994 SUMA_RETURN(NOPE);
3995 }
3996
3997 /* store the surface's idcode pointer for use in
3998 non mappable bloc below */
3999 Spec->IDcode[i] = SO->idcode_str;
4000
4001 /* check if surface read was unique
4002 it's inefficient to check after the surface is read,
4003 but idcode is generated in the read routine
4004 and users should not be making this mistake too often
4005 Search for similar comment elsewhere in the code once
4006 a better remedy is found*/
4007 if (SUMA_existSO (SO->idcode_str, dov, *N_dov)) {
4008 /* Check the filename match, to get around ID collision
4009 This modification is no guarantee that collisions
4010 won't occur but it is a start until I figure out
4011 the problem with hashcode */
4012 char *name=NULL, *mname=NULL;
4013 SUMA_SurfaceObject *SOm = NULL;
4014 SOm = SUMA_findSOp_inDOv(SO->idcode_str, dov, *N_dov);
4015 mname = SUMA_SurfaceFileName(SOm, 1);
4016 name = SUMA_SurfaceFileName(SO, 1);
4017 if (mname && name && strcmp(mname, name)) {
4018 char *stmp;
4019 /* give SO a new ID */
4020 stmp = SUMA_append_replace_string(name, SO->idcode_str,"_",0);
4021 SUMA_ifree(SO->idcode_str);
4022 SUMA_NEW_ID(SO->idcode_str, stmp);
4023 SUMA_ifree(stmp);
4024 }
4025 SUMA_ifree(name); SUMA_ifree(mname);
4026 }
4027 if (SUMA_existSO (SO->idcode_str, dov, *N_dov)) {
4028 SUMA_SurfaceObject *SOm = NULL;
4029 SOm = SUMA_findSOp_inDOv(SO->idcode_str, dov, *N_dov);
4030 SUMA_S_Errv("Surface %s %s (id %s) is in dov already as %s!\n",
4031 SPEC_NAME_DBG(Spec,i), SPEC_TOPO_DBG(Spec,i),
4032 SO->idcode_str, SOm->Label);
4033
4034 /* free SO */
4035 if (!SUMA_Free_Surface_Object (SO)) {
4036 fprintf(SUMA_STDERR,"Error %s: Error freeing SO.\n", FuncName);
4037 SUMA_RETURN (NOPE);
4038 }
4039 SO = NULL;
4040 SurfIn = NOPE;
4041 } else {
4042 if (!SUMA_PrepAddmappableSO(SO, dov, N_dov, debug, DsetList)) {
4043 SUMA_SL_Err("Failed in SUMA_PrepAddmappableSO.");
4044 SUMA_RETURN(NOPE);
4045 }
4046 }
4047 SurfIn = NOPE;
4048
4049 if (SO && Spec->LabelDset[i][0] != '\0') {
4050 SUMA_LHv("Will need to load label dset %s for %s\n",
4051 Spec->LabelDset[i], SO->Label);
4052 /* load it straight to SO */
4053 if (!(SUMA_LoadDsetOntoSO_eng(Spec->LabelDset[i], (void *)SO,
4054 -1, 0, 0, &NewColPlane))) {
4055 SUMA_S_Errv("Failed to read %s\n", Spec->LabelDset[i]);
4056 SUMA_RETURN(NOPE);
4057 }
4058 /* do some deeds on this overlay */
4059 NewColPlane->GlobalOpacity =
4060 SUMA_floatEnv("SUMA_LabelDsetOpacity", 0.2);
4061 if ( SUMA_isEnv("SUMA_ShowLabelDsetAtStartup","col") ||
4062 SUMA_isEnv("SUMA_ShowLabelDsetAtStartup","yes"))
4063 NewColPlane->ShowMode = SW_SurfCont_DsetViewCol;
4064 else if ( SUMA_isEnv("SUMA_ShowLabelDsetAtStartup","con") ) {
4065 NewColPlane->ShowMode = SW_SurfCont_DsetViewCon;
4066 }else if ( SUMA_isEnv("SUMA_ShowLabelDsetAtStartup","c&c") ) {
4067 NewColPlane->ShowMode = SW_SurfCont_DsetViewCaC;
4068 }else if ( SUMA_isEnv("SUMA_ShowLabelDsetAtStartup","xxx") ||
4069 SUMA_isEnv("SUMA_ShowLabelDsetAtStartup","no")) {
4070 NewColPlane->ShowMode = SW_SurfCont_DsetViewXXX;
4071 }else{ /* show as contours only */
4072 NewColPlane->ShowMode = SW_SurfCont_DsetViewCon;
4073 }
4074 /* create contours for this monster */
4075 SUMA_ContourateDsetOverlay(NewColPlane, NULL);
4076
4077 /* move that plane down the stack, nice to have convexity stay
4078 on top */
4079 SUMA_MovePlaneDown((SUMA_ALL_DO *)SO, NewColPlane->Name);
4080
4081 NewColPlane=NULL; /* don't let anyone here use it */
4082 }
4083 if (SO && Spec->NodeMarker[i][0] != '\0') {
4084 SUMA_LHv("Will load NodeMarker %s for %s\n",
4085 Spec->NodeMarker[i], SO->Label);
4086 if (!(SUMA_Load_SO_NodeMarker(SO, Spec->NodeMarker[i]))) {
4087 SUMA_S_Errv("Failed to loa NodeMarker %s onto %s\n"
4088 "Plodding on nonetheless.\n",
4089 Spec->NodeMarker[i], SO->Label);
4090 }
4091 SUMA_LHv("NodeMarker %s loaded\n", Spec->NodeMarker[i]);
4092 }
4093 /* Any dsets identically named? If so, load them */
4094 if (SUMA_isEnv("SUMA_AutoLoad_Matching_Dset","YES")){
4095 SUMA_AutoLoad_SO_Dsets(SO);
4096 }
4097 }/* Mappable surfaces */
4098 }/* first loop across mappable surfaces */
4099
4100 for (i=0; i<Spec->N_Surfs; ++i) { /* Now locate and load all
4101 NON Mappable surfaces */
4102
4103 if (Spec->VolParName[i][0] != '\0') {
4104 if (VolParName) {
4105 SUMA_LH("Using Volume Parent Specified in Spec File.\n"
4106 "This overrides -sv option.");
4107 }
4108 tmpVolParName = Spec->VolParName[i];
4109 }else {
4110 tmpVolParName = VolParName;
4111 }
4112
4113 if (SUMA_iswordin(Spec->LocalDomainParent[i],"SAME") != 1) {
4114 /* Non Mappable surfaces */
4115 if ( debug || LoadPacify) { \
4116 fprintf (SUMA_STDERR,"\nvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
4117 fprintf (SUMA_STDERR,
4118 "Surface #%d/%d (mappable via Local Domain Parent), "
4119 "loading ...\n",i+1, Spec->N_Surfs);
4120 }
4121
4122 SO = SUMA_Load_Spec_Surf(Spec, i, tmpVolParName, debug);
4123 if (SO) SurfIn = YUP;
4124 else {
4125 SurfIn = NOPE;
4126 SUMA_SL_Err("Failed to read surface.");
4127 SUMA_RETURN(NOPE);
4128 }
4129
4130
4131 /* check if surface read was unique
4132 it's inefficient to check after the surface is read,
4133 but idcode is generated in the read routine
4134 and users should not be making this mistake too often */
4135 if (SUMA_existSO (SO->idcode_str, dov, *N_dov)) {
4136 fprintf( SUMA_STDERR,
4137 "Error %s: Surface %d is specifed more than once.\n"
4138 "Multiple copies ignored.\n", FuncName, i);
4139 /* free SO */
4140 if (!SUMA_Free_Surface_Object (SO)) {
4141 fprintf( SUMA_STDERR,
4142 "Error %s: Error freeing SO.\n", FuncName);
4143 SUMA_RETURN (NOPE);
4144 }
4145 SurfIn = NOPE;
4146 }
4147
4148 /* if the surface is loaded OK,
4149 and it has not been loaded previously, register it */
4150 if (SurfIn) {
4151 Spec->IDcode[i] = SO->idcode_str;
4152 /* add its ID to its Spec entry */
4153 /* Create a Mesh Axis for the surface */
4154 SO->MeshAxis = SUMA_Alloc_Axis ("Surface Mesh Axis", AO_type);
4155 if (SO->MeshAxis == NULL) {
4156 fprintf( SUMA_STDERR,
4157 "Error %s: Error Allocating axis\n", FuncName);
4158 SUMA_RETURN(NOPE);
4159 }
4160 /* Change the defaults of Mesh axis to fit standard */
4161 SUMA_MeshAxisStandard (SO->MeshAxis, (SUMA_ALL_DO *)SO);
4162 /*turn off the viewing for the axis */
4163 SO->ShowMeshAxis = NOPE;
4164
4165 /* Store it into dov */
4166 if (!SUMA_AddDO(dov, N_dov, (void *)SO, SO_type, SUMA_WORLD)) {
4167 fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
4168 SUMA_RETURN(NOPE);
4169 }
4170
4171 /* set its MappingRef id to NULL if none is specified */
4172 if (Spec->LocalDomainParent[i][0] == '\0') {
4173 /* This should not happen after July 13 2010 fix above */
4174 SO->LocalDomainParentID = NULL; /* no known MapRef_idcode */
4175 SUMA_S_Warnv(
4176 "MappingRef field unavailable for %s in spec file ",
4177 SO->Label);
4178 } else {
4179 /* make sure that specified Mapping ref had been loaded */
4180 int j = 0, ifound = -1;
4181 while (j < Spec->N_Surfs) {
4182 if (LocalHead) {
4183 fprintf( SUMA_STDERR,
4184 "%s-voila%d/%d:\n%s\n%s\n%s\n%s\n",
4185 FuncName, j, Spec->N_Surfs,
4186 Spec->LocalDomainParent[i], Spec->CoordFile[j],
4187 Spec->TopoFile[j], Spec->SurfaceFile[j]);
4188 }
4189 if (strcmp( Spec->LocalDomainParent[i],
4190 Spec->CoordFile[j]) == 0 ||
4191 strcmp( Spec->LocalDomainParent[i],
4192 Spec->TopoFile[j]) == 0 ||
4193 strcmp( Spec->LocalDomainParent[i],
4194 Spec->SurfaceFile[j]) == 0) {
4195 /* found a match */
4196 ifound = j;
4197 j = Spec->N_Surfs + 1;
4198 }
4199 ++j;
4200 }
4201 if (ifound >= 0) { /* found */
4202 if (LocalHead)
4203 fprintf (SUMA_STDERR,
4204 "ifound = %d, i = %d\n"
4205 "Spec->LocalDomainParent[i]:->%s<-\n",
4206 ifound, i, Spec->LocalDomainParent[i]);
4207 if (!SUMA_existSO (Spec->IDcode[ifound], dov, *N_dov)) {
4208 fprintf( SUMA_STDERR,
4209 "MappingRef unavailable, "
4210 "that should not happen here.\n");
4211 SO->LocalDomainParentID = NULL;
4212 /* showme the contents */
4213 if (!SUMA_ShowSpecStruct (Spec, NULL, 3)) {
4214 SUMA_SL_Err("Failed in SUMA_ShowSpecStruct\n");
4215 exit(1);
4216 }
4217 } else {
4218 /*fprintf(SUMA_STDERR,
4219 "MappingRef found in mappable surfaces\n");*/
4220 SO->LocalDomainParentID =
4221 (char *)SUMA_calloc( strlen(Spec->IDcode[ifound])+1,
4222 sizeof(char));
4223 if (SO->LocalDomainParentID == NULL) {
4224 fprintf(SUMA_STDERR,
4225 "Error %s: Failed to allocate for "
4226 "SO->LocalDomainParentID. \n"
4227 "That is pretty bad.\n", FuncName);
4228 SUMA_RETURN (NOPE);
4229 }
4230 SO->LocalDomainParentID =
4231 strcpy(SO->LocalDomainParentID, Spec->IDcode[ifound]);
4232 }
4233 } else {
4234 if (debug)
4235 SUMA_S_Warnv(
4236 "MappingRef field unavailable for %s in spec file, "
4237 "You might have problems linking to volume.\n",
4238 SO->Label);
4239 SO->LocalDomainParentID = NULL;
4240 }
4241 }
4242
4243 /* create the colorlist vector and calculate the surface metrics
4244 with the possibility of inheriting from the mapping reference */
4245 {
4246 SUMA_SurfaceObject *SOinh = NULL;
4247 int ifound = -1;
4248
4249 if (SO->LocalDomainParentID) {
4250 ifound = SUMA_findSO_inDOv ( SO->LocalDomainParentID,
4251 dov, *N_dov);
4252 if (ifound < 0) {
4253 SOinh = NULL;
4254 }else {
4255 SOinh = (SUMA_SurfaceObject *)(dov[ifound].OP);
4256 }
4257 } else SOinh = NULL;
4258
4259 /* deal with surface controller */
4260 if (SOinh) {
4261 #if SUMA_SEPARATE_SURF_CONTROLLERS
4262 /* leave controllers separate */
4263 if (!SO->SurfCont) {
4264 SO->SurfCont =
4265 SUMA_CreateSurfContStruct(SO->idcode_str, SO_type);
4266 } else {
4267 SUMA_S_Note("Surface Controller Exists Already (b)\n");
4268 }
4269 #else
4270 /* create a link to the surface controller pointer */
4271 if (!SO->SurfCont) {
4272 SO->SurfCont = (SUMA_X_SurfCont*)
4273 SUMA_LinkToPointer((void *)SOinh->SurfCont);
4274 } else {
4275 SUMA_S_Note("Surface Controller Exists Already (c)\n");
4276 }
4277 #endif
4278 } else {
4279 /* brand new one */
4280 if (!SO->SurfCont) {
4281 SO->SurfCont = SUMA_CreateSurfContStruct(SO->idcode_str,
4282 SO_type);
4283 } else {
4284 SUMA_S_Note("Surface Controller Exists Already (d)\n");
4285 }
4286 }
4287
4288
4289 if (!SUMA_SurfaceMetrics_eng (SO, "EdgeList, MemberFace",
4290 SOinh, debug, DsetList)) {
4291 fprintf (SUMA_STDERR,
4292 "Error %s: Failed in SUMA_SurfaceMetrics.\n",
4293 FuncName);
4294 SUMA_RETURN (NOPE);
4295 }
4296 }
4297
4298 SurfIn = NOPE;
4299 }
4300 if (Spec->LabelDset[i][0] != '\0') { /* I do not think this should be */
4301 SUMA_S_Notev("Label dsets should only be attached to \n"
4302 "surfaces with LocalDomainParent = SAME).\n"
4303 "LabelDset %s is ignored.\n",
4304 Spec->LabelDset[i]);
4305 }
4306 if (SO && Spec->NodeMarker[i][0] != '\0') {
4307 SUMA_S_Notev("Will need to load NodeMarker %s for non mappable %s\n",
4308 Spec->NodeMarker[i], SO->Label);
4309 }
4310 if (SUMA_isEnv("SUMA_AutoLoad_Matching_Dset","YES"))
4311 SUMA_AutoLoad_SO_Dsets(SO);
4312
4313 }/* Non Mappable surfaces */
4314
4315 }/*locate and load all NON Mappable surfaces */
4316
4317 SUMA_LHv("Have %d DOs to load\n", Spec->N_DO);
4318 for (i=0; i<Spec->N_DO; ++i) {
4319 switch ((SUMA_DO_Types)Spec->DO_type[i]) {
4320 case TRACT_type: {
4321 SUMA_LoadSegDO (Spec->DO_name[i], NULL );
4322 break; }
4323 case MASK_type: {
4324 SUMA_LoadMaskDO (Spec->DO_name[i], NULL );
4325 break; }
4326 case VO_type: {
4327 SUMA_LoadVolDO (Spec->DO_name[i], SUMA_WORLD, NULL,1);
4328 break; }
4329 case GDSET_type:
4330 SUMA_LHv("Loading graph dset %s\n",Spec->DO_name[i]);
4331 /* Expecting it to be a graph dset */
4332 if (!(SUMA_LoadDsetOntoSO_eng(Spec->DO_name[i],
4333 NULL, 1, 1, 1, NULL))) {
4334 SUMA_S_Errv("Failed to load %s\n", Spec->DO_name[i]);
4335 }
4336 break;
4337 case CDOM_type:
4338 SUMA_LoadCIFTIDO (Spec->DO_name[i],
4339 SUMA_WORLD, NULL, 1, 1, 1, 1, NULL);
4340 break;
4341 default:
4342 SUMA_S_Errv("Bad or unexpected type %s for %s\n",
4343 SUMA_ObjectTypeCode2ObjectTypeName(Spec->DO_type[i]),
4344 Spec->DO_name[i]);
4345 break;
4346 }
4347 }
4348
4349 SUMA_RETURN (YUP);
4350 }/* SUMA_LoadSpec_eng */
4351
4352
4353 /*!
4354 SUMA_SurfaceMetrics - call the engine with debug set 20 Oct 2003 [rickr]
4355 */
SUMA_SurfaceMetrics(SUMA_SurfaceObject * SO,const char * Metrics,SUMA_SurfaceObject * SOinh)4356 SUMA_Boolean SUMA_SurfaceMetrics(SUMA_SurfaceObject *SO,
4357 const char *Metrics,
4358 SUMA_SurfaceObject *SOinh)
4359 {
4360 static char FuncName[]={"SUMA_SurfaceMetrics"};
4361
4362 SUMA_ENTRY;
4363
4364 SUMA_RETURN(SUMA_SurfaceMetrics_eng(SO, Metrics, SOinh, 1,
4365 SUMAg_CF->DsetList));
4366 }
4367
4368
4369 /* - appended _eng to engine function name 20 Oct 2003 [rickr]
4370 * - added debug parameter
4371 * - only output non-error info when debug flag is set
4372 */
4373 /*!
4374 calculate surface properties
4375
4376 ans = SUMA_SurfaceMetrics_eng (SO, Metrics, SOinh, debug, DList *DsetList)
4377 \param SO (SUMA_SurfaceObject *)
4378 \param Metrics (const char *) list of parameters to compute. Supported parameters are (case sensitive):
4379 "Convexity", "PolyArea", "Curvature", "EdgeList", "MemberFace", "CheckWind"
4380 You can specify more than one parameter "Convexity, PolyArea"
4381 if the field of a certain parameter is not NULL then it is assumed that
4382 this parameter was computed at an earlier time and will not be recalculated.
4383 Some parameters require the computation of others and that's done automatically.
4384 \param SOinh (SUMA_SurfaceObject *) Some of the metrics can be inherited from SOinh (done through inodes)
4385 if things make sense. SOinh is typically the Mapping Reference SO. Pass NULL not to use this feature.
4386 Currently, only EL and FN can use this feature if the number of nodes, facesets match and SOinh is the
4387 mapping reference of SO
4388 \param debug (int) flag specifying whether to output non-error info
4389 \param DsetList (DList *) pointer to list where computed elements are to be stored
4390 as datasets. For the moment, this pointer can be NULL and
4391 if that is the case then nothing will get stored as a dataset.
4392 \return ans (SUMA_Boolean) NOPE = failure
4393
4394 Convexity : Fills Cx field in SO, An inode is also created
4395
4396 EdgeList also runs SUMA_Build_FirstNeighb
4397
4398 Curvature requires also PolyArea, FaceNeighb and EdgeList
4399 CheckWind requires EdgeList
4400
4401
4402 */
SUMA_SurfaceMetrics_eng(SUMA_SurfaceObject * SO,const char * Metrics,SUMA_SurfaceObject * SOinh,int debug,DList * DsetList)4403 SUMA_Boolean SUMA_SurfaceMetrics_eng (
4404 SUMA_SurfaceObject *SO,
4405 const char *Metrics,
4406 SUMA_SurfaceObject *SOinh,
4407 int debug,
4408 DList *DsetList)
4409 {
4410 static char FuncName[]={"SUMA_SurfaceMetrics_eng"};
4411 float *Cx=NULL, *SOCx = NULL;
4412 SUMA_Boolean DoConv, DoArea, DoCurv, DoEL, DoMF, DoWind, DoDW,
4413 LocalHead = NOPE;
4414 int i = 0;
4415
4416 SUMA_ENTRY;
4417
4418 if (debug > 1)
4419 fprintf (SUMA_STDERR,
4420 "%s: Calculating surface metrics, please be patient...\n",
4421 FuncName);
4422
4423 if (!DsetList) {
4424 SUMA_SL_Err("DsetList now is a must.");
4425 SUMA_RETURN(NOPE);
4426 }
4427 DoConv = DoArea = DoCurv = DoEL = DoMF = DoWind = NOPE;
4428 DoDW = YUP; /* No need to skimp on this one, costs nothing */
4429
4430 if (SUMA_iswordin (Metrics, "Convexity")) DoConv = YUP;
4431 if (SUMA_iswordin (Metrics, "PolyArea")) DoArea = YUP;
4432 if (SUMA_iswordin (Metrics, "Curvature")) DoCurv = YUP;
4433 if (SUMA_iswordin (Metrics, "EdgeList")) DoEL = YUP;
4434 if (SUMA_iswordin (Metrics, "MemberFace")) DoMF = YUP;
4435 if (SUMA_iswordin (Metrics, "CheckWind")) DoWind = YUP;
4436
4437 /* check for input inconsistencies and warn */
4438 if (!DoConv && !DoArea && !DoCurv && !DoEL && !DoMF && !DoWind && !DoDW) {
4439 if (debug) fprintf ( SUMA_STDERR,
4440 "Warning %s: Nothing to do.\n", FuncName);
4441 SUMA_RETURN (YUP);
4442 }
4443
4444 if (DoConv && (SOCx = (float *)SUMA_GetCx (SO->idcode_str, DsetList, 0))) {
4445 if (debug) fprintf ( SUMA_STDERR,
4446 "Warning %s: SOCx != NULL \n"
4447 "and thus appears to have been precomputed.\n",
4448 FuncName);
4449 DoConv = NOPE;
4450 }
4451
4452 if (DoArea && SO->PolyArea != NULL) {
4453 if (debug) fprintf ( SUMA_STDERR,
4454 "Warning %s: SO->PolyArea != NULL and "
4455 "thus appears to have been precomputed.\n",
4456 FuncName);
4457 DoArea = NOPE;
4458 }
4459
4460 if (DoCurv && SO->SC != NULL) {
4461 if (debug) fprintf ( SUMA_STDERR,
4462 "Warning %s: SO->SC != NULL and thus "
4463 "appears to have been precomputed.\n",
4464 FuncName);
4465 DoCurv = NOPE;
4466 }
4467
4468 if (DoMF && SO->MF != NULL) {
4469 if (debug) fprintf ( SUMA_STDERR,
4470 "Warning %s: SO->MF != NULL and thus "
4471 "appears to have been precomputed.\n",
4472 FuncName);
4473 DoMF = NOPE;
4474 }
4475
4476 if (DoEL && (SO->EL != NULL || SO->FN != NULL)) {
4477 if (debug) fprintf ( SUMA_STDERR,
4478 "Warning %s: SO->EL != NULL || SO->FN != NULL "
4479 "and thus appears to have been precomputed.\n",
4480 FuncName);
4481 DoEL = NOPE;
4482 }
4483
4484 if (DoEL && SOinh) {
4485 if (strcmp(SO->LocalDomainParentID, SOinh->idcode_str)) {
4486 SUMA_SL_Warn( "Cannot inherit Edge List\n"
4487 "and First Neightbor.\n"
4488 "Cause: idcode mismatch.\n"
4489 "Independent lists will\n"
4490 "be created.\n" );
4491 SOinh = NULL;
4492 } else if (SO->N_Node != SOinh->N_Node ||
4493 SO->N_FaceSet != SOinh->N_FaceSet) {
4494 SUMA_SL_Note( "(IGNORE for surface with cuts)\n"
4495 "Cannot inherit Edge List\n"
4496 "and First Neightbor.\n"
4497 "Cause: Node number mismatch.\n"
4498 "Independent lists will\n"
4499 "be created.\n");
4500 SOinh = NULL;
4501 }
4502 }
4503
4504 if (DoMF && SOinh) {
4505 if (strcmp(SO->LocalDomainParentID, SOinh->idcode_str)) {
4506 SUMA_SL_Warn( "Cannot inherit MemberFaceSet\n"
4507 "Cause: idcode mismatch.\n"
4508 "Independent lists will\n"
4509 "be created.\n" );
4510 SOinh = NULL;
4511 } else if ( SO->N_Node != SOinh->N_Node ||
4512 SO->N_FaceSet != SOinh->N_FaceSet) {
4513 SUMA_SL_Warn( "(IGNORE for surface patches)\n"
4514 "Cannot inherit MemberFaceSet\n"
4515 "Cause: Node number mismatch.\n"
4516 "Independent lists will\n"
4517 "be created.\n");
4518 SOinh = NULL;
4519 }
4520 }
4521
4522 /* prerequisits */
4523 if (DoCurv) {
4524 DoArea = YUP;
4525 DoEL = YUP;
4526 }
4527
4528 if (DoWind) {
4529 DoEL = YUP;
4530 }
4531
4532 if (DoConv && (!SO->EL || !SO->FN)) {
4533 DoEL = YUP;
4534 }
4535
4536 /* the computations */
4537 if (DoArea) {
4538 /* create the triangle Area */
4539 if (SO->NodeDim == 3) {
4540 if (debug)
4541 fprintf( SUMA_STDOUT,
4542 "%s: Calculating triangle areas ...\n", FuncName);
4543 fflush(SUMA_STDOUT);
4544 SO->PolyArea = SUMA_TriSurf3v ( SO->NodeList,
4545 SO->FaceSetList, SO->N_FaceSet);
4546 } else {
4547 if (debug)
4548 fprintf( SUMA_STDOUT,
4549 "%s: Calculating polygon areas ...\n", FuncName);
4550 fflush(SUMA_STDOUT);
4551 SO->PolyArea = SUMA_PolySurf3 ( SO->NodeList, SO->N_Node,
4552 SO->FaceSetList, SO->N_FaceSet,
4553 SO->NodeDim, SO->FaceNormList, NOPE);
4554 #if 0
4555 /* a test of the functions for calculating areas */
4556 {
4557 int ji, in0, in1, in2;
4558 float *n0, *n1, *n2, A;
4559 for (ji=0; ji<SO->N_FaceSet; ++ji) {
4560 in0 = SO->FaceSetList[3*ji];
4561 in1 = SO->FaceSetList[3*ji+1];
4562 in2 = SO->FaceSetList[3*ji+2];
4563 n0 = &(SO->NodeList[3*in0]);
4564 n1 = &(SO->NodeList[3*in1]);
4565 n2 = &(SO->NodeList[3*in2]);
4566 A = SUMA_TriSurf3 (n0, n1, n2);
4567 if (abs(A - SO->PolyArea[ji]) > 0.00001) {
4568 fprintf (SUMA_STDERR,
4569 "Error %s: Failed comparing SUMA_TriSurf3 to SUMA_PolySurf3. A = %f vs %f.\n"
4570 "Tri = [ %f, %f, %f; %f, %f, %f; %f, %f, %f]\n",
4571 FuncName, A, SO->PolyArea[ji],
4572 n0[0], n0[1], n0[2],
4573 n1[0], n1[1], n1[2],
4574 n2[0], n2[1], n2[2]);
4575 }else fprintf (SUMA_STDERR, "-");
4576
4577 SUMA_TRI_AREA (n0, n1, n2, A);
4578 if (abs(A - SO->PolyArea[ji]) > 0.00001) {
4579 fprintf (SUMA_STDERR,
4580 "Error %s: Failed comparing SUMA_TRI_AREA to SUMA_PolySurf3. "
4581 "%f vs %f Exiting.\n",
4582 FuncName, A, SO->PolyArea[ji]);
4583 }else fprintf (SUMA_STDERR, ".");
4584 }
4585 }
4586 #endif
4587
4588 }
4589 if (SO->PolyArea == NULL) {
4590 fprintf(SUMA_STDERR,
4591 "Error %s: Error in SUMA_PolySurf3 or SUMA_TriSurf3v\n",
4592 FuncName);
4593 }
4594 }
4595
4596 if (DoEL) {
4597 if (!SOinh) {
4598 /* create the edge list, it's nice and dandy */
4599 if (LocalHead)
4600 fprintf(SUMA_STDOUT, "%s: Making Edge list ....\n", FuncName);
4601 if (SO->EL) {
4602 fprintf (SUMA_STDERR,
4603 "Warning %s:"
4604 " SO->FN appears to have been computed before. \n",
4605 FuncName);
4606 } else {
4607 SO->EL = SUMA_Make_Edge_List_eng (SO->FaceSetList, SO->N_FaceSet,
4608 SO->N_Node, SO->NodeList, debug,
4609 SO->idcode_str);
4610 if (SO->EL == NULL) {
4611 fprintf( SUMA_STDERR,
4612 "Error %s: Failed in SUMA_Make_Edge_List.\n"
4613 " Neighbor list will not be created\n", FuncName);
4614 } else {
4615 if (LocalHead)
4616 fprintf( SUMA_STDOUT,
4617 "%s: Making Node Neighbor list ....\n", FuncName);
4618 /* create the node neighbor list */
4619 if (SO->FN) {
4620 fprintf (SUMA_STDERR,
4621 "Warning %s:"
4622 " SO->FN appears to have been computed before. \n",
4623 FuncName);
4624 } else {
4625 SO->FN = SUMA_Build_FirstNeighb (SO->EL, SO->N_Node,
4626 SO->idcode_str, debug);
4627 if (SO->FN == NULL) {
4628 fprintf( SUMA_STDERR,
4629 "Error %s: Failed in SUMA_Build_FirstNeighb.\n",
4630 FuncName);
4631 }
4632 }
4633 }
4634 }
4635 } else {
4636 if (LocalHead)
4637 fprintf( SUMA_STDOUT,
4638 "%s: Linking Edge List and First Neighbor Lits ...\n",
4639 FuncName);
4640 SO->FN = (SUMA_NODE_FIRST_NEIGHB*)SUMA_LinkToPointer((void *)SOinh->FN);
4641 SO->EL = (SUMA_EDGE_LIST*)SUMA_LinkToPointer((void *)SOinh->EL);
4642 }
4643 }
4644
4645 if (DoConv) {
4646 /* calculate convexity */
4647 if (LocalHead)
4648 fprintf(SUMA_STDOUT, "%s: Calculating convexity ...\n", FuncName);
4649 Cx = SUMA_Convexity(SO->NodeList, SO->N_Node, SO->NodeNormList,
4650 SO->FN, NULL);
4651 if (Cx == NULL) {
4652 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Convexity\n", FuncName);
4653 }
4654
4655 /* flip sign of convexity if it's a SureFit Surface */
4656 if ( (SO->normdir == 0 && (SO->FileType == SUMA_SUREFIT)) /* guess */
4657 || SO->normdir == -1 /* You know they'z got to be flipped */
4658 ) {
4659 for (i=0; i < SO->N_Node; ++i) {
4660 Cx[i] = -Cx[i];
4661 }
4662 }
4663
4664 #if 0
4665 {
4666 /* smooth the estimate twice*/
4667 float *attr_sm;
4668 attr_sm = SUMA_SmoothAttr_Neighb ( Cx, SO->N_Node, NULL,
4669 SO->FN, 1, NULL);
4670 if (attr_sm == NULL) {
4671 fprintf( stderr,
4672 "Error %s: Failed in SUMA_SmoothAttr_Neighb\n",
4673 FuncName);
4674 } else {
4675 Cx = SUMA_SmoothAttr_Neighb ( attr_sm, SO->N_Node, Cx,
4676 SO->FN, 1, NULL);
4677 if (attr_sm) SUMA_free(attr_sm);
4678 }
4679 }
4680 #else
4681 /* smooth the estimate as much as specified*/
4682 {
4683 char *eee = getenv("SUMA_NumConvSmooth");
4684 if (eee) {
4685 int N_smooth = (int)strtod(eee, NULL);
4686 if (N_smooth > 1) {
4687 Cx = SUMA_SmoothAttr_Neighb_Rec (Cx, SO->N_Node, Cx,
4688 SO->FN, 1, N_smooth, NULL, 1);
4689 } else {
4690 Cx = SUMA_SmoothAttr_Neighb_Rec (Cx, SO->N_Node, Cx,
4691 SO->FN, 1, 5, NULL, 1);
4692 }
4693 }
4694 }
4695 #endif
4696
4697 if (Cx == NULL) {
4698 fprintf (SUMA_STDERR,
4699 "Error %s: Failed in SUMA_SmoothAttr_Neighb\n", FuncName);
4700 }
4701
4702 /* create a dataset of the convexity */
4703 if (DsetList){ /* put the convexity as a DataSet */
4704 SUMA_DSET *dset = NULL;
4705 char *name_tmp=NULL;
4706 if ((name_tmp = SUMA_SurfaceFileName(SO, 1))) {
4707 /* Go with this baby, maybe someday modify
4708 fuction above to return full path, making it
4709 more robust */
4710 name_tmp = SUMA_append_replace_string("Convexity_",name_tmp,"",2);
4711 } else if (SO->Label) {
4712 name_tmp = SUMA_append_string("Convexity_",SO->Label);
4713 } else if (SO->idcode_str) {
4714 name_tmp = SUMA_append_string("Convexity_",SO->idcode_str);
4715 } else {
4716 name_tmp = SUMA_append_string("Convexity_","Give_Peace_A_Chance");
4717 }
4718 dset = SUMA_CreateDsetPointer(name_tmp, /* no file name, but specify a
4719 name anyway _COD is
4720 computed on demand*/
4721 SUMA_NODE_CONVEXITY,
4722 NULL, /* let function create ID code */
4723 SO->idcode_str, /* domain owner */
4724 SO->N_Node);
4725 SUMA_free(name_tmp); name_tmp = NULL;
4726 if (!SUMA_InsertDsetPointer(&dset, DsetList, 0)) {
4727 SUMA_SL_Err("Failed to insert dset into list");
4728 SUMA_RETURN(NOPE);
4729 }
4730 if (!SUMA_AddDsetNelCol ( dset, "convexity", SUMA_NODE_CX,
4731 (void *)Cx, NULL ,1)) {
4732 SUMA_SL_Err("Failed in SUMA_AddNelCol");
4733 SUMA_RETURN(NOPE);
4734 }
4735
4736 SUMA_free(Cx); Cx = NULL; /* Cx is safe and sound in DsetList */
4737
4738 }
4739 } /* DoConv */
4740
4741
4742 if (DoWind){
4743 int trouble;
4744 /* make sure winding is consistent */
4745 if (!SUMA_MakeConsistent ( SO->FaceSetList, SO->N_FaceSet, SO->EL,
4746 1, &trouble)) {
4747 fprintf( SUMA_STDERR,
4748 "Error %s: Failed in SUMA_MakeConsistent.\n", FuncName);
4749 }else {
4750 if (LocalHead) fprintf(SUMA_STDERR,"%s: Eeeexcellent.\n", FuncName);
4751 }
4752 if (trouble) {
4753 SUMA_SL_Note( "Even if winding was made consistent,\n"
4754 "Pre-computed normals and normals-related\n"
4755 "measures and edge lists will need to be\n"
4756 "recalculated.\n"
4757 "See also SurfQual and \n"
4758 "ConvertSurface's -make_consistent option.\n");
4759 }
4760 }
4761
4762
4763 if (DoCurv) {
4764 /* calculate the curvature */
4765 if (LocalHead)
4766 fprintf(SUMA_STDOUT, "%s: Calculating curvature ...\n", FuncName);
4767 SO->SC = SUMA_Surface_Curvature (SO->NodeList, SO->N_Node,
4768 SO->NodeNormList, SO->PolyArea,
4769 SO->N_FaceSet, SO->FN, SO->EL, NULL,
4770 debug);
4771 }
4772
4773
4774 if (DoMF) {
4775 if (!SOinh) {
4776 /* determine the MemberFaceSets */
4777 if (LocalHead)
4778 fprintf(SUMA_STDOUT, "%s: Determining MemberFaceSets ...\n",
4779 FuncName);
4780 SO->MF = SUMA_MemberFaceSets(SO->N_Node, SO->FaceSetList, SO->N_FaceSet, SO->FaceSetDim, SO->idcode_str);
4781 if (SO->MF->NodeMemberOfFaceSet == NULL) {
4782 fprintf( SUMA_STDERR,
4783 "Error %s: Error in SUMA_MemberFaceSets\n", FuncName);
4784 SUMA_RETURN (NOPE);/* do not free MF, that's done when SO is freed */
4785 }else {
4786 }
4787 } else { /* inherit */
4788 if (LocalHead)
4789 fprintf(SUMA_STDOUT, "%s: Linking Member Facesets ...\n", FuncName);
4790 SO->MF = (SUMA_MEMBER_FACE_SETS*)SUMA_LinkToPointer((void*)SOinh->MF);
4791 }
4792 }
4793
4794 /* Initialize drawing masks */
4795 if (DoDW) {
4796 if (!SOinh) {
4797 SO->DW = (SUMA_DRAW_MASKS *)SUMA_calloc(1,sizeof(SUMA_DRAW_MASKS));
4798 SO->DW->do_type = not_DO_type;
4799 SO->DW->LinkedPtrType = SUMA_LINKED_DRAW_MASKS_TYPE;
4800 SO->DW->N_links = 0;
4801 if (SO->idcode_str) sprintf(SO->DW->owner_id, "%s", SO->idcode_str);
4802 else SO->DW->owner_id[0] = '\0';
4803 SUMA_EmptyDrawMasks(SO->DW);
4804 } else {
4805 if (LocalHead)
4806 fprintf(SUMA_STDOUT, "%s: Linking Drawing Masks ...\n", FuncName);
4807 SO->DW = (SUMA_DRAW_MASKS *)SUMA_LinkToPointer((void*)SOinh->DW);
4808 }
4809 }
4810 SUMA_RETURN (YUP);
4811 }
4812
4813
4814
4815
4816 /*! function to return a string containing the name of the files
4817 defining a surface object
4818
4819 ans = SUMA_SurfaceFileName (SO, MitPath);
4820 \param SO (SUMA_SurfaceObject *) the surface object
4821 \param MitPath (SUMA_Boolean) if YUP then path is included
4822 \ret ans (char *) containing the name of the file from which the surface
4823 was loaded. If the surface is freesurfer format, the filename is
4824 something like rh.smooth.asc. If it's a SureFit surface then you'll
4825 get both .coord and .topo xxx.coord__yyy.topo
4826 ans is allocated in the function, of course, and must be freed after use
4827 */
4828
SUMA_SurfaceFileName(SUMA_SurfaceObject * SO,SUMA_Boolean MitPath)4829 char * SUMA_SurfaceFileName (SUMA_SurfaceObject * SO, SUMA_Boolean MitPath)
4830 {
4831 static char FuncName[]={"SUMA_SurfaceFileName"};
4832 char *Name=NULL;
4833 int nalloc=0;
4834
4835 SUMA_ENTRY;
4836
4837 /* check if recognizable type */
4838 switch (SO->FileType) {
4839 case SUMA_VEC:
4840 case SUMA_SUREFIT:
4841 if (!SO->Name_coord.Path || !SO->Name_coord.FileName ||
4842 !SO->Name_topo.Path || !SO->Name_topo.FileName) {
4843 SUMA_RETURN(NULL);
4844 }
4845 if (MitPath) nalloc =
4846 strlen(SO->Name_coord.Path) +
4847 strlen(SO->Name_coord.FileName) +
4848 strlen(SO->Name_topo.Path) +
4849 strlen(SO->Name_topo.FileName) + 5;
4850 else nalloc = strlen(SO->Name_coord.FileName) +
4851 strlen(SO->Name_topo.FileName) + 5;
4852 break;
4853 case SUMA_FT_NOT_SPECIFIED:
4854 case SUMA_INVENTOR_GENERIC:
4855 case SUMA_FREE_SURFER:
4856 case SUMA_FREE_SURFER_PATCH:
4857 case SUMA_BRAIN_VOYAGER:
4858 case SUMA_OPENDX_MESH:
4859 case SUMA_OBJ_MESH:
4860 case SUMA_BYU:
4861 case SUMA_GIFTI:
4862 case SUMA_PREDEFINED:
4863 case SUMA_MNI_OBJ:
4864 case SUMA_STL:
4865 case SUMA_PLY:
4866 if (!SO->Name.Path || !SO->Name.FileName ) {
4867 SUMA_RETURN(NULL);
4868 }
4869 if (MitPath)
4870 nalloc = strlen(SO->Name.Path) + strlen(SO->Name.FileName) + 5;
4871 else nalloc = strlen(SO->Name.FileName) + 5;
4872 break;
4873 default:
4874 SUMA_error_message(FuncName, "SO_FileType not supported", 0);
4875 SUMA_RETURN (NULL);
4876 break;
4877 }
4878
4879 Name = (char *) SUMA_calloc (nalloc, sizeof(char));
4880 if (!Name) {
4881 fprintf (SUMA_STDERR,"Error %s: Could not allocate for Name.\n", FuncName);
4882 SUMA_RETURN (NULL);
4883 }
4884
4885 switch (SO->FileType) {
4886 case SUMA_FT_NOT_SPECIFIED:
4887 case SUMA_INVENTOR_GENERIC:
4888 case SUMA_FREE_SURFER:
4889 case SUMA_FREE_SURFER_PATCH:
4890 case SUMA_STL:
4891 case SUMA_PLY:
4892 case SUMA_OPENDX_MESH:
4893 case SUMA_OBJ_MESH:
4894 case SUMA_BYU:
4895 case SUMA_GIFTI:
4896 case SUMA_PREDEFINED:
4897 case SUMA_MNI_OBJ:
4898 case SUMA_BRAIN_VOYAGER:
4899 if (MitPath) sprintf(Name,"%s%s", SO->Name.Path, SO->Name.FileName);
4900 else sprintf(Name,"%s", SO->Name.FileName);
4901 break;
4902 case SUMA_SUREFIT:
4903 if (MitPath) sprintf(Name,"%s%s__%s%s",
4904 SO->Name_coord.Path, SO->Name_coord.FileName,
4905 SO->Name_topo.Path, SO->Name_topo.FileName);
4906 else sprintf(Name,"%s__%s",
4907 SO->Name_coord.FileName, SO->Name_topo.FileName);
4908 break;
4909 case SUMA_VEC:
4910 if (MitPath) sprintf(Name,"%s%s__%s%s",
4911 SO->Name_coord.Path, SO->Name_coord.FileName,
4912 SO->Name_topo.Path, SO->Name_topo.FileName);
4913 else sprintf(Name,"%s__%s",
4914 SO->Name_coord.FileName, SO->Name_topo.FileName);
4915 break;
4916 case SUMA_N_SO_FILE_TYPE:
4917 case SUMA_CMAP_SO:
4918 case SUMA_FT_ERROR:
4919 break;
4920 }
4921 SUMA_RETURN (Name);
4922
4923 }
4924
4925 /*!
4926 Guess if a surface is anaomically correct from the name.
4927 */
SUMA_GuessAnatCorrect(SUMA_SurfaceObject * SO)4928 char SUMA_GuessAnatCorrect(SUMA_SurfaceObject *SO)
4929 {
4930 static char FuncName[]={"SUMA_GuessAnatCorrect"};
4931
4932 SUMA_ENTRY;
4933
4934 switch (SO->FileType) {
4935 case SUMA_INVENTOR_GENERIC:
4936 case SUMA_FREE_SURFER:
4937 case SUMA_FREE_SURFER_PATCH:
4938 case SUMA_OPENDX_MESH:
4939 case SUMA_OBJ_MESH:
4940 case SUMA_STL:
4941 case SUMA_PLY:
4942 case SUMA_BYU:
4943 case SUMA_MNI_OBJ:
4944 case SUMA_PREDEFINED:
4945 case SUMA_BRAIN_VOYAGER:
4946 if ( SUMA_iswordin (SO->Name.FileName, ".white") == 1 ||
4947 SUMA_iswordin (SO->Name.FileName, ".smoothwm") == 1 ||
4948 SUMA_iswordin (SO->Name.FileName, ".pial") == 1 ||
4949 SUMA_iswordin (SO->Name.FileName, ".orig") == 1 ||
4950 SUMA_iswordin (SO->Name.FileName, ".fiducial") == 1 ||
4951 SUMA_iswordin_ci (SO->Name.FileName, "_WM") == 1 ||
4952 SUMA_iswordin_ci (SO->Name.FileName, "_GM") == 1 ||
4953 ( SUMA_iswordin (SO->Name.FileName, "_RECO") == 1 &&
4954 !(SUMA_iswordin (SO->Name.FileName, "_inf") == 1) )
4955 ) {
4956 SUMA_RETURN('Y');
4957 } else {
4958 SUMA_RETURN('N');
4959 }
4960 break;
4961 case SUMA_SUREFIT:
4962 case SUMA_VEC:
4963 if ( SUMA_iswordin (SO->Name_coord.FileName, ".white") == 1 ||
4964 SUMA_iswordin (SO->Name_coord.FileName, ".smoothwm") == 1 ||
4965 SUMA_iswordin (SO->Name_coord.FileName, ".pial") == 1 ||
4966 SUMA_iswordin (SO->Name_coord.FileName, ".orig") == 1 ||
4967 SUMA_iswordin (SO->Name_coord.FileName, ".fiducial") == 1 ||
4968 SUMA_iswordin_ci (SO->Name_coord.FileName, ".Fiducial") == 1 ||
4969 SUMA_iswordin (SO->Name_coord.FileName, ".Raw") == 1 ||
4970 SUMA_iswordin (SO->Name.FileName, "_WM") == 1 ||
4971 SUMA_iswordin (SO->Name.FileName, "_GM") == 1
4972 ) {
4973 SUMA_RETURN('Y');
4974 } else {
4975 SUMA_RETURN('N');
4976 }
4977 break;
4978 case SUMA_N_SO_FILE_TYPE:
4979 case SUMA_FT_NOT_SPECIFIED:
4980 case SUMA_CMAP_SO:
4981 case SUMA_FT_ERROR:
4982 break;
4983 case SUMA_GIFTI:
4984 if (SO->aSO) {
4985 if ( SUMA_iswordsame_ci ( SUMA_NI_AttrOfNamedElement(
4986 SO->aSO,
4987 "Node_XYZ",
4988 "GeometricType"),
4989 "Reconstruction") == 1 ||
4990 SUMA_iswordsame_ci ( SUMA_NI_AttrOfNamedElement(
4991 SO->aSO,
4992 "Node_XYZ",
4993 "GeometricType"),
4994 "Anatomical") == 1 ) {
4995 SUMA_RETURN('Y');
4996 }else {
4997 SUMA_RETURN('N');
4998 }
4999 } else {
5000 SUMA_RETURN('N');
5001 }
5002 break;
5003 }
5004
5005 SUMA_RETURN('\0');
5006 }
5007
SUMA_GuessSide(SUMA_SurfaceObject * SO)5008 SUMA_SO_SIDE SUMA_GuessSide(SUMA_SurfaceObject *SO)
5009 {
5010 static char FuncName[]={"SUMA_GuessSide"};
5011 char *cc=NULL;
5012
5013 SUMA_ENTRY;
5014
5015 switch (SO->FileType) {
5016 case SUMA_INVENTOR_GENERIC:
5017 break;
5018 case SUMA_FREE_SURFER:
5019 case SUMA_FREE_SURFER_PATCH:
5020 if (SUMA_iswordin (SO->Name.FileName, "lh") == 1) {
5021 SUMA_RETURN(SUMA_LEFT);
5022 } else if (SUMA_iswordin (SO->Name.FileName, "rh") == 1) {
5023 SUMA_RETURN(SUMA_RIGHT);
5024 }
5025 /* try some more */
5026 if (SUMA_iswordin_ci (SO->Name.FileName, "_lh") == 1 ||
5027 SUMA_iswordin_ci (SO->Name.FileName, ".lh") == 1 ||
5028 SUMA_iswordin_ci (SO->Name.FileName, "lh_") == 1 ||
5029 SUMA_iswordin_ci (SO->Name.FileName, "lh.") == 1) {
5030 SUMA_RETURN(SUMA_LEFT);
5031 } else if (SUMA_iswordin_ci (SO->Name.FileName, "_rh") == 1||
5032 SUMA_iswordin_ci (SO->Name.FileName, ".rh") == 1 ||
5033 SUMA_iswordin_ci (SO->Name.FileName, "rh_") == 1 ||
5034 SUMA_iswordin_ci (SO->Name.FileName, "rh.") == 1) {
5035 SUMA_RETURN(SUMA_RIGHT);
5036 }
5037 break;
5038 case SUMA_BRAIN_VOYAGER:
5039 if (SUMA_iswordin (SO->Name.FileName, "_LH") == 1) {
5040 SUMA_RETURN(SUMA_LEFT);
5041 } else if (SUMA_iswordin (SO->Name.FileName, "_RH") == 1) {
5042 SUMA_RETURN(SUMA_RIGHT);
5043 }
5044 break;
5045 case SUMA_SUREFIT:
5046 if (SUMA_iswordin_ci (SO->Name_coord.FileName, "left") == 1 ||
5047 SUMA_iswordin (SO->Name_coord.FileName, ".L.") == 1) {
5048 SUMA_RETURN(SUMA_LEFT);
5049 } else if (SUMA_iswordin_ci (SO->Name_coord.FileName, "right") == 1 ||
5050 SUMA_iswordin (SO->Name_coord.FileName, ".R.") == 1) {
5051 SUMA_RETURN(SUMA_RIGHT);
5052 }
5053 break;
5054 case SUMA_VEC:
5055 if (SUMA_iswordin (SO->Name_coord.FileName, "lh") == 1 ||
5056 SUMA_iswordin (SO->Name_coord.FileName, "left") == 1) {
5057 SUMA_RETURN(SUMA_LEFT);
5058 } else if (SUMA_iswordin (SO->Name_coord.FileName, "rh") == 1 ||
5059 SUMA_iswordin (SO->Name_coord.FileName, "right") == 1) {
5060 SUMA_RETURN(SUMA_RIGHT);
5061 }
5062 break;
5063 case SUMA_FT_NOT_SPECIFIED:
5064 case SUMA_CMAP_SO:
5065 case SUMA_N_SO_FILE_TYPE:
5066 case SUMA_FT_ERROR:
5067 break;
5068 case SUMA_OPENDX_MESH:
5069 case SUMA_OBJ_MESH:
5070 case SUMA_BYU:
5071 case SUMA_MNI_OBJ:
5072 case SUMA_PREDEFINED:
5073 case SUMA_STL:
5074 case SUMA_PLY:
5075 if (SUMA_iswordin (SO->Name.FileName, "lh") == 1 ||
5076 SUMA_iswordin (SO->Name.FileName, "left") == 1) {
5077 SUMA_RETURN(SUMA_LEFT);
5078 } else if (SUMA_iswordin (SO->Name.FileName, "rh") == 1 ||
5079 SUMA_iswordin (SO->Name.FileName, "right") == 1) {
5080 SUMA_RETURN(SUMA_RIGHT);
5081 }
5082 break;
5083 case SUMA_GIFTI:
5084 if (SO->aSO) {
5085 cc = SUMA_NI_AttrOfNamedElement( SO->aSO,
5086 "Node_XYZ",
5087 "AnatomicalStructurePrimary");
5088 if (!cc || !strcmp(cc,"Unknown")) {
5089 if (SUMA_iswordin (SO->Name.FileName, "lh") == 1 ) {
5090 SUMA_RETURN(SUMA_LEFT);
5091 } else if (SUMA_iswordin (SO->Name.FileName, "rh") == 1 ) {
5092 SUMA_RETURN(SUMA_RIGHT);
5093 } else if (SUMA_iswordin (SO->Name_coord.FileName, "lh") == 1 ) {
5094 SUMA_RETURN(SUMA_LEFT);
5095 } else if (SUMA_iswordin (SO->Name_coord.FileName, "rh") == 1 ) {
5096 SUMA_RETURN(SUMA_RIGHT);
5097 } else {
5098 SUMA_RETURN (SUMA_NO_SIDE);
5099 }
5100 } else {
5101 SUMA_RETURN(SUMA_giiStringToNumSide(cc));
5102 }
5103 } else {
5104 SUMA_RETURN(SUMA_NO_SIDE);
5105 }
5106 break;
5107 }
5108
5109 SUMA_RETURN (SUMA_NO_SIDE);
5110 }
5111
5112 /*!
5113 tol is the percent tolerance for accepting a surface as a sphere if
5114 its radius fluctuates by tol percent.
5115 */
SUMA_SetSphereParams(SUMA_SurfaceObject * SO,float tol)5116 int SUMA_SetSphereParams(SUMA_SurfaceObject *SO, float tol)
5117 {
5118 static char FuncName[]={"SUMA_SetSphereParams"};
5119 double cent[3], centmed[3], RAD, RAD0, RAD1, rad;
5120 int i, i3;
5121 double r[3], ra=0.0;
5122 char *cc=NULL;
5123 SUMA_GEOM_TYPE isSphere = SUMA_GEOM_NOT_SET;
5124 SUMA_Boolean LocalHead = NOPE;
5125
5126 SUMA_ENTRY;
5127
5128 isSphere = SUMA_GEOM_NOT_SET;
5129 if (tol < 0.0) tol = 0.2;
5130
5131 SUMA_LHv("Setting spheriosity for %s (EmbedDim=%d)\n",
5132 SO->Label ? SO->Label:"NULL", SO->EmbedDim);
5133
5134 /* Can't rely on SO->EmbedDim for this function.
5135 It is not set when you get here, and you could
5136 get the default of 3, but check it anyway
5137 */
5138 if (SO->EmbedDim > 0 && SO->EmbedDim < 3) SUMA_RETURN(SUMA_GEOM_IRREGULAR);
5139
5140 /* has this been determined ? */
5141 if (SUMA_IS_GEOM_SYMM(SO->isSphere)) {
5142 SUMA_LHv("%s is labeled as %d already\n", SO->Label, SO->isSphere);
5143 isSphere = SO->isSphere;
5144 }
5145
5146 if (isSphere == SUMA_GEOM_NOT_SET) { /* try to guess from name */
5147 SUMA_LHv("Trying to guess from name %s\n", SO->Name.FileName);
5148 switch (SO->FileType) {
5149 case SUMA_INVENTOR_GENERIC:
5150 break;
5151 case SUMA_FREE_SURFER:
5152 case SUMA_FREE_SURFER_PATCH:
5153 if ( SUMA_iswordin_ci (SO->Name.FileName, "sphere.reg") == 1 ||
5154 SUMA_iswordin (SO->Name.FileName, "sphere") == 1 ) {
5155 isSphere = SUMA_GEOM_SPHERE;
5156 }
5157 break;
5158 case SUMA_BRAIN_VOYAGER:
5159 break;
5160 case SUMA_BYU:
5161 break;
5162 case SUMA_SUREFIT:
5163 if (SUMA_iswordin_ci (SO->Name_coord.FileName, "sphere") == 1 ) {
5164 isSphere = SUMA_GEOM_SPHERE;
5165 }
5166 break;
5167 case SUMA_VEC:
5168 break;
5169 case SUMA_FT_NOT_SPECIFIED:
5170 case SUMA_CMAP_SO:
5171 case SUMA_N_SO_FILE_TYPE:
5172 case SUMA_FT_ERROR:
5173 break;
5174 case SUMA_OPENDX_MESH:
5175 case SUMA_OBJ_MESH:
5176 case SUMA_MNI_OBJ:
5177 case SUMA_STL:
5178 case SUMA_PLY:
5179 break;
5180 case SUMA_PREDEFINED:
5181 if ( !strncmp(SO->Name.FileName, "ld",2) ) {
5182 isSphere = SUMA_GEOM_SPHERE;
5183 }
5184 break;
5185 case SUMA_GIFTI:
5186 if (SO->aSO) {
5187 if ((cc = SUMA_NI_AttrOfNamedElement( SO->aSO,
5188 "Node_XYZ", "GeometricType"))) {
5189 if (SUMA_iswordsame_ci(cc,"spherical")) {
5190 isSphere = SUMA_GEOM_SPHERE;
5191 }
5192 } else {
5193 if ( SUMA_iswordin_ci (SO->Name.FileName, "sphere.reg") == 1
5194 ||SUMA_iswordin (SO->Name.FileName, "sphere") == 1 ) {
5195 isSphere = SUMA_GEOM_SPHERE;
5196 }
5197 }
5198 } else {
5199 if ( SUMA_iswordin_ci (SO->Name.FileName, "sphere.reg") == 1
5200 ||SUMA_iswordin (SO->Name.FileName, "sphere") == 1 ) {
5201 isSphere = SUMA_GEOM_SPHERE;
5202 }
5203 }
5204 break;
5205 }
5206
5207 /* the quick way, make sure bounding box is not that of a flat surface*/
5208 SUMA_LH("Trying to guess from aspect ratio");
5209 if (!SUMA_isSODimInitialized(SO)) {
5210 if (!SUMA_SetSODims(SO)) {
5211 SUMA_S_Err("Failed to set dims!");
5212 SUMA_RETURN(NOPE);
5213 }
5214 }else {
5215 SUMA_LH("SODim initialized already");
5216 }
5217 ra = 0.0;
5218 for (i=0;i<3;++i) { r[i] = SO->MaxDims[i]-SO->MinDims[i]; ra += r[i]; }
5219 ra /= 3.0;
5220
5221 if ( r[0] < 0.001 || r[1] < 0.001 || r[2] < 0.001 ||
5222 r[0]/ra < 0.8 || r[1]/ra < 0.8 || r[2]/ra < 0.8) {
5223 SUMA_LHv("too distorted bounding box dimensions=[%f %f %f]\n",
5224 r[0], r[1], r[2]);
5225 isSphere = SUMA_GEOM_IRREGULAR;
5226 }
5227 }
5228
5229
5230
5231 if ( isSphere == SUMA_GEOM_NOT_SET ||
5232 (SUMA_IS_GEOM_SYMM(isSphere) && SO->SphereRadius < 0.0) ) {
5233 /* need to figure out the hard way
5234 or need to fill up params */
5235 if (isSphere == SUMA_GEOM_NOT_SET) {
5236 SUMA_LHv("The hard way (tol = %f)\n", tol);
5237 } else {
5238 SUMA_LHv("Need to set radius and center. tol = %f\n", tol);
5239 }
5240 /* the hard way */
5241 if (!SUMA_GetCenterOfSphereSurface(SO, 500, cent, centmed)) {
5242 SUMA_S_Warn("Failed to guess at spheriosity.");
5243 SUMA_RETURN(NOPE);
5244 }
5245 /* is this center inside the bounding box or are we fitting
5246 spheres to flat surfaces */
5247 if ( centmed[0] <= SO->MinDims[0] || centmed[0] >= SO->MaxDims[0] ||
5248 centmed[1] <= SO->MinDims[1] || centmed[1] >= SO->MaxDims[1] ||
5249 centmed[2] <= SO->MinDims[2] || centmed[2] >= SO->MaxDims[2] ) {
5250 SUMA_LH("Failed center test, outside boundig box. Flat surface?\n");
5251 isSphere = SUMA_GEOM_IRREGULAR;
5252 goto DONE;
5253 }
5254 /* have center, verify that all nodes are within 1/1000 of Rad */
5255 SUMA_LHv("Have a center of [%f %f %f] for %s\n",
5256 centmed[0] , centmed[1], centmed[2] ,
5257 SUMA_CHECK_NULL_STR(SO->Label)) ;
5258 RAD = sqrt( SUMA_POW2( SO->NodeList[0] - centmed[0] ) +
5259 SUMA_POW2( SO->NodeList[1] - centmed[1] ) +
5260 SUMA_POW2( SO->NodeList[2] - centmed[2] ) );
5261 RAD0 = RAD * (100.0-tol)/100.0;
5262 RAD1 = RAD * (100.0+tol)/100.0;
5263 isSphere = SUMA_GEOM_SPHERE;
5264 for (i=1; i<SO->N_Node && isSphere == SUMA_GEOM_SPHERE; ++i) {
5265 i3 = 3*i;
5266 rad = sqrt( SUMA_POW2( SO->NodeList[i3 ] - centmed[0] ) +
5267 SUMA_POW2( SO->NodeList[i3+1] - centmed[1] ) +
5268 SUMA_POW2( SO->NodeList[i3+2] - centmed[2] ) );
5269 if (rad < RAD0 || rad > RAD1) {
5270 /* no cigar */
5271 SUMA_LHv("Failed radius test:\n"
5272 "Rad range [%f %f]\n"
5273 "Rad %f\n", RAD0, RAD1, rad);
5274 isSphere = SUMA_GEOM_IRREGULAR;
5275 }
5276 }
5277 if (isSphere == SUMA_GEOM_SPHERE) {
5278 SO->SphereRadius = RAD;
5279 SO->SphereCenter[0] = centmed[0];
5280 SO->SphereCenter[1] = centmed[1];
5281 SO->SphereCenter[2] = centmed[2];
5282 SUMA_LHv("A sphere it is: \n"
5283 "r = %f\n"
5284 "c = [%f %f %f]\n", SO->SphereRadius,
5285 SO->SphereCenter[0], SO->SphereCenter[1], SO->SphereCenter[2]);
5286 }else{
5287 SUMA_LH("A sphere it is NOT, assuming it is irregular");
5288 }
5289 } else {
5290 SUMA_LHv("isSphere is %d, "
5291 "SUMA_IS_GEOM_SYMM(isSphere) = %d, SO->SphereRadius=%f\n",
5292 isSphere , SUMA_IS_GEOM_SYMM(isSphere), SO->SphereRadius);
5293 }
5294
5295 DONE:
5296 SO->isSphere = isSphere;
5297 SUMA_RETURN (YUP);
5298 }
5299
5300 /*---------------------------------------------------------------------------
5301 * SUMA_spec_select_surfs - restrict spec results to given names
5302 * [rickr]
5303 * for each name in list
5304 * - verify that it is in the spec file
5305 * - verify that it is unique in the spec file
5306 * restrict the spec contents to the given name list
5307 *
5308 * return:
5309 * (-1) on failure
5310 * new N_Surfs on success
5311 *---------------------------------------------------------------------------
5312 */
SUMA_spec_select_surfs(SUMA_SurfSpecFile * spec,char ** names,int nnames,int debug)5313 int SUMA_spec_select_surfs( SUMA_SurfSpecFile * spec, char ** names, int nnames,
5314 int debug )
5315 {
5316 static char FuncName[]={"SUMA_spec_select_surfs"};
5317 char * nfile;
5318 int name, surf, name_ind;
5319
5320 SUMA_ENTRY;
5321
5322 if ( ! spec || ! names )
5323 {
5324 fprintf(stderr,"** SUMA_spec_select_surfs: invalid params (%p,%p)\n",
5325 spec, names);
5326 SUMA_RETURN( -1 );
5327 }
5328
5329 if ( debug > 1 )
5330 fprintf(stderr, "-- select surfs: searching %d names...\n", nnames);
5331
5332 if ( nnames <= 0 )
5333 SUMA_RETURN( 0 );
5334
5335 /* first, check for existence and uniquenes in list */
5336 for ( name = 0; name < nnames; name++ )
5337 {
5338 if ( ! names[name] ) /* then end the process */
5339 {
5340 nnames = name;
5341 break;
5342 }
5343
5344 name_ind = SUMA_unique_name_ind(spec, names[name]);
5345
5346 if ( name_ind < 0 )
5347 {
5348 if ( name_ind == -1 )
5349 fprintf(stderr,"** surface name '%s' not found\n",names[name]);
5350 SUMA_RETURN( -1 );
5351 }
5352
5353 if ( debug > 1 )
5354 fprintf(stderr, "-- select surfs: found name '%s'\n", names[name]);
5355
5356 if ( name_ind != name )
5357 SUMA_swap_spec_entries(spec, name, name_ind, debug);
5358 }
5359
5360 /* now set N_Surfs and N_Groups */
5361 spec->N_Surfs = nnames;
5362
5363 if ( debug > 1 )
5364 fprintf(stderr, "-- select surfs: returning %d names\n", nnames);
5365
5366 SUMA_RETURN( nnames );
5367 }
5368
5369 /*---------------------------------------------------------------------------
5370 * SUMA_spec_set_map_refs - set *all* mapping refs to SAME
5371 * [rickr]
5372 *---------------------------------------------------------------------------
5373 */
SUMA_spec_set_map_refs(SUMA_SurfSpecFile * spec,int debug)5374 int SUMA_spec_set_map_refs( SUMA_SurfSpecFile * spec, int debug )
5375 {
5376 int sc;
5377
5378 for (sc = 0; sc < spec->N_Surfs; sc++ )
5379 {
5380 if ( ! strstr(spec->MappingRef[sc],"SAME") )
5381 {
5382 if ( debug > 0 )
5383 fprintf(stderr,"-- map ref: replace '%s' with '%s'\n",
5384 spec->MappingRef[sc], "./SAME");
5385 strcpy(spec->MappingRef[sc], "./SAME");
5386 }
5387 else if ( debug > 2 )
5388 fprintf(stderr,"-- mr: have good map ref '%s'\n",
5389 spec->MappingRef[sc]);
5390 }
5391
5392 return 0;
5393 }
5394
5395 /*---------------------------------------------------------------------------
5396 * SUMA_swap_spec_entries - swap entries for the 2 given indices
5397 * [rickr]
5398 * return:
5399 * 0 on success
5400 * -1 on failure
5401 *---------------------------------------------------------------------------
5402 */
SUMA_swap_spec_entries(SUMA_SurfSpecFile * spec,int i0,int i1,int debug)5403 int SUMA_swap_spec_entries( SUMA_SurfSpecFile * spec, int i0, int i1, int debug)
5404 {
5405 char * cpsave;
5406 char cssave[SUMA_MAX_NAME_LENGTH];
5407 int isave, c;
5408
5409 if ( !spec || (i0 < 0) || (i0 >= spec->N_Surfs) ||
5410 (i1 < 0) || (i1 >= spec->N_Surfs) )
5411 {
5412 fprintf(stderr,"** swap_spec_entries: bad params (%p,%d,%d)\n",
5413 spec, i0, i1);
5414 return -1;
5415 }
5416
5417 if ( debug > 2 )
5418 fprintf(stderr,"-- swapping spec entries %d and %d\n", i0, i1);
5419
5420 cssave[SUMA_MAX_NAME_LENGTH-1] = '\0'; /* to be safe */
5421
5422 swap_strings(spec->SurfaceType[i0], spec->SurfaceType[i1],
5423 cssave, SUMA_MAX_LABEL_LENGTH);
5424 swap_strings(spec->SurfaceFormat[i0], spec->SurfaceFormat[i1],
5425 cssave, SUMA_MAX_LABEL_LENGTH);
5426 swap_strings(spec->TopoFile[i0], spec->TopoFile[i1],
5427 cssave, SUMA_MAX_NAME_LENGTH);
5428 swap_strings(spec->CoordFile[i0], spec->CoordFile[i1],
5429 cssave, SUMA_MAX_NAME_LENGTH);
5430 swap_strings(spec->MappingRef[i0], spec->MappingRef[i1],
5431 cssave, SUMA_MAX_NAME_LENGTH);
5432 swap_strings(spec->AnatCorrect[i0], spec->AnatCorrect[i1],
5433 cssave, SUMA_MAX_NAME_LENGTH);
5434 swap_strings(spec->Hemisphere[i0], spec->Hemisphere[i1],
5435 cssave, SUMA_MAX_NAME_LENGTH);
5436 swap_strings(spec->DomainGrandParentID[i0], spec->DomainGrandParentID[i1],
5437 cssave, SUMA_MAX_NAME_LENGTH);
5438 swap_strings(spec->OriginatorID[i0], spec->OriginatorID[i1],
5439 cssave, SUMA_MAX_NAME_LENGTH);
5440 swap_strings(spec->LocalCurvatureParent[i0], spec->LocalCurvatureParent[i1],
5441 cssave, SUMA_MAX_NAME_LENGTH);
5442 swap_strings(spec->LocalDomainParent[i0], spec->LocalDomainParent[i1],
5443 cssave, SUMA_MAX_NAME_LENGTH);
5444 swap_strings(spec->SureFitVolParam[i0], spec->SureFitVolParam[i1],
5445 cssave, SUMA_MAX_NAME_LENGTH);
5446 swap_strings(spec->SurfaceFile[i0], spec->SurfaceFile[i1],
5447 cssave, SUMA_MAX_NAME_LENGTH);
5448 swap_strings(spec->VolParName[i0], spec->VolParName[i1],
5449 cssave, SUMA_MAX_NAME_LENGTH);
5450
5451 cpsave = spec->IDcode[i0]; /* (char *)IDcode */
5452 spec->IDcode[i0] = spec->IDcode[i1];
5453 spec->IDcode[i1] = cpsave;
5454
5455 swap_strings(spec->State[i0], spec->State[i1],
5456 cssave, SUMA_MAX_LABEL_LENGTH);
5457 swap_strings(spec->Group[i0], spec->Group[i1],
5458 cssave, SUMA_MAX_NAME_LENGTH);
5459 swap_strings(spec->SurfaceLabel[i0], spec->SurfaceLabel[i1],
5460 cssave, SUMA_MAX_NAME_LENGTH);
5461
5462 isave = spec->EmbedDim[i0];
5463 spec->EmbedDim[i0] = spec->EmbedDim[i1];
5464 spec->EmbedDim[i1] = isave;
5465
5466 /* leave N_Surfs, N_States, N_Groups, StateList, SpecFilePath */
5467
5468 return 0;
5469 }
5470
SUMA_copy_spec_entries(SUMA_SurfSpecFile * spec0,SUMA_SurfSpecFile * spec1,int i0,int i1,int debug)5471 int SUMA_copy_spec_entries( SUMA_SurfSpecFile * spec0, SUMA_SurfSpecFile *spec1,
5472 int i0, int i1, int debug)
5473 {
5474 static char FuncName[]={"SUMA_copy_spec_entries"};
5475 if ( !spec0 || !spec1 ||
5476 (i0 < 0) || (i0 >= spec0->N_Surfs) ||
5477 (i1 < 0) || (i1 >= spec1->N_Surfs) )
5478 {
5479 fprintf(stderr,"** copy_spec_entries: bad params (%p,%d,%p,%d)\n",
5480 spec0, i0, spec1, i1);
5481 return -1;
5482 }
5483
5484 if ( debug > 2 )
5485 fprintf(stderr,"-- copying spec entries from spec0[%d] to spec1[%d]\n",
5486 i0, i1);
5487
5488 copy_strings(spec0->SurfaceType[i0], spec1->SurfaceType[i1],
5489 SUMA_MAX_LABEL_LENGTH);
5490 copy_strings(spec0->SurfaceFormat[i0], spec1->SurfaceFormat[i1],
5491 SUMA_MAX_LABEL_LENGTH);
5492 copy_strings(spec0->TopoFile[i0], spec1->TopoFile[i1],
5493 SUMA_MAX_FP_NAME_LENGTH);
5494 copy_strings(spec0->CoordFile[i0], spec1->CoordFile[i1],
5495 SUMA_MAX_NAME_LENGTH);
5496 copy_strings(spec0->MappingRef[i0], spec1->MappingRef[i1],
5497 SUMA_MAX_FP_NAME_LENGTH);
5498 copy_strings(spec0->AnatCorrect[i0], spec1->AnatCorrect[i1],
5499 SUMA_MAX_LABEL_LENGTH);
5500 copy_strings(spec0->Hemisphere[i0], spec1->Hemisphere[i1],
5501 SUMA_MAX_LABEL_LENGTH);
5502 copy_strings(spec0->DomainGrandParentID[i0], spec1->DomainGrandParentID[i1],
5503 SUMA_MAX_LABEL_LENGTH);
5504 copy_strings(spec0->OriginatorID[i0], spec1->OriginatorID[i1],
5505 SUMA_MAX_LABEL_LENGTH);
5506 copy_strings(spec0->LocalCurvatureParent[i0],spec1->LocalCurvatureParent[i1],
5507 SUMA_MAX_FP_NAME_LENGTH);
5508 copy_strings(spec0->LocalDomainParent[i0], spec1->LocalDomainParent[i1],
5509 SUMA_MAX_FP_NAME_LENGTH);
5510 copy_strings(spec0->SureFitVolParam[i0], spec1->SureFitVolParam[i1],
5511 SUMA_MAX_FP_NAME_LENGTH);
5512 copy_strings(spec0->SurfaceFile[i0], spec1->SurfaceFile[i1],
5513 SUMA_MAX_FP_NAME_LENGTH);
5514 copy_strings(spec0->VolParName[i0], spec1->VolParName[i1],
5515 SUMA_MAX_FP_NAME_LENGTH);
5516
5517 spec1->IDcode[i1] = spec0->IDcode[i0]; /* always pointer copy for this one */
5518
5519 copy_strings(spec0->State[i0], spec1->State[i1],
5520 SUMA_MAX_LABEL_LENGTH);
5521 copy_strings(spec0->Group[i0], spec1->Group[i1],
5522 SUMA_MAX_LABEL_LENGTH);
5523 copy_strings(spec0->SurfaceLabel[i0], spec1->SurfaceLabel[i1],
5524 SUMA_MAX_LABEL_LENGTH);
5525
5526 spec1->EmbedDim[i1] = spec0->EmbedDim[i0];
5527
5528 /* leave N_Surfs, N_States, N_Groups, StateList, SpecFilePath */
5529
5530 return 0;
5531 }
5532
5533 /*---------------------------------------------------------------------------
5534 * swap_strings - swap the two strings using the given space
5535 * [rickr]
5536 * return:
5537 * (-1) on failure
5538 * new N_Surfs on success
5539 *---------------------------------------------------------------------------
5540 */
swap_strings(char * s0,char * s1,char * space,int len)5541 int swap_strings( char * s0, char * s1, char * space, int len )
5542 {
5543 if ( ! s0 || ! s1 || ! space || len < 1 )
5544 {
5545 fprintf(stderr,"** swap_strings: invalid params (%p,%p,%p,%d)\n",
5546 s0, s1, space, len);
5547 }
5548
5549 s0 [len-1] = '\0'; /* now safe using strcpy */
5550 s1 [len-1] = '\0';
5551 space[len-1] = '\0';
5552
5553 strcpy(space, s0);
5554 strcpy(s0, s1);
5555 strcpy(s1, space);
5556
5557 return 0;
5558 }
copy_strings(char * s0,char * s1,int len)5559 int copy_strings( char * s0, char * s1, int len )
5560 {
5561 if ( ! s0 || ! s1 || len < 1 )
5562 {
5563 fprintf(stderr,"** copy_strings: invalid params (%p,%p,%d)\n",
5564 s0, s1, len);
5565 }
5566
5567 s0 [len-1] = '\0'; /* now safe using strcpy */
5568 s1 [len-1] = '\0';
5569
5570 strcpy(s1, s0);
5571
5572 return 0;
5573 }
5574
5575 /*---------------------------------------------------------------------------
5576 * SUMA_unique_name_ind - check that name exists uniquely [rickr]
5577 *
5578 * return:
5579
5580 * -1 on "not found"
5581 * -2 on "multiple matches"
5582 * -3 on "bad, horrible failure"
5583 *---------------------------------------------------------------------------
5584 */
SUMA_unique_name_ind(SUMA_SurfSpecFile * spec,char * sname)5585 int SUMA_unique_name_ind( SUMA_SurfSpecFile * spec, char * sname )
5586 {
5587 char * nfile;
5588 int surf, index = -1;
5589
5590 if ( ! spec || ! sname )
5591 {
5592 fprintf(stderr,"** unique_name_ind: bad params (%p, %p)\n",spec,sname);
5593 return -3;
5594 }
5595
5596 for ( surf = 0; surf < spec->N_Surfs; surf++ )
5597 {
5598 nfile = SUMA_coord_file(spec, surf);
5599
5600 if ( ! nfile )
5601 {
5602 fprintf(stderr,"** surf %d, no coord file\n", surf);
5603 return -3;
5604 }
5605
5606 /* we have a match */
5607 if ( strstr(nfile, sname) )
5608 {
5609 if ( index >= 0 )
5610 {
5611 fprintf(stderr,"** surf name %d, '%s': multiple matches\n"
5612 " '%s' and '%s'\n",
5613 surf, sname, nfile, SUMA_coord_file(spec,index));
5614 return -2;
5615 }
5616
5617 index = surf;
5618 }
5619 }
5620
5621 return index;
5622 }
5623
5624 /* Like SUMA_unique_name_ind, but return a pointer copy to the
5625 coordfile name instead.
5626 An empty string is retuned in error cases or no match */
SUMA_unique_name(SUMA_SurfSpecFile * spec,char * sname)5627 char * SUMA_unique_name( SUMA_SurfSpecFile * spec, char * sname )
5628 {
5629 char * nfile;
5630 int surf, index = -1;
5631
5632 if ( ! spec || ! sname )
5633 {
5634 fprintf(stderr,"** unique_name_ind: bad params (%p, %p)\n",spec,sname);
5635 return ("");
5636 }
5637
5638 for ( surf = 0; surf < spec->N_Surfs; surf++ )
5639 {
5640 nfile = SUMA_coord_file(spec, surf);
5641
5642 if ( ! nfile )
5643 {
5644 fprintf(stderr,"** surf %d, no coord file\n", surf);
5645 return ("");
5646 }
5647
5648 /* we have a match */
5649 if ( strstr(nfile, sname) )
5650 {
5651 if ( index >= 0 )
5652 {
5653 fprintf(stderr,"** surf name %d, '%s': multiple matches\n"
5654 " '%s' and '%s'\n",
5655 surf, sname, nfile, SUMA_coord_file(spec,index));
5656 return ("");
5657 }
5658
5659 index = surf;
5660 }
5661 }
5662
5663 if (!(nfile = SUMA_coord_file(spec,index))) return("");
5664 return (nfile);
5665 }
5666
5667 /*---------------------------------------------------------------------------
5668 * SUMA_coord_file - based on the surf type, return coord file
5669 * [rickr]
5670 * return:
5671 * on success, pointer to coord file
5672 * on any failure, NULL
5673 *---------------------------------------------------------------------------
5674 */
SUMA_coord_file(SUMA_SurfSpecFile * spec,int index)5675 char * SUMA_coord_file( SUMA_SurfSpecFile * spec, int index )
5676 {
5677 char * rp;
5678
5679 if ( ! spec || (index < 0) )
5680 {
5681 fprintf(stderr,"** coord_file: bad params (%p,%d)\n", spec, index);
5682 return NULL;
5683 }
5684
5685 /* SurfaceType field must match the TypeCodes 13 Nov 2007 */
5686 switch( SUMA_SurfaceTypeCode((spec->SurfaceType[index])) ){
5687 case SUMA_FT_NOT_SPECIFIED:
5688 return NULL;
5689 case SUMA_VEC:
5690 case SUMA_SUREFIT:
5691 return spec->CoordFile[index];
5692 default: /* FreeSurfer, Ply, etc. */
5693 return spec->SurfaceFile[index];
5694 }
5695 }
5696
5697 /*!
5698 return 1 if ld# surface, par takes #
5699 2 if rd# surface, par takes #
5700 3 if template spec, par is useless
5701 4 if template surface, par is useless
5702 0 not a prededined surface name
5703
5704 \sa SUMA_IS_LOADABLE_SO_NAME
5705 */
SUMA_is_predefined_SO_name(char * name,int * upar,char ** pdspec,char ** pdsv,char ** pdsname)5706 int SUMA_is_predefined_SO_name(char *name, int *upar,
5707 char **pdspec, char **pdsv, char **pdsname)
5708 {
5709 static char FuncName[]={"SUMA_is_predefined_SO_name"};
5710 int ldv = 0, tp = 0, par, StdOK=0, ii=0;
5711 NI_str_array *nisa=NULL;
5712 char *template=NULL, *leftover=NULL, *svname=NULL,
5713 *sname=NULL, *ss=NULL, stmp[64], *specname, *spref=NULL;
5714 SUMA_SO_SIDE side = SUMA_SIDE_ERROR;
5715 SUMA_SurfSpecFile spec;
5716 SUMA_Boolean LocalHead = NOPE;
5717
5718 SUMA_ENTRY;
5719
5720 if (!name) SUMA_RETURN(tp);
5721 if ( (pdspec && *pdspec) || (pdsv && *pdsv) || (pdsname && *pdsname)) {
5722 SUMA_S_Err("Must sent pointer to null char * pointer, or just NULL");
5723 SUMA_RETURN(tp);
5724 }
5725
5726 if (upar) *upar = -1;
5727
5728 if (!(nisa = SUMA_comp_str_2_NI_str_ar(name, ":"))) SUMA_RETURN(tp);
5729
5730 if (nisa->num == 0) {
5731 /* this should not happen... */
5732 SUMA_free_NI_str_array(nisa); SUMA_RETURN(tp);
5733 }
5734
5735 par = -1; tp = 0;
5736 template = NULL; side = SUMA_LR; StdOK = 1;
5737 leftover = NULL;
5738 for (ii=0; ii<nisa->num && StdOK; ++ii) {
5739 if ( (!strncmp(nisa->str[ii],"ld",2) || !strncmp(nisa->str[ii],"rd",2)) &&
5740 (strlen(nisa->str[ii]) <= 5) ) { /* Look for something like ld60 */
5741 ldv = (int)atoi(nisa->str[ii]+2);
5742 if (*nisa->str[ii]=='r' && ldv >= 0 && ldv <=100) {
5743 par = ldv;
5744 tp = 2;
5745 }
5746 if (*nisa->str[ii]=='l' && ldv >= 0 && ldv <=1000) {
5747 par = ldv;
5748 tp = 1;
5749 }
5750 if (par == -1) { /* not that kind of a block, and
5751 hence not a standard name, leave */
5752 StdOK = 0;
5753 }
5754 } else if ( !strcmp(nisa->str[ii],"MNI_N27") ) {/* A template name */
5755 template = "suma_MNI_N27";
5756 spref = "MNI_N27";
5757 } else if (!strcmp(nisa->str[ii],"TT_N27") ) {/* A template name */
5758 template = "suma_TT_N27";
5759 spref = "TT_N27";
5760 } else if ( !strcasecmp(nisa->str[ii],"l") ||
5761 !strcasecmp(nisa->str[ii],"lh") ||
5762 !strcasecmp(nisa->str[ii],"left") ) { /* side */
5763 side = SUMA_LEFT;
5764 } else if ( !strcasecmp(nisa->str[ii],"r") ||
5765 !strcasecmp(nisa->str[ii],"rh") ||
5766 !strcasecmp(nisa->str[ii],"right") ) { /* side */
5767 side = SUMA_RIGHT;
5768 } else if ( !strcasecmp(nisa->str[ii],"lr") ||
5769 !strcasecmp(nisa->str[ii],"both") ||
5770 !strcasecmp(nisa->str[ii],"rl") ) { /* side */
5771 side = SUMA_LR;
5772 } else if (!leftover) { /* state/surf name, potentially */
5773 if (nisa->str[ii] && nisa->str[ii][0] != '\0') leftover = nisa->str[ii];
5774 } else { /* Uncool, get out */
5775 StdOK = 0;
5776 }
5777 }
5778
5779 if (!template && leftover) { /* Not a standard name */
5780 SUMA_free_NI_str_array(nisa); nisa = NULL;
5781 if (upar) *upar = -1;
5782 SUMA_RETURN(0);
5783 }
5784
5785 if (!template) {
5786 SUMA_free_NI_str_array(nisa); nisa = NULL;
5787 if (upar) *upar = par;
5788 SUMA_LHv("Command line string >>%s<< parsed to:\n"
5789 "par %d, tp = %d\n",
5790 name, par, tp);
5791 SUMA_RETURN(tp);
5792 } else { /* now it gets complicated */
5793 if (par > 0) {
5794 sprintf(stmp, "std.%d.", par);
5795 } else {
5796 stmp[0]='\0';
5797 }
5798 specname = SUMA_append_replace_string(template,stmp,"/",0);
5799 switch (side) {
5800 case SUMA_LEFT:
5801 specname = SUMA_append_replace_string(specname,"_lh.spec",spref,1);
5802 break;
5803 case SUMA_RIGHT:
5804 specname = SUMA_append_replace_string(specname,"_rh.spec",spref,1);
5805 break;
5806 case SUMA_LR:
5807 specname = SUMA_append_replace_string(specname,"_both.spec",spref,1);
5808 break;
5809 default:
5810 SUMA_S_Errv("illegal spec file 'side' == %d\n", side);
5811 specname = SUMA_append_replace_string(specname,"_BAD.spec",spref,1);
5812 break;
5813 }
5814 ss = find_afni_file(specname, 0, NULL);
5815 if (ss[0] == '\0') {
5816 SUMA_S_Errv("Spec file %s not found despite effort\n", specname);
5817 SUMA_ifree(specname); specname = NULL;
5818 SUMA_free_NI_str_array(nisa); nisa = NULL;
5819 if (upar) *upar = -1;
5820 SUMA_RETURN(0);
5821 } else {
5822 SUMA_free(specname); specname = SUMA_copy_string(ss);
5823 tp = 3;
5824 }
5825
5826 svname = SUMA_append_replace_string(template,spref,"/",0);
5827 svname = SUMA_append_replace_string(svname,"_SurfVol.nii","",1);
5828 ss = find_afni_file(svname, 0, NULL);
5829 if (ss[0] == '\0') {/* try one more time */
5830 svname = SUMA_append_replace_string(svname,".gz","",1);
5831 ss = find_afni_file(svname, 0, NULL);
5832 }
5833 if (ss[0] == '\0') {
5834 SUMA_S_Warnv("No sv found for %s\n", specname);
5835 SUMA_ifree(svname);
5836 } else {
5837 SUMA_free(svname); svname=SUMA_copy_string(ss);
5838 }
5839 }
5840
5841 /* So now we have a template spec, do we have a request for a particular
5842 surface ? */
5843 if (leftover) {
5844 /* load the spec, identify the surface and set its name */
5845 SUMA_AllocSpecFields(&spec);
5846 if (!SUMA_Read_SpecFile (specname, &spec)) {
5847 SUMA_S_Errv("Failed to read SpecFile %s\n", specname);
5848 SUMA_ifree(specname); specname = NULL;
5849 SUMA_free_NI_str_array(nisa); nisa = NULL;
5850 if (upar) *upar = -1;
5851 SUMA_FreeSpecFields(&spec);
5852 SUMA_RETURN(0);
5853 }
5854 ss = SUMA_unique_name( &spec, leftover );
5855 SUMA_LH("dd %s", ss);
5856 if (ss[0]=='\0') {
5857 SUMA_S_Errv("Failed to get %s from %s\n", leftover, specname);
5858 SUMA_ifree(specname); specname = NULL;
5859 SUMA_free_NI_str_array(nisa); nisa = NULL;
5860 if (upar) *upar = -1;
5861 SUMA_FreeSpecFields(&spec);
5862 SUMA_RETURN(0);
5863 }
5864 /* OK, now we have a full surface name */
5865 sname = SUMA_copy_string(ss);
5866 SUMA_FreeSpecFields(&spec);
5867
5868 tp = 4;
5869 }
5870
5871 SUMA_LHv("Command line string >>%s<< parsed to:\n"
5872 "specname %s, svname %s, sname %s, par %d, side %d, tp %d\n",
5873 name, specname?specname:"NULL", svname?svname:"NULL",
5874 sname?sname:"NULL", par, side, tp);
5875
5876 if (pdspec) *pdspec = specname;
5877 else SUMA_ifree(specname);
5878 if (pdsv) *pdsv = svname;
5879 else SUMA_ifree(svname);
5880 if (pdsname) *pdsname = sname;
5881 else SUMA_ifree(sname);
5882
5883 SUMA_RETURN(tp);
5884 }
5885
5886 #define SUMA_CHECK_INPUT_SURF(name, topo, ok) { \
5887 ok = 0; \
5888 if (SUMA_is_predefined_SO_name(name, NULL, NULL, NULL, NULL)) {\
5889 ok = 1; \
5890 } else if (SUMA_filexists(name)) { \
5891 if (!(topo)) { ok = 1; } \
5892 else { if (SUMA_filexists(topo)) {ok = 1;} } \
5893 } \
5894 if (!ok) { \
5895 if (topo) { \
5896 fprintf(SUMA_STDERR,"Error %s:\nCould not locate surface %s %s\n", FuncName, name, topo); \
5897 } else { \
5898 fprintf(SUMA_STDERR,"Error %s:\nCould not locate surface %s \n", FuncName, name); \
5899 } \
5900 } \
5901 }
5902
5903 #define SUMA_BLANK_NEW_SPEC_SURF(spec) {\
5904 spec->IDcode[spec->N_Surfs]= NULL; \
5905 spec->SurfaceLabel[spec->N_Surfs][0] = '\0'; \
5906 spec->EmbedDim[spec->N_Surfs] = 3; \
5907 strcpy(spec->AnatCorrect[spec->N_Surfs], "Y"); \
5908 spec->Hemisphere[spec->N_Surfs][0] = '\0'; \
5909 spec->DomainGrandParentID[spec->N_Surfs][0] = '\0'; \
5910 strcpy(spec->LocalDomainParent[spec->N_Surfs],"SAME"); \
5911 spec->LocalCurvatureParent[spec->N_Surfs][0] = '\0'; \
5912 spec->OriginatorID[spec->N_Surfs][0] = '\0'; \
5913 }
5914
SUMA_Show_IO_args(SUMA_GENERIC_ARGV_PARSE * ps)5915 void SUMA_Show_IO_args(SUMA_GENERIC_ARGV_PARSE *ps)
5916 {
5917 static char FuncName[]={"SUMA_Show_IO_args"};
5918 int i;
5919
5920 SUMA_ENTRY;
5921
5922 if (!ps) { fprintf(SUMA_STDERR,"NULL ps\n"); SUMA_RETURNe; }
5923
5924 fprintf(SUMA_STDERR,"%saccepting -t* options\n",
5925 ps->accept_t ? "":"not");
5926 fprintf(SUMA_STDERR,"%saccepting -surf_* options\n",
5927 ps->accept_s ? "":"not");
5928 fprintf(SUMA_STDERR,"%saccepting -i_* options\n",
5929 ps->accept_i ? "":"not");
5930 fprintf(SUMA_STDERR,"%saccepting -ipar_* options\n",
5931 ps->accept_ipar ? "":"not");
5932 fprintf(SUMA_STDERR,"%saccepting -o_* options\n",
5933 ps->accept_o ? "":"not");
5934 fprintf(SUMA_STDERR,"%saccepting -spec option\n",
5935 ps->accept_spec ? "":"not");
5936 fprintf(SUMA_STDERR,"%saccepting -sv option\n",
5937 ps->accept_sv ? "":"not");
5938 fprintf(SUMA_STDERR,"%saccepting -talk_suma options\n",
5939 ps->accept_talk_suma ? "":"not");
5940 fprintf(SUMA_STDERR,"%saccepting -mask options\n",
5941 ps->accept_mask ? "":"not");
5942 fprintf(SUMA_STDERR,"%saccepting -cmap options\n",
5943 ps->accept_cmap ? "":"not");
5944 fprintf(SUMA_STDERR,"%saccepting -dset options\n",
5945 ps->accept_dset ? "":"not");
5946 fprintf(SUMA_STDERR,
5947 "Check for input surface files: %d\n", ps->check_input_surf);
5948 fprintf(SUMA_STDERR,"%d sv:\n", ps->N_sv);
5949 if (ps->N_sv) {
5950 for (i=0; i<ps->N_sv; ++i) {
5951 fprintf(SUMA_STDERR," %d: %s\n", i, ps->sv[i]);
5952 }
5953 }
5954 fprintf(SUMA_STDERR,"%d vp:\n", ps->N_vp);
5955 if (ps->N_vp) {
5956 for (i=0; i<ps->N_vp; ++i) {
5957 fprintf(SUMA_STDERR," %d: %s\n", i, ps->vp[i]);
5958 }
5959 }
5960 fprintf(SUMA_STDERR,"bmaskname: %s\n", CHECK_NULL_STR(ps->bmaskname));
5961 fprintf(SUMA_STDERR,"nmaskname: %s\n", CHECK_NULL_STR(ps->nmaskname));
5962 fprintf(SUMA_STDERR,"cmask: %s\n", CHECK_NULL_STR(ps->cmask));
5963
5964 fprintf(SUMA_STDERR,"%d spec names:\n", ps->N_spec_names);
5965 for (i=0; i<ps->N_spec_names; ++i) {
5966 fprintf(SUMA_STDERR," %d: %s\n", i, ps->spec_names[i]);
5967 }
5968 fprintf(SUMA_STDERR,"%d s_surfnames from %s\n",
5969 ps->s_N_surfnames, ps->spec_names[0]);
5970 for (i=0; i<ps->s_N_surfnames; ++i) {
5971 fprintf(SUMA_STDERR," %d: %s\n", i, ps->s_surfnames[i]);
5972 }
5973 fprintf(SUMA_STDERR,"%d i_surfnames\n", ps->i_N_surfnames);
5974 for (i=0; i<ps->i_N_surfnames; ++i) {
5975 if (ps->i_surftopo[i])
5976 fprintf(SUMA_STDERR,
5977 " %d: %s %s %s %s\n",
5978 i, ps->i_group[i], ps->i_state[i],
5979 ps->i_surfnames[i], ps->i_surftopo[i]);
5980 else fprintf(SUMA_STDERR,
5981 " %d: %s %s %s\n",
5982 i, ps->i_group[i], ps->i_state[i],ps->i_surfnames[i]);
5983 }
5984 fprintf(SUMA_STDERR,"%d ipar_surfnames\n", ps->ipar_N_surfnames);
5985 for (i=0; i<ps->ipar_N_surfnames; ++i) {
5986 if (ps->ipar_surftopo[i])
5987 fprintf(SUMA_STDERR,
5988 " %d: %s %s %s %s\n",
5989 i, ps->ipar_group[i], ps->ipar_state[i],
5990 ps->ipar_surfnames[i], ps->ipar_surftopo[i]);
5991 else fprintf(SUMA_STDERR,
5992 " %d: %s %s %s\n",
5993 i, ps->ipar_group[i], ps->ipar_state[i],
5994 ps->ipar_surfnames[i]);
5995 }
5996 fprintf(SUMA_STDERR,"%d o_surfnames\n", ps->o_N_surfnames);
5997 for (i=0; i<ps->o_N_surfnames; ++i) {
5998 if (ps->o_surftopo[i])
5999 fprintf(SUMA_STDERR,
6000 " %d: %s %s %s %s\n",
6001 i, ps->o_group[i], ps->o_state[i],
6002 ps->o_surfnames[i], ps->o_surftopo[i]);
6003 else fprintf(SUMA_STDERR,
6004 " %d: %s %s %s\n",
6005 i, ps->o_group[i], ps->o_state[i], ps->o_surfnames[i]);
6006 }
6007 fprintf(SUMA_STDERR,"%d t_surfnames\n", ps->t_N_surfnames);
6008 for (i=0; i<ps->t_N_surfnames; ++i) {
6009 if (ps->t_surftopo[i])
6010 fprintf(SUMA_STDERR,
6011 " %d: %s %s %s %s\n",
6012 i, ps->o_group[i], ps->t_state[i],
6013 ps->t_surfnames[i], ps->t_surftopo[i]);
6014 else fprintf(SUMA_STDERR,
6015 " %d: %s %s %s\n",
6016 i, ps->o_group[i], ps->t_state[i], ps->t_surfnames[i]);
6017 }
6018
6019 if (ps->accept_talk_suma) {
6020 if (!ps->cs) {
6021 fprintf(SUMA_STDERR,"No Talking to SUMA requested\n");
6022 } else {
6023 fprintf(SUMA_STDERR,"Talking to SUMA requested.\n");
6024 }
6025 }
6026 fprintf( SUMA_STDERR,
6027 "%d arguments on command line (+checked, -not checked):\n"
6028 , ps->N_args);
6029 for (i=0; i<ps->N_args; ++i) {
6030 if (ps->arg_checked[i])
6031 fprintf(SUMA_STDERR,
6032 " %d+ ",i);
6033 else fprintf(SUMA_STDERR," %d- ",i);
6034 }
6035 fprintf(SUMA_STDERR,"\n");
6036
6037 SUMA_RETURNe;
6038 }
6039
6040 /*!
6041 Take a vector of independent surfaces and get a Spec file that goes
6042 with them
6043 */
SUMA_SOGroup_2_Spec(SUMA_SurfaceObject ** SOv,int N_SOv)6044 SUMA_SurfSpecFile *SUMA_SOGroup_2_Spec(SUMA_SurfaceObject **SOv, int N_SOv)
6045 {
6046 static char FuncName[]={"SUMA_SOGroup_2_Spec"};
6047 SUMA_SurfSpecFile *spec = NULL;
6048 int i, nspec;
6049 char si[100];
6050 SUMA_GENERIC_ARGV_PARSE *ps=NULL;
6051 SUMA_Boolean LocalHead = NOPE;
6052
6053 SUMA_ENTRY;
6054
6055 ps = SUMA_CreateGenericArgParse("-i;");
6056 ps->check_input_surf = 0;
6057 ps->i_N_surfnames = N_SOv;
6058 for (i=0; i<ps->i_N_surfnames; ++i) {
6059 sprintf(si, "s_%d\n", i);
6060 if (SOv[i]->Label) ps->i_surfnames[i] = SUMA_copy_string(SOv[i]->Label);
6061 else ps->i_surfnames[i] = SUMA_copy_string(si);
6062 if (SOv[i]->State) ps->i_state[i] = SUMA_copy_string(SOv[i]->State);
6063 if (SOv[i]->Group) ps->i_group[i] = SUMA_copy_string(SOv[i]->Group);
6064 ps->i_FT[i] = SUMA_FT_NOT_SPECIFIED; ps->i_FF[i] = SUMA_FF_NOT_SPECIFIED;
6065 }
6066
6067 spec = SUMA_IO_args_2_spec(ps, &nspec);
6068 if (nspec != 1) {
6069 SUMA_S_Err( "Expecting one spec struct here!\n"
6070 "Trouble might befall you ahead.");
6071 }
6072 SUMA_FreeGenericArgParse(ps); ps = NULL;
6073
6074 SUMA_RETURN(spec);
6075 }
6076
SUMA_IO_args_2_spec(SUMA_GENERIC_ARGV_PARSE * ps,int * nspec)6077 SUMA_SurfSpecFile *SUMA_IO_args_2_spec(SUMA_GENERIC_ARGV_PARSE *ps, int *nspec)
6078 {
6079 static char FuncName[]={"SUMA_IO_args_2_spec"};
6080 int i=0, ispec0;
6081 byte ok;
6082 char sbuf[SUMA_MAX_LABEL_LENGTH+1];
6083 static char defgroup[]={SUMA_DEF_GROUP_NAME};
6084 SUMA_SurfSpecFile *spec = NULL;
6085 SUMA_Boolean LocalHead = NOPE;
6086
6087 SUMA_ENTRY;
6088
6089
6090 /* first look for virtual spec */
6091 *nspec = 1;
6092 spec = (SUMA_SurfSpecFile *)SUMA_malloc(sizeof(SUMA_SurfSpecFile));
6093 /* initialize the spec ZSS Jan 9 06*/
6094 if (!SUMA_AllocSpecFields(spec)) {
6095 SUMA_S_Err("Failed to initialize spec\n" );
6096 SUMA_RETURN(NULL);
6097 }
6098
6099 spec->N_Surfs = 0;
6100 spec->N_States = 0;
6101 spec->N_DO = 0;
6102 spec->N_Groups = 1;
6103 strcpy(spec->SpecFilePath, "./");
6104 strcpy(spec->SpecFileName, "FromCommandLine.spec");
6105 SUMA_LHv("Accept_do: %d, %d DOs\n", ps->accept_do, ps->N_DO);
6106 if (ps->accept_do) {
6107 SUMA_LH("Processing -tract/-graph/-vol");
6108 if (ps->N_DO+spec->N_DO >= SUMA_MAX_N_DO_SPEC) {
6109 SUMA_S_Err("Too many DOs to work with.\n");
6110 *nspec = 0; SUMA_RETURN(spec);
6111 }
6112 for (i=0; i<ps->N_DO; ++i) {
6113 spec->DO_type[spec->N_DO] = ps->DO_type[i];
6114 strcpy(spec->DO_name[spec->N_DO], ps->DO_name[i]);
6115 ++spec->N_DO;
6116 }
6117 }
6118
6119 if (ps->accept_i) {
6120 SUMA_LH("Processing -i");
6121 if (ps->i_N_surfnames+spec->N_Surfs >= SUMA_MAX_N_SURFACE_SPEC) {
6122 SUMA_S_Err("Too many surfaces to work with.\n");
6123 *nspec = 0; SUMA_RETURN(spec);
6124 }
6125 for (i=0; i<ps->i_N_surfnames; ++i) {
6126 if (ps->check_input_surf) {
6127 SUMA_CHECK_INPUT_SURF(ps->i_surfnames[i], ps->i_surftopo[i], ok);
6128 if (!ok) {
6129 SUMA_free(spec); spec = NULL; *nspec = 0; SUMA_RETURN(spec);
6130 }
6131 }
6132 strcpy( spec->SurfaceType[spec->N_Surfs],
6133 SUMA_SurfaceTypeString (ps->i_FT[i]));
6134 if ( ps->i_FF[i] == SUMA_BINARY ||
6135 ps->i_FF[i] == SUMA_BINARY_LE ||
6136 ps->i_FF[i] == SUMA_BINARY_BE)
6137 strcpy(spec->SurfaceFormat[spec->N_Surfs], "BINARY");
6138 else if (ps->i_FF[i] == SUMA_XML_SURF ||
6139 ps->i_FF[i] == SUMA_XML_ASCII_SURF ||
6140 ps->i_FF[i] == SUMA_XML_B64_SURF ||
6141 ps->i_FF[i] == SUMA_XML_B64GZ_SURF )
6142 strcpy(spec->SurfaceFormat[spec->N_Surfs], "XML");
6143 else strcpy(spec->SurfaceFormat[spec->N_Surfs], "ASCII");
6144 if (ps->i_FT[i] == SUMA_SUREFIT || ps->i_FT[i] == SUMA_VEC) {
6145 strcpy(spec->TopoFile[spec->N_Surfs], ps->i_surftopo[i]);
6146 strcpy(spec->CoordFile[spec->N_Surfs], ps->i_surfnames[i]);
6147 if (ps->vp[i])
6148 strcpy(spec->SureFitVolParam[spec->N_Surfs], ps->vp[i]);
6149 } else {
6150 strcpy(spec->SurfaceFile[spec->N_Surfs], ps->i_surfnames[i]);
6151 }
6152 if (ps->sv[i])
6153 strcpy(spec->VolParName[spec->N_Surfs], ps->sv[i]);
6154 else spec->VolParName[spec->N_Surfs][0] = '\0';
6155 if (ps->i_state[i]) {
6156 strcpy(spec->State[spec->N_Surfs], ps->i_state[i]);
6157 ++spec->N_States;
6158 } else {
6159 if (!ps->onestate) {
6160 sprintf(spec->State[spec->N_Surfs], "iS_%d", spec->N_States);
6161 ++spec->N_States;
6162 } else {
6163 sprintf(spec->State[spec->N_Surfs], "iS");
6164 spec->N_States = 1;
6165 }
6166 }
6167 if (ps->anatomical == 1) sprintf(spec->AnatCorrect[spec->N_Surfs],"Y");
6168 else if (ps->anatomical == -1)
6169 sprintf(spec->AnatCorrect[spec->N_Surfs],"N");
6170 if (ps->i_group[i]) {
6171 strcpy(spec->Group[spec->N_Surfs], ps->i_group[i]);
6172 } else { strcpy(spec->Group[spec->N_Surfs], defgroup); }
6173 SUMA_BLANK_NEW_SPEC_SURF(spec);
6174 ++spec->N_Surfs;
6175 }
6176 }
6177
6178 if (ps->accept_ipar) {
6179 SUMA_LH("Processing -ipar");
6180 if (ps->ipar_N_surfnames+spec->N_Surfs >= SUMA_MAX_N_SURFACE_SPEC) {
6181 SUMA_S_Err("Too many surfaces to work with.\n");
6182 *nspec = 0;
6183 SUMA_RETURN(spec);
6184 }
6185 for (i=0; i<ps->ipar_N_surfnames; ++i) {
6186 if (ps->check_input_surf) {
6187 SUMA_CHECK_INPUT_SURF( ps->ipar_surfnames[i],
6188 ps->ipar_surftopo[i], ok);
6189 if (!ok) {
6190 SUMA_free(spec); spec = NULL; *nspec = 0; SUMA_RETURN(spec);
6191 }
6192 }
6193 strcpy( spec->SurfaceType[spec->N_Surfs],
6194 SUMA_SurfaceTypeString (ps->ipar_FT[i]));
6195 if ( ps->ipar_FF[i] == SUMA_BINARY || ps->ipar_FF[i] == SUMA_BINARY_LE
6196 || ps->ipar_FF[i] == SUMA_BINARY_BE)
6197 strcpy(spec->SurfaceFormat[spec->N_Surfs], "BINARY");
6198 else if (ps->ipar_FF[i] == SUMA_XML_SURF ||
6199 ps->ipar_FF[i] == SUMA_XML_ASCII_SURF ||
6200 ps->ipar_FF[i] == SUMA_XML_B64_SURF ||
6201 ps->ipar_FF[i] == SUMA_XML_B64GZ_SURF )
6202 strcpy(spec->SurfaceFormat[spec->N_Surfs], "XML");
6203 else strcpy(spec->SurfaceFormat[spec->N_Surfs], "ASCII");
6204 if (ps->ipar_FT[i] == SUMA_SUREFIT || ps->ipar_FT[i] == SUMA_VEC) {
6205 strcpy(spec->TopoFile[spec->N_Surfs], ps->ipar_surftopo[i]);
6206 strcpy(spec->CoordFile[spec->N_Surfs], ps->ipar_surfnames[i]);
6207 if (ps->vp[i])
6208 strcpy(spec->SureFitVolParam[spec->N_Surfs], ps->vp[i]);
6209 } else {
6210 strcpy(spec->SurfaceFile[spec->N_Surfs], ps->ipar_surfnames[i]);
6211 }
6212 if (ps->sv[i])
6213 strcpy(spec->VolParName[spec->N_Surfs], ps->sv[i]);
6214 else spec->VolParName[spec->N_Surfs][0] = '\0';
6215 if (ps->ipar_state[i]) {
6216 strcpy(spec->State[spec->N_Surfs], ps->ipar_state[i]);
6217 ++spec->N_States;
6218 } else {
6219 sprintf(spec->State[spec->N_Surfs], "iS_%d", spec->N_States);
6220 ++spec->N_States;
6221 }
6222 if (ps->ipar_group[i]) {
6223 strcpy(spec->Group[spec->N_Surfs], ps->ipar_group[i]);
6224 } else { strcpy(spec->Group[spec->N_Surfs], defgroup); }
6225 SUMA_BLANK_NEW_SPEC_SURF(spec);
6226 ++spec->N_Surfs;
6227 }
6228 }
6229
6230 if (ps->accept_t) {
6231 SUMA_LH("Processing -t");
6232 if (ps->t_N_surfnames+spec->N_Surfs >= SUMA_MAX_N_SURFACE_SPEC) {
6233 SUMA_S_Err("Too many surfaces to work with.\n");
6234 *nspec = 0;
6235 SUMA_RETURN(spec);
6236 }
6237 for (i=0; i<ps->t_N_surfnames; ++i) {
6238 if (ps->check_input_surf) {
6239 SUMA_CHECK_INPUT_SURF(ps->t_surfnames[i], ps->t_surftopo[i], ok);
6240 if (!ok) {
6241 SUMA_free(spec); spec = NULL; *nspec = 0;
6242 SUMA_RETURN(spec);
6243 }
6244 }
6245 strcpy( spec->SurfaceType[spec->N_Surfs],
6246 SUMA_SurfaceTypeString (ps->t_FT[i]));
6247 if ( ps->t_FF[i] == SUMA_BINARY || ps->t_FF[i] == SUMA_BINARY_LE
6248 || ps->t_FF[i] == SUMA_BINARY_BE)
6249 strcpy(spec->SurfaceFormat[spec->N_Surfs], "BINARY");
6250 else if (ps->t_FF[i] == SUMA_XML_SURF ||
6251 ps->t_FF[i] == SUMA_XML_ASCII_SURF ||
6252 ps->t_FF[i] == SUMA_XML_B64_SURF ||
6253 ps->t_FF[i] == SUMA_XML_B64GZ_SURF )
6254 strcpy(spec->SurfaceFormat[spec->N_Surfs], "XML");
6255 else strcpy(spec->SurfaceFormat[spec->N_Surfs], "ASCII");
6256 if (ps->t_FT[i] == SUMA_SUREFIT || ps->t_FT[i] == SUMA_VEC) {
6257 strcpy(spec->TopoFile[spec->N_Surfs], ps->t_surftopo[i]);
6258 strcpy(spec->CoordFile[spec->N_Surfs], ps->t_surfnames[i]);
6259 if (ps->vp[i])
6260 strcpy(spec->SureFitVolParam[spec->N_Surfs], ps->vp[i]);
6261 } else {
6262 strcpy(spec->SurfaceFile[spec->N_Surfs], ps->t_surfnames[i]);
6263 }
6264 if (ps->sv[i]) strcpy(spec->VolParName[spec->N_Surfs], ps->sv[i]);
6265 else spec->VolParName[spec->N_Surfs][0] = '\0';
6266 if (ps->t_state[i]) {
6267 strcpy(spec->State[spec->N_Surfs], ps->t_state[i]);
6268 ++spec->N_States;
6269 } else {
6270 sprintf(spec->State[spec->N_Surfs], "iS_%d", spec->N_States);
6271 ++spec->N_States;
6272 }
6273 if (ps->anatomical == 1) sprintf(spec->AnatCorrect[spec->N_Surfs],"Y");
6274 else if (ps->anatomical == -1)
6275 sprintf(spec->AnatCorrect[spec->N_Surfs],"N");
6276 if (ps->t_group[i]) {
6277 strcpy(spec->Group[spec->N_Surfs], ps->t_group[i]);
6278 } else { strcpy(spec->Group[spec->N_Surfs], defgroup); }
6279 SUMA_BLANK_NEW_SPEC_SURF(spec);
6280 ++spec->N_Surfs;
6281 }
6282 }
6283
6284 SUMA_LH("Working States");
6285
6286 /* now create the states list */
6287 if (spec->N_Surfs || spec->N_DO) {
6288 if (spec->N_Surfs) {
6289 spec->N_States = 1;
6290 sprintf(spec->StateList, "%s|", spec->State[0]);
6291 for (i=1; i<spec->N_Surfs; ++i) {
6292 sprintf(sbuf,"%s|",spec->State[i]);
6293 if (!SUMA_iswordin(spec->StateList, sbuf)) {
6294 sprintf(spec->StateList, "%s|", spec->State[i]);
6295 ++spec->N_States;
6296 }
6297 }
6298 if (LocalHead)
6299 fprintf( SUMA_STDERR,"%s:\n%d distinct states\n%s\n",
6300 FuncName, spec->N_States, spec->StateList);
6301 }
6302
6303 if (spec->N_DO) {
6304 spec->N_States = 1;
6305 sprintf(spec->StateList, "ANY|");
6306 }
6307
6308 if (spec->Group[0][0] == '\0') {
6309 /* Perhaps only DOs loaded, label the group */
6310 strcpy(spec->Group[0], "ANY");
6311 }
6312
6313 ispec0 = *nspec;
6314 } else {
6315 if (LocalHead) fprintf(SUMA_STDERR,"%s:\n no surfs\n", FuncName);
6316 /* free Spec */
6317 {
6318 int k=0;
6319 for (k=0; k<*nspec; ++k) {
6320 if (!SUMA_FreeSpecFields(&(spec[k]))) {
6321 SUMA_S_Err("Failed to free spec fields");
6322 }
6323 }
6324 }
6325 SUMA_free(spec); spec = NULL; *nspec = 0; ispec0 = 0;
6326 }
6327
6328 /* Now see if you have explicity define specs on command line */
6329 if (ps->accept_spec || ps->accept_s) {
6330 SUMA_LHv("Working Specs, %d %d\n"
6331 "ispec0 = %d, ps->N_spec_names = %d\n"
6332 "i=%d\n",
6333 ps->accept_spec, ps->accept_s,
6334 ispec0, ps->N_spec_names,
6335 i);
6336 if (ps->N_spec_names) {
6337 *nspec = ispec0 + ps->N_spec_names;
6338 spec = (SUMA_SurfSpecFile *)
6339 SUMA_realloc( spec,
6340 *nspec * sizeof(SUMA_SurfSpecFile));
6341 SUMA_LH("Here");
6342 for (i=0; i<ps->N_spec_names; ++i) {
6343 if (!SUMA_AllocSpecFields(&(spec[i+ispec0]))) {
6344 SUMA_S_Err("Failed to init spec fields");
6345 }
6346 if (!SUMA_Read_SpecFile (ps->spec_names[i], &(spec[i+ispec0]))) {
6347 SUMA_SL_Err("Failed to read SpecFile");
6348 {
6349 int k=0;
6350 for (k=0; k<*nspec; ++k) {
6351 if (!SUMA_FreeSpecFields(&(spec[k]))) {
6352 SUMA_S_Err("Failed to free spec fields");
6353 }
6354 }
6355 }
6356 SUMA_free(spec); spec = NULL; *nspec = 0;
6357 SUMA_RETURN(spec);
6358 }
6359 }
6360 /* do we have a set of surfaces to read here ?
6361 only works with one spec */
6362 SUMA_LHv("Have %d surf_\n",ps->s_N_surfnames);
6363 if (ps->s_N_surfnames) {
6364 int n_read;
6365 if (ps->N_spec_names > 1) {
6366 SUMA_S_Err( "Cannot deal with multiple -spec on \n"
6367 "command line combined with -surf_ selectors.");
6368 {
6369 int k=0;
6370 for (k=0; k<*nspec; ++k) {
6371 if (!SUMA_FreeSpecFields(&(spec[k]))) {
6372 SUMA_S_Err("Failed to free spec fields");
6373 }
6374 }
6375 }
6376 SUMA_free(spec); spec = NULL; *nspec = 0;
6377 SUMA_RETURN(spec);
6378 }
6379 /* purify the spec */
6380 n_read = SUMA_spec_select_surfs( &(spec[0+ispec0]),
6381 ps->s_surfnames,
6382 ps->s_N_surfnames, LocalHead);
6383 if (n_read < 1) {
6384 SUMA_S_Err("Failed to find surfaces in spec file");
6385 SUMA_free(spec); spec = NULL; *nspec = 0;
6386 SUMA_RETURN(spec);
6387 }
6388 if (LocalHead) {
6389 fprintf( SUMA_STDERR,
6390 "%s (%s:%d): Selected in %d surfaces\n",
6391 FuncName, __FILE__, __LINE__, n_read);
6392 }
6393 }
6394
6395 }
6396 }
6397
6398 if (LocalHead) {
6399 fprintf( SUMA_STDERR,
6400 "%s: About to return, have %d spec files.\n", FuncName, *nspec);
6401 }
6402 SUMA_RETURN(spec);
6403 }
6404
6405 /*
6406 Current state of loading CIFTI
6407
6408 Load dset,
6409 Prep domains
6410 Breakup dset into parts and load them individually onto their respective domains
6411 need some sort of unifying 'yoking' marker for dsets, domains, and overlays so that when user touches them it is known that user is dealing with CIFTI object
6412
6413 Yoking can be done much like how left/right yoking in suma is handled, except there should be no guess work involved.
6414
6415 Note that 'what' the user clicked on involve knowing the domain overwhich they clicked in conjunction with the data displayed on that domain. -- do we need this distinction?
6416 */
SUMA_LoadCIFTIDO(char * fname,SUMA_DO_CoordUnits coord_type,SUMA_DSET ** odset,int OkAdopt,int SetupOverlay,int LaunchDisplay,int MakeOverlayCurrent,SUMA_OVERLAYS ** used_over)6417 SUMA_Boolean SUMA_LoadCIFTIDO (char *fname,
6418 SUMA_DO_CoordUnits coord_type, SUMA_DSET **odset,
6419 int OkAdopt, int SetupOverlay, int LaunchDisplay,
6420 int MakeOverlayCurrent, SUMA_OVERLAYS **used_over)
6421 {
6422 static char FuncName[]={"SUMA_LoadCIFTIDO"};
6423 SUMA_CIFTI_SAUX *CSaux=NULL;
6424 SUMA_DSET *cdset=NULL, *sddset=NULL;
6425 SUMA_CIFTI_DO *CO = NULL;
6426 SUMA_ALL_DO *asdo = NULL;
6427 SUMA_DSET_FORMAT tff = SUMA_NIML;
6428 DList *list=NULL;
6429 SUMA_LIST_WIDGET *LW=NULL;
6430 SUMA_DSET *dsetpre = NULL;
6431 SUMA_OVERLAYS *NewColPlane = NULL, *colplanepre = NULL;
6432 int OverInd=-1, OKdup=-1, loc[2], pre_exist=0, isd=0;
6433 char *dsetcmap=NULL;
6434 SUMA_X_SurfCont *SurfCont=NULL;
6435 SUMA_Boolean LocalHead = NOPE;
6436
6437 SUMA_ENTRY;
6438
6439 if (!fname) SUMA_RETURN(NOPE);
6440 /* same value, but SUMA_WORLD should prob be _UNIT [22 Jun 2021 rickr] */
6441 if (coord_type != SUMA_NORM_SCREEN_UNIT &&
6442 coord_type != SUMA_WORLD_UNIT) coord_type = SUMA_WORLD_UNIT;
6443
6444 if (!(cdset = SUMA_LoadDset_eng( fname, &tff, 1 ))) {
6445 SUMA_S_Errv("Failed to open %s\n", fname);
6446 SUMA_free(fname); fname = NULL;
6447 SUMA_RETURN(NOPE);
6448 }
6449
6450 if (!SUMA_isCIFTIDsetNgr(cdset->ngr)) {
6451 SUMA_S_Err("All is bad that starts bad, or is it?\nNot a CIFTIcle.");
6452 SUMA_RETURN(NOPE);
6453 }
6454
6455 /* Swaps ?*/
6456 if (odset) {
6457 if (*odset == NULL) {
6458 *odset = cdset;
6459 } else {
6460 /* Replace any existing parts of *odset, with those from cdset */
6461 if (!SUMA_FreeDsetContent(*odset)) {
6462 SUMA_S_Err("Failed to free dset content");
6463 SUMA_RETURN(NOPE);
6464 }
6465 (*odset)->ngr = cdset->ngr; cdset->ngr = NULL;
6466 SUMA_FreeDset(cdset);
6467 cdset = *odset;
6468 }
6469 }
6470
6471 /* Does this dset have a built in colormap?
6472 If it does, then loadit into SCM */
6473 if (!SUMA_Insert_Cmap_of_Dset(cdset)) {
6474 SUMA_S_Err("Failed to insert Cmap");
6475 SUMA_FreeDset(cdset); cdset = NULL;
6476
6477 SUMA_RETURN(NOPE);
6478 }
6479
6480
6481 /* Get domains info from Ngr and create elementary dsets*/
6482 if (!(SUMA_CIFTI_DomainsFromNgr( cdset, SUMAg_CF->DsetList,
6483 SUMAg_CF->Allow_Dset_Replace, NULL))) {
6484 SUMA_S_Err("Failed to get domains from Ngr");
6485 SUMA_FreeDset(cdset);
6486 SUMA_RETURN(NOPE);
6487 }
6488
6489 /* Can we pile onto an existing domain? (think multiple
6490 datasets over the same surface) */
6491
6492 CO = NULL;
6493 if (OkAdopt && (CO = SUMA_CIFTI_find_matching_domain(cdset, NULL, -1))) {
6494 SUMA_LH("Adopting CO");
6495 } else {
6496 SUMA_LH("Create CO from cdset");
6497 if (!(CO=SUMA_CIFTI_DO_from_dset(cdset))) {
6498 SUMA_S_Err("Failed to create DO from dset");
6499 SUMA_FreeDset(cdset);
6500 SUMA_RETURN(NOPE);
6501 }
6502 }
6503
6504 SUMA_LH("Do we really need a separate controller for CIFTI?"
6505 "Leave it for now, kill CSaux later if we stick with"
6506 "current setup...");
6507 if (!(CSaux = CDO_CSAUX(CO))) {
6508 SUMA_S_Warn("That is weird, should this happen?");
6509 if (!SUMA_AddCIFTISaux(CO)) {
6510 SUMA_S_Err("Failed to create Saux struct");
6511 SUMA_RETURN(NOPE);
6512 }
6513 CSaux = CDO_CSAUX(CO);
6514 }
6515
6516 /* add the dset to the list SUMAg_CF->DsetList, the elementary datasets were
6517 added inside SUMA_CIFTI_DomainsFromNgr */
6518 dsetpre = cdset;
6519 if (LocalHead) {
6520 fprintf( SUMA_STDERR,
6521 "%s: New dset (%s) has pointer %p\n",
6522 FuncName, SDSET_LABEL(cdset), cdset);
6523 }
6524 if (!SUMA_InsertDsetPointer( &cdset, SUMAg_CF->DsetList,
6525 SUMAg_CF->Allow_Dset_Replace)) {
6526 SUMA_SLP_Err("Failed to add new dset to list");
6527 /* is there not a function to replace a dset yet? */
6528 SUMA_FreeDset(cdset); cdset = NULL;
6529 SUMA_RETURN(NOPE);
6530 }
6531 if (LocalHead) {
6532 fprintf( SUMA_STDERR,
6533 "%s: Now dset (%s) is pointer %p\n",
6534 FuncName, SDSET_LABEL(cdset), cdset);
6535 }
6536
6537 /*
6538 Note that there is currently no solid way
6539 of attaching a dataset to a displayable object.
6540 That has not been needed so far. There is a meek
6541 attempt to do something with SUMA_SetParent_DsetToLoad()
6542 but only for surface-based datasets, and ONLY for generating
6543 an ID that is based on a combo of filename and parent surface.
6544
6545 Should we need to find the DO that defines the domain of
6546 a particular CIFTI dataset, we might need to write a function
6547 to search which CDOM_type object contains an overlay for the
6548 dataset in question.
6549 */
6550
6551 /* There is no one overlay a CIFTI dataset (or should there be a shell
6552 overlay at some point that mereley points to each of the subdomains?
6553 I don't know if that is needed yet. For now I will create a separate
6554 overlay for each of the elementary datasets */
6555 if (SetupOverlay) {
6556 if (cdset != dsetpre) { /* dset was pre-existing in the list */
6557 pre_exist = 1;
6558 } else pre_exist = 0;
6559
6560
6561 SUMA_LH("Setting up overlay for %d CIFTI elmentary datasets",
6562 cdset->Aux->N_doms);
6563
6564 for (isd=0; isd<cdset->Aux->N_doms; ++isd) {
6565 OverInd = -1;
6566 {
6567 asdo = SUMA_CIFTI_subdom_ado(CO, isd);
6568 if (!(sddset = DSET_FIND(cdset->Aux->doms[isd]->edset_id))) {
6569 SUMA_S_Err("Should have found that dset (id %s), "
6570 "returning with potential leaks!",
6571 cdset->Aux->doms[isd]->edset_id);
6572 SUMA_RETURN(NOPE);
6573 }
6574 if (pre_exist) { /* Parent dset was pre-existing in the list,
6575 assuming the
6576 same for all elementrary datasets */
6577 if (LocalHead) {
6578 fprintf( SUMA_STDERR,
6579 "%s: assuming dset %s (%dth from %s) (%p) pre-existing, "
6580 "finding its pre-existing overlays.\n",
6581 FuncName, SDSET_LABEL(sddset), isd,
6582 SDSET_LABEL(cdset), sddset);
6583 }
6584 if (!(colplanepre = SUMA_Fetch_OverlayPointerByDset (
6585 asdo, sddset, &OverInd))) {
6586 SUMA_SLP_Err("Failed to fetch existing dset's "
6587 "overlay pointer");
6588 SUMA_RETURN(NOPE);
6589 }
6590 /* Here you'd remove coord bias if you end up using it */
6591 /* and set flag to recompute clusters if you support clustering */
6592 OKdup = 1;
6593 } else { /* cdset and therefore its babies are considered new */
6594 SUMA_LH("New overlay for %s", SDSET_LABEL(sddset));
6595 colplanepre = NULL;
6596 /* The overlay index for that plane is SO->N_Overlays */
6597 OverInd = SUMA_ADO_N_Overlays(asdo);
6598 OKdup = 0;
6599 }
6600
6601 /* set up the colormap for this dset */
6602 if (!(NewColPlane = SUMA_CreateOverlayPointer ( SDSET_FILENAME(sddset),
6603 sddset, ADO_ID(asdo),
6604 colplanepre))) {
6605 SUMA_S_Err("Failed in SUMA_CreateOverlayPointer for %s\n",
6606 SDSET_LABEL(sddset));
6607 SUMA_RETURN(NOPE);
6608 }
6609
6610 if (SetupOverlay < 0) {
6611 SUMA_LH("Have not pondered how to do 'background' for the "
6612 "volume part of a CIFTI domain...");
6613 NewColPlane->isBackGrnd = YUP;
6614 } else NewColPlane->isBackGrnd = NOPE;
6615
6616 /* Add this plane to Overlays */
6617 SUMA_LH("Adding new plane to Overlays");
6618 if (!SUMA_AddNewPlane (asdo, NewColPlane, SUMAg_DOv,
6619 SUMAg_N_DOv, OKdup)) {
6620 SUMA_SL_Err("Failed in SUMA_AddNewPlane");
6621 SUMA_FreeOverlayPointer(NewColPlane);
6622 SUMA_S_Warn("Usually I would delete loaded dset, "
6623 "but here I would have to delete elementary beasts "
6624 "also. Leaving it out for now");
6625
6626 SUMA_RETURN(NOPE);
6627 }
6628 }
6629
6630 /* Match old settings? */
6631 SUMA_LH("Settings");
6632 if (colplanepre == NewColPlane) { /* old col plane found for this dset*/
6633 /* Don't change settings. Before Aug 2012, it would reset as below */
6634 } else if ((SurfCont = SUMA_ADO_Cont(asdo)) &&
6635 SUMA_PreserveOverlaySettings(SurfCont->curColPlane,
6636 NewColPlane)) {
6637 /* attempt to preserve current situation */
6638 SUMA_OVERLAYS *settingPlane = NULL;
6639 settingPlane = SurfCont->curColPlane;
6640 NewColPlane->GlobalOpacity = settingPlane->GlobalOpacity;
6641 NewColPlane->ShowMode = settingPlane->ShowMode;
6642 NewColPlane->OptScl->BrightFact = settingPlane->OptScl->BrightFact;
6643 NewColPlane->OptScl->find = settingPlane->OptScl->find;
6644 NewColPlane->OptScl->tind = settingPlane->OptScl->tind;
6645 NewColPlane->OptScl->bind = settingPlane->OptScl->bind;
6646 NewColPlane->OptScl->UseThr = settingPlane->OptScl->UseThr;
6647 NewColPlane->OptScl->UseBrt = settingPlane->OptScl->UseBrt;
6648 NewColPlane->OptScl->ThrMode = settingPlane->OptScl->ThrMode;
6649 NewColPlane->OptScl->ThreshRange[0] =
6650 settingPlane->OptScl->ThreshRange[0];
6651 NewColPlane->OptScl->ThreshRange[1] =
6652 settingPlane->OptScl->ThreshRange[1];
6653 NewColPlane->OptScl->BrightRange[0] =
6654 settingPlane->OptScl->BrightRange[0];
6655 NewColPlane->OptScl->BrightRange[1] =
6656 settingPlane->OptScl->BrightRange[1];
6657 NewColPlane->OptScl->BrightMap[0] =
6658 settingPlane->OptScl->BrightMap[0];
6659 NewColPlane->OptScl->BrightMap[1] =
6660 settingPlane->OptScl->BrightMap[1];
6661 NewColPlane->SymIrange = settingPlane->SymIrange;
6662 NewColPlane->OptScl->IntRange[0] = settingPlane->OptScl->IntRange[0];
6663 NewColPlane->OptScl->IntRange[1] = settingPlane->OptScl->IntRange[1];
6664 dsetcmap = NI_get_attribute(sddset->ngr,"SRT_use_this_cmap");
6665 if (dsetcmap) {
6666 SUMA_STRING_REPLACE(NewColPlane->cmapname, dsetcmap);
6667 } else {
6668 SUMA_STRING_REPLACE(NewColPlane->cmapname,
6669 settingPlane->cmapname);
6670 }
6671 NewColPlane->OptScl->Clusterize = settingPlane->OptScl->Clusterize;
6672 NewColPlane->OptScl->ClustOpt->AreaLim =
6673 settingPlane->OptScl->ClustOpt->AreaLim;
6674 NewColPlane->OptScl->ClustOpt->DistLim =
6675 settingPlane->OptScl->ClustOpt->DistLim;
6676 } else {
6677 SUMA_LH("New settings");
6678 /* set the opacity, index column and the range */
6679 NewColPlane->GlobalOpacity = YUP;
6680 NewColPlane->ShowMode = SW_SurfCont_DsetViewCol;
6681 if (!colplanepre) {/* only set this if first time creating plane*/
6682 NewColPlane->OptScl->BrightFact = 0.8;
6683 }
6684 NewColPlane->OptScl->find = 0;
6685 NewColPlane->OptScl->tind = 0;
6686 NewColPlane->OptScl->bind = 0;
6687 SUMA_GetDsetColRange(sddset, 0, NewColPlane->OptScl->IntRange, loc);
6688 if (NewColPlane->SymIrange) {
6689 NewColPlane->OptScl->IntRange[0] =
6690 -fabs(SUMA_MAX_PAIR( NewColPlane->OptScl->IntRange[0],
6691 NewColPlane->OptScl->IntRange[1]));
6692 NewColPlane->OptScl->IntRange[1] =
6693 -NewColPlane->OptScl->IntRange[0];
6694 }
6695
6696 /* stick a colormap onto that plane ? */
6697 dsetcmap = NI_get_attribute(sddset->ngr,"SRT_use_this_cmap");
6698 if (dsetcmap) {
6699 SUMA_STRING_REPLACE(NewColPlane->cmapname, dsetcmap);
6700 } else {
6701 /* don't worry, there's a default one */
6702 }
6703 }
6704 if (NewColPlane->OptScl->Clusterize)
6705 NewColPlane->OptScl->RecomputeClust = 1;
6706 /* colorize the plane */
6707 SUMA_LH("Colorizing Plane");
6708 SUMA_ColorizePlane(NewColPlane);
6709
6710 /* SUMA_Show_ColorOverlayPlanes(&NewColPlane, 1, 1); */
6711
6712 if (SurfCont && MakeOverlayCurrent)
6713 SurfCont->curColPlane = SUMA_ADO_Overlay(asdo, OverInd);
6714 }
6715 }
6716
6717 for (isd=0; isd<cdset->Aux->N_doms; ++isd) {
6718 asdo = SUMA_CIFTI_subdom_ado(CO, isd);
6719 if (!(sddset = DSET_FIND(cdset->Aux->doms[isd]->edset_id))) {
6720 SUMA_S_Err("Should had found that dset, returning with potential "
6721 "leaks!");
6722 SUMA_RETURN(NOPE);
6723 }
6724 /* Need to get OverInd again */
6725 if (!(SUMA_Fetch_OverlayPointerByDset ( asdo, sddset, &OverInd))) {
6726 SUMA_SLP_Err("How can this possibly happen?");
6727 SUMA_RETURN(NOPE);
6728 }
6729 if ((SurfCont = SUMA_ADO_Cont(asdo)) && LaunchDisplay) {
6730 SUMA_LHv("Remix Redisplay %s\n", ADO_LABEL(asdo));
6731 /* remix-redisplay for surface */
6732 if (!SUMA_Remixedisplay (asdo)) {
6733 SUMA_RETURN(NOPE);
6734 }
6735
6736 SUMA_LH("Refreshing Dset list");
6737 /*update the list widget if open */
6738 LW = SurfCont->SwitchDsetlst;
6739 if (LW) {
6740 if (!LW->isShaded) SUMA_RefreshDsetList (asdo);
6741 }
6742
6743 SUMA_LH("Refreshing sub-brick selectors");
6744 /* if lists for switching sub-bricks are not shaded, update them too */
6745 if (SurfCont->SwitchIntMenu) {
6746 if ((LW = SurfCont->SwitchIntMenu->lw) && !LW->isShaded) {
6747 SUMA_DsetColSelectList(asdo, 0, 0, 1);
6748 }
6749 if ((LW = SurfCont->SwitchThrMenu->lw) && !LW->isShaded) {
6750 SUMA_DsetColSelectList(asdo, 1, 0, 1);
6751 }
6752 if ((LW = SurfCont->SwitchBrtMenu->lw) && !LW->isShaded) {
6753 SUMA_DsetColSelectList(asdo, 2, 0, 1);
6754 }
6755
6756 if (LocalHead)
6757 fprintf (SUMA_STDERR,
6758
6759 "%s: Updating Dset frame, OverInd=%d\n",
6760 FuncName, OverInd);
6761 /* update the Dset frame */
6762 if (OverInd >= 0)
6763 SUMA_InitializeColPlaneShell(asdo,
6764 SUMA_ADO_Overlay(asdo, OverInd));
6765 }
6766 }
6767 }
6768
6769 if (used_over) {
6770 SUMA_S_Warn( "Not sure how to use this for CIFTI, at the moment have"
6771 "multiple overlays per CO, returning last thing in hand.");
6772 *used_over = SUMA_ADO_Overlay(asdo, OverInd);
6773 }
6774
6775 SUMA_RETURN(YUP);
6776
6777 }
6778
6779 /* Create CIFTI displayable object from the CIFTI dataset
6780 In the current incarnation (Tuesday Aug. 11 2015), the CIFTI DO
6781 will not be a fully fledged DO such as a surface or a volume. It
6782 is a bucket that contains references to "elementary" DOs (to parallel
6783 what happens to a multi-domain CIFTI dataset). It does not look like
6784 it will get its own controller. I am no longer seeing the need for
6785 that.
6786 */
SUMA_CIFTI_DO_from_dset(SUMA_DSET * cdset)6787 SUMA_CIFTI_DO * SUMA_CIFTI_DO_from_dset(SUMA_DSET *cdset)
6788 {
6789 static char FuncName[]={"SUMA_CIFTI_DO_from_dset"};
6790 int k;
6791 char *ss=NULL;
6792 SUMA_ALL_DO *ado=NULL;
6793 SUMA_CIFTI_DO *CO=NULL;
6794 SUMA_DSET *sddset=NULL;
6795 SUMA_Boolean LocalHead = NOPE;
6796
6797 SUMA_ENTRY;
6798
6799 if (!SUMA_isCIFTIDset(cdset)) {
6800 SUMA_S_Err("Not for this you don't");
6801 SUMA_RETURN(NULL);
6802 }
6803 if (!cdset || !cdset->Aux || !cdset->Aux->N_doms) {
6804 SUMA_S_Err("Junk in the house");
6805 SUMA_RETURN(NULL);
6806 }
6807 ss = SUMA_ar_string("DO_", ADO_LABEL((SUMA_ALL_DO *)cdset),"",0);
6808 CO = SUMA_CreateCIFTIObject(ss); SUMA_ifree(ss);
6809
6810 if (CO->N_subdoms < 0) CO->N_subdoms = 0;
6811 for (k=0; k<cdset->Aux->N_doms; ++k) {
6812 if (!cdset->Aux->doms[k]->Source) {
6813 SUMA_S_Err("Null source");
6814 SUMA_FreeCIFTIObject(CO);
6815 SUMA_RETURN(NULL);
6816 }
6817
6818 SUMA_LH("Loading source[%d]=%s", k, cdset->Aux->doms[k]->Source);
6819 switch (cdset->Aux->doms[k]->ModelType) {
6820 case SO_type: {
6821 ado = (SUMA_ALL_DO *)
6822 SUMA_Load_Surface_Object_eng(
6823 cdset->Aux->doms[k]->Source,
6824 SUMA_FT_NOT_SPECIFIED, SUMA_FF_NOT_SPECIFIED,
6825 NULL, 2);
6826 SUMA_SurfaceObject *SO=(SUMA_SurfaceObject *)ado;
6827 if (!SUMA_ADO_Label(ado)) {
6828 SO->Label = SUMA_copy_string(cdset->Aux->doms[k]->Source);
6829 }
6830 SUMA_ifree(SO->State);
6831 SO->State = SUMA_copy_string("ANY_ANATOMICAL");
6832 SUMA_ifree(SO->Group);
6833 SO->Group = SUMA_copy_string("ANY");
6834 if (1) {
6835 SUMA_LH("Adding CO %s SOs to objects list",
6836 ADO_LABEL((SUMA_ALL_DO *)CO));
6837 if (!SUMA_PrepAddmappableSO(SO, SUMAg_DOv, &SUMAg_N_DOv,
6838 1, SUMAg_CF->DsetList)) {
6839 SUMA_SL_Err("Failed in SUMA_PrepAddmappableSO.");
6840 SUMA_FreeCIFTIObject(CO); CO = NULL;
6841 SUMA_RETURN(NULL);
6842 }
6843 }
6844 /* make domain parent of matching dset be SO */
6845 if (!(sddset = DSET_FIND(cdset->Aux->doms[k]->edset_id))) {
6846 SUMA_S_Err("Should have found that dset (id %s)!",
6847 cdset->Aux->doms[k]->edset_id);
6848 } else {
6849 NI_set_attribute(sddset->ngr,
6850 "domain_parent_idcode", ADO_ID(ado));
6851 }
6852 break; }
6853 case VO_type: {
6854 SUMA_VolumeObject *VO=NULL;
6855 SUMA_VOL_SAUX *VSaux = NULL;
6856 SUMA_LH("This requires some additional thinking:\n"
6857 "1-All is needed for the volume is the grid.\n"
6858 " So might want to have LoadVolDO create a \n"
6859 " dummy volume from just a grid string (AFNI has\n"
6860 " such utilities.\n"
6861 " The actual data in the volume is now loaded by\n"
6862 " default but it is useless because it is \n"
6863 " to be trumped by the data in the CIFTI dataset.\n"
6864 "2-Even if loading volume, might want to have an\n"
6865 " autocrop at loading option. See AFNI convenience\n"
6866 " function: THD_autobbox()\n The smaller the grid \n"
6867 " the faster the volume rendering.\n");
6868 /* again, SUMA_WORLD should prob be _UNIT [22 Jun 2021 rickr] */
6869 if (SUMA_LoadVolDO(cdset->Aux->doms[k]->Source,
6870 SUMA_WORLD_UNIT, &VO, 1)){
6871 ado = (SUMA_ALL_DO *)VO;
6872 /* Change the state of the volume so that it is no longer
6873 of the default ANY_ANATOMICAL state. (See comment for string
6874 'State' definition in SUMA_VOL_SAUX */
6875 if (!(VSaux = SUMA_ADO_VSaux(ado))){
6876 SUMA_S_Err("No VSaux?");
6877 SUMA_FreeCIFTIObject(CO); CO = NULL;
6878 SUMA_RETURN(NULL);
6879 }
6880 SUMA_ifree(VSaux->State);
6881 VSaux->State = SUMA_copy_string("ANY_ANATOMICAL");
6882 VO = NULL;
6883
6884 VSaux->ShowVrSlc = 1; /* easier for debugging */
6885 }
6886 break; }
6887 default:
6888 SUMA_S_Err("Not ready for domain %d (%s) with CIFTI",
6889 cdset->Aux->doms[k]->ModelType,
6890 SUMA_ObjectTypeCode2ObjectTypeName(
6891 cdset->Aux->doms[k]->ModelType));
6892 SUMA_FreeCIFTIObject(CO); CO = NULL;
6893 SUMA_RETURN(NULL);
6894 break;
6895 }
6896 if (!ado) {
6897 SUMA_S_Err("Failed to load %s\n", cdset->Aux->doms[k]->Source);
6898 SUMA_FreeCIFTIObject(CO); CO = NULL;
6899 SUMA_RETURN(NULL);
6900 } else {
6901 ++CO->N_subdoms;
6902 CO->subdoms_id = (char **)SUMA_realloc(CO->subdoms_id,
6903 CO->N_subdoms*sizeof(char *));
6904 CO->subdoms_id[CO->N_subdoms-1] = SUMA_copy_string(ADO_ID(ado));
6905 ado = NULL;
6906 }
6907 }
6908
6909 if (1) {
6910 SUMA_LH("Adding CO %s to objects list", ADO_LABEL((SUMA_ALL_DO *)CO));
6911 if (!SUMA_AddDO(SUMAg_DOv, &(SUMAg_N_DOv), (void *)CO,
6912 CDOM_type, SUMA_WORLD)) {
6913 fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
6914 SUMA_FreeCIFTIObject(CO); CO = NULL;
6915 SUMA_RETURN(NULL);
6916 }
6917 }
6918
6919
6920 SUMA_RETURN(CO);
6921 }
6922
6923 /* Search all DOs for a CIFTIObject that can be the domain
6924 for a certain CIFTI dataset.
6925
6926 For now, subdomains indices do not have to match. Might want to
6927 enforce that. */
SUMA_CIFTI_find_matching_domain(SUMA_DSET * cdset,SUMA_DO * dov,int N_dov)6928 SUMA_CIFTI_DO *SUMA_CIFTI_find_matching_domain(SUMA_DSET *cdset,
6929 SUMA_DO *dov, int N_dov)
6930 {
6931 static char FuncName[]={"SUMA_CIFTI_find_matching_domain"};
6932 SUMA_CIFTI_DO *CO=NULL;
6933 int i, f, k;
6934 char *sid;
6935
6936 SUMA_ENTRY;
6937
6938 if (!dov) { dov = SUMAg_DOv; N_dov = SUMAg_N_DOv; }
6939
6940 for (i=0; i<N_dov; ++i) {
6941 if (dov[i].ObjectType == CDOM_type) {
6942 CO = (SUMA_CIFTI_DO *)dov[i].OP;
6943 for (f=0,k=0; k<cdset->Aux->N_doms; ++k) {
6944 sid = SUMA_CIFTI_find_sub_domain(CO,
6945 cdset->Aux->doms[k]->ModelType,
6946 cdset->Aux->doms[k]->ModelSide,
6947 cdset->Aux->doms[k]->Max_N_Data, NULL);
6948 if (sid) {++f;}
6949 }
6950 if (f == cdset->Aux->N_doms) {
6951 SUMA_RETURN(CO);
6952 }
6953 }
6954 }
6955 SUMA_RETURN(NULL);
6956 }
6957
6958 /* Search the sub-domains of a CIFTIObject to match desired parameters */
SUMA_CIFTI_find_sub_domain(SUMA_CIFTI_DO * CO,SUMA_DO_Types ModelType,SUMA_SO_SIDE ModelSide,int Max_N_Data,int * k)6959 char *SUMA_CIFTI_find_sub_domain(SUMA_CIFTI_DO *CO, SUMA_DO_Types ModelType,
6960 SUMA_SO_SIDE ModelSide,
6961 int Max_N_Data,
6962 int *k)
6963 {
6964 static char FuncName[]={"SUMA_CIFTI_find_sub_domain"};
6965 char *sid = NULL;
6966 int i;
6967 SUMA_ALL_DO *ado=NULL;
6968
6969 SUMA_ENTRY;
6970 if (k) *k = -1;
6971
6972 for (i=0; i<CO->N_subdoms; ++i) {
6973 ado = SUMA_CIFTI_subdom_ado(CO, i);
6974 if ( ado->do_type == ModelType &&
6975 ( ModelType != SO_type ||
6976 ModelSide == ((SUMA_SurfaceObject *)(ado))->Side ) &&
6977 Max_N_Data == SUMA_ADO_N_Datum(ado) ) {
6978 if (k) *k = i;
6979 SUMA_RETURN(ADO_ID((SUMA_ALL_DO*)CO));
6980 }
6981 }
6982
6983 SUMA_RETURN(NULL);
6984 }
6985
6986 /* Search all displayable objects for a CIFTI object containing a particular
6987 domain. */
SUMA_find_CIFTI_subdom_container(char * SD_id,int * ksubdom,SUMA_DO * dov,int N_dov)6988 SUMA_CIFTI_DO *SUMA_find_CIFTI_subdom_container(char *SD_id, int *ksubdom,
6989 SUMA_DO *dov, int N_dov)
6990 {
6991 static char FuncName[]={"SUMA_find_CIFTI_subdom_container"};
6992 int i, k;
6993 SUMA_CIFTI_DO *CO=NULL;
6994
6995 SUMA_ENTRY;
6996
6997 if (!dov) {
6998 dov = SUMAg_DOv;
6999 N_dov = SUMAg_N_DOv;
7000 }
7001
7002 for (i=0; i<N_dov; ++i) {
7003 switch (dov[i].ObjectType) {
7004 default:
7005 SUMA_S_Err("invalid ObjectType in container");
7006 SUMA_RETURN(NULL);
7007 break;
7008 case CDOM_type:
7009 CO = (SUMA_CIFTI_DO *)dov[i].OP;
7010 for (k=0; k<CO->N_subdoms; ++k) {
7011 if (CO->subdoms_id[k] && !strcmp(SD_id, CO->subdoms_id[k])) {
7012 /* got it */
7013 if (ksubdom) *ksubdom = k;
7014 SUMA_RETURN(CO);
7015 }
7016 }
7017 break;
7018 }
7019 }
7020
7021 SUMA_RETURN(NULL);
7022 }
7023
SUMA_CIFTI_SubDomFullOffset(SUMA_CIFTI_DO * CO,int ksub)7024 int SUMA_CIFTI_SubDomFullOffset(SUMA_CIFTI_DO *CO, int ksub)
7025 {
7026 static char FuncName[]={"SUMA_CIFTI_SubDomFullOffset"};
7027 int i, N=0;
7028
7029 for (i=1; i<=ksub; ++i) {
7030 N += SUMA_ADO_N_Datum(SUMA_CIFTI_subdom_ado(CO,i-1));
7031 }
7032 return(N);
7033 }
7034
SUMA_CIFTI_subdom_ado(SUMA_CIFTI_DO * CO,int ksub)7035 SUMA_ALL_DO *SUMA_CIFTI_subdom_ado(SUMA_CIFTI_DO *CO, int ksub)
7036 {
7037 static char FuncName[]={"SUMA_CIFTI_subdom_ado"};
7038 SUMA_ALL_DO *ado=NULL;
7039
7040 SUMA_ENTRY;
7041
7042 if (CO && ksub >=0 && ksub < CO->N_subdoms && CO->subdoms_id[ksub]) {
7043 ado = SUMA_whichADOg(CO->subdoms_id[ksub]);
7044 }
7045
7046 SUMA_RETURN(ado);
7047 }
7048
7049