Skip to content

Extract margin tapering and make chunk ownership explicit - #4887

Open
galenlynch wants to merge 1 commit into
SpikeInterface:mainfrom
galenlynch:refactor/chunk-margin-taper
Open

galenlynch wants to merge 1 commit into
SpikeInterface:mainfrom
galenlynch:refactor/chunk-margin-taper

Conversation

@galenlynch

Copy link
Copy Markdown
Contributor

get_chunk_with_margin can return a view of parent data when no padding or casting is needed. Moving tapering outside that helper therefore requires an explicit way to obtain a buffer that callers can safely modify.

This extracts a private _taper_margins(traces, window) helper and adds copy=True to both margin helpers. phase_shift requests an owned buffer and builds its raised-cosine window once per segment, reusing it across chunks. Existing window_on_margin=True behavior remains supported.

Split out from #4563 because the FIR implementation no longer depends on this refactor.

Validation: six focused tests pass, including exact agreement with the legacy FFT path for int16, float32, and float64 inputs, and checks that read-only parent arrays remain untouched at interior and boundary chunks.

Keep the taper private and accept a precomputed window so phase_shift can
reuse it across chunks. Add an explicit copy option to the margin helpers
so in-place tapering cannot modify parent data when no cast is needed.

Preserve the existing window_on_margin behavior and verify exact FFT
output and parent isolation for interior and boundary chunks.
@alejoe91 alejoe91 added the preprocessing Related to preprocessing module label Oct 22, 2026
@JoeZiminski
JoeZiminski self-requested a review October 23, 2026 14:57
@JoeZiminski

JoeZiminski commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Thanks @galenlynch this is very nice, will review next week (and the cool FIR phase shift implementation) but wanted to ask here because I was thinking about it recently - do you think how the get_data()/get_traces() handle returning a copy or view could be generally made more explicit in SpikeInterface? I was surprised to learn recently that get_traces() can return a view at all, but also a copy under some conditions.

e.g. this can happen:

cached = recording.save(format="memory", sharedmem=False)
traces = cached.get_traces(start_frame=0, end_frame=100)
traces[:] = 0  # Also zeros those samples in cached

(this mostly effects NumpyRecordings, fortunately binary data are read-only, but nonetheless this could be brittle if people test new features on simulated data and write operations in-place, then crashes on binary data when released).

It would be nice to enforce a copy at the root get_traces() body and then all consuming functions can safely assume the received traces is a copy. Otherwise, we may (and probably are) repeatedly copying data chunks through the preprocessing chain to protect against the possibility of receiving a view. WDTY? If you agree maybe we can promote the copy to the core get_traces() (this could happen later, after this PR is merged).

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

Labels

preprocessing Related to preprocessing module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants