Beispiel #1
0
float* create_coo(const char* name, unsigned int D, const long dims[D])
{	
	int ofd;
	if (-1 == (ofd = open(name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)))
		io_error("Creating coo file %s", name);

	if (-1 == write_coo(ofd, D, dims))
		io_error("Creating coo file %s", name);

	long T = md_calc_size(D, dims) * sizeof(float);

	void* addr;

	if (NULL == (addr = create_data(ofd, 4096, T)))
		io_error("Creating coo file %s", name);

	if (-1 == close(ofd))
		io_error("Creating coo file %s", name);

	return (float*)addr;
}
Beispiel #2
0
const struct operator_p_s* prox_normaleq_create(const struct linop_s* op, const complex float* y)
{
	PTR_ALLOC(struct prox_normaleq_data, pdata);
	SET_TYPEID(prox_normaleq_data, pdata);
	PTR_ALLOC(struct iter_conjgrad_conf, cgconf);

	*cgconf = iter_conjgrad_defaults;
	cgconf->maxiter = 10;
	cgconf->l2lambda = 0;

	pdata->cgconf = PTR_PASS(cgconf);
	pdata->op = op;

	pdata->size = 2 * md_calc_size(linop_domain(op)->N, linop_domain(op)->dims);
	pdata->adj = md_alloc_sameplace(1, &(pdata->size), FL_SIZE, y);
	linop_adjoint_iter((struct linop_s*)op, pdata->adj, (const float*)y);

	return operator_p_create(linop_domain(op)->N, linop_domain(op)->dims, 
			linop_domain(op)->N, linop_domain(op)->dims, 
			CAST_UP(PTR_PASS(pdata)), prox_normaleq_apply, prox_normaleq_del);
}
Beispiel #3
0
extern gboolean refresh_callback(GtkWidget *widget, gpointer data)
{
	struct view_s* v = data;

	v->invalid = true;

	long size = md_calc_size(DIMS, v->dims);
	double max = 0.;
	for (long j = 0; j < size; j++)
		if (max < cabsf(v->data[j]))
			max = cabsf(v->data[j]);

	if (0. == max)
		max = 1.;

	v->max = max;

	update_view(v);

	return FALSE;
}
Beispiel #4
0
void noir_adj(struct noir_data* data, complex float* dst, const complex float* src)
{
	long split = md_calc_size(DIMS, data->imgs_dims);

	md_zmulc2(DIMS, data->sign_dims, data->sign_strs, data->tmp, data->data_strs, src, data->ptrn_strs, data->pattern);

	ifft(DIMS, data->sign_dims, FFT_FLAGS, data->tmp, data->tmp);

	// we should move it to the end, but fft scaling is applied so this would be need to moved into data->xn or weights maybe?
	md_zmulc2(DIMS, data->sign_dims, data->sign_strs, data->tmp, data->sign_strs, data->tmp, data->mask_strs, data->mask);

	md_clear(DIMS, data->coil_dims, dst + split, CFL_SIZE);
	md_zfmacc2(DIMS, data->sign_dims, data->coil_strs, dst + split, data->sign_strs, data->tmp, data->imgs_strs, data->xn);

	noir_back_coils(data, dst + split, dst + split);

	md_clear(DIMS, data->imgs_dims, dst, CFL_SIZE);
	md_zfmacc2(DIMS, data->sign_dims, data->imgs_strs, dst, data->sign_strs, data->tmp, data->coil_strs, data->sens);

	if (data->rvc)
		md_zreal(DIMS, data->imgs_dims, dst, dst);
}
Beispiel #5
0
static void linop_matrix_apply_normal(const linop_data_t* _data, complex float* dst, const complex float* src)
{
	const struct operator_matrix_s* data = CAST_DOWN(operator_matrix_s, _data);

	unsigned int N = data->mat_iovec->N;
	// FIXME check all the cases where computation can be done with blas
	
	//debug_printf(DP_DEBUG1, "compute normal\n");
	if (cgemm_forward_standard(data)) {

		long max_dims_gram[N];
		md_copy_dims(N, max_dims_gram, data->domain_iovec->dims);
		max_dims_gram[data->T_dim] = data->K;

		long tmp_dims[N];
		long tmp_str[N];
		md_copy_dims(N, tmp_dims, max_dims_gram);
		tmp_dims[data->K_dim] = 1;
		md_calc_strides(N, tmp_str, tmp_dims, CFL_SIZE);

		complex float* tmp = md_alloc_sameplace(N, data->domain_iovec->dims, CFL_SIZE, dst);

		md_clear(N, data->domain_iovec->dims, tmp, CFL_SIZE);
		md_zfmac2(N, max_dims_gram, tmp_str, tmp, data->domain_iovec->strs, src, data->mat_gram_iovec->strs, data->mat_gram);
		md_transpose(N, data->T_dim, data->K_dim, data->domain_iovec->dims, dst, tmp_dims, tmp, CFL_SIZE);

		md_free(tmp);

	} else {

		long L = md_calc_size(data->T_dim, data->domain_iovec->dims);

		blas_cgemm('N', 'T', L, data->K, data->K, 1.,
				L, (const complex float (*)[])src,
				data->K, (const complex float (*)[])data->mat_gram,
				0., L, (complex float (*)[])dst);
	}

}
Beispiel #6
0
float nucnorm_blockproc( const void* _data, const long blkdims[DIMS], complex float* dst, const complex float* src )
{
	UNUSED(dst);

	const struct svthresh_blockproc_data* data = (const struct svthresh_blockproc_data*) _data;

	long M = 1;
	long N = md_calc_size( DIMS, blkdims );


	for ( unsigned int i = 0; i < DIMS; i++ )
	{
		if (MD_IS_SET(data->mflags, i))
		{
			M *= blkdims[i];
			N /= blkdims[i];
		}
	}

	float G = sqrtf(M) + sqrtf(N);

	return G * nuclearnorm(M, N, src);
}
Beispiel #7
0
Datei: fft.c Projekt: hcmh/bart
static void fftmod2_r(unsigned int N, const long dims[N], unsigned long flags, const long ostrs[N], complex float* dst, const long istrs[N], const complex float* src, bool inv, double phase)
{
	if (0 == flags) {

		md_zsmul2(N, dims, ostrs, dst, istrs, src, cexp(M_PI * 2.i * (inv ? -phase : phase)));
		return;
	}


	/* this will also currently be slow on the GPU because we do not
	 * support strides there on the lowest level */

	unsigned int i = N - 1;
	while (!MD_IS_SET(flags, i))
		i--;

#if 1
	// If there is only one dimensions left and it is the innermost
	// which is contiguous optimize using md_zfftmod2

	if ((0u == MD_CLEAR(flags, i)) && (1 == md_calc_size(i, dims))
		&& (CFL_SIZE == ostrs[i]) && (CFL_SIZE == istrs[i])) {

		md_zfftmod2(N - i, dims + i, ostrs + i, dst, istrs + i, src, inv, phase);
		return;
	}
#endif

	long tdims[N];
	md_select_dims(N, ~MD_BIT(i), tdims, dims);

	#pragma omp parallel for
	for (int j = 0; j < dims[i]; j++)
		fftmod2_r(N, tdims, MD_CLEAR(flags, i),
			ostrs, (void*)dst + j * ostrs[i], istrs, (void*)src + j * istrs[i],
			inv, phase + fftmod_phase(dims[i], j));
}
Beispiel #8
0
void direct_calib(const long dims[5], complex float* sens, const long caldims[5], const complex float* data)
{
	complex float* tmp = md_alloc(5, caldims, CFL_SIZE);

	assert(1 == caldims[4]);
	assert(1 == dims[4]);

	md_copy(5, caldims, tmp, data, CFL_SIZE);

	// apply Kaiser-Bessel Window beta=4
	for (int z = 0; z < caldims[2]; z++)
		for (int y = 0; y < caldims[1]; y++)
			for (int x = 0; x < caldims[0]; x++)
				for (int c = 0; c < caldims[3]; c++)
					tmp[((c * caldims[2] + z) * caldims[1] + y) * caldims[0] + x]
						*= kaiser(4., caldims[2], z)
						* kaiser(4., caldims[1], y)
						* kaiser(4., caldims[0], x);

	md_resize_center(5, dims, sens, caldims, tmp, CFL_SIZE);

	ifftc(5, dims, 7, sens, sens);

	long dims1[5];
	md_select_dims(5, ~MD_BIT(COIL_DIM), dims1, dims);

	complex float* img = md_alloc(5, dims1, CFL_SIZE);

	md_zrss(5, dims, COIL_FLAG, img, sens);
#if 1
	long T = md_calc_size(5, dims1);
	for (int i = 0; i < T; i++)
		for (int j = 0; j < dims[COIL_DIM]; j++)
			sens[j * T + i] *= (cabs(img[i]) == 0.) ? 0. : (1. / cabs(img[i]));
#endif
	md_free(img);
}
Beispiel #9
0
void iwt(unsigned int N, unsigned int flags, const long shifts[N], const long dims[N], const long ostr[N], complex float* out, const complex float* in, const long minsize[N], const long flen, const float filter[2][2][flen])
{
	if (0 == flags) {

		if (out != in)
			md_copy2(N, dims, ostr, out, ostr, in, CFL_SIZE);

		return;
	}

	unsigned long coeffs = wavelet_coeffs(N, flags, dims, minsize, flen);

	long wdims[2 * N];
	wavelet_dims(N, flags, wdims, dims, flen);

	long istr[2 * N];
	md_calc_strides(2 * N, istr, wdims, CFL_SIZE);

	long offset = coeffs - md_calc_size(2 * N, wdims);

	debug_printf(DP_DEBUG4, "%d %ld %ld\n", flags, coeffs, offset);

	complex float* tmp = md_alloc_sameplace(2 * N, wdims, CFL_SIZE, out);

	md_copy(2 * N, wdims, tmp, in + offset, CFL_SIZE);

	long shifts0[N];
	for (unsigned int i = 0; i < N; i++)
		shifts0[i] = 0;

	// fix me we need temp storage
	iwt(N, wavelet_filter_flags(N, flags, wdims, minsize), shifts0, wdims, istr, tmp, in, minsize, flen, filter);
	iwtN(N, flags, shifts, dims, ostr, out, istr, tmp, flen, filter);

	md_free(tmp);
}
Beispiel #10
0
int main(int argc, char *argv[])
{
	MATFile *mat;
	const char* name = NULL;
	const mwSize* dims;

	if (argc != 2) {

		fprintf(stderr, "Usage: %s file.mat\n", argv[0]);
		exit(1);
	}


	if (NULL == (mat = matOpen(argv[1], "r")))
		exit(1);

	mxArray* ar;

	while (NULL != (ar = matGetNextVariable(mat, &name))) {

		int ndim = (int)mxGetNumberOfDimensions(ar);
		dims = mxGetDimensions(ar);

		bool cmp = mxIsComplex(ar);
		bool dbl = mxIsDouble(ar);

		printf("%s: [ ", name);

		if ((!cmp) || (!dbl)) {

			printf("not complex double\n");
			mxDestroyArray(ar);
			continue;
		}

		long ldims[ndim];
	        for (int i = 0; i < ndim; i++)
			ldims[i] = dims[i];	

		for (int i = 0; i < ndim; i++)
			printf("%ld ", ldims[i]);

		char outname[256];
		snprintf(outname, 256, "%s_%s", strtok(argv[1], "."), name);

		complex float* buf = create_cfl(outname, ndim, ldims);
		double* re = mxGetPr(ar);
		double* im = mxGetPi(ar);

		size_t size = md_calc_size(ndim, ldims);

		for (unsigned long i = 0; i < size; i++) 
			buf[i] = re[i] + 1.i * im[i];

		printf("] -> %s\n", outname);

		unmap_cfl(ndim, ldims, buf);
		mxDestroyArray(ar);
	}

	matClose(mat);
}
Beispiel #11
0
void overlapandsave2HB(const struct vec_ops* ops, int N, unsigned int flags, const long blk[N], const long dims1[N], complex float* dst, const long odims[N], const complex float* src1, const long dims2[N], const complex float* src2, const long mdims[N], const complex float* msk)
{
	long dims1B[N];

	long tdims[2 * N];
	long nodims[2 * N];
	long ndims2[2 * N];
	long nmdims[2 * N];


	int e = N;

	for (int i = 0; i < N; i++) {

		if (MD_IS_SET(flags, i)) {

			assert(1 == dims2[i] % 2);
			assert(0 == blk[i] % 2);
			assert(0 == dims1[i] % 2);
			assert(0 == odims[i] % blk[i]);
			assert(0 == dims1[i] % blk[i]);
			assert(dims1[i] == odims[i]);
			assert(dims2[i] <= blk[i]);
			assert(dims1[i] >= dims2[i]);
			assert((1 == mdims[i]) || (mdims[i] == dims1[i]));

			// blocked output

			nodims[e] = odims[i] / blk[i];
			nodims[i] = blk[i];

			// expanded temporary storage

			tdims[e] = dims1[i] / blk[i];
			tdims[i] = blk[i] + dims2[i] - 1;

			// blocked input

			// ---|---,---,---|---
			//   + +++ +
			//       + +++ +

			if (1 == mdims[i]) {

				nmdims[2 * i + 1] = 1;
				nmdims[2 * i + 1] = 1;

			} else {

				nmdims[2 * i + 1] = mdims[i] / blk[i];
				nmdims[2 * i + 0] = blk[i];
			}

			// resized input
			// minimal padding
			dims1B[i] = dims1[i] + (dims2[i] - 1);

			// kernel

			ndims2[e] = 1;
			ndims2[i] = dims2[i];

			e++;

		} else {

			nodims[i] = odims[i];
			tdims[i] = dims1[i];
			nmdims[2 * i + 1] = 1;
			nmdims[2 * i + 0] = mdims[i];

			dims1B[i] = dims1[i];
			ndims2[i] = dims2[i];
		}
	}

	int NE = e;

	// long S = md_calc_size(N, dims1B, 1);

	long str1[NE];

	long str1B[N];
	md_calc_strides(N, str1B, dims1B, sizeof(complex float));

	e = N;
	for (int i = 0; i < N; i++) {

		str1[i] = str1B[i];

		if (MD_IS_SET(flags, i))
			str1[e++] = str1B[i] * blk[i];
	}
	assert(NE == e);



	long str2[NE];
	md_calc_strides(NE, str2, tdims, sizeof(complex float));


	long ostr[NE];
	long mstr[NE];
	long mstrB[2 * N];

	md_calc_strides(NE, ostr, nodims, sizeof(complex float));
	md_calc_strides(2 * N, mstrB, nmdims, sizeof(complex float));

	e = N;
	for (int i = 0; i < N; i++) {

		mstr[i] = mstrB[2 * i + 0];

		if (MD_IS_SET(flags, i))
			mstr[e++] = mstrB[2 * i + 1];
	}
	assert(NE == e);
	
	// we can loop here
	assert(NE == N + 3);
	assert(1 == ndims2[N + 0]);
	assert(1 == ndims2[N + 1]);
	assert(1 == ndims2[N + 2]);
	assert(tdims[N + 0] == nodims[N + 0]);
	assert(tdims[N + 1] == nodims[N + 1]);
	assert(tdims[N + 2] == nodims[N + 2]);

	long R = md_calc_size(N, nodims);
	long T = md_calc_size(N, tdims);


	//complex float* src1C = xmalloc(S * sizeof(complex float));
	complex float* src1C = dst;

	md_clear(N, dims1B, src1C, CFL_SIZE);	// must be done here

	#pragma omp parallel for collapse(3)
	for (int k = 0; k < nodims[N + 2]; k++) {
	for (int j = 0; j < nodims[N + 1]; j++) {
	for (int i = 0; i < nodims[N + 0]; i++) {

		    complex float* tmp = (complex float*)ops->allocate(2 * T);
		    complex float* tmpX = (complex float*)ops->allocate(2 * R);

		    long off1 = str1[N + 0] * i + str1[N + 1] * j + str1[N + 2] * k;
		    long off2 = mstr[N + 0] * i + mstr[N + 1] * j + mstr[N + 2] * k;
		    long off3 = ostr[N + 0] * i + ostr[N + 1] * j + ostr[N + 2] * k;

		    md_zmul2(N, nodims, ostr, tmpX, ostr, ((const void*)src1) + off3, mstr, ((const void*)msk) + off2);
		    convH(N, flags, CONV_VALID, CONV_SYMMETRIC, tdims, tmp, nodims, tmpX, ndims2, src2);

		    #pragma omp critical
		    md_zadd2(N, tdims, str1, ((void*)src1C) + off1, str1, ((void*)src1C) + off1, str2,  tmp);

		    ops->del((void*)tmpX);
		    ops->del((void*)tmp);
	}}}
}
Beispiel #12
0
/* calculate point-wise maps 
 *
 */
