Esempio n. 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);
}
Esempio n. 2
0
/*!\**
File : SUMA.c
\author : Ziad Saad
Date : Thu Dec 27 16:21:01 EST 2001
   
Purpose : 
   
   
   
Input paramters : 
\param   
\param   
   
Usage : 
      SUMA ( )
   
   
Returns : 
\return   
\return   
   
Support : 
\sa   OpenGL prog. Guide 3rd edition
\sa   varray.c from book's sample code
   
Side effects : 
   
   
   
***/
int main (int argc,char *argv[])
{/* Main */
   static char FuncName[]={"suma"}; 
   int kar, i;
   SUMA_SFname *SF_name;
   SUMA_Boolean brk, SurfIn;
   char  *NameParam, *AfniHostName = NULL, *s = NULL, *pdspec=NULL, *pdsv=NULL;
   char *specfilename[SUMA_MAX_N_GROUPS], *VolParName[SUMA_MAX_N_GROUPS];
   byte InMem[SUMA_MAX_N_GROUPS];
   SUMA_SurfSpecFile *Specp[SUMA_MAX_N_GROUPS];   
   SUMA_Axis *EyeAxis;    
   SUMA_EngineData *ED= NULL;
   DList *list = NULL;
   DListElmt *Element= NULL;
   int iv15[15], N_iv15, ispec, nspec;
   struct stat stbuf;
   float fff=0.0;
   int Start_niml = 0;
   SUMA_Boolean  Domemtrace = YUP;
   SUMA_GENERIC_ARGV_PARSE *ps=NULL;
   SUMA_Boolean LocalHead = NOPE;
   
    
   SUMA_STANDALONE_INIT;
   SUMA_mainENTRY;
   
   
   SUMAg_CF->isGraphical = YUP;
   
   ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-dset;-do;");

   /* initialize Volume Parent and AfniHostName to nothing */
   for (ispec=0; ispec < SUMA_MAX_N_GROUPS; ++ispec) {
      specfilename[ispec] = NULL;
      VolParName[ispec] = NULL;
      Specp[ispec] = NULL;
      InMem[ispec] = 0;
   }
   AfniHostName = NULL; 
   
      
   /* Allocate space for DO structure */
   SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
   
   /* call the function to parse the other surface mode inputs */
   ispec = 0;
   if (LocalHead) SUMA_Show_IO_args(ps);
   if (ps->i_N_surfnames || ps->t_N_surfnames || ps->N_DO) {
      SUMA_LH("-i and/or -t surfaces on command line!");
      Specp[ispec] = SUMA_IO_args_2_spec (ps, &nspec); 
      if (Specp[ispec]) {
         ++ispec;
         if (nspec != 1) {
            SUMA_S_Errv("-spec is being parsed separately here, "
                        "expecting one spec only from SUMA_IO_args_2_spec, \n"
                        "got %d\n", nspec);
            exit (1);
         }
      } else {
         SUMA_S_Err("Failed to load -i/-t surfaces");
         exit(1);
      }
      
   }
   /* Work the options */
   kar = 1;
   brk = NOPE;
   SurfIn = NOPE;
   Domemtrace = YUP; 
   while (kar < argc) { /* loop accross command ine options */
      /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
      
      if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
         SUMA_usage (ps, strlen(argv[kar]) > 3 ? 2:1);
          exit (0); /* return a good status on -help   12 Jul 2013 [rickr] */
      }
      
      /* -list_ports list and quit */
      if( strncmp(argv[kar],"-list_ports", 8) == 0) {
         show_ports_list(); exit(0);
      }
      
      /* -port_number and quit */
      if( strncmp(argv[kar],"-port_number", 8) == 0) {
         int pp = 0;
         if( ++kar >= argc ) 
            ERROR_exit("need an argument after -port_number!"); 
         pp = get_port_named(argv[kar]);
         if (strcmp(argv[kar-1], "-port_number_quiet")) { 
            fprintf(stdout, "\nPort %s: %d\n", argv[kar], pp); 
         } else {
            fprintf(stdout, "%d\n", pp); 
         }
         if (pp < 1) exit(1);
         else exit(0);
      }
      
      if (strcmp(argv[kar], "-visuals") == 0) {
          SUMA_ShowAllVisuals ();
          exit (0);
      }
      
      if (strcmp(argv[kar], "-brethren_windows") == 0) {
          Display *dd=NULL; Window ww;
          if (!(dd = XOpenDisplay(NULL))) {
            SUMA_S_Err("No display "); exit(1);
          }
          ww = XDefaultRootWindow(dd);
          
          SUMA_WindowsOnRootDisplay(dd, ww , 0);
          exit (0);
      }
      
      if (strcmp(argv[kar], "-version") == 0) {
          s = SUMA_New_Additions (0.0, 1);
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-sources") == 0) {
          s = SUMA_sources_Info();
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-help_nido") == 0) {
         s = SUMA_NIDO_Info();
         fprintf (SUMA_STDOUT,"%s\n", s); 
         SUMA_free(s); s = NULL;
         exit (0);
      }
      
      if (strcmp(argv[kar], "-all_latest_news") == 0) {
          s = SUMA_New_Additions (-1.0, 0);
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-help_sphinx_interactive") == 0) {
         FILE *fout = NULL;
         if( ++kar >= argc ) 
            ERROR_exit("need a file name after -help_sphinx_interactive!");       
          fout = fopen(argv[kar],"w");
          if (!fout) {
            SUMA_S_Err("Failed to open %s for writing", argv[kar]);
            exit(1);
          }
          SUMA_help_message(fout,SPX);
          fclose(fout); fout = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-help_interactive") == 0) {
          FILE *fout = fopen("Mouse_Keyboard_Controls.txt","w");
          if (!fout) {
            SUMA_S_Err("Failed to open Mouse_Keyboard_Controls.txt for writing");
            exit(1);
          }
          SUMA_help_message(fout,TXT);
          fclose(fout); fout = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-test_help_string_edit") == 0) {
         SUMA_Sphinx_String_Edit_Help(SUMA_STDOUT, 0);
         exit(0);
      }
      if (strcmp(argv[kar], "-test_help_string_edit_web") == 0) {
         SUMA_Sphinx_String_Edit_Help(SUMA_STDOUT, 1);
         exit(0);
      }
      
      if (strcmp(argv[kar], "-environment") == 0) {
          s = SUMA_env_list_help (0, TXT);
          fprintf (SUMA_STDOUT,  
            "#SUMA ENVIRONMENT \n"
            "# If you do not have a ~/.sumarc file, cannot find a SUMA\n"
            "# environment variable that's been mentioned in documentation,\n"
            "# or fervently desire to update your current ~/.sumarc with  \n"
            "# all the latest variables that SUMA uses, you should run: \n"
            "# \n"
            "#    suma -update_env\n"
            "# \n"
            "# Unless you have setup SUMA environment variables outside of\n"
            "# your ~/.sumarc file, updating your ~/.sumarc file with \n"
            "# 'suma -update_env' WILL NOT ALTER changes you have already\n"
            "# made to the variables in your current ~/.sumarc. \n"
            "# For this reason consider running the update command after each \n"
            "# upgrade of your AFNI/SUMA binaries.\n" 
            "***ENVIRONMENT\n"
                  "%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-default_env") == 0) {
          s = SUMA_env_list_help (1, NO_FORMAT);
          fprintf (SUMA_STDOUT,  
                  "#SUMA DEFAULT ENVIRONMENT (user settings ignored)\n"
                  "# see also suma -udate_env or suma -environment\n"
                  "# \n"
                  "***ENVIRONMENT\n"
                  "%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-update_env") == 0) {
          if (system("suma -environment > ___sumarc")) {
            SUMA_S_Err("Failed to create env file.");
            exit(1);
          }
          if (SUMA_filexists("~/.sumarc")) {
            if (system("\\cp -f ~/.sumarc ~/.sumarc-bak")) {
               SUMA_S_Err("Failed to backup ~/.sumarc to ~/.sumarc-bak.");
               exit(1);
            }
          }
          if (system("\\mv ___sumarc ~/.sumarc")) {
            SUMA_S_Err("Failed to copy newrc (___sumarc) to ~/.sumarc");
            exit(1); 
          }
          SUMA_S_Note("Environment update done.");
          exit(0);
      }
      
      if (strcmp(argv[kar], "-latest_news") == 0) {
          s = SUMA_New_Additions (0.0, 0);
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-progs") == 0) {
          s = SUMA_All_Programs();
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-motif_ver") == 0) {  /* 9 Mar 2009 [rickr] */
         show_motif_version_string();
         exit (0);
      }
      
      if (!brk && (strcmp(argv[kar], "-iodbg") == 0)) {
         fprintf(SUMA_STDERR,"Error %s: Obsolete, use -trace\n", FuncName);
         exit (0);
         /*
         fprintf(SUMA_STDOUT,
                 "Warning %s: SUMA running in in/out debug mode.\n", FuncName);
         SUMA_INOUT_NOTIFY_ON; 
         brk = YUP;
         */
      }
      
      
      
      SUMA_SKIP_COMMON_OPTIONS(brk, kar);
      
      #if SUMA_MEMTRACE_FLAG
         if (!brk && (strcmp(argv[kar], "-memdbg") == 0)) {
            fprintf(SUMA_STDOUT,"Error %s: -memdbg is obsolete, use -trace\n", 
                                FuncName);
            exit (0);
            fprintf( SUMA_STDOUT,
                     "Warning %s: SUMA running in memory trace mode.\n", 
                     FuncName);
            SUMAg_CF->MemTrace = YUP;
            #ifdef USING_MCW_MALLOC
            #endif
            brk = YUP;
         }
      #endif
      
      if (!brk && (strcmp(argv[kar], "-dev") == 0)) {
         fprintf(SUMA_STDOUT,
                  "Warning %s: SUMA running in developer mode, "
                  "some options may malfunction.\n", FuncName);
         SUMAg_CF->Dev = YUP;
         brk = YUP;
      }
      
      if (!brk && (strcmp(argv[kar], "-fake_cmap") == 0)) {
         SUMA_S_Warn("-fake_cmap is for automatic selfies of the widgets.\n"
                     "You should not use this option for any other reason\n");
         SUMAg_CF->Fake_Cmap = YUP;
         brk = YUP;
      }
      
      if (!brk && SUMAg_CF->Dev && (strcmp(argv[kar], "-truth_table") == 0)) {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need expression after -truth_table \n");
            exit (1);
         }
         SUMA_bool_eval_truth_table(argv[kar], 0);  exit(0);
         brk = YUP;
      }
      
      if (!brk && (strcmp(argv[kar], "-niml") == 0)) {
         Start_niml = 1;
         brk = YUP;
      }

      if (!brk && (strcmp(argv[kar], "-noniml") == 0)) {
         Start_niml = -1;
         brk = YUP;
      }
      
      if (!brk && (strcmp(argv[kar], "-vp") == 0 || 
                   strcmp(argv[kar], "-sa") == 0 || 
                   strcmp(argv[kar], "-sv") == 0))
      {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -vp|-sa|-sv \n");
            exit (1);
         }
         if (ispec < 1) {
            fprintf (SUMA_STDERR, 
                     "a -spec option must precede the first -sv option\n");
            exit (1);
         }
         if (!specfilename[ispec-1] && !Specp[ispec-1]) {
            fprintf (SUMA_STDERR, 
                     "a -spec option must precede each -sv option\n");
            exit (1);
         }
         VolParName[ispec-1] = argv[kar]; 
         if (LocalHead) {
            fprintf(SUMA_STDOUT, "Found: %s\n", VolParName[ispec]);
         }
         
         brk = YUP;
      }      
      
      if (!brk && strcmp(argv[kar], "-drive_com") == 0)
      {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -drive_com\n");
            exit (1);
         }
         SUMAg_CF->dcom = (char **)SUMA_realloc(SUMAg_CF->dcom,
                                          (SUMAg_CF->N_dcom+1)*sizeof(char *));
         SUMAg_CF->dcom[SUMAg_CF->N_dcom] = SUMA_copy_string(argv[kar]);
         ++SUMAg_CF->N_dcom;
         brk = YUP;
      }
      
      if (!brk && strcmp(argv[kar], "-ah") == 0)
      {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -ah\n");
            exit (1);
         }
         if (strcmp(argv[kar],"localhost") != 0) {
            AfniHostName = argv[kar];
         }else {
           fprintf (SUMA_STDERR, 
                    "localhost is the default for -ah\n"
                    "No need to specify it.\n");
         }
         /*fprintf(SUMA_STDOUT, "Found: %s\n", AfniHostName);*/

         brk = YUP;
      }   
      
      if (!brk && strcmp(argv[kar], "-spec") == 0)
      { 
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -spec \n");
            exit (1);
         }
         
         if (ispec >= SUMA_MAX_N_GROUPS) {
            fprintf (SUMA_STDERR, 
                     "Cannot accept more than %d spec files.\n",     
                     SUMA_MAX_N_GROUPS);
            exit(1);
         }
         
         if (SUMA_is_predefined_SO_name(argv[kar], NULL, 
                                        &pdspec, &pdsv, NULL) == 3) {
            specfilename[ispec] = pdspec; pdspec = NULL; /* Memory leak! */
            VolParName[ispec] = pdsv; pdsv = NULL; /* Memory leak! */
         } else {
            specfilename[ispec] = argv[kar]; 
         }
         if (LocalHead) {
            fprintf(SUMA_STDOUT, "Found: %s\n", specfilename[ispec]);
         }
         ++ispec;
         brk = YUP;
      } 
      
      
      if (!brk && !ps->arg_checked[kar]) {
         if (  !strcmp(argv[kar], "-i") ||
               !strncmp(argv[kar], "-i_",3) ) {
            fprintf (SUMA_STDERR,
      "Error %s: Option %s not understood. \n"
      "  Make sure parameter after -i or -i_ is the full name of a surface.\n"
      "%s",
      FuncName, argv[kar], 
      strlen(argv[kar])==2 ? 
         "For -i to work, SUMA needs to guess at the surface type from\n"
         "  the filename extensions. If SUMA fails try the full -i_* option"
         " instead.\n" : ""
      );
         } else {
            fprintf (SUMA_STDERR,
                  "Error %s: Option %s not understood. Try -help for usage\n", 
                  FuncName, argv[kar]);
            suggest_best_prog_option(argv[0], argv[kar]);
         }
         exit (1);
      } else {   
         brk = NOPE;
         kar ++;
      }
      
   }/* loop accross command ine options */
   /* -ah option now checked for in ps */
   if (ps->cs->afni_host_name && !AfniHostName) {
      AfniHostName = SUMA_copy_string(ps->cs->afni_host_name);
   }
   
   #if 0
   SUMA_S_Note("KILL ME");
   { 
      int i,j, nl; 
      SUMA_TextBoxSize("Hello", &i,&j,&nl,NULL); 
      SUMA_TextBoxSize("", 
                        &i,&j,&nl,GLUT_BITMAP_8_BY_13); 
      SUMA_TextBoxSize("O", 
                        &i,&j,&nl,GLUT_BITMAP_8_BY_13); 
                        SUMA_TextBoxSize(NULL, 
                        &i,&j,&nl,GLUT_BITMAP_8_BY_13); 
   }
   SUMA_ReadNIDO("/Users/ziad/SUMA_test_dirs/DO/TextDO/sample.niml.do", NULL);   
   exit(1);
      
   #endif
      
   /* Make surface loading pacifying */
   SetLoadPacify(1);
   
   #if 0
   if (ps->N_DO) { /* Have DOs on command line */
      if (Specp[0]) { /* Add to Specp[0] */
         if (ps->N_DO + Specp[0]->N_DO > SUMA_MAX_DO_SPEC) {
            SUMA_S_Warn("Too many DOs, increase static limit..");
                                       /* ignore extras for now */
            ps->N_DO = SUMA_MAX_DO_SPEC - Specp[0]->N_DO;
         }
         for (i=0; i<ps->N_DO; ++i) {
            strcpy(Specp[0]->DO_name[Specp[0]->N_DO], ps->DO_name[i]);
            Specp[0]->DO_type[Specp[0]->N_DO] = ps->DO_type[i];
            ++Specp[0]->N_DO;
         }
      } else {
         Specp[0]
      }
   }
   #endif
      
   /* any Specp to be found ?*/
   if (specfilename[0] == NULL && Specp[0] == NULL) {
      SUMA_SurfaceObject **SOv=NULL;
      int N_SOv = 0;
      fprintf (SUMA_STDERR,
               "\n"
               "%s: \n"
               "     No input specified, loading some toy surfaces...\n"
               "     Use '.' and ',' to cycle between them.\n"
               "     See suma -help for assistance.\n"
               "\n", FuncName);
      /* create your own surface and put it in a spec file */
      SOv = SUMA_GimmeSomeSOs(&N_SOv);
      Specp[ispec] = SUMA_SOGroup_2_Spec (SOv, N_SOv);
      SUMA_free(SOv); SOv = NULL;
      InMem[ispec] = 1;
      ++ispec;
   }

   if(!SUMA_Assign_HostName (SUMAg_CF, AfniHostName, -1)) {
      fprintf (SUMA_STDERR, 
         "Error %s: Failed in SUMA_Assign_HostName\n", FuncName);
      exit (1);
   }
   
   #ifdef SUMA_DISASTER
   /* a function to test Memtracing */
   {
      int *jnk;
      jnk = SUMA_disaster();
      SUMA_free(jnk); /* without the -trace, you'll get a 
                           warning here if jnk is corrupted */
   }
   #endif
   
   /* create an Eye Axis DO */
   EyeAxis = SUMA_Alloc_Axis ("Eye Axis", AO_type);
   if (EyeAxis == NULL) {
      SUMA_error_message (FuncName,"Error Creating Eye Axis",1);
      exit(1);
   }

   /* Store it into SUMAg_DOv */
   if (!SUMA_AddDO(  SUMAg_DOv, &SUMAg_N_DOv, 
                     (void *)EyeAxis,  AO_type, SUMA_SCREEN)) {
      SUMA_error_message (FuncName,"Error Adding DO", 1);
      exit(1);
   }
   /*fprintf (SUMA_STDERR, "SUMAg_N_DOv = %d created\n", SUMAg_N_DOv);
   SUMA_Show_DOv(SUMAg_DOv, SUMAg_N_DOv, NULL);*/

   /* Allocate space (and initialize) Surface Viewer Structure */
   SUMAg_SVv = SUMA_Alloc_SurfaceViewer_Struct (SUMA_MAX_SURF_VIEWERS);
   
   /* SUMAg_N_SVv gets updated in SUMA_X_SurfaceViewer_Create
   and reflects not the number of elements in SUMAg_SVv which is
   SUMA_MAX_SURF_VIEWERS, but the number of viewers that were realized
   by X */
   
   /* Check on initialization */
   /*SUMA_Show_SurfaceViewer_Struct (SUMAg_cSV, stdout);*/

   /* Create the Surface Viewer Window */
   if (!SUMA_X_SurfaceViewer_Create ()) {
      fprintf(stderr,"Error in SUMA_X_SurfaceViewer_Create. Exiting\n");
      return 1;
   }
   
   for (i=0; i<ispec; ++i) {
      if (!list) list = SUMA_CreateList();
      ED = SUMA_InitializeEngineListData (SE_Load_Group);
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_cp, (void *)specfilename[i], 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_Head, NULL ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_ip, (void *)Specp[i], 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
      fff = (float) InMem[i];
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_f, (void *)&fff, 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_vp, (void *)VolParName[i], 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }

      N_iv15 = SUMA_MAX_SURF_VIEWERS;
      if (N_iv15 > 15) {
         fprintf( SUMA_STDERR,
                  "Error %s: trying to register more than 15 viewers!\n", 
                  FuncName);
         exit(1);
      }
      for (kar=0; kar<N_iv15; ++kar) iv15[kar] = kar;
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_iv15, (void *)iv15, 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }

      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_i, (void *)&N_iv15, 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
   }
   
   if (ispec > 0 && !SUMA_Engine (&list)) {
      fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Engine\n", FuncName);
      exit (1);
   }
   
   /* For some reason, I had to add the glLightfv line below
   to force the lightflipping done in SUMA_SetupSVforDOs to take place
   in the A viewer when first opened. I don't know why that is, especially
   since other controllers would show up lit correctly without this 
   glLightfv line below.
      To make matters worse, the A controller's light0_position is correctly 
   flipped.
      It is just that the shading is done as if the position was never flipped. 
   Actually, without the line below, the first time you hit the F key (to 
   manually flip the light), nothing changes, that's because the light's position    is unflipped, which is supposed to show the incorrect lighting. 
   You'll have to hit F again to have the lighting correctly flipped 
   and the shading reflecting it.... ZSS, Aug. 05 04 */
   glLightfv(GL_LIGHT0, GL_POSITION, SUMAg_SVv[0].light0_position); 

   if (Start_niml != -1 && (Start_niml == 1|| AFNI_yesenv("SUMA_START_NIML"))) {
      if (!list) list = SUMA_CreateList();
      SUMA_REGISTER_HEAD_COMMAND_NO_DATA( list, SE_StartListening, 
                                          SES_Suma, NULL);

      if (!SUMA_Engine (&list)) {
         fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
         exit (1);   
      }
   }
   
   /* load the datasets onto the first SO, if any, else hope that dset 
      is some form of DO  */
   if (ps->N_dsetname>0) {
      SUMA_SurfaceObject *SO = SUMA_findanySOp_inDOv(SUMAg_DOv, 
                                                     SUMAg_N_DOv, NULL);
      if (!SO) {
         SUMA_LH("Could not find any SO, here is hoping dset is a DO");
      }
      for (i=0; i<ps->N_dsetname; ++i) {
         if (!(SUMA_LoadDsetOntoSO_eng(ps->dsetname[i], SO, 1, 1, 1, NULL))) {
            SUMA_S_Errv("Failed to load %s onto %s\n", 
                        ps->dsetname[i], SO?SO->Label:"NULL");
         }
      }
   }

   SUMA_FreeGenericArgParse(ps); ps = NULL;
 
   /* A Warning about no sumarc */
   if (NoSumaRcFound()) { 
         SUMA_S_Warn(
"\n"
" No sumarc file found. You should create one by running the following:\n"
"\n"
"              suma -update_env\n"
"\n"
" I also recommend you run 'suma -update_env' whenever you update AFNI.\n" 
"\n"
" See details for -environment and -update_env options in suma -help's output.\n"
"\n");
   }
   
   /*Main loop */
   XtAppMainLoop(SUMAg_CF->X->App);

   
   /* Done, clean up time */
   if (ispec) {
      int k=0; 
      for (k=0; k<ispec; ++k) {
         if (!SUMA_FreeSpecFields((Specp[k]))) { 
            SUMA_S_Err("Failed to free spec fields"); 
         } 
         Specp[k] = NULL;
      }
   } ispec = 0;
  
   if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) 
      SUMA_error_message(FuncName,"DO Cleanup Failed!",1);
   if (!SUMA_Free_SurfaceViewer_Struct_Vect (SUMAg_SVv, SUMA_MAX_SURF_VIEWERS)) 
      SUMA_error_message(FuncName,"SUMAg_SVv Cleanup Failed!",1);
   if (!SUMA_Free_CommonFields(SUMAg_CF)) 
      SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
  SUMA_RETURN(0);             /* ANSI C requires main to return int. */
}/* Main */ 
Esempio n. 3
0
int main (int argc,char *argv[])
{/* Main */    
   static char FuncName[]={"SurfClust"}; 
	int kar, SO_read, *ni=NULL, N_ni, cnt, i, *nip=NULL, N_Spec = 0;
   float *data_old = NULL, *far = NULL, *nv=NULL, *nt = NULL;
   void *SO_name = NULL;
   SUMA_SurfaceObject *SO = NULL, *SOnew = NULL;
   MRI_IMAGE *im = NULL;
   SUMA_DSET_FORMAT iform;
   SUMA_SURFCLUST_OPTIONS *Opt;  
	SUMA_SurfSpecFile *Spec=NULL; 
   DList *list = NULL;
   SUMA_DSET *dset = NULL;
   float *NodeArea = NULL;
   FILE *clustout=NULL;
   char *ClustOutName = NULL, *params=NULL, stmp[200];
   char sapa[32]={""}, sapd[32]={""}, sapn[32]={""}, sap[100]={""};
   SUMA_GENERIC_ARGV_PARSE *ps=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, "-spec;-i;-t;-sv;-s;");
   Opt = SUMA_SurfClust_ParseInput (argv, argc, ps);
   if (argc < 6)
       {
         SUMA_S_Err("Too few options");
          usage_SUMA_SurfClust(0);
          exit (1);
       }
   
   
   if (Opt->DistLim >= 0.0) {
      sprintf(sapd, "_r%.1f", Opt->DistLim);
   } else {
      sprintf(sapd, "_e%d", -(int)Opt->DistLim);
   }
   if (Opt->AreaLim < 0) {
      sapa[0]='\0';
   } else {
      sprintf(sapa, "_a%.1f", Opt->AreaLim);
   }
   if (Opt->NodeLim < 0) {
      sapn[0]='\0';
   } else {
      sprintf(sapn, "_n%d", Opt->NodeLim);
   }
   sprintf(sap, "%s%s%s", sapd, sapa, sapn);
   
   if (Opt->WriteFile) {
      sprintf(stmp,"_ClstTable%s.1D", sap);
      
      ClustOutName = SUMA_append_string(Opt->out_prefix, stmp);   
      if (SUMA_filexists(ClustOutName) && !THD_ok_overwrite()) {
         fprintf (SUMA_STDERR,
                  "Error %s:\n"
                  "Output file %s exists, will not overwrite.\n", 
                  FuncName, ClustOutName);
         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);
   }
   if (Spec->N_Surfs != 1) {
      SUMA_S_Err("1 and only 1 surface expected at input");
      exit(1);
   } 
   SUMA_LH("Loading surface...");
   SO = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], 0);
   if (!SO) {
         fprintf (SUMA_STDERR,"Error %s:\n"
                              "Failed to find surface\n"
                              "in spec file. \n",
                              FuncName );
         exit(1);
      
   }   
   if (!SUMA_SurfaceMetrics(SO, "EdgeList", NULL)) {
      SUMA_S_Err("Failed to compute edgelist");
      exit(1);
   }
   NodeArea = SUMA_CalculateNodeAreas(SO, NULL);
   if (!NodeArea) {
      SUMA_S_Err("Failed to calculate Node Areas.\n");
      exit(1);
   }   
   /* load the data */   
   iform = SUMA_NO_DSET_FORMAT;
   dset = SUMA_LoadDset_s (Opt->in_name, &iform, 0); 
   if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
   if (!dset) { SUMA_S_Err(  "Failed to load dataset.\n"
                              "Make sure file exists\n"
                              "and is of the specified\n"
                              "format."); 
               exit(1); }
   if (!SUMA_OKassign(dset, SO)) {
      SUMA_SL_Err("Failed to assign data set to surface.");
      exit(1);
   }
   /* get the node index column */
   nip = SUMA_GetNodeDef(dset);
   N_ni = SDSET_VECLEN(dset);
   if (!nip) {
      SUMA_S_Err("Failed to find node index column");
      exit(1);
   }
   /* copy nip's contents because you will be modifying in the 
      thresholding below */
   ni = (int *)SUMA_malloc(N_ni*sizeof(int));
   memcpy (ni, nip, N_ni*sizeof(int));
   nv = SUMA_DsetCol2Float(dset, Opt->labelcol, 0);
   if (!nv) {
      SUMA_S_Err("Failed to find node value column");
      exit(1);
   }
   
   /* any thresholding ? */
   if (Opt->DoThreshold > SUMA_NO_THRESH) {
      nt = SUMA_DsetCol2Float(dset, Opt->tind, 0);
      if (!nt) {
         SUMA_S_Err("Failed to find threshold column");
         exit(1);
      }
      cnt = 0;
      if (Opt->DoThreshold == SUMA_LESS_THAN) {
         if (Opt->update) 
            fprintf( SUMA_STDERR,
                     "%s: Thresholding at %f...\n", FuncName, Opt->ThreshR[0]);
         for (i=0;i<N_ni; ++i) {
            if (nt[i] >= Opt->ThreshR[0]) {
               ni[cnt] = ni[i];
               nv[cnt] = nv[i];
               ++cnt;
            }
         }
      } else if (Opt->DoThreshold == SUMA_ABS_LESS_THAN) {
         SUMA_LH("ABS Thresholding at %f...", Opt->ThreshR[0]);
         for (i=0;i<N_ni; ++i) {
            if (fabs(nt[i]) >= Opt->ThreshR[0]) {
               ni[cnt] = ni[i];
               nv[cnt] = nv[i];
               ++cnt;
            }
         }
      } else if (Opt->DoThreshold == SUMA_THRESH_INSIDE_RANGE) {
         SUMA_LH("Range Thresholding at %f %f...", 
                 Opt->ThreshR[0], Opt->ThreshR[1]);
         for (i=0;i<N_ni; ++i) {
            if (nt[i] >= Opt->ThreshR[0] && nt[i] <= Opt->ThreshR[1]) {
               ni[cnt] = ni[i];
               nv[cnt] = nv[i];
               ++cnt;
            }
         }
      } else if (Opt->DoThreshold ==  SUMA_THRESH_OUTSIDE_RANGE) {
         SUMA_LH("Ex Range Thresholding at %f %f...",
                  Opt->ThreshR[0], Opt->ThreshR[1]);
         for (i=0;i<N_ni; ++i) {
            if (nt[i] < Opt->ThreshR[0] || nt[i] > Opt->ThreshR[1]) {
               ni[cnt] = ni[i];
               nv[cnt] = nv[i];
               ++cnt;
            }
         }
      } else {
         SUMA_S_Err("Not ready for threshold mode of %d", Opt->DoThreshold);
      }
      N_ni = cnt;
   }
   if (Opt->update) {
      Opt->update = -(N_ni * Opt->update / 100); /* make it negative 
                                                   before you begin a 
                                                   clustering operation */
      if (LocalHead) {
         fprintf( SUMA_STDERR,
                  "Update parameter, once every %d nodes\n"
                  "%d nodes to work with.\n", 
                  -(int)Opt->update, N_ni);
      }    
   }
   
   /* make the call */
   list = SUMA_FindClusters (SO, ni, nv, N_ni, -1, Opt, NodeArea);
   if (!list) {
      SUMA_S_Err("Failed in SUMA_FindClusters"); 
      exit(1);      
   }
   
   if (list->size) {
      /* sort the list */
      if (!SUMA_Sort_ClustersList (list, Opt->SortMode)) {
         SUMA_S_Err("Failed to sort cluster list");
         exit(1);
      }
   }       
   /* Show the results */
   params = SUMA_HistString(FuncName, argc, argv, NULL);
   if (Opt->WriteFile) {
      if (0) {
         /* You can also write a NIML formatted cluster table with */
         NI_element *nel=NULL;
         int suc; char sbuf[512]={""};
         nel = SUMA_SurfClust_list_2_nel(list, 0, params, NULL);
         snprintf(sbuf, 510, "file:%s%s.niml.clstbl", Opt->out_prefix, sap);
         NEL_WRITE_TXH(nel, sbuf, suc);
         NI_free_element(nel); nel=NULL;
      }
      clustout = fopen(ClustOutName, "w");
      if (!clustout) {
         fprintf (SUMA_STDERR,
                  "Error %s:\n"
                  "Failed to open %s for writing.\n"
                  "Check permissions.\n",  
                  FuncName, ClustOutName);
         exit(1);
      }
      SUMA_Show_SurfClust_list(list, clustout, 0, params, NULL);
      fclose(clustout);clustout = NULL;  
   }  else SUMA_Show_SurfClust_list(list, NULL, 0, params, NULL);
   
   if (!list->size) {
      /* nothing left to do, quit */
      exit(0);
   }
   
   if (Opt->OutROI) {
      SUMA_DSET *dset_roi = NULL;
      char *ROIprefix = NULL;
      char *NameOut = NULL;
      
      sprintf(stmp,"_ClstMsk%s", sap);
      ROIprefix = SUMA_append_string(Opt->out_prefix, stmp);
      /* Call this function, write out the resultant dset to disk 
         then cleanup */
      dset_roi = 
         SUMA_SurfClust_list_2_DsetMask(SO, list, Opt->FullROIList, ROIprefix);
      
      if (!dset_roi) {
         SUMA_S_Err("NULL dset_roi");
         exit(1);
      }
      if (Opt->prepend_node_index) {/* prepend node index? */         
         if (!SUMA_InsertDsetNelCol (
               dset_roi, "Node Index Copy", SUMA_NODE_INT, 
               (void *)(dset_roi->inel->vec[0]), NULL ,1, 0)) {
            SUMA_S_Err("Failed to insert column");
         }
         if (LocalHead) SUMA_ShowDset(dset_roi,0, NULL); 
      }
      
      NameOut = SUMA_WriteDset_s (  ROIprefix, dset_roi, Opt->oform, 
                                    THD_ok_overwrite(), 0);
      if (!NameOut) { SUMA_SL_Err("Failed to write dataset."); exit(1); } 
      SUMA_FreeDset((void *)dset_roi); dset_roi = NULL; 
      if (NameOut) SUMA_free(NameOut); NameOut = NULL;
      if (ROIprefix) SUMA_free(ROIprefix); ROIprefix = NULL; 
   }
   
   if (Opt->OutClustDset) {
      SUMA_DSET *dset_clust = NULL;
      char *Clustprefix = NULL;
      char *NameOut = NULL;

      sprintf(stmp,"_Clustered%s", sap);
      Clustprefix = SUMA_append_string(Opt->out_prefix, stmp);
      /* Call this function, write out the resultant dset to disk 
         then cleanup */
      
      dset_clust = 
         SUMA_MaskDsetByClustList(  dset, SO, list, 
                                    Opt->FullROIList, Clustprefix);
      if (!dset_clust) {
         SUMA_S_Err("NULL dset_clust");
         exit(1);
      }
      NameOut = SUMA_WriteDset_s (  Clustprefix, dset_clust, Opt->oform, 
                                    THD_ok_overwrite(), 0);
      if (!NameOut) { SUMA_SL_Err("Failed to write dataset."); exit(1); } 
      SUMA_FreeDset((void *)dset_clust); dset_clust = NULL; 
      if (NameOut) SUMA_free(NameOut); NameOut = NULL;
      if (Clustprefix) SUMA_free(Clustprefix); Clustprefix = NULL; 
   }
   
   if (ClustOutName) SUMA_free(ClustOutName); ClustOutName = NULL;
   if (list) dlist_destroy(list); SUMA_free(list); list = NULL;
   if (ni) SUMA_free(ni); ni = NULL;
   if (nv) SUMA_free(nv); nv = NULL;
   if (nt) SUMA_free(nt); nt = NULL;
   if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL;
   if (Opt) SUMA_free_SurfClust_Opt(Opt);
   if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
   if (dset) SUMA_FreeDset((void *)dset); dset = NULL;
   if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) {
      SUMA_SL_Err("DO Cleanup Failed!");
   }
   exit(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);
}
Esempio n. 5
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);
} 
Esempio n. 6
0
int main (int argc,char *argv[])
{/* Main */    
   static char FuncName[]={"ConvexHull"}; 
	int i, i3, nspec = 0;
   void *SO_name=NULL;
   SUMA_SurfaceObject *SO = NULL;
   SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt;  
   char  stmp[200];
   SUMA_Boolean exists = NOPE;
   SUMA_Boolean LocalHead = NOPE;
   SUMA_GENERIC_ARGV_PARSE *ps=NULL;

   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, "-o;-i;-sv;");
   
   if (argc < 2) {
      usage_SUMA_ConvexHull(ps);
      exit (1);
   }
   
   Opt = SUMA_ConvexHull_ParseInput (argv, argc, ps);
      
   SO_name = SUMA_Prefix2SurfaceName(Opt->out_prefix, NULL, NULL, 
                                     Opt->SurfFileType, &exists);
   if (exists && !THD_ok_overwrite()) {
      SUMA_S_Err("Output file(s) %s* on disk.\nWill not overwrite.\n", 
                 Opt->out_prefix);
      exit(1);
   }
   
   if (Opt->obj_type < 0) {
      if (Opt->in_name) {
         if (Opt->debug) {
            SUMA_S_Note("Creating mask...");
         }
         if (!SUMA_Get_isosurface_datasets (Opt)) {
            SUMA_SL_Err("Failed to get data.");
            exit(1);
         }

         if (Opt->debug > 1) {
            if (Opt->debug == 2) {
               FILE *fout=fopen("inmaskvec.1D","w");
               SUMA_S_Note("Writing masked values...\n");
               if (!fout) {
                  SUMA_SL_Err("Failed to write maskvec");
                  exit(1);
               }
               fprintf(fout,  "#Col. 0 Voxel Index\n"
                              "#Col. 1 Is a mask (all values here should be 1)\n" );
               for (i=0; i<Opt->nvox; ++i) {
                  if (Opt->mcdatav[i]) {
                     fprintf(fout,"%d %.2f\n", i, Opt->mcdatav[i]);
                  }
               }
               fclose(fout); fout = NULL;
            } else {
               FILE *fout=fopen("maskvec.1D","w");
               SUMA_S_Note("Writing all mask values...\n");
               if (!fout) {
                  SUMA_S_Err("Failed to write maskvec");
                  exit(1);
               }
               fprintf(fout,  "#Col. 0 Voxel Index\n"
                              "#Col. 1 Is in mask ?\n" );
               for (i=0; i<Opt->nvox; ++i) {
                  fprintf(fout,"%d %.2f\n", i, Opt->mcdatav[i]);
               }
               fclose(fout); fout = NULL;
            }
         }
      } else if (Opt->in_1D) {
            MRI_IMAGE *im = NULL;
            float *far=NULL;
            int nx2;
            
            /* load the 1D file */
            im = mri_read_1D (Opt->in_1D);
            if (!im) {
               SUMA_S_Err("Failed to read file");
               exit(1);
            }   

            far = MRI_FLOAT_PTR(im);
            if (im->nx == 0) {
               fprintf(SUMA_STDERR,"Error %s:\n Empty file %s.\n", FuncName, Opt->in_1D);
               exit(1);
            }
            if (im->ny != 3) {
               fprintf(SUMA_STDERR,"Error %s:\n Found %d columns in %s. Expecting 3\n", FuncName, im->ny, Opt->in_1D);
               exit(1);
            }
            
            /* copy the columns */
            Opt->N_XYZ = im->nx;
            Opt->XYZ = (float *)SUMA_malloc(im->nx*im->ny*sizeof(float));
            if (!Opt->XYZ) {
               SUMA_S_Crit("Failed to allocate.");
               exit(1);
            }
            nx2 = 2*im->nx;
            for (i=0;i<Opt->N_XYZ; ++i) {
               i3 = 3*i;
               Opt->XYZ[i3  ] = far[i];
               Opt->XYZ[i3+1] = far[i+im->nx];
               Opt->XYZ[i3+2] = far[i+nx2];
            }
            
            /* done, clean up and out you go */
            if (im) mri_free(im); im = NULL; 
      } else if (ps->i_N_surfnames) {
         SUMA_SurfSpecFile *Spec=NULL;
         SUMA_SurfaceObject *SO=NULL;
         
         if (ps->i_N_surfnames > 1) {
            SUMA_S_Err("Only 1 input surface allowed!");
            exit(1);
         }
         Spec = SUMA_IO_args_2_spec(ps, &nspec);
         if (!Spec) {
            SUMA_S_Err("Failed to create spec!");
            exit(1);
         }
         if (nspec != 1) {
            SUMA_S_Warn("Expected one spec and nothing else");
         }
         /* load the surface object */
         SO = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], 0);
         if (!SO) {
            SUMA_S_Err("Failed to read surface.");
            exit(1);
         }
         /* transfer coords */
         if(SO->NodeDim != 3) {
            SUMA_S_Err("bad node coords.");
            exit(1);
         }
         
         Opt->N_XYZ = SO->N_Node;
         Opt->XYZ = (float *)SUMA_malloc(SO->N_Node * SO->NodeDim * sizeof(float));
         if (!Opt->XYZ) {
            SUMA_S_Crit("Failed to allocate.");
            exit(1);
         }
         for (i=0;i<SO->NodeDim*SO->N_Node; ++i) Opt->XYZ[i] = SO->NodeList[i];
         
         if (nspec) {
            int k=0; 
            for (k=0; k<nspec; ++k) {
               if (!SUMA_FreeSpecFields(&(Spec[k]))) { SUMA_S_Err("Failed to free spec fields"); } 
            }
            SUMA_free(Spec); Spec = NULL; nspec = 0;
         }

         if (SO) SUMA_Free_Surface_Object(SO); SO = NULL;
      } else {
         SUMA_S_Err("No input!");
         exit(1);
      }
   } else {
      SUMA_S_Err("Bad input!");
      exit(1);
   }
   
               
   /* Now call Marching Cube functions */
   if (!(SO = SUMA_ConvexHullSurface(Opt))) {
      SUMA_S_Err("Failed to create surface.\n");
      exit(1);
   }

   /* write the surface to disk */
   if (!SUMA_Save_Surface_Object (SO_name, SO, 
                        Opt->SurfFileType, Opt->SurfFileFormat, NULL)) {
      fprintf (SUMA_STDERR,
                  "Error %s: Failed to write surface object.\n", FuncName);
      exit (1);
   }
   
   if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
   if (Opt->fvec) SUMA_free(Opt->fvec); Opt->fvec = NULL;
   if (Opt->mcdatav) {SUMA_free(Opt->mcdatav); Opt->mcdatav = NULL;} 
   if (Opt->in_vol) { DSET_delete( Opt->in_vol); Opt->in_vol = NULL;} 
   if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL;
   if (Opt->XYZ) SUMA_free(Opt->XYZ); Opt->XYZ = NULL;
   if (Opt) SUMA_free(Opt);
   if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) {
      SUMA_SL_Err("DO Cleanup Failed!");
   }
   if (SO_name) SUMA_free(SO_name); SO_name = NULL;
   if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
   exit(0);
}