Skip to main content

EventStream

Struct EventStream 

Source
pub struct EventStream { /* private fields */ }
Expand description

A stream of events stored column-wise (struct-of-arrays). Columns compress and transform far better than interleaved rows, and timestamps use i64 (µs) so real multi-second recordings fit. See TASKS.md §3.

The columns are shared, not owned: a transform that rewrites one column hands the other three on untouched, and clone is four refcount bumps rather than a copy of the whole recording. Arc<Vec<T>> rather than Arc<[T]> because the latter cannot reuse a Vec’s allocation (the refcount header sits in the same block), so every EventStreamBuilder::build — every reader slice, every subsetting transform — would copy all four columns; and because Arc::make_mut gives copy-on-write for free on a Vec and is not available on an unsized [T].

Implementations§

Source§

impl EventStream

Source

pub fn event_rate(&self, bin_us: i64) -> EventRate

Bins the stream into fixed-width intervals of bin_us and counts events in each.

Bins span the stream’s own extent — from the earliest to the latest timestamp — so an empty stream produces no bins and a stream that does not divide evenly gets a final short bin that is still counted. A bin_us below 1 is clamped, since a zero-width bin has no rate.

Does not require sorted input: bins are indexed arithmetically from the minimum timestamp rather than by walking in order, so this is safe to call before sort_by_time.

Source§

impl EventStream

Source

pub fn random_flip_x(&self, p: f64, seed: u64) -> EventStream

Mirrors the stream left-right with probability p.

Source

pub fn random_flip_y(&self, p: f64, seed: u64) -> EventStream

Mirrors the stream top-bottom with probability p.

Source

pub fn random_polarity_flip(&self, p: f64, seed: u64) -> EventStream

Inverts every polarity with probability p.

Draws once for the stream, not once per event: flipping a random subset of polarities is label noise, whereas flipping all of them is the physically meaningful augmentation (the same scene with the contrast direction reversed).

Source

pub fn random_crop(&self, width: usize, height: usize, seed: u64) -> EventStream

Takes a random width × height crop. A window at least as large as the sensor is the identity, so this is safe to leave in a pipeline that also runs on smaller recordings.

Source

pub fn event_drop(&self, p: f64, seed: u64) -> EventStream

Drops each event independently with probability p, thinning the stream without changing its geometry or duration. p <= 0 is the identity; p >= 1 empties the stream.

Source

pub fn pixel_dropout(&self, p: f64, seed: u64) -> EventStream

Silences a random p fraction of pixels for the whole stream.

Unlike EventStream::event_drop, which thins events independently, this removes every event from the chosen pixels — the failure mode of a real sensor with dead pixels, and a much harder augmentation for a model to average away.

Source

pub fn spatial_jitter(&self, sigma: f64, seed: u64) -> EventStream

Jitters each event’s position by a rounded gaussian offset with standard deviation sigma pixels. Events pushed off the sensor are dropped, so a large sigma also thins the stream.

Source

pub fn time_jitter(&self, sigma: f64, seed: u64) -> EventStream

Jitters each event’s timestamp by a rounded gaussian offset with standard deviation sigma (same units as the stored timestamps, i.e. µs).

Re-sorts afterwards: jitter can reorder neighbouring events, and the correlation-based filters (background_activity_filter, refractory_filter) require ascending time.

Source

pub fn time_reversal(&self, p: f64, seed: u64) -> EventStream

Plays the stream backwards with probability p, inverting polarity to match.

Reversing time without inverting polarity would be physically wrong: an edge that brightened as it passed darkens when the same motion is run in reverse. Timestamps are mirrored within the stream’s own span, so the result starts and ends where the original did.

Source§

impl EventStream

Source

pub fn iwe( &self, model: WarpModel, params: &[f64], ) -> Result<EventFrame, CmaxError>

Accumulates the image of warped events for an explicit motion.

The picture the objective actually scores, returned so it can be looked at — a blurred IWE with the “right” parameters is the clearest sign that a warp model does not fit the scene.

Source

pub fn contrast_maximise( &self, model: WarpModel, config: CmaxConfig, ) -> Result<CmaxResult, CmaxError>

Finds the motion that makes the warped events sharpest.

Returns the recovered parameters along with the score at rest, so the caller can tell a real estimate from the optimiser wandering on a flat landscape — see CmaxResult::improvement.

Source§

impl EventStream

Source

pub fn efast(&self) -> EventStream

eFAST event corner detector (Mueggler et al., Fast Event-based Corner Detection, BMVC 2017). For each event it updates its polarity’s SAE, then tests two Bresenham rings (radius 3 and 4) around the pixel: an event is a corner when, on both rings, the most recent timestamps form a contiguous arc within the INNER_ARC/OUTER_ARC bounds — the signature of a moving corner rather than a straight edge. Events too close to the border to evaluate the outer ring are dropped. Returns the corner events as a new stream.

