Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4f5cf32
Fix CircleCI [skip azp] [skip actions]
larsoner Jun 22, 2026
941a3c3
TST: Fine [circle full] [skip azp] [skip actions]
larsoner Jun 22, 2026
f4a1c3a
FIX: Try [skip azp] [skip actions]
larsoner Jun 23, 2026
2726cc7
FIX: Try again [skip azp] [skip actions]
larsoner Jun 23, 2026
56c85cb
FIX: Try again [skip azp] [skip actions]
larsoner Jun 23, 2026
69b34a3
FIX: Try again [skip azp] [skip actions]
larsoner Jun 23, 2026
5b0d0f4
FIX: Try again [skip azp] [skip actions]
larsoner Jun 23, 2026
3450a9d
FIX: Try again [skip azp] [skip actions] [circle front]
larsoner Jun 23, 2026
e45602d
FIX: Try again [skip azp] [skip actions] [circle front]
larsoner Jun 23, 2026
cbb0d7e
FIX: Try again [skip azp] [skip actions] [circle front]
larsoner Jun 23, 2026
337232a
FIX: Try again [skip azp] [skip actions] [circle front]
larsoner Jun 23, 2026
d29f704
FIX: Try again [skip azp] [skip actions] [circle front]
larsoner Jun 23, 2026
5a62c5e
FIX: Try again [skip azp] [skip actions] [circle front]
larsoner Jun 23, 2026
41a6503
TST: All [circle full] [circle linkcheck]
larsoner Jun 23, 2026
1a467ac
FIX: Maybe [circle linkcheck] [skip azp] [skip actions]
larsoner Jun 23, 2026
1d7298c
FIX: Maybe [circle linkcheck] [skip azp] [skip actions]
larsoner Jun 23, 2026
e6c2bf2
FIX: Maybe [circle linkcheck] [skip azp] [skip actions]
larsoner Jun 23, 2026
6d85739
FIX: Maybe [circle linkcheck] [skip azp] [skip actions]
larsoner Jun 23, 2026
d7ad73a
TST: Ping [circle linkcheck]
larsoner Jun 23, 2026
019a983
FIX: Link
larsoner Jun 23, 2026
6fe71e9
FIX: Depth
larsoner Jun 23, 2026
6c1356d
FIX: Upgrade
larsoner Jun 23, 2026
482ed96
FIX: Dont use git
larsoner Jun 23, 2026
05ac8e7
FIX: Dont need
larsoner Jun 23, 2026
d13ac32
Update .github/workflows/release.yml
larsoner Jun 23, 2026
15a9946
Merge branch 'main' into doc
larsoner Jun 23, 2026
94fbde3
FIX: Dont use
larsoner Jun 23, 2026
fddc7e8
FIX: Dont pin
larsoner Jun 23, 2026
b42b1a6
classname
drammock Jun 23, 2026
9c50ccb
missed one
drammock Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ _check_skip: &check_skip
circleci-agent step halt;
fi

_machine_image: &machine_image
image: ubuntu-2604:2026.05.1

jobs:
build_docs:
parameters:
scheduled:
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
Expand Down Expand Up @@ -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
Expand All @@ -122,7 +125,7 @@ jobs:
./tools/circleci_dependencies.sh

- save_cache:
key: pip-cache-0
key: pip-cache-1
paths:
- ~/.cache/pip
- save_cache:
Expand Down Expand Up @@ -419,7 +422,7 @@ jobs:
type: string
default: "false"
machine:
image: ubuntu-2404:current
<<: *machine_image
resource_class: large
steps:
- restore_cache:
Expand All @@ -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: |
Expand All @@ -460,7 +463,7 @@ jobs:

deploy:
machine:
image: ubuntu-2404:current
<<: *machine_image
steps:
- attach_workspace:
at: /tmp/build
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/credit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/spec_zero.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions doc/_static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions doc/_templates/homepage.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
<!-- current funders -->
{% for item in current_sponsors -%}
<div class="card my-1 mx-2 {{ item.klass }}">
<a href="{{ pathto('credit/funding.html', 1) }}">
<a href="{{ pathto('credits/sponsors.html', 1) }}">
<img class="card-img" src="{{ pathto('_static/funding/' + item.img, 1) }}" title="{{ item.title }}" alt="{{ item.title }}">
</a>
</div>
{% endfor %}
<!-- current partner institutions -->
{% for inst in current_institutions -%}
<div class="card my-1 mx-2 {{ inst.klass }}">
<a href="{{ pathto('credit/funding.html#supporting-institutions', 1) }}">
<a href="{{ pathto('credits/sponsors.html#supporting-institutions', 1) }}">
Comment thread
larsoner marked this conversation as resolved.
<img class="card-img" src="{{ pathto('_static/institution_logos/' + inst.img, 1) }}" title="{{ inst.name }}" alt="{{ inst.name }}"/>
</a>
</div>
Expand Down
4 changes: 2 additions & 2 deletions doc/changes/names.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand All @@ -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/",
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions doc/credits/sponsors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://reporter.nih.gov/project-details/10175064>`_
Expand All @@ -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 <https://reporter.nih.gov/project-details/9053482>`_,
Expand Down Expand Up @@ -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") %}
Expand Down
2 changes: 1 addition & 1 deletion doc/development/roadmap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/fieldtrip/fieldtrip/tree/master/contrib/nutmegtrip>`__
`NutmegTrip <https://github.com/fieldtrip/fieldtrip/tree/20260408/contrib/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):
Expand Down
2 changes: 1 addition & 1 deletion doc/links.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion doc/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -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}
}

Expand Down
21 changes: 13 additions & 8 deletions doc/sphinxext/mne_doc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

import functools
import gc
import os
import time
Expand All @@ -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,
)
Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions examples/visualization/eyetracking_plot_heatmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down
39 changes: 21 additions & 18 deletions mne/viz/ui_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import re
import weakref
from dataclasses import dataclass
from functools import partial

from matplotlib.colors import Colormap

Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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.<locals>.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()
Loading
Loading