int
main(int argc, char *argv[]) {
  char   **av, fname[STRLEN] ;
  int    ac, nargs, i ;
  MRI    *mri_flash[MAX_IMAGES], *mri_T1, *mri_PD ;
  char   *in_fname, *out_PD_fname, *out_T1_fname ;
  int          msec, minutes, seconds, nvolumes ;
  struct timeb start ;

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

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

  TimerStart(&start) ;
  parms.dt = 1e-6 ;
  parms.tol = 1e-5 ;
  parms.momentum = 0.0 ;
  parms.niterations = 20 ;

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

  out_T1_fname = argv[argc-2] ;
  out_PD_fname = argv[argc-1] ;
  FileNameOnly(out_T1_fname, fname) ;
  FileNameRemoveExtension(fname, fname) ;
  strcpy(parms.base_name, fname) ;

  nvolumes = 0 ;
  for (i = 1 ; i < argc-2 ; i++) {
    if (argv[i][0] == '-') {
      if (!stricmp(argv[i]+1, "te"))
        te = atof(argv[i+1]) ;
      else if (!stricmp(argv[i]+1, "tr"))
        tr = atof(argv[i+1]) ;
      else if (!stricmp(argv[i]+1, "fa"))
        fa = RADIANS(atof(argv[i+1])) ;
      else
        ErrorExit(ERROR_BADPARM, "%s: unsupported MR parameter %s",
                  Progname, argv[i]+1) ;
      i++ ;  /* skip parameter */
      continue ;
    }

    in_fname = argv[i] ;
    printf("reading %s...", in_fname) ;

    mri_flash[nvolumes] = MRIread(in_fname) ;
    if (!mri_flash[nvolumes])
      ErrorExit(Gerror, "%s: MRIread(%s) failed", Progname, in_fname) ;
    if (tr > 0) {
      mri_flash[nvolumes]->tr = tr ;
      tr = 0 ;
    }
    if (te > 0) {
      mri_flash[nvolumes]->te = te ;
      te = 0 ;
    }
    if (fa > 0) {
      mri_flash[nvolumes]->flip_angle = fa ;
      fa = 0 ;
    }
    printf("TE = %2.2f, TR = %2.2f, alpha = %2.2f\n", mri_flash[nvolumes]->te,
           mri_flash[nvolumes]->tr, DEGREES(mri_flash[nvolumes]->flip_angle)) ;
    mri_flash[nvolumes]->flip_angle = mri_flash[nvolumes]->flip_angle;
    if (conform) {
      MRI *mri_tmp ;

      printf("embedding and interpolating volume\n") ;
      mri_tmp = MRIconform(mri_flash[nvolumes]) ;
      /*      MRIfree(&mri_src) ;*/
      mri_flash[nvolumes] = mri_tmp ;
    }
    if (FZERO(mri_flash[nvolumes]->tr) ||
        FZERO(mri_flash[nvolumes]->flip_angle))
      ErrorExit(ERROR_BADPARM, "%s: invalid TR or FA for image %d:%s",
                Progname, nvolumes, in_fname) ;
    nvolumes++ ;
  }
  printf("using %d FLASH volumes to estimate tissue parameters.\n", nvolumes) ;
  mri_T1 = MRIclone(mri_flash[0], NULL) ;
  mri_PD = MRIclone(mri_flash[0], NULL) ;


  {
    double   sse, last_T1, last_PD, total_rms, avg_rms ;
    int      x, y, z, width, height, depth, total_vox, ignored, nvox ;
    struct timeb first_slice ;

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

    TimerStart(&first_slice) ;

    last_T1 = last_PD = 1000 ;
    sse = 0.0 ;
    width = mri_T1->width ;
    height = mri_T1->height ;
    depth = mri_T1->depth ;
    total_vox = width*depth*height ;
#if 0
    estimateVoxelParameters(mri_flash, nvolumes, width/2, height/2, depth/2,
                            mri_T1, mri_PD, last_T1, last_PD) ;
#endif
    if (Gdiag_no == 999) {
      x = 130 ;
      y = 124 ;
      z = 74 ; /* CSF */
      computeErrorSurface("error_surf_csf.dat",mri_flash,nvolumes,x,y,z,500,3000,500,3000);
      x = 161 ;
      y = 157 ;
      z = 63 ;  /* wm */
      computeErrorSurface("error_surf_wm.dat",mri_flash,nvolumes,x,y,z,250,3000,250,3000);
      x = 166 ;
      y = 153 ;
      z = 63 ;  /* gm */
      computeErrorSurface("error_surf_gm.dat",mri_flash,nvolumes,x,y,z,250,3000,250,3000);
    }
    avg_rms = 0 ;
    for (ignored = z = 0 ; z < depth ; z++) {
      if (z > 0)
        printf("z = %d, avg rms=%2.1f, T1=%2.0f, PD=%2.0f...\n",
               z, avg_rms, last_T1, last_PD) ;
#if 0
      if (z > 0 && z*width*height - ignored > 0) {
        int processed = z*width*height - ignored, hours ;

        msec = TimerStop(&first_slice) ;
        seconds = nint((float)msec/1000.0f) ;
        minutes = seconds / 60 ;
        seconds = seconds % 60 ;
        hours = minutes / 60 ;
        minutes = minutes % 60 ;
        printf("%02d:%02d:%02d total processing time ... ",
               hours,minutes,seconds);
        msec = (int)((float)(total_vox-ignored)*msec/(float)processed) ;
        seconds = nint((float)msec/1000.0f) ;
        minutes = seconds / 60 ;
        seconds = seconds % 60 ;
        hours = minutes / 60 ;
        minutes = minutes % 60 ;
        printf("estimate %02d:%02d:%02d remaining.\n", hours,minutes, seconds);
      }
#endif
      if (write_iterations > 0 && z > 0 && !(z%write_iterations)) {
        printf("writing T1 esimates to %s...\n", out_T1_fname) ;
        printf("writing PD estimates to %s...\n", out_PD_fname) ;
        MRIwrite(mri_T1, out_T1_fname) ;
        MRIwrite(mri_PD, out_PD_fname) ;
        printf("writing residuals to %s...\n", residual_name) ;
        if (residual_name) {
          MRI *mri_res, *mri_res_total = NULL ;
          for (i = 0 ; i < nvolumes ; i++) {

            mri_res = compute_residuals(mri_flash[i], mri_T1, mri_PD) ;
            sprintf(fname, "%s%d.mgh", residual_name, i) ;
#if 0
            MRIwrite(mri_res, fname) ;
#endif
            if (!mri_res_total) {
              mri_res_total = MRIcopy(mri_res, NULL) ;
            } else {
              MRIsadd(mri_res, mri_res_total, mri_res_total) ;
            }

            MRIfree(&mri_res) ;
          }
          MRIsscalarMul(mri_res_total, mri_res_total, 1.0/(float)nvolumes) ;
          MRIssqrt(mri_res_total, mri_res_total) ;
          sprintf(fname, "%s.mgh", residual_name) ;
          MRIwrite(mri_res_total, fname) ;
        }
      }

      nvox = 0 ;
      total_rms = 0 ;
      for (y = 0 ; y < height ; y++) {
#if 0
        if (y%32 == 0 && nvox > 0)
          printf("z = %d, y = %d, avg rms=%2.1f, T1=%2.0f, PD=%2.0f...\n",
                 z, y, total_rms/(double)nvox, last_T1, last_PD) ;
#endif
        for (x = 0 ; x < width ; x++) {
#if 0
          for (i = 0 ; i < nvolumes ; i++)
            if (MRISvox(mri_flash[i],x,y,z) > thresh)
              break ;
          if (i >= nvolumes)
#else
          if (no_valid_data(mri_flash, nvolumes, x, y, z, thresh))
#endif
          {
            ignored++ ;
            MRISvox(mri_T1, x, y, z) = MRISvox(mri_PD, x, y, z) = 0 ;
            /*            last_T1 = last_PD = 1000 ;*/
            continue ;
          }
#if 0
          sse = findInitialParameters(mri_flash, nvolumes, x, y, z,
                                      last_PD-1000, last_PD+1000,
                                      last_T1-1000, last_T1+1000,
                                      &last_PD, &last_T1, 10) ;
#endif
#if 0
          sse = findInitialParameters(mri_flash, nvolumes, x, y, z,
                                      last_PD-100, last_PD+100,
                                      last_T1-100, last_T1+100,
                                      &last_PD, &last_T1, 10) ;
          if (last_T1 <= MIN_T1 || last_PD <= 0) {
            ignored++ ;
            MRISvox(mri_T1, x, y, z) = MRISvox(mri_PD, x, y, z) = 0 ;
            /*            last_T1 = last_PD = 1000 ;*/
            continue ;
          }
#endif
          sse = estimateVoxelParameters(mri_flash, nvolumes, x, y, z,
                                        mri_T1, mri_PD, nsteps) ;
          nvox++ ;
          last_T1 = MRISvox(mri_T1, x, y, z) ;
          last_PD = MRISvox(mri_PD, x, y, z) ;
          total_rms += sqrt(sse/nvolumes) ;
          if (!finite(total_rms))
            DiagBreak() ;
        }
      }
      avg_rms = total_rms / nvox ;
      if (!finite(avg_rms))
        DiagBreak() ;
    }
  }


  printf("writing T1 esimates to %s...\n", out_T1_fname) ;
  printf("writing PD estimates to %s...\n", out_PD_fname) ;
  MRIwrite(mri_T1, out_T1_fname) ;
  MRIwrite(mri_PD, out_PD_fname) ;
  if (residual_name) {
    MRI *mri_res_total = NULL ;

    for (i = 0 ; i < nvolumes ; i++) {
      MRI *mri_res ;

      mri_res = compute_residuals(mri_flash[i], mri_T1, mri_PD) ;
#if 0
      sprintf(fname, "%s%d.mgh", residual_name, i) ;
      MRIwrite(mri_res, fname) ;
#endif
      if (!mri_res_total) {
        mri_res_total = MRIcopy(mri_res, NULL) ;
      } else {
        MRIsadd(mri_res, mri_res_total, mri_res_total) ;
      }
      MRIfree(&mri_res) ;
    }
    MRIsscalarMul(mri_res_total, mri_res_total, 1.0/(float)nvolumes) ;
    MRIssqrt(mri_res_total, mri_res_total) ;
    sprintf(fname, "%s.mgh", residual_name) ;
    MRIwrite(mri_res_total, fname) ;
  }
  MRIfree(&mri_T1) ;
  MRIfree(&mri_PD) ;
  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf("parameter estimation took %d minutes and %d seconds.\n",
         minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
Exemple #2
0
/* DIFF: was gto_fit_rxyscale */
static int
geo_fit_linear(
        geomap_fit_t* const fit,
        surface_t* const sx1,
        surface_t* const sy1,
        const size_t ncoord,
        const coord_t* const input,
        const coord_t* const ref,
        const double* const weights,
        double* const residual_x,
        double* const residual_y,
        stimage_error_t* error) {

    bbox_t  bbox;
    double  sw      = 0.0;
    coord_t sr      = {0.0, 0.0};
    coord_t si      = {0.0, 0.0};
    coord_t r0      = {0.0, 0.0};
    coord_t i0      = {0.0, 0.0};
    double  sxrxr   = 0.0;
    double  syryr   = 0.0;
    double  syrxi   = 0.0;
    double  sxryi   = 0.0;
    double  sxrxi   = 0.0;
    double  syryi   = 0.0;
    double  num     = 0.0;
    double  denom   = 0.0;
    double  theta   = 0.0;
    double  ctheta  = 0.0;
    double  stheta  = 0.0;
    coord_t cthetac = {0.0, 0.0};
    coord_t sthetac = {0.0, 0.0};
    double  xmag    = 0.0;
    double  ymag    = 0.0;
    size_t  i       = 0;
    int     status  = 1;

    assert(fit);
    assert(sx1);
    assert(sy1);
    assert(input);
    assert(ref);
    assert(weights);
    assert(residual_x);
    assert(residual_y);

    surface_free(sx1);
    surface_free(sy1);

    bbox_copy(&fit->bbox, &bbox);
    bbox_make_nonsingular(&bbox);

    /* Compute the sums required to determine the offsets */
    compute_sums(ncoord, input, ref, weights, &sw, &si, &sr);

    if (sw < 3.0) {
        if (fit->projection == geomap_proj_none) {
            stimage_error_set_message(
                    error, "Too few data points for X and Y fits.");
        } else {
            stimage_error_set_message(
                    error, "Too few data points for XI and ETA fits.");
        }
        goto exit;
    }

    r0.x = sr.x / sw;
    r0.y = sr.y / sw;
    i0.x = si.x / sw;
    i0.y = si.y / sw;
    for (i = 0; i < ncoord; ++i) {
        sxrxr += weights[i] * (ref[i].x - r0.x) * (ref[i].x - r0.x);
        syryr += weights[i] * (ref[i].y - r0.y) * (ref[i].y - r0.y);
        syrxi += weights[i] * (ref[i].y - r0.y) * (input[i].x - i0.x);
        sxryi += weights[i] * (ref[i].x - r0.x) * (input[i].y - i0.y);
        sxrxi += weights[i] * (ref[i].x - r0.x) * (input[i].x - i0.x);
        syryi += weights[i] * (ref[i].y - r0.y) * (input[i].y - i0.y);
    }

    /* Compute the rotation angle */
    num = 2.0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi);
    denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - \
        sxrxr * (syrxi + syryi) * (syrxi - syryi);
    if (double_approx_equal(num, 0.0) && double_approx_equal(denom, 0.0)) {
        theta = 0.0;
    } else {
        theta = atan2(num, denom) / 2.0;
        if (theta < 0.0) {
            theta += M_PI * 2.0;
        }
    }

    ctheta = cos(theta);
    stheta = sin(theta);

    /* Compute the X magnification factor */
    num = sxrxi * ctheta - sxryi * stheta;
    denom = sxrxr;
    if (denom <= 0.0) {
        xmag = 1.0;
    } else {
        xmag = num / denom;
    }

    /* Compute the Y magnification factor */
    num = syrxi * stheta + syryi * ctheta;
    denom = syryr;
    if (denom <= 0.0) {
        ymag = 1.0;
    } else {
        ymag = num / denom;
    }

    /* Compute the polynomial coefficients */
    cthetac.x = xmag * ctheta;
    sthetac.x = ymag * stheta;
    sthetac.y = xmag * stheta;
    cthetac.x = ymag * ctheta;

    /* Compute the X and Y fit coefficients */
    if (compute_surface_coefficients(
                fit->function, &bbox, &i0, &r0, &cthetac, &sthetac, sx1, sy1,
                error)) goto exit;

    /* Compute the residuals */
    if (compute_residuals(
                sx1, sy1, ncoord, input, ref, residual_x, residual_y,
                error)) goto exit;

    /* Compute the number of zero-weighted points */
    fit->n_zero_weighted = count_zero_weighted(ncoord, weights);

    /* Compute the rms of the x and y fits */
    compute_rms(
            ncoord, weights, residual_x, residual_y, &fit->xrms, &fit->yrms);

    fit->ncoord = ncoord;

    status = 0;

 exit:

    return status;
}