LTA *ltaReadFileEx(const char *fname)
{
  FILE             *fp;
  LINEAR_TRANSFORM *lt ;
  int              i, nxforms, type ;
  char             line[STRLEN], *cp ;
  LTA              *lta ;

  fp = fopen(fname,"r");
  if (fp==NULL)
    ErrorReturn(NULL,
                (ERROR_BADFILE, "ltaReadFile(%s): can't open file",fname));
  cp = fgetl(line, 199, fp) ;
  if (cp == NULL)
  {
    fclose(fp) ;
    ErrorReturn(NULL, (ERROR_BADFILE, "ltaReadFile(%s): can't read data",fname));
  }
  sscanf(cp, "type      = %d\n", &type) ;
  cp = fgetl(line, 199, fp) ;
  sscanf(cp, "nxforms   = %d\n", &nxforms) ;
  lta = LTAalloc(nxforms, NULL) ;
  lta->type = type ;
  for (i = 0 ; i < lta->num_xforms ; i++)
  {
    lt = &lta->xforms[i] ;
    fscanf(fp, "mean      = %f %f %f\n", &lt->x0, &lt->y0, &lt->z0) ;
    fscanf(fp, "sigma     = %f\n", &lt->sigma) ;
    MatrixAsciiReadFrom(fp, lt->m_L) ;
  }
  // oh, well this is the added part
  for (i=0; i < lta->num_xforms; i++)
  {
    if (fgets(line, 199, fp))
    {
      if (strncmp(line, "src volume info", 15)==0)
      {
        char *p;
        readVolGeom(fp, &lta->xforms[i].src);
        p = fgets(line, 199, fp);
        if (strncmp(line, "dst volume info", 15)==0)
          readVolGeom(fp, &lta->xforms[i].dst);
      }
    }
  }
  fclose(fp) ;
  return(lta) ;
}
示例#2
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) ;
}
int
main(int argc, char *argv[]) {
  char         **av, *avg_surf_name, *canon_surf_name, fname[STRLEN],
  *mdir, ico_fname[STRLEN], *hemi, *out_sname ;
  int          ac, nargs, i, vno, n ;
  VERTEX       *v ;
  MRI_SURFACE  *mris_ico ;
  MRI_SP       *mrisp_total ;
  LTA          *lta ;
  VOL_GEOM     vg;
  float        average_surface_area = 0.0 ;
  MATRIX *XFM=NULL;
  GCA_MORPH *gcam=NULL;

  memset((void *) &vg, 0, sizeof (VOL_GEOM));

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

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

  mdir = getenv("FREESURFER_HOME") ;
  if (!mdir)
    ErrorExit(ERROR_BADPARM, 
              "%s: no FREESURFER_HOME in environment.\n",Progname);
  ac = argc ;
  av = argv ;
  for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) {
    nargs = get_option(argc, argv) ;
    argc -= nargs ;
    argv += nargs ;
  }
  if (sdir == NULL) {
    sdir =  getenv("SUBJECTS_DIR");
    if (!sdir)
      ErrorExit(ERROR_BADPARM, 
                "%s: no SUBJECTS_DIR in environment.\n",Progname);
  }
  if (sdirout == NULL) sdirout = sdir;
  if (argc < 6) usage_exit() ;

  hemi = argv[1] ;
  avg_surf_name = argv[2] ;
  canon_surf_name = argv[3] ;
  out_sname = argv[4] ;

  printf("---------------------------------------------------\n");
  printf("hemi            = %s\n",hemi);
  printf("avg_surf_name   = %s\n",avg_surf_name);
  printf("canon_surf_name = %s\n",canon_surf_name);
  printf("out_sname       = %s\n",out_sname);
  printf("xform           = %s\n",xform_name);
  printf("---------------------------------------------------\n");
  printf("\n\n");
  fflush(stdout);

