eegproc package

eegproc.apply_detrend(detrend, df)[source]
Parameters:
  • detrend (str | None)

  • df (DataFrame)

Return type:

DataFrame

eegproc.bandpass_filter(df, fs, bands={'alpha': (8.0, 13.0), 'betaH': (20.0, 30.0), 'betaL': (13.0, 20.0), 'delta': (0.5, 4.0), 'gamma': (30.0, 45.0), 'theta': (4.0, 8.0)}, low=None, high=None, *, order=4, notch_hz=[60, 120], notch_q=30.0, reref=True, detrend=True)[source]

Applies band-pass filtering over raw EEG data on each channel.

Pipeline

  1. Coerce to numeric (with interpolation).

  2. Optional common average reference (CAR) across channels (reref=True).

  3. Optional notch filtering at notch_hz (and 2x harmonics when safe).

4a) If bands is a dict: apply a per-band Butterworth band-pass (SOS) and

return columns named {channel}_{band}.

4b) Else: require (low, high) and apply a single band-pass to each channel,

returning the original channel names.

  1. Optional constant detrending per output column.

type df:

DataFrame

param df:

Raw data EEG dataframe. Numeric columns; NaNs are interpolated internally by _numeric_interp before filtering.

type df:

pandas.DataFrame

type fs:

float

param fs:

Sampling rate in Hz.

type fs:

float

type bands:

dict[str, tuple[float, float]], default: {'delta': (0.5, 4.0), 'theta': (4.0, 8.0), 'alpha': (8.0, 13.0), 'betaL': (13.0, 20.0), 'betaH': (20.0, 30.0), 'gamma': (30.0, 45.0)}

param bands:

If provided, a mapping from band name to (low, high) in Hz. When given, one output column per {channel}_{band} is produced. If None, low and high must be provided to define a single passband.

type bands:

dict[str, tuple[float, float]] or None, default=FREQUENCY_BANDS

type low:

Optional[float], default: None

param low:

Low cutoff in Hz for the single band-pass path (ignored if bands provided).

type low:

float or None, default=None

type high:

Optional[float], default: None

param high:

High cutoff in Hz for the single band-pass path (ignored if bands provided).

type high:

float or None, default=None

type order:

int, default: 4

param order:

Butterworth filter order for band-pass design.

type order:

int, default=4

type notch_hz:

float | int | list | tuple | None, default: [60, 120]

param notch_hz:

Fundamental notch frequency/frequencies. None disables notch filtering.

type notch_hz:

float | int | list | tuple | None, default=[60, 120]

type notch_q:

float, default: 30.0

param notch_q:

Quality factor for the notch (higher = narrower).

type notch_q:

float, default=30.0

type reref:

bool, default: True

param reref:

If True and there are ≥2 channels, apply common average reference (CAR).

type reref:

bool, default=True

type detrend:

bool, default: True

param detrend:

If True, remove the mean (constant detrend) after filtering.

type detrend:

bool, default=True

rtype:

DataFrame

returns:

pandas.DataFrame – Filtered dataframe indexed like the input. If bands is provided, columns are {channel}_{band}; otherwise, the original channel names are preserved.

raises ValueError:
  • When bands is None and either low or high is missing. - When any cutoff does not satisfy 0 < low < high < fs/2. - When a band in bands violates Nyquist constraints.

Warning

RuntimeWarning

Emitted when reref=True but only one channel is present (CAR requires ≥2).

Notes

  • Band-pass filters are designed with scipy.signal.butter(..., output="sos") and applied with a NaN-robust zero-phase filter via _sosfiltfilt_safe().

  • Notch filtering is applied once before band-pass filtering.

  • Constant detrend uses scipy.signal.detrend(..., type="constant").

  • For stability, very short columns may be skipped inside helper routines.

eegproc.hjorth_params(df, fs, window_sec=4.0, overlap=0.5, detrend='constant', eps=1e-300)[source]

Compute Hjorth parameters (activity, mobility, complexity) per channel over windows.

Expects columns named {channel}_{band} where each band is a key in bands (bandpass_filter) may be used to achieve the expected table. For each numeric column, the function computes: - Activity: variance of the signal - Mobility: sqrt(var(Δx) / var(x)) - Complexity: mobility(Δx) / mobility(x)

Parameters:
  • df (pandas.DataFrame) – Bandpass Filtered EEG dataframe. Numeric columns must be named like {channel}_{band} (e.g., AF3_alpha).

  • fs (float) – Sampling rate in Hz.

  • window_sec (float, default=4.0) – Window length in seconds.

  • overlap (float, default=0.5) – Fractional overlap in [0, 1) between windows.

  • detrend ({"constant", "linear", None}, default="constant") – Detrending applied per column prior to differencing.

  • eps (float, default=1e-300) – Numerical guard to prevent division by zero.

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window, with columns: {channel}_activity, {channel}_mobility, {channel}_complexity.

