Skip to main content

ripple_detection

PyPI version Python 3.10+ License: MIT Test, Build, and Publish codecov

A Python package for detecting sharp-wave ripple events (150-250 Hz) from local field potentials (LFPs) in neuroscience research.

Features

  • Multiple Detection Algorithms

    • Kay_ripple_detector - Multi-channel consensus approach (Kay et al. 2016)
    • Karlsson_ripple_detector - Per-channel detection with merging (Karlsson et al. 2009)
    • Roumis_ripple_detector - Alternative detection method
    • multiunit_HSE_detector - High Synchrony Event detection from multiunit activity
  • Comprehensive Event Statistics

    • Temporal metrics (start time, end time, duration)
    • Z-score metrics (mean, median, max, min, sustained threshold)
    • Signal metrics (area under curve, total energy)
    • Movement metrics (speed during event)
  • Flexible Signal Processing

    • Bandpass filtering (150-250 Hz)
    • Envelope extraction via Hilbert transform
    • Gaussian smoothing with configurable parameters
    • Movement exclusion based on speed thresholds
  • Simulation Tools

    • Generate synthetic LFPs with embedded ripples
    • Multiple noise types (white, pink, brown)
    • Useful for testing and validation

Installation

From PyPI

pip install ripple_detection

From Conda

conda install -c edeno ripple_detection

From Source

# Clone the repository
git clone https://github.com/Eden-Kramer-Lab/ripple_detection.git
cd ripple_detection

# Install with optional dependencies
pip install -e .[dev,examples]

Requirements

  • Python >= 3.10
  • numpy >= 1.23.0
  • scipy >= 1.9.0
  • pandas >= 1.5.0

Quick Start

Basic Usage

from ripple_detection import Kay_ripple_detector
import numpy as np

# Your data
time = np.arange(0, 10, 0.001)  # 10 seconds at 1000 Hz
LFPs = np.random.randn(len(time), 4)  # 4 channels of LFP data
speed = np.abs(np.random.randn(len(time)))  # Animal speed
sampling_frequency = 1000  # Hz

# Detect ripples
ripple_times = Kay_ripple_detector(
    time, LFPs, speed, sampling_frequency,
    speed_threshold=4.0,        # cm/s
    minimum_duration=0.015,     # seconds
    zscore_threshold=2.0
)

print(ripple_times)

Advanced Usage

from ripple_detection import Karlsson_ripple_detector

# Detect ripples with custom parameters
ripples = Karlsson_ripple_detector(
    time, LFPs, speed, sampling_frequency,
    speed_threshold=4.0,
    minimum_duration=0.015,
    zscore_threshold=3.0,
    smoothing_sigma=0.004,
    close_ripple_threshold=0.0
)

# Access detailed statistics
print(f"Detected {len(ripples)} ripple events")
print(f"Mean duration: {ripples['duration'].mean():.3f} seconds")
print(f"Mean z-score: {ripples['mean_zscore'].mean():.2f}")

Output Format

All detectors return a pandas DataFrame with comprehensive event statistics:

Column Description
start_time Event start time
end_time Event end time
duration Event duration (seconds)
max_thresh Maximum sustained threshold
mean_zscore Mean z-score during event
median_zscore Median z-score during event
max_zscore Maximum z-score during event
min_zscore Minimum z-score during event
area Integral of z-score over time
total_energy Integral of squared z-score
speed_at_start Animal speed at event start
speed_at_end Animal speed at event end
max_speed Maximum speed during event
min_speed Minimum speed during event
median_speed Median speed during event
mean_speed Mean speed during event

Examples

See the examples directory for Jupyter notebooks demonstrating:

Troubleshooting

Common Errors

"axis 1 is out of bounds" or "must be a 2D array"

Your LFP data must be 2D with shape (n_time, n_channels). Even for a single channel, the array must be 2D.

# Wrong - 1D array
lfps = np.random.randn(1000)  # Shape: (1000,)

# Correct - 2D array with single channel
lfps = np.random.randn(1000, 1)  # Shape: (1000, 1)
# OR reshape existing 1D array:
lfps = lfps.reshape(-1, 1)

"Array length mismatch detected"

Your time, LFPs, and speed arrays must have the same length. Check dimensions:

print(f"time: {len(time)}, LFPs: {len(lfps)}, speed: {len(speed)}")

Make sure all arrays cover the same time period and sampling rate.

"Sampling frequency is too low for the pre-computed filter"

The built-in filter_ripple_band() function uses a pre-computed filter designed for 1500 Hz sampling. For other sampling rates, generate a custom filter:

from ripple_detection import ripple_bandpass_filter
from scipy.signal import filtfilt

# Generate custom filter for your sampling rate
filter_num, filter_denom = ripple_bandpass_filter(sampling_frequency)
filtered_lfps = filtfilt(filter_num, filter_denom, raw_lfps, axis=0)

No ripples detected (empty DataFrame)

If detection returns no events, try adjusting parameters:

ripples = Kay_ripple_detector(
    time, filtered_lfps, speed, sampling_frequency,
    zscore_threshold=1.5,      # Lower from default 2.0
    minimum_duration=0.010,    # Lower from default 0.015
    speed_threshold=10.0       # Increase if too restrictive (default 4.0)
)

Diagnostic steps:

  1. Check if your LFPs actually contain ripples (150-250 Hz oscillations)
  2. Verify speed is in cm/s (not m/s)
  3. Plot the filtered LFP to visually inspect for ripple events
  4. Try different detector algorithms (Kay, Karlsson, Roumis)

Parameter Selection Guide

