Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

SUMA_Surface_IO.c

Go to the documentation of this file.
00001 
00002 #include "SUMA_suma.h"
00003 #include "PLY/ply.h"
00004 
00005 #undef STAND_ALONE
00006 
00007 #if defined SUMA_SureFit_STAND_ALONE
00008 #define STAND_ALONE 
00009 #elif defined SUMA_FreeSurfer_STAND_ALONE
00010 #define STAND_ALONE
00011 #elif defined SUMA_Ply_Read_STAND_ALONE
00012 #define STAND_ALONE
00013 #elif defined SUMA_ConvertSurface_STAND_ALONE
00014 #define STAND_ALONE
00015 #endif
00016 
00017 #ifdef STAND_ALONE
00018 /* these global variables must be declared even if they will not be used by this main */
00019 SUMA_SurfaceViewer *SUMAg_cSV; /*!< Global pointer to current Surface Viewer structure*/
00020 SUMA_SurfaceViewer *SUMAg_SVv; /*!< Global pointer to the vector containing the various Surface Viewer Structures */
00021 int SUMAg_N_SVv = 0; /*!< Number of SVs stored in SVv */
00022 SUMA_DO *SUMAg_DOv;   /*!< Global pointer to Displayable Object structure vector*/
00023 int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */
00024 SUMA_CommonFields *SUMAg_CF; /*!< Global pointer to structure containing info common to all viewers */
00025 #else
00026 extern SUMA_CommonFields *SUMAg_CF;
00027 extern SUMA_DO *SUMAg_DOv;
00028 extern SUMA_SurfaceViewer *SUMAg_SVv;
00029 extern int SUMAg_N_SVv; 
00030 extern int SUMAg_N_DOv;  
00031 #endif
00032    
00033 /* CODE */
00034    
00035    
00036    
00037 /*!**  
00038 Function: SUMA_SureFit_Read_Coord 
00039 Usage : 
00040 Ret = SUMA_SureFit_Read_Coord (coordname, SureFit)
00041    
00042    
00043 Input paramters : 
00044 \param coordname (char *) name of .coord file
00045 \param SureFit (SUMA_SureFit_struct *) pointer to the SureFit structure
00046    
00047 Returns : 
00048 \return  (SUMA_Boolean) YUP/NOPE for success/failure
00049    
00050 Support : 
00051 \sa   
00052 \sa   
00053    
00054 Side effects : 
00055    
00056    
00057    
00058 ***/
00059 SUMA_Boolean SUMA_SureFit_Read_Coord (char * f_name, SUMA_SureFit_struct *SF)
00060 {/*SUMA_SureFit_Read_Coord*/
00061    static char FuncName[]={"SUMA_SureFit_Read_Coord"}; 
00062    FILE *sf_file;
00063         int ex, EndHead, FoundHead, evl, cnt, skp, ND, id;
00064         char stmp[100], head_strt[100], head_end[100], s[1000], delimstr[] = {' ', '\0'}, *st;
00065         
00066         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00067         
00068         ND = 3;
00069         
00070         /* check for existence */
00071         if (!SUMA_filexists(f_name)) {
00072                 fprintf(SUMA_STDERR,"File %s does not exist or cannot be read.\n", f_name);
00073                 SUMA_RETURN (NOPE);
00074         }
00075         
00076         sprintf(SF->name_coord, "%s", f_name);
00077         
00078         /* start reading */
00079         sf_file = fopen (f_name,"r");
00080         if (sf_file == NULL)
00081                 {
00082                         SUMA_error_message (FuncName,"Could not open input file ",0);
00083                         SUMA_RETURN (NOPE);
00084                 }
00085 
00086         /* read until you reach the begin header BeginHeader */
00087         ex = 1;
00088         FoundHead = 0;
00089         sprintf(head_strt,"BeginHeader");
00090         while (ex != EOF && !FoundHead)
00091         {
00092                 ex = fscanf (sf_file,"%s",s);
00093                 if (strlen (s) >= strlen(head_strt)) 
00094                         {
00095                                 evl = SUMA_iswordin (s,head_strt);
00096                                 if (evl == 1) FoundHead = 1;
00097                         }
00098         }
00099         
00100         if (!FoundHead) {
00101                 fprintf(SUMA_STDERR,"Error %s: BeginHeader not found in %s.\nPerhaps you are using old versions of Caret/SureFit files.\n", FuncName, f_name);
00102                 SUMA_RETURN (NOPE);
00103         }
00104         EndHead = 0;
00105         sprintf(head_end,"EndHeader");
00106         sprintf(delimstr," ");
00107         
00108         while (ex != EOF && !EndHead)   {
00109                 ex = fscanf (sf_file,"%s",s);
00110                 /*fprintf(stdout,"%s\n", s);*/
00111                 if (strlen (s) >= strlen(head_end)) 
00112                         {
00113                                 evl = SUMA_iswordin (s,head_end);
00114                                 if (evl == 1) EndHead = 1;
00115                         }
00116                 /* look for some tokens */
00117                 skp = 0;
00118                 if (!EndHead) {
00119                         st = strtok(s, delimstr);
00120                         sprintf(stmp,"encoding");
00121                         if (!skp && SUMA_iswordin (st, stmp) == 1) {
00122                                 /*fprintf(stdout,"Found encoding\n");*/
00123                                 ex = fscanf (sf_file,"%s",(SF->encoding_coord));
00124                                 skp = 1;
00125                         }
00126                         
00127                         sprintf(stmp,"configuration_id");
00128                         if (!skp && SUMA_iswordin (st, stmp) == 1) {
00129                                 /*fprintf(stdout,"Found configuration_id\n");*/
00130                                 ex = fscanf (sf_file,"%s",(SF->configuration_id));
00131                                 skp = 1;
00132                         }
00133                         
00134                         sprintf(stmp,"coordframe_id");
00135                         if (!skp && SUMA_iswordin (st, stmp) == 1) {
00136                                 /*fprintf(stdout,"Found configuration_id\n");*/
00137                                 ex = fscanf (sf_file,"%s",(SF->coordframe_id));
00138                                 skp = 1;
00139                         }
00140 
00141                 }
00142         }
00143         /* Now read the Number of Nodes */
00144         fscanf(sf_file, "%d", &SF->N_Node);
00145         /*fprintf (stdout,"Expecting %d nodes.\n", SF->N_Node);*/
00146         
00147         /* allocate space */
00148         SF->NodeList = (float *)SUMA_calloc(SF->N_Node * ND, sizeof(float));
00149         SF->NodeId = (int *)SUMA_calloc (SF->N_Node, sizeof(int));
00150         
00151         if (SF->NodeList == NULL || SF->NodeId == NULL) {
00152                 fprintf(SUMA_STDERR, "Error %s: Could not allocate space for NodeList &/| NodeId.\n", FuncName);
00153                 SUMA_RETURN (NOPE);
00154         }
00155         
00156         /* Now read the nodes until the end of the file */
00157                 cnt = 0;
00158                 while (ex != EOF && cnt < SF->N_Node)   {
00159                         id = cnt * ND;
00160                         ex = fscanf (sf_file,"%d %f %f %f",&(SF->NodeId[cnt]), \
00161                                         &(SF->NodeList[id]), &(SF->NodeList[id+1]), &(SF->NodeList[id+2]));
00162                         ++cnt;
00163                 }
00164         if (cnt != SF->N_Node) {
00165                 fprintf(SUMA_STDERR, "Error %s: Expecting %d Nodes, read %d.\n", FuncName, SF->N_Node, cnt);
00166                 SUMA_RETURN (NOPE);
00167         }
00168         fclose (sf_file);
00169         SUMA_RETURN (YUP); 
00170 }/*SUMA_SureFit_Read_Coord*/
00171 
00172 SUMA_Boolean SUMA_SureFit_Read_Topo (char * f_name, SUMA_SureFit_struct *SF)
00173 {/*SUMA_SureFit_Read_Topo*/
00174         static char FuncName[]={"SUMA_SureFit_Read_Topo"}; 
00175    FILE *sf_file;
00176         int ex, EndHead, FoundHead, evl, cnt, skp, jnk, i, ip, NP;
00177         char stmp[100], head_strt[100], head_end[100], s[1000], delimstr[] = {' ', '\0'}, *st;
00178         
00179         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00180 
00181         /* check for existence */
00182         if (!SUMA_filexists(f_name)) {
00183                 fprintf(SUMA_STDERR,"File %s does not exist or cannot be read.\n", f_name);
00184                 SUMA_RETURN (NOPE);
00185         }
00186         
00187         sprintf(SF->name_topo, "%s", f_name);
00188         
00189         /* start reading */
00190         sf_file = fopen (f_name,"r");
00191         if (sf_file == NULL)
00192                 {
00193                         SUMA_error_message (FuncName,"Could not open input file ",0);
00194                         SUMA_RETURN (NOPE);
00195                 }
00196 
00197         /* read until you reach the begin header BeginHeader */
00198         ex = 1;
00199         FoundHead = 0;
00200         sprintf(head_strt,"BeginHeader");
00201         while (ex != EOF && !FoundHead)
00202         {
00203                 ex = fscanf (sf_file,"%s",s);
00204                 if (strlen (s) >= strlen(head_strt)) 
00205                         {
00206                                 evl = SUMA_iswordin (s,head_strt);
00207                                 if (evl == 1) FoundHead = 1;
00208                         }
00209         }
00210         if (!FoundHead) {
00211                 fprintf(SUMA_STDERR,"Error %s: BeginHeader not found in %s.\nPerhaps you are using old versions of Caret/SureFit files.\n", FuncName, f_name);
00212                 SUMA_RETURN (NOPE);
00213         }
00214         EndHead = 0;
00215         sprintf(head_end,"EndHeader");
00216         sprintf(delimstr," ");
00217         
00218         while (ex != EOF && !EndHead)   {
00219                 ex = fscanf (sf_file,"%s",s);
00220                 /*fprintf(stdout,"%s\n", s);*/
00221                 if (strlen (s) >= strlen(head_end)) 
00222                         {
00223                                 evl = SUMA_iswordin (s,head_end);
00224                                 if (evl == 1) EndHead = 1;
00225                         }
00226                 /* look for some tokens */
00227                 skp = 0;
00228                 if (!EndHead) {
00229                         st = strtok(s, delimstr);
00230                         sprintf(stmp,"encoding");
00231                         if (!skp && SUMA_iswordin (st, stmp) == 1) {
00232                                 /*fprintf(stdout,"Found encoding\n");*/
00233                                 ex = fscanf (sf_file,"%s",(SF->encoding_topo));
00234                                 skp = 1;
00235                         }
00236                         
00237                         sprintf(stmp,"perimeter_id");
00238                         if (!skp && SUMA_iswordin (st, stmp) == 1) {
00239                                 /*fprintf(stdout,"Found perimeter_id\n");*/
00240                                 ex = fscanf (sf_file,"%s",(SF->perimeter_id));
00241                                 skp = 1;
00242                         }
00243                         
00244                         sprintf(stmp,"date");
00245                         if (!skp && SUMA_iswordin (st, stmp) == 1) {
00246                                 /*fprintf(stdout,"Found date\n");*/
00247                                 ex = fscanf (sf_file,"%s\n",(SF->date));
00248                                 skp = 1;
00249                         }
00250 
00251                 }
00252         }
00253         /* Now read the Number of Nodes Specs */
00254         fscanf(sf_file, "%d", &SF->N_Node_Specs);
00255         /*fprintf (stdout,"Expecting %d Node_Specs.\n", SF->N_Node_Specs);*/
00256         
00257         SF->FN.N_Node = SF->N_Node_Specs;
00258         SF->FN.N_Neighb_max = 0;
00259 
00260         /* allocate for Node Specs Matrix and First_Neighb structure*/
00261         SF->Specs_mat = (int **) SUMA_allocate2D(SF->N_Node_Specs, 6, sizeof(int));
00262         /*assume maximum number of neighbors is SUMA_MAX_NUMBER_NODE_NEIGHB */
00263         SF->FN.FirstNeighb = (int **) SUMA_allocate2D(SF->FN.N_Node, SUMA_MAX_NUMBER_NODE_NEIGHB, sizeof (int));
00264         SF->FN.N_Neighb = (int *) SUMA_calloc (SF->FN.N_Node, sizeof(int));
00265         SF->FN.NodeId = (int *) SUMA_calloc (SF->FN.N_Node, sizeof(int));
00266         
00267         if (SF->Specs_mat == NULL || SF->FN.FirstNeighb == NULL || SF->FN.N_Neighb == NULL || SF->FN.NodeId == NULL ){
00268                 fprintf(SUMA_STDERR, "Error %s: Could not allocate space for SF->Specs_mat &/| SF->FN.FirstNeighb &/| SF->FN.N_Neighb &/| SF->FN.NodeId.\n", FuncName);
00269                 SUMA_RETURN (NOPE);
00270         } 
00271         
00272         /* Now read the node specs */
00273         /*fprintf (stdout,"About to read specs\n");*/
00274         cnt = 0;
00275         while (ex != EOF && cnt < SF->N_Node_Specs)     {
00276                 ex = fscanf (sf_file,"%d %d %d %d %d %d",&(SF->Specs_mat[cnt][0]), &(SF->Specs_mat[cnt][1]), \
00277                                 &(SF->Specs_mat[cnt][2]), &(SF->Specs_mat[cnt][3]), &(SF->Specs_mat[cnt][4]), &(SF->Specs_mat[cnt][5]));
00278                 SF->FN.NodeId[cnt] = SF->Specs_mat[cnt][0];
00279                 SF->FN.N_Neighb[cnt] = SF->Specs_mat[cnt][1];
00280                 if (SF->FN.N_Neighb[cnt] > SUMA_MAX_NUMBER_NODE_NEIGHB-1) {
00281                         fprintf (SUMA_STDERR,"Error %s: Node %d has more neighbors (%d) than the maximum allowed (%d)\n", \
00282                                 FuncName, SF->FN.NodeId[cnt], SF->FN.N_Neighb[cnt], SUMA_MAX_NUMBER_NODE_NEIGHB-1);
00283                         SUMA_RETURN (NOPE);
00284                 }
00285                 if (SF->FN.N_Neighb[cnt] > SF->FN.N_Neighb_max) SF->FN.N_Neighb_max = SF->FN.N_Neighb[cnt];
00286                 
00287                 /* Now Read in the Neighbors info */
00288                 for (i=0; i < SF->FN.N_Neighb[cnt]; ++ i) {
00289                         ex = fscanf (sf_file,"%d %d", &jnk, &(SF->FN.FirstNeighb[cnt][i]));
00290                 }
00291                 /* seal with -1 */
00292                 SF->FN.FirstNeighb[cnt][SF->FN.N_Neighb[cnt]] = -1;
00293                 
00294                 ++cnt;
00295         }
00296         if (cnt != SF->N_Node_Specs) {
00297                 fprintf(SUMA_STDERR, "Error %s: Expecting %d NodeSpecs, read %d.\n", FuncName, SF->N_Node_Specs, cnt);
00298                 SUMA_RETURN (NOPE);
00299         }
00300         /*fprintf (stdout, "Done with Node Specs.\n");*/
00301         ex = fscanf (sf_file,"%d", &(SF->N_FaceSet));
00302         /*fprintf (stdout, "Expecting to read %d facesets.\n", SF->N_FaceSet);*/
00303         
00304         NP = 3;
00305         SF->FaceSetList = (int *) SUMA_calloc(SF->N_FaceSet * 3, sizeof(int));
00306         if (SF->FaceSetList == NULL){
00307                 fprintf(SUMA_STDERR, "Error %s: Could not allocate space for SF->FaceSetList.\n", FuncName);
00308                 SUMA_RETURN (NOPE);
00309         } 
00310         
00311         /*fprintf (stdout,"About to read FaceSets\n");*/
00312         cnt = 0;
00313         while (ex != EOF && cnt < SF->N_FaceSet)        {
00314                 ip = NP * cnt;
00315                 ex = fscanf (sf_file,"%d %d %d ",&(SF->FaceSetList[ip]), &(SF->FaceSetList[ip+1]), \
00316                                 &(SF->FaceSetList[ip+2]));
00317                 ++cnt;
00318         }
00319         if (cnt != SF->N_FaceSet) {
00320                 fprintf(SUMA_STDERR, "Error %s: Expecting %d FaceSets, read %d.\n", FuncName, SF->N_FaceSet, cnt);
00321                 SUMA_RETURN (NOPE);
00322         }
00323         fclose (sf_file);
00324         
00325 SUMA_RETURN (YUP);
00326 }/*SUMA_SureFit_Read_Topo*/
00327 
00328 /*!
00329 Show data structure containing SureFit surface object
00330 */
00331 void SUMA_Show_SureFit (SUMA_SureFit_struct *SF, FILE *Out)
00332 {       int cnt, id, ND, NP;
00333         static char FuncName[]={"SUMA_Show_SureFit"};
00334         
00335         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00336 
00337         ND = 3;
00338         NP = 3;
00339         if (Out == NULL) Out = SUMA_STDOUT;
00340         fprintf (Out, "\n%s: Coord Info\n", SF->name_coord);
00341         fprintf (Out, "N_Node %d\n", SF->N_Node);
00342         fprintf (Out, "encoding_coord: %s\nconfiguration id: %s, coordframe_id: %s\n", SF->encoding_coord,SF->configuration_id, SF->coordframe_id);
00343         fprintf (Out, "First 2 points [id] X Y Z:\n\t[%d] %f %f %f\n\t[%d] %f %f %f\n", \
00344                 SF->NodeId[0], SF->NodeList[0], SF->NodeList[1], SF->NodeList[2],
00345                 SF->NodeId[1], SF->NodeList[3], SF->NodeList[4], SF->NodeList[5]);
00346         if (SF->N_Node > 2) {
00347       fprintf (Out, "Last 2 points [id] X Y Z:\n\t[%d] %f %f %f\n\t[%d] %f %f %f\n", \
00348                    SF->NodeId[SF->N_Node-2], SF->NodeList[ND*(SF->N_Node-2)], SF->NodeList[ND*(SF->N_Node-2)+1], SF->NodeList[ND*(SF->N_Node-2)+2],
00349                    SF->NodeId[SF->N_Node-1], SF->NodeList[ND*(SF->N_Node-1)], SF->NodeList[ND*(SF->N_Node-1)+1], SF->NodeList[ND*(SF->N_Node-1)+2]);
00350         }
00351    fprintf (Out, "\n%s: Topo Info\n", SF->name_topo);
00352         fprintf (Out, "N_Node_Specs %d\n", SF->N_Node_Specs);
00353         fprintf (Out, "ecnoding_topo: %s, date %s\n",  SF->encoding_topo, SF->date);
00354         fprintf (Out, "N_FaceSet %d\n", SF->N_FaceSet);
00355         if (SF->N_FaceSet > 2) {
00356            fprintf (Out, "First 2 polygons:\n\t%d %d %d\n\t%d %d %d\n", \
00357                    SF->FaceSetList[0], SF->FaceSetList[1], SF->FaceSetList[2],
00358                    SF->FaceSetList[3], SF->FaceSetList[4], SF->FaceSetList[5]);
00359       fprintf (Out, "Last 2 polygons:\n\t%d %d %d\n\t%d %d %d\n", \
00360                    SF->FaceSetList[NP*(SF->N_FaceSet-2)], SF->FaceSetList[NP*(SF->N_FaceSet-2) + 1], SF->FaceSetList[NP*(SF->N_FaceSet-2) + 2],
00361                    SF->FaceSetList[NP*(SF->N_FaceSet-1)], SF->FaceSetList[NP*(SF->N_FaceSet-1) + 1], SF->FaceSetList[NP*(SF->N_FaceSet-1) + 2]);
00362         } else {
00363       fprintf (Out, "First polygon:\n\t%d %d %d\n", \
00364                    SF->FaceSetList[0], SF->FaceSetList[1], SF->FaceSetList[2] );
00365    }
00366    fprintf (Out, "\nNode Specs (%d):\n", SF->N_Node_Specs);
00367         fprintf (Out, "First Entry: \t%d %d %d %d %d %d\n", \
00368         SF->Specs_mat[0][0], SF->Specs_mat[0][1],SF->Specs_mat[0][2], SF->Specs_mat[0][3],SF->Specs_mat[0][4], SF->Specs_mat[0][5]);
00369         cnt = 0;
00370         while (cnt < SF->FN.N_Neighb[0]) {
00371                 fprintf (Out, "\t%d %d\n", cnt, SF->FN.FirstNeighb[0][cnt]); 
00372                 ++cnt;
00373         }
00374         fprintf (Out, "Last Entry: \t%d %d %d %d %d %d\n", \
00375                 SF->Specs_mat[SF->N_Node_Specs-1][0], SF->Specs_mat[SF->N_Node_Specs-1][1],SF->Specs_mat[SF->N_Node_Specs-1][2],\
00376                 SF->Specs_mat[SF->N_Node_Specs-1][3],SF->Specs_mat[SF->N_Node_Specs-1][4], SF->Specs_mat[SF->N_Node_Specs-1][5]);
00377         cnt = 0;
00378         while (cnt < SF->FN.N_Neighb[SF->N_Node_Specs-1]) {
00379                 fprintf (Out, "\t%d %d\n", cnt, SF->FN.FirstNeighb[SF->N_Node_Specs-1][cnt]); 
00380                 ++cnt;
00381         }
00382 
00383         SUMA_RETURNe;
00384 }
00385 
00386 /*!
00387    \brief writes a surface in SureFit format
00388    ans = SUMA_SureFit_Write (Fname,SO);
00389    
00390    \param  Fname (SUMA_SFname *) uses the SureFit filename structure to store
00391                                  the names (and paths) of the NodeList (name_coord)
00392                                  and the FaceSetList (name_topo) files.
00393    \param SO (SUMA_SurfaceObject *) pointer to SO structure.
00394    \return YUP/NOPE
00395    
00396    \sa SUMA_SureFit_Read_Topo() 
00397    \sa SUMA_SureFit_Read_Coord() 
00398    
00399    The function will not overwrite pre-existing files.
00400    
00401 
00402 NOTE: Header info is incomplete. 
00403 for .coord:
00404 BeginHeader
00405 configuration_id NA
00406 coordframe_id NA
00407 encoding ASCII
00408 EndHeader
00409 
00410 for .topo:
00411 BeginHeader
00412 date NA
00413 encoding ASCII
00414 perimeter_id NA
00415 EndHeader
00416 
00417 also, the last 4 integers in the node neighbor list lines are set to 0. I have never used them and do not know what they are for.
00418 
00419 The naming convention of SureFit surfaces is not enforced.
00420 
00421 */  
00422 SUMA_Boolean SUMA_SureFit_Write (SUMA_SFname *Fname, SUMA_SurfaceObject *SO)
00423 {
00424    
00425    static char FuncName[]={"SUMA_SureFit_Write"};
00426    int i, j;
00427    FILE *outFile = NULL;
00428    
00429    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00430 
00431    if (SUMA_filexists(Fname->name_coord)) {
00432       fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n",FuncName, Fname->name_coord);
00433       SUMA_RETURN (NOPE);
00434    }
00435    if (SUMA_filexists(Fname->name_topo)) {
00436       fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n",FuncName, Fname->name_topo);
00437       SUMA_RETURN (NOPE);
00438    }
00439    if (SO->NodeDim != 3 || SO->FaceSetDim != 3) {
00440       fprintf (SUMA_STDERR, "Error %s: Must have NodeDim and FaceSetDim = 3.\n",FuncName);
00441       SUMA_RETURN (NOPE);
00442    }
00443    
00444    outFile = fopen(Fname->name_coord, "w");
00445    if (!outFile) {
00446       fprintf (SUMA_STDERR, "Error %s: Failed in opening %s for writing.\n",FuncName, Fname->name_coord);
00447       SUMA_RETURN (NOPE);
00448    }
00449    
00450    /* write header */
00451    fprintf (outFile,"BeginHeader\nconfiguration_id NA\ncoordframe_id NA\nencoding ASCII\nEndHeader\n");
00452    fprintf (outFile,"%d\n", SO->N_Node);
00453 
00454    j=0;
00455    for (i=0; i<SO->N_Node; ++i) {
00456       j=SO->NodeDim * i;
00457       fprintf (outFile, "%d %f %f %f\n", i, SO->NodeList[j], SO->NodeList[j+1], SO->NodeList[j+2]);
00458    }
00459    
00460    fclose (outFile);
00461    
00462    outFile = fopen(Fname->name_topo, "w");
00463    if (!outFile) {
00464       fprintf (SUMA_STDERR, "Error %s: Failed in opening %s for writing.\n",FuncName, Fname->name_topo);
00465       SUMA_RETURN (NOPE);
00466    }
00467 
00468    /* make sure you have the first neighbor list ! */
00469    if (!SO->FN) {
00470       fprintf (SUMA_STDERR, "%s: Must compute Node Neighborhood list.\n", FuncName);
00471       if (!SUMA_SurfaceMetrics(SO, "EdgeList", NULL)){
00472          fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
00473          SUMA_RETURN (NOPE);
00474       }
00475       #if 0 /* better to use SUMA_SurfaceMetrics */
00476       if (!SO->EL) {
00477          fprintf (SUMA_STDERR, "%s: Computing Edge List...\n", FuncName);
00478          SO->EL = SUMA_Make_Edge_List (SO->FaceSetList, SO->N_FaceSet, SO->N_Node, SO->NodeList);
00479       }
00480       if (!SO->EL) {
00481          fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Make_Edge_List.\n", FuncName);
00482          SUMA_RETURN (NOPE);
00483       }
00484       fprintf (SUMA_STDERR, "%s: Computing FirstNeighb list.\n", FuncName);
00485       SO->FN = SUMA_Build_FirstNeighb (SO->EL, SO->N_Node);
00486       if (!SO->FN) {
00487          fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Build_FirstNeighb.\n", FuncName);
00488          SUMA_RETURN (NOPE);
00489       }
00490       #endif
00491       
00492    }
00493    /* write header */
00494    fprintf (outFile,"BeginHeader\ndate NA\nencoding ASCII\nperimeter_id NA\nEndHeader\n");
00495    fprintf (outFile,"%d\n", SO->N_Node);
00496         j = 0;
00497         while (j < SO->FN->N_Node)      {
00498       /* dunno what last 4 ints of upcoming line are */
00499                 fprintf (outFile,"%d %d 0 0 0 0\n", SO->FN->NodeId[j], SO->FN->N_Neighb[j]);
00500                 
00501                 /* Now write the Neighbors info */
00502                 for (i=0; i < SO->FN->N_Neighb[j]; ++ i) {
00503                         fprintf (outFile,"%d %d\n", i, SO->FN->FirstNeighb[j][i]);
00504                 }
00505                 ++j;
00506         }
00507 
00508         fprintf (outFile,"%d\n", SO->N_FaceSet);
00509         
00510    j=0;
00511    for (i=0; i<SO->N_FaceSet; ++i) {
00512       j = SO->FaceSetDim * i;
00513       fprintf (outFile, "%d %d %d\n", SO->FaceSetList[j], SO->FaceSetList[j+1], SO->FaceSetList[j+2]);
00514    }
00515 
00516    fclose (outFile);
00517    SUMA_RETURN (YUP);
00518 
00519 }
00520 
00521 /*!
00522 free data structure containing SureFit surface object
00523 */
00524 SUMA_Boolean SUMA_Free_SureFit (SUMA_SureFit_struct *SF)  
00525 {
00526         static char FuncName[]={"SUMA_Free_SureFit"};
00527         
00528         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00529 
00530         if (SF->NodeList != NULL) SUMA_free(SF->NodeList);
00531         if (SF->NodeId != NULL) SUMA_free(SF->NodeId);
00532         if (SF->Specs_mat != NULL) SUMA_free2D ((char **)SF->Specs_mat, SF->N_Node_Specs);
00533         if (SF->FN.FirstNeighb != NULL) SUMA_free2D((char **)SF->FN.FirstNeighb, SF->FN.N_Node);
00534         if (SF->FN.N_Neighb != NULL) SUMA_free(SF->FN.N_Neighb);
00535         if (SF->FN.NodeId != NULL) SUMA_free(SF->FN.NodeId);
00536         if (SF->FaceSetList != NULL) SUMA_free(SF->FaceSetList);
00537         if (SF!= NULL) SUMA_free(SF);
00538         
00539         SUMA_RETURN (YUP);
00540 }
00541 
00542 /*!
00543 Read in some parameters from a .param file
00544 */
00545 SUMA_Boolean SUMA_Read_SureFit_Param (char *f_name, SUMA_SureFit_struct *SF)
00546 {
00547         static char FuncName[]={"SUMA_Read_SureFit_Param"};
00548         int ex, evl; 
00549    FILE *sf_file;
00550         SUMA_Boolean Done;
00551         char delimstr[] = {' ', '\0'}, stmp[100], s[1000], *st;
00552 
00553         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00554 
00555         /* check for existence */
00556         if (!SUMA_filexists(f_name)) {
00557                 fprintf(SUMA_STDERR,"File %s does not exist or cannot be read.\n", f_name);
00558                 SUMA_RETURN (NOPE);
00559         }
00560 
00561         sprintf(SF->name_param, "%s", f_name);
00562 
00563         /* start reading */
00564         sf_file = fopen (f_name,"r");
00565         if (sf_file == NULL)
00566                 {
00567                         fprintf (SUMA_STDERR,"Error %s: Could not open input file ",FuncName);
00568                         SUMA_RETURN (NOPE);
00569                 }
00570 
00571         /* read until you reach something you like */
00572         ex = 1;
00573         Done = NOPE;                    
00574         sprintf(delimstr,"=");
00575         while (ex != EOF && !Done)
00576         {
00577                 ex = fscanf (sf_file,"%s",s);
00578                 
00579                 sprintf(stmp,"ACx_WholeVolume");
00580                 evl = SUMA_iswordin (s,stmp);
00581                 if (evl == 1) {
00582                         /* found ACx_WholeVolume */
00583                         /*fprintf(SUMA_STDOUT, "Found ACx_WholeVolume:");*/
00584                         /* go past the = sign and grab the value */
00585                         st = strtok(s, delimstr);
00586                         st = strtok(NULL, delimstr);
00587                         SF->AC_WholeVolume[0] = atof(st);
00588                         /*fprintf(SUMA_STDOUT, " %f\n", SF->AC_WholeVolume[0]);*/
00589                         continue;
00590                 }
00591                 sprintf(stmp,"ACy_WholeVolume");
00592                 evl = SUMA_iswordin (s,stmp);
00593                 if (evl == 1) {
00594                         /* found ACy_WholeVolume */
00595                         /*fprintf(SUMA_STDOUT, "Found ACy_WholeVolume:");*/
00596                         /* go past the = sign and grab the value */
00597                         st = strtok(s, delimstr);
00598                         st = strtok(NULL, delimstr);
00599                         SF->AC_WholeVolume[1] = atof(st);
00600                         /*fprintf(SUMA_STDOUT, " %f\n", SF->AC_WholeVolume[1]);*/
00601                         continue;
00602                 }
00603                 sprintf(stmp,"ACz_WholeVolume");
00604                 evl = SUMA_iswordin (s,stmp);
00605                 if (evl == 1) {
00606                         /* found ACz_WholeVolume */
00607                         /*fprintf(SUMA_STDOUT, "Found ACz_WholeVolume:");*/
00608                         /* go past the = sign and grab the value */
00609                         st = strtok(s, delimstr);
00610                         st = strtok(NULL, delimstr);
00611                         SF->AC_WholeVolume[2] = atof(st);
00612                         /*fprintf(SUMA_STDOUT, " %f\n", SF->AC_WholeVolume[2]);*/
00613                         continue;
00614                 }
00615                  
00616                 sprintf(stmp,"ACx");
00617                 evl = SUMA_iswordin (s,stmp);
00618                 if (evl == 1) {
00619                         /* found ACx */
00620                         /*fprintf(SUMA_STDOUT, "Found ACx:");*/
00621                         /* go past the = sign and grab the value */
00622                         st = strtok(s, delimstr);
00623                         st = strtok(NULL, delimstr);
00624                         SF->AC[0] = atof(st);
00625                         /*fprintf(SUMA_STDOUT, " %f\n", SF->AC[0]);*/
00626                         continue;
00627                 }
00628                 sprintf(stmp,"ACy");
00629                 evl = SUMA_iswordin (s,stmp);
00630                 if (evl == 1) {
00631                         /* found ACy */
00632                         /*fprintf(SUMA_STDOUT, "Found ACy:");*/
00633                         /* go past the = sign and grab the value */
00634                         st = strtok(s, delimstr);
00635                         st = strtok(NULL, delimstr);
00636                         SF->AC[1] = atof(st);
00637                         /*fprintf(SUMA_STDOUT, " %f\n", SF->AC[1]);*/
00638                         continue;
00639                 }
00640                 sprintf(stmp,"ACz");
00641                 evl = SUMA_iswordin (s,stmp);
00642                 if (evl == 1) {
00643                         /* found ACz */
00644                         /*fprintf(SUMA_STDOUT, "Found ACz:");*/
00645                         /* go past the = sign and grab the value */
00646                         st = strtok(s, delimstr);
00647                         st = strtok(NULL, delimstr);
00648                         SF->AC[2] = atof(st);
00649                         /*fprintf(SUMA_STDOUT, " %f\n", SF->AC[2]);*/
00650                         continue;
00651                 }
00652                 
00653         }
00654         
00655         fclose(sf_file);
00656         
00657         /* Sanity Checks */
00658         if (SF->AC[0] == 0.0 && SF->AC[1] == 0.0 && SF->AC[2] == 0.0) {
00659                 fprintf (SUMA_STDERR,"Error %s: All values for AC are 0.0. Check your params file.\n", FuncName);
00660                 SUMA_RETURN (NOPE);
00661         }
00662         
00663         if (SF->AC_WholeVolume[0] == 0.0 && SF->AC_WholeVolume[1] == 0.0 && SF->AC_WholeVolume[2] == 0.0) {
00664                 fprintf (SUMA_STDERR,"Error %s: All values for AC_WholeVolume are 0.0. Check your params file.\n", FuncName);
00665                 SUMA_RETURN (NOPE);
00666         }
00667         
00668         if (SF->AC[0] == SF->AC_WholeVolume[0] && SF->AC[1] == SF->AC_WholeVolume[1] && SF->AC[2] == SF->AC_WholeVolume[2])
00669         {
00670                 fprintf (SUMA_STDERR,"Error %s: Idetincal values for AC and AC_WholeVolume. Check you params file.\n", FuncName);
00671                 SUMA_RETURN (NOPE);
00672         }
00673         if (SF->AC[0] < 0 || SF->AC[1] < 0 || SF->AC[2] < 0 || SF->AC_WholeVolume[0] < 0 || SF->AC_WholeVolume[1] < 0 || SF->AC_WholeVolume[2] < 0) 
00674         {
00675                 fprintf (SUMA_STDERR,"Error %s: Negative values in AC or AC_WholeVolume. Check you params file.\n", FuncName);
00676                 SUMA_RETURN (NOPE);
00677         }
00678         
00679         SUMA_RETURN (YUP);
00680 }
00681 #ifdef SUMA_SureFit_STAND_ALONE
00682 
00683 
00684 
00685 void usage_SUMA_SureFit_Main ()
00686    
00687   {/*Usage*/
00688           printf ("\n\33[1mUsage: \33[0m SUMA_SureFit CoordRoot TopoRoot \n");
00689           printf ("\t ..... \n\n");
00690           printf ("\t To Compile:\ngcc -DSUMA_SureFit_STAND_ALONE -Wall -o $1 $1.c -I./ -I//usr/X11R6/include SUMA_lib.a\n");
00691           printf ("\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \tFri Feb 8 16:29:06 EST 2002 \n");
00692           exit (0);
00693   }/*Usage*/
00694    
00695 int main (int argc,char *argv[])
00696 {/* Main */
00697    static char FuncName[]={"SUMA_SureFit_Main"}; 
00698    char SF_name[200];
00699         SUMA_SureFit_struct *SF;
00700         
00701         /* allocate space for CommonFields structure */
00702         SUMAg_CF = SUMA_Create_CommonFields ();
00703         if (SUMAg_CF == NULL) {
00704                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
00705                 exit(1);
00706         }
00707         
00708         /* Allocate for SF */
00709         SF = (SUMA_SureFit_struct *) SUMA_malloc(sizeof(SUMA_SureFit_struct));  
00710         if (SF == NULL) {
00711                 fprintf(SUMA_STDERR,"Error %s: Failed to allocate for SF\n", FuncName);
00712                 exit(1);
00713         }
00714    
00715    if (argc < 3)
00716        {
00717           usage_SUMA_SureFit_Main ();
00718           exit (1);
00719        }
00720    
00721         sprintf(SF_name, "%s.coord", argv[1]);
00722         if (!SUMA_SureFit_Read_Coord (SF_name, SF)) {
00723                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SureFit_Read_Coord.\n", FuncName);
00724                 exit(1);
00725         }
00726         
00727         sprintf(SF_name, "%s.topo", argv[2]);
00728         if (!SUMA_SureFit_Read_Topo (SF_name, SF)) {
00729                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SureFit_Read_Topo.\n", FuncName);
00730                 exit(1);
00731         }
00732         
00733         SUMA_Show_SureFit (SF, NULL);
00734         fprintf(stdout, "freeing ..\n");
00735         if (!SUMA_Free_SureFit (SF)) {
00736                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Free_SureFit.\n", FuncName);
00737                 exit(1);
00738         }
00739         
00740         if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
00741 
00742         SUMA_RETURN (0);
00743 }/* Main */
00744 #endif
00745 
00746 
00747 /*! Functions to read and manipulate FreeSurfer surfaces*/
00748 
00749 /* CODE */
00750    
00751    
00752    
00753 /*!**  
00754 Usage : 
00755 Ret = SUMA_FreeSurfer_Read (surfname, FreeSurfer)
00756         
00757         For a full surface definition, it is assumed that the first line can be a comment.
00758         The second line contains the number of nodes followed by the number of FaceSets
00759         The NodeList follows with X Y Z 0
00760         The FaceSetList follows with i1 i2 i3 0
00761    
00762         
00763 Input paramters : 
00764 \param surfname (char *) name of surface (or patch) file output by:
00765         mris_convert <surface_name> <surface_name.asc>
00766    or if it is a patch by
00767         mris_convert -p <patch_name> <patch_name.asc>
00768        
00769 \param FreeSurfer (SUMA_FreeSurfer_struct *) pointer to the FreeSurfer structure
00770    
00771 Returns : 
00772 \return  (SUMA_Boolean) YUP/NOPE for success/failure
00773    
00774 Support : 
00775 \sa   LoadFreeSurf.m
00776 \sa   
00777    
00778 Side effects : 
00779    
00780    
00781    
00782 ***/
00783 SUMA_Boolean SUMA_FreeSurfer_Read (char * f_name, SUMA_FreeSurfer_struct *FS)
00784 {/*SUMA_FreeSurfer_Read*/
00785    char stmp[50]; 
00786    FILE *fs_file;
00787         int ex, cnt, jnki, amax[3], maxamax, maxamax2, id, ND, id2, NP, ip, *NodeId;
00788         float jnkf, *NodeList;
00789         char c;
00790         static char FuncName[]={"SUMA_FreeSurfer_Read"};
00791         SUMA_Boolean LocalHead = NOPE;
00792            
00793         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00794 
00795         /* check for existence */
00796         if (!SUMA_filexists(f_name)) {
00797                 fprintf(SUMA_STDERR,"Error %s: File %s does not exist or cannot be read.\n", FuncName, f_name);
00798                 SUMA_RETURN (NOPE);
00799         }else {
00800                 fprintf(SUMA_STDERR,"%s: File %s exists and will be read.\n", FuncName, f_name);
00801         }
00802         
00803         
00804         /* start reading */
00805         fs_file = fopen (f_name,"r");
00806         if (fs_file == NULL)
00807                 {
00808                         SUMA_error_message (FuncName,"Could not open input file ",0);
00809                         SUMA_RETURN (NOPE);
00810                 }
00811 
00812         sprintf(FS->name, "%s", f_name);
00813         
00814         /* read first character and check if it is a comment */
00815         ex = fscanf (fs_file,"%c",&c);
00816         if (c == '#') {
00817                 if (LocalHead) fprintf (SUMA_STDOUT, "%s: Found comment\n", FuncName); 
00818                 
00819       /*skip till next line */
00820                 sprintf(FS->comment,"#"); 
00821                 cnt = 0;
00822                 while (ex != EOF && c != '\n') {
00823                         ex = fscanf (fs_file,"%c",&c);
00824                         if (cnt < SUMA_MAX_STRING_LENGTH-2) {
00825                                 sprintf(FS->comment, "%s%c", FS->comment, c);
00826                                 ++cnt;
00827                         } else {
00828                                 fprintf(SUMA_STDERR,"Error %s: Too long a comment in FS file, increase SUMA_FS_MAX_COMMENT_LENGTH\n", FuncName);
00829                                 SUMA_RETURN (NOPE);
00830                         }
00831                 }
00832         }
00833         
00834         /* find out if surface is patch */
00835         sprintf(stmp,"patch");
00836         if (SUMA_iswordin (FS->comment, stmp) == 1) {
00837                 FS->isPatch = YUP;
00838         }
00839         else {
00840                 FS->isPatch = NOPE;
00841         }
00842                 
00843         /* read in the number of nodes and the number of facesets */
00844         ex = fscanf(fs_file, "%d %d", &(FS->N_Node), &(FS->N_FaceSet));
00845         
00846         if (LocalHead) fprintf (SUMA_STDOUT, "%s: Allocating for NodeList (%dx3) and FaceSetList(%dx3)\n", FuncName, FS->N_Node, FS->N_FaceSet);
00847    
00848    /* allocate space for NodeList and FaceSetList */
00849         FS->NodeList = (float *)SUMA_calloc(FS->N_Node * 3, sizeof(float));
00850         FS->FaceSetList = (int *)SUMA_calloc(FS->N_FaceSet * 3, sizeof(int));
00851         FS->NodeId = (int *)SUMA_calloc(FS->N_Node, sizeof(int));
00852         if (FS->NodeList == NULL || FS->FaceSetList == NULL || FS->NodeId == NULL) {
00853                 fprintf(SUMA_STDERR,"Error %s: Could not allocate for FS->NodeList &/| FS->FaceSetList &/| FS->NodeId\n", FuncName);
00854                 SUMA_RETURN (NOPE);
00855         } 
00856         if (FS->isPatch) {
00857                 FS->FaceSetIndexInParent = (int *)SUMA_calloc(FS->N_FaceSet, sizeof(int));
00858                 if (FS->FaceSetIndexInParent == NULL) {
00859                         fprintf(SUMA_STDERR,"Error %s: Could not allocate for FS->FaceSetIndexInParent\n", FuncName);
00860                         SUMA_RETURN (NOPE);
00861                 }
00862         } else {
00863                 FS->FaceSetIndexInParent = NULL;
00864         }
00865         
00866         if (!FS->isPatch) {
00867            if (LocalHead) fprintf (SUMA_STDOUT, "%s: Reading full surface...\n", FuncName);
00868                 /* read in the nodes */
00869                 cnt = 0;
00870                 while (ex != EOF && cnt < FS->N_Node) {
00871                         FS->NodeId[cnt] = cnt;
00872                         id = 3 * cnt;
00873                         ex = fscanf(fs_file, "%f %f %f %f", &(FS->NodeList[id]), &(FS->NodeList[id+1]),&(FS->NodeList[id+2]), &jnkf);
00874                         ++cnt;
00875                 }
00876                 if (cnt != FS->N_Node) {
00877                         fprintf(SUMA_STDERR,"Error %s: Expected %d nodes, %d read.\n", FuncName, FS->N_Node, cnt);
00878                         SUMA_RETURN (NOPE);
00879                 }
00880 
00881                 /* read in the facesets */
00882                 cnt = 0;
00883                 while (ex != EOF && cnt < FS->N_FaceSet) {
00884                         ip = 3 * cnt;
00885                         ex = fscanf(fs_file, "%d %d %d %d", &(FS->FaceSetList[ip]), &(FS->FaceSetList[ip+1]),&(FS->FaceSetList[ip+2]), &jnki);
00886                         ++cnt;
00887                 }
00888                 if (cnt != FS->N_FaceSet) {
00889                         fprintf(SUMA_STDERR,"Error %s: Expected %d FaceSets, %d read.\n", FuncName, FS->N_FaceSet, cnt);
00890                         SUMA_RETURN (NOPE);
00891                 }
00892         } /* read a full surface */
00893         else { /* that's a patch */
00894            if (LocalHead) fprintf (SUMA_STDOUT, "%s: Reading patch ...\n", FuncName);
00895                 /* Node IDs are a reference to those in the parent surface */
00896                 cnt = 0;
00897       while (ex != EOF && cnt < FS->N_Node) {
00898                         ex = fscanf(fs_file, "%d", &(FS->NodeId[cnt]));
00899                         id = 3 * cnt;
00900          /* fprintf (SUMA_STDERR, "FS->NodeId[cnt] = %d: cnt = %d, id=%d, id1 = %d, id2 = %d\n", FS->NodeId[cnt], cnt, id, id+1, id+2); */ 
00901                         ex = fscanf(fs_file, "%f %f %f", &(FS->NodeList[id]),&(FS->NodeList[id+1]),&(FS->NodeList[id+2]));
00902                         ++cnt;
00903                 }
00904       if (cnt != FS->N_Node) {
00905                         fprintf(SUMA_STDERR,"Error %s: Expected %d nodes, %d read.\n", FuncName, FS->N_Node, cnt);
00906                         SUMA_RETURN (NOPE);
00907                 }
00908                 
00909       if (LocalHead) fprintf (SUMA_STDOUT, "%s: Reading FaceSets...\n", FuncName);
00910                 /* read in the facesets */
00911                 cnt = 0;
00912                 while (ex != EOF && cnt < FS->N_FaceSet) {
00913                         ex = fscanf(fs_file, "%d", &(FS->FaceSetIndexInParent[cnt]));
00914                         ip = 3 * cnt;
00915                         ex = fscanf(fs_file, "%d %d %d",  &(FS->FaceSetList[ip]), &(FS->FaceSetList[ip+1]),&(FS->FaceSetList[ip+2]));
00916                         ++cnt;
00917                 }
00918                 if (cnt != FS->N_FaceSet) {
00919                         fprintf(SUMA_STDERR,"Error %s: Expected %d FaceSets, %d read.\n", FuncName, FS->N_FaceSet, cnt);
00920                         SUMA_RETURN (NOPE);
00921                 }
00922                 /* The FaceSet List which will be read next, uses indices into the NodeList of the parent surface
00923                 This means that it expects a NodeList of the size of the NodeList in the parent surface. 
00924                 One could read the maximum number of nodes in the parent surface and create a NodeList of that size.
00925                 However, that would require keeping track of the link between the patch file and the parent file.
00926                 Instead, I will search through the FaceSetList for the highest index and allocate a new nodelist to match it*/
00927       
00928                 SUMA_MAX_VEC(FS->FaceSetList, FS->N_FaceSet * 3, maxamax); ++maxamax;
00929       /* make sure that the node list does not refer to nodes of an index higher than that in NodeId */
00930       SUMA_MAX_VEC(FS->NodeId, FS->N_Node, maxamax2); ++maxamax2;
00931       if (maxamax2 > maxamax) {
00932          fprintf(SUMA_STDERR,"Error %s: Found NodeId in the NodeList larger than Ids found in FaceSetList.\n", FuncName);
00933          SUMA_RETURN (NOPE);
00934       }
00935       if (LocalHead) fprintf (SUMA_STDOUT, "%s: Copying NodeList, allocating for new nodelist %dx3 elements...\n", \
00936          FuncName, maxamax);
00937          
00938                 NodeList = (float *)SUMA_calloc(maxamax * 3, sizeof(float));
00939                 NodeId = (int *)SUMA_calloc (maxamax, sizeof(int));
00940       
00941       if (NodeList == NULL || NodeId == NULL)
00942                 {
00943                         fprintf(SUMA_STDERR,"Error %s: Could not allocate for NodeList or NodeId\n", FuncName);
00944                         SUMA_RETURN (NOPE);
00945                 } 
00946                 /*Now copy pertinent nodes into NodeList */
00947                 
00948       for (cnt=0; cnt< FS->N_Node; ++cnt) {
00949                         id = 3*cnt; 
00950                         id2 = 3*FS->NodeId[cnt];
00951          /* fprintf (SUMA_STDERR, "%s: id = %d id2 = %d\n", FuncName, id, id2); */
00952                         NodeList[id2] = FS->NodeList[id];
00953                         NodeList[id2+1] = FS->NodeList[id+1];
00954                         NodeList[id2+2] = FS->NodeList[id+2];
00955                 }
00956                 
00957       /* this is redundant here, but should be done to match what comes out of a full surface */
00958       for (cnt=0; cnt< maxamax; ++cnt) {
00959          NodeId[cnt] = cnt;
00960       }
00961       
00962       /* Now free FS->NodeList & FS->NodeId */
00963                 SUMA_free(FS->NodeList);
00964                 SUMA_free(FS->NodeId);
00965       
00966                 /*make FS->NodeList be NodeList */
00967                 FS->NodeList = NodeList;
00968       FS->NodeId = NodeId;
00969                 FS->N_Node = maxamax;
00970         } /* read a patch */
00971         
00972         fclose (fs_file);
00973         SUMA_RETURN (YUP);
00974         
00975 }/* SUMA_FreeSurfer_Read*/
00976 
00977 /*! 
00978         free memory allocated for FreeSurfer structure  
00979 */
00980 SUMA_Boolean SUMA_Free_FreeSurfer (SUMA_FreeSurfer_struct *FS)
00981 {
00982         static char FuncName[]={"SUMA_Free_FreeSurfer"};
00983    
00984    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
00985 
00986         if (FS->FaceSetList != NULL) SUMA_free(FS->FaceSetList);
00987         if (FS->NodeList != NULL) SUMA_free(FS->NodeList);
00988         if (FS->NodeId != NULL) SUMA_free(FS->NodeId);
00989         if (FS->FaceSetIndexInParent != NULL) SUMA_free(FS->FaceSetIndexInParent);
00990         if (FS != NULL) SUMA_free(FS);
00991         SUMA_RETURN (YUP);
00992 }
00993 
00994 /*! 
00995         Show elements of FreeSurfer structure 
00996 */
00997 void SUMA_Show_FreeSurfer (SUMA_FreeSurfer_struct *FS, FILE *Out)
00998 {       
00999         static char FuncName[]={"SUMA_Show_FreeSurfer"};
01000         int ND = 3, id, ip;
01001         
01002         if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01003 
01004         if (Out == NULL) Out = SUMA_STDOUT;
01005         fprintf (Out, "Comment: %s\n", FS->comment);
01006         fprintf (Out, "N_Node %d\n", FS->N_Node);
01007         fprintf (Out, "First 2 points [id] X Y Z:\n\t[%d] %f %f %f\n\t[%d] %f %f %f\n", \
01008                 FS->NodeId[0], FS->NodeList[0], FS->NodeList[1], FS->NodeList[2],
01009                 FS->NodeId[1], FS->NodeList[3], FS->NodeList[4], FS->NodeList[5]);
01010         if (FS->N_Node > 2) {
01011       fprintf (Out, "Last 2 points [id] X Y Z:\n\t[%d] %f %f %f\n\t[%d] %f %f %f\n", \
01012                    FS->NodeId[FS->N_Node-2], FS->NodeList[3*(FS->N_Node-2)], FS->NodeList[3*(FS->N_Node-2)+1], FS->NodeList[3*(FS->N_Node-2)+2],
01013                    FS->NodeId[FS->N_Node-1], FS->NodeList[3*(FS->N_Node-1)], FS->NodeList[3*(FS->N_Node-1)+1], FS->NodeList[3*(FS->N_Node-1)+2]);
01014    }
01015         fprintf (Out, "N_FaceSet %d\n", FS->N_FaceSet);
01016         if (!FS->isPatch) {
01017                 if (FS->N_FaceSet > 2) {
01018         fprintf (Out, "First 2 polygons:\n\t%d %d %d\n\t%d %d %d\n", \
01019                         FS->FaceSetList[0], FS->FaceSetList[1], FS->FaceSetList[2],
01020                         FS->FaceSetList[3], FS->FaceSetList[4], FS->FaceSetList[5]);
01021         fprintf (Out, "Last 2 polygons:\n%d %d %d\n%d %d %d\n", \
01022                         FS->FaceSetList[3 * (FS->N_FaceSet-2)], FS->FaceSetList[3 * (FS->N_FaceSet-2) + 1], FS->FaceSetList[3 * (FS->N_FaceSet-2) + 2],
01023                         FS->FaceSetList[3 * (FS->N_FaceSet-1)], FS->FaceSetList[3 * (FS->N_FaceSet-1) + 1], FS->FaceSetList[3 * (FS->N_FaceSet-1) + 2]);
01024       }else {
01025          fprintf (Out, "First polygon:\n\t%d %d %d\n", \
01026                         FS->FaceSetList[0], FS->FaceSetList[1], FS->FaceSetList[2]);
01027       }
01028         } else {
01029                 if (FS->N_FaceSet > 2) {
01030          fprintf (Out, "First 2 polygons:\n\t[parent ID:%d] %d %d %d\n\t[parent ID:%d] %d %d %d\n", \
01031                         FS->FaceSetIndexInParent[0], FS->FaceSetList[0], FS->FaceSetList[1], FS->FaceSetList[2],
01032                         FS->FaceSetIndexInParent[1], FS->FaceSetList[3], FS->FaceSetList[4], FS->FaceSetList[5]);
01033                    fprintf (Out, "Last 2 polygons:\n\t[parent ID:%d]%d %d %d\n\t[parent ID:%d]%d %d %d\n", \
01034                         FS->FaceSetIndexInParent[FS->N_FaceSet-2], FS->FaceSetList[3 * (FS->N_FaceSet-2)], \
01035                         FS->FaceSetList[3 * (FS->N_FaceSet-2) + 1], FS->FaceSetList[3 * (FS->N_FaceSet-2) + 2], \
01036                         FS->FaceSetIndexInParent[FS->N_FaceSet-1], FS->FaceSetList[3 * (FS->N_FaceSet-1)], \
01037                         FS->FaceSetList[3 * (FS->N_FaceSet-1) + 1], FS->FaceSetList[3 * (FS->N_FaceSet-1) + 2]);
01038       } else {
01039          fprintf (Out, "First polygon:\n\t[parent ID:%d] %d %d %d\n", \
01040                         FS->FaceSetIndexInParent[0], FS->FaceSetList[0], FS->FaceSetList[1], FS->FaceSetList[2]);
01041       }
01042         }
01043         SUMA_RETURNe;
01044 
01045 }
01046 
01047 #ifdef SUMA_FreeSurfer_STAND_ALONE
01048 
01049 
01050 void usage_SUMA_FreeSurfer_Main ()
01051    
01052   {/*Usage*/
01053           printf ("\n\33[1mUsage: \33[0m SUMA_FreeSurfer f_name \n");
01054           printf ("\t ..... \n\n");
01055           printf ("\t To Compile:\ngcc -DSUMA_FreeSurfer_STAND_ALONE -Wall -o $1 $1.c -I./ -I//usr/X11R6/include SUMA_lib.a\n");
01056           printf ("\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \tFri Feb 8 16:29:06 EST 2002 \n");
01057           exit (0);
01058   }/*Usage*/
01059    
01060 int main (int argc,char *argv[])
01061 {/* Main */
01062    char FuncName[100]; 
01063    char FS_name[200];
01064         SUMA_FreeSurfer_struct *FS;
01065         
01066    /* initialize Main function name for verbose output */
01067    sprintf (FuncName,"SUMA_FreeSurfer-Main-");
01068    
01069         /* allocate space for CommonFields structure */
01070         SUMAg_CF = SUMA_Create_CommonFields ();
01071         if (SUMAg_CF == NULL) {
01072                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
01073                 exit(1);
01074         }
01075         
01076         /* Allocate for FS */
01077         FS = (SUMA_FreeSurfer_struct *) SUMA_malloc(sizeof(SUMA_FreeSurfer_struct));    
01078         if (FS == NULL) {
01079                 fprintf(SUMA_STDERR,"Error %s: Failed to allocate for FS\n", FuncName);
01080                 exit(1);
01081         }
01082    
01083    if (argc < 2)
01084        {
01085           usage_SUMA_FreeSurfer_Main ();
01086           exit (1);
01087        }
01088    
01089         sprintf(FS_name, "%s", argv[1]);
01090         if (!SUMA_FreeSurfer_Read (FS_name, FS)) {
01091                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_FreeSurfer_Read\n", FuncName);
01092                 exit(1);
01093         }
01094         
01095         
01096         SUMA_Show_FreeSurfer (FS, NULL);
01097         fprintf(stdout, "freeing ..\n");
01098         if (!SUMA_Free_FreeSurfer (FS)) {
01099                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Free_FreeSurfer.\n", FuncName);
01100                 exit(1);
01101         }
01102         
01103         if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
01104 
01105         return (0);
01106 }/* Main */
01107 #endif
01108 
01109 /*** Code to read ply format data 
01110 Ply functions are based on code by Greg Turk. 
01111 ---------------------------------------------------------------
01112 
01113 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
01114 Junior University.  All rights reserved.   
01115   
01116 Permission to use, copy, modify and distribute this software and its   
01117 documentation for any purpose is hereby granted without fee, provided   
01118 that the above copyright notice and this permission notice appear in   
01119 all copies of this software and that you do not sell the software.   
01120   
01121 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,   
01122 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY   
01123 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   
01124 
01125 
01126 */
01127 
01128 /* user's vertex and face definitions for a polygonal object */
01129 
01130 typedef struct Vertex {
01131   float x,y,z;             /* the usual 3-space position of a vertex */
01132 } Vertex;
01133 
01134 typedef struct Face {
01135   unsigned char intensity; /* this user attaches intensity to faces */
01136   unsigned char nverts;    /* number of vertex indices in list */
01137   int *verts;              /* vertex index list */
01138 } Face;
01139 
01140 /* information needed to describe the user's data to the PLY routines */
01141 
01142 PlyProperty vert_props[] = { /* list of property information for a vertex */
01143   {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
01144   {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0},
01145   {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0},
01146 };
01147 
01148 PlyProperty face_props[] = { /* list of property information for a vertex */
01149   {"intensity", PLY_UCHAR, PLY_UCHAR, offsetof(Face,intensity), 0, 0, 0, 0},
01150   {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
01151    1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
01152 };
01153 
01154 /*!
01155    \brief Reads a Ply formatted file into a SUMA_SurfaceObject structure
01156    ans = SUMA_Ply_Read (f_name, SO);
01157    
01158    \param f_name (char *) name (and path) of .ply file to read. Extension .ply is optional
01159    \param SO (SUMA_SurfaceObject *) pointer to a structure to return surface in f_name in
01160    \return ans (SUMA_Boolean) YUP/NOPE
01161    
01162    The following fields are set in SO:
01163    SO->NodeDim
01164    SO->FaceSetDim
01165    SO->NodeList
01166    SO->FaceSetList
01167    SO->N_Node;
01168    SO->N_FaceSet;
01169    SO->Name;
01170    SO->FileType;
01171    SO->FileFormat
01172    
01173    \sa SUMA_Ply_Write()
01174    
01175    This function is a wrap around code by Greg Turk. 
01176    
01177 */
01178 SUMA_Boolean SUMA_Ply_Read (char * f_name, SUMA_SurfaceObject *SO) 
01179 {
01180    static char FuncName[]={"SUMA_Ply_Read"};
01181    int i,j,k, j3, ji;
01182    PlyFile *ply = NULL;
01183    int nelems;
01184    char **elist = NULL;
01185    int file_type;
01186    float version;
01187    int nprops;
01188    int num_elems;
01189    PlyProperty **plist = NULL;
01190    Vertex **vlist = NULL;
01191    Face **flist = NULL;
01192    char *elem_name;
01193    int num_comments;
01194    char **comments = NULL;
01195    int num_obj_info;
01196    char **obj_info = NULL;
01197    SUMA_Boolean LocalHead = NOPE;
01198    
01199    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01200 
01201    /* open a PLY file for reading */
01202    ply = ply_open_for_reading(f_name, &nelems, &elist, &file_type, &version);
01203    if (!ply) {
01204       fprintf (SUMA_STDERR, "Error %s: Failed to find/read %s.\n", FuncName, f_name);
01205       SUMA_RETURN (NOPE);
01206    }
01207    
01208    /* print what we found out about the file */
01209    if (LocalHead) fprintf (SUMA_STDERR, "%s: version %f\n", FuncName, version);
01210    if (LocalHead) fprintf (SUMA_STDERR, "%s: type %d\n", FuncName, file_type);
01211 
01212    /* go through each kind of element that we learned is in the file */
01213    /* and read them */
01214 
01215    for (i = 0; i < nelems; i++) {
01216 
01217     /* get the description of the first element */
01218     elem_name = elist[i];
01219     plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
01220 
01221     /* print the name of the element, for debugging */
01222     if (LocalHead) fprintf (SUMA_STDERR, "%s: element %s %d\n", FuncName, elem_name, num_elems);
01223 
01224     /* if we're on vertex elements, read them in */
01225     if (equal_strings ("vertex", elem_name)) {
01226 
01227       /* create a vertex list to hold all the vertices */
01228       #ifdef USE_PLY_VERTEX
01229       vlist = (Vertex **) SUMA_malloc (sizeof (Vertex *) * num_elems);
01230       #endif
01231       
01232       SO->NodeList = (float *) SUMA_calloc (3*num_elems, sizeof(float));
01233       if (!SO->NodeList) {
01234          fprintf (SUMA_STDERR, "Error %s: Failed to allocate for SO->NodeList.\n", FuncName);
01235          SUMA_RETURN(NOPE);
01236       }
01237       
01238       /* set up for getting vertex elements */
01239 
01240       ply_get_property (ply, elem_name, &vert_props[0]);
01241       ply_get_property (ply, elem_name, &vert_props[1]);
01242       ply_get_property (ply, elem_name, &vert_props[2]);
01243       
01244       SO->NodeDim = 3;
01245       SO->N_Node = num_elems;
01246       /* grab all the vertex elements */
01247       for (j = 0; j < num_elems; j++) {
01248 
01249         /* grab and element from the file */
01250         #ifdef USE_PLY_VERTEX
01251         //vlist[j] = (Vertex *) SUMA_malloc (sizeof (Vertex));
01252         //ply_get_element (ply, (void *) vlist[j]);
01253         /* print out vertex x,y,z for debugging */
01254         if (LocalHead) fprintf (SUMA_STDERR, "%s vertex: %g %g %g\n", FuncName, vlist[j]->x, vlist[j]->y, vlist[j]->z);
01255         /* copy to NodeList */
01256         j3 = SO->NodeDim*j;
01257         SO->NodeList[j3] = vlist[j]->x;
01258         SO->NodeList[j3+1] = vlist[j]->y;
01259         SO->NodeList[j3+2] = vlist[j]->z;
01260         
01261         #else
01262         j3 = SO->NodeDim*j;
01263         ply_get_element (ply, (void *) &(SO->NodeList[j3]));
01264         /* print out vertex x,y,z for debugging */
01265         if (LocalHead) fprintf (SUMA_STDERR, "%s vertex: %g %g %g\n", FuncName, 
01266          SO->NodeList[j3], SO->NodeList[j3+1], SO->NodeList[j3+2]);
01267         #endif
01268          
01269       }
01270     }
01271 
01272     /* if we're on face elements, read them in */
01273     if (equal_strings ("face", elem_name)) {
01274 
01275       /* create a list to hold all the face elements */
01276       flist = (Face **) SUMA_malloc (sizeof (Face *) * num_elems);
01277 
01278       /* set up for getting face elements */
01279 
01280       ply_get_property (ply, elem_name, &face_props[0]);
01281       ply_get_property (ply, elem_name, &face_props[1]);
01282 
01283       /* grab all the face elements */
01284       for (j = 0; j < num_elems; j++) {
01285 
01286         /* grab and element from the file */
01287         flist[j] = (Face *) SUMA_malloc (sizeof (Face));
01288         ply_get_element (ply, (void *) flist[j]);
01289 
01290         /* print out face info, for debugging */
01291         if (LocalHead) {
01292          fprintf (SUMA_STDERR,"%s face: %d, list = ", FuncName, flist[j]->intensity);
01293          for (k = 0; k < flist[j]->nverts; k++)
01294             fprintf (SUMA_STDERR,"%d ", flist[j]->verts[k]);
01295          fprintf (SUMA_STDERR,"\n");
01296         }
01297         
01298       }
01299       /* copy face elements to SO structure */
01300       SO->FaceSetDim = flist[0]->nverts;
01301       SO->N_FaceSet = num_elems;
01302       SO->FaceSetList = (int *) SUMA_calloc (SO->FaceSetDim * num_elems, sizeof(int));
01303       if (!SO->FaceSetList) {
01304          fprintf (SUMA_STDERR, "Error %s: Failed to allocate for SO->NodeList.\n", FuncName);
01305          if (SO->NodeList) SUMA_free(SO->NodeList); 
01306          SUMA_RETURN(NOPE);
01307       }
01308       
01309       for (j = 0; j < num_elems; j++) {
01310          if (flist[j]->nverts != SO->FaceSetDim) {
01311             fprintf (SUMA_STDERR, "Error %s: All FaceSets must have the same dimension for SUMA.\n", FuncName);
01312             if (SO->NodeList) SUMA_free(SO->NodeList); 
01313             if (SO->FaceSetList) SUMA_free(SO->FaceSetList);
01314             SO->NodeList = NULL;
01315             SO->FaceSetList = NULL;
01316             SUMA_RETURN(NOPE);
01317          }
01318          ji = SO->FaceSetDim * j;
01319          for (k = 0; k < flist[j]->nverts; k++)
01320             SO->FaceSetList[ji+k] = flist[j]->verts[k];
01321       }
01322     }
01323 
01324    /* fill up a few more fields */
01325    SO->FileType = SUMA_PLY;
01326    if (file_type == PLY_ASCII) SO->FileFormat = SUMA_ASCII;
01327       else if (file_type == PLY_BINARY_BE) SO->FileFormat = SUMA_BINARY_BE;
01328          else if (file_type == PLY_BINARY_LE) SO->FileFormat = SUMA_BINARY_LE;
01329             else {
01330                fprintf (SUMA_STDERR, "Error %s: PLY_TYPE %d not recognized.\n", FuncName, file_type);
01331             }
01332             
01333    SO->Name = SUMA_StripPath(f_name);
01334    
01335     /* print out the properties we got, for debugging */
01336     for (j = 0; j < nprops; j++)
01337       fprintf (SUMA_STDERR, "%s property %s\n", FuncName, plist[j]->name);
01338    }
01339 
01340    /* grab and print out the comments in the file */
01341    comments = ply_get_comments (ply, &num_comments);
01342    for (i = 0; i < num_comments; i++)
01343     fprintf (SUMA_STDERR, "%s comment = '%s'\n", FuncName, comments[i]);
01344 
01345    /* grab and print out the object information */
01346    obj_info = ply_get_obj_info (ply, &num_obj_info);
01347    for (i = 0; i < num_obj_info; i++)
01348     fprintf (SUMA_STDERR, "%s obj_info = '%s'\n", FuncName, obj_info[i]);
01349 
01350    /* free the allocations necessary for vertex and facesetlists */
01351    for (j = 0; j < SO->N_FaceSet; j++) {
01352       SUMA_free(flist[j]);
01353    }
01354    SUMA_free(flist); flist = NULL;
01355    
01356    #ifdef USE_PLY_VERTEX
01357    for (j = 0; j < SO->N_Node; j++) {
01358       SUMA_free(vlist[j]);
01359    }
01360    SUMA_free(vlist); vlist = NULL;
01361    #endif
01362    /* close the PLY file, ply structure is freed within*/
01363    ply_close (ply);
01364    
01365    /* free plist */
01366    for (j = 0; j < nprops; j++) if (plist[j]) SUMA_free (plist[j]);
01367    if (plist) SUMA_free(plist);
01368    
01369    /* free comments */
01370    for (i = 0; i < num_comments; i++) if (comments[i]) SUMA_free (comments[i]);
01371    if (comments) SUMA_free (comments);
01372    
01373    /* free elist */
01374    for (i = 0; i < nelems; i++) if (elist[i]) SUMA_free (elist[i]);
01375    if (elist) SUMA_free (elist);
01376    
01377    /* free obj_info */
01378    for (i = 0; i < num_obj_info; i++) if (obj_info[i]) SUMA_free (obj_info[i]);
01379    if (obj_info) SUMA_free (obj_info);
01380     
01381    SUMA_RETURN(YUP);
01382 }
01383 
01384 /*!
01385    \brief Writes an SO into a .ply file
01386    ans = SUMA_Ply_Write (f_name, SO);
01387    \param f_name (char *) name of .ply file. if .ply is not attached it will be added.
01388    \param SO (SUMA_SurfaceObject *) Surface object to write out. 
01389       if SO->FileFormat = SUMA_BINARY_BE or SUMA_BINARY_LE the surface is written in binary ply format.
01390       SUMA_BINARY is set to SUMA_BINARY_BE
01391    \return ans (SUMA_Boolean) success flag.
01392    
01393    In its current incarnation, the function does not overwrite a pre-existing file.
01394       
01395 */ 
01396 SUMA_Boolean SUMA_Ply_Write (char * f_name, SUMA_SurfaceObject *SO) 
01397 {
01398    static char FuncName[]={"SUMA_Ply_Write"};
01399    int i,j;
01400    PlyFile *ply = NULL;
01401    int nelems;
01402    int file_type;
01403    float version;
01404    int nverts ;
01405    int nfaces ;
01406    char *f_name2, *elem_names[] = { "vertex", "face" };/* list of the kinds of elements in the user's object */
01407    int n_elem_names = 2;
01408    Vertex **verts = NULL;
01409    Face *faces = NULL;
01410    SUMA_Boolean LocalHead = NOPE;
01411    
01412    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01413    
01414    if (SUMA_filexists (f_name)) {
01415       fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n", FuncName, f_name);
01416       SUMA_RETURN (NOPE);
01417    }else {
01418       f_name2 = (char*) SUMA_malloc ((strlen(f_name)+10) * sizeof(char));
01419       sprintf(f_name2,"%s.ply", f_name);
01420       if (SUMA_filexists (f_name2)) {
01421          fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n", FuncName, f_name2);
01422          SUMA_free(f_name2);
01423          SUMA_RETURN (NOPE);
01424       }
01425       SUMA_free(f_name2);
01426    }
01427    
01428    nverts = SO->N_Node;
01429    nfaces = SO->N_FaceSet;
01430    
01431    /* must have XYZ */
01432    if (SO->NodeDim != 3) {
01433       fprintf (SUMA_STDERR, "Error %s: SO->NodeDim != 3.\n", FuncName);
01434       SUMA_RETURN (NOPE);
01435    }
01436 
01437    /* create the object in ply format */
01438    verts = (Vertex **) SUMA_malloc (nverts*sizeof(Vertex *));
01439    faces = (Face *) SUMA_malloc (nfaces*sizeof(Face));
01440    if (!verts || !faces) {
01441       fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
01442       if (verts) SUMA_free(verts);
01443       if (faces) SUMA_free(faces);
01444       SUMA_RETURN (NOPE);
01445    }
01446 
01447    for (i = 0; i < nfaces; i++) {
01448       faces[i].intensity = '\001';
01449       faces[i].nverts = SO->FaceSetDim;
01450       faces[i].verts = &(SO->FaceSetList[SO->FaceSetDim*i]);
01451    }
01452    
01453    /* open either a binary or ascii PLY file for writing */
01454    /* (the file will be called "test.ply" because the routines */
01455    /*  enforce the .ply filename extension) */
01456 
01457    switch (SO->FileType) {
01458       case SUMA_BINARY_BE:
01459          ply = ply_open_for_writing(f_name, n_elem_names, elem_names, PLY_BINARY_BE, &version);
01460          break;
01461       
01462       case SUMA_BINARY_LE:
01463          ply = ply_open_for_writing(f_name, n_elem_names, elem_names, PLY_BINARY_LE, &version);
01464          break;
01465       
01466       case SUMA_ASCII:
01467          ply = ply_open_for_writing(f_name, n_elem_names, elem_names, PLY_ASCII, &version);
01468          break;
01469       
01470       case SUMA_BINARY:
01471          ply = ply_open_for_writing(f_name, n_elem_names, elem_names, PLY_BINARY_BE, &version);
01472          break;
01473             
01474       default:
01475          fprintf (SUMA_STDERR, "Error %s: Unrecognized file type.\n", FuncName);
01476          SUMA_RETURN (NOPE);
01477          break;  
01478    }
01479 
01480    if (!ply) {
01481       fprintf (SUMA_STDERR,"Error %s: Failed to create %s.\n", FuncName, f_name);
01482       if (verts) SUMA_free(verts);
01483       if (faces) SUMA_free(faces);
01484       SUMA_RETURN (NOPE);
01485    }
01486    /* describe what properties go into the vertex and face elements */
01487 
01488    ply_element_count (ply, "vertex", nverts);
01489    ply_describe_property (ply, "vertex", &vert_props[0]);
01490    ply_describe_property (ply, "vertex", &vert_props[1]);
01491    ply_describe_property (ply, "vertex", &vert_props[2]);
01492 
01493    ply_element_count (ply, "face", nfaces);
01494    ply_describe_property (ply, "face", &face_props[0]);
01495    ply_describe_property (ply, "face", &face_props[1]);
01496 
01497    /* write a comment and an object information field */
01498    ply_put_comment (ply, "author: Greg Turk");
01499    ply_put_obj_info (ply, "random information");
01500 
01501    /* we have described exactly what we will put in the file, so */
01502    /* we are now done with the header info */
01503    ply_header_complete (ply);
01504 
01505    /* set up and write the vertex elements */
01506    ply_put_element_setup (ply, "vertex");
01507    for (i = 0; i < nverts; i++)
01508     ply_put_element (ply, (void *) &(SO->NodeList[SO->NodeDim*i]));
01509 
01510    /* set up and write the face elements */
01511    ply_put_element_setup (ply, "face");
01512    for (i = 0; i < nfaces; i++)
01513     ply_put_element (ply, (void *) &faces[i]);
01514 
01515    /* close the PLY file */
01516    ply_close (ply);
01517 
01518    /* free */
01519    if (verts) SUMA_free(verts);
01520    if (faces) SUMA_free(faces);
01521    
01522    SUMA_RETURN (YUP);
01523 }
01524 
01525 /*! 
01526    \brief Function to write a surface object to a FreeSurfer .asc file format
01527    ans = SUMA_Boolean SUMA_FS_Write (fileNm, SO, firstLine);
01528    \param  fileNm (char *) name (and path) of file.
01529    \param  SO (SUMA_SurfaceObject *) Surface Object
01530    \param firstLine (char *) string to place as comment (begins with #) in fileNm
01531    \return YUP/NOPE
01532    
01533    
01534    The function will not overwrite pre-existing.
01535    Written by Brenna Bargall
01536 */
01537 SUMA_Boolean SUMA_FS_Write (char *fileNm, SUMA_SurfaceObject *SO, char *firstLine) 
01538 {
01539    static char FuncName[]={"SUMA_FS_Write"};
01540    int i, j;
01541    FILE *outFile = NULL;
01542    
01543    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01544    
01545    if (SUMA_filexists(fileNm)) {
01546       fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n",FuncName, fileNm);
01547       SUMA_RETURN (NOPE);
01548    }
01549    
01550    if (SO->NodeDim != 3 || SO->FaceSetDim != 3) {
01551       fprintf (SUMA_STDERR, "Error %s: Must have NodeDim and FaceSetDim = 3.\n",FuncName);
01552       SUMA_RETURN (NOPE);
01553    }
01554 
01555    outFile = fopen(fileNm, "w");
01556    if (!outFile) {
01557       fprintf (SUMA_STDERR, "Error %s: Failed in opening %s for writing.\n",FuncName, fileNm);
01558       SUMA_RETURN (NOPE);
01559    } 
01560    
01561    fprintf (outFile,"#%s\n", firstLine);
01562    fprintf (outFile, "%d %d\n", SO->N_Node, SO->N_FaceSet);
01563 
01564    j=0;
01565    for (i=0; i<SO->N_Node; ++i) {
01566       j=SO->NodeDim * i;
01567       fprintf (outFile, "%f  %f  %f  0\n", SO->NodeList[j], SO->NodeList[j+1], SO->NodeList[j+2]);
01568    }
01569 
01570    j=0;
01571    for (i=0; i<SO->N_FaceSet; ++i) {
01572       j = SO->FaceSetDim * i;
01573       fprintf (outFile, "%d %d %d 0\n", SO->FaceSetList[j], SO->FaceSetList[j+1], SO->FaceSetList[j+2]);
01574    }
01575     
01576    
01577    fclose(outFile);
01578 
01579    SUMA_RETURN (YUP);
01580    
01581 }
01582 
01583 /*!
01584    \brief writes the NodeList and FaceSetList of SO to 2 ascii files
01585    ans = SUMA_Boolean SUMA_VEC_Write (SUMA_SFname *Fname, SUMA_SurfaceObject *SO);
01586    \param  Fname (SUMA_SFname *) uses the SureFit filename structure to store
01587                                  the names (and paths) of the NodeList (name_coord)
01588                                  and the FaceSetList (name_topo) files.
01589    \param SO (SUMA_SurfaceObject *) pointer to SO structure.
01590    \return YUP/NOPE
01591    
01592    \sa SUMA_VEC_Read
01593    The function will not overwrite pre-existing files.
01594    
01595 */
01596 SUMA_Boolean SUMA_VEC_Write (SUMA_SFname *Fname, SUMA_SurfaceObject *SO)
01597 {
01598    
01599    static char FuncName[]={"SUMA_VEC_Write"};
01600    int i, j;
01601    FILE *outFile = NULL;
01602    
01603    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
01604 
01605    if (SUMA_filexists(Fname->name_coord)) {
01606       fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n",FuncName, Fname->name_coord);
01607       SUMA_RETURN (NOPE);
01608    }
01609    if (SUMA_filexists(Fname->name_topo)) {
01610       fprintf (SUMA_STDERR, "Error %s: file %s exists, will not overwrite.\n",FuncName, Fname->name_topo);
01611       SUMA_RETURN (NOPE);
01612    }
01613    if (SO->NodeDim != 3 || SO->FaceSetDim != 3) {
01614       fprintf (SUMA_STDERR, "Error %s: Must have NodeDim and FaceSetDim = 3.\n",FuncName);
01615       SUMA_RETURN (NOPE);
01616    }
01617    
01618    outFile = fopen(Fname->name_coord, "w");
01619    if (!outFile) {
01620       fprintf (SUMA_STDERR, "Error %s: Failed in opening %s for writing.\n",FuncName, Fname->name_coord);
01621       SUMA_RETURN (NOPE);
01622    }
01623    
01624    j=0;
01625    for (i=0; i<SO->N_Node; ++i) {
01626       j=SO->NodeDim * i;
01627       fprintf (outFile, "%f  %f  %f \n", SO->NodeList[j], SO->NodeList[j+1], SO->NodeList[j+2]);
01628    }
01629    
01630    fclose (outFile);
01631    
01632    outFile = fopen(Fname->name_topo, "w");
01633    if (!outFile) {
01634       fprintf (SUMA_STDERR, "Error %s: Failed in opening %s for writing.\n",FuncName, Fname->name_topo);
01635       SUMA_RETURN (NOPE);
01636    }
01637    j=0;
01638    for (i=0; i<SO->N_FaceSet; ++i) {
01639       j = SO->FaceSetDim * i;
01640       fprintf (outFile, "%d %d %d\n", SO->FaceSetList[j], SO->FaceSetList[j+1], SO->FaceSetList[j+2]);
01641    }
01642 
01643    fclose (outFile);
01644    SUMA_RETURN (YUP);
01645 
01646 }
01647 
01648 /*!
01649    \brief A function to write a Surface Object into a Surefit ascii format 
01650    \param F_prefix (char *) Prefix of surace filenames. Output will be of the form:
01651          Prefix.N_NODE.topo
01652          Prefix.N_NODE.coord where N_Node is the number of nodes making up the surface.
01653    \param SO (SUMA_SurfaceObject *) surface object
01654    \return YUP/NOPE
01655    
01656 */
01657 
01658 
01659 #ifdef SUMA_Ply_Read_STAND_ALONE
01660 void usage_SUMA_Ply_Read_Main ()
01661    
01662   {/*Usage*/
01663           printf ("\n\33[1mUsage: \33[0m SUMA_Ply_Read -s f_name \n");
01664           printf ("\t reads in a .ply file and writes it out to copy_f_name.ply\n");
01665           printf ("\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \t Wed Jan  8 13:44:29 EST 2003 \n");
01666           exit (0);
01667   }/*Usage*/
01668    
01669 int main (int argc,char *argv[])
01670 {/* Main */
01671    static char FuncName[]={"SUMA_Ply_Read_Main"}; 
01672         int kar;
01673    char *f_name=NULL, out_f_name[200];
01674    SUMA_SurfaceObject *SO = NULL;
01675    SUMA_Boolean brk;
01676    
01677         /* allocate space for CommonFields structure */
01678         SUMAg_CF = SUMA_Create_CommonFields ();
01679         if (SUMAg_CF == NULL) {
01680                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
01681                 exit(1);
01682         }
01683    
01684    if (argc < 3)
01685        {
01686           usage_SUMA_Ply_Read_Main ();
01687           exit (1);
01688        }
01689    
01690    kar = 1;
01691         brk = NOPE;
01692         while (kar < argc) { /* loop accross command ine options */
01693                 /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
01694                 if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
01695                          usage_SUMA_Ply_Read_Main();
01696           exit (1);
01697                 }
01698                 
01699                 if (!brk && (strcmp(argv[kar], "-s") == 0)) {
01700                         kar ++;
01701                         if (kar >= argc)  {
01702                                 fprintf (SUMA_STDERR, "need argument after -s ");
01703                                 exit (1);
01704                         }
01705                         f_name = argv[kar];
01706                         /*fprintf(SUMA_STDOUT, "Found: %s\n", f_name);*/
01707 
01708                         brk = YUP;
01709                 }
01710       
01711       if (!brk) {
01712                         fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]);
01713                         exit (1);
01714                 } else {        
01715                         brk = NOPE;
01716                         kar ++;
01717                 }
01718    }
01719    
01720    if (!f_name) {
01721       fprintf (SUMA_STDERR,"Error %s: Missing filename.\n", FuncName);
01722       exit(1);
01723    }
01724    
01725    SO = SUMA_Alloc_SurfObject_Struct(1);   
01726    if (!SUMA_Ply_Read (f_name, SO)) {
01727       fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Ply_Read.\n", FuncName);
01728       exit (1);
01729    } 
01730    
01731    SO->Label = SUMA_SurfaceFileName (SO, NOPE);
01732    sprintf (out_f_name , "copy_%s", SO->Label);   
01733    fprintf (SUMA_STDERR,"%s: Success apparent. Now writing SO to %s\n", FuncName, out_f_name);
01734    if (!SUMA_Ply_Write (out_f_name, SO)) {
01735       fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Ply_Read.\n", FuncName);
01736       exit (1);
01737    } 
01738       
01739    SUMA_Free_Surface_Object (SO);
01740    
01741    return (0);
01742  } /* Main */  
01743 #endif
01744 
01745 #ifdef SUMA_ConvertSurface_STAND_ALONE
01746 void usage_SUMA_ConvertSurface ()
01747    
01748   {/*Usage*/
01749           printf ("\n\33[1mUsage: \33[0m ConvertSurface <-i_TYPE inSurf> <-o_TYPE outSurf> [<-sv SurfaceVolume [VolParam for sf surfaces]>] [-tlrc]\n");
01750           printf ("\t reads in a surface and writes it out in another format.\n");
01751           printf ("\t Note: This is a not a general utility conversion program. \n");
01752           printf ("\t Only fields pertinent to SUMA are preserved.\n");
01753           printf ("\t -i_TYPE inSurf specifies the input surface, TYPE is one of the following:\n");
01754           printf ("\t    fs: FreeSurfer surface. \n");
01755           printf ("\t        Only .asc surfaces are read.\n");
01756           printf ("\t    sf: SureFit surface. \n");
01757           printf ("\t        You must specify the .coord followed by the .topo file.\n");
01758           printf ("\t    vec: Simple ascii matrix format. \n");
01759           printf ("\t         You must specify the NodeList file followed by the FaceSetList file.\n");
01760           printf ("\t         NodeList contains 3 floats per line, representing X Y Z vertex coordinates.\n");
01761           printf ("\t         FaceSetList contains 3 ints per line, representing v1 v2 v3 triangle vertices.\n");
01762           printf ("\t    ply: PLY format, ascii or binary.\n");
01763           printf ("\t         Only vertex and triangulation info is preserved.\n");
01764           printf ("\t -o_TYPE outSurf specifies the output surface, TYPE is one of the following:\n");
01765           printf ("\t    fs: FreeSurfer ascii surface. \n");
01766           printf ("\t    sf: SureFit surface. (NOT IMPLEMENTED YET)\n");
01767           printf ("\t        You must specify the .coord followed by the .topo file.\n");
01768           printf ("\t    vec: Simple ascii matrix format. \n");
01769           printf ("\t         see help for vec under -i_TYPE options for format specifications.\n");
01770           printf ("\t    ply: PLY format, ascii or binary.\n");
01771           printf ("\t -sv SurfaceVolume [VolParam for sf surfaces]\n");
01772           printf ("\t    This option must not come before the -i_TYPE option.\n");
01773           printf ("\t    If you supply a surface volume, the coordinates of the input surface.\n");
01774           printf ("\t     are modified to SUMA's convention and aligned with SurfaceVolume.\n");
01775           printf ("\t     You must also specify a VolParam file for SureFit surfaces.\n");
01776           printf ("\t -tlrc: Apply taliairach transform (which must be in talairach version of SurfaceVolume)\n");
01777           printf ("\t     to the surface vertex coordinates. This option must be used with the -sv option.\n");
01778           printf ("\tNOTE: The vertex coordinates coordinates of the input surfaces are only\n");
01779           printf ("\t      transformed if -sv option is used. If you do transform surfaces, \n");
01780           printf ("\t      take care not to load them into SUMA with another -sv option.\n");  
01781           printf ("\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \t Wed Jan  8 13:44:29 EST 2003 \n");
01782           exit (0);
01783   }/*Usage*/
01784    
01785 int main (int argc,char *argv[])
01786 {/* Main */
01787    static char FuncName[]={"SUMA_ConvertSurface"}; 
01788         int kar;
01789    char  *if_name = NULL, *of_name = NULL, *if_name2 = NULL, 
01790          *of_name2 = NULL, *sv_name = NULL, *vp_name = NULL, 
01791          *OF_name = NULL, *OF_name2 = NULL, *tlrc_name = NULL;
01792    SUMA_SO_File_Type iType = SUMA_FT_NOT_SPECIFIED, oType = SUMA_FT_NOT_SPECIFIED;
01793    SUMA_SurfaceObject *SO = NULL;
01794    SUMA_PARSED_NAME *of_name_strip = NULL, *of_name2_strip = NULL;
01795    SUMA_SFname *SF_name = NULL;
01796    void *SO_name = NULL;
01797    THD_warp *warp=NULL ;
01798    THD_3dim_dataset *aset=NULL;
01799    SUMA_Boolean brk, Do_tlrc, LocalHead = NOPE;
01800    
01801         /* allocate space for CommonFields structure */
01802         SUMAg_CF = SUMA_Create_CommonFields ();
01803         if (SUMAg_CF == NULL) {
01804                 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
01805                 exit(1);
01806         }
01807    
01808    if (argc < 4)
01809        {
01810           usage_SUMA_ConvertSurface ();
01811           exit (1);
01812        }
01813    
01814    kar = 1;
01815         brk = NOPE;
01816    Do_tlrc = NOPE;
01817         while (kar < argc) { /* loop accross command ine options */
01818                 /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
01819                 if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
01820                          usage_SUMA_ConvertSurface();
01821           exit (1);
01822                 }
01823                 
01824                 if (!brk && (strcmp(argv[kar], "-i_fs") == 0)) {
01825          kar ++;
01826                         if (kar >= argc)  {
01827                                 fprintf (SUMA_STDERR, "need argument after -i_fs ");
01828                                 exit (1);
01829                         }
01830                         if_name = argv[kar];
01831          iType = SUMA_FREE_SURFER;
01832                         brk = YUP;
01833                 }
01834       
01835       if (!brk && (strcmp(argv[kar], "-i_sf") == 0)) {
01836          kar ++;
01837                         if (kar+1 >= argc)  {
01838                                 fprintf (SUMA_STDERR, "need 2 argument after -i_sf");
01839                                 exit (1);
01840                         }
01841                         if_name = argv[kar]; kar ++;
01842          if_name2 = argv[kar];
01843          iType = SUMA_SUREFIT;
01844                         brk = YUP;
01845                 }
01846       
01847       if (!brk && (strcmp(argv[kar], "-i_vec") == 0)) {
01848          kar ++;
01849                         if (kar+1 >= argc)  {
01850                                 fprintf (SUMA_STDERR, "need 2 argument after -i_vec");
01851                                 exit (1);
01852                         }
01853                         if_name = argv[kar]; kar ++;
01854          if_name2 = argv[kar];
01855          iType = SUMA_VEC;
01856                         brk = YUP;
01857                 }
01858       
01859       if (!brk && (strcmp(argv[kar], "-i_ply") == 0)) {
01860          kar ++;
01861                         if (kar >= argc)  {
01862                                 fprintf (SUMA_STDERR, "need argument after -i_ply ");
01863                                 exit (1);
01864                         }
01865                         if_name = argv[kar];
01866          iType = SUMA_PLY;
01867                         brk = YUP;
01868                 }
01869       
01870       if (!brk && (strcmp(argv[kar], "-sv") == 0)) {
01871          if (iType == SUMA_FT_NOT_SPECIFIED) {
01872             fprintf (SUMA_STDERR, " -sv option must be preceeded by -i_TYPE option.");
01873             exit(1);
01874          }
01875          kar ++;
01876                         if (iType == SUMA_SUREFIT) {
01877             if (kar+1 >= argc)  {
01878                                    fprintf (SUMA_STDERR, "need 2 argument after -sv (SurfaceVolume and VolumeParent)");
01879                                    exit (1);
01880                            }
01881             sv_name = argv[kar]; kar ++;
01882             vp_name = argv[kar];
01883          } else {
01884             if (kar >= argc)  {
01885                                    fprintf (SUMA_STDERR, "need argument after -sv ");
01886                                    exit (1);
01887                            }
01888                            sv_name = argv[kar];
01889          }
01890                         brk = YUP;
01891                 }
01892       
01893       if (!brk && (strcmp(argv[kar], "-o_fs") == 0)) {
01894          kar ++;
01895                         if (kar >= argc)  {
01896                                 fprintf (SUMA_STDERR, "need argument after -o_fs ");
01897                                 exit (1);
01898                         }
01899                         of_name = argv[kar];
01900          oType = SUMA_FREE_SURFER;
01901                         brk = YUP;
01902                 }
01903       
01904       if (!brk && (strcmp(argv[kar], "-o_sf") == 0)) {
01905          kar ++;
01906                         if (kar+1 >= argc)  {
01907                                 fprintf (SUMA_STDERR, "need 2 argument after -o_sf");
01908                                 exit (1);
01909                         }
01910                         of_name = argv[kar]; kar ++;
01911          of_name2 = argv[kar];
01912          oType = SUMA_SUREFIT;
01913                         brk = YUP;
01914                 }
01915       
01916       if (!brk && (strcmp(argv[kar], "-o_vec") == 0)) {
01917          kar ++;
01918                         if (kar+1 >= argc)  {
01919                                 fprintf (SUMA_STDERR, "need 2 argument after -o_vec");
01920                                 exit (1);
01921                         }
01922                         of_name = argv[kar]; kar ++;
01923          of_name2 = argv[kar];
01924          oType = SUMA_VEC;
01925                         brk = YUP;
01926                 }
01927       
01928       if (!brk && (strcmp(argv[kar], "-o_ply") == 0)) {
01929          kar ++;
01930                         if (kar >= argc)  {
01931                                 fprintf (SUMA_STDERR, "need argument after -o_ply ");
01932                                 exit (1);
01933                         }
01934                         of_name = argv[kar];
01935          oType = SUMA_PLY;
01936                         brk = YUP;
01937                 }
01938       
01939       if (!brk && (strcmp(argv[kar], "-tlrc") == 0)) {
01940          Do_tlrc = YUP;
01941          brk = YUP;
01942       }
01943       
01944       if (!brk) {
01945                         fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]);
01946                         exit (1);
01947                 } else {        
01948                         brk = NOPE;
01949                         kar ++;
01950                 }
01951    }
01952 
01953    /* sanity checks */
01954    if (!if_name) {
01955       fprintf (SUMA_STDERR,"Error %s: input surface not specified.\n", FuncName);
01956       exit(1);
01957    }
01958    if (!of_name) {
01959       fprintf (SUMA_STDERR,"Error %s: output surface not specified.\n", FuncName);
01960       exit(1);
01961    }
01962    if (iType == SUMA_FT_NOT_SPECIFIED) {
01963       fprintf (SUMA_STDERR,"Error %s: input type not recognized.\n", FuncName);
01964       exit(1);
01965    }
01966    if (oType == SUMA_FT_NOT_SPECIFIED) {
01967       fprintf (SUMA_STDERR,"Error %s: output type not recognized.\n", FuncName);
01968       exit(1);
01969    }
01970    if (iType == SUMA_SUREFIT) {
01971       if (!if_name2) {
01972          fprintf (SUMA_STDERR,"Error %s: input SureFit surface incorrectly specified.\n", FuncName);
01973          exit(1);
01974       }
01975       if (sv_name && !vp_name) {
01976          fprintf (SUMA_STDERR,"Error %s: VolParent must specified with -sv potion for SureFit surfaces. \n", FuncName);
01977          exit(1);
01978       }
01979    }
01980    if (iType == SUMA_VEC) {
01981       if (!if_name2) {
01982          fprintf (SUMA_STDERR,"Error %s: input vec surface incorrectly specified.\n", FuncName);
01983          exit(1);
01984       }
01985    }
01986 
01987    if (oType == SUMA_SUREFIT) {
01988       if (!of_name2) {
01989        fprintf (SUMA_STDERR,"Error %s: output SureFit surface incorrectly specified. \n", FuncName);
01990        exit(1);
01991       }
01992    }
01993    
01994    if (oType == SUMA_VEC) {
01995       if (!of_name2) {
01996        fprintf (SUMA_STDERR,"Error %s: output vec surface incorrectly specified. \n", FuncName);
01997        exit(1);
01998       }
01999    }
02000 
02001    /* test for existence of input files */
02002    if (!SUMA_filexists(if_name)) {
02003       fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, if_name);
02004       exit(1);
02005    }
02006    
02007    if (if_name2) {
02008       if (!SUMA_filexists(if_name2)) {
02009          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, if_name2);
02010          exit(1);
02011       }
02012    }
02013 
02014    if (sv_name) {
02015       if (!SUMA_filexists(sv_name)) {
02016          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, sv_name);
02017          exit(1);
02018       }
02019    }
02020    
02021    if (Do_tlrc && !sv_name) {
02022       fprintf (SUMA_STDERR,"Error %s: -tlrc must be used with -sv option.\n", FuncName);
02023       exit(1);
02024    }
02025    
02026    if (vp_name) {
02027       if (!SUMA_filexists(vp_name)) {
02028          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, vp_name);
02029          exit(1);
02030       }
02031    }
02032 
02033    /* check for existence of output files */
02034    if (of_name) {
02035       of_name_strip = SUMA_ParseFname (of_name);
02036       OF_name = (char *) SUMA_malloc (sizeof(char)*(strlen(of_name)+20));
02037    }
02038    if (of_name2) {
02039       of_name2_strip = SUMA_ParseFname (of_name2);
02040       OF_name2 = (char *) SUMA_malloc (sizeof(char)*(strlen(of_name2)+20));
02041    }
02042 
02043    if (oType == SUMA_FREE_SURFER) {
02044       if (strcmp (of_name_strip->Ext,".asc")==0) {
02045          sprintf (OF_name,"%s%s.asc", of_name_strip->Path, of_name_strip->FileName_NoExt);
02046       }else {
02047          sprintf (OF_name,"%s%s.asc", of_name_strip->Path, of_name_strip->FileName);
02048       }
02049    }else if (oType == SUMA_PLY) {
02050       if (strcmp (of_name_strip->Ext,".ply")==0) {
02051          sprintf (OF_name,"%s%s.ply", of_name_strip->Path, of_name_strip->FileName_NoExt);
02052       }else {
02053          sprintf (OF_name,"%s%s.ply", of_name_strip->Path, of_name_strip->FileName);
02054       }
02055    }else if (oType == SUMA_SUREFIT) {
02056       if (strcmp (of_name_strip->Ext,".coord")==0) {
02057          sprintf (OF_name,"%s%s.coord", of_name_strip->Path, of_name_strip->FileName_NoExt);
02058       }else {
02059          sprintf (OF_name,"%s%s.coord", of_name_strip->Path, of_name_strip->FileName);
02060       }
02061       if (strcmp (of_name2_strip->Ext,".topo")==0) {
02062          sprintf (OF_name2,"%s%s.topo", of_name2_strip->Path, of_name2_strip->FileName_NoExt);
02063       }else {
02064          sprintf (OF_name2,"%s%s.topo", of_name2_strip->Path, of_name2_strip->FileName);
02065       }
02066    }else {
02067       sprintf (OF_name, "%s",of_name);
02068       if (of_name2) sprintf(OF_name2, "%s",of_name2);
02069    }
02070     
02071    if (SUMA_filexists(OF_name)) {
02072       fprintf (SUMA_STDERR,"Error %s: %s exists already.\n", FuncName, OF_name);
02073       exit(1);
02074    }
02075    
02076    if (of_name2) {
02077       if (SUMA_filexists(OF_name2)) {
02078          fprintf (SUMA_STDERR,"Error %s: %s exists already.\n", FuncName, OF_name2);
02079          exit(1);
02080       }
02081    }
02082    
02083    /* now for the real work */
02084    /* prepare the name of the surface object to read*/
02085    switch (iType) {
02086       case SUMA_SUREFIT:
02087          SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
02088          sprintf(SF_name->name_coord,"%s", if_name);
02089          sprintf(SF_name->name_topo,"%s", if_name2); 
02090          if (!vp_name) { /* initialize to empty string */
02091             SF_name->name_param[0] = '\0'; 
02092          }
02093          else {
02094             sprintf(SF_name->name_param,"%s", vp_name);
02095          }
02096          SO_name = (void *)SF_name;
02097          fprintf (SUMA_STDOUT,"Reading %s and %s...\n", SF_name->name_coord, SF_name->name_topo);
02098          SO = SUMA_Load_Surface_Object (SO_name, SUMA_SUREFIT, SUMA_ASCII, sv_name);
02099          break;
02100       case SUMA_VEC:
02101          SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
02102          sprintf(SF_name->name_coord,"%s", if_name);
02103          sprintf(SF_name->name_topo,"%s", if_name2); 
02104          SO_name = (void *)SF_name;
02105          fprintf (SUMA_STDOUT,"Reading %s and %s...\n", SF_name->name_coord, SF_name->name_topo);
02106          SO = SUMA_Load_Surface_Object (SO_name, SUMA_VEC, SUMA_ASCII, sv_name);
02107          break;
02108       case SUMA_FREE_SURFER:
02109          SO_name = (void *)if_name; 
02110          fprintf (SUMA_STDOUT,"Reading %s ...\n",if_name);
02111          SO = SUMA_Load_Surface_Object (SO_name, SUMA_FREE_SURFER, SUMA_ASCII, sv_name);
02112          break;  
02113       case SUMA_PLY:
02114          SO_name = (void *)if_name; 
02115          fprintf (SUMA_STDOUT,"Reading %s ...\n",if_name);
02116          SO = SUMA_Load_Surface_Object (SO_name, SUMA_PLY, SUMA_FF_NOT_SPECIFIED, sv_name);
02117          break;  
02118       default:
02119          fprintf (SUMA_STDERR,"Error %s: Bad format.\n", FuncName);
02120          exit(1);
02121    }
02122    
02123    if (!SO) {
02124       fprintf (SUMA_STDERR,"Error %s: Failed to read input surface.\n", FuncName);
02125       exit (1);
02126    }
02127    
02128    if (Do_tlrc) {
02129       fprintf (SUMA_STDOUT,"Performing talairach transform...\n");
02130 
02131       /* form the tlrc version of the surface volume */
02132       tlrc_name = (char *) SUMA_calloc (strlen(SO->VolPar->dirname)+strlen(SO->VolPar->prefix)+60, sizeof(char));
02133       sprintf (tlrc_name, "%s%s+tlrc.HEAD", SO->VolPar->dirname, SO->VolPar->prefix);
02134       if (!SUMA_filexists(tlrc_name)) {
02135          fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, tlrc_name);
02136          exit(1);
02137       }
02138       
02139       /* read the tlrc header */
02140       aset = THD_open_dataset(tlrc_name) ;
02141       if( !ISVALID_DSET(aset) ){
02142          fprintf (SUMA_STDERR,"Error %s: %s is not a valid data set.\n", FuncName, tlrc_name) ;
02143          exit(1);
02144       }
02145       if( aset->warp == NULL ){
02146          fprintf (SUMA_STDERR,"Error %s: tlrc_name does not contain a talairach transform.\n", FuncName);
02147          exit(1);
02148       }
02149       
02150       warp = aset->warp ;
02151       
02152       /* now warp the coordinates, one node at a time */
02153       if (!SUMA_AFNI_forward_warp_xyz(warp, SO->NodeList, SO->N_Node)) {
02154          fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AFNI_forward_warp_xyz.\n", FuncName);
02155          exit(1);
02156       }
02157 
02158       
02159       
02160    }
02161    
02162    if (LocalHead) SUMA_Print_Surface_Object (SO, stderr);
02163    
02164    fprintf (SUMA_STDOUT,"Writing surface...\n");
02165    
02166 
02167    /* write the surface object */
02168    switch (oType) {
02169       case SUMA_SUREFIT:
02170          if (SF_name) SUMA_free(SF_name);
02171          SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
02172          sprintf(SF_name->name_coord,"%s", of_name);
02173          sprintf(SF_name->name_topo,"%s", of_name2); 
02174          if (!vp_name) { /* initialize to empty string */
02175             SF_name->name_param[0] = '\0'; 
02176          }
02177          else {
02178             sprintf(SF_name->name_param,"%s", vp_name);
02179          }
02180          SO_name = (void *)SF_name;
02181          if (!SUMA_Save_Surface_Object (SO_name, SO,  SUMA_SUREFIT, SUMA_ASCII)) {
02182             fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
02183             exit (1);
02184          }
02185          break;
02186       case SUMA_VEC:
02187          if (SF_name) SUMA_free(SF_name);
02188          SF_name = (SUMA_SFname *) SUMA_malloc(sizeof(SUMA_SFname));
02189          sprintf(SF_name->name_coord,"%s", of_name);
02190          sprintf(SF_name->name_topo,"%s", of_name2); 
02191          SO_name = (void *)SF_name;
02192          if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_VEC, SUMA_ASCII)) {
02193             fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
02194             exit (1);
02195          }
02196          break;
02197       case SUMA_FREE_SURFER:
02198          SO_name = (void *)of_name; 
02199          if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_FREE_SURFER, SUMA_ASCII)) {
02200             fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
02201             exit (1);
02202          }
02203          break;  
02204       case SUMA_PLY:
02205          SO_name = (void *)of_name; 
02206          if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_PLY, SUMA_FF_NOT_SPECIFIED)) {
02207             fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
02208             exit (1);
02209          }
02210          break;  
02211       default:
02212          fprintf (SUMA_STDERR,"Error %s: Bad format.\n", FuncName);
02213          exit(1);
02214    }
02215    
02216    
02217    
02218    if (of_name_strip) of_name_strip = SUMA_Free_Parsed_Name (of_name_strip);
02219    if (of_name2_strip) of_name2_strip = SUMA_Free_Parsed_Name (of_name2_strip);
02220    if (OF_name) SUMA_free(OF_name);
02221    if (OF_name2) SUMA_free(OF_name2);
02222    if (SF_name) SUMA_free(SF_name);
02223    if (SO) SUMA_Free_Surface_Object(SO);
02224    return (0);
02225 }
02226 #endif
02227 
02228 /*!
02229    \brief Handles opening an ROI file
02230    \param filename (char *)
02231    \param data(void *) */
02232 void SUMA_OpenDrawnROI (char *filename, void *data)
02233 {
02234    static char FuncName[]={"SUMA_OpenDrawnROI"};
02235    DList *list=NULL;
02236    int i;
02237    SUMA_SurfaceObject *SO=NULL;
02238    
02239    SUMA_Boolean LocalHead = NOPE;
02240    
02241    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02242 
02243    SUMA_LH("Called");   
02244 
02245    /* check for type ... */
02246    
02247    if (SUMA_isExtension(filename, ".niml.roi")) {
02248       /* load niml ROI */
02249       if (!SUMA_OpenDrawnROI_NIML (filename)) {
02250          SUMA_SLP_Err("Failed to read NIML ROI.");
02251          SUMA_RETURNe;
02252       }
02253    }else if (SUMA_isExtension(filename, ".1D.roi")) {
02254       /* load 1D ROI */
02255       SUMA_SLP_Warn("Assuming parent surface.");
02256       SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SUMAg_SVv[0].Focus_SO_ID].OP);
02257       if (!SUMA_OpenDrawnROI_1D (filename, SO->idcode_str)) {
02258          SUMA_SLP_Err("Failed to read NIML ROI.");
02259          SUMA_RETURNe;
02260       }
02261    }else {
02262       SUMA_SLP_Err(  "Failed to recognize\n"
02263                      "ROI type from filename.");
02264       SUMA_RETURNe;
02265    } 
02266    /* if there are no currentROIs selected, set currentROI to the
02267       first in the list */
02268    if (!SUMAg_CF->X->DrawROI->curDrawnROI) {
02269       i = 0;
02270       do {
02271          if (SUMAg_DOv[i].ObjectType == ROIdO_type) SUMAg_CF->X->DrawROI->curDrawnROI =
02272                                              (SUMA_DRAWN_ROI *)SUMAg_DOv[i].OP;
02273          ++i;
02274       } while (i < SUMAg_N_DOv && !SUMAg_CF->X->DrawROI->curDrawnROI);
02275    }
02276    
02277    if (SUMAg_CF->X->DrawROI->curDrawnROI) {
02278       SUMA_InitializeDrawROIWindow(SUMAg_CF->X->DrawROI->curDrawnROI);   
02279    }
02280    
02281    /* Now update the Paint job on the ROI plane */
02282    if (!SUMA_Paint_SO_ROIplanes (
02283             SUMA_findSOp_inDOv(SUMAg_CF->X->DrawROI->curDrawnROI->Parent_idcode_str, 
02284             SUMAg_DOv, SUMAg_N_DOv), SUMAg_DOv, SUMAg_N_DOv)) {
02285       SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes.");
02286       SUMA_RETURNe;
02287    }
02288    
02289    /* put a nice redisplay here */
02290    if (!list) list = SUMA_CreateList ();
02291    SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible, SES_Suma, NULL); 
02292    if (!SUMA_Engine(&list)) {
02293       SUMA_SLP_Err("Failed to redisplay.");
02294       SUMA_RETURNe;
02295    }
02296    
02297    SUMA_RETURNe; 
02298 }
02299 
02300 /*!
02301    Since parent information does not exist in ROI 1D files, 
02302    you need to specify the parent surface. 
02303 */ 
02304 SUMA_Boolean SUMA_OpenDrawnROI_1D (char *filename, char *Parent_idcode_str)
02305 {
02306    static char FuncName[]={"SUMA_OpenDrawnROI_1D"};
02307    MRI_IMAGE *im = NULL;
02308    int ncol, nrow, *iLabel=NULL, *iNode = NULL, *isort=NULL,
02309       i, N_Labels, *iStart=NULL, *iStop=NULL, cnt = 0;
02310    float *far=NULL;
02311    SUMA_DRAWN_ROI *ROI=NULL;
02312    SUMA_Boolean LocalHead = YUP;
02313    
02314    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02315 
02316    SUMA_LH("Called");
02317    
02318    im = mri_read_1D (filename);
02319    
02320    if (!im) {
02321       SUMA_SLP_Err("Failed to read 1D file");
02322       SUMA_RETURN(NOPE);
02323    }
02324    
02325    far = MRI_FLOAT_PTR(im);
02326    ncol = im->nx;
02327    nrow = im->ny;
02328    
02329    if (!ncol) {
02330       SUMA_SL_Err("Empty file");
02331       SUMA_RETURN(NOPE);
02332    }
02333    if (nrow != 2) {
02334       SUMA_SL_Err("File must have\n"
02335                   " 2 columns.");
02336       SUMA_RETURN(NOPE);
02337    }
02338    
02339    if (LocalHead) {
02340       SUMA_disp_vect(far, ncol*nrow);
02341    }
02342    
02343    /* Now you must turn the thing to some form of ROI */
02344    /* 1- Sort by label
02345       2- For each label, 
02346          * figure out the contours and the fillers
02347          * create an ROI for them
02348    */ 
02349    
02350    /* copy the node indices and labels for cleanliness */
02351    iLabel = (int *)SUMA_malloc(ncol*sizeof(int));
02352    iNode = (int *)SUMA_malloc(ncol*sizeof(int));
02353    if (!iNode || !iLabel) {
02354       SUMA_SL_Err("Failed to allocate");
02355       SUMA_RETURN(NOPE);
02356    }
02357    for (i=0; i < ncol; ++i) iLabel[i] = (int)far[i+ncol];
02358    /* sort the Labels and the iNode accordingly */
02359    isort = SUMA_z_dqsort( iLabel, ncol);
02360    for (i=0; i < ncol; ++i) iNode[i] = (int)far[isort[i]];
02361    
02362    mri_free(im); im = NULL;   /* done with that baby */
02363    
02364    /* Count the number of distinct labels */
02365    N_Labels = 1;
02366    for (i=1; i < ncol; ++i) if (iLabel[i] != iLabel[i-1]) ++N_Labels;
02367    /* store where each label begins and ends */
02368    iStart = (int *)SUMA_malloc(N_Labels*sizeof(int));
02369    iStop = (int *)SUMA_malloc(N_Labels*sizeof(int));
02370    if (!iStart || !iStop) {
02371       SUMA_SL_Err("Failed to allocate");
02372       SUMA_RETURN(NOPE);
02373    }
02374    cnt = 0;
02375    iStart[cnt] = 0;
02376    iStop[cnt] = ncol -1;
02377    for (i=1; i < ncol; ++i) {
02378       if (iLabel[i] != iLabel[i-1]) {
02379          iStop[cnt] = i-1;
02380          ++cnt; 
02381          iStart[cnt] = i;
02382          iStop[cnt] = ncol -1;
02383       }
02384    }
02385    
02386    for (i=0; i < N_Labels; ++i) {
02387       int Value, N_Node, *Node=NULL;
02388       float fillcolor[3], edgecolor[3];
02389       int edgethickness;
02390       
02391       edgethickness = 3;
02392       fillcolor[0] = 1; fillcolor[1] = 1; fillcolor[2] = 0; 
02393       edgecolor[0] = 0; edgecolor[1] = 0; edgecolor[2] = 1; 
02394       Value = iLabel[iStart[i]]; /* the index label of this ROI */
02395       N_Node = iStop[i] - iStart[i] + 1; /* Number of Nodes in this ROI */
02396       Node = &(iNode[iStart[i]]); /* pointer to location of first index in this ROI */
02397       ROI = SUMA_1DROI_to_DrawnROI( Node, N_Node , 
02398                                     Value, Parent_idcode_str,
02399                                     filename, NULL,
02400                                     fillcolor, edgecolor, edgethickness);
02401       
02402       if (LocalHead) fprintf (SUMA_STDERR, "%s: ROI->Parent_idcode_str %s\n", FuncName, ROI->Parent_idcode_str);
02403 
02404       /* add ROI to DO list */
02405       if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)ROI, ROIdO_type, SUMA_LOCAL)) {
02406          fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
02407       }
02408    }
02409    
02410    if (iLabel) SUMA_free(iLabel); iLabel = NULL;
02411    if (isort) SUMA_free(isort); isort = NULL;
02412    if (iNode) SUMA_free(iNode); iNode = NULL;
02413    if (iStart) SUMA_free(iStart); iStart = NULL;
02414    if (iStop) SUMA_free(iStop); iStop = NULL;
02415    
02416    SUMA_RETURN(YUP);
02417      
02418 }
02419 
02420 SUMA_Boolean SUMA_OpenDrawnROI_NIML (char *filename)
02421 { /* begin embedded function */
02422    static char FuncName[]={"SUMA_OpenDrawnROI_NIML"};
02423    char stmp[SUMA_MAX_NAME_LENGTH+100], *nel_idcode;
02424    NI_element *nel = NULL;
02425    NI_element **nelv=NULL;
02426    NI_stream ns ;
02427    int n_read=0, idat, answer, inel, iDO, N_nel;
02428    SUMA_NIML_ROI_DATUM *niml_ROI_datum_buff=NULL;
02429    SUMA_NIML_DRAWN_ROI * nimlROI=NULL;
02430    SUMA_DRAWN_ROI *ROI=NULL;
02431    SUMA_Boolean found = YUP, AddNel = YUP, AlwaysReplace = NOPE, NeverReplace = NOPE;
02432    SUMA_Boolean LocalHead = YUP;
02433    
02434    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02435 
02436    
02437    if (SUMAg_CF->nimlROI_Datum_type < 0) {
02438       SUMA_SL_Err("Bad niml type code");
02439       SUMA_RETURN(NOPE);
02440    }
02441    if (LocalHead) fprintf(SUMA_STDERR, "%s: roi_type code = %d\n", FuncName, SUMAg_CF->nimlROI_Datum_type) ;
02442 
02443    sprintf(stmp,"file:%s", filename);
02444    ns = NI_stream_open( stmp , "r" ) ;
02445    if( ns == NULL ){
02446       SUMA_SL_Err("Can't open ROI file"); 
02447       SUMA_RETURN(NOPE);
02448    }
02449    
02450    nelv = (NI_element **) SUMA_calloc(SUMA_MAX_DISPLAYABLE_OBJECTS, sizeof(NI_element *));
02451    if (!nelv) {
02452       SUMA_SLP_Crit("Failed to allocate");
02453       SUMA_RETURN(NOPE);
02454    }
02455    
02456    NeverReplace = NOPE;
02457    AlwaysReplace = NOPE;
02458    inel = 0;
02459    do {
02460       nel = NI_read_element(ns,1) ;
02461       
02462       if (nel) {
02463          found = YUP;
02464          
02465          if (LocalHead && 0) SUMA_nel_stdout (nel);
02466          
02467          if (strcmp(nel->name,"A_drawn_ROI")) {
02468             SUMA_SLP_Err ("ni element not of the \n'A_drawn_ROI' variety.\nElement discarded.");
02469             NI_free_element(nel) ; nel = NULL;
02470             SUMA_RETURN(NOPE);
02471          }
02472          /* somewhat redundant test */
02473          if (nel->vec_typ[0] != SUMAg_CF->nimlROI_Datum_type) {
02474             SUMA_SLP_Err ("Datum type mismatch.");
02475             NI_free_element(nel) ; nel = NULL;
02476             SUMA_RETURN(NOPE);
02477          }
02478 
02479          /* find out if a displayable object exists with the same idcode_str */
02480          nel_idcode = NI_get_attribute( nel , "idcode_str");
02481          if (SUMA_existDO(nel_idcode, SUMAg_DOv, SUMAg_N_DOv)) {
02482             if (AlwaysReplace) {
02483                AddNel = YUP; 
02484             }
02485             if (NeverReplace) {
02486                AddNel = NOPE;
02487             }
02488             if (!AlwaysReplace && !NeverReplace) {   /* ASk */
02489                sprintf(stmp, "Found duplicate ROIs.\n"\
02490                                           "Replace ROI %s (%s) by\n" \
02491                                           "version in file ?", 
02492                NI_get_attribute( nel , "Label"), nel_idcode); 
02493 
02494                answer = SUMA_AskUser_ROI_replace (SUMAg_SVv[0].X->TOPLEVEL, 
02495                                  stmp, 
02496                                  0);
02497                if (LocalHead) fprintf (SUMA_STDERR,"%s: Got %d, You ?\n", FuncName, answer);
02498                switch (answer) {
02499                   case SUMA_YES:
02500                      SUMA_LH("YES");
02501                      AddNel = YUP;
02502                      break;
02503 
02504                   case SUMA_NO:
02505                      SUMA_LH("NO");
02506                      /* don't add this one */
02507                      AddNel = NOPE;
02508                      break;
02509 
02510                   case SUMA_YES_ALL:
02511                      SUMA_LH("YES ALL");
02512                      /* cancel Check_Prior */
02513                      AddNel = YUP;
02514                      AlwaysReplace = YUP;
02515                      break;
02516 
02517                   case SUMA_NO_ALL:
02518                      SUMA_LH("NO ALL");
02519                      /* don't add this one and set flag to ignore the doubles */
02520                      AddNel = NOPE;
02521                      NeverReplace = YUP;
02522                      break;
02523 
02524                   default:
02525                      SUMA_SLP_Crit("Don't know what to do with this button.");
02526                      SUMA_RETURN(NOPE);
02527                      break;
02528                }
02529             } 
02530          } else {
02531             AddNel = YUP;
02532          } 
02533          
02534          if (AddNel) {
02535             SUMA_LH("Adding Nel");
02536             nelv[inel] = nel;
02537             ++inel; 
02538          }else {
02539             SUMA_LH("Skipping Nel");
02540          }
02541          
02542          ++n_read;
02543       }else {
02544          found = NOPE;
02545       } 
02546       
02547    } while (found);
02548    
02549    NI_stream_close(ns) ;
02550    N_nel = inel;
02551    
02552    if( !n_read){
02553       SUMA_SL_Err("Found no elements in file!"); 
02554       SUMA_free(nelv);
02555       SUMA_RETURN(NOPE);
02556    }
02557    
02558    /* Now turn those nel into ROIS */
02559    for (inel=0; inel < N_nel; ++inel) {
02560       if (LocalHead) fprintf (SUMA_STDERR,"%s: Processing nel %d/%d...\n", FuncName, inel, N_nel);
02561       nel = nelv[inel];
02562       nel_idcode = NI_get_attribute( nel , "idcode_str");
02563 
02564       /* store nel in nimlROI struct */
02565 
02566       /* allocate for nimlROI */
02567       nimlROI = (SUMA_NIML_DRAWN_ROI *)SUMA_malloc(sizeof(SUMA_NIML_DRAWN_ROI));
02568       nimlROI->Type = (int)strtod(NI_get_attribute( nel , "Type"), NULL);
02569       nimlROI->idcode_str = NI_get_attribute( nel , "idcode_str");
02570       nimlROI->Parent_idcode_str = NI_get_attribute( nel , "Parent_idcode_str");
02571       nimlROI->Label = NI_get_attribute( nel , "Label");
02572       nimlROI->iLabel = (int)strtod(NI_get_attribute( nel , "iLabel"), NULL);
02573       nimlROI->N_ROI_datum = nel->vec_len;
02574       nimlROI->ColPlaneName = NI_get_attribute( nel , "ColPlaneName");
02575       if (SUMA_StringToNum (NI_get_attribute( nel , "FillColor"), 
02576                            nimlROI->FillColor, 3) < 0) {
02577          SUMA_SLP_Err("Failed in reading FillColor.");
02578          SUMA_free(nelv);
02579          SUMA_RETURN(NOPE);
02580       }
02581       if (SUMA_StringToNum (NI_get_attribute( nel , "EdgeColor"), 
02582                            nimlROI->EdgeColor, 3) < 0) {
02583          SUMA_SLP_Err("Failed in reading EdgeColor.");
02584          SUMA_free(nelv);
02585          SUMA_RETURN(NOPE);
02586       }
02587       nimlROI->EdgeThickness = (int)strtod(NI_get_attribute( nel , "EdgeThickness"), NULL);              
02588       
02589       if (LocalHead) {
02590          fprintf (SUMA_STDERR,"%s: vec_type[0] = %d (%d)\n", 
02591             FuncName, nel->vec_typ[0], SUMAg_CF->nimlROI_Datum_type) ;
02592          fprintf (SUMA_STDERR,"%s: vec_len =%d\tvec_num = %d\nidcode_str %s, Parent_idcode_str %s\n",
02593             FuncName, nel->vec_len, nel->vec_num,
02594             nimlROI->idcode_str, nimlROI->Parent_idcode_str);
02595       }
02596 
02597       nimlROI->ROI_datum = (SUMA_NIML_ROI_DATUM *)SUMA_malloc(nimlROI->N_ROI_datum*sizeof(SUMA_NIML_ROI_DATUM));
02598 
02599       /* DO NOT use niml_ROI_datum_buff = (SUMA_NIML_ROI_DATUM *)nel->vec[idat];
02600       inside the loop.
02601       For the SUMA_NIML_DRAWN_ROI you have one column of (SUMA_NIML_ROI_DATUM *)
02602       ni_type = "SUMA_NIML_ROI_DATUM". If you had for type:
02603       "SUMA_NIML_ROI_DATUM, int" then you'd have two columns with the second
02604       column being a vector of ints. The only caveat is that the second column
02605       must be of equal length to the first. */
02606       niml_ROI_datum_buff = (SUMA_NIML_ROI_DATUM *)nel->vec[0]; 
02607       /* now fill the ROI_datum structures */
02608       SUMA_LH("Filling ROI datum structures...");
02609       for (idat=0; idat< nimlROI->N_ROI_datum ; ++idat) {
02610          if (LocalHead) fprintf (SUMA_STDERR,"%s: i=%d\n", FuncName, idat);
02611          nimlROI->ROI_datum[idat].action = niml_ROI_datum_buff[idat].action;
02612          nimlROI->ROI_datum[idat].Type = niml_ROI_datum_buff[idat].Type;
02613          nimlROI->ROI_datum[idat].N_n = niml_ROI_datum_buff[idat].N_n;
02614          if (nimlROI->ROI_datum[idat].N_n > 0) {
02615             if (LocalHead) fprintf (SUMA_STDERR,"%s: Copying nPath, %d values\n", FuncName, nimlROI->ROI_datum[idat].N_n);
02616             nimlROI->ROI_datum[idat].nPath = (int *)SUMA_malloc(sizeof(int)*nimlROI->ROI_datum[idat].N_n);
02617             memcpy(nimlROI->ROI_datum[idat].nPath, niml_ROI_datum_buff[idat].nPath, sizeof(int)*nimlROI->ROI_datum[idat].N_n);
02618          } else {
02619             SUMA_LH("Null nPath");
02620             nimlROI->ROI_datum[idat].nPath = NULL;
02621          } 
02622          if (LocalHead) { 
02623             fprintf (SUMA_STDERR,"%s: Segment %d\tType %d\tN_n %d\taction %d\n", 
02624                FuncName, idat, nimlROI->ROI_datum[idat].Type,  
02625                nimlROI->ROI_datum[idat].N_n,nimlROI->ROI_datum[idat].action);
02626          }
02627       }
02628 
02629       /* Does ROI already exist with the same idcode_str ?*/
02630       
02631       SUMA_LH("Checking for duplicates...");
02632       if ((iDO = SUMA_whichDO(nel_idcode, SUMAg_DOv, SUMAg_N_DOv)) >= 0) {
02633          SUMA_LH("Duplicate found ... Deleteing old one...");
02634          /* ROI already exists delete it */
02635          if (!SUMA_DeleteROI ((SUMA_DRAWN_ROI *)SUMAg_DOv[iDO].OP)) {
02636             SUMA_SLP_Err("Failed to delete ROI");
02637             SUMA_RETURN(NOPE); 
02638          }
02639       }
02640       
02641       /* transfom nimlROI to a series of drawing actions */
02642       SUMA_LH("Transforming ROI to a series of actions...");
02643       ROI = SUMA_NIMLDrawnROI_to_DrawnROI (nimlROI);
02644       if (LocalHead) fprintf (SUMA_STDERR, "%s: ROI->Parent_idcode_str %s\n", FuncName, ROI->Parent_idcode_str);
02645 
02646       /* add ROI to DO list */
02647       if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)ROI, ROIdO_type, SUMA_LOCAL)) {
02648          fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
02649       }
02650 
02651       /* manually free nimlROI fields that received copies of allocated space as opposed to pointer copies */
02652       SUMA_free(nimlROI->idcode_str);
02653       SUMA_free(nimlROI->Parent_idcode_str); 
02654       SUMA_free(nimlROI->Label);
02655       SUMA_free(nimlROI->ColPlaneName);
02656 
02657 
02658       /* free nimlROI */
02659       nimlROI = SUMA_Free_NIMLDrawROI(nimlROI);
02660 
02661       /* free nel and get it ready for the next load */
02662       NI_free_element(nel) ; nel = NULL;
02663       
02664    }
02665    
02666    /* free nelv */
02667    SUMA_free(nelv);
02668    
02669    SUMA_RETURN(YUP);
02670 } 
02671    
02672 /*!
02673    \brief handles saving ROI to filename.
02674    
02675    \param filename (char *)
02676    \param data(void *) pointer to DrawnROI stucture to be saved.
02677           If you pass null then SUMAg_CF->X->DrawROI->curDrawnROI is used.
02678 */
02679 void SUMA_SaveDrawnROI (char *filename, void *data)
02680 {
02681    static char FuncName[]={"SUMA_SaveDrawnROI"};
02682    SUMA_DRAWN_ROI *DrawnROI=NULL;
02683    SUMA_SurfaceObject *SO= NULL;
02684    SUMA_Boolean LocalHead = YUP;
02685    
02686    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02687 
02688    SUMA_LH("Called");   
02689    if (!data) {
02690       DrawnROI = SUMAg_CF->X->DrawROI->curDrawnROI;
02691    } else {
02692       DrawnROI = (SUMA_DRAWN_ROI *)data;
02693    }
02694    
02695    /* is there a DrawnROI to work with ? */
02696    if (!DrawnROI) {
02697       SUMA_SLP_Err("No ROI selected.");
02698       SUMA_RETURNe;
02699    }
02700    
02701    /* Find the parent SO of that ROI */
02702    SO = SUMA_findSOp_inDOv(DrawnROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv);
02703    if (!SO) {
02704       SUMA_SLP_Err("No Parent surface found.");
02705       SUMA_RETURNe;
02706    }
02707    
02708    /* switch the type of saving */
02709    switch (SUMAg_CF->X->DrawROI->SaveMode) {
02710       case SW_DrawROI_SaveMode1D:
02711          if (!SUMA_SaveDrawnROI_1D (filename, SO, DrawnROI, SUMAg_CF->X->DrawROI->SaveWhat)) {
02712             SUMA_SLP_Err("Failed to save ROI to disk");
02713             SUMA_RETURNe;
02714          }   
02715          break;
02716       case SW_DrawROI_SaveModeNIML:
02717          if (!SUMA_SaveDrawnROINIML (filename, SO, DrawnROI, SUMAg_CF->X->DrawROI->SaveWhat, SUMA_ASCII)) {
02718             SUMA_SLP_Err("Failed to save ROI to disk");
02719             SUMA_RETURNe;
02720          }
02721          break;
02722       case SW_DrawROI_SaveMode:
02723       case SW_N_DrawROI_SaveMode:
02724       default:
02725          SUMA_SL_Err("WhatYouTalkinAbout?");
02726          SUMA_RETURNe;
02727          break;
02728    }
02729    
02730    SUMA_RETURNe;
02731 } 
02732 
02733 SUMA_Boolean SUMA_SaveDrawnROI_1D (char *filename, SUMA_SurfaceObject *SO, SUMA_DRAWN_ROI *DrawnROI, int SaveWhat) 
02734 {
02735    static char FuncName[]={"SUMA_SaveDrawnROI_1D"};
02736    char stmp[SUMA_MAX_NAME_LENGTH+20];
02737    SUMA_DRAWN_ROI **ROIv = NULL;
02738    int N_ROI=0;
02739    SUMA_Boolean LocalHead = YUP;
02740    
02741    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02742    SUMA_LH("Called");   
02743 
02744    if (SaveWhat == SW_DrawROI_SaveWhatThis) {
02745       if (!SUMA_Write_DrawnROI_1D (&DrawnROI, 1, filename)) {
02746          sprintf(stmp,"Failed to write %s", filename);
02747          SUMA_SLP_Err(stmp);
02748          SUMA_RETURN(NOPE);
02749       }
02750    }else if (SaveWhat == SW_DrawROI_SaveWhatRelated){
02751       /* get the pointers to the ROIs that are related to SO*/
02752       if (!(ROIv = SUMA_Find_ROIrelatedtoSO (SO, SUMAg_DOv, SUMAg_N_DOv, &N_ROI))) {
02753          SUMA_SLP_Err("Failed to write ROIs related to SO.");
02754          SUMA_RETURN(NOPE);
02755       }
02756       if (!SUMA_Write_DrawnROI_1D (ROIv, N_ROI, filename)) {
02757          sprintf(stmp,"Failed to write %s", filename);
02758          SUMA_SLP_Err(stmp);
02759          SUMA_RETURN(NOPE);
02760       }
02761         
02762       if (ROIv) SUMA_free(ROIv);    
02763    } else {
02764       SUMA_SLP_Err("SaveWhat option not nderstood");
02765       SUMA_RETURN(NOPE);
02766    }
02767    
02768    
02769 
02770    SUMA_RETURN(YUP);
02771 }
02772 
02773 SUMA_Boolean SUMA_SaveDrawnROINIML (char *filename, SUMA_SurfaceObject *SO, SUMA_DRAWN_ROI *DrawnROI, int SaveWhat, int Format) 
02774 {
02775    static char FuncName[]={"SaveDrawnROINIML"};
02776    char stmp[SUMA_MAX_NAME_LENGTH+20];
02777    SUMA_DRAWN_ROI **ROIv = NULL;
02778    int N_ROI=0;
02779    SUMA_Boolean LocalHead = YUP;
02780    
02781    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02782    SUMA_LH("Called");   
02783 
02784    if (SaveWhat == SW_DrawROI_SaveWhatThis) {
02785       if (!SUMA_Write_DrawnROI_NIML (&DrawnROI, 1, filename, Format)) {
02786          sprintf(stmp,"Failed to write %s", filename);
02787          SUMA_SLP_Err(stmp);
02788          SUMA_RETURN(NOPE);
02789       }
02790    }else if (SaveWhat == SW_DrawROI_SaveWhatRelated){
02791       /* get the pointers to the ROIs that are related to SO*/
02792       if (!(ROIv = SUMA_Find_ROIrelatedtoSO (SO, SUMAg_DOv, SUMAg_N_DOv, &N_ROI))) {
02793          SUMA_SLP_Err("Failed to write ROIs related to SO.");
02794          SUMA_RETURN(NOPE);
02795       }
02796       if (!SUMA_Write_DrawnROI_NIML (ROIv, N_ROI, filename, Format)) {
02797          sprintf(stmp,"Failed to write %s", filename);
02798          SUMA_SLP_Err(stmp);
02799          SUMA_RETURN(NOPE);
02800       }
02801         
02802       if (ROIv) SUMA_free(ROIv);    
02803    } else {
02804       SUMA_SLP_Err("SaveWhat option not nderstood");
02805       SUMA_RETURN(NOPE);
02806    }
02807   
02808    SUMA_RETURN(YUP);
02809 }
02810 
02811 /*!
02812    \brief writes a vector of SUMA_DRAWN_ROI * to disk in NIML format
02813 */
02814 
02815 SUMA_Boolean SUMA_Write_DrawnROI_NIML (SUMA_DRAWN_ROI **ROIv, int N_ROI, char *filename, int Format) 
02816 {
02817    static char FuncName[]={"SUMA_Write_DrawnROI_NIML"};
02818    char stmp[SUMA_MAX_NAME_LENGTH+20];
02819    char *newname=NULL;
02820    int i;
02821    NI_element *nel ;
02822    NI_stream ns ;
02823    SUMA_NIML_DRAWN_ROI *niml_ROI = NULL;
02824    SUMA_DRAWN_ROI *ROI = NULL;
02825    SUMA_Boolean WriteBin = NOPE, LocalHead = YUP;
02826 
02827    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02828 
02829    if (Format == SUMA_ASCII) WriteBin = NOPE;
02830    else if (Format == SUMA_BINARY) WriteBin = YUP;
02831    else {
02832       SUMA_SL_Err("Wrong format");
02833       SUMA_RETURN(NOPE);
02834    }
02835    
02836    if (SUMAg_CF->nimlROI_Datum_type < 0) {
02837       SUMA_SL_Err("Bad niml type code");
02838       SUMA_RETURN(NOPE);
02839    }
02840    if (LocalHead) fprintf(SUMA_STDERR, "%s: roi_type code = %d\n", FuncName, SUMAg_CF->nimlROI_Datum_type) ;
02841 
02842    /* add a .niml.roi extension */
02843    if (strlen(filename) >= SUMA_MAX_NAME_LENGTH-20) {
02844       SUMA_SLP_Err("Give me a break, what kind of a filename is this ?");
02845       SUMA_RETURN(NOPE);
02846    }
02847 
02848    sprintf(stmp,"file:%s", filename);
02849    newname = SUMA_Extension(stmp, ".niml.roi", NOPE); 
02850    SUMA_LH(newname);
02851    ns = NI_stream_open( newname , "w" ) ;
02852 
02853    /* write the various ROIs */
02854    for (i=0; i < N_ROI; ++i) {
02855       ROI = ROIv[i];
02856       if (!ROI) {
02857          SUMA_SL_Err("NULL ROI!");
02858          NI_stream_close( ns ) ; 
02859          SUMA_RETURN(NOPE);
02860       }
02861       /* Transform the ROI to niml friendly structure */
02862       if (!(niml_ROI = SUMA_DrawnROI_to_NIMLDrawnROI (ROI))) {
02863          SUMA_SL_Err("NULL niml_ROI!");
02864          NI_stream_close( ns ) ; 
02865          SUMA_RETURN(NOPE);
02866       }
02867 
02868       /* Now create a ni element */
02869       if (LocalHead) fprintf(SUMA_STDERR,"%s: Creating new element of %d segments\n", FuncName, niml_ROI->N_ROI_datum);
02870       nel = NI_new_data_element("A_drawn_ROI",  niml_ROI->N_ROI_datum);
02871 
02872       SUMA_LH("Adding column...");
02873       NI_add_column( nel , SUMAg_CF->nimlROI_Datum_type, niml_ROI->ROI_datum );
02874 
02875       SUMA_LH("Setting attributes...");
02876       NI_set_attribute (nel, "idcode_str", niml_ROI->idcode_str);
02877       NI_set_attribute (nel, "Parent_idcode_str", niml_ROI->Parent_idcode_str);
02878       NI_set_attribute (nel, "Label", niml_ROI->Label);
02879       sprintf(stmp,"%d", niml_ROI->iLabel);
02880       NI_set_attribute (nel, "iLabel", stmp);
02881       sprintf(stmp,"%d", niml_ROI->Type);
02882       NI_set_attribute (nel, "Type", stmp);
02883       NI_set_attribute (nel, "ColPlaneName", niml_ROI->ColPlaneName);
02884       sprintf(stmp,"%f %f %f", niml_ROI->FillColor[0], niml_ROI->FillColor[1],
02885                               niml_ROI->FillColor[2]);
02886       NI_set_attribute (nel, "FillColor",stmp);
02887       sprintf(stmp,"%f %f %f", niml_ROI->EdgeColor[0], niml_ROI->EdgeColor[1],
02888                               niml_ROI->EdgeColor[2]);
02889       NI_set_attribute (nel, "EdgeColor",stmp);
02890       sprintf(stmp,"%d", niml_ROI->EdgeThickness);
02891       NI_set_attribute (nel, "EdgeThickness", stmp);                   
02892       
02893       if (LocalHead) SUMA_nel_stdout (nel);
02894 
02895       if (!WriteBin) {
02896          SUMA_LH ("Writing element, Text mode.");
02897          if (NI_write_element( ns , nel , NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) < 0) {
02898            SUMA_SL_Err("Badness, failed to write nel");
02899            NI_stream_close( ns ) ; 
02900            SUMA_RETURN(NOPE);
02901          }
02902       } else {
02903          SUMA_LH ("Writing element, Binary mode.");
02904          if (NI_write_element( ns , nel , NI_BINARY_MODE) < 0) {
02905            SUMA_SL_Err("Badness, failed to write nel");
02906            NI_stream_close( ns ) ; 
02907            SUMA_RETURN(NOPE);
02908          }
02909       } 
02910 
02911       /* free nel */
02912       NI_free_element(nel) ; nel = NULL;
02913 
02914       /* free the niml_ROI structure */
02915       niml_ROI = SUMA_Free_NIMLDrawROI (niml_ROI); niml_ROI = NULL;
02916       
02917    }
02918    
02919    NI_stream_close( ns ) ; 
02920    
02921    if (newname) SUMA_free(newname);
02922    
02923    SUMA_RETURN(YUP);
02924 }
02925 
02926 
02927 /*!
02928    \brief A function to take a SUMA_DRAWN_ROI struct and return an equivalent
02929    SUMA_1D_DRAWN_ROI struct. 
02930    
02931    - Do not free SUMA_1D_DRAWN_ROI manually, many of its fields are 
02932    pointer copies of values in SUMA_DRAWN_ROI.
02933    
02934    \sa SUMA_Free_1DDrawROI
02935 */
02936 SUMA_1D_DRAWN_ROI * SUMA_DrawnROI_to_1DDrawROI (SUMA_DRAWN_ROI *ROI)
02937 {
02938    static char FuncName[]={"SUMA_DrawnROI_to_1DDrawROI"};
02939    SUMA_1D_DRAWN_ROI *ROI_1D=NULL;
02940    SUMA_ROI_DATUM *ROI_Datum=NULL;
02941    DListElmt *Elm = NULL;
02942    int i = -1, cnt = 0, *isort=NULL, *iLabel=NULL, *iNode=NULL;
02943    SUMA_Boolean LocalHead = YUP;
02944 
02945    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
02946 
02947    if (!ROI) {
02948       SUMA_SL_Err("Null ROI");
02949       SUMA_RETURN(NULL);
02950    }
02951    
02952    /* count the total number of nodes in ROI */
02953    
02954    /* allocate for nimlROI */
02955    ROI_1D = (SUMA_1D_DRAWN_ROI *)SUMA_malloc(sizeof(SUMA_1D_DRAWN_ROI));
02956    Elm = NULL;
02957    ROI_1D->N = 0;
02958    do {
02959       if (!Elm) Elm = dlist_head(ROI->ROIstrokelist); 
02960       else Elm = Elm->next;
02961       ROI_Datum = (SUMA_ROI_DATUM *)Elm->data;
02962       ROI_1D->N += ROI_Datum->N_n;
02963    } while (Elm != dlist_tail(ROI->ROIstrokelist));
02964       
02965    ROI_1D->Type = (int)ROI->Type;
02966    ROI_1D->idcode_str = ROI->idcode_str;
02967    ROI_1D->Parent_idcode_str = ROI->Parent_idcode_str;
02968    ROI_1D->Label = ROI->Label;
02969    ROI_1D->iNode = NULL;
02970    ROI_1D->iLabel = NULL;
02971    iNode = (int *) SUMA_calloc(ROI_1D->N, sizeof(int));
02972    iLabel = (int *) SUMA_calloc(ROI_1D->N, sizeof(int));
02973    if (!iNode || !iLabel) {
02974       SUMA_SL_Err("Failed to allocate");
02975       SUMA_RETURN(NULL);
02976    }
02977    
02978    /* now fill the node indices and the node values */
02979    Elm = NULL;
02980    cnt = 0;
02981    do {
02982       if (!Elm) Elm = dlist_head(ROI->ROIstrokelist);
02983       else Elm = Elm->next;
02984       ROI_Datum = (SUMA_ROI_DATUM *)Elm->data;
02985       for (i=0; i < ROI_Datum->N_n; ++i) {
02986          iNode[cnt] = ROI_Datum->nPath[i];
02987          iLabel[cnt] = ROI->iLabel;
02988          ++cnt;
02989       }
02990    } while (Elm != dlist_tail(ROI->ROIstrokelist));
02991    
02992    /* some node entries are redundant, clear those up */
02993    /* first sort iNode */
02994    isort = SUMA_z_dqsort( iNode, ROI_1D->N);
02995 
02996    /* Now sort the labels accordingly */
02997    ROI_1D->iLabel = (int *) SUMA_calloc(ROI_1D->N, sizeof(int));
02998    ROI_1D->iNode = (int *) SUMA_calloc(ROI_1D->N, sizeof(int));
02999    if (!ROI_1D->iNode || !ROI_1D->iLabel) {
03000       SUMA_SL_Err("Failed to allocate");
03001       SUMA_RETURN(NULL);
03002    }
03003    
03004    for (i=0; i < ROI_1D->N; ++i) {
03005       ROI_1D->iLabel[i] = iLabel[isort[i]];
03006    }
03007    if (iLabel) SUMA_free(iLabel); iLabel = NULL; /* done with unsorted version of iLabel */
03008    
03009    /* Now remove redundant entries */
03010    cnt = 0;
03011    ROI_1D->iNode[cnt] = iNode[0]; 
03012    ROI_1D->iLabel[cnt] = ROI_1D->iLabel[0];
03013    ++cnt;
03014    for (i=1;i<ROI_1D->N;++i)
03015     {
03016       if ((iNode[i] != iNode[i- 1]))
03017          {
03018             ROI_1D->iNode[cnt] = iNode[i];
03019             ROI_1D->iLabel[cnt] = ROI_1D->iLabel[i]; 
03020             ++cnt;   
03021          }
03022    }
03023 
03024    
03025    /* you would reallocate here, because cnt is always <= ROI_1D->N,
03026    but it is not worth the effort because cnt is only slightly
03027    less than ROI_1D->N */
03028    
03029    /* just update ROI_1D->N */
03030    ROI_1D->N = cnt;
03031    
03032    if (isort) SUMA_free(isort); isort = NULL;
03033    if (iNode) SUMA_free(iNode); iNode = NULL;
03034    
03035    SUMA_RETURN(ROI_1D);
03036 }
03037 
03038 /*!
03039    \brief frees a ROI_1D structure. These structures are created by
03040     the likes of SUMA_DrawnROI_to_1DDrawROI
03041     
03042     \sa SUMA_DrawnROI_to_1DDrawROI
03043 */
03044 SUMA_1D_DRAWN_ROI * SUMA_Free_1DDrawROI (SUMA_1D_DRAWN_ROI *ROI_1D)
03045 {
03046    static char FuncName[]={"SUMA_Free_1DDrawROI"};
03047    SUMA_Boolean LocalHead = YUP;
03048    
03049    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
03050 
03051    if (!ROI_1D) SUMA_RETURN(NULL);
03052    
03053    if (ROI_1D->iLabel) SUMA_free(ROI_1D->iLabel); 
03054    if (ROI_1D->iNode) SUMA_free(ROI_1D->iNode);
03055    
03056    SUMA_free(ROI_1D);
03057    
03058    SUMA_RETURN(NULL);
03059 }
03060 
03061 
03062 /*!
03063    \brief writes a vector of SUMA_DRAWN_ROI * to disk in afni's 1D ascii format
03064 */
03065 
03066 SUMA_Boolean SUMA_Write_DrawnROI_1D (SUMA_DRAWN_ROI **ROIv, int N_ROI, char *filename) 
03067 {
03068    static char FuncName[]={"SUMA_Write_DrawnROI_1D"};
03069    char *newname=NULL;
03070    int i,j;
03071    SUMA_1D_DRAWN_ROI *ROI_1D = NULL;
03072    SUMA_DRAWN_ROI *ROI = NULL;
03073    FILE *fout=NULL;
03074    SUMA_Boolean LocalHead = YUP;
03075 
03076    if (SUMAg_CF->InOut_Notify) SUMA_DBG_IN_NOTIFY(FuncName);
03077 
03078    /* add a .1D.roi extension */
03079    newname = SUMA_Extension(filename, ".1D.roi", NOPE); 
03080    if (!newname) {
03081       SUMA_SL_Err("Invalid filename");
03082       SUMA_RETURN(NOPE);
03083    }
03084    
03085    SUMA_LH(newname);
03086 
03087    fout = fopen(newname,"w");
03088    if (!fout) {
03089       SUMA_SL_Err("Failed to open file for writing.");
03090       SUMA_RETURN(NOPE);
03091    }
03092 
03093    /* write the various ROIs */
03094    for (i=0; i < N_ROI; ++i) {
03095       ROI = ROIv[i];
03096       if (!ROI) {
03097          SUMA_SL_Err("NULL ROI!");
03098          fclose(fout);
03099          SUMA_RETURN(NOPE);
03100       }
03101       /* Transform the ROI to niml friendly structure */
03102       if (!(ROI_1D = SUMA_DrawnROI_to_1DDrawROI (ROI))) {
03103          SUMA_SL_Err("NULL niml_ROI!");
03104          fclose(fout);
03105          SUMA_RETURN(NOPE);
03106       }
03107 
03108       /* write it out in a NIML friendly format */
03109       /* begin with attributes */
03110       fprintf (fout,"# <A_drawn_ROI\n");
03111       fprintf (fout,"#  ni_type = \"SUMA_1D_ROI_DATUMorint,int?\"\n");
03112       fprintf (fout,"#  ni_dimen = \"%d\"\n",  ROI_1D->N);
03113       fprintf (fout,"#  ni_datasize = \"???\"\n");
03114       fprintf (fout,"#  idcode_str = \"%s\"\n", ROI_1D->idcode_str);
03115       fprintf (fout,"#  Parent_idcode_str = \"%s\"\n", ROI_1D->Parent_idcode_str);
03116       fprintf (fout,"#  Label = \"%s\"\n", ROI_1D->Label);
03117       fprintf (fout,"# >\n");
03118       for (j=0; j < ROI_1D->N; ++j) 
03119          fprintf (fout," %d %d\n", ROI_1D->iNode[j], ROI_1D->iLabel[j]);
03120       fprintf (fout,"# </A_drawn_ROI>\n");
03121       fprintf (fout,"\n");
03122        
03123       /* free the ROI_1D structure */
03124       ROI_1D = SUMA_Free_1DDrawROI (ROI_1D); ROI_1D = NULL;
03125    }
03126    
03127    fclose(fout) ; 
03128    if (newname) SUMA_free(newname);
03129    
03130    SUMA_RETURN(YUP);
03131 }

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