Plotting sensor layouts of EEG systems#

This example illustrates how to load all the EEG system montages shipped in MNE-python, and display it on the fsaverage template subject.

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Joan Massich <mailsik@gmail.com>
#
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
import gc
import os.path as op

import matplotlib.pyplot as plt
import numpy as np

import mne
from mne.channels.montage import get_builtin_montages
from mne.datasets import fetch_fsaverage
from mne.viz import (
    clear_3d_figure,
    close_3d_figure,
    concatenate_images,
    create_3d_figure,
    set_3d_view,
)

There are a lot of montages to look at, so rather than opening one 3D figure per montage (which uses a lot of memory), we plot them one at a time into a single reusable figure, take a screenshot of each, and combine the screenshots into one Matplotlib figure at the end.

montages = get_builtin_montages()
size = (400, 400)  # size of each montage screenshot, in pixels
bgcolor = (0.5, 0.5, 0.5)
n_cols = 6
n_rows = int(np.ceil(len(montages) / n_cols))
# Size of each montage in the combined figure. Setting this rather than deriving it
# from ``size`` keeps the title font size independent of the screenshot resolution.
inches_per_montage = 2.5


def plot_montage_grid(images, titles):
    """Combine 3D screenshots into a single Matplotlib figure."""
    rows = [
        concatenate_images(images[start : start + n_cols], axis=1, bgcolor=bgcolor)
        for start in range(0, len(images), n_cols)
    ]
    grid = concatenate_images(rows, axis=0, bgcolor=bgcolor, centered=False)
    height, width = images[0].shape[:2]
    fig = plt.figure()
    # sizes the window to the figure, so the whole grid is visible interactively
    fig.set_size_inches(n_cols * inches_per_montage, n_rows * inches_per_montage)
    ax = fig.add_axes([0, 0, 1, 1])  # fill the entire figure
    ax.set_axis_off()
    ax.imshow(grid)
    for idx, title in enumerate(titles):
        row, col = divmod(idx, n_cols)
        ax.text(
            (col + 0.5) * width,
            (row + 0.05) * height,
            title,
            color="w",
            ha="center",
            va="top",
            fontsize=11,
        )
    return fig

Check all montages against a sphere

# The figure must be created and closed within a single code block, because
# Sphinx-Gallery screenshots (and closes) every open 3D figure at the end of a block.
fig_3d = create_3d_figure(size=size, bgcolor=bgcolor)
set_3d_view(
    figure=fig_3d,
    azimuth=135,
    elevation=80,
    distance=0.6,
    focalpoint=(0.0, 0.0, 0.0),
)
images = list()
for current_montage in montages:
    montage = mne.channels.make_standard_montage(current_montage)
    info = mne.create_info(ch_names=montage.ch_names, sfreq=100.0, ch_types="eeg")
    info.set_montage(montage)
    sphere = mne.make_sphere_model(
        r0="auto", head_radius="auto", info=info, verbose="error"
    )
    mne.viz.plot_alignment(
        # Plot options
        show_axes=True,
        dig="fiducials",
        surfaces="head",
        trans=mne.Transform("head", "mri", trans=np.eye(4)),  # identity
        bem=sphere,
        info=info,
        fig=fig_3d,
        set_view=False,  # keep the view we set above
    )
    images.append(fig_3d.plotter.screenshot())
    clear_3d_figure(fig_3d)  # reuse the same figure for the next montage
    gc.collect()

close_3d_figure(fig_3d)
plot_montage_grid(images, montages)
montage
Channel types:: eeg: 335
Channel types:: eeg: 70
Channel types:: eeg: 21
Channel types:: eeg: 343
Channel types:: eeg: 94
Channel types:: eeg: 65
Channel types:: eeg: 100
Channel types:: eeg: 74
Channel types:: eeg: 100
Channel types:: eeg: 16
Channel types:: eeg: 32
Channel types:: eeg: 64
Channel types:: eeg: 128
Channel types:: eeg: 160
Channel types:: eeg: 256
Channel types:: eeg: 74
Channel types:: eeg: 61
Channel types:: eeg: 64
Channel types:: eeg: 256
Channel types:: eeg: 33
Channel types:: eeg: 64
Channel types:: eeg: 65
Channel types:: eeg: 128
Channel types:: eeg: 129
Channel types:: eeg: 256
Channel types:: eeg: 257
Channel types:: eeg: 60
Channel types:: eeg: 70
Channel types:: eeg: 10
Channel types:: eeg: 18
Channel types:: eeg: 130
Channel types:: eeg: 344
Channel types:: eeg: 70
Channel types:: eeg: 21

Check all montages against fsaverage

subjects_dir = op.dirname(fetch_fsaverage())

fig_3d = create_3d_figure(size=size, bgcolor=bgcolor)
set_3d_view(
    figure=fig_3d,
    azimuth=135,
    elevation=80,
    distance=0.6,
    focalpoint=(0.0, 0.0, 0.0),
)
images = list()
for current_montage in montages:
    montage = mne.channels.make_standard_montage(current_montage)
    # Create dummy info
    info = mne.create_info(ch_names=montage.ch_names, sfreq=100.0, ch_types="eeg")
    info.set_montage(montage)
    mne.viz.plot_alignment(
        # Plot options
        show_axes=True,
        dig="fiducials",
        surfaces="head",
        mri_fiducials=True,
        subject="fsaverage",
        subjects_dir=subjects_dir,
        info=info,
        coord_frame="mri",
        trans="fsaverage",  # transform from head coords to fsaverage's MRI
        fig=fig_3d,
        set_view=False,  # keep the view we set above
    )
    images.append(fig_3d.plotter.screenshot())
    clear_3d_figure(fig_3d)
    gc.collect()

close_3d_figure(fig_3d)
plot_montage_grid(images, montages)
montage
0 files missing from root.txt in /home/circleci/mne_data/MNE-fsaverage-data
0 files missing from bem.txt in /home/circleci/mne_data/MNE-fsaverage-data/fsaverage
Using outer_skin.surf for head surface.
Channel types:: eeg: 335
Using outer_skin.surf for head surface.
Channel types:: eeg: 70
Using outer_skin.surf for head surface.
Channel types:: eeg: 21
Using outer_skin.surf for head surface.
Channel types:: eeg: 343
Using outer_skin.surf for head surface.
Channel types:: eeg: 94
Using outer_skin.surf for head surface.
Channel types:: eeg: 65
Using outer_skin.surf for head surface.
Channel types:: eeg: 100
Using outer_skin.surf for head surface.
Channel types:: eeg: 74
Using outer_skin.surf for head surface.
Channel types:: eeg: 100
Using outer_skin.surf for head surface.
Channel types:: eeg: 16
Using outer_skin.surf for head surface.
Channel types:: eeg: 32
Using outer_skin.surf for head surface.
Channel types:: eeg: 64
Using outer_skin.surf for head surface.
Channel types:: eeg: 128
Using outer_skin.surf for head surface.
Channel types:: eeg: 160
Using outer_skin.surf for head surface.
Channel types:: eeg: 256
Using outer_skin.surf for head surface.
Channel types:: eeg: 74
Using outer_skin.surf for head surface.
Channel types:: eeg: 61
Using outer_skin.surf for head surface.
Channel types:: eeg: 64
Using outer_skin.surf for head surface.
Channel types:: eeg: 256
Using outer_skin.surf for head surface.
Channel types:: eeg: 33
Using outer_skin.surf for head surface.
Channel types:: eeg: 64
Using outer_skin.surf for head surface.
Channel types:: eeg: 65
Using outer_skin.surf for head surface.
Channel types:: eeg: 128
Using outer_skin.surf for head surface.
Channel types:: eeg: 129
Using outer_skin.surf for head surface.
Channel types:: eeg: 256
Using outer_skin.surf for head surface.
Channel types:: eeg: 257
Using outer_skin.surf for head surface.
Channel types:: eeg: 60
Using outer_skin.surf for head surface.
Channel types:: eeg: 70
Using outer_skin.surf for head surface.
Channel types:: eeg: 10
Using outer_skin.surf for head surface.
Channel types:: eeg: 18
Using outer_skin.surf for head surface.
Channel types:: eeg: 130
Using outer_skin.surf for head surface.
Channel types:: eeg: 344
Using outer_skin.surf for head surface.
Channel types:: eeg: 70
Using outer_skin.surf for head surface.
Channel types:: eeg: 21

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

Gallery generated by Sphinx-Gallery