Raises:

ValueError – If window is too small (needs >= 3 samples) or overlap is invalid.

eegproc.imf_band_energy(df, fs, imf_to_band=['gamma', 'betaH', 'betaL', 'alpha', 'theta', 'delta'], window_sec=4.0, overlap=0.5, EMD_kwargs={})[source]

Compute Intrinsic Mode Function (IMF) band-energy distributions per channel using Empirical Mode Decomposition (EMD).

Expects columns named {channel} where each row is a reading of raw EEG data. For each column, applies EMD decomposition to find mean m(t) of envelopes (cubic splines fit to extremas) and takes difference between raw data point and m(t) [d(t) = x(t) - m(t)]. For each window and channel, the IMF band-energy is based on the cumulative sums of the IMFs returned by the EMD function.

Parameters:
  • df (pandas.DataFrame) – Raw data EEG dataframe. Numeric columns.

  • fs (float) – Sampling rate in Hz (used only for window sizing).

  • imf_to_band (list[str], default=["gamma", "betaH", "betaL", "alpha", "theta", "delta"]) – Labels to assign to IMFs 1..K (K = number of labels).

  • window_sec (float, default=4.0) – Window length in seconds.

  • overlap (float, default=0.5) – Fractional overlap in [0, 1).

  • EMD_kwargs (dict, default={}) – Extra keyword arguments passed to PyEMD.EMD (e.g., max_imf is internally set).

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window; columns: {channel}_{band}_imfenergy for each band label.

Raises:

ValueError – If window too small, overlap invalid, or window longer than available samples.

Notes

  • IMF indices are assigned in order to the names in imf_to_band; if fewer IMFs are present than labels, missing energies are filled with 0.0.

  • The EMD is computed once per full signal and reused for all windows via cumulative sums.

eegproc.imf_entropy(imf_energy_df, bands=['gamma', 'betaH', 'betaL', 'alpha', 'theta', 'delta'], normalize=True, eps=1e-300)[source]

Compute (normalized) Shannon entropy of IMF energy distributions per channel.

For each window and channel, uses the vector of _imfenergy values across bands as a distribution and computes -Σplogp. Optionally normalizes by log(K) where K = len(bands).

Parameters:
  • imf_energy_df (pandas.DataFrame) – Output from imf_band_energy() with columns {ch}_{band}_imfenergy.

  • bands (list[str], default=["gamma", "betaH", "betaL", "alpha", "theta", "delta"]) – Band labels (order defines component order).

  • normalize (bool, default=True) – If True, divide entropy by log(K) to obtain values in [0, 1].

  • eps (float, default=1e-300) – Numerical guard for zero energies.

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window; columns {ch}_imfentropy.

eegproc.psd_bandpowers(df, fs, bands={'alpha': (8.0, 13.0), 'betaH': (20.0, 30.0), 'betaL': (13.0, 20.0), 'delta': (0.5, 4.0), 'gamma': (30.0, 45.0), 'theta': (4.0, 8.0)}, window_sec=4.0, overlap=0.5, detrend='constant')[source]

Compute Welch PSD band powers per channel-band column over selected window size.

Expects columns named {channel}_{band} where each band is a key in bands (bandpass_filter) may be used to achieve the expected table. Each row of the expected df is a wave amplitude reading of the channel-band combination. For each window, integrates the Welch PSD within each band using the trapezoid rule.

Parameters:
  • df (pandas.DataFrame) – Bandpass Filtered EEG dataframe. Numeric columns must be named like {channel}_{band} (e.g., AF3_alpha).

  • fs (float) – Sampling rate in Hz.

  • bands (dict[str, tuple[float, float]], default=FREQUENCY_BANDS) – Mapping of band name to inclusive frequency bounds (Hz) (lo, hi).

  • window_sec (float, default=4.0) – Window length in seconds used for Welch’s method (nperseg = round(fs*window_sec)).

  • overlap (float, default=0.5) – Fractional overlap in [0, 1) between consecutive windows.

  • detrend ({"constant", "linear", None}, default="constant") – Detrending applied before PSD computation via apply_detrend.

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window, columns match the input band columns (e.g., AF3_alpha) and contain power spectral density-integrated band powers.

Raises:

ValueError – If no valid {channel}_{band} columns are found, if the window is too small, or if overlap is outside [0, 1).

Notes

  • Uses scipy.signal.welch with a Hann window and no overlap inside the Welch call (windowing/overlap are controlled at the outer sliding-window level).

Examples

Minimal example with synthetic data (two channels, one band):

