示例#1
0
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) ;
}
示例#2
0
int
main(int argc, char *argv[])
{
  char   **av ;
  int    ac, nargs, n ;
  MRI    *mri_src, *mri_dst = NULL, *mri_bias, *mri_orig, *mri_aseg = NULL ;
  char   *in_fname, *out_fname ;
  int          msec, minutes, seconds ;
  struct timeb start ;

  char cmdline[CMD_LINE_LEN] ;

  make_cmd_version_string
  (argc, argv,
   "$Id: mri_normalize.c,v 1.80 2012/10/16 21:38:35 nicks Exp $",
   "$Name:  $",
   cmdline);

  /* rkt: check for and handle version tag */
  nargs = handle_version_option
          (argc, argv,
           "$Id: mri_normalize.c,v 1.80 2012/10/16 21:38:35 nicks Exp $",
           "$Name:  $");
  if (nargs && argc - nargs == 1)
  {
    exit (0);
  }
  argc -= nargs;

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

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

  if (argc < 3)
  {
    usage_exit(0) ;
  }
  if (argc < 1)
  {
    ErrorExit(ERROR_BADPARM, "%s: no input name specified", Progname) ;
  }
  in_fname = argv[1] ;

  if (argc < 2)
  {
    ErrorExit(ERROR_BADPARM, "%s: no output name specified", Progname) ;
  }
  out_fname = argv[2] ;

  if(verbose)
  {
    printf( "reading from %s...\n", in_fname) ;
  }
  mri_src = MRIread(in_fname) ;
  if (!mri_src)
    ErrorExit(ERROR_NO_FILE, "%s: could not open source file %s",
              Progname, in_fname) ;
  MRIaddCommandLine(mri_src, cmdline) ;

  if(nsurfs > 0)
  {
    MRI_SURFACE *mris ;
    MRI         *mri_dist=NULL, *mri_dist_sup=NULL, *mri_ctrl, *mri_dist_one ;
    LTA          *lta= NULL ;
    int          i ;
    TRANSFORM    *surface_xform ;

    if (control_point_fname)  // do one pass with only file control points first
    {
      MRI3dUseFileControlPoints(mri_src, control_point_fname) ;
      mri_dst =
        MRI3dGentleNormalize(mri_src,
                             NULL,
                             DEFAULT_DESIRED_WHITE_MATTER_VALUE,
                             NULL,
                             intensity_above,
                             intensity_below/2,1,
                             bias_sigma, mri_not_control);
    }
    else
    {
      mri_dst = MRIcopy(mri_src, NULL) ;
    }
    for (i = 0 ; i < nsurfs ; i++)
    {
      mris = MRISread(surface_fnames[i]) ;
      if (mris == NULL)
        ErrorExit(ERROR_NOFILE,"%s: could not surface %s",
                  Progname,surface_fnames[i]);
      surface_xform = surface_xforms[i] ;
      TransformInvert(surface_xform, NULL) ;
      if (surface_xform->type == MNI_TRANSFORM_TYPE ||
          surface_xform->type == TRANSFORM_ARRAY_TYPE ||
          surface_xform->type  == REGISTER_DAT)
      {
        lta = (LTA *)(surface_xform->xform) ;

#if 0
        if (invert)
        {
          VOL_GEOM vgtmp;
          LT *lt;
          MATRIX *m_tmp = lta->xforms[0].m_L ;
          lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ;
          MatrixFree(&m_tmp) ;
          lt = &lta->xforms[0];
          if (lt->dst.valid == 0 || lt->src.valid == 0)
          {
            printf( "WARNING:***************************************************************\n");
            printf( "WARNING:dst volume infor is invalid.  Most likely produce wrong inverse.\n");
            printf( "WARNING:***************************************************************\n");
          }
          copyVolGeom(&lt->dst, &vgtmp);
          copyVolGeom(&lt->src, &lt->dst);
          copyVolGeom(&vgtmp, &lt->src);
        }
#endif
      }

      if (stricmp(surface_xform_fnames[i], "identity.nofile") != 0)
      {
        MRIStransform(mris, NULL, surface_xform, NULL) ;
      }

      mri_dist_one = MRIcloneDifferentType(mri_dst, MRI_FLOAT) ;
      printf("computing distance transform\n") ;
      MRIScomputeDistanceToSurface(mris, mri_dist_one, mri_dist_one->xsize) ;
      if (i == 0)
      {
        mri_dist = MRIcopy(mri_dist_one, NULL) ;
      }
      else
      {
        MRIcombineDistanceTransforms(mri_dist_one, mri_dist, mri_dist) ;
      }
//  MRIminAbs(mri_dist_one, mri_dist, mri_dist) ;
      MRIfree(&mri_dist_one) ;
    }
    MRIscalarMul(mri_dist, mri_dist, -1) ;

    if (nonmax_suppress)
    {
      printf("computing nonmaximum suppression\n") ;
      mri_dist_sup = MRInonMaxSuppress(mri_dist, NULL, 0, 1) ;
      mri_ctrl = MRIcloneDifferentType(mri_dist_sup, MRI_UCHAR) ;
      MRIbinarize(mri_dist_sup, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ;
    }
    else if (erode)
    {
      int i ;
      mri_ctrl = MRIcloneDifferentType(mri_dist, MRI_UCHAR) ;
      MRIbinarize(mri_dist, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ;
      for (i = 0 ; i < erode ; i++)
      {
        MRIerode(mri_ctrl, mri_ctrl) ;
      }
    }
    else
    {
      mri_ctrl = MRIcloneDifferentType(mri_dist, MRI_UCHAR) ;
      MRIbinarize(mri_dist, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ;
    }

    if (control_point_fname)
    {
      MRInormAddFileControlPoints(mri_ctrl, CONTROL_MARKED) ;
    }

    if (mask_sigma > 0)
    {
      MRI *mri_smooth, *mri_mag, *mri_grad ;
      mri_smooth = MRIgaussianSmooth(mri_dst, mask_sigma, 1, NULL) ;
      mri_mag = MRIcloneDifferentType(mri_dst, MRI_FLOAT) ;
      mri_grad = MRIsobel(mri_smooth, NULL, mri_mag) ;
      MRIbinarize(mri_mag, mri_mag, mask_thresh, 1, 0) ;
      MRImask(mri_ctrl, mri_mag, mri_ctrl, 0, CONTROL_NONE) ;
      MRIfree(&mri_grad) ;
      MRIfree(&mri_mag) ;
      MRIfree(&mri_smooth) ;
    }
    if (mask_orig_fname)
    {
      MRI *mri_orig ;

      mri_orig = MRIread(mask_orig_fname) ;
      MRIbinarize(mri_orig, mri_orig, mask_orig_thresh, 0, 1) ;

      MRImask(mri_ctrl, mri_orig, mri_ctrl, 0, CONTROL_NONE) ;
      MRIfree(&mri_orig) ;
    }
    if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    {
      MRIwrite(mri_dist, "d.mgz");
      MRIwrite(mri_dist_sup, "dm.mgz");
      MRIwrite(mri_ctrl, "c.mgz");
    }
    MRIeraseBorderPlanes(mri_ctrl, 4) ;
    if (aseg_fname)
    {
      mri_aseg = MRIread(aseg_fname) ;
      if (mri_aseg == NULL)
      {
        ErrorExit(ERROR_NOFILE,
                  "%s: could not load aseg from %s", Progname, aseg_fname) ;
      }
      remove_nonwm_voxels(mri_ctrl, mri_aseg, mri_ctrl) ;
      MRIfree(&mri_aseg) ;
    }
    else
    {
      remove_surface_outliers(mri_ctrl, mri_dist, mri_dst, mri_ctrl) ;
    }
    mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ;
    if (mri_dist)
    {
      MRIfree(&mri_dist) ;
    }
    if (mri_dist_sup)
    {
      MRIfree(&mri_dist_sup) ;
    }
    if (bias_sigma> 0)
    {
      MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ;
      if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
      {
        MRIwrite(mri_bias, "b.mgz") ;
      }
      printf("smoothing bias field\n") ;
      MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ;
      if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
      {
        MRIwrite(mri_bias, "bs.mgz") ;
      }
      MRIfree(&mri_kernel);
    }
    MRIfree(&mri_ctrl) ;
    mri_dst = MRIapplyBiasCorrectionSameGeometry
              (mri_dst, mri_bias, mri_dst,
               DEFAULT_DESIRED_WHITE_MATTER_VALUE) ;
    printf("writing normalized volume to %s\n", out_fname) ;
    MRIwrite(mri_dst, out_fname) ;
    exit(0) ;
  } // end if(surface_fname)

  if (!mriConformed(mri_src) && conform > 0)
  {
    printf("unconformed source detected - conforming...\n") ;
    mri_src = MRIconform(mri_src) ;
  }

  if (mask_fname)
  {
    MRI *mri_mask ;

    mri_mask = MRIread(mask_fname) ;
    if (!mri_mask)
      ErrorExit(ERROR_NOFILE, "%s: could not open mask volume %s.\n",
                Progname, mask_fname) ;
    MRImask(mri_src, mri_mask, mri_src, 0, 0) ;
    MRIfree(&mri_mask) ;
  }

  if (read_flag)
  {
    MRI *mri_ctrl ;
    double scale ;

    mri_bias = MRIread(bias_volume_fname) ;
    if (!mri_bias)
      ErrorExit
      (ERROR_BADPARM,
       "%s: could not read bias volume %s", Progname, bias_volume_fname) ;
    mri_ctrl = MRIread(control_volume_fname) ;
    if (!mri_ctrl)
      ErrorExit
      (ERROR_BADPARM,
       "%s: could not read control volume %s",
       Progname, control_volume_fname) ;
    MRIbinarize(mri_ctrl, mri_ctrl, 1, 0, 128) ;
    mri_dst = MRImultiply(mri_bias, mri_src, NULL) ;
    scale = MRImeanInLabel(mri_dst, mri_ctrl, 128) ;
    printf("mean in wm is %2.0f, scaling by %2.2f\n", scale, 110/scale) ;
    scale = 110/scale ;
    MRIscalarMul(mri_dst, mri_dst, scale) ;
    MRIwrite(mri_dst, out_fname) ;
    exit(0) ;
  }

  if(long_flag)
  {
    MRI *mri_ctrl ;
    double scale ;

    mri_bias = MRIread(long_bias_volume_fname) ;
    if (!mri_bias)
      ErrorExit
      (ERROR_BADPARM,
       "%s: could not read bias volume %s", Progname, long_bias_volume_fname) ;
    mri_ctrl = MRIread(long_control_volume_fname) ;
    if (!mri_ctrl)
      ErrorExit
      (ERROR_BADPARM,
       "%s: could not read control volume %s",
       Progname, long_control_volume_fname) ;
    MRIbinarize(mri_ctrl, mri_ctrl, 1, 0, CONTROL_MARKED) ;
    if (mri_ctrl->type != MRI_UCHAR)
    {
      MRI *mri_tmp ;
      mri_tmp = MRIchangeType(mri_ctrl, MRI_UCHAR, 0, 1,1);
      MRIfree(&mri_ctrl) ;
      mri_ctrl = mri_tmp ;
    }
    scale = MRImeanInLabel(mri_src, mri_ctrl, CONTROL_MARKED) ;
    printf("mean in wm is %2.0f, scaling by %2.2f\n", scale, 110/scale) ;
    scale = DEFAULT_DESIRED_WHITE_MATTER_VALUE/scale ;
    mri_dst = MRIscalarMul(mri_src, NULL, scale) ;
    MRIremoveWMOutliers(mri_dst, mri_ctrl, mri_ctrl, intensity_below/2) ;
    mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ;
    MRIsoapBubble(mri_bias, mri_ctrl, mri_bias, 50, 1) ;
    MRIapplyBiasCorrectionSameGeometry(mri_dst, mri_bias, mri_dst,
                                       DEFAULT_DESIRED_WHITE_MATTER_VALUE);
    //    MRIwrite(mri_dst, out_fname) ;
    //    exit(0) ;
  } // end if(long_flag)

  if (grad_thresh > 0)
  {
    float thresh ;
    MRI   *mri_mag, *mri_grad, *mri_smooth ;
    MRI *mri_kernel = MRIgaussian1d(.5, -1) ;

    mri_not_control = MRIcloneDifferentType(mri_src, MRI_UCHAR) ;
    switch (scan_type)
    {
    case MRI_MGH_MPRAGE:
      thresh = 15 ;
      break ;
    case MRI_WASHU_MPRAGE:
      thresh = 20 ;
      break ;
    case MRI_UNKNOWN:
    default:
      thresh = 12 ;
      break ;
    }
    mri_smooth = MRIconvolveGaussian(mri_src, NULL, mri_kernel) ;
    thresh = grad_thresh ;
    mri_mag = MRIcloneDifferentType(mri_src, MRI_FLOAT) ;
    mri_grad = MRIsobel(mri_smooth, NULL, mri_mag) ;
    MRIwrite(mri_mag, "m.mgz") ;
    MRIbinarize(mri_mag, mri_not_control, thresh, 0, 1) ;
    MRIwrite(mri_not_control, "nc.mgz") ;
    MRIfree(&mri_mag) ;
    MRIfree(&mri_grad) ;
    MRIfree(&mri_smooth) ;
    MRIfree(&mri_kernel) ;
  }
#if 0
#if 0
  if ((mri_src->type != MRI_UCHAR) ||
      (!(mri_src->xsize == 1 && mri_src->ysize == 1 && mri_src->zsize == 1)))
#else
  if (conform || (mri_src->type != MRI_UCHAR && conform > 0))
#endif
  {
    MRI  *mri_tmp ;

    fprintf
    (stderr,
     "downsampling to 8 bits and scaling to isotropic voxels...\n") ;
    mri_tmp = MRIconform(mri_src) ;
    mri_src = mri_tmp ;
  }
#endif

  if(aseg_fname)
  {
    printf("Reading aseg %s\n",aseg_fname);
    mri_aseg = MRIread(aseg_fname) ;
    if (mri_aseg == NULL)
      ErrorExit
      (ERROR_NOFILE,
       "%s: could not read aseg from file %s", Progname, aseg_fname) ;
    if (!mriConformed(mri_aseg))
    {
      ErrorExit(ERROR_UNSUPPORTED, "%s: aseg volume %s must be conformed",
                Progname, aseg_fname) ;
    }
  }
  else
  {
    mri_aseg = NULL ;
  }

  if(verbose)
  {
    printf( "normalizing image...\n") ;
  }
  fflush(stdout);
  fflush(stderr);

  TimerStart(&start) ;

  if (control_point_fname)
  {
    MRI3dUseFileControlPoints(mri_src, control_point_fname) ;
  }

  // this just setup writing control-point volume saving
  if(control_volume_fname)
  {
    MRI3dWriteControlPoints(control_volume_fname) ;
  }


  /* first do a gentle normalization to get
     things in the right intensity range */
  if(long_flag == 0)   // if long, then this will already have been done with base control points
  {
    if(control_point_fname != NULL)  /* do one pass with only
                                         file control points first */
      mri_dst =
        MRI3dGentleNormalize(mri_src,
                             NULL,
                             DEFAULT_DESIRED_WHITE_MATTER_VALUE,
                             NULL,
                             intensity_above,
                             intensity_below/2,1,
                             bias_sigma, mri_not_control);
    else
    {
      mri_dst = MRIcopy(mri_src, NULL) ;
    }
  }
  fflush(stdout);
  fflush(stderr);

  if(mri_aseg)
  {
    MRI *mri_ctrl, *mri_bias ;
    int  i ;

    printf("processing with aseg\n");

    mri_ctrl = MRIclone(mri_aseg, NULL) ;
    for (i = 0 ; i < NWM_LABELS ; i++)
    {
      MRIcopyLabel(mri_aseg, mri_ctrl, aseg_wm_labels[i]) ;
    }
    printf("removing outliers in the aseg WM...\n") ;
    MRIremoveWMOutliersAndRetainMedialSurface(mri_dst,
        mri_ctrl,
        mri_ctrl,
        intensity_below) ;
    MRIbinarize(mri_ctrl, mri_ctrl, 1, CONTROL_NONE, CONTROL_MARKED) ;
    MRInormAddFileControlPoints(mri_ctrl, CONTROL_MARKED) ;

    if (interior_fname1)
    {
      MRIS *mris_interior1, *mris_interior2 ;
      mris_interior1 = MRISread(interior_fname1) ;
      if (mris_interior1 == NULL)
        ErrorExit(ERROR_NOFILE,
                  "%s: could not read white matter surface from %s\n",
                  Progname, interior_fname1) ;
      mris_interior2 = MRISread(interior_fname2) ;
      if (mris_interior2 == NULL)
        ErrorExit(ERROR_NOFILE,
                  "%s: could not read white matter surface from %s\n",
                  Progname, interior_fname2) ;
      add_interior_points(mri_ctrl,
                          mri_dst,
                          intensity_above,
                          1.25*intensity_below,
                          mris_interior1,
                          mris_interior2,
                          mri_aseg,
                          mri_ctrl) ;
      MRISfree(&mris_interior1) ;
      MRISfree(&mris_interior2) ;
    }
    if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    {
      MRIwrite(mri_ctrl, "norm_ctrl.mgz") ;
    }

    printf("Building bias image\n");
    fflush(stdout);
    fflush(stderr);
    mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ;
    fflush(stdout);
    fflush(stderr);

    if (bias_sigma> 0)
    {
      printf("Smoothing with sigma %g\n",bias_sigma);
      MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ;
      MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ;
      MRIfree(&mri_kernel);
      fflush(stdout);
      fflush(stderr);
    }
    MRIfree(&mri_ctrl) ;
    MRIfree(&mri_aseg) ;
    printf("Applying bias correction\n");
    mri_dst = MRIapplyBiasCorrectionSameGeometry
              (mri_dst, mri_bias, mri_dst,
               DEFAULT_DESIRED_WHITE_MATTER_VALUE) ;
    if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    {
      MRIwrite(mri_dst, "norm_1.mgz") ;
    }
    fflush(stdout);
    fflush(stderr);
  } // if(mri_aseg)
  else
  {
    printf("processing without aseg, no1d=%d\n",no1d);
    if (!no1d)
    {
      printf("MRInormInit(): \n");
      MRInormInit(mri_src, &mni, 0, 0, 0, 0, 0.0f) ;
      printf("MRInormalize(): \n");
      mri_dst = MRInormalize(mri_src, NULL, &mni) ;
      if (!mri_dst)
      {
        no1d = 1 ;
        printf("1d normalization failed - trying no1d...\n") ;
        // ErrorExit(ERROR_BADPARM, "%s: normalization failed", Progname) ;
      }
    }
    if(no1d)
    {
      if ((file_only && nosnr) ||
          ((gentle_flag != 0) && (control_point_fname != NULL)))
      {
        if (mri_dst == NULL)
        {
          mri_dst = MRIcopy(mri_src, NULL) ;
        }
      }
      else
      {
        if (nosnr)
        {
          if (interior_fname1)
          {
            MRIS *mris_interior1, *mris_interior2 ;
            MRI  *mri_ctrl ;

            printf("computing initial normalization using surface interiors\n");
            mri_ctrl = MRIcloneDifferentType(mri_src, MRI_UCHAR) ;
            mris_interior1 = MRISread(interior_fname1) ;
            if (mris_interior1 == NULL)
              ErrorExit(ERROR_NOFILE,
                        "%s: could not read white matter surface from %s\n",
                        Progname, interior_fname1) ;
            mris_interior2 = MRISread(interior_fname2) ;
            if (mris_interior2 == NULL)
              ErrorExit(ERROR_NOFILE,
                        "%s: could not read white matter surface from %s\n",
                        Progname, interior_fname2) ;
            add_interior_points(mri_ctrl,
                                mri_dst,
                                intensity_above,
                                1.25*intensity_below,
                                mris_interior1,
                                mris_interior2,
                                mri_aseg,
                                mri_ctrl) ;
            MRISfree(&mris_interior1) ;
            MRISfree(&mris_interior2) ;
            mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ;
            if (bias_sigma> 0)
            {
              MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ;
              MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ;
              MRIfree(&mri_kernel);
            }
            mri_dst = MRIapplyBiasCorrectionSameGeometry
                      (mri_src,
                       mri_bias,
                       mri_dst,
                       DEFAULT_DESIRED_WHITE_MATTER_VALUE) ;
            MRIfree(&mri_ctrl) ;
          }
          else if (long_flag == 0)  // no initial normalization specified
          {
            mri_dst = MRIcopy(mri_src, NULL) ;
          }
        }
        else
        {
          printf("computing initial normalization using SNR...\n") ;
          mri_dst = MRInormalizeHighSignalLowStd
                    (mri_src, mri_dst, bias_sigma,
                     DEFAULT_DESIRED_WHITE_MATTER_VALUE) ;
        }
      }
      if (!mri_dst)
        ErrorExit
        (ERROR_BADPARM, "%s: could not allocate volume", Progname) ;
    }
  } // else (not using aseg)
  fflush(stdout);
  fflush(stderr);

  if (file_only == 0)
    MRI3dGentleNormalize(mri_dst, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE,
                         mri_dst,
                         intensity_above, intensity_below/2,
                         file_only, bias_sigma, mri_not_control);

  mri_orig = MRIcopy(mri_dst, NULL) ;
  printf("\n");
  printf("Iterating %d times\n",num_3d_iter);
  for (n = 0 ; n < num_3d_iter ; n++)
  {
    if(file_only)
    {
      break ;
    }

    printf( "---------------------------------\n");
    printf( "3d normalization pass %d of %d\n", n+1, num_3d_iter) ;
    if (gentle_flag)
      MRI3dGentleNormalize(mri_dst, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE,
                           mri_dst,
                           intensity_above/2, intensity_below/2,
                           file_only, bias_sigma, mri_not_control);
    else
      MRI3dNormalize(mri_orig, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE,
                     mri_dst,
                     intensity_above, intensity_below,
                     file_only, prune, bias_sigma, scan_type, mri_not_control);
  }
  printf( "Done iterating ---------------------------------\n");

  // this just setup writing control-point volume saving
  if(control_volume_fname)
  {
    MRI3dWriteControlPoints(control_volume_fname) ;
  }

  if(bias_volume_fname)
  {
    mri_bias = compute_bias(mri_src, mri_dst, NULL) ;
    printf("writing bias field to %s....\n", bias_volume_fname) ;
    MRIwrite(mri_bias, bias_volume_fname) ;
    MRIfree(&mri_bias) ;
  }

  if (verbose)
  {
    printf("writing output to %s\n", out_fname) ;
  }
  MRIwrite(mri_dst, out_fname) ;
  msec = TimerStop(&start) ;

  MRIfree(&mri_src);
  MRIfree(&mri_dst);

  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf( "3D bias adjustment took %d minutes and %d seconds.\n",
          minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
static int
write_surface_warp_into_volume(MRI_SURFACE *mris, MRI *mri, int niter)
{
  int    vno, xvi, yvi, zvi, frame ;
  VERTEX *v ;
  double  dx, dy, dz, xv, yv, zv, xv1, yv1, zv1 ;
  MRI     *mri_weights, *mri_ctrl, *mri_frame ;
  float    wt ;

  mri_weights = MRIallocSequence(mri->width, mri->height, mri->depth, MRI_FLOAT, 1) ;
  mri_ctrl = MRIallocSequence(mri->width, mri->height, mri->depth, MRI_UCHAR, 1) ;
  MRIcopyHeader(mri, mri_weights) ; MRIcopyHeader(mri, mri_ctrl) ;
  //   build a 3 frame volume with the voxel-coords warp (dx, dy, dz) in frames 0, 1 and 2 respectively
  for (vno = 0 ; vno < mris->nvertices ; vno++)
  {
    v = &mris->vertices[vno] ;
    if (v->ripflag)
      continue ;

    MRISsurfaceRASToVoxelCached(mris, mri, v->origx, v->origy, v->origz, &xv, &yv, &zv) ;
    MRISsurfaceRASToVoxelCached(mris, mri, v->x, v->y, v->z, &xv1, &yv1, &zv1) ;
    dx = xv1-xv ; dy = yv1-yv ; dz = zv1-zv ;
    xvi = nint(xv) ; yvi = nint(yv) ; zvi = nint(zv) ;
    if (vno == Gdiag_no)
    {
      printf("surface vertex %d: inflated (%2.0f, %2.0f, %2.0f), orig (%2.0f, %2.0f, %2.0f), "
	     "dx=(%2.0f, %2.0f, %2.0f)\n", vno, xv1, yv1, zv1, xv, yv, zv, dx, dy, dz) ;
      DiagBreak() ;
    }
    if (xvi < 0 || xvi >= mri->width || yv < 0 || yv >= mri->height || zv < 0 || zv >= mri->depth)
    {
      continue ;
    }
    MRIinterpolateIntoVolumeFrame(mri, xv, yv, zv, 0, dx) ;
    MRIinterpolateIntoVolumeFrame(mri, xv, yv, zv, 1, dy) ;
    MRIinterpolateIntoVolumeFrame(mri, xv, yv, zv, 2, dz) ;
    MRIinterpolateIntoVolume(mri_weights, xv, yv, zv, 1.0) ;
  }

#if 0
  // set boundary conditions in the edge planes to be 0 warping
  for (xvi = 0 ; xvi < mri->width ; xvi++)
    for (yvi = 0 ; yvi < mri->height ; yvi++)
    {
      MRIsetVoxVal(mri_ctrl, xvi, yvi, 0, 0, CONTROL_MARKED) ;
      MRIsetVoxVal(mri, xvi, yvi, 0, 0, 0) ;
      MRIsetVoxVal(mri, xvi, yvi, 0, 1, 0) ;
      MRIsetVoxVal(mri, xvi, yvi, 0, 2, 0) ;

      MRIsetVoxVal(mri_ctrl, xvi, yvi, mri->depth-1, 0, CONTROL_MARKED) ;
      MRIsetVoxVal(mri, xvi, yvi, mri->depth-1, 0, 0) ;
      MRIsetVoxVal(mri, xvi, yvi, mri->depth-1, 1, 0) ;
      MRIsetVoxVal(mri, xvi, yvi, mri->depth-1, 2, 0) ;
    }

  for (xvi = 0 ; xvi < mri->width ; xvi++)
    for (zvi = 0 ; zvi < mri->depth ; zvi++)
    {
      MRIsetVoxVal(mri_ctrl, xvi, 0, zvi, 0, CONTROL_MARKED) ;
      MRIsetVoxVal(mri, xvi, 0, zvi, 0, 0) ;
      MRIsetVoxVal(mri, xvi, 0, zvi, 1, 0) ;
      MRIsetVoxVal(mri, xvi, 0, zvi, 2, 0) ;

      MRIsetVoxVal(mri_ctrl, xvi, mri->height-1, zvi, 0, CONTROL_MARKED) ;
      MRIsetVoxVal(mri, xvi, mri->height-1, zvi, 0, 0) ;
      MRIsetVoxVal(mri, xvi, mri->height-1, zvi, 1, 0) ;
      MRIsetVoxVal(mri, xvi, mri->height-1, zvi, 2, 0) ;
    }

  for (yvi = 0 ; yvi < mri->width ; yvi++)
    for (zvi = 0 ; zvi < mri->depth ; zvi++)
    {
      MRIsetVoxVal(mri_ctrl, 0, yvi, zvi, 0, CONTROL_MARKED) ;
      MRIsetVoxVal(mri, 0, yvi, zvi, 0, 0) ;
      MRIsetVoxVal(mri, 0, yvi, zvi, 1, 0) ;
      MRIsetVoxVal(mri, 0, yvi, zvi, 2, 0) ;

      MRIsetVoxVal(mri_ctrl, mri->width-1, yvi, zvi, 0, CONTROL_MARKED) ;
      MRIsetVoxVal(mri, mri->width-1, yvi, zvi, 0, 0) ;
      MRIsetVoxVal(mri, mri->width-1, yvi, zvi, 1, 0) ;
      MRIsetVoxVal(mri, mri->width-1, yvi, zvi, 2, 0) ;

    }
#endif

  // normalize the warp field using a weighted average of all vertices that map to every voxel
  for (xvi = 0 ; xvi < mri->width ; xvi++)
    for (yvi = 0 ; yvi < mri->height ; yvi++)
      for (zvi = 0 ; zvi < mri->depth ; zvi++)
      {
        if (xvi == Gx && yvi == Gy && zvi == Gz)
          DiagBreak() ;

        wt = MRIgetVoxVal(mri_weights, xvi, yvi, zvi, 0) ;
        dx = MRIgetVoxVal(mri, xvi, yvi, zvi, 0) ;
        dy = MRIgetVoxVal(mri, xvi, yvi, zvi, 1) ;
        dz = MRIgetVoxVal(mri, xvi, yvi, zvi, 2) ;
        if (FZERO(wt))
          continue ;

        dx /= wt ; dy /= wt ; dz /= wt ;
        MRIsetVoxVal(mri, xvi, yvi, zvi, 0, dx) ;
        MRIsetVoxVal(mri, xvi, yvi, zvi, 1, dy) ;
        MRIsetVoxVal(mri, xvi, yvi, zvi, 2, dz) ;
        MRIsetVoxVal(mri_ctrl, xvi, yvi, zvi, 0, CONTROL_MARKED) ;  // it is a control point
      }

  if (Gdiag & DIAG_WRITE)
  {
    MRIwrite(mri, "warp0.mgz") ;
    MRIwrite(mri_ctrl, "ctrl.mgz") ;
  }

  for (frame = 0 ; frame < mri->nframes ; frame++)
  {
    printf("interpolating frame %d\n", frame+1) ;
    mri_frame = MRIcopyFrame(mri, NULL, frame, 0) ;
    MRIbuildVoronoiDiagram(mri_frame, mri_ctrl, mri_frame) ;
    MRIsoapBubble(mri_frame, mri_ctrl, mri_frame, niter, mri_frame->xsize*.05) ;
#if 0
    {
      int x, y, z ;
      float val ;
      for (x  = 0 ; x < mri_frame->width ; x++)
        for (y  = 0 ; y < mri_frame->height ; y++)
          for (z  = 0 ; z < mri_frame->depth ; z++)
          {
            val = MRIgetVoxVal(mri_frame, x, y, z, 0) ;
            switch (frame)
            {
            default:
            case 0:
              val += x ;
              break ;
            case 1:
              val += y ;
              break ;
            case 2:
              val += z ;
              break ;
            }

            MRIsetVoxVal(mri_frame, x, y, z, 0, val) ;
          }
    }
#endif
    MRIcopyFrame(mri_frame, mri, 0, frame) ;
    MRIfree(&mri_frame) ;
  }
  MRIfree(&mri_weights) ;
  MRIfree(&mri_ctrl) ;
  return(NO_ERROR) ;
}