static int
initialize_cluster_centers(MRI_SURFACE *mris, MRI *mri_profiles, CLUSTER *ct, int k) {
  int i, j, done, vno, nsamples, vnos[MAX_CLUSTERS], iter ;
  double dist, min_dist ;
  VERTEX *v, *vn ;

  nsamples = mri_profiles->nframes ;
  min_dist = sqrt(mris->total_area/k) / 2 ;
  for (i = 0 ; i < k ; i++) {
    iter = 0 ;
    do {
      do {
        vno = (int)randomNumber(0, mris->nvertices-1) ;
        v = &mris->vertices[vno] ;
      } while (v->ripflag) ;

      // see if any of the other centers are too close to this one
      done = 1 ;
      for (j = 0 ; done && j < i ; j++) {
        if (j == i)
          continue ;
        vn = &mris->vertices[vnos[j]] ;
        dist = sqrt(SQR(vn->x-v->x)+SQR(vn->y-v->y)+SQR(vn->z-v->z)) ;
        if (dist < min_dist) {
          done = 0 ;
          break ;
        }
      }
      if (iter++ > mris->nvertices)
        done = 1 ;
    } while (!done) ;
    vnos[i] = vno ;
    for (j = 0 ; j < nsamples ; j++)
      VECTOR_ELT(ct[i].v_mean, j+1) = MRIgetVoxVal(mri_profiles, vno, 0, 0, j) ;
  }
  mris->ct = CTABalloc(k) ;
  for (i = 0 ; i < k ; i++) {
    mris->vertices[vnos[i]].curv = i ;
    ct[i].npoints++ ;
    ct[i].vno = vnos[i] ;
    CTABannotationAtIndex(mris->ct, i, &mris->vertices[vnos[i]].annotation) ;
  }
  return(NO_ERROR) ;
}
static int
mark_clusters(MRI_SURFACE *mris, MRI *mri_profiles, CLUSTER *ct, int k) {
  int    i, vno, min_i, nsamples, num[MAX_CLUSTERS], nchanged ;
  double min_dist, dist ;
  VECTOR *v1 ;
  VERTEX *v ;

  memset(num, 0, sizeof(num)) ;
  nsamples = mri_profiles->nframes ;
  v1 = VectorAlloc(nsamples, MATRIX_REAL) ;
  for (nchanged = vno = 0 ; vno < mris->nvertices ; vno++) {
    v = &mris->vertices[vno] ;
    if (v->ripflag)
      continue ;
    if (vno == Gdiag_no)
      DiagBreak() ;

    for (i = 0 ; i < nsamples ; i++)
      VECTOR_ELT(v1, i+1) = MRIgetVoxVal(mri_profiles, vno, 0, 0, i) ;
    min_dist = MatrixMahalanobisDistance(ct[0].v_mean, ct[0].m_cov, v1) ;
    min_i = 0 ;
    for (i = 1 ; i < k ; i++) {
      if (i == Gdiag_no)
        DiagBreak() ;
      dist = MatrixMahalanobisDistance(ct[i].v_mean, ct[i].m_cov, v1) ;
      if (dist < min_dist) {
        min_dist = dist ;
        min_i = i ;
      }
    }
    CTABannotationAtIndex(mris->ct, min_i, &v->annotation) ;
    if (v->curv != min_i)
      nchanged++ ;
    v->curv = min_i ;
    num[min_i]++ ;
  }
  for (i = 0 ; i < k ; i++)
    if (num[i] == 0)
      DiagBreak() ;
  VectorFree(&v1) ;
  printf("%d vertices changed clusters...\n", nchanged) ;
  return(nchanged) ;
}
Exemple #3
0
/* ------------------------------------------------------------
   int sclustAnnot(MRIS *surf, int NClusters)
   Convert clusters into annotation
   ------------------------------------------------------------*/
