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
Coerce to numeric (with interpolation).
Optional common average reference (CAR) across channels (
reref=True).Optional notch filtering at
notch_hz(and 2x harmonics when safe).
- 4a) If
bandsis 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.
Optional constant detrending per output column.
- type df:
DataFrame- param df:
Raw data EEG dataframe. Numeric columns; NaNs are interpolated internally by
_numeric_interpbefore 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. IfNone,lowandhighmust 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
bandsprovided).- 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
bandsprovided).- 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.
Nonedisables 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
bandsis provided, columns are{channel}_{band}; otherwise, the original channel names are preserved.- raises ValueError:
When
bandsisNoneand eitherloworhighis missing. - When any cutoff does not satisfy0 < low < high < fs/2. - When a band inbandsviolates Nyquist constraints.
Warning
- RuntimeWarning
Emitted when
reref=Truebut 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 eachbandis a key inbands(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_imfis internally set).
- Return type:
DataFrame- Returns:
pandas.DataFrame – One row per window; columns:
{channel}_{band}_imfenergyfor 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
_imfenergyvalues acrossbandsas a distribution and computes-Σplogp. Optionally normalizes bylog(K)whereK = 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 eachbandis a key inbands(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 ifoverlapis outside[0, 1).
Notes
Uses
scipy.signal.welchwith 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 eachbandis a key inbands(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}_entropyfor 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}_wenergyfor eachchannelindfand each band inbands.- Raises:
ValueError – If window too small,
overlapinvalid, 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}_wenergywhere each row is a windowed wavelet band energy. For each window and channel, treats the vector of_wenergyvalues acrossbandsas a distribution, then computes-Σplogp. Optionally normalizes bylog(K)whereK = 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}_wenergycolumns are found.