Source code for monalisa.recon._sensa

"""Port of src/fourier123/solver_function/imDim/nonCartesian/bmSensa.m."""

import numpy as np

from monalisa._mat import double, isempty, single, vec
from monalisa.array._block_reshape import block_reshape
from monalisa.array._col_reshape import col_reshape
from monalisa.fourier._kf import kf
from monalisa.fourier._kf_conj import kf_conj
from monalisa.fourier._nakatsha import nakatsha
from monalisa.fourier._shanna import shanna
from monalisa.optim._witness_info import cell_row_set, cell_set
from monalisa.optim._y_ve_reshape import y_ve_reshape
from monalisa.recon._common import dot, inv_single, sq


[docs] def sensa(x, y, ve, C, Gu, Gut, frSize, nCGD, ve_max, nIter, witnessInfo): """SENSE reconstruction: ``nIter`` restarts of ``nCGD`` conjugate gradient steps on the density-weighted least squares data fidelity, from ``x``.""" myEps = np.float32(10 * np.finfo(np.float32).eps) y = single(y) nCh = y.shape[1] N_u = double(single(vec(Gu.N_u))) frSize = double(single(vec(frSize))) dK_u = double(single(vec(Gu.d_u))) C = single(col_reshape(C, N_u)) ve = single(y_ve_reshape(ve, y.shape)) kp = (Gu.kernel_type, Gu.nWin, Gu.kernelParam) KFC = single(col_reshape(kf(C, N_u, frSize, dK_u, nCh, *kp), frSize)) KFC_conj = single(col_reshape(kf_conj(np.conj(C), N_u, frSize, dK_u, nCh, *kp), frSize)) x = single(col_reshape(x, frSize)) dX_u = single((np.float32(1) / single(dK_u)) / single(N_u)) HX = np.prod(dX_u) if isempty(ve_max): ve_max = np.max(ve) HY = np.minimum(ve, np.float32(ve_max)) inv_HX = inv_single(HX) for k, (name, val) in enumerate([("recon_name", "sensa"), ("dK_u", dK_u), ("N_u", N_u), ("frSize", frSize), ("nIter", nIter), ("nCGD", nCGD), ("ve_max", ve_max), ("residu", np.zeros((1, int(nIter))))], start=1): cell_set(witnessInfo.param_name, k, name) cell_set(witnessInfo.param, k, val) def M(v): return shanna(v, Gu, KFC, frSize, "MATLAB") def dagM(r): return inv_HX * nakatsha(HY * r, Gut, KFC_conj, True, frSize, "MATLAB") c = 0 for c in range(1, int(nIter) + 1): res_next = y - M(x) dagM_res_next = dagM(res_next) sqn_next = np.real(dot(dagM_res_next, HX * dagM_res_next)) p_next = dagM_res_next for i in range(1, int(nCGD) + 1): res_curr, sqn_curr, p_curr = res_next, sqn_next, p_next if sqn_curr < myEps: break Mp = M(p_curr) a = sqn_curr / sq(Mp, HY) x = x + a * p_curr if i == nCGD: break res_next = res_curr - a * Mp dagM_res_next = dagM(res_next) sqn_next = np.real(dot(dagM_res_next, HX * dagM_res_next)) b = sqn_next / sqn_curr p_next = dagM_res_next + b * p_curr temp_r = y - M(x) cell_row_set(witnessInfo.param, 7, c, sq(temp_r, HY)) # upstream writes the residual into param{7} witnessInfo.watch(c, x, frSize, "loop") witnessInfo.watch(c, x, frSize, "final") return block_reshape(x, frSize)