{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n# Compute spatial resolution metrics to compare MEG with EEG+MEG\n\nCompute peak localisation error and spatial deviation for the point-spread\nfunctions of dSPM and MNE. Plot their distributions and difference of\ndistributions. This example mimics some results from :footcite:`HaukEtAl2019`,\nnamely Figure 3 (peak localisation error for PSFs, L2-MNE vs dSPM) and Figure 4\n(spatial deviation for PSFs, L2-MNE vs dSPM). It shows that combining MEG with\nEEG reduces the point-spread function and increases the spatial resolution of\nsource imaging, especially for deeper sources.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Author: Olaf Hauk \n#\n# License: BSD-3-Clause\n# Copyright the MNE-Python contributors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import mne\nfrom mne.datasets import sample\nfrom mne.minimum_norm.resolution_matrix import make_inverse_resolution_matrix\nfrom mne.minimum_norm.spatial_resolution import resolution_metrics\n\nprint(__doc__)\n\ndata_path = sample.data_path()\nsubjects_dir = data_path / \"subjects/\"\nmeg_path = data_path / \"MEG\" / \"sample\"\nfname_fwd_emeg = meg_path / \"sample_audvis-meg-eeg-oct-6-fwd.fif\"\nfname_cov = meg_path / \"sample_audvis-cov.fif\"\nfname_evo = meg_path / \"sample_audvis-ave.fif\"\n\n# read forward solution with EEG and MEG\nforward_emeg = mne.read_forward_solution(fname_fwd_emeg)\n# forward operator with fixed source orientations\nforward_emeg = mne.convert_forward_solution(\n forward_emeg, surf_ori=True, force_fixed=True\n)\n\n# create a forward solution with MEG only\nforward_meg = mne.pick_types_forward(forward_emeg, meg=True, eeg=False)\n\n# noise covariance matrix\nnoise_cov = mne.read_cov(fname_cov)\n\n# evoked data for info\nevoked = mne.read_evokeds(fname_evo, 0)\n\n# make inverse operator from forward solution for MEG and EEGMEG\ninv_emeg = mne.minimum_norm.make_inverse_operator(\n info=evoked.info, forward=forward_emeg, noise_cov=noise_cov, loose=0.0, depth=None\n)\n\ninv_meg = mne.minimum_norm.make_inverse_operator(\n info=evoked.info, forward=forward_meg, noise_cov=noise_cov, loose=0.0, depth=None\n)\n\n# regularisation parameter\nsnr = 3.0\nlambda2 = 1.0 / snr**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## EEGMEG\nCompute resolution matrices, localization error, and spatial deviations\nfor MNE:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "rm_emeg = make_inverse_resolution_matrix(\n forward_emeg, inv_emeg, method=\"MNE\", lambda2=lambda2\n)\nple_psf_emeg = resolution_metrics(\n rm_emeg, inv_emeg[\"src\"], function=\"psf\", metric=\"peak_err\"\n)\nsd_psf_emeg = resolution_metrics(\n rm_emeg, inv_emeg[\"src\"], function=\"psf\", metric=\"sd_ext\"\n)\ndel rm_emeg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## MEG\nDo the same for MEG:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "rm_meg = make_inverse_resolution_matrix(\n forward_meg, inv_meg, method=\"MNE\", lambda2=lambda2\n)\nple_psf_meg = resolution_metrics(\n rm_meg, inv_meg[\"src\"], function=\"psf\", metric=\"peak_err\"\n)\nsd_psf_meg = resolution_metrics(rm_meg, inv_meg[\"src\"], function=\"psf\", metric=\"sd_ext\")\ndel rm_meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualization\nLook at peak localisation error (PLE) across the whole cortex for PSF:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "brain_ple_emeg = ple_psf_emeg.plot(\n \"sample\",\n \"inflated\",\n \"lh\",\n subjects_dir=subjects_dir,\n figure=1,\n clim=dict(kind=\"value\", lims=(0, 2, 4)),\n)\n\nbrain_ple_emeg.add_text(0.1, 0.9, \"PLE PSF EMEG\", \"title\", font_size=16)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For MEG only:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "brain_ple_meg = ple_psf_meg.plot(\n \"sample\",\n \"inflated\",\n \"lh\",\n subjects_dir=subjects_dir,\n figure=2,\n clim=dict(kind=\"value\", lims=(0, 2, 4)),\n)\n\nbrain_ple_meg.add_text(0.1, 0.9, \"PLE PSF MEG\", \"title\", font_size=16)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Subtract the two distributions and plot this difference:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "diff_ple = ple_psf_emeg - ple_psf_meg\n\nbrain_ple_diff = diff_ple.plot(\n \"sample\",\n \"inflated\",\n \"lh\",\n subjects_dir=subjects_dir,\n figure=3,\n clim=dict(kind=\"value\", pos_lims=(0.0, 0.5, 1.0)),\n smoothing_steps=20,\n)\n\nbrain_ple_diff.add_text(0.1, 0.9, \"PLE EMEG-MEG\", \"title\", font_size=16)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These plots show that with respect to peak localization error, adding EEG to\nMEG does not bring much benefit. Next let's visualise spatial deviation (SD)\nacross the whole cortex for PSF:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "brain_sd_emeg = sd_psf_emeg.plot(\n \"sample\",\n \"inflated\",\n \"lh\",\n subjects_dir=subjects_dir,\n figure=4,\n clim=dict(kind=\"value\", lims=(0, 2, 4)),\n)\n\nbrain_sd_emeg.add_text(0.1, 0.9, \"SD PSF EMEG\", \"title\", font_size=16)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For MEG only:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "brain_sd_meg = sd_psf_meg.plot(\n \"sample\",\n \"inflated\",\n \"lh\",\n subjects_dir=subjects_dir,\n figure=5,\n clim=dict(kind=\"value\", lims=(0, 2, 4)),\n)\n\nbrain_sd_meg.add_text(0.1, 0.9, \"SD PSF MEG\", \"title\", font_size=16)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Subtract the two distributions and plot this difference:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "diff_sd = sd_psf_emeg - sd_psf_meg\n\nbrain_sd_diff = diff_sd.plot(\n \"sample\",\n \"inflated\",\n \"lh\",\n subjects_dir=subjects_dir,\n figure=6,\n clim=dict(kind=\"value\", pos_lims=(0.0, 0.5, 1.0)),\n smoothing_steps=20,\n)\n\nbrain_sd_diff.add_text(0.1, 0.9, \"SD EMEG-MEG\", \"title\", font_size=16)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Adding EEG to MEG decreases the spatial extent of point-spread\nfunctions (lower spatial deviation, blue colors), thus increasing\nresolution, especially for deeper source locations.\n\n## References\n.. footbibliography::\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.2" } }, "nbformat": 4, "nbformat_minor": 0 }