From 549b77673073e00699b07915f6677c7b51fd3b79 Mon Sep 17 00:00:00 2001 From: Gnefil Date: Sun, 5 Jul 2026 00:35:01 +0800 Subject: [PATCH 1/7] ENH: add vertical marker in plot evoked that listens to timechange --- mne/viz/evoked.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 63aca378b59..b48ff42bf15 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -46,6 +46,7 @@ _set_contour_locator, plot_topomap, ) +from .ui_events import subscribe from .utils import ( DraggableColorbar, _check_cov, @@ -849,6 +850,17 @@ def _plot_lines( props=dict(alpha=0.5, facecolor="red"), ) + def on_time_change(event): + """Respond to a time change UI event.""" + for ax in np.array(axes)[selectables]: + if hasattr(ax, "_selectline") and ax._selectline is not None: + ax._selectline.remove() + + ax._selectline = ax.axvline(event.time, color="black", alpha=1) + ax.figure.canvas.draw() + + subscribe(fig, "time_change", on_time_change) + def _add_nave(ax, nave): """Add nave to axes.""" From 6a8101a5b764dd0925125c68bed45cd7bd10d569 Mon Sep 17 00:00:00 2001 From: Gnefil Date: Tue, 7 Jul 2026 13:30:59 +0800 Subject: [PATCH 2/7] ENH: Implement test for plot evoked timechange subscriber --- mne/viz/tests/test_evoked.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 5335f163bad..081600c9bc1 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -28,7 +28,7 @@ from mne.io import read_raw_fif from mne.stats.parametric import _parametric_ci from mne.utils import _record_warnings, catch_logging -from mne.viz import plot_compare_evokeds, plot_evoked_white +from mne.viz import plot_compare_evokeds, plot_evoked_white, ui_events from mne.viz.utils import _fake_click, _get_cmap base_dir = Path(__file__).parents[2] / "io" / "tests" / "data" @@ -230,6 +230,23 @@ def test_plot_evoked(): assert not np.all(np.isnan(line_clr) & (line_clr == 0)) +def test_plot_evoked_timechange(): + """Test that time change events are properly handled in plot_evoked.""" + epochs = _get_epochs() + evoked = epochs.average() + fig = evoked.plot(picks="mag") + ax = fig.axes[0] + + assert not hasattr(ax, "_selectline") + ui_events.publish(fig, ui_events.TimeChange(time=0.0)) + assert hasattr(ax, "_selectline") + assert ax._selectline.get_xdata()[0] == 0.0 + ui_events.publish(fig, ui_events.TimeChange(time=0.1)) + assert ax._selectline.get_xdata()[0] == 0.1 + + plt.close("all") + + def test_constrained_layout(): """Test that we handle constrained layouts correctly.""" fig, ax = plt.subplots(1, 1, layout="constrained") From b0d9e29c471611dd229f3bffdc108a5ccde5237b Mon Sep 17 00:00:00 2001 From: Gnefil Date: Tue, 7 Jul 2026 13:39:32 +0800 Subject: [PATCH 3/7] ENH: Document timechange listening behaviour --- mne/viz/evoked.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index b48ff42bf15..bcd29ed2594 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1123,6 +1123,14 @@ def plot_evoked( fig : instance of matplotlib.figure.Figure Figure containing the butterfly plots. + Notes + ----- + The figure will subscribe to the following UI events: + + * :class:`~mne.viz.ui_events.TimeChange` + + .. versionadded:: 1.13.0 + See Also -------- mne.viz.plot_evoked_white From 41933f527de7eb31b88c510fe5ddf5bfb9190df6 Mon Sep 17 00:00:00 2001 From: Gnefil Date: Tue, 7 Jul 2026 13:54:27 +0800 Subject: [PATCH 4/7] ENH: include non-selectable channels and improve logic --- mne/viz/evoked.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index bcd29ed2594..02467b35e7d 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -852,12 +852,12 @@ def _plot_lines( def on_time_change(event): """Respond to a time change UI event.""" - for ax in np.array(axes)[selectables]: - if hasattr(ax, "_selectline") and ax._selectline is not None: + for ax in np.array(axes): + if getattr(ax, "_selectline", None) is not None: ax._selectline.remove() ax._selectline = ax.axvline(event.time, color="black", alpha=1) - ax.figure.canvas.draw() + ax.figure.canvas.draw() subscribe(fig, "time_change", on_time_change) From 6029f36c8b1cd9f078ba48130681f7dfafa293fa Mon Sep 17 00:00:00 2001 From: Gnefil Date: Tue, 7 Jul 2026 15:24:03 +0800 Subject: [PATCH 5/7] BUG: Fix empty click after span select bug --- mne/viz/evoked.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 02467b35e7d..f2a945a7491 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -133,6 +133,8 @@ def _line_plot_onselect( ch_types = [type_ for type_ in ch_types if type_ in ("eeg", "grad", "mag")] if len(ch_types) == 0: raise ValueError("Interactive topomaps only allowed for EEG and MEG channels.") + if xmin == xmax: + return if ( "grad" in ch_types and len(_pair_grad_sensors(info, topomap_coords=False, raise_error=False)) < 2 From f8b7524c5dd87b818f1700ce3e54cb717929e230 Mon Sep 17 00:00:00 2001 From: Gnefil Date: Tue, 7 Jul 2026 15:27:44 +0800 Subject: [PATCH 6/7] ENH: add publish timechange behaviour to plot_evoked --- mne/viz/evoked.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index f2a945a7491..7dab4a33633 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -46,7 +46,7 @@ _set_contour_locator, plot_topomap, ) -from .ui_events import subscribe +from .ui_events import TimeChange, publish, subscribe from .utils import ( DraggableColorbar, _check_cov, @@ -112,6 +112,8 @@ def _butterfly_on_button_press(event, params): event.canvas.draw() params["need_draw"] = False + publish(params["axes"][0].figure, TimeChange(event.xdata)) + def _line_plot_onselect( xmin, @@ -133,6 +135,7 @@ def _line_plot_onselect( ch_types = [type_ for type_ in ch_types if type_ in ("eeg", "grad", "mag")] if len(ch_types) == 0: raise ValueError("Interactive topomaps only allowed for EEG and MEG channels.") + # if xmin == xmax: return if ( From d695aa363ee550f41021a19cacbd5d9baf411d54 Mon Sep 17 00:00:00 2001 From: Gnefil Date: Tue, 7 Jul 2026 15:36:34 +0800 Subject: [PATCH 7/7] BUG: Fix spatial colors not defaulted to auto bug --- mne/viz/evoked.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 7dab4a33633..43cf00b0888 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1003,7 +1003,7 @@ def plot_evoked( axes=None, gfp=False, window_title=None, - spatial_colors=False, + spatial_colors="auto", zorder="unsorted", selectable=True, noise_cov=None,