From e48e050f851f44f356892c4bbb66d4fc8bec2707 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Thu, 31 Aug 2017 17:44:59 +0200 Subject: [PATCH 01/41] init --- mne/viz/evoked.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 98e9a6b91be..90322061cf0 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1501,6 +1501,21 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "Vis/L", "Vis/R", `styles` can be `{"Aud/L":{"linewidth":1}}` to set the linewidth for "Aud/L" to 1. Note that HED ('/'-separated) tags are not supported. + cmap : None | str | instance of matplotlib.colormap + If not None, plot evoked potentials with colors from a color gradient - + either the one provided, or, if 'str', the colormap retrieved from + Matplotlib (e.g., 'viridis' or 'Reds'). In that case, the color of + each line depends on ``evokeds`` and ``cmap``. + If ``evokeds`` is a list and ``colors`` is `None`, the color will + depend on the list position. If ``colors`` is a list, it must contain + integers where the list positions correspond to ``evokeds``, and the + value corresponds to the position on the colorbar. + If ``evokeds`` is a dict, ``colors`` should be a dict mapping from + (potentially HED-style) condition tags to integers corresponding to + positions on the colorbar. E.g., :: + + cmap='viridis', cmap=dict(cond1=1 cond2=2, cond3=3), + vlines : list of int A list of integers corresponding to the positions, in seconds, at which to plot dashed vertical lines. @@ -1559,6 +1574,11 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if isinstance(evokeds, Evoked): evokeds = dict(Evoked=evokeds) # title becomes 'Evoked' elif not isinstance(evokeds, dict): + if cmap is not None: + if colors is None: + colors = dict( + (str(ii + 1), ii) for ii, evoked in enumerate(evokeds)) + colors = {} evokeds = dict((str(ii + 1), evoked) for ii, evoked in enumerate(evokeds)) for cond in evokeds.keys(): @@ -1712,6 +1732,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, colors = dict((condition, color) for condition, color in zip(conditions, colors)) + if cmap is not None: + if + if not isinstance(colors, dict): # default colors from M Waskom's Seaborn # XXX should put a good list of default colors into defaults.py colors_ = ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', From d7556f9cfd35e32f2c731d191ac97b2ac77dd36b Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 1 Sep 2017 12:31:23 +0200 Subject: [PATCH 02/41] make it work --- mne/viz/evoked.py | 100 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 9 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 90322061cf0..713996a3ec1 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1441,10 +1441,10 @@ def _truncate_yaxis(axes, ymin, ymax, orig_ymin, orig_ymax, fraction, def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, - linestyles=['-'], styles=None, vlines=list((0.,)), - ci=0.95, truncate_yaxis=False, truncate_xaxis=True, - ylim=dict(), invert_y=False, show_sensors=None, - show_legend=True, axes=None, title=None, show=True): + linestyles=['-'], styles=None, cmap=None, vlines=list((0.,)), + ci=0.95, truncate_yaxis=False, truncate_xaxis=True, ylim=dict(), + invert_y=False, show_legend=True, show_sensors=None, + split_legend=True, axes=None, title=None, show=True): """Plot evoked time courses for one or multiple channels and conditions. This function is useful for comparing ER[P/F]s at a specific location. It @@ -1501,7 +1501,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "Vis/L", "Vis/R", `styles` can be `{"Aud/L":{"linewidth":1}}` to set the linewidth for "Aud/L" to 1. Note that HED ('/'-separated) tags are not supported. - cmap : None | str | instance of matplotlib.colormap + cmap : None | dict | str | instance of matplotlib.colormap If not None, plot evoked potentials with colors from a color gradient - either the one provided, or, if 'str', the colormap retrieved from Matplotlib (e.g., 'viridis' or 'Reds'). In that case, the color of @@ -1516,6 +1516,12 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, cmap='viridis', cmap=dict(cond1=1 cond2=2, cond3=3), + If ``cmap`` is a (non-string) iterable of length 2, the first must be + a string which will become the colorbar label, and the second one + must be a colormap, e.g. :: + + cmap=('conds', 'viridis'), cmap=dict(cond1=1 cond2=2, cond3=3), + vlines : list of int A list of integers corresponding to the positions, in seconds, at which to plot dashed vertical lines. @@ -1552,6 +1558,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, show_legend : bool | int If not False, show a legend. If int, the position of the axes (forwarded to ``mpl_toolkits.axes_grid1.inset_locator.inset_axes``). + split_legend : bool + If True, the legend shows color and linestyle separately. Defaults to + True if ``cmap`` is not None, else defaults to False. axes : None | `matplotlib.axes.Axes` instance | list of `axes` What axes to plot to. If None, a new axes is created. When plotting multiple channel types, can also be a list of axes, one @@ -1733,7 +1742,43 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, in zip(conditions, colors)) if cmap is not None: - if + if not isinstance(cmap, string_types) and len(cmap) == 2: + cmap_label, cmap = cmap + else: + cmap_label = "" + + if split_legend is None: + split_legend = cmap is not None + if split_legend is True: + import matplotlib.lines as mlines + legend_lines = list() + if cmap is None: + for color in sorted(colors.keys()): + l = mlines.Line2D([], [], linestyle="-", + color=colors[color], label=color) + legend_lines.append(l) + + if len(list(linestyles)) > 1: + for style, s in linestyles.items(): + l = mlines.Line2D([], [], color='k', linestyle=s, label=style) + legend_lines.append(l) + if cmap is not None: + cmapper = getattr(plt.cm, cmap, plt.cm.hot) + color_conds = list(colors.keys()) + all_colors = [colors[c] for c in color_conds] + n_colors = len(all_colors) + color_order = np.array(all_colors).argsort() + + the_colors = cmapper(np.linspace(0, 1, n_colors)) + + colors_ = {cond: ind + for cond, ind in zip(colors, color_order)} + colors = dict() + for cond in evokeds.keys(): + for cond_number, color in colors_.items(): + if cond_number in cond: + colors[cond] = the_colors[color] + continue if not isinstance(colors, dict): # default colors from M Waskom's Seaborn # XXX should put a good list of default colors into defaults.py @@ -1849,11 +1894,48 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, show_sensors, size=20) - if show_legend and len(conditions) > 1: + if len(conditions) > 1: if show_legend is True: show_legend = 'best' - axes.legend(loc=show_legend, ncol=1 + (len(conditions) // 5), - frameon=True) + legend_params = dict(loc=show_legend, frameon=True) + if split_legend: + if len(legend_lines) > 1: + axes.legend(handles=legend_lines, + ncol=1 + (len(legend_lines) // 4), **legend_params) + else: + axes.legend(ncol=1 + (len(conditions) // 5), **legend_params) + + if split_legend and cmap is not None: + import matplotlib as mpl + + print("colors_:", colors_) + colors_l = np.array([n for n in color_conds])[color_order] + print("colors_l 1:", colors_l) + colors_m = [colors_[k] for k in colors_l] + colors_m = list() + for k1 in colors_l: + for k2 in colors: + if k1 in k2: + colors_m.append(colors[k2]) + continue + print("colors_m:", colors_m) + colors_l = np.array([float(n) for n in colors_l]) + print("colors_l 2:", colors_l) + l = plt.cm.jet.from_list(colors_l + [colors_l[-1] + 100], + colors_m + [colors_m[-1]]) + + norm = mpl.colors.BoundaryNorm(all_colors + [all_colors[-1] + 1], l.N) + sm = plt.cm.ScalarMappable(cmap=l, norm=norm) + sm.set_array(colors_l) + + cbar = plt.colorbar(sm, ax=axes) + offset = np.diff(np.concatenate((all_colors, [all_colors[-1] + 1]))) / 2 + cbar.set_ticks(np.array(all_colors) + offset) + cbar.set_ticklabels(all_colors) + cbar.set_label(cmap_label) + fig.cbar = cbar + + fig.ts_ax = axes plt_show(show) return fig From 1b32fc7c896538929bd0cdee27f6be6026c9dcb3 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 1 Sep 2017 13:59:25 +0200 Subject: [PATCH 03/41] fx --- mne/viz/evoked.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 713996a3ec1..26b191760de 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1454,7 +1454,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, Parameters ---------- evokeds : instance of mne.Evoked | list | dict - If a single evoked instance, it is plotted as a time series. + If a single Evoked instance, it is plotted as a time series. If a dict whose values are Evoked objects, the contents are plotted as single time series each and the keys are used as condition labels. If a list of Evokeds, the contents are plotted with indices as labels. @@ -1474,7 +1474,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, Power plotted. gfp : bool If True, the channel type wise GFP is plotted. - If `picks` is an empty list (default), this is set to True. + If ``picks`` is an empty list (default), this is set to True. colors : list | dict | None If a list, will be sequentially used for line colors. If a dict, can map evoked keys or '/'-separated (HED) tags to @@ -1498,7 +1498,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, parameters will be passed to the line plot call of the corresponding condition, overriding defaults. E.g., if evokeds is a dict with the keys "Aud/L", "Aud/R", - "Vis/L", "Vis/R", `styles` can be `{"Aud/L":{"linewidth":1}}` to set + "Vis/L", "Vis/R", `styles` can be `{"Aud/L":{"linewidth": 1}}` to set the linewidth for "Aud/L" to 1. Note that HED ('/'-separated) tags are not supported. cmap : None | dict | str | instance of matplotlib.colormap @@ -1511,10 +1511,12 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, integers where the list positions correspond to ``evokeds``, and the value corresponds to the position on the colorbar. If ``evokeds`` is a dict, ``colors`` should be a dict mapping from - (potentially HED-style) condition tags to integers corresponding to - positions on the colorbar. E.g., :: - - cmap='viridis', cmap=dict(cond1=1 cond2=2, cond3=3), + (potentially HED-style) condition tags to numbers corresponding to + rank order positions on the colorbar. E.g., :: + + evokeds={"cond1/A": ev1, "cond2/A": ev2, "cond3/A": ev3, "B": ev4}, + cmap='viridis', colors=dict(cond1=1 cond2=2, cond3=3), + linestyles={"A": "-", "B": ":"} If ``cmap`` is a (non-string) iterable of length 2, the first must be a string which will become the colorbar label, and the second one @@ -1566,8 +1568,11 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, When plotting multiple channel types, can also be a list of axes, one per channel type. title : None | str - If str, will be plotted as figure title. If None, the channel - names will be shown. + If str, will be plotted as figure title. If None, the channel names + will be shown. + split_legend : bool + If True, the legend shows color and linestyle separately. Defaults to + True if ``cmap`` is not None, else defaults to False. show : bool If True, show the figure. @@ -1763,6 +1768,13 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, l = mlines.Line2D([], [], color='k', linestyle=s, label=style) legend_lines.append(l) if cmap is not None: + for color_value in colors.values(): + try: + float(color_value) + except ValueError: + raise ValueError("If ``cmap`` is not None, the values of " + "``colors`` needs to be numeric. Got " + + str(type(color_value))) cmapper = getattr(plt.cm, cmap, plt.cm.hot) color_conds = list(colors.keys()) all_colors = [colors[c] for c in color_conds] From 36d3617bcc3e3b91598af2e062bb66b305ea7f02 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 1 Sep 2017 23:05:39 +0200 Subject: [PATCH 04/41] tests --- mne/viz/evoked.py | 21 ++++++++------ mne/viz/tests/test_evoked.py | 54 +++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 26b191760de..b74f4448a84 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1683,6 +1683,14 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if (ymin is None) and all_positive: ymin = 0. # 'grad' and GFP are plotted as all-positive +<<<<<<< HEAD +======= + # deal with dict/list of lists and the CI + if not isinstance(ci, np.float): + msg = '"ci" must be float, got {0} instead.' + raise TypeError(msg.format(type(ci))) + +>>>>>>> tests # if we have a dict/list of lists, we compute the grand average and the CI if ci is None: ci = False @@ -1777,7 +1785,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, str(type(color_value))) cmapper = getattr(plt.cm, cmap, plt.cm.hot) color_conds = list(colors.keys()) - all_colors = [colors[c] for c in color_conds] + all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) color_order = np.array(all_colors).argsort() @@ -1918,21 +1926,17 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, axes.legend(ncol=1 + (len(conditions) // 5), **legend_params) if split_legend and cmap is not None: + # plot the colorbar ... complicated cause we don't have a heatmap import matplotlib as mpl - print("colors_:", colors_) colors_l = np.array([n for n in color_conds])[color_order] - print("colors_l 1:", colors_l) - colors_m = [colors_[k] for k in colors_l] colors_m = list() for k1 in colors_l: for k2 in colors: if k1 in k2: colors_m.append(colors[k2]) continue - print("colors_m:", colors_m) - colors_l = np.array([float(n) for n in colors_l]) - print("colors_l 2:", colors_l) + colors_l = list(range(len(colors_l))) l = plt.cm.jet.from_list(colors_l + [colors_l[-1] + 100], colors_m + [colors_m[-1]]) @@ -1941,7 +1945,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, sm.set_array(colors_l) cbar = plt.colorbar(sm, ax=axes) - offset = np.diff(np.concatenate((all_colors, [all_colors[-1] + 1]))) / 2 + offset = np.diff(np.concatenate((all_colors, + [all_colors[-1] + 1]))) / 2 cbar.set_ticks(np.array(all_colors) + offset) cbar.set_ticklabels(all_colors) cbar.set_label(cmap_label) diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 1fe3eac9ed1..2e009ad7644 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -153,35 +153,49 @@ def test_plot_evoked(): contrast["red/stim"] = list((evoked.copy(), red)) contrast["blue/stim"] = list((evoked.copy(), blue)) # test a bunch of params at once + for evokeds_ in (evoked.copy().pick_types(meg='mag'), contrast, + [red, blue], [[red, evoked], [blue, evoked]]): + plot_compare_evokeds(evokeds_, picks=0) # also tests CI + plt.close('all') + # test styling + a bunch of other params at once + colors, linestyles = dict(red='r', blue='b'), dict(red='--', blue='-') plot_compare_evokeds(contrast, colors=colors, linestyles=linestyles, picks=[0, 2], vlines=[.01, -.04], invert_y=True, truncate_yaxis=False, ylim=dict(mag=(-10, 10)), - styles={"red/stim": {"linewidth": 1}}, - show_sensors=True) - assert_raises(ValueError, plot_compare_evokeds, - contrast, picks='str') # bad picks: not int - assert_raises(ValueError, plot_compare_evokeds, evoked, picks=3, - colors=dict(fake=1)) # 'fake' not in conds - assert_raises(ValueError, plot_compare_evokeds, evoked, picks=3, - styles=dict(fake=1)) # 'fake' not in conds - assert_raises(ValueError, plot_compare_evokeds, [[1, 2], [3, 4]], - picks=3) # evoked must contain Evokeds - assert_raises(ValueError, plot_compare_evokeds, evoked, picks=3, - styles=dict(err=1)) # bad styles dict - assert_raises(ValueError, plot_compare_evokeds, evoked, picks=3, - gfp=True) # no single-channel GFP - assert_raises(TypeError, plot_compare_evokeds, evoked, picks=3, - ci='fake') # ci must be float or None - assert_raises(TypeError, plot_compare_evokeds, evoked, picks=3, - show_sensors='a') # show_sensors must be int or bool - contrast["red/stim"] = red - contrast["blue/stim"] = blue + styles={"red/stim": {"linewidth": 1}}, show_sensors=True) + # various bad styles + params = [dict(picks='str'), dict(picks=3, colors=dict(fake=1)), + dict(picks=3, styles=dict(fake=1)), dict(picks=3, gfp=True), + dict(picks=3, show_sensors="a")] + for param in params: + assert_raises(ValueError, plot_compare_evokeds, evoked, **param) + plt.close('all') + # `evoked` must contain Evokeds + assert_raises(ValueError, plot_compare_evokeds, [[1, 2], [3, 4]]) + # `ci` must be float + assert_raises(TypeError, plot_compare_evokeds, contrast, ci='err') + # all-positive ylim + contrast["red/stim"], contrast["blue/stim"] = red, blue plot_compare_evokeds(contrast, picks=[0], colors=['r', 'b'], ylim=dict(mag=(1, 10)), ci=_parametric_ci, truncate_yaxis='max_ticks') + + # sequential colors + evokeds = (evoked, blue, red) + contrasts = {"a{}/b".format(ii): ev for ii, ev in + enumerate(evokeds)} + colors = {"a" + str(ii): ii for ii, _ in enumerate(evokeds)} + contrasts["a1/c"] = evoked.copy() + for split in (True, False): + for linestyles in (["-"], {"b": "-", "c": ":"}): + plot_compare_evokeds(contrasts, colors=colors, picks=[0], + cmap='Reds', split_legend=split, + linestyles=linestyles) red.info["chs"][0]["loc"][:2] = 0 # test plotting channel at zero plot_compare_evokeds(red, picks=[0]) + plt.close('all') + # Hack to test plotting of maxfiltered data evoked_sss = evoked.copy() sss = dict(sss_info=dict(in_order=80, components=np.arange(80))) From 6dc04938edf10a52187691d8c7a91fe612d662c3 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sat, 2 Sep 2017 11:46:37 +0200 Subject: [PATCH 05/41] fix for mpl=1.3 --- mne/viz/evoked.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index b74f4448a84..75a0b693edb 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1683,14 +1683,6 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if (ymin is None) and all_positive: ymin = 0. # 'grad' and GFP are plotted as all-positive -<<<<<<< HEAD -======= - # deal with dict/list of lists and the CI - if not isinstance(ci, np.float): - msg = '"ci" must be float, got {0} instead.' - raise TypeError(msg.format(type(ci))) - ->>>>>>> tests # if we have a dict/list of lists, we compute the grand average and the CI if ci is None: ci = False @@ -1764,17 +1756,20 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, split_legend = cmap is not None if split_legend is True: import matplotlib.lines as mlines - legend_lines = list() + # mpl 1.3 requires us to split it like this. with recent mpl, + # we could use the label parameter of the Line2D + legend_lines, legend_labels = list(), list() if cmap is None: for color in sorted(colors.keys()): - l = mlines.Line2D([], [], linestyle="-", - color=colors[color], label=color) + l = mlines.Line2D([], [], linestyle="-", color=colors[color]) legend_lines.append(l) + legend_labels.append(color) if len(list(linestyles)) > 1: for style, s in linestyles.items(): - l = mlines.Line2D([], [], color='k', linestyle=s, label=style) + l = mlines.Line2D([], [], color='k', linestyle=s) legend_lines.append(l) + legend_labels.append(style) if cmap is not None: for color_value in colors.values(): try: @@ -1920,8 +1915,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, legend_params = dict(loc=show_legend, frameon=True) if split_legend: if len(legend_lines) > 1: - axes.legend(handles=legend_lines, - ncol=1 + (len(legend_lines) // 4), **legend_params) + axes.legend(legend_lines, legend_labels, # see above: mpl 1.3 + ncol=1 + (len(legend_lines) // 4), **legend_params) else: axes.legend(ncol=1 + (len(conditions) // 5), **legend_params) From 81db3a0cba02dcf6c5bb4310a09fc6c10382f02d Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sat, 2 Sep 2017 18:59:48 +0200 Subject: [PATCH 06/41] just pep8 --- 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 75a0b693edb..2d93d138d5f 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1787,7 +1787,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, the_colors = cmapper(np.linspace(0, 1, n_colors)) colors_ = {cond: ind - for cond, ind in zip(colors, color_order)} + for cond, ind in zip(colors, color_order)} colors = dict() for cond in evokeds.keys(): for cond_number, color in colors_.items(): From 3feb2fd109f0cdd60a48f46060d815e3d88b3d79 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sun, 3 Sep 2017 17:40:47 +0200 Subject: [PATCH 07/41] ... --- mne/viz/evoked.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 2d93d138d5f..8da92d60aa1 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1786,8 +1786,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, the_colors = cmapper(np.linspace(0, 1, n_colors)) - colors_ = {cond: ind - for cond, ind in zip(colors, color_order)} + colors_ = {cond: ind for cond, ind in zip(colors, color_order)} colors = dict() for cond in evokeds.keys(): for cond_number, color in colors_.items(): From 8b8731410c0abd4757d9621477008c33a840f36b Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 01:20:06 +0200 Subject: [PATCH 08/41] tutorial --- tutorials/plot_metadata_epochs.py | 75 +++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 8e37eca47c3..d64ff6b71f4 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -69,35 +69,72 @@ # of each epoch. We'll create a new column in our metadata object and use # it to generate averages for many subsets of trials. -# Create a new metadata column +# Create two new metadata columns meta = epochs.metadata -is_concrete = meta["WordFrequency"] > meta["WordFrequency"].median() +is_concrete = meta["Concreteness"] > meta["Concreteness"].median() meta["is_concrete"] = np.where(is_concrete, 'Concrete', 'Abstract') +is_concrete = meta["NumberOfLetters"] > 5 +meta["is_long"] = np.where(is_concrete, 'Long', 'Short') epochs.metadata = meta -# We'll create a dictionary so that we can plot with ``plot_compare_evokeds`` -categories = ["NumberOfLetters", "is_concrete"] -avs = {} -for (cat1, cat2), _ in epochs.metadata.groupby(categories): - query = 'NumberOfLetters == {} and is_concrete == "{}"'.format(cat1, cat2) - this_epochs = epochs[query] - avs["{}/{}".format(cat1, cat2)] = this_epochs.average() +################################################################################ +# Now we can quickly extract (and plot) subsets of the data. For example, to +# look at words split by word length and concreteness: -# Style the plot -colors = np.linspace(0, 1, num=len(avs)) +query = "is_long == '{0}' & is_concrete == '{1}'" +evokeds = dict() +for concreteness in ("Concrete", "Abstract"): + for length in ("Long", "Short"): + subset = epochs[query.format(length, concreteness)] + evokeds["/".join((concreteness, length))] = list(subset.iter_evoked()) + +# For the actual visualisation, we store a number of shared parameters. style_plot = dict( - colors=plt.get_cmap('YlGnBu_r')(colors), - linestyles={'Concrete': '-', 'Abstract': '--'} + colors={"Long": "Crimson", "Short": "Cornflowerblue"}, + linestyles={"Concrete":"-", "Abstract":":"}, + split_legend=True, + ci=.68, + show_sensors=4, + show_legend=3, + truncate_yaxis="max_ticks", + picks=epochs.ch_names.index("Pz"), ) -# Make the plot -ix_plot = mne.pick_channels(epochs.ch_names, ['Pz']) -fig, ax = plt.subplots(figsize=(6, 3)) -fig = mne.viz.evoked.plot_compare_evokeds( - avs, picks=ix_plot, show=False, axes=ax, **style_plot) -ax.legend(loc=[1.05, .1]) +fig, ax = plt.subplots(figsize=(6, 4)) +mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot); +plt.show() + +################################################################################ +# To compare words which are 4, 5, 6, 7 or 8 letters long: + +evokeds = dict() +for nlet in epochs.metadata["NumberOfLetters"].unique(): + evokeds[str(nlet)] = epochs["NumberOfLetters == " + str(nlet)].average() + +style_plot["colors"] = {str(nlet):int(nlet) for nlet in + epochs.metadata["NumberOfLetters"].unique()} +style_plot["cmap"] = "viridis" +del style_plot['linestyles'] + +fig, ax = plt.subplots(figsize=(6, 4)) +mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot); plt.show() +# And finally, for the interaction between concreteness and continuous length in letters: +evokeds = dict() +query = "is_concrete == '{0}' & NumberOfLetters == {1}" +for concreteness in ("Concrete", "Abstract"): + for nlet in epochs.metadata["NumberOfLetters"].unique(): + subset = epochs[query.format(concreteness, nlet)] + evokeds["/".join((concreteness, str(nlet)))] = subset.average() + +style_plot["linestyles"] = {"Concrete":"-", "Abstract":":"} + +fig, ax = plt.subplots(figsize=(6, 4)) +mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot); +plt.show() + + ############################################################################### # .. note:: # From 9488c602261453ff1e08854e5421a8197e12067c Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 13:26:40 +0200 Subject: [PATCH 09/41] change cmap --- tutorials/plot_metadata_epochs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index d64ff6b71f4..23a7e96e5d8 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -113,7 +113,7 @@ style_plot["colors"] = {str(nlet):int(nlet) for nlet in epochs.metadata["NumberOfLetters"].unique()} -style_plot["cmap"] = "viridis" +style_plot["cmap"] = "summer" del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) From c2269b7da31d463ed5f8eb7a8eea2a438850a895 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 13:53:52 +0200 Subject: [PATCH 10/41] fixes --- mne/viz/evoked.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 8da92d60aa1..4f19ab0395f 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1444,7 +1444,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, linestyles=['-'], styles=None, cmap=None, vlines=list((0.,)), ci=0.95, truncate_yaxis=False, truncate_xaxis=True, ylim=dict(), invert_y=False, show_legend=True, show_sensors=None, - split_legend=True, axes=None, title=None, show=True): + split_legend=False, axes=None, title=None, show=True): """Plot evoked time courses for one or multiple channels and conditions. This function is useful for comparing ER[P/F]s at a specific location. It @@ -1561,8 +1561,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, If not False, show a legend. If int, the position of the axes (forwarded to ``mpl_toolkits.axes_grid1.inset_locator.inset_axes``). split_legend : bool - If True, the legend shows color and linestyle separately. Defaults to - True if ``cmap`` is not None, else defaults to False. + If True, the legend shows color and linestyle separately; `colors` must not be + None. Defaults to True if ``cmap`` is not None, else defaults to False. axes : None | `matplotlib.axes.Axes` instance | list of `axes` What axes to plot to. If None, a new axes is created. When plotting multiple channel types, can also be a list of axes, one @@ -1570,9 +1570,6 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, title : None | str If str, will be plotted as figure title. If None, the channel names will be shown. - split_legend : bool - If True, the legend shows color and linestyle separately. Defaults to - True if ``cmap`` is not None, else defaults to False. show : bool If True, show the figure. @@ -1755,6 +1752,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if split_legend is None: split_legend = cmap is not None if split_legend is True: + if colors is None: + raise ValueError("If `split_legend` is True, `colors` must not be None.") import matplotlib.lines as mlines # mpl 1.3 requires us to split it like this. with recent mpl, # we could use the label parameter of the Line2D @@ -1901,7 +1900,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, head_pos = {'center': (0, 0), 'scale': (0.5, 0.5)} pos, outlines = _check_outlines(pos, np.array([1, 1]), head_pos) if not isinstance(show_sensors, (np.int, bool)): - raise TypeError("`show_sensors` must be numeric or bool, not" + + raise ValueError("`show_sensors` must be numeric or bool, not" + str(type(show_sensors))) if show_sensors is True: show_sensors = 2 From 4c49a87e5f6e9ab01984e08f1e7a287e79cadd25 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 14:46:25 +0200 Subject: [PATCH 11/41] fix docstring --- 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 4f19ab0395f..34006d6d33d 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1443,7 +1443,7 @@ def _truncate_yaxis(axes, ymin, ymax, orig_ymin, orig_ymax, fraction, def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, linestyles=['-'], styles=None, cmap=None, vlines=list((0.,)), ci=0.95, truncate_yaxis=False, truncate_xaxis=True, ylim=dict(), - invert_y=False, show_legend=True, show_sensors=None, + invert_y=False, show_sensors=None, show_legend=True, split_legend=False, axes=None, title=None, show=True): """Plot evoked time courses for one or multiple channels and conditions. From 27f43714e3d2f9f145ccc5af48f193cb5bb07ef1 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 15:49:36 +0200 Subject: [PATCH 12/41] pep8 --- mne/viz/evoked.py | 19 +++++++++++-------- mne/viz/tests/test_evoked.py | 3 ++- tutorials/plot_metadata_epochs.py | 22 ++++++++++++---------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 34006d6d33d..9f57fafe22a 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1441,9 +1441,10 @@ def _truncate_yaxis(axes, ymin, ymax, orig_ymin, orig_ymax, fraction, def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, - linestyles=['-'], styles=None, cmap=None, vlines=list((0.,)), - ci=0.95, truncate_yaxis=False, truncate_xaxis=True, ylim=dict(), - invert_y=False, show_sensors=None, show_legend=True, + linestyles=['-'], styles=None, cmap=None, + vlines=list((0.,)), ci=0.95, truncate_yaxis=False, + truncate_xaxis=True, ylim=dict(), invert_y=False, + show_sensors=None, show_legend=True, split_legend=False, axes=None, title=None, show=True): """Plot evoked time courses for one or multiple channels and conditions. @@ -1561,8 +1562,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, If not False, show a legend. If int, the position of the axes (forwarded to ``mpl_toolkits.axes_grid1.inset_locator.inset_axes``). split_legend : bool - If True, the legend shows color and linestyle separately; `colors` must not be - None. Defaults to True if ``cmap`` is not None, else defaults to False. + If True, the legend shows color and linestyle separately; `colors` must + not be None. Defaults to True if ``cmap`` is not None, else defaults to + False. axes : None | `matplotlib.axes.Axes` instance | list of `axes` What axes to plot to. If None, a new axes is created. When plotting multiple channel types, can also be a list of axes, one @@ -1753,7 +1755,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, split_legend = cmap is not None if split_legend is True: if colors is None: - raise ValueError("If `split_legend` is True, `colors` must not be None.") + raise ValueError( + "If `split_legend` is True, `colors` must not be None.") import matplotlib.lines as mlines # mpl 1.3 requires us to split it like this. with recent mpl, # we could use the label parameter of the Line2D @@ -1900,8 +1903,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, head_pos = {'center': (0, 0), 'scale': (0.5, 0.5)} pos, outlines = _check_outlines(pos, np.array([1, 1]), head_pos) if not isinstance(show_sensors, (np.int, bool)): - raise ValueError("`show_sensors` must be numeric or bool, not" + - str(type(show_sensors))) + raise ValueError("show_sensors must be numeric or bool, not" + + str(type(show_sensors))) if show_sensors is True: show_sensors = 2 _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 2e009ad7644..31e3a7fafee 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -162,7 +162,8 @@ def test_plot_evoked(): plot_compare_evokeds(contrast, colors=colors, linestyles=linestyles, picks=[0, 2], vlines=[.01, -.04], invert_y=True, truncate_yaxis=False, ylim=dict(mag=(-10, 10)), - styles={"red/stim": {"linewidth": 1}}, show_sensors=True) + styles={"red/stim": {"linewidth": 1}}, + show_sensors=True) # various bad styles params = [dict(picks='str'), dict(picks=3, colors=dict(fake=1)), dict(picks=3, styles=dict(fake=1)), dict(picks=3, gfp=True), diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 23a7e96e5d8..f291d4dfdab 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -77,7 +77,7 @@ meta["is_long"] = np.where(is_concrete, 'Long', 'Short') epochs.metadata = meta -################################################################################ +############################################################################### # Now we can quickly extract (and plot) subsets of the data. For example, to # look at words split by word length and concreteness: @@ -91,7 +91,7 @@ # For the actual visualisation, we store a number of shared parameters. style_plot = dict( colors={"Long": "Crimson", "Short": "Cornflowerblue"}, - linestyles={"Concrete":"-", "Abstract":":"}, + linestyles={"Concrete": "-", "Abstract": ":"}, split_legend=True, ci=.68, show_sensors=4, @@ -101,26 +101,28 @@ ) fig, ax = plt.subplots(figsize=(6, 4)) -mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot); +mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot) plt.show() -################################################################################ +############################################################################### # To compare words which are 4, 5, 6, 7 or 8 letters long: evokeds = dict() for nlet in epochs.metadata["NumberOfLetters"].unique(): - evokeds[str(nlet)] = epochs["NumberOfLetters == " + str(nlet)].average() + evokeds[str(nlet)] = epochs["NumberOfLetters == " + str(nlet)].average() -style_plot["colors"] = {str(nlet):int(nlet) for nlet in +style_plot["colors"] = {str(nlet): int(nlet) for nlet in epochs.metadata["NumberOfLetters"].unique()} style_plot["cmap"] = "summer" del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) -mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot); +mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot) plt.show() -# And finally, for the interaction between concreteness and continuous length in letters: +############################################################################### +# And finally, for the interaction between concreteness and continuous length +# in letters: evokeds = dict() query = "is_concrete == '{0}' & NumberOfLetters == {1}" for concreteness in ("Concrete", "Abstract"): @@ -128,10 +130,10 @@ subset = epochs[query.format(concreteness, nlet)] evokeds["/".join((concreteness, str(nlet)))] = subset.average() -style_plot["linestyles"] = {"Concrete":"-", "Abstract":":"} +style_plot["linestyles"] = {"Concrete": "-", "Abstract": ":"} fig, ax = plt.subplots(figsize=(6, 4)) -mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot); +mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot) plt.show() From 7c8c36b46df6a76fd738e903dae794d480a9dc8b Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 17:15:22 +0200 Subject: [PATCH 13/41] pep8 --- mne/viz/tests/test_evoked.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 31e3a7fafee..3a6501fb78e 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -162,7 +162,7 @@ def test_plot_evoked(): plot_compare_evokeds(contrast, colors=colors, linestyles=linestyles, picks=[0, 2], vlines=[.01, -.04], invert_y=True, truncate_yaxis=False, ylim=dict(mag=(-10, 10)), - styles={"red/stim": {"linewidth": 1}}, + styles={"red/stim": {"linewidth": 1}}, show_sensors=True) # various bad styles params = [dict(picks='str'), dict(picks=3, colors=dict(fake=1)), From f4d29ac632c5c43c7ac01107fe7311d6bb0592e6 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 23:07:34 +0200 Subject: [PATCH 14/41] heatmap for the cbar --- mne/viz/evoked.py | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 9f57fafe22a..c8b05ac0cbe 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1788,7 +1788,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, the_colors = cmapper(np.linspace(0, 1, n_colors)) - colors_ = {cond: ind for cond, ind in zip(colors, color_order)} + colors_ = {cond: ind for cond, ind in zip(color_conds, color_order)} colors = dict() for cond in evokeds.keys(): for cond_number, color in colors_.items(): @@ -1923,31 +1923,15 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if split_legend and cmap is not None: # plot the colorbar ... complicated cause we don't have a heatmap - import matplotlib as mpl - - colors_l = np.array([n for n in color_conds])[color_order] - colors_m = list() - for k1 in colors_l: - for k2 in colors: - if k1 in k2: - colors_m.append(colors[k2]) - continue - colors_l = list(range(len(colors_l))) - l = plt.cm.jet.from_list(colors_l + [colors_l[-1] + 100], - colors_m + [colors_m[-1]]) - - norm = mpl.colors.BoundaryNorm(all_colors + [all_colors[-1] + 1], l.N) - sm = plt.cm.ScalarMappable(cmap=l, norm=norm) - sm.set_array(colors_l) - - cbar = plt.colorbar(sm, ax=axes) - offset = np.diff(np.concatenate((all_colors, - [all_colors[-1] + 1]))) / 2 - cbar.set_ticks(np.array(all_colors) + offset) - cbar.set_ticklabels(all_colors) - cbar.set_label(cmap_label) - fig.cbar = cbar - + from mpl_toolkits.axes_grid1 import make_axes_locatable + divider = make_axes_locatable(axes) + ax_cb = divider.append_axes("right", size="5%", pad=0.05) + ax_cb.imshow(the_colors[:, np.newaxis, : ], interpolation='none') + ax_cb.set_yticks(np.arange(len(the_colors))) + ax_cb.set_yticklabels(np.array(color_conds)[color_order]) + ax_cb.yaxis.tick_right() + ax_cb.set_xticks(()) + fig.cbar = ax_cb fig.ts_ax = axes plt_show(show) From 5a01d28c55c3362baccf2c5bd15195f77f8348e8 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 20 Oct 2017 23:10:45 +0200 Subject: [PATCH 15/41] trigger circle --- tutorials/plot_metadata_epochs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index f291d4dfdab..ab864ac2ee2 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -113,7 +113,7 @@ style_plot["colors"] = {str(nlet): int(nlet) for nlet in epochs.metadata["NumberOfLetters"].unique()} -style_plot["cmap"] = "summer" +style_plot["cmap"] = "summer_r" del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) From 63db06cdf767a35dcc18f9edfeda323af00f16eb Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sat, 21 Oct 2017 22:24:57 +0200 Subject: [PATCH 16/41] pep8 --- mne/viz/evoked.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index c8b05ac0cbe..621171b8026 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1926,11 +1926,12 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, from mpl_toolkits.axes_grid1 import make_axes_locatable divider = make_axes_locatable(axes) ax_cb = divider.append_axes("right", size="5%", pad=0.05) - ax_cb.imshow(the_colors[:, np.newaxis, : ], interpolation='none') + ax_cb.imshow(the_colors[:, np.newaxis, :], interpolation='none') ax_cb.set_yticks(np.arange(len(the_colors))) ax_cb.set_yticklabels(np.array(color_conds)[color_order]) ax_cb.yaxis.tick_right() ax_cb.set_xticks(()) + ax_cb.set_ylabel(cmap_label) fig.cbar = ax_cb fig.ts_ax = axes From 1b8c75b4233d594a291292df1f00ef4767507738 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sat, 21 Oct 2017 22:55:28 +0200 Subject: [PATCH 17/41] tiny fixes --- mne/viz/evoked.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 621171b8026..11c6d857759 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1484,6 +1484,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "Vis/L", "Vis/R", `colors` can be `dict(Aud='r', Vis='b')` to map both Aud/L and Aud/R to the color red and both Visual conditions to blue. If None (default), a sequence of desaturated colors is used. + If `cmap` is None, `colors` will indicate how each condition will be + colored with reference to its position on the colormap - see `colormap` + below. linestyles : list | dict If a list, will be sequentially and repeatedly used for evoked plot linestyles. @@ -1502,7 +1505,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "Vis/L", "Vis/R", `styles` can be `{"Aud/L":{"linewidth": 1}}` to set the linewidth for "Aud/L" to 1. Note that HED ('/'-separated) tags are not supported. - cmap : None | dict | str | instance of matplotlib.colormap + cmap : None | dict | str | tuple | instance of matplotlib.colormap If not None, plot evoked potentials with colors from a color gradient - either the one provided, or, if 'str', the colormap retrieved from Matplotlib (e.g., 'viridis' or 'Reds'). In that case, the color of @@ -1519,7 +1522,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, cmap='viridis', colors=dict(cond1=1 cond2=2, cond3=3), linestyles={"A": "-", "B": ":"} - If ``cmap`` is a (non-string) iterable of length 2, the first must be + If ``cmap`` is a tuple of length 2, the first item must be a string which will become the colorbar label, and the second one must be a colormap, e.g. :: @@ -1586,7 +1589,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, # set up labels and instances if isinstance(evokeds, Evoked): evokeds = dict(Evoked=evokeds) # title becomes 'Evoked' - elif not isinstance(evokeds, dict): + elif not isinstance(evokeds, dict): # it's assumed to be a list if cmap is not None: if colors is None: colors = dict( @@ -1641,8 +1644,11 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, ch_types = list(set(channel_type(example.info, pick_) for pick_ in picks)) # XXX: could possibly be refactored; plot_joint is doing a similar thing - if any([type_ not in _VALID_CHANNEL_TYPES for type_ in ch_types]): - raise ValueError("Non-data channel picked.") + non_data_channels = [str(pick) for pick, type_ in zip(picks, ch_types) + if type_ not in _VALID_CHANNEL_TYPES] + if len(non_data_channels) > 0: + msg = "Non-data channel(s) {0} were picked." + raise ValueError(msg.format(", ".join(non_data_channels))) if len(ch_types) > 1: warn("Multiple channel types selected, returning one figure per type.") if axes is not None: @@ -1652,7 +1658,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, for ii, t in enumerate(ch_types): picks_ = [idx for idx in picks if channel_type(example.info, idx) == t] - title_ = "GFP, " + t if not title and gfp is True else title + title_ = "GFP, " + t if (not title and (gfp is True)) else title ax_ = axes[ii] if axes is not None else None figs.append( plot_compare_evokeds( @@ -1752,7 +1758,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, cmap_label = "" if split_legend is None: - split_legend = cmap is not None + split_legend = cmap is not None # default to True iff cmap is given if split_legend is True: if colors is None: raise ValueError( @@ -1780,7 +1786,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, raise ValueError("If ``cmap`` is not None, the values of " "``colors`` needs to be numeric. Got " + str(type(color_value))) - cmapper = getattr(plt.cm, cmap, plt.cm.hot) + cmapper = getattr(plt.cm, cmap, plt.cm.summer) color_conds = list(colors.keys()) all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) @@ -1892,6 +1898,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, _setup_ax_spines(axes, vlines, tmin, tmax, invert_y, ymax_bound, unit, truncate_xaxis) + # and now for 3 "legends" .. + # a head plot showing the sensors that are being plotted if show_sensors: try: pos = _auto_topomap_coords( @@ -1910,6 +1918,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, show_sensors, size=20) + # the condition legend if len(conditions) > 1: if show_legend is True: show_legend = 'best' @@ -1921,6 +1930,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, else: axes.legend(ncol=1 + (len(conditions) // 5), **legend_params) + # the colormap, if `cmap` is provided if split_legend and cmap is not None: # plot the colorbar ... complicated cause we don't have a heatmap from mpl_toolkits.axes_grid1 import make_axes_locatable From a414256065220f7c2cc4f29d690ac7e9893cde05 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sun, 22 Oct 2017 01:17:24 +0200 Subject: [PATCH 18/41] coverage --- mne/viz/evoked.py | 5 ++--- mne/viz/tests/test_evoked.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 11c6d857759..79c8f2e346b 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1594,7 +1594,6 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if colors is None: colors = dict( (str(ii + 1), ii) for ii, evoked in enumerate(evokeds)) - colors = {} evokeds = dict((str(ii + 1), evoked) for ii, evoked in enumerate(evokeds)) for cond in evokeds.keys(): @@ -1784,9 +1783,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, float(color_value) except ValueError: raise ValueError("If ``cmap`` is not None, the values of " - "``colors`` needs to be numeric. Got " + + "``colors`` need to be numeric. Got " + str(type(color_value))) - cmapper = getattr(plt.cm, cmap, plt.cm.summer) + cmapper = getattr(plt.cm, cmap, cmap) color_conds = list(colors.keys()) all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 3a6501fb78e..643af51985a 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -173,13 +173,14 @@ def test_plot_evoked(): plt.close('all') # `evoked` must contain Evokeds assert_raises(ValueError, plot_compare_evokeds, [[1, 2], [3, 4]]) - # `ci` must be float + # `ci` must be float or None assert_raises(TypeError, plot_compare_evokeds, contrast, ci='err') # all-positive ylim contrast["red/stim"], contrast["blue/stim"] = red, blue plot_compare_evokeds(contrast, picks=[0], colors=['r', 'b'], ylim=dict(mag=(1, 10)), ci=_parametric_ci, - truncate_yaxis='max_ticks') + truncate_yaxis='max_ticks', show_sensors=False, + show_legend=False) # sequential colors evokeds = (evoked, blue, red) @@ -193,7 +194,11 @@ def test_plot_evoked(): cmap='Reds', split_legend=split, linestyles=linestyles) red.info["chs"][0]["loc"][:2] = 0 # test plotting channel at zero - plot_compare_evokeds(red, picks=[0]) + plot_compare_evokeds(red, picks=[0], ci=lambda x: x.std(1)) + plot_compare_evokeds([red, blue], picks=[0], cmap="summer", ci=None, + split_legend=None) + plot_compare_evokeds([red, blue], cmap=None, split_legend=True) + assert_raises(ValueError, plot_compare_evokeds, [red] * 20) plt.close('all') From 51769c711e499b7596db3ab89bed07811483f24e Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sun, 22 Oct 2017 01:48:22 +0200 Subject: [PATCH 19/41] a few comments and docs --- mne/viz/evoked.py | 16 +++++++++------- tutorials/plot_metadata_epochs.py | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 79c8f2e346b..26770f68d19 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1502,11 +1502,11 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, parameters will be passed to the line plot call of the corresponding condition, overriding defaults. E.g., if evokeds is a dict with the keys "Aud/L", "Aud/R", - "Vis/L", "Vis/R", `styles` can be `{"Aud/L":{"linewidth": 1}}` to set + "Vis/L", "Vis/R", `styles` can be `{"Aud/L": {"linewidth": 1}}` to set the linewidth for "Aud/L" to 1. Note that HED ('/'-separated) tags are not supported. cmap : None | dict | str | tuple | instance of matplotlib.colormap - If not None, plot evoked potentials with colors from a color gradient - + If not None, plot evoked activity with colors from a color gradient - either the one provided, or, if 'str', the colormap retrieved from Matplotlib (e.g., 'viridis' or 'Reds'). In that case, the color of each line depends on ``evokeds`` and ``cmap``. @@ -1743,7 +1743,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "conditions. Condition " + style_ + " was not found in the supplied data.") - # second, color + # third, color # check: is color a list? if (colors is not None and not isinstance(colors, string_types) and not isinstance(colors, dict) and len(colors) > 1): @@ -1756,6 +1756,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, else: cmap_label = "" + # dealing with a split legend if split_legend is None: split_legend = cmap is not None # default to True iff cmap is given if split_legend is True: @@ -1766,17 +1767,18 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, # mpl 1.3 requires us to split it like this. with recent mpl, # we could use the label parameter of the Line2D legend_lines, legend_labels = list(), list() - if cmap is None: + if cmap is None: # ... one set of lines for the colors for color in sorted(colors.keys()): l = mlines.Line2D([], [], linestyle="-", color=colors[color]) legend_lines.append(l) legend_labels.append(color) - - if len(list(linestyles)) > 1: + if len(list(linestyles)) > 1: # ... one set for the linestyle for style, s in linestyles.items(): l = mlines.Line2D([], [], color='k', linestyle=s) legend_lines.append(l) legend_labels.append(style) + + # dealing with continuous colors if cmap is not None: for color_value in colors.values(): try: @@ -1845,7 +1847,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, d = np.sqrt((d * d).mean(axis=-1)) else: d = d.mean(-1) - axes.plot(times, d, zorder=1000, label=condition, **styles[condition]) + axes.plot(times, d, zorder=100, label=condition, **styles[condition]) if any(d > 0) or all_positive: any_positive = True if np.any(d < 0): diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index ab864ac2ee2..fa4ec96df83 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -101,7 +101,7 @@ ) fig, ax = plt.subplots(figsize=(6, 4)) -mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot) +mne.viz.plot_compare_evokeds(evokeds, axes=ax, **style_plot) plt.show() ############################################################################### @@ -117,7 +117,7 @@ del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) -mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot) +mne.viz.plot_compare_evokeds(evokeds, axes=ax, **style_plot) plt.show() ############################################################################### @@ -133,7 +133,7 @@ style_plot["linestyles"] = {"Concrete": "-", "Abstract": ":"} fig, ax = plt.subplots(figsize=(6, 4)) -mne.viz.evoked.plot_compare_evokeds(evokeds, axes=ax, **style_plot) +mne.viz.plot_compare_evokeds(evokeds, axes=ax, **style_plot) plt.show() From eb17427b22b70c9110d5b6f77be02cdfa5148e67 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sun, 22 Oct 2017 04:47:32 +0200 Subject: [PATCH 20/41] fix --- 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 26770f68d19..ff105db8168 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1854,7 +1854,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, any_negative = True # plot the confidence interval - if ci and (gfp is not True): + if ci: ci_ = ci_array[condition] axes.fill_between(times, ci_[0].flatten(), ci_[1].flatten(), zorder=9, color=styles[condition]['c'], alpha=.3) From 5e79013a1ff336a492df412a6d948c9f2196b7e9 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Tue, 24 Oct 2017 00:14:54 +0200 Subject: [PATCH 21/41] tiny stuff --- mne/viz/evoked.py | 11 +++++------ tutorials/plot_visualize_evoked.py | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index ff105db8168..3f16700634e 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1505,11 +1505,10 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "Vis/L", "Vis/R", `styles` can be `{"Aud/L": {"linewidth": 1}}` to set the linewidth for "Aud/L" to 1. Note that HED ('/'-separated) tags are not supported. - cmap : None | dict | str | tuple | instance of matplotlib.colormap - If not None, plot evoked activity with colors from a color gradient - - either the one provided, or, if 'str', the colormap retrieved from - Matplotlib (e.g., 'viridis' or 'Reds'). In that case, the color of - each line depends on ``evokeds`` and ``cmap``. + cmap : None | str | tuple + If not None, plot evoked activity with colors from a color gradient + (indicated by a str referencing a matplotlib colormap - e.g., "viridis" + or "Reds"). If ``evokeds`` is a list and ``colors`` is `None`, the color will depend on the list position. If ``colors`` is a list, it must contain integers where the list positions correspond to ``evokeds``, and the @@ -1524,7 +1523,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, If ``cmap`` is a tuple of length 2, the first item must be a string which will become the colorbar label, and the second one - must be a colormap, e.g. :: + must indicate a colormap, e.g. :: cmap=('conds', 'viridis'), cmap=dict(cond1=1 cond2=2, cond3=3), diff --git a/tutorials/plot_visualize_evoked.py b/tutorials/plot_visualize_evoked.py index aa7364ddcad..18f374d865e 100644 --- a/tutorials/plot_visualize_evoked.py +++ b/tutorials/plot_visualize_evoked.py @@ -149,7 +149,7 @@ pick = evoked_dict["Left/Auditory"].ch_names.index('MEG 1811') mne.viz.plot_compare_evokeds(evoked_dict, picks=pick, colors=colors, - linestyles=linestyles) + linestyles=linestyles, split_legend=True) ############################################################################### # We can also plot the activations as images. The time runs along the x-axis From 9eeb617d6e57a3659e4ccdd013f94b755e3282f5 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Tue, 24 Oct 2017 10:10:00 +0200 Subject: [PATCH 22/41] doc --- 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 3f16700634e..360979d66d4 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1525,7 +1525,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, a string which will become the colorbar label, and the second one must indicate a colormap, e.g. :: - cmap=('conds', 'viridis'), cmap=dict(cond1=1 cond2=2, cond3=3), + cmap=('conds', 'viridis'), colors=dict(cond1=1 cond2=2, cond3=3), vlines : list of int A list of integers corresponding to the positions, in seconds, From 55c7298f93f65c40dcb798343488bb21895b78cf Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Tue, 24 Oct 2017 12:25:55 +0200 Subject: [PATCH 23/41] only my pep8 --- mne/viz/evoked.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 360979d66d4..89006d7e30a 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1768,8 +1768,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, legend_lines, legend_labels = list(), list() if cmap is None: # ... one set of lines for the colors for color in sorted(colors.keys()): - l = mlines.Line2D([], [], linestyle="-", color=colors[color]) - legend_lines.append(l) + line = mlines.Line2D([], [], linestyle="-", + color=colors[color]) + legend_lines.append(line) legend_labels.append(color) if len(list(linestyles)) > 1: # ... one set for the linestyle for style, s in linestyles.items(): From 21833fbee4309d4899b2de487ae218e9bad54dd9 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 27 Oct 2017 15:10:52 +0200 Subject: [PATCH 24/41] rather important fix --- 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 89006d7e30a..f60c6777d5b 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1791,7 +1791,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, color_conds = list(colors.keys()) all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) - color_order = np.array(all_colors).argsort() + color_order = np.array(all_colors).argsort().argsort() the_colors = cmapper(np.linspace(0, 1, n_colors)) From f957146c06c2ffc77a647c0890134719135b394e Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 27 Oct 2017 16:03:11 +0200 Subject: [PATCH 25/41] cbar label --- mne/viz/evoked.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index f60c6777d5b..2cbe5e4b65a 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1791,11 +1791,12 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, color_conds = list(colors.keys()) all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) - color_order = np.array(all_colors).argsort().argsort() + color_order = np.array(all_colors).argsort() + color_indices = color_order.argsort() the_colors = cmapper(np.linspace(0, 1, n_colors)) - colors_ = {cond: ind for cond, ind in zip(color_conds, color_order)} + colors_ = {cond: ind for cond, ind in zip(color_conds, color_indices)} colors = dict() for cond in evokeds.keys(): for cond_number, color in colors_.items(): From 4374c42b2abcbb498776e2810d168cd92526bb2f Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Fri, 27 Oct 2017 23:35:09 +0200 Subject: [PATCH 26/41] another fix --- 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 2cbe5e4b65a..56a4feab899 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1792,7 +1792,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) color_order = np.array(all_colors).argsort() - color_indices = color_order.argsort() + color_indices = color_order.argsort()[::-1] the_colors = cmapper(np.linspace(0, 1, n_colors)) From db4d5611488a39b97b07cfccd7d3501f87fbe739 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Sat, 28 Oct 2017 01:06:09 +0200 Subject: [PATCH 27/41] another fix --- 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 56a4feab899..2cbe5e4b65a 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1792,7 +1792,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, all_colors = [colors[cond] for cond in color_conds] n_colors = len(all_colors) color_order = np.array(all_colors).argsort() - color_indices = color_order.argsort()[::-1] + color_indices = color_order.argsort() the_colors = cmapper(np.linspace(0, 1, n_colors)) From cfb5ce6425b9bc368786fa9829bfef35ebad039c Mon Sep 17 00:00:00 2001 From: Alexandre Gramfort Date: Fri, 3 Nov 2017 13:56:50 +0100 Subject: [PATCH 28/41] cosmits --- mne/viz/evoked.py | 9 ++++----- tutorials/plot_metadata_epochs.py | 29 ++++++++++++++++------------- tutorials/plot_visualize_evoked.py | 3 +++ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 2cbe5e4b65a..2991b1df9aa 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1475,7 +1475,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, Power plotted. gfp : bool If True, the channel type wise GFP is plotted. - If ``picks`` is an empty list (default), this is set to True. + If `picks` is an empty list (default), this is set to True. colors : list | dict | None If a list, will be sequentially used for line colors. If a dict, can map evoked keys or '/'-separated (HED) tags to @@ -1589,10 +1589,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if isinstance(evokeds, Evoked): evokeds = dict(Evoked=evokeds) # title becomes 'Evoked' elif not isinstance(evokeds, dict): # it's assumed to be a list - if cmap is not None: - if colors is None: - colors = dict( - (str(ii + 1), ii) for ii, evoked in enumerate(evokeds)) + if (cmap is not None) and (colors is None): + colors = dict( + (str(ii + 1), ii) for ii, evoked in enumerate(evokeds)) evokeds = dict((str(ii + 1), evoked) for ii, evoked in enumerate(evokeds)) for cond in evokeds.keys(): diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index fa4ec96df83..707da01318e 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -1,4 +1,6 @@ """ +.. _tut_metadata_epochs: + ================================================ Pandas querying and metadata with Epochs objects ================================================ @@ -70,12 +72,12 @@ # it to generate averages for many subsets of trials. # Create two new metadata columns -meta = epochs.metadata -is_concrete = meta["Concreteness"] > meta["Concreteness"].median() -meta["is_concrete"] = np.where(is_concrete, 'Concrete', 'Abstract') -is_concrete = meta["NumberOfLetters"] > 5 -meta["is_long"] = np.where(is_concrete, 'Long', 'Short') -epochs.metadata = meta +metadata = epochs.metadata +is_concrete = metadata["Concreteness"] > metadata["Concreteness"].median() +metadata["is_concrete"] = np.where(is_concrete, 'Concrete', 'Abstract') +is_concrete = metadata["NumberOfLetters"] > 5 +metadata["is_long"] = np.where(is_concrete, 'Long', 'Short') +epochs.metadata = metadata ############################################################################### # Now we can quickly extract (and plot) subsets of the data. For example, to @@ -108,12 +110,13 @@ # To compare words which are 4, 5, 6, 7 or 8 letters long: evokeds = dict() -for nlet in epochs.metadata["NumberOfLetters"].unique(): - evokeds[str(nlet)] = epochs["NumberOfLetters == " + str(nlet)].average() +for n_letters in epochs.metadata["NumberOfLetters"].unique(): + n_letters = str(n_letters) + evokeds[n_letters] = epochs["NumberOfLetters == " + n_letters].average() -style_plot["colors"] = {str(nlet): int(nlet) for nlet in +style_plot["colors"] = {str(n_letters): int(n_letters) for n_letters in epochs.metadata["NumberOfLetters"].unique()} -style_plot["cmap"] = "summer_r" +style_plot["cmap"] = ("Number of letters", "summer_r") del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) @@ -126,9 +129,9 @@ evokeds = dict() query = "is_concrete == '{0}' & NumberOfLetters == {1}" for concreteness in ("Concrete", "Abstract"): - for nlet in epochs.metadata["NumberOfLetters"].unique(): - subset = epochs[query.format(concreteness, nlet)] - evokeds["/".join((concreteness, str(nlet)))] = subset.average() + for n_letters in epochs.metadata["NumberOfLetters"].unique(): + subset = epochs[query.format(concreteness, n_letters)] + evokeds["/".join((concreteness, str(n_letters)))] = subset.average() style_plot["linestyles"] = {"Concrete": "-", "Abstract": ":"} diff --git a/tutorials/plot_visualize_evoked.py b/tutorials/plot_visualize_evoked.py index 18f374d865e..914a333c7c7 100644 --- a/tutorials/plot_visualize_evoked.py +++ b/tutorials/plot_visualize_evoked.py @@ -137,6 +137,9 @@ # with :func:`mne.viz.plot_compare_evokeds`. # The plot is styled with dictionary arguments, again using "/"-separated tags. # We plot a MEG channel with a strong auditory response. +# +# For move advanced plotting using :func:`mne.viz.plot_compare_evokeds` +# see also :ref:`tut_metadata_epochs`. conditions = ["Left Auditory", "Right Auditory", "Left visual", "Right visual"] evoked_dict = dict() for condition in conditions: From c1f8e34b03b2fa792818adffa05b47539ebb48da Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Wed, 8 Nov 2017 13:59:59 -0500 Subject: [PATCH 29/41] address mikolajs comments --- mne/viz/evoked.py | 27 +++++++++++++-------------- tutorials/plot_metadata_epochs.py | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 2991b1df9aa..eb3072ef39b 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1484,8 +1484,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "Vis/L", "Vis/R", `colors` can be `dict(Aud='r', Vis='b')` to map both Aud/L and Aud/R to the color red and both Visual conditions to blue. If None (default), a sequence of desaturated colors is used. - If `cmap` is None, `colors` will indicate how each condition will be - colored with reference to its position on the colormap - see `colormap` + If `cmap` is None, `colors` will indicate how each condition is + colored with reference to its position on the colormap - see `cmap` below. linestyles : list | dict If a list, will be sequentially and repeatedly used for evoked plot @@ -1555,13 +1555,13 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, invert_y : bool If True, negative values are plotted up (as is sometimes done for ERPs out of tradition). Defaults to False. - show_sensors: bool | int | None + show_sensors: bool | int | str | None If not False, channel locations are plotted on a small head circle. - If an int, the position of the axes (forwarded to + If int or str, the position of the axes (forwarded to ``mpl_toolkits.axes_grid1.inset_locator.inset_axes``). If None, defaults to True if ``gfp`` is False, else to False. - show_legend : bool | int - If not False, show a legend. If int, the position of the axes + show_legend : bool | str | int + If not False, show a legend. If int or str, the position of the axes (forwarded to ``mpl_toolkits.axes_grid1.inset_locator.inset_axes``). split_legend : bool If True, the legend shows color and linestyle separately; `colors` must @@ -1614,13 +1614,12 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if isinstance(picks, Integral): picks = [picks] elif len(picks) == 0: - warn("No picks, plotting the GFP ...") gfp = True picks = _pick_data_channels(example.info) - if len(picks) == 0: raise ValueError("No valid channels were found to plot the GFP. " + "Use 'picks' instead to select them manually.") + warn("No picks, plotting the GFP ...") if ylim is None: ylim = dict() @@ -1635,7 +1634,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, else: if not isinstance(picks[0], (int, np.integer)): msg = "'picks' must be int or a list of int, not {0}." - raise ValueError(msg.format(type(picks))) + raise TypeError(msg.format(type(picks))) show_sensors = True if show_sensors is None else show_sensors ch_names = [example.ch_names[pick] for pick in picks] ch_types = list(set(channel_type(example.info, pick_) @@ -1783,8 +1782,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, try: float(color_value) except ValueError: - raise ValueError("If ``cmap`` is not None, the values of " - "``colors`` need to be numeric. Got " + + raise TypeError("If ``cmap`` is not None, the values of " + "``colors`` must be numeric. Got " + str(type(color_value))) cmapper = getattr(plt.cm, cmap, cmap) color_conds = list(colors.keys()) @@ -1911,9 +1910,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, else: head_pos = {'center': (0, 0), 'scale': (0.5, 0.5)} pos, outlines = _check_outlines(pos, np.array([1, 1]), head_pos) - if not isinstance(show_sensors, (np.int, bool)): - raise ValueError("show_sensors must be numeric or bool, not" + - str(type(show_sensors))) + if not isinstance(show_sensors, (np.int, bool, str)): + raise TypeError("show_sensors must be numeric, str or bool, " + "not " + str(type(show_sensors))) if show_sensors is True: show_sensors = 2 _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 707da01318e..106354b0b05 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -109,7 +109,10 @@ ############################################################################### # To compare words which are 4, 5, 6, 7 or 8 letters long: +letters = epochs.metadata["NumberOfLetters"].unique().astype(str) + evokeds = dict() +<<<<<<< HEAD for n_letters in epochs.metadata["NumberOfLetters"].unique(): n_letters = str(n_letters) evokeds[n_letters] = epochs["NumberOfLetters == " + n_letters].average() @@ -117,6 +120,14 @@ style_plot["colors"] = {str(n_letters): int(n_letters) for n_letters in epochs.metadata["NumberOfLetters"].unique()} style_plot["cmap"] = ("Number of letters", "summer_r") +======= +for n_letters in letters: + evokeds[n_letters] = epochs["NumberOfLetters == " + n_letters].average() + +style_plot["colors"] = {n_letters: int(float(n_letters)) + for n_letters in letters} +style_plot["cmap"] = "summer_r" +>>>>>>> address mikolajs comments del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) @@ -129,9 +140,9 @@ evokeds = dict() query = "is_concrete == '{0}' & NumberOfLetters == {1}" for concreteness in ("Concrete", "Abstract"): - for n_letters in epochs.metadata["NumberOfLetters"].unique(): + for n_letters in letters: subset = epochs[query.format(concreteness, n_letters)] - evokeds["/".join((concreteness, str(n_letters)))] = subset.average() + evokeds["/".join((concreteness, n_letters))] = subset.average() style_plot["linestyles"] = {"Concrete": "-", "Abstract": ":"} From e7524a7bdf5f133415c7d38bec1bab8d749cd799 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Wed, 8 Nov 2017 17:03:31 -0500 Subject: [PATCH 30/41] strings for mpl locs --- mne/viz/evoked.py | 14 +++++++++++++- mne/viz/tests/test_evoked.py | 4 +++- tutorials/plot_metadata_epochs.py | 4 ++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index eb3072ef39b..ac7807250ad 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1440,6 +1440,16 @@ def _truncate_yaxis(axes, ymin, ymax, orig_ymin, orig_ymax, fraction, return ymin_bound, ymax_bound +def _check_loc_legal(loc, what): + """Check if a loc is a legal for MPL""" + str_locs = ["best", "right", "center", "upper right", "upper left", + "lower right", "lower left", "center right", "center left", + "upper center", "lower center"] + if not (loc is True or loc in range(1, 11) or loc in str_locs): + raise ValueError(str(loc) + " is not a legal MPL loc, please supply" + "another value for " + what + ".") + + def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, linestyles=['-'], styles=None, cmap=None, vlines=list((0.,)), ci=0.95, truncate_yaxis=False, @@ -1915,13 +1925,15 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, "not " + str(type(show_sensors))) if show_sensors is True: show_sensors = 2 + _check_loc_legal(show_sensors, "show_sensors") _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, show_sensors, size=20) # the condition legend - if len(conditions) > 1: + if len(conditions) > 1 and show_legend is not False: if show_legend is True: show_legend = 'best' + _check_loc_legal(show_legend, "show_legend") legend_params = dict(loc=show_legend, frameon=True) if split_legend: if len(legend_lines) > 1: diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 643af51985a..9df771db2aa 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -165,11 +165,13 @@ def test_plot_evoked(): styles={"red/stim": {"linewidth": 1}}, show_sensors=True) # various bad styles - params = [dict(picks='str'), dict(picks=3, colors=dict(fake=1)), + params = [dict(picks=3, colors=dict(fake=1)), dict(picks=3, styles=dict(fake=1)), dict(picks=3, gfp=True), dict(picks=3, show_sensors="a")] for param in params: + print(params) assert_raises(ValueError, plot_compare_evokeds, evoked, **param) + assert_raises(TypeError, plot_compare_evokeds, evoked, picks='str') plt.close('all') # `evoked` must contain Evokeds assert_raises(ValueError, plot_compare_evokeds, [[1, 2], [3, 4]]) diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 106354b0b05..e8286ca3145 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -96,8 +96,8 @@ linestyles={"Concrete": "-", "Abstract": ":"}, split_legend=True, ci=.68, - show_sensors=4, - show_legend=3, + show_sensors='upper right', + show_legend='lower left', truncate_yaxis="max_ticks", picks=epochs.ch_names.index("Pz"), ) From 5d6d4362843a3b2319143196eb8bc979e833e7a5 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Wed, 8 Nov 2017 17:33:34 -0500 Subject: [PATCH 31/41] pep8 --- mne/viz/evoked.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index ac7807250ad..ba88e33c03e 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1441,7 +1441,7 @@ def _truncate_yaxis(axes, ymin, ymax, orig_ymin, orig_ymax, fraction, def _check_loc_legal(loc, what): - """Check if a loc is a legal for MPL""" + """Check if a loc is a legal for MPL.""" str_locs = ["best", "right", "center", "upper right", "upper left", "lower right", "lower left", "center right", "center left", "upper center", "lower center"] @@ -1782,8 +1782,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, legend_labels.append(color) if len(list(linestyles)) > 1: # ... one set for the linestyle for style, s in linestyles.items(): - l = mlines.Line2D([], [], color='k', linestyle=s) - legend_lines.append(l) + line = mlines.Line2D([], [], color='k', linestyle=s) + legend_lines.append(line) legend_labels.append(style) # dealing with continuous colors @@ -1793,8 +1793,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, float(color_value) except ValueError: raise TypeError("If ``cmap`` is not None, the values of " - "``colors`` must be numeric. Got " + - str(type(color_value))) + "``colors`` must be numeric. Got " + + str(type(color_value))) cmapper = getattr(plt.cm, cmap, cmap) color_conds = list(colors.keys()) all_colors = [colors[cond] for cond in color_conds] From f62ebbaff3030406bb5c01d571faf7f758aa1766 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Wed, 8 Nov 2017 22:51:35 -0500 Subject: [PATCH 32/41] more pep8 --- 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 ba88e33c03e..e2ee407517f 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1922,7 +1922,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, pos, outlines = _check_outlines(pos, np.array([1, 1]), head_pos) if not isinstance(show_sensors, (np.int, bool, str)): raise TypeError("show_sensors must be numeric, str or bool, " - "not " + str(type(show_sensors))) + "not " + str(type(show_sensors))) if show_sensors is True: show_sensors = 2 _check_loc_legal(show_sensors, "show_sensors") From 41eaa4012c533aab0c8dcc25be5a0c2ff406d11c Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 10:41:27 -0600 Subject: [PATCH 33/41] bool ci --- mne/viz/evoked.py | 13 ++++++++----- mne/viz/tests/test_evoked.py | 7 +++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index e2ee407517f..81567a770e7 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1540,7 +1540,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, vlines : list of int A list of integers corresponding to the positions, in seconds, at which to plot dashed vertical lines. - ci : float | callable | None + ci : float | callable | None | bool If not None and ``evokeds`` is a [list/dict] of lists, a shaded confidence interval is drawn around the individual time series. If float, a percentile bootstrap method is used to estimate the confidence @@ -1548,7 +1548,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, .95 (the default), the 95% confidence interval is drawn. If a callable, it must take as its single argument an array (observations x times) and return the upper and lower confidence bands. - If None, no confidence band is plotted. + If None or False, no confidence band is plotted. + If True, the 95% confidence interval is drawn. truncate_yaxis : bool | str If True, the left y axis spine is truncated to reduce visual clutter. If 'max_ticks', the spine is truncated at the minimum and maximum @@ -1678,7 +1679,11 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, ymin, ymax = ylim.get(ch_type, [None, None]) # deal with dict/list of lists and the CI - if ci is not None and not (isinstance(ci, np.float) or callable(ci)): + if ci is None: + ci = False + if ci is True: + ci = .95 + elif ci is not False and not (isinstance(ci, np.float) or callable(ci)): raise TypeError('ci must be float or callable, got ' + str(type(ci))) scaling = _handle_default("scalings")[ch_type] @@ -1695,8 +1700,6 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, ymin = 0. # 'grad' and GFP are plotted as all-positive # if we have a dict/list of lists, we compute the grand average and the CI - if ci is None: - ci = False if not all([isinstance(evoked_, Evoked) for evoked_ in evokeds.values()]): if ci is not False: if callable(ci): diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 9df771db2aa..c757995cddf 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -155,7 +155,7 @@ def test_plot_evoked(): # test a bunch of params at once for evokeds_ in (evoked.copy().pick_types(meg='mag'), contrast, [red, blue], [[red, evoked], [blue, evoked]]): - plot_compare_evokeds(evokeds_, picks=0) # also tests CI + plot_compare_evokeds(evokeds_, picks=0, ci=True) # also tests CI plt.close('all') # test styling + a bunch of other params at once colors, linestyles = dict(red='r', blue='b'), dict(red='--', blue='-') @@ -169,7 +169,6 @@ def test_plot_evoked(): dict(picks=3, styles=dict(fake=1)), dict(picks=3, gfp=True), dict(picks=3, show_sensors="a")] for param in params: - print(params) assert_raises(ValueError, plot_compare_evokeds, evoked, **param) assert_raises(TypeError, plot_compare_evokeds, evoked, picks='str') plt.close('all') @@ -177,7 +176,7 @@ def test_plot_evoked(): assert_raises(ValueError, plot_compare_evokeds, [[1, 2], [3, 4]]) # `ci` must be float or None assert_raises(TypeError, plot_compare_evokeds, contrast, ci='err') - # all-positive ylim + # test all-positive ylim contrast["red/stim"], contrast["blue/stim"] = red, blue plot_compare_evokeds(contrast, picks=[0], colors=['r', 'b'], ylim=dict(mag=(1, 10)), ci=_parametric_ci, @@ -194,7 +193,7 @@ def test_plot_evoked(): for linestyles in (["-"], {"b": "-", "c": ":"}): plot_compare_evokeds(contrasts, colors=colors, picks=[0], cmap='Reds', split_legend=split, - linestyles=linestyles) + linestyles=linestyles, ci=False) red.info["chs"][0]["loc"][:2] = 0 # test plotting channel at zero plot_compare_evokeds(red, picks=[0], ci=lambda x: x.std(1)) plot_compare_evokeds([red, blue], picks=[0], cmap="summer", ci=None, From 66bd908f0491c5a25131a120772699cc919a2bdc Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 10:49:46 -0600 Subject: [PATCH 34/41] speed up tests a bit --- mne/viz/tests/test_evoked.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index c757995cddf..966b5cd09b5 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -135,8 +135,9 @@ def test_plot_evoked(): # plot_compare_evokeds: test condition contrast, CI, color assignment plot_compare_evokeds(evoked.copy().pick_types(meg='mag')) - plot_compare_evokeds(evoked.copy().pick_types(meg='grad'), - picks=[1, 2]) + plot_compare_evokeds( + evoked.copy().pick_types(meg='grad'), picks=[1, 2], + show_sensors="upper right", show_legend="upper left") evoked.rename_channels({'MEG 2142': "MEG 1642"}) assert len(plot_compare_evokeds(evoked)) == 2 colors = dict(red='r', blue='b') @@ -191,9 +192,10 @@ def test_plot_evoked(): contrasts["a1/c"] = evoked.copy() for split in (True, False): for linestyles in (["-"], {"b": "-", "c": ":"}): - plot_compare_evokeds(contrasts, colors=colors, picks=[0], - cmap='Reds', split_legend=split, - linestyles=linestyles, ci=False) + plot_compare_evokeds( + contrasts, colors=colors, picks=[0], cmap='Reds', + split_legend=split, linestyles=linestyles, + ci=False, show_sensors=False) red.info["chs"][0]["loc"][:2] = 0 # test plotting channel at zero plot_compare_evokeds(red, picks=[0], ci=lambda x: x.std(1)) plot_compare_evokeds([red, blue], picks=[0], cmap="summer", ci=None, From 2b2dc534b9b1aa679780437e55e3742399af0641 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 13:27:37 -0600 Subject: [PATCH 35/41] fix bad rebase --- tutorials/plot_metadata_epochs.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index e8286ca3145..164f18eb9e5 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -112,22 +112,12 @@ letters = epochs.metadata["NumberOfLetters"].unique().astype(str) evokeds = dict() -<<<<<<< HEAD -for n_letters in epochs.metadata["NumberOfLetters"].unique(): - n_letters = str(n_letters) - evokeds[n_letters] = epochs["NumberOfLetters == " + n_letters].average() - -style_plot["colors"] = {str(n_letters): int(n_letters) for n_letters in - epochs.metadata["NumberOfLetters"].unique()} -style_plot["cmap"] = ("Number of letters", "summer_r") -======= for n_letters in letters: evokeds[n_letters] = epochs["NumberOfLetters == " + n_letters].average() style_plot["colors"] = {n_letters: int(float(n_letters)) for n_letters in letters} -style_plot["cmap"] = "summer_r" ->>>>>>> address mikolajs comments +style_plot["cmap"] = ("Number of Letters", "viridis") del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) From fd23602fd0320a8e65bb9491880e1ad59c10d6f2 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 14:10:40 -0600 Subject: [PATCH 36/41] fix legend default --- mne/viz/evoked.py | 22 +++++++++++++--------- tutorials/plot_metadata_epochs.py | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 81567a770e7..25973cfdbd9 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1440,14 +1440,18 @@ def _truncate_yaxis(axes, ymin, ymax, orig_ymin, orig_ymax, fraction, return ymin_bound, ymax_bound -def _check_loc_legal(loc, what): +def _check_loc_legal(loc, what='your choice'): """Check if a loc is a legal for MPL.""" - str_locs = ["best", "right", "center", "upper right", "upper left", - "lower right", "lower left", "center right", "center left", - "upper center", "lower center"] - if not (loc is True or loc in range(1, 11) or loc in str_locs): + true_default = {"show_legend": 3, "show_sensors": 4}.get(what, 1) + loc_dict = {'upper right': 1, 'upper left': 2, 'lower left': 3, + 'lower right': 4, 'right': 5, 'center left': 6, + 'center right': 7, 'lower center': 8, 'upper center': 9, + 'center': 10, True: true_default} + loc_ = loc_dict.get(loc, loc) + if loc_ not in range(11): raise ValueError(str(loc) + " is not a legal MPL loc, please supply" "another value for " + what + ".") + return loc_ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, @@ -1926,9 +1930,9 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if not isinstance(show_sensors, (np.int, bool, str)): raise TypeError("show_sensors must be numeric, str or bool, " "not " + str(type(show_sensors))) - if show_sensors is True: - show_sensors = 2 - _check_loc_legal(show_sensors, "show_sensors") +# if show_sensors is True: +# show_sensors = 2 + show_sensors = _check_loc_legal(show_sensors, "show_sensors") _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, show_sensors, size=20) @@ -1936,7 +1940,7 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if len(conditions) > 1 and show_legend is not False: if show_legend is True: show_legend = 'best' - _check_loc_legal(show_legend, "show_legend") + show_legend = _check_loc_legal(show_legend, "show_legend") legend_params = dict(loc=show_legend, frameon=True) if split_legend: if len(legend_lines) > 1: diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 164f18eb9e5..87a4657cb3a 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -96,7 +96,7 @@ linestyles={"Concrete": "-", "Abstract": ":"}, split_legend=True, ci=.68, - show_sensors='upper right', + show_sensors='lower right', show_legend='lower left', truncate_yaxis="max_ticks", picks=epochs.ch_names.index("Pz"), @@ -117,7 +117,7 @@ style_plot["colors"] = {n_letters: int(float(n_letters)) for n_letters in letters} -style_plot["cmap"] = ("Number of Letters", "viridis") +style_plot["cmap"] = ("Number of Letters", "viridis_r") del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) From fb37f87e1f6f93eeec9c90220121e67bd5e146ec Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 14:26:25 -0600 Subject: [PATCH 37/41] *curses* --- mne/viz/evoked.py | 4 ---- tutorials/plot_metadata_epochs.py | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 25973cfdbd9..3eba3f5fcbb 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1930,16 +1930,12 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if not isinstance(show_sensors, (np.int, bool, str)): raise TypeError("show_sensors must be numeric, str or bool, " "not " + str(type(show_sensors))) -# if show_sensors is True: -# show_sensors = 2 show_sensors = _check_loc_legal(show_sensors, "show_sensors") _plot_legend(pos, ["k" for pick in picks], axes, list(), outlines, show_sensors, size=20) # the condition legend if len(conditions) > 1 and show_legend is not False: - if show_legend is True: - show_legend = 'best' show_legend = _check_loc_legal(show_legend, "show_legend") legend_params = dict(loc=show_legend, frameon=True) if split_legend: diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 87a4657cb3a..8d8d8c74285 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -117,7 +117,7 @@ style_plot["colors"] = {n_letters: int(float(n_letters)) for n_letters in letters} -style_plot["cmap"] = ("Number of Letters", "viridis_r") +style_plot["cmap"] = ("# of Letters", "viridis_r") del style_plot['linestyles'] fig, ax = plt.subplots(figsize=(6, 4)) From 4c24b4de069cf028b3cca226c079db5d5501429c Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 15:23:00 -0600 Subject: [PATCH 38/41] fix plot_epochs_image --- mne/viz/epochs.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mne/viz/epochs.py b/mne/viz/epochs.py index 0c7a0da45be..110d0d9917d 100644 --- a/mne/viz/epochs.py +++ b/mne/viz/epochs.py @@ -160,6 +160,9 @@ def plot_epochs_image(epochs, picks=None, sigma=0., vmin=None, group_by = "type" combine = "gfp" + if combine is not None: + ts_args["show_sensors"] = False + if picks is None: picks = pick_types(epochs.info, meg=True, eeg=True, ref_meg=False, exclude='bads') From 06a285ac9690a7bd572a9357690af1aea7b76943 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 17:13:05 -0600 Subject: [PATCH 39/41] pep --- mne/viz/tests/test_evoked.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py index 966b5cd09b5..f1163cf7084 100644 --- a/mne/viz/tests/test_evoked.py +++ b/mne/viz/tests/test_evoked.py @@ -136,7 +136,7 @@ def test_plot_evoked(): # plot_compare_evokeds: test condition contrast, CI, color assignment plot_compare_evokeds(evoked.copy().pick_types(meg='mag')) plot_compare_evokeds( - evoked.copy().pick_types(meg='grad'), picks=[1, 2], + evoked.copy().pick_types(meg='grad'), picks=[1, 2], show_sensors="upper right", show_legend="upper left") evoked.rename_channels({'MEG 2142': "MEG 1642"}) assert len(plot_compare_evokeds(evoked)) == 2 @@ -195,7 +195,7 @@ def test_plot_evoked(): plot_compare_evokeds( contrasts, colors=colors, picks=[0], cmap='Reds', split_legend=split, linestyles=linestyles, - ci=False, show_sensors=False) + ci=False, show_sensors=False) red.info["chs"][0]["loc"][:2] = 0 # test plotting channel at zero plot_compare_evokeds(red, picks=[0], ci=lambda x: x.std(1)) plot_compare_evokeds([red, blue], picks=[0], cmap="summer", ci=None, From a5fc30a190335ce7dd6f9ba8ebe38f20ae62dfdd Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Mon, 13 Nov 2017 23:01:24 -0600 Subject: [PATCH 40/41] fixes --- mne/viz/evoked.py | 4 +--- tutorials/plot_metadata_epochs.py | 1 - tutorials/plot_visualize_evoked.py | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index 3eba3f5fcbb..ef10e0e981a 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -15,6 +15,7 @@ from numbers import Integral import numpy as np +import matplotlib.lines as mlines from ..io.pick import (channel_type, pick_types, _picks_by_type, _pick_data_channels, _VALID_CHANNEL_TYPES) @@ -1777,7 +1778,6 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if colors is None: raise ValueError( "If `split_legend` is True, `colors` must not be None.") - import matplotlib.lines as mlines # mpl 1.3 requires us to split it like this. with recent mpl, # we could use the label parameter of the Line2D legend_lines, legend_labels = list(), list() @@ -1957,8 +1957,6 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, ax_cb.yaxis.tick_right() ax_cb.set_xticks(()) ax_cb.set_ylabel(cmap_label) - fig.cbar = ax_cb - fig.ts_ax = axes plt_show(show) return fig diff --git a/tutorials/plot_metadata_epochs.py b/tutorials/plot_metadata_epochs.py index 8d8d8c74285..99bee1902b0 100644 --- a/tutorials/plot_metadata_epochs.py +++ b/tutorials/plot_metadata_epochs.py @@ -1,5 +1,4 @@ """ -.. _tut_metadata_epochs: ================================================ Pandas querying and metadata with Epochs objects diff --git a/tutorials/plot_visualize_evoked.py b/tutorials/plot_visualize_evoked.py index 914a333c7c7..be9eb254cd9 100644 --- a/tutorials/plot_visualize_evoked.py +++ b/tutorials/plot_visualize_evoked.py @@ -139,7 +139,7 @@ # We plot a MEG channel with a strong auditory response. # # For move advanced plotting using :func:`mne.viz.plot_compare_evokeds` -# see also :ref:`tut_metadata_epochs`. +# see also :ref:`metadata_epochs`. conditions = ["Left Auditory", "Right Auditory", "Left visual", "Right visual"] evoked_dict = dict() for condition in conditions: From b9afa02636fba4cc5a320d8d5b94fe2a81f86be3 Mon Sep 17 00:00:00 2001 From: jona-sassenhagen Date: Tue, 14 Nov 2017 16:05:24 -0600 Subject: [PATCH 41/41] comment --- mne/viz/evoked.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py index ef10e0e981a..a183f35afea 100644 --- a/mne/viz/evoked.py +++ b/mne/viz/evoked.py @@ -1689,7 +1689,8 @@ def plot_compare_evokeds(evokeds, picks=list(), gfp=False, colors=None, if ci is True: ci = .95 elif ci is not False and not (isinstance(ci, np.float) or callable(ci)): - raise TypeError('ci must be float or callable, got ' + str(type(ci))) + raise TypeError('ci must be None, bool, float or callable, got ' + + str(type(ci))) scaling = _handle_default("scalings")[ch_type] unit = _handle_default("units")[ch_type]