Files
openrgb-hue/tests/test_mapping.py
T

140 lines
5.3 KiB
Python
Raw Permalink Normal View History

import pytest
from openrgb_hue.color import Color
from openrgb_hue.gradient import Gradient
from openrgb_hue.mapping import (
FrameParams,
MatrixMapping,
MirrorMapping,
PerDeviceMapping,
PerZoneMapping,
SequenceMapping,
ShuffleMapping,
UnknownMappingModeError,
base_positions,
build_mapping,
render_frame,
)
from openrgb_hue.targets import synthetic_targets
def test_sequence_mapping_linear_spacing(synthetic_leds):
positions = SequenceMapping().positions(synthetic_leds)
ordered = [positions[led] for led in synthetic_leds]
assert ordered[0] == 0.0
assert ordered[-1] == 1.0
assert ordered == sorted(ordered)
def test_sequence_mapping_single_target_is_zero():
leds = synthetic_targets(1)
positions = SequenceMapping().positions(leds)
assert positions[leds[0]] == 0.0
def test_per_device_mapping_each_device_spans_full_range():
leds = synthetic_targets() # two linear devices + one matrix device
positions = PerDeviceMapping().positions(leds)
for device_index in {led.device_index for led in leds}:
device_leds = [led for led in leds if led.device_index == device_index]
values = [positions[led] for led in device_leds]
assert min(values) == 0.0
assert max(values) == 1.0
def test_per_zone_mapping_groups_by_zone():
leds = synthetic_targets()
positions = PerZoneMapping().positions(leds)
for key in {(led.device_index, led.zone_index) for led in leds}:
zone_leds = [led for led in leds if (led.device_index, led.zone_index) == key]
values = [positions[led] for led in zone_leds]
assert min(values) == 0.0
assert max(values) == 1.0
@pytest.fixture
def matrix_leds():
return [led for led in synthetic_targets() if led.matrix_row is not None]
def test_matrix_mapping_left_right(matrix_leds):
positions = MatrixMapping(direction="left-right").positions(matrix_leds)
top_left = next(led for led in matrix_leds if led.matrix_row == 0 and led.matrix_col == 0)
top_right = next(led for led in matrix_leds if led.matrix_row == 0 and led.matrix_col == 3)
assert positions[top_left] == 0.0
assert positions[top_right] == 1.0
def test_matrix_mapping_top_bottom(matrix_leds):
positions = MatrixMapping(direction="top-bottom").positions(matrix_leds)
top = next(led for led in matrix_leds if led.matrix_row == 0 and led.matrix_col == 0)
bottom = next(led for led in matrix_leds if led.matrix_row == 3 and led.matrix_col == 0)
assert positions[top] == 0.0
assert positions[bottom] == 1.0
def test_matrix_mapping_diagonal(matrix_leds):
positions = MatrixMapping(direction="diagonal").positions(matrix_leds)
corner_near = next(led for led in matrix_leds if led.matrix_row == 0 and led.matrix_col == 0)
corner_far = next(led for led in matrix_leds if led.matrix_row == 3 and led.matrix_col == 3)
assert positions[corner_near] == 0.0
assert positions[corner_far] == 1.0
def test_matrix_mapping_radial_center_is_minimum(matrix_leds):
positions = MatrixMapping(direction="radial").positions(matrix_leds)
# On a 4x4 grid the center falls between cells; corners should be
# further from center than the near-center cells.
corner = next(led for led in matrix_leds if led.matrix_row == 0 and led.matrix_col == 0)
near_center = next(led for led in matrix_leds if led.matrix_row == 1 and led.matrix_col == 1)
assert positions[near_center] < positions[corner]
def test_matrix_mapping_invalid_direction_raises():
with pytest.raises(ValueError):
MatrixMapping(direction="sideways")
def test_matrix_mapping_warns_on_non_matrix_leds():
leds = synthetic_targets(4) # flat LEDs, no matrix coordinates
warnings = []
MatrixMapping(warn=warnings.append).positions(leds)
assert len(warnings) == 1
assert all(led.matrix_row is None for led in leds)
def test_mirror_mapping_is_symmetric(synthetic_leds):
positions = MirrorMapping().positions(synthetic_leds)
values = [positions[led] for led in synthetic_leds]
n = len(values)
for i in range(n):
assert values[i] == pytest.approx(values[n - 1 - i])
def test_shuffle_mapping_deterministic_and_seed_sensitive(synthetic_leds):
a = ShuffleMapping(seed=1).positions(synthetic_leds)
b = ShuffleMapping(seed=1).positions(synthetic_leds)
c = ShuffleMapping(seed=2).positions(synthetic_leds)
assert a == b
assert a != c
def test_build_mapping_unknown_name_raises():
with pytest.raises(UnknownMappingModeError):
build_mapping("not-a-real-mode")
def test_render_frame_uses_gradient_and_offset(synthetic_leds):
gradient = Gradient.from_colors([Color(255, 0, 0), Color(0, 0, 255)], interpolation="rgb")
base = base_positions(SequenceMapping(), synthetic_leds)
colors = render_frame(base, gradient, FrameParams(t_offset=0.0, brightness=1.0))
assert colors[synthetic_leds[0]] == gradient.sample(0.0)
def test_render_frame_brightness_fn_overrides_scalar_brightness(synthetic_leds):
gradient = Gradient.from_colors([Color(255, 255, 255)], interpolation="rgb")
base = base_positions(SequenceMapping(), synthetic_leds)
params = FrameParams(brightness=1.0, brightness_fn=lambda t: 0.0)
colors = render_frame(base, gradient, params)
assert all(c == Color(0, 0, 0) for c in colors.values())