void eigenmaps(const long out_dims[DIMS], complex float* optr, complex float* eptr, const complex float* imgcov2, const long msk_dims[3], const bool* msk, bool orthiter, bool ecal_usegpu)
{
#ifdef USE_CUDA
	if (ecal_usegpu) {

		//FIXME cuda version should be able to return sensitivities for a subset of image-space points
		assert(!msk);
		eigenmapscu(out_dims, optr, eptr, imgcov2);
		return;
	}
#else
	assert(!ecal_usegpu);
#endif

	long channels = out_dims[3];
	long maps = out_dims[4];

	assert(DIMS >= 5);
	assert(1 == md_calc_size(DIMS - 5, out_dims + 5));
	assert(maps <= channels);

	long xx = out_dims[0];
	long yy = out_dims[1];
	long zz = out_dims[2];

	float scale = 1.; // for some reason, not

	if (msk_dims) {

		assert(msk_dims[0] == xx);
		assert(msk_dims[1] == yy);
		assert(msk_dims[2] == zz);
	}

	md_clear(5, out_dims, optr, CFL_SIZE);

#pragma omp parallel for collapse(3)
	for (long k = 0; k < zz; k++) {
		for (long j = 0; j < yy; j++) {
			for (long i = 0; i < xx; i++) {

				if (!msk || msk[i + xx * (j + yy * k)])	{

					float val[channels];
					complex float cov[channels][channels];

					complex float tmp[channels * (channels + 1) / 2];

					for (long l = 0; l < channels * (channels + 1) / 2; l++)
						tmp[l] = imgcov2[((l * zz + k) * yy + j) * xx + i] / scale;

					unpack_tri_matrix(channels, cov, tmp);

					if (orthiter) 
						eigen_herm3(maps, channels, val, cov);
					else 
						lapack_eig(channels, val, cov);

					for (long u = 0; u < maps; u++) {

						long ru = (orthiter ? maps : channels) - 1 - u;

						for (long v = 0; v < channels; v++) 
							optr[((((u * channels + v) * zz + k) * yy + j) * xx + i)] = cov[ru][v];

						if (NULL != eptr)
							eptr[((u * zz + k) * yy + j) * xx + i] = val[ru];
					}
				}
			}
		}
	}
}
Beispiel #13
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);
	}