#define SCALE 1
  mrisp_total = MRISPalloc(SCALE, 3) ;
  for (n = 0, i = 5 ; i < argc ; i++) {
    MRI *mri;
    MRI_SURFACE *mris;
    MRI_SP *mrisp;

    printf("\n---------------------------------------------------\n");
    printf("#@# processing subject %d/%d %s...\n", i-4,argc-5,argv[i]) ;
    fflush(stdout);

    // read sphere.reg
    sprintf(fname, "%s/%s/surf/%s.%s", sdir, argv[i], hemi, canon_surf_name) ;
    printf("  Reading %s\n",fname);
    fflush(stdout);
    mris = MRISread(fname) ;
    if (!mris) {
      ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s",
                Progname, fname) ;
      exit(1);
    }
    // get "pial" surface vertex into ->origx, origy, origz
    if (MRISreadOriginalProperties(mris, orig_name) != NO_ERROR)
      ErrorExit(ERROR_BADFILE,"%s: could not read orig file for %s.\n",
                Progname, argv[1]);
    // read transform
    if (0) {
      sprintf(fname, "%s/%s/mri/transforms/%s", sdir, argv[i], xform_name) ;
      lta = LTAreadEx(fname) ;
      if (!lta)
        ErrorExit(ERROR_BADPARM, 
                  "%s: could not read transform from %s", Progname, fname) ;
    }

    // read T1 volume
    sprintf(fname, "%s/%s/mri/T1.mgz", sdir, argv[i]) ;
    if (fio_FileExistsReadable(fname)) mri = MRIreadHeader(fname,MRI_MGH_FILE);
    else {
      sprintf(fname, "%s/%s/mri/T1", sdir, argv[i]) ;
      mri = MRIreadHeader(fname, MRI_UCHAR); // MRI_CORONAL_SLICE_DIRECTORY) ;
    }
    printf("  Read %s\n",fname);
    fflush(stdout);

    if (!mri)
      ErrorExit(ERROR_BADPARM, 
                "%s: could not read reference MRI volume from %s",
                Progname, fname) ;

    // save current vertex position into ->cx
    MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ;
    // get the vertex position from ->origx, ... 
    // (get the "pial" vertex position)
    MRISrestoreVertexPositions(mris, ORIGINAL_VERTICES) ;
    MRIScomputeMetricProperties(mris) ;
    printf("  Surface area: %2.1f cm^2\n", mris->total_area/100) ;
    fflush(stdout);
    average_surface_area += mris->total_area ;

    // this means that we transform "pial" surface

    if (xform_name)
    {
      if (!strcmp(xform_name,"talairach.xfm")) {
        printf("  Applying linear transform\n");
        fflush(stdout);
        XFM = DevolveXFMWithSubjectsDir(argv[i], NULL, "talairach.xfm", sdir);
        if (XFM == NULL) exit(1);
        MRISmatrixMultiply(mris, XFM);
        MatrixFree(&XFM);
      } else if (!strcmp(xform_name,"talairach.m3z")) {
        printf("  Applying GCA Morph\n");
        fflush(stdout);
        sprintf(fname, "%s/%s/mri/transforms/talairach.m3z", sdir, argv[i]) ;
        gcam = GCAMreadAndInvert(fname);
        if (gcam == NULL) exit(1);
        GCAMmorphSurf(mris, gcam);
        GCAMfree(&gcam);
      } else {
        printf("ERROR: don't know what to do with %s\n",xform_name);
        exit(1);
      }
    }

    // save transformed position in ->orig 
    // (store "pial" vertices position in orig)
    MRIScomputeMetricProperties(mris) ;
    MRISsaveVertexPositions(mris, ORIGINAL_VERTICES) ;
    // get the vertex position from ->cx 
    // (note that this is not transformed)  sphere.reg vertices
    MRISrestoreVertexPositions(mris, CANONICAL_VERTICES) ;
    // mris contains sphere.reg in vertex and pial vertices in orig
    // map to a theta-phi space and accumulate values
    mrisp = MRIScoordsToParameterization(mris, NULL, SCALE, ORIGINAL_VERTICES) ;
    MRISPaccumulate(mrisp, mrisp_total, 0) ;
    MRISPaccumulate(mrisp, mrisp_total, 1) ;
    MRISPaccumulate(mrisp, mrisp_total, 2) ;
    MRISPfree(&mrisp) ;
    MRISfree(&mris) ;
    MRIfree(&mri) ;
    //LTAfree(&lta) ;
    fflush(stdout);
    n++ ;
  }
  printf("Finished loading all data\n");
  average_surface_area /= (float)n ;
  printf("Avg surf area = %g cm\n",average_surface_area/100.0);
  fflush(stdout);

  // mrisp_total lost info on the modified surface
  sprintf(ico_fname, "%s/lib/bem/ic%d.tri", mdir, ico_no) ;
  printf("Reading icosahedron from %s...\n", ico_fname) ;
  mris_ico = ICOread(ico_fname) ;
  if (!mris_ico)
    ErrorExit(ERROR_NOFILE, "%s: could not read icosahedron file %s\n",
              Progname,ico_fname) ;
  MRISscaleBrain(mris_ico, mris_ico,
                 DEFAULT_RADIUS/MRISaverageRadius(mris_ico)) ;
  // save current ico position to ->cx, cy, cz
  MRISsaveVertexPositions(mris_ico, CANONICAL_VERTICES) ;
  // using mrisp_total to calculate position into ->origx, origy, origz 
  // (orig is the "pial" vertices)
  MRIScoordsFromParameterization(mrisp_total, mris_ico, ORIGINAL_VERTICES) ;
  // copy geometry info
  memcpy((void *) &mris_ico->vg, (void *) &vg, sizeof (VOL_GEOM));

  if (Gdiag_no >= 0 && Gdiag_no < mris_ico->nvertices) {
    int n ;
    VERTEX *vn ;

    v = &mris_ico->vertices[Gdiag_no] ;
    printf( "v %d: x = (%2.2f, %2.2f, %2.2f)\n",
            Gdiag_no, v->origx, v->origy, v->origz) ;
    for (n = 0 ; n < v->vnum ; n++) {
      vn = &mris_ico->vertices[v->v[n]] ;
      printf( "v %d: x = (%2.2f, %2.2f, %2.2f)\n",
              v->v[n], vn->origx, vn->origy, vn->origz) ;
    }
  }
  // write *h.sphere.reg
  sprintf(fname, "%s/%s/surf/%s.%s", 
          sdirout, out_sname, hemi, canon_surf_name) ;
  if (Gdiag & DIAG_SHOW)
    printf("writing average canonical surface to %s\n", fname);
  MRISwrite(mris_ico, fname) ;

  // get "pial vertices" from orig
  MRISrestoreVertexPositions(mris_ico, ORIG_VERTICES);
  for (vno = 0 ; vno < mris_ico->nvertices ; vno++) {
    v = &mris_ico->vertices[vno] ;
    // n = number of subjects
    v->x /= (float)n ;
    v->y /= (float)n ;
    v->z /= (float)n ;
  }
  if (normalize_area) {
    MRIScomputeMetricProperties(mris_ico) ;
    printf("setting group surface area to be %2.1f cm^2 (scale=%2.2f)\n",
           average_surface_area/100.0,
           sqrt(average_surface_area/mris_ico->total_area)) ;

#if 0
    MRISscaleBrain(mris_ico, mris_ico,
                   sqrt(average_surface_area/mris_ico->total_area)) ;
#else
    mris_ico->group_avg_surface_area = average_surface_area ;
#endif
    MRIScomputeMetricProperties(mris_ico) ;
  }

  sprintf(fname, "%s/%s/surf/%s.%s", sdirout,out_sname, hemi, avg_surf_name) ;
  printf("writing average %s surface to %s\n", avg_surf_name, fname);
  MRISwrite(mris_ico,  fname) ;

  if (0) {
    char path[STRLEN] ;
    LTA  *lta ;

    FileNamePath(fname, path) ;
    lta = LTAalloc(1, NULL) ;
    // write to a different location
    sprintf(fname, "%s/../mri/transforms/%s", path,xform_name) ;
    LTAwriteEx(lta, fname) ;
    LTAfree(&lta) ;
  }

  MRISfree(&mris_ico) ;
  MRISPfree(&mrisp_total) ;

  printf("mris_make_average_surface done\n");

  exit(0) ;
  return(0) ;  /* for ansi */
}
int main(int argc, char *argv[])
{

  char **av, *ltafn1, *ltafn2, *ltafn_total;
  LTA *lta1, *lta2, *lta_total;
  FILE *fo;
  MATRIX *r_to_i_1, *i_to_r_1, *i_to_r_2, *r_to_i_2;
  MATRIX *RAS_1_to_1, *RAS_2_to_2, *m_tmp;
  int nargs, ac;
  int type = 0;

  Progname = argv[0];

  nargs = handle_version_option
          (argc, argv,
           "$Id: mri_concatenate_lta.c,v 1.10 2011/03/16 21:23:48 nicks Exp $",
           "$Name: stable5 $");
  if (nargs && argc - nargs == 1)
  {
    exit (0);
  }
  argc -= nargs ;

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

  ltafn1 = argv[1];
  ltafn2 = argv[2];
  ltafn_total = argv[3];

  printf("Read individual LTAs\n");
  //lta1 = ltaReadFileEx(ltafn1);
  TRANSFORM * trans = TransformRead(ltafn1);
  lta1 =  (LTA *)trans->xform ;

  if (!lta1)
  {
    ErrorExit(ERROR_BADFILE, "%s: can't read file %s",Progname, ltafn1);
  }

  if (invert1)
  {
    VOL_GEOM vgtmp;
    LT *lt;
    MATRIX *m_tmp = lta1->xforms[0].m_L ;
    lta1->xforms[0].m_L = MatrixInverse(lta1->xforms[0].m_L, NULL) ;
    MatrixFree(&m_tmp) ;
    lt = &lta1->xforms[0];
    if (lt->dst.valid == 0 || lt->src.valid == 0)
    {
      fprintf
      (stderr,
       "WARNING:********************************************************\n");
      fprintf
      (stderr,
       "WARNING:dst or src volume is invalid.  Inverse likely wrong.\n");
      fprintf
      (stderr,
       "WARNING:********************************************************\n");
    }
    copyVolGeom(&lt->dst, &vgtmp);
    copyVolGeom(&lt->src, &lt->dst);
    copyVolGeom(&vgtmp, &lt->src);
  }

  if (strcmp(ltafn2,"identity.nofile") == 0)
  {
    type = TransformFileNameType(ltafn_total);
    if (type == MNI_TRANSFORM_TYPE)
    {
      ltaMNIwrite(lta1, ltafn_total);
    }
    else
    {
      //change type to VOXEL_VOXEL
      if (lta1->type != out_type)
      {
        LTAchangeType(lta1, out_type);
      }

      printf("Writing  LTA to file %s...\n", ltafn_total);
      fo = fopen(ltafn_total,"w");
      if (fo==NULL)
        ErrorExit(ERROR_BADFILE,
                  "%s: can't create file %s",Progname, ltafn_total);

      LTAprint(fo, lta1);

      fclose(fo);
    }
    LTAfree(&lta1);
    printf("%s successful.\n", Progname);
    return 0;
  }


  type = TransformFileNameType(ltafn2);
  if (type == MNI_TRANSFORM_TYPE)
  {
    if (invert2 != 0)
      ErrorExit
      (ERROR_BADFILE,
       "%s: LTA2 is talairach.xfm, and shouldn't be inverted ",
       Progname);

    lta2 = ltaMNIreadEx(ltafn2) ;
    //the talairach xform is supposed to be linear_RAS_TO_RAS, right? Yes
    lta2->type =  LINEAR_RAS_TO_RAS;

    if (tal_src_file == 0 && lta2->xforms[0].src.valid == 0)
      ErrorExit
      (ERROR_BADFILE,
       "%s: pls use -tal option to give talairach src and "
       "template filenames",Progname);
    if (tal_dst_file == 0 && lta2->xforms[0].dst.valid == 0)
      ErrorExit
      (ERROR_BADFILE,
       "%s: pls use -tal option to give talairach src and "
       "template filenames",Progname);

    if (tal_src_file != 0)
    {
      LTAmodifySrcDstGeom(lta2, tal_src, NULL);  // add src and dst information
    }
    if (tal_dst_file != 0)
    {
      LTAmodifySrcDstGeom(lta2, NULL, tal_dst);  // add src and dst information
    }
  }
  else
  {
    TRANSFORM * trans = TransformRead(ltafn2);
    lta2 =  (LTA *)trans->xform ;
    //lta2 = ltaReadFileEx(ltafn2);
  }

  if (!lta2)
  {
    ErrorExit(ERROR_BADFILE, "%s: can't read file %s",Progname, ltafn2);
  }

  if (invert2)
  {
    VOL_GEOM vgtmp;
    LT *lt;
    MATRIX *m_tmp = lta2->xforms[0].m_L ;
    lta2->xforms[0].m_L = MatrixInverse(lta2->xforms[0].m_L, NULL) ;
    MatrixFree(&m_tmp) ;
    lt = &lta2->xforms[0];
    if (lt->dst.valid == 0 || lt->src.valid == 0)
    {
      fprintf
      (stderr,
       "WARNING:********************************************************\n");
      fprintf
      (stderr,
       "WARNING:dst or src volume is invalid.  Inverse likely wrong.\n");
      fprintf
      (stderr,
       "WARNING:********************************************************\n");
    }
    copyVolGeom(&lt->dst, &vgtmp);
    copyVolGeom(&lt->src, &lt->dst);
    copyVolGeom(&vgtmp, &lt->src);
  }

  if (vg_isEqual(&lta1->xforms[0].dst, &lta2->xforms[0].src) == 0)
  {
    /*    ErrorExit(ERROR_BADFILE,
          "%s: dst volume of lta1 doesn't match src
          volume of lta2",Progname);*/
    printf("Warning: dst volume of lta1 doesn't match src volume of lta2\n");
    printf("Volume geometry for lta1-dst: \n");
    vg_print(&lta1->xforms[0].dst);
    printf("Volume geometry for lta2-src:\n");
    vg_print(&lta2->xforms[0].src);
  }

  printf("Combining the two LTAs to get a RAS-to-RAS from src "
         "of LTA1 to dst of LTA2...\n");

  if (lta1->type == LINEAR_RAS_TO_RAS)
  {
    RAS_1_to_1 =  MatrixCopy(lta1->xforms[0].m_L, NULL);
  }
  else if (lta1->type == LINEAR_VOX_TO_VOX)
  {
    r_to_i_1 = vg_r_to_i(&lta1->xforms[0].src);
    i_to_r_1 = vg_i_to_r(&lta1->xforms[0].dst);
    if (!r_to_i_1 || !i_to_r_1)
      ErrorExit(ERROR_BADFILE,
                "%s: failed to convert LTA1 to RAS_to_RAS",Progname);
    m_tmp = MatrixMultiply(lta1->xforms[0].m_L, r_to_i_1, NULL);
    RAS_1_to_1 = MatrixMultiply(i_to_r_1, m_tmp, NULL);
    MatrixFree(&m_tmp);
  }
  else
  {
    ErrorExit(ERROR_BADFILE,
              "%s: unknown transform type for LTA1",Progname);
  }

  if (lta2->type == LINEAR_RAS_TO_RAS)
  {
    RAS_2_to_2 =  MatrixCopy(lta2->xforms[0].m_L, NULL);
  }
  else if (lta2->type == LINEAR_VOX_TO_VOX)
  {
    r_to_i_2 = vg_r_to_i(&lta2->xforms[0].src);
    i_to_r_2 = vg_i_to_r(&lta2->xforms[0].dst);
    if (!r_to_i_2 || !i_to_r_2)
      ErrorExit(ERROR_BADFILE,
                "%s: failed to convert LTA1 to RAS_to_RAS",Progname);
    m_tmp = MatrixMultiply(lta2->xforms[0].m_L, r_to_i_2, NULL);
    RAS_2_to_2 = MatrixMultiply(i_to_r_2, m_tmp, NULL);
    MatrixFree(&m_tmp);
  }
  else
  {
    ErrorExit(ERROR_BADFILE, "%s: unknown transform type for LTA1",Progname);
  }

  lta_total = LTAalloc(1, NULL);
  lta_total->type = LINEAR_RAS_TO_RAS;
  MatrixMultiply(RAS_2_to_2, RAS_1_to_1, lta_total->xforms[0].m_L);
  lta_total->xforms[0].src = lta1->xforms[0].src;
  lta_total->xforms[0].dst = lta2->xforms[0].dst;
  lta_total->xforms[0].x0 = 0;
  lta_total->xforms[0].y0 = 0;
  lta_total->xforms[0].z0 = 0;
  lta_total->xforms[0].sigma = 1.0f;

  type = TransformFileNameType(ltafn_total);
  if (type == MNI_TRANSFORM_TYPE)
  {
    ltaMNIwrite(lta_total, ltafn_total);
  }
  else
  {
    //change type to VOXEL_VOXEL
    if (lta_total->type != out_type)
    {
      LTAchangeType(lta_total, out_type);
    }

    printf("Writing combined LTA to file %s...\n", ltafn_total);
    fo = fopen(ltafn_total,"w");
    if (fo==NULL)
      ErrorExit(ERROR_BADFILE,
                "%s: can't create file %s",Progname, ltafn_total);

    LTAprint(fo, lta_total);

    fclose(fo);
  }

  LTAfree(&lta1);
  LTAfree(&lta2);
  LTAfree(&lta_total);
  MatrixFree(&RAS_1_to_1);
  MatrixFree(&RAS_2_to_2);

  if (tal_src)
  {
    MRIfree(&tal_src);
  }
  if (tal_dst)
  {
    MRIfree(&tal_dst);
  }

  printf("%s successful.\n", Progname);

  return(0);

}  /*  end main()  */
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;
}
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) ;
}