Coverage for src/evutils/transforms/functional/_common.py: 100%
15 statements
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-18 05:24 +0000
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-18 05:24 +0000
1"""Shared helpers for the functional transforms.
3Every functional follows the same shape: validate arguments, then unwrap the
4events into the constituent ``(t, x, y, p)`` arrays, run a Numba-compiled
5kernel, and repack the result into the caller's original container. The
6:func:`apply_kernel` helper centralises the unwrap/kernel/repack dance so each
7functional only has to express its argument handling and pick a kernel.
8"""
9from __future__ import annotations
11from typing import Callable
13import numpy as np
15def apply_kernel(events: "EventArray", kernel: Callable[..., "EventArray"], *args: object) -> "EventArray":
16 """Unwrap ``events``, run ``kernel(t, x, y, p, *args)``, repack the result.
18 Empty inputs are returned untouched so kernels never see zero-length arrays
19 (several derive a sensor extent from ``x.max()`` / ``y.max()``).
20 """
21 from evutils.transforms.compose import repack_events, unwrap_events
23 if len(events) == 0:
24 return events
26 t, x, y, p = unwrap_events(events)
27 t, x, y, p = kernel(t, x, y, p, *args)
28 return repack_events(events, t, x, y, p)
30def sample_range(value: "tuple[float, float] | list[float] | float") -> float:
31 """Return ``value``, or a uniform sample in ``[lo, hi)`` if it is a 2-tuple.
33 Mirrors the range-sampling convention used across the tonic transforms,
34 where a scalar is used verbatim and a ``(lo, hi)`` pair is sampled per call.
35 """
36 if isinstance(value, (tuple, list)):
37 lo, hi = value
38 return (hi - lo) * np.random.random_sample() + lo
39 return float(value)