Example #1
0
int main (int argc,char *argv[])
{/* Main */    
   static char FuncName[]={"SampBias"};
   int N_Spec = -1;
   int i;
   SUMA_SurfaceObject *SO = NULL;
   SUMA_SurfSpecFile *Spec;
   SUMA_GENERIC_ARGV_PARSE *ps=NULL;
   void *SO_name = NULL;
   SUMA_DSET *dset=NULL;
   SUMA_Boolean LocalHead = NOPE;
   SUMA_KUBATEST_OPTIONS Opt;
   
   SUMA_STANDALONE_INIT;
   SUMA_mainENTRY;
   
   
   /* Allocate space for DO structure */
   SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
   ps = SUMA_Parse_IO_Args(argc, argv, "-i;-spec;-sv;-s;-o;");
   
   SUMA_SampBias_ParseInput (argv, argc, &Opt, ps);
   if (argc < 4)
   {
      SUMA_S_Err("Too few arguments");
      exit (0);
   }
   
   
   /* read surface */
   Spec = SUMA_IO_args_2_spec(ps, &N_Spec);
   if (N_Spec == 0) {
      SUMA_S_Err("No surfaces found.");
      exit(1);
   }

   SUMA_LH("Loading surface...");
   SO = SUMA_Load_Spec_Surf_with_Metrics(Spec, 0, ps->sv[0], Opt.debug);
   if (!SO) {
         fprintf (SUMA_STDERR,"Error %s:\n"
                              "Failed to find surface\n"
                              "in spec file. \n",
                              FuncName );
         exit(1);
      
   }
   
   
   if (!(dset = calcWithOffsets(SO, &Opt))) {
      SUMA_S_Err("Failed to calc ratios");
      exit(1);
   }
      
   if (!SUMA_AddNgrHist(dset->ngr, "SampBias", argc, argv)) {
      SUMA_S_Err("Failed to add history");
   }

   if (Opt.prefix) {
      char *cc = SUMA_WriteDset_s(Opt.prefix, dset, 
                                  SUMA_NO_DSET_FORMAT, 1,1);
      if (cc) SUMA_free(cc);
   }   
      
   SUMA_LH("clean up");
   if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) {
      SUMA_SL_Err("DO Cleanup Failed!");
   }

   if (Opt.outfile) SUMA_free(Opt.outfile);
   if (Opt.histnote) SUMA_free(Opt.histnote);
   if (Opt.prefix) SUMA_free(Opt.prefix);
   if (Opt.segdo) SUMA_free(Opt.segdo);
   
   if (!SUMA_FreeSpecFields(Spec)) {
      SUMA_S_Err("Failed to free SpecFields");
   } SUMA_free(Spec); Spec = NULL;
   if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
   
   if (!SUMA_Free_CommonFields(SUMAg_CF)) {
      SUMA_SL_Err("SUMAg_CF Cleanup Failed!");}
   
   
   SUMA_RETURN(0);
}
int main (int argc,char *argv[])
{   /* Main */
    static char FuncName[]= {"SurfQual"};
    char *OutName = NULL, ext[5], *prefix = NULL, *shist=NULL;
    SUMA_SURFQUAL_OPTIONS *Opt;
    int SO_read = -1;
    int i, cnt, trouble, consistent = -1, eu = -1, nsi = -1, N_Spec=0;
    SUMA_SurfaceObject *SO = NULL;
    SUMA_SurfSpecFile *Spec=NULL;
    void *SO_name = NULL;
    SUMA_Boolean DoConv = NOPE, DoSphQ = NOPE, DoSelfInt = NOPE;
    int N_bad_nodes, N_bad_facesets;
    SUMA_GENERIC_ARGV_PARSE *ps=NULL;
    SUMA_Boolean LocalHead = NOPE;

    SUMA_STANDALONE_INIT;
    SUMA_mainENTRY;

    ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;");

    /* Allocate space for DO structure */
    SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);

    Opt = SUMA_SurfQual_ParseInput (argv, argc, ps);
    if (argc < 2)
    {
        SUMA_S_Err("Too few options");
        usage_SUMA_SurfQual(ps, 0);
        exit (1);
    }

    /* read all surfaces */
    Spec = SUMA_IO_args_2_spec(ps, &N_Spec);
    if (N_Spec == 0) {
        SUMA_S_Err("No surfaces found.");
        exit(1);
    }

    if (N_Spec > 1 ) {
        SUMA_S_Err( "Mike, you cannot mix -spec with -i or -t options "
                    "for specifying surfaces.");
        exit(1);
    }

    if (Spec->N_Surfs < 1) {
        SUMA_S_Err("No surfaces");
        exit(1);
    }

    if (Opt->self_intersect) DoSelfInt = YUP;

    DoConv = NOPE;
    DoSphQ = NOPE;
    if (Opt->surftype) {
        if (!strcmp(Opt->surftype, "-sphere")) {
            DoSphQ = YUP;
        } else {
            /* Don't complain anymore, maybe winding checking is all users need */
        }
    }

    for (i=0; i < Spec->N_Surfs; ++i) {/* loop to read in surfaces */
        /* now identify surface needed */
        if (!(SO = SUMA_Load_Spec_Surf_with_Metrics(Spec, i, ps->sv[0], 0))) {
            SUMA_S_Err("Failed to load surface .\n");
            exit(1);
        }
        fprintf(SUMA_STDERR,"\nReport for Surface %s\n", SO->Label);
        /* do the quality thing based on the Opt->surftype */
        if (!Opt->out_prefix) prefix = SUMA_copy_string(SO->Label);
        else prefix = SUMA_copy_string (Opt->out_prefix);

        /* check the winding */
        if (!SUMA_MakeConsistent (SO->FaceSetList, SO->N_FaceSet,
                                  SO->EL, 0, &trouble)) {
            SUMA_S_Warn(
                "Failed to make sure surface's mesh is consistently wound.\n"
                "You should fix the mesh.\n");
            consistent = 0;
        }

        {
            int iii=0, isbad=0, ht0;
            int *badedge=(int*)SUMA_calloc(SO->N_Node, sizeof(int));
            /* check on troubled edges */
            while (iii < SO->EL->N_EL) {
                ht0 = SO->EL->ELps[iii][1];
                /* make sure edge is not part of three triangles, if it is,skip it*/
                if (SO->EL->ELps[iii][2] > 2) {
                    ++iii;
                    fprintf( SUMA_STDERR,
                             "%s: Bad edge (#%d: %d--%d), \n"
                             " part of more than 2 triangles, skip it\n",
                             FuncName, i, SO->EL->EL[iii][0], SO->EL->EL[iii][1]);
                    ++badedge[SO->EL->EL[iii][0]];
                    ++badedge[SO->EL->EL[iii][1]];
                    isbad = 1;
                    continue;
                }
                ++iii;
            }
            if (isbad) {
                if (Spec->N_Surfs > 1) {
                    sprintf(ext,"_%c", 65+i);
                    OutName = SUMA_append_replace_string (
                                  prefix,
                                  "_BadEdgeNodes.1D.dset",
                                  ext, 0);
                } else {
                    OutName = SUMA_append_string (prefix, "_BadEdgeNodes.1D.dset");
                }
                SUMA_WRITE_ARRAY_1D(badedge,SO->N_Node,1,OutName);
                if (OutName) SUMA_free(OutName);
                OutName = NULL;
            }
            SUMA_free(badedge);
            badedge = NULL;
        }

        if (DoConv) {
            float *Cx = NULL;
            if (Spec->N_Surfs > 1) {
                sprintf(ext,"_%c", 65+i);
                OutName = SUMA_append_replace_string
                          (prefix, "_Conv_detail.1D.dset", ext, 0);
            } else {
                OutName = SUMA_append_string (prefix, "_Conv_detail.1D.dset");
            }
            Cx = SUMA_Convexity_Engine ( SO->NodeList, SO->N_Node,
                                         SO->NodeNormList, SO->FN, OutName, NULL);
            if (Cx) SUMA_free(Cx);
            Cx = NULL;
            if (OutName) SUMA_free(OutName);
            OutName = NULL;
        }

        if (DoSphQ) {
            if (Spec->N_Surfs > 1) {
                sprintf(ext,"_%c", 65+i);
                OutName = SUMA_append_string (prefix, ext);
            } else {
                OutName = SUMA_copy_string (prefix);
            }
            shist = SUMA_HistString (NULL, argc, argv, NULL);
            SUMA_SphereQuality (SO, OutName, shist, &N_bad_nodes, &N_bad_facesets);
            if (shist) SUMA_free(shist);
            shist = NULL;
            if (OutName) SUMA_free(OutName);
            OutName = NULL;
        }

        if (trouble) { /* put winding problem here to make it visible */
            fprintf (SUMA_STDERR,"\n");
            SUMA_S_Warn(
                "Mesh is not consistent, use ConvertSurface's -make_consistent \n"
                "option to fix the problem before proceeding further.\n"
                "Other results reported by this and other programs\n"
                "may be incorrect if mesh is not consistently wound.\n" );
            consistent = 0;
        } else {
            consistent = 1;
            fprintf (SUMA_STDERR,"\n");
            fprintf (SUMA_STDERR,"Surface is consistently wound\n");
        }
        {
            SUMA_EULER_SO(SO, eu);
            fprintf (SUMA_STDERR,"\n");
            fprintf(SUMA_STDERR,"Surface Euler Characteristic is: %d\n", eu);
        }
        if ((SO->EL->min_N_Hosts == 1 || SO->EL->max_N_Hosts == 1)) {
            fprintf (SUMA_STDERR,"\n");
            fprintf(SUMA_STDERR,
                    "Warning %s:\n"
                    " Min/Max number of edge hosting triangles: [%d/%d] \n",
                    FuncName, SO->EL->min_N_Hosts, SO->EL->max_N_Hosts);
            fprintf( SUMA_STDERR,
                     " You have edges that form a border in the surface.\n");
        }
        if (SO->EL->min_N_Hosts == 2 && SO->EL->max_N_Hosts == 2) {
            fprintf (SUMA_STDERR,"\n");
            fprintf(SUMA_STDERR,"Surface is closed and is a 2-manifold.");
        }
        if (SO->EL->min_N_Hosts > 2 || SO->EL->max_N_Hosts > 2) {
            fprintf (SUMA_STDERR,"\n");
            fprintf( SUMA_STDERR,
                     "Warning %s:\n"
                     "Min/Max number of edge hosting triangles: [%d/%d] \n",
                     FuncName, SO->EL->min_N_Hosts, SO->EL->max_N_Hosts);
            fprintf(SUMA_STDERR,
                    "Warning %s:\n"
                    " You have edges that belong to more than two triangles.\n"
                    " Bad for analysis assuming surface is a 2-manifold.\n",
                    FuncName);
            if (1) {
                int iii=0;
                fprintf( SUMA_STDERR,
                         " These edges are formed by the following nodes:\n");
                for (iii = 0; iii < SO->EL->N_EL; ++iii) {
                    if (SO->EL->ELps[iii][2] > 2)
                        fprintf (SUMA_STDERR,
                                 " %d: Edge [%d %d] shared by %d triangles.\n",
                                 iii+1, SO->EL->EL[iii][0], SO->EL->EL[iii][1] ,
                                 SO->EL->ELps[iii][2] );
                }
            }
        }

        if (DoSelfInt) {
            int iii;
            FILE *fout=NULL;
            byte *report = (byte *)SUMA_calloc(SO->N_Node, sizeof(byte));
            if (!report) {
                SUMA_SL_Crit("Failed to allocate for report");
                report = NULL;
            }
            fprintf( SUMA_STDERR, "\n\nChecking for intersections...:\n");
            nsi = SUMA_isSelfIntersect(SO, 500, report);
            if (nsi) {
                fprintf( SUMA_STDERR,
                         " Surface is self intersecting.\n"
                         "%d segments were found to intersect the surface.\n", nsi);
                if (nsi >= 500) {
                    fprintf( SUMA_STDERR,
                             " It is possible that you have additional segments"
                             " intersecting the surface.\n");
                }
                if (report) {
                    if (Spec->N_Surfs > 1) {
                        sprintf(ext,"_%c", 65+i);
                        OutName = SUMA_append_replace_string ( prefix,
                                                               "_IntersNodes.1D.dset",
                                                               ext, 0);
                    } else {
                        OutName = SUMA_append_string (prefix, "_IntersNodes.1D.dset");
                    }
                    fout = fopen(OutName, "w");
                    if (fout) {
                        fprintf(fout,
                                "#List of nodes that are part of segments which intersect "
                                "the surface\n"
                                "#%s\n"
                                "#A total of %d segments (search limit is 500) were found to "
                                "intersect the surface.\n"
                                "#Col.1 : Node index\n"
                                "#Col.2 : Dummy flag, always 1\n",
                                SUMA_CHECK_NULL_STR(SO->Label), nsi );
                        for (iii=0; iii<SO->N_Node; ++iii)
                            if (report[iii]) fprintf(fout, "%d\t1\n", iii);
                        fclose(fout);
                        fout = NULL;
                    } else {
                        SUMA_SL_Err("Failed to open file for output.");
                    }
                    if (OutName) SUMA_free(OutName);
                }
            } else {
                fprintf(SUMA_STDERR, " Surface is not self intersecting.\n");
            }
            if (report) SUMA_free(report);
            report = NULL;
        }

        fprintf (SUMA_STDERR,"\n");

        if (Opt->DoSum) {   /* do not change syntax, scripts depend on this */
            fprintf(stdout,"Summary for %s:\n", SO->Label);
            fprintf(stdout,"Euler_Charac. %d\n", eu);
            fprintf(stdout,"Consistent_Winding %d\n", consistent);
            if (DoSphQ) {
                fprintf(stdout,"Folding_Triangles %d\n", N_bad_facesets);
                fprintf(stdout,"Sketchy_nodes %d\n", N_bad_nodes);
            }
            if (DoSelfInt)
                fprintf(stdout,"Self_Intersections %d\n", nsi);
            fprintf(stdout,"\n");
        }

    }



    SUMA_LH("clean up");
    if (!SUMA_FreeSpecFields(Spec)) {
        SUMA_S_Err("Failed to free spec fields");
    }
    SUMA_free(Spec);
    Spec = NULL;
    if (prefix) SUMA_free(prefix);
    prefix = NULL;
    if (Opt->out_prefix) SUMA_free(Opt->out_prefix);
    Opt->out_prefix = NULL;
    if (Opt) SUMA_free(Opt);
    if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) {
        SUMA_SL_Err("DO Cleanup Failed!");
    }
    if (!SUMA_Free_CommonFields(SUMAg_CF))
        SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);

    SUMA_RETURN(0);
}
Example #3
0
int main (int argc,char *argv[])
{/* Main */    
   static char FuncName[]={"SurfMatch"}; 
   SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt;  
   SUMA_GENERIC_ARGV_PARSE *ps=NULL;
   SUMA_SurfSpecFile *Spec = NULL;
   int N_Spec=0, N_inmask;
   byte *cmask=NULL;
   SUMA_SurfaceObject *SO = NULL, *SOr=NULL;
   SUMA_Boolean LocalHead = NOPE;

   SUMA_STANDALONE_INIT;
	SUMA_mainENTRY;

   /* Allocate space for DO structure */
	SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
   ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;");
   
   if (argc < 2) {
      usage_SurfMatch(ps, 0);
      exit (1);
   }
   
   Opt = SUMA_SurfMatch_ParseInput (argv, argc, ps);

   if (Opt->debug > 2) LocalHead = YUP;
   
   /* check on inputs */
   if (ps->s_N_surfnames + ps->i_N_surfnames + ps->t_N_surfnames != 2) {
      SUMA_S_Err("Must have two surfaces");
      exit(1);
   }

   Spec = SUMA_IO_args_2_spec(ps, &N_Spec);
   if (N_Spec == 0) {
      SUMA_S_Err("No surfaces found.");
      exit(1);
   }
   if (N_Spec != 1) {
      SUMA_S_Err("Multiple spec at input.");
      exit(1);
   }

   SOr = SUMA_Load_Spec_Surf_with_Metrics(Spec, 0, ps->sv[0], 1);
   if (!SOr) {
         fprintf (SUMA_STDERR,"Error %s:\n"
                              "Failed to find surface\n"
                              "in spec file. \n",
                              FuncName );
         exit(1);
      
   }   
   
   if (Opt->efrac>0.0) {
      SUMA_SurfaceObject *SOrr=NULL;
      if (!(SOrr = SUMA_Mesh_Resample_nodes(SOr, Opt->efrac))) {
         SUMA_S_Errv("Failed to resample initial mesh at %f\n",Opt->efrac);
         exit(1);
      }
      SUMA_Free_Surface_Object(SOr); SOr=SOrr; SOrr=NULL;
      SUMA_SurfaceMetrics_eng(SOr, "EdgeList|MemberFace", NULL, 0, 
                                          SUMAg_CF->DsetList);
      if (!SOr->Label && !(SUMA_SurfaceFileName(SOr, NOPE))) {
         SOr->Label = SUMA_copy_string("Le_Remaille");
      }
   }
   
   SO = SUMA_Load_Spec_Surf_with_Metrics(Spec, 1, ps->sv[0], 1);

   if (Opt->flt1 != 1.0) {
      SUMA_LHv("Masking out nodes deeper than %f mm", Opt->flt1);
      N_inmask = SUMA_NodeDepth(SO->NodeList, SO->N_Node, prjdir,  NULL, 
                                Opt->flt1, &cmask, NULL);
   } else {
      N_inmask = SO->N_Node;
   }
   
   SUMA_S_Notev("Have Reference %s %d nodes, input %s, %d nodes (%d in mask)\n",
                  SOr->Label, SOr->N_Node, SO->Label, SO->N_Node, N_inmask);
   if (Opt->b1) {
      Opt->s = SUMA_append_replace_string(Opt->s,"City", " ; ", 1);
   }
   SUMA_AlignCoords(SO->NodeList, SO->N_Node, cmask, 1, SOr, Opt->s);
   
   /* write surface */
   if (!SUMA_Save_Surface_Object_Wrap (Opt->out_prefix, NULL, SO, 
                                  SUMA_FT_NOT_SPECIFIED, SUMA_FF_NOT_SPECIFIED, 
                                  NULL)) {
      SUMA_S_Err("Failed to write surface of whole head");
      exit (1);
   }

   if (SOr) SUMA_Free_Surface_Object(SOr); SOr = NULL;
   if (SO) SUMA_Free_Surface_Object(SO); SO = NULL;
   
   if (cmask) SUMA_free(cmask); cmask=NULL;                 
   if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
   if (N_Spec) {
      int k=0; 
      for (k=0; k<N_Spec; ++k) {
         if (!SUMA_FreeSpecFields(&(Spec[k]))) { 
            SUMA_S_Err("Failed to free spec fields"); 
         } 
      }
      SUMA_free(Spec); Spec = NULL; N_Spec = 0;
   }
   if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt);
   if (!SUMA_Free_CommonFields(SUMAg_CF)) 
      SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
   exit(0);
   
} 
Example #4
0
int main (int argc,char *argv[])
{/* Main */    
   static char FuncName[]={"SurfPatch"};
   SUMA_GETPATCH_OPTIONS *Opt; 
   char *ppref=NULL, ext[5]; 
   float *far=NULL;
   MRI_IMAGE *im = NULL;
   int SO_read = -1;
   int   *NodePatch=NULL, N_NodePatch=-1, *FaceSetList=NULL , 
         N_FaceSet = -1, N_Node = -1, N_Spec=0;          
   int i, inodeoff=-1, ilabeloff=-1, nvec, ncol, cnt;
   SUMA_SurfaceObject *SO = NULL;
   SUMA_PATCH *ptch = NULL; 
   SUMA_SurfSpecFile *Spec;
   SUMA_INDEXING_ORDER d_order;
   void *SO_name = NULL;
   SUMA_Boolean exists = NOPE;
   SUMA_SO_File_Type typetmp;
   SUMA_SurfaceObject *SOnew = NULL;
   float *NodeList = NULL;
   SUMA_GENERIC_ARGV_PARSE *ps=NULL;
   SUMA_Boolean LocalHead = NOPE;
	
   SUMA_STANDALONE_INIT;
   SUMA_mainENTRY;
   
   
   ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;");
   
	/* Allocate space for DO structure */
	SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
   
   Opt = SUMA_GetPatch_ParseInput (argv, argc, ps);
   if (argc < 2)
    {
       SUMA_S_Err("Too few options");
       usage_SUMA_getPatch(ps, 0);
       exit (1);
    }


   /* read all surfaces */
   Spec = SUMA_IO_args_2_spec(ps, &N_Spec);
   if (N_Spec == 0) {
      SUMA_S_Err("No surfaces found.");
      exit(1);
   }

   if (N_Spec > 1 ) {
      SUMA_S_Err( "Mike, you cannot mix -spec with -i or -t options "
                  "for specifying surfaces.");
      exit(1);
   }
   
   if (Spec->N_Surfs < 1) {
      SUMA_S_Err("No surfaces");
      exit(1);
   }
     
   if (Opt->DoVol && Spec->N_Surfs != 2) {
      SUMA_S_Errv("Must specify 2 and only 2 surfaces with -vol options\n"
                  "Have %d from the command line\n",Spec->N_Surfs);
      exit(1);
   }
   
   if (Opt->oType != SUMA_FT_NOT_SPECIFIED && !Opt->VolOnly) { 
      for (i=0; i < Spec->N_Surfs; ++i) {
         if (Spec->N_Surfs > 1) {
            sprintf(ext, "_%c", 65+i);
            ppref = SUMA_append_string(Opt->out_prefix, ext);
         } else {
            ppref = SUMA_copy_string(Opt->out_prefix);
         }
         
         SO_name = SUMA_Prefix2SurfaceName(ppref, NULL, NULL, 
                                           Opt->oType, &exists);
         if (exists && !THD_ok_overwrite()) {
            fprintf(SUMA_STDERR, "Error %s:\nOutput file(s) %s* on disk.\n"
                                 "Will not overwrite.\n", FuncName, ppref);
            exit(1);
         }
         if (ppref) SUMA_free(ppref); ppref = NULL; 
         if (SO_name) SUMA_free(SO_name); SO_name = NULL;
      } 
   }
   
   /* read in the file containing the node information */
   im = mri_read_1D (Opt->in_name);

   if (!im) {
      SUMA_S_Errv("Failed to read 1D file '%s'\n", Opt->in_name);
      exit(1);
   }

   far = MRI_FLOAT_PTR(im);
   nvec = im->nx;
   ncol = im->ny;
   if (Opt->nodecol >= ncol || Opt->labelcol >= ncol) {
      fprintf(SUMA_STDERR, "\n"
                           "Error %s: Input file has a total of %d columns.\n"
                           "One or both user-specified node (%d) and \n"
                           "label (%d) columns are too high. Maximum usable\n"
                           "column index is %d.\n"
                           , FuncName, ncol, Opt->nodecol, 
                           Opt->labelcol, ncol -1 );
      exit(1);
   }
   
   d_order = SUMA_COLUMN_MAJOR;

   if (!nvec) {
      SUMA_SL_Err("Empty file");
      exit(1);
   }
   /* form the node vector */
   NodePatch = (int *)SUMA_malloc(sizeof(int)*nvec);
   if (!NodePatch) {
      SUMA_SL_Crit("Failed to allocate.");
      exit(1);
   }
   inodeoff = Opt->nodecol*nvec;
   if (Opt->labelcol < 0) { /* all listed nodes */ 
      for (i=0; i<nvec; ++i) {
         NodePatch[i] = far[i+inodeoff];
      }
      N_NodePatch = nvec;
   } else {
      ilabeloff =  Opt->labelcol*nvec;
      if (Opt->thislabel < 0) { /* all nodes with non zero labels */
         cnt = 0;
         for (i=0; i<nvec; ++i) {
            if (far[i+ilabeloff]) {
               NodePatch[cnt] = far[i+inodeoff];
               ++cnt;
            }
         }
         N_NodePatch = cnt;     
      } else { /* select labels */
         cnt = 0;
         for (i=0; i<nvec; ++i) {
            if (far[i+ilabeloff] == Opt->thislabel) {
               NodePatch[cnt] = far[i+inodeoff];
               ++cnt;
            }
         }
         N_NodePatch = cnt;    
      }
      NodePatch = (int *) SUMA_realloc(NodePatch , sizeof(int)*N_NodePatch);
   }
   
   /* done with im, free it */
   mri_free(im); im = NULL;   
   
   if (Opt->DoVol) {
      SUMA_SurfaceObject *SO1 = 
         SUMA_Load_Spec_Surf_with_Metrics(Spec, 0, ps->sv[0], 0);
      SUMA_SurfaceObject *SO2 = 
         SUMA_Load_Spec_Surf_with_Metrics(Spec, 1, ps->sv[0], 0);
      double Vol = 0.0;
      SUMA_SurfaceObject *SOp = SUMA_Alloc_SurfObject_Struct(1);
      byte *adj_N=NULL;
      
      if (Opt->adjust_contour) 
         adj_N = SUMA_calloc(SO1->N_Node, sizeof(byte));
      
      if (!SO1 || !SO2) {
         SUMA_SL_Err("Failed to load surfaces.");
         exit(1);
      }
      /* a chunk used to test SUMA_Pattie_Volume */
      Vol = SUMA_Pattie_Volume(SO1, SO2, NodePatch, N_NodePatch, 
                               SOp, Opt->minhits, 
                               Opt->FixBowTie, Opt->adjust_contour, 
                               adj_N, Opt->verb);
      fprintf (SUMA_STDOUT,"Volume = %f\n", fabs(Vol));
      if (Opt->out_volprefix) {
         if (Opt->oType != SUMA_FT_NOT_SPECIFIED) SOp->FileType = Opt->oType;
         if (Opt->flip) {
            if (Opt->verb > 1) 
               SUMA_S_Note("Flipping stitched surf's triangles\n");
            SUMA_FlipSOTriangles (SOp);
         }

         if (!(SUMA_Save_Surface_Object_Wrap ( Opt->out_volprefix, NULL,
                                               SOp, SUMA_PLY, SUMA_ASCII, 
                                               NULL))) {
            fprintf (SUMA_STDERR,
                     "Error %s: Failed to write surface object.\n", FuncName);
         }
         if (Opt->adjust_contour && adj_N) {
            Opt->out_volprefix = 
                     SUMA_append_replace_string(Opt->out_volprefix, 
                                                   ".adjneighb","",1);
            ppref = SUMA_Extension(Opt->out_volprefix, ".1D.dset", NOPE);
            SUMA_WRITE_IND_ARRAY_1D(adj_N, NULL, SO1->N_Node, 1, ppref);
            SUMA_free(ppref); ppref=NULL;
         }
      }
      if (SOp) SUMA_Free_Surface_Object(SOp); SOp = NULL;
   }
   
   
   if (!Opt->VolOnly) {
      FaceSetList = NULL;
      N_FaceSet = -1;
      for (i=0; i < Spec->N_Surfs; ++i) {/* loop to read in surfaces */
         /* now identify surface needed */
         if (!(SO = SUMA_Load_Spec_Surf_with_Metrics(Spec, i, ps->sv[0], 0))) {
            SUMA_S_Err("Failed to load surface .\n");
            exit(1);
         }
         if (SO->aSO) {
            /* otherwise, when you reset the number of FaceSets for example,
               and you still write in GIFTI, the old contents of aSO will
               prevail */
            SO->aSO = SUMA_FreeAfniSurfaceObject(SO->aSO); 
         }
         /* extract the patch */
         ptch = SUMA_getPatch (NodePatch, N_NodePatch, SO->N_Node,
                               SO->FaceSetList,  SO->N_FaceSet, 
                               SO->MF, Opt->minhits, 
                               Opt->FixBowTie, (!i && !Opt->DoVol)); 
                                    /* verbose only for first patch, and 
                                    if no volume computation was required  
                                    This is to keep the warnings to a minimum*/
         if (!ptch) {
            SUMA_SL_Err("Failed to form patch.");
            exit(1);
         }
         if (LocalHead) SUMA_ShowPatch(ptch, NULL);
      
         /* Now create a surface with that patch */
         if (Spec->N_Surfs > 1) {
            sprintf(ext, "_%c", 65+i);
            ppref = SUMA_append_string(Opt->out_prefix, ext);
         } else {
            ppref = SUMA_copy_string(Opt->out_prefix);
         }
         /* save the original type */
         typetmp = SO->FileType;
         if (Opt->oType != SUMA_FT_NOT_SPECIFIED) SO->FileType = Opt->oType;
         SO_name = SUMA_Prefix2SurfaceName(ppref, NULL, NULL, 
                                           SO->FileType, &exists);
         if (ppref) SUMA_free(ppref); ppref = NULL;
         /* save the original pointers to the facesets and their number */
         FaceSetList = SO->FaceSetList;
         N_FaceSet = SO->N_FaceSet;
         NodeList = SO->NodeList;
         N_Node = SO->N_Node;
         
         /* replace with Patch */
         SO->FaceSetList = ptch->FaceSetList;
         SO->N_FaceSet = ptch->N_FaceSet; 
         
         if (Opt->Do_p2s) {
            if (LocalHead) 
               fprintf (SUMA_STDERR,
                        "%s: Changing patch to surface...\n", FuncName);
            SOnew = SUMA_Patch2Surf(SO->NodeList, SO->N_Node, 
                                    SO->FaceSetList, SO->N_FaceSet, 3);
            if (!SOnew) {
               SUMA_S_Err("Failed to change patch to surface.");
               exit(1);
            }
            SO->FaceSetList = SOnew->FaceSetList;
            SO->N_FaceSet = SOnew->N_FaceSet;
            SO->N_Node = SOnew->N_Node;
            SO->NodeList = SOnew->NodeList;
         }
          
         if (SO->N_FaceSet <= 0) {
            SUMA_S_Warn("The patch is empty.\n"
                        " Non existing surface not written to disk.\n");
         } else {
            /* Is the gain wanted? */
            if (Opt->coordgain) {
               SUMA_SL_Note("Applying coord gain to surface nodes!");
               for (cnt=0; cnt < SO->NodeDim*SO->N_Node; ++cnt) 
                  SO->NodeList[cnt] *= Opt->coordgain;
            }
            if (Opt->flip) {
               if (Opt->verb > 1) SUMA_S_Note("Flipping triangles\n");
               SUMA_FlipTriangles (SO->FaceSetList, SO->N_FaceSet);
               SUMA_RECOMPUTE_NORMALS(SO);
            }

            if (!SUMA_Save_Surface_Object (SO_name, SO, SO->FileType, 
                                           SUMA_ASCII, NULL)) {
                  fprintf (SUMA_STDERR,
                           "Error %s: Failed to write surface object.\n", 
                           FuncName);
                  exit (1);
            }
         }
         
         /* bring SO back to shape */
         SO->FileType = typetmp;
         SO->FaceSetList = FaceSetList; FaceSetList = NULL;
         SO->N_FaceSet = N_FaceSet; N_FaceSet = -1;
         SO->NodeList = NodeList; NodeList = NULL;
         SO->N_Node = N_Node; N_Node = -1;
         
         if (SO_name) SUMA_free(SO_name); SO_name = NULL;
         if (ptch) SUMA_freePatch(ptch); ptch = NULL;
         if (SOnew) SUMA_Free_Surface_Object(SOnew); SOnew = NULL; 
               /* get rid of old surface object */
            

      }
   } 
   
   SUMA_LH("clean up");
   if (!SUMA_FreeSpecFields(Spec)) { SUMA_S_Err("Failed to free spec fields"); }
   SUMA_free(Spec); Spec = NULL;
   if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL;
   if (Opt->out_volprefix) SUMA_free(Opt->out_volprefix); 
                                                Opt->out_volprefix = NULL;
   if (Opt) SUMA_free(Opt);   
   if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) {
      SUMA_SL_Err("DO Cleanup Failed!");
   }
   
   if (!SUMA_Free_CommonFields(SUMAg_CF)) {
      SUMA_SL_Err("SUMAg_CF Cleanup Failed!");
   }
   
   SUMA_RETURN(0);
}