On Day 9 you learned to compute PSD and extract band power. But here is the uncomfortable truth: traditional band power is confounded. What you measure as “alpha power” is actually a mixture of the genuine alpha oscillation plus the underlying 1/f aperiodic background. If the background shifts, your “alpha power” changes even when the oscillation itself hasn’t. FOOOF (now called specparam) solves this by mathematically decomposing the spectrum into its periodic and aperiodic components.
The 1/f Problem
Why Traditional Band Power is Confounded
Every neural power spectrum has two components riding on top of each other:
Aperiodic (1/f) component: A broadband, non-oscillatory background where power decreases as frequency increases, following a power law: P(f) = b · f−χ. The exponent χ (chi) reflects the balance between neural excitation and inhibition (E/I balance).
Periodic (oscillatory) component: The rhythmic peaks that rise above the 1/f background — your alpha, theta, beta oscillations.
When you compute “alpha power” by integrating 8–13 Hz, you are measuring both components lumped together. A steeper 1/f slope will inflate low-frequency band power and deflate high-frequency band power, even with zero change in actual oscillations.
Donoghue et al. (2020): “Parameterizing neural power spectra into periodic and aperiodic components” — the foundational paper showing that ignoring the aperiodic component leads to systematic misinterpretation of oscillatory changes across development, aging, and clinical conditions.
How specparam Works
Fit Background → Subtract → Find Peaks
The algorithm operates in three stages:
Stage 1 — Aperiodic fit: Model the 1/f background as a line in log-log space (or with a knee for spectra that flatten at low frequencies). Parameters: offset (overall power level) and exponent (slope steepness).
Stage 2 — Flatten: Subtract the aperiodic model from the spectrum. What remains are the oscillatory peaks sitting on a flat baseline.
Stage 3 — Peak detection: Fit Gaussians to the remaining peaks. Each peak is characterized by three parameters: center frequency, power (height above background), and bandwidth.
from specparam import SpectralModel # Compute PSD first spectrum = raw.compute_psd(method='welch', fmin=1, fmax=40) psds, freqs = spectrum.get_data(return_freqs=True) # Fit specparam on a single channel fm = SpectralModel(peak_width_limits=[1, 8], max_n_peaks=6, min_peak_height=0.1) fm.fit(freqs, psds[0], [1, 40]) fm.report() # Extract results print(f"Aperiodic: offset={fm.aperiodic_params_[0]:.2f}, " f"exponent={fm.aperiodic_params_[1]:.2f}") print(f"Peaks found: {len(fm.peak_params_)}") for peak in fm.peak_params_: print(f" CF={peak[0]:.1f} Hz, Power={peak[1]:.2f}, BW={peak[2]:.1f}")
The Aperiodic Exponent
A Window into E/I Balance
The aperiodic exponent is emerging as a powerful biomarker in its own right. Computational models show that a steeper exponent (more negative slope) reflects greater inhibition-dominant neural activity, while a flatter exponent reflects greater excitation.
This has clinical implications: the exponent changes systematically with aging (flattens), anaesthesia (steepens), ADHD (flatter), and disorders of consciousness.
Data-driven advantage: Unlike fixed band boundaries, specparam discovers where peaks actually are in your data. If a participant’s alpha peak is at 9.5 Hz instead of the canonical 10 Hz, specparam finds it automatically.
Batch Processing
SpectralGroupModel for Multiple Spectra
In practice you need to fit models across all channels, all subjects, and all conditions.
SpectralGroupModel handles this efficiently:
from specparam import SpectralGroupModel # Fit all channels at once fg = SpectralGroupModel(peak_width_limits=[1, 8], max_n_peaks=6, min_peak_height=0.1) fg.fit(freqs, psds, [1, 40]) # Extract exponents across all channels exponents = fg.get_params('aperiodic_params', 'exponent') print(f"Mean exponent: {exponents.mean():.2f} +/- {exponents.std():.2f}")