static int
normalize_timepoints_with_samples(MRI *mri, GCA_SAMPLE *gcas, int nsamples, int nsoap)
{
  int   frame, i, x, y, z ;
  double target, val ;
  MRI    *mri_ctrl, *mri_bias, *mri_target, *mri_frame ;

  mri_ctrl = MRIcloneDifferentType(mri, MRI_UCHAR) ;
  mri_bias = MRIcloneDifferentType(mri, MRI_FLOAT) ;
  mri_target = MRIcloneDifferentType(mri, MRI_FLOAT) ;

  for (i = 0 ; i < nsamples ; i++)
  {
    if (i == Gdiag_no)
      DiagBreak() ;
    x = nint(gcas[i].x)  ; y = nint(gcas[i].y) ; z = nint(gcas[i].z) ;
    MRIsetVoxVal(mri_ctrl, x, y, z, 0, CONTROL_MARKED) ;
    for (target = 0.0, frame = 0 ; frame < mri->nframes ; frame++)
      target += MRIgetVoxVal(mri, x, y, z, frame) ;
    target /= mri->nframes ;
    MRIsetVoxVal(mri_target, x, y, z, 0, target) ;
  }

  // build a bias correction for each time point (which each has its own frame)
  for (frame = 0 ; frame < mri->nframes ; frame++)
  {
    MRIclear(mri_bias) ; 
    for (i = 0 ; i < nsamples ; i++)
    {
      if (i == Gdiag_no)
        DiagBreak() ;
      x = nint(gcas[i].x)  ; y = nint(gcas[i].y) ; z = nint(gcas[i].z) ;
      target = MRIgetVoxVal(mri_target, x, y, z, 0) ;
      val = MRIgetVoxVal(mri, x, y, z, frame) ;
      if (FZERO(val))
        val = 1.0 ;
      MRIsetVoxVal(mri_bias, x, y, z, 0, target/val) ;
    }
    MRIbuildVoronoiDiagram(mri_bias, mri_ctrl, mri_bias) ;
    MRIsoapBubble(mri_bias, mri_ctrl, mri_bias, nsoap) ;
    mri_frame = MRIcopyFrame(mri, NULL, frame, 0) ;
    MRImultiply(mri_frame, mri_bias, mri_frame) ;
    if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    {
      char fname[STRLEN] ;
      sprintf(fname, "frame%d.mgz", frame) ;
      MRIwrite(mri_frame, fname) ;
      sprintf(fname, "bias%d.mgz", frame) ;
      MRIwrite(mri_bias, fname) ;
      sprintf(fname, "target%d.mgz", frame) ;
      MRIwrite(mri_target, fname) ;
    }
    MRIcopyFrame(mri_frame, mri, 0, frame) ;
  }
  MRIfree(&mri_bias) ; MRIfree(&mri_target) ; MRIfree(&mri_ctrl) ;
  return(NO_ERROR) ;
}
static int
normalize_timepoints(MRI *mri, double thresh, double cross_time_sigma)
{
  int   frame, x, y, z, skip, nvox ;
  double target, val ;
  MRI    *mri_ctrl, *mri_bias, *mri_target, *mri_frame, *mri_kernel ;

  mri_ctrl = MRIcloneDifferentType(mri, MRI_UCHAR) ;
  mri_bias = MRIcloneDifferentType(mri, MRI_FLOAT) ;
  mri_target = MRIcloneDifferentType(mri, MRI_FLOAT) ;
  mri_kernel = MRIgaussian1d(cross_time_sigma, -1) ;

  for (nvox = x = 0 ; x < mri->width ; x++)
    for (y = 0 ; y < mri->height ; y++)
      for (z = 0 ; z < mri->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
          DiagBreak() ;
        for (target = 0.0, frame = 0 ; frame < mri->nframes ; frame++)
          target += MRIgetVoxVal(mri, x, y, z, frame) ;
        target /= mri->nframes ;
        if (FZERO(target))
          continue ;  // both vals  0
        skip = 0 ;
        for (frame = 0 ; frame < mri->nframes ; frame++)
        {
          val = MRIgetVoxVal(mri, x, y, z, frame) ;
          if (fabs(val-target) > thresh)
          {
            skip = 1 ;
            break ;
          }
        }
        if (skip)
          continue ;
        nvox++ ;
        MRIsetVoxVal(mri_ctrl, x, y, z, 0, CONTROL_MARKED) ;
        MRIsetVoxVal(mri_target, x, y, z, 0, target) ;
      }

  printf("%d voxels found to base intensity correction on\n", nvox) ;

  // build a bias correction for each time point (which each has its own frame)
  for (frame = 0 ; frame < mri->nframes ; frame++)
  {
    MRIclear(mri_bias) ; 
    for (x = 0 ; x < mri->width ; x++)
      for (y = 0 ; y < mri->height ; y++)
        for (z = 0 ; z < mri->depth ; z++)
        {
          target = MRIgetVoxVal(mri_target, x, y, z, 0) ;
          val = MRIgetVoxVal(mri, x, y, z, frame) ;
          if (FZERO(val))
            val = 1.0 ;
          MRIsetVoxVal(mri_bias, x, y, z, 0, target/val) ;
        }
    MRIbuildVoronoiDiagram(mri_bias, mri_ctrl, mri_bias) ;
    MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ;
    //    MRIsoapBubble(mri_bias, mri_ctrl, mri_bias, nsoap) ;
    mri_frame = MRIcopyFrame(mri, NULL, frame, 0) ;
    MRImultiply(mri_frame, mri_bias, mri_frame) ;
    if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    {
      char fname[STRLEN] ;
      sprintf(fname, "frame%d.mgz", frame) ;
      MRIwrite(mri_frame, fname) ;
      sprintf(fname, "bias%d.mgz", frame) ;
      MRIwrite(mri_bias, fname) ;
      sprintf(fname, "target%d.mgz", frame) ;
      MRIwrite(mri_target, fname) ;
    }
    MRIcopyFrame(mri_frame, mri, 0, frame) ;
  }
  MRIfree(&mri_bias) ; MRIfree(&mri_kernel) ; MRIfree(&mri_target) ; MRIfree(&mri_ctrl) ;
  return(NO_ERROR) ;
}
/* Actually no need to modify this function, since I will only use the float
 * type here, so the roundoff I added will never take effect.
 * What I need to modify is the MRIchangeType function!
 */
