{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n# Plotting topographic maps of evoked data\n\nLoad evoked data and plot topomaps for selected time points using multiple\nadditional options.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Authors: Christian Brodbeck \n# Tal Linzen \n# Denis A. Engeman \n# Miko\u0142aj Magnuski \n# Eric Larson \n# Alex Rockhill \n#\n# License: BSD-3-Clause\n# Copyright the MNE-Python contributors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom mne import read_evokeds\nfrom mne.datasets import sample\n\nprint(__doc__)\n\npath = sample.data_path()\nfname = path / \"MEG\" / \"sample\" / \"sample_audvis-ave.fif\"\n\n# load evoked corresponding to a specific condition\n# from the fif file and subtract baseline\ncondition = \"Left Auditory\"\nevoked = read_evokeds(fname, condition=condition, baseline=(None, 0))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic :func:`~mne.viz.plot_topomap` options\n\nWe plot evoked topographies using :func:`mne.Evoked.plot_topomap`. The first\nargument, ``times`` allows to specify time instants (in seconds!) for which\ntopographies will be shown. We select timepoints from 50 to 150 ms with a\nstep of 20ms and plot magnetometer data:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "times = np.arange(0.05, 0.151, 0.02)\nevoked.plot_topomap(times, ch_type=\"mag\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If times is set to None at most 10 regularly spaced topographies will be\nshown:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(ch_type=\"mag\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use ``nrows`` and ``ncols`` parameter to create multiline plots\nwith more timepoints.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "all_times = np.arange(-0.2, 0.5, 0.03)\nevoked.plot_topomap(all_times, ch_type=\"mag\", ncols=8, nrows=\"auto\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of showing topographies at specific time points we can compute\naverages of 50 ms bins centered on these time points to reduce the noise in\nthe topographies:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(times, ch_type=\"mag\", average=0.05)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can plot gradiometer data (plots the RMS for each pair of gradiometers)\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(times, ch_type=\"grad\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional :func:`~mne.viz.plot_topomap` options\n\nWe can also use a range of various :func:`mne.viz.plot_topomap` arguments\nthat control how the topography is drawn. For example:\n\n* ``cmap`` - to specify the color map\n* ``res`` - to control the resolution of the topographies (lower resolution\n means faster plotting)\n* ``contours`` to define how many contour lines should be plotted\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(times, ch_type=\"mag\", cmap=\"Spectral_r\", res=32, contours=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you look at the edges of the head circle of a single topomap you'll see\nthe effect of extrapolation. There are three extrapolation modes:\n\n- ``extrapolate='local'`` extrapolates only to points close to the sensors.\n- ``extrapolate='head'`` extrapolates out to the head circle.\n- ``extrapolate='box'`` extrapolates to a large box stretching beyond the\n head circle.\n\nThe default value ``extrapolate='auto'`` will use ``'local'`` for MEG sensors\nand ``'head'`` otherwise. Here we show each option:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "extrapolations = [\"local\", \"head\", \"box\"]\nfig, axes = plt.subplots(figsize=(7.5, 4.5), nrows=2, ncols=3, layout=\"constrained\")\n\n# Here we look at EEG channels, and use a custom head sphere to get all the\n# sensors to be well within the drawn head surface\nfor axes_row, ch_type in zip(axes, (\"mag\", \"eeg\")):\n for ax, extr in zip(axes_row, extrapolations):\n evoked.plot_topomap(\n 0.1,\n ch_type=ch_type,\n size=2,\n extrapolate=extr,\n axes=ax,\n show=False,\n colorbar=False,\n sphere=(0.0, 0.0, 0.0, 0.09),\n )\n ax.set_title(f\"{ch_type.upper()} {extr}\", fontsize=14)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## More advanced usage\n\nNow we plot magnetometer data as topomap at a single time point: 100 ms\npost-stimulus, add channel labels, title and adjust plot margins:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig = evoked.plot_topomap(\n 0.1, ch_type=\"mag\", show_names=True, colorbar=False, size=6, res=128\n)\nfig.suptitle(\"Auditory response\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also highlight specific channels by adding a mask, to e.g. mark\nchannels exceeding a threshold at a given time:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Define a threshold and create the mask\nmask = evoked.data > 1e-13\n\n# Select times and plot\ntimes = (0.09, 0.1, 0.11)\nmask_params = dict(markersize=10, markerfacecolor=\"y\")\nevoked.plot_topomap(times, ch_type=\"mag\", mask=mask, mask_params=mask_params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or by manually picking the channels to highlight at different times:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "times = (0.09, 0.1, 0.11)\n_times = ((np.abs(evoked.times - t)).argmin() for t in times)\nsignificant_channels = [\n (\"MEG 0231\", \"MEG 1611\", \"MEG 1621\", \"MEG 1631\", \"MEG 1811\"),\n (\"MEG 2411\", \"MEG 2421\"),\n (\"MEG 1621\"),\n]\n_channels = [np.isin(evoked.ch_names, ch) for ch in significant_channels]\n\nmask = np.zeros(evoked.data.shape, dtype=\"bool\")\nfor _chs, _time in zip(_channels, _times):\n mask[_chs, _time] = True\n\nevoked.plot_topomap(times, ch_type=\"mag\", mask=mask, mask_params=mask_params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interpolating topomaps\nWe can also look at the effects of interpolating our data. Perhaps, we\nmight have data per channel such as the impedance of each electrode that\nwe don't want interpolated, or we just want to visualize the data without\ninterpolation as a sanity check. We can use ``image_interp='nearest'`` to\nprevent any interpolation or ``image_interp='linear'`` to do a linear\ninterpolation instead of the default cubic interpolation.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The default cubic interpolation is the smoothest and is great for\npublications.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(times, ch_type=\"eeg\", image_interp=\"cubic\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The linear interpolation might be helpful in some cases.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(times, ch_type=\"eeg\", image_interp=\"linear\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The nearest (Voronoi, no interpolation) interpolation is especially helpful\nfor debugging and seeing the values assigned to the topomap unaltered.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "evoked.plot_topomap(times, ch_type=\"eeg\", image_interp=\"nearest\", contours=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Animating the topomap\n\nInstead of using a still image we can plot magnetometer data as an animation,\nwhich animates properly only in matplotlib interactive mode.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "times = np.arange(0.05, 0.151, 0.01)\nfig, anim = evoked.animate_topomap(times=times, ch_type=\"mag\", frame_rate=2, blit=False)" ] } ], "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 }