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