From ed998b2cd79a5b00d09d1ba4178631145e5cf37c Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Thu, 18 Jun 2015 11:53:45 +0300 Subject: [PATCH 01/24] Layout uses pixels instead of inches. --- mne/viz/epochs.py | 5 +++-- mne/viz/utils.py | 19 ++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 525438a1761..4486e73ff57 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -555,8 +555,9 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, fig = figure_nobar(facecolor='w', figsize=size) fig.canvas.set_window_title('mne_browse_epochs') ax = plt.subplot2grid((10, 15), (0, 1), colspan=13, rowspan=9) - ax.annotate(title, xy=(0.5, 1), xytext=(0, ax.get_ylim()[1] + 13), - ha='center', va='bottom', size=10, xycoords='axes fraction', + + ax.annotate(fig_title, xy=(0.5, 1), xytext=(0, ax.get_ylim()[1] + 15), + ha='center', va='bottom', size=12, xycoords='axes fraction', textcoords='offset points') ax.axis([0, duration, 0, 200]) diff --git a/mne/viz/utils.py b/mne/viz/utils.py index c1514cd704e..f778756c928 100644 --- a/mne/viz/utils.py +++ b/mne/viz/utils.py @@ -270,17 +270,14 @@ def _draw_proj_checkbox(event, params, draw_current_state=True): def _layout_figure(params, platform=None): """Aux function for setting figure layout""" - size = params['fig'].get_size_inches() - scroll_width = 0.33 - if platform is None or platform == "linux" or platform == "linux2": - hscroll_dist = 0.33 - else: - hscroll_dist = 0.8 - vscroll_dist = 0.1 - l_border = 1.2 - r_border = 0.1 - t_border = 0.33 - b_border = 0.5 + size = params['fig'].get_size_inches() * params['fig'].dpi + scroll_width = 25 + hscroll_dist = 25 + vscroll_dist = 10 + l_border = 100 + r_border = 10 + t_border = 35 + b_border = 40 # only bother trying to reset layout if it's reasonable to do so if size[0] < 2 * scroll_width or size[1] < 2 * scroll_width + hscroll_dist: From 7d4e87ced3896dc4f31c0eadc5d9b769a0007f53 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Thu, 18 Jun 2015 11:55:57 +0300 Subject: [PATCH 02/24] Removed unused param. --- mne/viz/epochs.py | 3 +-- mne/viz/utils.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 4486e73ff57..81a7498c9bf 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -13,7 +13,6 @@ from collections import deque from functools import partial import copy -from sys import platform import numpy as np @@ -1358,4 +1357,4 @@ def _close_event(event, params): def _resize_event(event, params): """Function to handle resize event""" - _layout_figure(params, platform) + _layout_figure(params) diff --git a/mne/viz/utils.py b/mne/viz/utils.py index f778756c928..57bc42ae443 100644 --- a/mne/viz/utils.py +++ b/mne/viz/utils.py @@ -268,7 +268,7 @@ def _draw_proj_checkbox(event, params, draw_current_state=True): pass -def _layout_figure(params, platform=None): +def _layout_figure(params): """Aux function for setting figure layout""" size = params['fig'].get_size_inches() * params['fig'].dpi scroll_width = 25 From 864fda008cb3214c6c4de969f34ded61cae9ad43 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Sun, 21 Jun 2015 14:22:34 +0300 Subject: [PATCH 03/24] Rebase --- doc/source/whats_new.rst | 5 +++++ mne/viz/epochs.py | 35 +++++++++++++++++++++++++++++++++++ mne/viz/utils.py | 8 +++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/doc/source/whats_new.rst b/doc/source/whats_new.rst index 2d81023b71d..9057dee46cc 100644 --- a/doc/source/whats_new.rst +++ b/doc/source/whats_new.rst @@ -16,6 +16,8 @@ Changelog - Speed up zero-phase overlap-add (default) filtering by a factor of up to 2 using linearity by `Ross Maddox`_ and `Eric Larson`_ + - Add support for scaling and adjusting the number of channels/time per view by `Jaakko Leppakangas`_ + BUG ~~~ @@ -26,8 +28,11 @@ BUG - Fix FFT filter artifacts when using short windows in overlap-add by `Eric Larson`_ +<<<<<<< HEAD - Fix picking channels from forward operator could return a channel ordering different from ``info['chs']`` by `Chris Bailey`_ +======= +>>>>>>> Rebase .. _changes_0_9: Version 0.9 diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 81a7498c9bf..82a264b19fb 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -650,6 +650,11 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, text = ax.text(0, 0, 'blank', zorder=2, verticalalignment='baseline', horizontalalignment='left', fontweight='bold') text.set_visible(False) + + ax_help_button = plt.subplot2grid((10, 15), (0, 14)) + help_button = mpl.widgets.Button(ax_help_button, 'Help') + help_button.on_clicked(_onclick_help) + params = {'fig': fig, 'ax': ax, 'ax2': ax2, @@ -688,6 +693,7 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, 'vertline_t': vertline_t, 'butterfly': False, 'text': text} + 'ax_help_button': ax_help_button} if len(projs) > 0 and not epochs.proj: ax_button = plt.subplot2grid((10, 15), (9, 14)) @@ -1358,3 +1364,32 @@ def _close_event(event, params): def _resize_event(event, params): """Function to handle resize event""" _layout_figure(params) + + +def _onclick_help(event): + """Function for drawing help window""" + import matplotlib.pyplot as plt + text = 'left arrow : Navigate left\n'\ + 'right arrow : Navigate right\n'\ + 'down arrow : Navigate channels down\n'\ + 'up arrow : Navigate channels up\n'\ + '- : Scale down\n'\ + '+ : Scale up\n'\ + '= : Scale up\n'\ + 'home : Reduce the number of epochs per view\n'\ + 'end : Increase the number of epochs per view\n'\ + 'page down : Reduce the number of channels per view\n'\ + 'page up : Increase the number of channels per view\n'\ + 'b : Toggle butterfly plot on/off\n' + width = 10 + height = 0.2 * 15 + fig_help = figure_nobar(figsize=(width, height)) + fig_help.canvas.set_window_title('Help') + plt.axis('off') + plt.text(0, 0, text) + # this should work for non-test cases + try: + fig_help.canvas.draw() + fig_help.show() + except Exception: + pass diff --git a/mne/viz/utils.py b/mne/viz/utils.py index 57bc42ae443..668e20ac3d3 100644 --- a/mne/viz/utils.py +++ b/mne/viz/utils.py @@ -269,7 +269,7 @@ def _draw_proj_checkbox(event, params, draw_current_state=True): def _layout_figure(params): - """Aux function for setting figure layout""" + """Function for setting figure layout. Shared with raw and epoch plots""" size = params['fig'].get_size_inches() * params['fig'].dpi scroll_width = 25 hscroll_dist = 25 @@ -298,6 +298,8 @@ def _layout_figure(params): ax_height = 1.0 - ax_y - t_border pos = [l_border, ax_y, ax_width, ax_height] + + params['ax'].set_position(pos) if 'ax2' in params: params['ax2'].set_position(pos) params['ax'].set_position(pos) @@ -313,6 +315,10 @@ def _layout_figure(params): pos = [l_border + ax_width + vscroll_dist, b_border, scroll_width_x, scroll_width_y] params['ax_button'].set_position(pos) + if 'ax_help_button' in params: + pos = [l_border - vscroll_dist - scroll_width_x * 2, b_border, + scroll_width_x * 2, scroll_width_y] + params['ax_help_button'].set_position(pos) params['fig'].canvas.draw() From 2a54e7b2948a699b265e67e7ac2da82658503c17 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Sun, 21 Jun 2015 14:17:54 +0300 Subject: [PATCH 04/24] Small fixes. --- mne/viz/epochs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 82a264b19fb..6c18c6b6080 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -568,9 +568,13 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, ax_hscroll.set_xlabel('Epochs') ax_vscroll = plt.subplot2grid((10, 15), (0, 14), rowspan=9) ax_vscroll.set_axis_off() - ax_vscroll.add_patch(mpl.patches.Rectangle((0, 0), 1, len(picks), facecolor='w', zorder=2)) + + ax_help_button = plt.subplot2grid((10, 15), (9, 0), colspan=1) + help_button = mpl.widgets.Button(ax_help_button, 'Help') + help_button.on_clicked(_onclick_help) + # populate vertical and horizontal scrollbars for ci in range(len(picks)): ax_vscroll.add_patch(mpl.patches.Rectangle((0, ci), 1, 1, @@ -651,10 +655,6 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, horizontalalignment='left', fontweight='bold') text.set_visible(False) - ax_help_button = plt.subplot2grid((10, 15), (0, 14)) - help_button = mpl.widgets.Button(ax_help_button, 'Help') - help_button.on_clicked(_onclick_help) - params = {'fig': fig, 'ax': ax, 'ax2': ax2, From 9ef1b90a83c874b1424bc30febee60994b15521d Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Tue, 23 Jun 2015 16:17:40 +0300 Subject: [PATCH 05/24] Added options for adjusting epochs/channels. --- mne/viz/epochs.py | 81 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 6c18c6b6080..dc32e6e7ca3 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -692,8 +692,9 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, 'vert_lines': list(), 'vertline_t': vertline_t, 'butterfly': False, - 'text': text} - 'ax_help_button': ax_help_button} + 'text': text, + 'ax_help_button': ax_help_button, + 'fig_options': None} if len(projs) > 0 and not epochs.proj: ax_button = plt.subplot2grid((10, 15), (9, 14)) @@ -1240,6 +1241,9 @@ def _plot_onkey(event, params): n_times = len(params['epochs'].times) if n_times * n_epochs > len(params['data'][0]): return + if params['t_start'] + n_times * n_epochs > len(params['data'][0]): + params['t_start'] -= n_times + params['hsel_patch'].set_x(params['t_start']) ticks = params['epoch_times'] + 0.5 * n_times params['ax2'].set_xticks(ticks[:n_epochs]) params['n_epochs'] = n_epochs @@ -1257,6 +1261,8 @@ def _plot_onkey(event, params): elif event.key == 'b': _prepare_butterfly(params) _plot_traces(params) + elif event.key == 'i': + _open_options(params) elif event.key == 'escape': plt.close(params['fig']) @@ -1393,3 +1399,74 @@ def _onclick_help(event): fig_help.show() except Exception: pass + + +def _update_epochs(params, n_epochs): + """Function for changing the amount of epochs per view.""" + n_times = len(params['epochs'].times) + ticks = params['epoch_times'] + 0.5 * n_times + params['ax2'].set_xticks(ticks[:n_epochs]) + params['n_epochs'] = n_epochs + params['duration'] = n_times * n_epochs + params['hsel_patch'].set_width(params['duration']) + if params['t_start'] + n_times * n_epochs > len(params['data'][0]): + params['t_start'] = len(params['data'][0]) - n_times * n_epochs + params['hsel_patch'].set_x(params['t_start']) + + +def _update_channels(params, n_channels): + """Function for changing the amount of channels per view.""" + from matplotlib.collections import LineCollection + offset = params['ax'].get_ylim()[0] / n_channels + params['offsets'] = np.arange(n_channels) * offset + (offset / 2.) + while len(params['lines']) > n_channels: + params['ax'].collections.pop() + params['lines'].pop() + while len(params['lines']) < n_channels: + lc = LineCollection(list(), linewidths=0.5, zorder=3) + params['ax'].add_collection(lc) + params['lines'].append(lc) + params['ax'].set_yticks(params['offsets']) + params['vsel_patch'].set_height(n_channels) + params['n_channels'] = n_channels + + +def _open_options(params): + """Function for opening the option window.""" + import matplotlib.pyplot as plt + import matplotlib as mpl + if params['fig_options'] is not None: + # turn off options dialog + plt.close(params['fig_options']) + params['fig_options'] = None + return + width = 10 + height = 7.5 + params['fig_options'] = figure_nobar(figsize=(width, height)) + ax_color = 'lightgoldenrodyellow' + ax_channels = plt.axes([0.25, 0.1, 0.65, 0.2], axisbg=ax_color) + ax_epochs = plt.axes([0.25, 0.35, 0.65, 0.2], axisbg=ax_color) + channel_slider = mpl.widgets.Slider(ax_channels, 'Channels', 1, + len(params['ch_names']), + valfmt='%0.0f', + valinit=params['n_channels']) + epoch_slider = mpl.widgets.Slider(ax_epochs, 'Epochs', 1, + len(params['epoch_times']), + valfmt='%0.0f', + valinit=params['n_epochs']) + + def update_epochs(val): + _update_epochs(params, int(np.around(epoch_slider.val))) + _plot_traces(params) + + def update_channels(val): + _update_channels(params, int(np.around(channel_slider.val))) + _plot_traces(params) + + channel_slider.on_changed(update_channels) + epoch_slider.on_changed(update_epochs) + try: + params['fig_options'].canvas.draw() + params['fig_options'].show() + except Exception: + pass From 1c9e0e309f1aee01cb54e3901781da43fc7e6af1 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 24 Jun 2015 11:27:59 +0300 Subject: [PATCH 06/24] Update button to options. --- mne/viz/epochs.py | 68 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index dc32e6e7ca3..3810b34333b 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1401,22 +1401,11 @@ def _onclick_help(event): pass -def _update_epochs(params, n_epochs): - """Function for changing the amount of epochs per view.""" - n_times = len(params['epochs'].times) - ticks = params['epoch_times'] + 0.5 * n_times - params['ax2'].set_xticks(ticks[:n_epochs]) - params['n_epochs'] = n_epochs - params['duration'] = n_times * n_epochs - params['hsel_patch'].set_width(params['duration']) - if params['t_start'] + n_times * n_epochs > len(params['data'][0]): - params['t_start'] = len(params['data'][0]) - n_times * n_epochs - params['hsel_patch'].set_x(params['t_start']) - - -def _update_channels(params, n_channels): +def _update_channels_epochs(event, params): """Function for changing the amount of channels per view.""" from matplotlib.collections import LineCollection + # Channels + n_channels = int(np.around(params['channel_slider'].val)) offset = params['ax'].get_ylim()[0] / n_channels params['offsets'] = np.arange(n_channels) * offset + (offset / 2.) while len(params['lines']) > n_channels: @@ -1430,6 +1419,19 @@ def _update_channels(params, n_channels): params['vsel_patch'].set_height(n_channels) params['n_channels'] = n_channels + # Epochs + n_epochs = int(np.around(params['epoch_slider'].val)) + n_times = len(params['epochs'].times) + ticks = params['epoch_times'] + 0.5 * n_times + params['ax2'].set_xticks(ticks[:n_epochs]) + params['n_epochs'] = n_epochs + params['duration'] = n_times * n_epochs + params['hsel_patch'].set_width(params['duration']) + if params['t_start'] + n_times * n_epochs > len(params['data'][0]): + params['t_start'] = len(params['data'][0]) - n_times * n_epochs + params['hsel_patch'].set_x(params['t_start']) + _plot_traces(params) + def _open_options(params): """Function for opening the option window.""" @@ -1441,30 +1443,24 @@ def _open_options(params): params['fig_options'] = None return width = 10 - height = 7.5 + height = 5 params['fig_options'] = figure_nobar(figsize=(width, height)) ax_color = 'lightgoldenrodyellow' - ax_channels = plt.axes([0.25, 0.1, 0.65, 0.2], axisbg=ax_color) - ax_epochs = plt.axes([0.25, 0.35, 0.65, 0.2], axisbg=ax_color) - channel_slider = mpl.widgets.Slider(ax_channels, 'Channels', 1, - len(params['ch_names']), - valfmt='%0.0f', - valinit=params['n_channels']) - epoch_slider = mpl.widgets.Slider(ax_epochs, 'Epochs', 1, - len(params['epoch_times']), - valfmt='%0.0f', - valinit=params['n_epochs']) - - def update_epochs(val): - _update_epochs(params, int(np.around(epoch_slider.val))) - _plot_traces(params) - - def update_channels(val): - _update_channels(params, int(np.around(channel_slider.val))) - _plot_traces(params) - - channel_slider.on_changed(update_channels) - epoch_slider.on_changed(update_epochs) + ax_channels = plt.axes([0.15, 0.1, 0.65, 0.2], axisbg=ax_color) + ax_epochs = plt.axes([0.15, 0.35, 0.65, 0.2], axisbg=ax_color) + ax_button = plt.axes([0.85, 0.1, 0.1, 0.4]) + params['update_button'] = mpl.widgets.Button(ax_button, 'Update') + params['channel_slider'] = mpl.widgets.Slider(ax_channels, 'Channels', 1, + len(params['ch_names']), + valfmt='%0.0f', + valinit=params['n_channels']) + params['epoch_slider'] = mpl.widgets.Slider(ax_epochs, 'Epochs', 1, + len(params['epoch_times']), + valfmt='%0.0f', + valinit=params['n_epochs']) + + update = partial(_update_channels_epochs, params=params) + params['update_button'].on_clicked(update) try: params['fig_options'].canvas.draw() params['fig_options'].show() From f69c1e033d80a4e30d9ba716a951edbfaa243d10 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 24 Jun 2015 14:25:14 +0300 Subject: [PATCH 07/24] Infobox layout. --- mne/viz/epochs.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 3810b34333b..cdf6f5303e8 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1443,12 +1443,14 @@ def _open_options(params): params['fig_options'] = None return width = 10 - height = 5 - params['fig_options'] = figure_nobar(figsize=(width, height)) + height = 1 + fig_options = figure_nobar(figsize=(width, height)) + fig_options.canvas.set_window_title('Viewport dimensions') + params['fig_options'] = fig_options ax_color = 'lightgoldenrodyellow' - ax_channels = plt.axes([0.15, 0.1, 0.65, 0.2], axisbg=ax_color) - ax_epochs = plt.axes([0.15, 0.35, 0.65, 0.2], axisbg=ax_color) - ax_button = plt.axes([0.85, 0.1, 0.1, 0.4]) + ax_channels = plt.axes([0.15, 0.1, 0.65, 0.4], axisbg=ax_color) + ax_epochs = plt.axes([0.15, 0.55, 0.65, 0.4], axisbg=ax_color) + ax_button = plt.axes([0.85, 0.1, 0.1, 0.85]) params['update_button'] = mpl.widgets.Button(ax_button, 'Update') params['channel_slider'] = mpl.widgets.Slider(ax_channels, 'Channels', 1, len(params['ch_names']), From a270e601595b377f1c9d2c6f60ad378b21bfa3c3 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 24 Jun 2015 15:01:05 +0300 Subject: [PATCH 08/24] Updated help. --- mne/viz/epochs.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index cdf6f5303e8..c3460b32d6f 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -555,7 +555,7 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, fig.canvas.set_window_title('mne_browse_epochs') ax = plt.subplot2grid((10, 15), (0, 1), colspan=13, rowspan=9) - ax.annotate(fig_title, xy=(0.5, 1), xytext=(0, ax.get_ylim()[1] + 15), + ax.annotate(title, xy=(0.5, 1), xytext=(0, ax.get_ylim()[1] + 15), ha='center', va='bottom', size=12, xycoords='axes fraction', textcoords='offset points') @@ -1259,10 +1259,16 @@ def _plot_onkey(event, params): params['hsel_patch'].set_width(params['duration']) _plot_traces(params) elif event.key == 'b': + if params['fig_options'] is not None: + plt.close(params['fig_options']) + params['fig_options'] = None _prepare_butterfly(params) _plot_traces(params) - elif event.key == 'i': - _open_options(params) + elif event.key == 'o': + if not params['butterfly']: + _open_options(params) + elif event.key == '?': + _onclick_help(event) elif event.key == 'escape': plt.close(params['fig']) @@ -1386,9 +1392,13 @@ def _onclick_help(event): 'end : Increase the number of epochs per view\n'\ 'page down : Reduce the number of channels per view\n'\ 'page up : Increase the number of channels per view\n'\ - 'b : Toggle butterfly plot on/off\n' - width = 10 - height = 0.2 * 15 + 'b : Toggle butterfly plot on/off\n'\ + 'o : Open dialog for adjusting viewport dimensions\n'\ + 'f11 : Toggle full screen mode\n'\ + '? : Open help box'\ + 'esc : Close mne_browse_epochs\n' + width = 8 + height = 0.25 * 15 # 15 rows of text fig_help = figure_nobar(figsize=(width, height)) fig_help.canvas.set_window_title('Help') plt.axis('off') @@ -1412,7 +1422,8 @@ def _update_channels_epochs(event, params): params['ax'].collections.pop() params['lines'].pop() while len(params['lines']) < n_channels: - lc = LineCollection(list(), linewidths=0.5, zorder=3) + lc = LineCollection(list(), linewidths=0.5, antialiased=False, + zorder=2, picker=3.) params['ax'].add_collection(lc) params['lines'].append(lc) params['ax'].set_yticks(params['offsets']) From 2a208dbaaebab613d08d55f005ea6ed438491ed7 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 24 Jun 2015 15:38:05 +0300 Subject: [PATCH 09/24] Changed to hard coded dpi. Updated help. Fig size is saved. --- mne/viz/epochs.py | 31 +++++++++++++++++++------------ mne/viz/raw.py | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index c3460b32d6f..c6dad4cf449 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -16,7 +16,7 @@ import numpy as np -from ..utils import create_chunks, verbose, get_config, deprecated +from ..utils import create_chunks, verbose, get_config, deprecated, set_config from ..io.pick import pick_types, channel_type from ..io.proj import setup_proj from ..fixes import Counter, _in1d @@ -551,7 +551,7 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, title = epochs.name if epochs.name is None or len(title) == 0: title = '' - fig = figure_nobar(facecolor='w', figsize=size) + fig = figure_nobar(facecolor='w', figsize=size, dpi=80) fig.canvas.set_window_title('mne_browse_epochs') ax = plt.subplot2grid((10, 15), (0, 1), colspan=13, rowspan=9) @@ -1375,13 +1375,16 @@ def _close_event(event, params): def _resize_event(event, params): """Function to handle resize event""" + size = ','.join([str(s) for s in params['fig'].get_size_inches()]) + set_config('MNE_BROWSE_RAW_SIZE', size) _layout_figure(params) def _onclick_help(event): """Function for drawing help window""" import matplotlib.pyplot as plt - text = 'left arrow : Navigate left\n'\ + text = 'Hotkeys:\n\n'\ + 'left arrow : Navigate left\n'\ 'right arrow : Navigate right\n'\ 'down arrow : Navigate channels down\n'\ 'up arrow : Navigate channels up\n'\ @@ -1395,11 +1398,16 @@ def _onclick_help(event): 'b : Toggle butterfly plot on/off\n'\ 'o : Open dialog for adjusting viewport dimensions\n'\ 'f11 : Toggle full screen mode\n'\ - '? : Open help box'\ - 'esc : Close mne_browse_epochs\n' + '? : Open help box\n'\ + 'esc : Close mne_browse_epochs\n\n'\ + 'Left click on an epoch marks bad epoch to be dropped\n'\ + 'Right click on main axes draws a vertical line on the plot\n'\ + 'Middle click on a line shows the channel name\n'\ + 'Mouse click on the channel name marks a bad channel\n'\ + width = 8 - height = 0.25 * 15 # 15 rows of text - fig_help = figure_nobar(figsize=(width, height)) + height = 0.25 * 21 # 21 rows of text + fig_help = figure_nobar(figsize=(width, height), dpi=80) fig_help.canvas.set_window_title('Help') plt.axis('off') plt.text(0, 0, text) @@ -1412,7 +1420,7 @@ def _onclick_help(event): def _update_channels_epochs(event, params): - """Function for changing the amount of channels per view.""" + """Function for changing the amount of channels and epochs per view.""" from matplotlib.collections import LineCollection # Channels n_channels = int(np.around(params['channel_slider'].val)) @@ -1455,12 +1463,11 @@ def _open_options(params): return width = 10 height = 1 - fig_options = figure_nobar(figsize=(width, height)) + fig_options = figure_nobar(figsize=(width, height), dpi=80) fig_options.canvas.set_window_title('Viewport dimensions') params['fig_options'] = fig_options - ax_color = 'lightgoldenrodyellow' - ax_channels = plt.axes([0.15, 0.1, 0.65, 0.4], axisbg=ax_color) - ax_epochs = plt.axes([0.15, 0.55, 0.65, 0.4], axisbg=ax_color) + ax_channels = plt.axes([0.15, 0.1, 0.65, 0.4]) + ax_epochs = plt.axes([0.15, 0.55, 0.65, 0.4]) ax_button = plt.axes([0.85, 0.1, 0.1, 0.85]) params['update_button'] = mpl.widgets.Button(ax_button, 'Update') params['channel_slider'] = mpl.widgets.Slider(ax_channels, 'Channels', 1, diff --git a/mne/viz/raw.py b/mne/viz/raw.py index 24e8e1ab2a2..92a343b5e59 100644 --- a/mne/viz/raw.py +++ b/mne/viz/raw.py @@ -535,7 +535,7 @@ def plot_raw(raw, events=None, duration=10.0, start=0.0, n_channels=None, size = size.split(',') size = tuple([float(s) for s in size]) # have to try/catch when there's no toolbar - fig = figure_nobar(facecolor=bgcolor, figsize=size) + fig = figure_nobar(facecolor=bgcolor, figsize=size, dpi=80) fig.canvas.set_window_title('mne_browse_raw') ax = plt.subplot2grid((10, 10), (0, 0), colspan=9, rowspan=9) ax.set_title(title, fontsize=12) From 225c0d4905744ed9e54eb154c0d2ec9b842e8dfc Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 24 Jun 2015 15:58:38 +0300 Subject: [PATCH 10/24] Added message to notify of bad channels. --- mne/viz/epochs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index c6dad4cf449..4e40fb8d243 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -17,6 +17,7 @@ import numpy as np from ..utils import create_chunks, verbose, get_config, deprecated, set_config +from ..utils import logger from ..io.pick import pick_types, channel_type from ..io.proj import setup_proj from ..fixes import Counter, _in1d @@ -1371,6 +1372,7 @@ def _onpick(event, params): def _close_event(event, params): """Function to drop selected bad epochs. Called on closing of the plot.""" params['epochs'].drop_epochs(params['bads']) + logger.info('Channels marked as bad: %s' % params['epochs'].info['bads']) def _resize_event(event, params): From 09763b0798abe30c47fd0f04bb1d10ecb2340bce Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 24 Jun 2015 16:05:57 +0300 Subject: [PATCH 11/24] Small fix to docs. --- mne/viz/raw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/viz/raw.py b/mne/viz/raw.py index 92a343b5e59..753c910a126 100644 --- a/mne/viz/raw.py +++ b/mne/viz/raw.py @@ -350,7 +350,7 @@ def plot_raw(raw, events=None, duration=10.0, start=0.0, n_channels=None, color : dict | color object | None Color for the data traces. If None, defaults to:: - dict(mag='darkblue', grad='b', eeg='k', eog='k', ecg='r', + dict(mag='darkblue', grad='b', eeg='k', eog='k', ecg='m', emg='k', ref_meg='steelblue', misc='k', stim='k', resp='k', chpi='k') From da6bfd8555817e8387faf6ef53a9b35528a42e42 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Thu, 25 Jun 2015 12:30:11 +0300 Subject: [PATCH 12/24] Mods to help dialog. Tests. --- mne/viz/epochs.py | 78 ++++++++++++++++++++++++------------ mne/viz/tests/test_epochs.py | 2 + 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 4e40fb8d243..8e9aaa60f72 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1,6 +1,6 @@ """Functions to plot epochs data """ -from __future__ import print_function +from __future__ import print_function, unicode_literals # Authors: Alexandre Gramfort # Denis Engemann @@ -1385,34 +1385,60 @@ def _resize_event(event, params): def _onclick_help(event): """Function for drawing help window""" import matplotlib.pyplot as plt - text = 'Hotkeys:\n\n'\ - 'left arrow : Navigate left\n'\ - 'right arrow : Navigate right\n'\ - 'down arrow : Navigate channels down\n'\ - 'up arrow : Navigate channels up\n'\ - '- : Scale down\n'\ - '+ : Scale up\n'\ - '= : Scale up\n'\ - 'home : Reduce the number of epochs per view\n'\ - 'end : Increase the number of epochs per view\n'\ - 'page down : Reduce the number of channels per view\n'\ - 'page up : Increase the number of channels per view\n'\ - 'b : Toggle butterfly plot on/off\n'\ - 'o : Open dialog for adjusting viewport dimensions\n'\ - 'f11 : Toggle full screen mode\n'\ - '? : Open help box\n'\ - 'esc : Close mne_browse_epochs\n\n'\ - 'Left click on an epoch marks bad epoch to be dropped\n'\ - 'Right click on main axes draws a vertical line on the plot\n'\ - 'Middle click on a line shows the channel name\n'\ - 'Mouse click on the channel name marks a bad channel\n'\ - - width = 8 - height = 0.25 * 21 # 21 rows of text + + text = u'\u2190 : \n'\ + u'\u2192 : \n'\ + u'\u2193 : \n'\ + u'\u2191 : \n'\ + u'- : \n'\ + u'+ or = : \n'\ + u'home : \n'\ + u'end : \n'\ + u'page down : \n'\ + u'page up : \n'\ + u'b : \n'\ + u'o : \n'\ + u'F11 : \n'\ + u'? : \n'\ + u'esc : \n\n'\ + + text2 = 'Navigate left\n'\ + 'Navigate right\n'\ + 'Navigate channels down\n'\ + 'Navigate channels up\n'\ + 'Scale down\n'\ + 'Scale up\n'\ + 'Reduce the number of epochs per view\n'\ + 'Increase the number of epochs per view\n'\ + 'Reduce the number of channels per view\n'\ + 'Increase the number of channels per view\n'\ + 'Toggle butterfly plot on/off\n'\ + 'Open dialog for adjusting viewport\n'\ + 'Toggle full screen mode\n'\ + 'Open help box\n'\ + 'Close mne_browse_epochs\n\n' + + text3 = 'Left click on an epoch marks bad epoch to be dropped\n'\ + 'Right click on main axes draws a vertical line on the plot\n'\ + 'Middle click on a line shows the channel name\n'\ + 'Mouse click on the channel name marks a bad channel\n' + width = 5 + height = 0.25 * 19 # 19 rows of text + fig_help = figure_nobar(figsize=(width, height), dpi=80) fig_help.canvas.set_window_title('Help') + ax1 = plt.subplot2grid((3, 5), (0, 0), rowspan=2) + plt.text(0, 1, text, fontname='STIXGeneral', va='top', weight='bold') + ax1.set_title('Keyboard shortcuts', va='bottom', ha='left') + plt.axis('off') + plt.subplot2grid((3, 5), (0, 1), rowspan=2, colspan=4) + plt.text(0, 1, text2, fontname='STIXGeneral', va='top') plt.axis('off') - plt.text(0, 0, text) + plt.subplot2grid((3, 5), (2, 0), colspan=5) + plt.text(0, 1, text3, fontname='STIXGeneral', va='top') + plt.axis('off') + + tight_layout(fig=fig_help) # this should work for non-test cases try: fig_help.canvas.draw() diff --git a/mne/viz/tests/test_epochs.py b/mne/viz/tests/test_epochs.py index 23a12ee43c2..484b9faac7e 100644 --- a/mne/viz/tests/test_epochs.py +++ b/mne/viz/tests/test_epochs.py @@ -122,6 +122,8 @@ def test_plot_epochs(): fig.canvas.key_press_event('b') fig.canvas.key_press_event('f11') fig.canvas.key_press_event('home') + fig.canvas.key_press_event('?') + fig.canvas.key_press_event('o') fig.canvas.key_press_event('end') fig.canvas.resize_event() fig.canvas.close_event() # closing and epoch dropping From e6e0c0852dc8a560a7f96b98606110a499126b2d Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Thu, 25 Jun 2015 15:21:34 +0300 Subject: [PATCH 13/24] Rough version of label toggling. --- mne/viz/epochs.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 8e9aaa60f72..cdbbcfe4e9e 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -964,8 +964,6 @@ def _plot_traces(params): 1e6 * factor) ax.set_yticklabels(labels, fontsize=12, color='black') else: - if n_channels > 100: - tick_list = [''] ax.set_yticklabels(tick_list, fontsize=12) params['vsel_patch'].set_y(ch_start) params['fig'].canvas.draw() @@ -1098,7 +1096,7 @@ def _plot_onscroll(event, params): def _mouse_click(event, params): """Function to handle mouse click events.""" if event.inaxes is None: - if params['n_channels'] > 100 or params['butterfly']: + if params['butterfly']: return ax = params['ax'] ylim = ax.get_ylim() @@ -1416,7 +1414,7 @@ def _onclick_help(event): 'Open dialog for adjusting viewport\n'\ 'Toggle full screen mode\n'\ 'Open help box\n'\ - 'Close mne_browse_epochs\n\n' + 'Quit\n\n' text3 = 'Left click on an epoch marks bad epoch to be dropped\n'\ 'Right click on main axes draws a vertical line on the plot\n'\ @@ -1480,6 +1478,14 @@ def _update_channels_epochs(event, params): _plot_traces(params) +def _toggle_labels(label, params): + """Function for toggling y labels on/off.""" + labels = params['ax'].yaxis.get_ticklabels() + for label in labels: + label.set_visible(not label.get_visible()) + params['fig'].canvas.draw() + + def _open_options(params): """Function for opening the option window.""" import matplotlib.pyplot as plt @@ -1490,13 +1496,15 @@ def _open_options(params): params['fig_options'] = None return width = 10 - height = 1 + height = 5 fig_options = figure_nobar(figsize=(width, height), dpi=80) fig_options.canvas.set_window_title('Viewport dimensions') params['fig_options'] = fig_options - ax_channels = plt.axes([0.15, 0.1, 0.65, 0.4]) - ax_epochs = plt.axes([0.15, 0.55, 0.65, 0.4]) - ax_button = plt.axes([0.85, 0.1, 0.1, 0.85]) + ax_channels = plt.axes([0.15, 0.1, 0.65, 0.25]) + ax_epochs = plt.axes([0.15, 0.4, 0.65, 0.25]) + ax_button = plt.axes([0.85, 0.1, 0.1, 0.55]) + ax_check = plt.axes([0.15, 0.70, 0.4, 0.25]) + plt.axis('off') params['update_button'] = mpl.widgets.Button(ax_button, 'Update') params['channel_slider'] = mpl.widgets.Slider(ax_channels, 'Channels', 1, len(params['ch_names']), @@ -1506,9 +1514,14 @@ def _open_options(params): len(params['epoch_times']), valfmt='%0.0f', valinit=params['n_epochs']) - + toggled = params['ax'].yaxis.get_ticklabels()[0].get_visible() + params['checkbox'] = mpl.widgets.CheckButtons(ax_check, + ['Y labels visible'], + actives=[toggled]) update = partial(_update_channels_epochs, params=params) params['update_button'].on_clicked(update) + labels_callback = partial(_toggle_labels, params=params) + params['checkbox'].on_clicked(labels_callback) try: params['fig_options'].canvas.draw() params['fig_options'].show() From f63f61425face972b1ba372691b39059bae47ea4 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Thu, 25 Jun 2015 16:15:29 +0300 Subject: [PATCH 14/24] Rough version of toggling t0. --- mne/viz/epochs.py | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index cdbbcfe4e9e..ab75793342f 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -695,7 +695,8 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, 'butterfly': False, 'text': text, 'ax_help_button': ax_help_button, - 'fig_options': None} + 'fig_options': None, + 't0_visible': True} if len(projs) > 0 and not epochs.proj: ax_button = plt.subplot2grid((10, 15), (9, 14)) @@ -1031,14 +1032,16 @@ def _channels_changed(params): def _plot_vert_lines(params): """ Helper function for plotting vertical lines.""" ax = params['ax'] - ax.lines = list() + while len(ax.lines) > 0: + ax.lines.pop() epochs = params['epochs'] - t_zero = np.where(epochs.times == 0.)[0] - if len(t_zero) == 1: - for event_idx in range(len(epochs.events)): - pos = [event_idx * len(epochs.times) + t_zero[0], - event_idx * len(epochs.times) + t_zero[0]] - ax.plot(pos, ax.get_ylim(), 'g', zorder=3, alpha=0.4) + if params['t0_visible']: + t_zero = np.where(epochs.times == 0.)[0] + if len(t_zero) == 1: + for event_idx in range(len(epochs.events)): + pos = [event_idx * len(epochs.times) + t_zero[0], + event_idx * len(epochs.times) + t_zero[0]] + ax.plot(pos, ax.get_ylim(), 'g', zorder=3, alpha=0.4) for epoch_idx in range(len(epochs.events)): pos = [epoch_idx * len(epochs.times), epoch_idx * len(epochs.times)] ax.plot(pos, ax.get_ylim(), color='black', linestyle='--', zorder=1) @@ -1480,9 +1483,13 @@ def _update_channels_epochs(event, params): def _toggle_labels(label, params): """Function for toggling y labels on/off.""" - labels = params['ax'].yaxis.get_ticklabels() - for label in labels: - label.set_visible(not label.get_visible()) + if label == 'Y labels visible': + labels = params['ax'].yaxis.get_ticklabels() + for label in labels: + label.set_visible(not label.get_visible()) + elif label == 'T0 visible': + params['t0_visible'] = not params['t0_visible'] + _plot_vert_lines(params) params['fig'].canvas.draw() @@ -1500,10 +1507,10 @@ def _open_options(params): fig_options = figure_nobar(figsize=(width, height), dpi=80) fig_options.canvas.set_window_title('Viewport dimensions') params['fig_options'] = fig_options - ax_channels = plt.axes([0.15, 0.1, 0.65, 0.25]) - ax_epochs = plt.axes([0.15, 0.4, 0.65, 0.25]) - ax_button = plt.axes([0.85, 0.1, 0.1, 0.55]) - ax_check = plt.axes([0.15, 0.70, 0.4, 0.25]) + ax_channels = plt.axes([0.15, 0.1, 0.65, 0.2]) + ax_epochs = plt.axes([0.15, 0.35, 0.65, 0.2]) + ax_button = plt.axes([0.85, 0.1, 0.1, 0.45]) + ax_check = plt.axes([0.15, 0.60, 0.4, 0.35]) plt.axis('off') params['update_button'] = mpl.widgets.Button(ax_button, 'Update') params['channel_slider'] = mpl.widgets.Slider(ax_channels, 'Channels', 1, @@ -1514,10 +1521,12 @@ def _open_options(params): len(params['epoch_times']), valfmt='%0.0f', valinit=params['n_epochs']) - toggled = params['ax'].yaxis.get_ticklabels()[0].get_visible() + actives = [params['ax'].yaxis.get_ticklabels()[0].get_visible(), + params['t0_visible']] params['checkbox'] = mpl.widgets.CheckButtons(ax_check, - ['Y labels visible'], - actives=[toggled]) + ['Y labels visible', + 'T0 visible'], + actives=actives) update = partial(_update_channels_epochs, params=params) params['update_button'].on_clicked(update) labels_callback = partial(_toggle_labels, params=params) From ad056c7cb032006ce0840cf2d8637b717d276dca Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Thu, 25 Jun 2015 16:31:40 +0300 Subject: [PATCH 15/24] Layout of options. --- mne/viz/epochs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index ab75793342f..eac49fafc20 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1503,14 +1503,14 @@ def _open_options(params): params['fig_options'] = None return width = 10 - height = 5 + height = 3 fig_options = figure_nobar(figsize=(width, height), dpi=80) fig_options.canvas.set_window_title('Viewport dimensions') params['fig_options'] = fig_options - ax_channels = plt.axes([0.15, 0.1, 0.65, 0.2]) - ax_epochs = plt.axes([0.15, 0.35, 0.65, 0.2]) - ax_button = plt.axes([0.85, 0.1, 0.1, 0.45]) - ax_check = plt.axes([0.15, 0.60, 0.4, 0.35]) + ax_channels = plt.axes([0.15, 0.1, 0.65, 0.1]) + ax_epochs = plt.axes([0.15, 0.25, 0.65, 0.1]) + ax_button = plt.axes([0.85, 0.1, 0.1, 0.25]) + ax_check = plt.axes([0.15, 0.4, 0.4, 0.55]) plt.axis('off') params['update_button'] = mpl.widgets.Button(ax_button, 'Update') params['channel_slider'] = mpl.widgets.Slider(ax_channels, 'Channels', 1, From 45d03a46ab141ba65f8dd8c2933e34b77765df43 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Fri, 26 Jun 2015 11:14:05 +0300 Subject: [PATCH 16/24] Added check boxes. Changes to help. --- mne/viz/epochs.py | 68 +++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index eac49fafc20..1680c6795d7 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -696,7 +696,7 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, 'text': text, 'ax_help_button': ax_help_button, 'fig_options': None, - 't0_visible': True} + 'settings': [True, True, True, True]} # for options dialog if len(projs) > 0 and not epochs.proj: ax_button = plt.subplot2grid((10, 15), (9, 14)) @@ -1035,7 +1035,7 @@ def _plot_vert_lines(params): while len(ax.lines) > 0: ax.lines.pop() epochs = params['epochs'] - if params['t0_visible']: + if params['settings'][3]: # if zeroline visible t_zero = np.where(epochs.times == 0.)[0] if len(t_zero) == 1: for event_idx in range(len(epochs.events)): @@ -1402,6 +1402,11 @@ def _onclick_help(event): u'F11 : \n'\ u'? : \n'\ u'esc : \n\n'\ + u'Mouse controls\n'\ + u'click epoch :\n'\ + u'click channel name :\n'\ + u'right click :\n'\ + u'middle click :\n' text2 = 'Navigate left\n'\ 'Navigate right\n'\ @@ -1414,30 +1419,30 @@ def _onclick_help(event): 'Reduce the number of channels per view\n'\ 'Increase the number of channels per view\n'\ 'Toggle butterfly plot on/off\n'\ - 'Open dialog for adjusting viewport\n'\ + 'View settings (orig. view only)\n'\ 'Toggle full screen mode\n'\ 'Open help box\n'\ - 'Quit\n\n' + 'Quit\n\n\n'\ + 'Mark bad epoch\n'\ + 'Mark bad channel\n'\ + 'Verticlal line at a time instant\n'\ + 'Show channel name (butterfly plot)\n' - text3 = 'Left click on an epoch marks bad epoch to be dropped\n'\ - 'Right click on main axes draws a vertical line on the plot\n'\ - 'Middle click on a line shows the channel name\n'\ - 'Mouse click on the channel name marks a bad channel\n' - width = 5 + width = 5.5 height = 0.25 * 19 # 19 rows of text fig_help = figure_nobar(figsize=(width, height), dpi=80) fig_help.canvas.set_window_title('Help') - ax1 = plt.subplot2grid((3, 5), (0, 0), rowspan=2) - plt.text(0, 1, text, fontname='STIXGeneral', va='top', weight='bold') - ax1.set_title('Keyboard shortcuts', va='bottom', ha='left') + ax1 = plt.subplot2grid((1, 5), (0, 0), colspan=2) + ax1.set_yticklabels(list()) + plt.text(0.99, 1, text, fontname='STIXGeneral', va='top', weight='bold', + ha='right') plt.axis('off') - plt.subplot2grid((3, 5), (0, 1), rowspan=2, colspan=4) + + ax2 = plt.subplot2grid((1, 5), (0, 2), colspan=3) + ax2.set_yticklabels(list()) plt.text(0, 1, text2, fontname='STIXGeneral', va='top') plt.axis('off') - plt.subplot2grid((3, 5), (2, 0), colspan=5) - plt.text(0, 1, text3, fontname='STIXGeneral', va='top') - plt.axis('off') tight_layout(fig=fig_help) # this should work for non-test cases @@ -1482,13 +1487,24 @@ def _update_channels_epochs(event, params): def _toggle_labels(label, params): - """Function for toggling y labels on/off.""" - if label == 'Y labels visible': + """Function for toggling axis labels on/off.""" + if label == 'Channel names visible': + params['settings'][0] = not params['settings'][0] labels = params['ax'].yaxis.get_ticklabels() for label in labels: - label.set_visible(not label.get_visible()) - elif label == 'T0 visible': - params['t0_visible'] = not params['t0_visible'] + label.set_visible(params['settings'][0]) + elif label == 'Event-id visible': + params['settings'][1] = not params['settings'][1] + labels = params['ax2'].xaxis.get_ticklabels() + for label in labels: + label.set_visible(params['settings'][1]) + elif label == 'Epoch-id visible': + params['settings'][2] = not params['settings'][2] + labels = params['ax'].xaxis.get_ticklabels() + for label in labels: + label.set_visible(params['settings'][2]) + elif label == 'Zeroline visible': + params['settings'][3] = not params['settings'][3] _plot_vert_lines(params) params['fig'].canvas.draw() @@ -1521,12 +1537,12 @@ def _open_options(params): len(params['epoch_times']), valfmt='%0.0f', valinit=params['n_epochs']) - actives = [params['ax'].yaxis.get_ticklabels()[0].get_visible(), - params['t0_visible']] params['checkbox'] = mpl.widgets.CheckButtons(ax_check, - ['Y labels visible', - 'T0 visible'], - actives=actives) + ['Channel names visible', + 'Event-id visible', + 'Epoch-id visible', + 'Zeroline visible'], + actives=params['settings']) update = partial(_update_channels_epochs, params=params) params['update_button'].on_clicked(update) labels_callback = partial(_toggle_labels, params=params) From 4a7a79034e19283393e668cd56372b2b1708791c Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Fri, 26 Jun 2015 12:10:59 +0300 Subject: [PATCH 17/24] Title to help. --- mne/viz/epochs.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 1680c6795d7..85cf60d3acd 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1433,13 +1433,16 @@ def _onclick_help(event): fig_help = figure_nobar(figsize=(width, height), dpi=80) fig_help.canvas.set_window_title('Help') - ax1 = plt.subplot2grid((1, 5), (0, 0), colspan=2) + ax = plt.subplot2grid((8, 5), (0, 0), colspan=5) + ax.set_title('Keyboard shortcuts') + plt.axis('off') + ax1 = plt.subplot2grid((8, 5), (1, 0), rowspan=7, colspan=2) ax1.set_yticklabels(list()) plt.text(0.99, 1, text, fontname='STIXGeneral', va='top', weight='bold', ha='right') plt.axis('off') - ax2 = plt.subplot2grid((1, 5), (0, 2), colspan=3) + ax2 = plt.subplot2grid((8, 5), (1, 2), rowspan=7, colspan=3) ax2.set_yticklabels(list()) plt.text(0, 1, text2, fontname='STIXGeneral', va='top') plt.axis('off') From f570c2ac91777c63d0aaabc4ff2b59480d9fa215 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Fri, 26 Jun 2015 12:55:53 +0300 Subject: [PATCH 18/24] Small fixes. --- mne/viz/epochs.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 85cf60d3acd..592c946beb8 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1,6 +1,5 @@ """Functions to plot epochs data """ -from __future__ import print_function, unicode_literals # Authors: Alexandre Gramfort # Denis Engemann @@ -1099,7 +1098,7 @@ def _plot_onscroll(event, params): def _mouse_click(event, params): """Function to handle mouse click events.""" if event.inaxes is None: - if params['butterfly']: + if params['butterfly'] or not params['settings'][0]: return ax = params['ax'] ylim = ax.get_ylim() @@ -1286,6 +1285,9 @@ def _prepare_butterfly(params): return params['ax_vscroll'].set_visible(False) ax = params['ax'] + labels = ax.yaxis.get_ticklabels() + for label in labels: + label.set_visible(True) ylim = (5. * len(types), 0.) ax.set_ylim(ylim) offset = ylim[0] / (4. * len(types)) @@ -1337,9 +1339,12 @@ def _prepare_butterfly(params): while len(params['lines']) < len(params['picks']): lc = LineCollection(list(), antialiased=False, linewidths=0.5, zorder=2, picker=3.) - params['ax'].add_collection(lc) + ax.add_collection(lc) params['lines'].append(lc) else: # change back to default view + labels = params['ax'].yaxis.get_ticklabels() + for label in labels: + label.set_visible(params['settings'][0]) params['ax_vscroll'].set_visible(True) while len(params['ax2'].texts) > 0: params['ax2'].texts.pop() @@ -1524,7 +1529,7 @@ def _open_options(params): width = 10 height = 3 fig_options = figure_nobar(figsize=(width, height), dpi=80) - fig_options.canvas.set_window_title('Viewport dimensions') + fig_options.canvas.set_window_title('View settings') params['fig_options'] = fig_options ax_channels = plt.axes([0.15, 0.1, 0.65, 0.1]) ax_epochs = plt.axes([0.15, 0.25, 0.65, 0.1]) From e506fd77c9f0f2947255c3eeb1b075f709c00818 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Sat, 27 Jun 2015 12:36:07 +0300 Subject: [PATCH 19/24] Fix attempt. --- mne/viz/epochs.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 592c946beb8..ae76c90c056 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1141,6 +1141,8 @@ def _mouse_click(event, params): elif event.inaxes == params['ax'] and event.button == 2: # middle click params['fig'].canvas.draw() + if params['fig_proj'] is not None: + params['fig_proj'].canvas.draw() elif event.inaxes == params['ax'] and event.button == 3: # right click n_times = len(params['epochs'].times) xdata = int(event.xdata % n_times) @@ -1515,6 +1517,8 @@ def _toggle_labels(label, params): params['settings'][3] = not params['settings'][3] _plot_vert_lines(params) params['fig'].canvas.draw() + if params['fig_proj'] is not None: + params['fig_proj'].canvas.draw() def _open_options(params): @@ -1555,8 +1559,17 @@ def _open_options(params): params['update_button'].on_clicked(update) labels_callback = partial(_toggle_labels, params=params) params['checkbox'].on_clicked(labels_callback) + close_callback = partial(_settings_closed, params=params) + params['fig_options'].canvas.mpl_connect('close_event', close_callback) try: params['fig_options'].canvas.draw() params['fig_options'].show() + if params['fig_proj'] is not None: + params['fig_proj'].canvas.draw() except Exception: pass + + +def _settings_closed(events, params): + """Function to handle close event from settings dialog.""" + params['fig_options'] = None From cf40b7277550210e5d74e11a8f6298437648a8db Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Mon, 29 Jun 2015 08:41:47 +0300 Subject: [PATCH 20/24] Small tweaks. --- mne/viz/epochs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index ae76c90c056..aaf122e5f96 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1400,15 +1400,15 @@ def _onclick_help(event): u'\u2191 : \n'\ u'- : \n'\ u'+ or = : \n'\ - u'home : \n'\ - u'end : \n'\ - u'page down : \n'\ - u'page up : \n'\ + u'Home : \n'\ + u'End : \n'\ + u'Page down : \n'\ + u'Page up : \n'\ u'b : \n'\ u'o : \n'\ u'F11 : \n'\ u'? : \n'\ - u'esc : \n\n'\ + u'Esc : \n\n'\ u'Mouse controls\n'\ u'click epoch :\n'\ u'click channel name :\n'\ From 80a4e66f37908631cad9ff6ca1b1c8e7a923a735 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Tue, 30 Jun 2015 12:41:10 +0300 Subject: [PATCH 21/24] Changed the position of vertical line text field. --- mne/viz/epochs.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index aaf122e5f96..b3f87fef0d9 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -628,9 +628,7 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, ax2.set_xticklabels(labels) xlim = epoch_times[-1] + len(epochs.times) ax_hscroll.set_xlim(0, xlim) - vertline_t = ax_hscroll.text(0, 0.5, '', color='y', - verticalalignment='center', - horizontalalignment='right') + vertline_t = ax_hscroll.text(0, 1, '', color='y', va='bottom', ha='right') # fit horizontal scroll bar ticks hscroll_ticks = np.arange(0, xlim, xlim / 7.0) @@ -652,7 +650,7 @@ def plot_epochs(epochs, picks=None, scalings=None, n_epochs=20, alpha=0.25, linewidth=1, clip_on=False) ax_hscroll.add_patch(hsel_patch) text = ax.text(0, 0, 'blank', zorder=2, verticalalignment='baseline', - horizontalalignment='left', fontweight='bold') + ha='left', fontweight='bold') text.set_visible(False) params = {'fig': fig, From 85102c2bc1aa2679c0d67df7baed3ba266bcf23e Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 8 Jul 2015 15:46:23 +0300 Subject: [PATCH 22/24] Clean up. --- doc/source/whats_new.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/source/whats_new.rst b/doc/source/whats_new.rst index 9057dee46cc..f0ac91cc10d 100644 --- a/doc/source/whats_new.rst +++ b/doc/source/whats_new.rst @@ -28,11 +28,8 @@ BUG - Fix FFT filter artifacts when using short windows in overlap-add by `Eric Larson`_ -<<<<<<< HEAD - Fix picking channels from forward operator could return a channel ordering different from ``info['chs']`` by `Chris Bailey`_ -======= ->>>>>>> Rebase .. _changes_0_9: Version 0.9 From 8f1f5a9cd05da9c376158b5216375151ca234ae4 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 8 Jul 2015 15:52:03 +0300 Subject: [PATCH 23/24] Added empty line. --- mne/viz/epochs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index b3f87fef0d9..6a8c381f137 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1571,3 +1571,4 @@ def _open_options(params): def _settings_closed(events, params): """Function to handle close event from settings dialog.""" params['fig_options'] = None + From 709638e109d09841ddb7bafda8b6483f193d6139 Mon Sep 17 00:00:00 2001 From: Jaakko Leppakangas Date: Wed, 8 Jul 2015 16:38:23 +0300 Subject: [PATCH 24/24] Removed empty line. --- mne/viz/epochs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 6a8c381f137..b3f87fef0d9 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -1571,4 +1571,3 @@ def _open_options(params): def _settings_closed(events, params): """Function to handle close event from settings dialog.""" params['fig_options'] = None -