Compute SESAME inverse solution on high-density EEG data

In the present example we shall show how to perform a source modeling analysis using SESAME as a standalone software.

The data belongs to a recently published EEG dataset of high-density (256 channels) scalp recordings combined with a ground truth single dipolar source systematically provided through a brief current injection between two adjacent intracranial electrodes whose position is known with millimetric precision [1] [2] .

References

# Author: Gianvittorio Luria <luria@dima.unige.it>
#
# License: BSD (3-clause)

# sphinx_gallery_thumbnail_number = 2

import numpy as np
import scipy.io as sio
import scipy.spatial.distance as ssd
import matplotlib.pyplot as plt
from sesameeg import Sesame

Import the MATLAB data structure and extract the single quantities.

data_mat = sio.loadmat('data/sub-01_run-07_data.mat')

source_space = data_mat['src_coo']
good_chs = data_mat['good_chs'][0] - 1
lead_field = data_mat['LF'][good_chs]
data = data_mat['evoked']
data_times = data_mat['times'][0]
true_coords = np.array([0.034775, -0.00336, 0.039735])
true_sources = [np.argmin(ssd.cdist(source_space, true_coords.reshape(1, -1))[:, 0])]

Define the parameters.

sample_min, sample_max = 12, 24
subsample = None

# To accelerate the run time of this example, we use a small number of
# particles. We recall that the parameter ``n_parts`` represents, roughly speaking,
# the number of candidate solutions that are tested in the Monte Carlo procedure;
# larger values yield in principle more accurate reconstructions but also entail a
# higher computational cost. Setting the value to about a hundred seems to represent
# a good trade–off.
n_parts = 10
# If None, noise_std and dip_mom_std will be estimated by SESAME.
noise_std = None
dip_mom_std = None

Visualize the selected data.

plt.figure(figsize=(25,8))
plt.plot(data_times, data.T, label='EEG data')
plt.axvspan(data_times[sample_min], data_times[sample_max], alpha=0.2, label='Analyzed data')
plt.xlabel('Time')
plt.title(f'EEG Data ({data.shape[0]} channels)')
plt.show()
EEG Data (234 channels)

Apply SESAME.

_sesame = Sesame(source_space, lead_field, data, n_parts=n_parts, noise_std=noise_std,
                 s_max=sample_max, s_min=sample_min, dip_mom_std=dip_mom_std,
                 hyper_q=True, subsample=subsample, data_times=data_times)

_sesame.apply_sesame()

# Compute goodness of fit
gof = _sesame.goodness_of_fit()
print('    Goodness of fit with the recorded data: {0}%'.format(round(gof, 4) * 100))

# Compute source dispersion
sd = _sesame.source_dispersion()
print('    Source Dispersion: {0} mm'.format(round(sd, 2)))

# Compute distance to true source
distance = ssd.cdist(source_space[_sesame.est_locs[-1][0]].reshape(1,-1), true_coords.reshape(1,-1))[0][0]
print('    Distance to true source: {0} mm'.format(round(distance*1000, 2)))
Computing neighbours matrix [done]
Computing neighbours probabilities...[done]
Estimating dipole moment std...[done]
 Estimated dipole moment std: 2.1657e-06
Sampling hyperprior for dipole moment std.
Estimating noise std...[done]
 Estimated noise std: 2.8010e-04
Computing inverse solution. This will take a while...
/home/pasca/Tools/python/packages/sesameeg/sesameeg/particles.py:174: RuntimeWarning: invalid value encountered in log
  self.loglikelihood_unit = - (n_ist * noise_std**2) * np.log(det_sigma)
Estimated dipole strength variance: 2.20030636474554e-06
    Estimated number of sources: 1
    Estimated source locations:
        * source 1: [ 0.03371428 -0.00413685  0.03588749]
[done in 64 iterations]
    Goodness of fit with the recorded data: 78.89%
    Source Dispersion: 3.18 mm
    Distance to true source: 4.07 mm

Visualize the posterior map of the dipoles’ location p(r| \textbf{y}, 2) and the estimated sources on the inflated brain.

plot 07 compute sesame esi

Visualize the amplitude of the estimated sources as function of time.

plot 07 compute sesame esi

Save results.

# You can save SESAME result in an HDF5 file with:
# _sesame.save_h5(save_fname, sbj=subject, data_path=fname_evoked, fwd_path=fname_fwd)

# You can save SESAME result in a Pickle file with:
# _sesame.save_pkl(save_fname, sbj=subject, data_path=fname_evoked, fwd_path=fname_fwd)

Total running time of the script: (0 minutes 4.737 seconds)

Gallery generated by Sphinx-Gallery