Example #1
0
int
IOPNormalize(IOP *iop)
{
  int j,k,jc;
  double sum, val;

  for (j=0;j<iop->ndipoles;j++)
  {
    sum = 0;
    for (jc=0;jc<iop->ndipoles_per_location;jc++)
      for (k=0;k<iop->nchan;k++)
      {
        val = *MATRIX_RELT(iop->m_iop,j*iop->ndipoles_per_location+jc+1,k+1);
        sum += SQR(val);
      }

    sum = sqrt(sum);
    if (!DZERO(sum))
    {
      for (jc=0;jc<iop->ndipoles_per_location;jc++)
        for (k=0;k<iop->nchan;k++)
          *MATRIX_RELT(iop->m_iop,j*iop->ndipoles_per_location+jc+1,k+1)/= sum;
    }
  }
  return(NO_ERROR) ;
}
/*-----------------------------------------------------
        Parameters:

        Returns value:

        Description
------------------------------------------------------*/
static int
init_translation(MRI *mri_in, MRI *mri_ref, MATRIX *m_L) {
  MATRIX *m_translation ;
  float  in_means[4], ref_means[4] ;
  double dx, dy, dz ;

  m_translation = MatrixIdentity(4, NULL) ;
  MRIfindCenterOfBrain(mri_in, in_means, in_means+1, in_means+2) ;
  MRIfindCenterOfBrain(mri_ref, ref_means, ref_means+1, ref_means+2) ;
  dx = (double)(ref_means[0] - in_means[0]) * mri_in->thick ;
  dy = (double)(ref_means[1] - in_means[1]) * mri_in->thick ;
  dz = (double)(ref_means[2] - in_means[2]) * mri_in->thick ;
  if (Gdiag & DIAG_SHOW) {
    fprintf(stderr, "centering template around (%d,%d,%d) and input around"
            " (%d,%d,%d)\n",
            (int)ref_means[0], (int)ref_means[1], (int)ref_means[2],
            (int)in_means[0], (int)in_means[1], (int)in_means[2]) ;
    fprintf(stderr, "initial translation = (%2.0f, %2.0f, %2.0f).\n",dx,dy,dz);
  }
  *MATRIX_RELT(m_translation, 1, 4) = dx ;
  *MATRIX_RELT(m_translation, 2, 4) = dy ;
  *MATRIX_RELT(m_translation, 3, 4) = dz ;
  MatrixMultiply(m_translation, m_L, m_L) ;
  MatrixFree(&m_translation) ;
  return(NO_ERROR) ;
}
static int
test(MRI *mri1, MRI *mri2, MRI *mri3, MATRIX *m_vol1_to_vol2_ras) {
  VECTOR *v_test, *v_vox ;
  float  x_ras1, y_ras1, z_ras1, x_ras2, y_ras2, z_ras2, x_vox1, y_vox1,
  z_vox1, x_vox2, y_vox2, z_vox2 ;
  MATRIX  *m_vol2_vox2ras, *m_vol2_ras2vox, *m_vol1_ras2vox, *m_vol1_vox2ras,
  *m_vol3_ras2vox, *m_vol3_vox2ras ;
  int     val ;


  v_test = VectorAlloc(4, MATRIX_REAL) ;
  m_vol1_vox2ras = MRIgetVoxelToRasXform(mri1) ;
  m_vol2_vox2ras = MRIgetVoxelToRasXform(mri2) ;
  m_vol1_ras2vox = MRIgetRasToVoxelXform(mri1) ;
  m_vol2_ras2vox = MRIgetRasToVoxelXform(mri2) ;
  m_vol3_vox2ras = MRIgetVoxelToRasXform(mri3) ;
  m_vol3_ras2vox = MRIgetRasToVoxelXform(mri3) ;

  x_ras1 = 126.50 ;
  y_ras1 = -125.500 ;
  z_ras1 = 127.50 ;
  V3_X(v_test) = x_ras1 ;
  V3_Y(v_test) = y_ras1 ;
  V3_Z(v_test) = z_ras1 ;
  *MATRIX_RELT(v_test, 4, 1) = 1.0 ;
  v_vox = MatrixMultiply(m_vol1_ras2vox, v_test, NULL) ;
  x_vox1 = V3_X(v_vox) ;
  y_vox1 = V3_Y(v_vox) ;
  z_vox1 = V3_Z(v_vox) ;
  val = MRISvox(mri1, nint(x_vox1), nint(y_vox1), nint(z_vox1)) ;
  printf("VOL1: ras (%1.1f, %1.1f, %1.1f) --> VOX (%1.1f, %1.1f, %1.1f) = %d\n",
         x_ras1, y_ras1, z_ras1, x_vox1, y_vox1, z_vox1, val) ;


  x_ras2 = 76.5421 ;
  y_ras2 = 138.5352 ;
  z_ras2 = 96.0910 ;
  V3_X(v_test) = x_ras2 ;
  V3_Y(v_test) = y_ras2 ;
  V3_Z(v_test) = z_ras2 ;
  *MATRIX_RELT(v_test, 4, 1) = 1.0 ;
  v_vox = MatrixMultiply(m_vol2_ras2vox, v_test, NULL) ;
  x_vox2 = V3_X(v_vox) ;
  y_vox2 = V3_Y(v_vox) ;
  z_vox2 = V3_Z(v_vox) ;
  val = MRISvox(mri2, nint(x_vox2), nint(y_vox2), nint(z_vox2)) ;
  printf("VOL2: ras (%2.1f, %2.1f, %2.1f) --> VOX (%2.1f, %2.1f, %2.1f) = %d\n",
         x_ras2, y_ras2, z_ras2, x_vox2, y_vox2, z_vox2, val) ;



  MatrixFree(&v_test) ;
  return(NO_ERROR) ;
}
Example #4
0
void LayerDTI::InitializeDTIColorMap()
{
  vtkImageData* rasDTI = m_vectorSource->GetImageOutput();
  int* dim = rasDTI->GetDimensions();
  int nSize = dim[0]*dim[1]*dim[2];
  double v[4] = { 0, 0, 0, 1 };
  int c[3];
  vtkDataArray* vectors = rasDTI->GetPointData()->GetScalars();
  vtkFloatArray* fas = vtkFloatArray::New();
  fas->DeepCopy( m_imageData->GetPointData()->GetScalars() );
  m_imageData->SetNumberOfScalarComponents( 2 );
  m_imageData->AllocateScalars();
  vtkMatrix4x4* rotation_mat = vtkMatrix4x4::New();
  rotation_mat->Identity();
  MATRIX* reg = m_vectorSource->GetRegMatrix();
  if ( reg )
  {
    for ( int i = 0; i < 3; i++ )
    {
      for ( int j = 0; j < 3; j++ )
      {
        rotation_mat->SetElement( j, i, *MATRIX_RELT( reg, i+1, j+1 ) );
      }
    }
  }
  for ( int i = 0; i < nSize; i++ )
  {
    vectors->GetTuple( i, v );
    rotation_mat->MultiplyPoint( v, v );
    vtkMath::Normalize( v );
    double fa = fas->GetComponent( i, 0 );
    for ( int j = 0; j < 3; j++ )
    {
      c[j] = (int)(fabs(v[j]) * fa * 64);
      if ( c[j] > 63 )
      {
        c[j] = 63;
      }
    }
    float scalar = c[0]*64*64 + c[1]*64 + c[2];
    int x = i%dim[0];
    int y = (i/dim[0])%dim[1];
    int z = i/(dim[0]*dim[1]);
    m_imageData->SetScalarComponentFromFloat( x, y, z, 0, fa );
    m_imageData->SetScalarComponentFromFloat( x, y, z, 1, scalar );
    /*
    if ( wnd && nSize >= 5 && i%(nSize/5) == 0 )
    {
      event.SetInt( event.GetInt() + nProgressStep );
      wxPostEvent( wnd, event );
    }
    */
  }
  rotation_mat->Delete();
  fas->Delete();
}
static int
uniform_region(GCA *gca, MRI *mri, TRANSFORM *transform,
               int x, int y, int z,
               int wsize, GCA_SAMPLE *gcas,
               float nsigma)
{
  int   xk, yk, zk, whalf, xi, yi, zi, n, frame ;
  Real   val0, val, sigma, min_val,max_val, thresh ;
  MATRIX *m ;
  GC1D   *gc ;

  gc = GCAfindSourceGC(gca, mri, transform, x, y, z, gcas->label) ;
  if (!gc)
    return(0) ;
  m = load_covariance_matrix(gc, NULL, gca->ninputs) ;

  whalf = (wsize-1)/2 ;
  for (n = 0 ; n < gca->ninputs ; n++)
  {
    sigma = sqrt(*MATRIX_RELT(m, n+1, n+1)) ;
    MRIsampleVolumeFrame(mri, (Real)x, (Real)y, (Real)z, n, &val0) ;
    if (sigma < 0.05*val0)   /* don't let it be too small */
      sigma = 0.05*val0 ;
    if (sigma > 0.1*val0)    /* don't let it be too big */
      sigma = 0.1*val0 ;
    min_val = max_val = val0 ;
    thresh = nsigma*sigma ;

    for (frame = 0 ; frame < mri->nframes ; frame++)
    for (xk = -whalf ; xk <= whalf ; xk++)
    {
      xi = mri->xi[x+xk] ;
      for (yk = -whalf ; yk <= whalf ; yk++)
      {
        yi = mri->yi[y+yk] ;
        for (zk = -whalf ; zk <= whalf ; zk++)
        {
          zi = mri->zi[z+zk] ;
          MRIsampleVolumeFrame
            (mri, (Real)xi, (Real)yi, (Real)zi, frame, &val) ;
          if (val < min_val)
            min_val = val ;
          if (val > max_val)
            max_val = val ;
          if (fabs(val-val0) > thresh ||
              fabs(max_val-min_val) > thresh)
            return(0) ;
        }
      }
    }
  }

  MatrixFree(&m) ;
  return(1) ;
}
Example #6
0
static LTA  *
ltaFSLread(const char *fname) {
  LTA              *lta ;
  LINEAR_TRANSFORM *lt ;
  char             *cp, line[1000] ;
  FILE             *fp ;
  int              row ;
  MATRIX           *m_L ;

  fp = fopen(fname, "r") ;
  if (!fp)
    ErrorReturn(NULL,
                (ERROR_NOFILE, "ltFSLread: could not open file %s",fname));

  lta = LTAalloc(1, NULL) ;
  lt = &lta->xforms[0] ;
  lt->sigma = 1.0f ;
  lt->x0 = lt->y0 = lt->z0 = 0 ;

  m_L = lt->m_L ;
  for (row = 1 ; row <= 3 ; row++) {
    cp = fgetl(line, 900, fp) ;
    if (!cp) {
      LTAfree(&lta) ;
      ErrorReturn(NULL,
                  (ERROR_BADFILE, "ltFSLread: could not read row %d from %s",
                   row, fname)) ;
    }
    sscanf(cp, "%f %f %f %f",
           MATRIX_RELT(m_L,row,1), MATRIX_RELT(m_L,row,2),
           MATRIX_RELT(m_L,row,3), MATRIX_RELT(m_L,row,4)) ;
  }
  fclose(fp) ;
  lta->type = LINEAR_VOX_TO_VOX;
  return(lta) ;
}
static int
init_scaling(MRI *mri_in, MRI *mri_ref, MATRIX *m_L) {
  MATRIX      *m_scaling ;
  float       sx, sy, sz, dx, dy, dz ;
  MRI_REGION  in_bbox, ref_bbox ;

  m_scaling = MatrixIdentity(4, NULL) ;

  MRIboundingBox(mri_in, 60, &in_bbox) ;
  MRIboundingBox(mri_ref, 60, &ref_bbox) ;
  sx = (float)ref_bbox.dx / (float)in_bbox.dx ;
  sy = (float)ref_bbox.dy / (float)in_bbox.dy ;
  sz = (float)ref_bbox.dz / (float)in_bbox.dz ;
  dx = (ref_bbox.x+ref_bbox.dx-1)/2 - (in_bbox.x+in_bbox.dx-1)/2 ;
  dy = (ref_bbox.y+ref_bbox.dy-1)/2 - (in_bbox.y+in_bbox.dy-1)/2 ;
  dz = (ref_bbox.z+ref_bbox.dz-1)/2 - (in_bbox.z+in_bbox.dz-1)/2 ;

  if (sx > MAX_DX)
    sx = MAX_DX ;
  if (sx < MIN_DX)
    sx = MIN_DX ;
  if (sy > MAX_DY)
    sy = MAX_DY ;
  if (sy < MIN_DY)
    sy = MIN_DY ;
  if (sz > MAX_DZ)
    sz = MAX_DZ ;
  if (sz < MIN_DZ)
    sz = MIN_DZ ;
  if (Gdiag & DIAG_SHOW)
    fprintf(stderr, "initial scaling: (%2.2f, %2.2f, %2.2f) <-- "
            "(%d/%d,%d/%d,%d/%d)\n",
            sx,sy,sz, ref_bbox.dx, in_bbox.dx, ref_bbox.dy, in_bbox.dy,
            ref_bbox.dz, in_bbox.dz) ;
  *MATRIX_RELT(m_scaling, 1, 1) = sx ;
  *MATRIX_RELT(m_scaling, 2, 2) = sy ;
  *MATRIX_RELT(m_scaling, 3, 3) = sz ;

#if 0
  *MATRIX_RELT(m_L, 1, 4) = dx ;
  *MATRIX_RELT(m_L, 2, 4) = dy ;
  *MATRIX_RELT(m_L, 3, 4) = dz ;
#endif
  MatrixMultiply(m_scaling, m_L, m_L) ;
  return(NO_ERROR) ;
}
Example #8
0
IOP *
IOPRead(char *fname, int hemi)
{
  IOP   *iop ;
  int   i,j,k,jc,d, dipoles_in_decimation ;
  FILE  *fp;
  char  c,str[STRLEN];
  float f;
  int   z ;

  printf("read_iop(%s,%d)\n",fname,hemi);

  fp = fopen(fname,"r");
  if (fp==NULL)
    ErrorReturn(NULL,
                (ERROR_NOFILE, "IOPRead: can't open file %s\n",fname));
  iop = calloc(1, sizeof(IOP)) ;
  if (!iop)
    ErrorReturn(NULL,
                (ERROR_NOMEMORY, "IOPRead: can't allocate struct\n"));
  iop->pthresh = 1000;
  c = getc(fp);
  if (c=='#')
  {
    fscanf(fp,"%s",str);
    if (!strcmp(str,"version"))
      fscanf(fp,"%d",&iop->version);
    printf("iop version = %d\n",iop->version);
    fscanf(fp,"%d %d %d %d",
           &iop->neeg_channels,
           &iop->nmeg_channels,
           &iop->ndipoles_per_location,
           &iop->ndipole_files);

    iop->nchan = iop->neeg_channels+iop->nmeg_channels;
    for (i=1;i<=hemi;i++)
    {
      fscanf(fp,"%d %d",&dipoles_in_decimation,&iop->ndipoles);
      if (i==hemi)
      {
#if 0
        if (iop->ndipoles_per_location != sol_ndec)
        {
          fclose(fp);
          IOPFree(&iop) ;
          ErrorReturn(NULL,
                      (ERROR_BADFILE,
                       "IOPRead: .dec and .iop file mismatch (%d!=%d)\n",
                       sol_ndec,iop->ndipoles_per_location));
        }
#endif
        iop->m_iop =
          MatrixAlloc(iop->ndipoles*iop->ndipoles_per_location,iop->nchan,
                      MATRIX_REAL);
        if (iop->version==1)
          iop->m_forward =
            MatrixAlloc(iop->nchan,iop->ndipoles*iop->ndipoles_per_location,
                        MATRIX_REAL);

#if 0
        sol_M = matrix(iop->nchan,iop->nchan); /* temporary space for xtalk */
        sol_Mi = matrix(iop->nchan,iop->nchan);
        sol_sensvec1 = vector(iop->nchan);
        sol_sensvec2 = vector(iop->nchan);
        sol_sensval = vector(iop->nchan);
#endif

        iop->dipole_normalization = calloc(iop->ndipoles, sizeof(float));
        iop->dipole_vertices = calloc(iop->ndipoles, sizeof(int));
        if (!iop->dipole_vertices)
          ErrorReturn(NULL,
                      (ERROR_NOMEMORY,
                       "IOPRead: could not allocated %d v indices",
                       iop->ndipoles)) ;
        iop->pvals = VectorAlloc(iop->ndipoles, MATRIX_REAL);
        iop->spatial_priors = VectorAlloc(iop->ndipoles, MATRIX_REAL);


        iop->bad_sensors = calloc(iop->nchan, sizeof(int));
        if (!iop->bad_sensors)
          ErrorReturn(NULL,
                      (ERROR_NOMEMORY,
                       "IOPRead: could not allocate bad sensor array",
                       iop->nchan)) ;

        /* initialize bad sensor locations*/
        for (z=0;z<iop->nchan;z++)
          iop->bad_sensors[z] = 0;

      }
      for (j=0;j<iop->ndipoles;j++)
      {
        if (i==hemi)
        {
          fscanf(fp,"%d",&d);
          iop->dipole_vertices[j] = d;
        }
        else
          fscanf(fp,"%*d");
      }
      for (j=0;j<iop->ndipoles;j++)
      {
        if (i==hemi)
        {
          fscanf(fp,"%f",&f);
          *MATRIX_RELT(iop->pvals,j+1,1) = f;
          f = fabs(f);
          if (f<iop->pthresh)
            iop->pthresh = f;
        }
        else
          fscanf(fp,"%*f");
      }
      for (j=0;j<iop->ndipoles;j++)
      {
        if (i==hemi)
        {
          fscanf(fp,"%f",&f);
          *MATRIX_RELT(iop->spatial_priors,j+1,1) = f;
#if 0
          vertex[iop->dipole_vertices[j]].val = f;
#endif
        }
        else
          fscanf(fp,"%*f");
      }
      for (j=0;j<iop->ndipoles;j++)
      {
        for (jc=0;jc<iop->ndipoles_per_location;jc++)
        {
          for (k=0;k<iop->nchan;k++)
          {
            if (i==hemi)
            {
              fscanf(fp,"%f",&f);
              *MATRIX_RELT(iop->m_iop, j*iop->ndipoles_per_location+jc+1,k+1)
              = f;
            }
            else
              fscanf(fp,"%*f");
          }
        }
      }
      if (iop->version==1)
      {
        for (j=0;j<iop->ndipoles;j++)
        {
          for (jc=0;jc<iop->ndipoles_per_location;jc++)
          {
            for (k=0;k<iop->nchan;k++)
            {
              if (i==hemi)
              {
                fscanf(fp,"%f",&f);
                *MATRIX_RELT(iop->m_forward,
                             k+1,
                             j*iop->ndipoles_per_location+jc+1) = f;
              }
              else
                fscanf(fp,"%*f");
            }
          }
        }
      }
    }
  }
  else
  {
    printf("Can't read binary .iop files\n");
  }
  fclose(fp);
  printf("neeg_channels=%d, nmeg_channels=%d, iop->ndipoles_per_location=%d, "
         "iop->ndipole_files=%d\n",
         iop->neeg_channels, iop->nmeg_channels,iop->ndipoles_per_location,
         iop->ndipole_files);
  return(iop) ;
}
Example #9
0
REC *
RecRead(char *fname, int iop_neeg, int iop_nmeg)
{
  int   i,j,tnchan;
  float f;
  FILE  *fp;
  REC   *rec ;

  printf("read_rec(%s)\n",fname);


  fp = fopen(fname,"r");
  if (fp==NULL)
    ErrorReturn(NULL,
                (ERROR_BADFILE, "RecRead: could not open file %s",fname)) ;

  rec = (REC *)calloc(1, sizeof(REC)) ;
  if (rec==NULL)
    ErrorExit(ERROR_NOMEMORY, "RecRead: couldn't allocate rec struct") ;

  fscanf(fp,"%*s");
  fscanf(fp,"%d %d %d",&rec->ntimepts,&rec->nmeg_channels,&rec->neeg_channels);
  tnchan = rec->nmeg_channels+rec->neeg_channels ;
  rec->ptime = (int)(2*pow(2.0,ceil(log((float)rec->ntimepts)/log(2.0))));
  printf("ntimepts=%d, ptime=%d\n",rec->ntimepts, rec->ptime);
#if 0
  if (sol_ntime>0 && sol_ntime!=rec->ntimepts)
  {
    printf("ntime does not match rec->ntimepts (%d != %d)\n",sol_ntime,rec->ntimepts);
    exit(0);
  }

  sol_ntime = rec->ntimepts;
  sol_ptime = tptime;

  if (rec->nmeg_channels>0 && rec->nmeg_channels!=tnmeg)
  {
    printf("nmeg does not match tnmeg (%d != %d)\n",rec->nmeg_channels,tnmeg);
    exit(0);
  }
  if (sol_neeg>0 && sol_neeg!=tneeg)
  {
    printf("neeg does not match tnmeg (%d != %d)\n",sol_neeg,tneeg);
    exit(0);
  }
#endif

  rec->latencies = (float *)calloc(rec->ptime, sizeof(float));
  if (!rec->latencies)
    ErrorExit(ERROR_NOMEMORY, "RecRead(%s): could not allocate latency vector",
              fname) ;
  rec->m_data = MatrixAlloc(tnchan,rec->ptime, MATRIX_REAL);
  for (j=0;j<rec->ntimepts;j++)
  {
    fscanf(fp,"%f",&f);
    rec->latencies[j] = f;
    for (i=0;i<rec->neeg_channels;i++)
    {
      fscanf(fp,"%f",&f);
      if (iop_neeg > 0)
        *MATRIX_RELT(rec->m_data,i+1,j+1) = f;
    }
    for (i=0;i<rec->nmeg_channels;i++)
    {
      fscanf(fp,"%f",&f);
      if (iop_nmeg > 0)
        *MATRIX_RELT(rec->m_data,i+iop_neeg+1,j+1) = f;
    }
  }
  fclose(fp);
  printf("rec file read, sample period %2.4f, starting latency %2.4f\n",
         rec->latencies[1]-rec->latencies[0], rec->latencies[0]);

#if 0
  sol_dipcmp_val[sol_nrec] = matrix(sol_nnz*sol_nperdip,sol_ntime);
#endif
  return(rec) ;
}
int
main(int argc, char *argv[]) {
  TRANSFORM    *transform = NULL ;
  char         **av, fname[STRLEN], *gca_fname, *subject_name, *cp ;
  int          ac, nargs, i, n ;
  int          msec, minutes, seconds, nsubjects ;
  struct timeb start ;
  GCA          *gca ;
  MRI          *mri_parc, *mri_T1, *mri_PD ;
  FILE         *fp ;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mri_ca_tissue_parms.c,v 1.8 2011/03/02 00:04:14 nicks Exp $", "$Name: stable5 $");
  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 (!strlen(subjects_dir)) /* hasn't been set on command line */
  {
    cp = getenv("SUBJECTS_DIR") ;
    if (!cp)
      ErrorExit(ERROR_BADPARM, "%s: SUBJECTS_DIR not defined in environment",
                Progname);
    strcpy(subjects_dir, cp) ;
    if (argc < 3)
      usage_exit(1) ;
  }


  gca_fname = argv[1] ;
  nsubjects = argc-2 ;
  printf("computing average tissue parameters on %d subject\n",
         nsubjects) ;

  n = 0 ;

  printf("reading GCA from %s...\n", gca_fname) ;
  gca = GCAread(gca_fname) ;

  for (i = 0 ; i < nsubjects ; i++) {
    subject_name = argv[i+2] ;
    printf("processing subject %s, %d of %d...\n", subject_name,i+1,
           nsubjects);
    sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, parc_dir) ;
    if (DIAG_VERBOSE_ON)
      printf("reading parcellation from %s...\n", fname) ;
    mri_parc = MRIread(fname) ;
    if (!mri_parc)
      ErrorExit(ERROR_NOFILE, "%s: could not read parcellation file %s",
                Progname, fname) ;

    sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, T1_name) ;
    if (DIAG_VERBOSE_ON)
      printf("reading co-registered T1 from %s...\n", fname) ;
    mri_T1 = MRIread(fname) ;
    if (!mri_T1)
      ErrorExit(ERROR_NOFILE, "%s: could not read T1 data from file %s",
                Progname, fname) ;

    sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, PD_name) ;
    if (DIAG_VERBOSE_ON)
      printf("reading co-registered T1 from %s...\n", fname) ;
    mri_PD = MRIread(fname) ;
    if (!mri_PD)
      ErrorExit(ERROR_NOFILE, "%s: could not read PD data from file %s",
                Progname, fname) ;


    if (xform_name) {
      /*      VECTOR *v_tmp, *v_tmp2 ;*/

      sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, xform_name) ;
      printf("reading xform from %s...\n", fname) ;
      transform = TransformRead(fname) ;
      if (!transform)
        ErrorExit(ERROR_NOFILE, "%s: could not read xform from %s",
                  Progname, fname) ;
#if 0
      v_tmp = VectorAlloc(4,MATRIX_REAL) ;
      *MATRIX_RELT(v_tmp,4,1)=1.0 ;
      v_tmp2 = MatrixMultiply(lta->xforms[0].m_L, v_tmp, NULL) ;
      printf("RAS (0,0,0) -->\n") ;
      MatrixPrint(stdout, v_tmp2) ;
#endif

      if (transform->type == LINEAR_RAS_TO_RAS) {
        MATRIX *m_L ;
        m_L = ((LTA *)transform->xform)->xforms[0].m_L ;
        MRIrasXformToVoxelXform(mri_parc, mri_T1, m_L,m_L) ;
      }
#if 0
      v_tmp2 = MatrixMultiply(lta->xforms[0].m_L, v_tmp, v_tmp2) ;
      printf("voxel (0,0,0) -->\n") ;
      MatrixPrint(stdout, v_tmp2) ;
      VectorFree(&v_tmp) ;
      VectorFree(&v_tmp2) ;
      test(mri_parc, mri_T1, mri_PD, lta->xforms[0].m_L) ;
#endif
    }
    if (histo_parms)
      GCAhistogramTissueStatistics(gca,mri_T1,mri_PD,mri_parc,transform,histo_parms);
#if 0
    else
      GCAaccumulateTissueStatistics(gca, mri_T1, mri_PD, mri_parc, transform) ;
