示例#1
0
/*!
   A function to call SUMA_qhull_wrap or SUMA_qdelaunay_wrap
*/
SUMA_SurfaceObject *SUMA_ConvexHullSurface(
               SUMA_GENERIC_PROG_OPTIONS_STRUCT * Opt)
{
   static char FuncName[]={"SUMA_ConvexHullSurface"};
   SUMA_SurfaceObject *SO=NULL;
   float *xyz=NULL, *xyzp=NULL, *txyz=NULL;
   int npt, *ijk=NULL, nf=0, cnt, i, j, k, nxx, nyy, nzz,N_txyz=-1;
   FILE *fid=NULL;
   THD_fvec3 fv, iv;
   SUMA_Boolean LocalHead = NOPE;
   
   SUMA_ENTRY;
   
   npt = 0;
   N_txyz=-1;
   if (Opt->UseThisBrain) {
      MRI_IMAGE *im = NULL;
      float *far=NULL;
      int nx2, i3;

      /* load the 1D file */
      im = mri_read_1D (Opt->UseThisBrain);
      if (!im) {
         SUMA_S_Err("Failed to read file");
         SUMA_RETURN(NULL);
      }   

      far = MRI_FLOAT_PTR(im);
      if (im->nx == 0) {
         SUMA_S_Errv("Empty file %s.\n", Opt->UseThisBrain);
         SUMA_RETURN(NULL);
      }
      if (im->ny != 3) {
         SUMA_S_Errv("Found %d columns in %s. Expecting 3\n", 
                     im->ny, Opt->UseThisBrain);
         SUMA_RETURN(NULL);
      }

      /* copy the columns */
      N_txyz = im->nx;
      txyz = (float *)SUMA_malloc(im->nx*im->ny*sizeof(float));
      if (!txyz) {
         SUMA_S_Crit("Failed to allocate.");
         SUMA_RETURN(NULL);
      }
      nx2 = 2*im->nx;
      for (i=0; i<N_txyz; ++i) {
         i3 = 3*i;
         txyz[i3  ] = far[i];
         txyz[i3+1] = far[i+im->nx];
         txyz[i3+2] = far[i+nx2];
      }

      /* done, clean up and out you go */
      if (im) mri_free(im); im = NULL;       
   }
   
   if (Opt->in_vol) {
      cnt = 0; npt = 0;
      nxx = (DSET_NX(Opt->in_vol)); 
      nyy = (DSET_NY(Opt->in_vol));
      nzz = (DSET_NZ(Opt->in_vol));

      if (Opt->debug) fprintf(SUMA_STDERR,"%s:\nRunning qhull...\n", FuncName);
      xyz = (float *)SUMA_malloc(3*nxx*nyy*nzz*sizeof(float));
      if (!xyz) {
         SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NULL);
      }
      for(  k = 0 ; k < nzz ; k++ ) {
         for(  j = 0 ; j < nyy ; j++ ) {
            for(  i = 0 ; i < nxx ; i++ ) {
               if (Opt->mcdatav[cnt] == 1) {
                  fv.xyz[0] = DSET_XORG(Opt->in_vol) + i * DSET_DX(Opt->in_vol);
                  fv.xyz[1] = DSET_YORG(Opt->in_vol) + j * DSET_DY(Opt->in_vol);
                  fv.xyz[2] = DSET_ZORG(Opt->in_vol) + k * DSET_DZ(Opt->in_vol);
                  /* change mm to RAI coords */
		            iv = SUMA_THD_3dmm_to_dicomm( Opt->in_vol->daxes->xxorient, 
                                                Opt->in_vol->daxes->yyorient, 
                                                Opt->in_vol->daxes->zzorient, 
                                                fv );
                  xyz[3*npt] = iv.xyz[0]; 
                  xyz[3*npt+1] = iv.xyz[1]; xyz[3*npt+2] = iv.xyz[2]; 
                  npt++;
               }
               ++cnt;
            }
         }
      }
   } else if (Opt->XYZ) {
      xyz = (float *)SUMA_malloc(3*Opt->N_XYZ*sizeof(float));
      if (!xyz) {
         SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NULL);
      }
      for(  k = 0 ; k < 3*Opt->N_XYZ ; k++ ) {  
         xyz[k] = Opt->XYZ[k]; npt = Opt->N_XYZ; 
      }   
   } else {
      SUMA_S_Err("No input");
      goto CLEANUP; 
   }
   
   if (Opt->corder) {
      SUMA_PC_XYZ_PROJ *pcp=NULL;
      if (Opt->geom==1) {
         SUMA_S_Warn("PCA projection makes no sense for usual convex hull");
      }
      if (!(pcp = SUMA_Project_Coords_PCA (xyz, npt, npt/2, NULL,
                                            E3_PLN_PRJ, ROT_2_Z,0))) {
         SUMA_S_Err("Failed to project");
         goto CLEANUP;   
      }
      xyzp = pcp->xyzp; pcp->xyzp = NULL;
      pcp = SUMA_Free_PC_XYZ_Proj(pcp);
   } else {
      xyzp = xyz;
   }

   if (N_txyz >= 0 && N_txyz != npt) {
      SUMA_S_Errv("Mismatch between number of coordinates for convex hull\n"
                  "and number of coordinates to adopt in the end.\n"
                  " %d, versus %d in -these_coords\n",
                  npt, N_txyz);
      goto CLEANUP;            
   }  
   
   if (Opt->geom == 1) { /* convex hull */
      if (! (nf = SUMA_qhull_wrap(npt, xyzp, &ijk, 1, Opt->s)) ) {
         fprintf(SUMA_STDERR,"%s:\nFailed in SUMA_qhull_wrap\n", FuncName);
         goto CLEANUP; 
      }
      
      /* Other than unif==0 make no sense here, but leave it to the user */
      switch (Opt->unif) {
         case 0:  /* coordinates as passed to qhull, 
                     could be projected ones*/
            SO = SUMA_Patch2Surf(xyzp, npt, ijk, nf, 3);
            break;
         case 1:  /* Original corrdinates passed to qhull
                     (pre-projections, if any) */
            SO = SUMA_Patch2Surf(xyz, npt, ijk, nf, 3);
            break;
         case 2: /* special coordinates passed by user, 
                    never passed in any form to qhull */
            SUMA_S_Warn("Makes no sense to mess with coords for convex hull...");
            SO = SUMA_Patch2Surf(txyz, npt, ijk, nf, 3);
            break;
         default:
            SUMA_S_Err("pit of despair");
            goto CLEANUP; 
      }
            
      if (Opt->debug) fprintf(SUMA_STDERR,"%s:\n%d triangles.\n", FuncName, nf);
   } else if (Opt->geom == 2) { /* triangulation */
      if (! (nf = SUMA_qdelaunay_wrap(npt, xyzp, &ijk, 1, Opt->s)) ) {
         fprintf(SUMA_STDERR,"%s:\nFailed in SUMA_qdelaunay_wrap\n", FuncName);
         goto CLEANUP;    
      }
      switch (Opt->unif) {
         case 0:  /* coordinates as passed to qdelaunay, 
                     could be projected ones*/
            if (xyz == xyzp) xyz=NULL; /* xyzp will be set to 
                                         null in next call, 
                                         so xyz is treated 
                                         the same here */
            SO = SUMA_NewSO(&xyzp, npt, &ijk, nf, NULL);
            SUMA_LHv("xyzp %p, ijk %p\n", txyz, ijk);
           break;
         case 1:  /* Original corrdinates passed to qdelaunay
                     (pre-projections, if any) */
            SO = SUMA_NewSO(&xyz, npt, &ijk, nf, NULL);
            SUMA_LHv("xyz %p, ijk %p\n", txyz, ijk);
            break;
         case 2:  /* special coordinates passed by user, 
                     never passed in any form to qdelaunay */
            SO = SUMA_NewSO(&txyz, npt, &ijk, nf, NULL);
            SUMA_LHv("txyz %p, ijk %p\n", txyz, ijk);
            break;
         default:
            SUMA_S_Err("pit of despair, again");
            goto CLEANUP; 
      }
   } else {
      SUMA_S_Errv("Opt->geom = %d not valid\n", Opt->geom);
      goto CLEANUP;      
   }  
   
   CLEANUP:
   if (ijk) SUMA_free(ijk); ijk=NULL;
   if(txyz) SUMA_free(txyz); txyz=NULL;
   if (xyzp != xyz && xyzp != NULL) SUMA_free(xyzp); xyzp = NULL;
   if (xyz) SUMA_free(xyz); xyz = NULL;

   SUMA_RETURN(SO);
}
示例#2
0
int main(int argc, char **argv)
{
   static char FuncName[]={"3dGenFeatureDist"};
   SEG_OPTS *Opt=NULL;
   char *atr=NULL, sbuf[512], *methods=NULL;
   int  cc, /* class counter */
        kk, /* key counter */
        aa, /* feature counter */
        nn, /* sub-brick index */
        vv, /* voxel index */
        ss, /* subjects counter */
        iii, /* dummy counter */
        nbins, /* number of bins */
        *ifeat=NULL, key, 
        **N_alloc_FCset=NULL, /* Number of values allocated for each 
                                 vector in FCset */
        **N_FCset=NULL, /* Number of filled values for each vector in FCset */ 
        N_ffalloc=0, N_ff, isneg=0,
        missfeatwarn=-1 /* Missing feature warning for some subject */;
   float fsf=0.0, fsb=0.0, 
         ***FCset=NULL, /* Table holding samples for each feature/class combo */ 
         hrange[2]={-3.0, 3.0}, bwidth1=0.05, bwidth=0.0,
         *ff=NULL;
   short *sf=NULL, *sb=NULL;
   byte **masks=NULL;
   SUMA_HIST ***hh=NULL, **hf=NULL;
   double ff_m, ff_s;   
   SUMA_Boolean LocalHead = NOPE;

   SUMA_STANDALONE_INIT;
	SUMA_mainENTRY;
   
   SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
   Opt = GenFeatureDist_Default(argv,  argc);
   Opt = GenFeatureDist_ParseInput (Opt, argv,  argc);
   Opt->hist = tross_commandline( FuncName , argc , argv ) ;
   
   if (!GenFeatureDist_CheckOpts(Opt)) {
      ERROR_exit("Failed on option check");
   }
   
   /* labeltable? */
   if (Opt->labeltable_name) {
      Dtable *vl_dtable=NULL;
      char *labeltable_str=NULL;
      
      /* read the table */
      if (!(labeltable_str = AFNI_suck_file( Opt->labeltable_name))) {
         ERROR_exit("Failed to read %s", Opt->labeltable_name);
      }
      if (!(vl_dtable = Dtable_from_nimlstring(labeltable_str))) {
         ERROR_exit("Could not parse labeltable");
      }
      /* make sure all classes are in the labeltable */
      for (cc=0; cc<Opt->clss->num; ++cc) {
         if ((key = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[cc]))<0){
            ERROR_exit("Key not found in %s for %s ", 
                        Opt->labeltable_name, Opt->clss->str[cc]);
         }
         if (Opt->keys) {
            if (Opt->keys[cc]!=key) {
               ERROR_exit("Key mismatch %d %d", Opt->keys[cc], key);
            }
         }   
      }   
      if (!Opt->keys) { /* get them from table */
         Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int));
         for (cc=0; cc<Opt->clss->num; ++cc) {
            if ((key = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[cc]))<0){
               ERROR_exit("(should noy happen) Key not found in %s for %s ", 
                           Opt->labeltable_name, Opt->clss->str[cc]);
            }
            Opt->keys[cc] = key;
         }
      }
      destroy_Dtable(vl_dtable); vl_dtable=NULL;
   } 
   
   if (!Opt->keys) {
      /* add default keys */
      SUMA_S_Note("Keys not available, assuming defaults");
      Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int));
      for (cc=0; cc<Opt->clss->num; ++cc) {
         Opt->keys[cc] = cc+1;
      }
   }
   
   /* Show the match between keys and classes */
   SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys);
   /* For each feature, each class, collect the values */
   SUMA_S_Notev("Collecting data from %d subjects\n", Opt->sig_names->num);
   
   missfeatwarn = -1;
   for (ss=0; ss<Opt->sig_names->num; ++ss) { /* for each subject */
      /* load the input data */   
      if (!(Opt->sig = Seg_load_dset( Opt->sig_names->str[ss] ))) {      
         exit(1);
      }
      if (Opt->debug > 1) {
         SUMA_S_Notev("Have %d sub-bricks in signatures of dude %d\n",
                   DSET_NVALS(Opt->sig), ss);
      }
      
      if (ss == 0) { /* some setup based on initial grid */
         if (!Opt->feats) { /* create features from signature */
            char *allfeats=NULL;
            for (nn=0; nn<DSET_NVALS(Opt->sig); ++nn) {
               allfeats = 
                  SUMA_append_replace_string(allfeats,
                                          DSET_BRICK_LABEL(Opt->sig,nn),";", 1);
            }
            Opt->feats = NI_strict_decode_string_list(allfeats,";, ");
            SUMA_free(allfeats); allfeats=NULL;
         } 

         SUMA_S_Notev("Have to work with %d classes, %d features\n",
                      Opt->clss->num, Opt->feats->num);

         SUMA_S_Note("Initializing storage");
         /* Receptacles for all observations for each feature 
            and class combination */
         FCset = (float ***)SUMA_calloc(Opt->feats->num, sizeof(float **));
         N_FCset = (int **)SUMA_calloc(Opt->feats->num, sizeof(int *));
         N_alloc_FCset = (int **)SUMA_calloc(Opt->feats->num, sizeof(int *));
         ifeat = (int *)SUMA_calloc(Opt->feats->num, sizeof(int));
         for (aa=0; aa<Opt->feats->num; ++aa) {
            FCset[aa] = (float **)calloc(Opt->clss->num, sizeof(float *));
            N_FCset[aa] = (int *)SUMA_calloc(Opt->clss->num, sizeof(int));
            N_alloc_FCset[aa] = (int *)SUMA_calloc(Opt->clss->num, sizeof(int));
         }
         masks = (byte **)SUMA_calloc(Opt->sig_names->num, sizeof (byte *));

         /* Fix VoxDbg */
         if (Opt->VoxDbg >= 0) {
            Vox1D2Vox3D(Opt->VoxDbg, 
                        DSET_NX(Opt->sig), DSET_NX(Opt->sig)*DSET_NY(Opt->sig),
                        Opt->VoxDbg3);
         } else if (Opt->VoxDbg3[0]>=0) {
            Opt->VoxDbg =  Opt->VoxDbg3[0] + 
                           Opt->VoxDbg3[1]*DSET_NX(Opt->sig) +
                           Opt->VoxDbg3[2]*DSET_NX(Opt->sig)*DSET_NY(Opt->sig);
         }
      }
      
      /* allocate for mask which will be non-zero whenever a voxel is in at least         1 mask. It will have the 1st assignment */
      masks[ss] = (byte *)SUMA_calloc(DSET_NVOX(Opt->sig), sizeof(byte));
      
      /* create mapping between feature names and sub-briks */
      for (aa=0; aa<Opt->feats->num; ++aa) {
         ifeat[aa] = 0;
         while (ifeat[aa] < DSET_NVALS(Opt->sig) &&
            strcmp(DSET_BRICK_LABEL(Opt->sig,ifeat[aa]),
                   Opt->feats->str[aa])) ++ifeat[aa];
         if (ifeat[aa] >= DSET_NVALS(Opt->sig)) ifeat[aa]=-1;
         if (Opt->debug > 1) {
            SUMA_S_Notev("Have feature %s in sub-brick %d\n",
                      Opt->feats->str[aa], ifeat[aa]);
         }
      }
      
      SUMA_S_Notev("Loading sample classes for subject #%d\n", ss);
      if (!(Opt->samp = Seg_load_dset( Opt->samp_names->str[ss] ))) {      
         exit(1);
      }
      
      if (THD_dataset_mismatch(Opt->samp, Opt->sig)) {
         SUMA_S_Err(
            "Grid mismatch between -samp [%dx%dx%d] and \n"
            "                      -sig  [%dx%dx%d] volumes for pair #%d\n", 
            DSET_NX(Opt->samp), DSET_NY(Opt->samp), DSET_NZ(Opt->samp),
            DSET_NX(Opt->sig), DSET_NY(Opt->sig), DSET_NZ(Opt->sig), ss);
         exit(1);
      }
      
      if (Opt->debug > 1) {
         SUMA_S_Notev("Have %d sub-bricks in samples of dude %d\n", 
                     DSET_NVALS(Opt->samp), ss);
      }
      
      /* Now collect features for each class */
      SUMA_S_Note("Collecting features for each class");
      for (cc=0; cc<Opt->clss->num; ++cc) {
         if (Opt->debug > 1) {
            SUMA_S_Notev("Working class %s\n", Opt->clss->str[cc]);
         }
         key = Opt->keys[cc];
         for (nn=0; nn<DSET_NVALS(Opt->samp); ++nn) {
            if (Opt->debug > 2) {
               SUMA_S_Notev("Looking for key %d for class %s in sb %d\n",
                  key, Opt->clss->str[cc], nn);
            }
            sb = (short *)DSET_ARRAY(Opt->samp,nn);
            fsb = DSET_BRICK_FACTOR(Opt->samp,nn);
            if (fsb == 0.0) fsb = 1.0;
            if (fsb != 1.0) {
               SUMA_S_Err("Non-integral dset, possibly.");
               exit(1);
            }
            for (vv=0; vv<DSET_NVOX(Opt->samp); ++vv) {
               if (sb[vv] == key) {
                  for (aa=0; aa<Opt->feats->num; ++aa) {
                     if (ifeat[aa]>-1) {
                        if (N_alloc_FCset[aa][cc] <= N_FCset[aa][cc]) {
                           N_alloc_FCset[aa][cc] += 10000;
                           FCset[aa][cc] = 
                              (float*)SUMA_realloc(FCset[aa][cc],
                                           N_alloc_FCset[aa][cc]*sizeof(float));
                        }
                        sf = (short *)DSET_ARRAY(Opt->sig, ifeat[aa]);
                        fsf = DSET_BRICK_FACTOR(Opt->sig,ifeat[aa]);
                        if (fsf == 0.0) fsf = 1.0;
                        FCset[aa][cc][N_FCset[aa][cc]] = sf[vv]*fsf; 
                        ++N_FCset[aa][cc];
                        if (!masks[ss][vv]) {
                           masks[ss][vv] = (short)key; /* fcfs */
                                       /* in case we exceed short range */
                           if (masks[ss][vv]) masks[ss][vv] = 1; 
                        }
                     } else {
                        if (missfeatwarn != ss) {
                           SUMA_S_Warnv("Feature %s not found in subject %d\n",
                                 Opt->feats->str[aa], ss);
                           missfeatwarn = ss;
                        }
                     }  
                  }
               }  
            }
         }
      }
      DSET_delete(Opt->sig); Opt->sig=NULL;
      DSET_delete(Opt->samp); Opt->samp=NULL;
   } /* loop across all subjects */
   
   /* compute histograms of features across all classes and save them */
   hf = (SUMA_HIST **)SUMA_calloc(Opt->feats->num, sizeof(SUMA_HIST *));
   SUMA_S_Note("Computing histograms of features across all classes");
   ff = NULL; N_ffalloc = 0;
   for (aa=0; aa<Opt->feats->num; ++aa) {
      N_ff=0;
      for (cc=0; cc<Opt->clss->num; ++cc) {
         N_ff += N_FCset[aa][cc]; /* more than I need because same voxel 
                                     can belong to multiple classes, but just 
                                     to be safe */
      }
      if (N_ffalloc < N_ff) {
         N_ffalloc = N_ff;
         if (ff) SUMA_free(ff); ff=NULL;
         if (!(ff = (float*)SUMA_calloc(N_ff, sizeof(float)))) {
            SUMA_S_Crit("Failed to allocate");
            exit(1);
         }
      } 
      N_ff=0; isneg = 0; ff_m=0.0;
      for (ss=0; ss<Opt->sig_names->num; ++ss) { /* Once again, unfortunately  */
         /* load the input data */   
         if (!(Opt->sig = Seg_load_dset( Opt->sig_names->str[ss] ))) {      
            exit(1);
         }
         if (Opt->debug > 1) {
            SUMA_S_Notev("Have %d sub-bricks in signatures of dude %d\n",
                      DSET_NVALS(Opt->sig), ss);
         }
         if (ifeat[aa]>-1) {
            sb = (short *)DSET_ARRAY(Opt->sig,ifeat[aa]);
            fsb = DSET_BRICK_FACTOR(Opt->sig,ifeat[aa]);
            if (fsb == 0.0) fsb = 1.0;
            for (vv=0; vv<DSET_NVOX(Opt->sig); ++vv) {
               if (masks[ss][vv]) {
                  ff[N_ff] = sb[vv]*fsb;
                  if (ff[N_ff] < 0) ++isneg;
                  ff_m += ff[N_ff];
                  ++N_ff;
               }
            }
         }
         DSET_delete(Opt->sig); Opt->sig=NULL;
      }
      ff_m /= N_ff; ff_s=0.0;
      for (iii=0; iii<N_ff; ++iii) {
          ff_s += SUMA_POW2(ff[iii]-ff_m);
      }
      ff_s = sqrt(ff_s/N_ff);
      sprintf(sbuf, "h(%s)",Opt->feats->str[aa]);
      
      /* Check if you have user specified binning specs */
      bwidth = -1; nbins = -1;
      for (iii=0; iii<Opt->N_hspec; ++iii) {
         if (!strcmp(Opt->feats->str[aa], Opt->hspec[iii]->label)) {
            hrange[0] =  Opt->hspec[iii]->min;
            hrange[1] =  Opt->hspec[iii]->max;
            nbins     =  Opt->hspec[iii]->K;
            bwidth    = 0;
            methods   =  "hands off sir";
            break;
         }
      }
      

         
      if (bwidth < 0) {
         int nmatch = -1;
         /* Check the wildcard option */
         for (iii=0; iii<Opt->N_hspec; ++iii) {
            if ((nmatch = SUMA_is_wild_hspec_label(Opt->hspec[iii]->label))>=0) {
               if (!nmatch || !strncmp(Opt->feats->str[aa], 
                                       Opt->hspec[iii]->label, nmatch)) {
                  SUMA_S_Note("Feature %s matched with hspec %s\n",
                              Opt->feats->str[aa], Opt->hspec[iii]->label);
                  hrange[0] =  Opt->hspec[iii]->min;
                  hrange[1] =  Opt->hspec[iii]->max;
                  nbins     =  Opt->hspec[iii]->K;
                  bwidth    = 0;
                  methods   =  "hands woff sir";
                  break;
               }
            }
         }
      }
      
      if (bwidth < 0) { /* no user specs found */
         nbins = 0;
         methods = "Range|OsciBinWidth";
         if ((float)isneg/(float)N_ff*100.0 > 1.0) {
            hrange[0] =  ff_m-3*ff_s;
            hrange[1] =  ff_m+3*ff_s;
            bwidth = bwidth1*ff_s;
         } else if (ff_m-3*ff_s > 0) {
            hrange[0] =  ff_m-3*ff_s;
            hrange[1] =  ff_m+3*ff_s;
            bwidth = bwidth1*ff_s;
         } else {
            hrange[0] =  0;
            hrange[1] =  6.0*ff_s/2.0;
            bwidth = bwidth1*ff_s/2.0;
         }
      }
      SUMA_S_Notev("Feature %s: mean %f, std %f\n"
                   "Hist params: [%f %f], binwidth %f\n", 
                        Opt->feats->str[aa], ff_m, ff_s,
                        hrange[0], hrange[1], bwidth);
      if (!(hf[aa] = SUMA_hist_opt(ff, N_ff, nbins, bwidth, hrange, sbuf, 1, 
                                    0.1, methods))) {
         SUMA_S_Errv("Failed to generate histogram for %s. \n"
                     "This will cause trouble at classification.\n",
                     Opt->feats->str[aa]);
      } else {
         if ((float)hf[aa]->N_ignored/(float)hf[aa]->n > 0.05) {
            SUMA_S_Warnv("For histogram %s, %.2f%% of the samples were\n"
                         "ignored for being outside the range [%f %f]\n",
                   Opt->feats->str[aa],
                   100*(float)hf[aa]->N_ignored/(float)hf[aa]->n, 
                   hf[aa]->min, hf[aa]->max);
         }
         if (Opt->debug > 1) SUMA_Show_hist(hf[aa], 1, NULL);
         /* save the histogram */
         if (!SUMA_write_hist(hf[aa],
                  SUMA_hist_fname(Opt->proot, 
                                  Opt->feats->str[aa], NULL, 0))) {
            SUMA_S_Errv("Failed to write histog to %s\n", sbuf);
         } 
      }
   }  
   if (ff) SUMA_free(ff); ff = NULL;
   
   
   /* Compute histograms of features per class && save them*/
   hh = (SUMA_HIST ***)SUMA_calloc(Opt->feats->num, sizeof(SUMA_HIST **));
   for (aa=0; aa<Opt->feats->num; ++aa) {
      hh[aa] = (SUMA_HIST **)SUMA_calloc(Opt->clss->num, sizeof(SUMA_HIST *));
   }

   SUMA_S_Note("Computing histograms of features per class");
   for (cc=0; cc<Opt->clss->num; ++cc) {
      if (N_FCset[0][cc] < 10) {
         SUMA_S_Errv("Requested class %s (%d) has just %d samples.\n"
                     "Not enough to grease your pan.\n",
                     Opt->clss->str[cc], Opt->keys[cc], N_FCset[0][cc]);
         exit(1);
      }
      for (aa=0; aa<Opt->feats->num; ++aa) {
         sprintf(sbuf, "h(%s|%s)",Opt->feats->str[aa], Opt->clss->str[cc]);
         hrange[0] = hf[aa]->min; hrange[1] = hf[aa]->max; 
         /* Do not optimize hist range and binwidth anymore, 
            but allow smoothing. This is needed when a particular 
            class has very few samples */
         if (!(hh[aa][cc] = SUMA_hist_opt(FCset[aa][cc], N_FCset[aa][cc], 
                                    hf[aa]->K, hf[aa]->W, 
                                    hrange, sbuf, 1,
                                    0.1, "OsciSmooth"))) {
            SUMA_S_Errv("Failed to generate histogram for %s|%s. \n"
                        "This will cause trouble at classification.\n",
                        Opt->feats->str[aa], Opt->clss->str[cc])
         } else {
            if (Opt->debug > 1) SUMA_Show_hist(hh[aa][cc], 1, NULL);
            /* save the histogram */
            if (!SUMA_write_hist(hh[aa][cc],
                     SUMA_hist_fname(Opt->proot, 
                              Opt->feats->str[aa], Opt->clss->str[cc], 0))) {
               SUMA_S_Errv("Failed to write histog to %s\n", sbuf);
            } 
         }
      }
   }
   
   SUMA_S_Note("Computing Correlation matrices");
   /* L2 normalize all of FCset */
   for (cc=0; cc<Opt->clss->num; ++cc) {
      for (aa=0; aa<Opt->feats->num; ++aa) {
         THD_normalize(N_FCset[aa][cc], FCset[aa][cc]);
      }
   }
   
   {
      NI_element **CC=NULL;
      float *fm=NULL, *fn=NULL;
      NI_element *nel = NULL;
      int suc;
      
   /* Compute the correlation matrices for each class */
   CC = (NI_element **) SUMA_calloc(Opt->clss->num, sizeof(NI_element *));
   
   for(cc=0; cc<Opt->clss->num; ++cc) {
      sprintf(sbuf, "CorrMat(%s)", Opt->clss->str[cc]);
      CC[cc] = NI_new_data_element(sbuf, Opt->feats->num);
      NI_set_attribute(CC[cc],"Measure","correlation");
      atr = SUMA_NI_str_ar_2_comp_str(Opt->feats, " ; ");
      NI_set_attribute(CC[cc],"ColumnLabels", atr);SUMA_free(atr); atr = NULL;
      atr = SUMA_HistString (FuncName, argc, argv, NULL);
      NI_set_attribute(CC[cc],"CommandLine", atr);SUMA_free(atr); atr = NULL;
      for (aa=0; aa<Opt->feats->num; ++aa) {
         NI_add_column_stride ( CC[cc], NI_FLOAT, NULL, 1 );
      }
      for (aa=0; aa<Opt->feats->num; ++aa) {
         fm = (float*)CC[cc]->vec[aa];
         for (iii=0; iii<aa; ++iii) fm[iii] = 0.0; /* will fill later */
         fm[aa]=1.0;
         for (iii=aa+1; iii<Opt->feats->num; ++iii) {
            if (N_FCset[aa][cc]!=N_FCset[iii][cc]) {
               SUMA_S_Errv("Sanity check failed, %d != %d\n",
                              N_FCset[aa][cc], N_FCset[iii][cc]);
            }
            SUMA_DOTP_VEC(FCset[aa][cc], FCset[iii][cc], 
                          fm[iii], N_FCset[aa][cc], 
                          float, float);
         }
      }
      /* Now fill the remainder */
      for (aa=0; aa<Opt->feats->num; ++aa) {
         fm = (float*)CC[cc]->vec[aa];
         for (iii=0; iii<aa; ++iii) {
            fn = (float*)CC[cc]->vec[iii];
            fm[iii] = fn[aa];
         }
      }
      snprintf(sbuf, 510, "file:%s.niml.cormat", 
               SUMA_corrmat_fname(Opt->proot, Opt->clss->str[cc], 0));
      NEL_WRITE_TXH(CC[cc], sbuf, suc);
   }
   
   }
   /* free everything */
   if (FCset) {
      for (aa=0; aa<Opt->feats->num; ++aa) {
         for (cc=0; cc<Opt->clss->num; ++cc) {
            if (FCset[aa][cc]) SUMA_free(FCset[aa][cc]);
         }
         SUMA_free(FCset[aa]); 
      }
      SUMA_free(FCset); FCset=NULL;
   }
   if (N_FCset) {
      for (aa=0; aa<Opt->feats->num; ++aa) {
         SUMA_free(N_FCset[aa]);
      }
      SUMA_free(N_FCset); N_FCset=NULL;
   }
   if (N_alloc_FCset) {
      for (aa=0; aa<Opt->feats->num; ++aa) {
         SUMA_free(N_alloc_FCset[aa]);
      }
      SUMA_free(N_alloc_FCset); N_alloc_FCset=NULL;
   }
   if (ifeat) SUMA_free(ifeat); ifeat=NULL;
   
   if (hh) {
      for (aa=0; aa<Opt->feats->num; ++aa) {
         for (cc=0; cc<Opt->clss->num; ++cc) {
            if (hh[aa][cc]) hh[aa][cc] = SUMA_Free_hist(hh[aa][cc]);
         }
         SUMA_free(hh[aa]);
      }
      SUMA_free(hh); hh=NULL;
   }
   
   if (hf) {
      for (aa=0; aa<Opt->feats->num; ++aa) {
         if (hf[aa]) hf[aa] = SUMA_Free_hist(hf[aa]);
      }
      SUMA_free(hf); hf=NULL;
   }
   
   if (masks) {
      for (ss=0; ss<Opt->sig_names->num; ++ss) {
         if (masks[ss]) SUMA_free(masks[ss]);
      }
      masks[ss]=NULL;
   }
   
   SUMA_S_Notev("\n"
                "Consider running this script to examine the distributions:\n"
                "   @ExamineGenFeatDists -fdir %s -odir %s\n",
                Opt->proot, Opt->proot);
   
   /* all done, free */
   Opt = free_SegOpts(Opt);
   
   PRINT_COMPILE_DATE ; exit(0);
}
示例#3
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);
}