1- Neuropixels format readers: catalogue construction and recording-specific wiring
2- =================================================================================
1+ The Neuropixels catalogue pattern
2+ =================================
33
44.. currentmodule :: probeinterface
55
@@ -63,30 +63,31 @@ and produce a probe ready to use with SpikeInterface:
6363 Neuropixels 1.0, ``NP2000 `` for Neuropixels 2.0 single-shank, ``NP2014 ``
6464 for Neuropixels 2.0 4-shank
6565
66- The first three readers identify the actual probe stock-keeping unit (SKU)
67- from the recording metadata. SpikeGadgets is the exception: its ``.rec `` XML
68- does not carry a part number field, so the reader cannot identify the SKU.
69- It picks one representative per geometry-equivalent family (all Neuropixels
70- 1.0 staggered variants share contact positions; all Neuropixels 2.0
71- single-shank variants share contact positions; all Neuropixels 2.0 4-shank
72- variants share contact positions) and clears the ``model_name ``,
73- ``description ``, and ``part_number `` annotations on the returned probe so
74- downstream code does not read the stand-in as an attribution.
66+ The first three readers read the part number directly from the recording
67+ metadata. SpikeGadgets is the exception: its ``.rec `` XML does not carry a
68+ part number field, so the reader cannot know which specific variant produced
69+ the recording. It picks one representative per geometry-equivalent family
70+ (all Neuropixels 1.0 staggered variants share contact positions; all
71+ Neuropixels 2.0 single-shank variants share contact positions; all
72+ Neuropixels 2.0 4-shank variants share contact positions) and clears the
73+ ``model_name ``, ``description ``, and ``part_number `` annotations on the
74+ returned probe so downstream code does not read the stand-in as an
75+ attribution.
7576
7677
7778From catalogue probe to probe in a recording setup
7879--------------------------------------------------
7980
80- The catalogue probe is pure geometry, divorced from any session. A real
81+ The catalogue probe is pure geometry, divorced from any recording session. A real
8182recording uses only a subset of those contacts: the Neuropixels headstage
8283acquires 384 channels at a time, and the recording configuration selects
8384which catalogue contacts those 384 are drawn from (384 of 960 on Neuropixels
84851.0, 384 of 1280 per shank on Neuropixels 2.0 single-shank, 384 of 5120 on
8586Neuropixels 2.0 4-shank). The selection mechanism differs by recording
8687format (an IMRO table for SpikeGLX, a channel map in ``settings.xml `` for
87- Open Ephys, the ``SpikeNTrode `` list in SpikeGadgets's ``.rec `` XML); the
88- "Matching catalogue contacts to recorded data" section below covers each
89- case. On top of the selection, the recording adds session-specific state:
88+ Open Ephys, the ``SpikeNTrode `` list in SpikeGadgets's ``.rec `` XML); each
89+ reader's docstring covers the specifics for that format. On top of the
90+ selection, the recording adds session-specific state:
9091per-contact analog band (AP) and local field potential (LFP) gains, ADC
9192sample order, reference configuration, and the channel-to-file mapping that
9293says where each contact's data lives in the saved binary. Probeinterface
@@ -98,7 +99,7 @@ Each reader produces the recording-setup probe in the same three steps:
98991. Build the catalogue probe by calling
99100 :py:func: `build_neuropixels_probe(part_number) <build_neuropixels_probe> `
100101 with the part number obtained from the recording metadata.
101- 2. Slice the catalogue probe to the active electrodes for this session via
102+ 2. Slice the catalogue probe to the active electrodes for this recording session via
102103 :py:meth: `probe.get_slice(active_indices) <Probe.get_slice> `. The slice
103104 drops the unrecorded contacts but preserves the probe-level annotations
104105 and the per-contact catalogue annotations (ADC group, sample order) on the
@@ -109,35 +110,6 @@ Each reader produces the recording-setup probe in the same three steps:
109110 to record where each surviving contact's data lives in the saved file.
110111
111112
112- Matching catalogue contacts to recorded data
113- --------------------------------------------
114-
115- The catalogue-build step is the same across readers; the matching step is
116- where the formats differ. ``active_indices `` and ``device_channel_indices ``
117- come from a different field in each metadata source:
118-
119- * **SpikeGLX: ** ``active_indices `` is the electrode list parsed from the IMRO
120- table embedded in the ``.ap.meta `` file. ``device_channel_indices `` is
121- identity (``np.arange(n) ``) because SpikeGLX writes one column per active
122- electrode in IMRO selection order.
123- * **Open Ephys: ** ``active_indices `` is the electrode list parsed from the
124- ``CHANNELS `` block in ``settings.xml ``. ``device_channel_indices `` follows
125- the order the binary stream uses, which the same XML file describes.
126- * **IMRO (standalone): ** ``active_indices `` is parsed directly from the IMRO
127- entries. There is no recording to wire to, so :py:func: `read_imro ` returns
128- the sliced probe without setting ``device_channel_indices ``; callers that
129- have a corresponding ``.ap.bin `` use :py:func: `read_spikeglx ` instead.
130- * **SpikeGadgets: ** ``active_indices `` is the list of ``SpikeNTrode ``
131- electrodes from the ``.rec `` XML, remapped from Trodes' ``channelsOn `` bit
132- order to the catalogue's contact order (an identity remap for Neuropixels
133- 1.0; a row-major-to-shank-major remap for Neuropixels 2.0 4-shank; a
134- per-row column swap for Neuropixels 2.0 single-shank).
135- ``device_channel_indices `` is the ``hwChan `` attribute on each
136- ``SpikeNTrode ``, which happens to coincide with the column index in the
137- SpikeGadgets datalogger's binary stream because the firmware writes samples
138- in ``hwChan `` ascending order.
139-
140-
141113What the pattern solves
142114-----------------------
143115
@@ -161,7 +133,7 @@ before the catalogue pattern) had three problems:
161133 probe directly hid the fact that 576 catalogue contacts were silently
162134 dropped. The explicit ``probe.get_slice(active_indices) `` step makes the
163135 selection visible and inspectable: callers can ask "which catalogue
164- contacts did this session record?" and get a direct answer.
136+ contacts did this recording session record?" and get a direct answer.
165137
166138The pattern also pays out on the upgrade path. When IMEC ships a new probe
167139variant, the integration work is "add the part number to ProbeTable, re-run
0 commit comments