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_block_source "all" Blocks contributing to correlation/coherency: "all", "main", or "surface". PSD, RMS, and channel metadata still use all blocks.
extra_metrics () Optional metric extensions sharing the existing sampled reads and FFTs

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_channel_table_rows); rows the block did not record are NaN
_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>_mean_corr.npy Full per-band correlation matrix in channel-table row order
band_corr/<band>_coherency.npy Full per-band complex coherency matrix in channel-table row order
band_corr/<band>_shank<i>_mean_corr.npy Per-shank compatibility view sliced from the full matrix
band_corr/<band>_shank<i>_coherency.npy Per-shank compatibility view sliced from the full matrix
band_corr/row_channels.json Matrix row-to-channel table map (always written)
band_corr/channel_blocks.json Legacy multi-block channel map (only if surface-finding blocks are present)
channels.localCoordinates.npy Unique channel positions (x, y)
channels.rawInd.npy Legacy positional channel indices
channels.shankInd.npy Zero-based producer shank ID per channel-table row; physical IDs may be sparse
channels.contactId.npy Physical contact ID per channel-table row; empty string when unavailable
_iblqc_metrics.method.json Method metadata (FFT params, CMR flag)

Metrics method

For the directory boundary shared with preprocessing and the GUI, channel identity, shank derivation, matrix row maps, and split-stream examples, read the ephys collection contract. The datapackage references the collection directory, not individual QC files. Keep ALF objects at its root and correlation/coherency products in band_corr/.

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
  • Across-channel common-median referencing is applied.
  • Correlation and coherency combine all blocks by default. Set coherence_block_source="surface" to exclude main-recording artifacts while retaining surface-finding blocks; explicit asset provenance takes precedence over the legacy duration heuristic.

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

See CONTRIBUTING.md for developer setup, checks, and repository conventions. Coding agents should also read AGENTS.md.

License

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

Metadata

Release files for aind-ephys-ibl-gui-conversion 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aind-ephys-ibl-gui-conversion 0.6.0
File Size Uploaded
aind_ephys_ibl_gui_conversion-0.6.0.tar.gz 392.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aind-ephys-ibl-gui-conversion 0.6.0
File Interpreter ABI Platform
aind_ephys_ibl_gui_conversion-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 442.9 kB

Release files / aind_ephys_ibl_gui_conversion-0.6.0.tar.gz

Download URL aind_ephys_ibl_gui_conversion-0.6.0.tar.gz
Size 392.4 kB
Tags Source
SHA-256 checksum
How to use checksums
45ccd7635403327c4a6a2da6c036c72576bc48ef65ae8b38a8757a0f97fa1319
BLAKE2b-256 checksum
How to use checksums
3680921b18d9226b48779f7173a992216239e6b94eded5b9ed6ab7ca66e3c482
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}

Release files / aind_ephys_ibl_gui_conversion-0.6.0-py3-none-any.whl

Download URL aind_ephys_ibl_gui_conversion-0.6.0-py3-none-any.whl
Size 50.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ceedc5ab146176cd20cad8e59236246bfb0a352da3472631489c7c4e90fb11d9
BLAKE2b-256 checksum
How to use checksums
c2eccaa40c36c548f9f4e9e0b8de276dd2d08848ae34a0724501f38f1f605df5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page