Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX] fixes several plotting details in glm reports #4266

Merged
merged 8 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/changes/latest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Fixes
- :bdg-dark:`Code` Fix color bar handling with color map with only 1 level (:gh:`4255` by `Rémi Gau`_).
- :bdg-dark:`Code` Fix positions of the markers on the images on the sphere masker reports (:gh:`4285` by `Rémi Gau`_).
- :bdg-dark:`Code` Make sure that :class:`nilearn.maskers.NiftiSpheresMasker` reports displays properly when it contains only 1 sphere (:gh:`4269` by `Rémi Gau`_).
- :bdg-dark:`Code` Miscellaneous fixes in GLM reports (only display FIR delay if FIR is used, display color bar "Z score" legend...) (:gh:`4266` by `Rémi Gau`_).


Enhancements
------------
Expand All @@ -26,3 +28,4 @@ Changes
- :bdg-primary:`Doc` Render the description of the templates, atlases and datasets of the :mod:`nilearn.datasets` as part of the documentation (:gh:`4232` by `Rémi Gau`_).
- :bdg-dark:`Code` Change the colormap to ``gray`` for the background image in the :class:`nilearn.maskers.NiftiSpheresMasker` (:gh:`4269` by `Rémi Gau`_).
- :bdg-dark:`Code` Remove unused ``**kwargs`` from :func:`nilearn.plotting.view_img` and :func:`nilearn.plotting.plot_surf` (:gh:`4270` by `Rémi Gau`_).
- :bdg-dark:`Code` Use red to blue color map in the GLM reports (:gh:`4266` by `Rémi Gau`_).
9 changes: 8 additions & 1 deletion doc/visual_testing/reporter_visual_inspection_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def report_flm_adhd_dmn():
contrasts=contrasts,
title="ADHD DMN Report",
cluster_threshold=15,
alpha=0.0009,
height_control="bonferroni",
min_distance=8.0,
plot_type="glass",
Expand Down Expand Up @@ -176,6 +177,7 @@ def report_flm_bids_features():
contrasts="StopSuccess - Go",
title=title,
cluster_threshold=3,
plot_type="glass",
)

report.save_as_html(REPORTS_DIR / "flm_bids_features.html")
Expand Down Expand Up @@ -252,15 +254,20 @@ def report_slm_oasis():
oasis_dataset.gray_matter_maps, design_matrix=design_matrix
)

# TODO The following fails:
# TODO the following crashes
# contrast = [np.array([1, 0]), np.array([0, 1])]
# contrast = [[1, 0, 0], [0, 1, 0]]

# The following are equivalent
# contrast = [np.array([1, 0, 0]), np.array([0, 1, 0])]
contrast = ["age", "sex"]

report = make_glm_report(
model=second_level_model,
contrasts=contrast,
bg_img=datasets.fetch_icbm152_2009()["t1"],
height_control=None,
plot_type="glass",
)

report.save_as_html(REPORTS_DIR / "slm_oasis.html")
Expand Down
2 changes: 1 addition & 1 deletion nilearn/glm/first_level/first_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def mean_scaling(Y, axis=0):
mean = Y.mean(axis=axis)
if (mean == 0).any():
warn(
"Mean values of 0 observed."
"Mean values of 0 observed. "
"The data have probably been centered."
"Scaling might not work as expected",
UserWarning,
Expand Down
47 changes: 44 additions & 3 deletions nilearn/reporting/glm_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
import warnings
from collections import OrderedDict
from collections.abc import Iterable
from decimal import Decimal
from html import escape

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

from nilearn.plotting import plot_glass_brain, plot_roi, plot_stat_map
from nilearn.plotting.cm import _cmap_d as nilearn_cmaps
from nilearn.plotting.img_plotting import MNI152TEMPLATE
from nilearn.plotting.matrix_plotting import (
plot_contrast_matrix,
Expand All @@ -36,6 +38,7 @@
from nilearn.glm.thresholding import threshold_stats_img

from nilearn._utils import check_niimg
from nilearn._utils.niimg import safe_get_data
from nilearn.maskers import NiftiMasker
from nilearn.reporting.get_clusters_table import get_clusters_table
from nilearn.reporting.utils import figure_to_svg_quoted
Expand Down Expand Up @@ -480,13 +483,15 @@
"smoothing_fwhm",
"target_affine",
"slice_time_ref",
"fir_delays",
]
attribute_units = {
"t_r": "s",
"high_pass": "Hz",
}

if hasattr(model, "hrf_model") and getattr(model, "hrf_model") == "fir":
selected_attributes.append("fir_delays")

Check warning on line 493 in nilearn/reporting/glm_reporter.py

View check run for this annotation

Codecov / codecov/patch

nilearn/reporting/glm_reporter.py#L493

Added line #L493 was not covered by tests

selected_attributes.sort()
display_attributes = OrderedDict(
(attr_name, getattr(model, attr_name))
Expand Down Expand Up @@ -573,7 +578,8 @@
dmtx_text_ = string.Template(dmtx_template_text)
dmtx_plot = plot_design_matrix(design_matrix)
dmtx_title = f"Run {dmtx_count}"
plt.title(dmtx_title, y=0.987)
if len(design_matrices) > 1:
plt.title(dmtx_title, y=1.025, x=-0.1)

Check warning on line 582 in nilearn/reporting/glm_reporter.py

View check run for this annotation

Codecov / codecov/patch

nilearn/reporting/glm_reporter.py#L582

Added line #L582 was not covered by tests
dmtx_plot = _resize_plot_inches(dmtx_plot, height_change=0.3)
url_design_matrix_svg = _plot_to_svg(dmtx_plot)
# prevents sphinx-gallery & jupyter from scraping & inserting plots
Expand Down Expand Up @@ -811,7 +817,7 @@
)
table_details_html = _dataframe_to_html(
table_details,
precision=2,
precision=3,
header=False,
classes="cluster-details-table",
)
Expand Down Expand Up @@ -877,6 +883,8 @@
This is simpler than overloading the class using inheritance,
especially given limited Python2 use at time of release.
"""
if alpha < 0.001:
alpha = f"{Decimal(alpha):.2E}"

Check warning on line 887 in nilearn/reporting/glm_reporter.py

View check run for this annotation

Codecov / codecov/patch

nilearn/reporting/glm_reporter.py#L887

Added line #L887 was not covered by tests
if os.sys.version_info.major == 2:
table_details.update({"alpha": alpha})
else:
Expand Down Expand Up @@ -953,12 +961,28 @@
SVG Image Data URL representing a statistical map.

"""
data = safe_get_data(stat_img, ensure_finite=True)
stat_map_min = np.nanmin(data)
stat_map_max = np.nanmax(data)
symmetric_cbar = True
cmap = "bwr"
if stat_map_min >= 0.0:
symmetric_cbar = False
cmap = "red_transparent_full_alpha_range"
elif stat_map_max <= 0.0:
symmetric_cbar = False
cmap = "blue_transparent_full_alpha_range"
cmap = nilearn_cmaps[cmap].reversed()

Check warning on line 975 in nilearn/reporting/glm_reporter.py

View check run for this annotation

Codecov / codecov/patch

nilearn/reporting/glm_reporter.py#L973-L975

Added lines #L973 - L975 were not covered by tests

if plot_type == "slice":
stat_map_plot = plot_stat_map(
stat_img,
bg_img=bg_img,
cut_coords=cut_coords,
display_mode=display_mode,
colorbar=True,
cmap=cmap,
symmetric_cbar=symmetric_cbar,
threshold=threshold,
)
elif plot_type == "glass":
Expand All @@ -967,13 +991,30 @@
display_mode=display_mode,
colorbar=True,
plot_abs=False,
symmetric_cbar=symmetric_cbar,
cmap=cmap,
threshold=threshold,
)
else:
raise ValueError(
"Invalid plot type provided. "
"Acceptable options are 'slice' or 'glass'."
)

x_label_color = "black"
if plot_type == "slice":
x_label_color = "white"

if hasattr(stat_map_plot, "_cbar"):
cbar_ax = stat_map_plot._cbar.ax
cbar_ax.set_xlabel(
"Z score",
labelpad=5,
fontweight="bold",
loc="right",
color=x_label_color,
)

with pd.option_context("display.precision", 2):
_add_params_to_plot(table_details, stat_map_plot)
fig = plt.gcf()
Expand Down