Level 2 L2.4 pipeline thread

Filtering in practice

Goal-dependent high-pass and low-pass settings, the two-pass ICA strategy, boundary events, and when to downsample.

~45 min Widget: w-filter-sandbox Notebook: nb-2-4-filter-choices

Prerequisites: L1.5 · Filters: FIR, IIR, and what they do to your data, L2.3 · Re-referencing

1 claim on this page is unverified. TODO(confirm) marks a specific statement the author has not yet checked against a primary source. Everything else on this page has been reviewed. Treat a marked claim as provisional and go to the cited source rather than quoting the sentence.

Objectives

  • Choose high-pass and low-pass settings for ERP, oscillation and ICA goals
  • Implement the two-pass strategy (1 Hz copy for the ICA fit, applied to 0.1 Hz data)
  • Handle boundary events
  • Decide when to downsample

Why this matters

L1.5 showed what a filter does to a signal. This lesson is about where the filter goes and which settings the analysis actually needs — because the same filter that is correct for an ICA fit will distort the ERP you are fitting it for, and the same filter applied to epochs instead of continuous data puts its edge artifacts inside your measurement window. Filtering is a pipeline decision before it is a signal-processing decision.

Concepts

Settings follow the goal, not the habit

There is no default filter that is right for everything, because the three things people do with EEG want different bands and tolerate different distortions.

ERPs. The components are slow and broad, so the high-pass is the dangerous filter. A conservative cutoff — on the order of 0.1 Hz or lower — preserves slow components such as P3 and the CNV; higher cutoffs attenuate them and, because offline filters are zero-phase, redistribute the removed energy symmetrically in time as artifactual opposite-polarity deflections before and after the real component (Tanner, 2015) . A low-pass in the region of 30 Hz is usually harmless for measurement and mostly cosmetic: it makes waveforms readable without changing a mean amplitude much. Report both cutoffs, the filter type, its length or order, and whether it was applied zero-phase (Widmann, 2015) .

Oscillations (Level 4). A higher high-pass — near 1 Hz — is common because drift otherwise dominates the low end of a spectrum, and the slow components an ERP analyst protects are not the object of study. The real hazard here is the opposite one: a narrow band-pass makes noise look rhythmic (L4.3, L4.6). Prefer estimating a spectrum on lightly filtered data.

An ICA fit. ICA is a stationary linear model, and slow drift is neither stationary nor low-dimensional. Fitting on data high-passed around 1 Hz gives markedly better-separated components than fitting on data high-passed at 0.1 Hz. But a 1 Hz high-pass is exactly what you must not apply to ERP data. That is the reason for the two-pass strategy.

The two-pass strategy

The key point is that ICA produces a matrix, not data. You can estimate the unmixing matrix on one version of the recording and apply it to another, as long as the two share the same channels in the same order and the same reference:

  1. Copy the continuous data and high-pass the copy at about 1 Hz.
  2. Fit ICA on the copy, with the correct rank (L2.2, L2.6).
  3. Identify and mark the components to remove, using the copy.
  4. Apply the resulting unmixing/mixing operation to the analysis data — the 0.1 Hz-filtered continuous recording — and reconstruct.
raw_analysis = raw.copy().filter(l_freq=0.1, h_freq=30.)     # what you will analyse
raw_for_ica  = raw.copy().filter(l_freq=1.0, h_freq=None)    # what ICA sees
ica = mne.preprocessing.ICA(n_components=rank, random_state=seed)
ica.fit(raw_for_ica)
ica.exclude = [...]                                          # decided in L2.6
raw_clean = ica.apply(raw_analysis.copy())

What travels between the two copies is the matrix; the filtered signal does not. This is also why the widget’s pipeline mode draws the two copies side by side: they are different data, and the arrow between them carries only the unmixing.

Filter continuous data, before epoching

A filter needs samples on both sides of every point it computes. At the beginning and end of the data those samples do not exist, and the implementation pads — with zeros, a reflection, or a constant — so the first and last stretch of output, roughly as long as the filter’s impulse response, is contaminated.

