Current dipole fitting using independent components

Hello everyone,

MNE version: 1.3.0
System: Mac, Ventura 13.1, Apple M1

I am using MNE python to do some connectivity analysis. Meanwhile, I am interested in doing dipole fitting on a selected number of independent components. I have been working with FieldTrip, and I have been using this method a lot. Since I am new in MNE, I am assuming that there should be a way to run dipole fitting analysis on independent components.
So, it would be great if you could give me some hint on this question.

Thank you in advance,
Amir

1 Like

That is not really something we support. You could try and wrap the ICA component in an EvokedArray object so you can do mne.fit_dipole on it, but please check the results against fieldtrip before trusting them.

"""
Experimental code. Use at your own risk.
"""
import mne

# Grab some example data
root = mne.datasets.sample.data_path()
subjects_dir = root / 'subjects'
meg_dir = root / 'MEG' / 'sample'
raw = mne.io.read_raw_fif(meg_dir / 'sample_audvis_filt-0-40_raw.fif', preload=True)
raw.drop_channels(raw.info['bads'])

# Compute covariance
events = mne.find_events(raw)
epochs = mne.Epochs(raw, events, event_id={'aud/l': 1, 'aud/r': 2, 'vis/l': 3, 'vis/r': 4},
                    picks='meg', preload=True)
cov = mne.read_cov(meg_dir / 'sample_audvis-cov.fif')

# Hipass before fitting ICA
raw_high = raw.filter(1.0, None)

# Tuning ICA for speed over accuracy for this example
ica = mne.preprocessing.ICA(0.9, random_state=0).fit(raw_high, decim=5, picks='meg')

# Let's look through the components to see if there's one with a nice dipole pattern...
# Component 4 looks good! It seems to capture the auditory evoked potential.
ica.plot_properties(epochs['aud/l'], picks=4)

# Place the component in an Evoked object
component = mne.EvokedArray(ica.get_components()[:, [4]], info=epochs.info)

# Load a BEM model and fit a dipole
bem = mne.read_bem_solution(subjects_dir / 'sample' / 'bem' / 'sample-5120-5120-5120-bem-sol.fif')
trans = mne.read_trans(meg_dir / 'sample_audvis_raw-trans.fif')

# Fit the dipole using only the sensors on the left side of the head
picks_lh = [ch['ch_name'] for ch in epochs.info['chs'] if ch['loc'][0] < 0]
component_lh = component.pick_channels(picks_lh)
dip, _ = mne.fit_dipole(component_lh, cov, bem, trans)

# Plot dipole location
dip.plot_locations(trans, 'sample', subjects_dir)
4 Likes

The above code fits a dipole to the ICA weights. I don’t know if that makes any sense. But hopefully with the above to get you started you can make it do the same thing you have been doing in fieldtrip.

4 Likes

Hello Marijn,

Thank you so much for sharing the code.
Indeed, I tested the code and it nicely does the dipole fitting analysis on the independent component space.

Best,
Amirhossein

5 Likes

Hi @Amir @wmvanvliet ,

I am working on this, too and was very happy to see this discussion. Thanks.

Detail question coming next:

For the cov in fit_dipole – what makes most sense here?

  • in the example by Marijn, you use the covariance over the entire signal (I assume that’s what’s in 'sample_audvis-cov.fif')
  • yet, we only have a single “scalpmap” (that is, basically one “timepoint”), which we want to fit (a given IC)
  • would it instead also make sense, to simply use an identity matrix as the covariance?

or how would you create a cov for this task?

  • based on the raw data? Or whatever is passed to ica.fit?

For dipole fitting, you need the noise covariance matrix.

sample_audvis-cov.fif contains the covariance computed only during the baseline period. Yes you can use an identity matrix, as long as you don’t mix sensor types. For example, Xfit uses by default a diagonal matrix filled with estimates of the noise variance of each sensor type (grads, mags, eeg). Theoretically it should be better to use a proper noise covariance matrix though (but be careful of rank deficiency woes!).

1 Like

I see, thanks for the explanation!

In the present case, how would you compute such a noise covariance?

(the present case being: Fitting dipoles on “single time point evoked scalp maps” aka independent component scalpmaps from ICA)

Well, I’m not sure because I’ve never dug deep into fitting dipoles to ICA scalp maps, but my first guess would be that you just need a regular noise covariance matrix, computed on some suitable part of the signal. We just need to know the overall scaling of the signal at each sensor and the amount of cross-talk between them.

1 Like

Thanks! I will try out a few options, like

  • a noise covariance computed on a portion of the raw signal
  • a noise covariance computed on a portion of the backprojected signal, (backprojected using only the IC, the corresponding scalpmap of which I want to dipole-fit)

I am a bit clueless about the units, as the IC scalpmap has “arbitrary units” (reaching up to god knows what, like 60k), whereas the noise covariances would be in micro volts :thinking: do you think this matters much?