Filter parameters for mne.io.RawArray.plot()

  • MNE-Python version: 0.22.0
  • Ubuntu 18.04.3 LTS:

I would like to check what is the filter parameters of the mne.io.RawArray.plot() method? When I try to replicate the filter used in the plot function by looking at the log, I could not reconstruct the filtered signal. As shown in the code below code, the x_2.filter is trying to reconstruct the filter of the plot function.

full_eeg_2 = copy.deepcopy(full_eeg)

x = mne.io.RawArray(full_eeg, info=data_info, verbose=True)
z = x.plot(scalings='auto', lowpass = 40, highpass=0.5, filtorder = 1, 
           remove_dc=False,verbose=True)
z.show
print("#" * 80)
x_2 = mne.io.RawArray(full_eeg_2, info=data_info, verbose=True)
x_2 = x_2.filter(l_freq=0.5, h_freq=40, method="iir",
                     iir_params=dict(order=1, ftype='butter', output="ba"))
z = x_2.plot(scalings='auto')
z.show

The following are the log for the two filtering function which are identical except for the line

“Filtering raw data in 1 contiguous segment”

Creating RawArray with float64 data, n_channels=31, n_times=889240
    Range : 0 ... 889239 =      0.000 ...  3556.956 secs
Ready.
Setting up band-pass filter from 0.5 - 40 Hz

IIR filter parameters
---------------------
Butterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:
- Filter order 4 (effective, after forward-backward)
- Cutoffs at 0.50, 40.00 Hz: -6.02, -6.02 dB


################################################################################


Creating RawArray with float64 data, n_channels=31, n_times=889240
    Range : 0 ... 889239 =      0.000 ...  3556.956 secs
Ready.
Filtering raw data in 1 contiguous segment
Setting up band-pass filter from 0.5 - 40 Hz

IIR filter parameters
---------------------
Butterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:
- Filter order 4 (effective, after forward-backward)
- Cutoffs at 0.50, 40.00 Hz: -6.02, -6.02 dB

Hello, the filters use the exact same settings, it’s really only the log message that’s different. It is emitted by Raw.filter() – which Raw.plot() doesn’t use (not sure why that is). We probably should ensure the log messages look the same.

@drammock might know more.

Hi Richard,

But the filtered results are very different.

Can you show us the difference? Can you maybe edit your example code so that it is fully reproducible (e.g. with toy data)?

The following works for me (I tried to extract the exact parameters that Raw.plot() would use):

import os
import mne

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_raw.fif')

l_freq = 0.5
h_freq = 40
order = 2
method = 'iir'
iir_params = dict(order=order, output='sos', ftype='butter')
n_channels = 2

raw = mne.io.read_raw_fif(sample_data_raw_file, preload=True)
raw_filtered = raw.copy().filter(l_freq=l_freq, h_freq=h_freq, method=method,
                                 iir_params=iir_params)

raw.plot(highpass=l_freq, lowpass=h_freq, filtorder=order,
         n_channels=n_channels, title='Raw')
raw_filtered.plot(n_channels=n_channels, title='Raw filtered')

The first screenshot is by the plot function,
the below is filter + plot

I tried with a dummy data, you can try to replicate by assigning full_eeg to:
np.random.seed(11)
full_eeg = np.random.rand(31, 5000)

which will produce different results

Without a fully reproducible example, I’m afraid we cannot help

The scalings are different in the two plots - make sure you set it to identical values. Also, the data scale is off by a factor of 1e6. EEG data are expected to be in V (and not µV) in MNE.

Thanks Clemens, after rescaling the plot though the filtered data are not identical, but they are mostly the same with some difference in the artefacts.

They should be exactly identical though. When you set a fixed scaling in both plots, can you highlight one of the differences you noticed?

the following figures is generated with data
np.random.seed(11)
full_eeg = np.random.rand(31, 5000)

and if you plot with the two methods you will see a difference in the C3 channel at time 0, the above figure is >0 while the bottom figure is <0, the channel list is given: There are also other differences, which you can try to plot with the dummy random data, I think the filter setting for both methods are not identical which cause such differences.

[“Fp1”, “Fp2”,“F7”,“F3”,“Fz”,“F4”,“F8”,“FT7”,“FC3”,“FCz”,“FC4”,“FT8”,“T7”,“C3”,“Cz”,“C4”,“T8”, “CP3”,
“CPz”,“CP4”,“TP8”,“P7”,“P3”, “Pz”,“P4”,“P8”,“O1”,“Oz”,“O2”,“PO1”, “PO2”]

Indeed these two methods yield different results. I used the following code:

import numpy as np
import mne


np.random.seed(11)
data = np.random.rand(31, 5000) * 5e-5
info = mne.create_info(31, 256, "eeg")
raw = mne.io.RawArray(data, info)

l_freq = 0.5
h_freq = 40
order = 2
method = "iir"
iir_params = dict(order=order, output="sos", ftype="butter")

raw.plot(n_channels=8, lowpass=h_freq, highpass=l_freq, filtorder=order,
         remove_dc=False, title="Filtered in plot")

raw_filtered = raw.copy().filter(l_freq, h_freq, method=method,
                                 iir_params=iir_params)
raw_filtered.plot(n_channels=8, remove_dc=False, title="Filtered")

The data filtered inside plot is different at the end of each visible window. I think this could be due to how the filter is applied - it looks like it’s applied to the visible data only, whereas pre-filtering and then plotting filters the entire signal.

2 Likes

yes raw.plot does not apply filtering on the full data but but on the page you’re viewing and maybe a bit before
and after.

Alex

I have a question regarding the scaling of the plot. If I want to display my data with x microvolt/mm. How should I set my scale to achieve this?

You can use the scalings argument in raw.plot(). However, it won’t be easy to set a specific µV/mm scaling, because that would depend on your screen resolution and size.

1 Like