Repository navigation
Releases: siddiquifaras/frames2py
Release list
Frames2Py 1.1.0
Released 2026-10-07.
A release that adds to 1.0 without changing what 1.0 code does, apart from one fix (below):
waiting for a newer snapshot, two temporal representations for event-vision models, frames
at fixed steps of event time, and a tested recipe for handing snapshots to PyTorch.
pip install --upgrade frames2pyLicence
- Frames2Py is licensed under the Apache License, Version 2.0, from this release on.
1.0.0rc1 and 1.0.0 were published under the MIT License and stay under it: their files on
PyPI keep their MIT licence file and metadata. The licence text is in
LICENSE. - The package metadata and the copyright line name the author as Muhammad Faras Siddiqui.
New
-
Engine.wait_for_newer(sequence, *, timeout=None)blocks until a snapshot newer than
sequenceis published and returns the latest one, orNoneon timeout. It returns the
latest state, not every publication;stop()andreset()wake nobody; calling it on the
producer's thread raisesRuntimeError. Each publication releases the waiters registered
before it and never waits for one. With no waiter, a preregistered measurement on one
machine found no distinguishable cost toingest(); waiters do add work to each
publication. Details and figures:
Waiting for a newer snapshot. -
Two temporal kernels, exported from
frames2pyandframes2py.kernels:StackedHistogram(bins=..., bin_us=...):(2, bins, H, W)uint32, events per polarity
and time bin, as RVT consumes before its clip;VoxelGrid(bins=..., bin_us=...):(bins, H, W)float32, signed events split linearly
between time knots, as in E2VID and E-RAFT.
Both use bins on an absolute event-time grid and show only completed bins; they count
exactly in integers, give the same frame bit for bit whatever the order and batching of
the events, and apply no normalisation. They did not reach 20M events/s through the Engine
in every cell of their performance gate. Details:
Temporal kernels, the
semantics table and
Throughput. -
frames2py.replay.windows(batches, sensor_size, kernel, *, every_us)yields a frame
everyevery_usµs of event time from a recording's batches, deterministically and
independently of how the events are batched. It refusesExpDecay, whose result depends
on call boundaries. Details: Frames in event time. -
A PyTorch recipe: copy a snapshot, then
torch.from_numpy, with explicit dtype and
device handling, for every kernel. It is documentation tested in its own CI workflow;
Frames2Py has no PyTorch dependency, extra or code. Details:
Handing snapshots to PyTorch.
Changed
- Custom kernels:
read()may be given a later time.Kernel.read(state, out, watermark)may now receive a time later than the accumulated watermark, and must evaluate
the representation at it without changing the state. Onlyreplay.windows()does this;
AccumulatorandEnginestill pass the accumulated watermark, so a custom kernel used
through them behaves as in 1.0. The seven built-in kernels follow the rule. Details:
Custom kernels.
Fixes
- The producer check follows the thread, not its thread ident. CPython can give a new
thread the ident of one that has exited. Since 1.0,ingest()from a thread started after
the producer exited was accepted when that thread got the producer's ident; it now raises
RuntimeError, as documented, and such a thread may callwait_for_newer(). One case
remains on CPython 3.11 and 3.12, for threads created outsidethreading:
Known limitations.
Documentation
- The consumer pattern now waits with
wait_for_newer(), with polling as the alternative
for consumers on their own clock. SnapshotMeta.sequenceis described as strictly increasing, as the contract promises,
not as increasing by one per publication: a consumer can tell that it skipped
publications, not how many.- New: the temporal kernel semantics table, the measured cost of waiting, the results of the
v1 observation study (with its scope: one machine, one workload, threads in one process),
and a Known limitations section. - New data files in
benchmarks/results/: the temporal-kernel gate's two runs, the
wait_for_newermeasurement and the observation study's per-configuration table. - Diagrams: Frames2Py's arrangement next to two coupled pipelines on the
overview, waiting against polling under
Waiting for a newer snapshot,
and the temporal kernels' bins and closing time in the
semantics table. - An end-to-end notebook,
examples/live_observation.ipynb:
a live Engine on a synthetic stream, independent consumers waiting with
wait_for_newer(), one of them deliberately slow, areset(), and a modest analysis.
It runs from a checkout with the newnotebookdependency group, which is not a
dependency or an extra of the package. - CONTRIBUTING.md
and SECURITY.md, also
shown under Development in the documentation. - The README shows badges for CI on
main, the licence, the supported Python versions and
platforms, and the version on PyPI.
Maintenance
- CI also runs once a month on
main, including a job that installs the newest NumPy,
extras and CPython builds instead of the lockfile's. - A separate
notebook.ymlworkflow runs the end-to-end notebook against the built wheel. - The build backend is pinned to exactly
uv_build==0.12.20(1.0 allowed
>=0.12.20,<0.13), so building from the sdist uses the backend the release was built and
checked with.
Upgrading from 1.0
Nothing needs to change. The event contract, the five 1.0 kernels and their outputs,
Accumulator, Engine (ingest(), snapshot(), stats, the cadence and the
lifecycle), Snapshot and the publisher, the adapters, the recorder, paced() and the
viewer behave as in 1.0, apart from the producer-check fix above. The supported Python
versions and platforms and the NumPy floor are unchanged;
Supported Python and platforms.
- The licence changes from MIT to Apache 2.0 (above).
- On free-threaded CPython 3.14t, 3.14.5 or later is now recommended: 3.14.0 to 3.14.4 have
a CPython race that can end the process
(Free-threaded CPython). - A custom kernel you want to use with
replay.windows()must handle aread()time later
than its own watermark (above). - Two internal changes speed up 1.0 paths without changing their results: the Accumulator
reuses the timestamp maximum of the range check, andTimestampDecaycomputes its
exponentials in place. The v1 performance figures were measured before 1.0.0, on commit
6a0fa27, and were not re-measured on 1.1. - Cross-process snapshots are not part of 1.1.
Frames2Py 1.0.0
The first stable release. The code is that of 1.0.0rc1, which was installed from PyPI and
checked before this release. What changed: the version, the Development Status classifier
(now 5 - Production/Stable), and the documentation, which drops its release-candidate
install notes. From 1.0.0 on, the public API is stable: changing it incompatibly needs a 2.0.
pip install frames2pyWhat the release contains, from the core and its five kernels to the adapters, recorder,
replay and viewer, is listed under
1.0.0rc1.
Frames2Py 1.0.0rc1
The first release of Frames2Py, published to PyPI as a release candidate for 1.0.0. Its API
is the one intended for 1.0.0; 1.0.0 follows once this candidate has been checked as
installed from PyPI.
Installing the release candidate. pip and uv skip pre-releases such as 1.0.0rc1 when a
stable release exists, and install one only when none does. So while 1.0.0rc1 is the only
release, pip install frames2py installs it; once 1.0.0 is published, it installs 1.0.0. To
ask for the release candidate explicitly:
pip install frames2py==1.0.0rc1
pip install --pre frames2py # the newest release, pre-releases includedEverything below is new in this release.
Core
Engine: the live runtime. One producer thread callsingest(); any number of consumers
callsnapshot()and readstatsfrom other threads, and the producer never waits for
them. Publication happens at most once persnapshot_interval_ms(16 ms by default; 0
publishes on every call), only insideingest()andstop().start(),stop()and
reset()manage the lifecycle.Accumulator: the same accumulation, synchronous, with no publication or threads.- Snapshots (
frames2py.publish.Snapshot): a frame and its metadata (watermark,
sequence) from one publication. The frame is shared by every consumer and marked
read-only;copy()returns an independent writable copy. - The event contract:
EVENT_DTYPE(tuint64 µs,xandyuint16,puint8),
structural validation (TypeError), whole-call rejection of anyt >= 2**63
(ValueError), and out-of-bounds events counted instead of accumulated. - The
Kernelprotocol (frames2py.kernels.Kernel) and theSnapshotPublisherprotocol
(frames2py.publish) are public.
Details: Engine,
Event contract,
Snapshots and consumers.
Kernels
| kernel | output | mode |
|---|---|---|
event_count |
(H, W) uint32 | windowed; counts wrap modulo 2^32 |
polarity |
(H, W, 2) uint32 | windowed; channel 0 OFF, channel 1 ON |
time_surface |
(H, W) uint64 | running; the latest timestamp per pixel |
ExpDecay(decay) |
(H, W) float32 | running; decays once per call, so it depends on batching |
TimestampDecay(tau_us) |
(H, W) float32 | running; decays with event time, independent of batching |
Details: Kernels.
Data and consumers
Each of these is an optional extra; import frames2py needs NumPy only.
frames2py.adapters.evt(frames2py[evt]): EVT 2.0 and 3.0 (Prophesee RAW), decoded by
Frames2Py's own NumPy decoder, with no further dependency.frames2py.adapters.aedat4(frames2py[aedat4]): AEDAT 4.0 through dv-processing.frames2py.adapters.hdf5(frames2py[hdf5]): HDF5 files with 1-Dt,x,y,p
datasets, through h5py and hdf5plugin.frames2py.recorder(frames2py[recorder]): writes events to HDF5, called next to
ingest()by your own loop; the Engine never calls it.frames2py.replay.paced(): yields a recording's batches at their recorded pace.frames2py.viewer(frames2py[viewer], pyglet):render()turns a snapshot into an RGB
image;run()shows an Engine in a window.
There are no vendor SDK adapters: SDK output enters through EVENT_DTYPE. Details:
Adapters.
Python and platforms
CPython 3.11 to 3.14, and free-threaded CPython 3.14t with the GIL disabled, on Linux
x86_64, Linux ARM64 and macOS ARM64, with NumPy 2.4 or newer. Other free-threaded minor
versions with the GIL disabled are refused: Engine(...) raises RuntimeError. The wheel is
pure Python (py3-none-any). What CI tests on which platform:
Supported Python and platforms.
Performance
On one Apple M4 (16 GB), the v1 performance gate measured all 150 of its cells above 20M
events/s, on CPython 3.11 and free-threaded 3.14t. No other hardware has been measured.
The cells, the method and the caveats:
Performance.