Skip to content

Commit fe96e58

Browse files
ENH: adds annotation filtering to raw and ica source figures
1 parent c4de9b6 commit fe96e58

File tree

8 files changed

+77
-19
lines changed

8 files changed

+77
-19
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added `annotation_regex` parameter to :func:`mne.viz.raw.plot_raw` and :func:`mne.viz.ica.plot_sources`, automatically hiding annotations not matching the regex, by `Johannes Herforth`_.

mne/io/base.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,6 +1911,8 @@ def plot(
19111911
color=None,
19121912
bad_color="lightgray",
19131913
event_color="cyan",
1914+
*,
1915+
annotation_regex=".*",
19141916
scalings=None,
19151917
remove_dc=True,
19161918
order=None,
@@ -1934,7 +1936,6 @@ def plot(
19341936
time_format="float",
19351937
precompute=None,
19361938
use_opengl=None,
1937-
*,
19381939
picks=None,
19391940
theme=None,
19401941
overview_mode=None,
@@ -1951,22 +1952,23 @@ def plot(
19511952
color,
19521953
bad_color,
19531954
event_color,
1954-
scalings,
1955-
remove_dc,
1956-
order,
1957-
show_options,
1958-
title,
1959-
show,
1960-
block,
1961-
highpass,
1962-
lowpass,
1963-
filtorder,
1964-
clipping,
1965-
show_first_samp,
1966-
proj,
1967-
group_by,
1968-
butterfly,
1969-
decim,
1955+
annotation_regex=annotation_regex,
1956+
scalings=scalings,
1957+
remove_dc=remove_dc,
1958+
order=order,
1959+
show_options=show_options,
1960+
title=title,
1961+
show=show,
1962+
block=block,
1963+
highpass=highpass,
1964+
lowpass=lowpass,
1965+
filtorder=filtorder,
1966+
clipping=clipping,
1967+
show_first_samp=show_first_samp,
1968+
proj=proj,
1969+
group_by=group_by,
1970+
butterfly=butterfly,
1971+
decim=decim,
19701972
noise_cov=noise_cov,
19711973
event_id=event_id,
19721974
show_scrollbars=show_scrollbars,

mne/preprocessing/ica.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,6 +2585,7 @@ def plot_sources(
25852585
precompute=None,
25862586
use_opengl=None,
25872587
*,
2588+
annotation_regex=".*",
25882589
psd_args=None,
25892590
theme=None,
25902591
overview_mode=None,
@@ -2599,6 +2600,7 @@ def plot_sources(
25992600
title=title,
26002601
show=show,
26012602
block=block,
2603+
annotation_regex=annotation_regex,
26022604
psd_args=psd_args,
26032605
show_first_samp=show_first_samp,
26042606
show_scrollbars=show_scrollbars,

mne/viz/_figure.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import importlib
88
import inspect
9+
import re
910
from abc import ABC, abstractmethod
1011
from collections import OrderedDict
1112
from contextlib import contextmanager
@@ -182,7 +183,10 @@ def _setup_annotation_colors(self):
182183
segment_colors[key] = next(color_cycle)
183184
self.mne.annotation_segment_colors = segment_colors
184185
# init a couple other annotation-related variables
185-
self.mne.visible_annotations = {label: True for label in labels}
186+
annot_regex = re.compile(self.mne.annotation_regex)
187+
self.mne.visible_annotations = {
188+
label: True if annot_regex.findall(label) else False for label in labels
189+
}
186190
self.mne.show_hide_annotation_checkboxes = None
187191

188192
def _update_annotation_segments(self):

mne/viz/ica.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def plot_ica_sources(
5050
precompute=None,
5151
use_opengl=None,
5252
*,
53+
annotation_regex=".*",
5354
psd_args=None,
5455
theme=None,
5556
overview_mode=None,
@@ -92,6 +93,11 @@ def plot_ica_sources(
9293
%(time_format)s
9394
%(precompute)s
9495
%(use_opengl)s
96+
annotation_regex : str
97+
A regex pattern applied to each annotation's label.
98+
Matching labels remain visible, non-matching labels are hidden.
99+
100+
.. versionadded:: 1.11
95101
psd_args : dict | None
96102
Dictionary of arguments to pass to :meth:`~mne.Epochs.compute_psd` in
97103
interactive mode. Ignored if ``inst`` is not supplied. If ``None``,
@@ -140,6 +146,7 @@ def plot_ica_sources(
140146
show=show,
141147
title=title,
142148
block=block,
149+
annotation_regex=annotation_regex,
143150
psd_args=psd_args,
144151
show_first_samp=show_first_samp,
145152
show_scrollbars=show_scrollbars,
@@ -1292,6 +1299,7 @@ def _plot_sources(
12921299
precompute,
12931300
use_opengl,
12941301
*,
1302+
annotation_regex=".*",
12951303
psd_args,
12961304
theme=None,
12971305
overview_mode=None,
@@ -1415,6 +1423,7 @@ def _plot_sources(
14151423
decim=1,
14161424
# events
14171425
event_times=None if is_raw else event_times,
1426+
annotation_regex=annotation_regex,
14181427
# preprocessing
14191428
projs=list(),
14201429
projs_on=np.array([], dtype=bool),

mne/viz/raw.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ def plot_raw(
3737
color=None,
3838
bad_color="lightgray",
3939
event_color="cyan",
40+
*,
41+
annotation_regex=".*",
4042
scalings=None,
4143
remove_dc=True,
4244
order=None,
@@ -61,7 +63,6 @@ def plot_raw(
6163
precompute=None,
6264
use_opengl=None,
6365
picks=None,
64-
*,
6566
theme=None,
6667
overview_mode=None,
6768
splash=True,
@@ -99,6 +100,11 @@ def plot_raw(
99100
Color to make bad channels.
100101
%(event_color)s
101102
Defaults to ``'cyan'``.
103+
annotation_regex : str
104+
A regex pattern applied to each annotation's label.
105+
Matching labels remain visible, non-matching labels are hidden.
106+
107+
.. versionadded:: 1.11
102108
%(scalings)s
103109
remove_dc : bool
104110
If True remove DC component when plotting data.
@@ -373,6 +379,7 @@ def plot_raw(
373379
event_times=event_times,
374380
event_nums=event_nums,
375381
event_id_rev=event_id_rev,
382+
annotation_regex=annotation_regex,
376383
# preprocessing
377384
projs=projs,
378385
projs_on=projs_on,

mne/viz/tests/test_ica.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,22 @@ def test_plot_ica_sources(raw_orig, browser_backend, monkeypatch):
375375
leg = ax.get_legend()
376376
assert len(leg.get_texts()) == len(ica.exclude) == 1
377377

378+
# Check if annotation filtering works - All annotations
379+
annot = Annotations([0.1, 0.3], [0.1, 0.1], ["test", "test2"])
380+
raw.set_annotations(annot)
381+
382+
fig = ica.plot_sources(raw)
383+
384+
assert fig.mne.visible_annotations["test"] and fig.mne.visible_annotations["test2"]
385+
386+
# Check if annotation filtering works - filtering annotations
387+
# This should only make test2 visible and hide test
388+
fig = ica.plot_sources(raw, annotation_regex="2$")
389+
390+
assert (
391+
not fig.mne.visible_annotations["test"] and fig.mne.visible_annotations["test2"]
392+
)
393+
378394
# test passing psd_args argument
379395
ica.plot_sources(epochs, psd_args=dict(fmax=50))
380396

mne/viz/tests/test_raw.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,23 @@ def test_plot_annotations(raw, browser_backend):
809809
fig._toggle_single_channel_annotation(ch_pick, 0)
810810
assert fig.mne.inst.annotations.ch_names[0] == (ch_pick,)
811811

812+
# Check if annotation filtering works - All annotations
813+
annot = Annotations([42, 50], [1, 1], ["test", "test2"], raw.info["meas_date"])
814+
with pytest.warns(RuntimeWarning, match="expanding outside"):
815+
raw.set_annotations(annot)
816+
817+
fig = raw.plot()
818+
819+
assert fig.mne.visible_annotations["test"] and fig.mne.visible_annotations["test2"]
820+
821+
# Check if annotation filtering works - filtering annotations
822+
# This should only make test2 visible and hide test
823+
fig = raw.plot(annotation_regex="2$")
824+
825+
assert (
826+
not fig.mne.visible_annotations["test"] and fig.mne.visible_annotations["test2"]
827+
)
828+
812829

813830
@pytest.mark.parametrize("active_annot_idx", (0, 1, 2))
814831
def test_overlapping_annotation_deletion(raw, browser_backend, active_annot_idx):

0 commit comments

Comments
 (0)