Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

SUMA_DOmanip.c

Go to the documentation of this file.
00001 #include "SUMA_suma.h"
00002 
00003 extern SUMA_CommonFields *SUMAg_CF; 
00004 extern SUMA_DO *SUMAg_DOv;   
00005 extern int SUMAg_N_DOv;
00006 extern SUMA_SurfaceViewer *SUMAg_SVv;
00007 extern int SUMAg_N_SVv;
00008 
00009 /*! functions dealing with Drawable Object Manipulation */
00010 
00011 /*!
00012    This function Links one Inode to another.
00013    This is different from CreateInode in that no new node is being allocated for, only a link is created.
00014    SUMA_CreateInodeLink (SUMA_INODE * FromIN, SUMA_INODE *ToIN)
00015    
00016    FromIN = SUMA_CreateInodeLink (FromIN, ToIN);
00017    
00018    \param FromIN (SUMA_INODE *) this is the pointer to the IDnode wich will be linked to ToIN.
00019           As silly as this sounds, this should be a pointer to NULL otherwise the link will not
00020           be established. The use of this function will help reduce the risk of linking pointers
00021           that are pointing to allocated space.
00022    \param ToIN (SUMA_INODE *) pointer where the link is going
00023    \ret FromIN (SUMA_INODE *) if all is well, FromIN = ToIN
00024       otherwise, NULL is returned
00025       
00026       All this function does is check the FromIN is NULL and ToIN isn't and then it calls SUMA_AddLink (ToIN)
00027    \sa SUMA_BreakInodeLink
00028    \sa SUMA_isInodeLink
00029 */
00030 SUMA_INODE *SUMA_CreateInodeLink (SUMA_INODE * FromIN, SUMA_INODE *ToIN)
00031 {
00032    static char FuncName[] = {"SUMA_CreateInodeLink"};
00033    
00034    SUMA_ENTRY;
00035 
00036    if (FromIN) {
00037       fprintf (SUMA_STDERR,"Error %s: FromIN Inode is not NULL. \n\tFromIN pointer is left undisturbed.\n", FuncName);
00038       SUMA_RETURN(FromIN);
00039    }
00040    if (!ToIN) {
00041       fprintf (SUMA_STDERR,"Error %s: ToIN is NULL.\n\t Can't link to NULL, returning NULL.\n", FuncName);
00042       SUMA_RETURN(NULL); 
00043    }
00044    
00045    /* add a link to ToIN */
00046    if (!SUMA_AddLink (ToIN)) {
00047       fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AddLink.\n", FuncName);
00048       SUMA_RETURN(NULL);
00049    }
00050    
00051    /* now return the pointer to be linked to */
00052    SUMA_RETURN(ToIN);
00053 
00054 }
00055 
00056 /*! 
00057    This function determines if an Inode in a SO is a link or not.
00058    an Inode is a link if IN->ParentIDcode and HolderIDcode are different. 
00059    The function is nothing more than a strcmp.
00060    
00061    SUMA_Boolean SUMA_isInodeLink (SUMA_INODE *IN, const char *HolderIDcode)
00062 
00063     returns NOPE if IN == NULL or IN->ParentIDcode != HolderIDcode
00064 */
00065 SUMA_Boolean SUMA_isInodeLink (SUMA_INODE *IN, const char *HolderIDcode)
00066 {
00067    static char FuncName[] = {"SUMA_isInodeLink"};
00068    
00069    SUMA_ENTRY;
00070 
00071    if (!IN) {
00072       fprintf (SUMA_STDERR, "Warning %s: IN is null.\n", FuncName); 
00073       SUMA_RETURN(NOPE);
00074    } 
00075    if (!strcmp(IN->ParentIDcode, HolderIDcode)) SUMA_RETURN(YUP);
00076       
00077    SUMA_RETURN(NOPE);
00078 }
00079 
00080 /*! 
00081    function to remove the link of one IDnode to the next 
00082    SUMA_INODE * SUMA_BreakInodeLink (SUMA_INODE *IN, const char *HolderIDcode);
00083    \param IN (SUMA_INODE *) the linked inode
00084    \param HolderIDcode (const char *) the ID code that holds/contains IN
00085    \ret NULL if the link was broken or IN == NULL
00086       IN if IN is not a link but an actuak Inode (meaning IN->ParentIDcode == HolderIDcode
00087       
00088 
00089 */   
00090 SUMA_INODE * SUMA_BreakInodeLink (SUMA_INODE *IN, const char *HolderIDcode) 
00091 {
00092    static char FuncName[] = {"SUMA_BreakInodeLink"};
00093 
00094    SUMA_ENTRY;
00095 
00096    if (!IN) {
00097       fprintf (SUMA_STDERR, "Warning %s: IN is null, nothing to do.\n", FuncName); 
00098       SUMA_RETURN(NULL);
00099    }
00100    if (!SUMA_isInodeLink (IN, HolderIDcode)) {
00101       fprintf (SUMA_STDERR, "Error %s: Inode IN is not a link. Nothing done.\n", FuncName);
00102       SUMA_RETURN(IN);
00103    } 
00104    
00105    /* release the link */
00106    if (SUMA_ReleaseLink (IN) < 0) {
00107       fprintf (SUMA_STDERR, "Error %s: IN has no links. Nothing done.\n", FuncName);
00108       SUMA_RETURN(IN);
00109    }
00110    
00111    /* OK, link released, not return NULL */
00112    SUMA_RETURN(NULL);
00113 }
00114 
00115 /*! 
00116    This function decrements the N_link field in IN by 1 and returns the resultant N_link value
00117    a -1 is returned if IN->N_link = 0 or IN == NULL
00118 
00119 
00120    ans = SUMA_ReleaseLink (IN);
00121 
00122    \param IN (SUMA_INODE *) pointer to SUMA_INODE structure
00123    \ret ans (int) value of IN->N_link
00124    
00125    \sa SUMA_AddLink
00126 */
00127 int SUMA_ReleaseLink (SUMA_INODE * IN) 
00128 {
00129    static char FuncName[]={"SUMA_ReleaseLink"};
00130    SUMA_Boolean LocalHead = NOPE;
00131    
00132    SUMA_ENTRY;
00133 
00134    if (!IN) {
00135       /* This typically happens when A link was never created in the first place.
00136       It used to be an error message but now it is just a warning because some
00137       programs compute things like SO->Cx without creating an inode with it ...*/
00138       fprintf (SUMA_STDERR,"Warning %s: Inode is null. Returning -1.\n", FuncName);
00139       SUMA_RETURN(-1);
00140    }
00141    if (!IN->N_link) {
00142       if (LocalHead) fprintf (SUMA_STDERR,"%s: No links. Returning -1.\n", FuncName);
00143       /* You do not want to return a 0 because freeing is done when no links remain 
00144       THIS STUPID SYSTEM SHOULD BE ELIMINATED IN FAVOR OF THE METHOD USED FOR OVERLAYS*/
00145       SUMA_RETURN(-1);
00146    }
00147    else {
00148       IN->N_link--;
00149       SUMA_RETURN(IN->N_link);
00150    }
00151 }
00152    
00153 /*! 
00154    This function increments the N_link field in IN by 1 and returns the resultant N_link value
00155    a zero is returned in case of an error
00156 
00157 
00158    ans = SUMA_AddLink (IN);
00159 
00160    \param IN (SUMA_INODE *) pointer to SUMA_INODE structure
00161    \ret ans (int) value of IN->N_link
00162    \sa SUMA_ReleaseLink
00163 */
00164 int SUMA_AddLink (SUMA_INODE * IN) 
00165 {
00166    static char FuncName[]={"SUMA_AddLink"};
00167 
00168    SUMA_ENTRY;
00169 
00170    if (!IN) {
00171       fprintf (SUMA_STDERR,"Error %s: Inode is null.\n", FuncName);
00172       
00173       SUMA_RETURN(0);
00174    } else {
00175       IN->N_link++;
00176       SUMA_RETURN(IN->N_link);
00177    }
00178 }
00179 
00180 /*! 
00181    Function to create a SUMA_INODE structure 
00182    ans = SUMA_CreateInode (data, ParentIDcode);
00183    
00184    \param data (void *) pointer to data location
00185    \param ParentIDcode (char[SUMA_IDCODE_LENGTH]) containing the IDcode of the creator of the data
00186    \ret ans (SUMA_INODE *) pointer to SUMA_INODE for data
00187       NULL if error is encountered
00188 */
00189 
00190 SUMA_INODE *SUMA_CreateInode (void *data, char *ID)
00191 {
00192    static char FuncName[]={"SUMA_CreateInode"};
00193    SUMA_INODE *IN;
00194    
00195    SUMA_ENTRY;
00196 
00197    IN = (SUMA_INODE *)SUMA_malloc (sizeof(SUMA_INODE));
00198    if (IN == NULL) {
00199       fprintf (SUMA_STDERR,"Error %s: failed to allocate for Inode.\n", FuncName);
00200       SUMA_RETURN(NULL);
00201    }
00202    
00203    IN->data = data;
00204    strcpy (IN->ParentIDcode, ID);
00205    IN->N_link = 0;
00206    
00207    SUMA_RETURN(IN);
00208 }
00209 
00210 /*!
00211 Create a Displayable Object data structure 
00212 */
00213 SUMA_DO *SUMA_Alloc_DisplayObject_Struct (int N)
00214 {
00215    static char FuncName[]={"SUMA_Alloc_DisplayObject_Struct"};
00216    SUMA_DO *dov;
00217    
00218    SUMA_ENTRY;
00219 
00220    dov = (SUMA_DO *)SUMA_malloc(sizeof(SUMA_DO)*N);
00221    if (dov == NULL) {
00222       SUMA_alloc_problem("SUMA_Alloc_DisplayObject_Struct: could not allocate memory for SO");
00223    }
00224    SUMA_RETURN(dov);
00225 }/*SUMA_Alloc_DisplayObject_Struct*/
00226 
00227 
00228 /*!
00229 Free a Displayable Object data structure 
00230 */
00231 SUMA_Boolean SUMA_Free_Displayable_Object (SUMA_DO *dov)
00232 {
00233    static char FuncName[]={"SUMA_Free_Displayable_Object"};
00234 
00235    SUMA_ENTRY;
00236 
00237    switch (dov->ObjectType) {
00238       case SO_type:
00239          if (!SUMA_Free_Surface_Object ((SUMA_SurfaceObject *)dov->OP)) {
00240             fprintf(SUMA_STDERR,"Error SUMA_Free_Displayable_Object, could not free surface\n");
00241          }
00242          break;
00243       case ROIdO_type:
00244          if (!SUMA_freeDrawnROI ((SUMA_DRAWN_ROI *)dov->OP)) {
00245             fprintf(SUMA_STDERR,"Error SUMA_freeDrawnROI, could not free  ROI.\n");
00246          }
00247          break;
00248       case ROIO_type:
00249          if (!SUMA_freeROI ((SUMA_ROI *)dov->OP)) {
00250             fprintf(SUMA_STDERR,"Error SUMA_freeROI, could not free  ROI.\n");
00251          }
00252          break;
00253       case LS_type:
00254          SUMA_free_SegmentDO ((SUMA_SegmentDO *)dov->OP);
00255          break;
00256       case AO_type:
00257          SUMA_Free_Axis((SUMA_Axis*)dov->OP);
00258          break;
00259       case GO_type:
00260          fprintf(SUMA_STDERR,"Error SUMA_Free_Displayable_Object, Not trained to free GO objects\n");
00261          break;
00262          
00263    }   
00264 
00265    SUMA_RETURN(YUP);
00266 }
00267 
00268 SUMA_Boolean SUMA_Free_Displayable_Object_Vect (SUMA_DO *dov, int N)
00269 {
00270    static char FuncName[] = {"SUMA_Free_Displayable_Object_Vect"};
00271    int i;
00272    SUMA_Boolean Ret = YUP;
00273    
00274    SUMA_ENTRY;
00275 
00276    for (i=0; i < N; ++i) {
00277       if (&dov[i] != NULL) {
00278          Ret = Ret * SUMA_Free_Displayable_Object (&dov[i]);
00279       }
00280    }
00281 
00282    if (dov) SUMA_free(dov);
00283    SUMA_RETURN(Ret);
00284 
00285 }   
00286 /*!
00287 Add a displayable object to dov
00288 */
00289 SUMA_Boolean SUMA_AddDO(SUMA_DO *dov, int *N_dov, void *op, SUMA_DO_Types DO_Type, SUMA_DO_CoordType DO_CoordType)
00290 {
00291    static char FuncName[] = {"SUMA_AddDO"};
00292    
00293    SUMA_ENTRY;
00294 
00295    /* make sure you did not exceed allocated space */
00296    if (*N_dov >= SUMA_MAX_DISPLAYABLE_OBJECTS) {
00297       SUMA_error_message (FuncName, "Reached limit of DOv storage",0);
00298       SUMA_RETURN(NOPE);
00299    }
00300    dov[*N_dov].OP = op;
00301    dov[*N_dov].ObjectType = DO_Type;
00302    dov[*N_dov].CoordType = DO_CoordType;
00303    *N_dov = *N_dov+1;
00304    
00305    
00306    SUMA_RETURN(YUP);
00307 }
00308 
00309 /*!
00310    \brief Remove a displayable object from dov
00311    success = SUMA_RemoveDO(dov, N_dov, op, Free_op);
00312    
00313    \param dov (SUMA_DO*) vector containing displayable objects
00314    \param N_dov (int *) number of elements in dov
00315    \param op (void *) pointer to object sought
00316    \param Free_op (SUMA_Boolean) Flag for freeing space allocated for op's data.
00317          Freeing is done via SUMA_Free_Displayable_Object()
00318    \return success (SUMA_Boolean)  flag. 
00319 */
00320 SUMA_Boolean SUMA_RemoveDO(SUMA_DO *dov, int *N_dov, void *op, SUMA_Boolean Free_op)
00321 {
00322    static char FuncName[] = {"SUMA_RemoveDO"};
00323    int i;
00324    SUMA_Boolean LocalHead = NOPE, Found=NOPE;
00325    
00326    SUMA_ENTRY;
00327    
00328    SUMA_LH("Called");
00329    
00330    for (i=0; i<*N_dov; ++i) {
00331       if (dov[i].OP == op) {
00332          Found = YUP;
00333          if (LocalHead) fprintf (SUMA_STDERR,"%s: found object. Removing it from dov.\n", FuncName);
00334          if (Free_op) {
00335             if (LocalHead) fprintf (SUMA_STDERR,"%s: Freeing object.\n", FuncName);
00336             if (!SUMA_Free_Displayable_Object (&dov[i])) {
00337                SUMA_SLP_Crit("Failed to free displayable object.");
00338                SUMA_RETURN(NOPE);
00339             }
00340          }
00341          *N_dov = *N_dov-1;
00342          dov[i].OP = dov[*N_dov].OP;
00343          dov[i].ObjectType = dov[*N_dov].ObjectType;
00344          dov[i].CoordType = dov[*N_dov].CoordType;
00345       }
00346    }
00347 
00348    
00349    if (Found) {
00350       SUMA_RETURN(YUP);
00351    } else {
00352       SUMA_RETURN(NOPE);
00353    }
00354 }
00355 
00356 /*!
00357 Register a DO with surface viewer RegisteredDO vector 
00358 if dov_id is present in cSV, nothing is done
00359 if not found then dov_id is registered at the end of cSV->RegisteredDO 
00360 
00361 When a DO is registered, a ColorList is created if the DO is a surface object.
00362 and N_DO is updated
00363 */
00364 SUMA_Boolean SUMA_RegisterDO(int dov_id, SUMA_SurfaceViewer *cSV)
00365 {
00366    int i;
00367    static char FuncName[]={"SUMA_RegisterDO"};
00368    SUMA_Boolean LocalHead = NOPE;
00369    
00370    SUMA_ENTRY;
00371    
00372    if (LocalHead && SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) != 0) {
00373       fprintf(SUMA_STDERR,"%s: Muted for viewer[%c]\n", FuncName, 65+SUMA_WhichSV(cSV, SUMAg_SVv, SUMA_MAX_SURF_VIEWERS) );
00374       /* turn off the LocalHead, too much output*/
00375       LocalHead = NOPE;
00376    }  
00377     
00378    /* check to see if dov_id exists */
00379    i = 0;
00380    while (i < cSV->N_DO) {
00381       if (cSV->RegisteredDO[i] == dov_id) {
00382          /* found do nothing, return */
00383          SUMA_RETURN(YUP);
00384       }
00385       ++i;
00386    }
00387    cSV->RegisteredDO[cSV->N_DO] = dov_id;
00388    cSV->N_DO += 1;
00389    
00390    /* Now add the ColorList, if DO is a surface object */
00391    if (SUMA_isSO(SUMAg_DOv[dov_id])) {
00392       if (LocalHead) fprintf (SUMA_STDERR,"%s: Adding color list...\n", FuncName);
00393       /* add the ColorList */
00394       if (!SUMA_FillColorList (cSV, (SUMA_SurfaceObject *)SUMAg_DOv[dov_id].OP)) {
00395          fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_FillColorList.\n", FuncName);
00396          SUMA_RETURN (NOPE);
00397       }
00398    }
00399    
00400    if (LocalHead) fprintf (SUMA_STDERR, "%s: Back from SUMA_FillColorList. (%s/%d).\n", \
00401          FuncName, cSV->ColList[0].idcode_str, cSV->N_ColList);
00402    
00403    if (LocalHead) {
00404       fprintf (SUMA_STDERR,"%s: RegisteredDO is now:\n", FuncName);
00405       for (i=0; i< cSV->N_DO; ++i) {
00406          fprintf(SUMA_STDERR,"RegisteredDO[%d] = %d\t", i, cSV->RegisteredDO[i]);
00407       }
00408       fprintf(SUMA_STDERR,"\n");
00409    }
00410 
00411    /* update the title bar */
00412    SUMA_UpdateViewerTitle(cSV);   
00413 
00414    SUMA_RETURN(YUP); 
00415 }
00416 /*!
00417 remove DO with I.D. dov_id from RegisteredDO list of that current viewer
00418 removal of dov_id element is done by replacing it with the last entry in RegisteredDO
00419 list. If not found, nothing happens.
00420 */
00421 SUMA_Boolean SUMA_UnRegisterDO(int dov_id, SUMA_SurfaceViewer *cSV)
00422 {
00423    int i;
00424    static char FuncName[]={"SUMA_UnRegisterDO"};
00425    SUMA_Boolean LocalHead = NOPE;
00426    
00427    SUMA_ENTRY;
00428 
00429    /* check to see if dov_id exists */
00430    i = 0;
00431    while (i < cSV->N_DO) {
00432       if (cSV->RegisteredDO[i] == dov_id) {
00433          /* found, replace it by the last in the list */
00434          cSV->RegisteredDO[i] = cSV->RegisteredDO[cSV->N_DO-1];
00435          /*remove the last element of the list */
00436          cSV->RegisteredDO[cSV->N_DO-1] = 0;
00437          cSV->N_DO -= 1; 
00438          
00439          /* empty the ColorList for this surface */
00440          if (SUMA_isSO(SUMAg_DOv[dov_id])) {
00441             SUMA_SurfaceObject *SO = NULL;
00442             if (LocalHead) fprintf (SUMA_STDERR,"%s: Emptying ColorList ...\n", FuncName);
00443             SO = (SUMA_SurfaceObject *)SUMAg_DOv[dov_id].OP;
00444             if (!SUMA_EmptyColorList (cSV, SO->idcode_str)) {
00445                fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_EmptyColorList\n", FuncName);
00446                SUMA_RETURN(NOPE);
00447             }
00448          }
00449          
00450          if (LocalHead) {
00451             fprintf (SUMA_STDERR,"%s: RegisteredDO is now:\n", FuncName);
00452             for (i=0; i< cSV->N_DO; ++i) {
00453                fprintf(SUMA_STDERR,"RegisteredDO[%d] = %d\t", i, cSV->RegisteredDO[i]);
00454             }
00455             fprintf(SUMA_STDERR,"\n");
00456          }
00457 
00458          /* update the title bar */
00459          SUMA_UpdateViewerTitle(cSV);   
00460 
00461 
00462          SUMA_RETURN(YUP);
00463       }
00464       ++i;
00465    }
00466    /* Not found, nothing happens */
00467    
00468    if (LocalHead) {
00469       fprintf (SUMA_STDERR,"%s: RegisteredDO is now:\n", FuncName);
00470       for (i=0; i< cSV->N_DO; ++i) {
00471          fprintf(SUMA_STDERR,"RegisteredDO[%d] = %d\t", i, cSV->RegisteredDO[i]);
00472       }
00473       fprintf(SUMA_STDERR,"\n");
00474    }
00475    
00476    SUMA_RETURN(YUP); 
00477 }
00478 
00479 /*!
00480 print out the data contained in dov 
00481 */
00482 void SUMA_Show_DOv (SUMA_DO *dov, int N_dov, FILE *Out)
00483 {
00484    int i;
00485    SUMA_SurfaceObject *so_op;
00486    static char FuncName[]={"SUMA_Show_DOv"};
00487    
00488    SUMA_ENTRY;
00489 
00490    if (Out == NULL) Out = stdout;
00491    fprintf(Out,"\nDOv contents (%d elements):\n", N_dov);
00492    for (i=0; i < N_dov; ++i) {
00493       switch (dov[i].ObjectType) {
00494          case SO_type:
00495             so_op = (SUMA_SurfaceObject *)dov[i].OP;
00496             if (so_op->FileType != SUMA_SUREFIT) {
00497                fprintf(Out,"DOv ID: %d\n\tName: %s/%s\n\tType: %d, Axis Attachment %d\n",\
00498                   i, so_op->Name.Path, so_op->Name.FileName,\
00499                   dov[i].ObjectType, dov[i].CoordType);
00500             } else {
00501                fprintf(Out,"DOv ID: %d\n\tNameCoord: %s/%s\n\tNameTopo: %s/%s\n\tType: %d, Axis Attachment %d\n",\
00502                   i, so_op->Name_coord.Path, so_op->Name_coord.FileName,\
00503                   so_op->Name_topo.Path, so_op->Name_topo.FileName,\
00504                   dov[i].ObjectType, dov[i].CoordType);
00505             }   
00506             break;
00507          case AO_type:
00508             {
00509                SUMA_Axis* ao;
00510                ao = (SUMA_Axis*) dov[i].OP;
00511                fprintf(Out,"DOv ID: %d\n\tAxis Object\n\tType: %d, Axis Attachment %d\n", i,dov[i].ObjectType, dov[i].CoordType);
00512                fprintf(Out,"\tName: %s\tidcode: %s\n", ao->Name, ao->idcode_str);
00513             }
00514             break;
00515          case LS_type:
00516             {
00517                SUMA_SegmentDO *sdo=NULL;
00518                
00519                sdo = (SUMA_SegmentDO *)dov[i].OP;
00520                fprintf(Out,"DOv ID: %d\n\tLine Segment Object\n\tType: %d, Axis Attachment %d\n", i,dov[i].ObjectType, dov[i].CoordType);
00521                fprintf(Out,"\tLabel: %s\tidcode: %s\n", sdo->Label, sdo->idcode_str);
00522             
00523             }
00524             break;
00525          case ROIdO_type:
00526             {
00527                SUMA_DRAWN_ROI *dROI = NULL;
00528                
00529                dROI = (SUMA_DRAWN_ROI *)dov[i].OP;
00530                fprintf(Out,"DOv ID: %d\n\tLine Segment Object\n\tType: %d, Axis Attachment %d\n", i,dov[i].ObjectType, dov[i].CoordType);
00531                fprintf(Out,"\tLabel: %s\tidcode: %s\n", dROI->Label, dROI->idcode_str);
00532             }  
00533             break;
00534          case ROIO_type:
00535             {
00536                SUMA_ROI *ROI = NULL;
00537                
00538                ROI = (SUMA_ROI *)dov[i].OP;
00539                fprintf(Out,"DOv ID: %d\n\tLine Segment Object\n\tType: %d, Axis Attachment %d\n", i,dov[i].ObjectType, dov[i].CoordType);
00540                fprintf(Out,"\tLabel: %s\tidcode: %s\n", ROI->Label, ROI->idcode_str);
00541             }  
00542             break;
00543          case GO_type:
00544             fprintf(Out,"DOv ID: %d\n\tGrid Object\n", i);
00545             break;
00546          default:
00547             fprintf(Out,"DOv ID: %d\n\tUnknown Type!\n", i);
00548             break;
00549       }
00550    }
00551    SUMA_RETURNe;
00552 }
00553 
00554 /*!
00555 returns a vector of indices into dov for DO that meet DO_Type
00556 You should free the returned pointer once you're done with it
00557 N contains the number of elements found
00558 */
00559 int * SUMA_GetDO_Type(SUMA_DO *dov, int N_dov, SUMA_DO_Types DO_Type, int *N)
00560 {
00561    static char FuncName[]={"SUMA_GetDO_Type"};
00562    int *do_id, i;
00563    SUMA_Boolean LocalHead = NOPE;
00564       
00565    SUMA_ENTRY;
00566 
00567    *N = 0;
00568 
00569    do_id = (int *)SUMA_calloc (SUMA_MAX_DISPLAYABLE_OBJECTS, sizeof(int));
00570 
00571    if (do_id == NULL) {
00572       fprintf(stderr,"Error SUMA_GetDO_Type: Could not allocate for do_id\n");
00573       SUMA_RETURN(NULL);
00574    }
00575       i = 0;
00576       while (i < N_dov) {
00577          if (dov[i].ObjectType == DO_Type) {
00578             do_id[*N] = i;
00579             *N = *N + 1;
00580          }
00581       ++i;
00582       }
00583       SUMA_RETURN(do_id);
00584 }
00585 
00586 /*!
00587    searches all SO_type DO objects for idcode
00588    YUP if found, NOPE if not
00589 */
00590 SUMA_Boolean SUMA_existSO(char *idcode, SUMA_DO *dov, int N_dov)
00591 {
00592    static char FuncName[]={"SUMA_existSO"};
00593    SUMA_SurfaceObject *SO;
00594    int i;
00595    
00596    SUMA_ENTRY;
00597 
00598    if (idcode == NULL) {
00599       fprintf(SUMA_STDERR,"Warning SUMA_existSO: NULL idcode.\n");
00600       SUMA_RETURN (NOPE);
00601    }
00602    for (i=0; i< N_dov; ++i) {
00603       if (dov[i].ObjectType == SO_type) {
00604          SO = (SUMA_SurfaceObject *)dov[i].OP;
00605          if (strcmp(idcode, SO->idcode_str)== 0) {
00606             SUMA_RETURN (YUP);
00607          }
00608       }
00609    }
00610    SUMA_RETURN(NOPE);
00611 }
00612 
00613 /*!
00614    searches all DO objects with an idcode_str for idcode
00615    
00616    YUP if found, NOPE if not
00617 */
00618 SUMA_Boolean SUMA_existDO(char *idcode, SUMA_DO *dov, int N_dov)
00619 {
00620    static char FuncName[]={"SUMA_existDO"};
00621    int i;
00622    SUMA_SurfaceObject *SO = NULL;
00623    SUMA_DRAWN_ROI *dROI = NULL;
00624    SUMA_ROI *ROI = NULL;
00625    SUMA_SegmentDO *sdo = NULL;
00626    SUMA_Axis *sax = NULL;
00627    
00628    SUMA_ENTRY;
00629 
00630    if (idcode == NULL) {
00631       fprintf(SUMA_STDERR,"Warning %s: NULL idcode.\n", FuncName);
00632       SUMA_RETURN (NOPE);
00633    }
00634    for (i=0; i< N_dov; ++i) {
00635       switch (dov[i].ObjectType) {
00636          case (SO_type):
00637             SO = (SUMA_SurfaceObject *)dov[i].OP;
00638             if (strcmp(idcode, SO->idcode_str)== 0) {
00639                SUMA_RETURN (YUP);
00640             }
00641             break;
00642          case (ROIdO_type):
00643             dROI = (SUMA_DRAWN_ROI *)dov[i].OP;
00644             if (strcmp(idcode, dROI->idcode_str)== 0) {
00645                SUMA_RETURN (YUP);
00646             }
00647             break;
00648          case (ROIO_type):
00649             ROI = (SUMA_ROI *)dov[i].OP;
00650             if (strcmp(idcode, ROI->idcode_str)== 0) {
00651                SUMA_RETURN (YUP);
00652             }
00653             break;
00654          case (AO_type):
00655             sax = (SUMA_Axis *)dov[i].OP;
00656             if (strcmp(idcode, sax->idcode_str)== 0) {
00657                SUMA_RETURN (YUP);
00658             }
00659             break;
00660          case (LS_type):
00661             sdo = (SUMA_SegmentDO *)dov[i].OP;
00662             if (strcmp(idcode, sdo->idcode_str)== 0) {
00663                SUMA_RETURN (YUP);
00664             }
00665             break;
00666          default:
00667             fprintf(SUMA_STDERR,"Warning %s: Object type %d not checked.\n", FuncName, dov[i].ObjectType);
00668             break;
00669       }
00670    }
00671    SUMA_RETURN(NOPE);
00672 }
00673 
00674 /*!
00675    searches for DO object with an idcode_str equal to idcode
00676    It returns the DO's index into dov
00677    -1 if nothing was found
00678    
00679 */
00680 int SUMA_whichDO(char *idcode, SUMA_DO *dov, int N_dov)
00681 {
00682    static char FuncName[]={"SUMA_whichDO"};
00683    int i;
00684    SUMA_SurfaceObject *SO = NULL;
00685    SUMA_DRAWN_ROI *dROI = NULL;
00686    SUMA_ROI *ROI = NULL;
00687    SUMA_SegmentDO *sdo = NULL;
00688    SUMA_Axis *sax = NULL;
00689    
00690    SUMA_ENTRY;
00691 
00692    if (SUMA_IS_EMPTY_STR_ATTR(idcode)) { /* might come in as ~ at times */
00693       fprintf(SUMA_STDERR,"Warning %s: NULL idcode.\n", FuncName);
00694       SUMA_RETURN (-1);
00695    }
00696    for (i=0; i< N_dov; ++i) {
00697       switch (dov[i].ObjectType) {
00698          case (SO_type):
00699             SO = (SUMA_SurfaceObject *)dov[i].OP;
00700             if (strcmp(idcode, SO->idcode_str)== 0) {
00701                SUMA_RETURN (i);
00702             }
00703             break;
00704          case (ROIdO_type):
00705             dROI = (SUMA_DRAWN_ROI *)dov[i].OP;
00706             if (strcmp(idcode, dROI->idcode_str)== 0) {
00707                SUMA_RETURN (i);
00708             }
00709             break;
00710          case (ROIO_type):
00711             ROI = (SUMA_ROI *)dov[i].OP;
00712             if (strcmp(idcode, ROI->idcode_str)== 0) {
00713                SUMA_RETURN (i);
00714             }
00715             break;
00716          case (AO_type):
00717             sax = (SUMA_Axis *)dov[i].OP;
00718             if (strcmp(idcode, sax->idcode_str)== 0) {
00719                SUMA_RETURN (i);
00720             }
00721             break;
00722          case (LS_type):
00723             sdo = (SUMA_SegmentDO *)dov[i].OP;
00724             if (strcmp(idcode, sdo->idcode_str)== 0) {
00725                SUMA_RETURN (i);
00726             }
00727             break;
00728          default:
00729             fprintf(SUMA_STDERR,"Warning %s: Object type %d not checked.\n", FuncName, dov[i].ObjectType);
00730             break;
00731       }
00732    }
00733    SUMA_RETURN(-1);
00734 }
00735 
00736 /*!
00737    ans = SUMA_findSO_inDOv(idcode, dov, N_dov);
00738    searches all SO_type DO objects for idcode
00739    
00740    \param idcode (char *) idcode of SO you are searching for
00741    \param dov (SUMA_DO*) pointer to vector of Displayable Objects, typically SUMAg_DOv
00742    \param N_dov (int) number of DOs in dov
00743    \return ans (int) index into dov of object with matching idcode 
00744        -1 if not found
00745   \sa SUMA_findSOp_inDOv
00746 */
00747 int SUMA_findSO_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
00748 {
00749    static char FuncName[]={"SUMA_findSO_inDOv"};
00750    SUMA_SurfaceObject *SO;
00751    int i;
00752    SUMA_Boolean LocalHead = NOPE;
00753       
00754    SUMA_ENTRY;
00755 
00756    for (i=0; i<N_dov; ++i) {
00757       if (dov[i].ObjectType == SO_type) {
00758          SO = (SUMA_SurfaceObject *)dov[i].OP;
00759          if (LocalHead) fprintf (SUMA_STDERR, "%s: Comparing \n\t:%s:to\n\t:%s:\n", \
00760                   FuncName, idcode, SO->idcode_str);
00761          if (strcmp(idcode, SO->idcode_str)== 0) {
00762             SUMA_RETURN (i);
00763          }
00764       }
00765    }
00766    SUMA_RETURN(-1);
00767 }
00768 
00769 /*!
00770    
00771   SO = SUMA_findSOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
00772    searches all SO_type DO objects for idcode
00773    
00774    \param idcode (char *) idcode of SO you are searching for
00775    \param dov (SUMA_DO*) pointer to vector of Displayable Objects, typically SUMAg_DOv
00776    \param N_dov (int) number of DOs in dov
00777    \return SO (SUMA_SurfaceObject *) pointer of SO with matching idcode 
00778        NULL if not found
00779    \sa SUMA_findSO_inDOv
00780 */
00781 SUMA_SurfaceObject * SUMA_findSOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
00782 {
00783    static char FuncName[]={"SUMA_findSOp_inDOv"};
00784    SUMA_SurfaceObject *SO;
00785    int i;
00786    
00787    SUMA_ENTRY;
00788 
00789    for (i=0; i<N_dov; ++i) {
00790       if (dov[i].ObjectType == SO_type) {
00791          SO = (SUMA_SurfaceObject *)dov[i].OP;
00792          if (strcmp(idcode, SO->idcode_str)== 0) {
00793             SUMA_RETURN (SO);
00794          }
00795       }
00796    }
00797    SUMA_RETURN(NULL);
00798 }
00799 
00800 /*!
00801    
00802   SO = SUMA_find_named_SOp_inDOv(char *idcode, SUMA_DO *dov, int N_dov)
00803    searches all SO_type DO objects for idcode
00804    
00805    \param coordname (char *) filename of SO (without path) that you are searching for.
00806                              If surface is specified by 2 files, then use the coord file
00807                              name.  
00808    \param dov (SUMA_DO*) pointer to vector of Displayable Objects, typically SUMAg_DOv
00809    \param N_dov (int) number of DOs in dov
00810    \return SO (SUMA_SurfaceObject *) pointer of SO with matching idcode 
00811        NULL if not found
00812    \sa SUMA_findSO_inDOv
00813    \sa SUMA_findSOp_inDOv
00814 */
00815 SUMA_SurfaceObject * SUMA_find_named_SOp_inDOv(char *coordname, SUMA_DO *dov, int N_dov)
00816 {
00817    static char FuncName[]={"SUMA_find_named_SOp_inDOv"};
00818    SUMA_SurfaceObject *SO = NULL, *SOf = NULL;
00819    SUMA_STRING *SS=NULL;
00820    char *stmp=NULL;
00821    int i;
00822    
00823    SUMA_ENTRY;
00824    
00825    i=0;
00826    SOf = NULL;
00827    while (i<N_dov) {
00828       if (dov[i].ObjectType == SO_type) {
00829          SO = (SUMA_SurfaceObject *)dov[i].OP;
00830          switch(SO->FileType) {
00831             case SUMA_SUREFIT:
00832             case SUMA_VEC:
00833                if (strstr(SO->Name_coord.FileName, coordname)) {
00834                   if (SOf) {
00835                      SS = SUMA_StringAppend_va(NULL, NULL);
00836                      SS = SUMA_StringAppend_va(SS, 
00837                                     "Error %s:\n"
00838                                     "Surface name %s\n"
00839                                     "is not a unique identifier.\n"
00840                                     "Found %s and %s so far.\n"
00841                                     "Be more specific.\n", FuncName, 
00842                                     coordname, SOf->Name_coord.FileName,
00843                                     SO->Name_coord.FileName);
00844                      SUMA_SS2S(SS, stmp);
00845                      SUMA_SL_Err(stmp); if (stmp) SUMA_free(stmp); stmp = NULL;
00846                      SUMA_RETURN(NULL);
00847                   }
00848                   SOf = SO;
00849                }
00850                break;
00851             case SUMA_FREE_SURFER:
00852             case SUMA_FREE_SURFER_PATCH:
00853             case SUMA_INVENTOR_GENERIC:
00854             case SUMA_OPENDX_MESH:
00855             case SUMA_PLY: 
00856                if (strstr(SO->Name.FileName, coordname)) {
00857                   if (SOf) {
00858                      SS = SUMA_StringAppend_va(NULL, NULL);
00859                      SS = SUMA_StringAppend_va(SS, 
00860                                     "Error %s:\n"
00861                                     "Surface name %s\n"
00862                                     "is not a unique identifier.\n"
00863                                     "Found %s and %s so far.\n"
00864                                     "Be more specific.\n", FuncName, 
00865                                     coordname, SOf->Name_coord.FileName,
00866                                     SO->Name_coord.FileName);
00867                      SUMA_SS2S(SS, stmp);
00868                      SUMA_SL_Err(stmp); if (stmp) SUMA_free(stmp); stmp = NULL;
00869                      SUMA_RETURN(NULL);
00870                   }
00871                   SOf = SO;
00872                }
00873                break;
00874             default: 
00875                SUMA_SL_Err("Type not supported.");
00876                SUMA_RETURN(NULL);
00877          }
00878       }
00879       ++i;
00880    }
00881    
00882    SUMA_RETURN(SOf);
00883 }
00884 
00885 /*!
00886    determines if a Surface Object is mappable (ie LocalDomainParentID != NULL)
00887    ans = SUMA_ismappable (SUMA_SurfaceObject *SO)
00888    \param SO (SUMA_SurfaceObject *)
00889    \ret YUP/NOPE
00890 */
00891 SUMA_Boolean SUMA_ismappable (SUMA_SurfaceObject *SO)
00892 {
00893    static char FuncName[]={"SUMA_ismappable"};
00894    
00895    SUMA_ENTRY;
00896 
00897    if (SO->LocalDomainParentID != NULL) {
00898       /* SO is mappable */
00899       SUMA_RETURN (YUP);
00900    }
00901     
00902    SUMA_RETURN (NOPE);
00903 
00904 }
00905 
00906 /*!
00907    Left here temporarily for backward compatibility
00908    
00909    use the more appropriately named SUMA_isLocalDomainParent
00910 */
00911 SUMA_Boolean SUMA_isINHmappable (SUMA_SurfaceObject *SO)
00912 {
00913    static char FuncName[]={"SUMA_isINHmappable"};
00914    
00915    SUMA_ENTRY;
00916    
00917    SUMA_RETURN(SUMA_isLocalDomainParent(SO));
00918 }
00919 
00920 /*!
00921    determines if a Surface Object is a local domain parent (ie LocalDomainParentID == idcode_str)
00922    (used to be called inherently mappable) 
00923    ans = SUMA_isLocalDomainParent (SUMA_SurfaceObject *SO)
00924    \param SO (SUMA_SurfaceObject *)
00925    \ret YUP/NOPE
00926    
00927    -- Used to be called SUMA_isINHmappable
00928 */
00929 SUMA_Boolean SUMA_isLocalDomainParent (SUMA_SurfaceObject *SO)
00930 {
00931    static char FuncName[]={"SUMA_isLocalDomainParent"};
00932    
00933    SUMA_ENTRY;
00934 
00935    if (SO->LocalDomainParentID == NULL) {
00936       SUMA_RETURN (NOPE);
00937    }
00938    if (strcmp(SO->LocalDomainParentID, SO->idcode_str) == 0) {
00939       /* SO is the local domain parent */
00940       SUMA_RETURN (YUP);
00941    } 
00942    SUMA_RETURN (NOPE);
00943 }
00944 
00945 /*!
00946    \brief ans = SUMA_isRelated (SUMA_SurfaceObject *SO1, SUMA_SurfaceObject *SO2, int level);
00947    
00948    returns YUP if SO1 and SO2 are related at level 1 or 2
00949    level 1 means nuclear family (share the same parent)
00950    level 2 means extended family (share a grandparent, ultimately this could be the grand icosahedron duc
00951                                  Surfaces must be the of the same hemi side since both hemispheres can have
00952                                  the same grandparent, use level 3 if you want to go across hemis.)
00953    level 3 is like level 2 with no care for what side of the brain we're working with
00954    For more definitions on relationships:
00955    
00956    \sa SUMA_WhatAreYouToMe
00957 */
00958 
00959 SUMA_Boolean SUMA_isRelated ( SUMA_SurfaceObject *SO1, SUMA_SurfaceObject *SO2, int level)
00960 {
00961    static char FuncName[]={"SUMA_isRelated"};
00962    SUMA_DOMAIN_KINSHIPS kin;
00963    SUMA_Boolean LocalHead = NOPE;
00964    
00965    SUMA_ENTRY;
00966    
00967    kin =  SUMA_WhatAreYouToMe (SO1, SO2);
00968    switch (level) {
00969       case 3: /* anything goes */
00970          if (  (kin > SUMA_DOMAINS_NOT_RELATED) ) SUMA_RETURN(YUP);
00971          break;
00972       case 2: /* share an ancestor, but same side */
00973          if (  (kin > SUMA_DOMAINS_NOT_RELATED) &&
00974                (SO1->Side == SO2->Side) ) SUMA_RETURN(YUP);
00975          break;
00976       case 1: /* nuclear family only */
00977          if (  (kin > SUMA_DOMAINS_NOT_RELATED) && 
00978                (kin < SUMA_NUCELAR_FAMILY ) &&
00979                (SO1->Side == SO2->Side) ) SUMA_RETURN(YUP); /* last condition is not really necessary but it don't hoyt...*/
00980          break;
00981       default:
00982          SUMA_SL_Err("Bad value for level.");   
00983          break;
00984    }
00985    SUMA_RETURN(NOPE);
00986 }
00987 
00988 /*!
00989    \brief ans = SUMA_WhatAreYouToMe (SUMA_SurfaceObject *SO1, SUMA_SurfaceObject *SO2);
00990    returns a code for the kinship between two surfaces:
00991     
00992    SO1->idcode_str = SO2->idcode_str (in this case SO1 = SO2) or 
00993    SO1->LocalDomainParentID = SO2->idcode_str (SO2 is the mapping reference of SO1) or
00994    SO1->idcode_str = SO2->LocalDomainParentID (SO1 is the mapping reference of SO2)
00995    SO1->LocalDomainParentID = SO2->LocalDomainParentID (SO1 and SO2 have the same mapping reference) or 
00996    SO1->DomainGrandParentID = SO2->idcode_str (SO2 is the granddaddy of SO1) or
00997    SO1->idcode_str = SO2->DomainGrandParentID (SO1 is the granddaddy of SO2) or
00998    SO1->DomainGrandParentID = SO2->DomainGrandParentID (SO1 and SO2 have the same granddaddy) 
00999    
01000    \sa definition of SUMA_DOMAIN_KINSHIPS and
01001    \sa SUMA_DomainKinships_String
01002 */
01003 SUMA_DOMAIN_KINSHIPS SUMA_WhatAreYouToMe (SUMA_SurfaceObject *SO1, SUMA_SurfaceObject *SO2)
01004 {
01005    static char FuncName[]={"SUMA_WhatAreYouToMe"};
01006    SUMA_Boolean LocalHead = NOPE;
01007    
01008    SUMA_ENTRY;
01009    
01010    if (!SO1->idcode_str || !SO2->idcode_str) {
01011       fprintf (SUMA_STDERR, "Error %s: NULL idcode_str.\n", FuncName);
01012       SUMA_RETURN (SUMA_DOMAINS_NOT_RELATED);
01013    }
01014    
01015    if (strcmp (SO1->idcode_str, SO2->idcode_str) == 0) {
01016       /* SO1 = SO2 */
01017       SUMA_LH(SUMA_DomainKinships_String (SUMA_SO1_is_SO2));
01018       SUMA_RETURN (SUMA_SO1_is_SO2);
01019    }
01020    
01021    if (SO1->LocalDomainParentID) {
01022       if (strcmp (SO1->LocalDomainParentID, SO2->idcode_str) == 0) {
01023          /* SO2 is the local domain parent of SO1 */
01024          SUMA_LH(SUMA_DomainKinships_String (SUMA_SO2_is_LDPSO1));
01025          SUMA_RETURN (SUMA_SO2_is_LDPSO1);
01026       }
01027    }
01028    
01029    if (SO2->LocalDomainParentID) {
01030       if (strcmp (SO1->idcode_str, SO2->LocalDomainParentID) == 0) {
01031           /* SO1 is the local domain parent of SO2 */
01032           SUMA_LH(SUMA_DomainKinships_String (SUMA_SO1_is_LDPSO2));
01033           SUMA_RETURN (SUMA_SO1_is_LDPSO2);
01034       }
01035    }
01036    
01037    if (SO1->LocalDomainParentID && SO2->LocalDomainParentID) {
01038       if (strcmp (SO1->LocalDomainParentID, SO2->LocalDomainParentID) == 0) {
01039          /* SO1 and SO2 have the same local domain parent */
01040          SUMA_LH(SUMA_DomainKinships_String (SUMA_LDPSO1_is_LDPSO2));
01041          SUMA_RETURN (SUMA_LDPSO1_is_LDPSO2);
01042       }
01043    }
01044    
01045    if (SO1->DomainGrandParentID && SO2->idcode_str) {
01046       if (strcmp (SO1->DomainGrandParentID, SO2->idcode_str) == 0) {
01047          /* SO2 is the grand daddy of SO1 */
01048          SUMA_LH(SUMA_DomainKinships_String (SUMA_SO2_is_GPSO1));
01049          SUMA_RETURN (SUMA_SO2_is_GPSO1);
01050       }
01051    }
01052    
01053    if (SO1->idcode_str && SO2->DomainGrandParentID) {
01054       if (strcmp (SO1->idcode_str, SO2->DomainGrandParentID) == 0) {
01055          /* SO1 is the grand daddy of SO2 */
01056          SUMA_LH(SUMA_DomainKinships_String (SUMA_SO1_is_GPSO2));
01057          SUMA_RETURN (SUMA_SO1_is_GPSO2);
01058       }
01059    }
01060    
01061    if (SO1->DomainGrandParentID && SO2->DomainGrandParentID) {
01062       if (strcmp (SO1->DomainGrandParentID, SO2->DomainGrandParentID) == 0) {
01063          /* SO1 and SO2 have the same grand daddy */
01064          SUMA_LH(SUMA_DomainKinships_String (SUMA_GPSO1_is_GPSO2));
01065          SUMA_RETURN (SUMA_GPSO1_is_GPSO2);
01066       }
01067    }
01068    
01069    SUMA_LH(SUMA_DomainKinships_String (SUMA_DOMAINS_NOT_RELATED));
01070    SUMA_RETURN (SUMA_DOMAINS_NOT_RELATED);
01071    
01072 }
01073 
01074 /*!
01075    \brief SUMA_Boolean SUMA_isSO_G (SUMA_DO DO, char *Group) 
01076    returns YUP if DO is a surface object
01077    and is a part of the group Group
01078    
01079    \sa SUMA_isSO
01080 */
01081 SUMA_Boolean SUMA_isSO_G (SUMA_DO DO, char *Group) 
01082 {
01083    static char FuncName[]={"SUMA_isSO_G"};
01084    SUMA_SurfaceObject *SO = NULL;
01085    
01086    SUMA_ENTRY;
01087    
01088    if (!Group) {
01089       SUMA_SL_Err("Null Group");
01090       SUMA_RETURN(NOPE);
01091    }
01092    
01093    if (SUMA_isSO(DO)) {
01094       SO = (SUMA_SurfaceObject *)DO.OP;
01095       if (strcmp(SO->Group, Group)) { SUMA_RETURN(NOPE); }
01096       else { SUMA_RETURN(YUP); }
01097    }
01098    
01099    SUMA_RETURN(NOPE);
01100 }
01101 /*!
01102    \brief SUMA_Boolean SUMA_isSO (SUMA_DO DO) 
01103    returns YUP if DO is of SO_type
01104    ans = SUMA_isSO (DO) ;
01105    
01106    \sa SUMA_isSO_G (SUMA_DO DO, char *Group)
01107 */
01108 SUMA_Boolean SUMA_isSO (SUMA_DO DO) 
01109 {
01110    static char FuncName[]={"SUMA_isSO"};
01111    
01112    SUMA_ENTRY;
01113 
01114    if (DO.ObjectType == SO_type) {
01115       SUMA_RETURN (YUP);
01116    }
01117    SUMA_RETURN (NOPE);
01118 }
01119 
01120 /*!
01121    \brief Returns a list of the ROIs loaded into dov. 
01122    
01123    \param dov (SUMA_DO *) pointer to vector of DOs
01124    \param N_dov (int) number of DOs in dov
01125    \param SortByLabel (SUMA_Boolean) if YUP then returned strings are sorted by their ROI's labels
01126             (The parents must be part of dov). If Nope then strings are sorted by the labels of
01127              the ROI's parent.
01128    \return clist (SUMA_ASSEMBLE_LIST_STRUCT *) pointer to structure containing results
01129    
01130    \sa SUMA_FreeAssembleListStruct
01131    \sa SUMA_CreateAssembleListStruct
01132    
01133 */
01134 SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleAllROIList (SUMA_DO * dov, int N_dov, SUMA_Boolean SortByLabel) 
01135 {
01136    static char FuncName[]={"SUMA_AssembleAllROIList"};
01137    int i=-1, N_clist=-1; 
01138    DList *list=NULL, *listop = NULL;
01139    DListElmt *Elm = NULL, *Elmop = NULL;
01140    char Label[SUMA_MAX_NAME_LENGTH], Parent_Label[SUMA_MAX_NAME_LENGTH], *store=NULL;
01141    SUMA_SurfaceObject *SO = NULL;
01142    char **clist=NULL;
01143    void **oplist=NULL;
01144    SUMA_DRAWN_ROI *ROI=NULL;
01145    SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;
01146    SUMA_Boolean Found = NOPE;
01147    SUMA_Boolean LocalHead = NOPE;
01148 
01149    SUMA_ENTRY;
01150    
01151    list = (DList *)SUMA_malloc(sizeof(DList));
01152    listop = (DList *)SUMA_malloc(sizeof(DList));
01153    
01154    clist = NULL;
01155    N_clist = -1;
01156    
01157    dlist_init(list, NULL);
01158    dlist_init(listop, NULL);
01159    for (i=0; i < N_dov; ++i) {
01160       if (dov[i].ObjectType == ROIdO_type) {
01161          ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
01162          if (LocalHead) fprintf (SUMA_STDERR, "%s: Found an ROI %s\n", FuncName, ROI->Label);
01163          if (!ROI->Label) sprintf (Label,"NULL");
01164          else sprintf (Label,"%s", ROI->Label);
01165          if (!ROI->Parent_idcode_str) sprintf (Parent_Label,"NULL");
01166          else {
01167             SO = SUMA_findSOp_inDOv(ROI->Parent_idcode_str, dov, N_dov);
01168             if (!SO) sprintf (Parent_Label,"Unknown");
01169             else if (!SO->Label) sprintf (Parent_Label,"Empty");
01170             else sprintf (Parent_Label,"%s", SO->Label);
01171          }
01172          /* Now allocate space for that label */
01173          store = (char *)SUMA_calloc(strlen(Label)+strlen(Parent_Label)+5, sizeof(char));
01174          if (SortByLabel) {
01175             sprintf(store,"%s:%s", Label, Parent_Label);
01176          } else  {
01177             sprintf(store,"%s:%s", Parent_Label, Label);
01178          }
01179          
01180          /* now place it in the list by aplhpabetical order */
01181          if (!list->size) {
01182             dlist_ins_next(list, dlist_tail(list), (void*)store);
01183             dlist_ins_next(listop, dlist_tail(listop), (void*)ROI);
01184          }else { /* must sort first */
01185             Elm = NULL;
01186             Elmop = NULL;
01187             do {
01188                Found = NOPE;
01189                if (!Elm) {
01190                   Elm = dlist_head(list);
01191                   Elmop = dlist_head(listop);
01192                } else {
01193                   Elm = dlist_next(Elm);
01194                   Elmop = dlist_next(Elmop);
01195                }
01196                
01197                if (strcmp(store, (char*)Elm->data) <= 0) {
01198                   dlist_ins_prev(list, Elm, (void *)store);
01199                   dlist_ins_prev(listop, Elmop, (void *)ROI);
01200                   Found = YUP;
01201                } else if (Elm == dlist_tail(list)) {
01202                   /* reached the end, append */
01203                   dlist_ins_next(list, Elm, (void *)store);
01204                   dlist_ins_next(listop, Elmop, (void *)ROI);
01205                   Found = YUP;
01206                }
01207             } while (!Found);
01208          }
01209          
01210       }
01211    }
01212 
01213    if (!list->size) { /* Nothing found */
01214       N_clist = 0;
01215       
01216    }else {
01217    
01218       Elm = NULL;
01219       Elmop = NULL;
01220       clist = (char **)SUMA_calloc(list->size, sizeof(char *));
01221       oplist = (void **)SUMA_calloc(list->size, sizeof(void*));
01222       for (i=0; i< list->size; ++i) {
01223          if (!Elm) {
01224             Elm = dlist_head(list);
01225             Elmop = dlist_head(listop);
01226          } else {
01227             Elm = dlist_next(Elm);
01228             Elmop = dlist_next(Elmop);
01229          }
01230          clist[i] = (char*)Elm->data;
01231          oplist[i] = Elmop->data;
01232       }
01233 
01234       N_clist = list->size;
01235       /* destroy list */
01236       dlist_destroy(list);
01237       dlist_destroy(listop);
01238       SUMA_free(list);
01239       SUMA_free(listop);
01240    }
01241    
01242    clist_str = SUMA_CreateAssembleListStruct();
01243    clist_str->clist = clist;
01244    clist_str->oplist = oplist;
01245    clist_str->N_clist = N_clist;
01246    
01247    /* return */
01248    SUMA_RETURN (clist_str);  
01249 }
01250 
01251 /*!
01252    \brief Creates an SUMA_ASSEMBLE_LIST_STRUCT *structure
01253    \sa SUMA_FreeAssembleListStruct
01254 */
01255 SUMA_ASSEMBLE_LIST_STRUCT *SUMA_CreateAssembleListStruct(void)
01256 {
01257    static char FuncName[]={"SUMA_CreateAssembleListStruct"};
01258    SUMA_ASSEMBLE_LIST_STRUCT *str=NULL;
01259    
01260    SUMA_ENTRY;
01261    
01262    str = (SUMA_ASSEMBLE_LIST_STRUCT *)SUMA_malloc(sizeof(SUMA_ASSEMBLE_LIST_STRUCT));
01263    str->clist = NULL;
01264    str->N_clist = -1;
01265    str->oplist = NULL;
01266    
01267    SUMA_RETURN(str);
01268 }
01269 /*!
01270    \brief frees SUMA_ASSEMBLE_LIST_STRUCT *
01271    \param SUMA_ASSEMBLE_LIST_STRUCT *str
01272    
01273    \return NULL always
01274    
01275    -This function frees each string in clist. BUT NOT pointers in oplist (for obvious reasons)
01276 */
01277 SUMA_ASSEMBLE_LIST_STRUCT *SUMA_FreeAssembleListStruct(SUMA_ASSEMBLE_LIST_STRUCT *str) 
01278 {
01279    static char FuncName[]={"SUMA_FreeAssembleListStruct"};
01280    int i;
01281    
01282    SUMA_ENTRY;
01283    
01284    if (!str) SUMA_RETURN(NULL);
01285    
01286    if (str->clist) {
01287       for (i=0; i < str->N_clist; ++i)
01288          if (str->clist[i]) SUMA_free(str->clist[i]);
01289       SUMA_free(str->clist);
01290    }
01291    if (str->oplist) SUMA_free(str->oplist);
01292    SUMA_free(str);
01293    
01294    SUMA_RETURN(NULL);
01295 }
01296 
01297 
01298 /*!
01299 \brief Returns an ROI that is related to SO and is in InCreation (being actively drawn) DrawStatus 
01300  There should only be one ROI in creation at any one time for a group of related surfaces. 
01301  
01302  ROI = SUMA_
01303  ROI_InCreation (SO,  dov,  N_dov);
01304  
01305  \param SO (SUMA_SurfaceObject *) pointer to surface object
01306  \param dov (SUMA_DO *) pointer to vector of DOs (typically SUMAg_DOv)
01307  \param N_dov (int) number of elements in dov
01308  \return ROI (SUMA_DRAWN_ROI *) pointer to ROI object, NULL if no such object is found.
01309  
01310 */
01311 SUMA_DRAWN_ROI * SUMA_FetchROI_InCreation (SUMA_SurfaceObject *SO, SUMA_DO * dov, int N_dov) 
01312 {
01313    int i;
01314    SUMA_DRAWN_ROI *ROI = NULL;
01315    static char FuncName[]={"SUMA_FetchROI_InCreation"};
01316    
01317    SUMA_ENTRY;
01318    
01319    for (i=0; i < N_dov; ++i) {
01320       if (dov[i].ObjectType == ROIdO_type) {
01321          ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
01322          if (ROI->DrawStatus == SUMA_ROI_InCreation) {
01323             if (SUMA_isdROIrelated (ROI, SO)) {
01324                /* found an ROI, should be the only one, return */
01325                SUMA_RETURN (ROI);
01326             }
01327          }
01328       }
01329    }
01330    SUMA_RETURN (NULL);
01331 }
01332 
01333 /*!
01334 \brief Returns YUP if the surface: dROI->Parent_idcode_str is related to SO->idcode_str or SO->LocalDomainParentID.
01335 NOPE otherwise
01336 
01337 ans = SUMA_isdROIrelated (dROI, SO);
01338 
01339 \param ROI (SUMA_DRAWN_ROI *) pointer to drawn ROI
01340 \param SO (SUMA_SurfaceObject *) pointer to surface object
01341 \return ans (SUMA_Boolean) YUP/NOPE
01342 
01343 */
01344 SUMA_Boolean SUMA_isdROIrelated (SUMA_DRAWN_ROI *ROI, SUMA_SurfaceObject *SO)
01345 {
01346    static char FuncName[]={"SUMA_isdROIrelated"};
01347    SUMA_SurfaceObject *SO_ROI = NULL;
01348    SUMA_Boolean LocalHead = NOPE;
01349    
01350    SUMA_ENTRY;
01351    
01352    if (LocalHead) {
01353       fprintf (SUMA_STDERR, "%s: %s SO->LocalDomainParentID\n", FuncName, SO->LocalDomainParentID);
01354       fprintf (SUMA_STDERR, "%s: %s ROI->Parent_idcode_str\n", FuncName, ROI->Parent_idcode_str);
01355       fprintf (SUMA_STDERR, "%s: %s SO->idcode_str\n", FuncName, SO->idcode_str);
01356    }
01357    
01358    /* find the pointer to the surface having for an idcode_str: ROI->Parent_idcode_str */
01359    SO_ROI = SUMA_findSOp_inDOv(ROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
01360    
01361    if (!SO_ROI) {
01362       SUMA_SL_Err("Could not find surface of ROI->Parent_idcode_str");
01363       SUMA_RETURN (NOPE);
01364    }
01365    
01366    if (SUMA_isRelated (SO, SO_ROI, 1)) { /* relationship of the 1st order only */ 
01367       SUMA_RETURN (YUP);
01368    }
01369 
01370    SUMA_RETURN (NOPE);
01371 }
01372 
01373 /*!
01374 \brief Returns YUP if if the surface: ROI->Parent_idcode_str is related to SO->idcode_str or SO->LocalDomainParentID.
01375 NOPE otherwise
01376 
01377 ans = SUMA_isROIrelated (ROI, SO);
01378 
01379 \param ROI (SUMA_ROI *) pointer to ROI
01380 \param SO (SUMA_SurfaceObject *) pointer to surface object
01381 \return ans (SUMA_Boolean) YUP/NOPE
01382 
01383 */
01384 SUMA_Boolean SUMA_isROIrelated (SUMA_ROI *ROI, SUMA_SurfaceObject *SO)
01385 {
01386    static char FuncName[]={"SUMA_isROIrelated"};
01387    SUMA_SurfaceObject *SO_ROI = NULL;
01388    
01389    SUMA_ENTRY;
01390    
01391    /* find the pointer to the surface having for an idcode_str: ROI->Parent_idcode_str */
01392    SO_ROI = SUMA_findSOp_inDOv(ROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
01393    
01394    if (!SO_ROI) {
01395       SUMA_SL_Err("Could not find surface of ROI->Parent_idcode_str");
01396       SUMA_RETURN (NOPE);
01397    }
01398    
01399    if (SUMA_isRelated (SO, SO_ROI, 1)) { /* relationship of the 1st order only */
01400       SUMA_RETURN (YUP);
01401    }
01402 
01403    SUMA_RETURN (NOPE);
01404 }
01405 
01406 /*!
01407 \brief Return a mask of the nodes belonging to any ROI of a certain surface
01408    Mask = SUMA_Build_Mask_AllROI (dov, N_dov, SO, Mask, N_added);
01409 
01410 \param dov (SUMA_DO*) pointer to vector of displayable objects to consider
01411 \param N_dov (int) number of elements in dov
01412 \param SO (SUMA_SurfaceObject *)
01413 \param Mask (int *) pointer to mask vector.
01414          0 if node belongs to no ROI
01415          n if node belongs to n ROIs
01416          Pass NULL if you're calling this function for the first time.
01417 \param N_added (int *)integer containing the total number of nodes added to Mask.
01418       That would be the sum of the number of nodes found in all ROIs.
01419       Duplicate nodes are counted twice. If you want the number of nodes without
01420       the duplicates, you need to count non-zero values in Mask. 
01421 \return Mask (int *) pointer to modified mask vector. 
01422 */
01423 int * SUMA_Build_Mask_AllROI (SUMA_DO *dov, int N_do, SUMA_SurfaceObject *SO, int *Mask, int *N_added)
01424 {
01425    static char FuncName[]={"SUMA_Build_Mask_AllROI"};
01426    int Npart = 0,i;
01427    SUMA_DRAWN_ROI *D_ROI=NULL;
01428    SUMA_ROI *ROI = NULL;
01429    SUMA_Boolean LocalHead = NOPE;
01430     
01431    SUMA_ENTRY;
01432    
01433    *N_added = -1;
01434    
01435    if (!Mask) { /* allocate for it */
01436       Mask = (int *)SUMA_calloc(SO->N_Node, sizeof(int));
01437       if (!Mask) {
01438          SUMA_S_Err ("Failed to allocate for Mask.");
01439          SUMA_RETURN(NULL);
01440       }
01441    }
01442    
01443    for (i=0; i < N_do; ++i) {
01444       switch (dov[i].ObjectType) { /* case Object Type */
01445          case ROIdO_type:
01446             D_ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
01447             if (SUMA_isdROIrelated (D_ROI, SO)) {
01448                if (LocalHead) fprintf (SUMA_STDERR, "%s: Found a drawn ROI, building mask...\n", FuncName);
01449 
01450                Npart = SUMA_Build_Mask_DrawnROI (D_ROI, Mask);
01451                if (Npart < 0) {
01452                   SUMA_S_Err ("Badness in SUMA_Build_Mask_DrawnROI");
01453                   if (Mask) SUMA_free(Mask);
01454                   *N_added = -1;
01455                   SUMA_RETURN(NULL);
01456                }else {
01457                   *N_added = *N_added + Npart;
01458                   if (LocalHead) fprintf (SUMA_STDERR, "%s: %d nodes found in that ROI.\n", FuncName, Npart);
01459                }
01460             }
01461             break;
01462          case ROIO_type:
01463             ROI = (SUMA_ROI *)dov[i].OP;
01464             if (SUMA_isROIrelated (ROI, SO)) {
01465                SUMA_S_Err ("Not dealing with regular ROIs yet");
01466             }
01467             break;
01468          default:
01469             /* not an ROI */
01470             break;   
01471       }
01472    }
01473    
01474    SUMA_RETURN(Mask);
01475 }
01476 
01477 /*!
01478 \brief Return a mask of the nodes belonging to a drawn ROI of a certain surface
01479    N_added = SUMA_Build_Mask_DrawnROI (dROI, Mask);
01480    
01481 \param dROI (SUMA_DRAWN_ROI *) the pointer to the ROI structure
01482 \param Mask (int *) pointer to mask vector.
01483          0 if node belongs to no ROI
01484          n if node belongs to n ROIs
01485       It is the calling function's responsability to make sure enough space is allocated for
01486       Mask and that cleanup is properly handled.
01487 \return N_added (int *)integer containing the number of nodes found in dROI. 
01488       This variable is set to -1 when trouble occurs.  
01489 */ 
01490 int SUMA_Build_Mask_DrawnROI (SUMA_DRAWN_ROI *D_ROI, int *Mask)
01491 {
01492    static char FuncName[]={"SUMA_Build_Mask_DrawnROI"};
01493    DListElmt *NextElm=NULL;
01494    int ii, N_added;
01495    SUMA_ROI_DATUM *ROId=NULL;
01496    
01497    SUMA_ENTRY;
01498    
01499    N_added = -1;
01500    
01501    if (!Mask) { 
01502       SUMA_S_Err ("Mask is NULL");
01503       SUMA_RETURN(N_added);
01504    }
01505    
01506    if (!D_ROI->ROIstrokelist) {
01507      N_added = 0;
01508      SUMA_RETURN(N_added); 
01509    }
01510    
01511    if (!dlist_size(D_ROI->ROIstrokelist)) {
01512      N_added = 0;
01513      SUMA_RETURN(N_added); 
01514    }
01515    
01516    /* start with the first element */
01517    NextElm = NULL;
01518    do {
01519       if (!NextElm) {
01520          NextElm = dlist_head(D_ROI->ROIstrokelist);
01521       }else {
01522          NextElm = dlist_next(NextElm);
01523       }
01524       ROId = (SUMA_ROI_DATUM *)NextElm->data;
01525       if (ROId->N_n) {
01526          for (ii = 0; ii < ROId->N_n; ++ii) {
01527             ++Mask[ROId->nPath[ii]];
01528             ++N_added;
01529          }
01530       }
01531    } while (NextElm != dlist_tail(D_ROI->ROIstrokelist));
01532                
01533    SUMA_RETURN (N_added);
01534 }
01535 
01536 /*!
01537    \brief deletes an ROI from the list of drawn objects
01538 */
01539 SUMA_Boolean SUMA_DeleteROI (SUMA_DRAWN_ROI *ROI) 
01540 {
01541    static char FuncName[]={"SUMA_DeleteROI"};
01542    SUMA_ASSEMBLE_LIST_STRUCT *ALS = NULL;
01543    SUMA_DRAWN_ROI *NextROI=NULL;
01544    int i;
01545    SUMA_Boolean WasCurrent = NOPE, Shaded = NOPE;
01546    SUMA_Boolean LocalHead = NOPE;
01547 
01548    SUMA_ENTRY;
01549 
01550    if (!ROI) {
01551       SUMA_LH("Null ROI");
01552       SUMA_RETURN(YUP);
01553    }
01554    
01555    /* form a list of the current ROI available for editing */
01556 
01557    /* assemble the ROI list */
01558    ALS = SUMA_AssembleAllROIList (SUMAg_DOv, SUMAg_N_DOv, YUP);
01559 
01560    NextROI = NULL;
01561    if (ALS) {
01562       if (ALS->N_clist)  {
01563          i=0;
01564          while (!NextROI && i<ALS->N_clist) {
01565             if (ALS->oplist[i] != (void*)ROI) 
01566                NextROI = (SUMA_DRAWN_ROI *)ALS->oplist[i];
01567             ++i;
01568          }  
01569       }
01570       SUMA_FreeAssembleListStruct(ALS);
01571    }
01572 
01573    /* check to see if ROI being deleted is current one */
01574    if (ROI == SUMAg_CF->X->DrawROI->curDrawnROI) {
01575       WasCurrent = YUP;
01576    }else {
01577       WasCurrent = NOPE;
01578    }
01579    
01580    /* Close the ROIlist window if it is open */
01581    SUMA_IS_DRAW_ROI_SWITCH_ROI_SHADED(Shaded);
01582    if (!Shaded) {
01583       if (LocalHead) fprintf (SUMA_STDERR, "%s: Closing switch ROI window ...\n", FuncName);
01584       SUMA_cb_CloseSwitchROI(NULL, (XtPointer) SUMAg_CF->X->DrawROI->SwitchROIlst, NULL);
01585    }
01586 
01587    /* remove ROI for SUMAg_DO and clear the ROI structure*/
01588    if (!SUMA_RemoveDO(SUMAg_DOv, &SUMAg_N_DOv, (void *)ROI, YUP)) {
01589       SUMA_SLP_Err("Failed to remove DO from list.");
01590       SUMA_RETURN(NOPE);
01591    }
01592 
01593    if (WasCurrent) {
01594       SUMAg_CF->X->DrawROI->curDrawnROI = NextROI;
01595 
01596       /* reinitialize the draw ROI window */
01597       SUMA_InitializeDrawROIWindow(SUMAg_CF->X->DrawROI->curDrawnROI);
01598    }
01599    
01600    SUMA_RETURN(YUP);
01601 }
01602 
01603 /*!
01604    \brief return  +1 if surface is typically the outer layer surface used in Vol2Surf
01605                   -1 if surface is typically the inner layer surface used in Vol2Surf
01606                    0 if no comment 
01607 */
01608 int SUMA_isTypicalSOforVolSurf (SUMA_SurfaceObject *SO)
01609 {
01610    static char FuncName[]={"SUMA_isTypicalSOforVolSurf"};
01611    SUMA_ENTRY;
01612    
01613    switch (SO->FileType) {
01614       case SUMA_FREE_SURFER: 
01615          if (SUMA_iswordin (SO->Name.FileName, "smoothwm")) SUMA_RETURN(-1);
01616          else if (SUMA_iswordin (SO->Name.FileName, "pial")) SUMA_RETURN(1);
01617          else SUMA_RETURN(0);
01618          break;
01619       default:
01620          SUMA_RETURN(0);
01621          break;
01622    }
01623    
01624    SUMA_RETURN(0);
01625 }
01626 
 

Powered by Plone

This site conforms to the following standards: