static double bench_wavelet_thresh(int version, long scale) { long dims[DIMS] = { 1, 256 * scale, 256 * scale, 1, 16, 1, 1, 1 }; long minsize[DIMS] = { [0 ... DIMS - 1] = 1 }; minsize[0] = MIN(dims[0], 16); minsize[1] = MIN(dims[1], 16); minsize[2] = MIN(dims[2], 16); const struct operator_p_s* p; switch (version) { case 2: p = prox_wavethresh_create(DIMS, dims, 7, minsize, 1.1, true, false); break; case 3: p = prox_wavelet3_thresh_create(DIMS, dims, 6, minsize, 1.1, true); break; default: assert(0); } complex float* x = md_alloc(DIMS, dims, CFL_SIZE); md_gaussian_rand(DIMS, dims, x); double tic = timestamp(); operator_p_apply(p, 0.98, DIMS, dims, x, DIMS, dims, x); double toc = timestamp(); md_free(x); operator_p_free(p); return toc - tic; }
void opt_reg_configure(unsigned int N, const long img_dims[N], struct opt_reg_s* ropts, const struct operator_p_s* prox_ops[NUM_REGS], const struct linop_s* trafos[NUM_REGS], unsigned int llr_blk, bool randshift, bool use_gpu) { float lambda = ropts->lambda; if (-1. == lambda) lambda = 0.; // if no penalities specified but regularization // parameter is given, add a l2 penalty struct reg_s* regs = ropts->regs; if ((0 == ropts->r) && (lambda > 0.)) { regs[0].xform = L2IMG; regs[0].xflags = 0u; regs[0].jflags = 0u; regs[0].lambda = lambda; ropts->r = 1; } int nr_penalties = ropts->r; long blkdims[MAX_LEV][DIMS]; int levels; for (int nr = 0; nr < nr_penalties; nr++) { // fix up regularization parameter if (-1. == regs[nr].lambda) regs[nr].lambda = lambda; switch (regs[nr].xform) { case L1WAV: debug_printf(DP_INFO, "l1-wavelet regularization: %f\n", regs[nr].lambda); if (0 != regs[nr].jflags) debug_printf(DP_WARN, "joint l1-wavelet thresholding not currently supported.\n"); 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); unsigned int wflags = 0; for (unsigned int i = 0; i < DIMS; i++) { if ((1 < img_dims[i]) && MD_IS_SET(regs[nr].xflags, i)) { wflags = MD_SET(wflags, i); minsize[i] = MIN(img_dims[i], 16); } } trafos[nr] = linop_identity_create(DIMS, img_dims); prox_ops[nr] = prox_wavelet3_thresh_create(DIMS, img_dims, wflags, minsize, regs[nr].lambda, randshift); break; case TV: debug_printf(DP_INFO, "TV regularization: %f\n", regs[nr].lambda); trafos[nr] = linop_grad_create(DIMS, img_dims, regs[nr].xflags); prox_ops[nr] = prox_thresh_create(DIMS + 1, linop_codomain(trafos[nr])->dims, regs[nr].lambda, regs[nr].jflags | MD_BIT(DIMS), use_gpu); break; case LLR: debug_printf(DP_INFO, "lowrank regularization: %f\n", regs[nr].lambda); // add locally lowrank penalty levels = llr_blkdims(blkdims, regs[nr].jflags, img_dims, llr_blk); assert(1 == levels); assert(levels == img_dims[LEVEL_DIM]); for(int l = 0; l < levels; l++) #if 0 blkdims[l][MAPS_DIM] = img_dims[MAPS_DIM]; #else blkdims[l][MAPS_DIM] = 1; #endif int remove_mean = 0; trafos[nr] = linop_identity_create(DIMS, img_dims); prox_ops[nr] = lrthresh_create(img_dims, randshift, regs[nr].xflags, (const long (*)[DIMS])blkdims, regs[nr].lambda, false, remove_mean, use_gpu); break; case MLR: #if 0 // FIXME: multiscale low rank changes the output image dimensions // and requires the forward linear operator. This should be decoupled... debug_printf(DP_INFO, "multi-scale lowrank regularization: %f\n", regs[nr].lambda); levels = multilr_blkdims(blkdims, regs[nr].jflags, img_dims, 8, 1); img_dims[LEVEL_DIM] = levels; max_dims[LEVEL_DIM] = levels; for(int l = 0; l < levels; l++) blkdims[l][MAPS_DIM] = 1; trafos[nr] = linop_identity_create(DIMS, img_dims); prox_ops[nr] = lrthresh_create(img_dims, randshift, regs[nr].xflags, (const long (*)[DIMS])blkdims, regs[nr].lambda, false, 0, use_gpu); const struct linop_s* decom_op = sum_create( img_dims, use_gpu ); const struct linop_s* tmp_op = forward_op; forward_op = linop_chain(decom_op, forward_op); linop_free(decom_op); linop_free(tmp_op); #else debug_printf(DP_WARN, "multi-scale lowrank regularization not yet supported: %f\n", regs[nr].lambda); #endif break; case IMAGL1: debug_printf(DP_INFO, "l1 regularization of imaginary part: %f\n", regs[nr].lambda); trafos[nr] = linop_rdiag_create(DIMS, img_dims, 0, &(complex float){ 1.i }); prox_ops[nr] = prox_thresh_create(DIMS, img_dims, regs[nr].lambda, regs[nr].jflags, use_gpu); break; case IMAGL2: debug_printf(DP_INFO, "l2 regularization of imaginary part: %f\n", regs[nr].lambda); trafos[nr] = linop_rdiag_create(DIMS, img_dims, 0, &(complex float){ 1.i }); prox_ops[nr] = prox_leastsquares_create(DIMS, img_dims, regs[nr].lambda, NULL); break; case L1IMG: debug_printf(DP_INFO, "l1 regularization: %f\n", regs[nr].lambda); trafos[nr] = linop_identity_create(DIMS, img_dims); prox_ops[nr] = prox_thresh_create(DIMS, img_dims, regs[nr].lambda, regs[nr].jflags, use_gpu); break; case L2IMG: debug_printf(DP_INFO, "l2 regularization: %f\n", regs[nr].lambda); trafos[nr] = linop_identity_create(DIMS, img_dims); prox_ops[nr] = prox_leastsquares_create(DIMS, img_dims, regs[nr].lambda, NULL); break; case FTL1: debug_printf(DP_INFO, "l1 regularization of Fourier transform: %f\n", regs[nr].lambda); trafos[nr] = linop_fft_create(DIMS, img_dims, regs[nr].xflags); prox_ops[nr] = prox_thresh_create(DIMS, img_dims, regs[nr].lambda, regs[nr].jflags, use_gpu); break; }
void grecon(struct grecon_conf* param, const long dims1[DIMS], complex float* out1, const long cov1_dims[DIMS], complex float* cov1, const long w1_dims[DIMS], const complex float* weights, complex float* kspace1, bool usegpu) { struct sense_conf* conf = param->sense_conf; long ksp1_dims[DIMS]; md_select_dims(DIMS, ~MAPS_FLAG, ksp1_dims, dims1); long pat1_dims[DIMS]; const complex float* pattern; if (NULL == weights) { md_select_dims(DIMS, ~(COIL_FLAG | MAPS_FLAG), pat1_dims, dims1); complex float* tpattern = md_alloc(DIMS, pat1_dims, CFL_SIZE); estimate_pattern(DIMS, ksp1_dims, COIL_DIM, tpattern, kspace1); pattern = tpattern; } else { md_copy_dims(DIMS, pat1_dims, w1_dims); pattern = weights; } complex float* sens1; if (NULL != param->calib) { long img1_dims[DIMS]; md_select_dims(DIMS, ~COIL_FLAG, img1_dims, dims1); complex float* maps1 = md_alloc(DIMS, img1_dims, CFL_SIZE); sens1 = md_alloc(DIMS, dims1, CFL_SIZE); caltwo(param->calib, dims1, sens1, maps1, cov1_dims, cov1, NULL, NULL); crop_sens(dims1, sens1, param->calib->softcrop, param->calib->crop, maps1); fixphase(DIMS, dims1, COIL_DIM, sens1, sens1); md_free(maps1); } else { sens1 = cov1; } if (NOIR == param->algo) { assert(NULL == param->calib); assert(1 == dims1[MAPS_DIM]); sens1 = md_alloc(DIMS, dims1, CFL_SIZE); md_clear(DIMS, dims1, sens1, CFL_SIZE); fftmod(DIMS, ksp1_dims, FFT_FLAGS, kspace1, kspace1); } fftmod(DIMS, dims1, FFT_FLAGS, sens1, sens1); fftmod(DIMS, ksp1_dims, FFT_FLAGS, kspace1, kspace1); complex float* image1 = NULL; long img1_dims[DIMS]; md_select_dims(DIMS, ~COIL_FLAG, img1_dims, dims1); if (param->ksp && (POCS != param->algo)) { image1 = md_alloc(DIMS, img1_dims, CFL_SIZE); md_clear(DIMS, img1_dims, image1, CFL_SIZE); } else { image1 = out1; } #ifdef USE_CUDA int gpun = 0; if (usegpu) { int nr_cuda_devices = MIN(cuda_devices(), MAX_CUDA_DEVICES); gpun = omp_get_thread_num() % nr_cuda_devices; cuda_init(gpun); } #endif const struct operator_p_s* thresh_op = NULL; if (param->l1wav) { long minsize[DIMS] = { [0 ... DIMS - 1] = 1 }; minsize[0] = MIN(img1_dims[0], 16); minsize[1] = MIN(img1_dims[1], 16); minsize[2] = MIN(img1_dims[2], 16); #ifndef W3 thresh_op = prox_wavethresh_create(DIMS, img1_dims, FFT_FLAGS, minsize, param->lambda, param->randshift, usegpu); #else unsigned int wflags = 0; for (unsigned int i = 0; i < 3; i++) if (1 < img1_dims[i]) wflags = MD_SET(wflags, i); thresh_op = prox_wavelet3_thresh_create(DIMS, img1_dims, wflags, minsize, param->lambda, param->randshift); #endif }
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; iconf.rho = 10; // more sensibile default conf.iconf = CAST_UP(&iconf); 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', &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', &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_FLAG, 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 = linop_grad_create(DIMS, img_dims, FFT_FLAGS); l1prox = prox_thresh_create(DIMS + 1, linop_codomain(l1op)->dims, 1., 0u, usegpu); conf.l1op_obj = l1op; } else { long strs[N]; md_calc_strides(N, strs, img_dims, CFL_SIZE); bool randshift = true; l1op = linop_identity_create(DIMS, img_dims); conf.l1op_obj = linop_wavelet3_create(DIMS, FFT_FLAGS, img_dims, strs, minsize); l1prox = prox_wavelet3_thresh_create(DIMS, img_dims, FFT_FLAGS, minsize, 1., randshift); } // ----------------------------------------------------------- // 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