Chapter 4: Preprocessing — Filtering and Referencing¶
Preprocessing cleans up the continuous Raw signal before we cut it into epochs. This chapter covers filtering (removing unwanted frequency content) and re-referencing (changing the reference electrode scheme from Chapter 1).
import mne
import matplotlib.pyplot as plt
from pathlib import Path
mne.set_log_level("WARNING")
sample_folder = Path(mne.datasets.sample.data_path()) / "MEG" / "sample"
raw = mne.io.read_raw_fif(sample_folder / "sample_audvis_raw.fif", preload=True)
raw.pick(["eeg", "eog"])
raw
| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | and | |
| EOG | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
Filtering¶
A filter removes signal outside a chosen frequency range. Three kinds show up constantly in EEG preprocessing:
- High-pass filter (removes frequencies below a cutoff, e.g. 1 Hz): eliminates slow drift from sweat, electrode/skin impedance changes, and amplifier drift.
- Low-pass filter (removes frequencies above a cutoff, e.g. 40 Hz): eliminates muscle activity and other high-frequency noise; most ERP components live below 30 Hz anyway.
- Band-pass filter: a high-pass and low-pass combined in one call —
raw.filter(l_freq=1.0, h_freq=40.0). - Notch filter: removes a narrow frequency band, specifically targeting electrical line noise at 50 Hz (most of the world) or 60 Hz (Americas, parts of Asia) and its harmonics.
Let's filter and compare the power spectrum before/after.
raw.compute_psd(picks="eeg").plot()
plt.gcf().suptitle("Before filtering")
plt.show()
raw_filt = raw.copy().filter(l_freq=1.0, h_freq=40.0)
raw_filt.compute_psd(picks="eeg").plot()
plt.gcf().suptitle("After 1-40 Hz band-pass")
plt.show()


Notice the after-plot has essentially no power below 1 Hz or above 40 Hz — those bands are gone. This sample dataset happens to already be free of strong line noise, but the same call for a noisy recording (like your own) also needs a notch filter:
LINE_FREQ = 50 # or 60, depending on your country's mains frequency
raw_filt.notch_filter(freqs=LINE_FREQ)
Why filter before epoching, not after? Filters need some "runway" of data on either side of the segment they're applied to, to avoid edge artifacts. Filtering the full continuous recording first, then cutting into short epochs afterward, avoids distorting the start/end of each short epoch.
Re-referencing¶
Recall from Chapter 1: every EEG value is "this electrode minus a reference". You can mathematically switch references after the fact with set_eeg_reference(). The most common target for ERP work is the average reference — every channel's reference becomes the mean of all EEG channels.
raw_avg_ref = raw_filt.copy().set_eeg_reference(ref_channels="average")
raw_avg_ref
| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | and | |
| EOG | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 1.00 Hz | |
| Lowpass | 40.00 Hz | |
Other options: set_eeg_reference(ref_channels=["M1", "M2"]) for linked mastoids, or ref_channels=["Cz"] for a single-channel reference. There's no universally "correct" choice — it depends on your study design and what's conventional in your subfield/comparable prior work. If you're not sure, average reference is a reasonable default for exploratory ERP work.
A note on your own data: your file's channels are already referenced to CPz (visible in the original names, Fp1-CPz etc). That's a valid single-channel reference already in place — you can leave it as-is, or re-reference to average/mastoids the same way shown here if you have a reason to (e.g. matching a specific published paradigm's conventions).
Summary¶
- Band-pass filter (e.g. 1–40 Hz) removes drift and high-frequency noise; notch filter removes line noise.
- Always filter the continuous
Rawdata, before epoching. set_eeg_reference()mathematically switches the reference scheme after recording.