Repository: mne-tools/mne-python

Issue:
Option to scroll in smaller increments
It would be nice to be able to scroll `raw.plot` in smaller increments than a whole page. Currently, this doesn't seem to be possible. The right and left arrow keys scroll right/left by a whole page. Is it possible to map e.g. Shift+right/Shift+left to scrolling right/left by e.g. only 1/10 of a page?


Discussion:
+2.5, I wanted that pretty often too. Maybe ctrl + arrow (it would actually be more intuitive if simple arrow keypresses had smaller increments than ctrl + arrow, but that would not be convenient)?
I'd rather not change the current behavior. Ctrl+Arrow is problematic on Macs because this shortcut is associated with switching desktops, so I'd prefer Shift+Arrow. The interesting thing would be if Matplotlib supports shortcuts consisting of more than one keystroke...
no objection as long as it works on all platforms and it's documented

In my UI experience, shift+arrow being "take larger steps" is common. One way we could make it more uniform would be to have some `time_delta`-like argument that is expressed in units of `duration`, the default thus being `1`. You could use `0.1` for your use case (meaning, move 10% of the window duration each arrow press). shift+arrow could then be mapped to e.g. 5x whatever the standard increment is, more in line with how other software treats shift+arrow.
Yeah, I like this idea. Should I start with a PR?
I'd even go through a deprecation cycle to change the default to e.g. 25% or 50%. This is also more similar to what EEGLAB does (AFAIK EEGLAB takes 1/10 steps with each arrow press and a full step with some key combination).
For viz functions and interactions we're usually a bit more lenient on the deprecation cycle. +1 for change to 25% from me
Hmmm, Matplotlib doesn't seem to pick up the shift key as a modifier. Ctrl or command works, but when I press shift+right it only registers as right. Any ideas on how to proceed?
From very brief reading/searching it looks like `shift` is treated like a normal key not a modifier, so we can track the state internally, similar to this

https://stackoverflow.com/questions/18141069/matplotlib-how-to-pick-up-shift-click-on-figure
Unfortunately this doesn't work. Shift isn't registered at all. Also, even if it was registered, I probably couldn't combine it with another key (the SO example is combining shift with a mouse event).
Works for me, what backend are you on?
```
>>> fig = plt.figure()
>>> def on_key(event):
...     print('you pressed', event.key, event.xdata, event.ydata)
>>> fig.canvas.mpl_connect('key_press_event', on_key)
>>> def off_key(event):
...     print('you released', event.key, event.xdata, event.ydata)
>>> fig.canvas.mpl_connect('key_release_event', off_key)
you pressed shift None None
you pressed A None None
you released A None None
you released shift None None
```
Ah - it doesn't work with `osx`, but `qt5` works! Cool, I think we can live with that, another reason to always switch to the `qt5` backend. PR incoming.

Resolving patch:
diff --git a/mne/viz/raw.py b/mne/viz/raw.py
--- a/mne/viz/raw.py
+++ b/mne/viz/raw.py
@@ -213,11 +213,13 @@ def plot_raw(raw, events=None, duration=10.0, start=0.0, n_channels=20,
     The arrow keys (up/down/left/right) can typically be used to navigate
     between channels and time ranges, but this depends on the backend
     matplotlib is configured to use (e.g., mpl.use('TkAgg') should work). The
-    scaling can be adjusted with - and + (or =) keys. The viewport dimensions
-    can be adjusted with page up/page down and home/end keys. Full screen mode
-    can be to toggled with f11 key. To mark or un-mark a channel as bad, click
-    on the rather flat segments of a channel's time series. The changes will be
-    reflected immediately in the raw object's ``raw.info['bads']`` entry.
+    left/right arrows will scroll by 25% of ``duration``, whereas
+    shift+left/shift+right will scroll by 100% of ``duration``. The scaling can
+    be adjusted with - and + (or =) keys. The viewport dimensions can be
+    adjusted with page up/page down and home/end keys. Full screen mode can be
+    toggled with the F11 key. To mark or un-mark a channel as bad, click on a
+    channel label or a channel trace. The changes will be reflected immediately
+    in the raw object's ``raw.info['bads']`` entry.
 
     If projectors are present, a button labelled "Proj" in the lower right
     corner of the plot window opens a secondary control window, which allows
diff --git a/mne/viz/utils.py b/mne/viz/utils.py
--- a/mne/viz/utils.py
+++ b/mne/viz/utils.py
@@ -726,11 +726,21 @@ def _plot_raw_onkey(event, params):
         params['ch_start'] -= params['n_channels']
         _channels_changed(params, len(params['inds']))
     elif event.key == 'right':
+        value = params['t_start'] + params['duration'] / 4
+        _plot_raw_time(value, params)
+        params['update_fun']()
+        params['plot_fun']()
+    elif event.key == 'shift+right':
         value = params['t_start'] + params['duration']
         _plot_raw_time(value, params)
         params['update_fun']()
         params['plot_fun']()
     elif event.key == 'left':
+        value = params['t_start'] - params['duration'] / 4
+        _plot_raw_time(value, params)
+        params['update_fun']()
+        params['plot_fun']()
+    elif event.key == 'shift+left':
         value = params['t_start'] - params['duration']
         _plot_raw_time(value, params)
         params['update_fun']()


Test patch: