import numpy as np
import pytest
from hypothesis import given, settings
from hypothesis import strategies as st
from hypothesis.extra.numpy import arrays
from stream.composition import uniform_x_power_shape
from stream.utilities import (
cosine_shape,
cosine_shape_by_zero_endpoints,
just,
offset,
pair_mean,
pair_mean_1d,
)
from .conftest import are_close, non_neg_medium_integers
[docs]
def test_pair_mean_for_one_simple_case():
a = np.arange(6)
are_close(pair_mean(a), a[:-1] + 0.5)
are_close(pair_mean(a, append=6), a + 0.5)
are_close(pair_mean(a, prepend=-1), a - 0.5)
decent_floats = st.floats(min_value=-1e20, max_value=1e20, allow_nan=False, allow_infinity=False)
non_small_positive_floats = st.floats(min_value=0.5, max_value=10)
small_floats = st.floats(min_value=-10, max_value=10)
ints = st.integers(min_value=1, max_value=100)
PPF_values = st.floats(min_value=1.0, max_value=np.pi / 2)
illegal_ppf_values = st.one_of(
st.floats(min_value=0, max_value=0.99),
st.floats(min_value=np.pi / 2 + 0.01, max_value=3),
)
[docs]
@settings(deadline=None)
@given(
arrays(float, st.integers(1, 10), elements=decent_floats),
decent_floats,
st.integers(0, 2),
)
def test_pair_mean_1d_is_pair_mean(v, ext, case):
cas = {0: (None, None), 1: (ext, None), 2: (None, ext)}[case]
cas_numpy = [v if v is not None else np._NoValue for v in cas]
keys = ("prepend", "append")
d_numpy = dict(zip(keys, cas_numpy))
d_1d = dict(zip(keys, cas))
assert np.allclose(pair_mean(v, **d_numpy), pair_mean_1d(v, **d_1d))
[docs]
def test_just():
f = just(7)
assert f(1, 2, 3) == 7
assert f(a=1, b=2, c=3) == 7
assert f(1, 2, 3, a=1, b=2, c=3) == 7
[docs]
@given(non_neg_medium_integers, non_neg_medium_integers)
def test_offset(move_by, val):
assert offset(val, move_by) == val + move_by
assert offset(slice(val), move_by) == slice(move_by, val + move_by)
assert offset(slice(0, val), move_by) == slice(move_by, val + move_by)
assert offset({1: val, 2: 2 * val}, move_by) == {
1: val + move_by,
2: 2 * val + move_by,
}
assert offset({1: val, 2: slice(val, 2 * val), 3: np.zeros(1)}, move_by) == {
1: val + move_by,
2: slice(val + move_by, 2 * val + move_by),
3: np.full(1, move_by),
}
are_close(offset(np.arange(3), move_by), np.arange(move_by, 3 + move_by))
[docs]
def test_offset_of_an_unknown_type_raises_TypeError():
with pytest.raises(TypeError):
offset("hello", 8)
[docs]
@given(small_floats, non_small_positive_floats, PPF_values, st.integers(1, 100))
def test_cosine_shape_achieves_maximum_at_center(start, length, ppf, n):
x = np.linspace(start, start + length, num=2 * n + 2)
shape = cosine_shape(x, ppf=ppf)
assert (np.argmax(shape) == n) or np.isclose(ppf, 1.0), shape
[docs]
@given(PPF_values)
def test_cosine_shape_max_is_like_ppf_for_high_resolution(ppf):
"""This test ensures that the underlying cosine shape's max to mean ratio
meets the desired PPF value.
Since the function returns cell-integrated values, in order to approximate
the ppf value we need a high enough resolution.
"""
x = np.linspace(0, 1, 10000)
shape = cosine_shape(x, ppf=ppf)
mx = np.max(shape) / np.diff(x)[0]
mean = np.sum(shape)
assert np.isclose(mx / mean, ppf)
[docs]
@given(small_floats, non_small_positive_floats, PPF_values, st.integers(3, 100))
def test_cosine_shape_sums_to_1(start, length, ppf, n):
x = np.linspace(start, start + length, n)
shape = cosine_shape(x, ppf)
intv = np.sum(shape)
assert np.isclose(intv, 1)
[docs]
@given(small_floats, non_small_positive_floats, illegal_ppf_values)
def test_cosine_shape_throws_for_illegal_ppf(xi, length, ppf):
x = np.linspace(xi, xi + length, num=100)
with pytest.raises(ValueError):
cosine_shape(x, ppf)