Skip to content

Clarify docstrings in neuropixels_utils#3895

Merged
samuelgarcia merged 5 commits intoSpikeInterface:mainfrom
alejoe91:improve-np-utils-docs
May 7, 2025
Merged

Clarify docstrings in neuropixels_utils#3895
samuelgarcia merged 5 commits intoSpikeInterface:mainfrom
alejoe91:improve-np-utils-docs

Conversation

@alejoe91
Copy link
Member

@alejoe91 alejoe91 commented Apr 30, 2025

Fixes #3894

@billkarsh Do you mind taking a look? I believe that the main error and confusion point was in the use of num_channels_per_adc and its description

@chrishalcrow
Copy link
Member

Hello, is there some NeuroPixels documentation/manual which describes this stuff in more detail? Could we link to it?

@alejoe91
Copy link
Member Author

Hello, is there some NeuroPixels documentation/manual which describes this stuff in more detail? Could we link to it?

I couldn't find any good reference. Maybe @jsiegle and @billkarsh could provide some resources we could point at for the estimation of the channel inter sample shifts?

@billkarsh
Copy link

billkarsh commented Apr 30, 2025 via email

@billkarsh
Copy link

billkarsh commented Apr 30, 2025 via email

@jsiegle
Copy link
Contributor

jsiegle commented May 1, 2025

1.0 probes have 32 ADCs (each of which receives multiplexed input from 12 channels), while 2.0 probes have 24 ADCs (each of which receives multiplexed input from 16 channels). This is not explained anywhere in IMEC's public-facing documentation, as far as I'm aware.

The key piece of info for determining the sample shifts is knowing the order in which channels are sampled by a given ADC, rather than the total number of ADCs. And also keeping in mind that there are 13 cycles of digitization for the 1.0 probes (12 AP + 1 LFP), as Bill pointed out.

We created an illustration for the Open Ephys GUI documentation that may be helpful. Here, simultaneously sampled channels have the same color:

Neuropixels Sampling Pattern

@alejoe91
Copy link
Member Author

alejoe91 commented May 2, 2025

Thanks @jsiegle and @billkarsh!

I reverted the naming to num_channels_per_adc, which is correctly set to 12/16 for NP1/2 probes. The number of cycles (13 for NP1 and 16 for NP2) is also correct (both for Open Ephys and SpikeGLX).

@billkarsh I think that the mux table is super clear, but it is not available for older SpikeGLX versions and for Open Ephys. I checked a couple of muxTables entries in our test files and they correspond to the schema that Josh provided, which also corresponds to the "logic" implemented in the function:

# these correspond to the ADC#
adc_indices = np.floor(np.arange(num_channels) / (num_channels_per_adc * 2)) * 2 + np.mod(np.arange(num_channels), 2)

for adc_index in adc_indices:
    sample_shifts[adc_indices == adc_index] = np.arange(num_channels_per_adc) / num_cycles

I think this is correct for standard configurations, since np.nonzero(adc_indices == adc_index) results in the same mux table entries as some test files (e.g, this one). I'm not sure though if this logic is robust against custom configurations by the user or when only a subset of electrodes is selected.

@billkarsh how is the mux table generated by SpikeGLX? Is it retrieved by the probe registers or is there some logic in SpikeGLX to compute them? For the latter case, we can port the logic here to make sure it works for different SpikeGLX versions and for Open Ephys.

On the probeinterface side, we should are planning to sync all the NP info with ProbeTable repo. @billkarsh would it be possible to add the nGrp (i.e., num_channels_per_adc) to each entry? So we can propagate it to the metadata and read it from spikeinterface for each probe without hardcoding it.

@billkarsh
Copy link

billkarsh commented May 2, 2025 via email

@alejoe91
Copy link
Member Author

alejoe91 commented May 2, 2025

Thanks @billkarsh

If I understand correctly, then the mux tables are fixed and don't change if the user changes the selected electrodes.
Therefore:

  • whatever the user chooses as configuration the at-most 384 channels will be sampled by the ADCs as in the z_mux_tables
  • if a subset of channels are used, we can just slice the mux table values accordingly (e.g., if 100 channels are used, we'll take values until 100)

I think that then what I'll do is to refactor probeinterface to use this information and add the mux table index as an array annotation to the contact, so we can read it and compute the correct sample shift on the spikeinterface side.

Here is the issue on probeinterface: SpikeInterface/probeinterface#341

@alejoe91 alejoe91 added this to the 0.102.3 milestone May 2, 2025
@billkarsh
Copy link

billkarsh commented May 2, 2025 via email

@alejoe91 alejoe91 added the documentation Improvements or additions to documentation label May 3, 2025
@samuelgarcia samuelgarcia merged commit 8df701f into SpikeInterface:main May 7, 2025
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect assumptions in neuropixels_utils

5 participants