Skip to content

Blackrock: stop dropping NEV spikes and events at segment edges (1 ns timestamps) - #1925

Open
cboulay wants to merge 1 commit into
NeuralEnsemble:masterfrom
cboulay:nev-timestamp-slice-float-seconds
Open

cboulay wants to merge 1 commit into
NeuralEnsemble:masterfrom
cboulay:nev-timestamp-slice-float-seconds

Conversation

@cboulay

@cboulay cboulay commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

For a multi-segment .nev, BlackrockRawIO clipped spikes and events to the segment's time window: the bounds were float seconds converted back to ticks, then compared with np.searchsorted (which compares uint64 with a Python int as float64). Float64 seconds at 1.75e9 (PTP files, 1 ns resolution) are only precise to about 240 ns, so items at a segment's edge were kept or dropped by rounding. spike_count/event_count used the same window and could disagree with get_spike_timestamps. Non-PTP files (30 kHz ticks) are not affected.

On the NEV of blackrock_ptp_with_missing_samples opened alone (4 segments), 4 of 999 spikes were lost, with and without explicit bounds. Converting explicit bounds to exact integer ticks does not fix it (5 lost), because the rounding is in the float seconds the caller passes.

Changes:

  • Without t_start/t_stop, items are selected by segment id alone (the getters already did), and spike_count/event_count do the same.
  • With explicit bounds, timestamps are compared as float64 seconds, the same values neo reports, so a time taken from neo (e.g. segment_t_start) selects the item it came from.
  • t_stop stays exclusive. This is now documented, with the advice to pass t_stop + 1e-5 to include an item at t_stop (the old +1 tick in the default path was a no-op at 1 ns).

The new test checks every unit of every segment of that file against the segment ids, with and without bounds, and fails on the old code.

Found while working on Blackrock reading with Colin McNabb at Blackrock Neurotech.

…nts by id

At the 1 ns timestamp resolution of PTP files, spikes and events at the edge of a
segment were kept or dropped by rounding: the segment bounds went through float
seconds back to ticks, and np.searchsorted compared uint64 timestamps with a Python
int as float64. spike_count and event_count used the same window and could
disagree with the timestamps returned.

Without t_start/t_stop, items are selected by segment id alone, as the getters
already did, and the counts select the same way. Explicit bounds are compared with
the times neo reports (timestamps as float64 seconds), so a bound taken from neo,
such as segment_t_start, selects the item it came from. t_stop stays exclusive;
documented, with the advice to pass t_stop + 1e-5 to include an item at t_stop.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant