# Buggy code
def _plot_lines(
    data,
    info,
    picks,
    fig,
    axes,
    spatial_colors,
    unit,
    units,
    scalings,
    hline,
    gfp,
    types,
    zorder,
    xlim,
    ylim,
    times,
    bad_ch_idx,
    titles,
    ch_types_used,
    selectable,
    psd,
    line_alpha,
):
    """Plot data as butterfly plot."""
    from matplotlib import patheffects
    from matplotlib.widgets import SpanSelector

    texts = list()
    idxs = list()
    lines = list()
    path_effects = [patheffects.withStroke(linewidth=2, foreground="w", alpha=0.75)]
    gfp_path_effects = [patheffects.withStroke(linewidth=5, foreground="w", alpha=0.75)]
    if selectable:
        selectables = np.ones(len(ch_types_used), dtype=bool)
        for type_idx, this_type in enumerate(ch_types_used):
            idx = picks[types == this_type]
            if len(idx) < 2 or (this_type == "grad" and len(idx) < 4):
                # prevent unnecessary warnings for e.g. EOG
                if this_type in _DATA_CH_TYPES_SPLIT:
                    logger.info(
                        "Need more than one channel to make "
                        "topography for %s. Disabling interactivity." % (this_type,)
                    )
                selectables[type_idx] = False

    if selectable:
        # Parameters for butterfly interactive plots
        params = dict(
            axes=axes,
            texts=texts,
            lines=lines,
            ch_names=info["ch_names"],
            idxs=idxs,
            need_draw=False,
            path_effects=path_effects,
        )
        fig.canvas.mpl_connect("pick_event", partial(_butterfly_onpick, params=params))
        fig.canvas.mpl_connect(
            "button_press_event", partial(_butterfly_on_button_press, params=params)
        )
    for ax, this_type in zip(axes, ch_types_used):
        line_list = list()  # 'line_list' contains the lines for this axes
        if unit is False:
            this_scaling = 1.0
            ch_unit = "NA"  # no unit
        else:
            this_scaling = 1.0 if scalings is None else scalings[this_type]
            ch_unit = units[this_type]
        idx = list(picks[types == this_type])
        idxs.append(idx)

        if len(idx) > 0:
            # Set amplitude scaling
            D = this_scaling * data[idx, :]
            gfp_only = isinstance(gfp, string_types) and gfp == "only"
            if not gfp_only:
                chs = [info["chs"][i] for i in idx]
                locs3d = np.array([ch["loc"][:3] for ch in chs])
                if spatial_colors is True and (locs3d == 0).all():
                    warn("Channel locations not available. Disabling spatial colors.")
                    spatial_colors = selectable = False
                if spatial_colors is True and len(idx) != 1:
                    x, y, z = locs3d.T
                    colors = _rgb(x, y, z)
                    _handle_spatial_colors(colors, info, idx, this_type, psd, ax)
                else:
                    if isinstance(spatial_colors, (tuple, string_types)):
                        col = [spatial_colors]
                    else:
                        col = ["k"]
                    colors = col * len(idx)
                    for i in bad_ch_idx:
                        if i in idx:
                            colors[idx.index(i)] = "r"

                if zorder == "std":
                    # find the channels with the least activity
                    # to map them in front of the more active ones
                    z_ord = D.std(axis=1).argsort()
                elif zorder == "unsorted":
                    z_ord = list(range(D.shape[0]))
                elif not callable(zorder):
                    error = '`zorder` must be a function, "std" or "unsorted", not {0}.'
                    raise TypeError(error.format(type(zorder)))
                else:
                    z_ord = zorder(D)

                # plot channels
                for ch_idx, z in enumerate(z_ord):
                    line_list.append(
                        ax.plot(
                            times,
                            D[ch_idx],
                            picker=3.0,
                            zorder=z + 1 if spatial_colors is True else 1,
                            color=colors[ch_idx],
                            alpha=line_alpha,
                            linewidth=0.5,
                        )[0]
                    )

            if gfp:  # 'only' or boolean True
                gfp_color = 3 * (0.0,) if spatial_colors is True else (0.0, 1.0, 0.0)
                this_gfp = np.sqrt((D * D).mean(axis=0))
                this_ylim = (
                    ax.get_ylim()
                    if (ylim is None or this_type not in ylim.keys())
                    else ylim[this_type]
                )
                if gfp_only:
                    y_offset = 0.0
                else:
                    y_offset = this_ylim[0]
                this_gfp += y_offset
                ax.fill_between(
                    times,
                    y_offset,
                    this_gfp,
                    color="none",
                    facecolor=gfp_color,
                    zorder=1,
                    alpha=0.2,
                )
                line_list.append(
                    ax.plot(
                        times, this_gfp, color=gfp_color, zorder=3, alpha=line_alpha
                    )[0]
                )
                ax.text(
                    times[0] + 0.01 * (times[-1] - times[0]),
                    this_gfp[0] + 0.05 * np.diff(ax.get_ylim())[0],
                    "GFP",
                    zorder=4,
                    color=gfp_color,
                    path_effects=gfp_path_effects,
                )
            for ii, line in zip(idx, line_list):
                if ii in bad_ch_idx:
                    line.set_zorder(2)
                    if spatial_colors is True:
                        line.set_linestyle("--")
            ax.set_ylabel(ch_unit)
            # for old matplotlib, we actually need this to have a bounding
            # box (!), so we have to put some valid text here, change
            # alpha and path effects later
            texts.append(
                ax.text(
                    0,
                    0,
                    "blank",
                    zorder=3,
                    verticalalignment="baseline",
                    horizontalalignment="left",
                    fontweight="bold",
                    alpha=0,
                )
            )

            if xlim is not None:
                if xlim == "tight":
                    xlim = (times[0], times[-1])
                ax.set_xlim(xlim)
            if ylim is not None and this_type in ylim:
                ax.set_ylim(ylim[this_type])
            ax.set_title(titles[this_type] + " (%d channel%s)" % (len(D), _pl(D)))

            if hline is not None:
                for h in hline:
                    c = "grey" if spatial_colors is True else "r"
                    ax.axhline(h, linestyle="--", linewidth=2, color=c)
        lines.append(line_list)
    if selectable:
        import matplotlib.pyplot as plt

        for ax in np.array(axes)[selectables]:
            if len(ax.lines) == 1:
                continue
            text = ax.annotate(
                "Loading...",
                xy=(0.01, 0.1),
                xycoords="axes fraction",
                fontsize=20,
                color="green",
                zorder=3,
            )
            text.set_visible(False)
            callback_onselect = partial(
                _line_plot_onselect,
                ch_types=ch_types_used,
                info=info,
                data=data,
                times=times,
                text=text,
                psd=psd,
            )
            blit = False if plt.get_backend() == "MacOSX" else True
            minspan = 0 if len(times) < 2 else times[1] - times[0]
            ax._span_selector = SpanSelector(
                ax,
                callback_onselect,
                "horizontal",
                minspan=minspan,
                useblit=blit,
                rectprops=dict(alpha=0.5, facecolor="red"),
            )


