Coverage for nilearn/plotting/surface/tests/test_matplotlib_backend.py: 0%
96 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-20 10:58 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-20 10:58 +0200
1"""Test nilearn.plotting.surface._matplotlib_backend functions."""
3import numpy as np
4import pytest
6from nilearn.datasets import fetch_surf_fsaverage
7from nilearn.plotting.js_plotting_utils import colorscale
8from nilearn.plotting.surface._matplotlib_backend import (
9 MATPLOTLIB_VIEWS,
10 _compute_facecolors,
11 _get_bounds,
12 _get_ticks,
13 _get_vertexcolor,
14 _get_view_plot_surf,
15)
16from nilearn.surface import (
17 load_surf_data,
18 load_surf_mesh,
19)
21pytest.importorskip(
22 "matplotlib",
23 reason="Matplotlib is not installed; required to run the tests!",
24)
26EXPECTED_VIEW_MATPLOTLIB = {
27 "left": {
28 "anterior": (0, 90),
29 "posterior": (0, 270),
30 "medial": (0, 0),
31 "lateral": (0, 180),
32 "dorsal": (90, 0),
33 "ventral": (270, 0),
34 },
35 "right": {
36 "anterior": (0, 90),
37 "posterior": (0, 270),
38 "medial": (0, 180),
39 "lateral": (0, 0),
40 "dorsal": (90, 0),
41 "ventral": (270, 0),
42 },
43 "both": {
44 "right": (0, 0),
45 "left": (0, 180),
46 "dorsal": (90, 0),
47 "ventral": (270, 0),
48 "anterior": (0, 90),
49 "posterior": (0, 270),
50 },
51}
54@pytest.mark.parametrize("hemi, views", MATPLOTLIB_VIEWS.items())
55def test_get_view_plot_surf(hemi, views):
56 """Test if
57 nilearn.plotting.surface._matplotlib_backend.MatplotlibSurfaceBackend._get_view_plot_surf
58 returns expected values.
59 """
60 for v in views:
61 assert (
62 _get_view_plot_surf(hemi, v) == EXPECTED_VIEW_MATPLOTLIB[hemi][v]
63 )
66@pytest.mark.parametrize("hemi,view", [("foo", "medial"), ("bar", "anterior")])
67def test_get_view_plot_surf_hemisphere_errors(hemi, view):
68 """Test
69 nilearn.plotting.surface._matplotlib_backend.MatplotlibSurfaceBackend._get_view_plot_surf
70 for invalid hemisphere values.
71 """
72 with pytest.raises(ValueError, match="Invalid hemispheres definition"):
73 _get_view_plot_surf(hemi, view)
76@pytest.mark.parametrize(
77 "hemi,view",
78 [
79 ("left", "foo"),
80 ("right", "bar"),
81 ("both", "lateral"),
82 ("both", "medial"),
83 ("both", "foo"),
84 ],
85)
86def test_get_view_plot_surf_view_errors(hemi, view):
87 """Test
88 nilearn.plotting.surface._matplotlib_backend.MatplotlibSurfaceBackend._get_view_plot_surf
89 for invalid view values.
90 """
91 with pytest.raises(ValueError, match="Invalid view definition"):
92 _get_view_plot_surf(hemi, view)
95@pytest.mark.parametrize(
96 "data,expected",
97 [
98 (np.linspace(0, 1, 100), (0, 1)),
99 (np.linspace(-0.7, -0.01, 40), (-0.7, -0.01)),
100 ],
101)
102def test_get_bounds(data, expected):
103 """Test if nilearn.plotting.surface._matplotlib_backend._get_bounds
104 returns expected values.
105 """
106 assert _get_bounds(data) == expected
107 assert _get_bounds(data, vmin=0.2) == (0.2, expected[1])
108 assert _get_bounds(data, vmax=0.8) == (expected[0], 0.8)
109 assert _get_bounds(data, vmin=0.1, vmax=0.8) == (0.1, 0.8)
112@pytest.mark.parametrize(
113 "vmin,vmax,cbar_tick_format,expected",
114 [
115 (0, 0, "%i", [0]),
116 (0, 3, "%i", [0, 1, 2, 3]),
117 (0, 4, "%i", [0, 1, 2, 3, 4]),
118 (1, 5, "%i", [1, 2, 3, 4, 5]),
119 (0, 5, "%i", [0, 1.25, 2.5, 3.75, 5]),
120 (0, 10, "%i", [0, 2.5, 5, 7.5, 10]),
121 (0, 0, "%.1f", [0]),
122 (0, 1, "%.1f", [0, 0.25, 0.5, 0.75, 1]),
123 (1, 2, "%.1f", [1, 1.25, 1.5, 1.75, 2]),
124 (1.1, 1.2, "%.1f", [1.1, 1.125, 1.15, 1.175, 1.2]),
125 (0, np.nextafter(0, 1), "%.1f", [0.0e000, 5.0e-324]),
126 ],
127)
128def test_get_ticks(vmin, vmax, cbar_tick_format, expected):
129 """Test if nilearn.plotting.surface._matplotlib_backend._get_ticks
130 returns expected values.
131 """
132 ticks = _get_ticks(vmin, vmax, cbar_tick_format, threshold=None)
133 assert 1 <= len(ticks) <= 5
134 assert ticks[0] == vmin and ticks[-1] == vmax
135 assert (
136 len(np.unique(ticks)) == len(expected)
137 and (np.unique(ticks) == expected).all()
138 )
141def test_compute_facecolors():
142 """Test if nilearn.plotting.surface._matplotlib_backend._compute_facecolors
143 returns expected values.
144 """
145 fsaverage = fetch_surf_fsaverage()
146 mesh = load_surf_mesh(fsaverage["pial_left"])
147 alpha = "auto"
148 # Surface map whose value in each vertex is
149 # 1 if this vertex's curv > 0
150 # 0 if this vertex's curv is 0
151 # -1 if this vertex's curv < 0
152 bg_map = np.sign(load_surf_data(fsaverage["curv_left"]))
153 bg_min, bg_max = np.min(bg_map), np.max(bg_map)
154 assert bg_min < 0 or bg_max > 1
156 facecolors_auto_normalized = _compute_facecolors(
157 bg_map,
158 mesh.faces,
159 len(mesh.coordinates),
160 None,
161 alpha,
162 )
164 assert len(facecolors_auto_normalized) == len(mesh.faces)
166 # Manually set values of background map between 0 and 1
167 bg_map_normalized = (bg_map - bg_min) / (bg_max - bg_min)
168 assert np.min(bg_map_normalized) == 0 and np.max(bg_map_normalized) == 1
170 facecolors_manually_normalized = _compute_facecolors(
171 bg_map_normalized,
172 mesh.faces,
173 len(mesh.coordinates),
174 None,
175 alpha,
176 )
178 assert len(facecolors_manually_normalized) == len(mesh.faces)
179 assert np.allclose(
180 facecolors_manually_normalized, facecolors_auto_normalized
181 )
183 # Scale background map between 0.25 and 0.75
184 bg_map_scaled = bg_map_normalized / 2 + 0.25
185 assert np.min(bg_map_scaled) == 0.25 and np.max(bg_map_scaled) == 0.75
187 facecolors_manually_rescaled = _compute_facecolors(
188 bg_map_scaled,
189 mesh.faces,
190 len(mesh.coordinates),
191 None,
192 alpha,
193 )
195 assert len(facecolors_manually_rescaled) == len(mesh.faces)
196 assert not np.allclose(
197 facecolors_manually_rescaled, facecolors_auto_normalized
198 )
201def test_compute_facecolors_deprecation():
202 """Test warning deprecation."""
203 fsaverage = fetch_surf_fsaverage()
204 mesh = load_surf_mesh(fsaverage["pial_left"])
205 alpha = "auto"
206 # Surface map whose value in each vertex is
207 # 1 if this vertex's curv > 0
208 # 0 if this vertex's curv is 0
209 # -1 if this vertex's curv < 0
210 bg_map = np.sign(load_surf_data(fsaverage["curv_left"]))
211 bg_min, bg_max = np.min(bg_map), np.max(bg_map)
212 assert bg_min < 0 or bg_max > 1
213 with pytest.warns(
214 DeprecationWarning,
215 match=(
216 "The `darkness` parameter will be deprecated in release 0.13. "
217 "We recommend setting `darkness` to None"
218 ),
219 ):
220 _compute_facecolors(
221 bg_map,
222 mesh.faces,
223 len(mesh.coordinates),
224 0.5,
225 alpha,
226 )
229def test_get_vertexcolor():
230 """Test get_vertexcolor."""
231 fsaverage = fetch_surf_fsaverage()
232 mesh = load_surf_mesh(fsaverage["pial_left"])
233 surf_map = np.arange(len(mesh.coordinates))
234 colors = colorscale("jet", surf_map, 10)
236 vertexcolors = _get_vertexcolor(
237 surf_map,
238 colors["cmap"],
239 colors["norm"],
240 absolute_threshold=colors["abs_threshold"],
241 bg_map=fsaverage["sulc_left"],
242 )
244 assert len(vertexcolors) == len(mesh.coordinates)
246 vertexcolors = _get_vertexcolor(
247 surf_map,
248 colors["cmap"],
249 colors["norm"],
250 absolute_threshold=colors["abs_threshold"],
251 )
253 assert len(vertexcolors) == len(mesh.coordinates)
256def test_get_vertexcolor_bg_map():
257 """Test get_vertexcolor with background map."""
258 fsaverage = fetch_surf_fsaverage()
259 mesh = load_surf_mesh(fsaverage["pial_left"])
260 surf_map = np.arange(len(mesh.coordinates))
261 colors = colorscale("jet", surf_map, 10)
263 # Surface map whose value in each vertex is
264 # 1 if this vertex's curv > 0
265 # 0 if this vertex's curv is 0
266 # -1 if this vertex's curv < 0
267 bg_map = np.sign(load_surf_data(fsaverage["curv_left"]))
268 bg_min, bg_max = np.min(bg_map), np.max(bg_map)
269 assert bg_min < 0 or bg_max > 1
271 vertexcolors_auto_normalized = _get_vertexcolor(
272 surf_map,
273 colors["cmap"],
274 colors["norm"],
275 absolute_threshold=colors["abs_threshold"],
276 bg_map=bg_map,
277 )
279 assert len(vertexcolors_auto_normalized) == len(mesh.coordinates)
281 # Manually set values of background map between 0 and 1
282 bg_map_normalized = (bg_map - bg_min) / (bg_max - bg_min)
283 assert np.min(bg_map_normalized) == 0 and np.max(bg_map_normalized) == 1
285 vertexcolors_manually_normalized = _get_vertexcolor(
286 surf_map,
287 colors["cmap"],
288 colors["norm"],
289 absolute_threshold=colors["abs_threshold"],
290 bg_map=bg_map_normalized,
291 )
293 assert len(vertexcolors_manually_normalized) == len(mesh.coordinates)
294 assert vertexcolors_manually_normalized == vertexcolors_auto_normalized
296 # Scale background map between 0.25 and 0.75
297 bg_map_scaled = bg_map_normalized / 2 + 0.25
298 assert np.min(bg_map_scaled) == 0.25 and np.max(bg_map_scaled) == 0.75
300 vertexcolors_manually_rescaled = _get_vertexcolor(
301 surf_map,
302 colors["cmap"],
303 colors["norm"],
304 absolute_threshold=colors["abs_threshold"],
305 bg_map=bg_map_scaled,
306 )
308 assert len(vertexcolors_manually_rescaled) == len(mesh.coordinates)
309 assert vertexcolors_manually_rescaled != vertexcolors_auto_normalized
312def test_get_vertexcolor_deprecation():
313 """Check deprecation warning."""
314 fsaverage = fetch_surf_fsaverage()
315 mesh = load_surf_mesh(fsaverage["pial_left"])
316 surf_map = np.arange(len(mesh.coordinates))
317 colors = colorscale("jet", surf_map, 10)
319 with pytest.warns(
320 DeprecationWarning,
321 match=(
322 "The `darkness` parameter will be deprecated in release 0.13. "
323 "We recommend setting `darkness` to None"
324 ),
325 ):
326 _get_vertexcolor(
327 surf_map,
328 colors["cmap"],
329 colors["norm"],
330 darkness=0.5,
331 )