Exemple #1
0
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    info = create_info(['a', 'b', 'c', 'd', 'e'], 100, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    with warnings.catch_warnings(record=True):  # one outside range
        raw.annotations = Annotations([2, 100, 105, 148], [2, 8, 5, 8], 'BAD')
    data = raw.get_data([0, 1, 3, 4], 100, 11200, 'omit')
    assert_array_equal(data.shape, (4, 9900))

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    raw.annotations = Annotations([44, 47, 48], [1, 3, 1], 'BAD',
                                  raw.info['meas_date'])
    data, times = raw.get_data(range(10), 0, 6000, 'omit', True)
    assert_array_equal(data.shape, (10, 4799))
    assert_equal(times[-1], raw.times[5999])
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])

    data, times = raw.get_data(range(10), 0, 6000, 'NaN', True)
    assert_array_equal(data.shape, (10, 6000))
    assert_equal(times[-1], raw.times[5999])
    assert_true(np.isnan(data[:, 313:613]).all())  # 1s -2s
    assert_true(not np.isnan(data[:, 614].any()))
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])
    assert_array_equal(raw.get_data(), raw[:][0])

    # Test _sync_onset
    times = [10, -88, 190]
    onsets = _sync_onset(raw, times)
    assert_array_almost_equal(onsets,
                              times - raw.first_samp / raw.info['sfreq'])
    assert_array_almost_equal(times, _sync_onset(raw, onsets, True))
Exemple #2
0
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    info = create_info(['a', 'b', 'c', 'd', 'e'], 100, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    with warnings.catch_warnings(record=True):  # one outside range
        raw.annotations = Annotations([2, 100, 105, 148], [2, 8, 5, 8], 'BAD')
    data = raw.get_data([0, 1, 3, 4], 100, 11200, 'omit')
    assert_array_equal(data.shape, (4, 9900))

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    raw.annotations = Annotations([44, 47, 48], [1, 3, 1], 'BAD',
                                  raw.info['meas_date'])
    data, times = raw.get_data(range(10), 0, 6000, 'omit', True)
    assert_array_equal(data.shape, (10, 4799))
    assert_equal(times[-1], raw.times[5999])
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])

    data, times = raw.get_data(range(10), 0, 6000, 'NaN', True)
    assert_array_equal(data.shape, (10, 6000))
    assert_equal(times[-1], raw.times[5999])
    assert_true(np.isnan(data[:, 313:613]).all())  # 1s -2s
    assert_true(not np.isnan(data[:, 614].any()))
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])
    assert_array_equal(raw.get_data(), raw[:][0])

    # Test _sync_onset
    times = [10, -88, 190]
    onsets = _sync_onset(raw, times)
    assert_array_almost_equal(onsets, times - raw.first_samp /
                              raw.info['sfreq'])
    assert_array_almost_equal(times, _sync_onset(raw, onsets, True))