Beispiel #14
0
void calib2(const struct ecalib_conf* conf, const long out_dims[DIMS], complex float* out_data, complex float* eptr, unsigned int SN, float svals[SN], const long calreg_dims[DIMS], const complex float* data, const long msk_dims[3], const bool* msk)
{
	long channels = calreg_dims[3];
	long maps = out_dims[4];

	assert(calreg_dims[3] == out_dims[3]);
	assert(maps <= channels);

	assert(1 == md_calc_size(DIMS - 5, out_dims + 5));
	assert(1 == md_calc_size(DIMS - 5, calreg_dims + 5));

	complex float rot[channels][channels];

	if (conf->rotphase) {

		long scc_dims[DIMS] = MD_INIT_ARRAY(DIMS, 1);
		scc_dims[COIL_DIM] = channels;
		scc_dims[MAPS_DIM] = channels;
		scc(scc_dims, &rot[0][0], calreg_dims, data);

	} else {

		for (unsigned int i = 0; i < channels; i++)
			for (unsigned int j = 0; j < channels; j++)
				rot[i][j] = (i == j) ? 1. : 0.;
	}


	long cov_dims[4];

	calone_dims(conf, cov_dims, channels);

	complex float* imgcov = md_alloc(4, cov_dims, CFL_SIZE);

	calone(conf, cov_dims, imgcov, SN, svals, calreg_dims, data);

	caltwo(conf, out_dims, out_data, eptr, cov_dims, imgcov, msk_dims, msk);

	/* Intensity and phase normalization similar as proposed
	 * for adaptive combine (Walsh's method) in
	 * Griswold et al., ISMRM 10:2410 (2002)
	 */

	if (conf->intensity) {

		debug_printf(DP_DEBUG1, "Normalize...\n");

		/* I think the reason this works is because inhomogeneity usually
		 * comes from only a few coil elements which are close. The l1-norm
		 * is more resilient against such outliers. -- Martin
		 */

		normalizel1(DIMS, COIL_FLAG, out_dims, out_data);
		md_zsmul(DIMS, out_dims, out_data, out_data, sqrtf((float)channels));
	}

	debug_printf(DP_DEBUG1, "Crop maps... (%.2f)\n", conf->crop);

	crop_sens(out_dims, out_data, conf->softcrop, conf->crop, eptr);

	debug_printf(DP_DEBUG1, "Fix phase...\n");


	// rotate the the phase with respect to the first principle component
	fixphase2(DIMS, out_dims, COIL_DIM, rot[0], out_data, out_data);

	md_free(imgcov);
}
Beispiel #15
0
void iter2_niht(iter_conf* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s* prox_ops[D],
		const struct linop_s* ops[D],
		const float* biases[D],
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		struct iter_monitor_s* monitor)
{
	UNUSED(xupdate_op);
	UNUSED(biases);

	assert(D == 1);
	
	auto conf = CAST_DOWN(iter_niht_conf, _conf);
  
	struct niht_conf_s niht_conf = {
    
		.maxiter = conf->maxiter,
		.N = size,
		.trans = 0,
		.do_warmstart = conf->do_warmstart,
	};

	struct niht_transop trans;

	if (NULL != ops) {

		trans.forward = OPERATOR2ITOP(ops[0]->forward);
		trans.adjoint = OPERATOR2ITOP(ops[0]->adjoint);
		trans.N = 2 * md_calc_size(linop_codomain(ops[0])->N, linop_codomain(ops[0])->dims);
		niht_conf.trans = 1;
	}		
	
	float eps = md_norm(1, MD_DIMS(size), image_adj);

	if (checkeps(eps))
		goto cleanup;
  
	niht_conf.epsilon = eps * conf->tol;

	niht(&niht_conf, &trans, select_vecops(image_adj), OPERATOR2ITOP(normaleq_op), OPERATOR_P2ITOP(prox_ops[0]), image, image_adj, monitor);

cleanup:
	;
}
  
void iter2_call_iter(iter_conf* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s* prox_ops[D],
		const struct linop_s* ops[D],
		const float* biases[D],
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		struct iter_monitor_s* monitor)
{
	assert(D <= 1);
	assert(NULL == ops);
	assert(NULL == biases);

	UNUSED(xupdate_op);

	auto it = CAST_DOWN(iter_call_s, _conf);

	it->fun(it->_conf, normaleq_op, (1 == D) ? prox_ops[0] : NULL,
		size, image, image_adj, monitor);
}
Beispiel #16
0
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);
	}
Beispiel #17
0
/* O I M G
 * 1 1 1 1   - not used
 * 1 1 A !   - forbidden
 * 1 A 1 !   - forbidden
 * A 1 1 !   - forbidden
 * A A 1 1   - replicated
 * A 1 A 1   - output
 * 1 A A A/A - input
 * A A A A   - batch
 */
static struct operator_matrix_s* linop_matrix_priv2(unsigned int N, const long out_dims[N], const long in_dims[N], const long matrix_dims[N], const complex float* matrix)
{
	// to get assertions and cost estimate

	long max_dims[N];
	md_tenmul_dims(N, max_dims, out_dims, in_dims, matrix_dims);


	PTR_ALLOC(struct operator_matrix_s, data);
	SET_TYPEID(operator_matrix_s, data);

	data->N = N;

	PTR_ALLOC(long[N], out_dims1);
	md_copy_dims(N, *out_dims1, out_dims);
	data->out_dims = *PTR_PASS(out_dims1);