Source

pub fn harris_corners(&self, threshold: f64) -> EventStream

Harris corner score on the Surface of Active Events. For each event it updates a merged SAE of raw latest timestamps, then computes the normalised Harris response det(M)/trace(M)² - k of the structure tensor M = Σ ∇T ∇Tᵀ of the SAE’s spatial gradient over a 9×9 window. Because the SAE is a local time ramp, a straight moving edge has a constant gradient direction (rank-1 M, R < 0) while a corner mixes gradient directions (rank-2 M, R > 0) — so the default threshold = 0 keeps corners and rejects edges. The score is bounded to [-k, 0.25 - k] = [-0.04, 0.21], so raising threshold within that range is what makes it stricter; anything above 0.21 keeps nothing. Returns the corner events as a new stream; a score-based complement to Self::efast.

Source§

impl EventStream

Source

pub fn background_activity_filter(&self, dt: i64) -> EventStream

Background-activity (nearest-neighbour) noise filter. Keeps an event only if some pixel in its 3×3 neighbourhood fired within dt (raw timestamp units, as Self::time_window): uncorrelated noise, which has no recent neighbours, is dropped. Assumes ascending time.

See Self::background_activity_filter_with to use the 4-neighbour cross instead, which rejects uncorrelated noise more cleanly.

Source

pub fn background_activity_filter_with( &self, dt: i64, neighbourhood: Neighbourhood, ) -> EventStream

Source

pub fn refractory_filter(&self, dt: i64) -> EventStream

Refractory-period filter: after a pixel fires, suppress its events for dt (raw timestamp units). Keeps an event only when at least dt has elapsed since that pixel’s last kept event; dropped events do not refresh the dead time. Assumes ascending time.

That rule is RefreshOn::Kept, the hardware definition of a dead time. tonic and evlib instead restart the clock on every arriving event — see Self::refractory_filter_with to reproduce them.

Source

pub fn refractory_filter_with(&self, dt: i64, refresh: RefreshOn) -> EventStream

Self::refractory_filter under a chosen RefreshOn rule.

Source

pub fn hot_pixel_filter(&self, n_std: f64) -> EventStream

Hot-pixel removal: drops every event from stuck pixels whose total event count exceeds mean + n_std·std, with the mean and standard deviation taken over the active pixels (those with at least one event). A uniform or empty stream removes nothing.

Source

pub fn hot_pixel_mask(&self, n_std: f64) -> Vec<bool>

The hot-pixel mask this stream would remove: true at each pixel whose total event count exceeds mean + n_std·std (statistics over the active pixels), row-major width·height. Degenerate sensors give an empty mask. Exposed on its own so a reader can compute the mask once over a whole recording and apply it to every slice with Self::drop_masked_pixels — a per-slice hot_pixel_filter instead re-thresholds each window, so hot pixels survive at long accumulation times.

Source

pub fn add_pixel_counts(&self, counts: &mut [u64])

Adds this stream’s per-pixel event counts into counts (row-major width·height for this stream’s sensor); a mismatched buffer is left untouched. Lets a reader tally a whole recording chunk-by-chunk — feeding Self::hot_pixel_mask_from_counts — without ever materialising the full file, so the pre-scan stays within bounded memory.

Source

pub fn hot_pixel_mask_from_counts(counts: &[u64], n_std: f64) -> Vec<bool>

The hot-pixel mask for pre-tallied per-pixel counts: true where a count exceeds mean + n_std·std taken over the active (non-zero) pixels. All-zero counts flag nothing. The chunked-scan counterpart of Self::hot_pixel_mask.

Source

pub fn drop_masked_pixels(&self, mask: &[bool]) -> EventStream

Drops every event whose pixel is flagged true in mask (row-major width·height, as Self::hot_pixel_mask returns), keeping (x, y, p, t) and order. A mask that does not match the sensor grid (e.g. the empty mask of a degenerate sensor) removes nothing, so a reader can carry one whole-recording mask and apply it to every slice unconditionally.

Source§

impl EventStream

Source

pub fn optical_flow(&self, window: usize) -> Result<EventFrame, FlowError>

Estimates dense optical flow by Lucas-Kanade on the time surface. window is the half-width of the least-squares neighbourhood (a (2·window+1)² patch); it must be at least 1. Returns a two-channel f32 frame — channel 0 flow_x, channel 1 flow_y, in pixels/ms — zero wherever flow is undefined.

Source§

impl EventStream

Source

pub fn filter_polarity(&self, polarity: bool) -> EventStream

Keeps only events of the given polarity.

Source

pub fn invert_polarity(&self) -> EventStream

Flips every event’s polarity. Sensor and timestamps unchanged.

Source

pub fn sort_by_time(&self) -> EventStream

