Add multichannel EGG processing, ICA denoising, and preprocessing filters (Dalmaijer 2025) - #10
Conversation
Ports and integrates algorithms from Dalmaijer (2025) electrography into the gastropy signal processing toolkit. Follows the neurokit2 convention of named, citable method variants within existing functions. New in gastropy.signal: - hampel_filter: sliding-window median spike removal (Dalmaijer 2025) - mad_filter: global MAD outlier replacement (Dalmaijer 2025) - remove_movement_artifacts: LMMSE movement filter (Gharibans et al. 2018) - ica_denoise: FastICA spatial denoising for multi-channel EGG - fit_sine / sine_model: least-squares sine wave fitting New in gastropy.egg: - egg_process_multichannel: per_channel / best_channel / ica strategies - egg_clean gains method="dalmaijer2025" named pipeline variant Closes #9.
- API reference: add egg_process_multichannel and 6 new signal functions (hampel_filter, mad_filter, remove_movement_artifacts, ica_denoise, fit_sine, sine_model) - getting_started.rst: expand artifact removal, channel selection, and egg_clean method sections with examples for all new functionality - New example notebooks: artifact_removal.ipynb, multichannel_processing.ipynb - Update egg_process.ipynb with dalmaijer2025 cleaning pipeline cell - Update bandpass_filtering.ipynb with fit_sine demonstration cell - Register new notebooks in examples/index.rst
…/post timeseries
- Raise ica_snr_threshold to 30.0 so 2/7 components are removed,
producing visibly different per-channel results vs per_channel method
- Add pre vs post ICA timeseries plot for all channels
- Fix band_power_mean display (was 0.0000 due to tiny values; now uses
{:.4g} scientific notation)
- Update ICA markdown to explain the stricter demo threshold
- Suppress FastICA ConvergenceWarning in notebook output
- New tutorial: docs/tutorials/multichannel_pipeline.ipynb 28-cell pedagogical guide covering: data loading, channel quality assessment, step-by-step artefact removal (Hampel → LMMSE → IIR), all three multichannel strategies (per_channel / best_channel / ica), quantitative method comparison, and sine fitting. Fully executed. - Register tutorial in docs/tutorials/index.rst - Fix bandpass_filtering.ipynb: psd_welch returns (freqs, psd) ndarrays, not (_, info_dict); compute peak_hz correctly from the PSD array
There was a problem hiding this comment.
Pull request overview
This pull request adds comprehensive multi-channel EGG processing capabilities to GastroPy by porting core algorithms from the electrography package (Dalmaijer, 2025). The changes follow GastroPy's existing neurokit2-inspired convention of named, citable method variants and integrate seamlessly with the existing API.
Changes:
- Adds seven new public functions for preprocessing (Hampel/MAD filters, movement artifact removal), ICA spatial denoising, and sine wave fitting
- Introduces
egg_process_multichannelwith three processing strategies: per-channel, best-channel selection, and ICA-based denoising - Extends
egg_cleanwith amethod="dalmaijer2025"variant that chains Hampel spike removal → LMMSE movement filtering → IIR Butterworth bandpass - Adds scikit-learn as a core dependency for FastICA support
- Includes 43 new tests (19 preprocessing, 11 ICA, 13 multichannel) bringing total coverage to 270 tests
- Provides extensive documentation updates including API reference additions, expanded getting started guide, and tutorial content
Reviewed changes
Copilot reviewed 17 out of 21 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
gastropy/signal/preprocessing.py |
Time-domain artifact removal: Hampel filter, MAD filter, LMMSE movement artifact attenuation |
gastropy/signal/ica.py |
FastICA spatial denoising with gastric-band SNR thresholding for multi-channel EGG |
gastropy/signal/sine.py |
L-BFGS-B least-squares sine fitting for frequency/phase/amplitude characterization |
gastropy/signal/__init__.py |
Exports new preprocessing, ICA, and sine fitting functions |
gastropy/egg/multichannel.py |
Multi-channel processing pipeline with three named strategies |
gastropy/egg/egg_process.py |
Extended egg_clean with dalmaijer2025 method variant |
gastropy/egg/__init__.py |
Exports egg_process_multichannel |
tests/test_preprocessing.py |
19 tests for Hampel, MAD, and movement artifact filters |
tests/test_ica.py |
11 tests for ICA denoising including edge cases and reproducibility |
tests/test_egg.py |
13 new tests for multi-channel processing strategies |
pyproject.toml |
Adds scikit-learn>=1.3 dependency |
docs/api/index.rst |
Documents 7 new functions in signal preprocessing section |
docs/getting_started.rst |
Expanded artifact removal, channel selection, and multi-channel sections |
docs/examples/egg_process.ipynb |
Added dalmaijer2025 cleaning method example |
docs/examples/index.rst |
References two new example notebooks |
docs/tutorials/index.rst |
References new multichannel pipeline tutorial |
CHANGELOG.md |
Comprehensive documentation of all additions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ``egg_clean`` supports multiple named cleaning pipelines via its | ||
| ``method`` parameter. ``method="fir"`` (default) uses a zero-phase | ||
| FIR bandpass. ``method="dalmaijer2025"`` applies Hampel spike removal |
There was a problem hiding this comment.
The documentation states "0.033-0.067 Hz" for the normogastric band, but the actual NORMOGASTRIA constant uses 0.03333-0.06666 Hz (exactly 2-4 cpm). While functionally equivalent for most purposes, this minor inconsistency could cause confusion. Consider using the more precise values (0.0333-0.0667 Hz) or referring to the band by name (NORMOGASTRIA) to avoid hardcoding approximate values in documentation.
- Make scikit-learn optional ([ica] extra): lazy import in ica_denoise raises ImportError with install instructions when sklearn is absent; remove sklearn from core dependencies in pyproject.toml - Add filter_method= parameter to egg_process_multichannel to resolve the name collision with the multichannel strategy method= parameter - Add freq_init= parameter to fit_sine so free-frequency fits work outside the normogastric band; document that amplitude may be negative - Document DC-removal side effect in remove_movement_artifacts (Notes) - Document best_idx criterion difference between per_channel/ica and best_channel strategies (Notes in egg_process_multichannel) - Add tests/test_sine.py: 16 tests covering sine_model and fit_sine - Guard test_ica.py and ICA tests in test_egg.py with importorskip/ skipif so they skip cleanly when sklearn is not installed - Update CONTRIBUTING.md: sklearn is optional, lazy-imported
- Revise paper.md and gastropy_paper.tex to cover PR #10 features: preprocessing filters (Hampel, MAD, LMMSE), ICA spatial denoising, egg_process_multichannel, named method variants (dalmaijer2025) - Add references: Anisimova 2025, Gharibans 2018, Pedregosa 2011, Berther 2026; fix Wolpert 2020 author list - Update test count 178 -> 297, AI model versions, comparison tables - Solo author for preprint (Allen) - Bump pyproject.toml to v0.1.1 with maintainer field and Alpha status - Recompile preprint PDF
Summary
Ports core algorithms from electrography v1.1.1 (Dalmaijer, 2025) into GastroPy, following the neurokit2 convention of named, citable
method=variants. Closes #9.New public functions
hampel_filtersignalmad_filtersignalremove_movement_artifactssignalica_denoisesignalfit_sinesignalsine_modelsignalA·sin(2πft+φ)egg_process_multichanneleggper_channel/best_channel/ica)Extended existing functions
egg_cleangainsmethod="dalmaijer2025": Hampel → LMMSE → IIR Butterworth pipelineDependencies
scikit-learn>=1.3as a core dependency (used forFastICA)Tests
test_preprocessing.py(19 tests),test_ica.py(11 tests), extendedtest_egg.py(+13 tests)Documentation
docs/api/index.rstartifact_removal.ipynb,multichannel_processing.ipynbegg_process.ipynb(dalmaijer2025 cell),bandpass_filtering.ipynb(fit_sine cell)multichannel_pipeline.ipynb— 28-cell pedagogical guide covering the full multichannel workflow from raw data to sine fittingTest plan
pytestpasses on Python 3.10, 3.11, 3.12, 3.13ruff check gastropy/— no lint errorssphinx-build docs docs/_build -b html -W— no warnings or errorsReferences