From 6e1eacde3d6f42d94602a8bfea9f671c635044a5 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Wed, 2 Aug 2023 11:09:33 +0200 Subject: [PATCH 01/13] improve drawing of annotations with mpl --- mne/viz/_mpl_figure.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/mne/viz/_mpl_figure.py b/mne/viz/_mpl_figure.py index d84f8a20b2b..ff42463b458 100644 --- a/mne/viz/_mpl_figure.py +++ b/mne/viz/_mpl_figure.py @@ -1138,15 +1138,13 @@ def _create_annotation_fig(self): else: col = self.mne.annotation_segment_colors[self._get_annotation_labels()[0]] - # TODO: we would like useblit=True here, but it behaves oddly when the - # first span is dragged (subsequent spans seem to work OK) rect_kw = _prop_kw("rect", dict(alpha=0.5, facecolor=col)) selector = SpanSelector( self.mne.ax_main, self._select_annotation_span, "horizontal", minspan=0.1, - useblit=False, + useblit=True, button=1, **rect_kw, ) @@ -1339,8 +1337,14 @@ def _select_annotation_span(self, vmin, vmax): onset = _sync_onset(self.mne.inst, vmin, True) - self.mne.first_time duration = vmax - vmin buttons = self.mne.fig_annotation.mne.radio_ax.buttons - labels = [label.get_text() for label in buttons.labels] - if buttons.value_selected is not None: + if buttons is None or buttons.value_selected is None: + logger.warning( + "No annotation-label exists! " + "Add one by typing the name and clicking " + 'on "Add new label" in the annotation-dialog.' + ) + else: + labels = [label.get_text() for label in buttons.labels] active_idx = labels.index(buttons.value_selected) _merge_annotations( onset, onset + duration, labels[active_idx], self.mne.inst.annotations @@ -1349,12 +1353,6 @@ def _select_annotation_span(self, vmin, vmax): if not self.mne.visible_annotations[buttons.value_selected]: self.mne.show_hide_annotation_checkboxes.set_active(active_idx) self._redraw(update_data=False, annotations=True) - else: - logger.warning( - "No annotation-label exists! " - "Add one by typing the name and clicking " - 'on "Add new label" in the annotation-dialog.' - ) def _remove_annotation_hover_line(self): """Remove annotation line from the plot and reactivate selector.""" From 96fdad29ce81dc63b9c09a16b64a9f157c1adbb0 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Wed, 2 Aug 2023 13:06:40 +0200 Subject: [PATCH 02/13] improve instructions [ci skip] --- mne/viz/_mpl_figure.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/mne/viz/_mpl_figure.py b/mne/viz/_mpl_figure.py index ff42463b458..26d5a4d9953 100644 --- a/mne/viz/_mpl_figure.py +++ b/mne/viz/_mpl_figure.py @@ -1057,21 +1057,13 @@ def _create_annotation_fig(self): instructions_ax = div.append_axes( position="top", size=Fixed(1), pad=Fixed(5 * ANNOTATION_FIG_PAD) ) - # XXX when we support a newer matplotlib (something >3.0) the - # instructions can have inline bold formatting: - # instructions = '\n'.join( - # [r'$\mathbf{Left‐click~&~drag~on~plot:}$ create/modify annotation', # noqa E501 - # r'$\mathbf{Right‐click~on~plot~annotation:}$ delete annotation', - # r'$\mathbf{Type~in~annotation~window:}$ modify new label name', - # r'$\mathbf{Enter~(or~click~button):}$ add new label to list', - # r'$\mathbf{Esc:}$ exit annotation mode & close this window']) instructions = "\n".join( [ - "Left click & drag on plot: create/modify annotation", - "Right click on annotation highlight: delete annotation", - "Type in this window: modify new label name", - "Enter (or click button): add new label to list", - "Esc: exit annotation mode & close this dialog window", + r"$\mathbf{Left‐click~&~drag~on~plot:}$ create/modify annotation", + r"$\mathbf{Right‐click~on~plot~annotation:}$ delete annotation", + r"$\mathbf{Type~in~annotation~window:}$ modify new label name", + r"$\mathbf{Enter~(or~click~button):}$ add new label to list", + r"$\mathbf{Esc:}$ exit annotation mode & close this window", ] ) instructions_ax.text( From 453f10805c9c226b98e776e3e3b8414f5ab995f2 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Thu, 3 Aug 2023 13:09:13 +0200 Subject: [PATCH 03/13] avoid for loop [ci skip] --- mne/viz/_figure.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mne/viz/_figure.py b/mne/viz/_figure.py index 43efd89bb4f..7ac67b02731 100644 --- a/mne/viz/_figure.py +++ b/mne/viz/_figure.py @@ -177,16 +177,15 @@ def _setup_annotation_colors(self): def _update_annotation_segments(self): """Update the array of annotation start/end times.""" - segments = list() - raw = self.mne.inst - if len(raw.annotations): - for idx, annot in enumerate(raw.annotations): - annot_start = _sync_onset(raw, annot["onset"]) - annot_end = annot_start + max( - annot["duration"], 1 / self.mne.info["sfreq"] - ) - segments.append((annot_start, annot_end)) - self.mne.annotation_segments = np.array(segments) + self.mne.annotation_segments = np.array([]) + if len(self.mne.inst.annotations): + annot_start = _sync_onset(self.mne.inst, self.mne.inst.annotations.onset) + durations = self.mne.inst.annotations.duration.copy() + durations[durations < 1 / self.mne.info["sfreq"]] = ( + 1 / self.mne.info["sfreq"] + ) + annot_end = annot_start + durations + self.mne.annotation_segments = np.vstack((annot_start, annot_end)).T # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # PROJECTOR & BADS From d4cdb2de8f3f7541cfb2f96574d3fe5742da8858 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Thu, 3 Aug 2023 14:11:22 +0200 Subject: [PATCH 04/13] add test for merging annotations in the Qt backend by dragging edges or dragging the annotation directly --- mne/viz/tests/test_raw.py | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py index e3eabfecd97..d1ec4ecdfb4 100644 --- a/mne/viz/tests/test_raw.py +++ b/mne/viz/tests/test_raw.py @@ -827,6 +827,87 @@ def test_remove_annotations(raw, hide_which, browser_backend): assert len(raw.annotations) == len(hide_which) +def test_merge_annotations(raw, browser_backend): + """Test merging of annotations in the Qt backend. + + Let's not bother in figuring out on which sample the _fake_click actually + dropped the annotation, especially with the 600.614 Hz weird sampling rate. + -> atol = 1 / raw.info["sfreq"] + """ + if browser_backend.name == "matplotlib": + pytest.skip("The MPL backend does not support draggable annotations.") + annot = Annotations( + onset=[1, 3, 4, 5, 7, 8], + duration=[1, 0.5, 0.8, 1, 0.5, 0.5], + description=["bad_test", "bad_test", "bad_test", "test", "test", "test"], + ) + raw.set_annotations(annot) + fig = raw.plot() + fig._fake_keypress("a") # start annotation mode + assert len(raw.annotations) == 6 + assert_allclose( + raw.annotations.onset, + np.array([1, 3, 4, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], + atol=1 / raw.info["sfreq"], + ) + # drag edge and merge 2 annotations in focus (selected description) + fig._fake_click( + (3.5, 1.0), add_points=[(4.2, 1.0)], xform="data", button=1, kind="drag" + ) + assert len(raw.annotations) == 5 + assert_allclose( + raw.annotations.onset, + np.array([1, 3, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], + atol=1 / raw.info["sfreq"], + ) + assert_allclose( + raw.annotations.duration, + np.array([1, 1.8, 1, 0.5, 0.5]), + atol=1 / raw.info["sfreq"], + ) + # drag annotation and merge 2 annotations in focus (selected description) + fig._fake_click( + (1.5, 1.0), add_points=[(3, 1.0)], xform="data", button=1, kind="drag" + ) + assert len(raw.annotations) == 4 + assert_allclose( + raw.annotations.onset, + np.array([2.5, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], + atol=1 / raw.info["sfreq"], + ) + assert_allclose( + raw.annotations.duration, + np.array([2.3, 1, 0.5, 0.5]), + atol=1 / raw.info["sfreq"], + ) + # drag edge and merge 2 annotations not in focus + fig._fake_click( + (7.5, 1.0), add_points=[(8.2, 1.0)], xform="data", button=1, kind="drag" + ) + assert len(raw.annotations) == 3 + assert_allclose( + raw.annotations.onset, + np.array([2.5, 5, 7]) + raw.first_samp / raw.info["sfreq"], + atol=1 / raw.info["sfreq"], + ) + assert_allclose( + raw.annotations.duration, np.array([2.3, 1, 1.5]), atol=1 / raw.info["sfreq"] + ) + # drag annotation and merge 2 annotations not in focus + fig._fake_click( + (5.5, 1.0), add_points=[(7.2, 1.0)], xform="data", button=1, kind="drag" + ) + assert len(raw.annotations) == 2 + assert_allclose( + raw.annotations.onset, + np.array([2.5, 6.7]) + raw.first_samp / raw.info["sfreq"], + atol=1 / raw.info["sfreq"], + ) + assert_allclose( + raw.annotations.duration, np.array([2.3, 1.8]), atol=1 / raw.info["sfreq"] + ) + + @pytest.mark.parametrize("filtorder", (0, 2)) # FIR, IIR def test_plot_raw_filtered(filtorder, raw, browser_backend): """Test filtering of raw plots.""" From 60a9f8616382b08288b9782b53a7581edbdcfffb Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Thu, 3 Aug 2023 14:30:06 +0200 Subject: [PATCH 05/13] fix test by using different values --- mne/viz/tests/test_raw.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py index d1ec4ecdfb4..d852092a2d8 100644 --- a/mne/viz/tests/test_raw.py +++ b/mne/viz/tests/test_raw.py @@ -895,16 +895,16 @@ def test_merge_annotations(raw, browser_backend): ) # drag annotation and merge 2 annotations not in focus fig._fake_click( - (5.5, 1.0), add_points=[(7.2, 1.0)], xform="data", button=1, kind="drag" + (5.6, 1.0), add_points=[(7.2, 1.0)], xform="data", button=1, kind="drag" ) assert len(raw.annotations) == 2 assert_allclose( raw.annotations.onset, - np.array([2.5, 6.7]) + raw.first_samp / raw.info["sfreq"], + np.array([2.5, 6.6]) + raw.first_samp / raw.info["sfreq"], atol=1 / raw.info["sfreq"], ) assert_allclose( - raw.annotations.duration, np.array([2.3, 1.8]), atol=1 / raw.info["sfreq"] + raw.annotations.duration, np.array([2.3, 1.9]), atol=1 / raw.info["sfreq"] ) From 903a4f0ef613095b56267cf4b10e0d7638369b45 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Thu, 3 Aug 2023 15:32:01 +0200 Subject: [PATCH 06/13] give 2 sample of freedom to handle the click between samples --- mne/viz/tests/test_raw.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py index d852092a2d8..a7b58c97a25 100644 --- a/mne/viz/tests/test_raw.py +++ b/mne/viz/tests/test_raw.py @@ -832,7 +832,7 @@ def test_merge_annotations(raw, browser_backend): Let's not bother in figuring out on which sample the _fake_click actually dropped the annotation, especially with the 600.614 Hz weird sampling rate. - -> atol = 1 / raw.info["sfreq"] + -> atol = 2 / raw.info["sfreq"] """ if browser_backend.name == "matplotlib": pytest.skip("The MPL backend does not support draggable annotations.") @@ -848,7 +848,7 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([1, 3, 4, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) # drag edge and merge 2 annotations in focus (selected description) fig._fake_click( @@ -858,12 +858,12 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([1, 3, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) assert_allclose( raw.annotations.duration, np.array([1, 1.8, 1, 0.5, 0.5]), - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) # drag annotation and merge 2 annotations in focus (selected description) fig._fake_click( @@ -873,12 +873,12 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([2.5, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) assert_allclose( raw.annotations.duration, np.array([2.3, 1, 0.5, 0.5]), - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) # drag edge and merge 2 annotations not in focus fig._fake_click( @@ -888,10 +888,10 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([2.5, 5, 7]) + raw.first_samp / raw.info["sfreq"], - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) assert_allclose( - raw.annotations.duration, np.array([2.3, 1, 1.5]), atol=1 / raw.info["sfreq"] + raw.annotations.duration, np.array([2.3, 1, 1.5]), atol=2 / raw.info["sfreq"] ) # drag annotation and merge 2 annotations not in focus fig._fake_click( @@ -901,10 +901,10 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([2.5, 6.6]) + raw.first_samp / raw.info["sfreq"], - atol=1 / raw.info["sfreq"], + atol=2 / raw.info["sfreq"], ) assert_allclose( - raw.annotations.duration, np.array([2.3, 1.9]), atol=1 / raw.info["sfreq"] + raw.annotations.duration, np.array([2.3, 1.9]), atol=2 / raw.info["sfreq"] ) From f2aa3b25f9a97ef01c5a369b14dcbe4b5e973af0 Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Thu, 3 Aug 2023 16:06:06 +0200 Subject: [PATCH 07/13] give 10 samples of freedom to balance the imprecise _fake_click --- mne/viz/tests/test_raw.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py index a7b58c97a25..a2b4cd8bcd5 100644 --- a/mne/viz/tests/test_raw.py +++ b/mne/viz/tests/test_raw.py @@ -832,7 +832,7 @@ def test_merge_annotations(raw, browser_backend): Let's not bother in figuring out on which sample the _fake_click actually dropped the annotation, especially with the 600.614 Hz weird sampling rate. - -> atol = 2 / raw.info["sfreq"] + -> atol = 10 / raw.info["sfreq"] """ if browser_backend.name == "matplotlib": pytest.skip("The MPL backend does not support draggable annotations.") @@ -848,7 +848,7 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([1, 3, 4, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) # drag edge and merge 2 annotations in focus (selected description) fig._fake_click( @@ -858,12 +858,12 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([1, 3, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) assert_allclose( raw.annotations.duration, np.array([1, 1.8, 1, 0.5, 0.5]), - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) # drag annotation and merge 2 annotations in focus (selected description) fig._fake_click( @@ -873,12 +873,12 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([2.5, 5, 7, 8]) + raw.first_samp / raw.info["sfreq"], - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) assert_allclose( raw.annotations.duration, np.array([2.3, 1, 0.5, 0.5]), - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) # drag edge and merge 2 annotations not in focus fig._fake_click( @@ -888,10 +888,10 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([2.5, 5, 7]) + raw.first_samp / raw.info["sfreq"], - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) assert_allclose( - raw.annotations.duration, np.array([2.3, 1, 1.5]), atol=2 / raw.info["sfreq"] + raw.annotations.duration, np.array([2.3, 1, 1.5]), atol=10 / raw.info["sfreq"] ) # drag annotation and merge 2 annotations not in focus fig._fake_click( @@ -901,10 +901,10 @@ def test_merge_annotations(raw, browser_backend): assert_allclose( raw.annotations.onset, np.array([2.5, 6.6]) + raw.first_samp / raw.info["sfreq"], - atol=2 / raw.info["sfreq"], + atol=10 / raw.info["sfreq"], ) assert_allclose( - raw.annotations.duration, np.array([2.3, 1.9]), atol=2 / raw.info["sfreq"] + raw.annotations.duration, np.array([2.3, 1.9]), atol=10 / raw.info["sfreq"] ) From 3f6b63c7b0488b77ebfab763a4668b63f2315fac Mon Sep 17 00:00:00 2001 From: Mathieu Scheltienne Date: Thu, 3 Aug 2023 17:50:06 +0200 Subject: [PATCH 08/13] trigger cis From c2e0a7bf7fd66e099a5f692ebc207cd8752ee001 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 3 Aug 2023 14:26:07 -0400 Subject: [PATCH 09/13] FIX: Use main mne-qt-browser --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 08b983ef454..7525ad4a61f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -108,7 +108,7 @@ stages: - bash: | set -e python -m pip install --progress-bar off --upgrade pip setuptools wheel - python -m pip install --progress-bar off mne-qt-browser[opengl] pyvista scikit-learn pytest-error-for-skips python-picard "PySide6!=6.5.1" qtpy + python -m pip install --progress-bar off git+https://github.com/mne-tools/mne-qt-browser.git@main[opengl] pyvista scikit-learn pytest-error-for-skips python-picard "PySide6!=6.5.1" qtpy python -m pip uninstall -yq mne python -m pip install --progress-bar off --upgrade -e .[test] displayName: 'Install dependencies with pip' From 688bb7972b246e7f47a6e93e8106f3b4e26b160b Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 3 Aug 2023 14:33:33 -0400 Subject: [PATCH 10/13] FIX: pip --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7525ad4a61f..2aded4994fd 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -108,7 +108,7 @@ stages: - bash: | set -e python -m pip install --progress-bar off --upgrade pip setuptools wheel - python -m pip install --progress-bar off git+https://github.com/mne-tools/mne-qt-browser.git@main[opengl] pyvista scikit-learn pytest-error-for-skips python-picard "PySide6!=6.5.1" qtpy + python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git@main" pyvista scikit-learn pytest-error-for-skips python-picard "PySide6!=6.5.1" qtpy python -m pip uninstall -yq mne python -m pip install --progress-bar off --upgrade -e .[test] displayName: 'Install dependencies with pip' From a518dbd0f4eee8c8a10eca586ad48ccf0f37d0e0 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 3 Aug 2023 19:01:11 -0400 Subject: [PATCH 11/13] FIX: xfail --- mne/viz/tests/test_raw.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py index a2b4cd8bcd5..57d644bf7a3 100644 --- a/mne/viz/tests/test_raw.py +++ b/mne/viz/tests/test_raw.py @@ -836,6 +836,8 @@ def test_merge_annotations(raw, browser_backend): """ if browser_backend.name == "matplotlib": pytest.skip("The MPL backend does not support draggable annotations.") + elif not check_version("mne_qt_browser", "0.5.3"): + pytest.xfail("mne_qt_browser < 0.5.3 does not merge properly") annot = Annotations( onset=[1, 3, 4, 5, 7, 8], duration=[1, 0.5, 0.8, 1, 0.5, 0.5], From 93f860120e4853f4cf509a78f6d8f37e3e5f4d64 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Thu, 3 Aug 2023 19:23:48 -0400 Subject: [PATCH 12/13] FIX: More --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b726f20156b..b6dcdb06a60 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,6 +46,7 @@ jobs: pip install --upgrade pip setuptools wheel pip install --upgrade --only-binary "numpy,scipy,dipy,statsmodels" -ve . -r requirements.txt -r requirements_testing.txt -r requirements_testing_extra.txt PyQt6 pip uninstall -y vtk pyvista pyvistaqt # too slow on Apple's software renderer! + pip uninstall -y numba # creates weird segfaults :( mkdir -p test-results echo "set -eo pipefail" >> $BASH_ENV - run: From 491fdaca0f9fb980d83244bd3979f739b05810a4 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Mon, 14 Aug 2023 12:11:55 -0400 Subject: [PATCH 13/13] Update mne/viz/tests/test_raw.py [ci skip] Co-authored-by: Daniel McCloy --- mne/viz/tests/test_raw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py index 57d644bf7a3..23856fc509e 100644 --- a/mne/viz/tests/test_raw.py +++ b/mne/viz/tests/test_raw.py @@ -837,7 +837,7 @@ def test_merge_annotations(raw, browser_backend): if browser_backend.name == "matplotlib": pytest.skip("The MPL backend does not support draggable annotations.") elif not check_version("mne_qt_browser", "0.5.3"): - pytest.xfail("mne_qt_browser < 0.5.3 does not merge properly") + pytest.xfail("mne_qt_browser < 0.5.3 does not merge annotations properly") annot = Annotations( onset=[1, 3, 4, 5, 7, 8], duration=[1, 0.5, 0.8, 1, 0.5, 0.5],