AER Spike-Buffer Decoder¶
MIF-006 implements the local, upstream-pending AER ingress adapter that turns address-event spike streams into ControlObservation-compatible feature vectors. The surface is allocated to Python and Rust. Go remains reserved for optional network router scaffolding and is not a local decode backend.
Decode Strategies¶
For a decode window [t_start, t_start + W) and channel address a, the
implemented feature strategies are:
rate[a] = signed_spike_count[a] / W
temporal[a] = 1 - (first_spike_time[a] - t_start) / W
isi[a] = (n_spikes[a] - 1) / (last_spike_time[a] - first_spike_time[a])
Channels with no applicable spikes decode to 0.0. Event timestamps,
explicit window starts, and decode-window lengths are non-negative u64
nanosecond counters on both Python and Rust/PyO3 surfaces. Timestamps must be
monotone at buffer insertion time, addresses outside n_channels fail closed
at decode time, and decode windows whose exclusive stop would overflow u64
are rejected before feature extraction.
Python API¶
spike_buffer
¶
AER spike-buffer decoding for MIF-006.
AERSpikeEvent(address, t_ns, polarity=1)
dataclass
¶
Single address-event spike.
__post_init__()
¶
Validate and freeze the spike event address, timestamp, and polarity.
AERDecodeSpec(n_channels, window_ns, strategy='rate', start_ns=None)
dataclass
¶
Decode settings for AER spike streams.
__post_init__()
¶
Validate the decode channel count, time window, and optional start.
AERDecodedObservation(spec, features, window_start_ns, window_stop_ns, spike_count)
dataclass
¶
Decoded ControlObservation-compatible feature vector.
__post_init__()
¶
Freeze decoded features and validate observation counters.
SpikeBuffer(capacity)
¶
Deterministic monotone AER spike ring buffer.
events
property
¶
Return buffered events in arrival order.
n_channels
property
¶
Return the minimum channel count that covers all buffered addresses.
__len__()
¶
Return the number of buffered spike events.
push(event)
¶
Append one monotone event, dropping the oldest event when full.
clear()
¶
Remove all buffered events and reset timestamp state.
decode(spec)
¶
Decode buffered events according to spec.
AERControlObservation(spike_stream, decode_window_ns, decode_strategy='rate', n_channels=None, start_ns=None)
dataclass
¶
Local upstream-pending ControlObservation adapter for AER streams.
decode_spike_features(buffer, spec)
¶
Decode buffer and return only the feature vector.
decode_spike_observation(buffer, spec)
¶
Decode buffer into a ControlObservation-compatible report.
Dispatch¶
Use scpn_mif_core.aer.dispatched_aer_spike_buffer(...) for the fastest
available measured ring-buffer backend:
The pure Python SpikeBuffer remains available for deterministic debugging and
tests. The rate decode also ships a Mojo surface (mojo/aer_decode_rate.mojo,
compiled with mojo build -Xlinker -lm): a subprocess CLI with bit-exact
parity — the decode is sequential integer-to-float accumulation with no
transcendental and no fused multiply-add. Its per-call process spawn places it
behind the in-process backends but ahead of the Julia CLI; like Julia it is a
measured/parity surface, not the runtime hot path. Parity-tested in
tests/unit/aer/test_decode_rate_mojo_parity.py.
Acceptance¶
The committed acceptance fixture is a local SHD-compatible AER stream with four channels, a 100 ns decode window, and five monotone events. Tests verify:
- exact rate feature vector
[0.02, 0.01, 0.0, 0.02]; - exact temporal feature vector
[1.0, 0.5, 0.0, 0.9]; - exact ISI feature vector
[0.05, 0.0, 0.0, 0.0125]; - deterministic ring-buffer overflow behaviour;
- fail-closed handling for non-monotone timestamps and out-of-range addresses;
- Python/Rust parity for the
u64timestamp domain and decode-window overflow; - Python/Rust parity through the PyO3 surface.
Benchmarks¶
Measured on the local i5-11600K rig using Python 3.12.3 and Rust 1.85.0. This
was a non-isolated workstation comparison with the CPU governor set to
powersave and nontrivial host load; treat it as regression evidence, not a
production latency claim.
| Group | Backend | Mean | Result |
|---|---|---|---|
push_256 |
Rust | 14.96 us | fastest |
push_256 |
Python | 288.97 us | 19.3x slower than Rust |
decode_256 |
Rust | 1.31 us | fastest |
decode_256 |
Python | 51.59 us | 39.5x slower than Rust |
Raw summaries: bench/results/aer_spike_buffer.json and
bench/results/aer_decode_rate.json.
Ownership¶
SYNC-STATE: upstream-pending applies to all MIF-006 implementation surfaces.
SCPN-MIF-CORE owns the local AER ingress adapter until SCPN-CONTROL receives
the reusable AERControlObservation surface targeted for the 0.21.0 lane.