cannot plot into matplotlib subfigure

未关闭
#14,481 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@ishaaaan17 已经在做这个了。

开始于 2026年11月3日。

  • #14485 来自 @ishaaaan17 —— 未关闭

评估

难度
3/5
预计耗时
1-2 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
python

调研方向

The failure comes from _get_event_channel in mne/viz/ui_events.py, which runs a _validate_type check in mne/utils/check.py that accepts only Figure, Brain or EvokedField. Reproduce with the snippet in the issue, then read how plot_evoked in mne/viz/evoked.py passes the figure to subscribe. Pull request #14485 is already open against this issue, so review it before starting. Done means evoked.plot(axes=ax) works on an axes inside a SubFigure and the existing viz tests still pass.

由索引模型根据 Issue 内容生成。

描述

BUG
Description of the problem

evoked.plot() cannot plot into an axes within a matplotlib subfigure

Steps to reproduce
import matplotlib.pyplot as plt
import mne
import numpy as np

info = mne.create_info(["EEG1", "EEG2", "EEG3"], sfreq=100.0, ch_types="eeg")
data = np.zeros((3, 100))
evoked = mne.EvokedArray(data, info)

fig = plt.figure(layout="constrained")
subfig = fig.subfigures(1, 2)[0]
ax = subfig.subplots()
evoked.plot(axes=ax)
# TypeError: fig must be an instance of Figure, Brain, or EvokedField, got <class 'matplotlib.figure.SubFigure'> instead.
Link to data

used synthetic data, see above

Expected results

can plot into subfigure axes

Actual results

TypeError: fig must be an instance of Figure, Brain, or EvokedField, got <class 'matplotlib.figure.SubFigure'> instead.

full traceback
---------------------------------------------------------------------
TypeError                           Traceback (most recent call last)
Cell In[5], line 4
      2 subfig = fig.subfigures(1, 2)[0]
      3 ax = subfig.subplots()
----> 4 evoked.plot(axes=ax)

File /opt/mne/python/mne/evoked.py:889, in Evoked.plot(self, picks, exclude, unit, show, ylim, xlim, proj, hline, units, scalings, titles, axes, gfp, window_title, spatial_colors, zorder, selectable, noise_cov, time_unit, sphere, highlight, verbose)
    695 """Plot evoked data using butterfly plots.
    696 
    697 Left click to a line shows the channel name. Selecting an area by clicking
   (...)    885 .. versionadded:: 1.13.0
    886 """  # noqa: E501
    887 from .viz import plot_evoked
--> 889 return plot_evoked(
    890     self,
    891     picks=picks,
    892     exclude=exclude,
    893     unit=unit,
    894     show=show,
    895     ylim=ylim,
    896     proj=proj,
    897     xlim=xlim,
    898     hline=hline,
    899     units=units,
    900     scalings=scalings,
    901     titles=titles,
    902     axes=axes,
    903     gfp=gfp,
    904     window_title=window_title,
    905     spatial_colors=spatial_colors,
    906     zorder=zorder,
    907     selectable=selectable,
    908     noise_cov=noise_cov,
    909     time_unit=time_unit,
    910     sphere=sphere,
    911     highlight=highlight,
    912     verbose=verbose,
    913 )

File <decorator-gen-154>:12, in plot_evoked(evoked, picks, exclude, unit, show, ylim, xlim, proj, hline, units, scalings, titles, axes, gfp, window_title, spatial_colors, zorder, selectable, noise_cov, time_unit, sphere, highlight, verbose)

File /opt/mne/python/mne/viz/evoked.py:1269, in plot_evoked(evoked, picks, exclude, unit, show, ylim, xlim, proj, hline, units, scalings, titles, axes, gfp, window_title, spatial_colors, zorder, selectable, noise_cov, time_unit, sphere, highlight, verbose)
   1041 @verbose_static(
   1042     "picks_all",
   1043     "evoked_ylim_plot",
   (...)   1073     verbose=None,
   1074 ):
   1075     """Plot evoked data using butterfly plots.
   1076 
   1077     Left click to a line shows the channel name. Selecting an area by clicking
   (...)   1267     .. versionadded:: 1.13.0
   1268     """  # noqa: E501
-> 1269     return _plot_evoked(
   1270         evoked=evoked,
   1271         picks=picks,
   1272         exclude=exclude,
   1273         unit=unit,
   1274         show=show,
   1275         ylim=ylim,
   1276         proj=proj,
   1277         xlim=xlim,
   1278         hline=hline,
   1279         units=units,
   1280         scalings=scalings,
   1281         titles=titles,
   1282         axes=axes,
   1283         plot_type="butterfly",
   1284         gfp=gfp,
   1285         window_title=window_title,
   1286         spatial_colors=spatial_colors,
   1287         selectable=selectable,
   1288         zorder=zorder,
   1289         noise_cov=noise_cov,
   1290         time_unit=time_unit,
   1291         sphere=sphere,
   1292         highlight=highlight,
   1293     )

File /opt/mne/python/mne/viz/evoked.py:467, in _plot_evoked(evoked, picks, exclude, unit, show, ylim, proj, xlim, hline, units, scalings, titles, axes, plot_type, cmap, gfp, window_title, spatial_colors, selectable, zorder, noise_cov, colorbar, mask, mask_style, mask_cmap, mask_alpha, time_unit, show_names, group_by, sphere, highlight, draw)
    464     evoked = evoked.reconstruct_proj(origin=sphere[:3])
    466 if plot_type == "butterfly":
--> 467     _plot_lines(
    468         evoked.data,
    469         info,
    470         picks,
    471         fig,
    472         axes,
    473         spatial_colors,
    474         unit,
    475         units,
    476         scalings,
    477         hline,
    478         gfp,
    479         types,
    480         zorder,
    481         xlim,
    482         ylim,
    483         times,
    484         bad_ch_idx,
    485         titles,
    486         ch_types_used,
    487         selectable,
    488         False,
    489         line_alpha=1.0,
    490         nave=evoked.nave,
    491         time_unit=time_unit,
    492         sphere=sphere,
    493         highlight=highlight,
    494     )
    495     plt.setp(axes, xlabel=f"Time ({time_unit})")
    497 elif plot_type == "image":

File /opt/mne/python/mne/viz/evoked.py:917, in _plot_lines(data, info, picks, fig, axes, spatial_colors, unit, units, scalings, hline, gfp, types, zorder, xlim, ylim, times, bad_ch_idx, titles, ch_types_used, selectable, psd, line_alpha, nave, time_unit, sphere, highlight, linewidth, label_props)
    914             line.set_xdata([event.time, event.time])
    915     blit_manager.update()
--> 917 subscribe(fig, "time_change", on_time_change)
    919 return lines

File <decorator-gen-140>:12, in subscribe(fig, event_name, callback, verbose)

File /opt/mne/python/mne/viz/ui_events.py:447, in subscribe(fig, event_name, callback, verbose)
    424 @verbose_static()
    425 def subscribe(fig, event_name, callback, *, verbose=None):
    426     """Subscribe to an event on a figure's event channel.
    427 
    428     Parameters
   (...)    445     is published.
    446     """
--> 447     channel = _get_event_channel(fig)
    448     logger.debug(f"Subscribing to channel {channel}")
    449     if event_name not in channel:

File /opt/mne/python/mne/viz/ui_events.py:368, in _get_event_channel(fig)
    360 weakfig = weakref.ref(fig)
    362 # When the figure is closed, its associated event channel should be
    363 # deleted. This is a good time to set this up.
    364 
    365 # Hook up the above callback function to the close event of the figure
    366 # window. How this is done exactly depends on the various figure types
    367 # MNE-Python has.
--> 368 _validate_type(fig, (matplotlib.figure.Figure, Brain, EvokedField), "fig")
    369 this_delete_event_channel = partial(_delete_event_channel, weakfig=weakfig)
    370 if isinstance(fig, matplotlib.figure.Figure):

File /opt/mne/python/mne/utils/check.py:709, in _validate_type(item, types, item_name, type_name, extra)
    707 _item_name = "Item" if item_name is None else item_name
    708 _item_type = type(item) if item is not None else item
--> 709 raise TypeError(
    710     f"{_item_name} must be an instance of {type_name}{extra}, "
    711     f"got {_item_type} instead."
    712 )

TypeError: fig must be an instance of Figure, Brain, or EvokedField, got <class 'matplotlib.figure.SubFigure'> instead.
Additional information

Platform Linux-7.0.0-38-generic-x86_64-with-glibc2.43 (X11)
Python 3.14.10 | packaged by conda-forge | (main, Oct 26 2026, 11:35:38) [GCC 15.3.0]
Executable /opt/mne/pixi/.pixi/envs/default/bin/python3.14
CPU Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz (16 cores)
Memory 125.7 GiB

Core
├☑ mne 1.14.0.dev121+gf3e0db815 (development, latest release is 1.13.2)
├☑ numpy 2.5.3 (OpenBLAS 0.3.34 with 4 threads via pthreads)
├☑ scipy 1.17.1
└☑ matplotlib 3.11.1 (backend=qtagg)

Numerical (optional)
├☑ scikit-learn 1.9.1
├☑ threadpoolctl 3.6.0
├☑ numba 0.67.0
├☑ nibabel 5.4.2
├☑ nilearn 0.14.1
├☑ dipy 1.12.1
├☑ openmeeg 2.5.16
├☑ jamica 0.3.0
├☑ cupy 14.2.0
├☑ pandas 3.0.5
├☑ h5io 0.2.5
├☑ h5py 3.16.0
└☐ unavailable python-picard

Visualization (optional)
├☑ pyvista 0.48.4 (OpenGL 4.5.0 NVIDIA 595.99.02 via NVIDIA GeForce RTX 2060/PCIe/SSE2)
├☑ pyvistaqt 0.13.1
├☑ vtk 9.6.2
├☑ qtpy 2.4.3 (PySide6=6.11.2)
├☑ ipympl 0.10.0
├☑ pyqtgraph 0.14.0
├☑ mne-qt-browser 0.8.0.dev12+g34026bf8e
├☑ ipywidgets 8.1.9
├☑ trame 3.13.2
├☑ trame_client 3.13.2
├☑ trame_server 3.12.5
├☑ trame_pyvista 0.1.7
├☑ trame_vtk 2.11.16
└☑ trame_vuetify 3.2.5

Ecosystem (optional)
├☑ mne-bids 0.21.0.dev6+gcd32e35ff
├☑ mne-nirs 0.8.0.dev17+g1a3ede196
├☑ mne-connectivity 0.10.0.dev45+g03495d310
├☑ mne-icalabel 0.9.0
├☑ mne-bids-pipeline 1.11.0.dev86+ge2a34cf44.d20261020
├☑ autoreject 0.5.0
├☑ neo 0.14.5
├☑ eeglabio 0.1.3
├☑ edfio 0.4.17.dev4+g74788f24c
├☑ curryreader 0.1.2
├☑ mffpy 0.11.0
├☑ pybv 0.8.1
├☑ pymef 1.4.8
├☑ antio 0.7.1
├☑ defusedxml 0.7.1
└☐ unavailable mne-features

主要语言
Python
星标
3.6k
派生
1.6k
平均合并
1 天 18 小时
30 天内合并 PR
74

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

mne-tools/mne-python 的其他 Issue

查看 mne-tools/mne-python 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。