Skip to content

Commit 6f04dcb

Browse files
cbrnrlarsoner
andauthored
Add support for mouse wheel scrolling in raw.plot() (mne-tools#13988)
Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
1 parent e41f6c6 commit 6f04dcb

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add mouse wheel scrolling support to the ``'matplotlib'`` browser backend to navigate through channels, by `Clemens Brunner`_.

mne/viz/_mpl_figure.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ def _buttonpress(self, event):
220220
"""Handle buttonpress events."""
221221
pass
222222

223+
def _scroll(self, event):
224+
"""Handle scroll wheel events."""
225+
pass
226+
223227
def _pick(self, event):
224228
"""Handle matplotlib pick events."""
225229
pass
@@ -241,6 +245,7 @@ def _add_default_callbacks(self, **kwargs):
241245
resize_event=self._resize,
242246
key_press_event=self._keypress,
243247
button_press_event=self._buttonpress,
248+
scroll_event=self._scroll,
244249
close_event=self._close,
245250
pick_event=self._pick,
246251
)
@@ -958,6 +963,20 @@ def _buttonpress(self, event):
958963
elif event.inaxes == ax_main:
959964
self._toggle_vline(False)
960965

966+
def _scroll(self, event):
967+
"""Handle scroll wheel events for channel navigation."""
968+
if self.mne.butterfly or self.mne.fig_selection is not None:
969+
return
970+
direction = -1 if event.button == "up" else 1
971+
ceiling = len(self.mne.ch_order) - self.mne.n_channels
972+
old_start = self.mne.ch_start
973+
self.mne.ch_start = np.clip(self.mne.ch_start + direction, 0, ceiling)
974+
if self.mne.ch_start == old_start:
975+
return
976+
self._update_picks()
977+
self._update_vscroll()
978+
self._redraw()
979+
961980
def _pick(self, event):
962981
"""Handle matplotlib pick events."""
963982
from matplotlib.text import Text
@@ -1111,6 +1130,7 @@ def _get_help_text(self):
11111130
("?", "Open this help window"),
11121131
("esc", "Close focused figure or dialog window"),
11131132
("_MOUSE INTERACTION", " "),
1133+
("Scroll wheel", "Scroll channels up/down"),
11141134
(f"Left-click {ch_cmp} name", lclick_name),
11151135
(f"Left-click {ch_cmp} data", lclick_data),
11161136
("Left-click-and-drag on plot", ldrag),

mne/viz/tests/test_raw.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,32 @@ def test_plot_raw_keypresses(raw, browser_backend):
589589
fig._fake_keypress(key)
590590

591591

592+
def test_plot_raw_scroll(raw, browser_backend):
593+
"""Test scroll wheel channel navigation in raw.plot()."""
594+
with raw.info._unlock():
595+
raw.info["lowpass"] = 10.0
596+
# use n_channels < total so there is room to scroll
597+
fig = raw.plot(n_channels=3)
598+
assert len(fig.mne.ch_order) > fig.mne.n_channels # sanity check
599+
# the sign of "step" that means "scroll down" differs between backends
600+
down, up = (-1, 1) if browser_backend.name == "matplotlib" else (1, -1)
601+
# scroll down moves ch_start forward by 1
602+
ch_start_before = fig.mne.ch_start
603+
fig._fake_scroll(0.5, 0.5, down)
604+
assert fig.mne.ch_start == ch_start_before + 1
605+
# scroll up moves ch_start back by 1
606+
fig._fake_scroll(0.5, 0.5, up)
607+
assert fig.mne.ch_start == ch_start_before
608+
# scroll up at the top is a no-op (already at 0)
609+
assert fig.mne.ch_start == 0
610+
fig._fake_scroll(0.5, 0.5, up)
611+
assert fig.mne.ch_start == 0
612+
# scroll is a no-op in butterfly mode
613+
fig._fake_keypress("b")
614+
fig._fake_scroll(0.5, 0.5, down)
615+
assert fig.mne.ch_start == 0
616+
617+
592618
def test_plot_raw_traces(raw, events, browser_backend):
593619
"""Test plotting of raw data."""
594620
ismpl = browser_backend.name == "matplotlib"

0 commit comments

Comments
 (0)