static void perturb(const long dims[2], complex float* vecs, float amt) { complex float* noise = md_alloc(2, dims, CFL_SIZE); md_gaussian_rand(2, dims, noise); for (long j = 0; j < dims[1]; j++) { float nrm = md_znorm(1, dims, noise + j * dims[0]); complex float val = amt / nrm; md_zsmul(1, dims, noise + j * dims[0], noise + j * dims[0], val); } md_zadd(2, dims, vecs, vecs, noise); for (long j = 0; j < dims[1]; j++) { float nrm = md_znorm(1, dims, vecs + j * dims[0]); complex float val = 1 / nrm; md_zsmul(1, dims, vecs + j * dims[0], vecs + j * dims[0], val); } md_free(noise); }
static double bench_norm(int s, long scale) { long dims[DIMS] = { 256 * scale, 256 * scale, 1, 16, 1, 1, 1, 1 }; #if 0 complex float* x = md_alloc_gpu(DIMS, dims, CFL_SIZE); complex float* y = md_alloc_gpu(DIMS, dims, CFL_SIZE); #else complex float* x = md_alloc(DIMS, dims, CFL_SIZE); complex float* y = md_alloc(DIMS, dims, CFL_SIZE); #endif md_gaussian_rand(DIMS, dims, x); md_gaussian_rand(DIMS, dims, y); double tic = timestamp(); switch (s) { case 0: md_zscalar(DIMS, dims, x, y); break; case 1: md_zscalar_real(DIMS, dims, x, y); break; case 2: md_znorm(DIMS, dims, x); break; case 3: md_z1norm(DIMS, dims, x); break; } double toc = timestamp(); md_free(x); md_free(y); return toc - tic; }
int main_bpsense(int argc, char* argv[]) { // ----------------------------------------------------------- // set up conf and option parser struct bpsense_conf conf = bpsense_defaults; struct iter_admm_conf iconf = iter_admm_defaults; conf.iconf = &iconf; conf.iconf->rho = 10; // more sensibile default bool usegpu = false; const char* psf = NULL; const char* image_truth_fname = NULL; bool im_truth = false; bool use_tvnorm = false; double start_time = timestamp(); const struct opt_s opts[] = { OPT_FLOAT('e', &conf.eps, "eps", "data consistency error"), OPT_FLOAT('r', &conf.lambda, "lambda", "l2 regularization parameter"), OPT_FLOAT('u', &conf.iconf->rho, "rho", "ADMM penalty parameter"), OPT_SET('c', &conf.rvc, "real-value constraint"), OPT_SET('t', &use_tvnorm, "use TV norm"), OPT_STRING('T', &image_truth_fname, "file", "compare to truth image"), OPT_UINT('i', &conf.iconf->maxiter, "iter", "max. iterations"), OPT_SET('g', &usegpu, "(use gpu)"), OPT_STRING('p', &psf, "file", "point-spread function"), }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); if (NULL != image_truth_fname) im_truth = true; // ----------------------------------------------------------- // load data and print some info about the recon int N = DIMS; long dims[N]; long dims1[N]; long img_dims[N]; long ksp_dims[N]; complex float* kspace_data = load_cfl(argv[1], N, ksp_dims); complex float* sens_maps = load_cfl(argv[2], N, dims); for (int i = 0; i < 4; i++) // sizes2[4] may be > 1 if (ksp_dims[i] != dims[i]) error("Dimensions of kspace and sensitivities do not match!\n"); assert(1 == ksp_dims[MAPS_DIM]); (usegpu ? num_init_gpu : num_init)(); if (dims[MAPS_DIM] > 1) debug_printf(DP_INFO, "%ld maps.\nESPIRiT reconstruction.\n", dims[4]); if (conf.lambda > 0.) debug_printf(DP_INFO, "l2 regularization: %f\n", conf.lambda); if (use_tvnorm) debug_printf(DP_INFO, "use Total Variation\n"); else debug_printf(DP_INFO, "use Wavelets\n"); if (im_truth) debug_printf(DP_INFO, "Compare to truth\n"); md_select_dims(N, ~(COIL_FLAG | MAPS_FLAG), dims1, dims); md_select_dims(N, ~COIL_FLAG, img_dims, dims); // ----------------------------------------------------------- // initialize sampling pattern complex float* pattern = NULL; long pat_dims[N]; if (NULL != psf) { pattern = load_cfl(psf, N, pat_dims); // FIXME: check compatibility } else { pattern = md_alloc(N, dims1, CFL_SIZE); estimate_pattern(N, ksp_dims, COIL_DIM, pattern, kspace_data); } // ----------------------------------------------------------- // print some statistics size_t T = md_calc_size(N, dims1); long samples = (long)pow(md_znorm(N, dims1, pattern), 2.); debug_printf(DP_INFO, "Size: %ld Samples: %ld Acc: %.2f\n", T, samples, (float)T/(float)samples); // ----------------------------------------------------------- // fftmod to un-center data fftmod(N, ksp_dims, FFT_FLAGS, kspace_data, kspace_data); fftmod(N, dims, FFT_FLAGS, sens_maps, sens_maps); // ----------------------------------------------------------- // apply scaling float scaling = estimate_scaling(ksp_dims, NULL, kspace_data); debug_printf(DP_INFO, "Scaling: %f\n", scaling); if (scaling != 0.) md_zsmul(N, ksp_dims, kspace_data, kspace_data, 1. / scaling); // ----------------------------------------------------------- // create l1 prox operator and transform long minsize[DIMS] = { [0 ... DIMS - 1] = 1 }; minsize[0] = MIN(img_dims[0], 16); minsize[1] = MIN(img_dims[1], 16); minsize[2] = MIN(img_dims[2], 16); const struct linop_s* l1op = NULL; const struct operator_p_s* l1prox = NULL; if (use_tvnorm) { l1op = grad_init(DIMS, img_dims, FFT_FLAGS); l1prox = prox_thresh_create(DIMS + 1, linop_codomain(l1op)->dims, 1., 0u, usegpu); conf.l1op_obj = l1op; } else { bool randshift = true; l1op = linop_identity_create(DIMS, img_dims); conf.l1op_obj = wavelet_create(DIMS, img_dims, FFT_FLAGS, minsize, false, usegpu); l1prox = prox_wavethresh_create(DIMS, img_dims, FFT_FLAGS, minsize, 1., randshift, usegpu); } // ----------------------------------------------------------- // create image and load truth image complex float* image = create_cfl(argv[3], N, img_dims); md_clear(N, img_dims, image, CFL_SIZE); long img_truth_dims[DIMS]; complex float* image_truth = NULL; if (im_truth) image_truth = load_cfl(image_truth_fname, DIMS, img_truth_dims); // ----------------------------------------------------------- // call recon if (usegpu) #ifdef USE_CUDA bpsense_recon_gpu(&conf, dims, image, sens_maps, dims1, pattern, l1op, l1prox, ksp_dims, kspace_data, image_truth); #else assert(0); #endif else
int main_nlinv(int argc, char* argv[]) { int iter = 8; float l1 = -1.; bool waterfat = false; bool rvc = false; bool normalize = true; float restrict_fov = -1.; float csh[3] = { 0., 0., 0. }; bool usegpu = false; const char* psf = NULL; const struct opt_s opts[] = { { 'l', true, opt_float, &l1, NULL }, { 'i', true, opt_int, &iter, NULL }, { 'c', false, opt_set, &rvc, NULL }, { 'N', false, opt_clear, &normalize, NULL }, { 'f', true, opt_float, &restrict_fov, NULL }, { 'p', true, opt_string, &psf, NULL }, { 'g', false, opt_set, &usegpu, NULL }, }; cmdline(&argc, argv, 2, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); num_init(); assert(iter > 0); long ksp_dims[DIMS]; complex float* kspace_data = load_cfl(argv[1], DIMS, ksp_dims); long dims[DIMS]; md_copy_dims(DIMS, dims, ksp_dims); if (waterfat) dims[CSHIFT_DIM] = 2; long img_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS|CSHIFT_FLAG, img_dims, dims); long img_strs[DIMS]; md_calc_strides(DIMS, img_strs, img_dims, CFL_SIZE); complex float* image = create_cfl(argv[2], DIMS, img_dims); long msk_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS, msk_dims, dims); long msk_strs[DIMS]; md_calc_strides(DIMS, msk_strs, msk_dims, CFL_SIZE); complex float* mask; complex float* norm = md_alloc(DIMS, msk_dims, CFL_SIZE); complex float* sens; if (4 == argc) { sens = create_cfl(argv[3], DIMS, ksp_dims); } else { sens = md_alloc(DIMS, ksp_dims, CFL_SIZE); } complex float* pattern = NULL; long pat_dims[DIMS]; if (NULL != psf) { pattern = load_cfl(psf, DIMS, pat_dims); // FIXME: check compatibility } else { pattern = md_alloc(DIMS, img_dims, CFL_SIZE); estimate_pattern(DIMS, ksp_dims, COIL_DIM, pattern, kspace_data); } if (waterfat) { size_t size = md_calc_size(DIMS, msk_dims); md_copy(DIMS, msk_dims, pattern + size, pattern, CFL_SIZE); long shift_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS, shift_dims, msk_dims); long shift_strs[DIMS]; md_calc_strides(DIMS, shift_strs, shift_dims, CFL_SIZE); complex float* shift = md_alloc(DIMS, shift_dims, CFL_SIZE); unsigned int X = shift_dims[READ_DIM]; unsigned int Y = shift_dims[PHS1_DIM]; unsigned int Z = shift_dims[PHS2_DIM]; for (unsigned int x = 0; x < X; x++) for (unsigned int y = 0; y < Y; y++) for (unsigned int z = 0; z < Z; z++) shift[(z * Z + y) * Y + x] = cexp(2.i * M_PI * ((csh[0] * x) / X + (csh[1] * y) / Y + (csh[2] * z) / Z)); md_zmul2(DIMS, msk_dims, msk_strs, pattern + size, msk_strs, pattern + size, shift_strs, shift); md_free(shift); } #if 0 float scaling = 1. / estimate_scaling(ksp_dims, NULL, kspace_data); #else float scaling = 100. / md_znorm(DIMS, ksp_dims, kspace_data); #endif debug_printf(DP_INFO, "Scaling: %f\n", scaling); md_zsmul(DIMS, ksp_dims, kspace_data, kspace_data, scaling); if (-1. == restrict_fov) { mask = md_alloc(DIMS, msk_dims, CFL_SIZE); md_zfill(DIMS, msk_dims, mask, 1.); } else { float restrict_dims[DIMS] = { [0 ... DIMS - 1] = 1. }; restrict_dims[0] = restrict_fov; restrict_dims[1] = restrict_fov; restrict_dims[2] = restrict_fov; mask = compute_mask(DIMS, msk_dims, restrict_dims); } #ifdef USE_CUDA if (usegpu) { complex float* kspace_gpu = md_alloc_gpu(DIMS, ksp_dims, CFL_SIZE); md_copy(DIMS, ksp_dims, kspace_gpu, kspace_data, CFL_SIZE); noir_recon(dims, iter, l1, image, NULL, pattern, mask, kspace_gpu, rvc, usegpu); md_free(kspace_gpu); md_zfill(DIMS, ksp_dims, sens, 1.); } else #endif noir_recon(dims, iter, l1, image, sens, pattern, mask, kspace_data, rvc, usegpu); if (normalize) { md_zrss(DIMS, ksp_dims, COIL_FLAG, norm, sens); md_zmul2(DIMS, img_dims, img_strs, image, img_strs, image, msk_strs, norm); } if (4 == argc) { long strs[DIMS]; md_calc_strides(DIMS, strs, ksp_dims, CFL_SIZE); if (norm) md_zdiv2(DIMS, ksp_dims, strs, sens, strs, sens, img_strs, norm); fftmod(DIMS, ksp_dims, FFT_FLAGS, sens, sens); unmap_cfl(DIMS, ksp_dims, sens); } else { md_free(sens); } md_free(norm); md_free(mask); if (NULL != psf) unmap_cfl(DIMS, pat_dims, pattern); else md_free(pattern); unmap_cfl(DIMS, img_dims, image); unmap_cfl(DIMS, ksp_dims, kspace_data); exit(0); }
int main_pics(int argc, char* argv[]) { // Initialize default parameters struct sense_conf conf = sense_defaults; bool use_gpu = false; bool randshift = true; unsigned int maxiter = 30; float step = -1.; // Start time count double start_time = timestamp(); // Read input options struct nufft_conf_s nuconf = nufft_conf_defaults; nuconf.toeplitz = false; float restrict_fov = -1.; const char* pat_file = NULL; const char* traj_file = NULL; bool scale_im = false; bool eigen = false; float scaling = 0.; unsigned int llr_blk = 8; const char* image_truth_file = NULL; bool im_truth = false; const char* image_start_file = NULL; bool warm_start = false; bool hogwild = false; bool fast = false; float admm_rho = iter_admm_defaults.rho; unsigned int admm_maxitercg = iter_admm_defaults.maxitercg; struct opt_reg_s ropts; ropts.r = 0; ropts.algo = CG; ropts.lambda = -1.; const struct opt_s opts[] = { { 'l', true, opt_reg, &ropts, "1/-l2\t\ttoggle l1-wavelet or l2 regularization." }, OPT_FLOAT('r', &ropts.lambda, "lambda", "regularization parameter"), { 'R', true, opt_reg, &ropts, " <T>:A:B:C\tgeneralized regularization options (-Rh for help)" }, OPT_SET('c', &conf.rvc, "real-value constraint"), OPT_FLOAT('s', &step, "step", "iteration stepsize"), OPT_UINT('i', &maxiter, "iter", "max. number of iterations"), OPT_STRING('t', &traj_file, "file", "k-space trajectory"), OPT_CLEAR('n', &randshift, "disable random wavelet cycle spinning"), OPT_SET('g', &use_gpu, "use GPU"), OPT_STRING('p', &pat_file, "file", "pattern or weights"), OPT_SELECT('I', enum algo_t, &ropts.algo, IST, "(select IST)"), OPT_UINT('b', &llr_blk, "blk", "Lowrank block size"), OPT_SET('e', &eigen, "Scale stepsize based on max. eigenvalue"), OPT_SET('H', &hogwild, "(hogwild)"), OPT_SET('F', &fast, "(fast)"), OPT_STRING('T', &image_truth_file, "file", "(truth file)"), OPT_STRING('W', &image_start_file, "<img>", "Warm start with <img>"), OPT_INT('d', &debug_level, "level", "Debug level"), OPT_INT('O', &conf.rwiter, "rwiter", "(reweighting)"), OPT_FLOAT('o', &conf.gamma, "gamma", "(reweighting)"), OPT_FLOAT('u', &admm_rho, "rho", "ADMM rho"), OPT_UINT('C', &admm_maxitercg, "iter", "ADMM max. CG iterations"), OPT_FLOAT('q', &conf.cclambda, "cclambda", "(cclambda)"), OPT_FLOAT('f', &restrict_fov, "rfov", "restrict FOV"), OPT_SELECT('m', enum algo_t, &ropts.algo, ADMM, "Select ADMM"), OPT_FLOAT('w', &scaling, "val", "scaling"), OPT_SET('S', &scale_im, "Re-scale the image after reconstruction"), }; cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts); if (NULL != image_truth_file) im_truth = true; if (NULL != image_start_file) warm_start = true; long max_dims[DIMS]; long map_dims[DIMS]; long pat_dims[DIMS]; long img_dims[DIMS]; long coilim_dims[DIMS]; long ksp_dims[DIMS]; long traj_dims[DIMS]; // load kspace and maps and get dimensions complex float* kspace = load_cfl(argv[1], DIMS, ksp_dims); complex float* maps = load_cfl(argv[2], DIMS, map_dims); complex float* traj = NULL; if (NULL != traj_file) traj = load_cfl(traj_file, DIMS, traj_dims); md_copy_dims(DIMS, max_dims, ksp_dims); md_copy_dims(5, max_dims, map_dims); md_select_dims(DIMS, ~COIL_FLAG, img_dims, max_dims); md_select_dims(DIMS, ~MAPS_FLAG, coilim_dims, max_dims); if (!md_check_compat(DIMS, ~(MD_BIT(MAPS_DIM)|FFT_FLAGS), img_dims, map_dims)) error("Dimensions of image and sensitivities do not match!\n"); assert(1 == ksp_dims[MAPS_DIM]); (use_gpu ? num_init_gpu : num_init)(); // print options if (use_gpu) debug_printf(DP_INFO, "GPU reconstruction\n"); if (map_dims[MAPS_DIM] > 1) debug_printf(DP_INFO, "%ld maps.\nESPIRiT reconstruction.\n", map_dims[MAPS_DIM]); if (hogwild) debug_printf(DP_INFO, "Hogwild stepsize\n"); if (im_truth) debug_printf(DP_INFO, "Compare to truth\n"); // initialize sampling pattern complex float* pattern = NULL; if (NULL != pat_file) { pattern = load_cfl(pat_file, DIMS, pat_dims); assert(md_check_compat(DIMS, COIL_FLAG, ksp_dims, pat_dims)); } else { md_select_dims(DIMS, ~COIL_FLAG, pat_dims, ksp_dims); pattern = md_alloc(DIMS, pat_dims, CFL_SIZE); estimate_pattern(DIMS, ksp_dims, COIL_DIM, pattern, kspace); } if ((NULL != traj_file) && (NULL == pat_file)) { md_free(pattern); pattern = NULL; nuconf.toeplitz = true; } else { // print some statistics long T = md_calc_size(DIMS, pat_dims); long samples = (long)pow(md_znorm(DIMS, pat_dims, pattern), 2.); debug_printf(DP_INFO, "Size: %ld Samples: %ld Acc: %.2f\n", T, samples, (float)T / (float)samples); } if (NULL == traj_file) { fftmod(DIMS, ksp_dims, FFT_FLAGS, kspace, kspace); fftmod(DIMS, map_dims, FFT_FLAGS, maps, maps); } // apply fov mask to sensitivities if (-1. != restrict_fov) { float restrict_dims[DIMS] = { [0 ... DIMS - 1] = 1. }; restrict_dims[0] = restrict_fov; restrict_dims[1] = restrict_fov; restrict_dims[2] = restrict_fov; apply_mask(DIMS, map_dims, maps, restrict_dims); }
int main_sense(int argc, char* argv[]) { struct sense_conf conf = sense_defaults; double start_time = timestamp(); bool admm = false; bool ist = false; bool use_gpu = false; bool l1wav = false; bool lowrank = false; bool randshift = true; int maxiter = 30; float step = 0.95; float lambda = 0.; float restrict_fov = -1.; const char* pat_file = NULL; const char* traj_file = NULL; const char* image_truth_file = NULL; bool im_truth = false; bool scale_im = false; bool hogwild = false; bool fast = false; float admm_rho = iter_admm_defaults.rho; int c; while (-1 != (c = getopt(argc, argv, "Fq:l:r:s:i:u:o:O:f:t:cT:Imghp:Sd:H"))) { switch(c) { case 'H': hogwild = true; break; case 'F': fast = true; break; case 'I': ist = true; break; case 'T': im_truth = true; image_truth_file = strdup(optarg); assert(NULL != image_truth_file); break; case 'd': debug_level = atoi(optarg); break; case 'r': lambda = atof(optarg); break; case 'O': conf.rwiter = atoi(optarg); break; case 'o': conf.gamma = atof(optarg); break; case 's': step = atof(optarg); break; case 'i': maxiter = atoi(optarg); break; case 'l': if (1 == atoi(optarg)) { l1wav = true; lowrank = false; } else if (2 == atoi(optarg)) { l1wav = false; lowrank = false; } else if (3 == atoi(optarg)) { lowrank = true; l1wav = false; } else { usage(argv[0], stderr); exit(1); } break; case 'q': conf.cclambda = atof(optarg); break; case 'c': conf.rvc = true; break; case 'f': restrict_fov = atof(optarg); break; case 'm': admm = true; break; case 'u': admm_rho = atof(optarg); break; case 'g': use_gpu = true; break; case 'p': pat_file = strdup(optarg); break; case 't': assert(0); break; case 'S': scale_im = true; break; case 'h': usage(argv[0], stdout); help(); exit(0); default: usage(argv[0], stderr); exit(1); } } if (argc - optind != 3) { usage(argv[0], stderr); exit(1); } long map_dims[DIMS]; long pat_dims[DIMS]; long img_dims[DIMS]; long ksp_dims[DIMS]; long max_dims[DIMS]; // load kspace and maps and get dimensions complex float* kspace = load_cfl(argv[optind + 0], DIMS, ksp_dims); complex float* maps = load_cfl(argv[optind + 1], DIMS, map_dims); md_copy_dims(DIMS, max_dims, ksp_dims); max_dims[MAPS_DIM] = map_dims[MAPS_DIM]; md_select_dims(DIMS, ~COIL_FLAG, pat_dims, ksp_dims); md_select_dims(DIMS, ~COIL_FLAG, img_dims, max_dims); for (int i = 0; i < 4; i++) { // sizes2[4] may be > 1 if (ksp_dims[i] != map_dims[i]) { fprintf(stderr, "Dimensions of kspace and sensitivities do not match!\n"); exit(1); } } assert(1 == ksp_dims[MAPS_DIM]); (use_gpu ? num_init_gpu : num_init)(); // print options if (use_gpu) debug_printf(DP_INFO, "GPU reconstruction\n"); if (map_dims[MAPS_DIM] > 1) debug_printf(DP_INFO, "%ld maps.\nESPIRiT reconstruction.\n", map_dims[MAPS_DIM]); if (l1wav) debug_printf(DP_INFO, "l1-wavelet regularization\n"); if (ist) debug_printf(DP_INFO, "Use IST\n"); if (im_truth) debug_printf(DP_INFO, "Compare to truth\n"); // initialize sampling pattern complex float* pattern = NULL; long pat_dims2[DIMS]; if (NULL != pat_file) { pattern = load_cfl(pat_file, DIMS, pat_dims2); // FIXME: check compatibility } else { pattern = md_alloc(DIMS, pat_dims, CFL_SIZE); estimate_pattern(DIMS, ksp_dims, COIL_DIM, pattern, kspace); } // print some statistics size_t T = md_calc_size(DIMS, pat_dims); long samples = (long)pow(md_znorm(DIMS, pat_dims, pattern), 2.); debug_printf(DP_INFO, "Size: %ld Samples: %ld Acc: %.2f\n", T, samples, (float)T / (float)samples); fftmod(DIMS, ksp_dims, FFT_FLAGS, kspace, kspace); fftmod(DIMS, map_dims, FFT_FLAGS, maps, maps); // apply fov mask to sensitivities if (-1. != restrict_fov) { float restrict_dims[DIMS] = { [0 ... DIMS - 1] = 1. }; restrict_dims[0] = restrict_fov; restrict_dims[1] = restrict_fov; restrict_dims[2] = restrict_fov; apply_mask(DIMS, map_dims, maps, restrict_dims); }