/*---------------------------------------------------------------*/
int main(int argc, char *argv[]) {
  int nargs;
  char *surf1_fname ;
  char *surf2_fname ;
  char *out_fname ;
  MRI_SURFACE *mris1, *mris2 ;

  nargs = handle_version_option (argc, argv, vcid, "$Name:  $");
  if (nargs && argc - nargs == 1) exit (0);
  argc -= nargs;
  cmdline = argv2cmdline(argc,argv);
  uname(&uts);
  getcwd(cwd,2000);

  Progname = argv[0] ;
  argc --;
  argv++;
  ErrorInit(NULL, NULL, NULL) ;
  DiagInit(NULL, NULL, NULL) ;
  if (argc == 0) usage_exit();
  parse_commandline(argc, argv);
  check_options();
  if (checkoptsonly) return(0);
  dump_options(stdout);

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

  surf1_fname = argv[0] ; surf2_fname = argv[1] ; out_fname = argv[2] ; 
  mris1 = MRISread(surf1_fname) ;
  if (mris1 == NULL)
    ErrorExit(ERROR_NOFILE, "could not read surface 1 from %s", surf1_fname) ;
  mris2 = MRISread(surf2_fname) ;
  if (mris2 == NULL)
    ErrorExit(ERROR_NOFILE, "could not read surface 2 from %s", surf2_fname) ;

  compute_surface_distance(mris1, mris2, mris1) ;
  MRISwriteValues(mris1, out_fname) ;
  return 0;
}
int
main(int argc, char *argv[])
{
  char          **av, *output_fname ;
  int           ac, nargs, msec, mode=-1 ;
  LABEL         *area = NULL ;
  MRI_SURFACE   *mris ;
  struct timeb  then ;
  MRI           *mri_dist ;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option 
    (argc, argv, 
     "$Id: mris_distance_transform.c,v 1.5 2013/04/12 20:59:17 fischl Exp $", 
     "$Name:  $");
  if (nargs && argc - nargs == 1)
    exit (0);
  argc -= nargs;

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


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

  if (argc < 4)
    usage_exit() ;

  TimerStart(&then) ;
  mris = MRISread(argv[1]) ;
  if (mris == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not read surface %s",
              Progname, argv[1]) ;

  if (vol)
  {
/*
    mri_template = MRIread(argv[2]) ;
    if (!mri_template)
      ErrorExit(ERROR_NOFILE, "%s: could not read MRI volume from %s\n", Progname, argv[2]) ;
*/
  }
  else
  {
    area = LabelRead(NULL, argv[2]) ;
    if (area == NULL)
      ErrorExit(ERROR_NOFILE, "%s: could not read label %s",
		Progname, argv[2]) ;
    
    if (anterior_dist > 0)
      LabelCropAnterior(area, anterior_dist) ;
    if (posterior_dist > 0)
      LabelCropPosterior(area, posterior_dist) ;
  }
  
  if (stricmp(argv[3], "signed") == 0)
    mode = DTRANS_MODE_SIGNED ;
  else if (stricmp(argv[3], "unsigned") == 0)
    mode = DTRANS_MODE_UNSIGNED ;
  else if (stricmp(argv[3], "outside") == 0)
    mode = DTRANS_MODE_OUTSIDE ;
  else
  {
    print_usage() ;
    ErrorExit(ERROR_BADPARM, "unrecognized mode choice %s\n", argv[3]) ;
  }
  output_fname = argv[4] ;

  MRIScomputeMetricProperties(mris) ;
  if (vol)
  {
    mri_dist = MRIScomputeDistanceToSurface(mris, NULL, 0.25) ;
    MRIwrite(mri_dist, argv[4]) ;
  }
  else
  {
    MRIScomputeSecondFundamentalForm(mris) ;
    if (normalize > 0)
    {
      normalize = sqrt(mris->total_area) ;
      printf("normalizing surface distances by sqrt(%2.1f) = %2.1f\n", mris->total_area,normalize) ;
    }
    if (divide > 1)
    {
      int  i ;
      char fname[STRLEN], ext[STRLEN], base_name[STRLEN] ;
      LABEL *area_division ;
      
      FileNameExtension(output_fname, ext) ;
      FileNameRemoveExtension(output_fname, base_name) ;
      LabelMark(area, mris) ;
      MRIScopyMarksToAnnotation(mris) ;
      MRISsaveVertexPositions(mris, TMP_VERTICES) ;
      if (MRISreadVertexPositions(mris, divide_surf_name) != NO_ERROR)
	ErrorExit(ERROR_BADPARM, "%s: could not read vertex coords from %s", Progname, divide_surf_name) ;
      MRIScomputeSecondFundamentalForm(mris) ;
      MRISdivideAnnotationUnit(mris, 1, divide) ;
      MRISrestoreVertexPositions(mris, TMP_VERTICES) ;
      MRIScomputeSecondFundamentalForm(mris) ;
      
      
      // MRISdivideAnnotationUnit sets the marked to be in [0,divide-1], make it [1,divide]
      // make sure they are oriented along original a/p direction
#define MAX_UNITS 100    
      {
	double cx[MAX_UNITS], cy[MAX_UNITS], cz[MAX_UNITS], min_a ;
	int    index, num[MAX_UNITS], new_index[MAX_UNITS], j, min_i ;
	VERTEX *v ;
	
	memset(num, 0, sizeof(num[0])*divide) ;
	memset(cx, 0, sizeof(cx[0])*divide) ;
	memset(cy, 0, sizeof(cy[0])*divide) ;
	memset(cz, 0, sizeof(cz[0])*divide) ;
	for (i = 0 ; i < area->n_points ; i++)
	{
	  if (area->lv[i].vno < 0 || area->lv[i].deleted > 0)
	    continue ;
	  v = &mris->vertices[area->lv[i].vno] ;
	  v->marked++ ;
	  index = v->marked ;
	  cx[index] += v->x ;
	  cy[index] += v->y ;
	  cz[index] += v->z ;
	  num[index]++ ;
	}
	memset(new_index, 0, sizeof(new_index[0])*divide) ;
	for (i = 1 ; i <= divide ; i++)
	  cy[i] /= num[i] ;
	
	// order them from posterior to anterior
	for (j = 1 ; j <= divide ; j++)
	{
	  min_a = 1e10 ; min_i = 0 ;
	  for (i = 1 ; i <= divide ; i++)
	  {
	    if (cy[i] < min_a)
	    {
	      min_a = cy[i] ;
	      min_i = i ;
	    }
	  }
	  cy[min_i] = 1e10 ;  // make it biggest so it won't be considered again
	  new_index[j] = min_i ;
	}
	for (i = 0 ; i < area->n_points ; i++)
	{
	  if (area->lv[i].vno < 0 || area->lv[i].deleted > 0)
	    continue ;
	  v = &mris->vertices[area->lv[i].vno] ;
	  v->marked = new_index[v->marked] ;
	}
      }
      for (i = 1 ; i <= divide ; i++)
      {
	area_division = LabelFromMarkValue(mris, i) ;
	
	printf("performing distance transform on division %d with %d vertices\n", 
	       i, area_division->n_points) ;
	if (output_label)
	{
	  sprintf(fname, "%s%d.label", base_name, i) ;
	  printf("writing %dth subdivision to %s\n", i, fname) ;
	  LabelWrite(area_division, fname);
	}
	MRISdistanceTransform(mris, area_division, mode) ;
	sprintf(fname, "%s%d.%s", base_name, i, ext) ;
	if (normalize > 0)
	  MRISmulVal(mris, 1.0/normalize) ;
	MRISwriteValues(mris, fname) ;
      }
    }
    else
    {
      MRISdistanceTransform(mris, area, mode) ;
      if (normalize > 0)
	MRISmulVal(mris, 1.0/normalize) ;
      MRISwriteValues(mris, output_fname) ;
    }
  }

  msec = TimerStop(&then) ;
  fprintf(stderr,"distance transform took %2.1f minutes\n", (float)msec/(60*1000.0f));

  exit(0) ;
  return(0) ;  /* for ansi */
}
int
main(int argc, char *argv[]) {
  MRI_SURFACE  *mris ;
  char         **av, *curv_name, *surf_name, *hemi, fname[STRLEN],
  *cp, *subject_name, subjects_dir[STRLEN],
  **c1_subjects, **c2_subjects ;
  int          ac, nargs, n, num_class1, num_class2, i, nvertices,
  avgs, max_snr_avgs, nlabels = 0, done ;
  float        **c1_thickness, **c2_thickness, *curvs, *total_mean,
  *c1_mean, *c2_mean,
  *class_mean, *c1_var, *c2_var, *class_var,*pvals,
  **c1_avg_thickness,
  *vbest_snr, *vbest_avgs, *vtotal_var, *vsnr, **c2_avg_thickness,
  *vbest_pvalues, current_min_label_area, current_fthresh ;
  MRI_SP       *mrisp ;
  LABEL        *area, **labels = NULL ;
  FILE         *fp = NULL ;
  double       snr, max_snr ;
  struct timeb start ;
  int          msec, minutes, seconds ;
  double       **c1_label_thickness, **c2_label_thickness ;
  int          *sorted_indices = NULL, vno ;
  float        *test_thickness, *test_avg_thickness ;
  double       label_avg ;

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

  if (write_flag && DIAG_VERBOSE_ON)
    fp = fopen("scalespace.dat", "w") ;

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

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

  TimerStart(&start) ;

  /* subject_name hemi surface curvature */
  if (argc < 7)
    usage_exit() ;
  if (output_subject == NULL)
    ErrorExit(ERROR_BADPARM,
              "output subject must be specified with -o <subject name>");

  cp = getenv("SUBJECTS_DIR") ;
  if (!cp)
    ErrorExit(ERROR_BADPARM, "%s: SUBJECTS_DIR not defined in environment",
              Progname) ;

  strcpy(subjects_dir, cp) ;

  hemi = argv[1] ;
  surf_name = argv[2] ;
  curv_name = argv[3] ;

#define ARGV_OFFSET 4

  /* first determine the number of subjects in each class */
  num_class1 = 0 ;
  n = ARGV_OFFSET ;
  do {
    num_class1++ ;
    n++ ;
    if (argv[n] == NULL || n >= argc)
      ErrorExit(ERROR_BADPARM, "%s: must spectify ':' between class lists",
                Progname) ;
  } while (argv[n][0] != ':') ;

  /* find  # of vertices in output subject surface */
  sprintf(fname, "%s/%s/surf/%s.%s",
          subjects_dir,output_subject,hemi,surf_name);
  mris = MRISread(fname) ;
  if (!mris)
    ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
              Progname, fname) ;
  nvertices = mris->nvertices ;
  MRISfree(&mris) ;

  total_mean = (float *)calloc(nvertices, sizeof(float)) ;
  if (!total_mean)
    ErrorExit(ERROR_NOMEMORY,
              "%s: could not allocate mean list of %d curvatures",
              Progname, n, nvertices) ;
  c1_mean = (float *)calloc(nvertices, sizeof(float)) ;
  if (!c1_mean)
    ErrorExit(ERROR_NOMEMORY,
              "%s: could not allocate c1 mean list of %d curvatures",
              Progname, n, nvertices) ;
  pvals = (float *)calloc(nvertices, sizeof(float)) ;
  if (!pvals)
    ErrorExit(ERROR_NOMEMORY,
              "%s: could not allocate pvals",
              Progname, n, nvertices) ;
  c2_mean = (float *)calloc(nvertices, sizeof(float)) ;
  if (!c2_mean)
    ErrorExit(ERROR_NOMEMORY,
              "%s: could not allocate c2 mean list of %d curvatures",
              Progname, n, nvertices) ;

  c1_var = (float *)calloc(nvertices, sizeof(float)) ;
  if (!c1_var)
    ErrorExit(ERROR_NOMEMORY,
              "%s: could not allocate c1 var list of %d curvatures",
              Progname, n, nvertices) ;
  c2_var = (float *)calloc(nvertices, sizeof(float)) ;
  if (!c2_var)
    ErrorExit(ERROR_NOMEMORY,
              "%s: could not allocate c2 var list of %d curvatures",
              Progname, n, nvertices) ;

  num_class2 = 0 ;
  n++ ; /* skip ':' */
  if (n >= argc)
    ErrorExit(ERROR_BADPARM, "%s: class2 list empty", Progname) ;
  do {
    num_class2++ ;
    n++ ;
    if (n >= argc)
      break ;
  } while (argv[n] != NULL) ;

  fprintf(stderr, "%d subjects in class 1, %d subjects in class 2\n",
          num_class1, num_class2) ;

  c1_subjects = (char **)calloc(num_class1, sizeof(char *)) ;
  c1_thickness = (float **)calloc(num_class1, sizeof(char *)) ;
  c1_avg_thickness = (float **)calloc(num_class1, sizeof(char *)) ;
  c2_subjects = (char **)calloc(num_class2, sizeof(char *)) ;
  c2_thickness = (float **)calloc(num_class2, sizeof(char *)) ;
  c2_avg_thickness = (float **)calloc(num_class2, sizeof(char *)) ;
  for (n = 0 ; n < num_class1 ; n++) {
    c1_subjects[n] = argv[ARGV_OFFSET+n] ;
    c1_thickness[n] = (float *)calloc(nvertices, sizeof(float)) ;
    c1_avg_thickness[n] = (float *)calloc(nvertices, sizeof(float)) ;
    if (!c1_thickness[n] || !c1_avg_thickness[n])
      ErrorExit(ERROR_NOMEMORY,
                "%s: could not allocate %dth list of %d curvatures",
                Progname, n, nvertices) ;

    strcpy(c1_subjects[n], argv[ARGV_OFFSET+n]) ;
    /*    fprintf(stderr, "class1[%d] - %s\n", n, c1_subjects[n]) ;*/
  }
  i = n+1+ARGV_OFFSET ;  /* starting index */
  for (n = 0 ; n < num_class2 ; n++) {
    c2_subjects[n] = argv[i+n] ;
    c2_thickness[n] = (float *)calloc(nvertices, sizeof(float)) ;
    c2_avg_thickness[n] = (float *)calloc(nvertices, sizeof(float)) ;
    if (!c2_thickness[n] || !c2_avg_thickness[n])
      ErrorExit(ERROR_NOMEMORY,
                "%s: could not allocate %dth list of %d curvatures",
                Progname, n, nvertices) ;
    strcpy(c2_subjects[n], argv[i+n]) ;
    /*    fprintf(stderr, "class2[%d] - %s\n", n, c2_subjects[n]) ;*/
  }

  if (label_name) {
    area = LabelRead(output_subject, label_name) ;
    if (!area)
      ErrorExit(ERROR_NOFILE, "%s: could not read label %s", Progname,
                label_name) ;
  } else
    area = NULL ;

  if (read_dir) {
    sprintf(fname, "%s/%s/surf/%s.%s",
            subjects_dir,output_subject,hemi,surf_name);
    mris = MRISread(fname) ;
    if (!mris)
      ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                Progname, fname) ;
    MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ;

    /* real all the curvatures in for group1 */
    for (n = 0 ; n < num_class1+num_class2 ; n++) {
      /* transform each subject's curvature into the output subject's space */
      subject_name = n < num_class1 ? c1_subjects[n]:c2_subjects[n-num_class1];
      fprintf(stderr, "reading subject %d of %d: %s\n",
              n+1, num_class1+num_class2, subject_name) ;
      sprintf(fname, "%s/%s.%s", read_dir,hemi,subject_name);
      if (MRISreadValues(mris, fname) != NO_ERROR)
        ErrorExit(Gerror,
                  "%s: could not read curvature file %s",Progname,fname);
      if (area)
        MRISmaskNotLabel(mris, area) ;
      curvs = (n < num_class1) ? c1_thickness[n] : c2_thickness[n-num_class1] ;
      class_mean = (n < num_class1) ? c1_mean : c2_mean ;
      class_var = (n < num_class1) ? c1_var : c2_var ;
      MRISexportValVector(mris, curvs) ;
      cvector_accumulate(curvs, total_mean, nvertices) ;
      cvector_accumulate(curvs, class_mean, nvertices) ;
      cvector_accumulate_square(curvs, class_var, nvertices) ;
    }
  } else {

    /* real all the curvatures in for group1 */
    for (n = 0 ; n < num_class1+num_class2 ; n++) {
      /* transform each subject's curvature into the output subject's space */
      subject_name = n < num_class1 ? c1_subjects[n]:c2_subjects[n-num_class1];
      fprintf(stderr, "reading subject %d of %d: %s\n",
              n+1, num_class1+num_class2, subject_name) ;
      sprintf(fname, "%s/%s/surf/%s.%s",
              subjects_dir,subject_name,hemi,surf_name);
      mris = MRISread(fname) ;
      if (!mris)
        ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                  Progname, fname) ;
      MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ;
      if (strchr(curv_name, '/') != NULL)
        strcpy(fname, curv_name) ;  /* full path specified */
      else
        sprintf(fname,"%s/%s/surf/%s.%s",
                subjects_dir,subject_name,hemi,curv_name);
      if (MRISreadCurvatureFile(mris, fname) != NO_ERROR)
        ErrorExit(Gerror,"%s: could no read curvature file %s",Progname,fname);
      mrisp = MRIStoParameterization(mris, NULL, 1, 0) ;
      MRISfree(&mris) ;

      sprintf(fname, "%s/%s/surf/%s.%s",
              subjects_dir,output_subject,hemi,surf_name);
      mris = MRISread(fname) ;
      if (!mris)
        ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                  Progname, fname) ;
      MRISfromParameterization(mrisp, mris, 0) ;
      if (area)
        MRISmaskNotLabel(mris, area) ;
      curvs = (n < num_class1) ? c1_thickness[n] : c2_thickness[n-num_class1] ;
      class_mean = (n < num_class1) ? c1_mean : c2_mean ;
      class_var = (n < num_class1) ? c1_var : c2_var ;
      MRISextractCurvatureVector(mris, curvs) ;
      cvector_accumulate(curvs, total_mean, nvertices) ;
      cvector_accumulate(curvs, class_mean, nvertices) ;
      cvector_accumulate_square(curvs, class_var, nvertices) ;
      MRISPfree(&mrisp) ;
      MRISfree(&mris) ;
    }
  }

  /* compute within-group means, and total mean */
  cvector_normalize(total_mean, num_class1+num_class2, nvertices) ;
  cvector_normalize(c1_mean, num_class1, nvertices) ;
  cvector_normalize(c2_mean, num_class2, nvertices) ;
  cvector_compute_variance(c1_var, c1_mean, num_class1, nvertices) ;
  cvector_compute_variance(c2_var, c2_mean, num_class2, nvertices) ;
  cvector_compute_t_test(c1_mean, c1_var, c2_mean, c2_var,
                         num_class1, num_class2, pvals, nvertices) ;

  sprintf(fname, "%s/%s/surf/%s.%s",
          subjects_dir,output_subject,hemi,surf_name);
  fprintf(stderr, "reading output surface %s...\n", fname) ;
  mris = MRISread(fname) ;
  if (!mris)
    ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
              Progname, fname) ;

  if (area)
    MRISripNotLabel(mris, area) ;
  vbest_snr = cvector_alloc(nvertices) ;
  vbest_pvalues = cvector_alloc(nvertices) ;
  vbest_avgs = cvector_alloc(nvertices) ;
  vtotal_var = cvector_alloc(nvertices) ;
  vsnr = cvector_alloc(nvertices) ;

  if (read_dir == NULL)  /* recompute everything */
  {
    if (use_buggy_snr)
      cvector_multiply_variances(c1_var, c2_var, num_class1, num_class2,
                                 vtotal_var, nvertices) ;
    else
      cvector_add_variances(c1_var, c2_var, num_class1, num_class2,
                            vtotal_var, nvertices) ;
    if (use_no_distribution)
      snr = cvector_compute_dist_free_snr(c1_thickness, num_class1,
                                          c2_thickness, num_class2,
                                          c1_mean, c2_mean,
                                          vsnr, nvertices, &i);
    else
      snr = cvector_compute_snr(c1_mean, c2_mean, vtotal_var, vsnr, nvertices,
                                &i, 0.0f);
    fprintf(stderr,
            "raw SNR %2.2f, n=%2.4f, d=%2.4f, vno=%d\n",
            sqrt(snr), c1_mean[i]-c2_mean[i], sqrt(vtotal_var[i]), i) ;
    max_snr = snr ;
    max_snr_avgs = 0 ;
    cvector_track_best_snr(vsnr, vbest_snr, vbest_avgs, 0, nvertices) ;

    for (n = 0 ; n < num_class1 ; n++)
      cvector_copy(c1_thickness[n], c1_avg_thickness[n], nvertices) ;
    for (n = 0 ; n < num_class2 ; n++)
      cvector_copy(c2_thickness[n], c2_avg_thickness[n], nvertices) ;

    /* now incrementally average the data, keeping track of the best
       snr at each location, and at what scale it occurred. vbest_avgs
       and vbest_snr will contain the scale and the snr at that scale.
    */
    for (avgs = 1 ; avgs <= max_avgs ; avgs++) {
      /* c?_avg_thickness is the thickness at the current scale */
      if (!(avgs % 50))
        fprintf(stderr, "testing %d averages...\n", avgs) ;
      cvector_clear(c1_mean, nvertices) ;
      cvector_clear(c2_mean, nvertices) ;
      cvector_clear(c1_var, nvertices) ;
      cvector_clear(c2_var, nvertices) ;
      cvector_clear(total_mean, nvertices) ;
      for (n = 0 ; n < num_class1 ; n++) {
        MRISimportCurvatureVector(mris, c1_avg_thickness[n]) ;
        MRISaverageCurvatures(mris, 1) ;
        MRISextractCurvatureVector(mris, c1_avg_thickness[n]) ;
        cvector_accumulate(c1_avg_thickness[n], total_mean, nvertices) ;
        cvector_accumulate(c1_avg_thickness[n], c1_mean, nvertices) ;
        cvector_accumulate_square(c1_avg_thickness[n], c1_var, nvertices) ;
      }
      for (n = 0 ; n < num_class2 ; n++) {
        MRISimportCurvatureVector(mris, c2_avg_thickness[n]) ;
        MRISaverageCurvatures(mris, 1) ;
        MRISextractCurvatureVector(mris, c2_avg_thickness[n]) ;
        cvector_accumulate(c2_avg_thickness[n], total_mean, nvertices) ;
        cvector_accumulate(c2_avg_thickness[n], c2_mean, nvertices) ;
        cvector_accumulate_square(c2_avg_thickness[n], c2_var, nvertices) ;
      }
      cvector_normalize(total_mean, num_class1+num_class2, nvertices) ;
      cvector_normalize(c1_mean, num_class1, nvertices) ;
      cvector_normalize(c2_mean, num_class2, nvertices) ;
      cvector_compute_variance(c1_var, c1_mean, num_class1, nvertices) ;
      cvector_compute_variance(c2_var, c2_mean, num_class2, nvertices) ;
      if (use_buggy_snr)
        cvector_multiply_variances(c1_var, c2_var, num_class1, num_class2,
                                   vtotal_var, nvertices) ;
      else
        cvector_add_variances(c1_var, c2_var, num_class1, num_class2,
                              vtotal_var, nvertices) ;
      if (use_no_distribution)
        snr =
          cvector_compute_dist_free_snr(c1_avg_thickness,num_class1,
                                        c2_avg_thickness, num_class2, c1_mean,
                                        c2_mean, vsnr, nvertices, &i);
      else
        snr =
          cvector_compute_snr(c1_mean, c2_mean, vtotal_var, vsnr, nvertices,&i,
                              bonferroni ? log((double)avgs) : 0.0f);
      if (write_flag && DIAG_VERBOSE_ON) {
        fprintf(fp, "%d %2.1f  %2.2f %2.2f %2.2f ",
                avgs, sqrt((float)avgs), sqrt(snr), c1_mean[i]-c2_mean[i],
                sqrt(vtotal_var[i])) ;
        fflush(fp) ;
        for (n = 0 ; n < num_class1 ; n++)
          fprintf(fp, "%2.2f ", c1_avg_thickness[n][i]) ;
        for (n = 0 ; n < num_class2 ; n++)
          fprintf(fp, "%2.2f ", c2_avg_thickness[n][i]) ;
        fprintf(fp, "\n") ;
        fclose(fp) ;
      }
      if (snr > max_snr) {
        fprintf(stderr,
                "new max SNR found at avgs=%d (%2.1f mm)=%2.1f, n=%2.4f, "
                "d=%2.4f, vno=%d\n",
                avgs, sqrt((float)avgs), sqrt(snr), c1_mean[i]-c2_mean[i],
                sqrt(vtotal_var[i]), i) ;
        max_snr = snr ;
        max_snr_avgs = avgs ;
      }
      cvector_track_best_snr(vsnr, vbest_snr, vbest_avgs, avgs, nvertices) ;
    }
    if (compute_stats)
      cvector_compute_t(vbest_snr, vbest_pvalues,num_class1+num_class2,
                        nvertices) ;
    printf("max snr=%2.2f at %d averages\n", max_snr, max_snr_avgs) ;
    if (write_flag) {
      MRISimportValVector(mris, vbest_snr) ;
      sprintf(fname, "./%s.%s_best_snr", hemi,prefix) ;
      MRISwriteValues(mris, fname) ;
      MRISimportValVector(mris, vbest_avgs) ;
      sprintf(fname, "./%s.%s_best_avgs", hemi, prefix) ;
      MRISwriteValues(mris, fname) ;
      if (compute_stats) {
        MRISimportValVector(mris, vbest_pvalues) ;
        sprintf(fname, "./%s.%s_best_pval", hemi,prefix) ;
        MRISwriteValues(mris, fname) ;
      }
    }
  }
  else  /* read from directory containing precomputed optimal values */
  {
    sprintf(fname, "%s/%s.%s_best_snr", read_dir, hemi, prefix) ;
    if (MRISreadValues(mris, fname) != NO_ERROR)
      ErrorExit(Gerror, "%s: MRISreadValues(%s) failed",Progname,fname) ;
    MRISexportValVector(mris, vbest_snr) ;

    sprintf(fname, "%s/%s.%s_best_avgs", read_dir, hemi, prefix) ;
    if (MRISreadValues(mris, fname) != NO_ERROR)
      ErrorExit(Gerror, "%s: MRISreadValues(%s) failed",Progname,fname) ;
    MRISexportValVector(mris, vbest_avgs) ;
  }

  if (write_dir) {
    sprintf(fname, "%s/%s.%s_best_snr", write_dir, hemi,prefix) ;
    MRISimportValVector(mris, vbest_snr) ;
    if (MRISwriteValues(mris, fname) != NO_ERROR)
      ErrorExit(Gerror, "%s: MRISwriteValues(%s) failed",Progname,fname) ;

    sprintf(fname, "%s/%s.%s_best_avgs", write_dir, hemi, prefix) ;
    MRISimportValVector(mris, vbest_avgs) ;
    if (MRISwriteValues(mris, fname) != NO_ERROR)
      ErrorExit(Gerror, "%s: MRISwriteValues(%s) failed",Progname,fname) ;
  }

  if (nsort < -1)
    nsort = mris->nvertices ;

  if (nsort <= 0) {
    nlabels = 0 ;
    current_min_label_area = min_label_area ;
    for (done = 0, current_fthresh = fthresh ;
         !FZERO(current_fthresh) && !done ;
         current_fthresh *= 0.95) {
      int   npos_labels, nneg_labels ;
      LABEL **pos_labels, **neg_labels ;

      for (current_min_label_area = min_label_area ;
           current_min_label_area > 0.5 ;
           current_min_label_area *= 0.75) {
        MRISclearMarks(mris) ;
        sprintf(fname, "%s-%s_thickness", hemi, prefix ? prefix : "") ;
        mark_thresholded_vertices(mris, vbest_snr, vbest_avgs,current_fthresh);
        segment_and_write_labels(output_subject, fname, mris,
                                 &pos_labels, &npos_labels, 0,
                                 current_min_label_area) ;
        MRISclearMarks(mris) ;
        mark_thresholded_vertices(mris, vbest_snr,vbest_avgs,-current_fthresh);
        segment_and_write_labels(output_subject, fname, mris, &neg_labels,
                                 &nneg_labels, npos_labels,
                                 current_min_label_area) ;

        nlabels = nneg_labels + npos_labels ;
        if (nlabels) {
          labels = (LABEL **)calloc(nlabels, sizeof(LABEL *)) ;
          for (i = 0 ; i < npos_labels ; i++)
            labels[i] = pos_labels[i] ;
          for (i = 0 ; i < nneg_labels ; i++)
            labels[i+npos_labels] = neg_labels[i] ;
          free(pos_labels) ;
          free(neg_labels) ;
        }
        done = (nlabels >= min_labels) ;
        if (done)  /* found enough points */
          break ;

        /* couldn't find enough  points - free stuff and try again */
        for (i = 0 ; i < nlabels ; i++)
          LabelFree(&labels[i]) ;
        if (nlabels)
          free(labels) ;
#if 0
        fprintf(stderr,"%d labels found (min %d), reducing constraints...\n",
                nlabels, min_labels) ;
#endif
      }
    }

    printf("%d labels found with F > %2.1f and area > %2.0f\n",
           nlabels, current_fthresh, current_min_label_area) ;
    for (i = 0 ; i < nlabels ; i++)
      fprintf(stderr, "label %d: %d points, %2.1f mm\n",
              i, labels[i]->n_points, LabelArea(labels[i], mris)) ;
  }

  /* read or compute thickness at optimal scale and put it into
     c?_avg_thickness.
  */
  if (!read_dir) {
    fprintf(stderr, "extracting thickness at optimal scale...\n") ;

    /* now build feature vectors for each subject */
    extract_thickness_at_best_scale(mris, c1_avg_thickness, vbest_avgs,
                                    c1_thickness, nvertices, num_class1);
    fprintf(stderr, "extracting thickness for class 2...\n") ;
    extract_thickness_at_best_scale(mris, c2_avg_thickness, vbest_avgs,
                                    c2_thickness, nvertices, num_class2);
  } else  /* read in precomputed optimal thicknesses */
  {
    char fname[STRLEN] ;

    fprintf(stderr, "reading precomputed thickness vectors\n") ;
    for (n = 0 ; n < num_class1 ; n++) {
      sprintf(fname, "%s/%s.%s", read_dir, hemi, argv[ARGV_OFFSET+n]) ;
      fprintf(stderr, "reading thickness vector from %s...\n", fname) ;
      if (MRISreadValues(mris, fname) != NO_ERROR)
        ErrorExit(Gerror, "%s: could not read thickness file %s",
                  Progname,fname) ;
      MRISexportValVector(mris, c1_avg_thickness[n]) ;
    }
    for (n = 0 ; n < num_class2 ; n++) {
      sprintf(fname, "%s/%s.%s", read_dir, hemi,
              argv[n+num_class1+1+ARGV_OFFSET]) ;
      fprintf(stderr, "reading curvature vector from %s...\n", fname) ;
      if (MRISreadValues(mris, fname) != NO_ERROR)
        ErrorExit(Gerror, "%s: could not read thickness file %s",
                  Progname,fname) ;
      MRISexportValVector(mris, c2_avg_thickness[n]) ;
    }
  }

  if (write_dir)   /* write out optimal thicknesses */
  {
    char fname[STRLEN] ;

    for (n = 0 ; n < num_class1 ; n++) {
      sprintf(fname, "%s/%s.%s", write_dir, hemi, argv[ARGV_OFFSET+n]) ;
      fprintf(stderr, "writing curvature vector to %s...\n", fname) ;
      MRISimportValVector(mris, c1_avg_thickness[n]) ;
      MRISwriteValues(mris, fname) ;
    }
    for (n = 0 ; n < num_class2 ; n++) {
      sprintf(fname, "%s/%s.%s", write_dir, hemi,
              argv[n+num_class1+1+ARGV_OFFSET]) ;
      fprintf(stderr, "writing curvature vector to %s...\n", fname) ;
      MRISimportValVector(mris, c2_avg_thickness[n]) ;
      MRISwriteValues(mris, fname) ;
    }
  }


  /* should free c?_thickness here */

  if (nsort <= 0) {
    /* We have the thickness values at the most powerful scale stored for
       each subject in the c1_avg_thickness and c2_avg_thickness vectors.
       Now collapse them across each label and build  feature vector for
       classification.
    */
    c1_label_thickness = (double **)calloc(num_class1, sizeof(double *)) ;
    c2_label_thickness = (double **)calloc(num_class2, sizeof(double *)) ;
    for (n = 0 ; n < num_class1 ; n++)
      c1_label_thickness[n] = (double *)calloc(nlabels, sizeof(double)) ;
    for (n = 0 ; n < num_class2 ; n++)
      c2_label_thickness[n] = (double *)calloc(nlabels, sizeof(double)) ;

    fprintf(stderr, "collapsing thicknesses within labels for class 1\n") ;
    for (n = 0 ; n < num_class1 ; n++)
      for (i = 0 ; i < nlabels ; i++)
        c1_label_thickness[n][i] =
          cvector_average_in_label(c1_avg_thickness[n], labels[i], nvertices) ;
    fprintf(stderr, "collapsing thicknesses within labels for class 2\n") ;
    for (n = 0 ; n < num_class2 ; n++)
      for (i = 0 ; i < nlabels ; i++)
        c2_label_thickness[n][i] =
          cvector_average_in_label(c2_avg_thickness[n], labels[i], nvertices) ;
    sprintf(fname, "%s_%s_class1.dat", hemi,prefix) ;
    fprintf(stderr, "writing class 1 info to %s...\n", fname) ;
    fp = fopen(fname, "w") ;
    for (i = 0 ; i < nlabels ; i++)  /* for each row */
    {
      for (n = 0 ; n < num_class1 ; n++)  /* for each column */
        fprintf(fp, "%2.2f  ", c1_label_thickness[n][i]) ;
      fprintf(fp, "\n") ;
    }
    fclose(fp) ;

    sprintf(fname, "%s_%s_class2.dat", hemi,prefix) ;
    fprintf(stderr, "writing class 2 info to %s...\n", fname) ;
    fp = fopen(fname, "w") ;
    for (i = 0 ; i < nlabels ; i++) {
      for (n = 0 ; n < num_class2 ; n++)
        fprintf(fp, "%2.2f  ", c2_label_thickness[n][i]) ;
      fprintf(fp, "\n") ;
    }
    fclose(fp) ;
  } else {
    sorted_indices = cvector_sort(vbest_snr, nvertices) ;
    vno = sorted_indices[0] ;
    write_vertex_data("c1.dat", vno, c1_avg_thickness,num_class1);
    write_vertex_data("c2.dat", vno, c2_avg_thickness,num_class2);
    printf("sorting complete\n") ;

    /* re-write class means at these locations */
    sprintf(fname, "%s_%s_class1.dat", hemi,prefix) ;
    fprintf(stderr, "writing class 1 info to %s...\n", fname) ;
    fp = fopen(fname, "w") ;
    for (i = 0 ; i < nsort ; i++) {
      for (n = 0 ; n < num_class1 ; n++)
        fprintf(fp, "%2.2f  ", c1_avg_thickness[n][sorted_indices[i]]) ;
      fprintf(fp, "\n") ;
    }
    fclose(fp) ;
    sprintf(fname, "%s_%s_class2.dat", hemi,prefix) ;
    fprintf(stderr, "writing class 2 info to %s...\n", fname) ;
    fp = fopen(fname, "w") ;
    for (i = 0 ; i < nsort ; i++) {
      for (n = 0 ; n < num_class2 ; n++)
        fprintf(fp, "%2.2f  ", c2_avg_thickness[n][sorted_indices[i]]) ;
      fprintf(fp, "\n") ;
    }
    fclose(fp) ;
  }

  if (test_subject) {
    test_thickness = cvector_alloc(nvertices) ;
    test_avg_thickness = cvector_alloc(nvertices) ;
    MRISfree(&mris) ;
    fprintf(stderr, "reading subject %s\n", test_subject) ;
    sprintf(fname, "%s/%s/surf/%s.%s",
            subjects_dir,test_subject,hemi,surf_name);
    mris = MRISread(fname) ;
    if (!mris)
      ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                Progname, fname) ;
    MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ;
    if (strchr(curv_name, '/') != NULL)
      strcpy(fname, curv_name) ;  /* full path specified */
    else
      sprintf(fname,"%s/%s/surf/%s.%s",
              subjects_dir,test_subject,hemi,curv_name);
    if (MRISreadCurvatureFile(mris, fname) != NO_ERROR)
      ErrorExit(Gerror,"%s: could no read curvature file %s",Progname,fname);
    mrisp = MRIStoParameterization(mris, NULL, 1, 0) ;
    MRISfree(&mris) ;

    sprintf(fname, "%s/%s/surf/%s.%s",
            subjects_dir,output_subject,hemi,surf_name);
    mris = MRISread(fname) ;
    if (!mris)
      ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                Progname, fname) ;
    MRISfromParameterization(mrisp, mris, 0) ;
    if (area)
      MRISmaskNotLabel(mris, area) ;
    MRISextractCurvatureVector(mris, test_thickness) ;
    for (avgs = 0 ; avgs <= max_avgs ; avgs++) {
      cvector_extract_best_avg(vbest_avgs, test_thickness,test_avg_thickness,
                               avgs-1, nvertices) ;
      MRISimportCurvatureVector(mris, test_thickness) ;
      MRISaverageCurvatures(mris, 1) ;
      MRISextractCurvatureVector(mris, test_thickness) ;
    }

    if (nsort <= 0) {
      sprintf(fname, "%s_%s.dat", hemi,test_subject) ;
      fprintf(stderr, "writing test subject feature vector to %s...\n",
              fname) ;
      fp = fopen(fname, "w") ;
      for (i = 0 ; i < nlabels ; i++)  /* for each row */
      {
        label_avg =
          cvector_average_in_label(test_avg_thickness, labels[i], nvertices) ;
        fprintf(fp, "%2.2f\n", label_avg) ;
      }
      fclose(fp) ;
    } else   /* use sorting instead of connected areas */
    {
      double classification, offset, w ;
      int    total_correct, total_wrong, first_wrong, vno ;


      sprintf(fname, "%s_%s.dat", hemi,test_subject) ;
      fprintf(stderr, "writing test subject feature vector to %s...\n",
              fname) ;
      fp = fopen(fname, "w") ;

      first_wrong = -1 ;
      total_wrong = total_correct = 0 ;
      for (i = 0 ; i < nsort ; i++) {
        vno = sorted_indices[i] ;
        fprintf(fp, "%2.2f\n ", test_avg_thickness[sorted_indices[i]]) ;
        offset = (c1_mean[vno]+c2_mean[vno])/2.0 ;
        w = (c1_mean[vno]-c2_mean[vno]) ;
        classification = (test_avg_thickness[vno] - offset) * w ;

        if (((classification < 0) && (true_class == 1)) ||
            ((classification > 0) && (true_class == 2))) {
          total_wrong++ ;
          if (first_wrong < 0)
            first_wrong = i ;
        } else
          total_correct++ ;
      }
      fclose(fp) ;
      fprintf(stderr, "%d of %d correct = %2.1f%% (first wrong %d (%d)),"
              "min snr=%2.1f\n",
              total_correct, total_correct+total_wrong,
              100.0*total_correct / (total_correct+total_wrong),
              first_wrong, first_wrong >= 0 ? sorted_indices[first_wrong]:-1,
              vbest_snr[sorted_indices[nsort-1]]) ;

      if (first_wrong >= 0) {
        write_vertex_data("c1w.dat", sorted_indices[first_wrong],
                          c1_avg_thickness,num_class1);
        write_vertex_data("c2w.dat", sorted_indices[first_wrong],
                          c2_avg_thickness,num_class2);
      }
    }
  }

  msec = TimerStop(&start) ;
  free(total_mean);
  free(c1_mean) ;
  free(c2_mean) ;
  free(c1_var);
  free(c2_var);
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  fprintf(stderr, "classification took %d minutes and %d seconds.\n",
          minutes, seconds) ;
  exit(0) ;
  return(0) ;  /* for ansi */
}
Exemple #4
0
int
main(int argc, char *argv[]) {
  char         *cp, **av, *in_fname, fname[100], path[100],
  name[100], hemi[100] ;
  int          ac, nargs ;

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

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

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

  if (argc < 2)
    usage_exit() ;

  in_fname = argv[1] ;
#if 0
  out_fname = argv[2] ;
  cp = strrchr(out_fname, '.') ;
#endif

  if (patch_flag)   /* read in orig surface before reading in patch */
  {
    FileNamePath(in_fname, path) ;
    FileNameOnly(in_fname, name) ;
    cp = strchr(name, '.') ;
    if (cp) {
      strncpy(hemi, cp-2, 2) ;
      hemi[2] = 0 ;
    } else
      strcpy(hemi, "lh") ;
    sprintf(fname, "%s/%s.smoothwm", path, hemi) ;
    mris = MRISread(fname) ;
    if (!mris)
      ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                Progname, fname) ;
    FileNameOnly(in_fname, name) ;
    MRISstoreMetricProperties(mris) ;
    MRISsaveVertexPositions(mris, ORIGINAL_VERTICES) ;
    if (MRISreadPatch(mris, name) != NO_ERROR)
      ErrorExit(ERROR_NOFILE, "%s: could not read patch file %s",
                Progname, name) ;
  } else {
    mris = MRISread(in_fname) ;
    if (!mris)
      ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                Progname, in_fname) ;

    MRISreadOriginalProperties(mris, "smoothwm") ;
  }

  MRISsaveVertexPositions(mris, TMP_VERTICES) ;
  MRISrestoreVertexPositions(mris, ORIGINAL_VERTICES) ;
  MRISsampleAtEachDistance(mris, nbhd_size, max_nbrs) ;
  MRIScomputeMetricProperties(mris) ;
  MRISstoreMetricProperties(mris) ;

  MRISrestoreVertexPositions(mris, TMP_VERTICES) ;
  MRIScomputeMetricProperties(mris) ;

  MRIScomputeDistanceErrors(mris, nbhd_size, max_nbrs) ;
#if 0
  if (write_flag) {
    MRISareaErrors(mris) ;
    MRISangleErrors(mris) ;
  }

  if (area_flag) {
    sprintf(fname, "%s.area_error", in_fname) ;
    printf("writing area errors to %s\n", fname) ;
    MRISwriteAreaError(mris, fname) ;
    sprintf(fname, "%s.angle_error", in_fname) ;
    printf("writing angle errors to %s\n", fname) ;
    MRISwriteAngleError(mris, fname) ;
  }
#else
  sprintf(fname, "%s.distance_error", in_fname) ;
  fprintf(stderr, "writing errors to %s\n", fname) ;
  MRISwriteValues(mris, fname) ;
#endif

  MRISfree(&mris) ;

  exit(0) ;
  return(0) ;  /* for ansi */
}