#endif

    MRIfree(&mri_parc) ;
    MRIfree(&mri_T1) ;
    MRIfree(&mri_PD) ;
  }
  GCAnormalizeTissueStatistics(gca) ;

  if (log_fname) {
    printf("writing tissue parameters to %s\n", log_fname) ;
    fp = fopen(log_fname, "w") ;
    for (n = 1 ; n < MAX_GCA_LABELS ; n++) {
      GCA_TISSUE_PARMS *gca_tp ;

      gca_tp = &gca->tissue_parms[n] ;
      if (gca_tp->total_training <= 0)
        continue ;
      fprintf(fp, "%d  %f  %f\n", n, gca_tp->T1_mean, gca_tp->PD_mean) ;
    }
    fclose(fp) ;
  }

  if (write_flag)
    GCAwrite(gca, gca_fname) ;
  GCAfree(&gca) ;
  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf("tissue parameter statistic calculation took %d minutes"
         " and %d seconds.\n", minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
static int  ltaMNIwrite(LTA *lta, char *fname)
{
  FILE             *fp ;
  int              row ;
  MATRIX           *m_L ;

  fp = fopen(fname, "w") ;
  if (!fp)
    ErrorReturn(ERROR_NOFILE,
                (ERROR_NOFILE, "ltMNIwrite: could not open file %s",fname));

  fprintf(fp, "MNI Transform File\n") ;
  // now saves src and dst in comment line
  fprintf(fp, "%%Generated by %s src %s dst %s\n",
          Progname, lta->xforms[0].src.fname, lta->xforms[0].dst.fname) ;
  fprintf(fp, "\n") ;
  fprintf(fp, "Transform_Type = Linear;\n") ;
  fprintf(fp, "Linear_Transform =\n") ;

  if (lta->type == LINEAR_RAS_TO_RAS)
  {
    m_L = lta->xforms[0].m_L ;
    for (row = 1 ; row <= 3 ; row++)
    {
      fprintf(fp, "      %f       %f       %f       %f",
              *MATRIX_RELT(m_L,row,1), *MATRIX_RELT(m_L,row,2),
              *MATRIX_RELT(m_L,row,3), *MATRIX_RELT(m_L,row,4)) ;
      if (row == 3)
      {
        fprintf(fp, ";") ;
      }
      fprintf(fp, "\n") ;
    }
  }
  else if (lta->type == LINEAR_VOX_TO_VOX)
  {
    // we use src and dst info to create RAS_TO_RAS xfm
    MATRIX *voxFromRAS = 0;
    MATRIX *rasFromVoxel = 0;
    MATRIX *tmp = 0;
    MATRIX *rasToRAS = 0;
    MRI *src = 0;
    MRI *dst = 0;
    LT  *lt = 0;
    lt = &lta->xforms[0];
    src = MRIallocHeader(lt->src.width,
                         lt->src.height,
                         lt->src.depth,
                         MRI_UCHAR,
                         1);
    useVolGeomToMRI(&lt->src, src);
    dst = MRIallocHeader(lt->dst.width,
                         lt->dst.height,
                         lt->dst.depth,
                         MRI_UCHAR,
                         1);
    useVolGeomToMRI(&lt->dst, dst);
    voxFromRAS = extract_r_to_i(src);
    tmp = MatrixMultiply(lta->xforms[0].m_L, voxFromRAS, NULL);
    rasFromVoxel = extract_i_to_r(dst);
    rasToRAS = MatrixMultiply(rasFromVoxel, tmp, NULL);
    for (row = 1 ; row <= 3 ; row++)
    {
      fprintf(fp, "      %f       %f       %f       %f",
              *MATRIX_RELT(rasToRAS,row,1), *MATRIX_RELT(rasToRAS,row,2),
              *MATRIX_RELT(rasToRAS,row,3), *MATRIX_RELT(rasToRAS,row,4)) ;
      if (row == 3)
      {
        fprintf(fp, ";") ;
      }
      fprintf(fp, "\n") ;
    }
    MatrixFree(&voxFromRAS);
    MatrixFree(&rasFromVoxel);
    MatrixFree(&tmp);
    MatrixFree(&rasToRAS);
    MRIfree(&src);
    MRIfree(&dst);
  }
  fclose(fp) ;
  return(NO_ERROR);
}
static LTA *ltaMNIreadEx(const char *fname)
{
  LTA *lta = 0;
  LINEAR_TRANSFORM *lt ;
  char             *cp, line[1000], infoline[1024], infoline2[1024];
  FILE             *fp ;
  int              row ;
  MATRIX           *m_L ;
  int             no_volinfo = 0;

  fp = fopen(fname, "r") ;
  if (!fp)
    ErrorReturn(NULL,
                (ERROR_NOFILE, "ltMNIreadEx: could not open file %s",fname));

  lta = LTAalloc(1, NULL) ;
  lt = &lta->xforms[0] ;
  lt->sigma = 1.0f ;
  lt->x0 = lt->y0 = lt->z0 = 0 ;

  fgetl(line, 900, fp) ;   /* MNI Transform File */
  if (strncmp("MNI Transform File", line, 18))
    ErrorReturn(NULL,
                (ERROR_NOFILE,
                 "ltMNIreadEx:%s does not start as 'MNI Transform File'",
                 fname));

  fgetl(line, 900, fp) ;   /* fileinfo line */
  if (line[0] == '%')
  {
    strcpy(infoline, line);
  }
  else
  {
    no_volinfo = 1;
    if (!strncmp("Transform_Type", line, 14))
    {
      fgetl(line,900,fp);
      goto get_transform;
    }
  }
  // second line in %
  fgetl(line, 900, fp);
  if (line[0] == '%')
  {
    strcpy(infoline2, line);
    while (line[0] == '%')
    {
      fgetl(line, 900, fp) ;  /* variable # of comments */
    }
    fgetl(line, 900, fp) ;
    if (!strncmp("Transform_Type", line, 14))
    {
      fgetl(line,900,fp);
      goto get_transform;
    }
  }
  else
  {
    if (!strncmp("Transform_Type", line, 14))
    {
      fgetl(line, 900, fp);
      goto get_transform;
    }
    while (line[0] == '%')
    {
      fgetl(line, 900, fp) ;  /* variable # of comments */
    }
  }

get_transform:
  m_L = lt->m_L ;
  for (row = 1 ; row <= 3 ; row++)
  {
    cp = fgetl(line, 900, fp) ;
    if (!cp)
    {
      LTAfree(&lta) ;
      ErrorReturn
      (NULL,
       (ERROR_BADFILE, "ltMNIreadEx: could not read row %d from %s (%s)",
        row, fname, line)) ;
    }
    sscanf(cp, "%f %f %f %f",
           MATRIX_RELT(m_L,row,1), MATRIX_RELT(m_L,row,2),
           MATRIX_RELT(m_L,row,3), MATRIX_RELT(m_L,row,4)) ;
  }
  if (!lta)
  {
    fclose(fp);
    return NULL;
  }
  fclose(fp);

  // add original src and dst information
  if (no_volinfo == 0)
    mincGetVolInfo(infoline,
                   infoline2,
                   &lta->xforms[0].src,
                   &lta->xforms[0].dst);
  lta->type = LINEAR_RAS_TO_RAS;
  return lta;
}
static MATRIX *
pca_matrix(MATRIX *m_in_evectors, double in_means[3],
           MATRIX *m_ref_evectors, double ref_means[3]) {
  float   dx, dy, dz ;
  MATRIX  *mRot, *m_in_T, *mOrigin, *m_L, *m_R, *m_T, *m_tmp ;
  double  x_angle, y_angle, z_angle, r11, r21, r31, r32, r33, cosy ;
  int     row, col ;

  m_in_T = MatrixTranspose(m_in_evectors, NULL) ;
  mRot = MatrixMultiply(m_ref_evectors, m_in_T, NULL) ;

  r11 = mRot->rptr[1][1] ;
  r21 = mRot->rptr[2][1] ;
  r31 = mRot->rptr[3][1] ;
  r32 = mRot->rptr[3][2] ;
  r33 = mRot->rptr[3][3] ;
  y_angle = atan2(-r31, sqrt(r11*r11+r21*r21)) ;
  cosy = cos(y_angle) ;
  z_angle = atan2(r21 / cosy, r11 / cosy) ;
  x_angle = atan2(r32 / cosy, r33 / cosy) ;

#define MAX_ANGLE  (RADIANS(30))
  if (fabs(x_angle) > MAX_ANGLE || fabs(y_angle) > MAX_ANGLE ||
      fabs(z_angle) > MAX_ANGLE) {
    MatrixFree(&m_in_T) ;
    MatrixFree(&mRot) ;
    printf("eigenvector swap detected: ignoring PCA...\n") ;
    return(MatrixIdentity(4, NULL)) ;
  }

  mOrigin = VectorAlloc(3, MATRIX_REAL) ;
  mOrigin->rptr[1][1] = ref_means[0] ;
  mOrigin->rptr[2][1] = ref_means[1] ;
  mOrigin->rptr[3][1] = ref_means[2] ;

  printf("reference volume center of mass at (%2.1f,%2.1f,%2.1f)\n",
         ref_means[0], ref_means[1], ref_means[2]) ;
  printf("input volume center of mass at     (%2.1f,%2.1f,%2.1f)\n",
         in_means[0], in_means[1], in_means[2]) ;
  dx = ref_means[0] - in_means[0] ;
  dy = ref_means[1] - in_means[1] ;
  dz = ref_means[2] - in_means[2] ;

  printf("translating volume by %2.1f, %2.1f, %2.1f\n",
         dx, dy, dz) ;
  printf("rotating volume by (%2.2f, %2.2f, %2.2f)\n",
         DEGREES(x_angle), DEGREES(y_angle), DEGREES(z_angle)) ;

  /* build full rigid transform */
  m_R = MatrixAlloc(4,4,MATRIX_REAL) ;
  m_T = MatrixAlloc(4,4,MATRIX_REAL) ;
  for (row = 1 ; row <= 3 ; row++) {
    for (col = 1 ; col <= 3 ; col++) {
      *MATRIX_RELT(m_R,row,col) = *MATRIX_RELT(mRot, row, col) ;
    }
    *MATRIX_RELT(m_T,row,row) = 1.0 ;
  }
  *MATRIX_RELT(m_R, 4, 4) = 1.0 ;

  /* translation so that origin is at ref eigenvector origin */
  dx = -ref_means[0] ;
  dy = -ref_means[1] ;
  dz = -ref_means[2] ;
  *MATRIX_RELT(m_T, 1, 4) = dx ;
  *MATRIX_RELT(m_T, 2, 4) = dy ;
  *MATRIX_RELT(m_T, 3, 4) = dz ;
  *MATRIX_RELT(m_T, 4, 4) = 1 ;
  m_tmp = MatrixMultiply(m_R, m_T, NULL) ;
  *MATRIX_RELT(m_T, 1, 4) = -dx ;
  *MATRIX_RELT(m_T, 2, 4) = -dy ;
  *MATRIX_RELT(m_T, 3, 4) = -dz ;
  MatrixMultiply(m_T, m_tmp, m_R) ;

  /* now apply translation to take in centroid to ref centroid */
  dx = ref_means[0] - in_means[0] ;
  dy = ref_means[1] - in_means[1] ;
  dz = ref_means[2] - in_means[2] ;
  *MATRIX_RELT(m_T, 1, 4) = dx ;
  *MATRIX_RELT(m_T, 2, 4) = dy ;
  *MATRIX_RELT(m_T, 3, 4) = dz ;
  *MATRIX_RELT(m_T, 4, 4) = 1 ;

  m_L = MatrixMultiply(m_R, m_T, NULL) ;
  if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON) {
    printf("m_T:\n") ;
    MatrixPrint(stdout, m_T) ;
    printf("m_R:\n") ;
    MatrixPrint(stdout, m_R) ;
    printf("m_L:\n") ;
    MatrixPrint(stdout, m_L) ;
  }
  MatrixFree(&m_R) ;
  MatrixFree(&m_T) ;

  MatrixFree(&mRot) ;
  VectorFree(&mOrigin) ;
  return(m_L) ;
}
static int
order_eigenvectors(MATRIX *m_src_evectors, MATRIX *m_dst_evectors) {
  int    row, col, xcol, ycol, zcol ;
  double mx ;

  if (m_src_evectors == m_dst_evectors)
    m_src_evectors = MatrixCopy(m_src_evectors, NULL) ;

  /* find columx with smallest dot product with unit x vector */
  mx = fabs(*MATRIX_RELT(m_src_evectors, 1, 1)) ;
  xcol = 1 ;
  for (col = 2 ; col <= 3 ; col++)
    if (fabs(*MATRIX_RELT(m_src_evectors, 1, col)) > mx) {
      xcol = col ;
      mx = fabs(*MATRIX_RELT(m_src_evectors, 1, col)) ;
    }

  mx = fabs(*MATRIX_RELT(m_src_evectors, 2, 1)) ;
  ycol = 1 ;
  for (col = 2 ; col <= 3 ; col++)
    if (*MATRIX_RELT(m_src_evectors, 2, col) > mx) {
      ycol = col ;
      mx = fabs(*MATRIX_RELT(m_src_evectors, 2, col)) ;
    }

  mx = fabs(*MATRIX_RELT(m_src_evectors, 3, 1)) ;
  zcol = 1 ;
  for (col = 2 ; col <= 3 ; col++)
    if (fabs(*MATRIX_RELT(m_src_evectors, 3, col)) > mx) {
      zcol = col ;
      mx = fabs(*MATRIX_RELT(m_src_evectors, 3, col)) ;
    }

  for (row = 1 ; row <= 3 ; row++) {
    *MATRIX_RELT(m_dst_evectors,row,1) = *MATRIX_RELT(m_src_evectors,row,xcol);
    *MATRIX_RELT(m_dst_evectors,row,2) = *MATRIX_RELT(m_src_evectors,row,ycol);
    *MATRIX_RELT(m_dst_evectors,row,3) = *MATRIX_RELT(m_src_evectors,row,zcol);
  }
  return(NO_ERROR) ;
}