diff --git a/.circleci/config.yml b/.circleci/config.yml
index 97a4a5910cd..d47862ae880 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -21,6 +21,9 @@ _check_skip: &check_skip
circleci-agent step halt;
fi
+_machine_image: &machine_image
+ image: ubuntu-2604:2026.05.1
+
jobs:
build_docs:
parameters:
@@ -28,7 +31,7 @@ jobs:
type: string
default: "false"
machine:
- image: ubuntu-2404:current
+ <<: *machine_image
# large 4 vCPUs 15GB mem
# https://discuss.circleci.com/t/changes-to-remote-docker-reporting-pricing/47759
resource_class: large
@@ -110,7 +113,7 @@ jobs:
# Load pip cache
- restore_cache:
keys:
- - pip-cache-0
+ - pip-cache-1
- restore_cache:
keys:
- user-install-bin-cache-310
@@ -122,7 +125,7 @@ jobs:
./tools/circleci_dependencies.sh
- save_cache:
- key: pip-cache-0
+ key: pip-cache-1
paths:
- ~/.cache/pip
- save_cache:
@@ -419,7 +422,7 @@ jobs:
type: string
default: "false"
machine:
- image: ubuntu-2404:current
+ <<: *machine_image
resource_class: large
steps:
- restore_cache:
@@ -439,7 +442,7 @@ jobs:
command: ./tools/circleci_bash_env.sh
- restore_cache:
keys:
- - pip-cache-0
+ - pip-cache-1
- run:
name: Get Python running
command: |
@@ -460,7 +463,7 @@ jobs:
deploy:
machine:
- image: ubuntu-2404:current
+ <<: *machine_image
steps:
- attach_workspace:
at: /tmp/build
diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml
index 4e44f7f8c5f..ccf40e66f25 100644
--- a/.github/workflows/autofix.yml
+++ b/.github/workflows/autofix.yml
@@ -16,8 +16,6 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-python@v6
- with:
- python-version: '3.12'
- run: pip install --upgrade towncrier pygithub gitpython numpy
- run: python ./.github/actions/rename_towncrier/rename_towncrier.py
- run: python ./tools/dev/ensure_headers.py
diff --git a/.github/workflows/credit.yml b/.github/workflows/credit.yml
index 8d28e076799..d83eaf4eb7e 100644
--- a/.github/workflows/credit.yml
+++ b/.github/workflows/credit.yml
@@ -21,8 +21,6 @@ jobs:
with:
persist-credentials: true
- uses: actions/setup-python@v6
- with:
- python-version: '3.12'
- run: pip install pygithub -e .
- run: python tools/dev/update_credit_json.py
- run: git add -f doc/sphinxext/prs/*.json
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7d3d0bc4c86..9222601905b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -19,13 +19,11 @@ jobs:
- uses: actions/checkout@v6.0.3
with:
persist-credentials: false
+ fetch-depth: 0
- uses: actions/setup-python@v6
- with:
- python-version: '3.10'
- name: Install dependencies
run: |
- python -m pip install --upgrade pip
- pip install build twine
+ python -m pip install --upgrade pip packaging build twine
- run: python -m build --sdist --wheel
- run: twine check --strict dist/*
- uses: actions/upload-artifact@v7
diff --git a/.github/workflows/spec_zero.yml b/.github/workflows/spec_zero.yml
index e63b3d4d55d..7673474f30a 100644
--- a/.github/workflows/spec_zero.yml
+++ b/.github/workflows/spec_zero.yml
@@ -45,7 +45,7 @@ jobs:
with:
version: ">=0.9"
activate-environment: true
- python-version: 3.12
+ python-version: "3.12"
- name: Install dependencies
run: uv pip install -e . packaging requests tomlkit
- name: Update tracked dependencies
diff --git a/doc/_static/style.css b/doc/_static/style.css
index bb93e819233..59f1ddf3864 100644
--- a/doc/_static/style.css
+++ b/doc/_static/style.css
@@ -401,27 +401,27 @@ p.centered a img.instlogo {
}
/* ************************************************************ funders page */
-ul.current li {
+ul.currentsponsor li {
margin-left: calc(var(--mne-sponsor-logo-lg) + 0.5rem);
text-indent: calc(-1 * var(--mne-sponsor-logo-lg) - 0.5rem);
padding-bottom: 0.75rem;
}
-ul.former li {
+ul.formersponsor li {
margin-left: calc(var(--mne-sponsor-logo-sm) + 1rem);
text-indent: calc(-1 * var(--mne-sponsor-logo-sm) - 1rem);
padding-bottom: 0.5rem;
}
-ul.current li img,
-ul.former li img {
+ul.currentsponsor li img,
+ul.formersponsor li img {
background-color: unset !important;
box-sizing: content-box;
object-fit: contain;
}
-ul.current li img {
+ul.currentsponsor li img {
max-height: calc(0.4 * var(--mne-sponsor-logo-lg));
width: var(--mne-sponsor-logo-lg);
}
-ul.former li img {
+ul.formersponsor li img {
max-height: calc(0.5 * var(--mne-sponsor-logo-sm));
width: var(--mne-sponsor-logo-sm);
}
diff --git a/doc/_templates/homepage.html b/doc/_templates/homepage.html
index b559f069eaf..d3eb451d557 100644
--- a/doc/_templates/homepage.html
+++ b/doc/_templates/homepage.html
@@ -23,7 +23,7 @@
{% for item in current_sponsors -%}
@@ -31,7 +31,7 @@
{% for inst in current_institutions -%}
diff --git a/doc/changes/names.inc b/doc/changes/names.inc
index 667671b148e..6a08df3c88d 100644
--- a/doc/changes/names.inc
+++ b/doc/changes/names.inc
@@ -50,7 +50,7 @@
.. _btkcodedev: https://github.com/btkcodedev
.. _buildqa: https://github.com/buildqa
.. _Carina Forster: https://github.com/CarinaFo
-.. _Carlos de la Torre-Ortiz: https://ctorre.me
+.. _Carlos de la Torre-Ortiz: https://github.com/c-torre
.. _Cathy Nangini: https://github.com/KatiRG
.. _Chetan Gohil: https://github.com/cgohil8
.. _Chris Bailey: https://github.com/cjayb
@@ -239,7 +239,7 @@
.. _Mohammad Daneshzand: https://github.com/mdaneshzand
.. _Mojackhak: https://github.com/Mojackhak
.. _Moritz Gerster: https://github.com/moritz-gerster
-.. _Motofumi Fushimi: https://github.com/motofumi-fushimi/motofumi-fushimi.github.io
+.. _Motofumi Fushimi: https://github.com/motofumi-fushimi
.. _Nabil Alibou: https://github.com/nabilalibou
.. _Natalie Klein: https://github.com/natalieklein
.. _Nathalie Gayraud: https://github.com/ngayraud
diff --git a/doc/conf.py b/doc/conf.py
index f14026d21c6..6a48d9f1058 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -657,6 +657,7 @@ def fix_sklearn_inherited_docstrings(app, what, name, obj, options, lines):
"https://doi.org/10.1126/", # www.science.org
"https://doi.org/10.1137/", # epubs.siam.org
"https://doi.org/10.1145/", # dl.acm.org
+ "https://doi.org/10.5281/", # zenodo.org
"https://doi.org/10.1155/", # www.hindawi.com/journals/cin
"https://doi.org/10.1161/", # www.ahajournals.org
"https://doi.org/10.1162/", # direct.mit.edu/neco/article/
@@ -667,6 +668,8 @@ def fix_sklearn_inherited_docstrings(app, what, name, obj, options, lines):
"https://doi.org/10.3390/", # mdpi.com
"https://hms.harvard.edu/", # doc/funding.rst
"https://stackoverflow.com/questions/21752259/python-why-pickle", # doc/help/faq
+ "https://mitpress.mit.edu/9780262525855", # works but linkcheck fails to resolve
+ "https://zenodo.org", # doc/help/faq
"https://blender.org",
"https://home.alexk101.dev",
"https://www.mq.edu.au/",
@@ -711,8 +714,12 @@ def fix_sklearn_inherited_docstrings(app, what, name, obj, options, lines):
"https://psychophysiology.cpmc.columbia.edu",
"https://erc.easme-web.eu",
"https://www.crnl.fr",
+ # Spurious failure
+ "https://megcore.nih.gov/index.php/Staff",
# Not rendered by linkcheck builder
r"ides\.html",
+ # Sponsors not rendered properly by linkcheck builder
+ "{{inst.url}}",
]
linkcheck_anchors = False # saves a bit of time
linkcheck_timeout = 15 # some can be quite slow
diff --git a/doc/credits/sponsors.rst b/doc/credits/sponsors.rst
index 005eefb01bf..0ad5d88ddd8 100644
--- a/doc/credits/sponsors.rst
+++ b/doc/credits/sponsors.rst
@@ -7,7 +7,7 @@ Sponsors
Maintenance and development of MNE-Python is currently supported by the following funding agencies and partners:
-.. rst-class:: list-unstyled current
+.. rst-class:: list-unstyled currentsponsor
- |nih| **National Institutes of Health:**
`R01-NS104585 `_
@@ -18,7 +18,7 @@ Maintenance and development of MNE-Python is currently supported by the followin
Past sponsors
-------------
-.. rst-class:: list-unstyled former
+.. rst-class:: list-unstyled formersponsor
- |nih| National Institutes of Health:
`R01-EB009048 `_,
@@ -56,7 +56,7 @@ Supporting institutions
Some institutions support their employees’ contributions to MNE-Python as part of normal work duties. Current supporting institutions include:
-.. rst-class:: list-unstyled current
+.. rst-class:: list-unstyled currentsponsor
{% for inst in current_institutions %}
{% if not inst.name.endswith("_dk") %}
diff --git a/doc/development/roadmap.rst b/doc/development/roadmap.rst
index a608062a135..8d09cc03a8b 100644
--- a/doc/development/roadmap.rst
+++ b/doc/development/roadmap.rst
@@ -273,7 +273,7 @@ Time-frequency visualization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We implemented a viewer for interactive visualization of volumetric
source-time-frequency (5-D) maps on MRI slices (orthogonal 2D viewer).
-`NutmegTrip `__
+`NutmegTrip `__
(written by Sarang Dalal) provides similar functionality in MATLAB in
conjunction with FieldTrip. Example of NutmegTrip's source-time-frequency mode
in action (click for link to YouTube):
diff --git a/doc/links.inc b/doc/links.inc
index 95fab1b1bf5..3f8caf28081 100644
--- a/doc/links.inc
+++ b/doc/links.inc
@@ -20,7 +20,7 @@
.. _`MNE-HCP`: http://mne.tools/mne-hcp
.. _`MNE-Realtime`: https://mne.tools/mne-realtime
.. _`MNE-LSL`: https://mne.tools/mne-lsl
-.. _`MNE-RT`: https://payamsash.github.io/mne-rt/
+.. _`MNE-RT`: https://mne-rt-org.github.io/mne-rt/
.. _`MNE-gui-addons`: https://mne.tools/mne-gui-addons
.. _`MNE-MATLAB`: https://github.com/mne-tools/mne-matlab
.. _`MNE-Docker`: https://github.com/mne-tools/mne-docker
diff --git a/doc/references.bib b/doc/references.bib
index c7eefd9e808..825dbd96f6c 100644
--- a/doc/references.bib
+++ b/doc/references.bib
@@ -2375,7 +2375,7 @@ @book{Luck2014
edition = {2nd},
publisher = {The MIT Press},
address = {Cambridge, MA},
- url = {https://mitpress.mit.edu/books/introduction-event-related-potential-technique-second-edition},
+ url = {https://mitpress.mit.edu/9780262525855/an-introduction-to-the-event-related-potential-technique},
isbn = {978-0-262-52585-5}
}
diff --git a/doc/sphinxext/mne_doc_utils.py b/doc/sphinxext/mne_doc_utils.py
index 090a80cbe20..8e7415b3375 100644
--- a/doc/sphinxext/mne_doc_utils.py
+++ b/doc/sphinxext/mne_doc_utils.py
@@ -4,6 +4,7 @@
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
+import functools
import gc
import os
import time
@@ -17,9 +18,7 @@
import mne
from mne.utils import (
- _assert_no_instances as _assert_no_instances_mne,
-)
-from mne.utils import (
+ _assert_no_instances,
_get_extra_data_path,
sizeof_fmt,
)
@@ -123,14 +122,20 @@ def reset_warnings(gallery_conf, fname):
t0 = time.time()
-def _assert_no_instances(cls, when):
+def _reraise_extension_error(func):
"""Wrap our internal one but make the traceback nicer when it fails."""
- try:
- _assert_no_instances_mne(cls, when)
- except Exception as exc:
- raise ExtensionError(str(exc)) from None
+
+ @functools.wraps(func)
+ def _wrapper(gallery_conf, fname, when):
+ try:
+ return func(gallery_conf, fname, when)
+ except Exception:
+ raise ExtensionError(f"{func.__name__} failed: {when=}, {fname=}")
+
+ return _wrapper
+@_reraise_extension_error
def reset_modules(gallery_conf, fname, when):
"""Do the reset."""
import matplotlib.pyplot as plt
diff --git a/examples/visualization/eyetracking_plot_heatmap.py b/examples/visualization/eyetracking_plot_heatmap.py
index 07983685b5e..8d656708a12 100644
--- a/examples/visualization/eyetracking_plot_heatmap.py
+++ b/examples/visualization/eyetracking_plot_heatmap.py
@@ -82,8 +82,10 @@
# start at a value greater than the darkest value in our previous heatmap, which will
# make the darkest colors of the heatmap transparent.
-cmap.set_under("k", alpha=0) # make the lowest values transparent
-ax = plt.subplot()
+cmap = cmap.with_extremes(
+ under=(0.0, 0.0, 0.0, 0.0)
+) # make the lowest values transparent
+_, ax = plt.subplots(figsize=(6, 3.5), layout="constrained")
ax.imshow(plt.imread(stim_fpath))
plot_gaze(
epochs["natural"],
diff --git a/mne/viz/ui_events.py b/mne/viz/ui_events.py
index 3363c398f35..64cf81d1c9d 100644
--- a/mne/viz/ui_events.py
+++ b/mne/viz/ui_events.py
@@ -18,6 +18,7 @@
import re
import weakref
from dataclasses import dataclass
+from functools import partial
from matplotlib.colors import Colormap
@@ -230,6 +231,22 @@ class ChannelsSelect(UIEvent):
ch_names: list[str]
+def _delete_event_channel(event=None, *, weakfig):
+ """Delete the event channel (callback function)."""
+ fig = weakfig()
+ if fig is None:
+ return
+ publish(fig, event=FigureClosing()) # Notify subscribers of imminent close
+ logger.debug(f"unlink(({fig})")
+ unlink(fig) # Remove channel from the _event_channel_links dict
+ if fig in _event_channels:
+ logger.debug(f" del _event_channels[{fig}]")
+ del _event_channels[fig]
+ if fig in _disabled_event_channels:
+ logger.debug(f" _disabled_event_channels.remove({fig})")
+ _disabled_event_channels.remove(fig)
+
+
def _get_event_channel(fig):
"""Get the event channel associated with a figure.
@@ -263,30 +280,17 @@ def _get_event_channel(fig):
# When the figure is closed, its associated event channel should be
# deleted. This is a good time to set this up.
- def delete_event_channel(event=None, *, weakfig=weakfig):
- """Delete the event channel (callback function)."""
- fig = weakfig()
- if fig is None:
- return
- publish(fig, event=FigureClosing()) # Notify subscribers of imminent close
- logger.debug(f"unlink(({fig})")
- unlink(fig) # Remove channel from the _event_channel_links dict
- if fig in _event_channels:
- logger.debug(f" del _event_channels[{fig}]")
- del _event_channels[fig]
- if fig in _disabled_event_channels:
- logger.debug(f" _disabled_event_channels.remove({fig})")
- _disabled_event_channels.remove(fig)
# Hook up the above callback function to the close event of the figure
# window. How this is done exactly depends on the various figure types
# MNE-Python has.
_validate_type(fig, (matplotlib.figure.Figure, Brain, EvokedField), "fig")
+ this_delete_event_channel = partial(_delete_event_channel, weakfig=weakfig)
if isinstance(fig, matplotlib.figure.Figure):
- fig.canvas.mpl_connect("close_event", delete_event_channel)
+ fig.canvas.mpl_connect("close_event", this_delete_event_channel)
else:
assert hasattr(fig, "_renderer") # figures like Brain, EvokedField, etc.
- fig._renderer._window_close_connect(delete_event_channel, after=False)
+ fig._renderer._window_close_connect(this_delete_event_channel, after=False)
# Now the event channel exists for sure.
return _event_channels[fig]
@@ -491,6 +495,5 @@ def _cleanup_agg():
if isinstance(key, matplotlib.figure.Figure):
for cb in key.canvas.callbacks.callbacks["close_event"].values():
cb = cb() # get the true ref
- # Our __name__ is "_get_event_channel..delete_event_channel"
- if cb is not None and cb.__name__.endswith("delete_event_channel"):
+ if isinstance(cb, partial) and cb.func is _delete_event_channel:
cb()
diff --git a/pyproject.toml b/pyproject.toml
index 956074974f8..83a7b7f043a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -17,7 +17,7 @@ doc = [
"numpydoc >= 0.5",
"openneuro-py >= 2020.1",
"psutil",
- "pydata_sphinx_theme >= 0.15.2",
+ "pydata-sphinx-theme >= 0.15.2",
"pygments >= 2.13",
"pymef",
"pyvistaqt >= 0.11", # released 2023-06-30, no newer version available
diff --git a/tools/circleci_bash_env.sh b/tools/circleci_bash_env.sh
index 91df8a4f1b7..91056558e39 100755
--- a/tools/circleci_bash_env.sh
+++ b/tools/circleci_bash_env.sh
@@ -4,10 +4,10 @@ set -e
set -o pipefail
./tools/setup_xvfb.sh
-sudo apt install -qq graphviz optipng python3.12-venv python3-venv libxft2 ffmpeg r-base libtirpc-dev
+sudo apt install -qq graphviz optipng python3-venv libxft2 ffmpeg r-base libtirpc-dev libgvplugin-neato-layout8
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install ./google-chrome-stable_current_amd64.deb
-python3.12 -m venv ~/python_env
+python -m venv ~/python_env
echo "set -e" >> $BASH_ENV
echo "set -o pipefail" >> $BASH_ENV
echo "export XDG_RUNTIME_DIR=/tmp/runtime-circleci" >> $BASH_ENV
diff --git a/tools/install_pre_requirements.sh b/tools/install_pre_requirements.sh
index 0d9d523ec29..894f5e7114e 100755
--- a/tools/install_pre_requirements.sh
+++ b/tools/install_pre_requirements.sh
@@ -55,12 +55,11 @@ python -m pip install $STD_ARGS \
git+https://github.com/pyqtgraph/pyqtgraph \
"mne-qt-browser @ https://github.com/mne-tools/mne-qt-browser/archive/refs/heads/main.zip" \
"mne-bids @ https://github.com/mne-tools/mne-bids/archive/refs/heads/main.zip" \
- git+https://github.com/nipy/nibabel \
+ "nibabel @ https://github.com/nipy/nibabel/archive/refs/heads/master.zip" \
git+https://github.com/joblib/joblib \
git+https://github.com/h5io/h5io \
git+https://github.com/BUNPC/pysnirf2 \
git+https://github.com/the-siesta-group/edfio \
- git+https://github.com/python-quantities/python-quantities \
trame trame-vtk trame-vuetify trame-pyvista nest-asyncio2 jupyter ipyevents ipympl \
openmeeg imageio-ffmpeg xlrd mffpy traitlets pybv eeglabio defusedxml antio curryreader
echo "::endgroup::"
diff --git a/tools/setup_xvfb.sh b/tools/setup_xvfb.sh
index d22f8e2b7ac..61fab33f1c3 100755
--- a/tools/setup_xvfb.sh
+++ b/tools/setup_xvfb.sh
@@ -11,5 +11,11 @@ done
# This also includes the libraries necessary for PyQt5/PyQt6
sudo apt update
-sudo apt install -yqq xvfb libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libopengl0 libegl1 libosmesa6 mesa-utils libxcb-shape0 libxcb-cursor0 libxml2
+# Need two different libxml2 variants for 24.04 and 26.04
+if [[ $(lsb_release -rs) == "26.04" ]]; then
+ XML_DEP=libxml2-16
+else
+ XML_DEP=libxml2
+fi
+sudo apt install -yqq xvfb libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libopengl0 libegl1 libosmesa6 mesa-utils libxcb-shape0 libxcb-cursor0 $XML_DEP
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1400x900x24 -ac +extension GLX +render -noreset
diff --git a/tutorials/epochs/20_visualize_epochs.py b/tutorials/epochs/20_visualize_epochs.py
index 04eca026b7e..596046f2710 100644
--- a/tutorials/epochs/20_visualize_epochs.py
+++ b/tutorials/epochs/20_visualize_epochs.py
@@ -25,12 +25,11 @@
raw = mne.io.read_raw_fif(sample_data_raw_file, verbose=False).crop(tmax=120)
# %%
-# To create the `~mne.Epochs` data structure, we'll extract the event
-# IDs stored in the :term:`stim channel`, map those integer event IDs to more
-# descriptive condition labels using an event dictionary, and pass those to the
-# `~mne.Epochs` constructor, along with the `~mne.io.Raw` data and the
-# desired temporal limits of our epochs, ``tmin`` and ``tmax`` (for a
-# detailed explanation of these steps, see :ref:`tut-epochs-class`).
+# To create the `~mne.Epochs` data structure, we'll extract the event IDs stored in the
+# :term:`stim channel`, map those integer event IDs to more descriptive condition labels
+# using an event dictionary, and pass those to the `~mne.Epochs` constructor, along with
+# the `~mne.io.Raw` data and the desired temporal limits of our epochs, ``tmin`` and
+# ``tmax`` (for a detailed explanation of these steps, see :ref:`tut-epochs-class`).
events = mne.find_events(raw, stim_channel="STI 014")
event_dict = {
diff --git a/tutorials/epochs/60_make_fixed_length_epochs.py b/tutorials/epochs/60_make_fixed_length_epochs.py
index 10b8c12ea19..f13d49a0657 100644
--- a/tutorials/epochs/60_make_fixed_length_epochs.py
+++ b/tutorials/epochs/60_make_fixed_length_epochs.py
@@ -16,15 +16,6 @@
epochs by segmenting the data around the onset of each stimulus, we will
create 30 second epochs that allow us to perform non-event-related analyses of
the signal.
-
-.. note::
- Starting in version 1.0, all functions in the ``mne.connectivity``
- sub-module are housed in a separate package called
- :mod:`mne-connectivity `. Download it by running:
-
- .. code-block:: console
-
- $ pip install mne-connectivity
"""
# Authors: The MNE-Python contributors.
diff --git a/tutorials/evoked/10_evoked_overview.py b/tutorials/evoked/10_evoked_overview.py
index b251a1f8239..4e639dea7b8 100644
--- a/tutorials/evoked/10_evoked_overview.py
+++ b/tutorials/evoked/10_evoked_overview.py
@@ -58,9 +58,8 @@
# :class:`~mne.Epochs` object, but may also be initiated (or disabled)
# manually. We will discuss this in more detail later.
#
-# The information about the baseline period of :class:`~mne.Epochs` is
-# transferred to derived :class:`~mne.Evoked` objects to maintain provenance as
-# you process your data:
+# The information about the baseline period of :class:`~mne.Epochs` is transferred to
+# derived :class:`~mne.Evoked` objects to maintain provenance as you process your data:
print(f"Epochs baseline: {epochs.baseline}")
print(f"Evoked baseline: {evoked.baseline}")
diff --git a/tutorials/evoked/20_visualize_evoked.py b/tutorials/evoked/20_visualize_evoked.py
index 3a91c38bb3d..eb172a4704b 100644
--- a/tutorials/evoked/20_visualize_evoked.py
+++ b/tutorials/evoked/20_visualize_evoked.py
@@ -5,8 +5,7 @@
Visualizing Evoked data
=======================
-This tutorial shows the different visualization methods for
-:class:`~mne.Evoked` objects.
+This tutorial shows different visualization methods for :class:`~mne.Evoked` objects.
As usual we'll start by importing the modules we need:
"""