# Traceback (IndexError)
/miniconda3/envs/mne/lib/python2.7/site-packages/mne/viz/evoked.py:433: VisibleDeprecationWarning: boolean index did not match indexed array along dimension 0; dimension is 1 but corresponding boolean dimension is 2
for ax in np.array(axes)[selectables]:
Traceback (most recent call last):
File "psd_bug.py", line 10, in <module>
ax = raw.plot_psd(picks=picks, dB=False, show=True, average=False)
File "<string>", line 2, in plot_psd
File "/home/erik/miniconda3/envs/mne/lib/python2.7/site-packages/mne/utils.py", line 728, in verbose
return function(*args, **kwargs)
File "/home/erik/miniconda3/envs/mne/lib/python2.7/site-packages/mne/io/base.py", line 1779, in plot_psd
xscale=xscale, reject_by_annotation=reject_by_annotation)
File "<string>", line 2, in plot_raw_psd
File "/home/erik/miniconda3/envs/mne/lib/python2.7/site-packages/mne/utils.py", line 728, in verbose
return function(*args, **kwargs)
File "/home/erik/miniconda3/envs/mne/lib/python2.7/site-packages/mne/viz/raw.py", line 812, in plot_raw_psd
line_alpha=line_alpha)
File "/home/erik/miniconda3/envs/mne/lib/python2.7/site-packages/mne/viz/evoked.py", line 433, in _plot_lines
for ax in np.array(axes)[selectables]:
IndexError: index 1 is out of bounds for axis 1 with size 1

