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}.")
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}.")
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
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}.")
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}.")