Example #1
0
def test_interpolations(
        xs, ys, interpolation, k
):  # noqa: C901; the method is not complex, it's just a long switch case
    # pylint: disable=too-many-branches
    """Tests the functionality of the interpolation functions."""
    xs = sorted(xs)
    bands = sumpf.Bands(bands=dict(zip(xs, ys)), interpolations=interpolation)
    x = xs[0] + k * (xs[1] - xs[0])
    if x == xs[0]:
        assert bands(x)[0] == ys[0]
    elif x == xs[1]:
        assert bands(x)[0] == ys[1]
    else:
        if interpolation is sumpf.Bands.interpolations.ZERO:
            assert bands(x)[0] == 0.0
        elif interpolation is sumpf.Bands.interpolations.ONE:
            assert bands(x)[0] == 1.0
        elif interpolation is sumpf.Bands.interpolations.LINEAR:
            assert bands(x)[0] == pytest.approx(numpy.interp(x, xs, ys))
        elif interpolation is sumpf.Bands.interpolations.LOGARITHMIC:
            bands = sumpf.Bands(bands={x: abs(y)
                                       for x, y in zip(xs, ys)},
                                interpolations=interpolation)
            log_xs = numpy.log2(xs)
            log_ys = numpy.log(numpy.abs(ys))
            assert bands(x)[0] == pytest.approx(numpy.exp(
                numpy.interp(numpy.log2(x), log_xs, log_ys)),
                                                nan_ok=True)
        elif interpolation is sumpf.Bands.interpolations.LOG_X:
            log_xs = numpy.log2(xs)
            assert bands(x)[0] == pytest.approx(numpy.interp(
                numpy.log2(x), log_xs, ys),
                                                nan_ok=True)
        elif interpolation is sumpf.Bands.interpolations.LOG_Y:
            bands = sumpf.Bands(bands={x: abs(y)
                                       for x, y in zip(xs, ys)},
                                interpolations=interpolation)
            log_ys = numpy.log(numpy.abs(ys))
            assert bands(x)[0] == pytest.approx(numpy.exp(
                numpy.interp(x, xs, log_ys)),
                                                nan_ok=True)
        elif interpolation is sumpf.Bands.interpolations.STAIRS_LIN:
            if k < 0.5:
                assert bands(x)[0] == ys[0]
            else:
                assert bands(x)[0] == ys[1]
        elif interpolation is sumpf.Bands.interpolations.STAIRS_LOG:
            if numpy.log(x) - numpy.log(xs[0]) < numpy.log(
                    xs[1]) - numpy.log(x):
                assert bands(x)[0] == ys[0]
            else:
                assert bands(x)[0] == ys[1]
        else:
            raise ValueError(f"Unknown interpolation: {interpolation}.")
Example #2
0
def test_interpolation(
    interpolation, xs, ys, k
):  # noqa: C901; the function is not complex, it's just a long switch case
    # pylint: disable=too-many-branches
    """Tests the computation of an interpolated value."""
    func = sumpf_internal.interpolation.get(interpolation)
    xs = numpy.array(sorted(xs))
    if interpolation in (sumpf_internal.Interpolations.LOGARITHMIC,
                         sumpf_internal.Interpolations.LOG_X,
                         sumpf_internal.Interpolations.STAIRS_LOG) and \
       min(xs) < 0.0:
        xs -= min(xs)
    if interpolation in (sumpf_internal.Interpolations.LOGARITHMIC,
                         sumpf_internal.Interpolations.LOG_Y):
        ys = numpy.abs(ys)
    x = xs[0] + k * (xs[1] - xs[0])
    hypothesis.assume(
        x not in xs
    )  # due to the limited precision of floating point numbers, this can still happen
    if interpolation is sumpf_internal.Interpolations.ZERO:
        assert func(x, xs, ys) == 0.0
    elif interpolation is sumpf_internal.Interpolations.ONE:
        assert func(x, xs, ys) == 1.0
    elif interpolation is sumpf_internal.Interpolations.LINEAR:
        assert func(x, xs, ys) == pytest.approx(numpy.interp(x, xs, ys))
    elif interpolation is sumpf_internal.Interpolations.LOGARITHMIC:
        log_xs = numpy.log2(xs)
        log_ys = numpy.log(numpy.abs(ys))
        assert func(x, xs, ys) == pytest.approx(numpy.exp(
            numpy.interp(numpy.log2(x), log_xs, log_ys)),
                                                nan_ok=True)
    elif interpolation is sumpf_internal.Interpolations.LOG_X:
        log_xs = numpy.log2(xs)
        assert func(x, xs, ys) == pytest.approx(
            numpy.interp(numpy.log2(x), log_xs, ys))
    elif interpolation is sumpf_internal.Interpolations.LOG_Y:
        log_ys = numpy.log(numpy.abs(ys))
        assert func(x, xs,
                    ys) == pytest.approx(numpy.exp(numpy.interp(x, xs,
                                                                log_ys)),
                                         nan_ok=True)
    elif interpolation is sumpf_internal.Interpolations.STAIRS_LIN:
        if k < 0.5:
            assert func(x, xs, ys) == ys[0]
        else:
            assert func(x, xs, ys) == ys[1]
    elif interpolation is sumpf_internal.Interpolations.STAIRS_LOG:
        if numpy.log(x) - numpy.log(xs[0]) < numpy.log(xs[1]) - numpy.log(x):
            assert func(x, xs, ys) == ys[0]
        else:
            assert func(x, xs, ys) == ys[1]
    else:
        raise ValueError(f"Unknown interpolation: {interpolation}.")
Example #3
0
def xs_ys(data, interpolation):
    """A helper function, that creates arrays of x and y values from the data pairs,
    that have been created by hypothesis.
    """
    if data:
        xs, ys = map(numpy.array, zip(*sorted(data)))
    else:
        xs = numpy.empty(0)
        ys = numpy.empty(0)
    if interpolation in (sumpf_internal.Interpolations.LOGARITHMIC,
                         sumpf_internal.Interpolations.LOG_X,
                         sumpf_internal.Interpolations.STAIRS_LOG):
        if (xs <= 0).any():
            xs -= xs.min()
            xs += 1e-15
    if interpolation in (sumpf_internal.Interpolations.LOGARITHMIC,
                         sumpf_internal.Interpolations.LOG_Y):
        ys = numpy.abs(ys) + 1e-15
    return xs, ys
Example #4
0
def test_extrapolation(
    xs, ys, interpolation, delta_x
):  # noqa: C901; the function is not complex, it's just a long switch case
    # pylint: disable=too-many-branches,too-many-statements
    """Tests the computation of an extrapolated value."""
    func = sumpf_internal.interpolation.get(interpolation)
    xs = numpy.array(sorted(xs))
    if interpolation in (sumpf_internal.Interpolations.LOGARITHMIC,
                         sumpf_internal.Interpolations.LOG_X,
                         sumpf_internal.Interpolations.STAIRS_LOG) and \
       min(xs) < 0.0:
        xs -= min(xs)
    if interpolation in (sumpf_internal.Interpolations.LOGARITHMIC,
                         sumpf_internal.Interpolations.LOG_Y):
        ys = numpy.abs(ys)
    x0 = xs[0] * (1.0 - delta_x) - delta_x
    x1 = xs[1] * (1.0 + delta_x) + delta_x
    if interpolation is sumpf_internal.Interpolations.ZERO:
        assert func(x0, xs, ys) == 0.0
        assert func(x1, xs, ys) == 0.0
    elif interpolation is sumpf_internal.Interpolations.ONE:
        assert func(x0, xs, ys) == 1.0
        assert func(x1, xs, ys) == 1.0
    elif interpolation is sumpf_internal.Interpolations.LINEAR:
        m = (ys[1] - ys[0]) / (xs[1] - xs[0])
        n0 = ys[0] - m * xs[0]
        n1 = ys[1] - m * xs[1]
        assert func(x0, xs, ys) == pytest.approx(m * x0 + n0)
        assert func(x1, xs, ys) == pytest.approx(m * x1 + n1)
    elif interpolation is sumpf_internal.Interpolations.LOGARITHMIC:
        if 0.0 in ys:
            assert numpy.isnan(func(x0, xs, ys))
            assert numpy.isnan(func(x1, xs, ys))
        else:
            log_xs = numpy.log2(xs)
            log_ys = numpy.log2(ys)
            m = (log_ys[1] - log_ys[0]) / (log_xs[1] - log_xs[0])
            r0 = numpy.exp2(m * numpy.log2(x0) + log_ys[0] - m * log_xs[0])
            r1 = numpy.exp2(m * numpy.log2(x1) + log_ys[1] - m * log_xs[1])
            assert (numpy.isnan(func(x0, xs, ys))
                    and numpy.isnan(r0)) or (func(x0, xs, ys)
                                             == pytest.approx(r0))
            assert (numpy.isnan(func(x1, xs, ys))
                    and numpy.isnan(r1)) or (func(x1, xs, ys)
                                             == pytest.approx(r1))
    elif interpolation is sumpf_internal.Interpolations.LOG_X:
        log_xs = numpy.log2(xs)
        m = (ys[1] - ys[0]) / (log_xs[1] - log_xs[0])
        r0 = m * numpy.log2(x0) + ys[0] - m * log_xs[0]
        r1 = m * numpy.log2(x1) + ys[1] - m * log_xs[1]
        assert (numpy.isnan(func(x0, xs, ys)) and numpy.isnan(r0)) or (func(
            x0, xs, ys) == pytest.approx(r0))
        assert (numpy.isnan(func(x1, xs, ys)) and numpy.isnan(r1)) or (func(
            x1, xs, ys) == pytest.approx(r1))
    elif interpolation is sumpf_internal.Interpolations.LOG_Y:
        if 0.0 in ys:
            assert numpy.isnan(func(x0, xs, ys))
            assert numpy.isnan(func(x1, xs, ys))
        else:
            log_ys = numpy.log2(ys)
            m = (log_ys[1] - log_ys[0]) / (xs[1] - xs[0])
            n0 = log_ys[0] - m * xs[0]
            n1 = log_ys[1] - m * xs[1]
            assert func(x0, xs, ys) == pytest.approx(numpy.exp2(m * x0 + n0))
            assert func(x1, xs, ys) == pytest.approx(numpy.exp2(m * x1 + n1))
    elif interpolation is sumpf_internal.Interpolations.STAIRS_LIN:
        assert func(x0, xs, ys) == ys[0]
        assert func(x1, xs, ys) == ys[1]
    elif interpolation is sumpf_internal.Interpolations.STAIRS_LOG:
        assert func(x0, xs, ys) == ys[0]
        assert func(x1, xs, ys) == ys[1]
    else:
        raise ValueError(f"Unknown interpolation: {interpolation}.")
