def test_multiple_penalties(): # ====================================================================== "Check that multiple additional penaltyies can be passed correctly" t = np.linspace(0, 5, 300) r = np.linspace(2, 6, 90) P = dd_gauss(r, 4.5, 0.25) param = 0.2 K = dipolarkernel(t, r, mod=param) V = K @ P + whitegaussnoise(t, 0.001, seed=1) dr = np.mean(np.diff(r)) beta = 0.05 R = 0.5 compactness_penalty = lambda pnonlin, plin: beta * np.sqrt(plin * ( r - np.trapz(plin * r, r))**2 * dr) radial_penalty = lambda pnonlin, plin: 1 / R**2 * (np.linalg.norm( (pnonlin - param) / param - R))**2 Kmodel = lambda lam: dipolarkernel(t, r, mod=lam) fit0 = snlls(V, Kmodel, par0=0.2, lb=0, ub=1, lbl=np.zeros_like(r), extrapenalty=[compactness_penalty]) fitmoved = snlls(V, Kmodel, par0=0.2, lb=0, ub=1, lbl=np.zeros_like(r), extrapenalty=[compactness_penalty, radial_penalty]) assert ovl(P, fit0.lin) > ovl(P, fitmoved.lin)
def assert_uq(uq,attr): if attr=='mean': assert np.allclose(uq.mean,means,rtol=1e-2) elif attr=='std': assert np.allclose(uq.std,std,rtol=1e-2) elif attr=='median': assert np.allclose(uq.median,p50,rtol=1e-2) elif attr=='ci': assert np.allclose(uq.ci(95),ci95,rtol=1e-2) assert np.allclose(uq.ci(90),ci90,rtol=1e-2) assert np.allclose(uq.ci(50),ci50,rtol=1e-2) elif attr=='percentile': assert np.allclose(uq.percentile(95),p95,rtol=1e-2) assert np.allclose(uq.percentile(5),p5,rtol=1e-2) assert np.allclose(uq.percentile(50),p50,rtol=1e-2) elif attr=='pardist': x1,pdf1 = uq.pardist(0) x2,pdf2 = uq.pardist(1) xs = [x1,x2] pdfs = [pdf1,pdf2] pdfs_ref = [dd_gauss(x,mean,sigma) for x,mean,sigma in zip(xs,means,std)] assert ovl(pdfs[0],pdfs_ref[0])>0.99 assert ovl(pdfs[1],pdfs_ref[1])>0.99
def test_extrapenalty(): # ====================================================================== "Check that custom penalties can be passed and act on the solution" t = np.linspace(0, 3, 300) r = np.linspace(2, 5, 200) P = dd_gauss2(r, 3.5, 0.5, 0.5, 4, 0.1, 0.5) K = dipolarkernel(t, r) V = K @ P + whitegaussnoise(t, 0.15, seed=1) par0 = [2.5, 0.01, 0.1, 4.5, 0.01, 0.6] lb = [1, 0.01, 0, 1, 0.01, 0] ub = [20, 1, 1, 20, 1, 1] # Fit case it fails, stuck at "spicky" Gaussians model = lambda p: K @ dd_gauss2(r, *p) fit = snlls(V, model, par0, lb, ub) # Fit with Tikhonov penalty on the Gaussians model L = regoperator(r, 2) alpha = 1e-4 tikhonov = lambda p, _: alpha * L @ dd_gauss2(r, *p) fit_tikh = snlls(V, model, par0, lb, ub, extrapenalty=tikhonov) Pfit = dd_gauss2(r, *fit.nonlin) Pfit_tikh = dd_gauss2(r, *fit_tikh.nonlin) assert ovl(P, Pfit) < ovl(P, Pfit_tikh)
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_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 test_fit_weight_unbounded(): "Check fitting with a penalty with unbounded weight" model = deepcopy(dd_gauss) penaltyobj = Penalty(penalty_fcn,'icc') result = fit(model,mock_data,x,penalties=penaltyobj) assert not ovl(result.model,mock_data)>0.975
def test_fit_weight_bounded(): "Check fitting with a penalty with bounded weight" model = deepcopy(dd_gauss) penaltyobj = Penalty(penalty_fcn,'aicc') penaltyobj.weight.set(lb=1e-10,ub=1e1) result = fit(model,mock_data,x,penalties=penaltyobj) assert ovl(result.model,mock_data)>0.975
def test_fit_weight_frozen(): "Check fitting with a penalty with frozen weight" model = deepcopy(dd_gauss) penaltyobj = Penalty(penalty_fcn,'icc') penaltyobj.weight.freeze(0.00001) result = fit(model,mock_data,x,penalties=penaltyobj) assert ovl(result.model,mock_data)>0.975
def test_fit_icc(): "Check fitting with a penalty with ICC-selected weight" model = deepcopy(dd_gauss) penaltyobj = Penalty(penalty_fcn,'icc') penaltyobj.weight.set(lb=1e-6,ub=1e1) result = fit(model,mock_data,x,penalties=penaltyobj) assert ovl(result.model,mock_data)>0.975
def test_global_weights(): # ====================================================================== "Check that the global weights properly work when specified" t = np.linspace(0, 5, 300) r = np.linspace(2, 8, 150) K = dipolarkernel(t, r) param1 = [3, 0.2] param2 = [5, 0.2] P1 = dd_gauss(r, *param1) P2 = dd_gauss(r, *param2) V1 = K @ P1 + whitegaussnoise(t, 0.01, seed=1) V2 = K @ P2 + whitegaussnoise(t, 0.01, seed=1) fit1 = snlls([V1, V2], [K, K], lbl=np.zeros_like(r), weights=[1, 1e-10]) fit2 = snlls([V1, V2], [K, K], lbl=np.zeros_like(r), weights=[1e-10, 1]) assert ovl(P1, fit1.param) > 0.95 and ovl(P2, fit2.param) > 0.95
def test_fit_multiple_penalties(): "Check fitting with multiple penalties" model = deepcopy(dd_gauss) penaltyobj = Penalty(penalty_fcn,'icc') penaltyobj2 = deepcopy(penaltyobj) penaltyobj.weight.freeze(0.00001) penaltyobj2.weight.freeze(0.00001) result = fit(model,mock_data,x,penalties=[penaltyobj,penaltyobj2]) assert ovl(result.model,mock_data)>0.975
def assert_solver(solver): #============================================================ np.random.seed(1) t = np.linspace(-2, 4, 300) r = np.linspace(2, 6, 100) P = dd_gauss(r, 3, 0.2) K = dipolarkernel(t, r) V = K @ P + whitegaussnoise(t, 0.01) fit = snlls(V, K, lbl=np.zeros_like(r), nnlsSolver=solver, uq=False) assert ovl(P, fit.param) > 0.95 # more than 95% overlap
def test_convergence_criteria(): #============================================================ "Check that convergence criteria can be specified without crashing" t = np.linspace(0, 3, 200) r = np.linspace(1, 5, 100) P = dd_gauss(r, 3, 0.08) K = dipolarkernel(t, r) V = K @ P fit = snlls(V, K, lin_tol=1e-9, lin_maxiter=2e3, lbl=np.zeros_like(r)) assert ovl(P, fit.param) > 0.90 # more than 80% overlap
def test_global_weights(): # ====================================================================== "Check that the global weights properly work when specified" t = np.linspace(-0.3, 5, 300) r = np.linspace(2, 6, 150) P1 = dd_gauss(r, 3, 0.2) P2 = dd_gauss(r, 5, 0.2) K = dipolarkernel(t, r, mod=0.2) scales = [1e3, 1e9] sigma1 = 0.001 V1 = K @ P1 + whitegaussnoise(t, sigma1, seed=1) sigma2 = 0.001 V2 = K @ P2 + whitegaussnoise(t, sigma2, seed=1) V1 = scales[0] * V1 V2 = scales[1] * V2 Kmodel = lambda lam: [dipolarkernel(t, r, mod=lam)] * 2 fit1 = snlls([V1, V2], Kmodel, par0=[0.2], lb=0, ub=1, lbl=np.zeros_like(r), weights=[1, 1e-10]) fit2 = snlls([V1, V2], Kmodel, par0=[0.2], lb=0, ub=1, lbl=np.zeros_like(r), weights=[1e-10, 1]) assert ovl(P1, fit1.lin) > 0.93 and ovl(P2, fit2.lin) > 0.93
def test_tikh_with_noise(): #============================================================ "Check the Tikhonov regularization method with noise" np.random.seed(1) t = np.linspace(0, 3, 200) r = np.linspace(1, 5, 100) P = dd_gauss(r, 3, 0.08) K = dipolarkernel(t, r) V = K @ P + whitegaussnoise(t, 0.01) fit = snlls(V, K, lbl=np.zeros_like(r)) assert ovl(P, fit.param) > 0.95 # more than 95% overlap
def test_unconstrained(): #============================================================ "Check that unconstrained distributions are correctly fitted" t = np.linspace(-2, 4, 300) r = np.linspace(2, 6, 200) P = dd_gauss(r, 3, 0.2) K = dipolarkernel(t, r) L = regoperator(np.arange(len(r)), 2) V = K @ P fit = snlls(V, K, regparam=0.2) Pfit_ref = np.linalg.solve(K.T @ K + 0.2**2 * L.T @ L, K.T @ V) assert ovl(Pfit_ref, fit.param) > 0.99 # more than 99% overlap
def test_global_weights_default(): # ====================================================================== "Check the correct fit of two signals when one is of very low quality" t = np.linspace(0, 5, 300) r = np.linspace(2, 6, 90) P = dd_gauss(r, 4.5, 0.25) K = dipolarkernel(t, r) scales = [1e3, 1e3] V1 = scales[0] * K @ P + whitegaussnoise(t, 0.001, seed=1) V2 = scales[1] * K @ P + whitegaussnoise(t, 0.1, seed=1) fit = snlls([V1, V2], [K, K], lbl=np.zeros_like(r)) assert ovl(P, fit.param) > 0.95
def test_global_weights_default(): # ====================================================================== "Check the correct fit of two signals when one is of very low quality" t = np.linspace(0, 5, 300) r = np.linspace(2, 6, 90) param = [4.5, 0.25] P = dd_gauss(r, *param) K = dipolarkernel(t, r, mod=0.2) scales = [1e3, 1e9] V1 = scales[0] * (K @ P + whitegaussnoise(t, 0.001, seed=1)) V2 = scales[1] * (K @ P + whitegaussnoise(t, 0.1, seed=1)) Kmodel = lambda lam: [dipolarkernel(t, r, mod=lam)] * 2 fit = snlls([V1, V2], Kmodel, par0=[0.2], lb=0, ub=1, lbl=np.zeros_like(r)) assert ovl(P, fit.lin) > 0.93
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
def test_extrapenalty(): # ====================================================================== "Check that an additional penalty can be passed correctly" t = np.linspace(0, 5, 300) r = np.linspace(2, 6, 90) P = dd_gauss(r, 4.5, 0.25) K = dipolarkernel(t, r, mod=0.2) V = K @ P + whitegaussnoise(t, 0.001, seed=1) dr = np.mean(np.diff(r)) beta = 0.05 compactness_penalty = lambda _, plin: beta * np.sqrt(plin * (r - np.trapz( plin * r, r))**2 * dr) Kmodel = lambda lam: dipolarkernel(t, r, mod=lam) fit = snlls(V, Kmodel, par0=0.2, lb=0, ub=1, lbl=np.zeros_like(r), extrapenalty=compactness_penalty) assert ovl(P, fit.lin) > 0.95