Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

SUMA_Load_Surface_Object.c

Go to the documentation of this file.
00001     
00002 /* Header FILES */
00003    
00004 #include "SUMA_suma.h"
00005 
00006 
00007 /*#define  DO_SCALE_RANGE   *//*!< scale node coordinates to 0 <--> 100. DO NOT USE IT, OBSOLETE*/
00008 #ifndef DO_SCALE_RANGE
00009    #define DO_SCALE 319.7   /*!< scale node coordinates by specified factor. Useful for tesscon coordinate system in iv files*/
00010 #endif
00011 
00012 #undef STAND_ALONE
00013 
00014 #if defined SUMA_Read_SpecFile_STAND_ALONE
00015 #define STAND_ALONE
00016 #elif defined SUMA_Load_Surface_Object_STAND_ALONE
00017 #define STAND_ALONE
00018 #elif defined SUMA_SurfaceMetrics_STAND_ALONE
00019 #define STAND_ALONE 
00020 #endif
00021 
00022 #ifdef STAND_ALONE
00023 /* these global variables must be declared even if they will not be used by this main */
00024 SUMA_SurfaceViewer *SUMAg_cSV; /*!< Global pointer to current Surface Viewer structure*/
00025 SUMA_SurfaceViewer *SUMAg_SVv; /*!< Global pointer to the vector containing the various Surface Viewer Structures */
00026 int SUMAg_N_SVv = 0; /*!< Number of SVs stored in SVv */
00027 SUMA_DO *SUMAg_DOv;   /*!< Global pointer to Displayable Object structure vector*/
00028 int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */
00029 SUMA_CommonFields *SUMAg_CF; /*!< Global pointer to structure containing info common to all viewers */
00030 #else
00031 extern SUMA_CommonFields *SUMAg_CF;
00032 extern SUMA_DO *SUMAg_DOv;
00033 extern SUMA_SurfaceViewer *SUMAg_SVv;
00034 extern int SUMAg_N_SVv; 
00035 extern int SUMAg_N_DOv;  
00036 #endif
00037 
00038 /* CODE */
00039 
00040    
00041 /*!
00042    \brief Function to write surface objects to disk in various formats
00043    ans = SUMA_Save_Surface_Object (void * F_name, SUMA_SurfaceObject *SO, SUMA_SO_File_Type SO_FT, SUMA_SO_File_Format SO_FF);
00044    \param F_name (void *)
00045          For SUMA_INVENTOR_GENERIC F_name is (char *) containing path (if any) and filename of surface
00046          For SUMA_SUREFIT F_name is (SUMA_SFname *) containing full topo and coord names, with path (if any)
00047          For SUMA_FREE_SURFER F_name is  (char *) name of .asc file (with path)
00048          For SUMA_VEC (a dumb ascii format), F_name is (SUMA_SFname *) containing the nodelist file in name_coord 
00049           and facesetlist file in name_topo (path included).
00050          For SUMA_PLY (char *) name of .ply file (with path)
00051    \param   SO_FT (SUMA_SO_File_Type) file type to be read (inventor, free surfer , Surefit )
00052    \param   SO_FF (SUMA_SO_File_Format) Ascii or Binary (only ascii at the moment, except for .ply files)
00053 
00054    \sa SUMA_Load_Surface_Object()
00055    
00056    NOTE:
00057    Vertex coordinates are written as in SO->NodeList
00058    The Volume Parent transformation is not undone. 
00059    For SureFit surfaces, the volume param shift is not undone.
00060 */
00061 SUMA_Boolean SUMA_Save_Surface_Object (void * F_name, SUMA_SurfaceObject *SO, SUMA_SO_File_Type SO_FT, SUMA_SO_File_Format SO_FF)
00062 {/*SUMA_Save_Surface_Object*/
00063    static char FuncName[]={"SUMA_Save_Surface_Object"};
00064    
00065    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00066    
00067    
00068    switch (SO_FT) {
00069       case SUMA_PLY:
00070          if (!SUMA_Ply_Write ((char *)F_name, SO)) {
00071             fprintf (SUMA_STDERR, "Error %s: Failed to write PLY surface.\n", FuncName);
00072             SUMA_RETURN (NOPE);
00073          }
00074          break;
00075       case SUMA_FREE_SURFER:
00076          if (SO_FF != SUMA_ASCII) {
00077             fprintf (SUMA_STDERR, "Error %s: Only ASCII supported for Free Surfer surfaces.\n", FuncName);
00078             SUMA_RETURN (NOPE);
00079          }
00080          if (!SUMA_FS_Write ((char *)F_name, SO, "#Output of SUMA_SurfaceConvert")) {
00081             fprintf (SUMA_STDERR, "Error %s: Failed to write FreeSurfer surface.\n", FuncName);
00082             SUMA_RETURN (NOPE);
00083          }
00084          break;
00085       case SUMA_SUREFIT:
00086          if (SO_FF != SUMA_ASCII) {
00087             fprintf (SUMA_STDERR, "Error %s: Only ASCII supported for SureFit surfaces.\n", FuncName);
00088             SUMA_RETURN (NOPE);
00089          }
00090          if (!SUMA_SureFit_Write ((SUMA_SFname *)F_name, SO)) {
00091             fprintf (SUMA_STDERR, "Error %s: Failed to write SureFit surface.\n", FuncName);
00092             SUMA_RETURN (NOPE);
00093          }
00094          break;
00095       case SUMA_VEC:
00096          if (SO_FF != SUMA_ASCII) {
00097             fprintf (SUMA_STDERR, "Error %s: Only ASCII supported for vec surfaces.\n", FuncName);
00098             SUMA_RETURN (NOPE);
00099          }
00100          if (!SUMA_VEC_Write ((SUMA_SFname *)F_name, SO)) {
00101             fprintf (SUMA_STDERR, "Error %s: Failed to write vec surface.\n", FuncName);
00102             SUMA_RETURN (NOPE);
00103          }
00104          break;
00105       case SUMA_INVENTOR_GENERIC:
00106          fprintf (SUMA_STDERR, "Error %s: Not ready to deal with inventor surfaces.\n", FuncName);
00107          SUMA_RETURN (NOPE);
00108          break;
00109       case SUMA_FT_NOT_SPECIFIED:
00110       default:
00111          fprintf (SUMA_STDERR, "Error %s: Bad surface type.\n", FuncName);
00112          SUMA_RETURN (NOPE);
00113    
00114    }
00115    
00116    SUMA_RETURN (YUP);
00117 }
00118    
00119 /*!
00120 \brief
00121       SO = SUMA_Load_Surface_Object ( SO_FileName, SO_FT, SO_FF, char *VolParName)
00122    
00123    
00124 Input paramters : 
00125 \param   (void *) SO_FileName 
00126          For SUMA_INVENTOR_GENERIC SO_FileName is (char *) containing path (if any) and filename of surface
00127          For SUMA_SUREFIT SO_FileName is (SUMA_SFname *) containing full topo and coord names, with path (if any)
00128          For SUMA_FREE_SURFER SO_FileName is  (char *) name of .asc file (with path)
00129          For SUMA_VEC (a dumb ascii format), SO_FileName is (SUMA_SFname *) containing the nodelist file in name_coord 
00130           and facesetlist file in name_topo (path included).
00131          For SUMA_PLY (char *) name of .ply file (with path)
00132 \param   SO_FT (SUMA_SO_File_Type) file type to be read (inventor, free surfer , Surefit )
00133 \param   SO_FF (SUMA_SO_File_Format) Ascii or Binary (only ascii at the moment, except for .ply files)
00134 \param   VolParName (char *) filename (+path) of parent volume, pass NULL for none
00135          If you pass NULL, no transformation is applied to the coordinates read. 
00136    
00137 \return   SO (SUMA_SurfaceObject *) Surface Object pointer
00138    The following fields are set (or initialized):
00139    SO->NodeDim
00140    SO->FaceSetDim
00141    SO->NodeList
00142    SO->FaceSetList
00143    SO->N_Node;
00144    SO->N_FaceSet;
00145    SO->Name;
00146    SO->FileType;
00147    SO->FileFormat
00148    SO->idcode_str
00149    SO->Center
00150    SO->aMaxDims
00151    SO->aMinDims
00152    SO->NodeNormList
00153    SO->FaceNormList
00154    SO->glar_NodeList
00155    SO->glar_FaceSetList
00156    SO->glar_FaceNormList
00157    SO->glar_NodeNormList
00158    SO->RotationWeight
00159    SO->ViewCenterWeight
00160    SO->ShowSelectedNode
00161    SO->ShowSelectedFaceSet
00162    SO->SelectedFaceSet
00163    SO->SelectedNode
00164    SO->NodeMarker
00165    SO->FaceSetMarker
00166    SO->VolPar
00167    SO->SUMA_VolPar_Aligned   
00168    
00169 \sa SUMA_IV*
00170 \sa SUMA_Save_Surface_Object()
00171 \sa SUMA_Align_to_VolPar()   
00172    
00173 ***/
00174 SUMA_SurfaceObject * SUMA_Load_Surface_Object (void *SO_FileName_vp, SUMA_SO_File_Type SO_FT, SUMA_SO_File_Format SO_FF, char *VolParName)
00175 {/*SUMA_Load_Surface_Object*/
00176    char FuncName[]={"SUMA_Load_Surface_Object"};
00177    char stmp[1000], *SO_FileName=NULL;
00178    SUMA_SFname *SF_FileName; 
00179    int k, ND, id;
00180    SUMA_SureFit_struct *SF;
00181    SUMA_FreeSurfer_struct *FS;
00182    SUMA_SurfaceObject *SO;
00183    SUMA_SURF_NORM SN;
00184    SUMA_Boolean LocalHead = NOPE;
00185    
00186    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00187 
00188    /* Allocate and initialize SUMA_SurfaceObject Pointer */
00189    SO = SUMA_Alloc_SurfObject_Struct(1);
00190    
00191    /* check if recognizable type */
00192    switch (SO_FT) {
00193       case SUMA_INVENTOR_GENERIC:
00194          break;
00195       case SUMA_SUREFIT:
00196          break;
00197       case SUMA_FREE_SURFER:
00198          break;
00199       case SUMA_PLY:
00200          break;
00201       case SUMA_VEC:
00202          break;
00203       default:
00204          SUMA_error_message(FuncName, "SO_FileType not supported", 0);
00205          SUMA_RETURN (NULL);
00206          break;
00207    } /* SO_FT*/
00208 
00209    
00210    /* proceed for reading */
00211    switch (SO_FT) {
00212       case SUMA_FT_NOT_SPECIFIED:
00213          fprintf (SUMA_STDERR,"Error %s: No File Type specified.\n", FuncName);
00214          SUMA_RETURN(NULL);
00215          
00216       case SUMA_PLY:
00217          if (!SUMA_Ply_Read ((char *)SO_FileName_vp, SO)) {
00218             fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Ply_Read.\n", FuncName);
00219             SUMA_RETURN(NULL);
00220          }
00221          SO->idcode_str = UNIQ_hashcode((char *)SO_FileName_vp); 
00222          
00223          /* change coordinates to align them with volparent data set, if possible */
00224          if (VolParName != NULL) {
00225             SO->VolPar = SUMA_VolPar_Attr (VolParName);
00226             if (SO->VolPar == NULL) {
00227                fprintf(SUMA_STDERR,"Error %s: Failed to load parent volume attributes.\n", FuncName);
00228             } else {
00229 
00230             if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
00231                else {
00232                   SO->SUMA_VolPar_Aligned = YUP;
00233                   /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
00234                }
00235          }
00236          } else { 
00237             SO->SUMA_VolPar_Aligned = NOPE;
00238          }
00239 
00240          break;
00241          
00242       case SUMA_INVENTOR_GENERIC:
00243          SO_FileName = (char *)SO_FileName_vp;
00244          /* You need to split name into path and name ... */
00245          fprintf(stdout,"%s\n", SO_FileName);
00246          SO->Name = SUMA_StripPath(SO_FileName);
00247          /* check for file existence  */
00248          if (!SUMA_filexists(SO_FileName)) {
00249             sprintf(stmp,"File %s not found!", SO_FileName);
00250             SUMA_error_message(FuncName, stmp, 0);
00251             SUMA_RETURN (NULL);
00252          }
00253          SO->FileType = SO_FT;
00254          SO->FileFormat = SO_FF;
00255          SO->NodeDim = 3; /* This must be automated */
00256          SO->NodeList = SUMA_IV_XYZextract (SO_FileName, &(SO->N_Node), 0);
00257          if (SO->NodeList == NULL) {
00258             SUMA_error_message(FuncName,"SUMA_IV_XYZextract failed!",0);
00259             SUMA_RETURN(NULL);
00260          }
00261          SO->FaceSetList = SUMA_IV_FaceSetsextract (SO_FileName, &(SO->N_FaceSet));
00262          if (SO->FaceSetList == NULL) {
00263             SUMA_error_message(FuncName,"SUMA_IV_FaceSetsextract failed!",0);
00264             SUMA_RETURN(NULL);
00265          }
00266          SO->FaceSetDim = 3; /*This must also be automated */
00267          SO->idcode_str = UNIQ_hashcode(SO_FileName); 
00268          break;
00269          
00270       case SUMA_FREE_SURFER:
00271          /* Allocate for FS */
00272          FS = (SUMA_FreeSurfer_struct *) SUMA_malloc(sizeof(SUMA_FreeSurfer_struct));   
00273          if (FS == NULL) {
00274             fprintf(SUMA_STDERR,"Error %s: Failed to allocate for FS\n", FuncName);
00275             SUMA_RETURN (NULL);
00276          }
00277          SO->Name = SUMA_StripPath((char*)SO_FileName_vp);
00278          SO->FileType = SO_FT;
00279          SO->FileFormat = SO_FF;
00280          SO->NodeDim = 3; /* This must be automated */
00281          /*read the surface file */
00282          if (!SUMA_FreeSurfer_Read ((char*)SO_FileName_vp, FS)) {
00283             fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_FreeSurfer_Read.\n", FuncName);
00284             SUMA_RETURN (NULL);
00285          }
00286          
00287          SUMA_Show_FreeSurfer (FS, NULL);
00288          /* save the juice and clean up the rest */
00289          SO->N_Node = FS->N_Node;
00290          /* Save the pointers to NodeList and FaceSetList and clear what is left of FS structure at the end */
00291          SO->NodeList = FS->NodeList;
00292          FS->NodeList = NULL;
00293          SO->FaceSetList = FS->FaceSetList;
00294          SO->N_FaceSet = FS->N_FaceSet;
00295          FS->FaceSetList = NULL;
00296          SO->FaceSetDim = 3; /*This must also be automated */
00297          
00298          
00299          /* change coordinates to align them with volparent data set, if possible */
00300          if (VolParName != NULL) {
00301             SO->VolPar = SUMA_VolPar_Attr (VolParName);
00302             if (SO->VolPar == NULL) {
00303                fprintf(SUMA_STDERR,"Error %s: Failed to load parent volume attributes.\n", FuncName);
00304             } else {
00305 
00306                if (!SUMA_Align_to_VolPar (SO, (void*)FS)) SO->SUMA_VolPar_Aligned = NOPE;
00307                   else {
00308                      SO->SUMA_VolPar_Aligned = YUP;
00309                      /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
00310                   }
00311          }
00312          } else { 
00313             SO->SUMA_VolPar_Aligned = NOPE;
00314          }
00315          
00316          /* free FS */
00317          if (!SUMA_Free_FreeSurfer (FS)) {
00318             fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Free_FreeSurfer.\n", FuncName);
00319             SUMA_RETURN (NULL);
00320          }
00321          
00322          /* create the IDcode */
00323          SO->idcode_str = UNIQ_hashcode(SO_FileName_vp);
00324          if (LocalHead) fprintf (SUMA_STDERR, "%s: Assigned idcode_str:%s:.\n", FuncName, SO->idcode_str);
00325          break;
00326          
00327       case SUMA_VEC:
00328          /* naming is with two files, similar to SureFit */
00329          SF_FileName = (SUMA_SFname *)SO_FileName_vp;      
00330          /* form the topo and the coord names */
00331          SO->Name_coord = SUMA_StripPath(SF_FileName->name_coord);
00332          SO->Name_topo = SUMA_StripPath(SF_FileName->name_topo);
00333          SO->FileType = SO_FT;
00334          SO->FileFormat = SO_FF;
00335          SO->NodeDim = 3; /* This must be automated */
00336          /* check for files */
00337          if (!SUMA_filexists(SF_FileName->name_coord)) {
00338             fprintf(SUMA_STDERR,"Error %s: Could not find %s\n", FuncName, SF_FileName->name_coord);
00339             SUMA_RETURN (NULL);
00340          }
00341          if (!SUMA_filexists(SF_FileName->name_topo)) {
00342             fprintf(SUMA_STDERR,"Error %s: Could not find %s\n", FuncName, SF_FileName->name_topo);
00343             SUMA_RETURN (NULL);
00344          }
00345          /* check number of elements */
00346          SO->N_Node = SUMA_float_file_size (SF_FileName->name_coord);
00347          if ((SO->N_Node %3)) {
00348             fprintf(SUMA_STDERR,"Error %s: Number of elements (%d) in vertex file %s is not multiple of 3.\n", 
00349                FuncName, SO->N_Node, SF_FileName->name_coord);
00350             SUMA_RETURN (NULL);
00351          }
00352          SO->N_Node /= 3;
00353          SO->N_FaceSet = SUMA_float_file_size (SF_FileName->name_topo);
00354          if ((SO->N_FaceSet % 3)) {
00355             fprintf(SUMA_STDERR,"Error %s: Number of elements (%d) in faceset file %s is not multiple of 3.\n", 
00356                FuncName, SO->N_Node, SF_FileName->name_topo);
00357             SUMA_RETURN (NULL);
00358          }
00359          SO->N_FaceSet /= 3;
00360          SO->FaceSetDim = 3;
00361          
00362          SO->NodeList = (float *)SUMA_calloc (SO->N_Node*SO->NodeDim, sizeof(float));
00363          SO->FaceSetList = (int *) SUMA_calloc (SO->N_FaceSet*SO->FaceSetDim, sizeof(int));
00364          if (!SO->NodeList || !SO->FaceSetList) {
00365             fprintf(SUMA_STDERR,"Error %s: Failed to allocate for NodeList or FaceSetList.\n", FuncName);
00366             if (SO->NodeList) SUMA_free(SO->NodeList);
00367             if (SO->FaceSetList) SUMA_free(SO->FaceSetList);
00368             SUMA_RETURN (NULL);
00369          }
00370          SUMA_Read_file (SO->NodeList, SF_FileName->name_coord, SO->N_Node*SO->NodeDim);
00371          SUMA_Read_dfile (SO->FaceSetList, SF_FileName->name_topo, SO->N_FaceSet*SO->FaceSetDim);
00372         
00373          
00374          sprintf (stmp, "%s%s", SF_FileName->name_coord, SF_FileName->name_topo);
00375          
00376          /* change coordinates to align them with volparent data set, if possible */
00377          if (VolParName != NULL) {
00378             SO->VolPar = SUMA_VolPar_Attr (VolParName);
00379             if (SO->VolPar == NULL) {
00380                fprintf(SUMA_STDERR,"Error %s: Failed to load parent volume attributes.\n", FuncName);
00381             } else {
00382 
00383             if (!SUMA_Align_to_VolPar (SO, NULL)) SO->SUMA_VolPar_Aligned = NOPE;
00384                else {
00385                   SO->SUMA_VolPar_Aligned = YUP;
00386                   /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
00387                }
00388          }
00389          } else { 
00390             SO->SUMA_VolPar_Aligned = NOPE;
00391          }
00392 
00393          SO->idcode_str = UNIQ_hashcode(stmp);
00394          break;
00395          
00396       case SUMA_SUREFIT:
00397          /* Allocate for SF */
00398          SF = (SUMA_SureFit_struct *) SUMA_malloc(sizeof(SUMA_SureFit_struct));   
00399          if (SF == NULL) {
00400             fprintf(SUMA_STDERR,"Error %s: Failed to allocate for SF\n", FuncName);
00401             SUMA_RETURN (NULL);
00402          }
00403          SF_FileName = (SUMA_SFname *)SO_FileName_vp;
00404          /* form the topo and the coord names */
00405          SO->Name_coord = SUMA_StripPath(SF_FileName->name_coord);
00406          SO->Name_topo = SUMA_StripPath(SF_FileName->name_topo);
00407          SO->FileType = SO_FT;
00408          SO->FileFormat = SO_FF;
00409          SO->NodeDim = 3; /* This must be automated */
00410          /*read the coordinate file */
00411          if (!SUMA_SureFit_Read_Coord (SF_FileName->name_coord, SF)) {
00412             fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SureFit_Read_Coord.\n", FuncName);
00413             SUMA_RETURN (NULL);
00414          }
00415          /* copy the pertinent data to SO */
00416          SO->N_Node = SF->N_Node;
00417          /* Save the pointers to NodeList and FaceSetList and clear what is left of SF structure at the end */
00418          SO->NodeList = SF->NodeList;
00419          SF->NodeList = NULL;
00420          
00421          /*read the topology file */
00422          if (!SUMA_SureFit_Read_Topo (SF_FileName->name_topo, SF)) {
00423             fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SureFit_Read_Topo.\n", FuncName);
00424             SUMA_RETURN (NULL);
00425          }
00426          /* read the param file */
00427          if (strlen(SF_FileName->name_param)){
00428             if (!SUMA_Read_SureFit_Param(SF_FileName->name_param, SF)) {
00429                fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SureFit_Read_Topo.\n", FuncName);
00430             }
00431          } else {
00432             if (VolParName != NULL) {
00433                fprintf(SUMA_STDERR,"Error %s: Volume Parent specified without .param file.\nParent Volume Alignment will not be done.", FuncName);
00434             }
00435          }
00436          
00437          /* copy the pertinent data to SO */
00438          SO->FaceSetList = SF->FaceSetList;
00439          SO->N_FaceSet = SF->N_FaceSet;
00440          SF->FaceSetList = NULL;
00441          SO->FaceSetDim = 3; /*This must also be automated */
00442 
00443          /* change coordinates to align them with volparent data set, if possible */
00444          if (VolParName != NULL && strlen(SF_FileName->name_param)) {
00445             SO->VolPar = SUMA_VolPar_Attr (VolParName);
00446             if (SO->VolPar == NULL) {
00447                fprintf(SUMA_STDERR,"Error %s: Failed to load parent volume attributes.\n", FuncName);
00448             } else {
00449                /*SUMA_Show_VolPar(SO->VolPar, NULL);*/
00450 
00451                if (!SUMA_Align_to_VolPar (SO, (void *)SF)) SO->SUMA_VolPar_Aligned = NOPE;
00452                   else SO->SUMA_VolPar_Aligned = YUP;
00453                }
00454          } else { 
00455             SO->SUMA_VolPar_Aligned = NOPE;
00456          }
00457          
00458          /* free SF */
00459          if (!SUMA_Free_SureFit (SF)) {
00460             fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Free_SureFit.\n", FuncName);
00461             SUMA_RETURN (NULL);
00462          }
00463          
00464          sprintf (stmp, "%s%s", SF_FileName->name_coord, SF_FileName->name_topo);
00465          SO->idcode_str = UNIQ_hashcode(stmp);
00466          break;
00467    } /* SO_FileType*/
00468 
00469    /* Calculate Min, Max, Mean */
00470    
00471    SUMA_MIN_MAX_SUM_VECMAT_COL (SO->NodeList, SO->N_Node, SO->NodeDim, SO->MinDims, SO->MaxDims, SO->Center);
00472      
00473    SO->Center[0] /= SO->N_Node;
00474    SO->Center[1] /= SO->N_Node;
00475    SO->Center[2] /= SO->N_Node;
00476 
00477    SUMA_MIN_VEC (SO->MinDims, 3, SO->aMinDims );
00478    SUMA_MAX_VEC (SO->MaxDims, 3, SO->aMaxDims);
00479 
00480    #ifdef DO_SCALE_RANGE
00481    { float tmpfact;
00482    /* Now do some scaling */
00483    tmpfact = (SO->aMaxDims - SO->aMinDims)/100;
00484    ND = SO->NodeDim;
00485    for (k=0; k < SO->N_Node; k++)
00486    {
00487       id = NodeDim * k;
00488       SO->NodeList[k] = (SO->NodeList[k] - SO->aMinDims)/tmpfact;
00489       SO->NodeList[k+1] = (SO->NodeList[k+1] - SO->aMinDims)/tmpfact;
00490       SO->NodeList[k+2] = (SO->NodeList[k+2] - SO->aMinDims)/tmpfact;
00491    }
00492    
00493    SO->Center[0] = (SO->Center[0] - SO->aMinDims)/tmpfact;
00494    SO->Center[1] = (SO->Center[1] - SO->aMinDims)/tmpfact;
00495    SO->Center[2] = (SO->Center[2] - SO->aMinDims)/tmpfact;
00496 
00497    SO->MinDims[0] = (SO->MinDims[0] - SO->aMinDims)/tmpfact;
00498    SO->MinDims[1] = (SO->MinDims[1] - SO->aMinDims)/tmpfact;
00499    SO->MinDims[2] = (SO->MinDims[2] - SO->aMinDims)/tmpfact;
00500 
00501    SO->MaxDims[0] = (SO->MaxDims[0] - SO->aMinDims)/tmpfact;
00502    SO->MaxDims[1] = (SO->MaxDims[1] - SO->aMinDims)/tmpfact;
00503    SO->MaxDims[2] = (SO->MaxDims[2] - SO->aMinDims)/tmpfact;
00504 
00505    SO->aMinDims = 0.0;
00506    SO->aMaxDims = 100.0;
00507    }
00508    #endif
00509    #ifdef DO_SCALE
00510    /* Now do some scaling */
00511    if ((SO->aMaxDims - SO->aMinDims) > SUMA_TESSCON_DIFF_FLAG) {
00512       fprintf (stdout,"\n\nWARNING %s:\n Assuming %s to be in tesscon units, scaling down by %f.\n\aYou might have abnormally large or small freakish vertex coordinates\n\n",\
00513          FuncName, SO_FileName, SUMA_TESSCON_TO_MM);
00514       ND = SO->NodeDim;
00515       for (k=0; k < SO->N_Node; k++)
00516       {
00517          id = ND * k;
00518          SO->NodeList[id] /= SUMA_TESSCON_TO_MM;
00519          SO->NodeList[id+1] /= SUMA_TESSCON_TO_MM;
00520          SO->NodeList[id+2] /= SUMA_TESSCON_TO_MM;
00521       }
00522 
00523       SO->Center[0] /= SUMA_TESSCON_TO_MM;
00524       SO->Center[1] /= SUMA_TESSCON_TO_MM;
00525       SO->Center[2] /= SUMA_TESSCON_TO_MM;
00526 
00527       SO->MinDims[0] /= SUMA_TESSCON_TO_MM;
00528       SO->MinDims[1] /= SUMA_TESSCON_TO_MM;
00529       SO->MinDims[2] /= SUMA_TESSCON_TO_MM;
00530 
00531       SO->MaxDims[0] /= SUMA_TESSCON_TO_MM;
00532       SO->MaxDims[1] /= SUMA_TESSCON_TO_MM;
00533       SO->MaxDims[2] /= SUMA_TESSCON_TO_MM;
00534 
00535       SO->aMinDims /= SUMA_TESSCON_TO_MM;
00536       SO->aMaxDims /= SUMA_TESSCON_TO_MM;
00537    } 
00538    #endif
00539     
00540    
00541    /* Calculate SurfaceNormals */
00542    SN = SUMA_SurfNorm(SO->NodeList,  SO->N_Node, SO->FaceSetList, SO->N_FaceSet );
00543    SO->NodeNormList = SN.NodeNormList;
00544    SO->FaceNormList = SN.FaceNormList;
00545 
00546    /*create the structures for GL rendering */
00547    /*The data is being duplicated at the moment and perhaps I should just stick with the 1D stuf */
00548    SO->glar_NodeList = (GLfloat *) SO->NodeList; /* just copy the pointer, not the data */
00549    SO->glar_FaceSetList = (GLint *) SO->FaceSetList; /* just copy the pointer, not the data */
00550    SO->glar_FaceNormList = (GLfloat *) SO->FaceNormList; /* just copy the pointer, not the data */
00551    SO->glar_NodeNormList = (GLfloat *) SO->NodeNormList; /* just copy the pointer, not the data */
00552 
00553    /* a surface object does contribute to the rotation center of the viewer displaying it */
00554    SO->RotationWeight = SO->N_Node;
00555    SO->ViewCenterWeight = SO->N_Node;
00556    
00557    /* No selections yet, but make the preps */
00558       SO->ShowSelectedNode = YUP;
00559       SO->ShowSelectedFaceSet = YUP;
00560       SO->SelectedFaceSet = -1;
00561       SO->SelectedNode = -1;
00562       /* create the ball object*/
00563       SO->NodeMarker = SUMA_Alloc_SphereMarker ();
00564       if (SO->NodeMarker == NULL) {
00565          fprintf(SUMA_STDERR,"Error%s: Could not allocate for SO->NodeMarker\n", FuncName);
00566          SUMA_Free_Surface_Object (SO);
00567          SUMA_RETURN (NULL);
00568       }
00569       /* create the FaceSetMarker object */
00570       SO->FaceSetMarker = SUMA_Alloc_FaceSetMarker();
00571       if (SO->FaceSetMarker == NULL) {
00572          fprintf(SUMA_STDERR,"Error%s: Could not allocate for SO->FaceSetMarker\n", FuncName);
00573          SUMA_Free_Surface_Object (SO);
00574          SUMA_RETURN (NULL);
00575       }
00576    SUMA_RETURN (SO);
00577    
00578 }/*SUMA_Load_Surface_Object*/
00579 
00580  
00581 /*!
00582    SUMA_Boolean SUMA_ParseLHS_RHS (char *s, char *lhs, char *rhs)
00583    
00584    Parses S of the form "lhs = rhs" 
00585    blanks are necessary around the = sign
00586    s, lhs and rhs must be allocated for
00587    
00588    \param s (char *) "joe = fred"
00589    \param lhs (char *) "joe"
00590    \param rhs (char *) returned "fred"
00591    \ret YUP/NOPE for goodness, badness
00592    
00593 */
00594 SUMA_Boolean SUMA_ParseLHS_RHS (char *s, char *lhs, char *rhs)
00595 {
00596    static char FuncName[]={"SUMA_ParseLHS_RHS"};
00597    char *st;
00598 
00599    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00600 
00601    if (s == NULL) {
00602       fprintf(SUMA_STDERR,"Error %s: NULL s\n", FuncName);
00603       SUMA_RETURN (NOPE);
00604    }
00605    st = strtok(s, " \0=");
00606    if (SUMA_iswordin (st,"=") == 1) { /* no blanks it seems */
00607       /*fprintf(SUMA_STDERR,"NO BLANK, st:%s\n", st);*/
00608       fprintf(SUMA_STDERR,"Error %s: Bad file format. Perhaps no blanks before = sign after LHS argument %s.\n", FuncName, lhs);
00609       SUMA_RETURN (NOPE);
00610    } else { /* skip the next blank to = */
00611       st = strtok(NULL, " \0=");
00612       if (SUMA_iswordin (st,"=")!=1) {
00613          fprintf(SUMA_STDERR,"Error %s: Bad file format. Perhaps no blanks around = after LHS argument %s.\n", FuncName, lhs);
00614          SUMA_RETURN (NOPE);
00615       }
00616    }
00617    /* get the rhs */
00618    st = strtok(NULL, " \0=");
00619    if (st == NULL) {
00620       fprintf(SUMA_STDERR,"Error %s: Bad file format. Perhaps no blanks after = after LHS argument %s.\n", FuncName, lhs);
00621       SUMA_RETURN (NOPE);
00622    } else {
00623       sprintf(rhs,"%s", st);
00624       /*fprintf(SUMA_STDERR,"RHS: %s\n", rhs);*/
00625    }
00626    SUMA_RETURN (YUP); 
00627 }
00628 
00629 /*! 
00630    Function to read the surface specs file.
00631    \param fname (char *) name of the specs file
00632    \param Spec (SUMA_SurfSpecFile *) pre-allocated pointer to SUMA_SurfSpecFile structure )
00633    \ret YUP, good, NOPE, not good
00634 */
00635 SUMA_Boolean SUMA_Read_SpecFile (char *f_name, SUMA_SurfSpecFile * Spec)
00636 {/* SUMA_Read_SpecFile */
00637    static char FuncName[]={"SUMA_Read_SpecFile"};
00638    char s[SUMA_MAX_DIR_LENGTH], stmp[SUMA_MAX_DIR_LENGTH],  stmp2[SUMA_MAX_DIR_LENGTH], c;
00639    int ex, skp, evl, i;
00640    FILE *sf_file;
00641    SUMA_FileName SpecName;
00642    SUMA_Boolean OKread_SurfaceFormat, OKread_SurfaceType, OKread_SureFitTopo, OKread_SureFitCoord;
00643    SUMA_Boolean OKread_MappingRef, OKread_SureFitVolParam, OKread_FreeSurferSurface, OKread_InventorSurface;
00644    SUMA_Boolean OKread_Group, OKread_State, OKread_EmbedDim, OKread_SurfaceVolume, OKread_SurfaceLabel;
00645    char DupWarn[]={"Bad format in specfile (you may need a NewSurface line). Duplicate specification of"};
00646    char NewSurfWarn[]={"Bad format in specfile. You must start with NewSurface line before any other field."};
00647 
00648    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00649 
00650    /*make sure file is there */
00651    if (!SUMA_filexists(f_name)) {
00652       fprintf(SUMA_STDERR,"Error %s: File %s does not exist or cannot be read.\n", FuncName, f_name);
00653       SUMA_RETURN (NOPE);
00654    }
00655    Spec->N_Surfs = 0;
00656    
00657    /* set the path for the spec file */
00658    SpecName = SUMA_StripPath (f_name);
00659    if (strlen(SpecName.Path) > SUMA_MAX_DIR_LENGTH-1) {
00660       fprintf(SUMA_STDERR,"Error %s: Path of specfile > %d charcters.\n", FuncName, SUMA_MAX_DIR_LENGTH-1);
00661       SUMA_RETURN (NOPE);
00662    }
00663    sprintf(Spec->SpecFilePath,"%s", SpecName.Path);
00664    /* free SpecName since it's not used elsewhere */
00665    if (SpecName.Path) SUMA_free(SpecName.Path);
00666    if (SpecName.FileName) SUMA_free(SpecName.FileName);
00667 
00668    /*read the thing*/
00669    sf_file = fopen (f_name,"r");
00670    if (sf_file == NULL)
00671       {
00672          fprintf(SUMA_STDERR,"Error %s: Could not open file for read\n", FuncName);
00673          SUMA_RETURN (NOPE);
00674       }
00675    
00676    /*read until you find not a comment */
00677  
00678    /* read the first line, skipping leading space */
00679    do {
00680       ex = fscanf (sf_file,"%c",&c);
00681    } while (ex != EOF && isspace(c));
00682    
00683    i=0;
00684    while (ex != EOF && c != '\n') {   
00685          s[i] = c; ++i;
00686       ex = fscanf (sf_file,"%c",&c);
00687    }
00688    s[i] = '\0';
00689    /*fprintf(SUMA_STDERR,"Read %s\n", s);*/
00690    OKread_Group = YUP; /* it is OK to read a group before a new surface is declared */
00691    OKread_SurfaceFormat = OKread_SurfaceType = OKread_SureFitTopo = OKread_SureFitCoord = NOPE;
00692    OKread_MappingRef = OKread_SureFitVolParam = OKread_FreeSurferSurface = OKread_InventorSurface = NOPE;
00693    OKread_State = OKread_EmbedDim = OKread_SurfaceVolume = OKread_SurfaceLabel = NOPE ;
00694    
00695    Spec->StateList[0] = '\0';
00696    Spec->Group[0][0] = '\0';
00697    Spec->N_Surfs = Spec->N_States = Spec->N_Groups = 0;
00698    while (ex !=EOF) {
00699       evl = SUMA_iswordin (s,"#");
00700       if (evl != 1) { /* not a comment */
00701          /*fprintf(SUMA_STDERR,"Not a comment: %s\n", s);*/
00702          skp = 0;
00703          sprintf(stmp,"NewSurface");
00704          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00705             if(Spec->N_Surfs >= SUMA_MAX_N_SURFACE_SPEC) {
00706                fprintf(SUMA_STDERR,"Error %s: Cannot read in more than %d new surfaces.\n", FuncName, SUMA_MAX_N_SURFACE_SPEC);
00707                SUMA_RETURN (NOPE);
00708             }
00709             Spec->N_Surfs += 1;
00710             /*fprintf(SUMA_STDERR,"Found New Surface, N = %d\n", Spec->N_Surfs);*/
00711             /* initialize some of the fields */
00712             if (Spec->N_Surfs == 1) { /* first surface, initialize to empty */
00713                sprintf(Spec->SurfaceFormat[Spec->N_Surfs-1],"ASCII");
00714                Spec->SurfaceType[Spec->N_Surfs-1][0] = '\0';
00715                Spec->SureFitTopo[Spec->N_Surfs-1][0] = Spec->SureFitCoord[Spec->N_Surfs-1][0] = '\0';
00716                Spec->MappingRef[Spec->N_Surfs-1][0] = '\0';
00717                Spec->SureFitVolParam[Spec->N_Surfs-1][0] = '\0';
00718                Spec->FreeSurferSurface[Spec->N_Surfs-1][0] = Spec->InventorSurface[Spec->N_Surfs-1][0] = '\0';
00719                Spec->State[Spec->N_Surfs-1][0] = '\0';
00720                Spec->IDcode[Spec->N_Surfs-1] = NULL; /* this field is set in LoadSpec function */
00721                Spec->EmbedDim[Spec->N_Surfs-1] = 3;
00722                Spec->VolParName[Spec->N_Surfs-1][0] = '\0';
00723                Spec->SurfaceLabel[Spec->N_Surfs-1][0] = '\0';
00724             } else { 
00725                /* make sure important fields have been filled */
00726                if (Spec->SurfaceType[Spec->N_Surfs-2][0] == '\0') {
00727                   fprintf(SUMA_STDERR,"Error %s: Failed to specify surface type for surface %d\n", FuncName, Spec->N_Surfs-2);
00728                   SUMA_RETURN (NOPE);
00729                }
00730                /* initilize SOME of the fields to previous one */
00731                strcpy(Spec->SurfaceFormat[Spec->N_Surfs-1], Spec->SurfaceFormat[Spec->N_Surfs-2]);
00732                strcpy(Spec->SurfaceType[Spec->N_Surfs-1], Spec->SurfaceType[Spec->N_Surfs-2]);
00733                strcpy(Spec->SureFitTopo[Spec->N_Surfs-1], Spec->SureFitTopo[Spec->N_Surfs-2]);
00734                strcpy(Spec->MappingRef[Spec->N_Surfs-1], Spec->MappingRef[Spec->N_Surfs-2]);
00735                strcpy(Spec->SureFitVolParam[Spec->N_Surfs-1], Spec->SureFitVolParam[Spec->N_Surfs-2]);
00736                strcpy(Spec->VolParName[Spec->N_Surfs-1],Spec->VolParName[Spec->N_Surfs-2]);
00737                Spec->IDcode[Spec->N_Surfs-1] = NULL; /* this field is set in LoadSpec function */
00738                Spec->SurfaceLabel[Spec->N_Surfs-1][0] = '\0';
00739                strcpy(Spec->Group[Spec->N_Surfs-1], Spec->Group[Spec->N_Surfs-2]);
00740                strcpy(Spec->State[Spec->N_Surfs-1], Spec->State[Spec->N_Surfs-2]);
00741                Spec->EmbedDim[Spec->N_Surfs-1] = Spec->EmbedDim[Spec->N_Surfs-2];
00742                /* only Spec->SureFitCoord, Spec->FreeSurferSurface or Spec->InventorSurface MUST be specified with a new surface */
00743             } 
00744             OKread_SurfaceFormat = OKread_SurfaceType = OKread_SureFitTopo = OKread_SureFitCoord = YUP;
00745             OKread_MappingRef = OKread_SureFitVolParam = OKread_FreeSurferSurface = OKread_InventorSurface = YUP;
00746             OKread_Group = OKread_State = OKread_EmbedDim = OKread_SurfaceLabel = OKread_SurfaceVolume = YUP;
00747             skp = 1;
00748          }
00749          
00750          sprintf(stmp,"StateDef");
00751          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00752             /* found a state definition, parse it */
00753             if (!SUMA_ParseLHS_RHS (s, stmp, Spec->State[Spec->N_Surfs-1])) {
00754                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00755                SUMA_RETURN (NOPE);
00756             }
00757             if (Spec->N_States == 0) {
00758                /* first state, add it to the list of states */
00759                sprintf(Spec->StateList, "%s|", Spec->State[Spec->N_Surfs-1]);
00760                Spec->N_States += 1;
00761             } else  {
00762                if (strcmp(Spec->StateList, Spec->State[Spec->N_Surfs-1]) == 0) {
00763                   /* it's a duplicate, complain and get outa here */
00764                   fprintf(SUMA_STDERR,"Error %s: Duplicate StateDef (%s).\n", FuncName, Spec->State[Spec->N_Surfs-1]);
00765                   SUMA_RETURN (NOPE);
00766                } else {
00767                   /* a new one, add it to the list and increment States counter */
00768                   sprintf(Spec->StateList, "%s%s|", Spec->StateList, Spec->State[Spec->N_Surfs-1]);
00769                   Spec->N_States += 1;
00770                }
00771             }
00772             skp = 1;
00773          }
00774          
00775          sprintf(stmp,"Group");
00776          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00777             /* found a state definition, parse it */
00778             /*fprintf(SUMA_STDERR,"%s: Found %s.\n", FuncName, stmp);*/
00779             if (Spec->N_Surfs < 1) { /* no surfaces have been defined yet, group goes for all */
00780                if (!SUMA_ParseLHS_RHS (s, stmp, Spec->Group[0])) {
00781                   fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00782                   SUMA_RETURN (NOPE);
00783                }
00784             }
00785             else {
00786                if (!SUMA_ParseLHS_RHS (s, stmp, Spec->Group[Spec->N_Surfs-1])) {
00787                   fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00788                   SUMA_RETURN (NOPE);
00789                }
00790             }
00791 
00792             Spec->N_Groups += 1;
00793             
00794             if (!OKread_Group) {
00795                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00796                SUMA_RETURN (NOPE);
00797             } else {
00798                OKread_Group = NOPE;
00799             }
00800             skp = 1;
00801          }
00802          
00803          sprintf(stmp,"EmbedDimension");
00804          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00805             /* found surface embedding dimension, parse it */
00806             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
00807                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00808                SUMA_RETURN (NOPE);
00809             }
00810             Spec->EmbedDim[Spec->N_Surfs-1] = atoi(stmp2);
00811             if (Spec->EmbedDim[Spec->N_Surfs-1] < 2 || Spec->EmbedDim[Spec->N_Surfs-1] > 3) {
00812                fprintf(SUMA_STDERR,"Error %s: Bad Embedding dimension %d. Only 2 and 3 allowed.\n", \
00813                   FuncName, Spec->EmbedDim[Spec->N_Surfs-1]);
00814                SUMA_RETURN (NOPE); 
00815             }
00816             if (!OKread_EmbedDim) {
00817                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00818                SUMA_RETURN (NOPE);
00819             } else  {
00820                OKread_EmbedDim = NOPE;
00821             }
00822             skp = 1;
00823          }
00824             
00825          sprintf(stmp,"SurfaceState");
00826          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00827             /* found surface state, parse it */
00828             if (!SUMA_ParseLHS_RHS (s, stmp, Spec->State[Spec->N_Surfs-1])) {
00829                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00830                SUMA_RETURN (NOPE);
00831             }
00832             /* make sure it is in the StateList */
00833             if (SUMA_iswordin (Spec->StateList, Spec->State[Spec->N_Surfs-1]) != 1) {
00834                fprintf(SUMA_STDERR,"Error %s: State %s was not predefined in StateDef.\nStateDef List (| delimited) = %s \n",\
00835                 FuncName, Spec->State[Spec->N_Surfs-1], Spec->StateList);
00836                SUMA_RETURN (NOPE);
00837             }
00838             if (!OKread_State) {
00839                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00840                SUMA_RETURN (NOPE);
00841             } else  {
00842                OKread_State = NOPE;
00843             }
00844             skp = 1;
00845          }
00846          
00847          sprintf(stmp,"SurfaceFormat");
00848          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00849             if (Spec->N_Surfs < 1) {
00850                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00851                SUMA_RETURN (NOPE);
00852             }
00853             /*fprintf(SUMA_STDERR,"Found %s: ", stmp);*/
00854             
00855             if (!SUMA_ParseLHS_RHS (s, stmp, Spec->SurfaceFormat[Spec->N_Surfs-1])) {
00856                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00857                SUMA_RETURN (NOPE);
00858             }
00859             
00860             if (!OKread_SurfaceFormat) {
00861                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00862                SUMA_RETURN (NOPE);
00863             } else {
00864                OKread_SurfaceFormat = NOPE;
00865             }
00866             skp = 1;
00867             /*fprintf(SUMA_STDERR,"%s\n", Spec->SurfaceFormat[Spec->N_Surfs-1]);*/
00868          }
00869          
00870          sprintf(stmp,"SurfaceType");
00871          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00872             if (Spec->N_Surfs < 1) {
00873                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00874                SUMA_RETURN (NOPE);
00875             }
00876             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
00877             if (!SUMA_ParseLHS_RHS (s, stmp, Spec->SurfaceType[Spec->N_Surfs-1])) {
00878                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00879                SUMA_RETURN (NOPE);
00880             }
00881             if (!OKread_SurfaceType) {
00882                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00883                SUMA_RETURN (NOPE);
00884             } else {
00885                OKread_SurfaceType = NOPE;
00886             }
00887             skp = 1;
00888          }
00889          
00890          sprintf(stmp,"SureFitTopo");
00891          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00892             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
00893             if (Spec->N_Surfs < 1) {
00894                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00895                SUMA_RETURN (NOPE);
00896             }
00897             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
00898                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00899                SUMA_RETURN (NOPE);
00900             }
00901             sprintf(Spec->SureFitTopo[Spec->N_Surfs-1], "%s%s", Spec->SpecFilePath, stmp2);
00902             if (!OKread_SureFitTopo) {
00903                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00904                SUMA_RETURN (NOPE);
00905             } else {
00906                OKread_SureFitTopo = NOPE;
00907             }
00908             skp = 1;
00909          }
00910          
00911          sprintf(stmp,"SureFitCoord");
00912          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00913             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
00914             if (Spec->N_Surfs < 1) {
00915                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00916                SUMA_RETURN (NOPE);
00917             }
00918             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
00919                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00920                SUMA_RETURN (NOPE);
00921             }
00922             sprintf (Spec->SureFitCoord[Spec->N_Surfs-1], "%s%s", Spec->SpecFilePath, stmp2);
00923             
00924             if (!OKread_SureFitCoord) {
00925                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00926                SUMA_RETURN (NOPE);
00927             } else {
00928                OKread_SureFitCoord = NOPE;
00929             }
00930             skp = 1;
00931          }
00932          
00933          sprintf(stmp,"MappingRef");
00934          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00935             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
00936             if (Spec->N_Surfs < 1) {
00937                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00938                SUMA_RETURN (NOPE);
00939             }
00940             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
00941                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00942                SUMA_RETURN (NOPE);
00943             }
00944             sprintf (Spec->MappingRef[Spec->N_Surfs-1], "%s%s", Spec->SpecFilePath, stmp2);
00945             if (!OKread_MappingRef) {
00946                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00947                SUMA_RETURN (NOPE);
00948             } else {
00949                OKread_MappingRef = NOPE;
00950             }
00951             skp = 1;
00952          }
00953          
00954          sprintf(stmp,"SureFitVolParam");
00955          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00956             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
00957             if (Spec->N_Surfs < 1) {
00958                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00959                SUMA_RETURN (NOPE);
00960             }
00961             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
00962                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00963                SUMA_RETURN (NOPE);
00964             }
00965             sprintf (Spec->SureFitVolParam[Spec->N_Surfs-1], "%s%s", Spec->SpecFilePath, stmp2);
00966             
00967             if (!OKread_SureFitVolParam) {
00968                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00969                SUMA_RETURN (NOPE);
00970             } else {
00971                OKread_SureFitVolParam = NOPE;
00972             }
00973             skp = 1;
00974          }
00975          
00976          sprintf(stmp,"FreeSurferSurface");
00977          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00978             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
00979             if (Spec->N_Surfs < 1) {
00980                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
00981                SUMA_RETURN (NOPE);
00982             }
00983             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
00984                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
00985                SUMA_RETURN (NOPE);
00986             }
00987             sprintf (Spec->FreeSurferSurface[Spec->N_Surfs-1], "%s%s", Spec->SpecFilePath, stmp2);
00988             if (!OKread_FreeSurferSurface) {
00989                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
00990                SUMA_RETURN (NOPE);
00991             } else {
00992                OKread_FreeSurferSurface = NOPE;
00993             }
00994             skp = 1;
00995          }
00996          
00997          sprintf(stmp,"InventorSurface");
00998          if (!skp && SUMA_iswordin (s, stmp) == 1) {
00999             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
01000             if (Spec->N_Surfs < 1) {
01001                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
01002                SUMA_RETURN (NOPE);
01003             }
01004             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
01005                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
01006                SUMA_RETURN (NOPE);
01007             }
01008             sprintf(Spec->InventorSurface[Spec->N_Surfs-1], "%s%s", Spec->SpecFilePath, stmp2);
01009             
01010             if (!OKread_InventorSurface) {
01011                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
01012                SUMA_RETURN (NOPE);
01013             } else {
01014                OKread_InventorSurface = NOPE;
01015             }
01016             skp = 1;
01017          }
01018 
01019          sprintf(stmp,"SurfaceVolume");
01020          if (!skp && SUMA_iswordin (s, stmp) == 1) {
01021             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
01022             if (Spec->N_Surfs < 1) {
01023                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
01024                SUMA_RETURN (NOPE);
01025             }
01026             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
01027                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
01028                SUMA_RETURN (NOPE);
01029             }
01030             
01031             fprintf(SUMA_STDOUT,"Warning %s: Found SurfaceVolume in Spec File, Name must include path to volume.\n", FuncName);
01032             
01033             sprintf(Spec->VolParName[Spec->N_Surfs-1], "%s",  stmp2);
01034             
01035             if (!OKread_SurfaceVolume) {
01036                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
01037                SUMA_RETURN (NOPE);
01038             } else {
01039                OKread_SurfaceVolume = NOPE;
01040             }
01041             skp = 1;
01042          }
01043          
01044          sprintf(stmp,"SurfaceLabel");
01045          if (!skp && SUMA_iswordin (s, stmp) == 1) {
01046             /*fprintf(SUMA_STDERR,"Found %s\n", stmp);*/
01047             if (Spec->N_Surfs < 1) {
01048                fprintf(SUMA_STDERR,"Error %s: %s\n", FuncName, NewSurfWarn);
01049                SUMA_RETURN (NOPE);
01050             }
01051             if (!SUMA_ParseLHS_RHS (s, stmp, stmp2)) {
01052                fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ParseLHS_RHS.\n", FuncName);
01053                SUMA_RETURN (NOPE);
01054             }
01055                         
01056             sprintf(Spec->SurfaceLabel[Spec->N_Surfs-1], "%s",  stmp2);
01057             
01058             if (!OKread_SurfaceLabel) {
01059                fprintf(SUMA_STDERR,"Error %s: %s %s\n", FuncName, DupWarn, stmp);
01060                SUMA_RETURN (NOPE);
01061             } else {
01062                OKread_SurfaceLabel = NOPE;
01063             }
01064             skp = 1;
01065          }
01066          
01067          if (!skp) {
01068             fprintf(SUMA_STDERR,"Error %s: Your spec file contains uncommented gibberish:\n%s\nPlease deal with it.\n", \
01069             FuncName, s);
01070             SUMA_RETURN (NOPE);
01071          }
01072       } else {/* not not a comment */
01073          /*fprintf(SUMA_STDERR,"A comment: %s\n", s);*/
01074       }
01075 
01076       /* read the next line */
01077       do {
01078          ex = fscanf (sf_file,"%c",&c);
01079       } while (ex!=EOF && isspace(c));
01080       i=0;
01081       while (ex != EOF && c != '\n') {   
01082          s[i] = c; ++i;
01083          ex = fscanf (sf_file,"%c",&c);
01084       }
01085       s[i] = '\0';
01086       /*fprintf(SUMA_STDERR,"Read %s\n", s); */
01087    }
01088    fclose (sf_file);
01089    /* make sure last entry was good */
01090    if (Spec->SurfaceType[Spec->N_Surfs-1][0] == '\0') {
01091       fprintf(SUMA_STDERR,"Error %s: Failed to specify surface type for surface %d\n", FuncName, Spec->N_Surfs-1);
01092       SUMA_RETURN (NOPE);
01093    }
01094 
01095    SUMA_RETURN (YUP); 
01096 }/* SUMA_Read_SpecFile */
01097 
01098 /*! 
01099    Loads the surfaces specified in Spec and stores them in DOv
01100 */
01101 SUMA_Boolean SUMA_LoadSpec (SUMA_SurfSpecFile *Spec, SUMA_DO *dov, int *N_dov, char *VolParName)
01102 {/* SUMA_LoadSpec */
01103    static char FuncName[]={"SUMA_LoadSpec"};
01104    int i, k;
01105    char *tmpid, *tmpVolParName = NULL;
01106    SUMA_SurfaceObject *SO=NULL;
01107    SUMA_Axis *EyeAxis;
01108    SUMA_SFname *SF_name;
01109    SUMA_OVERLAYS *NewColPlane=NULL;
01110    SUMA_INODE *NewColPlane_Inode = NULL;
01111    SUMA_Boolean brk, SurfIn=NOPE;
01112    
01113    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01114 
01115    fprintf (SUMA_STDERR, "Expecting to read %d surfaces.\n", Spec->N_Surfs);
01116    for (i=0; i<Spec->N_Surfs; ++i) { /* first loop across mappable surfaces */
01117       /*locate and load all Mappable surfaces */
01118       if (SUMA_iswordin(Spec->MappingRef[i],"SAME") == 1) { /* Mappable surfaces */
01119          fprintf (SUMA_STDERR,"\nvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
01120          fprintf (SUMA_STDERR,"Surface #%d (directly mappable), loading ...\n",i);
01121 
01122          if (Spec->VolParName[i][0] != '\0') {
01123             fprintf (SUMA_STDOUT, "Warning %s: Using Volume Parent Specified in Spec File. This overrides -sv option.\n", FuncName);
01124             tmpVolParName = Spec->VolParName[i];
01125          }else {
01126             tmpVolParName = VolParName;
01127          }
01128 
01129          brk = NOPE;
01130          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "SureFit") == 1) {/* load surefit surface */
01131             SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
01132             sprintf(SF_name->name_coord,"%s", Spec->SureFitCoord[i]); ;
01133             sprintf(SF_name->name_topo,"%s", Spec->SureFitTopo[i]); 
01134             if (!strlen(Spec->SureFitVolParam[i])) { /* initialize to empty string */
01135                SF_name->name_param[0] = '\0'; 
01136             }
01137             else {
01138                sprintf(SF_name->name_param,"%s", Spec->SureFitVolParam[i]);
01139             }
01140 
01141             /* Load The Surface */
01142             if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1) {
01143                SO = SUMA_Load_Surface_Object ((void *)SF_name, SUMA_SUREFIT, SUMA_ASCII, tmpVolParName);
01144             } else {
01145                fprintf(SUMA_STDERR,"Error %s: Only ASCII surfaces can be read for now.\n", FuncName);
01146                SUMA_RETURN (NOPE);
01147             }
01148             if (SO == NULL)   {
01149                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01150                SUMA_RETURN(NOPE);
01151             }
01152 
01153             SUMA_free(SF_name); 
01154 
01155             SurfIn = YUP;         
01156             brk = YUP;
01157          }/* load surefit surface */ 
01158          
01159          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "FreeSurfer") == 1) {/* load FreeSurfer surface */
01160             
01161             if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1)
01162                SO = SUMA_Load_Surface_Object ((void *)Spec->FreeSurferSurface[i], SUMA_FREE_SURFER, SUMA_ASCII, tmpVolParName);
01163             else {
01164                fprintf(SUMA_STDERR,"Error %s: Only ASCII surfaces can be read for now.\n", FuncName);
01165                SUMA_RETURN(NOPE);
01166             }
01167             if (SO == NULL)   {
01168                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01169                SUMA_RETURN(NOPE);
01170             }
01171             SurfIn = YUP;
01172             brk = YUP;
01173          } /* load FreeSurfer surface */
01174 
01175          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "Ply") == 1) {/* load Ply format surface */
01176             
01177             SO = SUMA_Load_Surface_Object ((void *)Spec->FreeSurferSurface[i], SUMA_PLY, SUMA_FF_NOT_SPECIFIED, tmpVolParName);
01178             
01179             if (SO == NULL)   {
01180                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01181                SUMA_RETURN(NOPE);
01182             }
01183             SurfIn = YUP;
01184             brk = YUP;
01185          } /* load Ply format surface */
01186          
01187          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "GenericInventor") == 1) {/* load generic inventor format surface */
01188             if (tmpVolParName != NULL) {
01189                fprintf(SUMA_STDERR,"Error %s: Sorry, but Parent volumes are not supported for generic inventor surfaces.\n", FuncName);
01190                SUMA_RETURN (NOPE);
01191             }
01192             if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1)
01193                SO = SUMA_Load_Surface_Object ((void *)Spec->InventorSurface[i], SUMA_INVENTOR_GENERIC, SUMA_ASCII, NULL);
01194             else {
01195                fprintf(SUMA_STDERR,"Error %s: Only ASCII surfaces can be read for now.\n", FuncName);
01196                SUMA_RETURN(NOPE);
01197             }
01198             if (SO == NULL)   {
01199                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01200                SUMA_RETURN(NOPE);
01201             }
01202             SurfIn = YUP;
01203 
01204             brk = YUP;
01205          }
01206          
01207          if (!brk) {
01208             fprintf(SUMA_STDERR,"Error %s: Unknown SurfaceFormat %s.\n", FuncName, Spec->SurfaceType[i]);
01209             SUMA_RETURN(NOPE);
01210          }
01211          
01212          if (!SurfIn) {
01213             fprintf(SUMA_STDERR,"Error %s: Failed to read input surface.\n", FuncName);
01214             SUMA_RETURN(NOPE);
01215          }
01216 
01217          /* store the surface's idcode pointer for use in non mappable bloc below */
01218             Spec->IDcode[i] = SO->idcode_str;
01219 
01220          /* set its MappingRef id to its own */
01221             SO->MapRef_idcode_str = (char *)SUMA_calloc(strlen(SO->idcode_str)+1, sizeof(char));
01222             if (SO->MapRef_idcode_str == NULL) {
01223                fprintf(SUMA_STDERR,"Error %s: Failed to allocate for SO->MapRef_idcode_str. That is pretty bad.\n", FuncName);
01224                SUMA_RETURN (NOPE);
01225             }
01226             SO->MapRef_idcode_str = strcpy(SO->MapRef_idcode_str, SO->idcode_str);
01227 
01228          /* check if surface read was unique 
01229             it's inefficient to check after the surface is read, but idcode is generated in the read routine 
01230             and users should not be making this mistake too often */
01231             if (SUMA_existSO (SO->idcode_str, dov, *N_dov)) {
01232                fprintf(SUMA_STDERR,"Error %s: Surface %d is specifed more than once, multiple copies ignored.\n", FuncName, i);
01233                /* free SO */
01234                if (!SUMA_Free_Surface_Object (SO)) {
01235                   fprintf(SUMA_STDERR,"Error %s: Error freeing SO.\n", FuncName);
01236                   SUMA_RETURN (NOPE);
01237                }
01238                SurfIn = NOPE;
01239             }
01240          
01241          /* if the surface is loaded OK, and it has not been loaded previously, register it */
01242          if (SurfIn) {
01243             if (!SUMA_SurfaceMetrics (SO, "Convexity, EdgeList, MemberFace", NULL)) {
01244                fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
01245                SUMA_RETURN (NOPE);
01246             }
01247             #if SUMA_CHECK_WINDING
01248             if (!SUMA_SurfaceMetrics (SO, "CheckWind", NULL)) {
01249                fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
01250                SUMA_RETURN (NOPE);
01251             }
01252             #endif
01253    
01254 
01255             /* Now create the color map that goes with Cx */
01256             { /* MOST OF THIS BLOCK SHOULD BE TURNED TO A FUNCTION */
01257                SUMA_COLOR_MAP *CM;
01258                SUMA_SCALE_TO_MAP_OPT * OptScl;
01259                SUMA_STANDARD_CMAP MapType;
01260                SUMA_COLOR_SCALED_VECT * SV;
01261                float ClipRange[2], *Vsort;
01262                
01263                /* create the color mapping of Cx (SUMA_CMAP_MATLAB_DEF_BGYR64)*/
01264                CM = SUMA_GetStandardMap (SUMA_CMAP_nGRAY20);
01265                if (CM == NULL) {
01266                   fprintf (SUMA_STDERR,"Error %s: Could not get standard colormap.\n", FuncName); 
01267                   SUMA_RETURN (NOPE);
01268                }
01269 
01270                /* get the options for creating the scaled color mapping */
01271                OptScl = SUMA_ScaleToMapOptInit();
01272                if (!OptScl) {
01273                   fprintf (SUMA_STDERR,"Error %s: Could not get scaling option structure.\n", FuncName);
01274                   SUMA_RETURN (NOPE); 
01275                }
01276 
01277                /* work the options a bit */
01278                OptScl->ApplyClip = YUP;
01279                ClipRange[0] = 5; ClipRange[1] = 95; /* percentile clipping range*/ 
01280                Vsort = SUMA_PercRange (SO->Cx, NULL, SO->N_Node, ClipRange, ClipRange); 
01281                OptScl->ClipRange[0] = ClipRange[0]; OptScl->ClipRange[1] = ClipRange[1];
01282 
01283                OptScl->BrightFact = SUMA_DIM_CONVEXITY_COLOR_FACTOR;
01284 
01285                /* map the values in SO->Cx to the colormap */
01286                SV = SUMA_Create_ColorScaledVect(SO->N_Node);/* allocate space for the result */
01287                if (!SV) {
01288                   fprintf (SUMA_STDERR,"Error %s: Could not allocate for SV.\n", FuncName);
01289                   SUMA_RETURN (NOPE);
01290                }
01291 
01292                /* finally ! */
01293                /*fprintf (SUMA_STDERR,"%s: 1st color in map %f %f %f\n", FuncName, CM->M[0][0], CM->M[0][1],CM->M[0][2]);*/
01294                if (!SUMA_ScaleToMap (SO->Cx, SO->N_Node, Vsort[0], Vsort[SO->N_Node-1], CM, OptScl, SV)) {
01295                   fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_ScaleToMap.\n", FuncName);
01296                   SUMA_RETURN (NOPE);
01297                }
01298 
01299 
01300                /* create an overlay plane */
01301                NewColPlane = SUMA_CreateOverlayPointer (SO->N_Node, "Convexity");
01302                if (!NewColPlane) {
01303                   fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateOverlayPointer.\n", FuncName);
01304                   SUMA_RETURN (NOPE);
01305                } 
01306 
01307                /* make an Inode for the overlay */
01308                NewColPlane_Inode = SUMA_CreateInode ((void *)NewColPlane, SO->idcode_str);
01309                if (!NewColPlane_Inode) {
01310                   fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateInode\n", FuncName);
01311                   SUMA_RETURN (NOPE);
01312                }
01313 
01314                /* Now place the color map in the Coloroverlay structure */
01315                NewColPlane->ColMat = SV->cM; SV->cM = NULL; /* this way the color matrix will not be freed */
01316                NewColPlane->N_NodeDef = SO->N_Node;
01317                NewColPlane->GlobalOpacity = SUMA_CONVEXITY_COLORPLANE_OPACITY;
01318                NewColPlane->Show = YUP;
01319                NewColPlane->BrightMod = YUP;
01320 
01321                /* Add this plane to SO->Overlays */
01322                if (!SUMA_AddNewPlane (SO, NewColPlane, NewColPlane_Inode)) {
01323                   SUMA_SL_Crit("Failed in SUMA_AddNewPlane");
01324                   SUMA_FreeOverlayPointer(NewColPlane);
01325                   SUMA_RETURN (NOPE);
01326                }
01327 
01328                
01329                /* free */
01330                if (Vsort) SUMA_free(Vsort);
01331                if (CM) SUMA_Free_ColorMap (CM);
01332                 if (OptScl) SUMA_free(OptScl);
01333                if (SV) SUMA_Free_ColorScaledVect (SV);
01334             }
01335             
01336             /* new surface loaded, do the deeds */
01337             /* assign its Group and State */
01338             SO->Group = (char *)SUMA_calloc(strlen(Spec->Group[i])+1, sizeof(char));
01339             SO->State = (char *)SUMA_calloc(strlen(Spec->State[i])+1, sizeof(char));
01340             if (Spec->SurfaceLabel[i][0] == '\0') {
01341                SO->Label = SUMA_SurfaceFileName (SO, NOPE);
01342                if (!SO->Label) {
01343                   fprintf (SUMA_STDERR,"Error %s: Failed to create Label.\n", FuncName);
01344                   SUMA_RETURN(NOPE);
01345                }
01346             } else {
01347                SO->Label = (char *)SUMA_calloc(strlen(Spec->SurfaceLabel[i])+1, sizeof(char));
01348                if (!SO->Label) {
01349                   fprintf(SUMA_STDERR,"Error %s: Error allocating lameness.\n", FuncName);
01350                   SUMA_RETURN (NOPE);
01351                }
01352                SO->Label = strcpy(SO->Label, Spec->SurfaceLabel[i]);
01353             }
01354             
01355             if (!SO->Group || !SO->State || !SO->Label) {
01356                fprintf(SUMA_STDERR,"Error %s: Error allocating lameness.\n", FuncName);
01357                SUMA_RETURN (NOPE);
01358             }
01359             SO->Group = strcpy(SO->Group, Spec->Group[i]);
01360             SO->State = strcpy(SO->State, Spec->State[i]);
01361             SO->EmbedDim = Spec->EmbedDim[i];
01362             
01363             /* Create a Mesh Axis for the surface */
01364             SO->MeshAxis = SUMA_Alloc_Axis ("Surface Mesh Axis");
01365             if (SO->MeshAxis == NULL) {
01366                fprintf(SUMA_STDERR,"Error %s: Error Allocating axis\n", FuncName);
01367                SUMA_RETURN(NOPE);
01368             }
01369             /* Change the defaults of Mesh axis to fit standard  */
01370             SUMA_MeshAxisStandard (SO->MeshAxis, SO);
01371             /*turn on the viewing for the axis */
01372             SO->ShowMeshAxis = YUP;
01373 
01374             /* Store it into dov */
01375             if (!SUMA_AddDO(dov, N_dov, (void *)SO,  SO_type, SUMA_LOCAL)) {
01376                fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
01377                SUMA_RETURN(NOPE);
01378             }
01379             
01380 
01381             SurfIn = NOPE;
01382          }
01383       }/* Mappable surfaces */
01384    }/* first loop across mappable surfaces */
01385 
01386    for (i=0; i<Spec->N_Surfs; ++i) { /* Now locate and load all NON Mappable surfaces */
01387 
01388       if (Spec->VolParName[i][0] != '\0') {
01389          fprintf (SUMA_STDOUT, "Warning %s: Using Volume Parent Specified in Spec File. This overrides -sv option.\n", FuncName);
01390          tmpVolParName = Spec->VolParName[i];
01391       }else {
01392          tmpVolParName = VolParName;
01393       }
01394 
01395       if (SUMA_iswordin(Spec->MappingRef[i],"SAME") != 1) { /* Non Mappable surfaces */
01396          fprintf (SUMA_STDERR,"\nvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
01397          fprintf (SUMA_STDERR,"Surface #%d (mappable via MappingRef), loading ...\n",i);
01398          
01399          brk = NOPE;
01400          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "SureFit") == 1) {/* load surefit surface */
01401             SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
01402             sprintf(SF_name->name_coord,"%s", Spec->SureFitCoord[i]); ;
01403             sprintf(SF_name->name_topo,"%s", Spec->SureFitTopo[i]); 
01404             if (!strlen(Spec->SureFitVolParam[i])) { /* initialize to empty string */
01405                SF_name->name_param[0] = '\0'; 
01406             }
01407             else {
01408                sprintf(SF_name->name_param,"%s", Spec->SureFitVolParam[i]);
01409             }
01410 
01411             /* Load The Surface */
01412             if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1) {
01413                SO = SUMA_Load_Surface_Object ((void *)SF_name, SUMA_SUREFIT, SUMA_ASCII, tmpVolParName);
01414             } else {
01415                fprintf(SUMA_STDERR,"Error %s: Only ASCII surfaces can be read for now.\n", FuncName);
01416                SUMA_RETURN (NOPE);
01417             }
01418             if (SO == NULL)   {
01419                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01420                SUMA_RETURN(NOPE);
01421             }
01422 
01423             SUMA_free(SF_name); 
01424 
01425             SurfIn = YUP;         
01426             brk = YUP;
01427          }/* load surefit surface */ 
01428 
01429          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "FreeSurfer") == 1) {/* load FreeSurfer surface */
01430             
01431             if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1)
01432                SO = SUMA_Load_Surface_Object ((void *)Spec->FreeSurferSurface[i], SUMA_FREE_SURFER, SUMA_ASCII, tmpVolParName);
01433             else {
01434                fprintf(SUMA_STDERR,"Error %s: Only ASCII surfaces can be read for now.\n", FuncName);
01435                SUMA_RETURN(NOPE);
01436             }
01437             if (SO == NULL)   {
01438                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01439                SUMA_RETURN(NOPE);
01440             }
01441             SurfIn = YUP;
01442             brk = YUP;
01443          } /* load FreeSurfer surface */
01444 
01445          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "Ply") == 1) {/* load Ply format surface */
01446             
01447             SO = SUMA_Load_Surface_Object ((void *)Spec->FreeSurferSurface[i], SUMA_PLY, SUMA_FF_NOT_SPECIFIED, tmpVolParName);
01448             
01449             if (SO == NULL)   {
01450                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01451                SUMA_RETURN(NOPE);
01452             }
01453             SurfIn = YUP;
01454             brk = YUP;
01455          } /* load Ply format surface */
01456          
01457          if (!brk && SUMA_iswordin(Spec->SurfaceType[i], "GenericInventor") == 1) {/* load generic inventor format surface */
01458             if (tmpVolParName != NULL) {
01459                fprintf(SUMA_STDERR,"Error %s: Sorry, but Parent volumes are not supported for generic inventor surfaces.\n", FuncName);
01460                SUMA_RETURN (NOPE);
01461             }
01462             if (SUMA_iswordin(Spec->SurfaceFormat[i], "ASCII") == 1)
01463                SO = SUMA_Load_Surface_Object ((void *)Spec->InventorSurface[i], SUMA_INVENTOR_GENERIC, SUMA_ASCII, NULL);
01464             else {
01465                fprintf(SUMA_STDERR,"Error %s: Only ASCII surfaces can be read for now.\n", FuncName);
01466                SUMA_RETURN(NOPE);
01467             }
01468             if (SO == NULL)   {
01469                fprintf(SUMA_STDERR,"Error %s: could not load SO\n", FuncName);
01470                SUMA_RETURN(NOPE);
01471             }
01472             SurfIn = YUP;
01473 
01474             brk = YUP;
01475          }
01476 
01477 
01478          /* check if surface read was unique 
01479             it's inefficient to check after the surface is read, but idcode is generated in the read routine 
01480             and users should not be making this mistake too often */
01481             if (SUMA_existSO (SO->idcode_str, dov, *N_dov)) {
01482                fprintf(SUMA_STDERR,"Error %s: Surface %d is specifed more than once, multiple copies ignored.\n", FuncName, i);
01483                /* free SO */
01484                if (!SUMA_Free_Surface_Object (SO)) {
01485                   fprintf(SUMA_STDERR,"Error %s: Error freeing SO.\n", FuncName);
01486                   SUMA_RETURN (NOPE);
01487                }
01488                SurfIn = NOPE;
01489             }
01490 
01491          /* if the surface is loaded OK, and it has not been loaded previously, register it */
01492          if (SurfIn) {
01493             /* assign its Group and State */
01494             SO->Group = (char *)SUMA_calloc(strlen(Spec->Group[i])+1, sizeof(char));
01495             SO->State = (char *)SUMA_calloc(strlen(Spec->State[i])+1, sizeof(char));
01496 
01497             if (Spec->SurfaceLabel[i][0] == '\0') {
01498                SO->Label = SUMA_SurfaceFileName (SO, NOPE);
01499                if (!SO->Label) {
01500                   fprintf (SUMA_STDERR,"Error %s: Failed to create Label.\n", FuncName);
01501                   SUMA_RETURN(NOPE);
01502                }
01503             } else {
01504                SO->Label = (char *)SUMA_calloc(strlen(Spec->SurfaceLabel[i])+1, sizeof(char));
01505                if (!SO->Label) {
01506                   fprintf(SUMA_STDERR,"Error %s: Error allocating lameness.\n", FuncName);
01507                   SUMA_RETURN (NOPE);
01508                }
01509                SO->Label = strcpy(SO->Label, Spec->SurfaceLabel[i]);
01510             }
01511             
01512             if (!SO->Group || !SO->State) {
01513                fprintf(SUMA_STDERR,"Error %s: Error allocating lameness.\n", FuncName);
01514                SUMA_RETURN (NOPE);
01515             }
01516             SO->Group = strcpy(SO->Group, Spec->Group[i]);
01517             SO->State = strcpy(SO->State, Spec->State[i]);
01518             SO->EmbedDim = Spec->EmbedDim[i];
01519 
01520             /* Create a Mesh Axis for the surface */
01521             SO->MeshAxis = SUMA_Alloc_Axis ("Surface Mesh Axis");
01522             if (SO->MeshAxis == NULL) {
01523                fprintf(SUMA_STDERR,"Error %s: Error Allocating axis\n", FuncName);
01524                SUMA_RETURN(NOPE);
01525             }
01526             /* Change the defaults of Mesh axis to fit standard  */
01527             SUMA_MeshAxisStandard (SO->MeshAxis, SO);
01528             /*turn on the viewing for the axis */
01529             SO->ShowMeshAxis = YUP;
01530 
01531             /* Store it into dov */
01532             if (!SUMA_AddDO(dov, N_dov, (void *)SO,  SO_type, SUMA_LOCAL)) {
01533                fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
01534                SUMA_RETURN(NOPE);
01535             }
01536             
01537          /* set its MappingRef id to NULL if none is specified */
01538             if (Spec->MappingRef[i][0] == '\0') {
01539                SO->MapRef_idcode_str = NULL; /* no known MapRef_idcode */
01540                fprintf(SUMA_STDERR,"No Mapping Ref specified.\n");
01541             } else {
01542                /* make sure that specified Mapping ref had been loaded */
01543                   int j = 0, ifound = -1;
01544                   while (j <=Spec->N_Surfs) {
01545                      /*fprintf(SUMA_STDERR,"%s\n%s\n%s\n%s\n%s\n", \
01546                         Spec->MappingRef[i], Spec->SureFitCoord[j], Spec->SureFitTopo[j],\
01547                         Spec->InventorSurface[j], Spec->FreeSurferSurface[j]);*/ 
01548                      if (strcmp(Spec->MappingRef[i], Spec->SureFitCoord[j]) == 0 || \
01549                          strcmp(Spec->MappingRef[i], Spec->SureFitTopo[j]) == 0 ||  \
01550                          strcmp(Spec->MappingRef[i], Spec->InventorSurface[j]) == 0 || \
01551                          strcmp(Spec->MappingRef[i], Spec->FreeSurferSurface[j]) == 0) {
01552                         /* found a match */
01553                         ifound = j;
01554                         j = Spec->N_Surfs + 1;   
01555                      }
01556                      ++j;
01557                   }
01558                if (ifound >= 0) { /* found */
01559                   /*fprintf (SUMA_STDERR,"ifound = %d, i = %d\nSpec->MappingRef[i]:->%s<-\n", ifound, i, Spec->MappingRef[i]);*/
01560                   if (!SUMA_existSO (Spec->IDcode[ifound], dov, *N_dov)) {
01561                      fprintf(SUMA_STDERR,"MappingRef unavailable, that should not happen here.\n");
01562                      SO->MapRef_idcode_str = NULL;
01563                   } else {
01564                      /*fprintf(SUMA_STDERR,"MappingRef found in mappable surfaces\n");*/
01565                      SO->MapRef_idcode_str = (char *)SUMA_calloc(strlen(Spec->IDcode[ifound])+1, sizeof(char));
01566                      if (SO->MapRef_idcode_str == NULL) {
01567                         fprintf(SUMA_STDERR,"Error %s: Failed to allocate for SO->MapRef_idcode_str. That is pretty bad.\n", FuncName);
01568                         SUMA_RETURN (NOPE);
01569                      }
01570                      SO->MapRef_idcode_str = strcpy(SO->MapRef_idcode_str, Spec->IDcode[ifound]);
01571                   }
01572                } else {
01573                   fprintf(SUMA_STDERR,"MappingRef unavailable, you won't be able to link to afni.\n");
01574                   SO->MapRef_idcode_str = NULL;
01575                }
01576             }
01577             
01578             /* create the colorlist vector and calculate the surface metrics with the possibility of inheriting from the mapping reference */
01579             {
01580                SUMA_SurfaceObject *SOinh = NULL;
01581                int ifound = -1; 
01582                
01583                if (SO->MapRef_idcode_str) {   
01584                   ifound =  SUMA_findSO_inDOv (SO->MapRef_idcode_str, dov, *N_dov);
01585                   if (ifound < 0) {
01586                      SOinh = NULL;
01587                   }else {
01588                      SOinh = (SUMA_SurfaceObject *)(dov[ifound].OP);
01589                   }
01590                } else SOinh = NULL;
01591          
01592                
01593                if (!SUMA_SurfaceMetrics (SO, "EdgeList", SOinh)) {
01594                   fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
01595                   SUMA_RETURN (NOPE);
01596                }
01597             }  
01598                
01599             
01600 
01601             SurfIn = NOPE;
01602          }
01603       }/* Non Mappable surfaces */
01604 
01605    }/*locate and load all NON Mappable surfaces */
01606 
01607    SUMA_RETURN (YUP);
01608 }/* SUMA_LoadSpec */
01609 
01610 
01611 /*!
01612    calculate surface properties
01613    
01614    ans = SUMA_SurfaceMetrics (SO, Metrics, SOinh)
01615    \param SO (SUMA_SurfaceObject *)
01616    \param Metrics (const char *) list of parameters to compute. Supported parameters are (case sensitive):
01617       "Convexity", "PolyArea", "Curvature", "EdgeList", "MemberFace", "CheckWind"
01618       You can specify more than one parameter "Convexity, PolyArea"
01619       if the field of a certain parameter is not NULL then it is assumed that 
01620       this parameter was computed at an earlier time and will not be recalculated.
01621       Some parameters require the computation of others and that's done automatically.
01622    \param SOinh (SUMA_SurfaceObject *) Some of the metrics can be inherited from SOinh (done through inodes)
01623       if things make sense. SOinh is typically the Mapping Reference SO. Pass NULL not to use this feature.
01624       Currently, only EL and FN can use this feature if the number of nodes, facesets match and SOinh is the 
01625       mapping reference of SO
01626    \return ans (SUMA_Boolean) NOPE = failure
01627    
01628    Convexity : Fills Cx field in SO, An inode is also created
01629    
01630    EdgeList also runs SUMA_Build_FirstNeighb
01631    
01632    Curvature requires also PolyArea, FaceNeighb and EdgeList
01633    CheckWind requires EdgeList
01634    
01635       
01636 */
01637 SUMA_Boolean SUMA_SurfaceMetrics (SUMA_SurfaceObject *SO, const char *Metrics, SUMA_SurfaceObject *SOinh)
01638 {
01639    static char FuncName[]={"SUMA_SurfaceMetrics"};
01640    SUMA_Boolean DoConv, DoArea, DoCurv, DoEL, DoMF, DoWind, LocalHead = NOPE;
01641    int i = 0;
01642    
01643    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01644 
01645    fprintf (SUMA_STDERR,"%s: Calculating surface metrics, please be patient...\n", FuncName);
01646    
01647    DoConv = DoArea = DoCurv = DoEL = DoMF = DoWind = NOPE;
01648    
01649    if (SUMA_iswordin (Metrics, "Convexity")) DoConv = YUP;
01650    if (SUMA_iswordin (Metrics, "PolyArea")) DoArea = YUP;
01651    if (SUMA_iswordin (Metrics, "Curvature")) DoCurv = YUP;
01652    if (SUMA_iswordin (Metrics, "EdgeList")) DoEL = YUP;
01653    if (SUMA_iswordin (Metrics, "MemberFace")) DoMF = YUP;
01654    if (SUMA_iswordin (Metrics, "CheckWind")) DoWind = YUP;
01655    
01656    /* check for input inconsistencies and warn */
01657    if (!DoConv && !DoArea && !DoCurv && !DoEL  && !DoMF && !DoWind) {
01658       fprintf (SUMA_STDERR,"Warning %s: Nothing to do.\n", FuncName);
01659       SUMA_RETURN (YUP);
01660    }
01661    
01662    if (DoConv && SO->Cx != NULL) {
01663       fprintf (SUMA_STDERR,"Warning %s: SO->Cx != NULL and thus appears to have been precomputed.\n", FuncName);
01664       DoConv = NOPE;
01665    }
01666    
01667    if (DoArea && SO->PolyArea != NULL) {
01668       fprintf (SUMA_STDERR,"Warning %s: SO->PolyArea != NULL and thus appears to have been precomputed.\n", FuncName);
01669       DoArea = NOPE;
01670    }
01671    
01672    if (DoCurv && SO->SC != NULL) {
01673       fprintf (SUMA_STDERR,"Warning %s: SO->SC != NULL and thus appears to have been precomputed.\n", FuncName);
01674       DoCurv = NOPE;
01675    }
01676    
01677    if (DoMF && SO->MF != NULL) {
01678       fprintf (SUMA_STDERR,"Warning %s: SO->MF != NULL and thus appears to have been precomputed.\n", FuncName);
01679       DoMF = NOPE;
01680    }
01681    
01682    if (DoEL && (SO->EL != NULL || SO->FN != NULL)) {
01683       fprintf (SUMA_STDERR,"Warning %s: SO->EL != NULL || SO->FN != NULL and thus appears to have been precomputed.\n", FuncName);
01684       DoEL = NOPE;
01685    }
01686    
01687    if (DoEL && SOinh) {
01688       if (strcmp(SO->MapRef_idcode_str, SOinh->idcode_str)) {
01689          SUMA_SL_Warn(  "Cannot inherit Edge List\n"
01690                         "and First Neightbor.\n"
01691                         "Cause: idcode mismatch.\n"
01692                         "Independent lists will\n"
01693                         "be created." );
01694          SOinh = NULL;
01695       }else if (!SOinh->EL_Inode || !SOinh->FN_Inode){
01696          SUMA_SL_Warn(  "Cannot inherit Edge List\n"
01697                         "and First Neightbor.\n"
01698                         "Cause: NULL inodes.\n"
01699                         "Independent lists will\n"
01700                         "be created.");
01701          SOinh = NULL;
01702       }else if (SO->N_Node != SOinh->N_Node || SO->N_FaceSet != SOinh->N_FaceSet) {
01703          SUMA_SL_Warn(  "(IGNORE for surface patches)\n"
01704                         "Cannot inherit Edge List\n"
01705                         "and First Neightbor.\n"
01706                         "Cause: Node number mismatch.\n"
01707                         "Independent lists will\n"
01708                         "be created.");
01709          SOinh = NULL;      
01710       }
01711    }
01712     
01713    /* prerequisits */
01714    if (DoCurv) {
01715       DoArea = YUP;
01716       DoEL = YUP;
01717    }
01718    
01719    if (DoWind) {
01720       DoEL = YUP;
01721    }
01722 
01723    if (DoConv) {
01724       DoEL = YUP;
01725    }
01726    
01727    /* the computations */
01728    if (DoArea) {
01729       /* create the triangle Area  */
01730       if (SO->NodeDim == 3) {
01731          fprintf(SUMA_STDOUT, "%s: Calculating triangle areas ...\n", FuncName); 
01732          SO->PolyArea = SUMA_TriSurf3v (SO->NodeList, SO->FaceSetList, SO->N_FaceSet);
01733       } else {
01734          fprintf(SUMA_STDOUT, "%s: Calculating polygon areas ...\n", FuncName); 
01735          SO->PolyArea = SUMA_PolySurf3 (SO->NodeList, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, SO->NodeDim, SO->FaceNormList, NOPE);
01736          #if 0
01737             /* a test of the functions for calculating areas */
01738             {
01739                int ji, in0, in1, in2;
01740                float *n0, *n1, *n2, A;
01741                for (ji=0; ji<SO->N_FaceSet; ++ji) {
01742                   in0 = SO->FaceSetList[3*ji];
01743                   in1 = SO->FaceSetList[3*ji+1];
01744                   in2 = SO->FaceSetList[3*ji+2];
01745                   n0 = &(SO->NodeList[3*in0]);
01746                   n1 = &(SO->NodeList[3*in1]);
01747                   n2 = &(SO->NodeList[3*in2]);
01748                   A = SUMA_TriSurf3 (n0, n1, n2);
01749                   if (abs(A - SO->PolyArea[ji]) > 0.00001) {
01750                      fprintf (SUMA_STDERR, "Error %s: Failed comparing SUMA_TriSurf3 to SUMA_PolySurf3. A = %f vs %f.\nTri = [ %f, %f, %f; %f, %f, %f; %f, %f, %f]\n", 
01751                         FuncName, A, SO->PolyArea[ji], n0[0], n0[1], n0[2], n1[0], n1[1], n1[2], n2[0], n2[1], n2[2]);
01752                   }else fprintf (SUMA_STDERR, "-");
01753 
01754                   SUMA_TRI_AREA (n0, n1, n2, A);
01755                   if (abs(A - SO->PolyArea[ji]) > 0.00001) {
01756                      fprintf (SUMA_STDERR, "Error %s: Failed comparing SUMA_TRI_AREA to SUMA_PolySurf3. %f vs %f Exiting.\n", 
01757                         FuncName, A, SO->PolyArea[ji]);
01758                   }else fprintf (SUMA_STDERR, ".");
01759                }  
01760             }
01761          #endif
01762 
01763       }
01764       if (SO->PolyArea == NULL) {
01765          fprintf(SUMA_STDERR,"Error %s: Error in SUMA_PolySurf3 or SUMA_TriSurf3v\n", FuncName);
01766       }
01767    }
01768    
01769    if (DoEL) {
01770       if (!SOinh) {
01771          /* create the edge list, it's nice and dandy */
01772          if (LocalHead) fprintf(SUMA_STDOUT, "%s: Making Edge list ....\n", FuncName); 
01773          SO->EL = SUMA_Make_Edge_List (SO->FaceSetList, SO->N_FaceSet, SO->N_Node, SO->NodeList);
01774          if (SO->EL == NULL) {
01775             fprintf(SUMA_STDERR, "Error %s: Failed in SUMA_Make_Edge_List. Neighbor list will not be created\n", FuncName);
01776             SO->EL_Inode = NULL;
01777          } else {
01778             /* create EL_Inode */
01779             SO->EL_Inode = SUMA_CreateInode ((void *)SO->EL, SO->idcode_str);
01780             if (!SO->EL_Inode) {
01781                fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateInode\n", FuncName);
01782             }
01783             if (LocalHead) fprintf(SUMA_STDOUT, "%s: Making Node Neighbor list ....\n", FuncName); 
01784             /* create the node neighbor list */
01785             SO->FN = SUMA_Build_FirstNeighb (SO->EL, SO->N_Node);   
01786             if (SO->FN == NULL) {
01787                fprintf(SUMA_STDERR, "Error %s: Failed in SUMA_Build_FirstNeighb.\n", FuncName);
01788                SO->FN_Inode = NULL;
01789             } else {
01790                /* create FN_Inode */
01791                SO->FN_Inode = SUMA_CreateInode ((void *)SO->FN, SO->idcode_str);
01792                if (!SO->FN_Inode) {
01793                   fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateInode\n", FuncName);
01794                }
01795             }
01796          }
01797       } else {
01798          if (LocalHead) fprintf(SUMA_STDOUT, "%s: Linking Edge List and First Neighbor Lits ...\n", FuncName);
01799          SO->EL_Inode = SUMA_CreateInodeLink (SO->EL_Inode, SOinh->EL_Inode);
01800          if (!SO->EL_Inode) {
01801             fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateInodeLink\n", FuncName);
01802             SUMA_RETURN (NOPE);
01803          }
01804          SO->EL = SOinh->EL;
01805          SO->FN_Inode = SUMA_CreateInodeLink (SO->FN_Inode, SOinh->FN_Inode);
01806          if (!SO->FN_Inode) {
01807             fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateInodeLink\n", FuncName);
01808             SUMA_RETURN (NOPE);
01809          }
01810          SO->FN = SOinh->FN;   
01811       }
01812    }
01813    
01814    if (DoConv) {
01815       /* calculate convexity */
01816       if (LocalHead) fprintf(SUMA_STDOUT, "%s: Calculating convexity ...\n", FuncName);
01817       SO->Cx = SUMA_Convexity   (SO->NodeList, SO->N_Node, SO->NodeNormList, SO->FN);
01818       if (SO->Cx == NULL) {
01819          fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Convexity\n", FuncName);
01820          SO->Cx_Inode = NULL;
01821       }   
01822             
01823       /* flip sign of convexity if it's a SureFit Surface */
01824       if (SO->FileType == SUMA_SUREFIT) {
01825          for (i=0; i < SO->N_Node; ++i) {
01826             SO->Cx[i] = -SO->Cx[i];
01827          }
01828       }
01829       
01830       {
01831          float *attr_sm;
01832          /* smooth estimate twice */
01833          attr_sm = SUMA_SmoothAttr_Neighb (SO->Cx, SO->N_Node, NULL, SO->FN);
01834          if (attr_sm == NULL) {
01835                fprintf(stderr,"Error %s: Failed in SUMA_SmoothAttr_Neighb\n", FuncName);
01836          }   else {
01837             SO->Cx = SUMA_SmoothAttr_Neighb (attr_sm, SO->N_Node, SO->Cx, SO->FN);
01838             if (attr_sm) SUMA_free(attr_sm);
01839          }
01840       }
01841       if (SO->Cx == NULL) {
01842          fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_SmoothAttr_Neighb\n", FuncName);
01843          SO->Cx_Inode = NULL;
01844       } else {
01845          /* create Cx_Inode */
01846          SO->Cx_Inode = SUMA_CreateInode ((void *)SO->Cx, SO->idcode_str);
01847          if (!SO->Cx_Inode) {
01848             fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateInode\n", FuncName);
01849          }
01850       }
01851    } /* DoConv */
01852    
01853    if (DoWind){   
01854       /* check to make sure winding is consistent */
01855       if (!SUMA_MakeConsistent (SO->FaceSetList, SO->N_FaceSet, SO->EL)) {
01856          fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_MakeConsistent.\n", FuncName);
01857       }else {
01858          if (LocalHead) fprintf(SUMA_STDERR,"%s: Eeeexcellent.\n", FuncName);
01859       }
01860    }
01861 
01862    
01863    if (DoCurv) {
01864       /* calculate the curvature */
01865       if (LocalHead) fprintf(SUMA_STDOUT, "%s: Calculating curvature ...\n", FuncName);
01866       SO->SC = SUMA_Surface_Curvature (SO->NodeList, SO->N_Node, SO->NodeNormList, SO->PolyArea, SO->N_FaceSet, SO->FN, SO->EL);
01867    }
01868    
01869    
01870    if (DoMF) {
01871       /* determine the MemberFaceSets */
01872       if (LocalHead) fprintf(SUMA_STDOUT, "%s: Determining MemberFaceSets  ...\n", FuncName);
01873       SO->MF = SUMA_MemberFaceSets(SO->N_Node, SO->FaceSetList, SO->N_FaceSet, SO->FaceSetDim);
01874       if (SO->MF->NodeMemberOfFaceSet == NULL) {
01875          fprintf(SUMA_STDERR,"Error %s: Error in SUMA_MemberFaceSets\n", FuncName);
01876          SO->MF = NULL;
01877       }
01878    }
01879 
01880    SUMA_RETURN (YUP);
01881 }
01882 
01883 #ifdef SUMA_SurfaceMetrics_STAND_ALONE
01884 
01885 void usage_SUMA_SurfaceMetrics ()
01886    {
01887       printf ("\n\33[1mUsage: \33[0m SurfaceMetrics <-Metric1> [[-Metric2] ...] \n"
01888               "\t<-i_TYPE inSurf> [<-sv SurfaceVolume [VolParam for sf surfaces]>]\n"
01889               "\t[-tlrc] [<-prefix prefix>]\n\n");
01890       printf ("\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \t Mon May 19 15:41:12 EDT 2003\n\n");   
01891    }
01892 
01893 int main (int argc,char *argv[])
01894 {/* Main */
01895    char FuncName[]={"Main_SUMA_SurfaceMetrics"};
01896    char  *OutName=NULL, *OutPrefix = NULL, *if_name = NULL, 
01897          *if_name2 = NULL, *sv_name = NULL, *vp_name = NULL,
01898          *tlrc_name = NULL;
01899    SUMA_STRING *MetricList = NULL;
01900    int i, n1, n2, n1_3, n2_3, kar, nt;
01901    double edgeL2;
01902    FILE *fout=NULL;
01903    SUMA_SO_File_Type iType = SUMA_FT_NOT_SPECIFIED;
01904    SUMA_SurfaceObject *SO = NULL;   
01905    SUMA_SFname *SF_name = NULL;
01906    void *SO_name = NULL;   
01907    THD_warp *warp=NULL ;
01908    THD_3dim_dataset *aset=NULL;
01909    SUMA_Boolean   brk, Do_tlrc, Do_conv, Do_curv, 
01910                   Do_area, Do_edges, LocalHead = YUP;  
01911    
01912    
01913         /* allocate space for CommonFields structure */
01914         SUMAg_CF = SUMA_Create_CommonFields ();
01915         if (SUMAg_CF == NULL) {
01916                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
01917                 exit(1);
01918         }
01919    
01920    if (argc < 4)
01921        {
01922           usage_SUMA_SurfaceMetrics ();
01923           exit (1);
01924        }
01925    
01926    MetricList = SUMA_StringAppend (NULL, NULL);
01927    kar = 1;
01928         brk = NOPE;
01929    Do_tlrc = NOPE;
01930    Do_conv = NOPE;
01931    Do_area = NOPE;
01932    Do_curv = NOPE;
01933    Do_edges = NOPE;
01934    OutPrefix = NULL;
01935    
01936         while (kar < argc) { /* loop accross command ine options */
01937                 /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
01938                 if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
01939                          usage_SUMA_SurfaceMetrics();
01940           exit (1);
01941                 }
01942                 
01943                 if (!brk && (strcmp(argv[kar], "-i_fs") == 0)) {
01944          kar ++;
01945                         if (kar >= argc)  {
01946                                 fprintf (SUMA_STDERR, "need argument after -i_fs ");
01947                                 exit (1);
01948                         }
01949                         if_name = argv[kar];
01950          iType = SUMA_FREE_SURFER;
01951                         brk = YUP;
01952                 }
01953       
01954       if (!brk && (strcmp(argv[kar], "-i_sf") == 0)) {
01955          kar ++;
01956                         if (kar+1 >= argc)  {
01957                                 fprintf (SUMA_STDERR, "need 2 argument after -i_sf");
01958                                 exit (1);
01959                         }
01960                         if_name = argv[kar]; kar ++;
01961          if_name2 = argv[kar];
01962          iType = SUMA_SUREFIT;
01963                         brk = YUP;
01964                 }
01965       
01966       if (!brk && (strcmp(argv[kar], "-i_vec") == 0)) {
01967          kar ++;
01968                         if (kar+1 >= argc)  {
01969                                 fprintf (SUMA_STDERR, "need 2 argument after -i_vec");
01970                                 exit (1);
01971                         }
01972                         if_name = argv[kar]; kar ++;
01973          if_name2 = argv[kar];
01974          iType = SUMA_VEC;
01975                         brk = YUP;
01976                 }
01977       
01978       if (!brk && (strcmp(argv[kar], "-i_ply") == 0)) {
01979          kar ++;
01980                         if (kar >= argc)  {
01981                                 fprintf (SUMA_STDERR, "need argument after -i_ply ");
01982                                 exit (1);
01983                         }
01984                         if_name = argv[kar];
01985          iType = SUMA_PLY;
01986                         brk = YUP;
01987                 }
01988       
01989       if (!brk && (strcmp(argv[kar], "-prefix") == 0)) {
01990          kar ++;
01991                         if (kar >= argc)  {
01992                                 fprintf (SUMA_STDERR, "need argument after -prefix ");
01993                                 exit (1);
01994                         }
01995                         OutPrefix = argv[kar];
01996                         brk = YUP;
01997                 }
01998       
01999       if (!brk && (strcmp(argv[kar], "-sv") == 0)) {
02000          if (iType == SUMA_FT_NOT_SPECIFIED) {
02001             fprintf (SUMA_STDERR, " -sv option must be preceeded by -i_TYPE option.");
02002             exit(1);
02003          }
02004          kar ++;
02005                         if (iType == SUMA_SUREFIT) {
02006             if (kar+1 >= argc)  {
02007                                    fprintf (SUMA_STDERR, "need 2 argument after -sv (SurfaceVolume and VolumeParent)");
02008                                    exit (1);
02009                            }
02010             sv_name = argv[kar]; kar ++;
02011             vp_name = argv[kar];
02012          } else {
02013             if (kar >= argc)  {
02014                                    fprintf (SUMA_STDERR, "need argument after -sv ");
02015                                    exit (1);
02016                            }
02017                            sv_name = argv[kar];
02018          }
02019                         brk = YUP;
02020                 }
02021 
02022       if (!brk && (strcmp(argv[kar], "-tlrc") == 0)) {
02023          Do_tlrc = YUP;
02024          brk = YUP;
02025       }
02026       
02027       if (!brk && (strcmp(argv[kar], "-conv") == 0)) {
02028          Do_conv = YUP;
02029          MetricList = SUMA_StringAppend (MetricList, "Convexity "); 
02030          brk = YUP;
02031       }
02032       
02033       if (!brk && (strcmp(argv[kar], "-area") == 0)) {
02034          Do_area = YUP;
02035          MetricList = SUMA_StringAppend (MetricList, "PolyArea "); 
02036          brk = YUP;
02037       }
02038 
02039       if (!brk && (strcmp(argv[kar], "-curv") == 0)) {
02040          Do_curv = YUP;
02041          MetricList = SUMA_StringAppend (MetricList, "Curvature "); 
02042          brk = YUP;
02043       }
02044       
02045       if (!brk && (strcmp(argv[kar], "-edges") == 0)) {
02046          Do_edges = YUP;
02047          MetricList = SUMA_StringAppend (MetricList, "EdgeList "); 
02048          brk = YUP;
02049       }
02050       
02051       if (!brk) {
02052                         fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]);
02053                         exit (1);
02054                 } else {        
02055                         brk = NOPE;
02056                         kar ++;
02057                 }
02058    }
02059 
02060    /* clean MetricList */
02061    MetricList = SUMA_StringAppend (MetricList, NULL); 
02062    
02063    /* sanity checks */
02064    if (!MetricList) {
02065       SUMA_S_Err("No Metrics specified.\nNothing to do.\n");
02066       exit(1);
02067    }
02068    
02069    if (!if_name) {
02070       SUMA_S_Err("Input surface not specified.\n");
02071       exit(1);
02072    }
02073    
02074    if (iType == SUMA_FT_NOT_SPECIFIED) {
02075       SUMA_S_Err("Input type not recognized.\n");
02076       exit(1);
02077    }
02078    
02079    if (iType == SUMA_SUREFIT) {
02080       if (!if_name2) {
02081          SUMA_S_Err("Input SureFit surface incorrectly specified.\n");
02082          exit(1);
02083       }
02084       if (sv_name && !vp_name) {
02085          SUMA_S_Err("VolParent must specified with -sv potion for SureFit surfaces. \n");
02086          exit(1);
02087       }
02088    }
02089    
02090    if (iType == SUMA_VEC) {
02091       if (!if_name2) {
02092          SUMA_S_Err("Input vec surface incorrectly specified.\n");
02093          exit(1);
02094       }
02095    }
02096    
02097    /* test for existence of input files */
02098    if (!SUMA_filexists(if_name)) {
02099       fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, if_name);
02100       exit(1);
02101    }
02102    
02103    if (if_name2) {
02104       if (!SUMA_filexists(if_name2)) {
02105          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, if_name2);
02106          exit(1);
02107       }
02108    }
02109 
02110    if (sv_name) {
02111       if (!SUMA_filexists(sv_name)) {
02112          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, sv_name);
02113          exit(1);
02114       }
02115    }
02116    
02117    if (Do_tlrc && !sv_name) {
02118       fprintf (SUMA_STDERR,"Error %s: -tlrc must be used with -sv option.\n", FuncName);
02119       exit(1);
02120    }
02121    
02122    if (vp_name) {
02123       if (!SUMA_filexists(vp_name)) {
02124          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, vp_name);
02125          exit(1);
02126       }
02127    }
02128 
02129    /* read the surface */
02130    
02131    /* prepare the name of the surface object to read*/
02132    switch (iType) {
02133       case SUMA_SUREFIT:
02134          SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
02135          sprintf(SF_name->name_coord,"%s", if_name);
02136          sprintf(SF_name->name_topo,"%s", if_name2); 
02137          if (!vp_name) { /* initialize to empty string */
02138             SF_name->name_param[0] = '\0'; 
02139          }
02140          else {
02141             sprintf(SF_name->name_param,"%s", vp_name);
02142          }
02143          SO_name = (void *)SF_name;
02144          fprintf (SUMA_STDOUT,"Reading %s and %s...\n", SF_name->name_coord, SF_name->name_topo);
02145          SO = SUMA_Load_Surface_Object (SO_name, SUMA_SUREFIT, SUMA_ASCII, sv_name);
02146          break;
02147       case SUMA_VEC:
02148          SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
02149          sprintf(SF_name->name_coord,"%s", if_name);
02150          sprintf(SF_name->name_topo,"%s", if_name2); 
02151          SO_name = (void *)SF_name;
02152          fprintf (SUMA_STDOUT,"Reading %s and %s...\n", SF_name->name_coord, SF_name->name_topo);
02153          SO = SUMA_Load_Surface_Object (SO_name, SUMA_VEC, SUMA_ASCII, sv_name);
02154          break;
02155       case SUMA_FREE_SURFER:
02156          SO_name = (void *)if_name; 
02157          fprintf (SUMA_STDOUT,"Reading %s ...\n",if_name);
02158          SO = SUMA_Load_Surface_Object (SO_name, SUMA_FREE_SURFER, SUMA_ASCII, sv_name);
02159          break;  
02160       case SUMA_PLY:
02161          SO_name = (void *)if_name; 
02162          fprintf (SUMA_STDOUT,"Reading %s ...\n",if_name);
02163          SO = SUMA_Load_Surface_Object (SO_name, SUMA_PLY, SUMA_FF_NOT_SPECIFIED, sv_name);
02164          break;  
02165       default:
02166          fprintf (SUMA_STDERR,"Error %s: Bad format.\n", FuncName);
02167          exit(1);
02168    }
02169    
02170    if (!SO) {
02171       fprintf (SUMA_STDERR,"Error %s: Failed to read input surface.\n", FuncName);
02172       exit (1);
02173    }
02174    
02175    if (Do_tlrc) {
02176       fprintf (SUMA_STDOUT,"Performing talairach transform...\n");
02177 
02178       /* form the tlrc version of the surface volume */
02179       tlrc_name = (char *) SUMA_calloc (strlen(SO->VolPar->dirname)+strlen(SO->VolPar->prefix)+60, sizeof(char));
02180       sprintf (tlrc_name, "%s%s+tlrc.HEAD", SO->VolPar->dirname, SO->VolPar->prefix);
02181       if (!SUMA_filexists(tlrc_name)) {
02182          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, tlrc_name);
02183          exit(1);
02184       }
02185       
02186       /* read the tlrc header */
02187       aset = THD_open_dataset(tlrc_name) ;
02188       if( !ISVALID_DSET(aset) ){
02189          fprintf (SUMA_STDERR,"Error %s: %s is not a valid data set.\n", FuncName, tlrc_name) ;
02190          exit(1);
02191       }
02192       if( aset->warp == NULL ){
02193          fprintf (SUMA_STDERR,"Error %s: tlrc_name does not contain a talairach transform.\n", FuncName);
02194          exit(1);
02195       }
02196       
02197       warp = aset->warp ;
02198       
02199       /* now warp the coordinates, one node at a time */
02200       if (!SUMA_AFNI_forward_warp_xyz(warp, SO->NodeList, SO->N_Node)) {
02201          fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AFNI_forward_warp_xyz.\n", FuncName);
02202          exit(1);
02203       }
02204 
02205       
02206       
02207    }
02208    
02209    /* create the surface label*/
02210    SO->Label = SUMA_SurfaceFileName (SO, NOPE);
02211    if (!SO->Label) {
02212       SUMA_S_Err("Failed to create Label");
02213       exit(1);
02214    }
02215 
02216    if (LocalHead) SUMA_Print_Surface_Object (SO, stderr);
02217    
02218    /* Now do the deed */
02219    SUMA_LH (MetricList->s);
02220    
02221    if (!SUMA_SurfaceMetrics (SO, MetricList->s, NULL)) {
02222       fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
02223       exit(1);
02224    }
02225    
02226    SUMA_LH ("Done with Metrics");
02227    
02228    /* output time */
02229    if (!OutPrefix) {
02230       OutPrefix = SUMA_copy_string(SO->Label);
02231    }
02232    
02233    OutName = (char*) SUMA_malloc((strlen(OutPrefix) + 30) * sizeof(char));
02234    
02235    
02236    if (Do_edges) {
02237       
02238       SUMA_S_Note("Writing edges...");
02239       
02240       if (!SO->EL) {
02241          SUMA_S_Err("Edge list not computed.");
02242          exit(1);
02243       }
02244       
02245       sprintf(OutName, "%s.edges", OutPrefix);
02246       if (SUMA_filexists(OutName)) {
02247          SUMA_S_Err("Edge output file exists.\nWill not overwrite.");
02248          exit(1);
02249       }
02250       
02251       fout = fopen(OutName,"w");
02252       if (!fout) {
02253          SUMA_S_Err("Failed to open file for writing.\nCheck your permissions.\n");
02254          exit(1);
02255       }
02256       
02257       fprintf (fout,"#Edge List\n");
02258       fprintf (fout,"#eI = Edge Index\n");
02259       fprintf (fout,"#n1 = Node 1\n");
02260       fprintf (fout,"#n2 = Node 2\n");
02261       fprintf (fout,"#nt = Number of triangles containing edge\n"); 
02262       fprintf (fout,"#eL = Edge Length\n");
02263       fprintf (fout,"#eI\tn1\tn2\tnt\teL\n\n");
02264       for (i=0; i < SO->EL->N_EL; ++i) {
02265          if (SO->EL->ELps[i][2] >= 0) {
02266             n1 = SO->EL->EL[i][0];
02267             n2 = SO->EL->EL[i][1];
02268             nt = SO->EL->ELps[i][2];
02269             n1_3 = 3 * n1;
02270             n2_3 = 3 * n2;
02271             edgeL2 = ( (SO->NodeList[n2_3] - SO->NodeList[n1_3]) * (SO->NodeList[n2_3] - SO->NodeList[n1_3]) ) +
02272                      ( (SO->NodeList[n2_3+1] - SO->NodeList[n1_3+1]) * (SO->NodeList[n2_3+1] - SO->NodeList[n1_3+1]) ) +
02273                      ( (SO->NodeList[n2_3+2] - SO->NodeList[n1_3+2]) * (SO->NodeList[n2_3+2] - SO->NodeList[n1_3+2]) ); 
02274                      
02275             fprintf (fout,"%d\t%d\t%d\t%d\t%f\n",
02276                   i, n1, n2, nt, sqrt(edgeL2));
02277                   
02278          }   
02279       }
02280       fclose(fout); fout = NULL;
02281       
02282    }
02283    
02284    if (Do_area) {
02285       SUMA_S_Note("Writing areas...");
02286       
02287       if (!SO->PolyArea) {
02288          SUMA_S_Err("Areas not computed");
02289          exit(1);
02290       }  
02291       
02292       sprintf(OutName, "%s.area", OutPrefix);
02293       if (SUMA_filexists(OutName)) {
02294          SUMA_S_Err("Area output file exists.\nWill not overwrite.");
02295          exit(1);
02296       }
02297       
02298       fout = fopen(OutName,"w");
02299       if (!fout) {
02300          SUMA_S_Err("Failed to open file for writing.\nCheck your permissions.\n");
02301          exit(1);
02302       }
02303       
02304       fprintf (fout,"#FaceSet Area\n");
02305       fprintf (fout,"#fI = FaceSet Index\n");
02306       fprintf (fout,"#fA = FaceSet Area\n");
02307       fprintf (fout,"#fI\t#fA\n\n");
02308       
02309       for (i=0; i < SO->N_FaceSet; ++i) {
02310          fprintf (fout,"%d\t%f\n", i, SO->PolyArea[i]);
02311       }  
02312       
02313       fclose(fout); fout = NULL;
02314    }
02315    
02316    if (Do_curv) {
02317       SUMA_S_Note("Writing curvatures ...");
02318       
02319       if (!SO->SC) {
02320          SUMA_S_Err("Curvatures not computed");
02321          exit(1);
02322       }
02323       
02324       sprintf(OutName, "%s.curv", OutPrefix);
02325       if (SUMA_filexists(OutName)) {
02326          SUMA_S_Err("Curvature output file exists.\nWill not overwrite.");
02327          exit(1);
02328       }
02329       
02330       fout = fopen(OutName,"w");
02331       if (!fout) {
02332          SUMA_S_Err("Failed to open file for writing.\nCheck your permissions.\n");
02333          exit(1);
02334       }  
02335       
02336       fprintf (fout,"#Curvature\n");
02337       fprintf (fout,"#nI = Node Index\n");
02338       fprintf (fout,"#T1 = 1 x 3 vector of 1st principal direction of surface\n");
02339       fprintf (fout,"#T2 = 1 x 3 vector of 2nd principal direction of surface\n");
02340       fprintf (fout,"#Kp1 = curvature along T1\n");
02341       fprintf (fout,"#Kp2 = curvature along T2\n");
02342       fprintf (fout,"#nI\tT1[0]\tT1[1]\tT1[2]\tT2[0]\tT2[1]\tT2[2]\tKp1\tKp2\n\n");
02343       
02344       for (i=0; i < SO->N_Node; ++i) {
02345          fprintf (fout,"%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
02346             i, SO->SC->T1[i][0], SO->SC->T1[i][1], SO->SC->T1[i][2], 
02347             SO->SC->T2[i][0], SO->SC->T2[i][1], SO->SC->T2[i][2],
02348             SO->SC->Kp1[i], SO->SC->Kp2[i] );
02349       }
02350       
02351       fclose(fout); fout = NULL;
02352    }
02353    
02354    if (Do_conv) {
02355       SUMA_S_Note("Writing convexities ...");
02356       
02357       if (!SO->Cx) {
02358          SUMA_S_Err("Convexities not computed");
02359          exit(1);
02360       }
02361       
02362       sprintf(OutName, "%s.conv", OutPrefix);
02363       if (SUMA_filexists(OutName)) {
02364          SUMA_S_Err("Convexities output file exists.\nWill not overwrite.");
02365          exit(1);
02366       }
02367       
02368       fout = fopen(OutName,"w");
02369       if (!fout) {
02370          SUMA_S_Err("Failed to open file for writing.\nCheck your permissions.\n");
02371          exit(1);
02372       }  
02373       
02374       fprintf (fout,"#Convexity\n");
02375       fprintf (fout,"nI = Node Index\n");
02376       fprintf (fout,"C = Convexity\n");
02377       fprintf (fout,"#nI\tC\n\n");
02378       
02379       for (i=0; i < SO->N_Node; ++i) {
02380          fprintf (fout,"%d\t%f\n", i, SO->Cx[i]);
02381       }
02382       
02383       fclose(fout); fout = NULL;
02384    }   
02385    
02386    SUMA_LH("Clean up");
02387    /* clean up */
02388    if (MetricList) SUMA_free(MetricList);
02389    if (OutPrefix) SUMA_free(OutPrefix);
02390    if (OutName) SUMA_free(OutName);   
02391    if (SO) SUMA_Free_Surface_Object(SO);
02392    
02393    return(0);
02394 } /* Main */
02395 #endif
02396 
02397 #ifdef SUMA_Read_SpecFile_STAND_ALONE
02398 
02399 void usage_SUMA_Read_SpecFile ()
02400    
02401   {/*Usage*/
02402           printf ("\n\33[1mUsage: \33[0m SUMA_Read_SpecFile <fname> \n");
02403           printf ("\t <fname> Filename of Surface Specs file\n");
02404           printf ("To compile: \ngcc -DSUMA_Read_SpecFile_STAND_ALONE -Wall -o SUMA_Load_Surface_Object  SUMA_Load_Surface_Object.c ");
02405           printf ("SUMA_lib.a libmri.a -I/usr/X11R6/include -I./ -L/usr/lib -L/usr/X11R6/lib -lm \n");
02406           printf ("\t\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \n");
02407           exit (0);
02408   }/*Usage*/
02409   
02410 int main (int argc,char *argv[])
02411 {/* Main */
02412    char FuncName[]={"Main_SUMA_Read_SpecFile"};
02413    SUMA_SurfSpecFile Spec;   
02414    
02415    if (argc < 2)
02416        {
02417           usage_SUMA_Read_SpecFile ();
02418           exit (1);
02419        }
02420 
02421    /* allocate space for CommonFields structure */
02422    SUMAg_CF = SUMA_Create_CommonFields ();
02423    if (SUMAg_CF == NULL) {
02424       fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
02425       exit(1);
02426    }
02427    
02428 
02429    if (!SUMA_Read_SpecFile (argv[1], &Spec)) {
02430       fprintf(SUMA_STDERR,"Error %s: Error in SUMA_Read_SpecFile\n", FuncName);
02431       if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
02432       return (1);
02433    }   else    {      
02434       if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
02435       return (0);
02436    }
02437 } /* Main */
02438 
02439 #endif
02440 
02441 #ifdef SUMA_Load_Surface_Object_STAND_ALONE
02442 
02443 void usage_SUMA_Load_Surface_Object_STAND_ALONE ()
02444    
02445   {/*Usage*/
02446           printf ("\n\33[1mUsage: \33[0m SUMA_Load_Surface_Object <SurfName> [<Type> <format>]\n");
02447           printf ("\t <SurfName> Filename of Surface Object\n");
02448           printf ("\t <Type>: 2 (hard coded at the moment for SUMA_INVENTOR_GENERIC)\n");
02449           printf ("\t <format>: 0 (hard coded at the moment for SUMA_ASCII\n"); 
02450           printf ("To compile: \ngcc -DSUMA_Load_Surface_Object_STAND_ALONE -Wall -o SUMA_Load_Surface_Object SUMA_Load_Surface_Object.c ");
02451           printf ("SUMA_lib.a  -I/usr/X11R6/include -I./ -L/usr/lib -L/usr/X11R6/lib -lm \n");
02452           printf ("-lGL -lGLU -lGLw -lXmu -lXm -lXt -lXext -lX11 -lMesaGLw -lMesaGLw\n");
02453           printf ("\t\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \tWed Jan 23 15:18:12 EST 2002 \n");
02454           exit (0);
02455   }/*Usage*/
02456    
02457 int main (int argc,char *argv[])
02458 {/* Main */
02459    char FuncName[100]; 
02460    SUMA_SurfaceObject *SO;
02461    
02462    /* allocate space for CommonFields structure */
02463    SUMAg_CF = SUMA_Create_CommonFields ();
02464    if (SUMAg_CF == NULL) {
02465       fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
02466       exit(1);
02467    }
02468    
02469    /* initialize Main function name for verbose output */
02470    sprintf (FuncName,"SUMA_Load_Surface_Object-Main-");
02471    
02472    
02473    
02474    if (argc < 2)
02475        {
02476           usage_SUMA_Load_Surface_Object_STAND_ALONE ();
02477           exit (1);
02478        }
02479    
02480    SO = SUMA_Load_Surface_Object((void *)argv[1], SUMA_INVENTOR_GENERIC, SUMA_ASCII, NULL);
02481    SUMA_Print_Surface_Object (SO, stdout);
02482    SUMA_Free_Surface_Object (SO);
02483 
02484    if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
02485 
02486    return (0);
02487 }/* Main */
02488 #endif
02489 
02490 /*! function to return a string containing the name of the files 
02491 defining a surface object
02492 
02493    ans = SUMA_SurfaceFileName (SO, MitPath);
02494    \param SO (SUMA_SurfaceObject *) the surface object
02495    \param MitPath (SUMA_Boolean) if YUP then path is included
02496    \ret ans (char *) containing the name of the file from which the surface
02497       was loaded. If the surface is freesurfer format, the filename is 
02498       something like rh.smooth.asc. If it's a SureFit surface then you'll 
02499       get both .coord and .topo xxx.coord__yyy.topo
02500       ans is allocated in the function, of course, and must be freed after use
02501 */
02502 
02503 char * SUMA_SurfaceFileName (SUMA_SurfaceObject * SO, SUMA_Boolean MitPath)
02504 {
02505    static char FuncName[]={"SUMA_SurfaceFileName"};
02506    char *Name=NULL;
02507    int nalloc=0;
02508    
02509    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02510 
02511    /* check if recognizable type */
02512    switch (SO->FileType) {
02513       case SUMA_INVENTOR_GENERIC:
02514       case SUMA_FT_NOT_SPECIFIED:
02515          SUMA_error_message(FuncName, "SO_FileType not specified", 0);
02516          SUMA_RETURN (NULL);
02517          break;
02518       case SUMA_VEC:
02519          if (MitPath) nalloc = strlen(SO->Name_coord.Path) + strlen(SO->Name_coord.FileName) \
02520                            +    strlen(SO->Name_topo.Path) + strlen(SO->Name_topo.FileName) + 5;
02521          else nalloc = strlen(SO->Name_coord.FileName) \
02522                      +   strlen(SO->Name_topo.FileName) + 5;
02523          break;
02524       case SUMA_FREE_SURFER:
02525          if (MitPath) nalloc = strlen(SO->Name.Path) + strlen(SO->Name.FileName) + 5;
02526          else nalloc = strlen(SO->Name.FileName) + 5;
02527          break;
02528       case SUMA_SUREFIT:
02529          if (MitPath) nalloc = strlen(SO->Name_coord.Path) + strlen(SO->Name_coord.FileName) \
02530                            +    strlen(SO->Name_topo.Path) + strlen(SO->Name_topo.FileName) + 5;
02531          else nalloc = strlen(SO->Name_coord.FileName) \
02532                      +   strlen(SO->Name_topo.FileName) + 5;
02533          break;
02534       case SUMA_PLY:
02535          if (MitPath) nalloc = strlen(SO->Name.Path) + strlen(SO->Name.FileName) + 5;
02536          else nalloc = strlen(SO->Name.FileName) + 5;
02537          break;
02538       default:
02539          SUMA_error_message(FuncName, "SO_FileType not supported", 0);
02540          SUMA_RETURN (NULL);
02541          break;
02542    } 
02543 
02544    Name = (char *) SUMA_calloc (nalloc, sizeof(char));
02545    if (!Name) {
02546       fprintf (SUMA_STDERR,"Error %s: Could not allocate for Name.\n", FuncName);
02547       SUMA_RETURN (NULL);
02548    }
02549    
02550    switch (SO->FileType) {
02551       case SUMA_INVENTOR_GENERIC:
02552       case SUMA_FREE_SURFER:
02553          if (MitPath) sprintf(Name,"%s%s", SO->Name.Path, SO->Name.FileName);
02554          else sprintf(Name,"%s", SO->Name.FileName);
02555          break;
02556       case SUMA_SUREFIT:
02557          if (MitPath) sprintf(Name,"%s%s__%s%s", SO->Name_coord.Path, SO->Name_coord.FileName, \
02558                               SO->Name_topo.Path, SO->Name_topo.FileName);
02559          else sprintf(Name,"%s__%s", SO->Name_coord.FileName, SO->Name_topo.FileName);
02560          break;
02561       case SUMA_VEC:
02562          if (MitPath) sprintf(Name,"%s%s__%s%s", SO->Name_coord.Path, SO->Name_coord.FileName, \
02563                               SO->Name_topo.Path, SO->Name_topo.FileName);
02564          else sprintf(Name,"%s__%s", SO->Name_coord.FileName, SO->Name_topo.FileName);
02565          break;
02566       case SUMA_FT_NOT_SPECIFIED:
02567          break;
02568       case SUMA_PLY:
02569          if (MitPath) sprintf(Name,"%s%s", SO->Name.Path, SO->Name.FileName);
02570          else sprintf(Name,"%s", SO->Name.FileName);
02571          break;
02572    } 
02573    SUMA_RETURN (Name);
02574    
02575 }

Generated on Tue May 27 18:23:16 2003 for SUMA Source Code by doxygen1.2.12-20011209 written by Dimitri van Heesch, © 1997-2001