Skip to main content

Dynamic Mode Decomposition for EEG signal analysis

Project description

pydmdeeg

Python 3.9+ License: MIT Code style: ruff

Dynamic Mode Decomposition for EEG Signal Analysis

A Python library for extracting spatio-temporal coherent patterns from EEG data using Dynamic Mode Decomposition (DMD). This method enables data-driven decomposition of neural recordings into interpretable oscillatory modes.

Features

  • Two DMD algorithms: Exact and standard implementations based on Tu et al. (2014)
  • Sliding window analysis: Configurable window size and overlap for time-resolved decomposition
  • Delay embedding: Shift-stacking technique for enhanced temporal dynamics capture
  • SVD truncation: Optional hard thresholding (optht) or fixed-rank truncation for noise reduction
  • Data scaling: Multiple preprocessing options (centering, normalization, z-scoring)
  • Rich visualization: Built-in plotting for DMD spectra, channel statistics, and reconstruction errors
  • Multi-trial support: Handle epoched EEG data with trial labels for condition comparisons

Installation

From PyPI (recommended)

pip install pydmdeeg

From source

git clone https://github.com/christiangoelz/pydmdeeg.git
cd pydmdeeg
pip install -e ".[dev]"

Quick Start

import numpy as np
from pydmdeeg import DMD

# Generate synthetic EEG-like data
# Shape: (n_trials, n_channels, n_timepoints)
n_trials, n_channels, n_times = 10, 64, 1000
sampling_rate = 256  # Hz

# Create data with oscillatory components
t = np.linspace(0, n_times/sampling_rate, n_times)
X = np.zeros((n_trials, n_channels, n_times))
for trial in range(n_trials):
    for ch in range(n_channels):
        # Alpha (10 Hz) and beta (20 Hz) oscillations with noise
        X[trial, ch, :] = (
            np.sin(2 * np.pi * 10 * t) +
            0.5 * np.sin(2 * np.pi * 20 * t) +
            0.3 * np.random.randn(n_times)
        )

# Trial labels (e.g., 0 = rest, 1 = task)
y = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])

# Channel names
channels = [f'Ch{i+1}' for i in range(n_channels)]

# Initialize DMD
dmd = DMD(
    X=X,
    y=y,
    channels=channels,
    dt=1/sampling_rate,
    win_size=128,
    overlap=64,
    algorithm='exact',
    datascale='norm'
)

# Run decomposition
dmd.DMD_win()

# Extract alpha band (8-12 Hz) mode statistics
alpha_stats = dmd.mode_stats(fbands=[[8, 12]], labels=[0, 1])
print(alpha_stats)

# Get mode magnitudes for specific frequency band
psi = dmd.get_PSI(fband=[8, 12], labels=[1])

API Reference

DMD Class

DMD(
    X,                    # EEG data: (n_trials, n_channels, n_times) or (n_channels, n_times)
    y,                    # Trial labels: (n_trials,)
    channels,             # Channel names: list of strings
    dt,                   # Sampling interval: 1/sampling_rate
    stacking_factor=0,    # Delay embedding factor (0 = no stacking)
    win_size=100,         # Window size in samples
    overlap=0,            # Window overlap in samples
    datascale='norm',     # Scaling: 'none', 'centre', 'norm', 'centre_norm'
    algorithm='exact',    # DMD algorithm: 'exact' or 'standard'
    truncation={'method': None, 'keep': None}  # SVD truncation settings
)

Key Methods

Method Description
DMD_win() Run DMD decomposition across sliding windows
mode_stats(fbands, labels) Compute statistics for modes in frequency bands
get_PSI(fband, labels) Extract mode magnitudes for frequency band
get_AMP(fband, labels) Extract mode amplitudes for frequency band
select_trials(selector) Select subset of trials
plot_frRPsi(labels) Plot DMD power spectrum
plot_frRLam(labels) Plot eigenvalue spectrum
plot_statsCH() Plot channel statistics heatmap
plot_ChAmpErr(labels) Plot reconstruction error

Mathematical Background

Dynamic Mode Decomposition approximates the linear operator A that best maps consecutive time snapshots:

X'AX

where X and X' are time-shifted data matrices. The eigenvalues of A (λ) encode oscillation frequencies and growth/decay rates, while eigenvectors (Φ) represent spatial patterns.

For EEG analysis:

  • Frequencies: μ = Im(log(λ)) / (2πΔt)
  • Spatial modes: Φ shows channel contributions to each oscillatory pattern
  • Amplitudes: |Φ| weighted by initial conditions

Publications Using This Method

This implementation has been validated in peer-reviewed neuroscience research:

  1. Goelz C et al. (2021). Classification of visuomotor tasks based on electroencephalographic data depends on age-related differences in brain activity patterns. Neural Networks. DOI

  2. Goelz C et al. (2021). Electrophysiological signatures of dedifferentiation differ between fit and less fit older adults. Cognitive Neurodynamics. DOI

  3. Goelz C et al. (2018). Improved Neural Control of Movements Manifests in Expertise-Related Differences in Force Output and Brain Network Dynamics. Frontiers in Physiology. DOI

  4. Vieluf S et al. (2018). Age- and Expertise-Related Differences of Sensorimotor Network Dynamics during Force Control. Neuroscience. DOI

References

  • Brunton BW et al. (2016). Extracting spatial-temporal coherent patterns in large-scale neural recordings using dynamic mode decomposition. J Neurosci Methods. DOI
  • Tu JH et al. (2014). On dynamic mode decomposition: Theory and applications. J Computational Dynamics. DOI
  • Donoho D & Gavish M (2014). The Optimal Hard Threshold for Singular Values is 4/√3. IEEE Trans Information Theory. DOI

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
ruff check .

# Run type checking
mypy pydmdeeg

License

MIT License - see LICENSE for details.

Citation

If you use this software in your research, please cite:

@software{pydmdeeg,
  author = {Goelz, Christian},
  title = {pydmdeeg: Dynamic Mode Decomposition for EEG Analysis},
  url = {https://github.com/christiangoelz/pydmdeeg},
  version = {0.2.0},
  year = {2024}
}

Project details


Download files

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

Source Distribution

pydmdeeg-0.2.0.tar.gz (21.9 kB view details)

Uploaded Source

Built Distribution

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

pydmdeeg-0.2.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file pydmdeeg-0.2.0.tar.gz.

File metadata

  • Download URL: pydmdeeg-0.2.0.tar.gz
  • Upload date:
  • Size: 21.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydmdeeg-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e194cf1954be152b14b06cf008ef7158f88e1cd4bcfc91494158df9a1afd3435
MD5 dd6b1d03480abf5d7af36cf87cb55ac3
BLAKE2b-256 794f38f0e9c4a7066b07e71cd123b4e1b68c11a5883379a3eb81461d1662362e

See more details on using hashes here.

File details

Details for the file pydmdeeg-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: pydmdeeg-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydmdeeg-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3c051ecb0bac5c1e79f7f103944b7a2bf5a13eaa2deaf7d22c57d4c6f6bffe0c
MD5 29a42139214d45dd1b77a1302581e524
BLAKE2b-256 8648adb6e794a04cda1f574b92618f538212d48fdf37b8e18ac13467f302651e

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 Pingdom Monitoring Sentry Error logging StatusPage Status page