Ejemplo n.º 1
0
def test_plot_raw_child_figures(raw):
    """Test spawning and closing of child figures."""
    raw.info['lowpass'] = 10.  # allow heavy decim during plotting
    plt.close('all')  # make sure we start clean
    assert len(plt.get_fignums()) == 0
    fig = raw.plot()
    assert len(plt.get_fignums()) == 1
    # test child fig toggles
    _child_fig_helper(fig, '?', 'fig_help')
    _child_fig_helper(fig, 'j', 'fig_proj')
    _child_fig_helper(fig, 'a', 'fig_annotation')
    assert len(fig.mne.child_figs) == 0  # make sure the helper cleaned up
    assert len(plt.get_fignums()) == 1
    # test right-click → channel location popup
    fig.canvas.draw()
    _click_ch_name(fig, ch_index=2, button=3)
    assert len(fig.mne.child_figs) == 1
    assert len(plt.get_fignums()) == 2
    fig.mne.child_figs[0].canvas.key_press_event('escape')
    _close_event(fig.mne.child_figs[0])
    assert len(plt.get_fignums()) == 1
    # test right-click on non-data channel
    ix = raw.get_channel_types().index('ias')  # find the shielding channel
    trace_ix = fig.mne.ch_order.tolist().index(ix)  # get its plotting position
    assert len(fig.mne.child_figs) == 0
    assert len(plt.get_fignums()) == 1
    fig.canvas.draw()
    _click_ch_name(fig, ch_index=trace_ix, button=3)  # should be no-op
    assert len(fig.mne.child_figs) == 0
    assert len(plt.get_fignums()) == 1
    # test resize of main window
    width, height = fig.canvas.manager.canvas.get_width_height()
    fig.canvas.manager.canvas.resize(width // 2, height // 2)
    plt.close('all')
Ejemplo n.º 2
0
def test_plot_raw_selection(raw):
    """Test selection mode of plot_raw()."""
    raw.info['lowpass'] = 10.  # allow heavy decim during plotting
    plt.close('all')           # ensure all are closed
    assert len(plt.get_fignums()) == 0
    fig = raw.plot(group_by='selection', proj=False)
    assert len(plt.get_fignums()) == 2
    sel_fig = fig.mne.fig_selection
    buttons = sel_fig.mne.radio_ax.buttons
    assert sel_fig is not None
    # test changing selection with arrow keys
    sel_dict = fig.mne.ch_selections
    assert len(fig.mne.traces) == len(sel_dict['Left-temporal'])  # 6
    sel_fig.canvas.key_press_event('down')
    assert len(fig.mne.traces) == len(sel_dict['Left-frontal'])  # 3
    sel_fig.canvas.key_press_event('down')
    assert len(fig.mne.traces) == len(sel_dict['Misc'])  # 1
    sel_fig.canvas.key_press_event('down')  # ignored; no custom sel defined
    assert len(fig.mne.traces) == len(sel_dict['Misc'])  # 1
    # switch to butterfly mode
    sel_fig.canvas.key_press_event('b')
    assert len(fig.mne.traces) == len(np.concatenate(list(sel_dict.values())))
    assert fig.mne.butterfly
    # test clicking on radio buttons → should cancel butterfly mode
    xy = buttons.circles[0].center
    _fake_click(sel_fig, sel_fig.mne.radio_ax, xy, xform='data')
    assert len(fig.mne.traces) == len(sel_dict['Left-temporal'])  # 6
    assert not fig.mne.butterfly
    # test clicking on "custom" when not defined: should be no-op
    before_state = buttons.value_selected
    xy = buttons.circles[-1].center
    _fake_click(sel_fig, sel_fig.mne.radio_ax, xy, xform='data')
    assert len(fig.mne.traces) == len(sel_dict['Left-temporal'])  # unchanged
    assert buttons.value_selected == before_state                 # unchanged
    # test marking bad channel in selection mode → should make sensor red
    assert sel_fig.lasso.ec[:, 0].sum() == 0   # R of RGBA zero for all chans
    _click_ch_name(fig, ch_index=1, button=1)  # mark bad
    assert sel_fig.lasso.ec[:, 0].sum() == 1   # one channel red
    _click_ch_name(fig, ch_index=1, button=1)  # mark good
    assert sel_fig.lasso.ec[:, 0].sum() == 0   # all channels black
    # test lasso
    sel_fig._set_custom_selection()  # lasso empty → should do nothing
    sensor_ax = sel_fig.mne.sensor_ax
    # Lasso with 1 mag/grad sensor unit (upper left)
    _fake_click(sel_fig, sensor_ax, (0, 1), xform='ax')
    _fake_click(sel_fig, sensor_ax, (0.65, 1), xform='ax', kind='motion')
    _fake_click(sel_fig, sensor_ax, (0.65, 0.7), xform='ax', kind='motion')
    _fake_click(sel_fig, sensor_ax, (0, 0.7), xform='ax', kind='release')
    want = ['MEG 0121', 'MEG 0122', 'MEG 0123']
    assert sorted(want) == sorted(sel_fig.lasso.selection)
    # test joint closing of selection & data windows
    sel_fig.canvas.key_press_event(sel_fig.mne.close_key)
    _close_event(sel_fig)
    assert len(plt.get_fignums()) == 0
Ejemplo n.º 3
0
def test_plot_epochs_clicks(epochs, capsys):
    """Test plot_epochs mouse interaction."""
    fig = epochs.plot(events=epochs.events)
    data_ax = fig.mne.ax_main
    x = fig.mne.traces[0].get_xdata()[3]
    y = fig.mne.traces[0].get_ydata()[3]
    n_epochs = len(epochs)
    epoch_num = fig.mne.inst.selection[0]
    # test (un)marking bad epochs
    _fake_click(fig, data_ax, [x, y], xform='data')  # mark a bad epoch
    assert epoch_num in fig.mne.bad_epochs
    _fake_click(fig, data_ax, [x, y], xform='data')  # unmark it
    assert epoch_num not in fig.mne.bad_epochs
    _fake_click(fig, data_ax, [x, y], xform='data')  # mark it bad again
    assert epoch_num in fig.mne.bad_epochs
    # test vline
    fig.canvas.key_press_event('escape')  # close and drop epochs
    _close_event(fig)  # XXX workaround, MPL Agg doesn't trigger close event
    assert (n_epochs - 1 == len(epochs))
    # test marking bad channels
    epochs = _get_epochs(None).load_data()  # need more than 1 epoch this time
    fig = epochs.plot(n_epochs=3)
    data_ax = fig.mne.ax_main
    first_ch = data_ax.get_yticklabels()[0].get_text()
    assert first_ch not in fig.mne.info['bads']
    _click_ch_name(fig, ch_index=0, button=1)  # click ch name to mark bad
    assert first_ch in fig.mne.info['bads']
    # test clicking scrollbars
    _fake_click(fig, fig.mne.ax_vscroll, [0.5, 0.5])
    _fake_click(fig, fig.mne.ax_hscroll, [0.5, 0.5])
    # test moving bad epoch offscreen
    fig.canvas.key_press_event('right')  # move right
    x = fig.mne.traces[0].get_xdata()[-3]
    y = fig.mne.traces[0].get_ydata()[-3]
    _fake_click(fig, data_ax, [x, y], xform='data')  # mark a bad epoch
    fig.canvas.key_press_event('left')  # move back
    out, err = capsys.readouterr()
    assert 'out of bounds' not in out
    assert 'out of bounds' not in err
    fig.canvas.key_press_event('escape')
    _close_event(fig)  # XXX workaround, MPL Agg doesn't trigger close event
    assert len(epochs) == 6
    # test rightclick → image plot
    fig = epochs.plot()
    _click_ch_name(fig, ch_index=0, button=3)  # show image plot
    assert len(fig.mne.child_figs) == 1
    # test scroll wheel
    fig.canvas.scroll_event(0.5, 0.5, -0.5)  # scroll down
    fig.canvas.scroll_event(0.5, 0.5, 0.5)  # scroll up
Ejemplo n.º 4
0
def test_plot_ica_sources(raw_orig, mpl_backend):
    """Test plotting of ICA panel."""
    raw = raw_orig.copy().crop(0, 1)
    picks = _get_picks(raw)
    epochs = _get_epochs()
    raw.pick_channels([raw.ch_names[k] for k in picks])
    ica_picks = pick_types(raw.info,
                           meg=True,
                           eeg=False,
                           stim=False,
                           ecg=False,
                           eog=False,
                           exclude='bads')
    ica = ICA(n_components=2)
    ica.fit(raw, picks=ica_picks)
    ica.exclude = [1]
    fig = ica.plot_sources(raw)
    assert mpl_backend._get_n_figs() == 1
    # change which component is in ICA.exclude (click data trace to remove
    # current one; click name to add other one)
    fig._redraw()
    # ToDo: This will be different methods in pyqtgraph
    x = fig.mne.traces[1].get_xdata()[5]
    y = fig.mne.traces[1].get_ydata()[5]
    fig._fake_click((x, y), xform='data')  # exclude = []
    _click_ch_name(fig, ch_index=0, button=1)  # exclude = [0]
    fig._fake_keypress(fig.mne.close_key)
    fig._close_event()
    assert mpl_backend._get_n_figs() == 0
    assert_array_equal(ica.exclude, [0])
    # test when picks does not include ica.exclude.
    fig = ica.plot_sources(raw, picks=[1])
    assert len(plt.get_fignums()) == 1
    mpl_backend._close_all()

    # dtype can change int->np.int64 after load, test it explicitly
    ica.n_components_ = np.int64(ica.n_components_)

    # test clicks on y-label (need >2 secs for plot_properties() to work)
    long_raw = raw_orig.crop(0, 5)
    fig = ica.plot_sources(long_raw)
    assert len(plt.get_fignums()) == 1
    fig._redraw()
    _click_ch_name(fig, ch_index=0, button=3)
    assert len(fig.mne.child_figs) == 1
    assert len(plt.get_fignums()) == 2
    # close child fig directly (workaround for mpl issue #18609)
    fig._fake_keypress('escape', fig=fig.mne.child_figs[0])
    assert len(plt.get_fignums()) == 1
    fig._fake_keypress(fig.mne.close_key)
    assert len(plt.get_fignums()) == 0
    del long_raw

    # test with annotations
    orig_annot = raw.annotations
    raw.set_annotations(Annotations([0.2], [0.1], 'Test'))
    fig = ica.plot_sources(raw)
    assert len(fig.mne.ax_main.collections) == 1
    assert len(fig.mne.ax_hscroll.collections) == 1
    raw.set_annotations(orig_annot)

    # test error handling
    raw_ = raw.copy().load_data()
    raw_.drop_channels('MEG 0113')
    with pytest.raises(RuntimeError, match="Raw doesn't match fitted data"), \
         pytest.warns(RuntimeWarning, match='could not be picked'):
        ica.plot_sources(inst=raw_)
    epochs_ = epochs.copy().load_data()
    epochs_.drop_channels('MEG 0113')
    with pytest.raises(RuntimeError, match="Epochs don't match fitted data"), \
         pytest.warns(RuntimeWarning, match='could not be picked'):
        ica.plot_sources(inst=epochs_)
    del raw_
    del epochs_

    # test w/ epochs and evokeds
    ica.plot_sources(epochs)
    ica.plot_sources(epochs.average())
    evoked = epochs.average()
    fig = ica.plot_sources(evoked)
    # Test a click
    ax = fig.get_axes()[0]
    line = ax.lines[0]
    _fake_click(fig, ax, [line.get_xdata()[0], line.get_ydata()[0]], 'data')
    _fake_click(fig, ax, [ax.get_xlim()[0], ax.get_ylim()[1]], 'data')

    # plot with bad channels excluded
    ica.exclude = [0]
    ica.plot_sources(evoked)

    # pretend find_bads_eog() yielded some results
    ica.labels_ = {'eog': [0], 'eog/0/crazy-channel': [0]}
    ica.plot_sources(evoked)  # now with labels

    # pass an invalid inst
    with pytest.raises(ValueError, match='must be of Raw or Epochs type'):
        ica.plot_sources('meeow')
Ejemplo n.º 5
0
def test_plot_raw_traces(raw):
    """Test plotting of raw data."""
    raw.info['lowpass'] = 10.  # allow heavy decim during plotting
    events = _get_events()
    plt.close('all')  # ensure all are closed
    fig = raw.plot(events=events, order=[1, 7, 5, 2, 3], n_channels=3,
                   group_by='original')
    assert hasattr(fig, 'mne')  # make sure fig.mne param object is present
    assert len(fig.axes) == 5

    # setup
    x = fig.mne.traces[0].get_xdata()[5]
    y = fig.mne.traces[0].get_ydata()[5]
    data_ax = fig.mne.ax_main
    hscroll = fig.mne.ax_hscroll
    vscroll = fig.mne.ax_vscroll
    # test marking bad channels
    label = fig.mne.ax_main.get_yticklabels()[0].get_text()
    assert label not in fig.mne.info['bads']
    _fake_click(fig, data_ax, [x, y], xform='data')  # click data to mark bad
    assert label in fig.mne.info['bads']
    _fake_click(fig, data_ax, [x, y], xform='data')  # click data to unmark bad
    assert label not in fig.mne.info['bads']
    _click_ch_name(fig, ch_index=0, button=1)        # click name to mark bad
    assert label in fig.mne.info['bads']
    # test other kinds of clicks
    _fake_click(fig, data_ax, [0.5, 0.999])  # click elsewhere (add vline)
    _fake_click(fig, data_ax, [0.5, 0.999], button=3)  # remove vline
    _fake_click(fig, hscroll, [0.5, 0.5])  # change time
    _fake_click(fig, hscroll, [0.5, 0.5])  # shouldn't change time this time
    # test scrolling through channels
    labels = [label.get_text() for label in data_ax.get_yticklabels()]
    assert labels == [raw.ch_names[1], raw.ch_names[7], raw.ch_names[5]]
    _fake_click(fig, vscroll, [0.5, 0.01])  # change channels to end
    labels = [label.get_text() for label in data_ax.get_yticklabels()]
    assert labels == [raw.ch_names[5], raw.ch_names[2], raw.ch_names[3]]
    for _ in (0, 0):
        # first click changes channels to mid; second time shouldn't change
        _fake_click(fig, vscroll, [0.5, 0.5])
        labels = [label.get_text() for label in data_ax.get_yticklabels()]
        assert labels == [raw.ch_names[7], raw.ch_names[5], raw.ch_names[2]]
        assert len(plt.get_fignums()) == 1

    # test clicking a channel name in butterfly mode
    bads = fig.mne.info['bads'].copy()
    fig.canvas.key_press_event('b')
    _click_ch_name(fig, ch_index=0, button=1)  # should be no-op
    assert fig.mne.info['bads'] == bads        # unchanged
    fig.canvas.key_press_event('b')

    # test starting up in zen mode
    fig = plot_raw(raw, show_scrollbars=False)
    # test order, title, & show_options kwargs
    with pytest.raises(ValueError, match='order should be array-like; got'):
        raw.plot(order='foo')
    with pytest.raises(TypeError, match='title must be None or a string, got'):
        raw.plot(title=1)
    raw.plot(show_options=True)
    plt.close('all')

    # Color setting
    with pytest.raises(KeyError, match='must be strictly positive, or -1'):
        raw.plot(event_color={0: 'r'})
    with pytest.raises(TypeError, match='event_color key must be an int, got'):
        raw.plot(event_color={'foo': 'r'})
    annot = Annotations([10, 10 + raw.first_samp / raw.info['sfreq']],
                        [10, 10], ['test', 'test'], raw.info['meas_date'])
    with pytest.warns(RuntimeWarning, match='outside data range'):
        raw.set_annotations(annot)
    fig = plot_raw(raw, events=events, event_color={-1: 'r', 998: 'b'})
    plt.close('all')
    for group_by, order in zip(['position', 'selection'],
                               [np.arange(len(raw.ch_names))[::-3],
                                [1, 2, 4, 6]]):
        fig = raw.plot(group_by=group_by, order=order)
        x = fig.get_axes()[0].lines[1].get_xdata()[10]
        y = fig.get_axes()[0].lines[1].get_ydata()[10]
        _fake_click(fig, data_ax, [x, y], xform='data')  # mark bad
        fig.canvas.key_press_event('down')  # change selection
        _fake_click(fig, fig.get_axes()[2], [0.5, 0.5])  # change channels
        sel_fig = plt.figure(1)
        topo_ax = sel_fig.axes[1]
        _fake_click(sel_fig, topo_ax, [-0.425, 0.20223853],
                    xform='data')
        fig.canvas.key_press_event('down')
        fig.canvas.key_press_event('up')
        fig.canvas.scroll_event(0.5, 0.5, -1)  # scroll down
        fig.canvas.scroll_event(0.5, 0.5, 1)  # scroll up
        _fake_click(sel_fig, topo_ax, [-0.5, 0.], xform='data')
        _fake_click(sel_fig, topo_ax, [0.5, 0.], xform='data',
                    kind='motion')
        _fake_click(sel_fig, topo_ax, [0.5, 0.5], xform='data',
                    kind='motion')
        _fake_click(sel_fig, topo_ax, [-0.5, 0.5], xform='data',
                    kind='release')

        plt.close('all')
    # test if meas_date is off
    raw.set_meas_date(_dt_to_stamp(raw.info['meas_date'])[0])
    annot = Annotations([1 + raw.first_samp / raw.info['sfreq']],
                        [5], ['bad'])
    with pytest.warns(RuntimeWarning, match='outside data range'):
        raw.set_annotations(annot)
    with pytest.warns(None):  # sometimes projection
        raw.plot(group_by='position', order=np.arange(8))
    for fig_num in plt.get_fignums():
        fig = plt.figure(fig_num)
        if hasattr(fig, 'radio'):  # Get access to selection fig.
            break
    for key in ['down', 'up', 'escape']:
        fig.canvas.key_press_event(key)

    raw._data[:] = np.nan
    # this should (at least) not die, the output should pretty clearly show
    # that there is a problem so probably okay to just plot something blank
    with pytest.warns(None):
        raw.plot(scalings='auto')

    plt.close('all')
Ejemplo n.º 6
0
def test_plot_ica_sources():
    """Test plotting of ICA panel."""
    raw = read_raw_fif(raw_fname).crop(0, 1).load_data()
    picks = _get_picks(raw)
    epochs = _get_epochs()
    raw.pick_channels([raw.ch_names[k] for k in picks])
    ica_picks = pick_types(raw.info,
                           meg=True,
                           eeg=False,
                           stim=False,
                           ecg=False,
                           eog=False,
                           exclude='bads')
    ica = ICA(n_components=2)
    ica.fit(raw, picks=ica_picks)
    ica.exclude = [1]
    fig = ica.plot_sources(raw)
    assert len(plt.get_fignums()) == 1
    # change which component is in ICA.exclude (click data trace to remove
    # current one; click name to add other one)
    fig.canvas.draw()
    x = fig.mne.traces[1].get_xdata()[5]
    y = fig.mne.traces[1].get_ydata()[5]
    _fake_click(fig, fig.mne.ax_main, (x, y), xform='data')  # exclude = []
    _click_ch_name(fig, ch_index=0, button=1)  # exclude = [0]
    fig.canvas.key_press_event(fig.mne.close_key)
    _close_event(fig)
    assert len(plt.get_fignums()) == 0
    assert_array_equal(ica.exclude, [0])
    # test when picks does not include ica.exclude.
    fig = ica.plot_sources(raw, picks=[1])
    assert len(plt.get_fignums()) == 1
    plt.close('all')

    # dtype can change int->np.int64 after load, test it explicitly
    ica.n_components_ = np.int64(ica.n_components_)

    # test clicks on y-label (need >2 secs for plot_properties() to work)
    long_raw = read_raw_fif(raw_fname).crop(0, 5).load_data()
    fig = ica.plot_sources(long_raw)
    assert len(plt.get_fignums()) == 1
    fig.canvas.draw()
    _fake_click(fig, fig.mne.ax_main, (-0.1, 0), xform='data', button=3)
    assert len(fig.mne.child_figs) == 1
    assert len(plt.get_fignums()) == 2
    # close child fig directly (workaround for mpl issue #18609)
    fig.mne.child_figs[0].canvas.key_press_event('escape')
    assert len(plt.get_fignums()) == 1
    fig.canvas.key_press_event(fig.mne.close_key)
    assert len(plt.get_fignums()) == 0
    del long_raw

    # test with annotations
    orig_annot = raw.annotations
    raw.set_annotations(Annotations([0.2], [0.1], 'Test'))
    fig = ica.plot_sources(raw)
    assert len(fig.mne.ax_main.collections) == 1
    assert len(fig.mne.ax_hscroll.collections) == 1
    raw.set_annotations(orig_annot)

    # test error handling
    raw.info['bads'] = ['MEG 0113']
    with pytest.raises(RuntimeError, match="Raw doesn't match fitted data"):
        ica.plot_sources(inst=raw)
    epochs.info['bads'] = ['MEG 0113']
    with pytest.raises(RuntimeError, match="Epochs don't match fitted data"):
        ica.plot_sources(inst=epochs)
    epochs.info['bads'] = []

    # test w/ epochs and evokeds
    ica.plot_sources(epochs)
    ica.plot_sources(epochs.average())
    evoked = epochs.average()
    fig = ica.plot_sources(evoked)
    # Test a click
    ax = fig.get_axes()[0]
    line = ax.lines[0]
    _fake_click(fig, ax, [line.get_xdata()[0], line.get_ydata()[0]], 'data')
    _fake_click(fig, ax, [ax.get_xlim()[0], ax.get_ylim()[1]], 'data')
    # plot with bad channels excluded
    ica.exclude = [0]
    ica.plot_sources(evoked)
    ica.labels_ = dict(eog=[0])
    ica.labels_['eog/0/crazy-channel'] = [0]
    ica.plot_sources(evoked)  # now with labels
    with pytest.raises(ValueError, match='must be of Raw or Epochs type'):
        ica.plot_sources('meeow')