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