Standard PSD analysis assumes a signal has stable frequency content over time. But neural oscillations are not stationary — alpha frequency drifts, theta bursts come and go, and the brain constantly shifts between spectral states. Frequency sliding tracks how the instantaneous frequency of a narrow-band signal changes moment by moment.
What is Instantaneous Frequency?
Phase Derivative of the Analytic Signal
The Hilbert transform (covered in detail on Day 16) converts a real-valued signal into a complex-valued analytic signal with instantaneous amplitude (envelope) and instantaneous phase. The instantaneous frequency is simply the time derivative of the instantaneous phase:
f(t) = (1 / 2π) · dφ(t) / dt
When the phase advances quickly, the instantaneous frequency is high. When it advances slowly, the frequency is low. This gives you a single number at every time point representing the dominant frequency of your filtered signal.
Cohen’s analogy (ANTS Ch. 14): Think of a spinning wheel. The phase is the current angle of the wheel. The instantaneous frequency is how fast the wheel is spinning right now. If the wheel speeds up, the instantaneous frequency increases — even though the “average RPM” over a long window might not change much.
The Frequency Sliding Pipeline
Filter → Hilbert → Phase → Derivative
Step 1: Band-pass filter around the oscillation of interest (e.g., 8–13 Hz for alpha).
Step 2: Apply the Hilbert transform to get the analytic signal.
Step 3: Extract instantaneous phase with np.angle().
Step 4: Unwrap the phase (remove 2π jumps) and compute the time derivative.
Step 5: Convert from radians/sample to Hz.
from scipy.signal import hilbert import numpy as np # Band-pass filter around alpha raw_alpha = raw.copy().filter(l_freq=8, h_freq=13) data = raw_alpha.get_data(picks='Oz')[0] # Hilbert transform → analytic signal analytic = hilbert(data) inst_phase = np.angle(analytic) # Unwrap & differentiate → instantaneous frequency phase_unwrapped = np.unwrap(inst_phase) inst_freq = np.diff(phase_unwrapped) / (2 * np.pi) * raw.info['sfreq'] # Smooth with a short moving average to reduce noise kernel = np.ones(50) / 50 inst_freq_smooth = np.convolve(inst_freq, kernel, mode='same')
Edge effects: The Hilbert transform produces artifacts at the beginning and end of the signal. Always discard the first and last ~500 ms of the instantaneous frequency trace. Also, instantaneous frequency is only meaningful for narrow-band signals — applying it to broadband data yields noisy, uninterpretable results.
Why Frequency Slides
Non-Stationarity in Neural Oscillations
Neural oscillations are not perfect sine waves locked to a fixed frequency. Alpha rhythm, for example, “slides” between ~8 and ~12 Hz depending on cognitive load, arousal, and task demands. Frequency sliding captures these dynamics:
• Alpha peak slows during drowsiness and increases during alert attention.
• Theta frequency shifts during memory encoding vs. retrieval.
• Beta bursts show frequency jitter around motor events.
This information is invisible to static PSD analysis, which averages over the entire recording.
Key reference: Cohen (2014), “Fluctuations in oscillation frequency control spike timing and coordinate neural networks.” Journal of Neuroscience.