static struct maps_data* maps_create_data(const long max_dims[DIMS], unsigned int sens_flags, const complex float* sens, bool gpu) { struct maps_data* data = xmalloc(sizeof(struct maps_data)); // maximal dimensions md_copy_dims(DIMS, data->max_dims, max_dims); // sensitivity dimensions md_select_dims(DIMS, sens_flags, data->mps_dims, max_dims); md_calc_strides(DIMS, data->strs_mps, data->mps_dims, CFL_SIZE); md_select_dims(DIMS, ~MAPS_FLAG, data->ksp_dims, max_dims); md_calc_strides(DIMS, data->strs_ksp, data->ksp_dims, CFL_SIZE); md_select_dims(DIMS, ~COIL_FLAG, data->img_dims, max_dims); md_calc_strides(DIMS, data->strs_img, data->img_dims, CFL_SIZE); #ifdef USE_CUDA complex float* nsens = (gpu ? md_alloc_gpu : md_alloc)(DIMS, data->mps_dims, CFL_SIZE); #else assert(!gpu); complex float* nsens = md_alloc(DIMS, data->mps_dims, CFL_SIZE); #endif md_copy(DIMS, data->mps_dims, nsens, sens, CFL_SIZE); data->sens = nsens; data->norm = NULL; return data; }
void noir_recon(const struct noir_conf_s* conf, const long dims[DIMS], complex float* outbuf, complex float* sensout, const complex float* psf, const complex float* mask, const complex float* kspace) { long imgs_dims[DIMS]; long coil_dims[DIMS]; long data_dims[DIMS]; long img1_dims[DIMS]; md_select_dims(DIMS, FFT_FLAGS|MAPS_FLAG|CSHIFT_FLAG, imgs_dims, dims); md_select_dims(DIMS, FFT_FLAGS|COIL_FLAG|MAPS_FLAG, coil_dims, dims); md_select_dims(DIMS, FFT_FLAGS|COIL_FLAG, data_dims, dims); md_select_dims(DIMS, FFT_FLAGS, img1_dims, dims); long skip = md_calc_size(DIMS, imgs_dims); long size = skip + md_calc_size(DIMS, coil_dims); long data_size = md_calc_size(DIMS, data_dims); long d1[1] = { size }; complex float* img = md_alloc_sameplace(1, d1, CFL_SIZE, kspace); complex float* imgH = md_alloc_sameplace(1, d1, CFL_SIZE, kspace); md_clear(DIMS, imgs_dims, img, CFL_SIZE); md_zfill(DIMS, img1_dims, outbuf, 1.); // initial only first image md_copy(DIMS, img1_dims, img, outbuf, CFL_SIZE); md_clear(DIMS, coil_dims, img + skip, CFL_SIZE); md_clear(DIMS, imgs_dims, imgH, CFL_SIZE); md_clear(DIMS, coil_dims, imgH + skip, CFL_SIZE); struct noir_data* ndata = noir_init(dims, mask, psf, conf->rvc, conf->usegpu); struct data data = { ndata }; struct iter3_irgnm_conf irgnm_conf = { .iter = conf->iter, .alpha = conf->alpha, .redu = conf->redu }; iter3_irgnm(&irgnm_conf.base, frw, der, adj, &data, size * 2, (float*)img, data_size * 2, (const float*)kspace); md_copy(DIMS, imgs_dims, outbuf, img, CFL_SIZE); if (NULL != sensout) { assert(!conf->usegpu); noir_forw_coils(ndata, sensout, img + skip); } noir_free(ndata); md_free(img); md_free(imgH); }
static double bench_generic_add(long dims[DIMS], unsigned int flags, bool forloop) { long dimsX[DIMS]; long dimsY[DIMS]; long dimsC[DIMS]; md_select_dims(DIMS, flags, dimsX, dims); md_select_dims(DIMS, ~flags, dimsC, dims); md_select_dims(DIMS, ~0u, dimsY, dims); long strsX[DIMS]; long strsY[DIMS]; md_calc_strides(DIMS, strsX, dimsX, CFL_SIZE); md_calc_strides(DIMS, strsY, dimsY, CFL_SIZE); complex float* x = md_alloc(DIMS, dimsX, CFL_SIZE); complex float* y = md_alloc(DIMS, dimsY, CFL_SIZE); md_gaussian_rand(DIMS, dimsX, x); md_gaussian_rand(DIMS, dimsY, y); long L = md_calc_size(DIMS, dimsC); long T = md_calc_size(DIMS, dimsX); double tic = timestamp(); if (forloop) { for (long i = 0; i < L; i++) { for (long j = 0; j < T; j++) y[i + j * L] += x[j]; } } else { md_zaxpy2(DIMS, dims, strsY, y, 1., strsX, x); } double toc = timestamp(); md_free(x); md_free(y); return toc - tic; }
const struct operator_s* nufft_precond_create(const struct linop_s* nufft_op) { const auto data = CAST_DOWN(nufft_data, linop_get_data(nufft_op)); PTR_ALLOC(struct nufft_precond_data, pdata); SET_TYPEID(nufft_precond_data, pdata); assert(data->conf.toeplitz); int N = data->N; int ND = N + 1; pdata->N = N; pdata->cim_dims = *TYPE_ALLOC(long[ND]); pdata->pre_dims = *TYPE_ALLOC(long[ND]); pdata->cim_strs = *TYPE_ALLOC(long[ND]); pdata->pre_strs = *TYPE_ALLOC(long[ND]); md_copy_dims(ND, pdata->cim_dims, data->cim_dims); md_select_dims(ND, data->flags, pdata->pre_dims, pdata->cim_dims); md_calc_strides(ND, pdata->cim_strs, pdata->cim_dims, CFL_SIZE); md_calc_strides(ND, pdata->pre_strs, pdata->pre_dims, CFL_SIZE); pdata->pre = compute_precond(pdata->N, pdata->pre_dims, pdata->pre_strs, data->psf_dims, data->psf_strs, data->psf, data->linphase); pdata->fft_op = linop_fft_create(pdata->N, pdata->cim_dims, data->flags); const long* cim_dims = pdata->cim_dims; // need to dereference pdata before PTR_PASS return operator_create(N, cim_dims, N, cim_dims, CAST_UP(PTR_PASS(pdata)), nufft_precond_apply, nufft_precond_del); }
/** * Intialize lrthresh data * * @param dims_decom - dimensions with levels at LEVEL_DIMS * @param randshift - randshift boolean * @param mflags - selects which dimensions gets reshaped as the first dimension in matrix * @param blkdims - contains block dimensions for all levels * */ static struct lrthresh_data_s* lrthresh_create_data(const long dims_decom[DIMS], bool randshift, unsigned long mflags, const long blkdims[MAX_LEV][DIMS], float lambda, bool noise, int remove_mean) { PTR_ALLOC(struct lrthresh_data_s, data); SET_TYPEID(lrthresh_data_s, data); data->randshift = randshift; data->mflags = mflags; data->lambda = lambda; data->noise = noise; data->remove_mean = remove_mean; // level dimensions md_copy_dims(DIMS, data->dims_decom, dims_decom); md_calc_strides(DIMS, data->strs_lev, dims_decom, CFL_SIZE); // image dimensions data->levels = dims_decom[LEVEL_DIM]; md_select_dims(DIMS, ~LEVEL_FLAG, data->dims, dims_decom); md_calc_strides(DIMS, data->strs, data->dims, CFL_SIZE); // blkdims for(long l = 0; l < data->levels; l++) { for (long i = 0; i < DIMS; i++) data->blkdims[l][i] = blkdims[l][i]; } return PTR_PASS(data); }
/* * Implements finite difference operator (order 1 for now) * using circular shift: diff(x) = x - circshift(x) * @param snip Keeps first entry if snip = false; clear first entry if snip = true * * optr = [iptr(1); diff(iptr)] */ static void md_zfinitediff_core2(unsigned int D, const long dims[D], unsigned int flags, bool snip, complex float* tmp, const long ostrs[D], complex float* optr, const long istrs[D], const complex float* iptr) { md_copy2(D, dims, istrs, tmp, istrs, iptr, sizeof(complex float)); long zdims[D]; long center[D]; md_select_dims(D, ~0, zdims, dims); memset(center, 0, D * sizeof(long)); for (unsigned int i=0; i < D; i++) { if (MD_IS_SET(flags, i)) { center[i] = 1; // order md_circ_shift2(D, dims, center, ostrs, optr, istrs, tmp, sizeof(complex float)); zdims[i] = 1; if (!snip) // zero out first dimension before subtracting md_clear2(D, zdims, ostrs, optr, sizeof(complex float)); md_zsub2(D, dims, ostrs, optr, istrs, tmp, ostrs, optr); md_copy2(D, dims, ostrs, tmp, ostrs, optr, sizeof(complex float)); if (snip) // zero out first dimension after subtracting md_clear2(D, zdims, ostrs, optr, sizeof(complex float)); center[i] = 0; zdims[i] = dims[i]; } } }
struct prox_dfwavelet_data* prepare_prox_dfwavelet_data(const long im_dims[DIMS], const long min_size[3], const complex float res[3], unsigned int flow_dim, float lambda, bool use_gpu) { // get dimension PTR_ALLOC(struct prox_dfwavelet_data, data); md_copy_dims(DIMS, data->im_dims, im_dims); md_select_dims(DIMS, FFT_FLAGS, data->tim_dims, im_dims); md_calc_strides(DIMS, data->im_strs, im_dims, CFL_SIZE); // initialize temp #ifdef USE_CUDA if (use_gpu) { data->vx = md_alloc_gpu(DIMS, data->tim_dims, CFL_SIZE); data->vy = md_alloc_gpu(DIMS, data->tim_dims, CFL_SIZE); data->vz = md_alloc_gpu(DIMS, data->tim_dims, CFL_SIZE); } else #endif { data->vx = md_alloc(DIMS, data->tim_dims, CFL_SIZE); data->vy = md_alloc(DIMS, data->tim_dims, CFL_SIZE); data->vz = md_alloc(DIMS, data->tim_dims, CFL_SIZE); } data->flow_dim = flow_dim; data->slice_flag = ~FFT_FLAGS; data->lambda = lambda; data->plan = prepare_dfwavelet_plan(3, data->tim_dims, (long*) min_size, (complex float*) res, use_gpu); return data; }
/* * Adjoint of finite difference operator along specified dimensions. * Equivalent to finite difference in reverse order * * @param snip if false: keeps the original value for the last entry; * if true: implements the adjoint of the difference matrix with all zero first row * * optr = [-diff(iptr); iptr(end)] = flip(fdiff_apply(flip(iptr))) */ static void fdiff_apply_adjoint(const linop_data_t* _data, complex float* optr, const complex float* iptr) { const auto data = CAST_DOWN(fdiff_s, _data); md_copy2(data->D, data->dims, data->str, optr, data->str, iptr, CFL_SIZE); for (unsigned int i=0; i < data->D; i++) { unsigned int single_flag = data->flags & MD_BIT(i); if (single_flag) { complex float* tmp = md_alloc_sameplace(data->D, data->dims, CFL_SIZE, optr); complex float* tmp2 = md_alloc_sameplace(data->D, data->dims, CFL_SIZE, optr); md_flip2(data->D, data->dims, single_flag, data->str, tmp2, data->str, optr, CFL_SIZE); md_zfinitediff_core2(data->D, data->dims, single_flag, false, tmp, data->str, tmp2, data->str, tmp2); md_flip2(data->D, data->dims, single_flag, data->str, optr, data->str, tmp2, CFL_SIZE); md_free(tmp2); md_free(tmp); if (data->snip) { long zdims[data->D]; md_select_dims(data->D, ~0, zdims, data->dims); zdims[i] = 1; md_zsub2(data->D, zdims, data->str, optr, data->str, optr, data->str, iptr); } } } }
complex float* compute_psf(unsigned int N, const long img2_dims[N], const long trj_dims[N], const complex float* traj, const complex float* weights) { long ksp_dims1[N]; md_select_dims(N, ~MD_BIT(0), ksp_dims1, trj_dims); struct linop_s* op2 = nufft_create(N, ksp_dims1, img2_dims, trj_dims, traj, NULL, nufft_conf_defaults, false); complex float* ones = md_alloc(N, ksp_dims1, CFL_SIZE); md_zfill(N, ksp_dims1, ones, 1.); if (NULL != weights) { md_zmul(N, ksp_dims1, ones, ones, weights); md_zmulc(N, ksp_dims1, ones, ones, weights); } complex float* psft = md_alloc(N, img2_dims, CFL_SIZE); linop_adjoint_unchecked(op2, psft, ones); md_free(ones); linop_free(op2); return psft; }
/** * Proximal operator for l1-norm with unitary transform: f(x) = lambda || T x ||_1 * * @param D number of dimensions * @param dim dimensions of x * @param lambda threshold parameter * @param unitary_op unitary linear operator * @param flags bitmask for joint soft-thresholding */ extern const struct operator_p_s* prox_unithresh_create(unsigned int D, const struct linop_s* unitary_op, const float lambda, const unsigned long flags) { PTR_ALLOC(struct thresh_s, data); SET_TYPEID(thresh_s, data); data->lambda = lambda; data->D = D; data->flags = flags; data->unitary_op = unitary_op; const long* dims = linop_domain(unitary_op)->dims; PTR_ALLOC(long[D], ndim); md_copy_dims(D, *ndim, dims); data->dim = *PTR_PASS(ndim); PTR_ALLOC(long[D], nstr); md_calc_strides(D, *nstr, data->dim, CFL_SIZE); data->str = *PTR_PASS(nstr); // norm dimensions are the flagged transform dimensions // FIXME should use linop_codomain(unitary_op)->N PTR_ALLOC(long[D], norm_dim); md_select_dims(D, ~flags, *norm_dim, linop_codomain(unitary_op)->dims); data->norm_dim = *PTR_PASS(norm_dim); return operator_p_create(D, dims, D, dims, CAST_UP(PTR_PASS(data)), unisoftthresh_apply, thresh_del); }
static struct linop_s* linop_gdiag_create(unsigned int N, const long dims[N], unsigned int flags, const complex float* diag, bool rdiag) { PTR_ALLOC(struct cdiag_s, data); SET_TYPEID(cdiag_s, data); data->rmul = rdiag; data->N = N; PTR_ALLOC(long[N], dims2); PTR_ALLOC(long[N], dstrs); PTR_ALLOC(long[N], strs); long ddims[N]; md_select_dims(N, flags, ddims, dims); md_copy_dims(N, *dims2, dims); md_calc_strides(N, *strs, dims, CFL_SIZE); md_calc_strides(N, *dstrs, ddims, CFL_SIZE); data->dims = *PTR_PASS(dims2); data->strs = *PTR_PASS(strs); data->dstrs = *PTR_PASS(dstrs); data->diag = diag; // make a copy? #ifdef USE_CUDA data->gpu_diag = NULL; #endif return linop_create(N, dims, N, dims, CAST_UP(PTR_PASS(data)), cdiag_apply, cdiag_adjoint, cdiag_normal, NULL, cdiag_free); }
/** * Generic functions which loops over all dimensions of a set of * multi-dimensional arrays and calls a given function for each position. * This functions tries to parallelize over the dimensions indicated * with flags. */ void md_parallel_nary(unsigned int C, unsigned int D, const long dim[D], unsigned long flags, const long* str[C], void* ptr[C], void* data, md_nary_fun_t fun) { if (0 == flags) { md_nary(C, D, dim, str, ptr, data, fun); return; } int b = ffsl(flags & -flags) - 1; assert(MD_IS_SET(flags, b)); flags = MD_CLEAR(flags, b); long dimc[D]; md_select_dims(D, ~MD_BIT(b), dimc, dim); debug_printf(DP_DEBUG4, "Parallelize: %d\n", dim[b]); // FIXME: this probably doesn't nest // (maybe collect all parallelizable dims into one giant loop?) #pragma omp parallel for for (long i = 0; i < dim[b]; i++) { void* moving_ptr[C]; for (unsigned int j = 0; j < C; j++) moving_ptr[j] = ptr[j] + i * str[j][b]; md_parallel_nary(C, D, dimc, flags, str, moving_ptr, data, fun); } }
/** * Thresholding operator for l0-norm: f(x) = || x ||_0 <= k, as used in NIHT algorithm. * y = HT(x, k) (hard thresholding, ie keeping the k largest elements). * * @param D number of dimensions * @param dim dimensions of x * @param k threshold parameter (non-zero elements to keep) * @param flags bitmask for joint thresholding */ const struct operator_p_s* prox_niht_thresh_create(unsigned int D, const long dim[D], const unsigned int k, const unsigned long flags) { PTR_ALLOC(struct thresh_s, data); SET_TYPEID(thresh_s, data); data->lambda = 0.; data->k = k; data->D = D; data->flags = flags; data->unitary_op = NULL; PTR_ALLOC(long[D], ndim); md_copy_dims(D, *ndim, dim); data->dim = *PTR_PASS(ndim); // norm dimensions are the flagged input dimensions PTR_ALLOC(long[D], norm_dim); md_select_dims(D, ~flags, *norm_dim, data->dim); data->norm_dim = *PTR_PASS(norm_dim); PTR_ALLOC(long[D], nstr); md_calc_strides(D, *nstr, data->dim, CFL_SIZE); data->str = *PTR_PASS(nstr); return operator_p_create(D, dim, D, dim, CAST_UP(PTR_PASS(data)), hardthresh_apply, thresh_del); }
int main_estdelay(int argc, char* argv[]) { bool ring = false; int pad_factor = 100; unsigned int no_intersec_sp = 1; float size = 1.5; const struct opt_s opts[] = { OPT_SET('R', &ring, "RING method"), OPT_INT('p', &pad_factor, "p", "[RING] Padding"), OPT_UINT('n', &no_intersec_sp, "n", "[RING] Number of intersecting spokes"), OPT_FLOAT('r', &size, "r", "[RING] Central region size"), }; cmdline(&argc, argv, 2, 2, usage_str, help_str, ARRAY_SIZE(opts), opts); num_init(); if (pad_factor % 2 != 0) error("Pad_factor -p should be even\n"); long tdims[DIMS]; const complex float* traj = load_cfl(argv[1], DIMS, tdims); long tdims1[DIMS]; md_select_dims(DIMS, ~MD_BIT(1), tdims1, tdims); complex float* traj1 = md_alloc(DIMS, tdims1, CFL_SIZE); md_slice(DIMS, MD_BIT(1), (long[DIMS]){ 0 }, tdims, traj1, traj, CFL_SIZE);
static struct linop_s* linop_fft_create_priv(int N, const long dims[N], unsigned int flags, bool forward, bool center) { const struct operator_s* plan = fft_measure_create(N, dims, flags, true, false); const struct operator_s* iplan = fft_measure_create(N, dims, flags, true, true); PTR_ALLOC(struct fft_linop_s, data); SET_TYPEID(fft_linop_s, data); data->frw = plan; data->adj = iplan; data->N = N; data->center = center; data->dims = *TYPE_ALLOC(long[N]); md_copy_dims(N, data->dims, dims); data->strs = *TYPE_ALLOC(long[N]); md_calc_strides(N, data->strs, data->dims, CFL_SIZE); long fft_dims[N]; md_select_dims(N, flags, fft_dims, dims); data->nscale = (float)md_calc_size(N, fft_dims); lop_fun_t apply = forward ? fft_linop_apply : fft_linop_adjoint; lop_fun_t adjoint = forward ? fft_linop_adjoint : fft_linop_apply; struct linop_s* lop = linop_create(N, dims, N, dims, CAST_UP(PTR_PASS(data)), apply, adjoint, fft_linop_normal, NULL, fft_linop_free); if (center) { // FIXME: should only allocate flagged dims complex float* fftmod_mat = md_alloc(N, dims, CFL_SIZE); complex float* fftmodk_mat = md_alloc(N, dims, CFL_SIZE); // we need fftmodk only because we want to apply scaling only once complex float one[1] = { 1. }; md_fill(N, dims, fftmod_mat, one, CFL_SIZE); fftmod(N, dims, flags, fftmodk_mat, fftmod_mat); fftscale(N, dims, flags, fftmod_mat, fftmodk_mat); struct linop_s* mod = linop_cdiag_create(N, dims, ~0u, fftmod_mat); struct linop_s* modk = linop_cdiag_create(N, dims, ~0u, fftmodk_mat); struct linop_s* tmp = linop_chain(mod, lop); tmp = linop_chain(tmp, modk); linop_free(lop); linop_free(mod); linop_free(modk); lop = tmp; } return lop; }
static const struct linop_s* sense_nc_init(const long max_dims[DIMS], const long map_dims[DIMS], const complex float* maps, const long ksp_dims[DIMS], const long traj_dims[DIMS], const complex float* traj, struct nufft_conf_s conf, _Bool use_gpu) { long coilim_dims[DIMS]; long img_dims[DIMS]; md_select_dims(DIMS, ~MAPS_FLAG, coilim_dims, max_dims); md_select_dims(DIMS, ~COIL_FLAG, img_dims, max_dims); const struct linop_s* fft_op = nufft_create(DIMS, ksp_dims, coilim_dims, traj_dims, traj, NULL, conf, use_gpu); const struct linop_s* maps_op = maps2_create(coilim_dims, map_dims, img_dims, maps, use_gpu); const struct linop_s* lop = linop_chain(maps_op, fft_op); linop_free(maps_op); linop_free(fft_op); return lop; }
void wavelet_coeffs2(unsigned int N, unsigned int flags, long odims[N], const long dims[N], const long min[N], const long flen) { md_select_dims(N, ~flags, odims, dims); if (0 == flags) return; unsigned int levels = wavelet_num_levels(N, flags, dims, min, flen); assert(levels > 0); long wdims[N]; md_select_dims(N, flags, wdims, dims); // remove unmodified dims unsigned int b = ffs(flags) - 1; odims[b] = wavelet_coeffs_r(levels - 1, N, flags, wdims, min, flen); }
void fftscale2(unsigned int N, const long dimensions[N], unsigned long flags, const long ostrides[N], complex float* dst, const long istrides[N], const complex float* src) { long fft_dims[N]; md_select_dims(N, flags, fft_dims, dimensions); float scale = 1. / sqrtf((float)md_calc_size(N, fft_dims)); md_zsmul2(N, dimensions, ostrides, dst, istrides, src, scale); }
const struct linop_s* linop_fmac_create(unsigned int N, const long dims[N], unsigned int oflags, unsigned int iflags, unsigned int tflags, const complex float* tensor) { PTR_ALLOC(struct fmac_data, data); SET_TYPEID(fmac_data, data); data->N = N; data->dims = *TYPE_ALLOC(long[N]); md_copy_dims(N, data->dims, dims); data->idims = *TYPE_ALLOC(long[N]); data->istrs = *TYPE_ALLOC(long[N]); md_select_dims(N, ~iflags, data->idims, dims); md_calc_strides(N, data->istrs, data->idims, CFL_SIZE); data->odims = *TYPE_ALLOC(long[N]); data->ostrs = *TYPE_ALLOC(long[N]); md_select_dims(N, ~oflags, data->odims, dims); md_calc_strides(N, data->ostrs, data->odims, CFL_SIZE); data->tstrs = *TYPE_ALLOC(long[N]); data->tdims = *TYPE_ALLOC(long[N]); md_select_dims(N, ~tflags, data->tdims, dims); md_calc_strides(N, data->tstrs, data->tdims, CFL_SIZE); data->tensor = tensor; #ifdef USE_CUDA data->gpu_tensor = NULL; #endif long odims[N]; md_copy_dims(N, odims, data->odims); long idims[N]; md_copy_dims(N, idims, data->idims); return linop_create(N, odims, N, idims, CAST_UP(PTR_PASS(data)), fmac_apply, fmac_adjoint, NULL, NULL, fmac_free_data); }
const struct operator_s* sense_recon_create(const struct sense_conf* conf, const long dims[DIMS], const struct linop_s* sense_op, const long pat_dims[DIMS], const complex float* pattern, italgo_fun2_t italgo, iter_conf* iconf, unsigned int num_funs, const struct operator_p_s* thresh_op[num_funs], const struct linop_s* thresh_funs[num_funs], const long ksp_dims[DIMS], const struct operator_s* precond_op) { struct lsqr_conf lsqr_conf = { conf->cclambda }; const struct operator_s* op = NULL; long img_dims[DIMS]; md_select_dims(DIMS, ~COIL_FLAG, img_dims, dims); if (conf->rvc) { struct linop_s* rvc = rvc_create(DIMS, img_dims); struct linop_s* tmp_op = linop_chain(rvc, sense_op); linop_free(rvc); linop_free(sense_op); sense_op = tmp_op; } assert(1 == conf->rwiter); if (NULL == pattern) { op = lsqr2_create(&lsqr_conf, italgo, iconf, sense_op, precond_op, num_funs, thresh_op, thresh_funs); } else { complex float* weights = md_alloc(DIMS, pat_dims, CFL_SIZE); // FIXME: GPU #if 0 // buggy // md_zsqrt(DIMS, pat_dims, weights, pattern); #else long dimsR[DIMS + 1]; real_from_complex_dims(DIMS, dimsR, pat_dims); md_sqrt(DIMS + 1, dimsR, (float*)weights, (const float*)pattern); #endif struct linop_s* weights_op = linop_cdiag_create(DIMS, ksp_dims, FFT_FLAGS, weights); // FIXME: check pat_dims op = wlsqr2_create(&lsqr_conf, italgo, iconf, sense_op, weights_op, precond_op, num_funs, thresh_op, thresh_funs); } return op; }
// assumes no overlap static long memory_footprint(int N, const long dims[N], const long strs[N]) { unsigned int flags = 0; for (int i = 0; i < N; i++) flags |= (0 == strs[i]); long dims2[N]; md_select_dims(N, ~flags, dims2, dims); return md_calc_size(N, dims2); }
static double bench_generic_matrix_multiply(long dims[DIMS]) { long dimsX[DIMS]; long dimsY[DIMS]; long dimsZ[DIMS]; md_select_dims(DIMS, 2 * 3 + 17, dimsX, dims); // 1 110 1 md_select_dims(DIMS, 2 * 6 + 17, dimsY, dims); // 1 011 1 md_select_dims(DIMS, 2 * 5 + 17, dimsZ, dims); // 1 101 1 long strsX[DIMS]; long strsY[DIMS]; long strsZ[DIMS]; md_calc_strides(DIMS, strsX, dimsX, CFL_SIZE); md_calc_strides(DIMS, strsY, dimsY, CFL_SIZE); md_calc_strides(DIMS, strsZ, dimsZ, CFL_SIZE); complex float* x = md_alloc(DIMS, dimsX, CFL_SIZE); complex float* y = md_alloc(DIMS, dimsY, CFL_SIZE); complex float* z = md_alloc(DIMS, dimsZ, CFL_SIZE); md_gaussian_rand(DIMS, dimsX, x); md_gaussian_rand(DIMS, dimsY, y); md_clear(DIMS, dimsZ, z, CFL_SIZE); double tic = timestamp(); md_zfmac2(DIMS, dims, strsZ, z, strsX, x, strsY, y); double toc = timestamp(); md_free(x); md_free(y); md_free(z); return toc - tic; }
static const struct linop_s* sense_nc_init(const long max_dims[DIMS], const long map_dims[DIMS], const complex float* maps, const long ksp_dims[DIMS], const long traj_dims[DIMS], const complex float* traj, struct nufft_conf_s conf, struct operator_s** precond_op) { long coilim_dims[DIMS]; long img_dims[DIMS]; md_select_dims(DIMS, ~MAPS_FLAG, coilim_dims, max_dims); md_select_dims(DIMS, ~COIL_FLAG, img_dims, max_dims); const struct linop_s* fft_op = nufft_create(DIMS, ksp_dims, coilim_dims, traj_dims, traj, NULL, conf); const struct linop_s* maps_op = maps2_create(coilim_dims, map_dims, img_dims, maps); //precond_op[0] = (struct operator_s*) nufft_precond_create( fft_op ); precond_op[0] = NULL; const struct linop_s* lop = linop_chain(maps_op, fft_op); linop_free(maps_op); linop_free(fft_op); return lop; }
void parslices(grecon_fun_t grecon, void* param, const long dims[DIMS], complex float* image, const long sens_dims[DIMS], const complex float* sens_maps, const long pat_dims[DIMS], const complex float* pattern, const complex float* kspace_data, bool output_ksp, bool gpu) { unsigned int N = DIMS; long ksp_dims[N]; long img_dims[N]; long ksp_strs[N]; long img_strs[N]; md_select_dims(N, ~MAPS_FLAG, ksp_dims, dims); md_calc_strides(N, ksp_strs, ksp_dims, CFL_SIZE); md_select_dims(N, output_ksp ? ~MAPS_FLAG : ~COIL_FLAG, img_dims, dims); md_calc_strides(N, img_strs, img_dims, CFL_SIZE); parslices2(grecon, param, dims, img_strs, image, sens_dims, sens_maps, pat_dims, pattern, ksp_strs, kspace_data, output_ksp, gpu); }
// [AC-Adaptive] static void radial_self_delays(unsigned int N, float shifts[N], const float phi[N], const long dims[DIMS], const complex float* in) { unsigned int d = 2; unsigned int flags = (1 << d); assert(N == dims[d]); long dims1[DIMS]; md_select_dims(DIMS, ~flags, dims1, dims); complex float* tmp1 = md_alloc(DIMS, dims1, CFL_SIZE); complex float* tmp2 = md_alloc(DIMS, dims1, CFL_SIZE); long pos[DIMS] = { 0 }; for (unsigned int i = 0; i < dims[d]; i++) { pos[d] = i; md_copy_block(DIMS, pos, dims1, tmp1, dims, in, CFL_SIZE); // find opposing spoke float mdelta = 0.; int mindex = 0; for (unsigned int j = 0; j < dims[d]; j++) { float delta = cabsf(cexpf(1.i * phi[j]) - cexpf(1.i * phi[i])); if (mdelta <= delta) { mdelta = delta; mindex = j; } } pos[d] = mindex; md_copy_block(DIMS, pos, dims1, tmp2, dims, in, CFL_SIZE); unsigned int d2 = 1; float rshifts[DIMS]; md_flip(DIMS, dims1, MD_BIT(d2), tmp2, tmp2, CFL_SIZE); // could be done by iFFT in est_subpixel_shift est_subpixel_shift(DIMS, rshifts, dims1, MD_BIT(d2), tmp2, tmp1); float mshift = rshifts[d2] / 2.; // mdelta shifts[i] = mshift; } md_free(tmp1); md_free(tmp2); }
struct linop_s* sampling_create(const long dims[DIMS], const long pat_dims[DIMS], const complex float* pattern) { struct sampling_data_s* data = xmalloc(sizeof(struct sampling_data_s)); md_select_dims(DIMS, ~MAPS_FLAG, data->dims, dims); // dimensions of kspace md_calc_strides(DIMS, data->strs, data->dims, CFL_SIZE); md_calc_strides(DIMS, data->pat_strs, pat_dims, CFL_SIZE); data->pattern = pattern; return linop_create(DIMS, data->dims, DIMS, data->dims, data, sampling_apply, sampling_apply, sampling_apply, NULL, sampling_free); }
int main_estdelay(int argc, char* argv[]) { mini_cmdline(&argc, argv, 2, usage_str, help_str); long tdims[DIMS]; const complex float* traj = load_cfl(argv[1], DIMS, tdims); long tdims1[DIMS]; md_select_dims(DIMS, ~MD_BIT(1), tdims1, tdims); complex float* traj1 = md_alloc(DIMS, tdims1, CFL_SIZE); md_slice(DIMS, MD_BIT(1), (long[DIMS]){ 0 }, tdims, traj1, traj, CFL_SIZE);
static void embed(unsigned int N, unsigned int flags, long ostr[N], const long dims[N], const long str[N]) { unsigned int b = ffs(flags) - 1; long dims1[N]; md_select_dims(N, flags, dims1, dims); md_calc_strides(N, ostr, dims1, str[b]); for (unsigned int i = 0; i < N; i++) if (!MD_IS_SET(flags, i)) ostr[i] = str[i]; }
void estimate_pattern(unsigned int D, const long dims[D], unsigned int flags, complex float* pattern, const complex float* kspace_data) { md_zrss(D, dims, flags, pattern, kspace_data); long dims2[D]; long strs2[D]; md_select_dims(D, ~flags, dims2, dims); md_calc_strides(D, strs2, dims2, CFL_SIZE); long strs1[D]; md_singleton_strides(D, strs1); md_zcmp2(D, dims2, strs2, pattern, strs2, pattern, strs1, &(complex float){ 0. });
static complex float* compute_psf2(unsigned int N, const long psf_dims[N + 3], const long trj_dims[N + 3], const complex float* traj, const complex float* weights) { unsigned int ND = N + 3; long img_dims[ND]; long img_strs[ND]; md_select_dims(ND, ~MD_BIT(N + 0), img_dims, psf_dims); md_calc_strides(ND, img_strs, img_dims, CFL_SIZE); // PSF 2x size long img2_dims[ND]; long img2_strs[ND]; md_copy_dims(ND, img2_dims, img_dims); for (int i = 0; i < 3; i++) img2_dims[i] = (1 == img_dims[i]) ? 1 : (2 * img_dims[i]); md_calc_strides(ND, img2_strs, img2_dims, CFL_SIZE); complex float* traj2 = md_alloc(ND, trj_dims, CFL_SIZE); md_zsmul(ND, trj_dims, traj2, traj, 2.); complex float* psft = compute_psf(ND, img2_dims, trj_dims, traj2, weights); md_free(traj2); fftuc(ND, img2_dims, FFT_FLAGS, psft, psft); // reformat long sub2_strs[ND]; md_copy_strides(ND, sub2_strs, img2_strs); for(int i = 0; i < 3; i++) sub2_strs[i] *= 2;; complex float* psf = md_alloc(ND, psf_dims, CFL_SIZE); long factors[N]; for (unsigned int i = 0; i < N; i++) factors[i] = ((img_dims[i] > 1) && (i < 3)) ? 2 : 1; md_decompose(N + 0, factors, psf_dims, psf, img2_dims, psft, CFL_SIZE); md_free(psft); return psf; }