# Fixed code
def _plot_lines(
    data,
    info,
    picks,
    fig,
    axes,
    spatial_colors,
    unit,
    units,
    scalings,
    hline,
    gfp,
    types,
    zorder,
    xlim,
    ylim,
    times,
    bad_ch_idx,
    titles,
    ch_types_used,
    selectable,
    psd,
    line_alpha,
):
    """Plot data as butterfly plot."""
    from matplotlib import patheffects
    from matplotlib.widgets import SpanSelector

    assert len(axes) == len(ch_types_used)
    texts = list()
    idxs = list()
    lines = list()
    path_effects = [patheffects.withStroke(linewidth=2, foreground="w", alpha=0.75)]
    gfp_path_effects = [patheffects.withStroke(linewidth=5, foreground="w", alpha=0.75)]
    if selectable:
        selectables = np.ones(len(ch_types_used), dtype=bool)
        for type_idx, this_type in enumerate(ch_types_used):
            idx = picks[types == this_type]
            if len(idx) < 2 or (this_type == "grad" and len(idx) < 4):
                # prevent unnecessary warnings for e.g. EOG
                if this_type in _DATA_CH_TYPES_SPLIT:
                    logger.info(
                        "Need more than one channel to make "
                        "topography for %s. Disabling interactivity." % (this_type,)
                    )
                selectables[type_idx] = False

    if selectable:
        # Parameters for butterfly interactive plots
        params = dict(
            axes=axes,
            texts=texts,
            lines=lines,
            ch_names=info["ch_names"],
            idxs=idxs,
            need_draw=False,
            path_effects=path_effects,
        )
        fig.canvas.mpl_connect("pick_event", partial(_butterfly_onpick, params=params))
        fig.canvas.mpl_connect(
            "button_press_event", partial(_butterfly_on_button_press, params=params)
        )
    for ax, this_type in zip(axes, ch_types_used):
        line_list = list()  # 'line_list' contains the lines for this axes
        if unit is False:
            this_scaling = 1.0
            ch_unit = "NA"  # no unit
        else:
            this_scaling = 1.0 if scalings is None else scalings[this_type]
            ch_unit = units[this_type]
        idx = list(picks[types == this_type])
        idxs.append(idx)

        if len(idx) > 0:
            # Set amplitude scaling
            D = this_scaling * data[idx, :]
            gfp_only = isinstance(gfp, string_types) and gfp == "only"
            if not gfp_only:
                chs = [info["chs"][i] for i in idx]
                locs3d = np.array([ch["loc"][:3] for ch in chs])
                if spatial_colors is True and (locs3d == 0).all():
                    warn("Channel locations not available. Disabling spatial colors.")
                    spatial_colors = selectable = False
                if spatial_colors is True and len(idx) != 1:
                    x, y, z = locs3d.T
                    colors = _rgb(x, y, z)
                    _handle_spatial_colors(colors, info, idx, this_type, psd, ax)
                else:
                    if isinstance(spatial_colors, (tuple, string_types)):
                        col = [spatial_colors]
                    else:
                        col = ["k"]
                    colors = col * len(idx)
                    for i in bad_ch_idx:
                        if i in idx:
                            colors[idx.index(i)] = "r"

                if zorder == "std":
                    # find the channels with the least activity
                    # to map them in front of the more active ones
                    z_ord = D.std(axis=1).argsort()
                elif zorder == "unsorted":
                    z_ord = list(range(D.shape[0]))
                elif not callable(zorder):
                    error = '`zorder` must be a function, "std" or "unsorted", not {0}.'
                    raise TypeError(error.format(type(zorder)))
                else:
                    z_ord = zorder(D)

                # plot channels
                for ch_idx, z in enumerate(z_ord):
                    line_list.append(
                        ax.plot(
                            times,
                            D[ch_idx],
                            picker=3.0,
                            zorder=z + 1 if spatial_colors is True else 1,
                            color=colors[ch_idx],
                            alpha=line_alpha,
                            linewidth=0.5,
                        )[0]
                    )

            if gfp:  # 'only' or boolean True
                gfp_color = 3 * (0.0,) if spatial_colors is True else (0.0, 1.0, 0.0)
                this_gfp = np.sqrt((D * D).mean(axis=0))
                this_ylim = (
                    ax.get_ylim()
                    if (ylim is None or this_type not in ylim.keys())
                    else ylim[this_type]
                )
                if gfp_only:
                    y_offset = 0.0
                else:
                    y_offset = this_ylim[0]
                this_gfp += y_offset
                ax.fill_between(
                    times,
                    y_offset,
                    this_gfp,
                    color="none",
                    facecolor=gfp_color,
                    zorder=1,
                    alpha=0.2,
                )
                line_list.append(
                    ax.plot(
                        times, this_gfp, color=gfp_color, zorder=3, alpha=line_alpha
                    )[0]
                )
                ax.text(
                    times[0] + 0.01 * (times[-1] - times[0]),
                    this_gfp[0] + 0.05 * np.diff(ax.get_ylim())[0],
                    "GFP",
                    zorder=4,
                    color=gfp_color,
                    path_effects=gfp_path_effects,
                )
            for ii, line in zip(idx, line_list):
                if ii in bad_ch_idx:
                    line.set_zorder(2)
                    if spatial_colors is True:
                        line.set_linestyle("--")
            ax.set_ylabel(ch_unit)
            # for old matplotlib, we actually need this to have a bounding
            # box (!), so we have to put some valid text here, change
            # alpha and path effects later
            texts.append(
                ax.text(
                    0,
                    0,
                    "blank",
                    zorder=3,
                    verticalalignment="baseline",
                    horizontalalignment="left",
                    fontweight="bold",
                    alpha=0,
                )
            )

            if xlim is not None:
                if xlim == "tight":
                    xlim = (times[0], times[-1])
                ax.set_xlim(xlim)
            if ylim is not None and this_type in ylim:
                ax.set_ylim(ylim[this_type])
            ax.set_title(titles[this_type] + " (%d channel%s)" % (len(D), _pl(D)))

            if hline is not None:
                for h in hline:
                    c = "grey" if spatial_colors is True else "r"
                    ax.axhline(h, linestyle="--", linewidth=2, color=c)
        lines.append(line_list)
    if selectable:
        import matplotlib.pyplot as plt

        for ax in np.array(axes)[selectables]:
            if len(ax.lines) == 1:
                continue
            text = ax.annotate(
                "Loading...",
                xy=(0.01, 0.1),
                xycoords="axes fraction",
                fontsize=20,
                color="green",
                zorder=3,
            )
            text.set_visible(False)
            callback_onselect = partial(
                _line_plot_onselect,
                ch_types=ch_types_used,
                info=info,
                data=data,
                times=times,
                text=text,
                psd=psd,
            )
            blit = False if plt.get_backend() == "MacOSX" else True
            minspan = 0 if len(times) < 2 else times[1] - times[0]
            ax._span_selector = SpanSelector(
                ax,
                callback_onselect,
                "horizontal",
                minspan=minspan,
                useblit=blit,
                rectprops=dict(alpha=0.5, facecolor="red"),
            )