Parameter Default Description When to Adjust
speed_threshold 4.0 cm/s Maximum speed for ripple detection Increase if too many events excluded during slow movement
minimum_duration 0.015 s Minimum ripple duration (15 ms) Decrease to 0.010 for shorter ripples; increase to 0.020 for stricter detection
zscore_threshold 2.0 (Kay/Roumis)
3.0 (Karlsson)
Detection sensitivity Decrease for more detections; increase for fewer, higher-confidence events
smoothing_sigma 0.004 s Gaussian smoothing window (4 ms) Rarely needs adjustment; increase for noisier data

Getting Help

Documentation

For detailed documentation on the detection algorithms and signal processing pipeline, see CLAUDE.md.

Algorithm Comparison

Algorithm Approach Best For
Kay Multi-channel consensus (sum of squared envelopes) High-density electrode arrays
Karlsson Per-channel detection with merging Independent channel analysis
Roumis Averaged square-root of squared envelopes Balanced multi-channel approach

Development

Setup Development Environment

# Create conda environment
conda env create -f environment.yml
conda activate ripple_detection

# Install in editable mode with dev dependencies
pip install -e .[dev,examples]

Run Tests

The package has comprehensive test coverage (93%) across 163 tests organized in 6 modules:

# Run all tests with coverage
pytest --cov=ripple_detection --cov-report=term-missing tests/

# Run specific test modules
pytest tests/test_core.py          # Core signal processing tests (70 tests)
pytest tests/test_detectors.py     # Detector integration tests (25 tests)
pytest tests/test_simulate.py      # Simulation module tests (36 tests)
pytest tests/test_properties.py    # Property-based tests (23 tests)
pytest tests/test_snapshots.py     # Snapshot/regression tests (9 tests)

# Run specific test
pytest tests/test_core.py::TestSegmentBooleanSeries::test_single_segment

# Generate HTML coverage report
pytest --cov=ripple_detection --cov-report=html tests/
# Open htmlcov/index.html in browser

Test Coverage:

  • core.py: 93%
  • detectors.py: 92%
  • simulate.py: 100%
  • Overall: 93%

Code Quality

# Format code with black
black ripple_detection/ tests/

# Lint code with ruff (modern, fast linter)
ruff check ripple_detection/ tests/

# Type check with mypy
mypy ripple_detection/

# Check formatting without modifying
black --check ripple_detection/ tests/

Release Process

Releases are automated via GitHub Actions when a version tag is pushed:

# 1. Ensure all tests pass and code quality checks pass
pytest --cov=ripple_detection tests/
black --check ripple_detection/ tests/
ruff check ripple_detection/ tests/
mypy ripple_detection/

# 2. Update CHANGELOG.md with new version and changes
# - Add ## [X.Y.Z] - YYYY-MM-DD section
# - Document changes under Added/Changed/Deprecated/Removed/Fixed/Security
# - Update comparison links at bottom

# 3. Commit and push changelog
git add CHANGELOG.md
git commit -m "Update CHANGELOG for vX.Y.Z release"
git push origin master

# 4. Create and push annotated tag (triggers release workflow)
git tag -a vX.Y.Z -m "Release vX.Y.Z with feature descriptions"
git push origin vX.Y.Z

The automated workflow will:

  • Run tests on Python 3.10, 3.11, 3.12, 3.13
  • Build source distribution and wheels
  • Publish to PyPI
  • Create GitHub release

Note: Version numbers follow Semantic Versioning (MAJOR.MINOR.PATCH). The package version is automatically determined from git tags via hatch-vcs.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Citation

If you use this package in your research, please cite the original papers:

Karlsson Method

@article{karlsson2009awake,
  title={Awake replay of remote experiences in the hippocampus},
  author={Karlsson, Mattias P and Frank, Loren M},
  journal={Nature neuroscience},
  volume={12},
  number={7},
  pages={913--918},
  year={2009},
  publisher={Nature Publishing Group}
}

Kay Method

@article{kay2016hippocampal,
  title={A hippocampal network for spatial coding during immobility and sleep},
  author={Kay, Kenneth and Sosa, Marielena and Chung, Jason E and Karlsson, Mattias P and Larkin, Margaret C and Frank, Loren M},
  journal={Nature},
  volume={531},
  number={7593},
  pages={185--190},
  year={2016},
  publisher={Nature Publishing Group}
}

License

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

Authors

Acknowledgments

  • Frank Lab for the pre-computed ripple filter
  • Original algorithm implementations by Karlsson et al. and Kay et al.

Support

Metadata

Release files for ripple-detection 1.7.1

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

Source distribution (sdist)

Source distribution for ripple-detection 1.7.1
File Size Uploaded
ripple_detection-1.7.1.tar.gz 2.3 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for ripple-detection 1.7.1
File Interpreter ABI Platform
ripple_detection-1.7.1-py3-none-any.whl Python 3 none any Details

Total release size: 2.3 MB

Release files / ripple_detection-1.7.1.tar.gz

Download URL ripple_detection-1.7.1.tar.gz
Size 2.3 MB
Tags Source
SHA-256 checksum
How to use checksums
87bae13fcbba3796dd64f35e0475ea9d125edbd789b3acab0a886da5ce0036ab
BLAKE2b-256 checksum
How to use checksums
49c9559d574404427c57ee0d5ad546f0325a8e7ecbecf4742b27135e8b289756
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 22, 2026.

Transparency log

Release files / ripple_detection-1.7.1-py3-none-any.whl

Download URL ripple_detection-1.7.1-py3-none-any.whl
Size 28.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11cbb2c04fe5687c2d6b419bda995ee53226468ed3618b483ca43078342620a2
BLAKE2b-256 checksum
How to use checksums
2499d1fc9953cbbfa976bbc951b6493fef9c07b0d79fb40c2f1c7414b99ad1e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 22, 2026.

Transparency log
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