SpikeInterface / SpikeInterface/spikeinterface

scale(recording, gain) doesn't update "gain_to_uV" and "offset_to_uV" in BaseRecording

Open
#3,888 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

preprocessing question
Dominant language
Python
Stars
847
Forks
280
Avg merge
3d 9h
Merged PRs (30d)
29

Description

I noticed that the methods in spikeinterface/preprocessing/normalize_scale.py don't appear to keep track of a change to the gain or offset.

I understand that for most use cases it might not be useful to keep track of a change in offset (e.g., demeaning traces), but for scaling the traces, I think it would be helpful to keep track of the gain so that return_scaled=True is consistent.

For now the following code works for me:

rec_scaled = si.scale(recording, gain=scale_factor, offset=0.0)

new_gain   = recording.get_channel_gains()/scale_factor
rec_scaled .set_channel_gains(
    gains=new_gain, channel_ids=recording.get_channel_ids())

Interestingly, scale_to_uV() does update the gain and offset, so return_scaled=True is consistent:

def scale_to_uV(recording: BasePreprocessor) -> BasePreprocessor:
    [...]

    scaled_to_uV_recording.set_channel_gains(gains=1.0)
    scaled_to_uV_recording.set_channel_offsets(offsets=0.0)

    return scaled_to_uV_recording

https://github.com/SpikeInterface/spikeinterface/blob/cb83327c192f16d65698994f710c3c005384b4df/src/spikeinterface/preprocessing/scale.py#L37C1-L38C60

Nevertheless, I think it would be helpful if BaseRecording was able to keep track of how the data was scaled using any of the methods in normalize_scale.py.

Where I think scaling is useful, and where I plan to use it, is to utilize more of the int16 bit range.

The ADC in Neuropixels 1.0 is 10-bits, and Neuropixels 2.0 is 12-bits. This means you can scale NP1 by 64x and NP2 by 16x with no worries of clipping when casting back to int16.

Given that most pre-processing is done after casting to float32, but it makes sense to cast back to int16 before writing to disk, I think scaling after pre-processing but before casting back to int16 makes a lot of sense.

What are your toughts?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in spikeinterface/preprocessing/normalize_scale.py and compare the scaling methods with scale_to_uV() in scale.py, which updates channel gains and offsets. Trace how BaseRecording exposes get_channel_gains(), set_channel_gains(), and return_scaled=True. Done means scaling preserves consistent gain and offset metadata so returned scaled traces reflect the transformation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.