Exemple #3
0
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    sfreq = 100.
    info = create_info(['a', 'b', 'c', 'd', 'e'], sfreq, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    with pytest.warns(RuntimeWarning, match='outside the data range'):
        raw.set_annotations(
            Annotations([2, 100, 105, 148], [2, 8, 5, 8], 'BAD'))
    data, times = raw.get_data(
        [0, 1, 3, 4],
        100,
        11200,  # 1-112 sec
        'omit',
        return_times=True)
    bad_times = np.concatenate([
        np.arange(200, 400),
        np.arange(10000, 10800),
        np.arange(10500, 11000)
    ])
    expected_times = np.setdiff1d(np.arange(100, 11200), bad_times) / sfreq
    assert_allclose(times, expected_times)

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    raw.set_annotations(
        Annotations(onset=[1, 4, 5] + raw._first_time,
                    duration=[1, 3, 1],
                    description='BAD',
                    orig_time=raw.info['meas_date']))
    t_stop = 18.
    assert raw.times[-1] > t_stop
    n_stop = int(round(t_stop * raw.info['sfreq']))
    n_drop = int(round(4 * raw.info['sfreq']))
    assert len(raw.times) >= n_stop
    data, times = raw.get_data(range(10), 0, n_stop, 'omit', True)
    assert data.shape == (10, n_stop - n_drop)
    assert times[-1] == raw.times[n_stop - 1]
    assert_array_equal(data[:, -100:], raw[:10, n_stop - 100:n_stop][0])

    data, times = raw.get_data(range(10), 0, n_stop, 'NaN', True)
    assert_array_equal(data.shape, (10, n_stop))
    assert times[-1] == raw.times[n_stop - 1]
    t_1, t_2 = raw.time_as_index([1, 2], use_rounding=True)
    assert np.isnan(data[:, t_1:t_2]).all()  # 1s -2s
    assert not np.isnan(data[:, :t_1].any())
    assert not np.isnan(data[:, t_2:].any())
    assert_array_equal(data[:, -100:], raw[:10, n_stop - 100:n_stop][0])
    assert_array_equal(raw.get_data(), raw[:][0])

    # Test _sync_onset
    times = [10, -88, 190]
    onsets = _sync_onset(raw, times)
    assert_array_almost_equal(onsets,
                              times - raw.first_samp / raw.info['sfreq'])
    assert_array_almost_equal(times, _sync_onset(raw, onsets, True))
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    sfreq = 100.
    info = create_info(['a', 'b', 'c', 'd', 'e'], sfreq, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    with pytest.warns(RuntimeWarning, match='outside the data range'):
        raw.set_annotations(Annotations([2, 100, 105, 148],
                                        [2, 8, 5, 8], 'BAD'))
    data, times = raw.get_data([0, 1, 3, 4], 100, 11200,  # 1-112 sec
                               'omit', return_times=True)
    bad_times = np.concatenate([np.arange(200, 400),
                                np.arange(10000, 10800),
                                np.arange(10500, 11000)])
    expected_times = np.setdiff1d(np.arange(100, 11200), bad_times) / sfreq
    assert_allclose(times, expected_times)

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    raw.set_annotations(Annotations(onset=[1, 4, 5] + raw._first_time,
                                    duration=[1, 3, 1],
                                    description='BAD',
                                    orig_time=raw.info['meas_date']))
    t_stop = 18.
    assert raw.times[-1] > t_stop
    n_stop = int(round(t_stop * raw.info['sfreq']))
    n_drop = int(round(4 * raw.info['sfreq']))
    assert len(raw.times) >= n_stop
    data, times = raw.get_data(range(10), 0, n_stop, 'omit', True)
    assert data.shape == (10, n_stop - n_drop)
    assert times[-1] == raw.times[n_stop - 1]
    assert_array_equal(data[:, -100:], raw[:10, n_stop - 100:n_stop][0])

    data, times = raw.get_data(range(10), 0, n_stop, 'NaN', True)
    assert_array_equal(data.shape, (10, n_stop))
    assert times[-1] == raw.times[n_stop - 1]
    t_1, t_2 = raw.time_as_index([1, 2], use_rounding=True)
    assert np.isnan(data[:, t_1:t_2]).all()  # 1s -2s
    assert not np.isnan(data[:, :t_1].any())
    assert not np.isnan(data[:, t_2:].any())
    assert_array_equal(data[:, -100:], raw[:10, n_stop - 100:n_stop][0])
    assert_array_equal(raw.get_data(), raw[:][0])

    # Test _sync_onset
    times = [10, -88, 190]
    onsets = _sync_onset(raw, times)
    assert_array_almost_equal(onsets, times - raw.first_samp /
                              raw.info['sfreq'])
    assert_array_almost_equal(times, _sync_onset(raw, onsets, True))
Exemple #5
0
def _annotation_helper(raw, browse_backend, events=False):
    """Test interactive annotations."""
    ismpl = browse_backend.name == 'matplotlib'
    # Some of our checks here require modern mpl to work properly
    n_anns = len(raw.annotations)
    browse_backend._close_all()

    if events:
        events = np.array([[raw.first_samp + 100, 0, 1],
                           [raw.first_samp + 300, 0, 3]])
        n_events = len(events)
    else:
        events = None
        n_events = 0
    fig = raw.plot(events=events)
    if ismpl:
        assert browse_backend._get_n_figs() == 1

    fig._fake_keypress('a')  # annotation mode
    ann_fig = fig.mne.fig_annotation
    if ismpl:
        assert browse_backend._get_n_figs() == 2
        # +3 from the scale bars
        n_scale = 3
        assert len(fig.mne.ax_main.texts) == n_anns + n_events + n_scale
    else:
        assert ann_fig.isVisible()

    # modify description to create label "BAD test"
    # semicolon is ignored
    if ismpl:
        for key in ['backspace'] + list(' test;') + ['enter']:
            fig._fake_keypress(key, fig=ann_fig)
        # change annotation label
        for ix in (-1, 0):
            xy = ann_fig.mne.radio_ax.buttons.circles[ix].center
            fig._fake_click(xy, fig=ann_fig, ax=ann_fig.mne.radio_ax,
                            xform='data')
    else:
        # The modal dialogs of the pyqtgraph-backend would block the test,
        # thus a new description will be added programmatically.
        ann_fig._add_description('BAD test')

    # draw annotation
    fig._fake_click((1., 1.), add_points=[(5., 1.)], xform='data', button=1,
                    kind='drag')
    if ismpl:
        assert len(fig.mne.ax_main.texts) == n_anns + 1 + n_events + n_scale
        # test hover event
        fig._fake_keypress('p')  # first turn on draggable mode
        assert fig.mne.draggable_annotations
        hover_kwargs = dict(xform='data', button=None, kind='motion')
        fig._fake_click((4.6, 1.), **hover_kwargs)  # well inside ann.
        fig._fake_click((4.9, 1.), **hover_kwargs)  # almost at edge
        assert fig.mne.annotation_hover_line is not None
        fig._fake_click((5.5, 1.), **hover_kwargs)  # well outside ann.
        assert fig.mne.annotation_hover_line is None
        # more tests of hover line
        fig._fake_click((4.6, 1.), **hover_kwargs)  # well inside ann.
        fig._fake_click((4.9, 1.), **hover_kwargs)  # almost at edge
        assert fig.mne.annotation_hover_line is not None
        fig._fake_keypress('p')  # turn off draggable mode, then move a bit
        fig._fake_click((4.95, 1.), **hover_kwargs)
        assert fig.mne.annotation_hover_line is None
        fig._fake_keypress('p')  # turn draggable mode back on
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert raw.annotations.description[n_anns] == 'BAD test'
    onset = raw.annotations.onset[n_anns]
    want_onset = _sync_onset(raw, 1., inverse=True)
    # pyqtgraph: during the transformation from pixel-coordinates
    # to scene-coordinates when the click is simulated on QGraphicsView
    # with QTest, there seems to happen a rounding of pixels to integers
    # internally. This deviatian also seems to change between runs
    # (maybe device-dependent?).
    atol = 1e-10 if ismpl else 1e-2
    assert_allclose(onset, want_onset, atol=atol)
    assert_allclose(raw.annotations.duration[n_anns], 4., atol=atol)
    # modify annotation from end (duration 4 → 1.5)
    fig._fake_click((4.9, 1.), xform='data', button=1,
                    kind='motion')  # ease up to it
    fig._fake_click((5., 1.), add_points=[(2.5, 1.)], xform='data',
                    button=1, kind='drag')
    assert raw.annotations.onset[n_anns] == onset
    # 4 → 1.5
    assert_allclose(raw.annotations.duration[n_anns], 1.5, atol=atol)
    # modify annotation from beginning (duration 1.5 → 2.0)
    fig._fake_click((1., 1.), add_points=[(0.5, 1.)], xform='data', button=1,
                    kind='drag')
    assert_allclose(raw.annotations.onset[n_anns], onset - 0.5, atol=atol)
    # 1.5 → 2.0
    assert_allclose(raw.annotations.duration[n_anns], 2.0, atol=atol)
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert raw.annotations.description[n_anns] == 'BAD test'
    if ismpl:
        assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale
        fig._fake_keypress('shift+right')
        assert len(fig.axes[0].texts) == n_scale
        fig._fake_keypress('shift+left')
        assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale

    # draw another annotation merging the two
    fig._fake_click((5.5, 1.), add_points=[(2., 1.)],
                    xform='data', button=1, kind='drag')
    # delete the annotation
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert_allclose(raw.annotations.onset[n_anns], onset - 0.5, atol=atol)
    assert_allclose(raw.annotations.duration[n_anns], 5.0, atol=atol)
    if ismpl:
        assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale
    # Delete
    fig._fake_click((1.5, 1.), xform='data', button=3, kind='press')
    # exit, re-enter, then exit a different way
    fig._fake_keypress('a')  # exit
    fig._fake_keypress('a')  # enter
    assert len(raw.annotations.onset) == n_anns
    if ismpl:
        fig._fake_keypress('escape', fig=fig.mne.fig_annotation)  # exit again
        assert len(fig.axes[0].texts) == n_anns + n_events + n_scale
        fig._fake_keypress('shift+right')
        assert len(fig.axes[0].texts) == n_scale
        fig._fake_keypress('shift+left')
        assert len(fig.axes[0].texts) == n_anns + n_events + n_scale
Exemple #6
0
def _annotation_helper(raw, events=False):
    """Test interactive annotations."""
    # Some of our checks here require modern mpl to work properly
    n_anns = len(raw.annotations)
    plt.close('all')

    if events:
        events = np.array([[raw.first_samp + 100, 0, 1],
                           [raw.first_samp + 300, 0, 3]])
        n_events = len(events)
    else:
        events = None
        n_events = 0
    fig = raw.plot(events=events)
    assert len(plt.get_fignums()) == 1
    data_ax = fig.mne.ax_main
    fig.canvas.key_press_event('a')  # annotation mode
    assert len(plt.get_fignums()) == 2
    # +2 from the scale bars
    n_scale = 2
    assert len(data_ax.texts) == n_anns + n_events + n_scale
    # modify description to create label "BAD test"
    ann_fig = fig.mne.fig_annotation
    for key in ['backspace'] + list(' test;'):  # semicolon is ignored
        ann_fig.canvas.key_press_event(key)
    ann_fig.canvas.key_press_event('enter')

    # change annotation label
    for ix in (-1, 0):
        xy = ann_fig.mne.radio_ax.buttons.circles[ix].center
        _fake_click(ann_fig, ann_fig.mne.radio_ax, xy, xform='data')

    # draw annotation
    _fake_click(fig, data_ax, [1., 1.], xform='data', button=1, kind='press')
    _fake_click(fig, data_ax, [5., 1.], xform='data', button=1, kind='motion')
    _fake_click(fig, data_ax, [5., 1.], xform='data', button=1, kind='release')
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert raw.annotations.description[n_anns] == 'BAD test'
    assert len(data_ax.texts) == n_anns + 1 + n_events + n_scale
    onset = raw.annotations.onset[n_anns]
    want_onset = _sync_onset(raw, 1., inverse=True)
    assert_allclose(onset, want_onset)
    assert_allclose(raw.annotations.duration[n_anns], 4.)
    # test hover event
    fig.canvas.key_press_event('p')  # first turn on draggable mode
    assert fig.mne.draggable_annotations
    hover_kwargs = dict(xform='data', button=None, kind='motion')
    _fake_click(fig, data_ax, [4.6, 1.], **hover_kwargs)  # well inside ann.
    _fake_click(fig, data_ax, [4.9, 1.], **hover_kwargs)  # almost at edge
    assert fig.mne.annotation_hover_line is not None
    _fake_click(fig, data_ax, [5.5, 1.], **hover_kwargs)  # well outside ann.
    assert fig.mne.annotation_hover_line is None
    # more tests of hover line
    _fake_click(fig, data_ax, [4.6, 1.], **hover_kwargs)  # well inside ann.
    _fake_click(fig, data_ax, [4.9, 1.], **hover_kwargs)  # almost at edge
    assert fig.mne.annotation_hover_line is not None
    fig.canvas.key_press_event('p')  # turn off draggable mode, then move a bit
    _fake_click(fig, data_ax, [4.95, 1.], **hover_kwargs)
    assert fig.mne.annotation_hover_line is None
    fig.canvas.key_press_event('p')  # turn draggable mode back on
    # modify annotation from end (duration 4 → 1.5)
    _fake_click(fig, data_ax, [4.9, 1.], xform='data', button=None,
                kind='motion')  # ease up to it
    _fake_click(fig, data_ax, [5., 1.], xform='data', button=1, kind='press')
    _fake_click(fig, data_ax, [2.5, 1.], xform='data', button=1, kind='motion')
    _fake_click(fig, data_ax, [2.5, 1.], xform='data', button=1,
                kind='release')
    assert raw.annotations.onset[n_anns] == onset
    assert_allclose(raw.annotations.duration[n_anns], 1.5)  # 4 → 1.5
    # modify annotation from beginning (duration 1.5 → 2.0)
    _fake_click(fig, data_ax, [1., 1.], xform='data', button=1, kind='press')
    _fake_click(fig, data_ax, [0.5, 1.], xform='data', button=1, kind='motion')
    _fake_click(fig, data_ax, [0.5, 1.], xform='data', button=1,
                kind='release')
    assert_allclose(raw.annotations.onset[n_anns], onset - 0.5, atol=1e-10)
    assert_allclose(raw.annotations.duration[n_anns], 2.0)  # 1.5 → 2.0
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert raw.annotations.description[n_anns] == 'BAD test'
    assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale
    fig.canvas.key_press_event('shift+right')
    assert len(fig.axes[0].texts) == n_scale
    fig.canvas.key_press_event('shift+left')
    assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale

    # draw another annotation merging the two
    _fake_click(fig, data_ax, [5.5, 1.], xform='data', button=1, kind='press')
    _fake_click(fig, data_ax, [2., 1.], xform='data', button=1, kind='motion')
    _fake_click(fig, data_ax, [2., 1.], xform='data', button=1, kind='release')
    # delete the annotation
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert_allclose(raw.annotations.onset[n_anns], onset - 0.5, atol=1e-10)
    assert_allclose(raw.annotations.duration[n_anns], 5.0)
    assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale
    # Delete
    _fake_click(fig, data_ax, [1.5, 1.], xform='data', button=3, kind='press')
    # exit, re-enter, then exit a different way
    fig.canvas.key_press_event('a')  # exit
    fig.canvas.key_press_event('a')  # enter
    fig.mne.fig_annotation.canvas.key_press_event('escape')  # exit again
    assert len(raw.annotations.onset) == n_anns
    assert len(fig.axes[0].texts) == n_anns + n_events + n_scale
    fig.canvas.key_press_event('shift+right')
    assert len(fig.axes[0].texts) == n_scale
    fig.canvas.key_press_event('shift+left')
    assert len(fig.axes[0].texts) == n_anns + n_events + n_scale
    plt.close('all')
Exemple #7
0
def _annotation_helper(raw, browse_backend, events=False):
    """Test interactive annotations."""
    # Some of our checks here require modern mpl to work properly
    n_anns = len(raw.annotations)
    browse_backend._close_all()

    if events:
        events = np.array([[raw.first_samp + 100, 0, 1],
                           [raw.first_samp + 300, 0, 3]])
        n_events = len(events)
    else:
        events = None
        n_events = 0
    fig = raw.plot(events=events)
    assert browse_backend._get_n_figs() == 1
    data_ax = fig.mne.ax_main
    fig._fake_keypress('a')  # annotation mode
    # ToDo: This will be different in pyqtgraph because it handles annotations
    #  from the toolbar.
    assert browse_backend._get_n_figs() == 2
    # +3 from the scale bars
    n_scale = 3
    assert len(data_ax.texts) == n_anns + n_events + n_scale
    # modify description to create label "BAD test"
    ann_fig = fig.mne.fig_annotation
    # semicolon is ignored
    for key in ['backspace'] + list(' test;') + ['enter']:
        fig._fake_keypress(key, fig=ann_fig)

    # change annotation label
    for ix in (-1, 0):
        xy = ann_fig.mne.radio_ax.buttons.circles[ix].center
        fig._fake_click(xy, ann_fig, ann_fig.mne.radio_ax, xform='data')

    # draw annotation
    fig._fake_click((1., 1.), xform='data', button=1, kind='press')
    fig._fake_click((5., 1.), xform='data', button=1, kind='motion')
    fig._fake_click((5., 1.), xform='data', button=1, kind='release')
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert raw.annotations.description[n_anns] == 'BAD test'
    assert len(data_ax.texts) == n_anns + 1 + n_events + n_scale
    onset = raw.annotations.onset[n_anns]
    want_onset = _sync_onset(raw, 1., inverse=True)
    assert_allclose(onset, want_onset)
    assert_allclose(raw.annotations.duration[n_anns], 4.)
    # test hover event
    fig._fake_keypress('p')  # first turn on draggable mode
    assert fig.mne.draggable_annotations
    hover_kwargs = dict(xform='data', button=None, kind='motion')
    fig._fake_click((4.6, 1.), **hover_kwargs)  # well inside ann.
    fig._fake_click((4.9, 1.), **hover_kwargs)  # almost at edge
    assert fig.mne.annotation_hover_line is not None
    fig._fake_click((5.5, 1.), **hover_kwargs)  # well outside ann.
    assert fig.mne.annotation_hover_line is None
    # more tests of hover line
    fig._fake_click((4.6, 1.), **hover_kwargs)  # well inside ann.
    fig._fake_click((4.9, 1.), **hover_kwargs)  # almost at edge
    assert fig.mne.annotation_hover_line is not None
    fig._fake_keypress('p')  # turn off draggable mode, then move a bit
    fig._fake_click((4.95, 1.), **hover_kwargs)
    assert fig.mne.annotation_hover_line is None
    fig._fake_keypress('p')  # turn draggable mode back on
    # modify annotation from end (duration 4 → 1.5)
    fig._fake_click((4.9, 1.), xform='data', button=None,
                    kind='motion')  # ease up to it
    fig._fake_click((5., 1.), xform='data', button=1, kind='press')
    fig._fake_click((2.5, 1.), xform='data', button=1, kind='motion')
    fig._fake_click((2.5, 1.), xform='data', button=1, kind='release')
    assert raw.annotations.onset[n_anns] == onset
    assert_allclose(raw.annotations.duration[n_anns], 1.5)  # 4 → 1.5
    # modify annotation from beginning (duration 1.5 → 2.0)
    fig._fake_click((1., 1.), xform='data', button=1, kind='press')
    fig._fake_click((0.5, 1.), xform='data', button=1, kind='motion')
    fig._fake_click((0.5, 1.), xform='data', button=1, kind='release')
    assert_allclose(raw.annotations.onset[n_anns], onset - 0.5, atol=1e-10)
    assert_allclose(raw.annotations.duration[n_anns], 2.0)  # 1.5 → 2.0
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert raw.annotations.description[n_anns] == 'BAD test'
    assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale
    fig._fake_keypress('shift+right')
    assert len(fig.axes[0].texts) == n_scale
    fig._fake_keypress('shift+left')
    assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale

    # draw another annotation merging the two
    fig._fake_click((5.5, 1.), xform='data', button=1, kind='press')
    fig._fake_click((2., 1.), xform='data', button=1, kind='motion')
    fig._fake_click((2., 1.), xform='data', button=1, kind='release')
    # delete the annotation
    assert len(raw.annotations.onset) == n_anns + 1
    assert len(raw.annotations.duration) == n_anns + 1
    assert len(raw.annotations.description) == n_anns + 1
    assert_allclose(raw.annotations.onset[n_anns], onset - 0.5, atol=1e-10)
    assert_allclose(raw.annotations.duration[n_anns], 5.0)
    assert len(fig.axes[0].texts) == n_anns + 1 + n_events + n_scale
    # Delete
    fig._fake_click((1.5, 1.), xform='data', button=3, kind='press')
    # exit, re-enter, then exit a different way
    fig._fake_keypress('a')  # exit
    fig._fake_keypress('a')  # enter
    fig._fake_keypress('escape', fig=fig.mne.fig_annotation)  # exit again
    assert len(raw.annotations.onset) == n_anns
    assert len(fig.axes[0].texts) == n_anns + n_events + n_scale
    fig._fake_keypress('shift+right')
    assert len(fig.axes[0].texts) == n_scale
    fig._fake_keypress('shift+left')
    assert len(fig.axes[0].texts) == n_anns + n_events + n_scale