int sclustAnnot(MRIS *surf, int NClusters)
{
  COLOR_TABLE *ct ;
  int vtxno, vtx_clusterno, annot, n;

  ct = CTABalloc(NClusters+1);
  surf->ct = ct;

  for(n=1; n < NClusters; n++) // no cluster 0
    sprintf(surf->ct->entries[n]->name, "%s-%03d","cluster",n);

  for(vtxno = 0; vtxno < surf->nvertices; vtxno++)  {
    vtx_clusterno = surf->vertices[vtxno].undefval;
    if(vtx_clusterno == 0 || vtx_clusterno > NClusters){
      surf->vertices[vtxno].annotation = 0;
      continue;
    }
    CTABannotationAtIndex(surf->ct, vtx_clusterno, &annot);
    surf->vertices[vtxno].annotation = annot;
  }
  return(0);
}
static int
add_vertex_to_cluster(MRI_SURFACE *mris, MRI *mri_profiles, CLUSTER *ct, int c, int vno) {
  int    nsamples;
  static VECTOR *v_vals = NULL ;

  nsamples = mri_profiles->nframes ;

  if (ct[c].npoints == 0)
    ct[c].vno = vno ;
  mris->vertices[vno].curv = c ;
  CTABannotationAtIndex(mris->ct, c, &mris->vertices[vno].annotation);
  if (v_vals == NULL)
    v_vals = VectorAlloc(nsamples, MATRIX_REAL) ;

  VectorScalarMul(ct[c].v_mean, ct[c].npoints, ct[c].v_mean) ;
  load_vals(mri_profiles, v_vals, vno) ;
  VectorAdd(ct[c].v_mean, v_vals, ct[c].v_mean) ;
  ct[c].npoints++ ;
  VectorScalarMul(ct[c].v_mean, 1.0/(double)ct[c].npoints, ct[c].v_mean) ;

  return(NO_ERROR) ;
}
static int
initialize_cluster_centers_with_ico(MRI_SURFACE *mris, MRI *mri_profiles, CLUSTER *ct, MRI_SURFACE *mris_ico) {
  int             i, j, vno, nsamples, vnos[MAX_CLUSTERS], k ;
  double          r1, r2, res ;
  float           fmin ;
  MRIS_HASH_TABLE *mht ;
  VERTEX          *vico ;

  k = mris_ico->nvertices ;
  MRISstoreRipFlags(mris) ;
  MRISunrip(mris) ;
  r1 = MRISaverageRadius(mris) ;
  r2 = MRISaverageRadius(mris_ico) ;
  MRISscaleBrain(mris_ico,mris_ico, r1/r2);

  res = sqrt(mris->total_area/mris->nvertices) ;
  mht = MHTfillVertexTableRes(mris, NULL, CURRENT_VERTICES, 2*res) ;
  nsamples = mri_profiles->nframes ;
  for (i = 0 ; i < mris_ico->nvertices ; i++) {
    vico = &mris_ico->vertices[i] ;
    vno = MRISfindClosestVertex(mris, vico->x, vico->y, vico->z, &fmin) ;
    if (vno < 0)
      continue ;
    vnos[i] = vno ;
    for (j = 0 ; j < nsamples ; j++)
      VECTOR_ELT(ct[i].v_mean, j+1) = MRIgetVoxVal(mri_profiles, vno, 0, 0, j) ;
  }
  mris->ct = CTABalloc(k) ;
  for (i = 0 ; i < k ; i++) {
    mris->vertices[vnos[i]].curv = i ;
    ct[i].npoints++ ;
    ct[i].vno = vnos[i] ;
    CTABannotationAtIndex(mris->ct, i, &mris->vertices[vnos[i]].annotation) ;
  }
  MRISrestoreRipFlags(mris) ;
  return(NO_ERROR) ;
}
/*----------------------------------------------------------------------
  Parameters:

  Description:
----------------------------------------------------------------------*/
static int
get_option(int argc, char *argv[])
{
  int    n,nargs = 0 ;
  char   *option ;
  float  f ;

  option = argv[1] + 1 ;            /* past '-' */
  if (!stricmp(option, "-help")||!stricmp(option, "-usage"))
  {
    print_help() ;
  }
  else if (!stricmp(option, "-version"))
  {
    print_version() ;
  }
  else if (!stricmp(option, "median"))
  {
    which_norm = NORM_MEDIAN ;
    printf("using median normalization\n") ;
  }
  else if (!stricmp(option, "vnum") || !stricmp(option, "distances"))
  {
    parms.nbhd_size = atof(argv[2]) ;
    parms.max_nbrs = atof(argv[3]) ;
    nargs = 2 ;
    fprintf(stderr, "nbr size = %d, max neighbors = %d\n",
            parms.nbhd_size, parms.max_nbrs) ;
  }
  else if (!stricmp(option, "nonorm"))
  {
    which_norm = NORM_NONE ;
    printf("disabling normalization\n") ;
  }
  else if (!stricmp(option, "vsmooth"))
  {
    parms.var_smoothness = 1 ;
    printf("using space/time varying smoothness weighting\n") ;
  }
  else if (!stricmp(option, "sigma"))
  {
    if (nsigmas >= MAX_SIGMAS)
    {
      ErrorExit(ERROR_NOMEMORY, "%s: too many sigmas specified (%d)\n",
                Progname, nsigmas) ;
    }
    sigmas[nsigmas] = atof(argv[2]) ;
    nargs = 1 ;
    nsigmas++ ;
  }
  else if (!stricmp(option, "vector"))
  {
    fprintf(stderr,
            "\nMultiframe Mode:\n");
    fprintf(stderr,
            "Use -addframe option to add extra-fields into average atlas\n");
    fprintf(stderr,
            "\t-addframe which_field where_in_atlas l_corr l_pcorr\n");
    fprintf(stderr,
            "\tfield code:\n");
    for (n=0 ; n < NUMBER_OF_VECTORIAL_FIELDS ; n++)
      fprintf(stderr,
              "\t      field %d is '%s' (type = %d)\n",
              n,ReturnFieldName(n),IsDistanceField(n));
    exit(1);
  }
  else if (!stricmp(option, "annot"))
  {
    annot_name = argv[2] ;
    fprintf(stderr,"zeroing medial wall in %s\n", annot_name) ;
    nargs=1;
  }
  else if (!stricmp(option, "init"))
  {
    use_initial_registration=1;
    fprintf(stderr,"use initial registration\n");
  }
  else if (!stricmp(option, "addframe"))
  {
    int which_field,where_in_atlas;
    float l_corr,l_pcorr;

    if (multiframes==0)
    {
      /* activate multiframes mode */
      initParms();
      multiframes = 1;
    }

    which_field=atoi(argv[2]);
    where_in_atlas=atoi(argv[3]);
    l_corr=atof(argv[4]);
    l_pcorr=atof(argv[5]);

    fprintf(stderr,
            "adding field %d (%s) with location %d in the atlas\n",
            which_field,ReturnFieldName(which_field),where_in_atlas) ;
    /* check if this field exist or not */
    for (n = 0 ; n < parms.nfields ; n++)
    {
      if (parms.fields[n].field==which_field)
      {
        fprintf(stderr,"ERROR: field already exists\n");
        exit(1);
      }
    }
    /* adding field into parms */
    n=parms.nfields++;
    SetFieldLabel(&parms.fields[n],
                  which_field,
                  where_in_atlas,
                  l_corr,
                  l_pcorr,
                  0,
                  which_norm);
    nargs = 4 ;
  }
  /* else if (!stricmp(option, "hippocampus")) */
  /*   { */
  /*   if(multiframes==0){ */
  /*    multiframes = 1 ; */
  /*    initParms(); */
  /*   } */
  /*   where=atoi(argv[2]); */
  /*   parms.l_corrs[]=atof(argv[3]); */
  /*   parms.l_pcorrs[]=atof(argv[4]); */
  /*   parms.frames[]=; */
  /*   parms. */
  /*     fprintf(stderr, "using hippocampus distance map\n") ; */
  /*   nargs=3; */
  /*   } */
  else if (!stricmp(option, "topology"))
  {
    parms.flags |= IPFLAG_PRESERVE_SPHERICAL_POSITIVE_AREA;
    fprintf(stderr, "preserving the topology of positive area triangles\n");
  }
  else if (!stricmp(option, "vnum") || !stricmp(option, "distances"))
  {
    parms.nbhd_size = atof(argv[2]) ;
    parms.max_nbrs = atof(argv[3]) ;
    nargs = 2 ;
    fprintf(stderr, "nbr size = %d, max neighbors = %d\n",
            parms.nbhd_size, parms.max_nbrs) ;
  }
  else if (!stricmp(option, "rotate"))
  {
    dalpha = atof(argv[2]) ;
    dbeta = atof(argv[3]) ;
    dgamma = atof(argv[4]) ;
    fprintf(stderr, "rotating brain by (%2.2f, %2.2f, %2.2f)\n",
            dalpha, dbeta, dgamma) ;
    nargs = 3 ;
  }
  else if (!stricmp(option, "reverse"))
  {
    reverse_flag = 1 ;
    fprintf(stderr, "mirror image reversing brain before morphing...\n") ;
  }
  else if (!stricmp(option, "min_degrees"))
  {
    min_degrees = atof(argv[2]) ;
    fprintf(stderr,
            "setting min angle for search to %2.2f degrees\n",
            min_degrees) ;
    nargs = 1 ;
  }
  else if (!stricmp(option, "max_degrees"))
  {
    max_degrees = atof(argv[2]) ;
    fprintf(stderr,
            "setting max angle for search to %2.2f degrees\n",
            max_degrees) ;
    nargs = 1 ;
  }
  else if (!stricmp(option, "nangles"))
  {
    nangles = atoi(argv[2]) ;
    fprintf(stderr, "setting # of angles/search per scale to %d\n", nangles) ;
    nargs = 1 ;
  }
  else if (!stricmp(option, "jacobian"))
  {
    jacobian_fname = argv[2] ;
    nargs = 1 ;
    printf("writing out jacobian of mapping to %s\n", jacobian_fname) ;
  }
  else if (!stricmp(option, "dist"))
  {
    sscanf(argv[2], "%f", &parms.l_dist) ;
    nargs = 1 ;
    use_defaults = 0 ;
    fprintf(stderr, "l_dist = %2.3f\n", parms.l_dist) ;
  }
  else if (!stricmp(option, "norot"))
  {
    fprintf(stderr, "disabling initial rigid alignment...\n") ;
    parms.flags |= IP_NO_RIGID_ALIGN ;
  }
  else if (!stricmp(option, "inflated"))
  {
    fprintf(stderr, "using inflated surface for initial alignment\n") ;
    parms.flags |= IP_USE_INFLATED ;
  }
  else if (!stricmp(option, "multi_scale"))
  {
    multi_scale = atoi(argv[2]) ;
    fprintf(stderr, "using %d scales for morphing\n", multi_scale) ;
    nargs = 1 ;
  }
  else if (!stricmp(option, "nsurfaces"))
  {
    parms.nsurfaces = atoi(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr,
            "using %d surfaces/curvatures for alignment\n",
            parms.nsurfaces) ;
  }
  else if (!stricmp(option, "infname"))
  {
    char fname[STRLEN] ;
    inflated_name = argv[2] ;
    surface_names[0] = argv[2] ;
    nargs = 1 ;
    printf("using %s as inflated surface name, "
           "and using it for initial alignment\n", inflated_name) ;
    sprintf(fname, "%s.H", argv[2]) ;
    curvature_names[0] = (char *)calloc(strlen(fname)+1, sizeof(char)) ;
    strcpy(curvature_names[0], fname) ;
    parms.flags |= IP_USE_INFLATED ;
  }
  else if (!stricmp(option, "nosulc"))
  {
    fprintf(stderr, "disabling initial sulc alignment...\n") ;
    parms.flags |= IP_NO_SULC ;
  }
  else if (!stricmp(option, "sulc"))
  {
    curvature_names[1] = argv[2] ;
    fprintf(stderr, "using %s to replace 'sulc' alignment\n",
            curvature_names[1]) ;
    nargs = 1 ;
    MRISsetSulcFileName(argv[2]);
  }

  else if (!stricmp(option, "surf0"))
  {
    surface_names[0]       = argv[2];
    fprintf(stderr, "using %s as input surface 0.\n",
            surface_names[0]) ;
    nargs = 1 ;
  }

  else if (!stricmp(option, "surf1"))
  {
    surface_names[1]       = argv[2];
    fprintf(stderr, "using %s as input surface 1.\n",
            surface_names[1]) ;
    nargs = 1 ;
  }

  else if (!stricmp(option, "surf2"))
  {
    surface_names[2]       = argv[2];
    fprintf(stderr, "using %s as input surface 2.\n",
            surface_names[2]) ;
    nargs = 1 ;
  }

  else if (!stricmp(option, "curv0"))
  {
    curvature_names[0]  = argv[2];
    fprintf(stderr, "using %s as curvature function for surface 0.\n",
            curvature_names[0]) ;
    nargs = 1 ;
  }

  else if (!stricmp(option, "curv1"))
  {
    curvature_names[1]  = argv[2];
    fprintf(stderr, "using %s as curvature function for surface 1.\n",
            curvature_names[1]) ;
    nargs = 1 ;
  }

  else if (!stricmp(option, "curv2"))
  {
    curvature_names[2]  = argv[2];
    fprintf(stderr, "using %s as curvature function for surface 2.\n",
            curvature_names[2]) ;
    nargs = 1 ;
  }


  else if (!stricmp(option, "lm"))
  {
    parms.integration_type = INTEGRATE_LINE_MINIMIZE ;
    fprintf(stderr, "integrating with line minimization\n") ;
  }
  else if (!stricmp(option, "search"))
  {
    parms.integration_type = INTEGRATE_LM_SEARCH ;
    fprintf(stderr, "integrating with binary search line minimization\n") ;
  }
  else if (!stricmp(option, "dt"))
  {
    parms.dt = atof(argv[2]) ;
    parms.base_dt = .2*parms.dt ;
    nargs = 1 ;
    fprintf(stderr, "momentum with dt = %2.2f\n", parms.dt) ;
  }
  else if (!stricmp(option, "area"))
  {
    use_defaults = 0 ;
    sscanf(argv[2], "%f", &parms.l_area) ;
    nargs = 1 ;
    fprintf(stderr, "using l_area = %2.3f\n", parms.l_area) ;
  }
  else if (!stricmp(option, "parea"))
  {
    use_defaults = 0 ;
    sscanf(argv[2], "%f", &parms.l_parea) ;
    nargs = 1 ;
    fprintf(stderr, "using l_parea = %2.3f\n", parms.l_parea) ;
  }
  else if (!stricmp(option, "nlarea"))
  {
    use_defaults = 0 ;
    sscanf(argv[2], "%f", &parms.l_nlarea) ;
    nargs = 1 ;
    fprintf(stderr, "using l_nlarea = %2.3f\n", parms.l_nlarea) ;
  }
  else if (!stricmp(option, "spring"))
  {
    use_defaults = 0 ;
    sscanf(argv[2], "%f", &parms.l_spring) ;
    nargs = 1 ;
    fprintf(stderr, "using l_spring = %2.3f\n", parms.l_spring) ;
  }
  else if (!stricmp(option, "corr"))
  {
    use_defaults = 0 ;
    sscanf(argv[2], "%f", &parms.l_corr) ;
    nargs = 1 ;
    fprintf(stderr, "using l_corr = %2.3f\n", parms.l_corr) ;
  }
  else if (!stricmp(option, "remove_negative"))
  {
    remove_negative = atoi(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr, "%sremoving negative triangles with iterative smoothing\n",
            remove_negative ? "" : "not ") ;
  }
  else if (!stricmp(option, "curv"))
  {
    parms.flags |= IP_USE_CURVATURE ;
    fprintf(stderr, "using smoothwm curvature for final alignment\n") ;
  }
  else if (!stricmp(option, "nocurv"))
  {
    parms.flags &= ~IP_USE_CURVATURE ;
    fprintf(stderr, "NOT using smoothwm curvature for final alignment\n") ;
  }
  else if (!stricmp(option, "sreg"))
  {
    starting_reg_fname = argv[2] ;
    nargs = 1 ;
    fprintf(stderr, "starting registration with coordinates in  %s\n",
            starting_reg_fname) ;
  }
  else if (!stricmp(option, "adaptive"))
  {
    parms.integration_type = INTEGRATE_ADAPTIVE ;
    fprintf(stderr, "using adaptive time step integration\n") ;
  }
  else if (!stricmp(option, "nbrs"))
  {
    nbrs = atoi(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr, "using neighborhood size=%d\n", nbrs) ;
  }
  else if (!stricmp(option, "tol"))
  {
    if (sscanf(argv[2], "%e", &f) < 1)
      ErrorExit(ERROR_BADPARM, "%s: could not scan tol from %s",
                Progname, argv[2]) ;
    parms.tol = (double)f ;
    nargs = 1 ;
    fprintf(stderr, "using tol = %2.2e\n", (float)parms.tol) ;
  }
  else if (!stricmp(option, "error_ratio"))
  {
    parms.error_ratio = atof(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr, "error_ratio=%2.3f\n", parms.error_ratio) ;
  }
  else if (!stricmp(option, "dt_inc"))
  {
    parms.dt_increase = atof(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr, "dt_increase=%2.3f\n", parms.dt_increase) ;
  }
  else if (!stricmp(option, "lap") || !stricmp(option, "lap"))
  {
    parms.l_lap = atof(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr, "l_laplacian = %2.3f\n", parms.l_lap) ;
  }
  else if (!stricmp(option, "vnum"))
  {
    parms.nbhd_size = atof(argv[2]) ;
    parms.max_nbrs = atof(argv[3]) ;
    nargs = 2 ;
    fprintf(stderr, "nbr size = %d, max neighbors = %d\n",
            parms.nbhd_size, parms.max_nbrs) ;
  }
  else if (!stricmp(option, "dt_dec"))
  {
    parms.dt_decrease = atof(argv[2]) ;
    nargs = 1 ;
    fprintf(stderr, "dt_decrease=%2.3f\n", parms.dt_decrease) ;
  }
  else if (!stricmp(option, "ocorr"))
  {
    l_ocorr = atof(argv[2]) ;
    printf("setting overlay correlation coefficient to %2.1f\n", l_ocorr) ;
    nargs = 1 ;
    fprintf(stderr, "dt_decrease=%2.3f\n", parms.dt_decrease) ;
  }
  else if (!stricmp(option, "overlay"))
  {
    int navgs ;
    if (noverlays == 0)
    {
      atlas_size = 0 ;
    }
    if (multiframes == 0)
    {
      initParms() ;
      multiframes = 1 ;
    }
    overlays[noverlays++] = argv[2] ;
    navgs = atof(argv[3]) ;
    printf("reading overlay from %s and smoothing it %d times\n",
           argv[2], navgs) ;
    n=parms.nfields++;
    SetFieldLabel(&parms.fields[n],
                  OVERLAY_FRAME,
                  atlas_size,
                  l_ocorr,
                  0.0,
                  navgs,
                  which_norm);
    SetFieldName(&parms.fields[n], argv[2]) ;
    atlas_size++ ;
    nargs = 2 ;
  }
  else if (!stricmp(option, "distance"))
  {
    int navgs ;
    if (noverlays == 0)
    {
      atlas_size = 0 ;
    }
    if (multiframes == 0)
    {
      initParms() ;
      multiframes = 1 ;
    }
    overlays[noverlays++] = argv[2] ;
    navgs = atof(argv[3]) ;
    printf("reading overlay from %s and smoothing it %d times\n",
           argv[2], navgs) ;
    n=parms.nfields++;
    SetFieldLabel(&parms.fields[n],
                  DISTANCE_TRANSFORM_FRAME,
                  atlas_size,
                  l_ocorr,
                  0.0,
                  navgs,
                  NORM_MAX) ;
    SetFieldName(&parms.fields[n], argv[2]) ;
    atlas_size++ ;
    nargs = 2 ;
  }
  else if (!stricmp(option, "canon"))
  {
    canon_name = argv[2] ;
    nargs = 1 ;
    fprintf(stderr, "using %s for canonical properties...\n", canon_name) ;
  }
  else if (!stricmp(option, "overlay-dir"))
  {
    parms.overlay_dir = strcpyalloc(argv[2]) ;
    nargs = 1 ;
  }
  else switch (toupper(*option))
    {
    case 'M':
      parms.integration_type = INTEGRATE_MOMENTUM ;
      parms.momentum = atof(argv[2]) ;
      nargs = 1 ;
      fprintf(stderr, "momentum = %2.2f\n", (float)parms.momentum) ;
      break ;
    case 'L':
      if (nlabels >= MAX_LABELS-1)
        ErrorExit(ERROR_NO_MEMORY,
                  "%s: too many labels specified (%d max)",
                  Progname, MAX_LABELS) ;
      nargs = 3 ;
      labels[nlabels] = LabelRead(NULL, argv[2]) ;
      if (labels[nlabels] == NULL)
        ErrorExit(ERROR_NOFILE,
                  "%s: could not read label file %s",
                  Progname, argv[2]) ;
      label_gcsa[nlabels] = GCSAread(argv[3]) ;
      if (label_gcsa[nlabels] == NULL)
        ErrorExit(ERROR_NOFILE,
                  "%s: could not read GCSA file %s",
                  Progname, argv[3]) ;
      label_names[nlabels] = argv[4] ;
      CTABfindName(label_gcsa[nlabels]->ct, argv[4],&label_indices[nlabels]) ;

      if (label_indices[nlabels] < 0)
        ErrorExit(ERROR_NOFILE,
                  "%s: could not map name %s to index",
                  Progname, argv[3]) ;
      CTABannotationAtIndex(label_gcsa[nlabels]->ct, label_indices[nlabels],
                            &label_annots[nlabels]);
      nlabels++ ;
      gMRISexternalSSE = gcsaSSE ;
      break ;
    case 'E':
      parms.l_external = atof(argv[2]) ;
      nargs = 1 ;
      printf("setting l_external = %2.1f\n", parms.l_external) ;
      break ;
    case 'C':
      strcpy(curvature_fname, argv[2]) ;
      nargs = 1 ;
      break ;
    case 'A':
      sscanf(argv[2], "%d", &parms.n_averages) ;
      nargs = 1 ;
      fprintf(stderr, "using n_averages = %d\n", parms.n_averages) ;
      break ;
    case '1':
      single_surf = True ;
      printf("treating target as a single subject's surface...\n") ;
      break ;
    case 'S':
      scale = atof(argv[2]) ;
      fprintf(stderr, "scaling distances by %2.2f\n", scale) ;
      nargs = 1 ;
      break ;
    case 'N':
      sscanf(argv[2], "%d", &parms.niterations) ;
      nargs = 1 ;
      fprintf(stderr, "using niterations = %d\n", parms.niterations) ;
      break ;
    case 'W':
      Gdiag |= DIAG_WRITE ;
      sscanf(argv[2], "%d", &parms.write_iterations) ;
      nargs = 1 ;
      fprintf(stderr,
              "using write iterations = %d\n",
              parms.write_iterations) ;
      break ;
    case 'V':
      Gdiag_no = atoi(argv[2]) ;
      nargs = 1 ;
      break ;
    case 'O':
      orig_name = argv[2] ;
      nargs = 1 ;
      fprintf(stderr, "using %s for original properties...\n", orig_name) ;
      break ;
    case 'P':
      max_passes = atoi(argv[2]) ;
      fprintf(stderr, "limiting unfolding to %d passes\n", max_passes) ;
      nargs = 1 ;
      break ;
    case '?':
    case 'H':
    case 'U':
      print_help() ;
      exit(1) ;
      break ;
    default:
      fprintf(stderr, "unknown option %s\n", argv[1]) ;
      exit(1) ;
      break ;
    }

  return(nargs) ;
}
int
main(int argc, char *argv[]) {
  char         **av, fname[STRLEN], *input_name, *subject_name, *cp,*hemi,
  *svm_name, *surf_name, *output_subject_name ;
  int          ac, nargs, vno ;
  int          msec, minutes, seconds ;
  struct timeb start ;
  MRI_SURFACE  *mris ;
  SVM          *svm ;
  double       classification ;
  float        *inputs ;
  MRI_SP       *mrisp ;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mris_svm_classify.c,v 1.6 2011/03/02 00:04:34 nicks Exp $", "$Name:  $");
  if (nargs && argc - nargs == 1)
    exit (0);
  argc -= nargs;

  Progname = argv[0] ;
  ErrorInit(NULL, NULL, NULL) ;
  DiagInit(NULL, NULL, NULL) ;

  TimerStart(&start) ;

  ac = argc ;
  av = argv ;
  for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) {
    nargs = get_option(argc, argv) ;
    argc -= nargs ;
    argv += nargs ;
  }

  if (!strlen(subjects_dir)) /* hasn't been set on command line */
  {
    cp = getenv("SUBJECTS_DIR") ;
    if (!cp)
      ErrorExit(ERROR_BADPARM, "%s: SUBJECTS_DIR not defined in environment",
                Progname);
    strcpy(subjects_dir, cp) ;
  }
  if (argc < 7)
    usage_exit(1) ;

  subject_name = argv[1] ;
  hemi = argv[2] ;
  surf_name = argv[3] ;
  input_name = argv[4] ;
  output_subject_name = argv[5] ;
  svm_name = argv[6] ;

  printf("reading svm from %s...\n", svm_name) ;
  svm = SVMread(svm_name) ;
  if (!svm)
    ErrorExit(ERROR_NOFILE, "%s: could not read classifier from %s",
              Progname, svm_name) ;
  if (log_fname != NULL)
    printf("logging results to %s, true_class = %s\n",
           log_fname, true_class > 0 ? svm->class1_name : svm->class2_name) ;

  sprintf(fname, "%s/%s/surf/%s.%s", subjects_dir,subject_name,hemi,surf_name);
  printf("reading surface from %s...\n", fname) ;
  mris = MRISread(fname) ;
  if (!mris)
    ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s for %s",
              Progname, fname, subject_name) ;
  MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ;

  if (MRISreadCurvature(mris, input_name) != NO_ERROR)
    ErrorExit(ERROR_BADPARM, "%s: could not read curvature from %s", input_name) ;

    if (nannotations > 0)
    {
      int vno, a, found ;
      VERTEX *v ;
      
      if (MRISreadAnnotation(mris, annot_name) != NO_ERROR)
        ErrorExit(ERROR_NOFILE, 
                  "%s: could not read annot file %s for subject %s",
                  Progname, annot_name, subject_name) ;
      for (a = 0 ; a < nannotations ; a++)
      {
        int index ;
        
        CTABfindName(mris->ct, anames[a], &index) ;
        CTABannotationAtIndex(mris->ct, index, &annotations[a]) ;
        printf("mapping annot %s to %d\n",
               anames[a], annotations[a]) ;
      }
      // rip all vertices that don't have one of the specified annotations
      for (vno = 0 ; vno < mris->nvertices ; vno++)
      {
        v = &mris->vertices[vno] ;
        if (v->ripflag)
          continue ;
        found = 0 ;
        for (a = 0 ; a < nannotations ; a++)
          if (v->annotation == annotations[a])
            found = 1 ;
        if (found == 0)
          v->ripflag = 1 ;
      }
    }
  if (navgs > 0)
    MRISaverageCurvatures(mris, navgs) ;

  mrisp = MRIStoParameterization(mris, NULL, 1, 0) ;
  MRISfree(&mris) ;

  /* read in output surface */
  sprintf(fname, "%s/%s/surf/%s.%s", subjects_dir,output_subject_name,hemi,surf_name);
  printf("reading output surface from %s...\n", fname) ;
  mris = MRISread(fname) ;
  if (!mris)
    ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s for %s",
              Progname, fname, output_subject_name) ;
  MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ;
  MRISfromParameterization(mrisp, mris, 0) ;

  if (label_name) {
    area = LabelRead(output_subject_name, label_name) ;
    if (!area)
      ErrorExit(ERROR_NOFILE, "%s: could not read label %s", Progname,
                label_name) ;
    MRISmaskNotLabel(mris, area) ;
  } else
    area = NULL ;
  if (mris->nvertices != svm->ninputs)
    ErrorExit(ERROR_BADPARM, "%s: svm input (%d) does not match # of "
              "surface vertices (%d)",
              Progname, svm->ninputs, mris->nvertices);

  inputs = (float *)calloc(mris->nvertices, sizeof(float)) ;
  if (!inputs)
    ErrorExit(ERROR_NOMEMORY, "%s: could not allocate %d input vector",
              Progname, mris->nvertices) ;
  for (vno = 0 ; vno < mris->nvertices ; vno++)
    inputs[vno] = mris->vertices[vno].curv ;
  classification = SVMclassify(svm, inputs) ;
  printf("classification %f, class = %s",classification,
         classification > 0 ? svm->class1_name : svm->class2_name) ;
  if (true_class != 0)
    printf(", %s", true_class*classification>0 ? "CORRECT" : "INCORRECT") ;
  printf("\n") ;

  if (log_fname) {
    FILE *fp ;
    fp = fopen(log_fname, "a") ;
    if (!fp)
      ErrorExit(ERROR_BADPARM, "%s: could not open log file %s", log_fname) ;
    fprintf(fp, "%-30.30s %s %d %f %f\n",
            subject_name, hemi, (true_class*classification)>0, classification,
            true_class) ;
    fclose(fp) ;
  }
  free(inputs) ;
  MRISfree(&mris) ;
  SVMfree(&svm) ;
  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf("classification took %d minutes and %d seconds.\n", minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
/* --------------------------------------------- */
static void check_options(void) {
  int n;

  if (subject == NULL) {
    printf("ERROR: need to specify subject\n");
    exit(1);
  }
  if (hemi == NULL) {
    printf("ERROR: need to specify hemi\n");
    exit(1);
  }
  if (CTabFile == NULL) {
    printf("ERROR: need to specify color table file\n");
    exit(1);
  }
  if(AnnotName && AnnotPath) {
    printf("ERROR: cannot spec both --annot and --annot-path\n");
    exit(1);
  }
  if(AnnotName == NULL && AnnotPath == NULL) {
    printf("ERROR: need to specify annotation name\n");
    exit(1);
  }

  SUBJECTS_DIR = getenv("SUBJECTS_DIR");
  if (SUBJECTS_DIR == NULL) {
    printf("ERROR: SUBJECTS_DIR not defined in environment\n");
    exit(1);
  }

  // Read the color table
  printf("Reading ctab %s\n",CTabFile);
  ctab = CTABreadASCII(CTabFile);
  if (ctab == NULL) {
    printf("ERROR: reading %s\n",CTabFile);
    exit(1);
  }
  if (dilate_label_name)
  {
    CTABfindName(ctab, dilate_label_name, &dilate_label_index) ;
    CTABannotationAtIndex(ctab, dilate_label_index, &dilate_label_annot);
    printf("label %s maps to index %d, annot %x\n",
           dilate_label_name, dilate_label_index, dilate_label_annot) ;
  }
  printf("Number of ctab entries %d\n",ctab->nentries);
  if (nlabels == 0) {
    printf("INFO: no labels specified, generating from ctab\n");
    if (labeldir == NULL) labeldir = ".";
    if (labeldirdefault) {
      sprintf(tmpstr,"%s/%s/label",SUBJECTS_DIR,subject);
      labeldir = strcpyalloc(tmpstr);
    }
    nlabels = ctab->nentries;
    for (n=0; n<nlabels; n++) {
      sprintf(tmpstr,"%s/%s.%s.label",labeldir,hemi,ctab->entries[n]->name);
      printf("%2d %s\n",n,tmpstr);
      LabelFiles[n] = strcpyalloc(tmpstr);
    }
  }
  return;
}