The raw EEG signal is a voltage-versus-time trace — informative, but difficult to interpret directly. The Power Spectral Density (PSD) transforms this into a power-versus-frequency representation, revealing the dominant rhythms in the brain. This is arguably the single most important feature extraction step in EEG analysis: nearly every study reports band power in the canonical frequency bands.
From Time to Frequency
The Fourier Intuition
Joseph Fourier’s insight (1807): Any signal can be decomposed into a sum of sine waves at different frequencies, amplitudes, and phases. The Fourier Transform computes exactly this decomposition. The PSD is the squared magnitude of the Fourier coefficients, telling you how much power the signal carries at each frequency.
But there’s a catch: the raw FFT of a long recording gives a jagged, noisy spectrum because each frequency bin has only one estimate. Welch’s method solves this by dividing the signal into overlapping segments, computing the FFT of each, and averaging them.
Cohen’s intuition (ANTS Ch. 10–11): Think of the FFT as a bank of tuning forks. Each tuning fork resonates at one frequency. You hold each fork next to the signal and measure how strongly it vibrates — that’s the power at that frequency. Welch’s method is like repeating this experiment many times and averaging.
Welch’s Method
Segment, Window, Average
Step 1 — Segment: Split the signal into overlapping chunks (typically 50% overlap).
Step 2 — Window: Multiply each chunk by a taper function (Hanning, Hamming) to reduce spectral leakage at the edges.
Step 3 — FFT: Compute the FFT of each tapered chunk.
Step 4 — Average: Average the squared magnitudes across all chunks.
More chunks = smoother spectrum but lower frequency resolution. This is the fundamental resolution–variance tradeoff in spectral estimation.
# MNE's built-in PSD computation spectrum = raw.compute_psd(method='welch', fmin=1, fmax=45, n_fft=2048, n_overlap=1024) spectrum.plot(average=True) # Extract power in specific bands import numpy as np psds, freqs = spectrum.get_data(return_freqs=True) # Alpha band power (8-13 Hz) alpha_mask = (freqs >= 8) & (freqs <= 13) alpha_power = psds[:, alpha_mask].mean(axis=1) print(f"Mean alpha power: {alpha_power.mean():.2e} V^2/Hz")
Canonical EEG Frequency Bands
δ θ α β γ
The EEG community has defined standard frequency bands, each associated with distinct brain states:
δ
1–4 Hz
Deep sleep
Slow-wave
θ
4–8 Hz
Drowsiness
Memory encoding
α
8–13 Hz
Relaxed wakefulness
Eyes closed
β
13–30 Hz
Active thinking
Motor planning
γ
30–100 Hz
Perception
Feature binding
Caution: These band boundaries are conventions, not physiological laws. Individual alpha peak frequency (IAF) varies from ~8 Hz to ~13 Hz across people. Using fixed bands can conflate theta with slow alpha. Days 11–12 (FOOOF, IRASA) address this problem.
Multitaper PSD
A Sneak Preview
Welch’s method reduces variance by averaging over time segments, but each segment still uses a single taper. Multitaper estimation uses multiple orthogonal tapers (DPSS/Slepian sequences) on the same data segment, giving you more independent spectral estimates without sacrificing time resolution. We explore this in depth on Day 15.
# Multitaper PSD in MNE spectrum_mt = raw.compute_psd(method='multitaper', fmin=1, fmax=45, bandwidth=2.0) spectrum_mt.plot(average=True)