SpikeInterface / SpikeInterface/spikeinterface
Proposal: Add anti-aliasing option to decimate()
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 847
- Forks
- 280
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 29
Description
DecimateRecording applies simple array slicing without an anti-aliasing (AA) filter:
"""
class DecimateRecording(BasePreprocessor):
Decimate the recording extractor traces using array slicing
Important: This uses simple array slicing for decimation rather than eg scipy.decimate.
This might introduce aliasing, or skip across signal of interest.
Consider spikeinterface.preprocessing.ResampleRecording for safe resampling.
...
"""
I'd like to add an "antialias" option to DecimateRecording:
- If
True, it would usescipy.decimate. - If
Trueanddecimation factor > 13, it would warn the user thatdecimate()should be called multiple times, with decimation factors as balanced as possible (e.g. for a total decimation factor of 48, a pass withq=8followed byq=6is preferable toq=12followed byq=4). I can see if there's a good way to handle this for the user, but I think it's impossible for theDecimateRecordingconstructor itself to chain togetherDecimateRecordings. Besides, this would be consistent with the behavior of the underlyingspicy.decimate(), which warns but does not refuseq > 13.- For consistency, I would add the same check and warning to the decimation path in
ResampleRecording.
- For consistency, I would add the same check and warning to the decimation path in
- If
True, a margin would be used to accommodate the AA filter, exactly as it is inResampleRecording. ResampleRecordingsays that decimation can "misbehave on some cases", and guards against this:
I would check for# Decimate can have issues for some cases, returning NaNs resampled_traces = signal.decimate(parent_traces, q=q, axis=0) # If that's the case, use signal.resample if np.any(np.isnan(resampled_traces)): resampled_traces = signal.resample(parent_traces, num, axis=0)NaNand warn the user if any are found. But in my experience, decimation only does this whenq > 13, so it could be dropped IMO. If there are other cases where this is known to happen, I would like to document them with a comment to justify the every-call overhead ofnp.any(np.isnan()).- I would make
antialias=Falsethe default, to preserve existing behavior.
One reason I'd like to do this is that antialiased decimation is currently provided by resample(), which does not take a decimation factor, just a target resample rate, and checks if np.mod(self._parent_rate, self._resample_rate) == 0 to determine whether antialiased decimation (vs FFT-based resampling) is done. The issue with this is that many integer decimation factors can't be achieved this way, because of float fragility. For example, with a parent rate of 625 Hz and a target rate of 125 Hz, np.mod(625, 125) == 0 correctly determines that this is an integer downsample factor of 5. But np.mod(625, 104.166666667) == 0 fails to detect a downsample factor of 6.
I would preserve the decimation path within ResampleRecording(), since it's still a free optimization, and preserves existing behavior.
If this sounds good, I'll submit a PR.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the DecimateRecording implementation and the decimation path in ResampleRecording, especially how ResampleRecording handles margins and scipy.decimate. Check the existing preprocessing tests and add coverage for the antialias option, large factors, and NaN handling. Done means preserving the default slicing behavior while supporting antialiased decimation with the proposed warnings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100