Line Noise(EEG)

Hi everyone,
I need some help with an issue in my EEG data. My power spectrum shows distinct sharp peaks at **25 Hz, 50 Hz, 75 Hz, 100 Hz, and so on** — these harmonics are far stronger than the actual brain signals around 12.5 Hz.
I’ve already tried low-pass filtering, notch filtering, and Zapline Plus, but none of them effectively removed this line noise (some didn’t work at all).

The figure below shows the power spectrum after **1–80 Hz bandpass filtering** and **49–51 Hz notch filtering**.

I have two questions:

  1. Does anyone know effective ways to fix this?
  2. If not, given that line noise power is much higher than the EEG signal in the raw data, is it still worth processing and analyzing this dataset?

Any advice would be greatly appreciated!

Have you tried re-referencing to the average? In addition, is the frequency content above 20Hz relevant in your analysis?

Thank you so much for your reply. After applying re-referencing prior to filtering, I observed a significant reduction in power at 25 Hz, 75 Hz and related harmonic frequencies. Subsequent 1–40 Hz bandpass filtering further yielded a remarkable improvement. While I am still puzzled by the underlying mechanism, this workflow has proven practical and highly effective. Your suggestions have been incredibly helpful.


I am nonetheless curious about why re-referencing caused such drastic changes. I conventionally perform re-referencing after ICA, mainly to account for bad channels and avoid rank deficiency issues during ICA computation.

Thanks again for your kind assistance.

Line noise is often present on many (sometimes all) channels, in which case average re-referencing can substantially reduce it.

I usually apply average referencing before ICA, as in theory the reference should not influence the decomposition at all (see Re-referencing - EEGLAB Wiki). My typical pipeline looks like this:

  • Mark bad channels
  • Re-reference to the average (bad channels are automatically excluded)
  • Interpolate bad channels
  • Perform ICA (note you need to high-pass filter the data for this step)

Regarding rank deficiency, running ICA should automatically infer the rank. To manually inspect the computed rank, you can check the output of:

mne.compute_rank(raw)

This should be equal to raw.info["nchan"] - n_bads - 1 (the minus one accounts for the average reference), and if this is not the case I usually set n_components manually:

ica = ICA(n_components=raw.info["nchan"] - n_bads - 1)

Thanks a lot for your detailed reply. Your additional explanations have resolved an issue that has troubled me for a long time.

As someone new to EEG preprocessing, I’ve studied plenty of tutorials and references, yet I struggled to get satisfying results in practical application. This setback slowed down my project progress and made me less confident with data processing.

Recently, I had to move forward with my work due to time pressure. With little expectation, I posted my first help request on the MNE Forum. I truly appreciate your generous guidance—it means a great deal to me.

To add to previous comments, and for the benefit of future reference:

The fact that “line” components are multiples of 25Hz is unexpected. It suggests two things to check. One is that the sampling rate might off by a factor 2. The other is a combination of (a) interference with high frequency power (e.g. high line harmonics), (b) insufficient antialiasing. The latter is a plausible explanation for inexplicable lines that one sometimes sees for data from certain systems. The fact that there is no dip in this spectrum circa 50Hz despite notch filtering is bizarre.

The sampling rate mismatch might explain why ZapLine didn’t work. Also, ZapLine requires finding the right number of components to remove (by trial and error) and, sometimes, for data with many channels, reducing its parameter p.nkeep to avoid overfitting. It also may not work well if the sampling rate is too low re line frequency (i.e. it is best applied before any downsampling).

Thank you for your reply! Regarding the sampling rate mismatch, the signals at 50Hz and 100Hz in the original spectrum are significantly stronger than those at 25Hz and 75Hz. This leads me to suspect environmental interference, possibly from a frequency divider. As for the notch filter issue, my senior colleague and I were equally puzzled; we double-checked the bandwidth at 50Hz, and it seemed reasonable.

I had tried various methods without success until I followed the suggestion to perform re-referencing first. To my surprise, that resolved the issue.

To be honest, I am still quite mystified by the underlying cause, but I truly appreciate your insights and the tips on using ZapLine. Thank you for your help!