def test_get_residual_minima(pm, TE_s, Cmats): sig = css.build_signal(TE_s, pm) pm_init = deepcopy(pm) pm_init[:, 0:2] = 0 pm_init[:, 1] = 0 pm_init[:, 2] -= pm_init[0, 2] pm_init[:, 3] = 0 print(pm_init) Cm, Cp, Cf, Cr = Cmats nlparams_in = [[pm[0, 1]], [pm[1, 1]], list(np.arange(-10, 20, 1)), list(np.arange(0, 20, 1))] shape = tuple([len(x) for x in nlparams_in]) nlparams = np.concatenate(nlparams_in).ravel() params_at_minima = residual.get_residual_minima(TE_s, sig, pm_init, Cm, Cp, Cf, Cr, nlparams, shape) print(pm, params_at_minima.shape, params_at_minima) assert params_at_minima[3, 0] == pm[0, 2] assert params_at_minima[4, 0] == pm[0, 3]
def test_add_noise(): TE_s = np.array([1, 2, 3, 4]) * 1e-3 pm = np.ones((3, 4)) pm[:, 0] = [1, 0.5, 0.5] pm[:, 1] = np.pi / 4 pm[:, 2] = 100 + np.array([0, 340, 440]) pm[:, 3] = 5 sig = css.build_signal(TE_s, pm) SNR = 20 noisy_sig = css.add_noise(sig, SNR) assert (noisy_sig != sig).all() assert noisy_sig.dtype == complex
def estimate_bias(TE_s, pm_true, pm_init, Cm, Cp, Cf, Cr, nlparams, shape, tol, itermax): sig = css.build_signal(TE_s, pm_true) pm0, min_residual = residual.get_global_residual_minimum(TE_s, sig, pm_init.copy(), Cm, Cp, Cf, Cr, nlparams, shape) pme, resnorm, iterations = css.varpro(TE_s, sig, pm0, Cm, Cp, Cf, Cr, tol, itermax) return pm_true - pme
def test_map_varpro(pm, TE_s, Cmats): Cm, Cp, Cf, Cr = Cmats sig = css.build_signal(TE_s, pm) nVoxel = 100 Sig = np.tile(sig.T, [nVoxel, 1]) pm0 = deepcopy(pm) pm0[:, 0:2] = 0 pm0[:, 3] = 0 Pm0 = np.tile(pm, [nVoxel, 1, 1]) Pme, Resnorm, Iterations = css.map_varpro(TE_s, Sig, Pm0, Cm, Cp, Cf, Cr, tol, itermax) assert np.allclose(Pm0, Pme)
def test_list_residuals(pm, TE_s, Cmats): Cm, Cp, Cf, Cr = Cmats sig = css.build_signal(TE_s, pm) nlparams_in = [[0], [0], list(np.arange(-100, 100, 5)), list(np.arange(0, 300, 30))] shape = np.array([len(x) for x in nlparams_in]) nlparams = np.concatenate(nlparams_in).ravel() Pm = sim.assemble_Pm(nlparams, shape, Cp, Cf, Cr, pm) residual_list = residual.list_residuals(TE_s, sig, Pm, Cm) print(Pm[residual_list.argmin(), :, :]) assert residual_list.ndim == 1 assert len(residual_list) == np.prod(shape)
def test_varpro(pm, TE_s, Cmats): Cm, Cp, Cf, Cr = Cmats sig = css.build_signal(TE_s, pm) tol = 1e-6 itermax = 100 pm0 = deepcopy(pm) pme, resnorm, i = css.varpro(TE_s, sig, pm0, Cm, Cp, Cf, Cr, tol, int(itermax)) print('i =', i, 'resnorm =', resnorm) print('result: pm =\n', pme, '\nerror =', pme - pm) assert np.allclose(pm, pme) assert isinstance(resnorm, float) assert isinstance(i, int) assert i == 1
def test_get_residual_array(pm, TE_s, Cmats): Cm, Cp, Cf, Cr = Cmats sig = css.build_signal(TE_s, pm) nlparams_in = [[0], [0], list(np.arange(-100, 100, 5)), list(np.arange(0, 300, 30))] shape = tuple([len(x) for x in nlparams_in]) nlparams = np.concatenate(nlparams_in).ravel() pm_init = deepcopy(pm) pm_init[:, 0:2] = 0 pm_init[:, 2] -= pm_init[0, 2] pm_init[:, 3] = 0 R = residual.get_residual_array(TE_s, sig, pm_init, Cm, Cp, Cf, Cr, nlparams, shape) print(pm) print(R.argmin()) assert R.shape == shape
def test_estimate_bias(pm, TE_s, Cmats): Cm, Cp, Cf, Cr = Cmats sig = css.build_signal(TE_s, pm) nlparams_in = [[0], [0], list(np.arange(-100, 100, 5)), list(np.arange(0, 300, 30))] shape = tuple([len(x) for x in nlparams_in]) nlparams = np.concatenate(nlparams_in).ravel() pm_init = deepcopy(pm) pm_init[:, 0:2] = 0 pm_init[:, 1] = 0 pm_init[:, 2] -= pm_init[0, 2] pm_init[:, 3] = 0 print(pm_init) bias = sim.estimate_bias(TE_s, pm, pm_init, Cm, Cp, Cf, Cr, nlparams, shape, tol, itermax) print(bias) assert (bias < tol).all()
def test_get_residual(pm, TE_s, Cmats): # FIXME: understand the failure Cm = Cmats[0] sig = css.build_signal(TE_s, pm) res = residual.get_residual(TE_s, pm, sig, Cm) assert res == 0
def sample_signal(self, SNR=None): if SNR is None: self.signal_samp = css.build_signal(self.TE_s, self.pm) else: self.signal_samp = \ css.add_noise(css.build_signal(self.TE_s, self.pm), SNR)
def build_signal(self): self.signal = css.build_signal(self.t_s, self.pm) self.sample_signal(self.SNR)
def test_build_signal(pm, TE_s): sig = css.build_signal(TE_s, pm) assert sig is not None assert sig.dtype == complex
def test_bydder(): from Fatmodel import Fatmodel F = Fatmodel() F.set_params_matrix() # F.build_signal() # F.plot_signal() # F.pm[1:, 1] = np.pi/2 F.build_signal() # F.plot_signal() # F.sample_signal(SNR=30) F.set_constraints_matrices() Cm, Cp, Cf, Cr = F.Cm, F.Cp, F.Cf, F.Cr Cmc = Cm.astype(np.complex128) sig = F.signal_samp tol = 1e-10 itermax = 100 pm = deepcopy(F.pm) pm[:, :2] = 0 pm[:, 2] -= pm0[0, 2] pm[:, 3] = 0 Cp = np.zeros((len(pm0), 1)) Cp[:, 0] = 1. TE_s = F.TE_s M, Ntot, Nm, Np, Nf, Nr = css.get_paramsCount(Cm, Cp, Cf, Cr) eps = 2 * tol i = 0 cond_thres = 1e6 while eps > tol and i < itermax: # update linear parameters A = css.get_Amatrix(TE_s, pm) if np.isnan(A).any() or np.isinf(A).any(): break if np.linalg.cond(A) > cond_thres: break # P = np.diag(np.exp(1.j * pm[:, 1])) # Atb = A.conj().T.dot(sig) # AtArealinv = np.linalg.inv(A.conj().T.dot(A).real) # pm[:, 0] = AtArealinv.dot(np.real(P.conj().dot(Atb))) # print(pm) # phi = 0.5 * np.angle(Atb.conj().T.dot(AtAinv).dot(P.conj().dot(Atb))) rho = np.linalg.lstsq(np.dot(A, Cmc), sig, rcond=-1)[0] Cm_rho = np.dot(Cmc, rho) pm[:, 0] = np.abs(Cm_rho) # pm[:, 1] = np.angle(Cm_rho) # pm[:, 0] = css.extract_param_type(0, pm, [Cm, Cp, Cf, Cr]) # pm[:, 1] = css.extract_param_type(1, pm, [Cm, Cp, Cf, Cr]) # update nonlinear parameters r = sig - css.build_signal(TE_s, pm) J = css.get_Jacobian(TE_s, pm, Cm, Cp, Cf, Cr) rr = np.concatenate((r.real, r.imag), axis=0) JJ = np.concatenate((J.real, J.imag), axis=0) if np.isnan(JJ).any() or np.isinf(JJ).any(): break if np.linalg.cond(JJ) > cond_thres: break updates = np.linalg.lstsq(JJ, rr, rcond=-1)[0] print(updates) eps = np.linalg.norm(updates) # for convergence criterium pm_update = np.zeros_like(pm) pm_update[:, 1] = np.dot(Cp, updates[Nm:Nm+Np]) pm_update[:, 2] = np.dot(Cf, updates[Nm+Np:Nm+Np+Nf]) pm_update[:, 3] = np.dot(Cr, updates[Nm+Np+Nf:Nm+Np+Nf+Nr]) pm += pm_update i += 1 resnorm = np.linalg.norm(sig - css.build_signal(TE_s, pm)) # residual norm print(pm0, F.pm, pm, pm - F.pm, resnorm, i, sep='\n') pme, resnorm, i = css.varpro(F.TE_s, sig, pm0, F.Cm, F.Cp, F.Cf, F.Cr, tol, itermax) print(pme) A = css.get_Amatrix(TE_s, pme) print(A) Atb = A.conj().T.dot(sig) print(Atb) AtArealinv = np.linalg.inv(A.conj().T.dot(A).real) print(AtArealinv) phi = 0.5 * np.angle(Atb.conj().T.dot(AtAinv).dot(Atb)) rho = AtArealinv.dot((np.exp(-1.j * phi) * Atb).real) print(rho, phi)