예제 #1
0
def test_interpolation_inversion():
    m = odijk("Nucleosome").invert(independent_max=120.0, interpolate=True)
    parvec = [5.77336105517341, 7.014180463612673, 1500.0000064812095, 4.11]
    result = np.array(
        [0.17843862, 0.18101283, 0.18364313, 0.18633117, 0.18907864])
    np.testing.assert_allclose(
        m._raw_call(np.arange(10, 250, 50) / 1000, parvec), result)
예제 #2
0
def test_fd_variable_order():
    # Fit takes dependent, then independent
    m = odijk("M")
    fit = Fit(m)
    fit._add_data("test", [1, 2, 3], [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test"].x, [1, 2, 3])
    np.testing.assert_allclose(fit[m].data["test"].y, [2, 3, 4])

    fit[m]._add_data("test2", [1, 2, 3], [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test2"].x, [1, 2, 3])
    np.testing.assert_allclose(fit[m].data["test2"].y, [2, 3, 4])

    m = inverted_odijk("M")
    fit = Fit(m)
    fit._add_data("test", [1, 2, 3], [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test"].x, [1, 2, 3])
    np.testing.assert_allclose(fit[m].data["test"].y, [2, 3, 4])

    fit[m]._add_data("test2", [1, 2, 3], [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test2"].x, [1, 2, 3])
    np.testing.assert_allclose(fit[m].data["test2"].y, [2, 3, 4])

    # FdFit always takes f, d and maps it to the correct values
    m = odijk("M")
    fit = FdFit(m)

    # Test the FdFit interface
    fit.add_data("test", [1, 2, 3], [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test"].x, [1, 2, 3])
    np.testing.assert_allclose(fit[m].data["test"].y, [2, 3, 4])

    # Test the FdDatasets interface
    fit[m].add_data("test2", [3, 4, 5], [4, 5, 6])
    np.testing.assert_allclose(fit[m].data["test2"].x, [3, 4, 5])
    np.testing.assert_allclose(fit[m].data["test2"].y, [4, 5, 6])

    m = inverted_odijk("M")
    fit = FdFit(m)
    fit.add_data("test", [1, 2, 3], [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test"].x, [2, 3, 4])
    np.testing.assert_allclose(fit[m].data["test"].y, [1, 2, 3])

    # Test the FdDatasets interface
    fit[m].add_data("test2", [3, 4, 5], [4, 5, 6])
    np.testing.assert_allclose(fit[m].data["test2"].x, [4, 5, 6])
    np.testing.assert_allclose(fit[m].data["test2"].y, [3, 4, 5])
예제 #3
0
def test_custom_legend_labels():
    """Test whether users can provide a custom label for plotting"""
    def test_labels(labels):
        for legend_entry, label in zip(plt.gca().get_legend().texts, labels):
            assert label == legend_entry.get_text()

    fit = Fit(odijk("m"))
    fit._add_data("data_1", [1, 2, 3], [2, 3, 4])
    fit.plot()
    test_labels(["data_1 (model)", "data_1 (data)"])
    plt.gca().clear()
    fit.plot(label="custom label")
    test_labels(["custom label (model)", "custom label (data)"])
예제 #4
0
def test_jacobian_test_fit():
    def f(independent, a, b):
        return a + b * independent

    def f_jac(independent, a, b):
        del a, b
        return np.vstack((np.ones((1, len(independent))), independent))

    def f_der(independent, a, b):
        del a
        return b * np.ones((len(independent)))

    def f_jac_wrong(independent, a, b):
        del a, b
        return np.vstack((2.0 * np.ones((1, len(independent))), independent))

    x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
    a_true, b_true = (5.0, 5.0)
    f_data = f(x, a_true, b_true)
    model = Model("f", f, jacobian=f_jac, derivative=f_der)
    fit = Fit(model)
    fit._add_data("test", x, f_data)
    fit.params["f/a"].value = a_true
    fit.params["f/b"].value = b_true
    assert fit.verify_jacobian(fit.params.values)

    model_bad = Model("f", f, jacobian=f_jac_wrong, derivative=f_der)
    fit = Fit(model_bad)
    fit._add_data("test", x, f_data)
    fit.params["f/a"].value = a_true
    fit.params["f/b"].value = b_true
    assert not fit.verify_jacobian(fit.params.values)

    with pytest.raises(ValueError):
        assert odijk("WLC").verify_jacobian([1.0, 2.0, 3.0], [1.0, 2.0])

    with pytest.raises(ValueError):
        odijk("WLC").verify_derivative([1, 2, 3], [1, 2, 3])
예제 #5
0
def test_fit_reprs():
    m = odijk("DNA")
    fit = Fit(m)
    d1 = fit._add_data("data_1", [1, 2, 3], [2, 3, 4])
    assert d1.__repr__() == "FitData(data_1, N=3)"

    d2 = fit._add_data("dataset_2", [1, 2, 3], [2, 3, 4],
                       {"DNA/Lc": "DNA/Lc_2"})
    assert d2.__repr__(
    ) == "FitData(dataset_2, N=3, Transformations: DNA/Lc → DNA/Lc_2)"

    f = Fit(m)
    assert f.__repr__()
    assert f._repr_html_()

    fit._add_data("data_3", [1, 2, 3], [2, 3, 4], {"DNA/Lc": 5})
    assert fit.__repr__()
    assert fit._repr_html_()

    m = inverted_odijk("DNA")
    fit = FdFit(m)
    fit._add_data("RecA", [1, 2, 3], [1, 2, 3])
    fit._add_data("RecA2", [1, 2, 3], [1, 2, 3])
    fit._add_data("RecA3", [1, 2, 3], [1, 2, 3])

    assert fit[m].__repr__(
    ) == "lumicks.pylake.FdDatasets(datasets={RecA, RecA2, RecA3}, N=9)"
    assert (
        fit[m].__str__() ==
        "Data sets:\n- FitData(RecA, N=3)\n- FitData(RecA2, N=3)\n- FitData(RecA3, N=3)\n"
    )
    assert fit[m]._repr_html_() == ("&ensp;&ensp;FitData(RecA, N=3)<br>\n"
                                    "&ensp;&ensp;FitData(RecA2, N=3)<br>\n"
                                    "&ensp;&ensp;FitData(RecA3, N=3)<br>\n")

    assert fit.__repr__() == "lumicks.pylake.FdFit(models={DNA}, N=9)"
    assert fit.__str__() == (
        "Fit\n  - Model: DNA\n  - Equation:\n"
        "      f(d) = argmin[f](norm(DNA.Lc * (1 - (1/2)*sqrt(kT/(f*DNA.Lp)) + f/DNA.St)-d))\n\n"
        "  - Data sets:\n    - FitData(RecA, N=3)\n    - FitData(RecA2, N=3)\n    "
        "- FitData(RecA3, N=3)\n\n  "
        "- Fitted parameters:\n"
        "    Name      Value  Unit      Fitted      Lower bound    Upper bound\n"
        "    ------  -------  --------  --------  -------------  -------------\n"
        "    DNA/Lp    40     [nm]      True                  0            100\n"
        "    DNA/Lc    16     [micron]  True                  0            inf\n"
        "    DNA/St  1500     [pN]      True                  0            inf\n"
        "    kT         4.11  [pN*nm]   False                 0              8"
    )
예제 #6
0
def test_simulation_api():
    dna = odijk("DNA")
    force = [0.1, 0.2, 0.3]
    np.testing.assert_allclose(
        dna(force, {"DNA/Lp": 50.0, "DNA/Lc": 16.0, "DNA/St": 1500.0, "kT": 4.11}),
        [8.74792941, 10.8733908, 11.81559925],
    )

    np.testing.assert_allclose(
        dna(
            [0.1, 0.2, 0.3],
            Params(
                **{
                    "DNA/Lp": Parameter(50.0),
                    "DNA/Lc": Parameter(16.0),
                    "DNA/St": Parameter(1500.0),
                    "kT": Parameter(4.11),
                }
            ),
        ),
        [8.74792941, 10.8733908, 11.81559925],
    )
예제 #7
0
def test_simulation_api_wrong_par():
    dna = odijk("DNA")

    with pytest.raises(KeyError):
        dna([1], {"DNA/Lp": 50.0, "DNA/Lc": 16.0, "DN/St": 1500.0, "kT": 4.11})
예제 #8
0
def test_plotting():
    m = odijk("DNA")
    m2 = odijk("protein")

    # Test single model plotting
    fit = Fit(m)
    fit[m]._add_data("data_1", [1, 2, 3], [2, 3, 4])
    fit.plot()
    fit.plot("data_1")
    with pytest.raises(AssertionError):
        fit.plot("non-existent-data")

    fit.plot(overrides={"DNA/Lc": 12})
    with pytest.raises(KeyError):
        fit.plot(overrides={"DNA/c": 12})

    fit.plot(overrides={"DNA/Lc": 12}, independent=np.arange(1.0, 5.0, 1.0))

    with pytest.raises(KeyError):
        fit[m2].plot()

    # Test multi-model plotting
    fit = Fit(m, m2)
    fit[m]._add_data("data_1", [1, 2, 3], [2, 3, 4])
    fit[m]._add_data("dataset_2", [1, 2, 3], [2, 3, 4], {"DNA/Lc": "DNA/Lc_2"})
    fit[m2]._add_data("data_1", [1, 2, 3], [2, 3, 4])
    fit[m2]._add_data("dataset_2", [1, 2, 3], [2, 3, 4],
                      {"protein/Lc": "protein/Lc_2"})
    fit[m2]._add_data("dataset 3", [1, 2, 3], [2, 3, 4],
                      {"protein/Lc": "protein/Lc_2"})

    with pytest.raises(AssertionError):
        fit.plot()

    fit[m].plot()
    fit[m2].plot()
    fit[m].plot("data_1")

    with pytest.raises(AssertionError):
        fit.plot(m, "non-existent-data")

    fit[m2].plot("dataset 3")
    with pytest.raises(AssertionError):
        fit[m].plot("dataset 3")

    fit[m].plot(overrides={"DNA/Lc": 12})
    with pytest.raises(KeyError):
        fit[m].plot(overrides={"DNA/c": 12})

    independent = np.arange(0.15, 2, 0.25)
    params = [38.18281266, 0.37704827, 278.50103452, 4.11]
    odijk("WLC").verify_jacobian(independent, params, plot=1)

    params = [38.18281266, 0.37704827, 278.50103452, 4.11]
    fit = FdFit(odijk("WLC"))
    fit.add_data("dataset 3", [1, 2, 3], [2, 3, 4])
    plt.figure()
    fit.verify_jacobian(params, plot=1)

    # Test live fit plotting
    fit = Fit(m, m2)
    fit[m]._add_data("data_1", [1, 2, 3], [2, 3, 4])
    fit[m]._add_data("dataset_2", [1, 2, 3], [2, 3, 4], {"DNA/Lc": "DNA/Lc_2"})
    fit[m2]._add_data("data_1", [1, 2, 3], [2, 3, 4])
    fit.fit(show_fit=True, max_nfev=1)
예제 #9
0
def test_model_composition():
    def f(x, a, b):
        return a + b * x

    def f_jac(x, a, b):
        return np.vstack((np.ones((1, len(x))), x))

    def f_jac_wrong(x, a, b):
        return np.vstack((np.zeros((1, len(x))), x))

    def g(x, a, d, b):
        return a - b * x + d * x * x

    def g_jac(x, a, d, b):
        return np.vstack((np.ones((1, len(x))), x * x, -x))

    def f_der(x, a, b):
        return b * np.ones((len(x)))

    def f_der_wrong(x, a, b):
        return np.ones((len(x)))

    def g_der(x, a, d, b):
        return -b * np.ones((len(x))) + 2.0 * d * x

    m1 = Model("M", f, dependent="x", jacobian=f_jac, derivative=f_der)
    m2 = Model("M", g, dependent="x", jacobian=g_jac, derivative=g_der)
    t = np.arange(0, 2, 0.5)

    # Check actual composition
    # (a + b * x) + a - b * x + d * x * x = 2 * a + d * x * x
    np.testing.assert_allclose(
        (m1 + m2)._raw_call(t, np.array([1.0, 2.0, 3.0])), 2.0 + 3.0 * t * t
    ), "Model composition returns invalid function evaluation (parameter order issue?)"

    # Check correctness of the Jacobians and derivatives
    assert (m1 + m2).verify_jacobian(t, [1.0, 2.0, 3.0])
    assert (m1 + m2).verify_derivative(t, [1.0, 2.0, 3.0])
    assert (m2 + m1).verify_jacobian(t, [1.0, 2.0, 3.0])
    assert (m2 + m1).verify_derivative(t, [1.0, 2.0, 3.0])
    assert (m2 + m1 + m2).verify_jacobian(t, [1.0, 2.0, 3.0])
    assert (m2 + m1 + m2).verify_derivative(t, [1.0, 2.0, 3.0])

    m1_wrong_jacobian = Model("M",
                              f,
                              dependent="x",
                              jacobian=f_jac_wrong,
                              derivative=f_der)
    assert not (m1_wrong_jacobian + m2).verify_jacobian(t, [1.0, 2.0, 3.0],
                                                        verbose=False)
    assert not (m2 + m1_wrong_jacobian).verify_jacobian(t, [1.0, 2.0, 3.0],
                                                        verbose=False)

    assert (InverseModel(m1) + m2).verify_jacobian(t, [-1.0, 2.0, 3.0],
                                                   verbose=False)
    assert InverseModel(m1 + m2).verify_jacobian(t, [-1.0, 2.0, 3.0],
                                                 verbose=False)
    assert InverseModel(m1 + m2 + m1).verify_jacobian(t, [-1.0, 2.0, 3.0],
                                                      verbose=False)

    assert (InverseModel(m1) + m2).verify_derivative(t, [-1.0, 2.0, 3.0])
    assert InverseModel(m1 + m2).verify_derivative(t, [-1.0, 2.0, 3.0])
    assert InverseModel(m1 + m2 + m1).verify_derivative(t, [-1.0, 2.0, 3.0])

    m1_wrong_derivative = Model("M",
                                f,
                                dependent="x",
                                jacobian=f_jac,
                                derivative=f_der_wrong)
    assert not (InverseModel(m1_wrong_derivative) + m2).verify_jacobian(
        t, [-1.0, 2.0, 3.0], verbose=False)
    assert not (InverseModel(m1_wrong_jacobian) + m2).verify_jacobian(
        t, [-1.0, 2.0, 3.0], verbose=False)
    assert not (InverseModel(m1_wrong_derivative) + m2).verify_derivative(
        t, [-1.0, 2.0, 3.0])

    assert m1.subtract_independent_offset().verify_jacobian(t,
                                                            [-1.0, 2.0, 3.0],
                                                            verbose=False)
    assert m1.subtract_independent_offset().verify_derivative(
        t, [-1.0, 2.0, 3.0])

    m1 = inverted_odijk("DNA").subtract_independent_offset() + force_offset(
        "f")
    m2 = (odijk("DNA") + distance_offset("DNA_d")).invert() + force_offset("f")
    t = np.array([0.19, 0.2, 0.3])
    p1 = np.array([0.1, 4.9e1, 3.8e-1, 2.1e2, 4.11, 1.5])
    p2 = np.array([4.9e1, 3.8e-1, 2.1e2, 4.11, 0.1, 1.5])
    np.testing.assert_allclose(m1._raw_call(t, p1), m2._raw_call(t, p2))

    # Check whether incompatible variables are found
    with pytest.raises(AssertionError):
        distance_offset("d") + force_offset("f")

    composite = distance_offset("d") + odijk("DNA")
    assert composite.dependent == "d"
    assert composite.independent == "f"
    assert composite._dependent_unit == "micron"
    assert composite._independent_unit == "pN"

    inverted = composite.invert()
    assert inverted.dependent == "f"
    assert inverted.independent == "d"
    assert inverted._dependent_unit == "pN"
    assert inverted._independent_unit == "micron"
예제 #10
0
    assert composite.dependent == "d"
    assert composite.independent == "f"
    assert composite._dependent_unit == "micron"
    assert composite._independent_unit == "pN"

    inverted = composite.invert()
    assert inverted.dependent == "f"
    assert inverted.independent == "d"
    assert inverted._dependent_unit == "pN"
    assert inverted._independent_unit == "micron"


@pytest.mark.parametrize(
    "model,param,unit",
    [
        (odijk("m").subtract_independent_offset(), "m/f_offset", "pN"),
        (inverted_odijk("m").subtract_independent_offset(), "m/d_offset",
         "micron"),
        ((odijk("m") + odijk("m")).subtract_independent_offset(),
         "m_with_m/f_offset", "pN"),
        (odijk("m").invert().subtract_independent_offset(), "inv(m)/d_offset",
         "micron"),
        (Model("m", lambda c, a: c + a).subtract_independent_offset(),
         "m/c_offset", "au"),
        (
            Model("m",
                  lambda c, a: c + a).invert().subtract_independent_offset(),
            "inv(m)/y_offset",
            "au",
        ),
    ],