Example #1
0
static int
write_snapshot(MRI *mri_target, MRI *mri_source, MATRIX *m_vox_xform, 
	       GCA_MORPH_PARMS *parms, int fno, int conform, char *in_fname)
{
  MRI *mri_aligned ;
  char fname[STRLEN] ;

  if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
    {
      printf("source->target vox->vox transform:\n") ;
      MatrixPrint(stdout, m_vox_xform) ;
    }
  if (conform || 1)
    {
      mri_aligned = MRIalloc(mri_target->width, mri_target->height,
			     mri_target->depth,mri_source->type);
      MRIcopyHeader(mri_target, mri_aligned) ;
      MRIlinearTransformInterp(mri_source, mri_aligned, m_vox_xform, SAMPLE_NEAREST);
    }
  else
    {
      mri_aligned = MRITransformedCenteredMatrix(mri_source, mri_target, m_vox_xform) ;
    }
  if (in_fname)
    sprintf(fname, "%s_%s", parms->base_name, in_fname) ;
  else
    sprintf(fname, "%s_%03d", parms->base_name, fno) ;
  MRIwriteImageViews(mri_aligned, fname, IMAGE_SIZE) ;
  if (in_fname)
    sprintf(fname, "%s_%s.mgz", parms->base_name, in_fname) ;
  else
    sprintf(fname, "%s_%03d.mgz", parms->base_name, fno) ;
  printf("writing snapshot to %s...\n", fname) ;
  MRIwrite(mri_aligned, fname) ;
  MRIfree(&mri_aligned) ;

  {
#if 0
    mri_aligned = MRIsrcTransformedCentered(mri_source, mri_target, m_vox_xform,
					    SAMPLE_NEAREST) ;
#else
    mri_aligned = MRITransformedCenteredMatrix(mri_source, mri_target, m_vox_xform) ;
#endif
    if (in_fname)
      sprintf(fname, "orig_%s_%s.mgz", parms->base_name, in_fname) ;
    else
      sprintf(fname, "orig_%s_%03d.mgz", parms->base_name, fno) ;
    printf("writing snapshot to %s...\n", fname) ;
    MRIwrite(mri_aligned, fname) ;
    MRIfree(&mri_aligned) ;
  }

  return(NO_ERROR) ;
}
static MATRIX *
initialize_transform(MRI *mri_in, MRI *mri_ref, MP *parms) {
  MATRIX *m_L ;

  fprintf(stderr, "initializing alignment using PCA...\n") ;
  if (Gdiag & DIAG_WRITE && parms->write_iterations > 0) {
    MRIwriteImageViews(parms->mri_ref, "ref", IMAGE_SIZE) ;
    MRIwriteImageViews(parms->mri_in, "before_pca", IMAGE_SIZE) ;
  }

  if (nopca)
    m_L = MatrixIdentity(3, NULL) ;
  else
    m_L = compute_pca(mri_in, mri_ref) ;

  init_scaling(mri_in, mri_ref, m_L) ;
#if 0
  init_translation(mri_in, mri_ref, m_L) ; /* in case PCA failed */
#endif

  /* convert it to RAS mm coordinates */
  MRIvoxelXformToRasXform(mri_in, mri_ref, m_L, m_L) ;

  if (Gdiag & DIAG_SHOW) {
    printf("initial transform:\n") ;
    MatrixPrint(stdout, m_L) ;
  }
  if (Gdiag & DIAG_WRITE && parms->write_iterations > 0) {
    MRI *mri_aligned ;

    mri_aligned = MRIapplyRASlinearTransform(parms->mri_in, NULL, m_L) ;
    MRIwriteImageViews(mri_aligned, "after_pca", IMAGE_SIZE) ;
    MRIfree(&mri_aligned) ;
  }
  return(m_L) ;
}
static int
register_mri(MRI *mri_in, MRI *mri_ref, MORPH_PARMS *parms, MATRIX *m_L) {
  MRI     *mri_in_windowed, *mri_ref_windowed ;

  fprintf(stderr, "aligning volume with average...\n") ;

  if (window_size > 0) {
    double in_means[3], ref_means[3] ;

    MRIcenterOfMass(mri_in, in_means, 0) ;
    MRIcenterOfMass(mri_ref, ref_means, 0) ;
    printf("windowing ref around (%d, %d, %d) and input around (%d, %d, %d)\n",
           nint(ref_means[0]), nint(ref_means[1]), nint(ref_means[2]),
           nint(in_means[0]), nint(in_means[1]), nint(in_means[2])) ;
    mri_in_windowed =
      MRIwindow(mri_in, NULL, WINDOW_HANNING,nint(in_means[0]),
                nint(in_means[1]), nint(in_means[2]),window_size);
    mri_ref_windowed =
      MRIwindow(mri_ref,NULL,WINDOW_HANNING,nint(ref_means[0]),
                nint(ref_means[1]), nint(ref_means[2]),window_size);
    mri_in = mri_in_windowed ;
    mri_ref = mri_ref_windowed ;
  }

  MRIrigidAlign(mri_in, mri_ref, parms, m_L) ;

  fprintf(stderr, "final transform:\n") ;
  MatrixPrint(stderr, parms->lta->xforms[0].m_L) ;
  fprintf(stderr, "\n") ;

  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) {
    MRI *mri_aligned ;

    mri_aligned =
      MRIapplyRASlinearTransform(mri_in, NULL, parms->lta->xforms[0].m_L) ;
    MRIwriteImageViews(mri_aligned, "after_alignment", IMAGE_SIZE) ;
    MRIfree(&mri_aligned) ;
  }


  MatrixCopy(parms->lta->xforms[0].m_L, m_L) ;
  return(NO_ERROR) ;
}
Example #4
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) ;
}
static MATRIX *
align_pca(MRI *mri_in, MRI *mri_ref) {
  int    row, col, i ;
  float  dot ;
  MATRIX *m_ref_evectors = NULL, *m_in_evectors = NULL ;
  float  in_evalues[3], ref_evalues[3] ;
  double  ref_means[3], in_means[3] ;
#if 0
  MRI     *mri_in_windowed, *mri_ref_windowed ;

  mri_in_windowed = MRIwindow(mri_in, NULL, WINDOW_HANNING,127,127,127,100.0f);
  mri_ref_windowed = MRIwindow(mri_ref,NULL,WINDOW_HANNING,127,127,127,100.0f);
  if (Gdiag & DIAG_WRITE) {
    MRIwriteImageViews(mri_in_windowed, "in_windowed", 400) ;
    MRIwriteImageViews(mri_ref_windowed, "ref_windowed", 400) ;
  }
#endif

  if (!m_ref_evectors)
    m_ref_evectors = MatrixAlloc(3,3,MATRIX_REAL) ;
  if (!m_in_evectors)
    m_in_evectors = MatrixAlloc(3,3,MATRIX_REAL) ;

  MRIprincipleComponents(mri_ref, m_ref_evectors, ref_evalues,
                         ref_means, thresh_low);
  MRIprincipleComponents(mri_in,m_in_evectors,in_evalues,in_means,thresh_low);

  /* check to make sure eigenvectors aren't reversed */
  for (col = 1 ; col <= 3 ; col++) {
#if 0
    float theta ;
#endif

    for (dot = 0.0f, row = 1 ; row <= 3 ; row++)
      dot += m_in_evectors->rptr[row][col] * m_ref_evectors->rptr[row][col] ;

    if (dot < 0.0f) {
      printf("WARNING: mirror image detected in eigenvector #%d\n",
             col) ;
      dot *= -1.0f ;
      for (row = 1 ; row <= 3 ; row++)
        m_in_evectors->rptr[row][col] *= -1.0f ;
    }
#if 0
    theta = acos(dot) ;
    printf("angle[%d] = %2.1f\n", col, DEGREES(theta)) ;
#endif
  }
  printf("ref_evectors = \n") ;
  for (i = 1 ; i <= 3 ; i++)
    printf("\t\t%2.2f    %2.2f    %2.2f\n",
           m_ref_evectors->rptr[i][1],
           m_ref_evectors->rptr[i][2],
           m_ref_evectors->rptr[i][3]) ;

  printf("\nin_evectors = \n") ;
  for (i = 1 ; i <= 3 ; i++)
    printf("\t\t%2.2f    %2.2f    %2.2f\n",
           m_in_evectors->rptr[i][1],
           m_in_evectors->rptr[i][2],
           m_in_evectors->rptr[i][3]) ;

  return(pca_matrix(m_in_evectors, in_means,m_ref_evectors, ref_means)) ;
}
static MRI *
align_with_average(MRI *mri_src, MRI *mri_avg) {
  MRI     *mri_aligned, *mri_in_red, *mri_ref_red ;
  MRI     *mri_in_windowed, *mri_ref_windowed, *mri_in_tmp, *mri_ref_tmp ;
  int     i ;
  MATRIX  *m_L ;

  printf("initializing alignment using PCA...\n") ;
  if (Gdiag & DIAG_WRITE) {
    MRIwriteImageViews(mri_avg, "ref", 400) ;
    MRIwriteImageViews(mri_src, "before_pca", 400) ;
  }

  m_L = align_pca(mri_src, mri_avg) ;
  if (Gdiag & DIAG_SHOW) {
    printf("initial transform:\n") ;
    MatrixPrint(stdout, m_L) ;
  }
  if (Gdiag & DIAG_WRITE) {
    if (sinc_flag)
      mri_aligned = MRIsincTransform(mri_src, NULL, m_L,sinchalfwindow) ;
    else
      mri_aligned = MRIlinearTransform(mri_src, NULL, m_L) ;
    MRIwriteImageViews(mri_aligned, "after_pca", 400) ;
    MRIfree(&mri_aligned) ;
  }

  printf("aligning volume with average...\n") ;

  if (window_flag) {
    mri_in_windowed =
      MRIwindow(mri_src, NULL, WINDOW_HANNING,127,127,127,100.0f);
    mri_ref_windowed =
      MRIwindow(mri_avg,NULL,WINDOW_HANNING,127,127,127,100.0f);
    mri_src = mri_in_windowed ;
    mri_avg = mri_ref_windowed ;
  }

  MRIscaleMeanIntensities(mri_src, mri_avg, mri_src);

  mri_in_red = mri_in_tmp = MRIcopy(mri_src, NULL) ;
  mri_ref_red = mri_ref_tmp = MRIcopy(mri_avg, NULL) ;
  for (i = 0 ; i < nreductions ; i++) {
    mri_in_red = MRIreduceByte(mri_in_tmp, NULL) ;
    mri_ref_red = MRIreduceByte(mri_ref_tmp,NULL);
    MRIfree(&mri_in_tmp);
    MRIfree(&mri_ref_tmp) ;
    mri_in_tmp = mri_in_red ;
    mri_ref_tmp = mri_ref_red ;
  }
  parms.mri_ref = mri_avg ;
  parms.mri_in = mri_src ;  /* for diagnostics */
  MRIrigidAlign(mri_in_red, mri_ref_red, &parms, m_L) ;

  printf("transforming input volume...\n") ;
  MatrixPrint(stderr, parms.lta->xforms[0].m_L) ;
  printf("\n") ;

  if (sinc_flag)
    mri_aligned = MRIsincTransform(mri_src, NULL, parms.lta->xforms[0].m_L,sinchalfwindow) ;
  else
    mri_aligned = MRIlinearTransform(mri_src, NULL, parms.lta->xforms[0].m_L) ;
  if (Gdiag & DIAG_WRITE)
    MRIwriteImageViews(mri_aligned, "after_alignment", 400) ;
  MRIfree(&mri_in_red) ;
  MRIfree(&mri_ref_red) ;

  return(mri_aligned) ;
}
int
main(int argc, char *argv[]) {
  char         *ref_fname, *in_fname, *out_fname, fname[STRLEN], **av ;
  MRI          *mri_ref, *mri_in, *mri_orig, *mri_in_red, *mri_ref_red,
  *mri_in_tmp, *mri_ref_tmp, *mri_ref_orig, *mri_in_orig ;
  int          ac, nargs, i, msec, minutes, seconds ;
  struct timeb start ;
  MATRIX       *m_L ;

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

  parms.mri_crop = NULL ;
  parms.l_intensity = 1.0f ;
  parms.niterations = 100 ;
  parms.levels = -1 ;   /* use default */
  parms.dt = 1e-6 ;  /* was 5e-6 */
  parms.tol = INTEGRATION_TOL*5 ;

  parms.dt = 5e-6 ;  /* was 5e-6 */
  parms.tol = 1e-3 ;
  parms.momentum = 0.8 ;
  parms.max_levels = MAX_LEVELS ;
  parms.factor = 1.0 ;
  parms.niterations = 25 ;
  Progname = argv[0] ;


  DiagInit(NULL, NULL, NULL) ;
  ErrorInit(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)
    ErrorExit(ERROR_BADPARM,
              "usage: %s <in brain> <template> <output file name>\n",
              Progname) ;

  in_fname = argv[1] ;
  ref_fname = argv[2] ;
  if (xform_mean_fname) {
    int   sno, nsubjects ;
    FILE  *fp ;

    parms.m_xform_mean = MatrixAsciiRead(xform_mean_fname, NULL) ;
    if (!parms.m_xform_mean)
      ErrorExit(Gerror, "%s: could not read parameter means from %s",
                Progname, xform_mean_fname) ;

    fp = fopen(xform_covariance_fname, "r") ;
    if (!fp)
      ErrorExit(ERROR_NOFILE, "%s: could not read covariances from %s",
                Progname, xform_covariance_fname) ;

    fscanf(fp, "nsubjects=%d", &nsubjects) ;
    printf("reading %d transforms...\n", nsubjects) ;

    parms.m_xforms = (MATRIX **)calloc(nsubjects, sizeof(MATRIX *)) ;
    if (!parms.m_xforms)
      ErrorExit(ERROR_NOMEMORY, "%s: could not allocate array of %d xforms",
                Progname, nsubjects) ;
    for (sno = 0 ; sno < nsubjects ; sno++) {
      parms.m_xforms[sno] = MatrixAsciiReadFrom(fp, NULL) ;
      if (!parms.m_xforms[sno])
        ErrorExit(ERROR_NOMEMORY, "%s: could not allocate %dth xform",
                  Progname, sno) ;

    }
    parms.m_xform_covariance = MatrixAsciiReadFrom(fp, NULL) ;
    if (!parms.m_xform_covariance)
      ErrorExit(Gerror, "%s: could not read parameter covariance from %s",
                Progname, xform_covariance_fname) ;
    fclose(fp) ;
    parms.l_priors = l_priors ;
    parms.nxforms = nsubjects ;
  }
  out_fname = argv[3] ;
  FileNameOnly(out_fname, fname) ;
  FileNameRemoveExtension(fname, fname) ;
  strcpy(parms.base_name, fname) ;
  fprintf(stderr, "logging results to %s.log\n", parms.base_name) ;

  TimerStart(&start) ;
  fprintf(stderr, "reading '%s'...\n", ref_fname) ;
  fflush(stderr) ;
  mri_ref = MRIread(ref_fname) ;
  if (!mri_ref)
    ErrorExit(ERROR_NOFILE, "%s: could not open reference volume %s.\n",
              Progname, ref_fname) ;
  if (mri_ref->type != MRI_UCHAR) {
    MRI *mri_tmp ;

    mri_tmp = MRIchangeType(mri_ref, MRI_UCHAR, 0.0, 0.999, FALSE) ;
    MRIfree(&mri_ref) ;
    mri_ref = mri_tmp ;
  }

  if (var_fname)  /* read in a volume of standard deviations */
  {
    MRI *mri_var, *mri_tmp ;

    fprintf(stderr, "reading '%s'...\n", var_fname) ;
    mri_var = MRIread(var_fname) ;
    if (!mri_var)
      ErrorExit(ERROR_NOFILE, "%s: could not open variance volume %s.\n",
                Progname, var_fname) ;
    mri_tmp = MRIconcatenateFrames(mri_ref, mri_var, NULL) ;
    MRIfree(&mri_var) ;
    MRIfree(&mri_ref) ;
    mri_ref = mri_tmp ;
  }
  fprintf(stderr, "reading '%s'...\n", in_fname) ;
  fflush(stderr) ;
  mri_orig = mri_in = MRIread(in_fname) ;
  if (!mri_in)
    ErrorExit(ERROR_NOFILE, "%s: could not open input volume %s.\n",
              Progname, in_fname) ;
  if (mri_in->type != MRI_UCHAR) {
    MRI *mri_tmp ;

    mri_orig = mri_tmp = MRIchangeType(mri_in, MRI_UCHAR, 0.0, 0.999, FALSE) ;
    MRIfree(&mri_in) ;
    mri_in = mri_tmp ;
  }

  /* make sure they are the same size */
  if (mri_in->width  != mri_ref->width ||
      mri_in->height != mri_ref->height  ||
      mri_in->depth  != mri_ref->depth) {
    int  width, height, depth ;
    MRI  *mri_tmp ;

    width = MAX(mri_in->width, mri_ref->width) ;
    height = MAX(mri_in->height, mri_ref->height) ;
    depth = MAX(mri_in->depth, mri_ref->depth) ;
    mri_tmp = MRIalloc(width, height, depth, MRI_UCHAR) ;
    MRIextractInto(mri_in, mri_tmp, 0, 0, 0,
                   mri_in->width, mri_in->height, mri_in->depth, 0, 0, 0) ;
#if 0
    MRIfree(&mri_in) ;
#else
    parms.mri_in = mri_in ;
#endif
    mri_in = mri_orig = mri_tmp ;

    mri_tmp = MRIallocSequence(width, height,depth,MRI_UCHAR,mri_ref->nframes);
    MRIextractInto(mri_ref, mri_tmp, 0, 0, 0,
                   mri_ref->width, mri_ref->height, mri_ref->depth, 0, 0, 0) ;
#if 0
    MRIfree(&mri_ref) ;
#else
    parms.mri_in = mri_in ;
#endif
    mri_ref = mri_tmp ;
  }


  if (!FZERO(tx) || !FZERO(ty) || !FZERO(tz)) {
    MRI *mri_tmp ;

    fprintf(stderr, "translating second volume by (%2.1f, %2.1f, %2.1f)\n",
            tx, ty, tz) ;
    mri_tmp = MRItranslate(mri_in, NULL, tx, ty, tz) ;
    MRIfree(&mri_in) ;
    mri_in = mri_tmp ;
  }

  if (!FZERO(rzrot)) {
    MRI *mri_tmp ;

    fprintf(stderr,
            "rotating second volume by %2.1f degrees around Z axis\n",
            (float)DEGREES(rzrot)) ;
    mri_tmp = MRIrotateZ_I(mri_in, NULL, rzrot) ;
    MRIfree(&mri_in) ;
    mri_in = mri_tmp ;
  }
  if (!FZERO(rxrot)) {
    MRI *mri_tmp ;

    fprintf(stderr,
            "rotating second volume by %2.1f degrees around X axis\n",
            (float)DEGREES(rxrot)) ;
    mri_tmp = MRIrotateX_I(mri_in, NULL, rxrot) ;
    MRIfree(&mri_in) ;
    mri_in = mri_tmp ;
  }
  if (!FZERO(ryrot)) {
    MRI *mri_tmp ;

    fprintf(stderr,
            "rotating second volume by %2.1f degrees around Y axis\n",
            (float)DEGREES(ryrot)) ;
    mri_tmp = MRIrotateY_I(mri_in, NULL, ryrot) ;
    MRIfree(&mri_in) ;
    mri_in = mri_tmp ;
  }

  if (!transform_loaded)   /* wasn't preloaded */
    parms.lta = LTAalloc(1, mri_in) ;

  if (!FZERO(blur_sigma)) {
    MRI *mri_kernel, *mri_tmp ;

    mri_kernel = MRIgaussian1d(blur_sigma, 100) ;
    mri_tmp = MRIconvolveGaussian(mri_in, NULL, mri_kernel) ;
    mri_in = mri_tmp ;
    MRIfree(&mri_kernel) ;
  }
  MRIscaleMeanIntensities(mri_in, mri_ref, mri_in);

  mri_ref_orig = mri_ref ;
  mri_in_orig = mri_in ;
  if (nreductions > 0) {
    mri_in_red = mri_in_tmp = MRIcopy(mri_in, NULL) ;
    mri_ref_red = mri_ref_tmp = MRIcopy(mri_ref, NULL) ;
    for (i = 0 ; i < nreductions ; i++) {
      mri_in_red = MRIreduceByte(mri_in_tmp, NULL) ;
      mri_ref_red = MRIreduceMeanAndStdByte(mri_ref_tmp,NULL);
      MRIfree(&mri_in_tmp);
      MRIfree(&mri_ref_tmp) ;
      mri_in_tmp = mri_in_red ;
      mri_ref_tmp = mri_ref_red ;
    }
    mri_in = mri_in_red ;
    mri_ref = mri_ref_red ;
  }
  /* for diagnostics */
  if (full_res) {
    parms.mri_ref = mri_ref ;
    parms.mri_in = mri_in ;
  } else {
    parms.mri_ref = mri_ref_orig ;
    parms.mri_in = mri_in_orig ;
  }

  m_L = initialize_transform(mri_in, mri_ref, &parms) ;

  if (use_gradient) {
    MRI  *mri_in_mag, *mri_ref_mag, *mri_grad, *mri_mag ;

    printf("computing gradient magnitude of input image...\n") ;
    mri_mag = MRIalloc(mri_in->width, mri_in->height, mri_in->depth,MRI_FLOAT);
    MRIcopyHeader(mri_in, mri_mag) ;
    mri_grad = MRIsobel(mri_in, NULL, mri_mag) ;
    MRIfree(&mri_grad) ;

    /* convert it to ubytes */
    MRIvalScale(mri_mag, mri_mag, 0.0f, 255.0f) ;
    mri_in_mag = MRIclone(mri_in, NULL) ;
    MRIcopy(mri_mag, mri_in_mag) ;
    MRIfree(&mri_mag) ;

    /* now compute gradient of ref image */
    printf("computing gradient magnitude of reference image...\n") ;
    mri_mag = MRIalloc(mri_ref->width, mri_ref->height, mri_ref->depth,MRI_FLOAT);
    MRIcopyHeader(mri_ref, mri_mag) ;
    mri_grad = MRIsobel(mri_ref, NULL, mri_mag) ;
    MRIfree(&mri_grad) ;

    /* convert it to ubytes */
    MRIvalScale(mri_mag, mri_mag, 0.0f, 255.0f) ;
    mri_ref_mag = MRIclone(mri_ref, NULL) ;
    MRIcopy(mri_mag, mri_ref_mag) ;
    MRIfree(&mri_mag) ;

    register_mri(mri_in_mag, mri_ref_mag, &parms, m_L) ;
    MRIfree(&mri_in_mag) ;
    MRIfree(&mri_ref_mag) ;
  }
  register_mri(mri_in, mri_ref, &parms, m_L) ;
  if (check_crop_flag)  /* not working yet! */
  {
    printf("searching for cropped regions in the input image...\n") ;
    parms.mri_crop = find_cropping(mri_orig, mri_ref, &parms) ;
    MRIwrite(parms.mri_crop, "crop.mgh") ;
    register_mri(mri_in, mri_ref, &parms, m_L) ;
  }

  if (voxel_coords) {
    printf("transforming xform to voxel coordinates...\n") ;
    MRIrasXformToVoxelXform(mri_in_orig, mri_ref_orig,
                            parms.lta->xforms[0].m_L,
                            parms.lta->xforms[0].m_L);
    if (Gdiag & DIAG_WRITE) {
      MRI *mri_tmp ;

      mri_tmp = MRIlinearTransform(mri_in_orig, NULL,parms.lta->xforms[0].m_L);
      MRIwriteImageViews(mri_tmp, "morphed", IMAGE_SIZE) ;
      MRIfree(&mri_tmp) ;
    }
  }
  // save src and target info in lta
  getVolGeom(mri_in_orig, &parms.lta->xforms[0].src);
  getVolGeom(mri_ref_orig, &parms.lta->xforms[0].dst);
  fprintf(stderr, "writing output transformation to %s...\n", out_fname) ;
  if (invert_flag) {
    MATRIX *m_tmp ;

    m_tmp = MatrixInverse(parms.lta->xforms[0].m_L, NULL) ;
    MatrixFree(&parms.lta->xforms[0].m_L) ;
    // change src and dst
    getVolGeom(mri_in_orig, &parms.lta->xforms[0].dst);
    getVolGeom(mri_ref_orig, &parms.lta->xforms[0].src);
    parms.lta->xforms[0].m_L = m_tmp ;
  }
  //
  LTAwriteEx(parms.lta, out_fname) ;
  //
  if (mri_ref)
    MRIfree(&mri_ref) ;
  if (mri_in)
    MRIfree(&mri_in) ;
  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  fprintf(stderr, "registration took %d minutes and %d seconds.\n",
          minutes, seconds) ;
  exit(0) ;
  return(0) ;
}