MNE/Matplotlib Visualization causes EasyGUI-QT to Crash

I’m facing an issue combining mne, matplotlib and easygui-qt and I’m not sure how to find out where the issue is exactly.

I’m trying to show the user an mne-generated figure (preferably interactive) and an easygui-qt-generated modal (see example below). I want the user to be able to play with the figure as much as they want, and eventually click provide input through the pop-up modal. Problem is, when generating the figure, matplotlib turns on interactive mode, which for some reason causes easygui-qt to crash.

For example, in the following code, no matter how I tried to turn off the interactive mode or prevent the figure from being rendered (see the # comments), the input2 line causes the script to crash as soon as the user provides an input (i.e., after clicking one of the buttons), and never reaches the print line.

import matplotlib
import mne
from mne.datasets import sample
from mne.io import read_raw_fif
import easygui_qt.easygui_qt as gui
import matplotlib.pyplot as plt

matplotlib.use('Qt5Agg')
mne.viz.set_browser_backend('qt')   # or "matplotlib"


fname = sample.data_path() / "MEG" / "sample" / "sample_audvis_raw.fif"
raw = read_raw_fif(fname, preload=False, verbose=False)
raw.crop(0, 60).pick("eeg")
raw.load_data(verbose=False)

input1 = gui.get_continue_or_cancel(title="Input 1", message="", continue_button_text="T", cancel_button_text="F")
fig = raw.plot(verbose=False, show=True)    # can set show=False with same downstream effect
# plt.ioff()                        # this has no effect
# matplotlib.interactive(False)     # this has no effect
input2 = gui.get_continue_or_cancel(title="Input 2", message="", continue_button_text="T", cancel_button_text="F")
print(f"In 1: {input1}\t\tIn 2: {input2}")

Thanks for the help :slight_smile:

Package versions:

matplotlib:3.8.4
PyQt5: 5.15.11
easygui-qt: 0.9.3
mne: 1.9.0
mne-qt-browser: 0.6.3

And other system info:

>>> mne.sys_info()
Platform             Windows-11-10.0.26100-SP0
Python               3.12.3 (tags/v3.12.3:f6650f9, Apr  9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)]
Executable           C:\Path\To\venv\Scripts\python.exe
CPU                  13th Gen Intel(R) Core(TM) i7-13700 (24 cores)
Memory               63.7 GiB
Core
 + mne               1.9.0 (latest release)
 + numpy             2.1.1 (OpenBLAS 0.3.27 with 24 threads)
 + scipy             1.15.1
 + matplotlib        3.8.4Backend QtAgg is interactive backend. Turning interactive mode on.
 (backend=QtAgg)
Numerical (optional)
 + sklearn           1.6.1
 + pandas            2.2.3
 + h5py              3.12.1
 - unavailable       numba, nibabel, nilearn, dipy, openmeeg, cupy, h5io
Visualization (optional)
 + qtpy              2.4.3 (PyQt6=6.8.2)
 + pyqtgraph         0.13.7
 + mne-qt-browser    0.6.3
 - unavailable       pyvista, pyvistaqt, vtk, ipympl, ipywidgets, trame_client, trame_server, trame_vtk, trame_vuetify
Ecosystem (optional)
 + mne-icalabel      0.7.0
 - unavailable       mne-bids, mne-nirs, mne-features, mne-connectivity, mne-bids-pipeline, neo, eeglabio, edfio, mffpy, pybv
1 Like

matplotlib’s interactive mode will create a QT event loop (or use ipython’s QT event loop). What is probably the issue is that easygui_qt tries to create their own QT event loop. You cannot have two such loops at the same time. The solution here would be for easygui_qt to use one of the already existing ones.

Are you aiming to run this inside ipython or as a standalone python script?

So the code I provided is just a minimally working example. I’m trying to write an ICA function that I could plug into existing pipeline(s) in my lab, and the GUI part is to have user inputs on the ICA algorithm, hyper-params, etc.
Details don’t matter, this is just to say that in my final implementation I plan to have a function (run_ica()) that can be called from whichever platform the user runs their pipeline on - a CLI, a Jupyter Notebook, PyCharm’s internal console… Hope that answers your question @wmvanvliet

try the %gui qt magic command.

I’m sorry, can you elaborate? try when?

in an ipython console: Built-in magic commands — IPython 9.1.0 documentation