예제 #1
0
int
main(int argc, char *argv[])
{
  char         **av, *out_name ;
  int          ac, nargs ;
  int          msec, minutes, seconds ;
  struct timeb start ;
  GCA_MORPH    *gcam ;
  MRI          *mri = NULL ;
  MATRIX       *m;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mri_warp_convert.c,v 1.1 2012/02/13 23:05:52 jonp Exp $", "$Name:  $");
  if (nargs && argc - nargs == 1)
  {
    exit (0);
  }
  argc -= nargs;

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

  TimerStart(&start) ;

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

  if (argc < 3)
  {
    usage_exit(1) ;
  }

  // mri_convert expects a relative warp
  fprintf(stdout, "[%s]:  reading warp file '%s'\n", Progname, argv[1]);
  fprintf(stdout, "assuming RELATIVE warp convention\n");

  // TODO: add support for absolute warps as well, add option to specify convention


  mri = MRIread(argv[1]) ;
  if (mri == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not read warp volume %s\n", Progname,argv[1]) ;

  m = MRIgetVoxelToRasXform(mri) ;

  // NOTE: this assumes a standard siemens image orientation in which
  // case a neurological orientation means that the first frame is
  // flipped

  if ( MatrixDeterminant(m) > 0 )
    {
      fprintf(stdout, "non-negative Jacobian determinant -- converting to radiological ordering\n");
    }
  {
    // 2012/feb/08: tested with anisotropic voxel sizes

    MRI *mri2 = NULL ;
    int c=0,r=0,s=0;
    float v;

    mri2 = MRIcopy(mri,NULL);
    for(c=0; c < mri->width; c++)
      {
        for(r=0; r < mri->height; r++)
          {
            for(s=0; s < mri->depth; s++)
              {
                // only flip first frame (by negating relative shifts)
                v = MRIgetVoxVal(mri, c,r,s,0) / mri->xsize;
                if ( MatrixDeterminant(m) > 0 )
                  MRIsetVoxVal(    mri2,c,r,s,0,-v);
                else
                  MRIsetVoxVal(    mri2,c,r,s,0, v);

                v = MRIgetVoxVal(mri, c,r,s,1) / mri->ysize;
                MRIsetVoxVal(    mri2,c,r,s,1, v);

                v = MRIgetVoxVal(mri, c,r,s,2) / mri->zsize;
                MRIsetVoxVal(    mri2,c,r,s,2, v);

              }
          }
      }
    MRIfree(&mri);
    mri = mri2;

  }
  MatrixFree(&m) ;


  // this does all the work! (gcamorph.c)
  gcam = GCAMalloc(mri->width, mri->height, mri->depth) ;
  GCAMinitVolGeom(gcam, mri, mri) ;

  // not sure if removing singularities is ever a bad thing
#if 1
  GCAMremoveSingularitiesAndReadWarpFromMRI(gcam, mri) ;
#else
  GCAMreadWarpFromMRI(gcam, mri) ;
#endif

  fprintf(stdout, "[%s]:  writing warp file '%s'\n", Progname, argv[2]);

  out_name = argv[2] ;
  GCAMwrite(gcam, out_name) ;

  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  fprintf(stderr, "conversion took %d minutes and %d seconds.\n", minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
예제 #2
0
int
main(int argc, char *argv[])
{
  char         **av, *source_fname, *target_fname, *out_fname, fname[STRLEN] ;
  int          ac, nargs, new_transform = 0, pad ;
  MRI          *mri_target, *mri_source, *mri_orig_source ;
  MRI_REGION   box ;
  struct timeb start ;
  int          msec, minutes, seconds ;
  GCA_MORPH    *gcam ;
  MATRIX       *m_L/*, *m_I*/ ;
  LTA          *lta ;


  /* initialize the morph params */
  memset(&mp, 0, sizeof(GCA_MORPH_PARMS));
  /* for nonlinear morph */
  mp.l_jacobian = 1 ;
  mp.min_sigma = 0.4 ;
  mp.l_distance = 0 ;
  mp.l_log_likelihood = .025 ;
  mp.dt = 0.005 ;
  mp.noneg = True ;
  mp.exp_k = 20 ;
  mp.diag_write_snapshots = 1 ;
  mp.momentum = 0.9 ;
  if (FZERO(mp.l_smoothness))
    mp.l_smoothness = 2 ;
  mp.sigma = 8 ;
  mp.relabel_avgs = -1 ;
  mp.navgs = 256 ;
  mp.levels = 6 ;
  mp.integration_type = GCAM_INTEGRATE_BOTH ;
  mp.nsmall = 1 ;
  mp.reset_avgs = -1 ;
  mp.npasses = 3 ;
  mp.regrid = regrid? True : False ;
  mp.tol = 0.1 ;
  mp.niterations = 1000 ;
	
  TimerStart(&start) ;
  setRandomSeed(-1L) ;
  DiagInit(NULL, NULL, NULL) ;
  ErrorInit(NULL, NULL, NULL) ;

  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) ;

  source_fname = argv[1] ;
  target_fname = argv[2] ;
  out_fname = argv[3] ;
  FileNameOnly(out_fname, fname) ;
  FileNameRemoveExtension(fname, fname) ;
  strcpy(mp.base_name, fname) ;
  mri_source = MRIread(source_fname) ;
  if (!mri_source)
    ErrorExit(ERROR_NOFILE, "%s: could not read source label volume %s",
	      Progname, source_fname) ;

  if (mri_source->type == MRI_INT)
    {
      MRI *mri_tmp = MRIchangeType(mri_source, MRI_FLOAT, 0, 1, 1) ;
      MRIfree(&mri_source); mri_source = mri_tmp ;
    }
  mri_target = MRIread(target_fname) ;
  if (!mri_target)
    ErrorExit(ERROR_NOFILE, "%s: could not read target label volume %s",
	      Progname, target_fname) ;
  if (mri_target->type == MRI_INT)
    {
      MRI *mri_tmp = MRIchangeType(mri_target, MRI_FLOAT, 0, 1, 1) ;
      MRIfree(&mri_target); mri_target = mri_tmp ;
    }
  if (erosions > 0)
    {
      int n ;
      for (n = 0 ; n < erosions ; n++)
	{
	  MRIerodeZero(mri_target, mri_target) ;
	  MRIerodeZero(mri_source, mri_source) ;
	}
    }
  if (scale_values > 0)
    {
      MRIscalarMul(mri_source, mri_source, scale_values) ;
      MRIscalarMul(mri_target, mri_target, scale_values) ;
    }
  if (transform && transform->type == MORPH_3D_TYPE)
    TransformRas2Vox(transform, mri_source,NULL) ;
  if (use_aseg == 0)
    {
      if (match_peak_intensity_ratio)
	MRImatchIntensityRatio(mri_source, mri_target, mri_source, .8, 1.2, 
			       100, 125) ;
      else if (match_mean_intensity)
	MRImatchMeanIntensity(mri_source, mri_target, mri_source) ;
      MRIboundingBox(mri_source, 0, &box) ;
      pad = (int)ceil(PADVOX * 
		      MAX(mri_target->xsize,MAX(mri_target->ysize,mri_target->zsize)) / 
		      MIN(mri_source->xsize,MIN(mri_source->ysize,mri_source->zsize))); 
#if 0
      { MRI *mri_tmp ;
	if (pad < 1)
	  pad = 1 ;
	printf("padding source with %d voxels...\n", pad) ;
	mri_tmp = MRIextractRegionAndPad(mri_source, NULL, &box, pad) ;
	if ((Gdiag & DIAG_WRITE) && DIAG_VERBOSE_ON)
	  MRIwrite(mri_tmp, "t.mgz") ;
	MRIfree(&mri_source) ;
	mri_source = mri_tmp ;
      }
#endif
    }
  mri_orig_source = MRIcopy(mri_source, NULL) ;

  mp.max_grad = 0.3*mri_source->xsize ;

  if (transform == NULL)
    transform = TransformAlloc(LINEAR_VOXEL_TO_VOXEL, NULL) ;

  if (transform->type != MORPH_3D_TYPE)  // initializing m3d from a linear transform
    {
      new_transform = 1 ;
      lta = ((LTA *)(transform->xform)) ;
      if (lta->type != LINEAR_VOX_TO_VOX)
	{
	  printf("converting ras xform to voxel xform\n") ;
	  m_L = MRIrasXformToVoxelXform(mri_source, mri_target, lta->xforms[0].m_L, NULL) ;
	  MatrixFree(&lta->xforms[0].m_L) ;
	  lta->type = LINEAR_VOX_TO_VOX ;
	}
      else
	{
	  printf("using voxel xform\n") ;
	  m_L = lta->xforms[0].m_L ;
	}
#if 0
      if (Gsx >= 0)   // update debugging coords
	{
	  VECTOR *v1, *v2 ;

	  v1 = VectorAlloc(4, MATRIX_REAL) ;
	  Gsx -= (box.x-pad) ;
	  Gsy -= (box.y-pad) ;
	  Gsz -= (box.z-pad) ;
	  V3_X(v1) = Gsx ; V3_Y(v1) = Gsy ; V3_Z(v1) = Gsz ;
	  VECTOR_ELT(v1,4) = 1.0 ;
	  v2 = MatrixMultiply(m_L, v1, NULL) ;
      
	  Gsx = nint(V3_X(v2)) ; Gsy = nint(V3_Y(v2)) ; Gsz = nint(V3_Z(v2)) ;
	  MatrixFree(&v2) ; MatrixFree(&v1) ;
	  printf("mapping by transform (%d, %d, %d) --> (%d, %d, %d) for rgb writing\n",
		 Gx, Gy, Gz, Gsx, Gsy, Gsz) ;
	}
#endif
      if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
	write_snapshot(mri_target, mri_source, m_L, &mp, 0, 1, "linear_init");

      lta->xforms[0].m_L = m_L ;
      printf("initializing GCAM with vox->vox matrix:\n") ;
      MatrixPrint(stdout, m_L) ;
      gcam = GCAMcreateFromIntensityImage(mri_source, mri_target, transform) ;
#if 0
      gcam->gca = gcaAllocMax(1, 1, 1, 
			      mri_target->width, mri_target->height, 
			      mri_target->depth,
			      0, 0) ;
#endif
      GCAMinitVolGeom(gcam, mri_source, mri_target) ;
      if (use_aseg)
	{
	  if (ribbon_name)
	    {
	      char fname[STRLEN], path[STRLEN], *str, *hemi ;
	      int  h, s, label ;
	      MRI_SURFACE *mris_white, *mris_pial ;
	      MRI         *mri ;

	      for (s = 0 ; s <= 1 ; s++) // source and target
		{
		  if (s == 0)
		    {
		      str = source_surf ;
		      mri = mri_source ;
		      FileNamePath(mri->fname, path) ;
		      strcat(path, "/../surf") ;
		    }
		  else
		    {
		      mri = mri_target ;
		      FileNamePath(mri->fname, path) ;
		      strcat(path, "/../elastic") ;
		      str = target_surf ;
		    }
		  // sorry - these values come from FreeSurferColorLUT.txt
		  MRIreplaceValueRange(mri, mri, 1000, 1034, Left_Cerebral_Cortex) ;
		  MRIreplaceValueRange(mri, mri, 1100, 1180, Left_Cerebral_Cortex) ;
		  MRIreplaceValueRange(mri, mri, 2000, 2034, Right_Cerebral_Cortex) ;
		  MRIreplaceValueRange(mri, mri, 2100, 2180, Right_Cerebral_Cortex) ;
		  for (h = LEFT_HEMISPHERE ; h <= RIGHT_HEMISPHERE ; h++)  
		    {
		      if (h == LEFT_HEMISPHERE)
			{
			  hemi = "lh" ;
			  label = Left_Cerebral_Cortex ;
			}
		      else
			{
			  label = Right_Cerebral_Cortex ;
			  hemi = "rh" ;
			}
		      sprintf(fname, "%s/%s%s.white", path, hemi, str) ;
		      mris_white = MRISread(fname) ;
		      if (mris_white == NULL)
			ErrorExit(ERROR_NOFILE, "%s: could not read surface %s", Progname, fname) ;
		      MRISsaveVertexPositions(mris_white, WHITE_VERTICES) ;
		      sprintf(fname, "%s/%s%s.pial", path, hemi, str) ;
		      mris_pial = MRISread(fname) ;
		      if (mris_pial == NULL)
			ErrorExit(ERROR_NOFILE, "%s: could not read surface %s", Progname, fname) ;
		      MRISsaveVertexPositions(mris_pial, PIAL_VERTICES) ;
		      if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
			{
			  sprintf(fname, "sb.mgz") ;
			  MRIwrite(mri_source, fname) ; 
			  sprintf(fname, "tb.mgz") ;
			  MRIwrite(mri_target, fname) ;
			}

		      insert_ribbon_into_aseg(mri, mri, mris_white, mris_pial, h) ;
		      if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
			{
			  sprintf(fname, "sa.mgz") ;
			  MRIwrite(mri_source, fname) ; 
			  sprintf(fname, "ta.mgz") ;
			  MRIwrite(mri_target, fname) ;
			}
		      MRISfree(&mris_white) ; MRISfree(&mris_pial) ;
		    }
		}
	      if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
		{
		  sprintf(fname, "s.mgz") ;
		  MRIwrite(mri_source, fname) ; 
		  sprintf(fname, "t.mgz") ;
		  MRIwrite(mri_target, fname) ;
		}
	    }
	  GCAMinitLabels(gcam, mri_target) ;
	  GCAMsetVariances(gcam, 1.0) ;
	  mp.mri_dist_map = create_distance_transforms(mri_source, mri_target, NULL, 40.0, gcam) ;
	}
    }
  else  /* use a previously create morph and integrate it some more */
    {
      printf("using previously create gcam...\n") ;
      gcam = (GCA_MORPH *)(transform->xform) ;
      GCAMrasToVox(gcam, mri_source) ;
      if (use_aseg)
	{
	  GCAMinitLabels(gcam, mri_target) ;
	  GCAMsetVariances(gcam, 1.0) ;
	  mp.mri_dist_map = create_distance_transforms(mri_source, mri_target, NULL, 40.0, gcam) ;
	}
      else
	GCAMaddIntensitiesFromImage(gcam, mri_target) ;
    }
  if (gcam->width != mri_source->width ||
      gcam->height != mri_source->height ||
      gcam->depth != mri_source->depth)
    ErrorExit(ERROR_BADPARM, "%s: warning gcam (%d, %d, %d), doesn't match source vol (%d, %d, %d)",
	      Progname, gcam->width, gcam->height, gcam->depth,
	      mri_source->width, mri_source->height, mri_source->depth) ;
	
  mp.mri_diag = mri_source ;
  mp.diag_morph_from_atlas = 0 ;
  mp.diag_write_snapshots = 1 ;
  mp.diag_sample_type = use_aseg ? SAMPLE_NEAREST : SAMPLE_TRILINEAR ;
  mp.diag_volume = use_aseg ? GCAM_LABEL : GCAM_MEANS ;

  if (renormalize)
    GCAMnormalizeIntensities(gcam, mri_target) ;
  if (mp.write_iterations != 0)
    {
      char fname[STRLEN] ;
      MRI  *mri_gca ;
		
      if (getenv("DONT_COMPRESS"))
        sprintf(fname, "%s_target.mgh", mp.base_name) ;
      else
        sprintf(fname, "%s_target.mgz", mp.base_name) ;
      if (mp.diag_morph_from_atlas == 0)
      {
        printf("writing target volume to %s...\n", fname) ;
        MRIwrite(mri_target, fname) ;
        sprintf(fname, "%s_target", mp.base_name) ;
        MRIwriteImageViews(mri_target, fname, IMAGE_SIZE) ;
      }
      else
      {
        if (use_aseg)
          mri_gca = GCAMwriteMRI(gcam, NULL, GCAM_LABEL) ;
        else
        {
          mri_gca = MRIclone(mri_source, NULL) ;
          GCAMbuildMostLikelyVolume(gcam, mri_gca) ;
        }
	  printf("writing target volume to %s...\n", fname) ;
	  MRIwrite(mri_gca, fname) ;
	  sprintf(fname, "%s_target", mp.base_name) ;
	  MRIwriteImageViews(mri_gca, fname, IMAGE_SIZE) ;
	  MRIfree(&mri_gca) ;
	}
    }

  if (nozero)
    {
      printf("disabling zero nodes\n") ;
      GCAMignoreZero(gcam, mri_target) ;
    }
  mp.mri = mri_target ;
  if (mp.regrid == True && new_transform == 0)
    GCAMregrid(gcam, mri_target, PAD, &mp, &mri_source) ;

  mp.write_fname = out_fname ;
  GCAMregister(gcam, mri_source, &mp) ; // atlas is target, morph target into register with it
  if (apply_transform)
    {
      MRI *mri_aligned ;
      char   fname[STRLEN] ;
		
      FileNameRemoveExtension(out_fname, fname) ;
      strcat(fname, ".mgz") ;
      mri_aligned = GCAMmorphToAtlas(mp.mri, gcam, NULL, -1, mp.diag_sample_type) ;
      printf("writing transformed output volume to %s...\n", fname) ;
      MRIwrite(mri_aligned, fname) ;
      MRIfree(&mri_aligned) ;
    }
  printf("writing warp vector field to %s\n", out_fname) ;
  GCAMvoxToRas(gcam) ;
  GCAMwrite(gcam, out_fname) ;
  GCAMrasToVox(gcam, mri_source) ;

  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf("registration took %d minutes and %d seconds.\n", 
	 minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
예제 #3
0
int
main(int argc, char *argv[])
{
  char        **av, *out_name ;
  int          ac, nargs ;
  int          msec, minutes, seconds ;
  struct timeb start ;
  MRI_SURFACE  *mris ;
  GCA_MORPH    *gcam ;
  MRI          *mri = NULL ;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mris_interpolate_warp.c,v 1.5 2011/10/07 12:07:26 fischl Exp $", "$Name:  $");
  if (nargs && argc - nargs == 1)
  {
    exit (0);
  }
  argc -= nargs;

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

  TimerStart(&start) ;

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

  if (argc < 3)
  {
    usage_exit(1) ;
  }


  /*
    note that a "forward" morph means a retraction, so we reverse the order of the argvs here.
    This means that for every voxel in the inflated image we have a vector that points to where in
    the original image it came from, and *NOT* the reverse.
  */
  mris = MRISread(argv[2]) ;
  if (mris == NULL)
    ErrorExit(ERROR_NOFILE, "%s: could not read source surface %s\n", Progname,argv[2]) ;

  MRISsaveVertexPositions(mris, ORIGINAL_VERTICES) ;
  if (MRISreadVertexPositions(mris, argv[1]) != NO_ERROR)
    ErrorExit(ERROR_NOFILE, "%s: could not read target surface %s\n", Progname,argv[1]) ;

  if (like_vol_name == NULL)
  {
    mri = MRIallocSequence(mris->vg.width, mris->vg.height, mris->vg.depth, MRI_FLOAT, 3) ;
    MRIcopyVolGeomToMRI(mri, &mris->vg) ;
  }
  else
  {
    MRI *mri_tmp ;
    mri_tmp = MRIread(like_vol_name) ;
    if (mri_tmp == NULL)
    {
      ErrorExit(ERROR_NOFILE, "%s: could not like volume %s\n", like_vol_name) ;
    }
    mri = MRIallocSequence(mri_tmp->width, mri_tmp->height, mri_tmp->depth, MRI_FLOAT, 3) ;
    MRIcopyHeader(mri_tmp, mri) ;
    MRIfree(&mri_tmp) ;
  }
  if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
  {
    double xv, yv, zv ;
    VERTEX *v = &mris->vertices[0] ;
    MRISsurfaceRASToVoxel(mris, mri, v->x, v->y, v->z, &xv, &yv, &zv) ;
    printf("v 0: sras (%f, %f, %f) --> vox (%f, %f, %f)\n", v->x,v->y,v->z,xv,yv,zv);
    MRISsurfaceRASToVoxelCached(mris, mri, v->x, v->y, v->z, &xv, &yv, &zv) ;
    printf("v 0: sras (%f, %f, %f) --> vox (%f, %f, %f)\n", v->x,v->y,v->z,xv,yv,zv);
    DiagBreak() ;
  }
  {
    MRI *mri_tmp ;
    mri_tmp = expand_mri_to_fit_surface(mris, mri) ;
    MRIfree(&mri) ; mri = mri_tmp ;
  }
  write_surface_warp_into_volume(mris, mri, niter) ;

  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
    MRIwrite(mri, "warp.mgz") ;
  gcam = GCAMalloc(mri->width, mri->height, mri->depth) ;
  GCAMinitVolGeom(gcam, mri, mri) ;
  GCAMremoveSingularitiesAndReadWarpFromMRI(gcam, mri) ;
//  GCAMreadWarpFromMRI(gcam, mri) ;
  //  GCAsetVolGeom(gca, &gcam->atlas);
#if 0
  gcam->gca = gcaAllocMax(1, 1, 1,
			  mri->width, mri->height,
			  mri->depth,
			  0, 0) ;
 GCAMinit(gcam, mri, NULL, NULL, 0) ;
#endif
#if 0
  GCAMinvert(gcam, mri) ;
  GCAMwriteInverseWarpToMRI(gcam, mri) ;
  GCAMremoveSingularitiesAndReadWarpFromMRI(gcam, mri) ;  // should be inverse now
#endif
  if (mri_in)
  {
    MRI *mri_warped, *mri_tmp ;
    printf("applying warp to %s and writing to %s\n", mri_in->fname, out_fname) ;
    mri_tmp = MRIextractRegionAndPad(mri_in, NULL, NULL, pad) ; MRIfree(&mri_in) ; mri_in = mri_tmp ;
    mri_warped = GCAMmorphToAtlas(mri_in, gcam, NULL, -1, SAMPLE_TRILINEAR) ;
    MRIwrite(mri_warped, out_fname) ;
    if (Gdiag_no >= 0)
    {
      double  xi, yi, zi, xo, yo, zo, val;
      int     xp, yp, zp ;
      GCA_MORPH_NODE *gcamn ;

      VERTEX *v = &mris->vertices[Gdiag_no] ;
      MRISsurfaceRASToVoxelCached(mris, mri, v->origx, v->origy, v->origz, &xi, &yi, &zi) ;
      MRISsurfaceRASToVoxelCached(mris, mri, v->x, v->y, v->z, &xo, &yo, &zo) ;
      printf("surface vertex %d: inflated (%2.0f, %2.0f, %2.0f), orig (%2.0f, %2.0f, %2.0f)\n", Gdiag_no, xi, yi, zi, xo, yo, zo) ;
      MRIsampleVolume(mri_in, xo, yo, zo, &val) ;
      xp = nint(xi) ; yp = nint(yi) ; zp = nint(zi) ;
      gcamn = &gcam->nodes[xp][yp][zp] ;
      printf("warp = (%2.1f, %2.1f, %2.1f), orig (%2.1f %2.1f %2.1f) = %2.1f \n", 
	     gcamn->x, gcamn->y, gcamn->z,
	     gcamn->origx, gcamn->origy, gcamn->origz,val) ;
      DiagBreak() ;
    }
  }
  if (no_write == 0)
  {
    out_name = argv[3] ;
    GCAMwrite(gcam, out_name) ;
  }
  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  fprintf(stderr, "warp field calculation took %d minutes and %d seconds.\n", minutes, seconds) ;
  exit(0) ;
  return(0) ;
}