Returns a copy reordered by ascending timestamp (stable for equal timestamps).

Source

pub fn concat(&self, others: &[&EventStream]) -> EventStream

Concatenates several streams into one (in argument order, not time-sorted). The sensor size is the element-wise maximum of the inputs; the timestamp scale comes from self.

Source§

impl EventStream

Source

pub fn crop(&self, x0: i64, y0: i64, w: usize, h: usize) -> EventStream

Keeps events inside the w×h window at (x0, y0) and shifts them to a new origin. The result is a w×h stream.

Source

pub fn flip_x(&self) -> EventStream

Mirrors horizontally (x → width-1-x). Sensor size unchanged.

Source

pub fn flip_y(&self) -> EventStream

Mirrors vertically (y → height-1-y). Sensor size unchanged.

Source

pub fn rotate90(&self, k: i32) -> EventStream

Rotates by k * 90° clockwise. k is taken mod 4; quarter turns swap the sensor dims.

A quarter turn swaps the two coordinate columns before rewriting one of them, so it copies one column rather than four.

Source

pub fn transpose(&self) -> EventStream

Reflects across the main diagonal ((x, y) → (y, x)); swaps the sensor dims.

Source

pub fn translate(&self, dx: i64, dy: i64) -> EventStream

Translates by (dx, dy); events shifted off the sensor are dropped. Sensor unchanged.

Source

pub fn resize(&self, w: usize, h: usize) -> EventStream

Resizes the sensor grid to w×h, rebinning each coordinate proportionally (floored — the destination bin, no interpolation). Every event maps into [0, w)×[0, h), so the count is conserved; on downscale several events may share a pixel (lossless).

Source

pub fn scale(&self, sx: f64, sy: f64) -> EventStream

Scales the sensor by (sx, sy), rounding the new dimensions. See Self::resize.

Source

pub fn warp_affine(&self, m: [[f64; 3]; 2]) -> EventStream

Applies a 2×3 affine matrix [[a,b,c],[d,e,f]] (x' = a·x+b·y+c, rounded). Sensor size unchanged; events warped off the sensor are dropped.

Source

pub fn warp_perspective(&self, m: [[f64; 3]; 3]) -> EventStream

Applies a 3×3 perspective (homography) matrix, dividing by the homogeneous coordinate. Events whose denominator is zero, or that warp off the sensor, are dropped.

Source

pub fn undistort(&self, camera: &Camera) -> EventStream

Rectifies events with a Camera’s intrinsics + distortion, mapping each event from its distorted pixel to the undistorted location on the same grid. Builds a per-pixel lookup once (the sensor grid is small), then remaps every event through it; events landing off the sensor after rectification are dropped. Sensor size unchanged.

Source

pub fn mask(&self, mask: &[bool], mask_w: usize, mask_h: usize) -> EventStream

Keeps only events where the mask_w×mask_h row-major boolean grid is true. Events outside the mask are dropped. Sensor size unchanged.

Source§

impl EventStream

Source

pub fn time_window(&self, t0: i64, t1: i64) -> EventStream

Keeps events whose timestamp lies in the half-open window [t0, t1).

In a time-ordered stream — what every reader and the simulator produce — the window is a contiguous range, so this is two binary searches and a slice rather than a predicate per event; a window covering the whole stream copies nothing at all. The scan that establishes the ordering is one pass over the timestamps and vectorises, and an unordered stream falls back to the general path rather than being silently mis-windowed.

Source

pub fn time_shift(&self, dt: i64) -> EventStream

Shifts every timestamp by dt (same units as the stored timestamps).

Source

pub fn time_scale(&self, factor: f64) -> EventStream

Scales every timestamp by factor (rounded), e.g. to change playback speed.

Source

pub fn normalize_time(&self) -> EventStream

Shifts timestamps so the earliest event starts at zero. A no-op on an empty stream.

Source

pub fn decimate(&self, k: usize) -> EventStream

Keeps every k-th event by index (k = 1 is the identity); k = 0 is treated as 1.

Source§

impl EventStream

Source

pub fn len(&self) -> usize

Source

pub fn is_empty(&self) -> bool

Source

pub fn sensor_size(&self) -> (usize, usize)

Source

pub fn timestamp_scale_ms(&self) -> f64

Source

pub fn xs(&self) -> &[u16]

Source

pub fn ys(&self) -> &[u16]

Source

pub fn ts(&self) -> &[i64]

Source

pub fn ps(&self) -> &[bool]

Source

pub fn iter(&self) -> impl Iterator<Item = Event> + '_

Source

pub fn to_array2(&self) -> Array2<u64>

Materialises an owned (N, 4) array of [x, y, t, p] rows for numpy interop.

Trait Implementations§

Source§

impl Clone for EventStream

Source§

fn clone(&self) -> EventStream

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for EventStream

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V