>>> import numpy as np, pandas as pd
>>> fs = 128.0
>>> t = np.arange(int(8*fs)) / fs   # 8 seconds
>>> # Two synthetic signals with an ~10 Hz component (alpha band)
>>> af3_alpha = 0.8*np.sin(2*np.pi*10*t) + 0.1*np.random.randn(t.size)
>>> f7_alpha  = 0.6*np.sin(2*np.pi*10*t + 0.7) + 0.1*np.random.randn(t.size)
>>> df = pd.DataFrame({
...     "AF3_alpha": af3_alpha,
...     "F7_alpha":  f7_alpha,
... })
>>> bands = {"alpha": (8.0, 12.0)}
>>> out = psd_bandpowers(df, fs=fs, bands=bands, window_sec=2.0, overlap=0.5)
>>> out.head()  
       AF3_alpha   F7_alpha
0       ...         ...
1       ...         ...
2       ...         ...
eegproc.shannons_entropy(df, fs, bands={'alpha': (8.0, 13.0), 'betaH': (20.0, 30.0), 'betaL': (13.0, 20.0), 'delta': (0.5, 4.0), 'gamma': (30.0, 45.0), 'theta': (4.0, 8.0)}, window_sec=4.0, overlap=0.5, eps=1e-300, detrend='constant')[source]

Compute normalized Shannon spectral entropy per channel-band over windows.

Expects columns named {channel}_{band} where each band is a key in bands (bandpass_filter) may be used to achieve the expected table. For each {channel}_{band} column, computes a Welch PSD in the band’s frequency range, then it converts each windowed row (bin) of energy to probability. Returns -Σplog2p/log2(#bins) in [0, 1] (NaN if insufficient bins or invalid totals).

Parameters:
  • df (pandas.DataFrame) – Bandpass Filtered EEG dataframe. Numeric columns must be named like {channel}_{band} (e.g., AF3_alpha).

  • fs (float) – Sampling rate in Hz.

  • bands (dict[str, tuple[float, float]], default=FREQUENCY_BANDS) – Mapping from band name to inclusive frequency bounds (Hz).

  • window_sec (float, default=4.0) – Window length in seconds for Welch.

  • overlap (float, default=0.5) – Fractional overlap in [0, 1) between windows.

  • eps (float, default=1e-300) – Numerical guard to avoid log(0) and zero division.

  • detrend ({"constant", "linear", None}, default="constant") – Detrending applied before PSD and Shannon.

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window. Columns are {channel}_{band}_entropy for each input band column.

Raises:

ValueError – If no band-annotated columns are found, window is too small, or overlap invalid.

Notes

  • Entropy is normalized by log2(count_of_band_bins) to yield values in [0, 1].

  • Outputs NaN when a band’s PSD has < 2 valid bins in a window.

eegproc.wavelet_band_energy(df, fs, bands, wavelet='db4', mode='periodization', window_sec=4.0, overlap=0.5)[source]

Compute band energies by distributing DWT subband energies into target bands.

Expects columns named {channel} where each row is a reading of raw EEG data. For each window and channel, performs a multilevel DWT, computes energy in each detail/approximation subband, then proportionally assigns subband energy to user bands by frequency overlap.

Parameters:
  • df (pandas.DataFrame) – Raw data EEG dataframe. Numeric columns.

  • fs (float) – Sampling rate in Hz.

  • bands (dict[str, tuple[float, float]]) – Target bands as {name: (lo, hi)} in Hz.

  • wavelet (str, default="db4") – PyWavelets wavelet name for pywt.wavedec.

  • mode (str, default="periodization") – Signal extension mode for DWT.

  • window_sec (float, default=4.0) – Window length in seconds.

  • overlap (float, default=0.5) – Fractional overlap in [0, 1).

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window; columns: {channel}_{band}_wenergy for each channel in df and each band in bands.

Raises:

ValueError – If window too small, overlap invalid, or window longer than available samples.

Notes

  • The DWT level is chosen automatically via choose_dwt_level() to respect both data length and minimum target band frequency.

  • Energy is computed as the sum of squared coefficients per subband.

  • Subband energy is apportioned to target bands by fractional frequency overlap.

eegproc.wavelet_entropy(wv_band_energy_df, bands, normalize=True, eps=1e-300)[source]

Compute (optionally normalized) Shannon entropy of wavelet band-energy distributions per channel.

Expects columns {channel}_{band}_wenergy where each row is a windowed wavelet band energy. For each window and channel, treats the vector of _wenergy values across bands as a distribution, then computes -Σplogp. Optionally normalizes by log(K) where K = len(bands).

Parameters:
  • wv_band_energy_df (pandas.DataFrame) – Output of wavelet_band_energy(); columns like {ch}_{band}_wenergy.

  • bands (dict[str, tuple[float, float]]) – Same band dictionary used for energy computation (order defines component order).

  • normalize (bool, default=True) – If True, divide entropy by log(K) to obtain values in [0, 1].

  • eps (float, default=1e-300) – Numerical guard for zero energies.

Return type:

DataFrame

Returns:

pandas.DataFrame – One row per window, columns {ch}_wentropy.

Raises:

ValueError – If no matching {channel}_{band}_wenergy columns are found.

Subpackages

Submodules