示例#1
0
def compare_analytical_derivative(n, nonuniform=False):
    #=======================================================================

    if nonuniform:
        r = np.linspace(0, 4.5**9, 2500)**(1 / 9)
    else:
        r = np.linspace(2, 5, 2500)
    dr = np.mean(np.diff(r))

    # Distance axis for the derivative
    if n == 0:
        rn = r
    elif n == 1:
        rn = r - dr / 2
    elif n == 2:
        rn = r
    elif n == 3:
        rn = r - dr / 2

    # Test function
    sig = 0.2
    rmean = 3.5
    P = 1 / sig / np.sqrt(2 * pi) * np.exp(-(r - rmean)**2 / 2 / sig**2)

    # Analytical derivatives of the Gaussian function
    if n == 0:
        dPnref = P
    elif n == 1:
        dPnref = -(rn - rmean) / sig**3 / np.sqrt(2 * pi) * np.exp(
            -(rn - rmean)**2 / 2 / sig**2)
    elif n == 2:
        dPnref = -(sig**2 - (rn - rmean)**2) / sig**5 / np.sqrt(
            2 * pi) * np.exp(-(rn - rmean)**2 / 2 / sig**2)
    elif n == 3:
        dPnref = -((rn - rmean)**3 - 3 *
                   ((rn - rmean)) * sig**2) / sig**7 / np.sqrt(
                       2 * pi) * np.exp(-(rn - rmean)**2 / 2 / sig**2)

    # Numerical finite-difference operators
    Ln = regoperator(r, n, includeedges=True)

    # Estimated derivatives of the Gaussian function
    dPn = Ln @ P

    if nonuniform:
        dPn = dPn[:-1]
        dPnref = dPnref[:-1]

    if nonuniform and n == 0:
        accuracy = 1e-5
    elif nonuniform and n == 1:
        accuracy = 5e-2
    elif nonuniform and n == 2:
        accuracy = 5e-1
    elif nonuniform and n == 3:
        accuracy = 5e-0
    else:
        accuracy = 10**(-5 + n)

    assert max(abs(dPn - dPnref)) < accuracy
示例#2
0
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)
示例#3
0
def assert_full_output(method):

    t = np.linspace(0, 5, 80)
    r = np.linspace(2, 5, 80)
    P = dd_gauss(r, 3, 0.4)
    K = dipolarkernel(t, r)
    L = regoperator(r, 2)
    V = K @ P

    alpha, alphas_evaled, functional, residuals, penalties = selregparam(
        V,
        K,
        cvxnnls,
        method='aic',
        algorithm=method,
        full_output=True,
        regop=L)
    errors = []
    if np.size(alpha) != 1:
        errors.append("alphaopt is not a scalar")
    if len(functional) != len(alphas_evaled):
        errors.append(
            "The number of elements of functional values and evaluated alphas are different."
        )
    if len(residuals) != len(penalties):
        errors.append(
            "The number of elements of evluated residuals and penalties are different"
        )
    if not alpha in alphas_evaled:
        errors.append("The optimal alpha is not part of the evaluated alphas")
    assert not errors, f"Errors occured:\n{chr(10).join(errors)}"
示例#4
0
def test_algorithms():
    #=======================================================================
    "Check that the value returned by the the grid and Brent algorithms coincide"

    t = np.linspace(0, 5, 80)
    r = np.linspace(2, 5, 80)
    P = dd_gauss(r, 3, 0.2)
    K = dipolarkernel(t, r)
    L = regoperator(r, 2)
    V = K @ P + whitegaussnoise(t, 0.02, seed=1)

    alpha_grid = selregparam(V,
                             K,
                             cvxnnls,
                             method='aic',
                             algorithm='grid',
                             regop=L)
    alpha_brent = selregparam(V,
                              K,
                              cvxnnls,
                              method='aic',
                              algorithm='brent',
                              regop=L)

    assert abs(1 - alpha_grid / alpha_brent) < 0.15
示例#5
0
def _prepare_linear_lsq(A, lb, ub, reg, L, tol, maxiter, nnlsSolver):
    """
    Preparation of linear least-squares 
    ===================================

    Evaluates the conditions of the linear least-squares problem and determines:
    - whether regularization is required
    - the type of boundary constraints
    - optimal linear least-squares solver to use
    """
    Nlin = np.shape(A)[1]

    # Determine whether to use regularization penalty
    if reg == 'auto':
        illConditioned = np.linalg.cond(A) > 10
        includeRegularization = illConditioned
    else:
        includeRegularization = reg

    # Check if the nonlinear and linear problems are constrained
    linearConstrained = (not np.all(np.isinf(lb))) or (not np.all(
        np.isinf(ub)))
    # Check for non-negativity constraints on the linear solution
    nonNegativeOnly = (np.all(lb == 0)) and (np.all(np.isinf(ub)))

    # Use an arbitrary axis
    axis = np.arange(Nlin)
    if L is None and includeRegularization:
        d = np.minimum(2, len(axis))
        L = dl.regoperator(axis, d)

    # Prepare the linear solver
    # ----------------------------------------------------------
    if not linearConstrained:
        # Unconstrained linear LSQ
        linSolver = np.linalg.solve
        parseResult = lambda result: result

    elif linearConstrained and not nonNegativeOnly:
        # Constrained linear LSQ
        linSolver = lambda AtA, Aty: lsq_linear(
            AtA, Aty, bounds=(lb, ub), method='bvls')
        parseResult = lambda result: result.x

    elif linearConstrained and nonNegativeOnly:
        # Non-negative linear LSQ
        if nnlsSolver == 'fnnls':
            linSolver = lambda AtA, Aty: fnnls(
                AtA, Aty, tol=tol, maxiter=maxiter)
        elif nnlsSolver == 'cvx':
            linSolver = lambda AtA, Aty: cvxnnls(
                AtA, Aty, tol=tol, maxiter=maxiter)
        parseResult = lambda result: result

    # Ensure correct formatting and shield against float-point errors
    validateResult = lambda result: np.maximum(
        lb, np.minimum(ub, np.atleast_1d(result)))
    # ----------------------------------------------------------
    return axis, L, linSolver, parseResult, validateResult, includeRegularization
