Loading...

ProbeInterface

Python package for handling probe layouts and channel configurations in electrophysiology

Neuroscience-Specific Analysis Tools Intermediate Specialized Tool
Quick Info
  • Category: Neuroscience-Specific Analysis Tools
  • Level: Intermediate
  • Type: Specialized Tool
  • Requires:

Why We Recommend ProbeInterface

ProbeInterface provides a standardized way to describe electrode probe geometries (Neuropixels, tetrodes, etc.). It handles the complex spatial layouts and wiring of modern high-density probes, making it easier to visualize and analyze multi-channel recordings.

Common Use Cases

  • Defining Neuropixels probe layouts
  • Visualizing electrode positions
  • Managing channel maps
  • Converting between probe formats

Getting Started

ProbeInterface is a Python package for handling probe and electrode layouts in extracellular electrophysiology. It provides a common framework for describing electrode positions, handling channel mappings, and visualizing probe geometries.

Why ProbeInterface?

  • Standardized: Common format across tools
  • Probe Library: Pre-defined popular probes
  • Visualization: Plot electrode layouts
  • Channel Mapping: Handle complex wiring
  • Integration: Works with SpikeInterface, Phy, etc.
  • Flexible: Support for any electrode geometry

Basic Usage

Create a Probe

from probeinterface import Probe
import numpy as np

# Create probe manually
probe = Probe(ndim=2, si_units='um')

# Define electrode positions (x, y)
positions = np.array([
    [0, 0],
    [0, 25],
    [0, 50],
    [0, 75]
])

probe.set_contacts(
    positions=positions,
    shapes='circle',
    shape_params={'radius': 5}
)

# Set device channel indices
probe.set_device_channel_indices(np.arange(4))

print(probe)

Visualize Probe

from probeinterface.plotting import plot_probe
import matplotlib.pyplot as plt

# Plot probe layout
plot_probe(probe)
plt.show()

# With channel numbers
plot_probe(probe, with_channel_index=True)
plt.show()

Pre-Defined Probes

Neuropixels

from probeinterface import get_probe

# Neuropixels 1.0
probe = get_probe('Neuropixels-1.0')
print(f"Channels: {probe.get_contact_count()}")

# Neuropixels 2.0
probe_np2 = get_probe('Neuropixels-2.0-single-shank')

# Neuropixels Ultra
probe_ultra = get_probe('Neuropixels-Ultra')

Browse Available Probes

from probeinterface import get_probe_list

# List all available probes
probes = get_probe_list()
for probe_name in probes:
    print(probe_name)

Load Specific Probe

# Neuronexus probe
probe = get_probe('Neuronexus-32')

# Cambridge NeuroTech
probe = get_probe('CambridgeNeuroTech-H2')

# Visualize
plot_probe(probe, with_channel_index=True)

Multi-Shank Probes

ProbeGroup for Multiple Shanks

from probeinterface import ProbeGroup, Probe

# Create probe group
probegroup = ProbeGroup()

# Add multiple shanks
for shank_id in range(4):
    probe = Probe(ndim=2, si_units='um')

    # Positions for this shank
    positions = np.zeros((32, 2))
    positions[:, 0] = shank_id * 200  # X offset between shanks
    positions[:, 1] = np.arange(32) * 25  # Y spacing

    probe.set_contacts(
        positions=positions,
        shapes='square',
        shape_params={'width': 12}
    )

    probe.set_device_channel_indices(np.arange(32) + shank_id * 32)

    probegroup.add_probe(probe)

# Visualize all shanks
plot_probe(probegroup)
plt.show()

Channel Mapping

Set Channel Indices

# Device channel indices (how probe is wired)
device_indices = np.array([32, 0, 33, 1, 34, 2, ...])  # Actual wiring
probe.set_device_channel_indices(device_indices)

# Contact IDs (for reference)
probe.set_contact_ids([f'elec{i}' for i in range(probe.get_contact_count())])

Reorder Channels

# Get current order
original_order = probe.device_channel_indices

# Create new mapping
new_order = np.argsort(probe.contact_positions[:, 1])  # Sort by Y position

# Apply reordering
probe.set_device_channel_indices(new_order)

Working with Recordings

Integrate with SpikeInterface

import spikeinterface as si
from probeinterface import read_prb

# Load recording
recording = si.read_spikeglx('data_folder')

# Load probe geometry
probe = read_prb('probe_layout.prb')

# Set probe to recording
recording_with_probe = recording.set_probe(probe)

# Now positions are available for analysis
positions = recording_with_probe.get_channel_locations()

Extract Probe from Recording

# Get probe info from recording
probe = recording.get_probe()

# Visualize electrode positions
plot_probe(probe)
plt.show()

