Filters: FIR, IIR, and what they do to your data
Choose a filter type, cutoff and transition band for a stated goal, and predict the distortions it will introduce.
Prerequisites: L1.2 · Time and frequency domains, L1.3 · Power spectral density
5 claims on this page are 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 filter type, cutoff and transition band for an ERP, an oscillation analysis and an ICA fit
- Explain zero-phase filtering and its non-causal consequences
- Recognize ringing, Gibbs and group delay in a trace
- Read a frequency and impulse response
Why this matters
A filter is the first thing most pipelines do to the data and the last thing most papers describe properly. Every filter removes something you wanted along with the thing you did not, and every filter smears energy in time. A high-pass cutoff chosen by habit can invent an early ERP component and shrink a late one; a notch chosen by default can ring for hundreds of milliseconds around every transient. This lesson makes those side effects visible on real traces so that you can predict them before you apply anything.
Concepts
What a filter is
A linear filter is a weighted combination of the signal’s own samples. Its frequency response says how much each frequency is scaled (magnitude) and shifted (phase); its impulse response is the output for a single unit spike, and it tells you how the filter smears energy in time. The two are Fourier pairs: a sharp cut in frequency means a long, ringing impulse response, and a short impulse response means a gentle slope in frequency. There is no way around this trade-off; you only choose where to sit on it.
Low-pass, high-pass, band-pass, band-stop (notch). A low-pass keeps frequencies below a cutoff; a high-pass keeps those above; a band-pass keeps a range; a notch removes a narrow range. The passband is what you keep, the stopband what you remove, and the transition band the region between them where the response slides from one to the other. The cutoff frequency is conventionally the point where the magnitude response has fallen to half power (-3 dB) or, in MNE’s convention, the middle of the transition band at -6 dB (TODO(confirm) which convention each tool reports).
FIR versus IIR
An FIR (finite impulse response) filter’s output is a weighted sum of a finite window of past (and, in offline use, future) input samples. It is always stable, it can be designed with exactly linear phase — every frequency delayed by the same amount — and its impulse response is exactly as long as its coefficient list, so its temporal smearing is bounded and known. The cost is length: a narrow transition band needs many coefficients, and the filter delays the signal by half its length.
An IIR (infinite impulse response) filter feeds its own past outputs back in. A few coefficients give a steep response — a Butterworth filter of order 4 does what an FIR of hundreds of taps does — but the phase response is nonlinear (different frequencies are delayed by different amounts), the impulse response decays exponentially rather than ending, and a high-order IIR can be numerically unstable unless implemented as cascaded second-order sections. Butterworth is the usual choice in EEG because it has a maximally flat passband: no ripple. Its roll-off steepens with order, at about 6 dB per octave per order (TODO(confirm)).
MNE’s default is an FIR designed with the window method (firwin, Hamming window), applied zero-phase, with transition bandwidths chosen automatically from the cutoffs (TODO(confirm) the exact defaults: the transition bandwidth rule and the filter-length rule of thumb for a Hamming window). Those defaults are reasonable for most offline analyses; the point of this lesson is to know what they do so that you can depart from them on purpose.
Order and transition bandwidth
For an FIR, the transition bandwidth is set by the filter length: longer filter, narrower transition, longer ringing. For an IIR, it is set by the order: higher order, steeper slope, more phase distortion and longer decay. In both cases “sharper” is bought with “longer”. A high-pass at 0.1 Hz with a narrow transition band needs an impulse response that lasts many seconds; that is why a high-pass is the filter most likely to smear an ERP over its whole epoch.
Phase, zero-phase filtering and causality
A causal filter (one that uses only past samples) delays everything. For a linear-phase FIR the delay is constant — the group delay equals half the filter length — and is easy to correct by shifting the output. For an IIR the delay varies with frequency, which distorts waveform shape: a sharp transient comes out with its components arriving at different times.
Offline, both problems are removed by forward–backward (zero-phase) filtering: run the filter forward, reverse the result, run it again, reverse again. The phase shifts cancel exactly. The price is that the filter is now non-causal: the impulse response is symmetric, so energy from a transient is spread both forward and backward in time. A filter ringing before the event that caused it is not a bug; it is what zero-phase filtering means. Also note that the magnitude response is applied twice, so a -3 dB cutoff becomes -6 dB and the effective IIR order doubles.
For real-time processing (L7.3) there is no future, so filters must be causal and their delay is part of the latency budget. The causal mode of the sandbox shows the same filter both ways.
Impulse response, step response, ringing and Gibbs
Look at a filter’s impulse response and step response before you look at what it does to EEG. An impulse response with visible oscillation will ring around every sharp feature in the data: electrode pops, stimulus artifacts, boundary edges, blinks. A step response with overshoot will turn a DC step (a pop, a drift correction, a file join) into a damped oscillation. The Gibbs phenomenon is the same thing seen from the frequency side: a filter with a sharp edge in its frequency response overshoots near discontinuities in the time domain, and making the filter longer does not remove the overshoot, only narrows it.
The sandbox includes a real electrode pop for exactly this reason: apply a sharp high-pass or a narrow notch and watch the ringing appear on both sides of the pop.
Edge effects and padding
A filter needs samples before and after every point it computes. At the start and end of a file (and at every boundary between concatenated files, or every epoch edge if you filter epochs) those samples do not exist; the implementation pads with zeros, with a reflected copy of the data, or with a constant, and the choice changes what the first and last impulse-response-length of data looks like. The rule that follows: filter continuous data, before epoching, and keep the edges of any epoch well away from any transient you care about. The two pitfalls on boundaries and on epoched data below are consequences of this one fact.
Choosing by goal
- ERP. The components are slow and broad; the high-pass is the dangerous filter. A conservative high-pass — on the order of 0.1 Hz or lower — preserves slow components such as P3 and the CNV; higher cutoffs attenuate them and can create artifactual opposite-polarity deflections before and after (the topic of the exercise). A low-pass around 30 Hz (or higher for early sensory components) is usually harmless if applied after the measurement window is decided. (Tanner, 2015) and (Widmann, 2015) give the case and the numbers; (de Cheveigné, 2019) argues for filtering as little as possible and knowing why.
- Oscillations (Levels 4). A high-pass near 1 Hz is common because slow drift dominates a spectrum otherwise, but any narrow band-pass will make noise look rhythmic (L4.3, L4.6). Prefer estimating the spectrum on lightly filtered data and reasoning about bands from the spectrum.
- ICA fit (L2.4, L2.6). ICA converges better on data with the slow drift removed; a 1 Hz high-pass for the fit is common practice, with the unmixing matrix then applied to the 0.1 Hz-filtered data you actually analyse. This “two-pass” strategy is set out in L2.4.
The question is never “which filter is correct” but “what does this filter do to this signal, and can I live with it?” Before applying a filter to a dataset, apply it to one trace with a known transient and look at the result at two time scales. If you cannot say what changed, you are not ready to filter the whole dataset.
The data behind this lesson
- The sandbox’s four single-channel 10-s traces (clean eyes-closed occipital, electrode pop, blink, and an 8-channel segment) come from
ds-eegbci, recorded with no hardware filters, so what you see is what the amplifier delivered. The line-noise trace comes fromds-iowapdat 500 Hz, becauseds-eegbci’s 160 Hz sampling puts the 60 Hz harmonics above the Nyquist frequency (L1.6). - The notebook applies high-pass filters to
ds-erpcoreP3 data. ERP CORE is not in the author’s catalog; its license (expected CC BY 4.0) and per-subject downloadability areTODO(confirm)(§13 item 22). The notebook downloads from OSF and ships no ERP CORE-derived asset. If ERP CORE cannot be fetched in CI by the end of Phase 0, the demonstration runs onds-brain-invadersP300 data instead (§12).
Explore
Try this sequence: on the clean trace, high-pass at 0.1 Hz then 1 Hz then 5 Hz and watch the spectrum; switch to the electrode pop and repeat, watching the trace; toggle FIR/IIR at the same cutoff and compare the impulse responses; toggle causal/zero-phase on the pop and watch where the ringing goes.
Practice
Filters: FIR versus IIR, zero-phase versus causal, and four high-pass cutoffs on a P300 nb-1-5-filters
Downloads from ds-eegbci, ds-brain-invaders.
The notebook designs filters with mne.filter.create_filter and SciPy, plots their frequency, impulse and step responses, then applies four high-pass cutoffs to the P3 data and measures the mean amplitude in a fixed window. Its final cell prints the four numbers the exercise asks for.
Exercises
Report the P3 mean amplitude (µV, at Pz, in the a-priori window stated in the notebook) after a high-pass at each cutoff. The answer keys are filled in from the notebook’s final cell.
Exercise ex-1-5-p3-hp-0-01
NumericP3 mean amplitude with a 0.01 Hz high-pass
Exercise ex-1-5-p3-hp-0-1
NumericP3 mean amplitude with a 0.1 Hz high-pass
Exercise ex-1-5-p3-hp-0-5
NumericP3 mean amplitude with a 0.5 Hz high-pass
Exercise ex-1-5-p3-hp-1
NumericP3 mean amplitude with a 1 Hz high-pass
Exercise ex-1-5-explain-trend
Free responseExplain the trend across the four cutoffs. What happens to the P3 amplitude, what appears around it, and why?
Pitfalls
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…
Filtering across discontinuities
- Symptom
- Ringing at file joins, breaks, or buffer edges.
- Cause
At a discontinuity the signal jumps: from the last sample of one run to the first sample of the next, from a value to zero padding at the file edge, or from the DC offset of one recording to that of another. To a filter a jump is a step, and a step response with overshoot or a long settling time produces ringing (for sharp FIR and high-order IIR filters) or a slow exponential swing (for a high-pa…
- Detect
- Keep a list of boundary events (MNE annotations of type BADboundary or equivalent) and inspect the filtered data around each one. - Look at the start and end of every file after filtering; compare with the unfiltered data. - Compute the impulse-response length of your filter and mark that much data on each side of every boundary as suspect. - In real-time pipelines, filter a test signal with a…
- Fix
- Filter each continuous run separately, then concatenate; never filter across a join. - Where a join is unavoidable, annotate the boundary and exclude epochs that overlap the boundary plus the filter’s impulse-response length. - Pad sensibly at file edges (MNE reflects the data by default; state the padding method) and discard the padded region’s worth of data from analysis. - Real-time: carry f…
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-…
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 pluginpop_firwsfirfilt plugin
FieldTrip
ft_preprocessing(lpfilter/hpfilter)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
- Widmann, Schröger & Maess (2015). Digital filter design for electrophysiological data. unverified
- Tanner, Morgan-Short & Luck (2015). Inappropriate high-pass filters. unverified
- de Cheveigné & Nelken (2019). Filters: when, why, and how (not) to use them. unverified