Recorder, viewer and replay API¶
recorder.open() returns a Recorder. The class is not part of the public API (not in
frames2py.recorder.__all__); it is documented here because open() returns one. See Recorder,
Viewer and Replay.
frames2py.recorder.open ¶
open(path: str | PathLike[str], *, sensor_size: tuple[int, int], group: str = 'events', compression: str | None = 'blosc', overwrite: bool = False) -> Recorder
Start a recording at path; events go in with write(), and close() finishes it.
The recording is written to a temporary file next to path and moved onto path only once it is complete.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The recording to create. |
required |
sensor_size
|
tuple[int, int]
|
|
required |
group
|
str
|
The HDF5 group that holds the datasets. |
'events'
|
compression
|
str | None
|
|
'blosc'
|
overwrite
|
bool
|
Replace an existing file at path when the recording is complete. Otherwise an existing file is an error. |
False
|
Raises:
| Type | Description |
|---|---|
ImportError
|
h5py or hdf5plugin is not installed ( |
TypeError
|
path is not a str or path, group not a str, overwrite not a bool, or sensor_size doesn't hold ints. |
ValueError
|
sensor_size is not a pair of positive ints, compression is not one of the three, or group is not a valid group name. |
FileExistsError
|
path exists and overwrite is false. |
IsADirectoryError
|
path is a directory. |
FileNotFoundError
|
path's directory doesn't exist. |
PermissionError
|
the directory can't be written. |
Recorder ¶
An open recording. write() adds events; close() or leaving the with block
finishes it.
write() runs on the caller's thread, compression and file writes included; the
recorder starts no thread. Events are kept in a buffer of at most one chunk until a
chunk is full, so a file's bytes depend only on the events written, not on how they were
split across calls.
close() writes the buffered events, closes the file and moves it onto the target
path. Leaving the with block through an exception, KeyboardInterrupt included,
closes it the same way: the recording then holds every event of every completed
write() call, plus a prefix, possibly empty, of the events of a call the exception
interrupted. A process that is killed or loses power leaves only the temporary file,
which is not a valid recording.
write ¶
Record one call's events, in order, exactly as given.
Raises TypeError for a malformed array and ValueError if any event has
t >= 2**63 (nothing of the call is recorded) or if the recorder is closed.
close ¶
Finish the recording and move it onto the target path. Closing twice is a no-op.
Raises FileExistsError if overwrite is false and a file appeared at the
target after open(); the finished recording is then left at the temporary path
the message names. If finishing the file fails, the temporary file is removed and
the error raised.
frames2py.viewer.render ¶
The snapshot as a new (height, width, 3) uint8 RGB image.
Reads snapshot.frame and snapshot.meta and never writes either. The mapping
follows the frame's dtype and shape, which are fixed per kernel:
(H, W)uint32 (event_count) and(H, W)float32 (exp_decay,timestamp_decay): grey,floor(255 * min(v, s) / s).(H, W, 2)uint32 (polarity; channel 0 OFF, channel 1 ON): OFF in blue, ON in red and green (yellow), both white, eachfloor(255 * min(v, s) / s).(H, W)uint64 (time_surface):floor(255 * max(0, 1 - (T - v) / window_us))withTthe snapshot's watermark;v == 0, no event yet, is black.
s is scale when given. With scale=None it comes from the frame's nonzero values
(both channels together for polarity): their maximum if there are fewer than 100,
otherwise their 99th percentile (NumPy's default linear interpolation, in float64).
Values above s show at full brightness. A frame with no nonzero value is black.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
snapshot
|
Snapshot
|
A published snapshot, such as |
required |
scale
|
float | None
|
The value shown at full brightness, or |
None
|
window_us
|
float
|
For |
50000
|
Raises:
| Type | Description |
|---|---|
TypeError
|
snapshot is not a |
ValueError
|
scale or window_us is not a finite positive number. |
frames2py.viewer.run ¶
run(source: Source, *, interval_ms: float = 16.0, title: str = 'Frames2Py', scale: float | None = None, window_us: float = 50000) -> None
Show the snapshots source returns in a window until the window is closed.
Once per interval_ms the viewer calls source, typically engine.snapshot, and,
when the publication is not the one it last showed, renders it with render(); a
None shows black. The window is as large as the frame. The viewer runs entirely on
the calling thread, which must be the main thread; it starts no thread. Run the producer
on a thread of its own.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Source
|
Called once per interval; returns a |
required |
interval_ms
|
float
|
How often to read source, in milliseconds. |
16.0
|
title
|
str
|
The window title. |
'Frames2Py'
|
scale
|
float | None
|
Passed to |
None
|
window_us
|
float
|
Passed to |
50000
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
called from a thread other than the main thread. |
ImportError
|
pyglet is not installed ( |
ValueError
|
interval_ms, scale or window_us is not a finite positive number. |
frames2py.replay.paced ¶
paced(batches: Iterable[EventArray], *, speed: float = 1.0, clock: Callable[[], int] = time.monotonic_ns, sleep: Callable[[float], Any] = time.sleep) -> Iterator[EventArray]
Yield each batch of batches, unchanged, once its timestamps say it is due.
The first nonempty batch sets the start: its smallest timestamp t0 and the clock's
reading when it arrives. M is the largest timestamp seen so far, the batch about to
be yielded included. A batch is yielded once the clock has advanced
(M - t0) / speed µs (rounded up to a whole ns) past the start. Timestamps are never repaired and no reset is
inferred; a discontinuity is the caller's to handle. A batch whose timestamps go back
leaves M where it was and is yielded without waiting; a jump forward makes the
batch, and the ones after it, wait for it. Empty batches are yielded at once. A
consumer slower than the recording gets every batch late; nothing is skipped to catch
up.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batches
|
Iterable[EventArray]
|
|
required |
speed
|
float
|
Replay rate relative to the recording; 2 is twice as fast. |
1.0
|
clock
|
Callable[[], int]
|
Nanoseconds, monotonic. Injectable for tests. |
monotonic_ns
|
sleep
|
Callable[[float], Any]
|
Waits the given seconds. Injectable for tests. |
sleep
|
Raises:
| Type | Description |
|---|---|
ValueError
|
speed is not a finite number above 0 (on the call). |
TypeError
|
a batch is not an |