Skip to main content

AIND Ephys IBL GUI Conversion

CI semantic-release: angular License ruff uv Copier

Convert AIND Neuropixels electrophysiology data into IBL ALF format for consumption by the IBL ephys alignment GUI. It extracts spike data from SpikeInterface sorting output and computes continuous QC metrics (RMS, spectral density, per-band coherence) from raw Neuropixels recordings.

Installation

From source (no PyPI release):

git clone https://github.com/AllenNeuralDynamics/aind-ephys-ibl-gui-conversion.git
cd aind-ephys-ibl-gui-conversion
pip install .

Or add as a dependency:

uv add "aind-ephys-ibl-gui-conversion @ git+https://github.com/AllenNeuralDynamics/aind-ephys-ibl-gui-conversion.git"

Usage

This package is a library -- there is no CLI. The two top-level entry points are extract_spikes() and extract_continuous(), both imported from the package root:

from pathlib import Path
from aind_ephys_ibl_gui_conversion import extract_spikes, extract_continuous

sorting_folder = Path("/path/to/<session>_sorted")
results_folder = Path("/path/to/output")

# Convert sorted spikes into IBL ALF format
extract_spikes(sorting_folder, results_folder)

# Compute continuous QC metrics (RMS, PSD, coherence)
extract_continuous(sorting_folder, results_folder)

Both functions write one subdirectory per probe under results_folder.

extract_spikes(sorting_folder, results_folder, ...)

Reads the postprocessed/ directory inside sorting_folder and writes IBL ALF spike files per probe.

Parameter Default Description
sorting_folder -- Path to the sorted session folder (name typically ends with _sorted)
results_folder -- Output directory (one subfolder per probe will be created)
stream_to_use None Filter to a single Open Ephys stream name (e.g. "Record Node 104#Neuropix-PXI-100.ProbeA-AP"). If None, all streams are processed.
min_duration_secs 300 Skip recordings shorter than this many seconds

extract_continuous(sorting_folder, results_folder, ...)

Reads compressed Neuropixels recordings from ecephys_compressed/ and writes per-band RMS, PSD, and coherence files in IBL ALF format.

Parameter Default Description
sorting_folder -- Path to the sorted session folder
results_folder -- Output directory
stream_to_use None Filter to a single Open Ephys stream
main_recording_min_secs 600 Minimum duration (s) for the main recording block
probe_surface_finding None Optional path to a separate surface-finding asset
rms_window_interval 30.0 Gap between analysis windows (s); auto-shortened on short recordings to guarantee >= 20 windows
rms_window_duration 4.0 Length of each analysis window (s)
num_parallel_jobs 4 Concurrent block processing

Coherence bands (from metrics.COHERENCE_BANDS):

Band Range (Hz)
delta 0.5 -- 4
theta 4 -- 12
alpha 12 -- 30
beta 30 -- 100
gamma 100 -- 300

Input data expectations

Both entry points expect the AIND session layout:

<session>/
|-- ecephys_clipped/                    # Open Ephys binary (read by SpikeInterface)
|-- ecephys_compressed/                 # Zarr + WavPack compressed recordings
|   |-- experiment1_<stream>.zarr
|   +-- experiment2_<stream>.zarr
|
+-- <session>_sorted/                   # SORTING_FOLDER argument points here
    +-- postprocessed/
        |-- experiment1_<stream>_recording1.zarr        # SortingAnalyzer
        +-- experiment1_<stream>_recording1_group<N>.zarr  # Multi-shank (one per shank)

The package handles both Neuropixels 1.0 (separate AP/LFP streams) and 2.0 (combined wideband) probes, as well as multi-shank probes.

Stream naming

Open Ephys stream names follow the pattern:

Record Node <id>#Neuropix-PXI-<model>.<probe_name>[-AP|-LFP]

For example, Record Node 104#Neuropix-PXI-100.ProbeA-AP is parsed into probe_name = "ProbeA".

Output format

All outputs are written under results_folder/<probe_name>/ in IBL ALF format.

From extract_spikes

File Shape / dtype Description
spikes.times.npy (n_spikes,) float64 Spike times in seconds
spikes.clusters.npy (n_spikes,) Cluster ID per spike
spikes.amps.npy (n_spikes,) float64 Spike amplitudes (negated)
spikes.depths.npy (n_spikes,) Spike depths along the probe (um)
spike_shank_indices.npy (n_spikes,) 0-based shank index per spike
clusters.channels.npy (n_clusters,) Peak channel per cluster
clusters.peakToTrough.npy (n_clusters,) Peak-to-trough duration (samples)
clusters.waveforms.npy (n_clusters, n_samples, n_channels) Mean waveforms
clusters.metrics.csv -- SpikeInterface quality metrics
unit_shank_indices.npy (n_clusters,) 0-based shank index per cluster

