ndx-extracellular-channels
is an extension of the NWB format to formally define information about neural probes as data types in NWB files. It comes with helper functions to easily construct ndx_extracellular_channels.Probe
from probeinterface.Probe
and vice versa.
It provides a new version of ElectricalSeries
called ExtracellularSeries
. Each ExtracellularSeries
is associated with its own ChannelsTable
that contains information about the channels and probe used to record the data. Each channel is mapped to contacts on the probe.
Use cases supported:
- Storing the manufacturer, model, and serial number of the probe
- Storing the size, shape, shank ID, and relative position of the contacts
- Associating a channel with a contact on a probe
- Storing multiple data streams (channels) from the same contacts on a probe, e.g., AP and LF bands from a Neuropixels probe
- Storing a selection of channels from a probe, e.g., the probe model has 960 contacts and only 384 are used
- Bipolar reference schemes, e.g., channel 1 is defined as the signal from contact 2 referenced to contact 1
- Storing precise information about the probe insertion position and orientation, separate from the targeted position and reconstructed position
- Storing separate channel tables for different data streams instead of a global channel table, which avoids creating columns that apply only to some streams
- Multiple instances of the same probe in the same file, e.g., a Neuropixels probe in the left and right hemispheres
It encompasses SpikeInterface's ndx-probeinterface
extension and started originally as @D1o0g9s's ndx-probe-interface extension.
(TODO publish to PyPI)
pip install ndx_extracellular_channels
import ndx_extracellular_channels
pi_probe = probeinterface.Probe(...)
pi_probegroup = probeinterface.ProbeGroup()
# from_probeinterface always returns a list of ndx_extracellular_channels.Probe devices
ndx_probes1 = ndx_extracellular_channels.from_probeinterface(pi_probe)
ndx_probes2 = ndx_extracellular_channels.from_probeinterface(pi_probegroup)
ndx_probes = ndx_probes1.extend(ndx_probes2)
nwbfile = pynwb.NWBFile(...)
# add Probe as NWB Devices
for ndx_probe in ndx_probes:
nwbfile.add_device(ndx_probe)
import ndx_extracellular_channels
# load ndx_extracellular_channels.Probe objects from NWB file
io = pynwb.NWBH5IO(file_path, "r")
nwbfile = io.read()
ndx_probes = []
for device in nwbfile:
if isinstance(device, ndx_extracellular_channels.Probe):
ndx_probes.append(device)
# convert to probeinterface.Probe objects
pi_probes = []
for ndx_probe in ndx_probes:
pi_probe = ndx_extracellular_channels.to_probeinterface(ndx_probe)
pi_probes.append(pi_probe)
See src/pynwb/tests/test_example_usage_probeinterface.py
for a full example.
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', "primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%%
classDiagram
direction LR
class ExtracellularSeries {
<<TimeSeries>>
data : numeric
--> unit : str = "microvolts"
channels : DynamicTableRegion
--> target : ChannelsTable
channel_conversion : List[float], optional
--> axis : int = 1
}
class ChannelsTable {
<<DynamicTable>>
--------------------------------------
attributes
--------------------------------------
name : str
description : str
probe : Probe
position_reference : str, optional
electrical_reference_description : str, optional
ground : str, optional
position_confirmation_method : str, optional
--------------------------------------
columns
--------------------------------------
id : VectorData[int]
contact : DynamicTableRegion
--> target : ContactsTable
reference_contact : DynamicTableRegion, optional
--> target : ContactsTable
filter : VectorData[str], optional
---> Strings such as "Bandpass 0-300 Hz".
estimated_position_ap_in_mm : VectorData[float], optional
estimated_position_ml_in_mm : VectorData[float], optional
estimated_position_dv_in_mm : VectorData[float], optional
estimated_brain_area : VectorData[str], optional
confirmed_position_ap_in_mm : VectorData[float], optional
confirmed_position_ml_in_mm : VectorData[float], optional
confirmed_position_dv_in_mm : VectorData[float], optional
confirmed_brain_area : VectorData[str], optional
... Any other custom columns, e.g., ADC information
}
class ProbeInsertion {
<<Container>>
insertion_position_ap_in_mm : float, optional
insertion_position_ml_in_mm : float, optional
insertion_position_dv_in_mm : float, optional
position_reference : str, optional
hemisphere : Literal["left", "right"], optional
insertion_angle_pitch_in_deg : float, optional
insertion_angle_roll_in_deg : float, optional
insertion_angle_yaw_in_deg : float, optional
depth_in_um : float, optional
}
namespace ProbeInterface {
class Probe {
<<Device>>
identifier : str
--> Usually the serial number
probe_model : ProbeModel
probe_insertion : ProbeInsertion, optional
}
class ProbeModel {
<<Device>>
name : str
manufacturer : str
model : str
ndim : int, optional
planar_contour_in_um : List[Tuple[float, float], Tuple[float, float, float]], optional
contacts_table : ContactsTable
}
class ContactsTable {
<<DynamicTable>>
--------------------------------------
attributes
--------------------------------------
name : str
description : str
--------------------------------------
columns
--------------------------------------
id : VectorData[int]
relative_position_in_um : List[Tuple[float, float], Tuple[float, float, float]]
contact_id : VectorData[str], optional
shank_id : VectorData[str], optional
plane_axes : List[Tuple[int, int], Tuple[int, int, int]], optional
shape : VectorData[str], optional
radius_in_um : VectorData[float], optional
width_in_um : VectorData[float], optional
height_in_um : VectorData[float], optional
}
}
Probe *..> ProbeModel : links to probe_model
Probe *--> ProbeInsertion: might contain ProbeInsertion
ProbeModel *--> ContactsTable : contains
ExtracellularSeries ..> ChannelsTable : links to channels
ChannelsTable *..> Probe : links to probe
ChannelsTable ..> ContactsTable : row reference to contact
note for ChannelsTable "ChannelsTable is no longer global"
- Publish on PyPI
- Incorporate this NDX into the core NWB schema via NWBEP002
- Add information about the headstage used for data acquisition
This extension was created using ndx-template.