{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n# Plotting the full vector-valued MNE solution\n\nThe source space that is used for the inverse computation defines a set of\ndipoles, distributed across the cortex. When visualizing a source estimate, it\nis sometimes useful to show the dipole directions in addition to their\nestimated magnitude. This can be accomplished by computing a\n:class:`mne.VectorSourceEstimate` and plotting it with\n:meth:`stc.plot `, which uses\n:func:`~mne.viz.plot_vector_source_estimates` under the hood rather than\n:func:`~mne.viz.plot_source_estimates`.\n\nIt can also be instructive to visualize the actual dipole/activation locations\nin 3D space in a glass brain, as opposed to activations imposed on an inflated\nsurface (as typically done in :meth:`mne.SourceEstimate.plot`), as it allows\nyou to get a better sense of the underlying source geometry.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Author: Marijn van Vliet \n#\n# License: BSD-3-Clause\n# Copyright the MNE-Python contributors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\n\nimport mne\nfrom mne.datasets import sample\nfrom mne.minimum_norm import apply_inverse, read_inverse_operator\n\nprint(__doc__)\n\ndata_path = sample.data_path()\nsubjects_dir = data_path / \"subjects\"\nsmoothing_steps = 7\n\n# Read evoked data\nmeg_path = data_path / \"MEG\" / \"sample\"\nfname_evoked = meg_path / \"sample_audvis-ave.fif\"\nevoked = mne.read_evokeds(fname_evoked, condition=0, baseline=(None, 0))\n\n# Read inverse solution\nfname_inv = meg_path / \"sample_audvis-meg-oct-6-meg-inv.fif\"\ninv = read_inverse_operator(fname_inv)\n\n# Apply inverse solution, set pick_ori='vector' to obtain a\n# :class:`mne.VectorSourceEstimate` object\nsnr = 3.0\nlambda2 = 1.0 / snr**2\nstc = apply_inverse(evoked, inv, lambda2, \"dSPM\", pick_ori=\"vector\")\n\n# Use peak getter to move visualization to the time point of the peak magnitude\n_, peak_time = stc.magnitude().get_peak(hemi=\"lh\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot the source estimate:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "brain = stc.plot(\n initial_time=peak_time,\n hemi=\"lh\",\n subjects_dir=subjects_dir,\n smoothing_steps=smoothing_steps,\n)\n\n# You can save a brain movie with:\n# brain.save_movie(time_dilation=20, tmin=0.05, tmax=0.16, framerate=10,\n# interpolation='linear', time_viewer=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot the activation in the direction of maximal power for this data:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "stc_max, directions = stc.project(\"pca\", src=inv[\"src\"])\n# These directions must by design be close to the normals because this\n# inverse was computed with loose=0.2\nprint(\n \"Absolute cosine similarity between source normals and directions: \"\n f'{np.abs(np.sum(directions * inv[\"source_nn\"][2::3], axis=-1)).mean()}'\n)\nbrain_max = stc_max.plot(\n initial_time=peak_time,\n hemi=\"lh\",\n subjects_dir=subjects_dir,\n time_label=\"Max power\",\n smoothing_steps=smoothing_steps,\n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The normal is very similar:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "brain_normal = stc.project(\"normal\", inv[\"src\"])[0].plot(\n initial_time=peak_time,\n hemi=\"lh\",\n subjects_dir=subjects_dir,\n time_label=\"Normal\",\n smoothing_steps=smoothing_steps,\n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also do this with a fixed-orientation inverse. It looks a lot like\nthe result above because the ``loose=0.2`` orientation constraint keeps\nsources close to fixed orientation:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fname_inv_fixed = meg_path / \"sample_audvis-meg-oct-6-meg-fixed-inv.fif\"\ninv_fixed = read_inverse_operator(fname_inv_fixed)\nstc_fixed = apply_inverse(evoked, inv_fixed, lambda2, \"dSPM\", pick_ori=\"vector\")\nbrain_fixed = stc_fixed.plot(\n initial_time=peak_time,\n hemi=\"lh\",\n subjects_dir=subjects_dir,\n smoothing_steps=smoothing_steps,\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 }