	PTR_ALLOC(long[N], mat_dims1);
	md_copy_dims(N, *mat_dims1, matrix_dims);
	data->mat_dims = *PTR_PASS(mat_dims1);

	PTR_ALLOC(long[N], in_dims1);
	md_copy_dims(N, *in_dims1, in_dims);
	data->in_dims = *PTR_PASS(in_dims1);


	complex float* mat = md_alloc(N, matrix_dims, CFL_SIZE);

	md_copy(N, matrix_dims, mat, matrix, CFL_SIZE);

	data->mat = mat;
	data->mat_gram = NULL;
#ifdef USE_CUDA
	data->mat_gpu = NULL;
	data->mat_gram_gpu = NULL;
#endif

#if 1
	// pre-multiply gram matrix (if there is a cost reduction)

	unsigned long out_flags = md_nontriv_dims(N, out_dims);
	unsigned long in_flags = md_nontriv_dims(N, in_dims);

	unsigned long del_flags = in_flags & ~out_flags;
	unsigned long new_flags = out_flags & ~in_flags;

	/* we double (again) for the gram matrix
	 */

	PTR_ALLOC(long[2 * N], mat_dims2);
	PTR_ALLOC(long[2 * N], in_dims2);
	PTR_ALLOC(long[2 * N], gmt_dims2);
	PTR_ALLOC(long[2 * N], gin_dims2);
	PTR_ALLOC(long[2 * N], grm_dims2);
	PTR_ALLOC(long[2 * N], gout_dims2);

	shadow_dims(N, *gmt_dims2, matrix_dims);
	shadow_dims(N, *mat_dims2, matrix_dims);
	shadow_dims(N, *in_dims2, in_dims);
	shadow_dims(N, *gout_dims2, in_dims);
	shadow_dims(N, *gin_dims2, in_dims);
	shadow_dims(N, *grm_dims2, matrix_dims);

	/* move removed input dims into shadow position
	 * for the gram matrix can have an output there
	 */
	for (unsigned int i = 0; i < N; i++) {

		if (MD_IS_SET(del_flags, i)) {

			assert((*mat_dims2)[2 * i + 0] == (*in_dims2)[2 * i + 0]);

			(*mat_dims2)[2 * i + 1] = (*mat_dims2)[2 * i + 0];
			(*mat_dims2)[2 * i + 0] = 1;

			(*in_dims2)[2 * i + 1] = (*gin_dims2)[2 * i + 0];
			(*in_dims2)[2 * i + 0] = 1;
		}
	}

	for (unsigned int i = 0; i < N; i++) {

		if (MD_IS_SET(new_flags, i)) {

			(*grm_dims2)[2 * i + 0] = 1;
			(*grm_dims2)[2 * i + 1] = 1;
		}

		if (MD_IS_SET(del_flags, i)) {

			(*gout_dims2)[2 * i + 1] = (*gin_dims2)[2 * i + 0];
			(*gout_dims2)[2 * i + 0] = 1;

			(*grm_dims2)[2 * i + 0] = in_dims[i];
			(*grm_dims2)[2 * i + 1] = in_dims[i];
		}
	}


	long gmx_dims[2 * N];
	md_tenmul_dims(2 * N, gmx_dims, *gout_dims2, *gin_dims2, *grm_dims2);

	long mult_mat = md_calc_size(N, max_dims);
	long mult_gram = md_calc_size(2 * N, gmx_dims);

	if (mult_gram < 2 * mult_mat) {	// FIXME: rethink

		debug_printf(DP_DEBUG2, "Gram matrix: 2x %ld vs %ld\n", mult_mat, mult_gram);

		complex float* mat_gram = md_alloc(2 * N, *grm_dims2, CFL_SIZE);

		md_ztenmulc(2 * N, *grm_dims2, mat_gram, *gmt_dims2, matrix, *mat_dims2, matrix);

		data->mat_gram = mat_gram;
	}

	PTR_FREE(gmt_dims2);
	PTR_FREE(mat_dims2);
	PTR_FREE(in_dims2);

	data->gin_dims = *PTR_PASS(gin_dims2);
	data->gout_dims = *PTR_PASS(gout_dims2);
	data->grm_dims = *PTR_PASS(grm_dims2);
#else
	data->gin_dims = NULL;
	data->gout_dims = NULL;
	data->grm_dims = NULL;
#endif

