def test_plot(): # ====================================================================== "Check that the plot method works" # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 200) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P # Linear parameters: non-negativity lbl = np.zeros(len(r)) # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), par0=0.2, lb=0, ub=1, lbl=lbl, uq=False) fig = fit.plot(show=False) assert str(fig.__class__) == "<class 'matplotlib.figure.Figure'>"
def test_cost_value(): #============================================================ "Check that the cost value is properly returned" # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 200) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P # Non-linear parameters nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) ubl = np.full(len(r), np.inf) # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, ubl) assert isinstance(fit.cost, float) and np.round( fit.cost / np.sum(fit.residuals**2), 5) == 1
def test_goodness_of_fit(): #============================================================ "Check the goodness-of-fit statistics are correct" # Prepare test data r = np.linspace(2, 5, 150) t = np.linspace(-0.2, 4, 100) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.15, 0.6, 4.5, 0.2, 0.4] P = dd_gauss2(r, *parin) sigma = 0.03 V = K @ P + whitegaussnoise(t, sigma, seed=2, rescale=True) # Non-linear parameters # nlpar = [lam] nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) ubl = [] # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, ubl, noiselvl=sigma, uq=False) stats = fit.stats assert abs(stats['chi2red'] - 1) < 0.05
def test_reg_tikhonov(): #============================================================ "Check that Tikhonov regularization of linear problem works" # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 100) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P # Non-linear parameters # nlpar = [lam] nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, uq=False) Pfit = fit.lin assert ovl(P, Pfit) > 0.95
def assert_solver(solver): # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 200) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P # Non-linear parameters # nlpar = [lam] nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) ubl = [] # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, ubl, nnlsSolver=solver, uq=False) Pfit = fit.lin assert ovl(P, Pfit) > 0.95
def test_confinter_model(): #======================================================================= "Check that the confidence intervals of the fitted model are correct" # Prepare test data r = np.linspace(1, 8, 150) t = np.linspace(0, 4, 200) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P + whitegaussnoise(t, 0.05, seed=1) nlpar0 = 0.2 lb = 0 ub = 1 lbl = np.full(len(r), 0) # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl) Vfit = fit.model Vuq = fit.modelUncert Vci50 = Vuq.ci(50) Vci95 = Vuq.ci(95) Vlb = np.full(len(t), -np.inf) Vub = np.full(len(t), np.inf) assert_confidence_intervals(Vci50, Vci95, Vfit, Vlb, Vub)
def test_confinter_nonlinear(): #======================================================================= "Check that the confidence intervals of the non-linear parameters are correct" # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 200) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P # Non-linear parameters # nlpar = [lam] nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) ubl = np.full(len(r), np.inf) # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, ubl) parfit = fit.nonlin uq = fit.nonlinUncert parci50 = np.atleast_2d(uq.ci(50)) parci95 = np.atleast_2d(uq.ci(95)) assert_confidence_intervals(parci50, parci95, parfit, lb, ub)
def test_confinter_linear(): #======================================================================= "Check that the confidence intervals of the linear parameters are correct" # Prepare test data r = np.linspace(1, 8, 150) t = np.linspace(0, 4, 200) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P + whitegaussnoise(t, 0.05, seed=1) # Non-linear parameters # nlpar = [lam] nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) ubl = np.full(len(r), np.inf) # Separable LSQ fit fit = snlls(V, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl) Pfit = np.round(fit.lin, 6) uq = fit.linUncert Pci50 = np.round(uq.ci(50), 6) Pci95 = np.round(uq.ci(95), 6) assert_confidence_intervals(Pci50, Pci95, Pfit, lbl, ubl)
def assert_multigauss_SNLLS_problem(nonlinearconstr=True, linearconstr=True): # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 200) K = dipolarkernel(t, r) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P def Kmodel(p, t, r): # Unpack parameters r1, w1, r2, w2 = p # Generate basic kernel K0 = dipolarkernel(t, r) # Get Gauss basis functions P1 = dd_gauss(r, r1, w1) P2 = dd_gauss(r, r2, w2) # Combine all non-linear functions into one K = np.zeros((len(t), 2)) K[:, 0] = K0 @ P1 K[:, 1] = K0 @ P2 return K # Non-linear parameters # nlpar = [r1 w1 r2 w2] nlpar0 = [3.2, 0.2, 4.2, 0.3] if nonlinearconstr: lb = [1, 0.1, 1, 0.1] ub = [20, 5, 20, 5] else: lb = [] ub = [] # Linear parameters if linearconstr: lbl = [0, 0] ubl = [1, 1] else: lbl = [] ubl = [] # Separable LSQ fit fit = snlls(V, lambda p: Kmodel(p, t, r), nlpar0, lb, ub, lbl, ubl, reg=False, uq=False) nonlinfit = fit.nonlin linfit = fit.lin parout = [ nonlinfit[0], nonlinfit[1], linfit[0], nonlinfit[2], nonlinfit[3], linfit[1] ] parout = np.asarray(parout) parin = np.asarray(parin) assert np.max(abs(parout - parin) < 1e-1)
def test_confinter_scaling(): #============================================================ "Check that the confidence intervals are agnostic w.r.t. scaling" # Prepare test data r = np.linspace(1, 8, 80) t = np.linspace(0, 4, 50) lam = 0.25 K = dipolarkernel(t, r, mod=lam) parin = [3.5, 0.4, 0.6, 4.5, 0.5, 0.4] P = dd_gauss2(r, *parin) V = K @ P + whitegaussnoise(t, 0.01, seed=1) # Non-linear parameters nlpar0 = 0.2 lb = 0 ub = 1 # Linear parameters: non-negativity lbl = np.zeros(len(r)) V0_1 = 1 V0_2 = 1e8 # Separable LSQ fit fit1 = snlls(V * V0_1, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, nonlin_tol=1e-3) fit2 = snlls(V * V0_2, lambda lam: dipolarkernel(t, r, mod=lam), nlpar0, lb, ub, lbl, nonlin_tol=1e-3) # Assess linear parameter uncertainties ci1 = fit1.linUncert.ci(95) ci2 = fit2.linUncert.ci(95) ci1[ci1 == 0] = 1e-16 ci2[ci2 == 0] = 1e-16 assert np.max(abs(ci2 / V0_2 - ci1)) < 1e-6 # Assess nonlinear parameter uncertainties ci1 = fit1.nonlinUncert.ci(95) ci2 = fit2.nonlinUncert.ci(95) ci1[ci1 == 0] = 1e-16 ci2[ci2 == 0] = 1e-16 assert np.max(abs(ci2 - ci1)) < 1e-6
def test_regularized_global(): #======================================================================= "Check global SNLLS of a nonlinear-constrained + linear-regularized problem" t1 = np.linspace(0, 3, 150) t2 = np.linspace(0, 4, 200) r = np.linspace(2.5, 5, 80) P = dd_gauss2(r, 3.7, 0.5, 0.5, 4.3, 0.3, 0.5) kappa = 0.50 lam1 = 0.25 lam2 = 0.35 K1 = dipolarkernel(t1, r, mod=lam1, bg=bg_exp(t1, kappa)) K2 = dipolarkernel(t2, r, mod=lam2, bg=bg_exp(t2, kappa)) V1 = K1 @ P V2 = K2 @ P # Global non-linear model def globalKmodel(par): # Unpack parameters kappa, lam1, lam2 = par K1 = dipolarkernel(t1, r, mod=lam1, bg=bg_exp(t1, kappa)) K2 = dipolarkernel(t2, r, mod=lam2, bg=bg_exp(t2, kappa)) return K1, K2 # Non-linear parameters # [kappa lambda1 lambda2] par0 = [0.5, 0.5, 0.5] lb = [0, 0, 0] ub = [1, 1, 1] # Linear parameters: non-negativity lbl = np.zeros(len(r)) ubl = [] # Separable LSQ fit fit = snlls([V1, V2], globalKmodel, par0, lb, ub, lbl, ubl, uq=False) Pfit = fit.lin assert ovl(P, Pfit) > 0.9