On a continuous recording those contaminated stretches are at the ends of the file, minutes away from anything you care about. On a 1-second epoch they are inside the epoch, and for a low high-pass the impulse response is longer than the epoch itself: there is nowhere for the edge artifact to go. Filtering epoched data is the pitfall pf-filter-epoched-data below. The rule: filter the continuous recording, then epoch, and keep epoch edges well away from any transient you care about.

Boundaries and discontinuities

The same argument applies wherever the continuous data is discontinuous: two files concatenated, a recording break, a segment removed. A filter run across such a joint rings on both sides of it (pf-filter-across-boundaries).

MNE handles this with BAD boundary annotations: mne.concatenate_raws inserts them, and raw.filter() respects them when filtering, so each contiguous span is filtered independently. Two habits keep it honest: never remove data by slicing and re-concatenating the array yourself (mark it bad instead, L2.5), and check that the boundary annotations survived every step of your pipeline — cropping, resampling and re-referencing all preserve them, but a round trip through a format that does not store annotations does not.

Downsampling: after the low-pass, and only for a reason

Downsampling without an anti-alias low-pass folds high-frequency content into your band (pf-aliasing-on-downsample, L1.1). MNE’s raw.resample() applies the anti-alias filter for you, but two subtleties matter in a pipeline:

  • Resample before epoching, or use Epochs.resample, but do not resample events separately. Event sample indices are only valid at the rate they were built for. Resampling continuous data with its annotations attached keeps the timing (annotations are in seconds); resampling an array of event samples by hand introduces jitter of up to one sample at the new rate, which can be several milliseconds.
  • Ask what you gain. Downsampling 1024 Hz ERP CORE data to 256 Hz makes ICA about four times faster and costs nothing above 128 Hz that an ERP analysis wanted. Downsampling to 100 Hz to save disk, and then wanting gamma, is not recoverable.

A related habit worth keeping: the low-pass you apply for anti-aliasing is a real filter with real side effects, so state it with the others rather than treating the resampling call as a formatting step.

Judgment call

Every filter in a pipeline should have a sentence attached: what it is for, what it costs, and what the analysis would look like without it. If you cannot write the sentence, the filter is a habit. The stronger version of this argument — filter as little as the data allow — is made in the L1.5 reading and is worth taking seriously even when you decide against it.

The data behind this lesson

  • The widget’s traces are the Level 1 set: four 10-second single-channel recordings and one 8-channel segment from ds-eegbci (160 Hz, no hardware filters) plus a line-noise trace from ds-iowapd (500 Hz). In pipeline mode the filtering is illustrative of placement; the ERP consequences are measured in the notebook on real ERP data.
  • The notebook works on ds-erpcore P3 data: CC BY 4.0, open, per-subject downloadable, 30 EEG + 3 EOG channels, 1024 Hz, 60 Hz mains, no software filters. TODO(confirm): the author mirrors the ERP CORE entry into the catalog registry and signs off the dataset page (§10.11 item 8).

Explore

Filter sandbox, pipeline mode — where the filter sits relative to epoching and the ICA fit

mode: pipeline Open lab page →
Loading Filter sandbox, pipeline mode — where the filter sits relative to epoching and the ICA fit…

What to look for

Data: ds-eegbci , subject S001, run R01, 36–46 s · license ODC-By-1.0 · DOI 10.13026/C28G6P · labels: algorithmic · a cropped, re-referenced or filtered derivative of the source recording.

Three things to do here: apply the same high-pass to the continuous trace and to a short epoch cut from it, and compare the epoch edges; move the filter from before epoching to after and watch what happens inside the analysis window; then switch on the two-pass view and check that the 1 Hz copy and the 0.1 Hz copy are visibly different data while the arrow between them carries only the unmixing matrix.

Practice

Filtering in practice: ERP distortion across six high-pass cutoffs, the two-pass ICA strategy measured, filtering epoched data, and a boundary artifact nb-2-4-filter-choices

Level 2 ~4 min
notebooks/L2/nb-2-4-filter-choices.ipynb

Downloads from ds-erpcore.

Open in Colab Download Read it here