Example #5
0
def test_extrapolations(xs, ys, extrapolation, delta_x):  # pylint: disable=too-many-statements
    """Tests the functionality of the extrapolation functions."""
    xs = sorted(xs)
    assert xs[1] - xs[0]
    bands = sumpf.Bands(bands=dict(zip(xs, ys)), extrapolations=extrapolation)
    if delta_x == 0.0:
        assert bands(xs[0])[0] == ys[0]
        assert bands(xs[1])[0] == ys[1]
    else:
        x0 = xs[0] - delta_x
        x1 = xs[1] + delta_x
        if extrapolation is sumpf.Bands.interpolations.ZERO:
            assert bands(x0)[0] == 0.0
            assert bands(x1)[0] == 0.0
        elif extrapolation is sumpf.Bands.interpolations.ONE:
            assert bands(x0)[0] == 1.0
            assert bands(x1)[0] == 1.0
        elif extrapolation is sumpf.Bands.interpolations.LINEAR:
            m = (ys[1] - ys[0]) / (xs[1] - xs[0])
            n0 = ys[0] - m * xs[0]
            n1 = ys[1] - m * xs[1]
            assert bands(x0)[0] == pytest.approx(m * x0 + n0)
            assert bands(x1)[0] == pytest.approx(m * x1 + n1)
        elif extrapolation is sumpf.Bands.interpolations.LOGARITHMIC:
            bands = sumpf.Bands(bands={x: abs(y)
                                       for x, y in zip(xs, ys)},
                                extrapolations=extrapolation)
            log_xs = numpy.log2(xs)
            log_ys = numpy.log2(numpy.abs(ys))
            m = (log_ys[1] - log_ys[0]) / (log_xs[1] - log_xs[0])
            n0 = log_ys[0] - m * log_xs[0]
            n1 = log_ys[1] - m * log_xs[1]
            r0 = n0 + log_ys[0] - m * log_xs[0]
            r1 = n1 + log_ys[1] - m * log_xs[1]
            assert bands(x0)[0] == pytest.approx(
                numpy.exp2(m * numpy.log2(x0) + n0), nan_ok=True)
            assert bands(x1)[0] == pytest.approx(
                numpy.exp2(m * numpy.log2(x1) + n1), nan_ok=True)
        elif extrapolation is sumpf.Bands.interpolations.LOG_X:
            log_xs = numpy.log2(xs)
            m = (ys[1] - ys[0]) / (log_xs[1] - log_xs[0])
            r0 = m * numpy.log2(x0) + ys[0] - m * log_xs[0]
            r1 = m * numpy.log2(x1) + ys[1] - m * log_xs[1]
            assert (numpy.isnan(bands(x0)[0])
                    and numpy.isnan(r0)) or (bands(x0)[0] == pytest.approx(r0))
            assert (numpy.isnan(bands(x1)[0])
                    and numpy.isnan(r1)) or (bands(x1)[0] == pytest.approx(r1))
        elif extrapolation is sumpf.Bands.interpolations.LOG_Y:
            bands = sumpf.Bands(bands={x: abs(y)
                                       for x, y in zip(xs, ys)},
                                extrapolations=extrapolation)
            log_ys = numpy.log2(numpy.abs(ys))
            m = (log_ys[1] - log_ys[0]) / (xs[1] - xs[0])
            n0 = log_ys[0] - m * xs[0]
            n1 = log_ys[1] - m * xs[1]
            assert bands(x0)[0] == pytest.approx(numpy.exp2(m * x0 + n0),
                                                 nan_ok=True)
            assert bands(x1)[0] == pytest.approx(numpy.exp2(m * x1 + n1),
                                                 nan_ok=True)
        elif extrapolation is sumpf.Bands.interpolations.STAIRS_LIN:
            assert bands(x0)[0] == ys[0]
            assert bands(x1)[0] == ys[1]
        elif extrapolation is sumpf.Bands.interpolations.STAIRS_LOG:
            assert bands(x0)[0] == ys[0]
            assert bands(x1)[0] == ys[1]
        else:
            raise ValueError(f"Unknown extrapolation: {extrapolation}.")