# Get contact positions
positions = probe.contact_positions
print(f"Shape: {positions.shape}")  # (n_channels, 2) or (n_channels, 3)

File I/O

Save/Load Probe

from probeinterface import write_probeinterface, read_probeinterface

# Save probe
write_probeinterface('my_probe.json', probe)

# Load probe
loaded_probe = read_probeinterface('my_probe.json')

Export to Other Formats

from probeinterface import write_prb, write_csv

# Export to .prb format (for Phy/KlustaKwik)
write_prb('probe.prb', probe)

# Export to CSV
write_csv('probe.csv', probe)

Load from Various Formats

from probeinterface import read_prb, read_csv, read_spikeglx

# From .prb file
probe = read_prb('probe.prb')

# From SpikeGLX meta file
probe = read_spikeglx('recording.ap.meta')

# From CSV
probe = read_csv('electrode_positions.csv')

Visualization Options

Basic Plot

from probeinterface.plotting import plot_probe

plot_probe(probe)
plt.title('Probe Layout')
plt.show()

With Annotations

# Show channel indices
plot_probe(probe, with_channel_index=True)

# Show contact IDs
plot_probe(probe, with_contact_id=True)

# Custom colors
colors = np.random.rand(probe.get_contact_count())
plot_probe(probe, contacts_colors=colors)

3D Probes

# For 3D probe geometries
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

positions = probe.contact_positions
ax.scatter(positions[:, 0], positions[:, 1], positions[:, 2])
ax.set_xlabel('X (μm)')
ax.set_ylabel('Y (μm)')
ax.set_zlabel('Z (μm)')
plt.show()

Practical Examples

Neuropixels Analysis

from probeinterface import get_probe
import matplotlib.pyplot as plt

# Load Neuropixels 1.0 probe
probe = get_probe('Neuropixels-1.0')

print(f"Total contacts: {probe.get_contact_count()}")
print(f"Shank length: {probe.contact_positions[:, 1].max()} μm")

# Visualize
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 10))

# Full probe
plot_probe(probe, ax=ax1)
ax1.set_title('Full Probe')

# Zoom to specific region
plot_probe(probe, ax=ax2)
ax2.set_xlim(-50, 50)
ax2.set_ylim(2000, 2500)
ax2.set_title('Detail View (2000-2500 μm)')

plt.tight_layout()
plt.show()

Custom Tetrode Array

from probeinterface import Probe, ProbeGroup

def create_tetrode(center_x, center_y, spacing=25):
    """Create a tetrode (4 closely-spaced electrodes)"""
    probe = Probe(ndim=2, si_units='um')

    positions = np.array([
        [center_x - spacing/2, center_y - spacing/2],
        [center_x + spacing/2, center_y - spacing/2],
        [center_x - spacing/2, center_y + spacing/2],
        [center_x + spacing/2, center_y + spacing/2]
    ])

    probe.set_contacts(
        positions=positions,
        shapes='circle',
        shape_params={'radius': 7.5}
    )

    return probe

# Create array of 8 tetrodes
probegroup = ProbeGroup()

for i in range(8):
    tetrode = create_tetrode(
        center_x=0,
        center_y=i * 200,  # 200 μm vertical spacing
        spacing=25
    )
    tetrode.set_device_channel_indices(np.arange(4) + i * 4)
    probegroup.add_probe(tetrode)

# Visualize
plot_probe(probegroup, with_channel_index=True)
plt.title('8-Tetrode Array')
plt.show()

Annotate Probes with Brain Regions

# Add annotations to probe
probe.annotate(manufacturer='IMEC', probe_type='Neuropixels 1.0')

# Add contact-specific annotations (e.g., brain regions)
brain_regions = ['V1'] * 100 + ['LGN'] * 284 + ['Deep'] * 616
probe.annotate_contacts(brain_area=brain_regions)

# Access annotations
print(probe.annotations)
print(probe.contact_annotations['brain_area'])

Integration with Analysis Tools

With Phy

# Export for manual curation in Phy
from probeinterface import write_prb

write_prb('probe_for_phy.prb', probe)
# Use this file in Phy for proper channel visualization

With SpikeInterface

import spikeinterface.full as si

# Load recording
recording = si.read_spikeglx('recording_folder')

# Set probe
recording = recording.set_probe(probe)

# Now spike sorting will use spatial information
sorting = si.run_sorter('kilosort3', recording)

Installation

# With pixi
pixi add probeinterface

# With pip
pip install probeinterface

# With plotting support
pixi add "probeinterface[plotting]"

Resources

Summary

ProbeInterface is essential for:

  • Standardization: Common probe format
  • Visualization: Understand electrode layouts
  • Analysis: Spatial information for spike sorting
  • Documentation: Record probe configurations

It provides the foundation for spatial analysis of multi-channel electrophysiology data.

Prerequisites

Top