// Forward: from image to kspace static void nufft_apply(const void* _data, complex float* dst, const complex float* src) { struct nufft_data* data = (struct nufft_data*)_data; assert(!data->conf.toeplitz); // if toeplitz linphase has no roll, so would need to be added unsigned int ND = data->N + 3; md_zmul2(ND, data->cml_dims, data->cml_strs, data->grid, data->cim_strs, src, data->lph_strs, data->linphase); linop_forward(data->fft_op, ND, data->cml_dims, data->grid, ND, data->cml_dims, data->grid); md_zmul2(ND, data->cml_dims, data->cml_strs, data->grid, data->cml_strs, data->grid, data->img_strs, data->fftmod); md_clear(ND, data->ksp_dims, dst, CFL_SIZE); complex float* gridX = md_alloc(data->N, data->cm2_dims, CFL_SIZE); long factors[data->N]; for (unsigned int i = 0; i < data->N; i++) factors[i] = ((data->img_dims[i] > 1) && (i < 3)) ? 2 : 1; md_recompose(data->N, factors, data->cm2_dims, gridX, data->cml_dims, data->grid, CFL_SIZE); grid2H(2., data->width, data->beta, ND, data->trj_dims, data->traj, data->ksp_dims, dst, data->cm2_dims, gridX); md_free(gridX); if (NULL != data->weights) md_zmul2(data->N, data->ksp_dims, data->ksp_strs, dst, data->ksp_strs, dst, data->wgh_strs, data->weights); }
static void unisoftthresh_apply(const operator_data_t* _data, float mu, complex float* dst, const complex float* src) { const auto data = CAST_DOWN(thresh_s, _data); if (0. == mu) { md_copy(data->D, data->dim, dst, src, CFL_SIZE); } else { const long* transform_dims = linop_codomain(data->unitary_op)->dims; const long* transform_strs = linop_codomain(data->unitary_op)->strs; complex float* tmp = md_alloc_sameplace(data->D, transform_dims, CFL_SIZE, dst); linop_forward(data->unitary_op, data->D, transform_dims, tmp, data->D, data->dim, src); complex float* tmp_norm = md_alloc_sameplace(data->D, data->norm_dim, CFL_SIZE, dst); md_zsoftthresh_core2(data->D, transform_dims, data->lambda * mu, data->flags, tmp_norm, transform_strs, tmp, transform_strs, tmp); md_free(tmp_norm); linop_adjoint(data->unitary_op, data->D, data->dim, dst, data->D, transform_dims, tmp); md_free(tmp); } }
/** * Undersampled FFT forward operator */ void ufft_apply(const linop_data_t* _data, complex float* dst, const complex float* src) { const struct ufft_data* data = CONTAINER_OF(_data, const struct ufft_data, base); linop_forward(data->fft_op, DIMS, data->ksp_dims, dst, DIMS, data->ksp_dims, src); md_zmul2(DIMS, data->ksp_dims, data->ksp_strs, dst, data->ksp_strs, dst, data->pat_strs, data->pat); }
/** * Undersampled FFT forward operator */ void ufft_apply(const linop_data_t* _data, complex float* dst, const complex float* src) { struct ufft_data* data = CAST_DOWN(ufft_data, _data); linop_forward(data->fft_op, DIMS, data->ksp_dims, dst, DIMS, data->ksp_dims, src); md_zmul2(DIMS, data->ksp_dims, data->ksp_strs, dst, data->ksp_strs, dst, data->pat_strs, data->pat); }
static void toeplitz_mult(const struct nufft_data* data, complex float* dst, const complex float* src) { unsigned int ND = data->N + 3; md_zmul2(ND, data->cml_dims, data->cml_strs, data->grid, data->cim_strs, src, data->lph_strs, data->linphase); linop_forward(data->fft_op, ND, data->cml_dims, data->grid, ND, data->cml_dims, data->grid); md_zmul2(ND, data->cml_dims, data->cml_strs, data->grid, data->cml_strs, data->grid, data->psf_strs, data->psf); linop_adjoint(data->fft_op, ND, data->cml_dims, data->grid, ND, data->cml_dims, data->grid); md_clear(ND, data->cim_dims, dst, CFL_SIZE); md_zfmacc2(ND, data->cml_dims, data->cim_strs, dst, data->cml_strs, data->grid, data->lph_strs, data->linphase); }
/** * 1/2 || Ax - b ||^2 + rho/2 || x - y ||^2 * * x = (ATA + lI)^-1 b * * X = 1 / (pat^2 + l) B * */ static void ufft_apply_pinverse(const linop_data_t* _data, float rho, complex float* dst, const complex float* src) { const struct ufft_data* data = CONTAINER_OF(_data, const struct ufft_data, base); md_zsadd(DIMS, data->pat_dims, data->pat, data->pat, rho); linop_forward(data->fft_op, DIMS, data->ksp_dims, dst, DIMS, data->ksp_dims, src); md_zdiv2(DIMS, data->ksp_dims, data->ksp_strs, dst, data->ksp_strs, dst, data->pat_strs, data->pat); linop_adjoint(data->fft_op, DIMS, data->ksp_dims, dst, DIMS, data->ksp_dims, dst); md_zsadd(DIMS, data->pat_dims, data->pat, data->pat, -rho); }
static void nufft_precond_apply(const operator_data_t* _data, unsigned int M, void* args[M]) { assert(2 == M); const auto data = CAST_DOWN(nufft_precond_data, _data); complex float* dst = args[0]; const complex float* src = args[1]; linop_forward(data->fft_op, data->N, data->cim_dims, dst, data->N, data->cim_dims, src); md_zdiv2(data->N, data->cim_dims, data->cim_strs, dst, data->cim_strs, dst, data->pre_strs, data->pre); linop_adjoint(data->fft_op, data->N, data->cim_dims, dst, data->N, data->cim_dims, dst); }