The notebook measures ERP distortion across high-pass cutoffs on ds-erpcore and demonstrates a boundary artifact by concatenating two runs with and without boundary handling. Its final cell prints the measured amplitudes and the boundary ringing duration.

Exercises

Three analyses, three sets of settings. Pick the defensible option for each, then write the reasoning.

Exercise ex-2-4-settings-erp

Multiple choice

Analysis 1: you will measure the mean amplitude of the P3 (a slow, broad positivity around 300–600 ms) in an a-priori window, on continuous data you have not yet epoched. Which filter settings?

Options

Exercise ex-2-4-settings-ica

Multiple choice

Analysis 2: the same recording, but now you want an ICA decomposition good enough to identify blink and muscle components, and you will then analyse the P3 on the cleaned data. Which filter settings?

Options

Exercise ex-2-4-settings-oscillation

Multiple choice

Analysis 3: the same subjects, but now you want the alpha-band power difference between eyes-open and eyes-closed rest, estimated from the spectrum. Which filter settings?

Options

Exercise ex-2-4-reasoning

Free response

Write the reasoning for your three choices: for each analysis, one sentence saying what the filter is for and one saying what it costs.

Pitfalls

Pitfall

High-pass cutoffs that distort slow ERPs

Symptom
Artifactual early components; attenuated late components.
Cause

Slow ERP components have most of their energy at low frequencies. A high-pass filter removes that energy, and because the standard offline filter is zero-phase, the removed energy is redistributed symmetrically in time: a large positive deflection is accompanied by negative deflections before and after it that were not in the data. The higher the cutoff (and the sharper the filter), the larger an…

Detect
  • Filter a single trace containing a known slow transient (the sandbox’s electrode pop, or a simulated boxcar of the component’s duration) with your chosen high-pass and look at what appears on either side. - Compute the ERP at several high-pass cutoffs (0.01, 0.1, 0.5, 1 Hz) and plot them together; an amplitude that falls steadily with cutoff, or a deflection that grows with cutoff, is a filter…
Fix
  • Use a conservative high-pass for ERPs — on the order of 0.1 Hz or lower — with a gentle transition band, and state the cutoff, filter type, order or length, and direction (zero-phase or causal) in the methods. - Treat the cutoff as an analysis choice to be justified, not a default: filter as little as the data allow and remove drift by other means where possible (good recording practice, baseli…

Full entry with example →

Pitfall

Filtering short epochs

Symptom
Edge artifacts inside the analysis window.
Cause

A filter needs samples on both sides of every point it computes. In a short epoch those samples do not exist near the edges, so the implementation pads (with zeros, a mirror image, or a constant); the padded values are not data, and the filter’s response to the padding leaks into the epoch by the length of its impulse response. For a high-pass with a low cutoff that length can exceed the whole ep…

Detect
  • Compare the ERP computed from epochs cut before filtering against the ERP from data filtered continuously and epoched afterwards; any difference is edge effect. - Compute the impulse-response length of the filter (FIR: the number of taps; IIR: the settling time) and compare it with the epoch length. - Plot the average of the pre-stimulus baseline across trials: a systematic slope or curvature n…
Fix
  • Filter continuous data, then epoch (the canonical order in L2.8). - If data are only available as epochs, use epochs long enough that the analysis window lies more than one impulse-response length from each edge, and state the padding method. - Choose the mildest filter that serves the goal; a lower-order or wider-transition-band filter has a shorter impulse response. - For real-time or single-…

Full entry with example →

In other tools

In other toolsEEGLAB · FieldTrip — names only

The equivalents of what this lesson does, for a reader who works in another toolbox. Function names only: their own documentation is the place to learn how to call them.

EEGLAB

  • pop_eegfiltnewfirfilt plugin

FieldTrip

  • ft_preprocessing(hpfilter/lpfilter)FieldTrip

Names checked 2026-09-18 against EEGLAB 2026.0.0 (plugins at the versions in EEGLAB’s own plugin list) and FieldTrip 20251218.

Reading

  1. Widmann, Schröger & Maess (2015). Digital filter design for electrophysiological data. unverified
  2. Tanner, Morgan-Short & Luck (2015). Inappropriate high-pass filters. unverified