Skip to content

Commit 0ab3f5f

Browse files
authored
ENH: Add support for plotting ICA source timecourses in Report.add_ica (#13697)
1 parent d52c89e commit 0ab3f5f

4 files changed

Lines changed: 62 additions & 1 deletion

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ICA source timecourse plots to :func:`mne.Report.add_ica`, by `Aniket Singh Yadav`_.

mne/report/report.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,22 @@ def _add_ica_components(self, *, ica, picks, image_format, section, tags, replac
20182018
replace=replace,
20192019
)
20202020

2021+
def _add_ica_sources(
2022+
self, *, ica, inst, picks, image_format, section, tags, replace
2023+
):
2024+
with use_browser_backend("matplotlib"):
2025+
fig = ica.plot_sources(inst=inst, picks=picks, show=False)
2026+
self._add_figure(
2027+
fig=fig,
2028+
title="Sources",
2029+
caption=None,
2030+
image_format=image_format,
2031+
tags=tags,
2032+
section=section,
2033+
replace=replace,
2034+
own_figure=True,
2035+
)
2036+
20212037
def _add_ica(
20222038
self,
20232039
*,
@@ -2034,6 +2050,7 @@ def _add_ica(
20342050
tags,
20352051
n_jobs,
20362052
replace,
2053+
plot_sources=False,
20372054
):
20382055
if _path_like(ica):
20392056
ica = read_ica(ica)
@@ -2164,6 +2181,26 @@ def _add_ica(
21642181
replace=replace,
21652182
)
21662183

2184+
# Sources plot
2185+
if plot_sources:
2186+
if inst is None:
2187+
raise ValueError(
2188+
"Cannot plot ICA sources because inst=None. "
2189+
"Please pass a Raw, Epochs, or Evoked instance to "
2190+
"add_ica() to enable source plotting, or pass "
2191+
"plot_sources=False."
2192+
)
2193+
2194+
self._add_ica_sources(
2195+
ica=ica,
2196+
inst=inst,
2197+
picks=picks,
2198+
image_format=image_format,
2199+
section=section,
2200+
tags=tags,
2201+
replace=replace,
2202+
)
2203+
21672204
@fill_doc
21682205
def add_ica(
21692206
self,
@@ -2179,6 +2216,7 @@ def add_ica(
21792216
n_jobs=None,
21802217
tags=("ica",),
21812218
replace=False,
2219+
plot_sources=False,
21822220
):
21832221
"""Add (a fitted) `~mne.preprocessing.ICA` to the report.
21842222
@@ -2205,6 +2243,12 @@ def add_ica(
22052243
%(n_jobs)s
22062244
%(tags_report)s
22072245
%(replace_report)s
2246+
plot_sources : bool
2247+
Whether to add a plot of the ICA source time-courses using
2248+
:meth:`mne.preprocessing.ICA.plot_sources`. Requires ``inst``
2249+
to be provided. Defaults to ``False``.
2250+
2251+
.. versionadded:: 1.12
22082252
22092253
Notes
22102254
-----
@@ -2225,6 +2269,7 @@ def add_ica(
22252269
section=title,
22262270
n_jobs=n_jobs,
22272271
replace=replace,
2272+
plot_sources=plot_sources,
22282273
)
22292274

22302275
def remove(self, *, title=None, tags=None, remove_all=False):

mne/report/tests/test_report.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,8 +1031,10 @@ def test_manual_report_2d(tmp_path, invisible_fig):
10311031
eog_evoked=ica_eog_evoked,
10321032
ecg_scores=ica_ecg_scores,
10331033
eog_scores=ica_eog_scores,
1034+
plot_sources=True,
10341035
)
1035-
assert "ICA component 2" in r._content[-1].html
1036+
assert "ICA component 2" in r._content[-2].html
1037+
assert "Sources" in r._content[-1].html
10361038
epochs_baseline = epochs_without_metadata.copy().load_data()
10371039
epochs_baseline.apply_baseline((None, 0))
10381040
r.add_ica(
@@ -1042,6 +1044,16 @@ def test_manual_report_2d(tmp_path, invisible_fig):
10421044
picks=[0],
10431045
)
10441046
r.add_ica(ica=ica, title="my ica with picks=None", inst=epochs_baseline, picks=None)
1047+
1048+
# plot_sources=True with inst=None should raise a ValueError
1049+
with pytest.raises(ValueError, match="Cannot plot ICA sources because inst=None"):
1050+
r.add_ica(
1051+
ica=ica,
1052+
title="my ica sources no inst",
1053+
inst=None,
1054+
plot_sources=True,
1055+
)
1056+
10451057
r.add_covariance(cov=cov, info=raw_fname, title="my cov")
10461058
r.add_forward(
10471059
forward=fwd_fname,

tutorials/intro/70_report.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@
231231
#
232232
# Lastly, by passing ``n_jobs``, you may largely speed up the generation of
233233
# the properties plots by enabling parallel execution.
234+
# To additionally include ICA source time-courses in the report, pass
235+
# ``plot_sources=True``. This requires ``inst`` to be provided.
234236
#
235237
# .. warning::
236238
# In the following example, we request a small number of ICA components
@@ -262,6 +264,7 @@
262264
title="ICA cleaning",
263265
picks=ica.exclude, # plot the excluded EOG components
264266
inst=raw,
267+
plot_sources=True,
265268
eog_evoked=eog_epochs.average(),
266269
eog_scores=eog_scores,
267270
n_jobs=None, # could be increased!

0 commit comments

Comments
 (0)