Tools for finding sharp-wave ripple events (150-250 Hz) from local field potentials.
Project description
ripple_detection
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 methodmultiunit_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:
- Detection Examples - Using different detectors
- Algorithm Components - Testing individual components
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:
- Check if your LFPs actually contain ripples (150-250 Hz oscillations)
- Verify speed is in cm/s (not m/s)
- Plot the filtered LFP to visually inspect for ripple events
- 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
- Issues: GitHub Issues
- Discussions: For questions about usage and parameter selection
- Email: edeno@bu.edu
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
- Eric Denovellis - edeno@bu.edu
Acknowledgments
- Frank Lab for the pre-computed ripple filter
- Original algorithm implementations by Karlsson et al. and Kay et al.
Support
- Issues: GitHub Issues
- Discussions: For questions and discussions about usage
- Email: edeno@bu.edu
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ripple_detection-1.7.1.tar.gz.
File metadata
- Download URL: ripple_detection-1.7.1.tar.gz
- Upload date:
- Size: 2.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87bae13fcbba3796dd64f35e0475ea9d125edbd789b3acab0a886da5ce0036ab
|
|
| MD5 |
4457332290f6bf374733a53112b63332
|
|
| BLAKE2b-256 |
49c9559d574404427c57ee0d5ad546f0325a8e7ecbecf4742b27135e8b289756
|
Provenance
The following attestation bundles were made for ripple_detection-1.7.1.tar.gz:
Publisher:
release.yml on Eden-Kramer-Lab/ripple_detection
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ripple_detection-1.7.1.tar.gz -
Subject digest:
87bae13fcbba3796dd64f35e0475ea9d125edbd789b3acab0a886da5ce0036ab - Sigstore transparency entry: 844923743
- Sigstore integration time:
-
Permalink:
Eden-Kramer-Lab/ripple_detection@34500e6a93fb17481a357167aa3abc9f2a89789c -
Branch / Tag:
refs/tags/v1.7.1 - Owner: https://github.com/Eden-Kramer-Lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@34500e6a93fb17481a357167aa3abc9f2a89789c -
Trigger Event:
push
-
Statement type:
File details
Details for the file ripple_detection-1.7.1-py3-none-any.whl.
File metadata
- Download URL: ripple_detection-1.7.1-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11cbb2c04fe5687c2d6b419bda995ee53226468ed3618b483ca43078342620a2
|
|
| MD5 |
6037f471bcec8618947384fe7b990ce5
|
|
| BLAKE2b-256 |
2499d1fc9953cbbfa976bbc951b6493fef9c07b0d79fb40c2f1c7414b99ad1e4
|
Provenance
The following attestation bundles were made for ripple_detection-1.7.1-py3-none-any.whl:
Publisher:
release.yml on Eden-Kramer-Lab/ripple_detection
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ripple_detection-1.7.1-py3-none-any.whl -
Subject digest:
11cbb2c04fe5687c2d6b419bda995ee53226468ed3618b483ca43078342620a2 - Sigstore transparency entry: 844923748
- Sigstore integration time:
-
Permalink:
Eden-Kramer-Lab/ripple_detection@34500e6a93fb17481a357167aa3abc9f2a89789c -
Branch / Tag:
refs/tags/v1.7.1 - Owner: https://github.com/Eden-Kramer-Lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@34500e6a93fb17481a357167aa3abc9f2a89789c -
Trigger Event:
push
-
Statement type: