Repository navigation
Description
Description of the problem
When using Evoked.plot() (assigning it to a figure handle) and then trying to export from that figure handle to a vector graphic (SVG, EPS or PDF), I get error messages like the one below (one for each axis / plot in the figure). Exporting as PNG works fine. Apparently, there seems to be a missing attribute copy_from_bbox.
Traceback (most recent call last):
File "/opt/Software4EEG/MNE/lib/python3.12/site-packages/matplotlib/cbook.py", line 361, in process
func(*args, **kwargs)
File "/opt/Software4EEG/MNE/lib/python3.12/site-packages/matplotlib/widgets.py", line 2167, in update_background
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'FigureCanvasSVG' object has no attribute 'copy_from_bbox'
Steps to reproduce
Use the code and the data from https://mne.tools/stable/auto_examples/visualization/channel_epochs_image.html (up to where epochs is created). Afterwards, use:
fig = epochs.average().plot()
fig.savefig('Trial.svg')
The error thrown after calling the last command.
fig.savefig('Trial.png') works without any problem, i.e., it is not a problem with generating the plot itself.Link to data
See above. But I assume, it would produce the error whenever one assigns Evoked.plot() to a figure handle and then tries to save a vector graphics (that requires a bounding box).
Expected results
Export of the figure without any error messages.
Additional information: It appears as if in some cases the exported figures can be read by Inkscape, in other cases they seem to contain mistakes and Inkscape crashes. I could not determine yet, why the exported figures sometimes seems to have valid format.
Actual results
Export of the figure with an error message.
Resulting SVG-files work sometimes, but not always.
Additional information
Platform Linux-6.11.0-21-generic-x86_64-with-glibc2.39
Python 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0]
Executable /opt/Software4EEG/MNE/bin/python
CPU Intel(R) Core(TM) Ultra 5 135U (14 cores)
Memory 30.8 GiB
Core
├☑ mne 1.9.0 (latest release)
├☑ numpy 2.2.4 (OpenBLAS 0.3.28 with 14 threads)
├☑ scipy 1.15.2
└☑ matplotlib 3.10.1 (backend=qtagg)
Numerical (optional)
├☑ sklearn 1.6.1
├☑ h5io 0.2.4
├☑ h5py 3.13.0
└☐ unavailable numba, nibabel, nilearn, dipy, openmeeg, cupy, pandas
Visualization (optional)
├☑ qtpy 2.4.3 (PySide6=6.9.0)
├☑ pyqtgraph 0.13.7
├☑ mne-qt-browser 0.7.1
└☐ unavailable pyvista, pyvistaqt, vtk, ipympl, ipywidgets, trame_client, trame_server, trame_vtk, trame_vuetify
Ecosystem (optional)
├☑ mne-bids 0.16.0
├☑ mne-icalabel 0.7.0
├☑ edfio 0.4.8
├☑ pybv 0.7.6
└☐ unavailable mne-nirs, mne-features, mne-connectivity, mne-bids-pipeline, neo, eeglabio, mffpy
Activity
agramfort commentedon May 11, 2025
AasmaGupta commentedon Aug 5, 2025
Hey, I'd like to work on this issue. Can you assign me this?
drammock commentedon Aug 5, 2025
@AasmaGupta you are welcome to work on it. Before I assign you though, can you do as @agramfort suggested to isolate whether the bug is actually in MNE-Python or in matplotlib? If it's a matplotlib problem there's nothing further to be done in this repo.
AasmaGupta commentedon Aug 5, 2025
@drammock I tested this as suggested:
Plain Matplotlib plotting and saving (SVG/PDF) works fine.
MNE plotting with evoked.plot() fails on fig.savefig() with:
AttributeError: 'FigureCanvasSVG' object has no attribute 'copy_from_bbox'
AttributeError: 'FigureCanvasPdf' object has no attribute 'copy_from_bbox'
This confirms the issue is specific to MNE’s plotting/export logic and not Matplotlib itself. I think you can assign me this then.
larsoner commentedon Aug 7, 2025
When you say this, did you just create some plain
matplotlibfigure, or did you follow the advice from #13242 (comment) ? The advice there suggests to start with our code copy-pasted and trim it down. The reason for this is that we will probably end up with a minimal bit of code that causes the problem. I don't think we do anything fancy, it's probably "just" a matter of having the correct matplotlib calls and objects in the correct state to cause the issue, and if you only create a vanilla plot it might not have the right complexity/matplotlib calls to cause the problem.AasmaGupta commentedon Aug 11, 2025
@larsoner Got it, thanks for clarifying. I initially only tested with a vanilla matplotlib plot, but I’ll now follow your advice — copy the MNE plotting code from evoked.plot(), and trim it down until I have a minimal reproducible snippet that still causes the error. I’ll let you know soon!
AasmaGupta commentedon Aug 11, 2025
Hi @larsoner ,
After testing, I can confirm this issue is not caused by Matplotlib itself. Plain Matplotlib plots save as SVG and PDF without any errors.
The error message:
AttributeError: 'FigureCanvasSVG' object has no attribute 'copy_from_bbox'occurs only when using MNE’s plotting functions (e.g., evoked.plot()) or code derived from them. This indicates the problem lies in MNE’s plotting/export logic and its interaction with specific Matplotlib backends.
From what I understand, this is likely due to interactive features or widget callbacks in MNE that depend on
copy_from_bbox, which is not available on non-interactive backends, such as SVG or PDF. Such backends don’t support some interactive optimizations, causing this attribute error during save.Following the suggestion to isolate the problem, I’m working on creating a minimal reproducible example that uses MNE plotting code and still triggers this error. Please let me know if you would like me to proceed or if there are any specific steps you would like me to take next to isolate the issue with MNE’s plotting code.
Thanks!
AasmaGupta commentedon Aug 20, 2025
Hi @larsoner,
I trimmed down from the MNE plotting code itself and ended up with this reproducible snippet (all directly from the codebase, no external dataset needed):
This always raises:
AttributeError: 'FigureCanvasSVG' object has no attribute 'copy_from_bbox'Let me know if this is what you needed, and what you’d like me to do next.
Thanks!
larsoner commentedon Aug 20, 2025
Okay next:
mne.vizfunctions (i.e., any functions you need should all be copied into the script, and the only remainingmne.calls/imports aremne.create_infoandmne.EvokedArray)FigureCanvasSVGerror (i.e., have copied all the code into the script correctly)FigureCanvasSVGerror still occurs when you trysavefig.FigureCanvasSVGerrormne.calls completely, i.e., reduce it tomatplotlibandnumpycallsAasmaGupta commentedon Aug 28, 2025
Hey @larsoner
I followed all the steps mentioned and I came up with the smallest snippet of code possible that still produces the following error:
Also, I have completely removed all the
mne.calls and reduced it tomatplotlibandnumpycalls.Let me know to proceed or if any other changes are to be done!
(ps. this was very fun to do ;)
Following is the code:
larsoner commentedon Aug 28, 2025
I think it can be reduced further... for example
_picks_to_idxcan be replaced just bynp.arange(len(data)). Remove conditionals likeif plot_type == "butterfly", it is in your reproducible example so you don't need the conditional.Can you remove the
SpanSelectorentirely and still have it fail tosavefigproperly?Can you remove all of the
ch_types_usedstuff and assume there is just one channel type (there is, EEG)?Can you continue simplifying to remove DummyInfo and DummyEvoked and make it operate on ndarrays?
How many
kwargscan you remove from the functions? For examplescalingsis no longer used at all so should be removed.AasmaGupta commentedon Aug 29, 2025
I did further changes and this is what I have come up with:
Only the SpanSelector couldn't be removed entirely, as I think it triggers bbox bug with SVG.
Rest all the
DummyInfo,DummyEvoked,_picks_to_idx, conditionals,ch_types_used, etc have been removed.Let me know if there are any further changes that I can make.
drammock commentedon Aug 29, 2025
It can actually be quite a bit simpler! I still get the error with this:
Not sure if you could trim it even further... I determined that
useblit=Falsemakes the error go away so that's when I stopped trimming.larsoner commentedon Aug 29, 2025
I think that snippet above is good enough to submit to matplotlib as a bug report! @AasmaGupta could you do that at https://github.com/matplotlib/matplotlib/issues ? Closing as this is a pure matplotlib issue!
drammock commentedon Aug 29, 2025
just reported upstream!
AasmaGupta commentedon Aug 29, 2025
I was simplifying the code further and came up with a smaller snippet. Thanks for reporting this issue as a bug further. Yes, this was a pure matplotlib issue! Thanks @larsoner and @drammock for the guidance!