示例#6
0
def test_L2shape_noedges():
    #=======================================================================
    "Check that L2 is returned with correct size if edges are excluded"

    n = 100
    r = np.linspace(2, 6, n)
    L = regoperator(r, 2, includeedges=False)

    assert L.shape == (n - 2, n)
示例#7
0
def test_L0shape():
    #=======================================================================
    "Check that L0 is returned with correct size"

    n = 100
    r = np.linspace(2, 6, n)
    L = regoperator(r, 0)

    assert L.shape == (n, n)
示例#8
0
def test_L2shape():
    #=======================================================================
    "Check that L2 is returned with correct size"

    n = 100
    r = np.linspace(2, 6, n)
    L = regoperator(r, 2, includeedges=True)

    assert L.shape == (n, n)
示例#9
0
def test_edge_smoothing():
    #=======================================================================
    "Check that L applies to edges and is NxN"

    r = np.arange(5)
    n = len(r)
    L = regoperator(r, 2, includeedges=True)
    Lref = (np.eye(n, n) * (-2) + np.eye(n, n, k=-1) + np.eye(n, n, k=1))

    assert np.max(np.abs(L - Lref)) < 1e-10
示例#10
0
def get_alpha_from_method(method):

    t = np.linspace(0, 5, 500)
    r = np.linspace(2, 5, 80)
    P = dd_gauss(r, 3.0, 0.16986436005760383)
    K = dipolarkernel(t, r)
    L = regoperator(r, 2, includeedges=True)
    V = K @ P

    alpha = selregparam(V, K, cvxnnls, method=method, noiselvl=0, regop=L)
    return np.log10(alpha)
示例#11
0
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
示例#12
0
def test_nonuniform_r():
    #=======================================================================
    "Check the value returned when using a non-uniform distance axis"

    t = np.linspace(0, 3, 200)
    r = np.sqrt(np.linspace(1, 7**2, 200))
    P = dd_gauss(r, 3, 0.2)
    K = dipolarkernel(t, r)
    L = regoperator(r, 2)
    V = K @ P

    logalpha = np.log10(selregparam(V, K, cvxnnls, method='aic', regop=L))
    logalpharef = -6.8517

    assert abs(1 - logalpha / logalpharef) < 0.2
示例#13
0
def test_unconstrained():
    #=======================================================================
    "Check the algorithm works with unconstrained disributions"

    t = np.linspace(0, 5, 80)
    r = np.linspace(2, 5, 80)
    P = dd_gauss(r, 3, 0.15)
    K = dipolarkernel(t, r)
    L = regoperator(r, 2, includeedges=True)
    V = K @ P

    logalpha = np.log10(
        selregparam(V, K, np.linalg.solve, method='aic', regop=L))
    logalpharef = -8.87

    assert abs(1 - logalpha / logalpharef) < 0.1
示例#14
0
def test_tikh_value():
    #=======================================================================
    "Check that the value returned by Tikhonov regularization"

    np.random.seed(1)
    t = np.linspace(0, 5, 500)
    r = np.linspace(2, 5, 80)
    P = dd_gauss(r, 3, 0.15)
    K = dipolarkernel(t, r)
    V = K @ P + whitegaussnoise(t, 0.01)
    L = regoperator(r, 2, includeedges=True)

    alpha = selregparam(V, K, cvxnnls, method='aic', regop=L)
    loga = np.log10(alpha)
    logaref = -3.51  # Computed with DeerLab-Matlab (0.9.2)

    assert abs(1 - loga / logaref) < 0.02  # less than 2% error
示例#15
0
def test_manual_candidates():
    #=======================================================================
    "Check that the alpha-search range can be manually passed"

    t = np.linspace(0, 5, 80)
    r = np.linspace(2, 5, 80)
    P = dd_gauss(r, 3, 0.15)
    K = dipolarkernel(t, r)
    L = regoperator(r, 2, includeedges=True)
    alphas = np.linspace(-8, 2, 60)
    V = K @ P

    alpha_manual = np.log10(
        selregparam(V, K, cvxnnls, method='aic', candidates=alphas, regop=L))
    alpha_auto = np.log10(selregparam(V, K, cvxnnls, method='aic', regop=L))

    assert abs(alpha_manual - alpha_auto) < 1e-4