	return PTR_PASS(data);
}
Beispiel #18
0
int main_reshape(int argc, char* argv[])
{
	int c;

        while (-1 != (c = getopt(argc, argv, "h"))) {

                switch (c) {

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

	unsigned int flags = atoi(argv[optind + 0]);
	unsigned int n = bitcount(flags);

	assert((int)n + 3 == argc - optind);

	long in_dims[DIMS];
	long in_strs[DIMS];

	long out_dims[DIMS];
	long out_strs[DIMS];

	complex float* in_data = load_cfl(argv[optind + n + 1], DIMS, in_dims);

	md_calc_strides(DIMS, in_strs, in_dims, CFL_SIZE);

	md_copy_dims(DIMS, out_dims, in_dims);
	
	unsigned int j = 0;

	for (unsigned int i = 0; i < DIMS; i++)
		if (MD_IS_SET(flags, i))
			out_dims[i] = atoi(argv[optind + j++ + 1]);

	assert(j == n);
	assert(md_calc_size(DIMS, in_dims) == md_calc_size(DIMS, out_dims));

	md_calc_strides(DIMS, out_strs, out_dims, CFL_SIZE);
	
	for (unsigned int i = 0; i < DIMS; i++)
		if (!(MD_IS_SET(flags, i) || (in_strs[i] == out_strs[i]))) 
			error("Dimensions are not consistent at index %d.\n");


	complex float* out_data = create_cfl(argv[optind + n + 2], DIMS, out_dims);

	md_copy(DIMS, in_dims, out_data, in_data, CFL_SIZE);

	unmap_cfl(DIMS, in_dims, in_data);
	unmap_cfl(DIMS, out_dims, out_data);
	exit(0);
}
Beispiel #19
0
/*
 * Low rank threhsolding for arbitrary block sizes
 */
static void lrthresh_apply(const operator_data_t* _data, float mu, complex float* dst, const complex float* src)
{
	struct lrthresh_data_s* data = CAST_DOWN(lrthresh_data_s, _data);

	float lambda = mu * data->lambda;

	long strs1[DIMS];
	md_calc_strides(DIMS, strs1, data->dims_decom, 1);

//#pragma omp parallel for
	for (int l = 0; l < data->levels; l++) {

		complex float* dstl = dst + l * strs1[LEVEL_DIM];
		const complex float* srcl = src + l * strs1[LEVEL_DIM];

		long blkdims[DIMS];
		long shifts[DIMS];
		long unshifts[DIMS];
		long zpad_dims[DIMS];
		long M = 1;

		for (unsigned int i = 0; i < DIMS; i++) {

			blkdims[i] = data->blkdims[l][i];
			zpad_dims[i] = (data->dims[i] + blkdims[i] - 1) / blkdims[i];
			zpad_dims[i] *= blkdims[i];

			if (MD_IS_SET(data->mflags, i))
				M *= blkdims[i];

			if (data->randshift)
				shifts[i] = rand_lim(MIN(blkdims[i] - 1, zpad_dims[i] - blkdims[i]));
			else
				shifts[i] = 0;

			unshifts[i] = -shifts[i];
		}

		long zpad_strs[DIMS];
		md_calc_strides(DIMS, zpad_strs, zpad_dims, CFL_SIZE);

		long blk_size = md_calc_size(DIMS, blkdims);
		long img_size = md_calc_size(DIMS, zpad_dims);
		long N = blk_size / M;
		long B = img_size / blk_size;

		if (data->noise && (l == data->levels - 1)) {

			M = img_size;
			N = 1;
			B = 1;
		}


		complex float* tmp = md_alloc_sameplace(DIMS, zpad_dims, CFL_SIZE, dst);

		md_circ_ext(DIMS, zpad_dims, tmp, data->dims, srcl, CFL_SIZE);

		md_circ_shift(DIMS, zpad_dims, shifts, tmp, tmp, CFL_SIZE);


		long mat_dims[2];
		basorati_dims(DIMS, mat_dims, blkdims, zpad_dims);

		complex float* tmp_mat = md_alloc_sameplace(2, mat_dims, CFL_SIZE, dst);

		// Reshape image into a blk_size x number of blocks matrix

		basorati_matrix(DIMS, blkdims, mat_dims, tmp_mat, zpad_dims, zpad_strs, tmp);

		batch_svthresh(M, N, mat_dims[1], lambda * GWIDTH(M, N, B), *(complex float (*)[mat_dims[1]][M][N])tmp_mat);

		//	for ( int b = 0; b < mat_dims[1]; b++ )
		//	svthresh(M, N, lambda * GWIDTH(M, N, B), tmp_mat, tmp_mat);

		basorati_matrixH(DIMS, blkdims, zpad_dims, zpad_strs, tmp, mat_dims, tmp_mat);

		md_circ_shift(DIMS, zpad_dims, unshifts, tmp, tmp, CFL_SIZE);

		md_resize(DIMS, data->dims, dstl, zpad_dims, tmp, CFL_SIZE);

		md_free(tmp);
		md_free(tmp_mat);
	}
}
Beispiel #20
0
int main_nufft(int argc, char* argv[])
{
	bool adjoint = false;
	bool inverse = false;
	bool use_gpu = false;
	bool precond = false;
	bool dft = false;

	struct nufft_conf_s conf = nufft_conf_defaults;
	struct iter_conjgrad_conf cgconf = iter_conjgrad_defaults;

	long coilim_vec[3] = { 0 };

	float lambda = 0.;

	const struct opt_s opts[] = {

		OPT_SET('a', &adjoint, "adjoint"),
		OPT_SET('i', &inverse, "inverse"),
		OPT_VEC3('d', &coilim_vec, "x:y:z", "dimensions"),
		OPT_VEC3('D', &coilim_vec, "", "()"),
		OPT_SET('t', &conf.toeplitz, "Toeplitz embedding for inverse NUFFT"),
		OPT_SET('c', &precond, "Preconditioning for inverse NUFFT"),
		OPT_FLOAT('l', &lambda, "lambda", "l2 regularization"),
		OPT_UINT('m', &cgconf.maxiter, "", "()"),
		OPT_SET('s', &dft, "DFT"),
	};

	cmdline(&argc, argv, 3, 3, usage_str, help_str, ARRAY_SIZE(opts), opts);

	long coilim_dims[DIMS] = { 0 };
	md_copy_dims(3, coilim_dims, coilim_vec);

	// Read trajectory
	long traj_dims[DIMS];
	complex float* traj = load_cfl(argv[1], DIMS, traj_dims);

	assert(3 == traj_dims[0]);


	num_init();

	if (inverse || adjoint) {

		long ksp_dims[DIMS];
		const complex float* ksp = load_cfl(argv[2], DIMS, ksp_dims);

		assert(1 == ksp_dims[0]);
		assert(md_check_compat(DIMS, ~(PHS1_FLAG|PHS2_FLAG), ksp_dims, traj_dims));

		md_copy_dims(DIMS - 3, coilim_dims + 3, ksp_dims + 3);

		if (0 == md_calc_size(DIMS, coilim_dims)) {

			estimate_im_dims(DIMS, coilim_dims, traj_dims, traj);
			debug_printf(DP_INFO, "Est. image size: %ld %ld %ld\n", coilim_dims[0], coilim_dims[1], coilim_dims[2]);
		}

		complex float* img = create_cfl(argv[3], DIMS, coilim_dims);

		md_clear(DIMS, coilim_dims, img, CFL_SIZE);

		const struct linop_s* nufft_op;

		if (!dft)
			nufft_op = nufft_create(DIMS, ksp_dims, coilim_dims, traj_dims, traj, NULL, conf, use_gpu);
		else
			nufft_op = nudft_create(DIMS, FFT_FLAGS, ksp_dims, coilim_dims, traj_dims, traj);


		if (inverse) {

			const struct operator_s* precond_op = NULL;

			if (conf.toeplitz && precond)
				precond_op = nufft_precond_create(nufft_op);

			lsqr(DIMS, &(struct lsqr_conf){ lambda }, iter_conjgrad, CAST_UP(&cgconf),
			     nufft_op, NULL, coilim_dims, img, ksp_dims, ksp, precond_op);

			if (conf.toeplitz && precond)
				operator_free(precond_op);

		} else {
void iter2_admm(void* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s** prox_ops,
		const struct linop_s** ops,
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		const float* image_truth,
		void* obj_eval_data,
		float (*obj_eval)(const void*, const float*))
{
	struct iter_admm_conf* conf = _conf;

	struct admm_plan_s admm_plan = {

		.maxiter = conf->maxiter,
		.maxitercg = conf->maxitercg,
		.rho = conf->rho,
		.image_truth = image_truth,
		.num_funs = D,
		.do_warmstart = conf->do_warmstart,
		.dynamic_rho = conf->dynamic_rho,
		.hogwild = conf->hogwild,
		.ABSTOL = conf->ABSTOL,
		.RELTOL = conf->RELTOL,
		.alpha = conf->alpha,
		.tau = conf->tau,
		.mu = conf->mu,
		.fast = conf->fast,
	};


	struct admm_op a_ops[D];
	struct admm_prox_op a_prox_ops[D];

	for (unsigned int i = 0; i < D; i++) {

		a_ops[i].forward = linop_forward_iter;
		a_ops[i].normal = linop_normal_iter;
		a_ops[i].adjoint =  linop_adjoint_iter;
		a_ops[i].data = (void*)ops[i];

		a_prox_ops[i].prox_fun = operator_p_iter;
		a_prox_ops[i].data = (void*)prox_ops[i];
	}

	admm_plan.ops = a_ops;
	admm_plan.prox_ops = a_prox_ops;

	admm_plan.xupdate_fun = operator_p_iter;
	admm_plan.xupdate_data = (void*)xupdate_op;


	struct admm_history_s admm_history;

	long z_dims[D];

	for (unsigned int i = 0; i < D; i++)
		z_dims[i] = 2 * md_calc_size(linop_codomain(ops[i])->N, linop_codomain(ops[i])->dims);

	if (NULL != image_adj) {

		float eps = md_norm(1, MD_DIMS(size), image_adj);

		if (checkeps(eps))
			goto cleanup;
	}

	admm(&admm_history, &admm_plan, admm_plan.num_funs, z_dims, size, (float*)image, image_adj, select_vecops(image), operator_iter, (void*)normaleq_op, obj_eval_data, obj_eval);

cleanup:
	;

}


void iter2_pocs(void* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s** prox_ops,
		const struct linop_s** ops,
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		const float* image_truth,
		void* obj_eval_data,
		float (*obj_eval)(const void*, const float*))
{

	const struct iter_pocs_conf* conf = _conf;

	assert(NULL == normaleq_op);
	assert(NULL == ops);
	assert(NULL == image_adj);

	UNUSED(xupdate_op);
	UNUSED(image_adj);
	
	struct pocs_proj_op proj_ops[D];

	for (unsigned int i = 0; i < D; i++) {

		proj_ops[i].proj_fun = operator_p_iter;
		proj_ops[i].data = (void*)prox_ops[i];
	}

	pocs(conf->maxiter, D, proj_ops, select_vecops(image), size, image, image_truth, obj_eval_data, obj_eval);
}


void iter2_call_iter(void* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s** prox_ops,
		const struct linop_s** ops,
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		const float* image_truth,
		void* obj_eval_data,
		float (*obj_eval)(const void*, const float*))
{
	assert(D <= 1);
	assert(NULL == ops);

	UNUSED(xupdate_op);

	struct iter_call_s* it = _conf;
	it->fun(it->_conf, normaleq_op, (1 == D) ? prox_ops[0] : NULL,
		size, image, image_adj,
		image_truth, obj_eval_data, obj_eval);
}
Beispiel #22
0
/*
 * Low rank threhsolding for arbitrary block sizes
 */
static void lrthresh_apply(const void* _data, float mu, complex float* dst, const complex float* src)
{
	struct lrthresh_data_s* data = (struct lrthresh_data_s*)_data;

	float lambda = mu * data->lambda;

	long strs1[DIMS];
	md_calc_strides(DIMS, strs1, data->dims_decom, 1);

//#pragma omp parallel for
	for (int l = 0; l < data->levels; l++) {

		complex float* dstl = dst + l * strs1[LEVEL_DIM];
		const complex float* srcl = src + l * strs1[LEVEL_DIM];

		// Initialize
		long blkdims[DIMS];
		long shifts[DIMS];
		long unshifts[DIMS];
		long zpad_dims[DIMS];
		long M = 1;

		for (unsigned int i = 0; i < DIMS; i++) {

			blkdims[i] = data->blkdims[l][i];
			zpad_dims[i] = (data->dims[i] + blkdims[i] - 1) / blkdims[i];
			zpad_dims[i] *= blkdims[i];

			if (MD_IS_SET(data->mflags, i))
				M *= blkdims[i];

			if (data->randshift)
				shifts[i] = rand_lim(MIN(blkdims[i] - 1, zpad_dims[i] - blkdims[i]));
			else
				shifts[i] = 0;

			unshifts[i] = -shifts[i];
		}

		long zpad_strs[DIMS];
		md_calc_strides(DIMS, zpad_strs, zpad_dims, CFL_SIZE);

		long blk_size = md_calc_size( DIMS, blkdims );
		long img_size = md_calc_size( DIMS, zpad_dims );
		long N = blk_size / M;
		long B = img_size / blk_size;

		if (data->noise && (l == data->levels - 1)) {

			M = img_size;
			N = 1;
			B = 1;
		}

		
		// Initialize tmp
		complex float* tmp_ext;
#ifdef USE_CUDA
		tmp_ext = (data->use_gpu ? md_alloc_gpu : md_alloc)(DIMS, zpad_dims, CFL_SIZE);
#else
		tmp_ext = md_alloc(DIMS, zpad_dims, CFL_SIZE);
#endif

		complex float* tmp;
#ifdef USE_CUDA
		tmp = (data->use_gpu ? md_alloc_gpu : md_alloc)(DIMS, zpad_dims, CFL_SIZE);
#else
		tmp = md_alloc(DIMS, zpad_dims, CFL_SIZE);
#endif
		// Copy to tmp
		md_circ_ext(DIMS, zpad_dims, tmp_ext, data->dims, srcl, CFL_SIZE);

		if (data->randshift)
			md_circ_shift(DIMS, zpad_dims, shifts, tmp, tmp_ext, CFL_SIZE);

		// Initialize tmp_mat
		long mat_dims[2];
		basorati_dims(DIMS, mat_dims, blkdims, zpad_dims);

		complex float* tmp_mat;
#ifdef USE_CUDA
		tmp_mat = (data->use_gpu ? md_alloc_gpu : md_alloc)(2, mat_dims, CFL_SIZE);
#else
		tmp_mat = md_alloc(2, mat_dims, CFL_SIZE);
#endif
		// Reshape image into a blk_size x number of blocks matrix

		basorati_matrix(DIMS, blkdims, mat_dims, tmp_mat, zpad_dims, zpad_strs, tmp);

		batch_svthresh(M, N, mat_dims[1], lambda * GWIDTH(M, N, B), tmp_mat, tmp_mat);

		//	for ( int b = 0; b < mat_dims[1]; b++ )
		//	svthresh(M, N, lambda * GWIDTH(M, N, B), tmp_mat, tmp_mat);

		basorati_matrixH(DIMS, blkdims, zpad_dims, zpad_strs, tmp, mat_dims, tmp_mat);


		// Copy to tmp

		if (data->randshift)
			md_circ_shift(DIMS, zpad_dims, unshifts, tmp_ext, tmp, CFL_SIZE);

		md_resize(DIMS, data->dims, dstl, zpad_dims, tmp_ext, CFL_SIZE);

		// Free data
		md_free(tmp);
		md_free(tmp_ext);
		md_free(tmp_mat);
	}
}
void overlapandsave2NE(int N, unsigned int flags, const long blk[N], const long odims[N], complex float* dst, const long dims1[N], complex float* src1, const long dims2[N], complex float* src2, const long mdims[N], complex float* msk)
{
    long dims1B[N];

    long tdims[2 * N];
    long nodims[2 * N];
    long ndims1[2 * N];
    long ndims2[2 * N];

    long shift[2 * N];

    unsigned int nflags = 0;

    for (int i = 0; i < N; i++) {

        if (MD_IS_SET(flags, i)) {

            nflags = MD_SET(nflags, 2 * i);

            assert(1 == dims2[i] % 2);
            assert(0 == blk[i] % 2);
            assert(0 == dims1[i] % 2);
            assert(0 == odims[i] % blk[i]);
            assert(0 == dims1[i] % blk[i]);
            assert(dims1[i] == odims[i]);
            assert(dims2[i] <= blk[i]);
            assert(dims1[i] >= dims2[i]);

            // blocked output

            nodims[i * 2 + 1] = odims[i] / blk[i];
            nodims[i * 2 + 0] = blk[i];

            // expanded temporary storage

            tdims[i * 2 + 1] = dims1[i] / blk[i];
            tdims[i * 2 + 0] = blk[i] + dims2[i] - 1;

            // blocked input

            // ---|---,---,---|---
            //   + +++ +
            //       + +++ +

            // resized input

            dims1B[i] = dims1[i] + 2 * blk[i];

            ndims1[i * 2 + 1] = dims1[i] / blk[i] + 2; // do we need two full blocks?
            ndims1[i * 2 + 0] = blk[i];

            shift[i * 2 + 1] = 0;
            shift[i * 2 + 0] = blk[i] - (dims2[i] - 1) / 2;

            // kernel

            ndims2[i * 2 + 1] = 1;
            ndims2[i * 2 + 0] = dims2[i];

        } else {

            nodims[i * 2 + 1] = 1;
            nodims[i * 2 + 0] = odims[i];

            tdims[i * 2 + 1] = 1;
            tdims[i * 2 + 0] = dims1[i];

            ndims1[i * 2 + 1] = 1;
            ndims1[i * 2 + 0] = dims1[i];

            shift[i * 2 + 1] = 0;
            shift[i * 2 + 0] = 0;


            dims1B[i] = dims1[i];

            ndims2[i * 2 + 1] = 1;
            ndims2[i * 2 + 0] = dims2[i];
        }
    }

    long R = md_calc_size(N, odims);
    long T = md_calc_size(2 * N, tdims);
    long S = md_calc_size(N, dims1B);

    complex float* src1B = xmalloc(S * sizeof(complex float));
    complex float* tmp = xmalloc(T * sizeof(complex float));
    complex float* tmpX = xmalloc(R * sizeof(complex float));

    long str1[2 * N];
    long str2[2 * N];

    md_calc_strides(2 * N, str1, ndims1, sizeof(complex float));
    md_calc_strides(2 * N, str2, tdims, sizeof(complex float));

    long off = md_calc_offset(2 * N, str1, shift);

    md_resize_center(N, dims1B, src1B, dims1, src1, sizeof(complex float));

    // we can loop here

    md_copy2(2 * N, tdims, str2, tmp, str1, ((void*)src1B) + off, sizeof(complex float));

    conv(2 * N, nflags, CONV_VALID, CONV_SYMMETRIC, nodims, tmpX, tdims, tmp, ndims2, src2);

    long ostr[N];
    long mstr[N];

    md_calc_strides(N, ostr, odims, sizeof(complex float));
    md_calc_strides(N, mstr, mdims, sizeof(complex float));

    md_zmul2(N, odims, ostr, tmpX, ostr, tmpX, mstr, msk);

    convH(2 * N, nflags, CONV_VALID, CONV_SYMMETRIC, tdims, tmp, nodims, tmpX, ndims2, src2);

    md_clear(N, dims1B, src1B, sizeof(complex float));
    md_zadd2(2 * N, tdims, str1, ((void*)src1B) + off, str1, ((void*)src1B) + off, str2, tmp);

    //

    md_resize_center(N, dims1, dst, dims1B, src1B, sizeof(complex float));

    free(src1B);
    free(tmpX);
    free(tmp);
}
Beispiel #24
0
/**
 * Efficiently chain two matrix linops by multiplying the actual matrices together.
 * Stores a copy of the new matrix.
 * Returns: C = B A
 *
 * @param a first matrix (applied to input)
 * @param b second matrix (applied to output of first matrix)
 */
struct linop_s* linop_matrix_chain(const struct linop_s* a, const struct linop_s* b)
{
	const struct operator_matrix_s* a_data = CAST_DOWN(operator_matrix_s, linop_get_data(a));
	const struct operator_matrix_s* b_data = CAST_DOWN(operator_matrix_s, linop_get_data(b));

	// check compatibility
	assert(linop_codomain(a)->N == linop_domain(b)->N);
	assert(md_check_compat(linop_codomain(a)->N, 0u, linop_codomain(a)->dims, linop_domain(b)->dims));

	unsigned int D = linop_domain(a)->N;

	unsigned long outB_flags = md_nontriv_dims(D, linop_codomain(b)->dims);
	unsigned long inB_flags = md_nontriv_dims(D, linop_domain(b)->dims);

	unsigned long delB_flags = inB_flags & ~outB_flags;

	unsigned int N = a_data->N;
	assert(N == 2 * D);

	long in_dims[N];
	md_copy_dims(N, in_dims, a_data->in_dims);

	long matA_dims[N];
	md_copy_dims(N, matA_dims, a_data->mat_dims);

	long matB_dims[N];
	md_copy_dims(N, matB_dims, b_data->mat_dims);

	long out_dims[N];
	md_copy_dims(N, out_dims, b_data->out_dims);

	for (unsigned int i = 0; i < D; i++) {

		if (MD_IS_SET(delB_flags, i)) {

			matA_dims[2 * i + 0] = a_data->mat_dims[2 * i + 1];
			matA_dims[2 * i + 1] = a_data->mat_dims[2 * i + 0];

			in_dims[2 * i + 0] = a_data->in_dims[2 * i + 1];
			in_dims[2 * i + 1] = a_data->in_dims[2 * i + 0];
		}
	}


	long matrix_dims[N];
	md_singleton_dims(N, matrix_dims);

	unsigned long iflags = md_nontriv_dims(N, in_dims);
	unsigned long oflags = md_nontriv_dims(N, out_dims);
	unsigned long flags = iflags | oflags;

	// we combine a and b and sum over dims not in input or output

	md_max_dims(N, flags, matrix_dims, matA_dims, matB_dims);

	debug_printf(DP_DEBUG1, "tensor chain: %ld x %ld -> %ld\n",
			md_calc_size(N, matA_dims), md_calc_size(N, matB_dims), md_calc_size(N, matrix_dims));


	complex float* matrix = md_alloc(N, matrix_dims, CFL_SIZE);

	debug_print_dims(DP_DEBUG2, N, matrix_dims);
	debug_print_dims(DP_DEBUG2, N, in_dims);
	debug_print_dims(DP_DEBUG2, N, matA_dims);
	debug_print_dims(DP_DEBUG2, N, matB_dims);
	debug_print_dims(DP_DEBUG2, N, out_dims);

	md_ztenmul(N, matrix_dims, matrix, matA_dims, a_data->mat, matB_dims, b_data->mat);

	// priv2 takes our doubled dimensions

	struct operator_matrix_s* data = linop_matrix_priv2(N, out_dims, in_dims, matrix_dims, matrix);

	/* although we internally use different dimensions we define the
	 * correct interface
	 */
	struct linop_s* c = linop_create(linop_codomain(b)->N, linop_codomain(b)->dims,
			linop_domain(a)->N, linop_domain(a)->dims, CAST_UP(data),
			linop_matrix_apply, linop_matrix_apply_adjoint,
			linop_matrix_apply_normal, NULL, linop_matrix_del);

	md_free(matrix);

	return c;
}
Beispiel #25
0
Datei: nlinv.c Projekt: nckz/bart
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);
}
Beispiel #26
0
void compute_kernels(const struct ecalib_conf* conf, long nskerns_dims[5], complex float** nskerns_ptr, unsigned int SN, float svals[SN], const long caldims[DIMS], const complex float* caldata)
{
	assert(1 == md_calc_size(DIMS - 5, caldims + 5));

	nskerns_dims[0] = conf->kdims[0];
	nskerns_dims[1] = conf->kdims[1];
	nskerns_dims[2] = conf->kdims[2];
	nskerns_dims[3] = caldims[3];

	long N = md_calc_size(4, nskerns_dims);

	assert(N > 0);
	nskerns_dims[4] = N;

	complex float* nskerns = md_alloc(5, nskerns_dims, CFL_SIZE);
	*nskerns_ptr = nskerns;

	complex float (*vec)[N] = xmalloc(N * N * sizeof(complex float));

	assert((NULL == svals) || (SN == N));
	float* val = (NULL != svals) ? svals : xmalloc(N * FL_SIZE);

	debug_printf(DP_DEBUG1, "Build calibration matrix and SVD...\n");

#ifdef CALMAT_SVD
	calmat_svd(conf->kdims, N, vec, val, caldims, caldata);

	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++) 
#ifndef FLIP
			nskerns[i * N + j] = (vec[j][i]) * (conf->weighting ? val[i] : 1.);
#else
			nskerns[i * N + j] = (vec[j][N - 1 - i]) * (conf->weighting ? val[N - 1 - i] : 1.);
#endif
#else
	covariance_function(conf->kdims, N, vec, caldims, caldata);

	debug_printf(DP_DEBUG1, "Eigen decomposition... (size: %ld)\n", N);

	// we could apply Nystroem method here to speed it up

	float tmp_val[N];
	lapack_eig(N, tmp_val, vec);

	for (int i = 0; i < N; i++)
		val[i] = sqrtf(tmp_val[N - 1 - i]);

	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++) 
#ifndef FLIP
			nskerns[i * N + j] = vec[N - 1 - i][j] * (conf->weighting ? val[i] : 1.);	// flip
#else
			nskerns[i * N + j] = vec[i][j] * (conf->weighting ? val[N - 1 - i] : 1.);	// flip
#endif
#endif

	if (conf->perturb > 0.) {

		long dims[2] = { N, N };
		perturb(dims, nskerns, conf->perturb);
	}

#ifndef FLIP
	nskerns_dims[4] = number_of_kernels(conf, N, val);
#else
	nskerns_dims[4] = N - number_of_kernels(conf, N, val);
#endif

	if (NULL == svals)
		free(val);

	free(vec);
}
Beispiel #27
0
static void prox_4pt_dfwavelet_thresh(const operator_data_t* _data, float thresh, complex float* out, const complex float* in)
{
	struct prox_4pt_dfwavelet_data* data = CONTAINER_OF(_data, struct prox_4pt_dfwavelet_data, base);

        bool done = false;
        long pos[DIMS];
        md_set_dims(DIMS, pos, 0);
        
        while (!done) {

                // copy pc
                md_slice(DIMS, data->slice_flag, pos, data->im_dims, data->pc0, in, CFL_SIZE);
                pos[data->flow_dim]++;
                md_slice(DIMS, data->slice_flag, pos, data->im_dims, data->pc1, in, CFL_SIZE);
                pos[data->flow_dim]++;
                md_slice(DIMS, data->slice_flag, pos, data->im_dims, data->pc2, in, CFL_SIZE);
                pos[data->flow_dim]++;
                md_slice(DIMS, data->slice_flag, pos, data->im_dims, data->pc3, in, CFL_SIZE);
                pos[data->flow_dim] = 0;

                // pc to velocity
                // TODO: Make gpu 
                for (int i = 0; i < md_calc_size(DIMS, data->tim_dims); i++) {

                        data->vx[i] = (data->pc1[i] - data->pc0[i]) / 2;
                        data->vy[i] = (data->pc2[i] - data->pc1[i]) / 2;
                        data->vz[i] = (data->pc3[i] - data->pc2[i]) / 2;
                        data->ph0[i] = (data->pc0[i] + data->pc3[i]) / 2;
                }

                // threshold
                dfwavelet_thresh(data->plan, thresh * data->lambda, thresh* data->lambda, data->vx, data->vy, data->vz, data->vx, data->vy, data->vz);
                operator_p_apply(data->wthresh_op, thresh, DIMS, data->tim_dims, data->ph0, DIMS, data->tim_dims, data->ph0);

                // velocity to pc
                for (int i = 0; i < md_calc_size(DIMS, data->tim_dims ); i++) {

                        data->pc0[i] = (- data->vx[i] - data->vy[i] - data->vz[i] + data->ph0[i]);
                        data->pc1[i] = (+ data->vx[i] - data->vy[i] - data->vz[i] + data->ph0[i]);
                        data->pc2[i] = (+ data->vx[i] + data->vy[i] - data->vz[i] + data->ph0[i]);
                        data->pc3[i] = (+ data->vx[i] + data->vy[i] + data->vz[i] + data->ph0[i]);
                }
                
                
                // copy pc
                md_copy_block(DIMS, pos, data->im_dims, out, data->tim_dims, data->pc0, CFL_SIZE);
                pos[data->flow_dim]++;
                md_copy_block(DIMS, pos, data->im_dims, out, data->tim_dims, data->pc1, CFL_SIZE);
                pos[data->flow_dim]++;
                md_copy_block( DIMS, pos, data->im_dims, out, data->tim_dims, data->pc2, CFL_SIZE );
                pos[data->flow_dim]++;
                md_copy_block( DIMS, pos, data->im_dims, out, data->tim_dims, data->pc3, CFL_SIZE );
                pos[data->flow_dim] = 0;

                // increment pos
                long carryon = 1;

                for(unsigned int i = 0; i < DIMS; i++) {

                        if (MD_IS_SET(data->slice_flag & ~MD_BIT(data->flow_dim), i)) {

                                pos[i] += carryon;

                                if (pos[i] < data->im_dims[i]) {

                                        carryon = 0;
                                        break;

                                } else {

                                        carryon = 1;
                                        pos[i] = 0;
                                }
                        }
                }

                done = carryon;
        }
}
Beispiel #28
0
void iter2_admm(iter_conf* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s* prox_ops[D],
		const struct linop_s* ops[D],
		const float* biases[D],
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		struct iter_monitor_s* monitor)
{
	auto conf = CAST_DOWN(iter_admm_conf, _conf);

	struct admm_plan_s admm_plan = {

		.maxiter = conf->maxiter,
		.maxitercg = conf->maxitercg,
		.cg_eps = conf->cg_eps,
		.rho = conf->rho,
		.num_funs = D,
		.do_warmstart = conf->do_warmstart,
		.dynamic_rho = conf->dynamic_rho,
		.dynamic_tau = conf->dynamic_tau,
		.relative_norm = conf->relative_norm,
		.hogwild = conf->hogwild,
		.ABSTOL = conf->ABSTOL,
		.RELTOL = conf->RELTOL,
		.alpha = conf->alpha,
		.tau = conf->tau,
		.tau_max = conf->tau_max,
		.mu = conf->mu,
		.fast = conf->fast,
		.biases = biases,
	};


	struct admm_op a_ops[D ?:1];
	struct iter_op_p_s a_prox_ops[D ?:1];

	for (unsigned int i = 0; i < D; i++) {

		a_ops[i].forward = OPERATOR2ITOP(ops[i]->forward),
		a_ops[i].normal = OPERATOR2ITOP(ops[i]->normal);
		a_ops[i].adjoint = OPERATOR2ITOP(ops[i]->adjoint);

		a_prox_ops[i] = OPERATOR_P2ITOP(prox_ops[i]);
	}

	admm_plan.ops = a_ops;
	admm_plan.prox_ops = a_prox_ops;

	admm_plan.xupdate = OPERATOR_P2ITOP(xupdate_op);


	long z_dims[D ?: 1];

	for (unsigned int i = 0; i < D; i++)
		z_dims[i] = 2 * md_calc_size(linop_codomain(ops[i])->N, linop_codomain(ops[i])->dims);

	if (NULL != image_adj) {

		float eps = md_norm(1, MD_DIMS(size), image_adj);

		if (checkeps(eps))
			goto cleanup;
	}

	admm(&admm_plan, admm_plan.num_funs, z_dims, size, (float*)image, image_adj, select_vecops(image), OPERATOR2ITOP(normaleq_op), monitor);

cleanup:
	;

}


void iter2_pocs(iter_conf* _conf,
		const struct operator_s* normaleq_op,
		unsigned int D,
		const struct operator_p_s* prox_ops[D],
		const struct linop_s* ops[D],
		const float* biases[D],
		const struct operator_p_s* xupdate_op,
		long size, float* image, const float* image_adj,
		struct iter_monitor_s* monitor)
{
	auto conf = CAST_DOWN(iter_pocs_conf, _conf);

	assert(NULL == normaleq_op);
	assert(NULL == ops);
	assert(NULL == biases);
	assert(NULL == image_adj);

	UNUSED(xupdate_op);
	UNUSED(image_adj);
	
	struct iter_op_p_s proj_ops[D];

	for (unsigned int i = 0; i < D; i++)
		proj_ops[i] = OPERATOR_P2ITOP(prox_ops[i]);

	pocs(conf->maxiter, D, proj_ops, select_vecops(image), size, image, monitor);
}
Beispiel #29
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
Beispiel #30
0
void iwt2(unsigned int N, unsigned int flags, const long shifts[N], const long odims[N], const long ostr[N], complex float* out, const long idims[N], const long istr[N], const complex float* in, const long minsize[N], const long flen, const float filter[2][2][flen])
{
	assert(wavelet_check_dims(N, flags, odims, minsize));

	if (0 == flags) {	// note: recursion does *not* end here

		assert(md_check_compat(N, 0u, odims, idims));

		md_copy2(N, idims, ostr, out, istr, in, CFL_SIZE);

		return;
	}

	// check input dimensions

	long idims2[N];
	wavelet_coeffs2(N, flags, idims2, odims, minsize, flen);

	assert(md_check_compat(N, 0u, idims2, idims));

	long wdims2[2 * N];
	wavelet_dims(N, flags, wdims2, odims, flen);

	// only consider transform dims...

	long dims1[N];
	md_select_dims(N, flags, dims1, odims);

	long wdims[2 * N];
	wavelet_dims(N, flags, wdims, dims1, flen);
	long level_coeffs = md_calc_size(2 * N, wdims);

	// ... which get embedded in dimension b

	unsigned int b = ffs(flags) - 1;

	long istr2[2 * N];
	md_calc_strides(2 * N, istr2, wdims, istr[b]);

	// merge with original strides

	for (unsigned int i = 0; i < N; i++)
		if (!MD_IS_SET(flags, i))
			istr2[i] = istr[i];

	assert(idims[b] >= level_coeffs);

	long offset = (idims[b] - level_coeffs) * (istr[b] / CFL_SIZE);

	long bands = md_calc_size(N, wdims + N);
	long coeffs = md_calc_size(N, wdims + 0);

	// subtract coefficients in high band

	idims2[b] -= (bands - 1) * coeffs;

	assert(idims2[b] > 0);

	debug_printf(DP_DEBUG4, "ifwt2: flags:%d lcoeffs:%ld coeffs:%ld (space:%ld) bands:%ld str:%ld off:%ld\n", flags, level_coeffs, coeffs, idims2[b], bands, istr[b], offset / ostr[b]);

	// fix me we need temp storage
	complex float* tmp = md_alloc_sameplace(2 * N, wdims2, CFL_SIZE, out);

	long tstr[2 * N];
	md_calc_strides(2 * N, tstr, wdims2, CFL_SIZE);

	md_copy2(2 * N, wdims2, tstr, tmp, istr2, in + offset, CFL_SIZE);

	long shifts0[N];
	for (unsigned int i = 0; i < N; i++)
		shifts0[i] = 0;

	unsigned int flags2 = wavelet_filter_flags(N, flags, wdims, minsize);
	assert((0 == offset) == (0u == flags2));

	if (0u != flags2) {

		long idims3[N];
		wavelet_coeffs2(N, flags2, idims3, wdims2, minsize, flen);

		long istr3[N];
		embed(N, flags, istr3, idims3, istr);

		iwt2(N, flags2, shifts0, wdims2, tstr, tmp, idims3, istr3, in, minsize, flen, filter);
	}

	iwtN(N, flags, shifts, odims, ostr, out, tstr, tmp, flen, filter);

	md_free(tmp);
}