Author : Alexandre Gramfort
In this session we're going to compute source estimates on the somatosensory dataset used on monday for preprocessing. We will use the boundary element method (BEM) for forward modeling.
The lines below assume that you have already:
mne_watershed_bem
mne_analyze
which generated the -trans.fif file (somstim_raw-trans.fif
)mne_setup_source_space --oct 6
. This generated the file called daniel-oct-6-src.fif
somstim-meg-oct-6-fwd.fif
using mne_setup_forward_model --homog --surf --ico 4
and mne_do_forward_solution --mindist 5 --spacing oct-6 --meas somstim_raw.fif --mri somstim_raw-trans.fif --bem daniel-5120 --megonly --overwrite --fwd somstim-meg-oct-6-fwd.fif
A full script looks like this:
#!/usr/bin/env bash
export SUBJECTS_DIR=$PWD
export SUBJECT=daniel
# Generate BEM models
mne_watershed_bem --overwrite
cd ${SUBJECTS_DIR}/${SUBJECT}/bem
ln -s watershed/${SUBJECT}_inner_skull_surface${SUBJECT}-inner_skull.surf
ln -s watershed/${SUBJECT}_outer_skin_surface${SUBJECT}-outer_skin.surf
ln -s watershed/${SUBJECT}_outer_skull_surface${SUBJECT}-outer_skull.surf
cd -
# Source space
mne_setup_source_space --ico -6 --overwrite
# Prepare for forward computation
mne_setup_forward_model --homog --surf --ico 4
# Generate morph maps for morphing between daniel and fsaverage
mne_make_morph_maps --from ${SUBJECT} --to fsaverage
# compute forward models for both experimental data
cd ../MEG
mne_do_forward_solution --mindist 5 --spacing oct-6 \
--meas somstim_raw.fif \
--mri somstim_raw-trans.fif \
--bem daniel-5120 --megonly \
--overwrite --fwd somstim-meg-oct-6-fwd.fif
Now you can try to run these commands on your machine or use the ones generated for you and available in the MEG folder. Once you're done you can start with what is next.
# add plot inline in the page (not necessary in Spyder)
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import mne
mne.set_log_level('WARNING')
data_path = '/Users/alex/Sync/karolinska_teaching/'
raw_fname = data_path + '/MEG/somstim_raw.fif'
raw = mne.fiff.Raw(raw_fname)
print raw
Apply fix...
def fix_info(raw):
raw.info['chs'][raw.ch_names.index('BIO001')]['kind'] = mne.fiff.constants.FIFF.FIFFV_EOG_CH
raw.info['chs'][raw.ch_names.index('BIO002')]['kind'] = mne.fiff.constants.FIFF.FIFFV_EOG_CH
raw.info['chs'][raw.ch_names.index('BIO003')]['kind'] = mne.fiff.constants.FIFF.FIFFV_ECG_CH
raw.info['chs'][raw.ch_names.index('BIO004')]['kind'] = mne.fiff.constants.FIFF.FIFFV_ECG_CH
fix_info(raw)
Looking at meta data, a.k.a. measurement info, such sampling frequency, channels etc.
print raw.info['sfreq']
First look for events / triggers
events = mne.find_events(raw, stim_channel='STI101', verbose=True)
event_id = dict(som=1) # event trigger and conditions
tmin = -0.1 # start of each epoch (200ms before the trigger)
tmax = 0.3 # end of each epoch (500ms after the trigger)
picks = mne.fiff.pick_types(raw.info, meg=True, eeg=False, eog=True,
exclude='bads')
baseline = (None, 0) # means from the first instant to t = 0
reject = dict(grad=4000e-13, mag=4e-12, eog=150e-6)
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, proj=True,
picks=picks, baseline=baseline, reject=reject,
preload=True)
print epochs
evoked = epochs.average()
evoked.save(data_path + '/MEG/somstim-ave.fif')
evoked.plot()
# Ugly hack due to acquisition problem when specifying the channel types
layout = mne.layouts.read_layout('Vectorview-mag.lout')
layout.names = mne.utils._clean_names(layout.names, remove_whitespace=True)
fig = evoked.plot_topomap(times=np.linspace(0.05, 0.12, 5), ch_type='mag', layout=layout)
One can observe a clean (slightly rotating) dipolar pattern first and then bilateral dipoles. The objective now is to locate these early and later components.
Inverse modeling requires the estimation of a noise covariance matrix. This is used to spatially whiten the data and typically allows to combine different types of sensors (magnetometers, gradiometers, EEG) for source localization.
noise_cov = mne.compute_covariance(epochs, tmax=-0.01) # stay away from the stim artifact
print noise_cov.data.shape
figs = mne.viz.plot_cov(noise_cov, raw.info)
# regularize noise covariance
noise_cov = mne.cov.regularize(noise_cov, epochs.info,
mag=0.1, grad=0.1, eeg=0.1, proj=True)
Recompute the noise covariance without setting proj=True when creating Epochs. What do you observe? Why?
Import the required functions:
from mne.forward import read_forward_solution
from mne.minimum_norm import make_inverse_operator, apply_inverse, \
write_inverse_operator
fname_fwd = data_path + '/MEG/somstim-meg-oct-6-fwd.fif'
fwd = mne.read_forward_solution(fname_fwd, surf_ori=True)
# compute the inverse operator
info = evoked.info
inverse_operator = make_inverse_operator(info, fwd, noise_cov,
loose=0.2, depth=0.8)
# save the inverse operator to disk
fname_inv = data_path + '/MEG/somsen-meg-oct-6-inv.fif'
write_inverse_operator(fname_inv, inverse_operator)
At this point one can you mne_analyze
for interactive analysis: http://martinos.org/mne/stable/manual/analyze.html
The acronym of sources estimates in the MNE software is stc
which stands for source time courses. The stc files can be visualized with mne_analyze
by loading it as overlays.
method = "dSPM"
snr = 3.
lambda2 = 1. / snr ** 2
stc = apply_inverse(evoked, inverse_operator, lambda2,
method=method, pick_ori=None)
print stc
stc.data.shape # we have 8196 cortical locations and 401 time points
print stc.times.shape, np.min(stc.times), np.max(stc.times)
you're done. The lines below show you have to visualize in Python and script figure generation. You'll find exercises at the bottom to go further.
You can browse the examples on inverse modeling at:
http://martinos.org/mne/stable/auto_examples/index.html#inverse-problem-and-source-analysis
# %matplotlib qt4
subjects_dir = data_path + '/subjects'
brain = stc.plot(surface='inflated', hemi='rh', subjects_dir=subjects_dir)
brain.set_data_time_index(144) # 221 for S2
brain.scale_data_colormap(fmin=4, fmid=8, fmax=12, transparent=True)
brain.show_view('lateral')
brain.save_image('dspm.jpg')
from IPython.display import Image
Image(filename='dspm.jpg', width=600)
"Morphing" data to an average brain for group studies
stc_fsaverage = stc.morph(subject_to='fsaverage', subjects_dir=subjects_dir)
Visualize on the average brain
brain_fsaverage = stc_fsaverage.plot(surface='inflated', hemi='rh',
subjects_dir=subjects_dir)
brain_fsaverage.set_data_time_index(171)
brain_fsaverage.scale_data_colormap(fmin=5, fmid=10, fmax=15, transparent=True)
brain_fsaverage.show_view('lateral')
brain_fsaverage.save_image('dspm_fsaverage.jpg')
from IPython.display import Image
Image(filename='dspm_fsaverage.jpg', width=600)
fname_label = data_path + '/subjects/daniel/label/lh.BA1.label'
label = mne.read_label(fname_label)
Compute inverse solution during the first 15s:
from mne.minimum_norm import apply_inverse_raw, apply_inverse_epochs
start, stop = raw.time_as_index([0, 15]) # read the first 15s of data
stc = apply_inverse_raw(raw, inverse_operator, lambda2, method, label,
start, stop)
Plot the dSPM time courses in the label
plt.plot(stc.times, stc.data.T)
plt.xlabel('time (s)')
plt.ylabel('dSPM value')
And on epochs:
from mne.minimum_norm import apply_inverse_epochs
# run it on 10 epochs only to avoid allocating too much memory
stcs = apply_inverse_epochs(epochs[:10], inverse_operator, lambda2, method, label)
print "Number of stcs : %d" % len(stcs)
print stcs[:3]