1 #include "SUMA_suma.h"
2
3 extern SUMA_CommonFields *SUMAg_CF;
4 extern SUMA_DO *SUMAg_DOv;
5 extern int SUMAg_N_DOv;
6 extern SUMA_SurfaceViewer *SUMAg_SVv;
7 extern int SUMAg_N_SVv;
8
9 /*! functions dealing with Drawable Object Manipulation */
10
11 /*!
12 This function Links one Inode to another.
13 This is different from CreateInode in that no new node is being allocated for, only a link is created.
14 SUMA_CreateInodeLink (SUMA_INODE * FromIN, SUMA_INODE *ToIN)
15
16 FromIN = SUMA_CreateInodeLink (FromIN, ToIN);
17
18 \param FromIN (SUMA_INODE *) this is the pointer to the IDnode wich will be linked to ToIN.
19 As silly as this sounds, this should be a pointer to NULL otherwise the link will not
20 be established. The use of this function will help reduce the risk of linking pointers
21 that are pointing to allocated space.
22 \param ToIN (SUMA_INODE *) pointer where the link is going
23 \ret FromIN (SUMA_INODE *) if all is well, FromIN = ToIN
24 otherwise, NULL is returned
25
26 All this function does is check the FromIN is NULL and ToIN isn't and then it calls SUMA_AddLink (ToIN)
27 \sa SUMA_BreakInodeLink
28 \sa SUMA_isInodeLink
29 */
SUMA_CreateInodeLink(SUMA_INODE * FromIN,SUMA_INODE * ToIN)30 SUMA_INODE *SUMA_CreateInodeLink (SUMA_INODE * FromIN, SUMA_INODE *ToIN)
31 {
32 static char FuncName[] = {"SUMA_CreateInodeLink"};
33
34 SUMA_ENTRY;
35
36 if (FromIN) {
37 fprintf (SUMA_STDERR,"Error %s: FromIN Inode is not NULL. \n\tFromIN pointer is left undisturbed.\n", FuncName);
38 SUMA_RETURN(FromIN);
39 }
40 if (!ToIN) {
41 fprintf (SUMA_STDERR,"Error %s: ToIN is NULL.\n\t Can't link to NULL, returning NULL.\n", FuncName);
42 SUMA_RETURN(NULL);
43 }
44
45 /* add a link to ToIN */
46 if (!SUMA_AddLink (ToIN)) {
47 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AddLink.\n", FuncName);
48 SUMA_RETURN(NULL);
49 }
50
51 /* now return the pointer to be linked to */
52 SUMA_RETURN(ToIN);
53
54 }
55
56 /*!
57 This function determines if an Inode in a SO is a link or not.
58 an Inode is a link if IN->ParentIDcode and HolderIDcode are different.
59 The function is nothing more than a strcmp.
60
61 SUMA_Boolean SUMA_isInodeLink (SUMA_INODE *IN, const char *HolderIDcode)
62
63 returns NOPE if IN == NULL or IN->ParentIDcode != HolderIDcode
64 */
SUMA_isInodeLink(SUMA_INODE * IN,const char * HolderIDcode)65 SUMA_Boolean SUMA_isInodeLink (SUMA_INODE *IN, const char *HolderIDcode)
66 {
67 static char FuncName[] = {"SUMA_isInodeLink"};
68
69 SUMA_ENTRY;
70
71 if (!IN) {
72 fprintf (SUMA_STDERR, "Warning %s: IN is null.\n", FuncName);
73 SUMA_RETURN(NOPE);
74 }
75 if (!strcmp(IN->ParentIDcode, HolderIDcode)) SUMA_RETURN(YUP);
76
77 SUMA_RETURN(NOPE);
78 }
79
80 /*!
81 function to remove the link of one IDnode to the next
82 SUMA_INODE * SUMA_BreakInodeLink (SUMA_INODE *IN, const char *HolderIDcode);
83 \param IN (SUMA_INODE *) the linked inode
84 \param HolderIDcode (const char *) the ID code that holds/contains IN
85 \ret NULL if the link was broken or IN == NULL
86 IN if IN is not a link but an actuak Inode (meaning IN->ParentIDcode == HolderIDcode
87
88
89 */
SUMA_BreakInodeLink(SUMA_INODE * IN,const char * HolderIDcode)90 SUMA_INODE * SUMA_BreakInodeLink (SUMA_INODE *IN, const char *HolderIDcode)
91 {
92 static char FuncName[] = {"SUMA_BreakInodeLink"};
93
94 SUMA_ENTRY;
95
96 if (!IN) {
97 fprintf (SUMA_STDERR, "Warning %s: IN is null, nothing to do.\n", FuncName);
98 SUMA_RETURN(NULL);
99 }
100 if (!SUMA_isInodeLink (IN, HolderIDcode)) {
101 fprintf (SUMA_STDERR, "Error %s: Inode IN is not a link. Nothing done.\n", FuncName);
102 SUMA_RETURN(IN);
103 }
104
105 /* release the link */
106 if (SUMA_ReleaseLink (IN) < 0) {
107 fprintf (SUMA_STDERR, "Error %s: IN has no links. Nothing done.\n", FuncName);
108 SUMA_RETURN(IN);
109 }
110
111 /* OK, link released, not return NULL */
112 SUMA_RETURN(NULL);
113 }
114
115 /*!
116 This function decrements the N_link field in IN by 1 and returns the resultant N_link value
117 a -1 is returned if IN->N_link = 0 or IN == NULL
118
119
120 ans = SUMA_ReleaseLink (IN);
121
122 \param IN (SUMA_INODE *) pointer to SUMA_INODE structure
123 \ret ans (int) value of IN->N_link
124
125 \sa SUMA_AddLink
126 */
SUMA_ReleaseLink(SUMA_INODE * IN)127 int SUMA_ReleaseLink (SUMA_INODE * IN)
128 {
129 static char FuncName[]={"SUMA_ReleaseLink"};
130 SUMA_Boolean LocalHead = NOPE;
131
132 SUMA_ENTRY;
133
134 if (!IN) {
135 /* This typically happens when A link was never created in the first place.
136 It used to be an error message but now it is just a warning because some
137 programs compute things like SO->Cx without creating an inode with it ...*/
138 fprintf (SUMA_STDERR,"Warning %s: Inode is null. Returning -1.\n", FuncName);
139 SUMA_RETURN(-1);
140 }
141 if (!IN->N_link) {
142 if (LocalHead) fprintf (SUMA_STDERR,"%s: No links. Returning -1.\n", FuncName);
143 /* You do not want to return a 0 because freeing is done when no links remain
144 THIS STUPID SYSTEM SHOULD BE ELIMINATED IN FAVOR OF THE METHOD USED FOR OVERLAYS*/
145 SUMA_RETURN(-1);
146 }
147 else {
148 IN->N_link--;
149 SUMA_RETURN(IN->N_link);
150 }
151 }
152
153 /*!
154 This function increments the N_link field in IN by 1 and returns the resultant N_link value
155 a zero is returned in case of an error
156
157
158 ans = SUMA_AddLink (IN);
159
160 \param IN (SUMA_INODE *) pointer to SUMA_INODE structure
161 \ret ans (int) value of IN->N_link
162 \sa SUMA_ReleaseLink
163 */
SUMA_AddLink(SUMA_INODE * IN)164 int SUMA_AddLink (SUMA_INODE * IN)
165 {
166 static char FuncName[]={"SUMA_AddLink"};
167
168 SUMA_ENTRY;
169
170 if (!IN) {
171 fprintf (SUMA_STDERR,"Error %s: Inode is null.\n", FuncName);
172
173 SUMA_RETURN(0);
174 } else {
175 IN->N_link++;
176 SUMA_RETURN(IN->N_link);
177 }
178 }
179
180 /*!
181 Function to create a SUMA_INODE structure
182 ans = SUMA_CreateInode (data, ParentIDcode);
183
184 \param data (void *) pointer to data location
185 \param ParentIDcode (char[SUMA_IDCODE_LENGTH]) containing the IDcode of the creator of the data
186 \ret ans (SUMA_INODE *) pointer to SUMA_INODE for data
187 NULL if error is encountered
188 */
189
SUMA_CreateInode(void * data,char * ID)190 SUMA_INODE *SUMA_CreateInode (void *data, char *ID)
191 {
192 static char FuncName[]={"SUMA_CreateInode"};
193 SUMA_INODE *IN;
194
195 SUMA_ENTRY;
196
197 IN = (SUMA_INODE *)SUMA_malloc (sizeof(SUMA_INODE));
198 if (IN == NULL) {
199 fprintf (SUMA_STDERR,"Error %s: failed to allocate for Inode.\n", FuncName);
200 SUMA_RETURN(NULL);
201 }
202
203 IN->data = data;
204 strcpy (IN->ParentIDcode, ID);
205 IN->N_link = 0;
206
207 SUMA_RETURN(IN);
208 }
209
210 /*!
211 Create a Displayable Object data structure
212 */
SUMA_Alloc_DisplayObject_Struct(int N)213 SUMA_DO *SUMA_Alloc_DisplayObject_Struct (int N)
214 {
215 static char FuncName[]={"SUMA_Alloc_DisplayObject_Struct"};
216 SUMA_DO *dov;
217
218 SUMA_ENTRY;
219
220 dov = (SUMA_DO *)SUMA_malloc(sizeof(SUMA_DO)*N);
221 if (dov == NULL) {
222 SUMA_alloc_problem("SUMA_Alloc_DisplayObject_Struct: could not allocate memory for SO");
223 }
224 SUMA_RETURN(dov);
225 }/*SUMA_Alloc_DisplayObject_Struct*/
226
227
228 /*!
229 Free a Displayable Object data structure
230 */
SUMA_Free_Displayable_Object(SUMA_DO * dov)231 SUMA_Boolean SUMA_Free_Displayable_Object (SUMA_DO *dov)
232 {
233 static char FuncName[]={"SUMA_Free_Displayable_Object"};
234
235 SUMA_ENTRY;
236
237 switch (dov->ObjectType) {
238 case VO_type:
239 if (!SUMA_FreeVolumeObject ((SUMA_VolumeObject *)dov->OP)) {
240 SUMA_S_Err("could not free volume");
241 }
242 break;
243 case SO_type:
244 if (!SUMA_Free_Surface_Object ((SUMA_SurfaceObject *)dov->OP)) {
245 fprintf(SUMA_STDERR,
246 "Error SUMA_Free_Displayable_Object, could not free surface\n");
247 }
248 break;
249 case ROIdO_type:
250 if (!SUMA_freeDrawnROI ((SUMA_DRAWN_ROI *)dov->OP)) {
251 fprintf(SUMA_STDERR,
252 "Error SUMA_freeDrawnROI, could not free ROI.\n");
253 }
254 break;
255 case ROIO_type:
256 if (!SUMA_freeROI ((SUMA_ROI *)dov->OP)) {
257 fprintf(SUMA_STDERR,"Error SUMA_freeROI, could not free ROI.\n");
258 }
259 break;
260 case ONBV_type:
261 case NBV_type:
262 case OLS_type:
263 case LS_type:
264 case ODIR_type:
265 case DIR_type:
266 case NBLS_type:
267 case NBOLS_type:
268 SUMA_free_SegmentDO ((SUMA_SegmentDO *)dov->OP);
269 break;
270 case AO_type:
271 SUMA_Free_Axis((SUMA_Axis*)dov->OP);
272 break;
273 case GO_type:
274 fprintf(SUMA_STDERR,
275 "Error SUMA_Free_Displayable_Object, "
276 "Not trained to free GO objects\n");
277 break;
278 case not_DO_type:
279 /* not a DO, leave it to beaver */
280 break;
281 case NOT_SET_type:
282 fprintf(SUMA_STDERR,
283 "Error SUMA_Free_Displayable_Object, "
284 "no free NOT_SET_type\n");
285 break;
286 case PNT_type:
287 case NBSP_type:
288 case SP_type:
289 SUMA_free_SphereDO ((SUMA_SphereDO *)dov->OP);
290 break;
291 case PL_type:
292 SUMA_free_PlaneDO ((SUMA_PlaneDO *)dov->OP);
293 break;
294 case NIDO_type:
295 SUMA_free_NIDO((SUMA_NIDO*)dov->OP);
296 break;
297 case CDOM_type:
298 SUMA_FreeCIFTIObject((SUMA_CIFTI_DO *)dov->OP);
299 break;
300 case NBT_type:
301 case SBT_type:
302 case DBT_type:
303 /* those types are not used */
304 SUMA_S_Warnv("Type %d should not be in use!\n", dov->ObjectType);
305 break;
306 case GDSET_type:
307 case MD_DSET_type:
308 case ANY_DSET_type:
309 SUMA_FreeDset(dov->OP);
310 break;
311 case TRACT_type:
312 SUMA_free_TractDO(dov->OP);
313 break;
314 case MASK_type:
315 SUMA_free_MaskDO(dov->OP);
316 break;
317 case GRAPH_LINK_type:
318 SUMA_free_GraphLinkDO(dov->OP);
319 break;
320 default:
321 SUMA_S_Errv("Type %d not accounted for!\n", dov->ObjectType);
322 break;
323 }
324
325 SUMA_RETURN(YUP);
326 }
327
SUMA_Free_Displayable_Object_Vect(SUMA_DO * dov,int N)328 SUMA_Boolean SUMA_Free_Displayable_Object_Vect (SUMA_DO *dov, int N)
329 {
330 static char FuncName[] = {"SUMA_Free_Displayable_Object_Vect"};
331 int i;
332 SUMA_Boolean Ret = YUP;
333
334 SUMA_ENTRY;
335
336 for (i=0; i < N; ++i) {
337 if (&dov[i] != NULL) {
338 Ret = Ret * SUMA_Free_Displayable_Object (&dov[i]);
339 }
340 }
341
342 if (dov) SUMA_free(dov);
343 SUMA_RETURN(Ret);
344
345 }
346
347 /*!
348 Find a DO's index by idcodestring
349 */
SUMA_FindDOi_byID(SUMA_DO * dov,int N_dov,char * idcode_str)350 int SUMA_FindDOi_byID(SUMA_DO *dov, int N_dov, char *idcode_str)
351 {
352 static char FuncName[] = {"SUMA_FindDOi_byID"};
353 int i;
354 void *op;
355 SUMA_ALL_DO *ado=NULL;
356 SUMA_Boolean LocalHead = NOPE;
357
358 SUMA_ENTRY;
359
360 SUMA_LHv("idcode %s\n", idcode_str);
361 if (!dov || !idcode_str) {
362 SUMA_RETURN(-1);
363 }
364
365 for (i=0; i<N_dov; ++i) {
366 if (dov[i].ObjectType > not_DO_type) {
367 ado = (SUMA_ALL_DO *)dov[i].OP;
368 SUMA_LHv("ado %p: Object %d/%d type: %d\n",
369 ado, i, N_dov, dov[i].ObjectType);
370 SUMA_LHv("ado->idcode_str= %s\n",
371 SUMA_CHECK_NULL_STR(SUMA_ADO_idcode(ado)));
372 SUMA_LHv("idcode_str= %s\n",
373 SUMA_CHECK_NULL_STR(idcode_str));
374 if (SUMA_ADO_idcode(ado) &&
375 strcmp(SUMA_ADO_idcode(ado), idcode_str) == 0) {
376 SUMA_RETURN(i);
377 }
378 } else {
379 SUMA_SL_Warn("Strange, no type for DO");
380 }
381 }
382 if (LocalHead) SUMA_Show_DOv (dov, N_dov, NULL);
383 SUMA_RETURN(-1);
384 }
385
386 /*!
387 Add a displayable object to dov
388 */
SUMA_AddDO(SUMA_DO * dov,int * N_dov,void * op,SUMA_DO_Types DO_Type,SUMA_DO_CoordType DO_CoordType)389 SUMA_Boolean SUMA_AddDO(SUMA_DO *dov, int *N_dov, void *op,
390 SUMA_DO_Types DO_Type, SUMA_DO_CoordType DO_CoordType)
391 {
392 static char FuncName[] = {"SUMA_AddDO"};
393 SUMA_ALL_DO *ado=NULL;
394 static int nm=0;
395 void *eo=NULL;
396 int ieo;
397 SUMA_Boolean LocalHead = NOPE;
398
399 SUMA_ENTRY;
400
401 ado = (SUMA_ALL_DO *)op;
402 if (!SUMA_ADO_idcode(ado)) {
403 SUMA_error_message (FuncName, "Need an idcode_str for do",0);
404 SUMA_RETURN(NOPE);
405 }
406 if (DO_Type <= not_DO_type || DO_Type >= N_DO_TYPES) {
407 SUMA_S_Errv("DO_type %d not valid\n", DO_Type);
408 SUMA_RETURN(NOPE);
409 }
410 /* Does that baby exist? */
411 if ((ieo = SUMA_FindDOi_byID(dov, *N_dov, SUMA_ADO_idcode(ado))) >= 0) {
412 if (DO_Type == SO_type) {
413 SUMA_SLP_Err("Surface exists, cannot be replaced this way.");
414 SUMA_RETURN(NOPE);
415 }
416 if (DO_Type == VO_type) {
417 SUMA_S_Warn("Replacing volume object, might get complicated...");
418 }
419 if (LocalHead ||
420 (!(nm % 300) && !SUMA_ADO_isLabel(ado,"AHorseWithNoName"))) {
421 SUMA_SL_Note( "Object %s existed as %s and will be replaced.\n"
422 "Message shown intermittently",
423 ADO_LABEL(ado), ADO_LABEL((SUMA_ALL_DO *)(dov[ieo].OP)));
424 ++nm;
425 }
426 /* free olde one */
427 if (!SUMA_Free_Displayable_Object(&(dov[ieo]))) {
428 SUMA_SL_Err("Failed to free displayable object");
429 SUMA_RETURN(NOPE);
430 }
431 dov[ieo].OP = op;
432 dov[ieo].ObjectType = DO_Type;
433 dov[ieo].CoordType = DO_CoordType;
434 } else {
435 /* Addington */
436 /* make sure you did not exceed allocated space */
437 if (*N_dov >= SUMA_MAX_DISPLAYABLE_OBJECTS) {
438 SUMA_error_message (FuncName, "Reached limit of DOv storage",0);
439 SUMA_RETURN(NOPE);
440 }
441 dov[*N_dov].OP = op;
442 dov[*N_dov].ObjectType = DO_Type;
443 dov[*N_dov].CoordType = DO_CoordType;
444 *N_dov = *N_dov+1;
445 }
446
447
448
449
450 SUMA_RETURN(YUP);
451 }
452
453 /*!
454 \brief Remove a displayable object from dov
455 success = SUMA_RemoveDO(dov, N_dov, op, Free_op);
456
457 \param dov (SUMA_DO*) vector containing displayable objects
458 \param N_dov (int *) number of elements in dov
459 \param op (void *) pointer to object sought
460 \param Free_op (SUMA_Boolean) Flag for freeing space allocated for op's data.
461 Freeing is done via SUMA_Free_Displayable_Object()
462 \return success (SUMA_Boolean) flag.
463 */
SUMA_RemoveDO(SUMA_DO * dov,int * N_dov,void * op,SUMA_Boolean Free_op)464 SUMA_Boolean SUMA_RemoveDO(SUMA_DO *dov, int *N_dov, void *op,
465 SUMA_Boolean Free_op)
466 {
467 static char FuncName[] = {"SUMA_RemoveDO"};
468 int i;
469 SUMA_Boolean Found=NOPE, State=YUP;
470 SUMA_Boolean LocalHead = NOPE;
471
472 SUMA_ENTRY;
473
474 SUMA_LH("Called");
475 if (LocalHead) {
476 SUMA_LH("Before deletion, %d objects", *N_dov);
477 for (i=0; i<*N_dov; ++i) {
478 fprintf(SUMA_STDERR,"%d: Label %s Type %s\n",
479 i, ADO_LABEL((SUMA_ALL_DO*)dov[i].OP),
480 ADO_TNAME((SUMA_ALL_DO*)dov[i].OP));
481 }
482 }
483 for (i=0; i<*N_dov; ++i) {
484 if (dov[i].OP == op) {
485 Found = YUP;
486 SUMA_LH("found object. Removing it from dov.");
487 if (Free_op) {
488 if (LocalHead) SUMA_S_Err("Freeing object.");
489 if (!SUMA_Free_Displayable_Object (&dov[i])) {
490 SUMA_SLP_Crit("Failed to free displayable object.");
491 SUMA_RETURN(NOPE);
492 }
493 }
494 *N_dov = *N_dov-1;
495 dov[i].OP = dov[*N_dov].OP;
496 dov[i].ObjectType = dov[*N_dov].ObjectType;
497 dov[i].CoordType = dov[*N_dov].CoordType;
498 }
499 }
500
501 if (LocalHead) {
502 SUMA_LH("At exit, %d objects", *N_dov);
503 for (i=0; i<*N_dov; ++i) {
504 fprintf(SUMA_STDERR,"%d: Label %s Type %s\n",
505 i, ADO_LABEL((SUMA_ALL_DO*)dov[i].OP),
506 ADO_TNAME((SUMA_ALL_DO*)dov[i].OP));
507 }
508 }
509
510 if (Found) {
511 State=YUP;
512 /* Refresh all things indexing dov */
513 if (!SUMA_AllSV_RegisteredDO_Refresh()) {
514 SUMA_S_Err("Failed to refresh all registDO vectors");
515 State=NOPE;
516 }
517 if (!SUMA_AllViewState_MembsRefresh()) {
518 SUMA_S_Err("Failed to refresh all viewstate hist vectors");
519 State=NOPE;
520 }
521 SUMA_RETURN(State);
522 } else {
523 SUMA_RETURN(NOPE);
524 }
525 }
526
527 /*
528 A function that must be called each time order of objects in
529 SUMAg_DOv is disturbed
530 */
SUMA_SV_RegisteredDO_Refresh(SUMA_SurfaceViewer * sv)531 SUMA_Boolean SUMA_SV_RegisteredDO_Refresh(SUMA_SurfaceViewer *sv)
532 {
533 static char FuncName[]={"SUMA_SV_RegisteredDO_Refresh"};
534 int ii=0, found = -1;
535 SUMA_Boolean LocalHead = NOPE;
536 SUMA_ENTRY;
537
538 if (!sv) SUMA_RETURN(NOPE);
539
540 ii = 0;
541 while (ii < sv->N_DO) {
542 if ( sv->RegistDO &&
543 (found = SUMA_whichDOg(sv->RegistDO[ii].idcode_str)) >= 0) {
544 /* A good thing, refresh index mapping */
545 sv->RegistDO[ii].dov_ind = found;
546 } else {
547 SUMA_LH("A bad entry in RegistDO at index %d/%d, cleaning",
548 ii, sv->N_DO);
549 if (ii != sv->N_DO-1) {
550 strcpy(sv->RegistDO[ii].idcode_str,
551 sv->RegistDO[sv->N_DO-1].idcode_str);
552 }
553 sv->RegistDO[ii].dov_ind = sv->RegistDO[sv->N_DO-1].dov_ind;
554 sv->N_DO = sv->N_DO-1;
555 }
556 ++ii;
557 }
558
559 SUMA_RETURN(YUP);
560 }
561
SUMA_AllSV_RegisteredDO_Refresh(void)562 SUMA_Boolean SUMA_AllSV_RegisteredDO_Refresh(void)
563 {
564 static char FuncName[]={"SUMA_AllSV_RegisteredDO_Refresh"};
565 int i;
566 SUMA_Boolean state = YUP;
567
568 SUMA_ENTRY;
569
570 state = YUP;
571 for (i=0; i<SUMAg_N_SVv; ++i) {
572 if ((SUMAg_SVv+i) &&
573 !SUMA_SV_RegisteredDO_Refresh(SUMAg_SVv+i)) state = NOPE;
574 }
575
576 SUMA_RETURN(state);
577 }
578
SUMA_FindFirst_dov_ind(SUMA_DO_LOCATOR * x0,SUMA_DO_LOCATOR * x1,int val)579 int SUMA_FindFirst_dov_ind (SUMA_DO_LOCATOR *x0, SUMA_DO_LOCATOR *x1, int val)
580 {/*SUMA_FindFirst_dov_ind*/
581 SUMA_DO_LOCATOR *xi=x0;
582 while(x0<x1) if ((*x0).dov_ind==val) return((int)(x0-xi)); else ++x0;
583 return(-1);
584 }
585
586 /*!
587 Register a DO with surface viewer RegisteredDO vector
588 if dov_id is present in cSV, nothing is done
589 if not found then dov_id is registered at the end of cSV->RegisteredDO
590
591 When a DO is registered, a ColorList is created if the DO is a surface object.
592 and N_DO is updated
593 */
SUMA_RegisterDO(int dov_id,SUMA_SurfaceViewer * cSVu)594 SUMA_Boolean SUMA_RegisterDO(int dov_id, SUMA_SurfaceViewer *cSVu)
595 {
596 static char FuncName[]={"SUMA_RegisterDO"};
597 int i, is, icsvmin=0, icsvmax=0, icsv=0;
598 char *sid=NULL;
599 SUMA_SurfaceViewer *cSV=NULL;
600 SUMA_Boolean LocalHead = NOPE;
601
602 SUMA_ENTRY;
603
604 if (LocalHead) {
605 SUMA_DUMP_TRACE("at RegisterDO");
606 }
607
608 if (dov_id < 0) {
609 SUMA_S_Err("A negative dov_id!");
610 SUMA_DUMP_TRACE("Negative dov_id bro? What gives?");
611 SUMA_RETURN(NOPE);
612 }
613
614 if (!cSVu) { /* Do this for all viewers */
615 SUMA_LHv("Working all %d svs (%d open X-realized)\n",
616 SUMA_MAX_SURF_VIEWERS, SUMAg_N_SVv);
617 icsvmin = 0; icsvmax=SUMAg_N_SVv;
618 } else {
619 icsvmin = SUMA_WhichSV(cSVu, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS);
620 if (icsvmin >=0) icsvmax = icsvmin+1;
621 else {
622 SUMA_DUMP_TRACE("No SV???");
623 SUMA_S_Err("Could not find sv!");
624 SUMA_RETURN(NOPE);
625 }
626 SUMA_LHv("Working from sv %d to %d\n", icsvmin, icsvmax);
627 }
628
629 icsv = icsvmin;
630 while (icsv < icsvmax) {
631 cSV = &(SUMAg_SVv[icsv]);
632 SUMA_LH("Process for viewer %d, %p, [%c]", icsv, cSV, 65+icsv);
633 #if 0
634 if (LocalHead) {
635 /* scan for trouble */
636 for (i=0; i<cSV->N_DO; ++i) {
637 if (cSV->RegistDO[i].dov_ind < 0) {
638 SUMA_DUMP_TRACE("What the what?");
639 exit(1);
640 }
641 }
642 }
643 #endif
644
645 if (LocalHead &&
646 SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) != 0) {
647 fprintf(SUMA_STDERR,"%s: Muted for viewer %p [%c]\n",
648 FuncName, cSV,
649 65+SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) );
650 /* turn off the LocalHead, too much output*/
651 LocalHead = NOPE;
652 }
653
654
655 switch (iDO_type(dov_id)) {
656 case SO_type: /* add it regardless. This may need revisiting if you
657 begin to load surfaces interactively, not from
658 the initial startup */
659 /* check to see if dov_id exists */
660
661 if (SUMA_FindFirst_dov_ind(cSV->RegistDO,
662 cSV->RegistDO+cSV->N_DO,
663 dov_id) >= 0) { // found, do nothing
664 goto NEXT_CSV;
665 }
666
667 // Not yet registered so add it
668 cSV->RegistDO[cSV->N_DO].dov_ind = dov_id;
669 sid = iDO_idcode(dov_id);
670 strcpy(cSV->RegistDO[cSV->N_DO].idcode_str,sid);
671 cSV->N_DO += 1;
672
673 // Now add the ColorList, if DO is a surface object
674 if (SUMA_isSO(SUMAg_DOv[dov_id])) {
675 if (LocalHead)
676 fprintf (SUMA_STDERR,"%s: Adding color list...\n", FuncName);
677 // add the ColorList
678 if (!SUMA_FillColorList (cSV,
679 (SUMA_ALL_DO *)SUMAg_DOv[dov_id].OP)) {
680 fprintf(SUMA_STDERR,
681 "Error %s: Failed in SUMA_FillColorList.\n", FuncName);
682 SUMA_RETURN (NOPE);
683 }
684 }
685 SUMA_LHv("Back from SUMA_FillColorList. (%s/%d).\n",
686 cSV->ColList[0]->idcode_str, cSV->N_ColList);
687
688 break;
689 case GRAPH_LINK_type:
690 {
691 SUMA_GraphLinkDO *GLDO=(SUMA_GraphLinkDO *)(SUMAg_DOv[dov_id].OP);
692 SUMA_LHv("With GLDO %s, variant %s, Anat Correctedness %s\n",
693 DO_label(GLDO), GLDO->variant,
694 SUMA_isDO_AnatCorrect(&(SUMAg_DOv[dov_id]))?"YES":"NO");
695 if (SUMA_isDO_AnatCorrect(&(SUMAg_DOv[dov_id]))) {
696 if (SUMA_FirstGoodAnatCorrState(cSV) < 0) {
697 /* have nothing yet, add one */
698 SUMA_LH("Not one anatomical state to be found for sv %p [%c],"
699 " adding one", cSV,
700 SUMA_WhichSVc(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS));
701 if (SUMA_Which_iDO_State(dov_id, cSV, 1) < 0) {
702 SUMA_S_Err("State could not be added!!!");
703 SUMA_RETURN (NOPE);
704 }
705 }
706
707 /* Register it also in all states of VSv that are AnatCorrect */
708 for (is=0; is < cSV->N_VSv; ++is) {
709 if (cSV->VSv[is].AnatCorrect &&
710 SUMA_FindFirst_dov_ind(cSV->VSv[is].MembDO,
711 cSV->VSv[is].MembDO+cSV->VSv[is].N_MembDO,
712 dov_id) < 0) {
713 cSV->VSv[is].N_MembDO += 1;
714 cSV->VSv[is].MembDO =
715 (SUMA_DO_LOCATOR *)SUMA_realloc(cSV->VSv[is].MembDO,
716 cSV->VSv[is].N_MembDO*sizeof(SUMA_DO_LOCATOR));
717 cSV->VSv[is].MembDO[cSV->VSv[is].N_MembDO-1].dov_ind =
718 dov_id;
719 sid = iDO_idcode(dov_id);
720 strcpy(
721 cSV->VSv[is].MembDO[cSV->VSv[is].N_MembDO-1].idcode_str,
722 sid);
723 }
724 }
725 /* if the current state is anatomical, register object also
726 in cSV->RegistDO */
727 if (SUMA_isViewerStateAnatomical(cSV)) {
728 if (SUMA_FindFirst_dov_ind(cSV->RegistDO,
729 cSV->RegistDO+cSV->N_DO,
730 dov_id) < 0) {
731 cSV->RegistDO[cSV->N_DO].dov_ind = dov_id;
732 sid = iDO_idcode(dov_id);
733 strcpy(cSV->RegistDO[cSV->N_DO].idcode_str,sid);
734 cSV->N_DO += 1;
735 } else {
736 SUMA_LHv(" GLDO %s, %s already in the bag at"
737 " cSV->RegisteredDO[%d]\n",
738 DO_label(GLDO), GLDO->variant,
739 SUMA_FindFirst_dov_ind(cSV->RegistDO,
740 cSV->RegistDO+cSV->N_DO,
741 dov_id));
742 }
743 SUMA_LH("Adding color list (if necessary)...");
744 /* add the ColorList */
745 if (!SUMA_FillColorList (cSV,
746 (SUMA_ALL_DO *)SUMAg_DOv[dov_id].OP)) {
747 SUMA_S_Err("Failed in SUMA_FillColorList.");
748 SUMA_RETURN (NOPE);
749 }
750
751 } else {
752 SUMA_LHv(" Viewer state (%s) not anatomical for GLDO %s, %s\n",
753 cSV->State, DO_label(GLDO), GLDO->variant);
754 }
755 } else {
756 is = SUMA_Which_iDO_State(dov_id, cSV, 1);
757 /* If we are in the proper state add it to RegisteredDO*/
758 SUMA_LHv("For GLDO %s\n State:%s,Group:%s found.\n"
759 "Comparing to current viewer state of %s\n",
760 GLDO->Label, SUMA_iDO_state(dov_id),
761 SUMA_iDO_group(dov_id), cSV->State);
762 if (!strcmp(cSV->State, SUMA_iDO_state(dov_id))) {
763 if (SUMA_FindFirst_dov_ind(cSV->RegistDO,
764 cSV->RegistDO+cSV->N_DO,
765 dov_id) < 0) {/* not present, add it */
766 SUMA_LHv(" GLDO %s, %s has been appended\n",
767 DO_label(GLDO), GLDO->variant);
768 cSV->RegistDO[cSV->N_DO].dov_ind = dov_id;
769 sid = iDO_idcode(dov_id);
770 strcpy(cSV->RegistDO[cSV->N_DO].idcode_str,sid);
771 cSV->N_DO += 1;
772 } else {
773 SUMA_LHv(" GLDO %s, %s already in the bag at"
774 " cSV->RegisteredDO[%d]\n",
775 DO_label(GLDO), GLDO->variant,
776 SUMA_FindFirst_dov_ind(cSV->RegistDO,
777 cSV->RegistDO+cSV->N_DO,
778 dov_id));
779 }
780 SUMA_LH("Adding color list.");
781 /* add the ColorList */
782 if (!SUMA_FillColorList (cSV,
783 (SUMA_ALL_DO *)SUMAg_DOv[dov_id].OP)) {
784 SUMA_S_Err("Failed in SUMA_FillColorList.");
785 SUMA_RETURN (NOPE);
786 }
787 }
788 }
789 }
790 break;
791 case MASK_type:
792 case VO_type:
793 case CDOM_type:
794 case TRACT_type:
795 {
796 SUMA_ALL_DO *ADO=(SUMA_ALL_DO *)(SUMAg_DOv[dov_id].OP);
797 SUMA_LHv("With ADO %s, Anat Correctedness %s\n",
798 ADO_LABEL(ADO),
799 SUMA_isDO_AnatCorrect(&(SUMAg_DOv[dov_id]))?"YES":"NO");
800 if (SUMA_isDO_AnatCorrect(&(SUMAg_DOv[dov_id]))) {
801 if (SUMA_FirstGoodAnatCorrState(cSV) < 0) {
802 SUMA_LH("Not one anatomical state to be found, adding one");
803 if (SUMA_Which_iDO_State(dov_id, cSV, 1) < 0) {
804 SUMA_S_Err("State could not be added!!!");
805 SUMA_RETURN (NOPE);
806 }
807 }
808 /* Register it also in all states of VSv that are AnatCorrect */
809 for (is=0; is < cSV->N_VSv; ++is) {
810 if (cSV->VSv[is].AnatCorrect &&
811 SUMA_FindFirst_dov_ind(cSV->VSv[is].MembDO,
812 cSV->VSv[is].MembDO+cSV->VSv[is].N_MembDO,
813 dov_id) < 0) {
814 cSV->VSv[is].N_MembDO += 1;
815 cSV->VSv[is].MembDO =
816 (SUMA_DO_LOCATOR *)SUMA_realloc(cSV->VSv[is].MembDO,
817 cSV->VSv[is].N_MembDO*sizeof(SUMA_DO_LOCATOR));
818 cSV->VSv[is].MembDO[cSV->VSv[is].N_MembDO-1].dov_ind =
819 dov_id;
820 sid = iDO_idcode(dov_id);
821 strcpy(
822 cSV->VSv[is].MembDO[cSV->VSv[is].N_MembDO-1].idcode_str,
823 sid);
824 }
825 }
826 /* if the current state is anatomical, register object also
827 in cSV->RegistDO */
828 if (SUMA_isViewerStateAnatomical(cSV)) {
829 if (SUMA_FindFirst_dov_ind(cSV->RegistDO,
830 cSV->RegistDO+cSV->N_DO,
831 dov_id) < 0) {
832 cSV->RegistDO[cSV->N_DO].dov_ind = dov_id;
833 sid = iDO_idcode(dov_id);
834 strcpy(cSV->RegistDO[cSV->N_DO].idcode_str,sid);
835 cSV->N_DO += 1;
836 } else {
837 SUMA_LHv(" ADO %s, already in the bag at"
838 " cSV->RegisteredDO[%d]\n",
839 ADO_LABEL(ADO),
840 SUMA_FindFirst_dov_ind(cSV->RegistDO,
841 cSV->RegistDO+cSV->N_DO,
842 dov_id));
843 }
844 SUMA_LH("Adding color list for %s (id %s), viewer %p %d [%c]",
845 iDO_label(dov_id), iDO_idcode(dov_id), cSV,
846 SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS),
847 SUMA_WhichSVc(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS));
848 /* add the ColorList */
849 if (!SUMA_FillColorList (cSV,
850 (SUMA_ALL_DO *)SUMAg_DOv[dov_id].OP)) {
851 SUMA_S_Err("Failed in SUMA_FillColorList.");
852 SUMA_RETURN (NOPE);
853 }
854
855 } else {
856 SUMA_LHv(" Viewer state (%s) not anatomical for ADO %s\n",
857 cSV->State, ADO_LABEL(ADO));
858 }
859 } else {
860 SUMA_S_Err("Tracts are supposed to be anatomically correct\n"
861 "If this is not an error, you'll need to put in\n"
862 "a block here that parallels what is not with \n"
863 "anatomically incorrect GLDOs above.");
864 SUMA_RETURN(NOPE);
865 }
866 }
867 break;
868 default:
869 SUMA_LHv("Just adding DO %s, no states, nothing\n",
870 iDO_label(dov_id));
871 if (SUMA_FindFirst_dov_ind(cSV->RegistDO,
872 cSV->RegistDO+cSV->N_DO,
873 dov_id) < 0){
874 /* just add for now */
875 cSV->RegistDO[cSV->N_DO].dov_ind = dov_id;
876 sid = iDO_idcode(dov_id);
877 strcpy(cSV->RegistDO[cSV->N_DO].idcode_str,sid);
878 cSV->N_DO += 1;
879 }
880 break;
881 }
882 if (LocalHead) {
883 fprintf (SUMA_STDERR,"%s: RegisteredDO is now:\n", FuncName);
884 for (i=0; i< cSV->N_DO; ++i) {
885 fprintf(SUMA_STDERR,
886 "RegisteredDO[%d] = %d , type=%d (%s) label %s\t", i,
887 cSV->RegistDO[i].dov_ind,
888 iDO_type(cSV->RegistDO[i].dov_ind),
889 SUMA_ObjectTypeCode2ObjectTypeName(iDO_type(cSV->RegistDO[i].dov_ind)),
890 iDO_label(cSV->RegistDO[i].dov_ind));
891 }
892 fprintf(SUMA_STDERR,"\n");
893 }
894
895 /* update the title bar */
896 SUMA_UpdateViewerTitle(cSV);
897
898 NEXT_CSV:
899 ++icsv;
900 }
901
902
903 SUMA_RETURN(YUP);
904 }
905 /*!
906 remove DO with I.D. dov_id from RegisteredDO list of that current viewer
907 removal of dov_id element is done by replacing it with the last entry in RegistDO
908 list. If not found, nothing happens.
909 */
SUMA_UnRegisterDO_idcode(char * idcode_str,SUMA_SurfaceViewer * cSV)910 SUMA_Boolean SUMA_UnRegisterDO_idcode(char *idcode_str, SUMA_SurfaceViewer *cSV)
911 {
912 static char FuncName[]={"SUMA_UnRegisterDO_idcode"};
913 int id = SUMA_FindDOi_byID(SUMAg_DOv, SUMAg_N_DOv, idcode_str), isv;
914 SUMA_Boolean LocalHead = NOPE;
915
916 SUMA_ENTRY;
917
918 SUMA_LH("Unregistering %s, iid %d (%s), sv %p",
919 idcode_str, id, iDO_label(id), cSV);
920 if (id >= 0) {
921 if (cSV) {
922 SUMA_RETURN(SUMA_UnRegisterDO(id, cSV));
923 } else {
924 for (isv=0; isv<SUMAg_N_SVv; ++isv) {
925 SUMA_UnRegisterDO(id,SUMAg_SVv+isv);
926 }
927 SUMA_RETURN(YUP);
928 }
929 }
930 SUMA_RETURN(YUP);
931 }
932
SUMA_UnRegisterDO(int dov_id,SUMA_SurfaceViewer * cSV)933 SUMA_Boolean SUMA_UnRegisterDO(int dov_id, SUMA_SurfaceViewer *cSV)
934 {
935 int i;
936 static char FuncName[]={"SUMA_UnRegisterDO"};
937 SUMA_ALL_DO *ado=NULL;
938 SUMA_Boolean LocalHead = NOPE;
939
940 SUMA_ENTRY;
941
942 if (!cSV) SUMA_RETURN(NOPE);
943
944 if (LocalHead) {
945 fprintf (SUMA_STDERR,"%s: RegistDO begins (target %d -- %s):\n",
946 FuncName, dov_id, ADO_LABEL((SUMA_ALL_DO*)SUMAg_DOv[dov_id].OP));
947 for (i=0; i< cSV->N_DO; ++i) {
948 fprintf(SUMA_STDERR,"RegistDO[%d] = %d in DOv (%s)\n",
949 i, cSV->RegistDO[i].dov_ind,
950 ADO_LABEL((SUMA_ALL_DO*)SUMAg_DOv[cSV->RegistDO[i].dov_ind].OP));
951 }
952 fprintf(SUMA_STDERR,"\n");
953 }
954
955 /* check to see if dov_id exists */
956 i = 0;
957 while (i < cSV->N_DO) {
958 if (cSV->RegistDO[i].dov_ind == dov_id) {
959 SUMA_LH("Removing %d", dov_id);
960 /* found, replace it by the last in the list */
961 cSV->RegistDO[i].dov_ind = cSV->RegistDO[cSV->N_DO-1].dov_ind;
962 if (i != cSV->N_DO-1) {
963 strcpy(cSV->RegistDO[i].idcode_str,
964 cSV->RegistDO[cSV->N_DO-1].idcode_str);
965 }
966 /*remove the last element of the list */
967 cSV->RegistDO[cSV->N_DO-1].dov_ind = -1;
968 cSV->RegistDO[cSV->N_DO-1].idcode_str[0]='\0';
969 cSV->N_DO -= 1;
970
971 /* empty the ColorList for this surface */
972 ado = iDO_ADO(dov_id);
973 switch (ado->do_type) {
974 case SO_type:
975 SUMA_LH("Emptying ColorList ...");
976 if (!SUMA_EmptyColorList (cSV, ADO_ID(ado))) {
977 SUMA_S_Err("Failed in SUMA_EmptyColorList\n");
978 SUMA_RETURN(NOPE);
979 }
980 break;
981 case GRAPH_LINK_type: {
982 SUMA_DSET *dset=SUMA_find_GLDO_Dset((SUMA_GraphLinkDO *)ado);
983 if (dset) SUMA_RETURN(SUMA_EmptyColorList(cSV,SDSET_ID(dset)));
984 } break;
985 default:
986 if (!SUMA_EmptyColorList (cSV, ADO_ID(ado))) {
987 SUMA_S_Err("Failed to empty color list for %s, type %s\n",
988 ADO_LABEL(ado), ADO_TNAME(ado));
989 SUMA_RETURN(NOPE);
990 }
991 break;
992 }
993
994 if (LocalHead) {
995 fprintf (SUMA_STDERR,"%s: RegistDO is now:\n", FuncName);
996 for (i=0; i< cSV->N_DO; ++i) {
997 fprintf(SUMA_STDERR,"RegistDO[%d] = %d in DOv (%s)\n",
998 i, cSV->RegistDO[i].dov_ind,
999 ADO_LABEL((SUMA_ALL_DO*)SUMAg_DOv[cSV->RegistDO[i].dov_ind].OP));
1000 }
1001 fprintf(SUMA_STDERR,"\n");
1002 }
1003
1004 /* update the title bar */
1005 SUMA_UpdateViewerTitle(cSV);
1006
1007
1008 SUMA_RETURN(YUP);
1009 }
1010 ++i;
1011 }
1012 /* Not found, nothing happens */
1013
1014 if (LocalHead) {
1015 fprintf (SUMA_STDERR,"%s: Nothing found, registeredDO still:\n", FuncName);
1016 for (i=0; i< cSV->N_DO; ++i) {
1017 fprintf(SUMA_STDERR,"RegistDO[%d] = %d\t", i, cSV->RegistDO[i].dov_ind);
1018 }
1019 fprintf(SUMA_STDERR,"\n");
1020 SUMA_DUMP_TRACE("Why nothing found?");
1021 }
1022
1023 SUMA_RETURN(YUP);
1024 }
1025
1026
SUMA_DOv_Info(SUMA_DO * dov,int N_dov,int detail)1027 char *SUMA_DOv_Info (SUMA_DO *dov, int N_dov, int detail)
1028 {
1029 static char FuncName[]={"SUMA_DOv_Info"};
1030 int i;
1031 SUMA_COL_TYPE ctp;
1032 char *s=NULL, stmp[200];
1033 SUMA_SurfaceObject *so_op=NULL;
1034 SUMA_VolumeObject *vo_op=NULL;
1035 SUMA_CIFTI_DO *co=NULL;
1036 SUMA_STRING *SS=NULL;
1037 SUMA_Boolean LocalHead = NOPE;
1038 SUMA_ENTRY;
1039
1040 SS = SUMA_StringAppend(NULL, NULL);
1041
1042 if (dov) {
1043 SS = SUMA_StringAppend_va(SS, "\nDOv contents (%d elements):\n", N_dov);
1044 for (i=0; i < N_dov; ++i) {
1045 switch (dov[i].ObjectType) {
1046 case VO_type:
1047 vo_op = (SUMA_VolumeObject *)dov[i].OP;
1048 SS = SUMA_StringAppend_va(SS,
1049 "DOv ID: %d\n\tName: %s\n"
1050 "\tType: %d (%s), Axis Attachment %d\n",
1051 i, SUMA_CHECK_NULL_STR(vo_op->Label),
1052 dov[i].ObjectType,
1053 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1054 dov[i].CoordType);
1055 break;
1056 case CDOM_type:
1057 co = (SUMA_CIFTI_DO *)dov[i].OP;
1058 SS = SUMA_StringAppend_va(SS,
1059 "DOv ID: %d\n\tName: %s\n"
1060 "\tType: %d (%s), Axis Attachment %d\n",
1061 i, SUMA_CHECK_NULL_STR(co->Label),
1062 dov[i].ObjectType,
1063 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1064 dov[i].CoordType);
1065 break;
1066 case SO_type:
1067 so_op = (SUMA_SurfaceObject *)dov[i].OP;
1068 #if 0
1069 if (so_op->FileType != SUMA_SUREFIT) {
1070 SS = SUMA_StringAppend_va(SS,
1071 "DOv ID: %d\n\tName: %s/%s\n"
1072 "\tType: %d (%s), Axis Attachment %d\n",
1073 i, SUMA_CHECK_NULL_STR(so_op->Name.Path),
1074 SUMA_CHECK_NULL_STR(so_op->Name.FileName),
1075 dov[i].ObjectType,
1076 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1077 dov[i].CoordType);
1078 } else {
1079 SS = SUMA_StringAppend_va(SS,
1080 "DOv ID: %d\n\tNameCoord: %s/%s\n"
1081 "\tNameTopo: %s/%s\n\tType: %d (%s), Axis Attachment %d\n",
1082 i, SUMA_CHECK_NULL_STR(so_op->Name_coord.Path),
1083 SUMA_CHECK_NULL_STR(so_op->Name_coord.FileName),
1084 so_op->Name_topo.Path, so_op->Name_topo.FileName,
1085 dov[i].ObjectType,
1086 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1087 dov[i].CoordType);
1088 }
1089 #else
1090 SS = SUMA_StringAppend_va(SS,
1091 "DOv ID: %d\n\tName: %s\n"
1092 "\tType: %d (%s), Axis Attachment %d\n",
1093 i, SUMA_CHECK_NULL_STR(so_op->Label),
1094 dov[i].ObjectType,
1095 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1096 dov[i].CoordType);
1097 #endif
1098 break;
1099 case AO_type:
1100 {
1101 SUMA_Axis* ao;
1102 SUMA_LH("HERE\n");
1103 ao = (SUMA_Axis*) dov[i].OP;
1104 SS = SUMA_StringAppend_va(SS,
1105 "DOv ID: %d\n\tAxis Object\n"
1106 "\tType: %d (%s), Axis Attachment %d\n",
1107 i,dov[i].ObjectType,
1108 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1109 dov[i].CoordType);
1110 SS = SUMA_StringAppend_va(SS,
1111 "\tName: %s\n\tidcode: %s\n", ao->Label, ao->idcode_str);
1112 }
1113 break;
1114 case OLS_type:
1115 {
1116 SUMA_SegmentDO *sdo=NULL;
1117
1118 sdo = (SUMA_SegmentDO *)dov[i].OP;
1119 SS = SUMA_StringAppend_va(SS,
1120 "DOv ID: %d\n\tOriented Line Segment Object\n"
1121 "\tType: %d (%s), Axis Attachment %d\n",
1122 i,dov[i].ObjectType,
1123 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1124 dov[i].CoordType);
1125 SS = SUMA_StringAppend_va(SS,
1126 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1127
1128 }
1129 break;
1130 case DIR_type:
1131 {
1132 SUMA_SegmentDO *sdo=NULL;
1133
1134 sdo = (SUMA_SegmentDO *)dov[i].OP;
1135 SS = SUMA_StringAppend_va(SS,
1136 "DOv ID: %d\n\tDirection Object\n"
1137 "\tType: %d (%s), Axis Attachment %d\n",
1138 i,dov[i].ObjectType,
1139 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1140 dov[i].CoordType);
1141 SS = SUMA_StringAppend_va(SS,
1142 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1143 }
1144 break;
1145 case ODIR_type:
1146 {
1147 SUMA_SegmentDO *sdo=NULL;
1148
1149 sdo = (SUMA_SegmentDO *)dov[i].OP;
1150 SS = SUMA_StringAppend_va(SS,
1151 "DOv ID: %d\n\tOriented Direction Object\n"
1152 "\tType: %d (%s), Axis Attachment %d\n",
1153 i,dov[i].ObjectType,
1154 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1155 dov[i].CoordType);
1156 SS = SUMA_StringAppend_va(SS,
1157 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1158
1159 }
1160 break;
1161 case ONBV_type:
1162 {
1163 SUMA_SegmentDO *sdo=NULL;
1164
1165 sdo = (SUMA_SegmentDO *)dov[i].OP;
1166 SS = SUMA_StringAppend_va(SS,
1167 "DOv ID: %d\n\tNode-Based Ball-Vector\n"
1168 "\tType: %d (%s), Axis Attachment %d\n",
1169 i,dov[i].ObjectType,
1170 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1171 dov[i].CoordType);
1172 SS = SUMA_StringAppend_va(SS,
1173 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1174
1175 }
1176 break;
1177 case NBV_type:
1178 {
1179 SUMA_SegmentDO *sdo=NULL;
1180
1181 sdo = (SUMA_SegmentDO *)dov[i].OP;
1182 SS = SUMA_StringAppend_va(SS,
1183 "DOv ID: %d\n\tNode-Based Vector\n"
1184 "\tType: %d (%s), Axis Attachment %d\n",
1185 i,dov[i].ObjectType,
1186 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1187 dov[i].CoordType);
1188 SS = SUMA_StringAppend_va(SS,
1189 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1190
1191 }
1192 break;
1193 case LS_type:
1194 {
1195 SUMA_SegmentDO *sdo=NULL;
1196
1197 sdo = (SUMA_SegmentDO *)dov[i].OP;
1198 SS = SUMA_StringAppend_va(SS,
1199 "DOv ID: %d\n\tLine Segment Object\n"
1200 "\tType: %d (%s), Axis Attachment %d\n",
1201 i,dov[i].ObjectType,
1202 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1203 dov[i].CoordType);
1204 SS = SUMA_StringAppend_va(SS,
1205 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1206
1207 }
1208 break;
1209 case NBSP_type:
1210 {
1211 SUMA_SphereDO *sdo=NULL;
1212
1213 sdo = (SUMA_SphereDO *)dov[i].OP;
1214 SS = SUMA_StringAppend_va(SS,
1215 "DOv ID: %d\n\tNode-Based Sphere Object\n"
1216 "\tType: %d (%s), Axis Attachment %d\n",
1217 i,dov[i].ObjectType,
1218 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1219 dov[i].CoordType);
1220 SS = SUMA_StringAppend_va(SS,
1221 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1222
1223 }
1224 break;
1225 case SP_type:
1226 {
1227 SUMA_SphereDO *sdo=NULL;
1228
1229 sdo = (SUMA_SphereDO *)dov[i].OP;
1230 SS = SUMA_StringAppend_va(SS,
1231 "DOv ID: %d\n\tSphere Object\n"
1232 "\tType: %d (%s), Axis Attachment %d\n",
1233 i,dov[i].ObjectType,
1234 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1235 dov[i].CoordType);
1236 SS = SUMA_StringAppend_va(SS,
1237 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1238
1239 }
1240 break;
1241 case PNT_type:
1242 {
1243 SUMA_SphereDO *sdo=NULL;
1244
1245 sdo = (SUMA_SphereDO *)dov[i].OP;
1246 SS = SUMA_StringAppend_va(SS,
1247 "DOv ID: %d\n\tPoint Object\n"
1248 "\tType: %d (%s), Axis Attachment %d\n",
1249 i,dov[i].ObjectType,
1250 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1251 dov[i].CoordType);
1252 SS = SUMA_StringAppend_va(SS,
1253 "\tLabel: %s\n\tidcode: %s\n", sdo->Label, sdo->idcode_str);
1254
1255 }
1256 break;
1257 case PL_type:
1258 {
1259 SUMA_PlaneDO *pdo=NULL;
1260
1261 pdo = (SUMA_PlaneDO *)dov[i].OP;
1262 SS = SUMA_StringAppend_va(SS,
1263 "DOv ID: %d\n\tPlane Object\n"
1264 "\tType: %d (%s), Axis Attachment %d\n",
1265 i,dov[i].ObjectType,
1266 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1267 dov[i].CoordType);
1268 SS = SUMA_StringAppend_va(SS,
1269 "\tLabel: %s\n\tidcode: %s\n", pdo->Label, pdo->idcode_str);
1270
1271 }
1272 break;
1273 case ROIdO_type:
1274 {
1275 SUMA_DRAWN_ROI *dROI = NULL;
1276
1277 dROI = (SUMA_DRAWN_ROI *)dov[i].OP;
1278 SS = SUMA_StringAppend_va(SS,
1279 "DOv ID: %d\n\tLine Segment Object\n"
1280 "\tType: %d (%s), Axis Attachment %d\n",
1281 i,dov[i].ObjectType,
1282 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1283 dov[i].CoordType);
1284 SS = SUMA_StringAppend_va(SS,
1285 "\tLabel: %s\n\tidcode: %s\n",
1286 dROI->Label, dROI->idcode_str);
1287 }
1288 break;
1289 case ROIO_type:
1290 {
1291 SUMA_ROI *ROI = NULL;
1292
1293 ROI = (SUMA_ROI *)dov[i].OP;
1294 SS = SUMA_StringAppend_va(SS,
1295 "DOv ID: %d\n\tLine Segment Object\n"
1296 "\tType: %d (%s), Axis Attachment %d\n",
1297 i,dov[i].ObjectType,
1298 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1299 dov[i].CoordType);
1300 SS = SUMA_StringAppend_va(SS,"\tLabel: %s\n\tidcode: %s\n",
1301 ROI->Label, ROI->idcode_str);
1302 }
1303 break;
1304 case GO_type:
1305 SS = SUMA_StringAppend_va(SS,"DOv ID: %d\n\tGrid Object\n", i);
1306 break;
1307 case NIDO_type:
1308 SS = SUMA_StringAppend_va(SS,
1309 "DOv ID: %d\n\tNIDO Object\n"
1310 "\tType: %d (%s), Axis Attachment %d\n",
1311 i,dov[i].ObjectType,
1312 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1313 dov[i].CoordType);
1314 break;
1315 case GRAPH_LINK_type: {
1316 SUMA_GraphLinkDO *gldo=(SUMA_GraphLinkDO *)dov[i].OP;
1317 SUMA_DSET *dset = SUMA_find_GLDO_Dset(gldo);
1318 SS = SUMA_StringAppend_va(SS,
1319 "DOv ID: %d\n\tGLDO Label: %s, id: %s%s\n"
1320 "\tType: %d (%s), Axis Attachment %d, Variant: %s,\n"
1321 "\tParent: %s (id %s)\n",
1322 i, gldo->Label, gldo->idcode_str,
1323 strcmp(gldo->variant,"TheShadow")?
1324 "":"(id always same as Parent's)",
1325 dov[i].ObjectType,
1326 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1327 dov[i].CoordType,
1328 gldo->variant, SDSET_LABEL(dset), gldo->Parent_idcode_str);
1329 break; }
1330 case TRACT_type: {
1331 SS = SUMA_StringAppend_va(SS,
1332 "DOv ID: %d\n\tTract Object\n"
1333 "\tType: %d (%s), Axis Attachment %d\n",
1334 i,dov[i].ObjectType,
1335 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1336 dov[i].CoordType);
1337 break; }
1338 case MASK_type: {
1339 SS = SUMA_StringAppend_va(SS,
1340 "DOv ID: %d\tLabel: %s\n\tMask Object\n"
1341 "\tType: %d (%s), Axis Attachment %d\n",
1342 i, ADO_LABEL((SUMA_ALL_DO *)dov[i].OP),
1343 dov[i].ObjectType,
1344 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType),
1345 dov[i].CoordType);
1346 break; }
1347 default:
1348 SS = SUMA_StringAppend_va(SS,"DOv ID: %d\n"
1349 "\tUnknown Type (%d) %s!\n",
1350 i, dov[i].ObjectType,
1351 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType)
1352 );
1353 break;
1354 }
1355 }
1356
1357 } else {
1358 SS = SUMA_StringAppend(SS, "NULL DO.");
1359 }
1360
1361 SUMA_SS2S(SS, s);
1362
1363 SUMA_RETURN(s);
1364 }
1365
SUMA_TractDOInfo(SUMA_TractDO * tdo,int detail)1366 char *SUMA_TractDOInfo (SUMA_TractDO *tdo, int detail)
1367 {
1368 static char FuncName[]={"SUMA_TractDOInfo"};
1369 int i;
1370 SUMA_COL_TYPE ctp;
1371 char *s=NULL, stmp[200];
1372 SUMA_STRING *SS=NULL;
1373 NI_group *ngr=NULL;
1374
1375 SUMA_ENTRY;
1376
1377 SS = SUMA_StringAppend(NULL, NULL);
1378
1379 if (tdo) {
1380 SS = SUMA_StringAppend_va(SS, "Tract %p\n", tdo);
1381 s = SUMA_Taylor_Network_Info(tdo->net, 2,5);
1382 SS = SUMA_StringAppend(SS,s);
1383 SUMA_ifree(s);
1384 } else {
1385 SS = SUMA_StringAppend(SS, "NULL Tract.");
1386 }
1387
1388 SUMA_SS2S(SS, s);
1389
1390 SUMA_RETURN(s);
1391 }
1392
SUMA_MaskDOInfo(SUMA_MaskDO * mdo,int detail)1393 char *SUMA_MaskDOInfo (SUMA_MaskDO *mdo, int detail)
1394 {
1395 static char FuncName[]={"SUMA_MaskDOInfo"};
1396 int i;
1397 SUMA_COL_TYPE ctp;
1398 char *s=NULL, stmp[200];
1399 SUMA_STRING *SS=NULL;
1400 NI_group *ngr=NULL;
1401
1402 SUMA_ENTRY;
1403
1404 SS = SUMA_StringAppend(NULL, NULL);
1405
1406 if (mdo) {
1407 SS = SUMA_StringAppend_va(SS, "Mask %p\n", mdo);
1408 SS = SUMA_StringAppend(SS,"No info for masks yet.");
1409 SUMA_ifree(s);
1410 } else {
1411 SS = SUMA_StringAppend(SS, "NULL Mask.");
1412 }
1413
1414 SUMA_SS2S(SS, s);
1415
1416 SUMA_RETURN(s);
1417 }
1418
SUMA_VolumeObjectInfo(SUMA_VolumeObject * vo,int detail)1419 char *SUMA_VolumeObjectInfo (SUMA_VolumeObject *vo, int detail)
1420 {
1421 static char FuncName[]={"SUMA_VolumeObjectInfo"};
1422 int i;
1423 SUMA_COL_TYPE ctp;
1424 char *s=NULL, stmp[200];
1425 SUMA_STRING *SS=NULL;
1426 NI_group *ngr=NULL;
1427
1428 SUMA_ENTRY;
1429
1430 SS = SUMA_StringAppend(NULL, NULL);
1431
1432 if (vo) {
1433 SS = SUMA_StringAppend_va(SS, "VolumeObject %p\n", vo);
1434 SS = SUMA_StringAppend(SS,"No info for volumes yet.");
1435 SUMA_ifree(s);
1436 } else {
1437 SS = SUMA_StringAppend(SS, "NULL VO.");
1438 }
1439
1440 SUMA_SS2S(SS, s);
1441
1442 SUMA_RETURN(s);
1443 }
1444
1445
1446 /*!
1447 print out the data contained in dov
1448 */
SUMA_Show_DOv(SUMA_DO * dov,int N_dov,FILE * Out)1449 void SUMA_Show_DOv (SUMA_DO *dov, int N_dov, FILE *Out)
1450 {
1451 int i;
1452 char *si=NULL;
1453 static char FuncName[]={"SUMA_Show_DOv"};
1454
1455 SUMA_ENTRY;
1456
1457 if (Out == NULL) Out = stdout;
1458
1459 si = SUMA_DOv_Info(dov, N_dov, 0);
1460
1461 fprintf(Out,"%s\n", si);
1462
1463 if (si) SUMA_free(si); si = NULL;
1464
1465 SUMA_RETURNe;
1466 }
1467
1468 /*!
1469 returns a vector of indices into dov for DO that meet DO_Type
1470 You should free the returned pointer once you're done with it
1471 N contains the number of elements found
1472 */
SUMA_GetDO_Type(SUMA_DO * dov,int N_dov,SUMA_DO_Types DO_Type,int * N)1473 int * SUMA_GetDO_Type(SUMA_DO *dov, int N_dov, SUMA_DO_Types DO_Type, int *N)
1474 {
1475 static char FuncName[]={"SUMA_GetDO_Type"};
1476 int *do_id, i;
1477 SUMA_Boolean LocalHead = NOPE;
1478
1479 SUMA_ENTRY;
1480
1481 *N = 0;
1482
1483 do_id = (int *)SUMA_calloc (SUMA_MAX_DISPLAYABLE_OBJECTS, sizeof(int));
1484
1485 if (do_id == NULL) {
1486 fprintf(stderr,"Error SUMA_GetDO_Type: Could not allocate for do_id\n");
1487 SUMA_RETURN(NULL);
1488 }
1489 i = 0;
1490 while (i < N_dov) {
1491 if (dov[i].ObjectType == DO_Type) {
1492 do_id[*N] = i;
1493 *N = *N + 1;
1494 }
1495 ++i;
1496 }
1497 SUMA_RETURN(do_id);
1498 }
1499
1500 /*!
1501 searches all SO_type DO objects for idcode
1502 YUP if found, NOPE if not
1503 */
SUMA_existSO(char * idcode,SUMA_DO * dov,int N_dov)1504 SUMA_Boolean SUMA_existSO(char *idcode, SUMA_DO *dov, int N_dov)
1505 {
1506 static char FuncName[]={"SUMA_existSO"};
1507 SUMA_SurfaceObject *SO;
1508 int i;
1509
1510 SUMA_ENTRY;
1511
1512 if (idcode == NULL) {
1513 fprintf(SUMA_STDERR,"Warning SUMA_existSO: NULL idcode.\n");
1514 SUMA_RETURN (NOPE);
1515 }
1516 for (i=0; i< N_dov; ++i) {
1517 if (dov[i].ObjectType == SO_type) {
1518 SO = (SUMA_SurfaceObject *)dov[i].OP;
1519 if (strcmp(idcode, SO->idcode_str)== 0) {
1520 SUMA_RETURN (YUP);
1521 }
1522 }
1523 }
1524 SUMA_RETURN(NOPE);
1525 }
1526 /*!
1527 searches all VO_type DO objects for idcode
1528 YUP if found, NOPE if not
1529 */
SUMA_existVO(char * idcode,SUMA_DO * dov,int N_dov)1530 SUMA_Boolean SUMA_existVO(char *idcode, SUMA_DO *dov, int N_dov)
1531 {
1532 static char FuncName[]={"SUMA_existVO"};
1533 SUMA_VolumeObject *VO;
1534 int i;
1535
1536 SUMA_ENTRY;
1537
1538 if (idcode == NULL) {
1539 fprintf(SUMA_STDERR,"Warning SUMA_existVO: NULL idcode.\n");
1540 SUMA_RETURN (NOPE);
1541 }
1542 for (i=0; i< N_dov; ++i) {
1543 if (dov[i].ObjectType == VO_type) {
1544 VO = (SUMA_VolumeObject *)dov[i].OP;
1545 if (strcmp(idcode, VO->idcode_str)== 0) {
1546 SUMA_RETURN (YUP);
1547 }
1548 }
1549 }
1550 SUMA_RETURN(NOPE);
1551 }
1552
1553 /*!
1554 searches all DO objects with an idcode_str for idcode
1555
1556 YUP if found, NOPE if not
1557 */
SUMA_existDO(char * idcode,SUMA_DO * dov,int N_dov)1558 SUMA_Boolean SUMA_existDO(char *idcode, SUMA_DO *dov, int N_dov)
1559 {
1560 static char FuncName[]={"SUMA_existDO"};
1561 int i;
1562 SUMA_SurfaceObject *SO = NULL;
1563 SUMA_VolumeObject *VO = NULL;
1564 SUMA_DRAWN_ROI *dROI = NULL;
1565 SUMA_ROI *ROI = NULL;
1566 SUMA_SegmentDO *sdo = NULL;
1567 SUMA_Axis *sax = NULL;
1568 SUMA_SphereDO *spdo=NULL;
1569 SUMA_NIDO *nido=NULL;
1570 SUMA_ENTRY;
1571
1572 if (idcode == NULL) {
1573 fprintf(SUMA_STDERR,"Warning %s: NULL idcode.\n", FuncName);
1574 SUMA_RETURN (NOPE);
1575 }
1576 for (i=0; i< N_dov; ++i) {
1577 switch (dov[i].ObjectType) {
1578 case (VO_type):
1579 VO = (SUMA_VolumeObject *)dov[i].OP;
1580 if (strcmp(idcode, VO->idcode_str)== 0) {
1581 SUMA_RETURN (YUP);
1582 }
1583 break;
1584 case (SO_type):
1585 SO = (SUMA_SurfaceObject *)dov[i].OP;
1586 if (strcmp(idcode, SO->idcode_str)== 0) {
1587 SUMA_RETURN (YUP);
1588 }
1589 break;
1590 case (ROIdO_type):
1591 dROI = (SUMA_DRAWN_ROI *)dov[i].OP;
1592 if (strcmp(idcode, dROI->idcode_str)== 0) {
1593 SUMA_RETURN (YUP);
1594 }
1595 break;
1596 case (ROIO_type):
1597 ROI = (SUMA_ROI *)dov[i].OP;
1598 if (strcmp(idcode, ROI->idcode_str)== 0) {
1599 SUMA_RETURN (YUP);
1600 }
1601 break;
1602 case (AO_type):
1603 sax = (SUMA_Axis *)dov[i].OP;
1604 if (strcmp(idcode, sax->idcode_str)== 0) {
1605 SUMA_RETURN (YUP);
1606 }
1607 break;
1608 case (SP_type):
1609 spdo = (SUMA_SphereDO *)dov[i].OP;
1610 if (strcmp(idcode, spdo->idcode_str)== 0) {
1611 SUMA_RETURN (YUP);
1612 }
1613 break;
1614 case (OLS_type):
1615 case (LS_type):
1616 sdo = (SUMA_SegmentDO *)dov[i].OP;
1617 if (strcmp(idcode, sdo->idcode_str)== 0) {
1618 SUMA_RETURN (YUP);
1619 }
1620 break;
1621 case (NIDO_type):
1622 nido = (SUMA_NIDO *)dov[i].OP;
1623 if (strcmp(idcode, nido->idcode_str)== 0) {
1624 SUMA_RETURN (i);
1625 }
1626 break;
1627 default:
1628 SUMA_S_Warnv("Object type %d not checked.\n", dov[i].ObjectType);
1629 break;
1630 }
1631 }
1632 SUMA_RETURN(NOPE);
1633 }
1634
SUMA_DO_dbg_info(char * idcode)1635 char *SUMA_DO_dbg_info(char *idcode)
1636 {
1637 static char FuncName[]={"SUMA_DO_dbg_info"};
1638 static int icall=0;
1639 static char Ret[10][500];
1640 char *s=NULL;
1641 int doid;
1642 SUMA_ALL_DO *ado=NULL;
1643
1644 SUMA_ENTRY;
1645 ++icall; if (icall > 9) icall = 0;
1646 s = (char *)Ret[icall];
1647 s[0] = '\0';
1648
1649 if (!idcode) {
1650 snprintf(s,499,"NULL idcode passed");
1651 } else if ( (doid = SUMA_whichDOg(idcode)) < 0) {
1652 snprintf(s,499,"id %s not found in global list.", idcode);
1653 } else {
1654 ado = iDO_ADO(doid);
1655 snprintf(s,499,"id %s: %s %s",
1656 idcode, ADO_LABEL(ado), ADO_TNAME(ado));
1657 }
1658 SUMA_RETURN(s);
1659 }
1660
1661 /*!
1662 searches for DO object with an idcode_str equal to idcode
1663 It returns the DO's index into dov
1664 -1 if nothing was found
1665
1666 */
SUMA_whichDO(char * idcode,SUMA_DO * dov,int N_dov)1667 int SUMA_whichDO(char *idcode, SUMA_DO *dov, int N_dov)
1668 {
1669 static char FuncName[]={"SUMA_whichDO"};
1670 int i;
1671 SUMA_VolumeObject *VO = NULL;
1672 SUMA_SurfaceObject *SO = NULL;
1673 SUMA_DRAWN_ROI *dROI = NULL;
1674 SUMA_ROI *ROI = NULL;
1675 SUMA_SegmentDO *sdo = NULL;
1676 SUMA_Axis *sax = NULL;
1677 SUMA_SphereDO *spdo=NULL;
1678 SUMA_NIDO *nido=NULL;
1679 SUMA_GraphLinkDO *gldo =NULL;
1680 SUMA_TractDO *tdo = NULL;
1681 SUMA_MaskDO *mdo=NULL;
1682 SUMA_CIFTI_DO *CO=NULL;
1683 SUMA_Boolean LocalHead=NOPE;
1684
1685 SUMA_ENTRY;
1686
1687 if (SUMA_IS_EMPTY_STR_ATTR(idcode)) { /* might come in as ~ at times */
1688 fprintf(SUMA_STDERR,"Warning %s: NULL idcode.\n", FuncName);
1689 if (LocalHead) SUMA_DUMP_TRACE("NUULL id");
1690 SUMA_RETURN (-1);
1691 }
1692 for (i=0; i< N_dov; ++i) {
1693 switch (dov[i].ObjectType) {
1694 case (VO_type):
1695 VO = (SUMA_VolumeObject *)dov[i].OP;
1696 if (strcmp(idcode, VO->idcode_str)== 0) {
1697 SUMA_RETURN (i);
1698 }
1699 break;
1700 case (SO_type):
1701 SO = (SUMA_SurfaceObject *)dov[i].OP;
1702 if (strcmp(idcode, SO->idcode_str)== 0) {
1703 SUMA_RETURN (i);
1704 }
1705 break;
1706 case (ROIdO_type):
1707 dROI = (SUMA_DRAWN_ROI *)dov[i].OP;
1708 if (strcmp(idcode, dROI->idcode_str)== 0) {
1709 SUMA_RETURN (i);
1710 }
1711 break;
1712 case (ROIO_type):
1713 ROI = (SUMA_ROI *)dov[i].OP;
1714 if (strcmp(idcode, ROI->idcode_str)== 0) {
1715 SUMA_RETURN (i);
1716 }
1717 break;
1718 case (AO_type):
1719 sax = (SUMA_Axis *)dov[i].OP;
1720 if (strcmp(idcode, sax->idcode_str)== 0) {
1721 SUMA_RETURN (i);
1722 }
1723 break;
1724 case (SP_type):
1725 spdo = (SUMA_SphereDO *)dov[i].OP;
1726 if (strcmp(idcode, spdo->idcode_str)== 0) {
1727 SUMA_RETURN (i);
1728 }
1729 break;
1730 case (OLS_type):
1731 case (LS_type):
1732 sdo = (SUMA_SegmentDO *)dov[i].OP;
1733 if (strcmp(idcode, sdo->idcode_str)== 0) {
1734 SUMA_RETURN (i);
1735 }
1736 break;
1737 case (NIDO_type):
1738 nido = (SUMA_NIDO *)dov[i].OP;
1739 if (strcmp(idcode, nido->idcode_str)== 0) {
1740 SUMA_RETURN (i);
1741 }
1742 break;
1743 case (GRAPH_LINK_type):
1744 gldo = (SUMA_GraphLinkDO *)dov[i].OP;
1745 if (strcmp(idcode, gldo->idcode_str)== 0) {
1746 SUMA_RETURN (i);
1747 }
1748 break;
1749 case TRACT_type:
1750 tdo = (SUMA_TractDO *)dov[i].OP;
1751 if (strcmp(idcode, tdo->idcode_str)== 0) {
1752 SUMA_RETURN (i);
1753 }
1754 break;
1755 case MASK_type:
1756 mdo = (SUMA_MaskDO *)dov[i].OP;
1757 if (strcmp(idcode, mdo->idcode_str)== 0) {
1758 SUMA_RETURN (i);
1759 }
1760 break;
1761 case CDOM_type:
1762 CO = (SUMA_CIFTI_DO *)dov[i].OP;
1763 if (strcmp(idcode, CO->idcode_str)== 0) {
1764 SUMA_RETURN (i);
1765 }
1766 break;
1767 default:
1768 SUMA_S_Warnv("Object type %d (%s) not checked.\n",
1769 dov[i].ObjectType,
1770 SUMA_ObjectTypeCode2ObjectTypeName(dov[i].ObjectType));
1771 break;
1772 }
1773 }
1774 SUMA_RETURN(-1);
1775 }
1776
SUMA_whichADO(char * idcode,SUMA_DO * dov,int N_dov)1777 SUMA_ALL_DO* SUMA_whichADO(char *idcode, SUMA_DO *dov, int N_dov)
1778 {
1779 static char FuncName[]={"SUMA_whichADO"};
1780 int ido = SUMA_whichDO(idcode, dov, N_dov);
1781
1782 if (ido < 0) return(NULL);
1783 return((SUMA_ALL_DO *)dov[ido].OP);
1784 }
1785
1786 /*!
1787 ans = SUMA_findSO_inDOv(idcode, dov, N_dov);
1788 searches all SO_type DO objects for idcode
1789
1790 \param idcode (char *) idcode of SO you are searching for
1791 \param dov (SUMA_DO*) pointer to vector of Displayable Objects,
1792 typically SUMAg_DOv
1793 \param N_dov (int) number of DOs in dov
1794 \return ans (int) index into dov of object with matching idcode
1795 -1 if not found
1796 \sa SUMA_findSOp_inDOv
1797 */
SUMA_findSO_inDOv(char * idcode,SUMA_DO * dov,int N_dov)1798 int SUMA_findSO_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
1799 {
1800 static char FuncName[]={"SUMA_findSO_inDOv"};
1801 SUMA_SurfaceObject *SO;
1802 int i;
1803 SUMA_Boolean LocalHead = NOPE;
1804
1805 SUMA_ENTRY;
1806
1807 for (i=0; i<N_dov; ++i) {
1808 if (dov[i].ObjectType == SO_type) {
1809 SO = (SUMA_SurfaceObject *)dov[i].OP;
1810 if (LocalHead)
1811 fprintf (SUMA_STDERR,
1812 "%s: Comparing \n\t:%s:to\n\t:%s:\n",
1813 FuncName, idcode, SO->idcode_str);
1814 if (strcmp(idcode, SO->idcode_str)== 0) {
1815 SUMA_RETURN (i);
1816 }
1817 }
1818 }
1819 SUMA_RETURN(-1);
1820 }
1821 /*!
1822 ans = SUMA_findVO_inDOv(idcode, dov, N_dov);
1823 searches all VO_type DO objects for idcode
1824
1825 \param idcode (char *) idcode of VO you are searching for
1826 \param dov (SUMA_DO*) pointer to vector of Displayable Objects,
1827 typically SUMAg_DOv
1828 \param N_dov (int) number of DOs in dov
1829 \return ans (int) index into dov of object with matching idcode
1830 -1 if not found
1831 \sa SUMA_findVOp_inDOv
1832 */
SUMA_findVO_inDOv(char * idcode,SUMA_DO * dov,int N_dov)1833 int SUMA_findVO_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
1834 {
1835 static char FuncName[]={"SUMA_findVO_inDOv"};
1836 SUMA_VolumeObject *VO;
1837 int i;
1838 SUMA_Boolean LocalHead = NOPE;
1839
1840 SUMA_ENTRY;
1841
1842 for (i=0; i<N_dov; ++i) {
1843 if (dov[i].ObjectType == VO_type) {
1844 VO = (SUMA_VolumeObject *)dov[i].OP;
1845 if (LocalHead)
1846 fprintf (SUMA_STDERR,
1847 "%s: Comparing \n\t:%s:to\n\t:%s:\n",
1848 FuncName, idcode, VO->idcode_str);
1849 if (strcmp(idcode, VO->idcode_str)== 0) {
1850 SUMA_RETURN (i);
1851 }
1852 }
1853 }
1854 SUMA_RETURN(-1);
1855 }
1856
1857 /*!
1858
1859 SO = SUMA_findSOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
1860 searches all SO_type DO objects for idcode
1861
1862 \param idcode (char *) idcode of SO you are searching for
1863 \param dov (SUMA_DO*) pointer to vector of Displayable Objects,
1864 typically SUMAg_DOv
1865 \param N_dov (int) number of DOs in dov
1866 \return SO (SUMA_SurfaceObject *) pointer of SO with matching idcode
1867 NULL if not found
1868 \sa SUMA_findSO_inDOv
1869 */
SUMA_findSOp_inDOv(char * idcode,SUMA_DO * dov,int N_dov)1870 SUMA_SurfaceObject * SUMA_findSOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
1871 {
1872 static char FuncName[]={"SUMA_findSOp_inDOv"};
1873 SUMA_SurfaceObject *SO;
1874 int i;
1875
1876 SUMA_ENTRY;
1877
1878 if (!idcode) SUMA_RETURN(NULL);
1879
1880 for (i=0; i<N_dov; ++i) {
1881 if (dov[i].ObjectType == SO_type) {
1882 SO = (SUMA_SurfaceObject *)dov[i].OP;
1883 if (strcmp(idcode, SO->idcode_str)== 0) {
1884 SUMA_RETURN (SO);
1885 }
1886 }
1887 }
1888 SUMA_RETURN(NULL);
1889 }
1890
1891 /*!
1892
1893 VO = SUMA_findVOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
1894 searches all VO_type DO objects for idcode
1895
1896 \param idcode (char *) idcode of VO you are searching for
1897 \param dov (SUMA_DO*) pointer to vector of Displayable Objects,
1898 typically SUMAg_DOv
1899 \param N_dov (int) number of DOs in dov
1900 \return VO (SUMA_VolumeObject *) pointer of VO with matching idcode
1901 NULL if not found
1902 \sa SUMA_findVO_inDOv
1903 */
SUMA_findVOp_inDOv(char * idcode,SUMA_DO * dov,int N_dov)1904 SUMA_VolumeObject * SUMA_findVOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
1905 {
1906 static char FuncName[]={"SUMA_findVOp_inDOv"};
1907 SUMA_VolumeObject *VO;
1908 int i;
1909
1910 SUMA_ENTRY;
1911
1912 if (!idcode) SUMA_RETURN(NULL);
1913
1914 for (i=0; i<N_dov; ++i) {
1915 if (dov[i].ObjectType == VO_type) {
1916 VO = (SUMA_VolumeObject *)dov[i].OP;
1917 if (strcmp(idcode, VO->idcode_str)== 0) {
1918 SUMA_RETURN (VO);
1919 }
1920 }
1921 }
1922 SUMA_RETURN(NULL);
1923 }
1924
1925 /*!
1926
1927 SO = SUMA_FindSOp_inDOv_from_N_Node(
1928 int N_Node, SUMA_SO_SIDE side,
1929 int check_unique, int return_parent,
1930 SUMA_DO *dov, int N_dov)
1931 searches all SO_type DO objects for a surface that best accommodates
1932 a mesh with N_Node node .
1933
1934 \param N_Node (int) Number of nodes forming the mesh
1935 \param side (SUMA_SO_SIDE) surface must be of the same side as 'side'
1936 \param check_unique (int): if 1, then be sure there is only one match
1937 \param return_parent (int): return local domain parent for that surface
1938 \param dov (SUMA_DO*) pointer to vector of Displayable Objects,
1939 typically SUMAg_DOv
1940 \param N_dov (int) number of DOs in dov
1941 \return SO (SUMA_SurfaceObject *) pointer of SO with matching criteria
1942
1943 Search logic:
1944 For each surface found:
1945 if SO->N_Node == N_Node && same side the return
1946
1947 NULL if not found
1948 \sa SUMA_findSO_inDOv
1949 */
1950
SUMA_FindSOp_inDOv_from_N_Node(int N_Node,SUMA_SO_SIDE side,int check_unique,int return_parent,SUMA_DO * dov,int N_dov)1951 SUMA_SurfaceObject *SUMA_FindSOp_inDOv_from_N_Node(
1952 int N_Node, SUMA_SO_SIDE side,
1953 int check_unique, int return_parent,
1954 SUMA_DO *dov, int N_dov)
1955 {
1956 static char FuncName[]={"SUMA_FindSOp_inDOv_from_N_Node"};
1957 int nFound=0, i = 0;
1958 SUMA_SurfaceObject *SO=NULL, *tSO=NULL;
1959
1960 SUMA_ENTRY;
1961
1962 i=0;
1963 while ((!nFound || check_unique) && i < N_dov) {
1964 if (dov[i].ObjectType == SO_type) {
1965 tSO = (SUMA_SurfaceObject *)dov[i].OP;
1966 if (return_parent &&
1967 !SUMA_isLocalDomainParent(tSO)) { /* Need parent only */
1968 if (!(tSO = SUMA_findSOp_inDOv(
1969 tSO->LocalDomainParentID, dov, N_dov))) {
1970 goto NEXT;
1971 }
1972 }
1973 if ( tSO != SO /* Happens often if you are picking parents */&&
1974 tSO->N_Node == N_Node) { /* candidate */
1975 if (side == SUMA_RIGHT || side == SUMA_LEFT || side == SUMA_LR) {
1976 if (tSO->Side != side) {
1977 goto NEXT;
1978 }
1979 }
1980 /* Looks like we made it */
1981 if (!SO) SO = tSO; /* only find the first */
1982 ++nFound;
1983 }
1984 }
1985 NEXT:
1986 ++i;
1987 }
1988
1989 if (check_unique && nFound > 1) {
1990 if (check_unique > 0) { /* error */
1991 SUMA_SLP_Err("More than 1 SO candidate found");
1992 } else { /* warning */
1993 SUMA_SLP_Warn("More than 1 SO candidate found. Returning first.");
1994 }
1995 }
1996
1997 SUMA_RETURN(SO);
1998 }
1999
SUMA_is_ID_4_SO(char * idcode,SUMA_SurfaceObject ** SOp)2000 SUMA_Boolean SUMA_is_ID_4_SO(char *idcode, SUMA_SurfaceObject **SOp)
2001 {
2002 static char FuncName[]={"SUMA_is_ID_4_SO"};
2003 SUMA_SurfaceObject *SO=NULL;
2004
2005 SUMA_ENTRY;
2006
2007 if (SOp) *SOp = NULL;
2008 if (!idcode) SUMA_RETURN(NOPE);
2009
2010 SO = SUMA_findSOp_inDOv(idcode, SUMAg_DOv, SUMAg_N_DOv);
2011
2012 if (SO) {
2013 if (SOp) *SOp = SO;
2014 SUMA_RETURN(YUP);
2015 }
2016
2017 SUMA_RETURN(NOPE);
2018 }
2019
2020
2021 /*!
2022 Returns an index into dov of a surface domain parent with the largest
2023 number of nodes
2024 */
SUMA_BiggestLocalDomainParent(SUMA_DO * dov,int N_dov)2025 int SUMA_BiggestLocalDomainParent(SUMA_DO *dov, int N_dov)
2026 {
2027 static char FuncName[]={"SUMA_BiggestLocalDomainParent"};
2028 SUMA_SurfaceObject *SO;
2029 int i, imax = -1, MaxNode=-1;
2030
2031 SUMA_ENTRY;
2032 MaxNode = -1;
2033 imax = -1;
2034 for (i=0; i<N_dov; ++i) {
2035 if (dov[i].ObjectType == SO_type) {
2036 SO = (SUMA_SurfaceObject *)dov[i].OP;
2037 if (SUMA_isLocalDomainParent(SO)) {
2038 if (SO->N_Node > MaxNode) {
2039 imax = i;
2040 MaxNode= SO->N_Node;
2041 }
2042 }
2043 }
2044 }
2045
2046 SUMA_RETURN(imax);
2047 }
2048
SUMA_isSurfaceOfSide(SUMA_SurfaceObject * SO,SUMA_SO_SIDE ss)2049 int SUMA_isSurfaceOfSide(SUMA_SurfaceObject *SO, SUMA_SO_SIDE ss)
2050 {
2051 if (!SO) return(0);
2052 if (SO->Side == ss) return(1);
2053 if (ss == SUMA_NO_SIDE || ss == SUMA_SIDE_ERROR) return(1);
2054 return(0);
2055 }
2056
SUMA_BiggestLocalDomainParent_Side(SUMA_DO * dov,int N_dov,SUMA_SO_SIDE ss)2057 int SUMA_BiggestLocalDomainParent_Side(SUMA_DO *dov, int N_dov, SUMA_SO_SIDE ss)
2058 {
2059 static char FuncName[]={"SUMA_BiggestLocalDomainParent_Side"};
2060 SUMA_SurfaceObject *SO;
2061 int i, imax = -1, MaxNode=-1;
2062
2063 SUMA_ENTRY;
2064 MaxNode = -1;
2065 imax = -1;
2066 for (i=0; i<N_dov; ++i) {
2067 if (dov[i].ObjectType == SO_type) {
2068 SO = (SUMA_SurfaceObject *)dov[i].OP;
2069 if (SUMA_isLocalDomainParent(SO) && SUMA_isSurfaceOfSide(SO,ss)) {
2070 if (SO->N_Node > MaxNode) {
2071 imax = i;
2072 MaxNode= SO->N_Node;
2073 }
2074 }
2075 }
2076 }
2077 SUMA_RETURN(imax);
2078 }
2079
2080 /* Try to find any idcode_str, not complete yet */
SUMA_find_any_object(char * idcode_str,SUMA_DO_Types * do_type)2081 void *SUMA_find_any_object(char *idcode_str, SUMA_DO_Types *do_type)
2082 {
2083 static char FuncName[]={"SUMA_find_any_object"};
2084 int i;
2085 void *PP=NULL;
2086
2087 SUMA_ENTRY;
2088
2089 if (!idcode_str) SUMA_RETURN(PP);
2090 if (do_type) *do_type = NOT_SET_type;
2091 if ((PP = SUMA_FindDset_s(idcode_str, SUMAg_CF->DsetList))) {
2092 if (do_type) {
2093 if (SUMA_isGraphDset((SUMA_DSET *)PP)) *do_type = GDSET_type;
2094 else if (SUMA_isMD_Dset((SUMA_DSET *)PP)) *do_type = MD_DSET_type;
2095 else *do_type = ANY_DSET_type;
2096 }
2097 SUMA_RETURN(PP);
2098 } else if ((PP = SUMA_findSOp_inDOv (idcode_str, SUMAg_DOv, SUMAg_N_DOv))){
2099 if (do_type) *do_type = SO_type;
2100 SUMA_RETURN(PP);
2101 } else if ((PP = SUMA_findVOp_inDOv (idcode_str, SUMAg_DOv, SUMAg_N_DOv))){
2102 if (do_type) *do_type = VO_type;
2103 SUMA_RETURN(PP);
2104 } else if ((i = SUMA_FindDOi_byID(SUMAg_DOv, SUMAg_N_DOv,idcode_str))>=0) {
2105 PP = (SUMAg_DOv[i].OP);
2106 if (do_type) *do_type = SUMAg_DOv[i].ObjectType;
2107 SUMA_RETURN(PP);
2108 } else {
2109 /* Can still search in overlay planes, ROIs, etc.
2110 But wait until we need them .. */
2111 }
2112
2113 SUMA_RETURN(NULL);
2114
2115 }
2116
SUMA_findanySOp(int * dov_id)2117 SUMA_SurfaceObject * SUMA_findanySOp(int *dov_id) {
2118 return(SUMA_findanySOp_inDOv(SUMAg_DOv, SUMAg_N_DOv, dov_id));
2119 }
SUMA_findanySOp_inDOv(SUMA_DO * dov,int N_dov,int * dov_id)2120 SUMA_SurfaceObject * SUMA_findanySOp_inDOv(SUMA_DO *dov, int N_dov, int *dov_id)
2121 {
2122 static char FuncName[]={"SUMA_findanySOp_inDOv"};
2123 SUMA_SurfaceObject *SO;
2124 int i;
2125
2126 SUMA_ENTRY;
2127
2128 if (dov_id) *dov_id = -1;
2129 SO = NULL;
2130 for (i=0; i<N_dov; ++i) {
2131 if (dov[i].ObjectType == SO_type) {
2132 SO = (SUMA_SurfaceObject *)dov[i].OP;
2133 if (dov_id) *dov_id = i;
2134 SUMA_RETURN (SO);
2135 }
2136 }
2137
2138 SUMA_RETURN(NULL);
2139 }
2140
SUMA_findanyVOp(int * dov_id)2141 SUMA_VolumeObject * SUMA_findanyVOp(int *dov_id) {
2142 return(SUMA_findanyVOp_inDOv(SUMAg_DOv, SUMAg_N_DOv, dov_id));
2143 }
SUMA_findanyVOp_inDOv(SUMA_DO * dov,int N_dov,int * dov_id)2144 SUMA_VolumeObject * SUMA_findanyVOp_inDOv(SUMA_DO *dov, int N_dov, int *dov_id)
2145 {
2146 static char FuncName[]={"SUMA_findanyVOp_inDOv"};
2147 SUMA_VolumeObject *VO;
2148 int i;
2149
2150 SUMA_ENTRY;
2151
2152 if (dov_id) *dov_id = -1;
2153 VO = NULL;
2154 for (i=0; i<N_dov; ++i) {
2155 if (dov[i].ObjectType == VO_type) {
2156 VO = (SUMA_VolumeObject *)dov[i].OP;
2157 if (dov_id) *dov_id = i;
2158 SUMA_RETURN (VO);
2159 }
2160 }
2161
2162 SUMA_RETURN(NULL);
2163 }
2164
SUMA_findanyTDOp(int * dov_id)2165 SUMA_TractDO * SUMA_findanyTDOp(int *dov_id) {
2166 return(SUMA_findanyTDOp_inDOv(SUMAg_DOv, SUMAg_N_DOv, dov_id));
2167 }
2168
SUMA_findanyTDOp_inDOv(SUMA_DO * dov,int N_dov,int * dov_id)2169 SUMA_TractDO * SUMA_findanyTDOp_inDOv(SUMA_DO *dov, int N_dov, int *dov_id)
2170 {
2171 static char FuncName[]={"SUMA_findanyTDOp_inDOv"};
2172 SUMA_TractDO *TDO;
2173 int i;
2174
2175 SUMA_ENTRY;
2176
2177 if (dov_id) *dov_id = -1;
2178 TDO = NULL;
2179 for (i=0; i<N_dov; ++i) {
2180 if (dov[i].ObjectType == TRACT_type) {
2181 TDO = (SUMA_TractDO *)dov[i].OP;
2182 if (dov_id) *dov_id = i;
2183 SUMA_RETURN (TDO);
2184 }
2185 }
2186
2187 SUMA_RETURN(NULL);
2188 }
2189
SUMA_findanyMDOp(int * dov_id)2190 SUMA_MaskDO * SUMA_findanyMDOp(int *dov_id)
2191 {
2192 return(SUMA_findanyMDOp_inDOv(SUMAg_DOv, SUMAg_N_DOv, dov_id));
2193 }
2194
SUMA_findanyMDOp_inDOv(SUMA_DO * dov,int N_dov,int * dov_id)2195 SUMA_MaskDO * SUMA_findanyMDOp_inDOv(SUMA_DO *dov, int N_dov, int *dov_id)
2196 {
2197 static char FuncName[]={"SUMA_findanyMDOp_inDOv"};
2198 SUMA_MaskDO *MDO;
2199 int i;
2200
2201 SUMA_ENTRY;
2202
2203 if (dov_id) *dov_id = -1;
2204 MDO = NULL;
2205 for (i=0; i<N_dov; ++i) {
2206 if (dov[i].ObjectType == MASK_type) {
2207 MDO = (SUMA_MaskDO *)dov[i].OP;
2208 if (dov_id) *dov_id = i;
2209 SUMA_RETURN (MDO);
2210 }
2211 }
2212
2213 SUMA_RETURN(NULL);
2214 }
2215
SUMA_findShadowMDOp_inDOv(SUMA_DO * dov,int N_dov,int * dov_id)2216 SUMA_MaskDO * SUMA_findShadowMDOp_inDOv(SUMA_DO *dov, int N_dov, int *dov_id)
2217 {
2218 static char FuncName[]={"SUMA_findShadowMDOp_inDOv"};
2219 SUMA_MaskDO *MDO;
2220 int i;
2221
2222 SUMA_ENTRY;
2223
2224 if (dov_id) *dov_id = -1;
2225 MDO = NULL;
2226 for (i=0; i<N_dov; ++i) {
2227 if (dov[i].ObjectType == MASK_type) {
2228 MDO = (SUMA_MaskDO *)dov[i].OP;
2229 if (MDO_IS_SHADOW(MDO)) {
2230 if (dov_id) *dov_id = i;
2231 SUMA_RETURN (MDO);
2232 }
2233 }
2234 }
2235
2236 SUMA_RETURN(NULL);
2237 }
2238
SUMA_find_SOLabel_from_idcode(char * idcode,SUMA_DO * dov,int N_dov)2239 char *SUMA_find_SOLabel_from_idcode (char *idcode, SUMA_DO *dov, int N_dov)
2240 {
2241 static char FuncName[]={"SUMA_find_SOLabel_from_idcode"};
2242 SUMA_SurfaceObject *SO;
2243 int i;
2244
2245 SUMA_ENTRY;
2246
2247 if (!idcode) SUMA_RETURN(NULL);
2248
2249 for (i=0; i<N_dov; ++i) {
2250 if (dov[i].ObjectType == SO_type) {
2251 SO = (SUMA_SurfaceObject *)dov[i].OP;
2252 if (strcmp(idcode, SO->idcode_str)== 0) {
2253 SUMA_RETURN (SO->Label);
2254 }
2255 }
2256 }
2257 SUMA_RETURN(NULL);
2258 }
2259
SUMA_find_VOLabel_from_idcode(char * idcode,SUMA_DO * dov,int N_dov)2260 char *SUMA_find_VOLabel_from_idcode (char *idcode, SUMA_DO *dov, int N_dov)
2261 {
2262 static char FuncName[]={"SUMA_find_VOLabel_from_idcode"};
2263 SUMA_VolumeObject *VO;
2264 int i;
2265
2266 SUMA_ENTRY;
2267
2268 if (!idcode) SUMA_RETURN(NULL);
2269
2270 for (i=0; i<N_dov; ++i) {
2271 if (dov[i].ObjectType == VO_type) {
2272 VO = (SUMA_VolumeObject *)dov[i].OP;
2273 if (strcmp(idcode, VO->idcode_str)== 0) {
2274 SUMA_RETURN (VO->Label);
2275 }
2276 }
2277 }
2278 SUMA_RETURN(NULL);
2279 }
2280
SUMA_find_SOidcode_from_label(char * label,SUMA_DO * dov,int N_dov)2281 char *SUMA_find_SOidcode_from_label (char *label, SUMA_DO *dov, int N_dov)
2282 {
2283 static char FuncName[]={"SUMA_find_SOidcode_from_label"};
2284 SUMA_SurfaceObject *SO;
2285 int i;
2286 char *found = NULL;
2287
2288 SUMA_ENTRY;
2289
2290 if (!label) SUMA_RETURN(NULL);
2291
2292 for (i=0; i<N_dov; ++i) {
2293 if (dov[i].ObjectType == SO_type) {
2294 SO = (SUMA_SurfaceObject *)dov[i].OP;
2295 if (strcmp(label, SO->Label)== 0) {
2296 if (!found) { found = SO->idcode_str; }
2297 else {
2298 SUMA_S_Errv("More than one surface with label %s found.\n",
2299 label);
2300 SUMA_RETURN(NULL);
2301 }
2302 }
2303 }
2304 }
2305
2306 if (!found) { /* try less stringent search */
2307 for (i=0; i<N_dov; ++i) {
2308 if (dov[i].ObjectType == SO_type) {
2309 SO = (SUMA_SurfaceObject *)dov[i].OP;
2310 if (SUMA_iswordin(SO->Label, label)) {
2311 if (!found) { found = SO->idcode_str; }
2312 else {
2313 SUMA_S_Errv(
2314 "Found more than one surface with labels patially matching %s.\n"
2315 "For example: surfaces %s, and %s .\n",
2316 label,
2317 SUMA_find_SOLabel_from_idcode(found, dov, N_dov),
2318 SO->Label);
2319 SUMA_RETURN(NULL);
2320 }
2321 }
2322 }
2323 }
2324 }
2325
2326 if (!found) { /* even less stringent search */
2327 for (i=0; i<N_dov; ++i) {
2328 if (dov[i].ObjectType == SO_type) {
2329 SO = (SUMA_SurfaceObject *)dov[i].OP;
2330 if (SUMA_iswordin_ci(SO->Label, label)) {
2331 if (!found) { found = SO->idcode_str; }
2332 else {
2333 SUMA_S_Errv(
2334 "Found more than one surface with labels patially matching %s.\n"
2335 "For example: surfaces %s, and %s .\n",
2336 label,
2337 SUMA_find_SOLabel_from_idcode(found, dov, N_dov),
2338 SO->Label);
2339 SUMA_RETURN(NULL);
2340 }
2341 }
2342 }
2343 }
2344 }
2345 SUMA_RETURN(found);
2346 }
2347
SUMA_find_ADOidcode_from_label(char * label,SUMA_DO * dov,int N_dov)2348 char *SUMA_find_ADOidcode_from_label (char *label, SUMA_DO *dov, int N_dov)
2349 {
2350 static char FuncName[]={"SUMA_find_ADOidcode_from_label"};
2351 SUMA_ALL_DO *ADO;
2352 int i;
2353 char *found = NULL;
2354
2355 SUMA_ENTRY;
2356
2357 if (!label) SUMA_RETURN(NULL);
2358
2359 for (i=0; i<N_dov; ++i) {
2360 {
2361 ADO = (SUMA_ALL_DO *)dov[i].OP;
2362 if (strcmp(label, ADO_LABEL(ADO))== 0) {
2363 if (!found) { found = ADO_ID(ADO); }
2364 else {
2365 SUMA_S_Errv("More than one ADO with label %s found.\n",
2366 label);
2367 SUMA_RETURN(NULL);
2368 }
2369 }
2370 }
2371 }
2372
2373 if (!found) { /* try less stringent search */
2374 for (i=0; i<N_dov; ++i) {
2375 {
2376 ADO = (SUMA_ALL_DO *)dov[i].OP;
2377 if (SUMA_iswordin(ADO_LABEL(ADO), label)) {
2378 if (!found) { found = ADO_ID(ADO); }
2379 else {
2380 SUMA_S_Errv(
2381 "Found more than one ADO with labels partially matching %s.\n"
2382 "For example: surfaces %s, and %s .\n",
2383 label,
2384 ADO_LABEL(SUMA_whichADO(found, dov, N_dov)),
2385 ADO_LABEL(ADO));
2386 SUMA_RETURN(NULL);
2387 }
2388 }
2389 }
2390 }
2391 }
2392
2393 if (!found) { /* even less stringent search */
2394 for (i=0; i<N_dov; ++i) {
2395 {
2396 ADO = (SUMA_ALL_DO *)dov[i].OP;
2397 if (SUMA_iswordin_ci(ADO_LABEL(ADO), label)) {
2398 if (!found) { found = ADO_ID(ADO); }
2399 else {
2400 SUMA_S_Errv(
2401 "Found more than one surface with labels patially matching %s.\n"
2402 "For example: surfaces %s, and %s .\n",
2403 label,
2404 ADO_LABEL(SUMA_whichADO(found, dov, N_dov)),
2405 ADO_LABEL(ADO));
2406 SUMA_RETURN(NULL);
2407 }
2408 }
2409 }
2410 }
2411 }
2412 SUMA_RETURN(found);
2413 }
2414
SUMA_find_VOidcode_from_label(char * label,SUMA_DO * dov,int N_dov)2415 char *SUMA_find_VOidcode_from_label (char *label, SUMA_DO *dov, int N_dov)
2416 {
2417 static char FuncName[]={"SUMA_find_VOidcode_from_label"};
2418 SUMA_VolumeObject *VO;
2419 int i;
2420 char *found = NULL;
2421
2422 SUMA_ENTRY;
2423
2424 if (!label) SUMA_RETURN(NULL);
2425
2426 for (i=0; i<N_dov; ++i) {
2427 if (dov[i].ObjectType == VO_type) {
2428 VO = (SUMA_VolumeObject *)dov[i].OP;
2429 if (strcmp(label, VO->Label)== 0) {
2430 if (!found) { found = VO->idcode_str; }
2431 else {
2432 SUMA_S_Errv("More than one volume with label %s found.\n",
2433 label);
2434 SUMA_RETURN(NULL);
2435 }
2436 }
2437 }
2438 }
2439
2440 if (!found) { /* try less stringent search */
2441 for (i=0; i<N_dov; ++i) {
2442 if (dov[i].ObjectType == VO_type) {
2443 VO = (SUMA_VolumeObject *)dov[i].OP;
2444 if (SUMA_iswordin(VO->Label, label)) {
2445 if (!found) { found = VO->idcode_str; }
2446 else {
2447 SUMA_S_Errv(
2448 "Found more than one volume with labels patially matching %s.\n"
2449 "For example: volumes %s, and %s .\n",
2450 label,
2451 SUMA_find_VOLabel_from_idcode(found, dov, N_dov),
2452 VO->Label);
2453 SUMA_RETURN(NULL);
2454 }
2455 }
2456 }
2457 }
2458 }
2459
2460 if (!found) { /* even less stringent search */
2461 for (i=0; i<N_dov; ++i) {
2462 if (dov[i].ObjectType == VO_type) {
2463 VO = (SUMA_VolumeObject *)dov[i].OP;
2464 if (SUMA_iswordin_ci(VO->Label, label)) {
2465 if (!found) { found = VO->idcode_str; }
2466 else {
2467 SUMA_S_Errv(
2468 "Found more than one volume with labels patially matching %s.\n"
2469 "For example: volumes %s, and %s .\n",
2470 label,
2471 SUMA_find_VOLabel_from_idcode(found, dov, N_dov),
2472 VO->Label);
2473 SUMA_RETURN(NULL);
2474 }
2475 }
2476 }
2477 }
2478 }
2479 SUMA_RETURN(found);
2480 }
2481
2482 /*!
2483
2484 VO = SUMA_find_named_VOp_inDOv(char *filename, SUMA_DO *dov, int N_dov)
2485 searches all VO_type DO objects constructed from a dset from file filename
2486
2487 \param filename (char *) filename of VO (as returned by DSET_HEADNAME)
2488 \param dov (SUMA_DO*) pointer to vector of Displayable Objects,
2489 typically SUMAg_DOv
2490 \param N_dov (int) number of DOs in dov
2491 \return VO (SUMA_VolumeObject *) pointer of VO with matching idcode
2492 NULL if not found
2493 \sa SUMA_findVO_inDOv
2494 \sa SUMA_findVOp_inDOv
2495 */
SUMA_find_named_VOp_inDOv(char * filename,SUMA_DO * dov,int N_dov)2496 SUMA_VolumeObject * SUMA_find_named_VOp_inDOv( char *filename,
2497 SUMA_DO *dov, int N_dov)
2498 {
2499 static char FuncName[]={"SUMA_find_named_VOp_inDOv"};
2500 SUMA_VolumeObject *VO = NULL, *VOf = NULL;
2501 SUMA_STRING *SS=NULL;
2502 char *stmp=NULL, *coordname=NULL;
2503 int i;
2504 SUMA_FileName sf;
2505
2506 SUMA_ENTRY;
2507
2508 if (!filename || !dov) SUMA_RETURN(NULL);
2509
2510
2511 i=0;
2512 VOf = NULL;
2513 while (i<N_dov) {
2514 if (dov[i].ObjectType == VO_type) {
2515 VO = (SUMA_VolumeObject *)dov[i].OP;
2516 if (VO->VE && VO->VE[0] &&
2517 !strcmp(filename, SUMA_VE_Headname(VO->VE, 0))) {
2518 if (VOf) {
2519 SUMA_S_Errv("Volume name %s\n"
2520 "is not a unique identifier.\n",
2521 filename);
2522 SUMA_RETURN(NULL);
2523 }
2524 VOf = VO;
2525 }
2526 }
2527 ++i;
2528 }
2529
2530 SUMA_RETURN(VOf);
2531 }
2532
2533 /*!
2534
2535 SO = SUMA_find_named_SOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
2536 searches all SO_type DO objects for idcode
2537
2538 \param coordname (char *) filename of SO (without path) that you are searching for.
2539 If surface is specified by 2 files, then use the coord file
2540 name.
2541 \param dov (SUMA_DO*) pointer to vector of Displayable Objects, typically SUMAg_DOv
2542 \param N_dov (int) number of DOs in dov
2543 \return SO (SUMA_SurfaceObject *) pointer of SO with matching idcode
2544 NULL if not found
2545 \sa SUMA_findSO_inDOv
2546 \sa SUMA_findSOp_inDOv
2547 */
SUMA_find_named_SOp_inDOv(char * coordnamei,SUMA_DO * dov,int N_dov)2548 SUMA_SurfaceObject * SUMA_find_named_SOp_inDOv( char *coordnamei,
2549 SUMA_DO *dov, int N_dov)
2550 {
2551 static char FuncName[]={"SUMA_find_named_SOp_inDOv"};
2552 SUMA_SurfaceObject *SO = NULL, *SOf = NULL;
2553 SUMA_STRING *SS=NULL;
2554 char *stmp=NULL, *coordname=NULL;
2555 int i;
2556 SUMA_FileName sf;
2557
2558 SUMA_ENTRY;
2559
2560 if (!coordnamei || !dov) SUMA_RETURN(NULL);
2561
2562 /* remove the path from coordname, to be sure */
2563 sf = SUMA_StripPath(coordnamei);
2564 if (!sf.FileName) SUMA_RETURN(NULL);
2565 else coordname = sf.FileName;
2566
2567 i=0;
2568 SOf = NULL;
2569 while (i<N_dov) {
2570 if (dov[i].ObjectType == SO_type) {
2571 SO = (SUMA_SurfaceObject *)dov[i].OP;
2572 switch(SO->FileType) {
2573 case SUMA_SUREFIT:
2574 case SUMA_VEC:
2575 if (strstr(SO->Name_coord.FileName, coordname)) {
2576 if (SOf) {
2577 SS = SUMA_StringAppend_va(NULL, NULL);
2578 SS = SUMA_StringAppend_va(SS,
2579 "Error %s:\n"
2580 "Surface name %s\n"
2581 "is not a unique identifier.\n"
2582 "Found %s and %s so far.\n"
2583 "Be more specific.\n", FuncName,
2584 coordname, SOf->Name_coord.FileName,
2585 SO->Name_coord.FileName);
2586 SUMA_SS2S(SS, stmp);
2587 SUMA_SL_Err("%s",stmp);
2588 if (stmp) SUMA_free(stmp); stmp = NULL;
2589 if (sf.FileName) SUMA_free(sf.FileName);
2590 sf.FileName = NULL;
2591 if (sf.Path) SUMA_free(sf.Path);
2592 sf.Path = NULL;
2593 SUMA_RETURN(NULL);
2594 }
2595 SOf = SO;
2596 }
2597 break;
2598 case SUMA_FREE_SURFER:
2599 case SUMA_FREE_SURFER_PATCH:
2600 case SUMA_INVENTOR_GENERIC:
2601 case SUMA_OBJ_MESH:
2602 case SUMA_OPENDX_MESH:
2603 case SUMA_PREDEFINED:
2604 case SUMA_BRAIN_VOYAGER:
2605 case SUMA_BYU:
2606 case SUMA_GIFTI:
2607 case SUMA_MNI_OBJ:
2608 case SUMA_STL:
2609 case SUMA_PLY:
2610 if (strstr(SO->Name.FileName, coordname)) {
2611 if (SOf) {
2612 SS = SUMA_StringAppend_va(NULL, NULL);
2613 SS = SUMA_StringAppend_va(SS,
2614 "Error %s:\n"
2615 "Surface name %s\n"
2616 "is not a unique identifier.\n"
2617 "Found %s and %s so far.\n"
2618 "Be more specific.\n", FuncName,
2619 coordname, SOf->Name_coord.FileName,
2620 SO->Name_coord.FileName);
2621 SUMA_SS2S(SS, stmp);
2622 SUMA_SL_Err("%s",stmp);
2623 if (stmp) SUMA_free(stmp); stmp = NULL;
2624 if (sf.FileName) SUMA_free(sf.FileName);
2625 sf.FileName = NULL;
2626 if (sf.Path) SUMA_free(sf.Path);
2627 sf.Path = NULL; SUMA_RETURN(NULL);
2628 }
2629 SOf = SO;
2630 }
2631 break;
2632 default:
2633 SUMA_SL_Err("Filetype not supported.");
2634 SUMA_RETURN(NULL);
2635 }
2636 }
2637 ++i;
2638 }
2639
2640 if (sf.FileName) SUMA_free(sf.FileName);
2641 sf.FileName = NULL;
2642 if (sf.Path) SUMA_free(sf.Path);
2643 sf.Path = NULL;
2644
2645 SUMA_RETURN(SOf);
2646 }
2647
2648 /*!
2649 determines if a Surface Object is mappable (ie LocalDomainParentID != NULL)
2650 ans = SUMA_ismappable (SUMA_SurfaceObject *SO)
2651 \param SO (SUMA_SurfaceObject *)
2652 \ret YUP/NOPE
2653 */
SUMA_ismappable(SUMA_SurfaceObject * SO)2654 SUMA_Boolean SUMA_ismappable (SUMA_SurfaceObject *SO)
2655 {
2656 static char FuncName[]={"SUMA_ismappable"};
2657
2658 SUMA_ENTRY;
2659
2660 if (SO->LocalDomainParentID != NULL) {
2661 /* SO is mappable */
2662 SUMA_RETURN (YUP);
2663 }
2664
2665 SUMA_RETURN (NOPE);
2666
2667 }
2668
2669 /*!
2670 Left here temporarily for backward compatibility
2671
2672 use the more appropriately named SUMA_isLocalDomainParent
2673 */
SUMA_isINHmappable(SUMA_SurfaceObject * SO)2674 SUMA_Boolean SUMA_isINHmappable (SUMA_SurfaceObject *SO)
2675 {
2676 static char FuncName[]={"SUMA_isINHmappable"};
2677
2678 SUMA_ENTRY;
2679
2680 SUMA_RETURN(SUMA_isLocalDomainParent(SO));
2681 }
2682
2683 /*!
2684 determines if a Surface Object is a local domain parent (ie LocalDomainParentID == idcode_str)
2685 (used to be called inherently mappable)
2686 ans = SUMA_isLocalDomainParent (SUMA_SurfaceObject *SO)
2687 \param SO (SUMA_SurfaceObject *)
2688 \ret YUP/NOPE
2689
2690 -- Used to be called SUMA_isINHmappable
2691 */
SUMA_isLocalDomainParent(SUMA_SurfaceObject * SO)2692 SUMA_Boolean SUMA_isLocalDomainParent (SUMA_SurfaceObject *SO)
2693 {
2694 static char FuncName[]={"SUMA_isLocalDomainParent"};
2695
2696 SUMA_ENTRY;
2697
2698 if (SO->LocalDomainParentID == NULL) {
2699 SUMA_RETURN (NOPE);
2700 }
2701 if (strcmp(SO->LocalDomainParentID, SO->idcode_str) == 0) {
2702 /* SO is the local domain parent */
2703 SUMA_RETURN (YUP);
2704 }
2705 SUMA_RETURN (NOPE);
2706 }
2707
2708
SUMA_isRelated(SUMA_ALL_DO * ado1,SUMA_ALL_DO * ado2,int level)2709 SUMA_Boolean SUMA_isRelated( SUMA_ALL_DO *ado1, SUMA_ALL_DO *ado2 , int level)
2710 {
2711 static char FuncName[]={"SUMA_isRelated"};
2712 char *p1=NULL, *p2=NULL;
2713 SUMA_Boolean LocalHead = NOPE;
2714
2715 SUMA_ENTRY;
2716
2717 if (!ado1 || !ado2) SUMA_RETURN(NOPE);
2718
2719 if (LocalHead) SUMA_DUMP_TRACE("Relatives!");
2720
2721 if (ado1 == ado2) SUMA_RETURN(YUP);
2722
2723 switch (ado1->do_type) {
2724 case SO_type:
2725 if (ado1->do_type != ado2->do_type) SUMA_RETURN(NOPE);
2726 SUMA_RETURN(SUMA_isRelated_SO((SUMA_SurfaceObject *)ado1,
2727 (SUMA_SurfaceObject *)ado2,level));
2728 break;
2729 case GDSET_type:
2730 case GRAPH_LINK_type:
2731 if (ado2->do_type != GDSET_type && ado2->do_type != GRAPH_LINK_type)
2732 SUMA_RETURN(NOPE);
2733 if ((p1=SUMA_ADO_Parent_idcode(ado1)) &&
2734 (p2=SUMA_ADO_Parent_idcode(ado2)) &&
2735 !strcmp(p1,p2)) {
2736 SUMA_RETURN(YUP);
2737 }
2738 SUMA_RETURN(NOPE);
2739 break;
2740 case CDOM_type:
2741 SUMA_S_Err("Fill me with love. Some day we might have 'isotopic' CIFTI "
2742 "domains. Let us leave complications alone for now");
2743 SUMA_RETURN(NOPE);
2744 break;
2745 case VO_type:
2746 case TRACT_type:
2747 if (ado2->do_type != ado1->do_type) SUMA_RETURN(NOPE);
2748 if ((p1=SUMA_ADO_Parent_idcode(ado1)) &&
2749 (p2=SUMA_ADO_Parent_idcode(ado2)) &&
2750 !strcmp(p1,p2)) {
2751 SUMA_RETURN(YUP);
2752 } else if (!p1 && !p2 && !strcmp(ADO_ID(ado1),ADO_ID(ado2))) {
2753 SUMA_RETURN(YUP);
2754 }
2755 SUMA_RETURN(NOPE);
2756 break;
2757 case MASK_type:
2758 if (ado2->do_type == ado1->do_type ||
2759 ado2->do_type == TRACT_type) {
2760 SUMA_RETURN(YUP);
2761 }
2762 SUMA_RETURN(NOPE);
2763 break;
2764 default:
2765 SUMA_S_Errv("Not ready to deal with type %s\n",
2766 SUMA_ObjectTypeCode2ObjectTypeName(ado1->do_type));
2767 SUMA_RETURN(NOPE);
2768 }
2769 SUMA_RETURN(NOPE);
2770 }
2771
2772 /*!
2773 \brief ans = SUMA_isRelated_SO (SUMA_SurfaceObject *SO1,
2774 SUMA_SurfaceObject *SO2, int level);
2775
2776 returns YUP if SO1 and SO2 are related at level 1 or 2
2777 level 1 means nuclear family (share the same parent)
2778 level 2 means extended family (share a grandparent, ultimately this could be
2779 the grand icosahedron duc
2780 Surfaces must be the of the same hemi side since both hemispheres
2781 can have the same grandparent, use level 3 if you want to go across
2782 hemis.)
2783 level 3 is like level 2 with no care for what side of the brain we're working
2784 with
2785
2786 For more definitions on relationships:
2787
2788 \sa SUMA_WhatAreYouToMe
2789 */
SUMA_isRelated_SO(SUMA_SurfaceObject * SO1,SUMA_SurfaceObject * SO2,int level)2790 SUMA_Boolean SUMA_isRelated_SO ( SUMA_SurfaceObject *SO1,
2791 SUMA_SurfaceObject *SO2, int level)
2792 {
2793 static char FuncName[]={"SUMA_isRelated_SO"};
2794 SUMA_DOMAIN_KINSHIPS kin;
2795 static int iwarn=0;
2796 SUMA_Boolean LocalHead = NOPE;
2797
2798 SUMA_ENTRY;
2799
2800 kin = SUMA_WhatAreYouToMe (SO1, SO2);
2801 switch (level) {
2802 case 3: /* anything goes */
2803 if ( (kin > SUMA_DOMAINS_NOT_RELATED) ) SUMA_RETURN(YUP);
2804 break;
2805 case 2: /* share an ancestor, but same side */
2806 if ( (kin > SUMA_DOMAINS_NOT_RELATED) ) {
2807 if ( (SO1->Side == SO2->Side) ) {
2808 SUMA_RETURN(YUP);
2809 } else {
2810 if (!(iwarn % 25)) {
2811 SUMA_S_Note( "Surfaces appear related at level 2 "
2812 "but sides are not the same.\n" "Kinship level is being ignored.\n"
2813 "(Message shown intermittenly)\n");
2814 }
2815 if ((SO1->Side < SUMA_LR || SO2->Side < SUMA_LR)) {
2816 SUMA_S_Note("Surface sides are not clearly defined. "
2817 "If this is in error, consider adding \n"
2818 "Hemisphere = R (or L or B) in the spec file\n"
2819 "to make sure surfaces sides are correctly "
2820 "labeled.\n");
2821 }
2822 ++iwarn;
2823 }
2824 }
2825 break;
2826 case 1: /* nuclear family only */
2827 if ( (kin > SUMA_DOMAINS_NOT_RELATED) &&
2828 (kin < SUMA_NUCELAR_FAMILY ) ) {
2829 if (SO1->Side == SO2->Side) {
2830 SUMA_RETURN(YUP);
2831 /* last condition is not really necessary but it
2832 don't hoyt...*/
2833 } else {
2834 SUMA_S_Note( "Surfaces appear related at level 2 "
2835 "but sides are not the same.\n" "Kinship level is being ignored.\n");
2836 if (SO1->Side < SUMA_LR || SO2->Side < SUMA_LR) {
2837 SUMA_S_Note("Surface sides are not clearly defined. "
2838 "If this is in error, consider adding \n"
2839 "Hemisphere = R (or L or B) in the spec file\n"
2840 "to make sure surfaces sides are correctly "
2841 "labeled.\n");
2842 }
2843 }
2844 }
2845 break;
2846 default:
2847 SUMA_SL_Err("Bad value for level.");
2848 break;
2849 }
2850 SUMA_RETURN(NOPE);
2851 }
2852
2853 /*!
2854 \brief finds a contralateral surface to SO that is of the same
2855 Group AND State
2856 */
SUMA_Contralateral_SO(SUMA_SurfaceObject * SO,SUMA_DO * dov,int N_dov)2857 SUMA_SurfaceObject *SUMA_Contralateral_SO(SUMA_SurfaceObject *SO,
2858 SUMA_DO *dov, int N_dov)
2859 {
2860 static char FuncName[]={"SUMA_Contralateral_SO"};
2861 SUMA_SurfaceObject *SOC=NULL;
2862 int findside = SUMA_SIDE_ERROR;
2863 int i;
2864 static int iwarn=0;
2865
2866 SUMA_ENTRY;
2867
2868 if (!SO) {
2869 SUMA_S_Err("NULL input");
2870 SUMA_RETURN(SOC);
2871 }
2872 if (!SO->Group) {
2873 SUMA_S_Err("Need SO->Group");
2874 SUMA_RETURN(SOC);
2875 }
2876
2877 if (SO->Side != SUMA_LEFT && SO->Side != SUMA_RIGHT) {
2878 if (SO->Side < SUMA_LR) {
2879 if (!iwarn) {
2880 SUMA_S_Warn("Surface sides are not clearly defined. "
2881 "If this is in error, consider adding \n"
2882 "Hemisphere = R (or L or B) in the spec file\n"
2883 "to make sure surfaces sides are correctly "
2884 "labeled.\n"
2885 "Similar warnings will be muted\n");
2886 ++iwarn;
2887 }
2888 }
2889 SUMA_RETURN(SOC);
2890 }
2891
2892 if (SO->Side == SUMA_LEFT) findside = SUMA_RIGHT;
2893 else findside = SUMA_LEFT;
2894
2895 fprintf(stderr, "SUMA_Contralateral_SO: N_dov=%d\n", N_dov);
2896 for (i=0; i<N_dov; ++i) {
2897 fprintf(stderr, "SUMA_Contralateral_SO: (i,SO->Group) =(%d, %s)\n", i, SO->Group);
2898 if (SUMA_isSO_G(dov[i], SO->Group)) {
2899 SOC = (SUMA_SurfaceObject *)dov[i].OP;
2900 if (SOC->Side == findside && !strcmp(SOC->State, SO->State) ) break;
2901 else SOC = NULL;
2902 }
2903 }
2904
2905 if (SOC && SUMA_isRelated_SO(SOC, SO, 1)) {
2906 SUMA_S_Warn("Unexpected surface pair with same localdomainparent.\n"
2907 "Good Luck To You");
2908 }
2909 /*
2910 if (SOC) SOC = SUMA_findSOp_inDOv( SOC->LocalDomainParentID,
2911 dov, N_dov);
2912 */
2913
2914
2915 SUMA_RETURN(SOC);
2916 }
2917
SUMA_isContralateral_name(char * s1,char * s2)2918 SUMA_Boolean SUMA_isContralateral_name(char *s1, char *s2)
2919 {
2920 static char FuncName[]={"SUMA_isContralateral_name"};
2921 char *sd=NULL, *sc1=NULL, *sc2=NULL;
2922 int ic1, ic2;
2923 SUMA_Boolean LocalHead = NOPE;
2924 SUMA_ENTRY;
2925
2926 if (s1 && s2 && strstr(s1,"FuncAfni_") && strstr(s2,"FuncAfni_") &&
2927 (sc1 = strstr(s1,TMP_NAME_SEP)) && (sc2 = strstr(s2,TMP_NAME_SEP)) ) {
2928 /* temporarily mask the idcode part */
2929 ic1 = sc1-s1; ic2 = sc2 - s2;
2930 s1[ic1] = '\0';
2931 s2[ic2] = '\0';
2932 }
2933 sd = SUMA_StringDiff(s1,s2);
2934 /* now put things back */
2935 if (sc1 && sc2) {
2936 s1[ic1] = sc1[0];
2937 s2[ic2] = sc2[0];
2938 }
2939 sc1 = sc2 = NULL;
2940
2941 SUMA_LHv("Diff of \n%s and \n%s is \n%s\n",
2942 CHECK_NULL_STR(s1), CHECK_NULL_STR(s2), CHECK_NULL_STR(sd));
2943
2944 if (!sd || sd[0] == '\0') SUMA_RETURN(NOPE);
2945
2946 /* If name is for live dsets from AFNI, make sure you cut after idcode_str */
2947 /* check for l or r only */
2948 if (sd[0] != 'l' && sd[0] != 'L' && sd[0] != 'r' && sd[0] != 'R') {
2949 /* not begginning with l or r */
2950 SUMA_free(sd); SUMA_RETURN(NOPE);
2951 } else if (sd[1] == '\0') { /* make sure it is only l or r */
2952 SUMA_free(sd); SUMA_RETURN(YUP);
2953 }
2954 if (strstr(s1,"GRP_ICORR") && strstr(s2,"GRP_ICORR")) {
2955 /* special treatment */
2956 if (strncasecmp(sd,"left",4) && strncasecmp(sd,"right",5)) {
2957 SUMA_free(sd); SUMA_RETURN(NOPE);
2958 }
2959 } else {
2960 /* not left and not right? */
2961 if (strcasecmp(sd,"left") && strcasecmp(sd,"right")) {
2962 SUMA_free(sd); SUMA_RETURN(NOPE);
2963 }
2964 }
2965 SUMA_free(sd);
2966 SUMA_RETURN(YUP);
2967 }
2968
SUMA_Contralateral_file(char * f1)2969 char *SUMA_Contralateral_file(char *f1)
2970 {
2971 static char FuncName[]={"SUMA_Contralateral_file"};
2972 char *f1C=NULL, *ff1=NULL;
2973 int ii=0;
2974 THD_string_array *sar=NULL;
2975 SUMA_Boolean LocalHead = NOPE;
2976
2977 SUMA_ENTRY;
2978
2979 if (!f1) SUMA_RETURN(f1C);
2980
2981 if (!(sar=THD_get_all_files(SUMA_FnameGet(f1, "pa", SUMAg_CF->cwd),0))){
2982 SUMA_RETURN(f1C);
2983 }
2984
2985 ff1 = SUMA_FnameGet(f1, "F", SUMAg_CF->cwd);
2986 for( ii=0 ; ii < sar->num ; ii++ ) {
2987 SUMA_LHv("%s vs\n"
2988 "%s\n", sar->ar[ii], ff1);
2989 if (SUMA_isContralateral_name(sar->ar[ii], ff1)) {
2990 if (!f1C) {
2991 f1C = SUMA_copy_string(sar->ar[ii]);
2992 } else {
2993 /* ambiguous contralateral files names */
2994 SUMA_S_Warnv("Found more than 1 contralateral candidates for %s\n"
2995 "%s and %s\n",
2996 ff1, f1C, sar->ar[ii]);
2997 DESTROY_SARR(sar) ; SUMA_free(f1C); f1C = NULL;
2998 SUMA_RETURN(f1C);
2999 }
3000 }
3001 }
3002
3003 DESTROY_SARR(sar) ; sar = NULL;
3004 if (f1C) {
3005 SUMA_LHv("%s is matched by\n%s\n",
3006 f1C, f1);
3007 } else {
3008 SUMA_LHv("No cigar for %s\n", f1);
3009 }
3010 SUMA_RETURN(f1C);
3011 }
3012
SUMA_Contralateral_dset(SUMA_DSET * dset,SUMA_SurfaceObject * SO,SUMA_SurfaceObject ** SOCp)3013 SUMA_DSET * SUMA_Contralateral_dset(SUMA_DSET *dset, SUMA_SurfaceObject *SO,
3014 SUMA_SurfaceObject**SOCp)
3015 {
3016 static char FuncName[]={"SUMA_Contralateral_dset"};
3017 SUMA_DSET *cdset=NULL, *dd=NULL;
3018 DListElmt *el=NULL;
3019 char *namediff=NULL;
3020 SUMA_SurfaceObject *SOC=NULL;
3021 SUMA_Boolean LocalHead = NOPE;
3022
3023 SUMA_ENTRY;
3024
3025 if (!dset) {
3026 SUMA_S_Err("NULL input");
3027 SUMA_RETURN(cdset);
3028 }
3029
3030 if (!SO) {
3031 if (!(SO =
3032 SUMA_findSOp_inDOv( SUMA_sdset_idmdom(dset),
3033 SUMAg_DOv, SUMAg_N_DOv))){
3034 SUMA_S_Err("Can't find dset's domain parent");
3035 SUMA_RETURN(cdset);
3036 }
3037 }
3038
3039 if (!(SOC = SUMA_Contralateral_SO(SO, SUMAg_DOv, SUMAg_N_DOv))) {
3040 /* Nothing there, return */
3041 SUMA_RETURN(cdset);
3042 }
3043
3044 SUMA_LH("Have contralateral surface to consider\n");
3045 el = dlist_head(SUMAg_CF->DsetList);
3046 while (el) {
3047 dd = (SUMA_DSET*)el->data;
3048 if (SUMA_isDsetRelated(dd,SOC)) {
3049 SUMA_LHv("Have Dset %s related to SOC\n", SDSET_LABEL(dd));
3050 /* Does dd relate to dset ? */
3051 if ( SUMA_isContralateral_name(SDSET_FILENAME(dset),
3052 SDSET_FILENAME(dd)) &&
3053 SUMA_isSameDsetColTypes(dset, dd) ) {
3054 if (!cdset) {
3055 cdset = dd;
3056 }else {
3057 SUMA_S_Warn("More than one dset matches\n"
3058 "Returning NULL");
3059 SUMA_RETURN(NULL);
3060 }
3061 }
3062 }
3063 el = dlist_next(el);
3064 }
3065
3066 if (SOCp) *SOCp=SOC;
3067 SUMA_RETURN(cdset);
3068 }
3069
SUMA_Contralateral_overlay(SUMA_OVERLAYS * over,SUMA_SurfaceObject * SO,SUMA_SurfaceObject ** SOCp)3070 SUMA_OVERLAYS *SUMA_Contralateral_overlay(SUMA_OVERLAYS *over,
3071 SUMA_SurfaceObject *SO,
3072 SUMA_SurfaceObject**SOCp)
3073 {
3074 static char FuncName[]={"SUMA_Contralateral_overlay"};
3075 SUMA_DSET *dsetC=NULL, *dset=NULL, *dd=NULL;
3076 DListElmt *el=NULL;
3077 SUMA_OVERLAYS *overC=NULL;
3078 int OverInd = -1;
3079 char *namediff=NULL;
3080 SUMA_SurfaceObject *SOC=NULL;
3081 SUMA_Boolean LocalHead = NOPE;
3082
3083 SUMA_ENTRY;
3084
3085 if (!over || !over->dset_link) {
3086 SUMA_S_Errv("NULL input (%p) or NULL dset_link (%p)",
3087 over, over ? over->dset_link:NULL);
3088 SUMA_RETURN(overC);
3089 }
3090
3091 dset = over->dset_link;
3092 if (!SO) {
3093 if (!(SO =
3094 SUMA_findSOp_inDOv( SUMA_sdset_idmdom(dset),
3095 SUMAg_DOv, SUMAg_N_DOv))){
3096 SUMA_S_Err("Can't find dset's domain parent");
3097 SUMA_RETURN(overC);
3098 }
3099 }
3100
3101 if (!(SOC = SUMA_Contralateral_SO(SO, SUMAg_DOv, SUMAg_N_DOv))) {
3102 /* Nothing there, return */
3103 SUMA_RETURN(overC);
3104 }
3105
3106 SUMA_LH("Have contralateral surface to consider");
3107 el = dlist_head(SUMAg_CF->DsetList);
3108 while (el) {
3109 dd = (SUMA_DSET*)el->data;
3110 if (SUMA_isDsetRelated(dd,SOC)) {
3111 SUMA_LHv("Have Dset %s (filename %s) related to SOC\n",
3112 SDSET_LABEL(dd), SDSET_FILENAME(dd));
3113 /* Does dd relate to dset ? */
3114 if ( SUMA_isContralateral_name(SDSET_FILENAME(dset),
3115 SDSET_FILENAME(dd)) &&
3116 SUMA_isSameDsetColTypes(dset, dd) ) {
3117 if (!dsetC) {
3118 dsetC = dd;
3119 }else {
3120 SUMA_S_Warn("More than one dset matches\n"
3121 "Returning NULL");
3122 SUMA_RETURN(NULL);
3123 }
3124 }
3125 }
3126 el = dlist_next(el);
3127 }
3128 if (!dsetC) {
3129 SUMA_LH("Quest failed, returning");
3130 SUMA_RETURN(overC);
3131 }
3132 if (!(overC=SUMA_Fetch_OverlayPointerByDset ((SUMA_ALL_DO *)SOC,
3133 dsetC, &OverInd))) {
3134 SUMA_S_Err("Failed oh failed to find overlay for contralateral dset"); SUMA_RETURN(NULL);
3135 }
3136
3137 if (!SUMA_isADO_Cont_Realized((SUMA_ALL_DO *)SOC)) {
3138 if (!(SUMA_OpenCloseSurfaceCont(NULL, (SUMA_ALL_DO *)SOC, NULL))) {
3139 SUMA_S_Err("Could not ensure controller is ready");
3140 SOC = NULL; overC=NULL;
3141 }
3142 }
3143 if (SOCp) *SOCp=SOC;
3144 SUMA_RETURN(overC);
3145 }
3146
3147 /*!
3148 \brief ans = SUMA_WhatAreYouToMe (SUMA_SurfaceObject *SO1, SUMA_SurfaceObject *SO2);
3149 returns a code for the kinship between two surfaces:
3150
3151 SO1->idcode_str = SO2->idcode_str (in this case SO1 = SO2) or
3152 SO1->LocalDomainParentID = SO2->idcode_str (SO2 is the mapping reference of SO1) or
3153 SO1->idcode_str = SO2->LocalDomainParentID (SO1 is the mapping reference of SO2)
3154 SO1->LocalDomainParentID = SO2->LocalDomainParentID (SO1 and SO2 have the same mapping reference) or
3155 SO1->DomainGrandParentID = SO2->idcode_str (SO2 is the granddaddy of SO1) or
3156 SO1->idcode_str = SO2->DomainGrandParentID (SO1 is the granddaddy of SO2) or
3157 SO1->DomainGrandParentID = SO2->DomainGrandParentID (SO1 and SO2 have the same granddaddy)
3158
3159 \sa definition of SUMA_DOMAIN_KINSHIPS and
3160 \sa SUMA_DomainKinships_String
3161 */
SUMA_WhatAreYouToMe(SUMA_SurfaceObject * SO1,SUMA_SurfaceObject * SO2)3162 SUMA_DOMAIN_KINSHIPS SUMA_WhatAreYouToMe (SUMA_SurfaceObject *SO1,
3163 SUMA_SurfaceObject *SO2)
3164 {
3165 static char FuncName[]={"SUMA_WhatAreYouToMe"};
3166 SUMA_Boolean LocalHead = NOPE;
3167
3168 SUMA_ENTRY;
3169
3170 if (!SO1 && !SO2) {
3171 SUMA_S_Err("Total NULLness");
3172 SUMA_RETURN (SUMA_DOMAINS_NOT_RELATED);
3173 }
3174
3175 if (!SO1 || !SO2) {
3176 SUMA_LH("One NULL SO"); /* Don't die, it is ok */
3177 SUMA_RETURN (SUMA_DOMAINS_NOT_RELATED);
3178 }
3179
3180 if (!SO1->idcode_str || !SO2->idcode_str) {
3181 SUMA_S_Err("NULL SO->idcode_str.");
3182 if (LocalHead) SUMA_DUMP_TRACE("Strange init");
3183 SUMA_RETURN (SUMA_DOMAINS_NOT_RELATED);
3184 }
3185
3186 if (SO1 == SO2 ||
3187 strcmp (SO1->idcode_str, SO2->idcode_str) == 0) {
3188 /* SO1 = SO2 */
3189 SUMA_LH("%s",SUMA_DomainKinships_String (SUMA_SO1_is_SO2));
3190 SUMA_RETURN (SUMA_SO1_is_SO2);
3191 }
3192
3193 if (SO1->LocalDomainParentID) {
3194 if (strcmp (SO1->LocalDomainParentID, SO2->idcode_str) == 0) {
3195 /* SO2 is the local domain parent of SO1 */
3196 SUMA_LH("%s",SUMA_DomainKinships_String (SUMA_SO2_is_LDPSO1));
3197 SUMA_RETURN (SUMA_SO2_is_LDPSO1);
3198 }
3199 }
3200
3201 if (SO2->LocalDomainParentID) {
3202 if (strcmp (SO1->idcode_str, SO2->LocalDomainParentID) == 0) {
3203 /* SO1 is the local domain parent of SO2 */
3204 SUMA_LH("%s",SUMA_DomainKinships_String (SUMA_SO1_is_LDPSO2));
3205 SUMA_RETURN (SUMA_SO1_is_LDPSO2);
3206 }
3207 }
3208
3209 if (SO1->LocalDomainParentID && SO2->LocalDomainParentID) {
3210 if (strcmp (SO1->LocalDomainParentID, SO2->LocalDomainParentID) == 0) {
3211 /* SO1 and SO2 have the same local domain parent */
3212 SUMA_LH("%s",SUMA_DomainKinships_String (SUMA_LDPSO1_is_LDPSO2));
3213 SUMA_RETURN (SUMA_LDPSO1_is_LDPSO2);
3214 }
3215 }
3216
3217 if (SO1->DomainGrandParentID && SO2->idcode_str) {
3218 if (strcmp (SO1->DomainGrandParentID, SO2->idcode_str) == 0) {
3219 /* SO2 is the grand daddy of SO1 */
3220 SUMA_LH("%s",SUMA_DomainKinships_String (SUMA_SO2_is_GPSO1));
3221 SUMA_RETURN (SUMA_SO2_is_GPSO1);
3222 }
3223 }
3224
3225 if (SO1->idcode_str && SO2->DomainGrandParentID) {
3226 if (strcmp (SO1->idcode_str, SO2->DomainGrandParentID) == 0) {
3227 /* SO1 is the grand daddy of SO2 */
3228 SUMA_LH("%s",SUMA_DomainKinships_String (SUMA_SO1_is_GPSO2));
3229 SUMA_RETURN (SUMA_SO1_is_GPSO2);
3230 }
3231 }
3232
3233 if (SO1->DomainGrandParentID && SO2->DomainGrandParentID) {
3234 if (strcmp (SO1->DomainGrandParentID, SO2->DomainGrandParentID) == 0) {
3235 /* SO1 and SO2 have the same grand daddy */
3236 SUMA_LH("%s", SUMA_DomainKinships_String (SUMA_GPSO1_is_GPSO2));
3237 SUMA_RETURN (SUMA_GPSO1_is_GPSO2);
3238 }
3239 }
3240 if (SO1->N_Node == SO2->N_Node) {
3241 SUMA_LH("%s", SUMA_DomainKinships_String (SUMA_N_NODE_SAME));
3242 SUMA_RETURN (SUMA_N_NODE_SAME);
3243 }
3244
3245 SUMA_LH("%s", SUMA_DomainKinships_String (SUMA_DOMAINS_NOT_RELATED));
3246 SUMA_RETURN (SUMA_DOMAINS_NOT_RELATED);
3247
3248 }
3249
3250 /*!
3251 \brief SUMA_Boolean SUMA_isSO_G (SUMA_DO DO, char *Group)
3252 returns YUP if DO is a surface object
3253 and is a part of the group Group
3254
3255 \sa SUMA_isSO
3256 */
SUMA_isSO_G(SUMA_DO DO,char * Group)3257 SUMA_Boolean SUMA_isSO_G (SUMA_DO DO, char *Group)
3258 {
3259 static char FuncName[]={"SUMA_isSO_G"};
3260 SUMA_SurfaceObject *SO = NULL;
3261
3262 SUMA_ENTRY;
3263
3264 if (!Group) {
3265 SUMA_SL_Err("Null Group");
3266 SUMA_RETURN(NOPE);
3267 }
3268
3269 if (SUMA_isSO(DO)) {
3270 SO = (SUMA_SurfaceObject *)DO.OP;
3271 if (!SO->Group) {
3272 SUMA_SL_Err("Surface has no group, imbecile");
3273 SUMA_RETURN(NOPE);
3274 }
3275 if (strcmp(SO->Group, Group)) { SUMA_RETURN(NOPE); }
3276 else { SUMA_RETURN(YUP); }
3277 }
3278
3279 SUMA_RETURN(NOPE);
3280 }
3281 /*!
3282 \brief SUMA_Boolean SUMA_isSO (SUMA_DO DO)
3283 returns YUP if DO is of SO_type
3284 ans = SUMA_isSO (DO) ;
3285
3286 \sa SUMA_isSO_G (SUMA_DO DO, char *Group)
3287 */
SUMA_isSO(SUMA_DO DO)3288 SUMA_Boolean SUMA_isSO (SUMA_DO DO)
3289 {
3290 static char FuncName[]={"SUMA_isSO"};
3291
3292 SUMA_ENTRY;
3293
3294 if (DO.ObjectType == SO_type) {
3295 SUMA_RETURN (YUP);
3296 }
3297 SUMA_RETURN (NOPE);
3298 }
3299
3300 /*!
3301 \brief SUMA_Boolean SUMA_isVO (SUMA_DO DO)
3302 returns YUP if DO is of VO_type
3303 ans = SUMA_isVO (DO) ;
3304
3305 \sa SUMA_isVO_G (SUMA_DO DO, char *Group)
3306 */
SUMA_isVO(SUMA_DO DO)3307 SUMA_Boolean SUMA_isVO (SUMA_DO DO)
3308 {
3309 static char FuncName[]={"SUMA_isVO"};
3310
3311 SUMA_ENTRY;
3312
3313 if (DO.ObjectType == VO_type) {
3314 SUMA_RETURN (YUP);
3315 }
3316 SUMA_RETURN (NOPE);
3317 }
3318
3319 /*!
3320 \brief Returns a list of the ROIs loaded into dov.
3321
3322 \param dov (SUMA_DO *) pointer to vector of DOs
3323 \param N_dov (int) number of DOs in dov
3324 \param SortByLabel (SUMA_Boolean) if YUP then returned strings are sorted by their ROI's labels
3325 (The parents must be part of dov). If Nope then strings are sorted by the labels of
3326 the ROI's parent.
3327 \return clist (SUMA_ASSEMBLE_LIST_STRUCT *) pointer to structure containing results
3328
3329 \sa SUMA_FreeAssembleListStruct
3330 \sa SUMA_CreateAssembleListStruct
3331
3332 */
SUMA_AssembleAllROIList(SUMA_DO * dov,int N_dov,SUMA_Boolean SortByLabel)3333 SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleAllROIList (SUMA_DO * dov, int N_dov,
3334 SUMA_Boolean SortByLabel)
3335 {
3336 static char FuncName[]={"SUMA_AssembleAllROIList"};
3337 int i=-1, N_clist=-1;
3338 DList *list=NULL, *listop = NULL;
3339 DListElmt *Elm = NULL, *Elmop = NULL;
3340 char Label[SUMA_MAX_NAME_LENGTH],
3341 Parent_Label[SUMA_MAX_NAME_LENGTH], *store=NULL;
3342 SUMA_SurfaceObject *SO = NULL;
3343 char **clist=NULL;
3344 void **oplist=NULL;
3345 SUMA_DRAWN_ROI *ROI=NULL;
3346 SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;
3347 SUMA_Boolean Found = NOPE;
3348 SUMA_Boolean LocalHead = NOPE;
3349
3350 SUMA_ENTRY;
3351
3352 list = (DList *)SUMA_malloc(sizeof(DList));
3353 listop = (DList *)SUMA_malloc(sizeof(DList));
3354
3355 clist = NULL;
3356 N_clist = -1;
3357
3358 dlist_init(list, NULL);
3359 dlist_init(listop, NULL);
3360 for (i=0; i < N_dov; ++i) {
3361 if (dov[i].ObjectType == ROIdO_type) {
3362 ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
3363 if (LocalHead)
3364 fprintf (SUMA_STDERR, "%s: Found an ROI %s\n", FuncName, ROI->Label);
3365 if (!ROI->Label) sprintf (Label,"NULL");
3366 else sprintf (Label,"%s", ROI->Label);
3367 if (!ROI->Parent_idcode_str) sprintf (Parent_Label,"NULL");
3368 else {
3369 SO = SUMA_findSOp_inDOv(ROI->Parent_idcode_str, dov, N_dov);
3370 if (!SO) sprintf (Parent_Label,"Unknown");
3371 else if (!SO->Label) sprintf (Parent_Label,"Empty");
3372 else sprintf (Parent_Label,"%s", SO->Label);
3373 }
3374 /* Now allocate space for that label */
3375 store = (char *)SUMA_calloc(strlen(Label)+strlen(Parent_Label)+5,
3376 sizeof(char));
3377 if (SortByLabel) {
3378 sprintf(store,"%s:%s", Label, Parent_Label);
3379 } else {
3380 sprintf(store,"%s:%s", Parent_Label, Label);
3381 }
3382
3383 /* now place it in the list by aplhpabetical order */
3384 if (!list->size) {
3385 dlist_ins_next(list, dlist_tail(list), (void*)store);
3386 dlist_ins_next(listop, dlist_tail(listop), (void*)ROI);
3387 }else { /* must sort first */
3388 Elm = NULL;
3389 Elmop = NULL;
3390 do {
3391 Found = NOPE;
3392 if (!Elm) {
3393 Elm = dlist_head(list);
3394 Elmop = dlist_head(listop);
3395 } else {
3396 Elm = dlist_next(Elm);
3397 Elmop = dlist_next(Elmop);
3398 }
3399
3400 if (strcmp(store, (char*)Elm->data) <= 0) {
3401 dlist_ins_prev(list, Elm, (void *)store);
3402 dlist_ins_prev(listop, Elmop, (void *)ROI);
3403 Found = YUP;
3404 } else if (Elm == dlist_tail(list)) {
3405 /* reached the end, append */
3406 dlist_ins_next(list, Elm, (void *)store);
3407 dlist_ins_next(listop, Elmop, (void *)ROI);
3408 Found = YUP;
3409 }
3410 } while (!Found);
3411 }
3412
3413 }
3414 }
3415
3416 if (!list->size) { /* Nothing found */
3417 N_clist = 0;
3418
3419 }else {
3420
3421 Elm = NULL;
3422 Elmop = NULL;
3423 clist = (char **)SUMA_calloc(list->size, sizeof(char *));
3424 oplist = (void **)SUMA_calloc(list->size, sizeof(void*));
3425 for (i=0; i< list->size; ++i) {
3426 if (!Elm) {
3427 Elm = dlist_head(list);
3428 Elmop = dlist_head(listop);
3429 } else {
3430 Elm = dlist_next(Elm);
3431 Elmop = dlist_next(Elmop);
3432 }
3433 clist[i] = (char*)Elm->data;
3434 oplist[i] = Elmop->data;
3435 }
3436
3437 N_clist = list->size;
3438 /* destroy list */
3439 dlist_destroy(list);SUMA_free(list);
3440 dlist_destroy(listop);SUMA_free(listop);
3441
3442
3443 }
3444
3445 clist_str = SUMA_CreateAssembleListStruct();
3446 clist_str->clist = clist;
3447 clist_str->oplist = oplist;
3448 clist_str->N_clist = N_clist;
3449
3450 /* return */
3451 SUMA_RETURN (clist_str);
3452 }
3453
3454 /*!
3455 \brief Creates an SUMA_ASSEMBLE_LIST_STRUCT *structure
3456 \sa SUMA_FreeAssembleListStruct
3457 */
SUMA_CreateAssembleListStruct(void)3458 SUMA_ASSEMBLE_LIST_STRUCT *SUMA_CreateAssembleListStruct(void)
3459 {
3460 static char FuncName[]={"SUMA_CreateAssembleListStruct"};
3461 SUMA_ASSEMBLE_LIST_STRUCT *str=NULL;
3462
3463 SUMA_ENTRY;
3464
3465 str = (SUMA_ASSEMBLE_LIST_STRUCT *)SUMA_malloc(sizeof(SUMA_ASSEMBLE_LIST_STRUCT));
3466 str->clist = NULL;
3467 str->N_clist = -1;
3468 str->oplist = NULL;
3469 str->content_id = NULL;
3470 SUMA_RETURN(str);
3471 }
3472 /*!
3473 \brief frees SUMA_ASSEMBLE_LIST_STRUCT *
3474 \param SUMA_ASSEMBLE_LIST_STRUCT *str
3475
3476 \return NULL always
3477
3478 -This function frees each string in clist. BUT NOT pointers in oplist (for obvious reasons)
3479 */
SUMA_FreeAssembleListStruct(SUMA_ASSEMBLE_LIST_STRUCT * str)3480 SUMA_ASSEMBLE_LIST_STRUCT *SUMA_FreeAssembleListStruct(
3481 SUMA_ASSEMBLE_LIST_STRUCT *str)
3482 {
3483 static char FuncName[]={"SUMA_FreeAssembleListStruct"};
3484 int i;
3485
3486 SUMA_ENTRY;
3487
3488 if (!str) SUMA_RETURN(NULL);
3489
3490 if (str->clist) {
3491 for (i=0; i < str->N_clist; ++i)
3492 if (str->clist[i]) SUMA_free(str->clist[i]);
3493 SUMA_free(str->clist);
3494 }
3495 if (str->oplist) SUMA_free(str->oplist);
3496 if (str->content_id) SUMA_free(str->content_id);
3497
3498 SUMA_free(str);
3499
3500 SUMA_RETURN(NULL);
3501 }
3502
3503
3504 /*!
3505 \brief Returns an ROI that is related to SO and is in InCreation (being actively drawn) DrawStatus
3506 There should only be one ROI in creation at any one time for a group of related surfaces.
3507
3508 ROI = SUMA_
3509 ROI_InCreation (SO, dov, N_dov);
3510
3511 \param SO (SUMA_SurfaceObject *) pointer to surface object
3512 \param dov (SUMA_DO *) pointer to vector of DOs (typically SUMAg_DOv)
3513 \param N_dov (int) number of elements in dov
3514 \return ROI (SUMA_DRAWN_ROI *) pointer to ROI object, NULL if no such object is found.
3515
3516 */
SUMA_FetchROI_InCreation(SUMA_SurfaceObject * SO,SUMA_DO * dov,int N_dov)3517 SUMA_DRAWN_ROI * SUMA_FetchROI_InCreation (SUMA_SurfaceObject *SO,
3518 SUMA_DO * dov, int N_dov)
3519 {
3520 int i;
3521 SUMA_DRAWN_ROI *ROI = NULL;
3522 static char FuncName[]={"SUMA_FetchROI_InCreation"};
3523
3524 SUMA_ENTRY;
3525
3526 for (i=0; i < N_dov; ++i) {
3527 if (dov[i].ObjectType == ROIdO_type) {
3528 ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
3529 if (ROI->DrawStatus == SUMA_ROI_InCreation) {
3530 if (SUMA_isdROIrelated (ROI, (SUMA_ALL_DO *)SO)) {
3531 /* found an ROI, should be the only one, return */
3532 SUMA_RETURN (ROI);
3533 }
3534 }
3535 }
3536 }
3537 SUMA_RETURN (NULL);
3538 }
3539
3540 /*!
3541 \brief Returns YUP if the surface: NBV(or NBSP)->Parent_idcode_str is the same as SO->idcode_str.
3542 NOPE otherwise
3543
3544 ans = SUMA_isNBDOrelated (NBDO, SO);
3545
3546 \param NBV (SUMA_NB_DO * ) pointer to NBV/NBSP object
3547 \param SO (SUMA_SurfaceObject *) pointer to surface object
3548 \return ans (SUMA_Boolean) YUP/NOPE
3549 \sa SUMA_isNIDOrelated
3550 */
SUMA_isNBDOrelated(SUMA_NB_DO * SDO,SUMA_SurfaceObject * SO)3551 SUMA_Boolean SUMA_isNBDOrelated (SUMA_NB_DO *SDO, SUMA_SurfaceObject *SO)
3552 {
3553 static char FuncName[]={"SUMA_isNBDOrelated"};
3554 SUMA_SurfaceObject *SO_NB = NULL;
3555 SUMA_Boolean LocalHead = NOPE;
3556
3557 SUMA_ENTRY;
3558
3559 /* Just compare the idcodes, not allowing for kinship yet but
3560 code below could do that */
3561 if (strcmp(SO->idcode_str, SDO->Parent_idcode_str) == 0) {
3562 SUMA_RETURN(YUP);
3563 } else {
3564 SUMA_RETURN(NOPE);
3565 }
3566
3567 SUMA_LHv(" %s SO->LocalDomainParentID\n"
3568 " %s SDO->Parent_idcode_str\n"
3569 " %s SO->idcode_str\n",
3570 SO->LocalDomainParentID, SDO->Parent_idcode_str, SO->idcode_str);
3571
3572 /* find the pointer to the surface having for an idcode_str:
3573 ROI->Parent_idcode_str */
3574 SO_NB = SUMA_findSOp_inDOv(SDO->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
3575
3576 if (!SO_NB) {
3577 SUMA_SL_Err("Could not find surface of SDO->Parent_idcode_str");
3578 SUMA_RETURN (NOPE);
3579 }
3580
3581 if (SUMA_isRelated_SO(SO, SO_NB, 1)){ /* relationship of the 1st order only */
3582 SUMA_RETURN (YUP);
3583 }
3584
3585 /* If you get here, you have SO_NB so return happily */
3586 SUMA_RETURN (NOPE);
3587 }
3588
SUMA_isNIDO_SurfBased(SUMA_NIDO * nido)3589 SUMA_Boolean SUMA_isNIDO_SurfBased(SUMA_NIDO *nido)
3590 {
3591 static char FuncName[]={"SUMA_isNIDO_SurfBased"};
3592 char *atr=NULL;
3593
3594 SUMA_ENTRY;
3595
3596 atr = NI_get_attribute(nido->ngr,"bond");
3597 if (!atr) SUMA_RETURN(NOPE);
3598
3599 if (atr[0] == 's') SUMA_RETURN(YUP);
3600
3601 SUMA_RETURN(NOPE);
3602 }
3603
3604 /*!
3605 If you make changes here, look into SUMA_isNBDOrelated
3606 */
SUMA_isNIDOrelated(SUMA_NIDO * SDO,SUMA_SurfaceObject * SO)3607 SUMA_Boolean SUMA_isNIDOrelated (SUMA_NIDO *SDO, SUMA_SurfaceObject *SO)
3608 {
3609 static char FuncName[]={"SUMA_isNIDOrelated"};
3610 SUMA_SurfaceObject *SO_NB = NULL;
3611 char *Parent_idcode_str=NULL;
3612 SUMA_Boolean LocalHead = NOPE;
3613
3614 SUMA_ENTRY;
3615
3616 /* Just compare the idcodes, not allowing
3617 for kinship yet but code below could do that */
3618 if ((Parent_idcode_str = NI_get_attribute(SDO->ngr, "Parent_idcode_str")) &&
3619 strcmp(SO->idcode_str, Parent_idcode_str) == 0) {
3620 SUMA_RETURN(YUP);
3621 } else {
3622 SUMA_RETURN(NOPE);
3623 }
3624
3625 SUMA_LHv(" %s SO->LocalDomainParentID\n"
3626 " %s SDO->Parent_idcode_str\n"
3627 " %s SO->idcode_str\n",
3628 SO->LocalDomainParentID, Parent_idcode_str, SO->idcode_str);
3629
3630 /* find the pointer to the surface having for an idcode_str:
3631 ROI->Parent_idcode_str */
3632 SO_NB = SUMA_findSOp_inDOv(Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
3633
3634 if (!SO_NB) {
3635 SUMA_SL_Err("Could not find surface of SDO->Parent_idcode_str");
3636 SUMA_RETURN (NOPE);
3637 }
3638
3639 if (SUMA_isRelated_SO(SO, SO_NB, 1)){ /*relationship of the 1st order only */
3640 SUMA_RETURN (YUP);
3641 }
3642
3643 /* If you get here, you have SO_NB so return happily */
3644 SUMA_RETURN (NOPE);
3645 }
3646
3647
3648
3649 /*!
3650 \brief Returns YUP if the surface: dROI->Parent_idcode_str is related to SO->idcode_str or SO->LocalDomainParentID.
3651 NOPE otherwise
3652
3653 ans = SUMA_isdROIrelated (dROI, SO);
3654
3655 \param ROI (SUMA_DRAWN_ROI *) pointer to drawn ROI
3656 \param SO (SUMA_SurfaceObject *) pointer to surface object
3657 \return ans (SUMA_Boolean) YUP/NOPE
3658
3659 */
SUMA_isdROIrelated(SUMA_DRAWN_ROI * ROI,SUMA_ALL_DO * ado)3660 SUMA_Boolean SUMA_isdROIrelated (SUMA_DRAWN_ROI *ROI, SUMA_ALL_DO *ado)
3661 {
3662 static char FuncName[]={"SUMA_isdROIrelated"};
3663 SUMA_SurfaceObject *SO_ROI = NULL;
3664 SUMA_Boolean LocalHead = NOPE;
3665
3666 SUMA_ENTRY;
3667
3668 if (!ado || !ROI) {
3669 SUMA_S_Err("NULL input");
3670 SUMA_RETURN(NOPE);
3671 }
3672 switch (ado->do_type) {
3673 case SO_type: {
3674 SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)ado;
3675 if (LocalHead) {
3676 fprintf (SUMA_STDERR,
3677 "%s: %s SO->LocalDomainParentID\n",
3678 FuncName, SO->LocalDomainParentID);
3679 fprintf (SUMA_STDERR,
3680 "%s: %s ROI->Parent_idcode_str\n",
3681 FuncName, ROI->Parent_idcode_str);
3682 fprintf (SUMA_STDERR,
3683 "%s: %s SO->idcode_str\n",
3684 FuncName, SO->idcode_str);
3685 }
3686
3687 /* find the pointer to the surface having for an
3688 idcode_str: ROI->Parent_idcode_str */
3689 SO_ROI = SUMA_findSOp_inDOv(ROI->Parent_idcode_str,
3690 SUMAg_DOv, SUMAg_N_DOv);
3691
3692 if (!SO_ROI) {
3693 SUMA_SL_Err("Could not find surface of ROI->Parent_idcode_str");
3694 SUMA_RETURN(NOPE);
3695 }
3696
3697 if (SUMA_isRelated_SO(SO, SO_ROI, 1)) {
3698 /* relationship of the 1st order only */
3699 SUMA_RETURN (YUP);
3700 }
3701 break; }
3702 default:
3703 SUMA_S_Errv("Not ready for %s\n",
3704 SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
3705 break;
3706 }
3707
3708 SUMA_RETURN (NOPE);
3709 }
3710
3711 /*!
3712 \brief Returns YUP if if the surface: ROI->Parent_idcode_str is related to SO->idcode_str or SO->LocalDomainParentID.
3713 NOPE otherwise
3714
3715 ans = SUMA_isROIrelated (ROI, SO);
3716
3717 \param ROI (SUMA_ROI *) pointer to ROI
3718 \param SO (SUMA_SurfaceObject *) pointer to surface object
3719 \return ans (SUMA_Boolean) YUP/NOPE
3720
3721 */
SUMA_isROIrelated(SUMA_ROI * ROI,SUMA_SurfaceObject * SO)3722 SUMA_Boolean SUMA_isROIrelated (SUMA_ROI *ROI, SUMA_SurfaceObject *SO)
3723 {
3724 static char FuncName[]={"SUMA_isROIrelated"};
3725 SUMA_SurfaceObject *SO_ROI = NULL;
3726
3727 SUMA_ENTRY;
3728
3729 /* find the pointer to the surface having for an idcode_str:
3730 ROI->Parent_idcode_str */
3731 SO_ROI = SUMA_findSOp_inDOv(ROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
3732
3733 if (!SO_ROI) {
3734 SUMA_SL_Err("Could not find surface of ROI->Parent_idcode_str");
3735 SUMA_RETURN (NOPE);
3736 }
3737
3738 if (SUMA_isRelated_SO(SO, SO_ROI, 1)){/* relationship of the 1st order only */
3739 SUMA_RETURN (YUP);
3740 }
3741
3742 SUMA_RETURN (NOPE);
3743 }
3744
3745 /*!
3746 \brief Return a mask of the nodes belonging to any ROI of a certain surface
3747 Mask = SUMA_Build_Mask_AllROI (dov, N_dov, SO, Mask, N_added);
3748
3749 \param dov (SUMA_DO*) pointer to vector of displayable objects to consider
3750 \param N_dov (int) number of elements in dov
3751 \param SO (SUMA_SurfaceObject *)
3752 \param Mask (int *) pointer to mask vector.
3753 0 if node belongs to no ROI
3754 n if node belongs to n ROIs
3755 Pass NULL if you're calling this function for the first time.
3756 \param N_added (int *)integer containing the total number of nodes added to Mask.
3757 That would be the sum of the number of nodes found in all ROIs.
3758 Duplicate nodes are counted twice. If you want the number of nodes without
3759 the duplicates, you need to count non-zero values in Mask.
3760 \return Mask (int *) pointer to modified mask vector.
3761 */
SUMA_Build_Mask_AllROI(SUMA_DO * dov,int N_do,SUMA_SurfaceObject * SO,int * Mask,int * N_added)3762 int * SUMA_Build_Mask_AllROI (SUMA_DO *dov, int N_do, SUMA_SurfaceObject *SO,
3763 int *Mask, int *N_added)
3764 {
3765 static char FuncName[]={"SUMA_Build_Mask_AllROI"};
3766 int Npart = 0,i;
3767 SUMA_DRAWN_ROI *D_ROI=NULL;
3768 SUMA_ROI *ROI = NULL;
3769 SUMA_Boolean LocalHead = NOPE;
3770
3771 SUMA_ENTRY;
3772
3773 *N_added = -1;
3774
3775 if (!Mask) { /* allocate for it */
3776 Mask = (int *)SUMA_calloc(SO->N_Node, sizeof(int));
3777 if (!Mask) {
3778 SUMA_S_Err ("Failed to allocate for Mask.");
3779 SUMA_RETURN(NULL);
3780 }
3781 }
3782
3783 for (i=0; i < N_do; ++i) {
3784 switch (dov[i].ObjectType) { /* case Object Type */
3785 case ROIdO_type:
3786 D_ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
3787 if (SUMA_isdROIrelated (D_ROI, (SUMA_ALL_DO *)SO)) {
3788 SUMA_LH("Found a drawn ROI, building mask...");
3789
3790 Npart = SUMA_Build_Mask_DrawnROI (D_ROI, Mask);
3791 if (Npart < 0) {
3792 SUMA_S_Err ("Badness in SUMA_Build_Mask_DrawnROI");
3793 if (Mask) SUMA_free(Mask);
3794 *N_added = -1;
3795 SUMA_RETURN(NULL);
3796 }else {
3797 *N_added = *N_added + Npart;
3798 SUMA_LHv("%d nodes found in that ROI.\n", Npart);
3799 }
3800 }
3801 break;
3802 case ROIO_type:
3803 ROI = (SUMA_ROI *)dov[i].OP;
3804 if (SUMA_isROIrelated (ROI, SO)) {
3805 SUMA_S_Err ("Not dealing with regular ROIs yet");
3806 }
3807 break;
3808 default:
3809 /* not an ROI */
3810 break;
3811 }
3812 }
3813
3814 SUMA_RETURN(Mask);
3815 }
3816
3817 /*!
3818 \brief Return a mask of the nodes belonging to a drawn ROI of a certain surface
3819 N_added = SUMA_Build_Mask_DrawnROI (dROI, Mask);
3820
3821 \param dROI (SUMA_DRAWN_ROI *) the pointer to the ROI structure
3822 \param Mask (int *) pointer to mask vector.
3823 0 if node belongs to no ROI
3824 n if node belongs to n ROIs
3825 It is the calling function's responsability to make sure enough space is allocated for
3826 Mask and that cleanup is properly handled.
3827 \return N_added (int *)integer containing the number of nodes found in dROI.
3828 This variable is set to -1 when trouble occurs.
3829 */
SUMA_Build_Mask_DrawnROI(SUMA_DRAWN_ROI * D_ROI,int * Mask)3830 int SUMA_Build_Mask_DrawnROI (SUMA_DRAWN_ROI *D_ROI, int *Mask)
3831 {
3832 static char FuncName[]={"SUMA_Build_Mask_DrawnROI"};
3833 DListElmt *NextElm=NULL;
3834 int ii, N_added;
3835 SUMA_ROI_DATUM *ROId=NULL;
3836
3837 SUMA_ENTRY;
3838
3839 N_added = -1;
3840
3841 if (!Mask) {
3842 SUMA_S_Err ("Mask is NULL");
3843 SUMA_RETURN(N_added);
3844 }
3845
3846 if (!D_ROI->ROIstrokelist) {
3847 N_added = 0;
3848 SUMA_RETURN(N_added);
3849 }
3850
3851 if (!dlist_size(D_ROI->ROIstrokelist)) {
3852 N_added = 0;
3853 SUMA_RETURN(N_added);
3854 }
3855
3856 /* start with the first element */
3857 NextElm = NULL;
3858 do {
3859 if (!NextElm) {
3860 NextElm = dlist_head(D_ROI->ROIstrokelist);
3861 }else {
3862 NextElm = dlist_next(NextElm);
3863 }
3864 ROId = (SUMA_ROI_DATUM *)NextElm->data;
3865 if (ROId->N_n) {
3866 for (ii = 0; ii < ROId->N_n; ++ii) {
3867 ++Mask[ROId->nPath[ii]];
3868 ++N_added;
3869 }
3870 }
3871 } while (NextElm != dlist_tail(D_ROI->ROIstrokelist));
3872
3873 SUMA_RETURN (N_added);
3874 }
3875
3876 /*!
3877 \brief deletes an ROI from the list of drawn objects
3878 */
SUMA_DeleteROI(SUMA_DRAWN_ROI * ROI)3879 SUMA_Boolean SUMA_DeleteROI (SUMA_DRAWN_ROI *ROI)
3880 {
3881 static char FuncName[]={"SUMA_DeleteROI"};
3882 SUMA_ASSEMBLE_LIST_STRUCT *ALS = NULL;
3883 SUMA_DRAWN_ROI *NextROI=NULL;
3884 int i;
3885 SUMA_Boolean WasCurrent = NOPE, Shaded = NOPE;
3886 SUMA_Boolean LocalHead = NOPE;
3887
3888 SUMA_ENTRY;
3889
3890 if (!ROI) {
3891 SUMA_LH("Null ROI");
3892 SUMA_RETURN(YUP);
3893 }
3894
3895 /* form a list of the current ROI available for editing */
3896
3897 /* assemble the ROI list */
3898 ALS = SUMA_AssembleAllROIList (SUMAg_DOv, SUMAg_N_DOv, YUP);
3899
3900 NextROI = NULL;
3901 if (ALS) {
3902 if (ALS->N_clist) {
3903 i=0;
3904 while (!NextROI && i<ALS->N_clist) {
3905 if (ALS->oplist[i] != (void*)ROI)
3906 NextROI = (SUMA_DRAWN_ROI *)ALS->oplist[i];
3907 ++i;
3908 }
3909 }
3910 SUMA_FreeAssembleListStruct(ALS);
3911 }
3912
3913 /* check to see if ROI being deleted is current one */
3914 if (ROI == SUMAg_CF->X->DrawROI->curDrawnROI) {
3915 WasCurrent = YUP;
3916 }else {
3917 WasCurrent = NOPE;
3918 }
3919
3920 /* Close the ROIlist window if it is open */
3921 SUMA_IS_DRAW_ROI_SWITCH_ROI_SHADED(Shaded);
3922 if (!Shaded) {
3923 SUMA_LH("Closing switch ROI window ...");
3924 SUMA_cb_CloseSwitchROI(NULL,
3925 (XtPointer) SUMAg_CF->X->DrawROI->SwitchROIlst, NULL);
3926 }
3927
3928 /* remove ROI for SUMAg_DO and clear the ROI structure*/
3929 if (!SUMA_RemoveDO(SUMAg_DOv, &SUMAg_N_DOv, (void *)ROI, YUP)) {
3930 SUMA_SLP_Err("Failed to remove DO from list.");
3931 SUMA_RETURN(NOPE);
3932 }
3933
3934 if (WasCurrent) {
3935 SUMAg_CF->X->DrawROI->curDrawnROI = NextROI;
3936
3937 /* reinitialize the draw ROI window */
3938 SUMA_InitializeDrawROIWindow(SUMAg_CF->X->DrawROI->curDrawnROI);
3939 }
3940
3941 SUMA_RETURN(YUP);
3942 }
3943
3944 /*!
3945 \brief return +1 if surface is typically the outer layer surface used in Vol2Surf
3946 -1 if surface is typically the inner layer surface used in Vol2Surf
3947 0 if no comment
3948 */
SUMA_isTypicalSOforVolSurf(SUMA_SurfaceObject * SO)3949 int SUMA_isTypicalSOforVolSurf (SUMA_SurfaceObject *SO)
3950 {
3951 static char FuncName[]={"SUMA_isTypicalSOforVolSurf"};
3952
3953 SUMA_ENTRY;
3954
3955 switch (SO->FileType) {
3956 case SUMA_STL:
3957 case SUMA_PLY:
3958 case SUMA_VEC:
3959 case SUMA_FREE_SURFER:
3960 if (SUMA_iswordin (SO->Name.FileName, "smoothwm")) SUMA_RETURN(-1);
3961 else if (SUMA_iswordin (SO->Name.FileName, "pial")) SUMA_RETURN(1);
3962 else SUMA_RETURN(0);
3963 break;
3964 default:
3965 SUMA_RETURN(0);
3966 break;
3967 }
3968
3969 SUMA_RETURN(0);
3970 }
3971
3972 /*!
3973 \brief Allow users to exclude certain states from being sent
3974 to AFNI
3975 SUMA_ExcludeFromToAfni
3976 */
SUMA_ExcludeFromSendToAfni(SUMA_SurfaceObject * SO)3977 int SUMA_ExcludeFromSendToAfni (SUMA_SurfaceObject *SO)
3978 {
3979 static char FuncName[]={"SUMA_ExcludeFromSendToAfni"};
3980
3981 SUMA_ENTRY;
3982
3983 if (SUMA_EnvEquals("SUMA_DoNotSendStates", SO->State, 1, " ,;"))
3984 RETURN(1);
3985
3986 RETURN(0);
3987 }
3988
SUMA_Find_XformByID(char * idcode_str)3989 SUMA_XFORM *SUMA_Find_XformByID(char *idcode_str)
3990 {
3991 static char FuncName[]={"SUMA_Find_XformByID"};
3992 SUMA_XFORM *xf = NULL, *xft=NULL;
3993 DListElmt *el=NULL;
3994 DList *lst = SUMAg_CF->xforms;
3995
3996 SUMA_ENTRY;
3997
3998 if (!lst || !idcode_str) SUMA_RETURN(xf);
3999
4000 el = dlist_head(lst);
4001
4002 while (el && !xf) {
4003 xft = (SUMA_XFORM *)el->data;
4004 if (!strcmp(xft->idcode_str,idcode_str)) {
4005 xf = xft; break;
4006 }
4007 el = dlist_next(el);
4008 }
4009
4010 SUMA_RETURN(xf);
4011 }
4012
4013
4014 /*!
4015 Find a transform with a particular name AND a parent with a matching idcode
4016 */
SUMA_Find_XformByParent(char * name,char * parent_idcode,int * iloc)4017 SUMA_XFORM *SUMA_Find_XformByParent(char *name, char *parent_idcode, int *iloc)
4018 {
4019 static char FuncName[]={"SUMA_Find_XformByParent"};
4020 SUMA_XFORM *xf = NULL, *xft=NULL;
4021 DListElmt *el=NULL;
4022 DList *lst = SUMAg_CF->xforms;
4023 int i;
4024
4025 SUMA_ENTRY;
4026
4027 if (!lst || !name || !parent_idcode) SUMA_RETURN(xf);
4028
4029 el = dlist_head(lst);
4030
4031 while (el && !xf) {
4032 xft = (SUMA_XFORM *)el->data;
4033 if (!strcmp(xft->name,name)) {
4034 for (i=0; i<xft->N_parents; ++i) {
4035 if (!strcmp(xft->parents[i], parent_idcode)) {
4036 xf = xft;
4037 if (iloc) *iloc = i;
4038 break;
4039 }
4040 }
4041 }
4042 el = dlist_next(el);
4043 }
4044
4045 SUMA_RETURN(xf);
4046 }
4047
SUMA_Find_XformByChild(char * name,char * child_idcode,int * iloc)4048 SUMA_XFORM *SUMA_Find_XformByChild(char *name, char *child_idcode, int *iloc)
4049 {
4050 static char FuncName[]={"SUMA_Find_XformByChild"};
4051 SUMA_XFORM *xf = NULL, *xft=NULL;
4052 DListElmt *el=NULL;
4053 DList *lst = SUMAg_CF->xforms;
4054 int i;
4055
4056 SUMA_ENTRY;
4057
4058 if (!lst || !name || !child_idcode) SUMA_RETURN(xf);
4059
4060 el = dlist_head(lst);
4061
4062 while (el && !xf) {
4063 xft = (SUMA_XFORM *)el->data;
4064 if (!strcmp(xft->name,name)) {
4065 for (i=0; i<xft->N_children; ++i) {
4066 if (!strcmp(xft->children[i], child_idcode)) {
4067 xf = xft;
4068 if (iloc) *iloc = i;
4069 break;
4070 }
4071 }
4072 }
4073 el = dlist_next(el);
4074 }
4075
4076 SUMA_RETURN(xf);
4077 }
4078
4079
SUMA_Show_Xforms(DList * dl,FILE * Out,int detail)4080 void SUMA_Show_Xforms (DList *dl, FILE *Out, int detail)
4081 {
4082 static char FuncName[]={"SUMA_Show_Xforms"};
4083 char *s = NULL;
4084
4085 SUMA_ENTRY;
4086
4087 if (Out == NULL) Out = stdout;
4088
4089 s = SUMA_Xforms_Info (dl, detail);
4090
4091 if (s) {
4092 fprintf(Out, "%s", s);
4093 SUMA_free(s); s = NULL;
4094 }else {
4095 SUMA_SL_Err("Failed in SUMA_Xforms_Info");
4096 }
4097
4098 SUMA_RETURNe;
4099 }
4100
SUMA_Xforms_Info(DList * dl,int detail)4101 char *SUMA_Xforms_Info(DList *dl, int detail)
4102 {
4103 static char FuncName[]={"SUMA_Xforms_Info"};
4104 DListElmt *el=NULL;
4105 char *s = NULL;
4106 SUMA_STRING *SS = NULL;
4107 SUMA_XFORM *xf=NULL;
4108 SUMA_DSET *dset=NULL;
4109 SUMA_SurfaceObject *SO=NULL;
4110 int i;
4111
4112 SUMA_ENTRY;
4113
4114 SS = SUMA_StringAppend(NULL, NULL);
4115
4116 if (!dl) {
4117 SS = SUMA_StringAppend(SS,"NULL Overlay Xforms List\n");
4118 SUMA_SS2S(SS, s);
4119 SUMA_RETURN(s);
4120 } else {
4121 SS = SUMA_StringAppend_va(SS,"%d Overlay Xforms in list.\n",
4122 dlist_size(dl));
4123 }
4124
4125 el = dlist_head(dl);
4126 while(el) {
4127 xf = (SUMA_XFORM *)el->data;
4128 SS = SUMA_StringAppend_va( SS,"Xform name: %s, id: %s\n"
4129 " active (1=Y, -1=N): %d\n",
4130 xf->name, xf->idcode_str,
4131 xf->active);
4132 for (i=0; i<xf->N_parents; ++i) {
4133 SS = SUMA_StringAppend_va( SS,
4134 " parent %d: %s\n",
4135 i, xf->parents[i]);
4136 if (SUMA_is_ID_4_SO(xf->parents[i], &SO)) {
4137 SS = SUMA_StringAppend_va( SS,
4138 " SO labeled %s \n",
4139 CHECK_NULL_STR(SO->Label));
4140 } else if (SUMA_is_ID_4_DSET(xf->parents[i], &dset)) {
4141 SS = SUMA_StringAppend_va( SS,
4142 " DSET labeled %s \n",
4143 CHECK_NULL_STR(SDSET_LABEL(dset)));
4144 } else {
4145 SS = SUMA_StringAppend_va( SS,
4146 " %s is neither SO, not DSET.\n",
4147 xf->parents[i]);
4148 }
4149 if (SUMA_is_ID_4_SO(xf->parents_domain[i], &SO)) {
4150 SS = SUMA_StringAppend_va( SS,
4151 " parent_domain: %s, labeled %s\n",
4152 xf->parents_domain[i],
4153 CHECK_NULL_STR(SO->Label));
4154 } else {
4155 SS = SUMA_StringAppend_va( SS,
4156 " parent_domain: %s, Not found!\n",
4157 xf->parents_domain[i]);
4158 }
4159
4160 }
4161
4162 for (i=0; i<xf->N_children; ++i) {
4163 SS = SUMA_StringAppend_va( SS,
4164 " child %d: %s\n",
4165 i, xf->children[i]);
4166 if (SUMA_is_ID_4_SO(xf->children[i], &SO)) {
4167 SS = SUMA_StringAppend_va( SS,
4168 " SO labeled %s \n",
4169 CHECK_NULL_STR(SO->Label));
4170 } else if (SUMA_is_ID_4_DSET(xf->parents[i], &dset)) {
4171 SS = SUMA_StringAppend_va( SS,
4172 " DSET labeled %s \n",
4173 CHECK_NULL_STR(SDSET_LABEL(dset)));
4174 } else {
4175 SS = SUMA_StringAppend_va( SS,
4176 " %s is neither SO, not DSET.\n",
4177 xf->children[i]);
4178 }
4179 }
4180
4181 if (xf->XformOpts) {
4182 s = SUMA_NI_nel_Info((NI_element *)xf->XformOpts, detail);
4183 SS = SUMA_StringAppend_va( SS,
4184 " XformOpts is:\n"
4185 "%s\n",
4186 s);
4187 SUMA_free(s);
4188 } else {
4189 SS = SUMA_StringAppend_va( SS,
4190 " XformOpts is NULL");
4191 }
4192
4193 if (xf->gui) {
4194 SS = SUMA_StringAppend_va( SS,
4195 " GUI is not null");
4196 } else {
4197 SS = SUMA_StringAppend_va( SS,
4198 " GUI is null");
4199 }
4200
4201 SS = SUMA_StringAppend(SS, "\n");
4202
4203 el = dlist_next(el);
4204 }
4205
4206 SUMA_SS2S(SS, s);
4207
4208 SUMA_RETURN(s);
4209 }
4210
SUMA_Show_Callbacks(DList * dl,FILE * Out,int detail)4211 void SUMA_Show_Callbacks (DList *dl, FILE *Out, int detail)
4212 {
4213 static char FuncName[]={"SUMA_Show_Callbacks"};
4214 char *s = NULL;
4215
4216 SUMA_ENTRY;
4217
4218 if (Out == NULL) Out = stdout;
4219
4220 s = SUMA_Callbacks_Info (dl, detail);
4221
4222 if (s) {
4223 fprintf(Out, "%s", s);
4224 SUMA_free(s); s = NULL;
4225 }else {
4226 SUMA_SL_Err("Failed in SUMA_Callbacks_Info");
4227 }
4228
4229 SUMA_RETURNe;
4230 }
4231
SUMA_Callbacks_Info(DList * dl,int detail)4232 char *SUMA_Callbacks_Info(DList *dl, int detail)
4233 {
4234 static char FuncName[]={"SUMA_Callbacks_Info"};
4235 char *s = NULL;
4236 DListElmt *el=NULL;
4237 NI_group *ngr=NULL;
4238 NI_element *nel = NULL;
4239 SUMA_STRING *SS = NULL;
4240 SUMA_DSET *dset=NULL;
4241 SUMA_SurfaceObject *SO=NULL;
4242 SUMA_CALLBACK *cb=NULL;
4243 SUMA_XFORM *xf=NULL;
4244 int i;
4245
4246 SUMA_ENTRY;
4247 SS = SUMA_StringAppend(NULL, NULL);
4248
4249 if (!dl) {
4250 SS = SUMA_StringAppend(SS,"NULL Callbacks List\n");
4251 SUMA_SS2S(SS, s);
4252 SUMA_RETURN(s);
4253 } else {
4254 SS = SUMA_StringAppend_va(SS,"%d Callbacks in list.\n",
4255 dlist_size(dl));
4256 }
4257
4258 el = dlist_head(dl);
4259 while(el) {
4260 cb = (SUMA_CALLBACK *)el->data;
4261 xf = SUMA_Find_XformByID(cb->creator_xform);
4262 SS = SUMA_StringAppend_va( SS,"CB trigger event: %d \n"
4263 " active (1=Y, -1=N): %d\n"
4264 " pending (1=Y, 0=N): %d\n"
4265 " trigger source %d\n"
4266 , cb->event
4267 , cb->active, cb->pending
4268 , cb->trigger_source );
4269 if (xf) {
4270 SS = SUMA_StringAppend_va( SS," Creator Xform: %s\n", xf->name);
4271 } else {
4272 SS = SUMA_StringAppend_va( SS," No creator xform found.\n");
4273 }
4274 for (i=0; i<cb->N_parents; ++i) {
4275 SS = SUMA_StringAppend_va( SS,
4276 " parent %d: %s\n",
4277 i, cb->parents[i]);
4278
4279 if (SUMA_is_ID_4_SO(cb->parents[i], &SO)) {
4280 SS = SUMA_StringAppend_va( SS,
4281 " SO labeled %s \n",
4282 CHECK_NULL_STR(SO->Label));
4283 } else if (SUMA_is_ID_4_DSET(cb->parents[i], &dset)) {
4284 SS = SUMA_StringAppend_va( SS,
4285 " DSET labeled %s \n",
4286 CHECK_NULL_STR(SDSET_LABEL(dset)));
4287 } else {
4288 SS = SUMA_StringAppend_va( SS,
4289 " %s is neither SO, not DSET.\n",
4290 cb->parents[i]);
4291 }
4292 if (SUMA_is_ID_4_SO(cb->parents_domain[i], &SO)) {
4293 SS = SUMA_StringAppend_va( SS,
4294 " parent_domain: %s, labeled %s\n",
4295 cb->parents_domain[i],
4296 CHECK_NULL_STR(SO->Label));
4297 } else {
4298 SS = SUMA_StringAppend_va( SS,
4299 " parent_domain: %s, Not found!\n",
4300 cb->parents_domain[i]);
4301 }
4302 }
4303
4304 SS = SUMA_StringAppend_va( SS,
4305 " Function Name %s (%p)\n",
4306 cb->FunctionName, cb->FunctionPtr);
4307
4308 s = SUMA_NI_nel_Info((NI_element *)cb->FunctionInput, detail);
4309 SS = SUMA_StringAppend_va( SS,
4310 " Function Params:\n%s\n-----\n",
4311 s); SUMA_free(s); s = NULL;
4312
4313 SS = SUMA_StringAppend(SS, "\n");
4314
4315 if (detail > 1) {
4316 SUMA_S_Note("Detailed nel view\n");
4317 SUMA_ShowNel(nel);
4318 }
4319 el = dlist_next(el);
4320 }
4321
4322
4323 SUMA_SS2S(SS, s);
4324
4325 SUMA_RETURN(s);
4326 }
4327
4328
4329
SUMA_SetXformActive(SUMA_XFORM * xf,int active,int fromgui)4330 SUMA_Boolean SUMA_SetXformActive(SUMA_XFORM *xf, int active, int fromgui)
4331 {
4332 static char FuncName[]={"SUMA_SetXformActive"};
4333 SUMA_CALLBACK *cb;
4334 DListElmt *el=NULL;
4335 DList *dl=SUMAg_CF->callbacks;
4336 SUMA_Boolean LocalHead = NOPE;
4337
4338 SUMA_ENTRY;
4339
4340 if (!xf) SUMA_RETURN(NOPE);
4341
4342 xf->active = active;
4343
4344 if (!xf->gui) {
4345 /* create GUI */
4346 SUMA_CreateXformInterface(xf);
4347 } else if (!fromgui){
4348 /* Raise GUI */
4349 if (LocalHead)
4350 fprintf (SUMA_STDERR,"%s: raising Xform GUI window \n", FuncName);
4351 XMapRaised(SUMAg_CF->X->DPY_controller1,
4352 XtWindow(xf->gui->AppShell));
4353 }
4354
4355
4356 if (0 && !fromgui) { /* not sure why I have this here.
4357 SUMA_InitializeXformInterface is called in SUMA_D_Key,
4358 which is the function called in both GUI and non GUI
4359 modes... */
4360 /* initialize the gui */
4361 SUMA_InitializeXformInterface(xf);
4362 }
4363
4364 if (!dl) SUMA_RETURN(YUP);
4365
4366 /* Now reflect that in all callbacks that were created by xform */
4367 el = dlist_head(dl);
4368 while (el) {
4369 cb = (SUMA_CALLBACK *)el->data;
4370 if (!strcmp(cb->creator_xform, xf->idcode_str)) {
4371 cb->active = active;
4372 if (!cb->active < 1) {
4373 SUMA_SetCallbackPending(cb, 0, SES_Empty);
4374 }
4375 }
4376 el = dlist_next(el);
4377 }
4378 SUMA_RETURN(YUP);
4379 }
4380
SUMA_SetXformShowPreProc(SUMA_XFORM * xf,int ShowPreProc,int fromgui)4381 SUMA_Boolean SUMA_SetXformShowPreProc(SUMA_XFORM *xf, int ShowPreProc,
4382 int fromgui)
4383 {
4384 static char FuncName[]={"SUMA_SetXformShowPreProc"};
4385 SUMA_CALLBACK *cb;
4386 DListElmt *el=NULL;
4387 DList *dl=SUMAg_CF->callbacks;
4388 NI_element *dotopt=NULL;
4389 int ii=0;
4390 SUMA_DSET *in_dset=NULL, *pp_dset=NULL;
4391 SUMA_Boolean LocalHead = NOPE;
4392
4393 SUMA_ENTRY;
4394
4395 if (!xf) SUMA_RETURN(NOPE);
4396
4397 xf->ShowPreProc = ShowPreProc;
4398
4399 if (!xf->gui) {
4400 /* create GUI */
4401 SUMA_CreateXformInterface(xf);
4402 } else if (!fromgui){
4403 /* Raise GUI */
4404 if (LocalHead)
4405 fprintf (SUMA_STDERR,"%s: raising Xform GUI window \n", FuncName);
4406 XMapRaised(SUMAg_CF->X->DPY_controller1,
4407 XtWindow(xf->gui->AppShell));
4408 }
4409
4410 if (!fromgui) {
4411 /* initialize the gui */
4412 SUMA_InitializeXformInterface(xf);
4413 }
4414
4415 if (!dl) SUMA_RETURN(YUP);
4416
4417 /* Now do something about showing */
4418 if (!strcmp(xf->name,"Dot")) {
4419 if (!(dotopt = SUMA_FindNgrNamedElement(xf->XformOpts, "dotopts"))) {
4420 SUMA_S_Err("dotopt not found");
4421 SUMA_RETURN(NOPE);
4422 }
4423 for (ii=0; ii<xf->N_parents; ++ii) {
4424 if (!SUMA_is_ID_4_DSET(xf->parents[ii], &in_dset)) {
4425 SUMA_S_Err("Parent not found");
4426 SUMA_RETURN(NOPE);
4427 }
4428 if (!(pp_dset = SUMA_GetDotPreprocessedDset(in_dset, dotopt))){
4429 SUMA_S_Err("PreProcParent not found");
4430 SUMA_RETURN(NOPE);
4431 }
4432 /* now make it visible */
4433 /* For this to work, you'll need to have a version of the
4434 block under LoadDsetFile beginning from OverInd = -1;
4435 To make matters more exciting, you'll need to update this sucker,
4436 any time that the preprocessing is redone because of changes in
4437 orts or bandpass, etc. So leave this feature out for now */
4438 }
4439 } else {
4440 SUMA_S_Errv("Don't know how to do this for %s\n", xf->name);
4441 SUMA_RETURN(NOPE);
4442 }
4443
4444 SUMA_RETURN(YUP);
4445 }
4446
SUMA_is_XformParent(SUMA_XFORM * xf,char * id,int * iloc)4447 SUMA_Boolean SUMA_is_XformParent (SUMA_XFORM *xf, char *id, int *iloc)
4448 {
4449 static char FuncName[]={"SUMA_is_XformParent"};
4450 int ii;
4451
4452 SUMA_ENTRY;
4453
4454 if (!xf || !id) SUMA_RETURN(NOPE);
4455
4456 for (ii=0; ii<xf->N_parents; ++ii) {
4457 if (!strcmp(xf->parents[ii],id)) {
4458 if (iloc) *iloc=ii;
4459 SUMA_RETURN(YUP);
4460 }
4461 }
4462
4463 SUMA_RETURN(NOPE);
4464 }
4465
SUMA_AddXformParent(SUMA_XFORM * xf,char * parent_idcode,char * parent_domain)4466 SUMA_Boolean SUMA_AddXformParent (SUMA_XFORM *xf,
4467 char *parent_idcode, char *parent_domain)
4468 {
4469 static char FuncName[]={"SUMA_AddXformParent"};
4470 SUMA_DSET *dset=NULL;
4471
4472 SUMA_ENTRY;
4473
4474 if (!xf || !parent_idcode) {
4475 SUMA_S_Err("NULL input");
4476 SUMA_RETURN(NOPE);
4477 }
4478 if (SUMA_is_XformParent(xf, parent_idcode, NULL)) {
4479 SUMA_S_Err("Parent exists");
4480 SUMA_RETURN(NOPE);
4481 }
4482
4483 strcpy(xf->parents[xf->N_parents], parent_idcode);
4484 if (!parent_domain) {
4485 if (SUMA_is_ID_4_DSET(parent_idcode, &dset)) {
4486 strcpy( xf->parents_domain[xf->N_parents],
4487 SDSET_IDMDOM(dset));
4488 } else {
4489 xf->parents_domain[xf->N_parents][0] = '\0';
4490 }
4491 } else {
4492 strcpy( xf->parents_domain[xf->N_parents],
4493 parent_domain);
4494 }
4495
4496
4497 ++xf->N_parents;
4498 SUMA_RETURN(YUP);
4499
4500 }
4501
SUMA_is_XformChild(SUMA_XFORM * xf,char * id,int * iloc)4502 SUMA_Boolean SUMA_is_XformChild (SUMA_XFORM *xf, char *id, int *iloc)
4503 {
4504 static char FuncName[]={"SUMA_is_XformChild"};
4505 int ii;
4506
4507 SUMA_ENTRY;
4508
4509 if (!xf || !id) SUMA_RETURN(NOPE);
4510
4511 for (ii=0; ii<xf->N_children; ++ii) {
4512 if (!strcmp(xf->children[ii],id)) {
4513 if (iloc) *iloc=ii;
4514 SUMA_RETURN(YUP);
4515 }
4516 }
4517
4518 SUMA_RETURN(NOPE);
4519 }
4520
SUMA_AddXformChild(SUMA_XFORM * xf,char * child_idcode)4521 SUMA_Boolean SUMA_AddXformChild (SUMA_XFORM *xf,
4522 char *child_idcode)
4523 {
4524 static char FuncName[]={"SUMA_AddXformChild"};
4525 SUMA_DSET *dset=NULL;
4526 int ii;
4527
4528 SUMA_ENTRY;
4529
4530 if (!xf || !child_idcode) {
4531 SUMA_S_Err("NULL input");
4532 SUMA_RETURN(NOPE);
4533 }
4534 if (SUMA_is_XformChild(xf, child_idcode, NULL)) {
4535 SUMA_S_Err("Child exists");
4536 SUMA_RETURN(NOPE);
4537 }
4538
4539 strcpy(xf->children[xf->N_children], child_idcode);
4540
4541 ++xf->N_children;
4542 SUMA_RETURN(YUP);
4543
4544 }
4545
4546
SUMA_NewXform(char * name,char * parent_idcode,char * parent_domain)4547 SUMA_XFORM *SUMA_NewXform(char *name, char *parent_idcode, char *parent_domain)
4548 {
4549 static char FuncName[]={"SUMA_NewXform"};
4550 SUMA_XFORM *xf = NULL;
4551
4552 SUMA_ENTRY;
4553 if (!name || !parent_idcode) SUMA_RETURN(xf);
4554
4555 if ( !SUMA_is_ID_4_SO(parent_idcode, NULL) &&
4556 !SUMA_is_ID_4_DSET(parent_idcode, NULL) ) {
4557 SUMA_S_Err("Invalid parent_idcode");
4558 SUMA_RETURN(xf);
4559 }
4560
4561 if (SUMA_Find_XformByParent("Dot", parent_idcode, NULL)) {
4562 SUMA_S_Err("An xform exists already");
4563 SUMA_RETURN(xf);
4564 }
4565
4566 xf = (SUMA_XFORM *)SUMA_calloc(1, sizeof(SUMA_XFORM));
4567
4568 snprintf(xf->name, 127*sizeof(char), "%s", name);
4569 UNIQ_idcode_fill(xf->idcode_str);
4570
4571 if (!SUMA_AddXformParent(xf,parent_idcode, parent_domain)) {
4572 SUMA_S_Err("Failed to add parent");
4573 SUMA_FreeXform(xf); xf = NULL;
4574 SUMA_RETURN(xf);
4575 }
4576
4577
4578 xf->N_children = 0;
4579
4580 xf->active = 0;
4581 xf->ShowPreProc = 0;
4582
4583 xf->XformOpts = NI_new_group_element();
4584 NI_rename_group(xf->XformOpts, "XformOpts");
4585
4586 dlist_ins_next(SUMAg_CF->xforms, dlist_tail(SUMAg_CF->xforms), xf);
4587
4588 SUMA_RETURN(xf);
4589 }
4590
SUMA_FreeXform(void * data)4591 void SUMA_FreeXform(void *data)
4592 {
4593 static char FuncName[]={"SUMA_FreeXform"};
4594 SUMA_XFORM *xf = (SUMA_XFORM *)data;
4595
4596 SUMA_ENTRY;
4597
4598 if (xf) {
4599 if (xf->XformOpts) NI_free_element(xf->XformOpts);
4600 if (xf->gui) SUMA_FreeXformInterface(xf->gui);
4601 SUMA_free(xf);
4602 }
4603
4604 SUMA_RETURNe;
4605 }
4606
SUMA_NewXformInterface(SUMA_XFORM * xf)4607 SUMA_GENERIC_XFORM_INTERFACE * SUMA_NewXformInterface(
4608 SUMA_XFORM *xf)
4609 {
4610 static char FuncName[]={"SUMA_NewXformInterface"};
4611 SUMA_GENERIC_XFORM_INTERFACE *gui=NULL;
4612
4613 SUMA_ENTRY;
4614
4615
4616 gui = (SUMA_GENERIC_XFORM_INTERFACE *)
4617 SUMA_calloc(1,sizeof(SUMA_GENERIC_XFORM_INTERFACE));
4618
4619 gui->AF0 =
4620 (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4621 gui->AF1 =
4622 (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4623 gui->AF2 =
4624 (SUMA_ARROW_TEXT_FIELD *)calloc(1, sizeof(SUMA_ARROW_TEXT_FIELD));
4625
4626 SUMA_RETURN(gui);
4627 }
4628
SUMA_FreeXformInterface(SUMA_GENERIC_XFORM_INTERFACE * gui)4629 void SUMA_FreeXformInterface(SUMA_GENERIC_XFORM_INTERFACE *gui)
4630 {
4631 static char FuncName[]={"SUMA_FreeXformInterface"};
4632
4633 SUMA_ENTRY;
4634 if (gui) {
4635 if (gui->AF0) SUMA_free(gui->AF0);
4636 if (gui->AF1) SUMA_free(gui->AF1);
4637 if (gui->AF2) SUMA_free(gui->AF2);
4638
4639 SUMA_free(gui);
4640 }
4641 SUMA_RETURNe;
4642 }
4643
SUMA_is_CallbackParent(SUMA_CALLBACK * cb,char * id,int * iloc)4644 SUMA_Boolean SUMA_is_CallbackParent (SUMA_CALLBACK *cb, char *id, int *iloc)
4645 {
4646 static char FuncName[]={"SUMA_is_CallbackParent"};
4647 int ii;
4648
4649 SUMA_ENTRY;
4650
4651 if (!cb || !id) SUMA_RETURN(NOPE);
4652
4653 for (ii=0; ii<cb->N_parents; ++ii) {
4654 if (!strcmp(cb->parents[ii],id)) {
4655 if (iloc) *iloc=ii;
4656 SUMA_RETURN(YUP);
4657 }
4658 }
4659
4660 SUMA_RETURN(NOPE);
4661 }
4662
4663
4664 /*!
4665 Find a callback with a particular name AND a parent with a matching idcode
4666 */
SUMA_Find_CallbackByParent(char * FunctionName,char * parent_idcode,int * iloc)4667 SUMA_CALLBACK *SUMA_Find_CallbackByParent(char *FunctionName,
4668 char *parent_idcode, int *iloc)
4669 {
4670 static char FuncName[]={"SUMA_Find_CallbackByParent"};
4671 SUMA_CALLBACK *cb = NULL, *cbt=NULL;
4672 DListElmt *el=NULL;
4673 DList *lst = SUMAg_CF->callbacks;
4674 int i;
4675
4676 SUMA_ENTRY;
4677
4678 if (!lst || !FunctionName || !parent_idcode) SUMA_RETURN(cb);
4679
4680 el = dlist_head(lst);
4681
4682 while (el && !cb) {
4683 cbt = (SUMA_CALLBACK *)el->data;
4684 if (!strcmp(cbt->FunctionName, FunctionName)) {
4685 for (i=0; i<cbt->N_parents; ++i) {
4686 if (!strcmp(cbt->parents[i], parent_idcode)) {
4687 cb = cbt;
4688 if (iloc) *iloc = i;
4689 break;
4690 }
4691 }
4692 }
4693 el = dlist_next(el);
4694 }
4695
4696 SUMA_RETURN(cb);
4697 }
4698
SUMA_Find_CallbackByCreatorXformID(char * creator_xform_idcode)4699 SUMA_CALLBACK *SUMA_Find_CallbackByCreatorXformID(char *creator_xform_idcode)
4700 {
4701 static char FuncName[]={"SUMA_Find_CallbackByCreatorXformID"};
4702 SUMA_CALLBACK *cb = NULL, *cbf=NULL;
4703 DListElmt *el=NULL;
4704 DList *lst = SUMAg_CF->callbacks;
4705 int i, found=0;
4706
4707 SUMA_ENTRY;
4708
4709 if (!lst || !creator_xform_idcode) SUMA_RETURN(cbf);
4710
4711 el = dlist_head(lst);
4712 cbf=NULL;
4713 while (el && !cbf) {
4714 cb = (SUMA_CALLBACK *)el->data;
4715 if (!strcmp(cb->creator_xform, creator_xform_idcode)) {
4716 ++found; cbf = cb;
4717 }
4718 el = dlist_next(el);
4719 }
4720 if (found > 1) {
4721 SUMA_S_Errv("%d callbacks found\n"
4722 "write a new function to return them all\n",
4723 found);
4724 }
4725 SUMA_RETURN(cbf);
4726 }
4727
SUMA_AddCallbackParent(SUMA_CALLBACK * cb,char * parent_idcode,char * parent_domain)4728 SUMA_Boolean SUMA_AddCallbackParent (SUMA_CALLBACK *cb,
4729 char *parent_idcode,
4730 char *parent_domain)
4731 {
4732 static char FuncName[]={"SUMA_AddCallbackParent"};
4733 SUMA_DSET *dset=NULL;
4734
4735 SUMA_ENTRY;
4736
4737 if (!cb || !parent_idcode) {
4738 SUMA_S_Err("NULL input");
4739 SUMA_RETURN(NOPE);
4740 }
4741
4742 if (SUMA_is_CallbackParent(cb, parent_idcode, NULL)) {
4743 SUMA_S_Err("Parent exists");
4744 SUMA_RETURN(NOPE);
4745 }
4746
4747 strcpy(cb->parents[cb->N_parents], parent_idcode);
4748 if (!parent_domain) {
4749 if (SUMA_is_ID_4_DSET(parent_idcode, &dset)) {
4750 strcpy( cb->parents_domain[cb->N_parents],
4751 SDSET_IDMDOM(dset));
4752 } else {
4753 cb->parents_domain[cb->N_parents][0] = '\0';
4754 }
4755 } else {
4756 strcpy( cb->parents_domain[cb->N_parents],
4757 parent_domain);
4758 }
4759
4760 ++cb->N_parents;
4761 SUMA_RETURN(YUP);
4762
4763 }
4764
SUMA_SetCallbackPending(SUMA_CALLBACK * cb,SUMA_Boolean pen,SUMA_ENGINE_SOURCE src)4765 SUMA_Boolean SUMA_SetCallbackPending (SUMA_CALLBACK *cb,
4766 SUMA_Boolean pen, SUMA_ENGINE_SOURCE src)
4767 {
4768 static char FuncName[]={"SUMA_SetCallbackPending"};
4769
4770 SUMA_ENTRY;
4771
4772 if (!cb) SUMA_RETURN(NOPE);
4773
4774 if (cb->active < 1 && pen) {
4775 SUMA_S_Notev("Callback %s inactive. Pending flag not set\n",
4776 cb->FunctionName);
4777 SUMA_RETURN(YUP);
4778 }
4779
4780 if (src <= SES_Empty && pen) {
4781 SUMA_S_Errv("Source %d is not appropriate.\n",src);
4782 SUMA_RETURN(NOPE);
4783 }
4784
4785 if (cb->pending && pen) {
4786 SUMA_S_Errv("Callback %s is already pending. \n",
4787 cb->FunctionName);
4788 SUMA_RETURN(NOPE);
4789 }
4790
4791 cb->pending = pen;
4792 if (!pen) cb->trigger_source = SES_Empty;
4793 else cb->trigger_source = pen;
4794
4795 SUMA_RETURN(YUP);
4796 }
4797
SUMA_NewCallback(char * FunctionName,SUMA_CALLBACK_ACTIVATE_EVENTS event,void * FunctionPtr,char * parent_idcode,char * parent_domain,char * creator_xform)4798 SUMA_CALLBACK *SUMA_NewCallback (char *FunctionName,
4799 SUMA_CALLBACK_ACTIVATE_EVENTS event,
4800 void *FunctionPtr,
4801 char *parent_idcode,
4802 char *parent_domain,
4803 char *creator_xform)
4804 {
4805 static char FuncName[]={"SUMA_NewCallback"};
4806 SUMA_XFORM *xf = NULL;
4807 NI_element *nel=NULL;
4808 SUMA_CALLBACK *cb = NULL;
4809 char stmp[256];
4810 SUMA_Boolean LocalHead = NOPE;
4811
4812 SUMA_ENTRY;
4813
4814 SUMA_LH("Checks");
4815 if (!parent_idcode || !FunctionName ||
4816 strlen(FunctionName) > 125 ) SUMA_RETURN(cb);
4817
4818 if ( !SUMA_is_ID_4_SO(parent_idcode, NULL) &&
4819 !SUMA_is_ID_4_DSET(parent_idcode, NULL) ) {
4820 SUMA_S_Err("Invalid parent_idcode");
4821 SUMA_RETURN(cb);
4822 }
4823
4824 if (SUMA_Find_CallbackByParent(FunctionName, parent_idcode, NULL)) {
4825 SUMA_S_Err("A callback exists already");
4826 SUMA_RETURN(cb);
4827 }
4828
4829 SUMA_LH("New callback");
4830 cb = (SUMA_CALLBACK *)calloc(1,sizeof(SUMA_CALLBACK));
4831
4832 cb->event = event;
4833 cb->active = 0;
4834 cb->pending = 0;
4835 cb->trigger_source = SES_Empty;
4836 strcpy(cb->FunctionName, FunctionName);
4837 cb->FunctionPtr = FunctionPtr;
4838
4839 SUMA_LH("Func input");
4840 cb->FunctionInput = NI_new_group_element();
4841 snprintf(stmp,sizeof(char)*64,"input.%s",FunctionName);
4842 NI_rename_group(cb->FunctionInput, stmp);
4843
4844 SUMA_LH("defaults");
4845 /* Set defaults for generic parameters */
4846 nel = NI_new_data_element("event_parameters", 0);
4847 NI_add_to_group(cb->FunctionInput, nel);
4848 NI_SET_INT(nel,"event.new_node", -1);
4849 NI_set_attribute(nel, "event.DO_idcode", "");
4850 NI_set_attribute(nel,"event.overlay_name", "");
4851
4852 SUMA_LH("Adding parent");
4853 if (!SUMA_AddCallbackParent(cb, parent_idcode, parent_domain)){
4854 SUMA_S_Err("Failed to add parent");
4855 SUMA_RETURN(NOPE);
4856 }
4857
4858
4859 if (creator_xform) {
4860 if (!(xf=SUMA_Find_XformByID(creator_xform))) {
4861 SUMA_S_Err("Failed to find xform");
4862 SUMA_RETURN(NOPE);
4863 }
4864 strcpy(cb->creator_xform, creator_xform);
4865 }
4866
4867 dlist_ins_next(SUMAg_CF->callbacks, dlist_tail(SUMAg_CF->callbacks), cb);
4868
4869 SUMA_RETURN(cb);
4870 }
4871
4872
SUMA_FreeCallback(void * data)4873 void SUMA_FreeCallback(void *data)
4874 {
4875 static char FuncName[]={"SUMA_FreeCallback"};
4876 SUMA_CALLBACK *cb = (SUMA_CALLBACK *)data;
4877
4878 SUMA_ENTRY;
4879
4880 if (cb) {
4881 if (cb->FunctionInput) {
4882 NI_free_element(cb->FunctionInput);
4883 }
4884 SUMA_free(cb);
4885 }
4886
4887 SUMA_RETURNe;
4888 }
4889
SUMA_FlushCallbackEventParameters(SUMA_CALLBACK * cb)4890 SUMA_Boolean SUMA_FlushCallbackEventParameters (SUMA_CALLBACK *cb)
4891 {
4892 static char FuncName[]={"SUMA_FlushCallbackEventParameters"};
4893 NI_element *nelpars=NULL;
4894
4895 SUMA_ENTRY;
4896
4897 if (!cb ||
4898 !(nelpars = SUMA_FindNgrNamedElement(
4899 cb->FunctionInput, "event_parameters"))) {
4900 SUMA_S_Err("NULL cb or Bad callback content");
4901 SUMA_RETURN(NOPE);
4902 }
4903
4904 switch (cb->event) {
4905 case SUMA_NEW_NODE_ACTIVATE_EVENT:
4906 SUMA_XFORM_SAVE_FLUSH_EVENT(nelpars);
4907 break;
4908 case SUMA_ERROR_ACTIVATE_EVENT:
4909 case SUMA_NO_ACTIVATE_EVENT:
4910 case SUMA_N_ACTIVATE_EVENTS:
4911 SUMA_S_Warn("This should not come up");
4912 break;
4913 default:
4914 SUMA_S_Err("Seriously off folks");
4915 SUMA_RETURN(NOPE);
4916 break;
4917 }
4918
4919 SUMA_RETURN(YUP);
4920 }
4921
SUMA_ExecuteCallback(SUMA_CALLBACK * cb,int refresh,SUMA_ALL_DO * ado,int doall)4922 SUMA_Boolean SUMA_ExecuteCallback(SUMA_CALLBACK *cb,
4923 int refresh, SUMA_ALL_DO *ado,
4924 int doall)
4925 {
4926 static char FuncName[]={"SUMA_ExecuteCallback"};
4927 SUMA_SurfaceObject *curSO=NULL, *targetSO=NULL;
4928 SUMA_OVERLAYS *targetSover=NULL;
4929 int i, jj=0;
4930 SUMA_DSET *targetDset=NULL;
4931 SUMA_Boolean LocalHead = NOPE;
4932
4933 SUMA_ENTRY;
4934
4935 SUMA_LH("Calling FunctionPtr(cb)");
4936 cb->FunctionPtr((void *)cb);
4937
4938 SUMA_LH("Set callback pending");
4939 SUMA_SetCallbackPending(cb, 0, SES_Empty);
4940
4941 /* flush event specific parameters */
4942 SUMA_FlushCallbackEventParameters(cb);
4943 SUMA_LH("Flushing done");
4944 if (refresh) {/* Now decide on what needs refreshing */
4945 if (!ado) {
4946 curSO = NULL;
4947 } else {
4948 curSO = SUMA_Cont_SO(SUMA_ADO_Cont(ado));
4949 }
4950 SUMA_LH("curSO = %p, ado = %p", curSO, ado);
4951 for (i=0; i<cb->N_parents; ++i) {
4952 if (SUMA_is_ID_4_DSET(cb->parents[i], &targetDset)) {
4953 targetSO = SUMA_findSOp_inDOv(cb->parents_domain[i],
4954 SUMAg_DOv, SUMAg_N_DOv);
4955 if (!targetSO) {
4956 if (ado && ado->do_type == SO_type) {
4957 SUMA_S_Warn("Could not find targetSO, using SO instead");
4958 targetSO = (SUMA_SurfaceObject *)ado;
4959 } else {
4960 SUMA_S_Err("Don't know what do do here");
4961 SUMA_RETURN(NOPE);
4962 }
4963 }
4964 /* refresh overlay and SO for this callback */
4965 targetSover = SUMA_Fetch_OverlayPointerByDset(
4966 (SUMA_ALL_DO*)targetSO,
4967 targetDset,
4968 &jj);
4969 SUMA_LHv("Colorizing %s\n", targetSover->Name);
4970 SUMA_ColorizePlane(targetSover);
4971 SUMA_LHv("Setting remix flag for %s\n",targetSO->Label);
4972 if (!SUMA_SetRemixFlag( targetSO->idcode_str,
4973 SUMAg_SVv, SUMAg_N_SVv)) {
4974 SUMA_SLP_Err("Failed in SUMA_SetRemixFlag.\n");
4975 SUMA_RETURN(NOPE);
4976 }
4977 if (doall || curSO != targetSO) {
4978 SUMA_UPDATE_ALL_NODE_GUI_FIELDS((SUMA_ALL_DO*)targetSO);
4979 SUMA_Remixedisplay((SUMA_ALL_DO*)targetSO);
4980 } else {
4981 /* Update and Remix will be done for curSO
4982 by the function who called this one */
4983 }
4984 /* it is possible that the callback caused a change
4985 in the p value so update it to be sure,
4986 but I am not fond of doing this all the time,
4987 every time there is a button click triggering the
4988 event .... */
4989 SUMA_LHv("Updating threshold at %f\n",
4990 targetSO->SurfCont->curColPlane->OptScl->ThreshRange[0]);
4991 SUMA_UpdatePvalueField( (SUMA_ALL_DO *)targetSO,
4992 targetSO->SurfCont->curColPlane->OptScl->ThreshRange[0]);
4993 } else if (SUMA_is_ID_4_SO(cb->parents[i], &targetSO)) {
4994 SUMA_S_Note("Got surface, don't know \n"
4995 "what to do in case like this yet\n");
4996 } else {
4997 SUMA_S_Err("Dunno what to do with such an object...");
4998 }
4999 }
5000
5001 }
5002 SUMA_RETURN(YUP);
5003 }
5004
5005