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)
def _child_fig_helper(fig, key, attr): # Spawn and close child figs of raw.plot() num_figs = len(plt.get_fignums()) assert getattr(fig.mne, attr) is None # spawn fig.canvas.key_press_event(key) assert len(fig.mne.child_figs) == 1 assert len(plt.get_fignums()) == num_figs + 1 child_fig = getattr(fig.mne, attr) assert child_fig is not None # close via main window toggle fig.canvas.key_press_event(key) _close_event(child_fig) assert len(fig.mne.child_figs) == 0 assert len(plt.get_fignums()) == num_figs assert getattr(fig.mne, attr) is None # spawn again fig.canvas.key_press_event(key) assert len(fig.mne.child_figs) == 1 assert len(plt.get_fignums()) == num_figs + 1 child_fig = getattr(fig.mne, attr) assert child_fig is not None # close via child window child_fig.canvas.key_press_event(child_fig.mne.close_key) _close_event(child_fig) assert len(fig.mne.child_figs) == 0 assert len(plt.get_fignums()) == num_figs assert getattr(fig.mne, attr) is None
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
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
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() _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.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')