MRI *MRIlinearTransformInterpBSpline(MRI *mri_src, MRI *mri_dst, MATRIX *mA,
                                     int splinedegree)
{
  int    y1, y2, y3, width, height, depth ;
  VECTOR *v_X, *v_Y ;   /* original and transformed coordinate systems */
  MATRIX *mAinv ;     /* inverse of mA */
  double   val, x1, x2, x3 ;
  MRI *mri_Bcoeff;

  mAinv = MatrixInverse(mA, NULL) ;      /* will sample from dst back to src */
  if (!mAinv)
    ErrorReturn(NULL, (ERROR_BADPARM,
                       "MRIlinearTransformBSpline: xform is singular")) ;

  if (!mri_dst) mri_dst = MRIclone(mri_src, NULL) ;
  else          MRIclear(mri_dst) ; /* set all values to zero */

  if (mri_src->type != MRI_FLOAT)
    mri_Bcoeff = MRIchangeType(mri_src, MRI_FLOAT, 0, 1.0, 1);
  else
    mri_Bcoeff = MRIcopy(mri_src, NULL);

  /* convert between a representation based on image samples */
  /* and a representation based on image B-spline coefficients */
  if (SamplesToCoefficients(mri_Bcoeff, splinedegree))
  {
    ErrorReturn(NULL, (ERROR_BADPARM, "Change of basis failed\n"));
  }

  printf("Direct B-spline Transform Finished. \n");

  width = mri_src->width ;
  height = mri_src->height ;
  depth = mri_src->depth ;
  v_X = VectorAlloc(4, MATRIX_REAL) ;  /* input (src) coordinates */
  v_Y = VectorAlloc(4, MATRIX_REAL) ;  /* transformed (dst) coordinates */

  v_Y->rptr[4][1] = 1.0f ;
  for (y3 = 0 ; y3 < mri_dst->depth ; y3++)
  {
    V3_Z(v_Y) = y3 ;
    for (y2 = 0 ; y2 < mri_dst->height ; y2++)
    {
      V3_Y(v_Y) = y2 ;
      for (y1 = 0 ; y1 < mri_dst->width ; y1++)
      {
        V3_X(v_Y) = y1 ;
        MatrixMultiply(mAinv, v_Y, v_X) ;

        x1 = V3_X(v_X) ;
        x2 = V3_Y(v_X) ;
        x3 = V3_Z(v_X) ;

        if (x1 <= -0.5 || x1 >= (width - 0.5) || x2 <= -0.5 ||
            x2 >= (height - 0.5) || x3 <= -0.5 || x3 >= (depth-0.5))
          val = 0.0;
        else
          val = InterpolatedValue(mri_Bcoeff, x1, x2, x3, splinedegree);

        switch (mri_dst->type)
        {
        case MRI_UCHAR:
          if (val <-0.5) val = -0.5;
          if (val > 254.5) val = 254.5;
          MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val+0.5) ;
          break ;
        case MRI_SHORT:
          MRISvox(mri_dst,y1,y2,y3) = (short)nint(val+0.5) ;
          break ;
        case MRI_FLOAT:
          MRIFvox(mri_dst,y1,y2,y3) = (float)(val) ;
          break ;
        case MRI_INT:
          MRIIvox(mri_dst,y1,y2,y3) = nint(val+0.5) ;
          break ;
        default:
          ErrorReturn(NULL,
                      (ERROR_UNSUPPORTED,
                       "MRIlinearTransformBSpline: unsupported dst type %d",
                       mri_dst->type)) ;
          break ;
        }
      }
    }
  }

  MatrixFree(&v_X) ;
  MatrixFree(&mAinv) ;
  MatrixFree(&v_Y) ;

  MRIfree(&mri_Bcoeff);
  return(mri_dst) ;
}
static MRI *
MRIcomputeSurfaceDistanceIntensities(MRI_SURFACE *mris,  MRI *mri_ribbon, MRI *mri_aparc, MRI *mri, MRI *mri_aseg, int whalf) 
{
  MRI          *mri_features, *mri_binary, *mri_white_dist, *mri_pial_dist ;
  int          vno, ngm, outside_of_ribbon, label0, label, ohemi_label, xi, yi, zi, xk, yk, zk, x0, y0, z0, hemi_label, assignable ;
  double       xv, yv, zv, step_size, dist, thickness, wdist, pdist, snx, sny, snz, nx, ny, nz, xl, yl, zl, x, y, z, dot, angle ;
  VERTEX       *v ;

  mri_features = MRIallocSequence(mris->nvertices, 1, 1, MRI_FLOAT, 1) ;  // one samples inwards, one in ribbon, and one outside
  MRIcopyHeader(mri, mri_features) ;

  mri_binary = MRIcopy(mri_ribbon, NULL) ;
  mri_binary = MRIbinarize(mri_ribbon, NULL, 1, 0, 1) ;
  mri_pial_dist = MRIdistanceTransform(mri_binary, NULL, 1, max_pial_dist+1, DTRANS_MODE_SIGNED,NULL);
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    MRIwrite(mri_pial_dist, "pd.mgz") ;

  MRIclear(mri_binary) ;
  MRIcopyLabel(mri_ribbon, mri_binary, Left_Cerebral_White_Matter) ;
  MRIcopyLabel(mri_ribbon, mri_binary, Right_Cerebral_White_Matter) ;
  MRIbinarize(mri_binary, mri_binary, 1, 0, 1) ;
  mri_white_dist = MRIdistanceTransform(mri_binary, NULL, 1, max_white_dist+1, DTRANS_MODE_SIGNED,NULL);
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    MRIwrite(mri_white_dist, "wd.mgz") ;

  if (mris->hemisphere == LEFT_HEMISPHERE)
  {
    ohemi_label = Right_Cerebral_Cortex ;
    hemi_label = Left_Cerebral_Cortex ;
  }
  else
  {
    hemi_label = Right_Cerebral_Cortex ;
    ohemi_label = Left_Cerebral_Cortex ;
  }

  step_size = mri->xsize/2 ;
  for (vno = 0 ; vno < mris->nvertices ; vno++)
  {
    v = &mris->vertices[vno] ;
    if (vno == Gdiag_no)
      DiagBreak() ;
    if (v->ripflag)
      continue ;  // not cortex
    nx = v->pialx - v->whitex ; ny = v->pialy - v->whitey ; nz = v->pialz - v->whitez ;
    thickness = sqrt(nx*nx + ny*ny + nz*nz) ;
    if (FZERO(thickness))
      continue ;   // no  cortex here


    x = (v->pialx + v->whitex)/2 ; y = (v->pialy + v->whitey)/2 ; z = (v->pialz + v->whitez)/2 ;  // halfway between white and pial is x0
    MRISsurfaceRASToVoxelCached(mris, mri_aseg, x, y, z, &xl, &yl, &zl) ;
    x0 = nint(xl); y0 = nint(yl) ; z0 = nint(zl) ;
    label0 = MRIgetVoxVal(mri_aparc, x0, y0, z0,0) ;

    // compute surface normal in voxel coords
    MRISsurfaceRASToVoxelCached(mris, mri_aseg, x+v->nx, y+v->ny, z+v->nz, &snx, &sny, &snz) ;
    snx -= xl ; sny -= yl ; snz -= zl ;

    for (ngm = 0, xk = -whalf ; xk <= whalf ; xk++)
    {
      xi = mri_aseg->xi[x0+xk] ;
      for (yk = -whalf ; yk <= whalf ; yk++)
      {
	yi = mri_aseg->yi[y0+yk] ;
	for (zk = -whalf ; zk <= whalf ; zk++)
	{
	  zi = mri_aseg->zi[z0+zk] ;
	  label = MRIgetVoxVal(mri_aseg, xi, yi, zi,0) ;
	  if (xi == Gx && yi == Gy && zi == Gz)
	    DiagBreak() ;
	  if (label != hemi_label)
	    continue ;
	  label = MRIgetVoxVal(mri_aparc, xi, yi, zi,0) ;
	  if (label && label != label0)  // if  outside the ribbon it won't be assigned to a parcel
	    continue ;  // constrain it to be in the same cortical parcel

	  // search along vector connecting x0 to this point to make sure it is we don't perforate wm or leave and re-enter cortex
	  nx = xi-x0 ; ny = yi-y0 ; nz = zi-z0 ;
	  thickness = sqrt(nx*nx + ny*ny + nz*nz) ;
	  assignable = 1 ;  // assume this point should be counted
	  if (thickness > 0)
	  {
	    nx /= thickness ; ny /= thickness ; nz /= thickness ;
	    dot = nx*snx + ny*sny + nz*snz ; angle = acos(dot) ;
	    if (FABS(angle) > angle_threshold)
	      assignable = 0 ;
	    outside_of_ribbon = 0 ;
	    for (dist = 0 ; assignable && dist <= thickness ; dist += step_size) 
	    {
	      xv = x0+nx*dist ;  yv = y0+ny*dist ;  zv = z0+nz*dist ; 
	      if (nint(xv) == Gx && nint(yv) == Gy && nint(zv) == Gz)
		DiagBreak() ;
	      MRIsampleVolume(mri_pial_dist, xv, yv, zv, &pdist) ;
	      MRIsampleVolume(mri_white_dist, xv, yv, zv, &wdist) ;
	      label = MRIgetVoxVal(mri_aseg, xi, yi, zi,0) ;
	      if (SKIP_LABEL(label) || label == ohemi_label)
		assignable = 0 ;
	      if (wdist < 0)  // entered wm - not assignable
		assignable = 0 ;
	      else
	      {
		if (pdist > 0)  // outside pial surface
		  outside_of_ribbon = 1 ;
		else
		{
		  if (outside_of_ribbon) // left ribbon and reentered
		    assignable = 0 ;
		}
	      }
	    }
	  }  // close of thickness > 0
	  if (assignable)
	    ngm++ ;
	  else
	    DiagBreak() ;
	}
      }
    }
    
    MRIsetVoxVal(mri_features, vno, 0, 0, 0, ngm) ;
  }

  MRIfree(&mri_white_dist) ; MRIfree(&mri_pial_dist) ; MRIfree(&mri_binary) ;
  return(mri_features) ;
}
static MRI *
MRIcomputeSurfaceDistanceProbabilities(MRI_SURFACE *mris,  MRI *mri_ribbon, MRI *mri, MRI *mri_aseg) 
{
  MRI          *mri_features, *mri_binary, *mri_white_dist, *mri_pial_dist, *mri_mask ;
  int          nwhite_bins, npial_bins, x, y, z, label, i ;
  HISTOGRAM2D *hw, *hp ; 
  float        pdist, wdist, val ;
  double       wval, pval ;

  mri_features = MRIallocSequence(mri->width, mri->height, mri->depth, MRI_FLOAT, 2) ;
  MRIcopyHeader(mri, mri_features) ;

  mri_binary = MRIcopy(mri_ribbon, NULL) ;
  mri_binary = MRIbinarize(mri_ribbon, NULL, 1, 0, 1) ;
  mri_pial_dist = MRIdistanceTransform(mri_binary, NULL, 1, max_pial_dist+1, DTRANS_MODE_SIGNED,NULL);
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    MRIwrite(mri_pial_dist, "pd.mgz") ;

  MRIclear(mri_binary) ;
  MRIcopyLabel(mri_ribbon, mri_binary, Left_Cerebral_White_Matter) ;
  MRIcopyLabel(mri_ribbon, mri_binary, Right_Cerebral_White_Matter) ;
  MRIbinarize(mri_binary, mri_binary, 1, 0, 1) ;
  mri_white_dist = MRIdistanceTransform(mri_binary, NULL, 1, max_white_dist+1, DTRANS_MODE_SIGNED,NULL);
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    MRIwrite(mri_white_dist, "wd.mgz") ;

  nwhite_bins = ceil((max_white_dist - min_white_dist) / white_bin_size)+1 ;
  npial_bins = ceil((max_pial_dist - min_pial_dist) / pial_bin_size)+1 ;
  hw = HISTO2Dalloc(NBINS, nwhite_bins) ;
  hp = HISTO2Dalloc(NBINS, npial_bins) ;

  HISTO2Dinit(hw, NBINS, nwhite_bins, 0, NBINS-1, min_white_dist, max_white_dist) ;
  HISTO2Dinit(hp, NBINS, npial_bins, 0, NBINS-1, min_pial_dist, max_pial_dist) ;

  for (x = 0 ; x < mri->width ; x++)
    for (y = 0 ; y < mri->height ; y++)
      for (z = 0 ; z < mri->depth ; z++)
      {
	label = MRIgetVoxVal(mri_aseg, x, y, z, 0) ;
	if (IS_CEREBELLUM(label) || IS_VENTRICLE(label) || label == Brain_Stem || IS_CC(label))
	  continue ;
	pdist = MRIgetVoxVal(mri_pial_dist, x, y, z, 0) ;
	wdist = MRIgetVoxVal(mri_pial_dist, x, y, z, 0) ;
	val  = MRIgetVoxVal(mri, x, y, z, 0) ;
	if (pdist >= min_pial_dist && pdist <= max_pial_dist)
	  HISTO2DaddSample(hp, val, pdist, 0, 0, 0, 0) ;
	if (wdist >= min_white_dist && wdist <= max_white_dist)
	  HISTO2DaddSample(hw, val, wdist, 0, 0, 0, 0) ;
      }
  HISTO2DmakePDF(hp, hp) ;
  HISTO2DmakePDF(hw, hw) ;
  for (x = 0 ; x < mri->width ; x++)
    for (y = 0 ; y < mri->height ; y++)
      for (z = 0 ; z < mri->depth ; z++)
      {
	label = MRIgetVoxVal(mri_aseg, x, y, z, 0) ;
	if (IS_CEREBELLUM(label) || IS_VENTRICLE(label) || label == Brain_Stem || IS_CC(label))
	  continue ;
	pdist = MRIgetVoxVal(mri_pial_dist, x, y, z, 0) ;
	wdist = MRIgetVoxVal(mri_pial_dist, x, y, z, 0) ;
	val  = MRIgetVoxVal(mri, x, y, z, 0) ;
	wval = HISTO2DgetCount(hw, val, wdist);
	if (DZERO(wval) == 0)
	  MRIsetVoxVal(mri_features, x, y, z, 1, -log10(wval)) ;
	pval = HISTO2DgetCount(hp, val, pdist);
	if (DZERO(pval) == 0)
	  MRIsetVoxVal(mri_features, x, y, z, 0, -log10(pval)) ;
      }

  MRIclear(mri_binary) ;
  MRIbinarize(mri_ribbon, mri_binary, 1, 0, 1) ;
  mri_mask = MRIcopy(mri_binary, NULL) ;
  for (i = 0 ; i < close_order ; i++)
  {
    MRIdilate(mri_binary, mri_mask) ;
    MRIcopy(mri_mask, mri_binary) ;
  }
  
  for (i = 0 ; i < close_order ; i++)
  {
    MRIerode(mri_binary, mri_mask) ;
    MRIcopy(mri_mask, mri_binary) ;
  }

  MRIwrite(mri_mask, "m.mgz") ;
  MRImask(mri_features, mri_mask, mri_features, 0, 0) ;
  HISTO2Dfree(&hw) ;
  HISTO2Dfree(&hp) ;
  MRIfree(&mri_white_dist) ; MRIfree(&mri_pial_dist) ; MRIfree(&mri_binary) ;
  return(mri_features) ;
}
Beispiel #6
0
MRI*
MRIcomputeVolumeFractionFromSurface(MRI_SURFACE *mris, double acc, MRI *mri_src, MRI *mri_fractions)
{
  const int width = mri_src->width;
  const int height = mri_src->height;
  const int depth = mri_src->depth;
  int x,y,z, vno;
  double xs, ys, zs, dist; 
  MRIS_HASH_TABLE *mht;
  VERTEX *v; 
  
  /* preparing the output */
  printf("preparing the output\n");
  if (mri_fractions == NULL)
    {
      mri_fractions = MRIalloc(width,height,depth,MRI_FLOAT);
      MRIcopyHeader(mri_src, mri_fractions);
    }
  MRI *mri_shell, *mri_interior; 
  /* creating a shell from the surface */
  printf("computing the shell\n");
  mri_shell = MRIclone(mri_src, NULL);
  mri_shell = MRISshell(mri_src, mris, mri_shell, 1);
  /* creating an interior image from the surface */
  printf("computing an interior image\n");
  mri_interior = MRIclone(mri_src, NULL);
  MRIclear(mri_interior);
  mri_interior = MRISfillInterior(mris, 0.0, mri_interior);
  /* creating the hash table related to the surface vertices */
  printf("computing the hash table\n");
  mht = MHTfillVertexTableRes(mris, NULL, CURRENT_VERTICES, 10);
  /* looping over the nonzero elements of the shell */
  printf("computing the fractions\n");
  volFraction frac;
  octTreeVoxel V; 
  double vox[3], vsize[3];
  vsize[0] = mri_src->xsize; vsize[1] = mri_src->ysize; vsize[2] = mri_src->zsize; 
  for (x = 0; x < width; x++)
    {
      for (y = 0; y < height; y++)
	{
	  for (z = 0; z < depth; z++)
	    {	  
	      if (MRIgetVoxVal (mri_shell, x, y, z, 0) > 125.0)
		{	      
		  /* change of coordinates from image to surface domain */
		  MRIvoxelToSurfaceRAS(mri_shell, x, y, z, &xs, &ys, &zs);
		  /* find the closest vertex to the point */
		  MHTfindClosestVertexGeneric(mht, mris, xs, ys, zs, 10, 2, &v, &vno, &dist);	      
		  /* creating the oct tree voxel structure */
		  vox[0] = xs - vsize[0] / 2.0; 
		  vox[1] = ys - vsize[1] / 2.0; 
		  vox[2] = zs - vsize[2] / 2.0; 
		  V = octTreeVoxelCreate(vox,vsize);
		  /* compute the volume fraction of this voxel */	      
		  frac = MRIcomputeVoxelFractions( V, v, acc, 1, mris);
		  MRIsetVoxVal(mri_fractions,x,y,z,0,frac.frac);
		}
	      else if(MRIgetVoxVal(mri_interior,x,y,z,0) > 0.0)
		MRIsetVoxVal(mri_fractions,x,y,z,0,1.0);

	    }
	}

    }
  return mri_fractions;
}
int
main(int argc, char *argv[]) {
  char   **av, fname[STRLEN] ;
  int    ac, nargs ;
  char   *reg_fname, *in_fname, *out_stem, *cp ;
  int    msec, minutes, seconds, nvox, float2int ;
  struct timeb start ;
  MRI_SURFACE *mris_lh_white, *mris_rh_white, *mris_lh_pial, *mris_rh_pial ;
  MRI         *mri_aseg, *mri_seg, *mri_pial, *mri_tmp, *mri_ribbon, *mri_in, *mri_cortex, 
    *mri_subcort_gm, *mri_wm, *mri_csf ;
  MATRIX      *m_regdat ;
  float       intensity, betplaneres, inplaneres ;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mri_compute_volume_fractions.c,v 1.9 2012/11/07 18:58:02 greve Exp $", "$Name:  $");
  if (nargs && argc - nargs == 1)
    exit (0);
  argc -= nargs;

  Progname = argv[0] ;
  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(1) ;
  if (!strlen(sdir)) {
    cp = getenv("SUBJECTS_DIR") ;
    if (!cp)
      ErrorExit(ERROR_BADPARM,
                "%s: SUBJECTS_DIR not defined in environment.\n", Progname) ;
    strcpy(sdir, cp) ;
  }
  reg_fname = argv[1] ; in_fname = argv[2] ;
  out_stem = argv[3] ; Progname = argv[0] ;
  ErrorInit(NULL, NULL, NULL) ;
  DiagInit(NULL, NULL, NULL) ;

  TimerStart(&start) ;

  if (stricmp(reg_fname, "identity.nofile") == 0)
  {
    printf("using identity transform\n") ;
    m_regdat = NULL ;
    inplaneres = betplaneres = intensity = 1 ;
    float2int = 0 ;
    if (subject == NULL)
      subject = "unknown" ;
  }
  else
  {
    char *saved_subject = subject ;
    printf("reading registration file %s\n", reg_fname) ;
    regio_read_register(reg_fname, &subject, &inplaneres,
                        &betplaneres, &intensity,  &m_regdat,
                        &float2int);
    
    if (saved_subject)  // specified on cmdline
      subject = saved_subject ;
    m_regdat = regio_read_registermat(reg_fname) ;
    if (m_regdat == NULL)
      ErrorExit(ERROR_NOFILE, "%s: could not load registration file from %s", Progname,reg_fname) ;
  }
  printf("Format is %s\n",fmt);
    
  sprintf(fname, "%s/%s/surf/lh.white", sdir, subject) ;
  printf("reading surface %s\n", fname) ;
  mris_lh_white = MRISread(fname) ;
  if (mris_lh_white == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not load lh white surface from %s", Progname,fname) ;

  sprintf(fname, "%s/%s/surf/rh.white", sdir, subject) ;
  printf("reading surface %s\n", fname) ;
  mris_rh_white = MRISread(fname) ;
  if (mris_rh_white == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not load rh white surface from %s", Progname,fname) ;

  sprintf(fname, "%s/%s/surf/lh.pial", sdir, subject) ;
  printf("reading surface %s\n", fname) ;
  mris_lh_pial = MRISread(fname) ;
  if (mris_lh_pial == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not load lh pial surface from %s", Progname,fname) ;

  sprintf(fname, "%s/%s/surf/rh.pial", sdir, subject) ;
  printf("reading surface %s\n", fname) ;
  mris_rh_pial = MRISread(fname) ;
  if (mris_rh_pial == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not load rh pial surface from %s", Progname,fname) ;

  sprintf(fname, "%s/%s/mri/aseg.mgz", sdir, subject) ;
  printf("reading volume %s\n", fname) ;
  mri_aseg = MRIread(fname) ;
  if (mri_aseg == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not load aseg volume from %s", Progname,fname) ;

  printf("reading movable volume %s\n", in_fname) ;
  mri_in = MRIread(in_fname) ;
  if (mri_in == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not load input volume from %s", Progname,in_fname) ;
 
  nvox = (int)ceil(256/resolution); 
  mri_pial = MRIalloc(nvox, nvox, nvox, MRI_UCHAR) ;
  MRIsetResolution(mri_pial, resolution, resolution, resolution) ;

  mri_pial->xstart = -resolution*mri_pial->width/2.0 ;
  mri_pial->xend = resolution*mri_pial->width/2.0 ;
  mri_pial->ystart = -resolution*mri_pial->height/2.0 ;
  mri_pial->yend = resolution*mri_pial->height/2.0 ;
  mri_pial->zstart = -resolution*mri_pial->depth/2.0 ;
  mri_pial->zend = resolution*mri_pial->depth/2 ;
  mri_pial->c_r = mri_aseg->c_r ; mri_pial->c_a = mri_aseg->c_a ; mri_pial->c_s = mri_aseg->c_s ;
  MRIreInitCache(mri_pial) ; 

  printf("filling interior of lh pial surface...\n") ;
  MRISfillInterior(mris_lh_pial, resolution, mri_pial) ;
  mri_seg = MRIclone(mri_pial, NULL) ;
  mri_tmp = MRIclone(mri_pial, NULL) ;
  printf("filling interior of rh pial surface...\n") ;
  MRISfillInterior(mris_rh_pial, resolution, mri_tmp) ;
  MRIcopyLabel(mri_tmp, mri_pial, 1) ;
  MRIclear(mri_tmp) ;
  printf("filling interior of lh white matter surface...\n") ;
  MRISfillWhiteMatterInterior(mris_lh_white, mri_aseg, mri_seg, resolution,
                              WM_VAL, SUBCORT_GM_VAL, CSF_VAL);
  printf("filling interior of rh white matter surface...\n") ;
  MRISfillWhiteMatterInterior(mris_rh_white, mri_aseg, mri_tmp, resolution,
                              WM_VAL, SUBCORT_GM_VAL, CSF_VAL);
  MRIcopyLabel(mri_tmp, mri_seg, WM_VAL) ;
  MRIcopyLabel(mri_tmp, mri_seg, SUBCORT_GM_VAL) ;
  MRIcopyLabel(mri_tmp, mri_seg, CSF_VAL) ;
  MRIfree(&mri_tmp) ;
  
  mri_ribbon = MRInot(mri_seg, NULL) ;
  MRIcopyLabel(mri_seg, mri_pial, CSF_VAL) ;
  MRIreplaceValuesOnly(mri_pial, mri_pial, CSF_VAL, 0) ;
  MRIand(mri_ribbon, mri_pial, mri_ribbon, 1) ;
  MRIbinarize(mri_ribbon, mri_ribbon, 1, 0, GM_VAL) ;
  MRIcopyLabel(mri_ribbon, mri_seg, GM_VAL) ;
  MRIreplaceValuesOnly(mri_seg, mri_seg, CSF_VAL, 0) ;
  add_aseg_structures_outside_ribbon(mri_seg, mri_aseg, mri_seg, WM_VAL, SUBCORT_GM_VAL, CSF_VAL) ;


  {
    MATRIX *m_conformed_to_epi_vox2vox, *m_seg_to_conformed_vox2vox,
           *m_seg_to_epi_vox2vox ;

    if (m_regdat == NULL)    // assume identity transform
      m_seg_to_epi_vox2vox = MRIgetVoxelToVoxelXform(mri_seg, mri_in) ;
    else
    {
      m_conformed_to_epi_vox2vox = MRIvoxToVoxFromTkRegMtx(mri_in, mri_aseg, m_regdat);
      m_seg_to_conformed_vox2vox = MRIgetVoxelToVoxelXform(mri_seg, mri_aseg) ;
      
      m_seg_to_epi_vox2vox = MatrixMultiply(m_conformed_to_epi_vox2vox, m_seg_to_conformed_vox2vox, NULL) ;
      MatrixFree(&m_regdat) ; MatrixFree(&m_conformed_to_epi_vox2vox) ; 
      MatrixFree(&m_seg_to_conformed_vox2vox);

    }
    printf("seg to EPI vox2vox matrix:\n") ;
    MatrixPrint(Gstdout, m_seg_to_epi_vox2vox) ;
    mri_cortex = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, MRI_FLOAT) ;
    MRIcopyHeader(mri_in, mri_cortex) ;
    mri_subcort_gm = MRIclone(mri_cortex, NULL) ;
    mri_wm = MRIclone(mri_cortex, NULL) ;
    mri_csf = MRIclone(mri_cortex, NULL) ;
    printf("computing partial volume fractions...\n") ;
    MRIcomputePartialVolumeFractions(mri_in, m_seg_to_epi_vox2vox, mri_seg, mri_wm, mri_subcort_gm, mri_cortex, mri_csf,
                                     WM_VAL, SUBCORT_GM_VAL, GM_VAL, 0) ;
  }
  
  sprintf(fname, "%s.wm.%s", out_stem,fmt) ;
  printf("writing wm %% to %s\n", fname) ;
  MRIwrite(mri_wm, fname) ;

  sprintf(fname, "%s.subcort_gm.%s", out_stem,fmt) ;
  printf("writing subcortical gm %% to %s\n", fname) ;
  MRIwrite(mri_subcort_gm, fname) ;

  sprintf(fname, "%s.cortex.%s", out_stem, fmt) ;
  printf("writing cortical gm %% to %s\n", fname) ;
  MRIwrite(mri_cortex, fname) ;
  
  sprintf(fname, "%s.csf.%s", out_stem,fmt) ;
  printf("writing csf %% to %s\n", fname) ;
  MRIwrite(mri_csf, fname) ;

  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf("volume fraction calculation took %d minutes"
          " and %d seconds.\n", minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
Beispiel #8
0
MRI *
MRIfillBasalGanglia(MRI *mri_src, MRI *mri_dst)
{
    float  low_thresh, hi_thresh ;
    int    total_filled, depth, height, width, x, y, z,
           xi, yi, zi, xk, yk, zk, fill, val0, val, i ;
    MRI    *mri_bg ;
    Real   tx, ty, tz ;
    MRI_SEGMENTATION  *mriseg ;
    MRI_SEGMENT       *mseg ;
    float  dx_left, dx_right, dy, dz, dist_left, dist_right ;

    if (!mri_dst)
    {
        mri_dst = MRIcopy(mri_src, NULL) ;
    }
    mri_bg = MRIclone(mri_src, NULL) ;

    width = mri_src->width ;
    height = mri_src->height ;
    depth = mri_src->depth ;
    low_thresh = 85 ;
    hi_thresh =  105 ;
    total_filled = 0 ;
    for (z = 0 ; z < depth ; z++)
    {
        for (y = 0 ; y < height ; y++)
        {
            for (x = 0 ; x < width ; x++)
            {
                if (x == 152 && y == 117 && z == 132)  /* 93 */
                {
                    DiagBreak() ;
                }
                val0 = MRIgetVoxVal(mri_src, x, y, z, 0) ;
#if 0
                if (val0 >= low_thresh && val0 <= hi_thresh &&
                        MRIvox(mri_dst,x,y,z) < WM_MIN_VAL)
#else
                if (val0 >= 85 && val0 <= 105)
#endif
                {
#undef WHALF
#undef WSIZE
#define WSIZE   7
#define WHALF  ((WSIZE-1)/2)
                    fill = 1 ;
                    for (zk = -WHALF ; fill && zk <= WHALF ; zk++)
                    {
                        zi = mri_src->zi[z+zk] ;
                        for (yk = -WHALF ; fill && yk <= WHALF ; yk++)
                        {
                            yi = mri_src->yi[y+yk] ;
                            for (xk = -WHALF ; fill && xk <= WHALF ; xk++)
                            {
                                xi = mri_src->xi[x+xk] ;
                                val = MRIgetVoxVal(mri_src, xi, yi, zi, 0) ;
                                if (val < 85 || val > 110)
                                {
                                    fill = 0 ;  /* not homogeneous enough */
                                }
                            }
                        }
                    }
                }
                else
                {
                    fill = 0 ;
                }
                if (fill)
                {
                    total_filled++ ;
                }
                if (fill)
                {
                    MRIsetVoxVal(mri_bg, x, y, z, 0, BASAL_GANGLIA_FILL) ;
                }
            }
        }
    }

    MRIclose(mri_bg, mri_bg) ;  /* remove small holes */

    /* segment into connected components */
    mriseg = MRIsegment(mri_bg, 1, 255) ;
    fprintf(stderr, "segmenting thick gray regions: %d %d mm segments found\n",
            mriseg->nsegments, WSIZE) ;

    /* dilate into regions that are not on */
    for (i = 0 ; i < 2*WSIZE ; i++)
    {
        MRIsegmentDilateThreshold(mriseg, mri_src, mri_src, 80, 100) ;
    }

    /* fill basal ganglia components */
    MRIclear(mri_bg) ;
    for (total_filled = i = 0 ; i < mriseg->nsegments ; i++)
    {
#define TAL_BG_LEFT_X    -30
#define TAL_BG_RIGHT_X   30
#define TAL_BG_Y         5
#define TAL_BG_Z         5
#define MAX_DIST         25

        mseg = &mriseg->segments[i] ;
        MRIvoxelToTalairach(mri_src, mseg->cx, mseg->cy, mseg->cz,&tx, &ty,&tz);
        dx_left = tx - TAL_BG_LEFT_X ;
        dx_right = tx - TAL_BG_RIGHT_X ;
        dy = ty - TAL_BG_Y ;
        dz = tz - TAL_BG_Z ;
        dist_left = sqrt(dx_left*dx_left+dy*dy+dz*dz) ;
        dist_right = sqrt(dx_right*dx_right+dy*dy+dz*dz) ;
        if (dist_left > MAX_DIST && dist_right > MAX_DIST)
        {
            continue ;
        }
        fprintf(stderr, "filling segment %d with %d voxels\n\tc = "
                "(%2.1f,%2.1f,%2.1f) tal (%2.1f,%2.1f,%2.1f), dist %2.1f,%2.1f\n",
                i, mseg->nvoxels, mseg->cx, mseg->cy, mseg->cz,
                tx, ty, tz, dist_left, dist_right) ;
        MRIsegmentToImage(mri_src, mri_bg, mriseg, i) ;
        total_filled += mseg->nvoxels ;
    }

#if 1
    /*  MRIremoveIslands(mri_bg, mri_bg, 3, .56) ;*/
    MRIbinarize(mri_bg, mri_bg, WM_MIN_VAL, 0, BASAL_GANGLIA_FILL) ;
#endif
    MRIsegmentFree(&mriseg) ;

    MRIunion(mri_dst, mri_bg, mri_dst) ;
    MRIfree(&mri_bg) ;
    if (Gdiag & DIAG_SHOW)
    {
        fprintf(stderr, "%d basal ganglia points filled\n", total_filled);
    }

    return(mri_dst) ;
}
Beispiel #9
0
int
FCDcomputeThicknessLabels(FCD_DATA *fcd,
                          double thickness_thresh,
                          double sigma,
                          int size_thresh)
{
  MRI    *mri_lh, *mri_rh, *mri_lh_diff, *mri_rh_diff ;
  int    niter, vno, s ;
  MRI_SEGMENTATION *mriseg ;

  fcdFreeLabels(fcd) ;  // free old ones if they exist
  niter = SIGMA_TO_SURFACE_SMOOTH_STEPS(sigma) ;

  // do LH
  mri_lh = MRIclone(fcd->lh_thickness_on_lh, NULL) ;
  mri_rh = MRIclone(fcd->lh_thickness_on_lh, NULL) ;

  exec_progress_callback(1, 8, 0, 1) ;
  MRISwriteFrameToValues(fcd->mris_lh, fcd->lh_thickness_on_lh, 0) ;
  MRISaverageVals(fcd->mris_lh, niter) ;
  MRISreadFrameFromValues(fcd->mris_lh, mri_lh, 0) ;

  exec_progress_callback(2, 8, 0, 1) ;
  MRISwriteFrameToValues(fcd->mris_lh, fcd->rh_thickness_on_lh, 0) ;
  MRISaverageVals(fcd->mris_lh, niter) ;
  MRISreadFrameFromValues(fcd->mris_lh, mri_rh, 0) ;
  mri_lh_diff = MRIsubtract(mri_lh, mri_rh, NULL) ;  // lh minus rh on lh
  MRIfree(&mri_lh);
  MRIfree(&mri_rh) ;

  // do RH
  mri_lh = MRIclone(fcd->lh_thickness_on_rh, NULL) ;
  mri_rh = MRIclone(fcd->lh_thickness_on_rh, NULL) ;

  exec_progress_callback(3, 8, 0, 1) ;
  MRISwriteFrameToValues(fcd->mris_rh, fcd->lh_thickness_on_rh, 0) ;
  MRISaverageVals(fcd->mris_rh, niter) ;
  MRISreadFrameFromValues(fcd->mris_rh, mri_lh, 0) ;

  exec_progress_callback(4, 8, 0, 1) ;
  MRISwriteFrameToValues(fcd->mris_rh, fcd->rh_thickness_on_rh, 0) ;
  MRISaverageVals(fcd->mris_rh, niter) ;
  MRISreadFrameFromValues(fcd->mris_rh, mri_rh, 0) ;
  mri_rh_diff = MRIsubtract(mri_rh, mri_lh, NULL) ;  // lh minus rh on rh
  MRIfree(&mri_lh);
  MRIfree(&mri_rh) ;

  MRIclear(fcd->mri_thickness_increase) ;
  MRIclear(fcd->mri_thickness_decrease) ;
  exec_progress_callback(5, 8, 0, 1) ;

  // process left hemisphere
#if 1
#ifdef HAVE_OPENMP
#pragma omp parallel for shared(fcd, mri_lh_diff, Gdiag_no, thickness_thresh) schedule(static,1)
#endif
#endif
  for (vno = 0 ; vno < fcd->mris_lh->nvertices ; vno++)
  {
    double d ;
    float val, val2, thickness;
    int base_label ;
    VERTEX *v ;

    v = &fcd->mris_lh->vertices[vno] ;
    if (v->ripflag)
    {
      continue ;
    }
    thickness = MRIgetVoxVal(fcd->lh_thickness_on_lh, vno, 0, 0, 0) ;
    if (vno == Gdiag_no)
    {
      DiagBreak() ;
    }
    val = MRIgetVoxVal(mri_lh_diff, vno, 0, 0, 0) ;
    if (fabs(val) < thickness_thresh)
    {
      continue ;
    }

    for (d = 0, base_label = 0 ; d < thickness ; d += 0.25)
    {
      double xv, yv, zv;
      double xs = v->x+d*v->nx ;
      double ys = v->y+d*v->ny ;
      double zs = v->z+d*v->nz ;
      MRISsurfaceRASToVoxel(fcd->mris_lh, 
                            fcd->mri_thickness_increase, 
                            xs, ys, zs, 
                            &xv, &yv, &zv) ;
      int xvi = nint(xv) ;
      int yvi = nint(yv) ;
      int zvi = nint(zv) ;
      int label = MRIgetVoxVal(fcd->mri_aparc, xvi, yvi, zvi, 0) ;
      if (IS_WM(label) == 0 && 
          label >= MIN_CORTICAL_PARCELLATION && 
          label != ctx_lh_unknown)
      {
        if (label != base_label)
        {
          if (base_label)
          {
            break ;
          }
        }
        else
        {
          base_label = label ;
        }
        if (val >= 0)
        {
          val2 = MRIgetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0) ;
          // check another thread already populated this voxel
          if (val > val2)
          {
            MRIsetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0, val) ;
          }
        }
        else
        {
          val2 = MRIgetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0) ;
          // check if another thread already populated this voxel
          if (val < val2)
          {
            MRIsetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0, val) ;
          }
        }
      }
    }
  }

  exec_progress_callback(6, 8, 0, 1) ;

  // now do right hemisphere
#if 1
#ifdef HAVE_OPENMP
  #pragma omp parallel for shared(fcd, mri_rh_diff, Gdiag_no, thickness_thresh) schedule(static,1)
#endif
#endif
  for (vno = 0 ; vno < fcd->mris_rh->nvertices ; vno++)
  {
    double d  ;
    float val, val2, thickness;
    int base_label ;
    VERTEX *v ;

    v = &fcd->mris_rh->vertices[vno] ;
    if (v->ripflag)
    {
      continue ;
    }
    if (vno == Gdiag_no)
    {
      DiagBreak() ;
    }
    val = MRIgetVoxVal(mri_rh_diff, vno, 0, 0, 0) ;
    if (fabs(val) < thickness_thresh)
    {
      continue ;
    }
    thickness = MRIgetVoxVal(fcd->rh_thickness_on_rh, vno, 0, 0, 0) ;

    for (d = 0, base_label = 0; d < thickness ; d += 0.25)
    {
      double xv, yv, zv;
      double xs = v->x+d*v->nx ;
      double ys = v->y+d*v->ny ;
      double zs = v->z+d*v->nz ;
      MRISsurfaceRASToVoxel(fcd->mris_rh, 
                            fcd->mri_thickness_increase,
                            xs, ys, zs,
                            &xv, &yv, &zv) ;
      int xvi = nint(xv) ;
      int yvi = nint(yv) ;
      int zvi = nint(zv) ;
      int label = MRIgetVoxVal(fcd->mri_aparc, xvi, yvi, zvi, 0) ;
      if (IS_WM(label) == 0 && 
          label >= MIN_CORTICAL_PARCELLATION && 
          label != ctx_rh_unknown)
      {
        if (label != base_label)
        {
          if (base_label)
          {
            break ;
          }
        }
        else
        {
          base_label = label ;
        }

        if (val >= 0)
        {
          val2 = MRIgetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0) ;
          if (val > val2)
          {
            MRIsetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0, val) ;
          }
        }
        else
        {
          val2 = MRIgetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0) ;
          if (val < val2)
          {
            MRIsetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0, val) ;
          }
        }
      }
    }
  }

  exec_progress_callback(7, 8, 0, 1) ;
  mriseg = MRIsegment(fcd->mri_thickness_increase, thickness_thresh, 1e10) ;
  MRIeraseSmallSegments(mriseg, fcd->mri_thickness_increase, thickness_thresh) ;
  MRIsegmentFree(&mriseg) ;
  MRIclose(fcd->mri_thickness_increase, fcd->mri_thickness_increase) ;
  mriseg = MRIsegment(fcd->mri_thickness_increase, thickness_thresh, 1e10) ;
  MRIremoveSmallSegments(mriseg, size_thresh) ;
  printf("segmenting volume at threshold %2.1f with %d "
         "smoothing iters yields %d segments\n",
         thickness_thresh, niter,mriseg->nsegments) ;
  fflush(stdout) ;

  exec_progress_callback(8, 8, 0, 1) ;
  fcd->nlabels = mriseg->nsegments ;
  for (s = 0 ; s < mriseg->nsegments ; s++)
  {
    int label ;

    fcd->labels[s] = MRIsegmentToLabel(mriseg, fcd->mri_thickness_increase, s) ;
    label = most_frequent_label(fcd->mri_aparc, &mriseg->segments[s]) ;
    strcpy(fcd->labels[s]->name, cma_label_to_name(label)) ;
  }
  sort_labels(fcd) ;

  MRIadd(fcd->mri_thickness_increase, fcd->mri_thickness_decrease, fcd->mri_thickness_difference);

  for (s = 0 ; s < mriseg->nsegments ; s++)
  {
    printf("%s: %2.3fmm\n", fcd->label_names[s], fcd->labels[s]->avg_stat) ;
    fflush(stdout) ;
  }
  MRIfree(&mri_lh_diff) ;
  MRIfree(&mri_rh_diff) ;
  MRIsegmentFree(&mriseg) ;

  return(fcd->nlabels) ;
}