Skip to content

Kernels API

frames2py.kernels holds the Kernel protocol and the five built-in kernels. The kernel classes are also exported from frames2py. Their semantics are on the Kernels page; the methods listed here are the Kernel protocol, which the Accumulator calls. You don't call them yourself unless you are writing a kernel.

frames2py.kernels.Kernel

Bases: Protocol

A representation kernel.

The Accumulator owns validation, the timestamp-range check, the bounds check, the watermark and the out-of-bounds count; a kernel only turns in-bounds events into its representation. For each accepted call the Accumulator calls begin_call once, then passes the call's in-bounds events to accumulate. Publication reads the representation, then closes the window.

output_spec

output_spec(sensor_size: tuple[int, int]) -> tuple[tuple[int, ...], np.dtype[Any]]

Shape and dtype of the representation for a (width, height) sensor.

init_state

init_state(sensor_size: tuple[int, int]) -> KernelState

Allocate the kernel's state for a (width, height) sensor.

begin_call

begin_call(state: KernelState) -> None

Once per accepted accumulate/ingest call, before any accumulation.

accumulate

accumulate(events: NDArray[void], state: KernelState, watermark: int | None) -> None

Merge the call's in-bounds events. watermark includes this call's events.

read

read(state: KernelState, out: NDArray[Any], watermark: int | None) -> None

Write the representation, evaluated at watermark, into out.

Must not change the state. watermark is None before the first in-bounds event; kernels without time dependence ignore it.

close_window

close_window(state: KernelState) -> None

Called after each publication. Windowed kernels start a new window here; running kernels do nothing.

reset

reset(state: KernelState) -> None

Return the state to what init_state produced.

frames2py.kernels.EventCount

Events per pixel in the current window. (H, W) uint32, windowed.

Counts wrap modulo 2**32; they never saturate.

frames2py.kernels.Polarity

Events per pixel and polarity in the current window. (H, W, 2) uint32, windowed. Channel 0 counts p == 0 (OFF), channel 1 every other p (ON).

Counts wrap modulo 2**32; they never saturate.

frames2py.kernels.TimeSurface

Largest timestamp per pixel. (H, W) uint64, running.

0 means no event, so an event at t = 0 is indistinguishable from none.

frames2py.kernels.ExpDecay

Exponentially decaying event count. (H, W) float32, running.

Once per accepted accumulate() or ingest() call the surface is multiplied by decay, then each in-bounds event adds 1. The decay is per call, not per unit of time, so the result depends on how events are batched into calls; use TimestampDecay for decay in event time.

Parameters:

Name Type Description Default
decay float

Finite, with 0 < decay < 1. Anything else raises ValueError.

required

frames2py.kernels.TimestampDecay

Event-time exponential decay. (H, W) float32, running.

Each pixel reads sum(exp(-(T - t_i) / tau_us)) over its accumulated in-bounds events, where T is the watermark. Every event weighs 1, whatever its polarity. Without new in-bounds events T doesn't move and the surface doesn't change; a consumer can extrapolate a snapshot to a later time T' by multiplying it by exp(-(T' - T) / tau_us).

In exact arithmetic the result doesn't depend on event order or on how events are split into calls. An accepted event with a far-future timestamp moves the watermark so far that earlier contributions underflow to zero.

Parameters:

Name Type Description Default
tau_us float

Time constant in µs. Finite and > 0; anything else raises ValueError.

required