mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-10-29 17:50:37 +00:00
Merge pull request #298 from lurch/new_source_tools
New source tools: booleanized, pre_periodic_filtered & post_periodic_filtered
This commit is contained in:
@@ -10,7 +10,7 @@ the :attr:`~gpiozero.SourceMixin.source` and
|
||||
library. These utility routines are in the ``tools`` module of GPIO Zero and
|
||||
are typically imported as follows::
|
||||
|
||||
from gpiozero.tools import scaled, negated, conjunction
|
||||
from gpiozero.tools import scaled, negated, all_values
|
||||
|
||||
Given that :attr:`~gpiozero.SourceMixin.source` and
|
||||
:attr:`~gpiozero.ValuesMixin.values` deal with infinite iterators, another
|
||||
@@ -29,6 +29,8 @@ Single source conversions
|
||||
|
||||
.. autofunction:: absoluted
|
||||
|
||||
.. autofunction:: booleanized
|
||||
|
||||
.. autofunction:: clamped
|
||||
|
||||
.. autofunction:: inverted
|
||||
@@ -37,8 +39,12 @@ Single source conversions
|
||||
|
||||
.. autofunction:: post_delayed
|
||||
|
||||
.. autofunction:: post_periodic_filtered
|
||||
|
||||
.. autofunction:: pre_delayed
|
||||
|
||||
.. autofunction:: pre_periodic_filtered
|
||||
|
||||
.. autofunction:: quantized
|
||||
|
||||
.. autofunction:: queued
|
||||
@@ -56,10 +62,10 @@ Combining sources
|
||||
|
||||
.. autofunction:: averaged
|
||||
|
||||
.. autofunction:: summed
|
||||
|
||||
.. autofunction:: multiplied
|
||||
|
||||
.. autofunction:: summed
|
||||
|
||||
Artificial sources
|
||||
==================
|
||||
|
||||
|
||||
@@ -41,10 +41,13 @@ def negated(values):
|
||||
yield not v
|
||||
|
||||
|
||||
def inverted(values):
|
||||
def inverted(values, input_min=0, input_max=1):
|
||||
"""
|
||||
Returns the inversion of the supplied values (1 becomes 0, 0 becomes 1,
|
||||
0.1 becomes 0.9, etc.). For example::
|
||||
Returns the inversion of the supplied values (*input_min* becomes
|
||||
*input_max*, *input_max* becomes *input_min*, `input_min + 0.1` becomes
|
||||
`input_max - 0.1`, etc.). All items in *values* are assumed to be between
|
||||
*input_min* and *input_max* (which default to 0 and 1 respectively), and
|
||||
the output will be in the same range. For example::
|
||||
|
||||
from gpiozero import MCP3008, PWMLED
|
||||
from gpiozero.tools import inverted
|
||||
@@ -55,8 +58,10 @@ def inverted(values):
|
||||
led.source = inverted(pot.values)
|
||||
pause()
|
||||
"""
|
||||
if input_min >= input_max:
|
||||
raise ValueError('input_min must be smaller than input_max')
|
||||
for v in values:
|
||||
yield 1 - v
|
||||
yield input_min + input_max - v
|
||||
|
||||
|
||||
def scaled(values, output_min, output_max, input_min=0, input_max=1):
|
||||
@@ -82,6 +87,8 @@ def scaled(values, output_min, output_max, input_min=0, input_max=1):
|
||||
*input_max* (inclusive) then the function will not produce values that
|
||||
lie within *output_min* to *output_max* (inclusive).
|
||||
"""
|
||||
if input_min >= input_max:
|
||||
raise ValueError('input_min must be smaller than input_max')
|
||||
input_size = input_max - input_min
|
||||
output_size = output_max - output_min
|
||||
for v in values:
|
||||
@@ -104,6 +111,8 @@ def clamped(values, output_min=0, output_max=1):
|
||||
led.source = clamped(pot.values, 0.5, 1.0)
|
||||
pause()
|
||||
"""
|
||||
if output_min >= output_max:
|
||||
raise ValueError('output_min must be smaller than output_max')
|
||||
for v in values:
|
||||
yield min(max(v, output_min), output_max)
|
||||
|
||||
@@ -128,11 +137,11 @@ def absoluted(values):
|
||||
yield abs(v)
|
||||
|
||||
|
||||
def quantized(values, steps, output_min=0, output_max=1):
|
||||
def quantized(values, steps, input_min=0, input_max=1):
|
||||
"""
|
||||
Returns *values* quantized to *steps* increments. All items in *values* are
|
||||
assumed to be between *output_min* and *output_max* (use :func:`scaled` to
|
||||
ensure this if necessary).
|
||||
assumed to be between *input_min* and *input_max* (which default to 0 and
|
||||
1 respectively), and the output will be in the same range.
|
||||
|
||||
For example, to quantize values between 0 and 1 to 5 "steps" (0.0, 0.25,
|
||||
0.5, 0.75, 1.0)::
|
||||
@@ -146,9 +155,72 @@ def quantized(values, steps, output_min=0, output_max=1):
|
||||
led.source = quantized(pot.values, 4)
|
||||
pause()
|
||||
"""
|
||||
output_size = output_max - output_min
|
||||
for v in scaled(values, 0, 1, output_min, output_max):
|
||||
yield ((int(v * steps) / steps) * output_size) + output_min
|
||||
if steps < 1:
|
||||
raise ValueError("steps must be 1 or larger")
|
||||
if input_min >= input_max:
|
||||
raise ValueError('input_min must be smaller than input_max')
|
||||
input_size = input_max - input_min
|
||||
for v in scaled(values, 0, 1, input_min, input_max):
|
||||
yield ((int(v * steps) / steps) * input_size) + input_min
|
||||
|
||||
|
||||
def booleanized(values, min_value, max_value, hysteresis=0):
|
||||
"""
|
||||
Returns True for each item in *values* between *min_value* and
|
||||
*max_value*, and False otherwise. *hysteresis* can optionally be used to
|
||||
add `hysteresis`_ which prevents the output value rapidly flipping when
|
||||
the input value is fluctuating near the *min_value* or *max_value*
|
||||
thresholds. For example, to light an LED only when a potentiometer is
|
||||
between 1/4 and 3/4 of its full range::
|
||||
|
||||
from gpiozero import LED, MCP3008
|
||||
from gpiozero.tools import booleanized
|
||||
from signal import pause
|
||||
|
||||
led = LED(4)
|
||||
pot = MCP3008(channel=0)
|
||||
led.source = booleanized(pot.values, 0.25, 0.75)
|
||||
pause()
|
||||
|
||||
.. _hysteresis: https://en.wikipedia.org/wiki/Hysteresis
|
||||
"""
|
||||
if min_value >= max_value:
|
||||
raise ValueError('min_value must be smaller than max_value')
|
||||
min_value = float(min_value)
|
||||
max_value = float(max_value)
|
||||
if hysteresis < 0:
|
||||
raise ValueError("hysteresis must be 0 or larger")
|
||||
else:
|
||||
hysteresis = float(hysteresis)
|
||||
if (max_value - min_value) <= hysteresis:
|
||||
raise ValueError('The gap between min_value and max_value must be larger than hysteresis')
|
||||
last_state = None
|
||||
for v in values:
|
||||
if v < min_value:
|
||||
new_state = 'below'
|
||||
elif v > max_value:
|
||||
new_state = 'above'
|
||||
else:
|
||||
new_state = 'in'
|
||||
switch = False
|
||||
if last_state == None or not hysteresis:
|
||||
switch = True
|
||||
elif new_state == last_state:
|
||||
pass
|
||||
else: # new_state != last_state
|
||||
if last_state == 'below' and new_state == 'in':
|
||||
switch = v >= min_value + hysteresis
|
||||
elif last_state == 'in' and new_state == 'below':
|
||||
switch = v < min_value - hysteresis
|
||||
elif last_state == 'in' and new_state == 'above':
|
||||
switch = v > max_value + hysteresis
|
||||
elif last_state == 'above' and new_state == 'in':
|
||||
switch = v <= max_value - hysteresis
|
||||
else: # above->below or below->above
|
||||
switch = True
|
||||
if switch:
|
||||
last_state = new_state
|
||||
yield last_state == 'in'
|
||||
|
||||
|
||||
def all_values(*values):
|
||||
@@ -284,6 +356,8 @@ def queued(values, qsize):
|
||||
leds[4].source = btn.values
|
||||
pause()
|
||||
"""
|
||||
if qsize < 1:
|
||||
raise ValueError("qsize must be 1 or larger")
|
||||
q = []
|
||||
it = iter(values)
|
||||
for i in range(qsize):
|
||||
@@ -308,9 +382,11 @@ def smoothed(values, qsize, average=mean):
|
||||
from gpiozero.tools import smoothed
|
||||
|
||||
with MCP3008(channel=0) as adc:
|
||||
for smoothvalue in smoothed(adc.values, 5):
|
||||
print smoothvalue
|
||||
for value in smoothed(adc.values, 5):
|
||||
print value
|
||||
"""
|
||||
if qsize < 1:
|
||||
raise ValueError("qsize must be 1 or larger")
|
||||
q = []
|
||||
it = iter(values)
|
||||
for i in range(qsize):
|
||||
@@ -327,6 +403,8 @@ def pre_delayed(values, delay):
|
||||
"""
|
||||
Waits for *delay* seconds before returning each item from *values*.
|
||||
"""
|
||||
if delay < 0:
|
||||
raise ValueError("delay must be 0 or larger")
|
||||
for v in values:
|
||||
sleep(delay)
|
||||
yield v
|
||||
@@ -336,11 +414,78 @@ def post_delayed(values, delay):
|
||||
"""
|
||||
Waits for *delay* seconds after returning each item from *values*.
|
||||
"""
|
||||
if delay < 0:
|
||||
raise ValueError("delay must be 0 or larger")
|
||||
for v in values:
|
||||
yield v
|
||||
sleep(delay)
|
||||
|
||||
|
||||
def pre_periodic_filtered(values, block, repeat_after):
|
||||
"""
|
||||
Blocks the first *block* items from *values*, repeating the block after
|
||||
every *repeat_after* items, if *repeat_after* is non-zero. For example, to
|
||||
discard the first 50 values read from an ADC::
|
||||
|
||||
from gpiozero import MCP3008
|
||||
from gpiozero.tools import pre_periodic_filtered
|
||||
|
||||
with MCP3008(channel=0) as adc:
|
||||
for value in pre_periodic_filtered(adc.values, 50, 0):
|
||||
print value
|
||||
|
||||
Or to only display every even item read from an ADC::
|
||||
|
||||
from gpiozero import MCP3008
|
||||
from gpiozero.tools import pre_periodic_filtered
|
||||
|
||||
with MCP3008(channel=0) as adc:
|
||||
for value in pre_periodic_filtered(adc.values, 1, 1):
|
||||
print value
|
||||
"""
|
||||
if block < 1:
|
||||
raise ValueError("block must be 1 or larger")
|
||||
if repeat_after < 0:
|
||||
raise ValueError("repeat_after must be 0 or larger")
|
||||
it = iter(values)
|
||||
if repeat_after == 0:
|
||||
for _ in range(block):
|
||||
next(it)
|
||||
while True:
|
||||
yield next(it)
|
||||
else:
|
||||
while True:
|
||||
for _ in range(block):
|
||||
next(it)
|
||||
for _ in range(repeat_after):
|
||||
yield next(it)
|
||||
|
||||
|
||||
def post_periodic_filtered(values, repeat_after, block):
|
||||
"""
|
||||
After every *repeat_after* items, blocks the next *block* items from
|
||||
*values*. Note that unlike :func:`pre_periodic_filtered`, *repeat_after*
|
||||
can't be 0. For example, to block every tenth item read from an ADC::
|
||||
|
||||
from gpiozero import MCP3008
|
||||
from gpiozero.tools import post_periodic_filtered
|
||||
|
||||
with MCP3008(channel=0) as adc:
|
||||
for value in post_periodic_filtered(adc.values, 9, 1):
|
||||
print value
|
||||
"""
|
||||
if repeat_after < 1:
|
||||
raise ValueError("repeat_after must be 1 or larger")
|
||||
if block < 1:
|
||||
raise ValueError("block must be 1 or larger")
|
||||
it = iter(values)
|
||||
while True:
|
||||
for _ in range(repeat_after):
|
||||
yield next(it)
|
||||
for _ in range(block):
|
||||
next(it)
|
||||
|
||||
|
||||
def random_values():
|
||||
"""
|
||||
Provides an infinite source of random values between 0 and 1. For example,
|
||||
|
||||
@@ -31,24 +31,108 @@ def test_negated():
|
||||
assert list(negated((True, True, False, False))) == [False, False, True, True]
|
||||
|
||||
def test_inverted():
|
||||
with pytest.raises(ValueError):
|
||||
list(inverted((), 0, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(inverted((), 1, 1))
|
||||
with pytest.raises(ValueError):
|
||||
list(inverted((), 1, 0))
|
||||
assert list(inverted(())) == []
|
||||
assert list(inverted((1, 0, 0.1, 0.5))) == [0, 1, 0.9, 0.5]
|
||||
assert list(inverted((1, 0, 0.1, 0.5), 0, 1)) == [0, 1, 0.9, 0.5]
|
||||
assert list(inverted((-1, 0, -0.1, -0.5), -1, 0)) == [0, -1, -0.9, -0.5]
|
||||
assert list(inverted((1, 0, 0.1, 0.5, -1, -0.1, -0.5), -1, 1)) == [-1, 0, -0.1, -0.5, 1, 0.1, 0.5]
|
||||
assert list(inverted((2, 1, 1.1, 1.5), 1, 2)) == [1, 2, 1.9, 1.5]
|
||||
|
||||
def test_scaled():
|
||||
with pytest.raises(ValueError):
|
||||
list(scaled((), 0, 1, 0, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(scaled((), 0, 1, 1, 1))
|
||||
with pytest.raises(ValueError):
|
||||
list(scaled((), 0, 1, 1, 0))
|
||||
assert list(scaled((), 0, 1)) == []
|
||||
# no scale
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 0, 1)) == [0, 1, 0.5, 0.1]
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 0, 1, 0, 1)) == [0, 1, 0.5, 0.1]
|
||||
# multiply by 2
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 0, 2, 0, 1)) == [0, 2, 1, 0.2]
|
||||
# add 1
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 1, 2, 0, 1)) == [1, 2, 1.5, 1.1]
|
||||
# multiply by 2 then add 1
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 1, 3, 0, 1)) == [1, 3, 2, 1.2]
|
||||
# add 1 then multiply by 2
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 2, 4, 0, 1)) == [2, 4, 3, 2.2]
|
||||
# invert
|
||||
assert list(scaled((0, 1, 0.5, 0.1), 1, 0, 0, 1)) == [1, 0, 0.5, 0.9]
|
||||
# multiply by -1 then subtract 1
|
||||
assert list(scaled((0, 1, 0.5, 0.1), -1, -2, 0, 1)) == [-1, -2, -1.5, -1.1]
|
||||
# scale 0->1 to -1->+1
|
||||
assert list(scaled((0, 1, 0.5, 0.1), -1, 1)) == [-1, 1, 0.0, -0.8]
|
||||
assert list(scaled((0, 1, 0.5, 0.1), -1, 1, 0, 1)) == [-1, 1, 0.0, -0.8]
|
||||
# scale -1->+1 to 0->1
|
||||
assert list(scaled((-1, 1, 0.0, -0.5), 0, 1, -1, 1)) == [0, 1, 0.5, 0.25]
|
||||
|
||||
def test_clamped():
|
||||
assert list(clamped((-1, 0, 1, 2))) == [0, 0, 1, 1]
|
||||
with pytest.raises(ValueError):
|
||||
list(clamped((), 0, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(clamped((), 1, 1))
|
||||
with pytest.raises(ValueError):
|
||||
list(clamped((), 1, 0))
|
||||
assert list(clamped(())) == []
|
||||
assert list(clamped((-2, -1, -0.5, 0, 0.5, 1, 2))) == [0, 0, 0, 0, 0.5, 1, 1]
|
||||
assert list(clamped((-2, -1, -0.5, 0, 0.5, 1, 2), 0, 1)) == [0, 0, 0, 0, 0.5, 1, 1]
|
||||
assert list(clamped((-2, -1, -0.5, 0, 0.5, 1, 2), -1, 1)) == [-1, -1, -0.5, 0, 0.5, 1, 1]
|
||||
assert list(clamped((-2, -1, -0.5, 0, 0.5, 1, 2), -2, 2)) == [-2, -1, -0.5, 0, 0.5, 1, 2]
|
||||
|
||||
def test_absoluted():
|
||||
assert list(absoluted(())) == []
|
||||
assert list(absoluted((-2, -1, 0, 1, 2))) == [2, 1, 0, 1, 2]
|
||||
|
||||
def test_quantized():
|
||||
with pytest.raises(ValueError):
|
||||
list(quantized((), 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(quantized((), 4, 0, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(quantized((), 4, 1, 1))
|
||||
with pytest.raises(ValueError):
|
||||
list(quantized((), 4, 1, 0))
|
||||
assert list(quantized((), 4)) == []
|
||||
assert list(quantized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 4)) == [
|
||||
0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.5, 0.75, 0.75, 1.0]
|
||||
assert list(quantized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 4, 0, 1)) == [
|
||||
0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.5, 0.75, 0.75, 1.0]
|
||||
assert list(quantized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 5)) == [
|
||||
0.0, 0.0, 0.2, 0.2, 0.4, 0.4, 0.6, 0.6, 0.8, 0.8, 1.0]
|
||||
assert list(quantized((0, 0.25, 0.5, 0.75, 1.0, 1.5, 1.75, 2.0), 2, 0, 2)) == [
|
||||
0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 2.0]
|
||||
assert list(quantized((1, 1.25, 1.5, 1.75, 2.0, 2.5, 2.75, 3.0), 2, 1, 3)) == [
|
||||
1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0]
|
||||
|
||||
def test_booleanized():
|
||||
with pytest.raises(ValueError):
|
||||
list(booleanized((), 0, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(booleanized((), 1, 1))
|
||||
with pytest.raises(ValueError):
|
||||
list(booleanized((), 1, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(booleanized((), 0, 0.5, -0.2))
|
||||
with pytest.raises(ValueError):
|
||||
list(booleanized((), 0, 0.5, 0.5))
|
||||
assert list(booleanized((), 0, 0.5)) == []
|
||||
assert list(booleanized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 0, 0.5)) == [
|
||||
True, True, True, True, True, True, False, False, False, False, False]
|
||||
assert list(booleanized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 0), 0.25, 0.75)) == [
|
||||
False, False, False, True, True, True, True, True, False, False, False, False]
|
||||
assert list(booleanized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 0), 0.25, 0.75, 0.2)) == [
|
||||
False, False, False, False, False, True, True, True, True, True, False, False]
|
||||
assert list(booleanized((1, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0, 1), 0.25, 0.75)) == [
|
||||
False, False, False, True, True, True, True, True, False, False, False, False]
|
||||
assert list(booleanized((1, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0, 1), 0.25, 0.75, 0.2)) == [
|
||||
False, False, False, False, False, True, True, True, True, True, False, False]
|
||||
|
||||
def test_all_values():
|
||||
assert list(all_values(())) == []
|
||||
@@ -62,52 +146,128 @@ def test_any_values():
|
||||
|
||||
def test_averaged():
|
||||
assert list(averaged(())) == []
|
||||
assert list(averaged((0, 0.5, 1))) == [0, 0.5, 1]
|
||||
assert list(averaged((0, 0.5, 1), (1, 1, 1))) == [0.5, 0.75, 1]
|
||||
|
||||
def test_summed():
|
||||
assert list(summed(())) == []
|
||||
assert list(summed((0, 0.5, 0.5, 1))) == [0, 0.5, 0.5, 1]
|
||||
assert list(summed((0, 0.5, 0.5, 1), (1, 0.5, 1, 1))) == [1, 1, 1.5, 2]
|
||||
|
||||
def test_multiplied():
|
||||
assert list(multiplied(())) == []
|
||||
assert list(multiplied((0, 0.5, 0.5, 1))) == [0, 0.5, 0.5, 1]
|
||||
assert list(multiplied((0, 0.5, 0.5, 1), (1, 0.5, 1, 1))) == [0, 0.25, 0.5, 1]
|
||||
|
||||
def test_queued():
|
||||
with pytest.raises(ValueError):
|
||||
list(queued((), 0))
|
||||
assert list(queued((), 5)) == []
|
||||
assert list(queued((1, 2, 3, 4, 5), 5)) == [1]
|
||||
assert list(queued((1, 2, 3, 4, 5, 6), 5)) == [1, 2]
|
||||
|
||||
def test_smoothed():
|
||||
with pytest.raises(ValueError):
|
||||
list(smoothed((), 0))
|
||||
assert list(smoothed((), 5)) == []
|
||||
assert list(smoothed((1, 2, 3, 4, 5), 5)) == [3.0]
|
||||
assert list(smoothed((1, 2, 3, 4, 5, 6), 5)) == [3.0, 4.0]
|
||||
assert list(smoothed((1, 2, 3, 4, 5, 6), 5, average=mean)) == [3.0, 4.0]
|
||||
assert list(smoothed((1, 1, 1, 4, 5, 5), 5, average=mean)) == [2.4, 3.2]
|
||||
assert list(smoothed((1, 1, 1, 4, 5, 5), 5, average=median)) == [1, 4]
|
||||
|
||||
def test_pre_delayed():
|
||||
with pytest.raises(ValueError):
|
||||
list(pre_delayed((), -1))
|
||||
assert list(pre_delayed((), 0.01)) == []
|
||||
count = 0
|
||||
start = time()
|
||||
for v in pre_delayed((0, 0, 0), 0.01):
|
||||
count += 1
|
||||
assert v == 0
|
||||
assert time() - start >= 0.01
|
||||
start = time()
|
||||
assert count == 3
|
||||
|
||||
def test_post_delayed():
|
||||
with pytest.raises(ValueError):
|
||||
list(post_delayed((), -1))
|
||||
assert list(post_delayed((), 0.01)) == []
|
||||
count = 0
|
||||
start = time()
|
||||
for v in post_delayed((1, 2, 2), 0.01):
|
||||
count += 1
|
||||
if v == 1:
|
||||
assert time() - start < 0.01
|
||||
else:
|
||||
elif v == 2:
|
||||
assert time() - start >= 0.01
|
||||
else:
|
||||
assert False
|
||||
start = time()
|
||||
assert time() - start >= 0.01
|
||||
assert count == 3
|
||||
|
||||
def test_pre_periodic_filtered():
|
||||
with pytest.raises(ValueError):
|
||||
list(pre_periodic_filtered((), 2, -1))
|
||||
with pytest.raises(ValueError):
|
||||
list(pre_periodic_filtered((), 0, 0))
|
||||
assert list(pre_periodic_filtered((), 2, 0)) == []
|
||||
assert list(pre_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 2, 0)) == [3, 4, 5, 6, 7, 8, 9, 10]
|
||||
assert list(pre_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 1, 1)) == [2, 4, 6, 8, 10]
|
||||
assert list(pre_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 1, 2)) == [2, 3, 5, 6, 8, 9]
|
||||
assert list(pre_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 2, 1)) == [3, 6, 9]
|
||||
|
||||
def test_post_periodic_filtered():
|
||||
with pytest.raises(ValueError):
|
||||
list(post_periodic_filtered((), 1, 0))
|
||||
with pytest.raises(ValueError):
|
||||
list(post_periodic_filtered((), 0, 1))
|
||||
assert list(pre_periodic_filtered((), 1, 1)) == []
|
||||
assert list(post_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 1, 1)) == [1, 3, 5, 7, 9]
|
||||
assert list(post_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 1, 2)) == [1, 4, 7, 10]
|
||||
assert list(post_periodic_filtered((1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 2, 1)) == [1, 2, 4, 5, 7, 8, 10]
|
||||
|
||||
def test_random_values():
|
||||
for i, v in zip(range(1000), random_values()):
|
||||
for _, v in zip(range(1000), random_values()):
|
||||
assert 0 <= v <= 1
|
||||
|
||||
def test_sin_values():
|
||||
firstval = None
|
||||
for i, v in zip(range(1000), sin_values()):
|
||||
assert -1 <= v <= 1
|
||||
assert isclose(v, sin(radians(i)), abs_tol=1e-9)
|
||||
if i == 0:
|
||||
firstval = v
|
||||
else:
|
||||
if i % 360 == 0:
|
||||
assert v == firstval
|
||||
for period in (360, 100):
|
||||
firstval = None
|
||||
for i, v in zip(range(1000), sin_values(period)):
|
||||
assert -1 <= v <= 1
|
||||
if i == 0:
|
||||
firstval = v
|
||||
else:
|
||||
if i % period == 0:
|
||||
assert v == firstval
|
||||
|
||||
def test_cos_values():
|
||||
firstval = None
|
||||
for i, v in zip(range(1000), cos_values()):
|
||||
assert -1 <= v <= 1
|
||||
assert isclose(v, cos(radians(i)), abs_tol=1e-9)
|
||||
|
||||
if i == 0:
|
||||
firstval = v
|
||||
else:
|
||||
if i % 360 == 0:
|
||||
assert v == firstval
|
||||
for period in (360, 100):
|
||||
firstval = None
|
||||
for i, v in zip(range(1000), cos_values(period)):
|
||||
assert -1 <= v <= 1
|
||||
if i == 0:
|
||||
firstval = v
|
||||
else:
|
||||
if i % period == 0:
|
||||
assert v == firstval
|
||||
|
||||
Reference in New Issue
Block a user