Project E: The zero-dollar version
Real EEG from 109 people, downloaded free, opened in Python. Find alpha, find a blink, find the heartbeat leaking in. Everything in Phase 1 without buying a part.
You are skimming: the title, the first figure, and the short version. Switch to Read in the header for the full page, or Deep to open every deep dive.
If you have no parts yet, or you want to see what a properly recorded 64-channel EEG looks like before you build a one-channel version, this is the project. PhysioNetPhysioNetA free archive of physiological recordings including EEG, ECG, and sleep data, run out of MIT. Glossary entry hosts the EEG Motor Movement/Imagery dataset: 109 people, 64 electrodes, sampled at 160 Hz, with two one-minute baseline recordings for each person, one with eyes open and one with eyes closed. MNE-PythonMNE-PythonThe standard open-source Python library for EEG and MEG analysis: filtering, epoching, ICA, topographies, source localization. Glossary entry will download it for you. In an hour you will have found alpha in a stranger’s brain and know what a blink and a heartbeat look like on a real recording.
On a 64-channel recording, in which channel will a blink be biggest?
Fp1, the frontal-polar electrode just above the eye. Blinks are eye movement, and the eyeball is a battery whose field is strongest right next to it. At Oz the same blink is a tenth the size.
Setup
pip install mne matplotlib
MNE has a loader for this dataset that fetches only the files you ask for. Run 1 is eyes open, run 2 is eyes closed.
import mne
from mne.datasets import eegbci
paths = eegbci.load_data(subject=1, runs=[1, 2]) # downloads ~2 MB per run
open_eyes = mne.io.read_raw_edf(paths[0], preload=True)
closed = mne.io.read_raw_edf(paths[1], preload=True)
for raw in (open_eyes, closed):
eegbci.standardize(raw) # clean up channel names
raw.set_montage('standard_1005') # tell MNE where the electrodes are
raw.filter(0.5, 40.) # the same band-pass as Project B
Find alpha
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
for raw, label in ((open_eyes, 'eyes open'), (closed, 'eyes closed')):
spec = raw.compute_psd(picks=['O1'], fmax=40)
freqs = spec.freqs; psd = spec.get_data()[0]
ax.semilogy(freqs, psd, label=label)
ax.set(xlabel='Hz', ylabel='power (V²/Hz)', title='Subject 1, O1'); ax.legend(); plt.show()
Two curves. The eyes-closed one has a peak somewhere between 8 and 12 Hz that the eyes-open one does not. That is alpha, in a person you have never met, recorded with a research amplifier. Note the peak frequency; it differs by a hertz or two between people, and it is stable within a person for years.
Try a few subjects. Some have enormous alpha; a few have almost none. Both are normal.
Find a blink
open_eyes.plot(start=0, duration=10, n_channels=8, scalings=dict(eeg=100e-6))
Look at Fp1 and Fp2 at the top. Blinks are the big, slow, paired deflections, a few hundred microvolts, about a third of a second wide, that show up in both frontal channels and fade as you go back. Now look at Oz at the same moment. Small or absent. You have just seen how a source’s location shows up as a pattern across electrodes, which is the physics that Phase 4’s head model is about.
Find the heartbeat
Pick a channel near an ear, such as T7 or TP7, and plot ten seconds with a smaller scaling. Look for a small sharp spike about once a second. That is the heart’s electrical activity, a millivolt on the chest, leaking to the head as a few microvolts. It is in almost every EEG and most people never notice it until it shows up in their average.
Draw the map
closed.compute_psd(fmax=40).plot_topomap(bands={'alpha (8-12 Hz)': (8, 12)})
A head, coloured by alpha power. It should be brightest at the back. This single picture is why Project B puts the electrode where it does.
- Install MNE and run the loader for subject 1, runs 1 and 2.
- Plot the O1 spectrum for both runs and identify the alpha peak. Write down its frequency.
- Plot ten seconds of the eyes-open run and find two blinks in Fp1. Measure their amplitude and width from the plot.
- Find the heartbeat in a temporal channel.
- Plot the alpha topography for eyes closed.
- Repeat step 2 for three more subjects. Save the four spectra as one figure with a legend, axes labelled.
Going further
Load run 3 (a motor task: open and close the left or right fist) and plot the C3 and C4 spectra while the subject moves versus rests. You will see the mu rhythm drop over the hemisphere opposite the moving hand. That is the phenomenon that motor imagery BCIs try to decode, and you have just seen it in a minute of data. Then go to the software pipeline project, which turns tonight’s script into a proper analysis.