-
Notifications
You must be signed in to change notification settings - Fork 49
Document the Neuropixels catalogue pattern #443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
alejoe91
merged 10 commits into
SpikeInterface:main
from
h-mayorquin:add_catalogue_recording_split_docs
Jun 8, 2026
Merged
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d5e8b78
add catalogue-recording pattern documentation
h-mayorquin f879ed0
document
h-mayorquin a4a0d01
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 5db34fd
spelling
h-mayorquin c94e60b
Merge remote-tracking branch 'refs/remotes/origin/add_catalogue_recor…
h-mayorquin 852fc67
title
h-mayorquin ce65555
bette structure
h-mayorquin 1c77f72
perfect muack done
h-mayorquin 24b972b
Merge branch 'main' into add_catalogue_recording_split_docs
h-mayorquin c2bb5b5
Apply suggestion from @alejoe91
alejoe91 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| The Neuropixels catalogue pattern | ||
| ================================= | ||
|
|
||
| .. currentmodule:: probeinterface | ||
|
|
||
|
|
||
| Two kinds of Neuropixels probe | ||
| ------------------------------ | ||
|
|
||
| Probeinterface distinguishes two kinds of Neuropixels probe. | ||
|
|
||
| **Catalogue probe.** The probe as it appears in the IMEC catalogue, with | ||
| every contact on the silicon present (960 on Neuropixels 1.0, 1280 per | ||
| shank on Neuropixels 2.0). Built via :py:func:`build_neuropixels_probe(part_number) | ||
| <build_neuropixels_probe>`. It carries: | ||
|
|
||
| * contact positions | ||
| * shank contour and dimensions | ||
| * contact shapes and sizes | ||
| * the analog-to-digital converter (ADC) multiplexer (MUX) routing on the | ||
| silicon | ||
| * identity metadata (manufacturer, model name, part number, description) | ||
|
|
||
| A catalogue probe is pure geometry, the same for every recording made with | ||
| that variant. Use it to plot the probe layout, compute distances between | ||
| contacts, or run any analysis that does not depend on a specific recording. | ||
|
|
||
| **Recording-setup probe.** The catalogue probe specialised for one | ||
| recording session: only the contacts actually recorded are present | ||
| (typically 384 of the 960 or more catalogue contacts), and per-contact | ||
| recording state is attached: | ||
|
|
||
| * per-contact analog band (AP) and local field potential (LFP) gains | ||
| * reference configuration | ||
| * per-contact sampling order | ||
| * probe wiring (the mapping from each contact to the recording channel | ||
| that captured its data) | ||
|
|
||
| Use a recording-setup probe to hand the recording to SpikeInterface so | ||
| spike sorters see both the geometry and the correct channel mapping, to | ||
| convert raw samples to microvolts via the per-contact gains, or to plot | ||
| the recorded contacts alongside the recorded traces. | ||
|
|
||
|
|
||
| The catalogue source | ||
| -------------------- | ||
|
|
||
| A probe part number (SKU) is an IMEC identifier such as ``"NP1000"``, | ||
| ``"NP2000"``, or ``"NP2014"``. The part number determines the silicon | ||
| geometry: 960 contacts on Neuropixels 1.0, 1280 per shank on Neuropixels | ||
| 2.0, plus all the per-variant pitch and shank dimensions. | ||
|
|
||
| The data behind the catalogue comes from the | ||
| `ProbeTable <https://github.com/billkarsh/ProbeTable>`_ repository maintained | ||
| by `Bill Karsh <https://github.com/billkarsh>`_ (author of SpikeGLX). | ||
| ProbeTable is the canonical machine-readable inventory of IMEC Neuropixels | ||
| probe specifications, all keyed by part number. | ||
|
|
||
|
|
||
| Format readers | ||
| -------------- | ||
|
|
||
| A format reader turns a Neuropixels recording into a recording-setup probe | ||
| in three steps: | ||
|
|
||
| 1. **Fetch the catalogue probe.** Look up the probe part number (SKU) in | ||
| the recording's metadata, then call | ||
| :py:func:`build_neuropixels_probe(part_number) <build_neuropixels_probe>`. | ||
| 2. **Identify the active electrodes.** Read the recording's channel | ||
| configuration to find which catalogue contacts were actually recorded, | ||
| and slice the catalogue probe down to that subset via | ||
| :py:meth:`probe.get_slice(active_indices) <Probe.get_slice>`. | ||
| 3. **Attach the recording-setup metadata.** Add the per-contact gains, | ||
| reference settings, and sampling order, and set the probe wiring. | ||
|
|
||
| The four readers in probeinterface differ in step 1: where they look up the | ||
| part number in the recording's metadata. | ||
|
|
||
| .. list-table:: | ||
| :header-rows: 1 | ||
| :widths: 30 30 40 | ||
|
|
||
| * - Reader | ||
| - Input | ||
| - Where the part number comes from | ||
| * - :py:func:`read_spikeglx` | ||
| - SpikeGLX ``.ap.meta`` (plus the ``.ap.bin`` it describes) | ||
| - ``imDatPrb_pn`` field in the meta file | ||
| * - :py:func:`read_openephys_neuropixels` | ||
| - Open Ephys ``settings.xml`` (plus the binary stream it describes) | ||
| - ``probe_part_number`` attribute in the XML | ||
| * - :py:func:`read_imro` | ||
| - SpikeGLX IMRO (Imec ReadOut) table file (``.imro``) | ||
| - First field of the IMRO header: a part number directly (new SpikeGLX | ||
| format) or a legacy numeric type code translated to a part number via | ||
| the catalogue mapping (old format). See SpikeGLX issue | ||
| `#432 <https://github.com/SpikeInterface/probeinterface/issues/432>`_ | ||
| for the format transition. | ||
| * - :py:func:`read_spikegadgets_neuropixels` | ||
| - SpikeGadgets ``.rec`` XML header | ||
| - Not present in the file; the reader picks a geometry-equivalent | ||
| stand-in based on ``(SpikeConfiguration.device, deviceSubType)``: | ||
| ``NP1000`` for Neuropixels 1.0, ``NP2000`` for Neuropixels 2.0 | ||
| single-shank, ``NP2014`` for Neuropixels 2.0 4-shank | ||
|
|
||
| The first three readers read the part number directly. SpikeGadgets is the | ||
| exception (its ``.rec`` XML does not carry a part number) and falls back to | ||
| a geometry-equivalent stand-in; the variants within each Neuropixels family | ||
| share identical 2D contact geometry, so any representative produces correct | ||
| positions. | ||
|
|
||
|
|
||
| What the pattern solves | ||
| ----------------------- | ||
|
|
||
| Building geometry from scratch inside each reader (the situation before this | ||
| pattern) caused three problems: | ||
|
|
||
| * **Drift across readers.** Each reader carried its own copy of the | ||
| manufacturer specs, and the copies could disagree. Centralising the | ||
| geometry in :py:func:`build_neuropixels_probe` and sourcing it from | ||
| ProbeTable means every reader returns the same positions for the same | ||
| part number. | ||
| * **Confused bugs.** When a saved recording looked wrong on the probe, it | ||
| was hard to tell whether the geometry was off or the channel-to-contact | ||
| mapping was off. With the two phases separated, a geometry bug is a bug | ||
| in :py:func:`build_neuropixels_probe`; a wiring bug is a bug in the | ||
| reader's slicing or wiring step. The two can be diagnosed independently. | ||
| * **Hidden electrode selection.** A reader that built a 384-contact probe | ||
| directly hid the fact that 576 catalogue contacts were silently dropped. | ||
| The explicit slice step makes the selection visible: callers can ask | ||
| which catalogue contacts the recording captured and get a direct answer. | ||
|
|
||
| The pattern also helps on the upgrade path. When IMEC ships a new probe | ||
| variant, the integration work is to add the part number to ProbeTable; the | ||
| readers do not change. | ||
|
|
||
|
|
||
| Discussion | ||
| ---------- | ||
|
|
||
| This pattern was proposed and is tracked in issue | ||
| `#405 <https://github.com/SpikeInterface/probeinterface/issues/405>`_. | ||
| Reopen the issue if you want to discuss changes. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.