From extract_continuous

File Description
_iblqc_ephysTimeRmsAP.rms.npy (*Main* if multi-block) AP-band RMS time series, shape (n_windows, n_channels)
_iblqc_ephysTimeRmsAP.timestamps.npy Window centers (s)
_iblqc_ephysTimeRmsLF*.rms.npy LFP-band RMS time series
_iblqc_ephysTimeRmsLF*.timestamps.npy Window centers (s)
_iblqc_ephysSpectralDensityLF.power.npy PSD (V^2/Hz), shape (n_freqs, n_channels)
_iblqc_ephysSpectralDensityLF.freqs.npy Frequencies (Hz)
band_corr/<band>_shank<i>_mean_corr.npy Per-band, per-shank correlation matrices (real, power-normalized)
band_corr/<band>_shank<i>_coherency.npy Per-band, per-shank complex coherency
band_corr/channel_blocks.json Multi-block channel map (only if surface-finding blocks are present)
channels.localCoordinates.npy Unique channel positions (x, y)
channels.rawInd.npy Channel indices
_iblqc_metrics.method.json Method metadata (FFT params, CMR flag)

Metrics method

RMS and PSD are computed via FFT, not time-domain filtering:

  • Hann-windowed segments, Welch-style PSD
  • Band-limited RMS via Parseval's theorem (integrate PSD over each band)
  • AP band: > 300 Hz (neural noise); LFP band: 1 -- 300 Hz
  • Common-mode rejection (CMR) is applied

Adapting to your own data

The package is tightly coupled to the AIND session layout and Open Ephys stream naming. To adapt it to a different setup, the main integration points are:

  1. Recording discovery: recording_utils.get_ecephys_stream_names() and io.load_probe_streams() enumerate compressed .zarr recordings under ecephys_compressed/. Replace these if your recordings live elsewhere or use a different container.
  2. Stream name parsing: recording_utils._stream_to_probe_name() extracts the probe name via a regex over the Open Ephys stream ID. Replace this if your stream names follow a different convention.
  3. Sorting output: extract_spikes() assumes SpikeInterface SortingAnalyzer output in <sorting_folder>/postprocessed/. If you have a different SortingAnalyzer location or a different post-processed format, point at it directly.
  4. Surface-finding recordings: If you use separate "surface finding" recordings (short probe-movement blocks used to map the cortical surface), pass the asset path via probe_surface_finding. Otherwise leave it unset.

The output format is IBL ALF and is decoupled from input assumptions -- it will work with any IBL GUI consumer.

Development

Set up the environment:

uv sync

Run the full check suite:

./scripts/run_linters_and_checks.sh -c

Or run individual checks:

uv run --frozen ruff format                          # Code formatting
uv run --frozen ruff check                           # Linting
uv run --frozen interrogate -v src                   # Docstring coverage (100% required)
uv run --frozen codespell --check-filenames          # Spell checking
uv run --frozen pytest --cov aind_ephys_ibl_gui_conversion  # Tests with coverage

License

This project is licensed under the MIT License -- see the LICENSE file for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aind_ephys_ibl_gui_conversion-0.3.3.tar.gz (248.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aind_ephys_ibl_gui_conversion-0.3.3-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file aind_ephys_ibl_gui_conversion-0.3.3.tar.gz.

File metadata

  • Download URL: aind_ephys_ibl_gui_conversion-0.3.3.tar.gz
  • Upload date:
  • Size: 248.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for aind_ephys_ibl_gui_conversion-0.3.3.tar.gz
Algorithm Hash digest
SHA256 70b188f3fce27e3fe97f8735d94825f76d5c19a76fed861c93daae540875a09d
MD5 12a68c1af7d2dfb5dc75ed8a7b0847f5
BLAKE2b-256 04097f55455f8f83e2abd816810a29dfb55f0dd30929a07c5bb5e55f302c11e6

See more details on using hashes here.

File details

Details for the file aind_ephys_ibl_gui_conversion-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: aind_ephys_ibl_gui_conversion-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 29.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for aind_ephys_ibl_gui_conversion-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 d15a81a6fd7bf84e6725bd4f191d4c6cd802236e62ea374e8c86aaa0619f5bbf
MD5 2791e33caf42762a2668d056ce84fd69
BLAKE2b-256 a435e42a85215854d9e729d75d024a7e975af391688785540f5b1b3b9c98bc6c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page