interpolate_bads did not work

Hello all! I have a problem interpolating bad channels of MEG data.

Here is my MEG data description:

I need to interpolate the MEG 079 channel based on other channels.

The original data looks like this:

After I called the meg_data.copy().interpolate_bads(reset_bads=False), it seemed that the MEG 079 channel was not changed.

I’m wondering what’s wrong during the process. I’d appreciate it if anyone could help! Thanks a lot!

That’s weird. Does reset_bads=True change anything?

No, it did not change the result. It just removes the bad channel information.

I don’t see the problem either. Can you try if it works when you remove the .copy() call?

Sadly it did not work

I’m kind of wondering if there is any latent requirement for the data?

You need channel locations, but these are available in your data. Maybe they are somehow incorrect? Can you plot the montage maybe? Otherwise, I have no idea what’s going on, but I have only ever used interpolation for EEG channels, so maybe someone else with MEG experience can chime in?

Yes I do have channel locations in the data. And the sensors look like this:

(Sorry about the figure’s size which makes channel names hard to recognize. I’m also working on adjusting that.)

Anyway, thanks so much for your time and help in this issue!

Hi there,

I really don’t know what is happening, but could it be the case that your syntax necessarily excludes channel 79?

I just have been looking at this example where they specifically mention the exclude=[] syntax, when calling pick_types, as a trick to make the interpolation work. At least it seems like it’s worth a shot.

The interpolation still failed. Maybe by calling .copy() without .pick_types, the syntax has already copied all the information without exclusion?


Anyway, thanks so much for your time and suggestion!

If this channels’ activity is constantly zero (?) and is included in the interpolation maybe this is the problem then? I mean the fact that you compute a dot product with an all-zeros vector; it will be an all-zeros vector.

Not taking this channel into account, or hacking this channels’ values and replacing them with ones maybe would solve your problem then.

I am not sure whether this is what the parameter exclude of interplolate_bads is trying to solve.

(But there must be a better way to do it than hacking; someone with a better grasp of the source code could answer this I guess)

You reminded me to check the initial values of this channel!

And interestingly, the initial value of this channel is much smaller than other channels.


It is not zero, but other channels have much higher values, like:

And interestingly, it seems that the interpolation has been done. However, the values of this channel are much smaller (near zero) after the interpolation. Is it due to the dot calculation?

I may provide more information for this problem (I’m afraid it’s because I’m doing something wrong before interpolation).

My data is from OSF | MASC-MEG. Currently the sample data for this problem is sub-01_ses-1_task-1. And following is all my codes:

import mne
import numpy as np
import pandas as pd
from mne.preprocessing import (ICA, corrmap, create_ecg_epochs, create_eog_epochs)

data_folder = '/bigvault/Projects/asymmetry_lang/MEG/sub-01/ses-1/meg'
data_raw_file = data_folder+'/sub-01_ses-1_task-1_meg.con'
marker_file_name = data_folder+'/sub-01_ses-1_task-1_markers.mrk'
marker_data = mne.io.kit.read_mrk(marker_file_name)
elp_file_name = data_folder+'/sub-01_ses-1_acq-ELP_headshape.pos'
hsp_file_name = data_folder+'/sub-01_ses-1_acq-HSP_headshape.pos'

def readPos(filename, start_line, point_num):
    df = pd.read_table(filename, header=None)
    line_num = len(df.values)-3
    save_data_row = []
    item = ''
    indicate_num = 0
    flag = False
    for line_index, m in enumerate(df.values[start_line:]):
        save_data_line = []
        for idx, n in enumerate(df.values[start_line+line_index][0].replace(' ','')):
            if flag:
                indicate_num += 1
            item += n
            if indicate_num == point_num:
                save_data_line.append(float(item))
                item = ''
                indicate_num = 0
                flag = False
            if n == '.':
                flag = True
        save_data_row.append(save_data_line)
    return np.array(save_data_row)

elp_data = readPos(elp_file_name, 3, 4)
hsp_data = readPos(hsp_file_name, 4, 2)

raw = mne.io.read_raw_kit(data_raw_file, mrk=marker_data/1000, elp=elp_data/1000, hsp=hsp_data/1000)
raw.info['bads']=['MEG 079']
raw.load_data()

meg_data = raw.copy().filter(l_freq=1, h_freq=40)
ref_channels = ['MEG 209','MEG 210','MEG 211','MEG 212','MEG 213','MEG 214','MEG 215','MEG 216',
               'MEG 217','MEG 218','MEG 219','MEG 220','MEG 221','MEG 222','MEG 223','MEG 224']
meg_data_interp = meg_data.copy()
meg_data_interp = meg_data_interp.interpolate_bads(reset_bads=False, exclude=ref_channels)
picks = mne.pick_channels(meg_data_interp.ch_names, include=['MEG 078','MEG 079','MEG 080'])
meg_data_interp.plot(duration=12, order=picks, n_channels=len(picks))

Ah, I see. It’s this difference in orders of magnitude that this channel introduces to the computations; your calculations must internally be something like this Xe-12 * Ye-14 = X*Ye-(12+14), X being the sum of all “good” channels.

Can’t say for sure, but I would:

  1. Try to see the raw activity (before filtering) for diagnostic purposes.
  2. Try re-referencing (CAR ???) if that’s a valid pre-processing step for what you are trying to do.
  3. Try adding MEG 079 as a channel to be excluded during the interpolation.

Thanks a lot!!!

I tried your suggestions and they helped a lot. The problem was finally solved by excluding the reference channels and also adding origin=(0.,0.,0.01) (the default is origin=(0.,0.,0.04) when calling .interpolate_bads(). Happily the interpolation is now working well!

Thanks a lot for all your time and help!

2 Likes

Hello!

I think I have a similar or even the same issue. The epochs before (first image) and after (second image) interpolation are exactly the same.


If I change the origin for example to origin = (0,0,0.01) as the OP or to origin = (0,0,0) (see image) some kind of interpolation is applied to the data.

However, no change can be detected with the default settings for the origin (i.e., origin = "auto") even though my data includes digitalisation points, hence this should work. Setting the origin to (0,0,0.1) or (0,0,0) seems a bit arbitrary, though. Could it be possible that the interpolate_bads() function accidentally determines the wrong origin (i.e., the head center in head coordinates rather than the head center in device coordinates)?

Thanks a lot in advance!

The same problem also occurs when trying to interpolate bad channels based on raw data. The first screenshot shows the continuous data with bad channels marked and the second screenshot after interpolation.

I just compared the data of both the raw and the interpolated file. The data actually seems to differ a bit (the magnitude of the difference is just very small)!