Skip to content

Commit 6f0355f

Browse files
committed
fix: require 3d backend for report source estimates
1 parent 696f362 commit 6f0355f

2 files changed

Lines changed: 26 additions & 100 deletions

File tree

mne/report/report.py

Lines changed: 11 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4600,81 +4600,29 @@ def _render_stc(
46004600
)
46014601
t_zero_idx = np.abs(times).argmin() # index of time closest to zero
46024602

4603-
# Plot using 3d backend if available, and use Matplotlib
4604-
# otherwise.
4605-
import matplotlib.pyplot as plt
4603+
if get_3d_backend() is None:
4604+
raise RuntimeError(
4605+
"A 3D backend is required to render source estimates in a report."
4606+
)
46064607

46074608
stc_plot_kwargs = _handle_default("report_stc_plot_kwargs", stc_plot_kwargs)
46084609
stc_plot_kwargs.update(subject=subject, subjects_dir=subjects_dir)
4609-
# we need to set the size based on the min (img_max_width can be None)
46104610
if self.img_max_width is not None:
46114611
stc_plot_kwargs["size"] = (
46124612
stc_plot_kwargs["size"][0],
46134613
min(stc_plot_kwargs["size"][1], self.img_max_width),
46144614
)
4615-
if get_3d_backend() is not None:
4616-
brain = stc.plot(**stc_plot_kwargs)
4617-
brain._renderer.plotter.subplot(0, 0)
4618-
backend_is_3d = True
4619-
else:
4620-
backend_is_3d = False
4615+
4616+
brain = stc.plot(**stc_plot_kwargs)
4617+
brain._renderer.plotter.subplot(0, 0)
46214618

46224619
figs = []
46234620
for t in times:
4624-
with warnings.catch_warnings():
4625-
warnings.filterwarnings(
4626-
action="ignore",
4627-
message="More than 20 figures have been opened",
4628-
category=RuntimeWarning,
4629-
)
4630-
4631-
if backend_is_3d:
4632-
brain.set_time(t)
4633-
figs.append(brain.screenshot(time_viewer=True, mode="rgb"))
4634-
else:
4635-
fig_lh = plt.figure()
4636-
fig_rh = plt.figure()
4637-
4638-
brain_lh = stc.plot(
4639-
views="lat",
4640-
hemi="lh",
4641-
initial_time=t,
4642-
backend="matplotlib",
4643-
subject=subject,
4644-
subjects_dir=subjects_dir,
4645-
figure=fig_lh,
4646-
)
4647-
brain_rh = stc.plot(
4648-
views="lat",
4649-
hemi="rh",
4650-
initial_time=t,
4651-
subject=subject,
4652-
subjects_dir=subjects_dir,
4653-
backend="matplotlib",
4654-
figure=fig_rh,
4655-
)
4656-
_constrain_fig_resolution(
4657-
fig_lh,
4658-
max_width=stc_plot_kwargs["size"][0],
4659-
max_res=self.img_max_res,
4660-
)
4661-
_constrain_fig_resolution(
4662-
fig_rh,
4663-
max_width=stc_plot_kwargs["size"][0],
4664-
max_res=self.img_max_res,
4665-
)
4666-
figs.append(brain_lh)
4667-
figs.append(brain_rh)
4668-
plt.close(fig_lh)
4669-
plt.close(fig_rh)
4670-
4671-
if backend_is_3d:
4672-
brain.close()
4621+
brain.set_time(t)
4622+
figs.append(brain.screenshot(time_viewer=True, mode="rgb"))
4623+
brain.close()
46734624

46744625
captions = [f"Time point: {round(t, 3):0.3f} s" for t in times]
4675-
if not backend_is_3d:
4676-
captions = [caption for caption in captions for _ in range(2)]
4677-
t_zero_idx *= 2
46784626
return self._render_slider(
46794627
figs=figs,
46804628
imgs=None,
@@ -4684,7 +4632,7 @@ def _render_stc(
46844632
start_idx=t_zero_idx,
46854633
tags=tags,
46864634
klass="stc",
4687-
own_figure=False, # prevent rescaling
4635+
own_figure=False,
46884636
)
46894637

46904638
@_use_agg

mne/report/tests/test_report.py

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -559,22 +559,6 @@ def test_add_forward_sensitivity_parameter():
559559
assert "sensitivity" in inspect.signature(Report.add_forward).parameters
560560

561561

562-
@testing.requires_testing_data
563-
def test_add_forward_sensitivity_matplotlib(monkeypatch):
564-
"""Test rendering forward sensitivity maps with the Matplotlib fallback."""
565-
pytest.importorskip("nibabel")
566-
monkeypatch.setattr(report_mod, "get_3d_backend", lambda: None)
567-
report = Report(subjects_dir=subjects_dir, image_format="png")
568-
report.add_forward(
569-
forward=fwd_fname,
570-
subjects_dir=subjects_dir,
571-
title="Forward solution",
572-
sensitivity=True,
573-
)
574-
assert len(report.html) == 1
575-
assert report.html[0].count("<img") == 6
576-
577-
578562
class _FakeBrain:
579563
"""Minimal stand-in for a 3D source-estimate plot."""
580564

@@ -626,8 +610,8 @@ def test_render_volume_stc(monkeypatch):
626610
assert callable(html_partial)
627611

628612

629-
def test_render_stc_matplotlib_captions(monkeypatch):
630-
"""Test Matplotlib source-estimate views have one caption per image."""
613+
def test_render_stc_requires_3d_backend(monkeypatch):
614+
"""Test rendering source estimates requires a 3D backend."""
631615
stc = SourceEstimate(
632616
data=np.ones((2, 3)),
633617
vertices=[np.array([0]), np.array([0])],
@@ -636,27 +620,21 @@ def test_render_stc_matplotlib_captions(monkeypatch):
636620
subject="sample",
637621
)
638622
report = Report()
639-
slider_kwargs = {}
640-
641-
def _render_slider(**kwargs):
642-
slider_kwargs.update(kwargs)
643-
return lambda **kwargs: ""
644-
645623
monkeypatch.setattr(report_mod, "get_3d_backend", lambda: None)
646624
monkeypatch.setattr(SourceEstimate, "plot", _fake_stc_plot)
647-
monkeypatch.setattr(report, "_render_slider", _render_slider)
648-
report._render_stc(
649-
stc=stc,
650-
title="Surface STC",
651-
subject="sample",
652-
subjects_dir=None,
653-
n_time_points=3,
654-
image_format="png",
655-
tags=(),
656-
stc_plot_kwargs=None,
657-
)
658-
assert len(slider_kwargs["figs"]) == len(slider_kwargs["captions"]) == 6
659-
assert slider_kwargs["start_idx"] == 2
625+
monkeypatch.setattr(report, "_render_slider", lambda **kwargs: None)
626+
627+
with pytest.raises(RuntimeError, match="3D backend"):
628+
report._render_stc(
629+
stc=stc,
630+
title="Surface STC",
631+
subject="sample",
632+
subjects_dir=None,
633+
n_time_points=3,
634+
image_format="png",
635+
tags=(),
636+
stc_plot_kwargs=None,
637+
)
660638

661639

662640
@testing.requires_testing_data

0 commit comments

Comments
 (0)