Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/dev/13722.newfeature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``sensitiviy`` kwarg in :meth:`mne.Report.add_forward` to get the sensitiviy map of the forward models, by `Himanshu Mahor`_.
150 changes: 147 additions & 3 deletions mne/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from ..minimum_norm import InverseOperator, read_inverse_operator
from ..parallel import parallel_func
from ..preprocessing.ica import read_ica
from ..proj import read_proj
from ..proj import read_proj, sensitivity_map
from ..source_estimate import SourceEstimate, read_source_estimate
from ..source_space._source_space import _ensure_src
from ..surface import dig_mri_distances
Expand Down Expand Up @@ -1546,6 +1546,7 @@ def add_forward(
subject=None,
subjects_dir=None,
plot=False,
sensitivity=False,
tags=("forward-solution",),
section=None,
replace=False,
Expand All @@ -1567,6 +1568,14 @@ def add_forward(
If True, plot the source space of the forward solution.

.. versionadded:: 1.10
sensitivity : bool | list of str
If True, compute and plot sensitivity maps for all available
channel types (MEG gradiometers, MEG magnetometers, and EEG).
If a list, compute sensitivity maps for only the specified
channel types (e.g., ``['grad', 'mag']``).
Valid channel types are ``'grad'``, ``'mag'``, and ``'eeg'``.

.. versionadded:: 1.12
%(tags_report)s
%(section_report)s

Expand All @@ -1589,6 +1598,7 @@ def add_forward(
tags=tags,
replace=replace,
plot=plot,
sensitivity=sensitivity,
)

@fill_doc
Expand Down Expand Up @@ -3616,6 +3626,7 @@ def _add_forward(
title,
image_format,
plot,
sensitivity,
section,
tags,
replace,
Expand All @@ -3626,10 +3637,143 @@ def _add_forward(

subject = self.subject if subject is None else subject
subject = forward["src"][0]["subject_his_id"] if subject is None else subject
subjects_dir = self.subjects_dir if subjects_dir is None else subjects_dir

# XXX Todo
# Render sensitivity maps
sensitivity_maps_html = ""
if sensitivity:
if subjects_dir is None:
raise ValueError(
"subjects_dir must be provided to compute sensitivity maps"
)

info = forward["info"]
meg_info = info.get("meg", False)
has_grad = meg_info and (
isinstance(meg_info, dict)
and meg_info.get("grad", False)
or meg_info is True
)
has_mag = meg_info and (
isinstance(meg_info, dict)
and meg_info.get("mag", False)
or meg_info is True
)
has_eeg = info.get("eeg", False)

all_ch_types = []
if has_grad:
all_ch_types.append("grad")
if has_mag:
all_ch_types.append("mag")
if has_eeg:
all_ch_types.append("eeg")

if not all_ch_types:
raise ValueError(
"No MEG or EEG channels found in forward solution. "
"Cannot compute sensitivity maps."
)

if sensitivity is True:
ch_types = all_ch_types
else:
ch_types = list(sensitivity)
for ch_type in ch_types:
_check_option("ch_type", ch_type, ["grad", "mag", "eeg"])
if ch_type not in all_ch_types:
raise ValueError(
f"Channel type '{ch_type}' not found in forward solution. "
f"Available types are: {all_ch_types}"
)

html_parts = []
for ch_type in ch_types:
_check_option("ch_type", ch_type, ["grad", "mag", "eeg"])

html_parts = []
for ch_type in ch_types:
stc = sensitivity_map(forward, ch_type=ch_type, mode="fixed")

stc_plot_kwargs = _handle_default("report_stc_plot_kwargs", dict())
stc_plot_kwargs.update(
subject=subject,
subjects_dir=subjects_dir,
clim=dict(kind="value", lims=[0, 50, 100]),
colorbar=True,
)

import matplotlib.pyplot as plt

if get_3d_backend() is not None:
brain = stc.plot(**stc_plot_kwargs)
brain._renderer.plotter.subplot(0, 0)
fig, ax = plt.subplots(figsize=(4.5, 4.5), layout="constrained")
ax.imshow(brain.screenshot(time_viewer=False, mode="rgb"))
ax.axis("off")
_constrain_fig_resolution(
fig,
max_width=stc_plot_kwargs.get("size", (800, 600))[0],
max_res=self.img_max_res,
)
plt.close(fig)
brain.close()
else:
fig_lh = plt.figure(layout="constrained")
fig_rh = plt.figure(layout="constrained")
brain_lh = stc.plot(
views="lat",
hemi="lh",
initial_time=stc.times[0],
backend="matplotlib",
subject=subject,
subjects_dir=subjects_dir,
figure=fig_lh,
**stc_plot_kwargs,
)
brain_rh = stc.plot(
views="lat",
hemi="rh",
initial_time=stc.times[0],
subject=subject,
subjects_dir=subjects_dir,
backend="matplotlib",
figure=fig_rh,
**stc_plot_kwargs,
)
_constrain_fig_resolution(
fig_lh,
max_width=stc_plot_kwargs.get("size", (800, 600))[0],
max_res=self.img_max_res,
)
_constrain_fig_resolution(
fig_rh,
max_width=stc_plot_kwargs.get("size", (800, 600))[0],
max_res=self.img_max_res,
)
fig = fig_lh
plt.close(fig_rh)
brain_lh.close()
brain_rh.close()

img = self._fig_to_img(fig=fig, image_format=image_format)
plt.close(fig)

img_id = f"forward-sensitivity-{ch_type}"
img_html = _html_image_element(
id_=img_id,
img=img,
image_format=image_format,
caption=f"Sensitivity map ({ch_type})",
show=True,
div_klass="forward-sensitivity-map",
img_klass="forward-sensitivity-map",
title=f"Sensitivity Map - {ch_type.upper()}",
tags=(),
)
html_parts.append(img_html)

sensitivity_maps_html = "\n".join(html_parts)

source_space_html = ""
if plot:
source_space_html = self._src_html(
Expand Down