Пример #1
0
void iter_admm(iter_conf* _conf,
		const struct operator_s* normaleq_op,
		const struct operator_p_s* thresh_prox,
		long size, float* image, const float* image_adj,
		struct iter_monitor_s* monitor)
{
	const struct linop_s* eye[1] = { linop_identity_create(1, MD_DIMS(size / 2)) }; // using complex float identity operator... divide size by 2

	iter2_admm(_conf, normaleq_op, 1, &thresh_prox, eye, NULL, NULL, size, image, image_adj, monitor);

	linop_free(eye[0]);
}
Пример #2
0
void iter_admm(iter_conf* _conf,
		const struct operator_s* normaleq_op,
		const struct operator_p_s* thresh_prox,
		long size, float* image, const float* image_adj,
		const float* image_truth,
		void* objval_data,
		float (*obj_eval)(const void*, const float*))
{
	const struct linop_s* eye[1] = { linop_identity_create(1, MD_DIMS(size / 2)) }; // using complex float identity operator... divide size by 2

	iter2_admm(_conf, normaleq_op, 1, &thresh_prox, eye, NULL, size, image, image_adj, image_truth, objval_data, obj_eval);

	linop_free(eye[0]);
}
Пример #3
0
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
Пример #4
0
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;
		}