Coverage for nilearn/plotting/tests/test_img_plotting/test_plot_connectome.py: 0%
85 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-16 12:32 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-16 12:32 +0200
1"""Tests for :func:`nilearn.plotting.plot_connectome`."""
3import numpy as np
4import pytest
5from matplotlib.patches import FancyArrow
6from scipy import sparse
8from nilearn.plotting import plot_connectome
11@pytest.fixture
12def non_symmetric_matrix():
13 """Non symmetric adjacency matrix."""
14 return np.array(
15 [
16 [1.0, -2.0, 0.3, 0.2],
17 [0.1, 1, 1.1, 0.1],
18 [0.01, 2.3, 1.0, 3.1],
19 [0.6, 0.03, 1.2, 1.0],
20 ]
21 )
24def test_plot_connectome_masked_array_sparse_matrix(
25 node_coords, adjacency, params_plot_connectome
26):
27 """Smoke tests for plot_connectome with masked arrays \
28 and sparse matrices as inputs.
29 """
30 masked_adjacency_matrix = np.ma.masked_array(
31 adjacency, np.abs(adjacency) < 0.5
32 )
33 plot_connectome(
34 masked_adjacency_matrix, node_coords, **params_plot_connectome
35 )
36 sparse_adjacency_matrix = sparse.coo_matrix(adjacency)
37 plot_connectome(
38 sparse_adjacency_matrix, node_coords, **params_plot_connectome
39 )
42def test_plot_connectome_with_nans(
43 adjacency, node_coords, params_plot_connectome
44):
45 """Smoke test for plot_connectome with nans in the adjacency matrix."""
46 adjacency[0, 1] = np.nan
47 adjacency[1, 0] = np.nan
48 params_plot_connectome["node_color"] = np.array(
49 ["green", "blue", "k", "yellow"]
50 )
51 plot_connectome(
52 adjacency, node_coords, colorbar=False, **params_plot_connectome
53 )
56def test_plot_connectome_tuple_node_coords(
57 adjacency, node_coords, params_plot_connectome
58):
59 """Smoke test for plot_connectome where node_coords is not provided \
60 as an array but as a list of tuples.
61 """
62 plot_connectome(
63 adjacency,
64 [tuple(each) for each in node_coords],
65 display_mode="x",
66 **params_plot_connectome,
67 )
70def test_plot_connectome_to_file(
71 adjacency, node_coords, params_plot_connectome, tmp_path
72):
73 """Smoke test for plot_connectome and saving to file."""
74 params_plot_connectome["display_mode"] = "x"
75 filename = tmp_path / "temp.png"
76 display = plot_connectome(
77 adjacency, node_coords, output_file=filename, **params_plot_connectome
78 )
79 assert display is None
80 assert filename.is_file()
81 assert filename.stat().st_size > 0
84def test_plot_connectome_with_too_high_edge_threshold(adjacency, node_coords):
85 """Smoke-test where there is no edge to draw, \
86 e.g. when edge_threshold is too high.
87 """
88 plot_connectome(
89 adjacency, node_coords, edge_threshold=1e12, colorbar=False
90 )
93def test_plot_connectome_non_symmetric(node_coords, non_symmetric_matrix):
94 """Tests for plot_connectome with non symmetric adjacency matrices."""
95 ax = plot_connectome(
96 non_symmetric_matrix, node_coords, display_mode="ortho"
97 )
98 # No thresholding was performed, we should get
99 # as many arrows as we have edges
100 for direction in ["x", "y", "z"]:
101 assert len(
102 [
103 patch
104 for patch in ax.axes[direction].ax.patches
105 if isinstance(patch, FancyArrow)
106 ]
107 ) == np.prod(non_symmetric_matrix.shape)
109 # Set a few elements of adjacency matrix to zero
110 non_symmetric_matrix[1, 0] = 0.0
111 non_symmetric_matrix[2, 3] = 0.0
112 # Plot with different display mode
113 ax = plot_connectome(
114 non_symmetric_matrix, node_coords, display_mode="lzry"
115 )
116 # No edge in direction 'l' because of node coords
117 assert not [
118 patch
119 for patch in ax.axes["l"].ax.patches
120 if isinstance(patch, FancyArrow)
121 ]
122 for direction in ["z", "r", "y"]:
123 assert (
124 len(
125 [
126 patch
127 for patch in ax.axes[direction].ax.patches
128 if isinstance(patch, FancyArrow)
129 ]
130 )
131 == np.prod(non_symmetric_matrix.shape) - 2
132 )
135def test_plot_connectome_edge_thresholding(node_coords, non_symmetric_matrix):
136 """Test for plot_connectome with edge thresholding."""
137 # Case 1: Threshold is a number
138 thresh = 1.1
139 ax = plot_connectome(
140 non_symmetric_matrix, node_coords, edge_threshold=thresh
141 )
142 for direction in ["x", "y", "z"]:
143 assert len(
144 [
145 patch
146 for patch in ax.axes[direction].ax.patches
147 if isinstance(patch, FancyArrow)
148 ]
149 ) == np.sum(np.abs(non_symmetric_matrix) >= thresh)
150 # Case 2: Threshold is a percentage
151 thresh = 80
152 ax = plot_connectome(
153 non_symmetric_matrix, node_coords, edge_threshold=f"{thresh}%"
154 )
155 for direction in ["x", "y", "z"]:
156 assert len(
157 [
158 patch
159 for patch in ax.axes[direction].ax.patches
160 if isinstance(patch, FancyArrow)
161 ]
162 ) == np.sum(
163 np.abs(non_symmetric_matrix)
164 >= np.percentile(np.abs(non_symmetric_matrix.ravel()), thresh)
165 )
168@pytest.mark.parametrize(
169 "matrix",
170 [
171 np.array([[1.0, 2], [0.4, 1.0]]),
172 np.ma.masked_array(
173 np.array([[1.0, 2.0], [2.0, 1.0]]), [[False, True], [False, False]]
174 ),
175 ],
176)
177def test_plot_connectome_exceptions_non_symmetric_adjacency(matrix):
178 """Tests that warning messages are given when the adjacency matrix \
179 ends up being non symmetric.
180 """
181 node_coords = np.arange(2 * 3).reshape((2, 3))
182 with pytest.warns(UserWarning, match="A directed graph will be plotted."):
183 plot_connectome(matrix, node_coords, display_mode="x")
186@pytest.mark.parametrize(
187 "node_color",
188 [
189 ["red", "blue"],
190 ["red", "blue", "yellow", "cyan", "green"],
191 np.array(["b", "y", "g", "c", "r"]),
192 ],
193)
194def test_plot_connectome_exceptions_wrong_number_node_colors(
195 node_color, adjacency, node_coords
196):
197 """Tests that a wrong number of node colors raises \
198 a ValueError in plot_connectome.
199 """
200 with pytest.raises(
201 ValueError, match="Mismatch between the number of nodes"
202 ):
203 plot_connectome(
204 adjacency, node_coords, node_color=node_color, display_mode="x"
205 )
208def test_plot_connectome_exception_wrong_edge_threshold(
209 adjacency, node_coords
210):
211 """Tests that a TypeError is raised in plot_connectome \
212 when edge threshold is neither a number nor a string.
213 """
214 with pytest.raises(
215 TypeError, match="should be either a number or a string"
216 ):
217 plot_connectome(
218 adjacency, node_coords, edge_threshold=object(), display_mode="x"
219 )
222@pytest.mark.parametrize("threshold", ["0.1", "10", "10.2.3%", "asdf%"])
223def test_plot_connectome_exception_wrong_edge_threshold_format(
224 threshold, adjacency, node_coords
225):
226 """Tests that a ValueError is raised when edge_threshold is \
227 an incorrectly formatted string.
228 """
229 with pytest.raises(
230 ValueError,
231 match=("should be a number followed by the percent sign"),
232 ):
233 plot_connectome(
234 adjacency, node_coords, edge_threshold=threshold, display_mode="x"
235 )
238def test_plot_connectome_wrong_shapes():
239 """Tests that ValueErrors are raised when wrong shapes for node_coords \
240 or adjacency_matrix are given.
241 """
242 kwargs = {"display_mode": "x"}
243 node_coords = np.arange(2 * 3).reshape((2, 3))
244 adjacency_matrix = np.array([[1.0, 2.0], [2.0, 1.0]])
245 with pytest.raises(
246 ValueError, match=r"supposed to have shape \(n, n\).+\(1L?, 2L?\)"
247 ):
248 plot_connectome(adjacency_matrix[:1, :], node_coords, **kwargs)
250 with pytest.raises(ValueError, match=r"shape \(2L?, 3L?\).+\(2L?,\)"):
251 plot_connectome(adjacency_matrix, node_coords[:, 2], **kwargs)
253 wrong_adjacency_matrix = np.zeros((3, 3))
254 with pytest.raises(
255 ValueError, match=r"Shape mismatch.+\(3L?, 3L?\).+\(2L?, 3L?\)"
256 ):
257 plot_connectome(wrong_adjacency_matrix, node_coords, **kwargs)
260@pytest.fixture
261def expected_error_node_kwargs(node_kwargs):
262 """Return the expected error message depending on node_kwargs."""
263 if "s" in node_kwargs:
264 return "Please use 'node_size' and not 'node_kwargs'"
265 elif "c" in node_kwargs:
266 return "Please use 'node_color' and not 'node_kwargs'"
269@pytest.mark.parametrize("node_kwargs", [{"s": 50}, {"c": "blue"}])
270def test_plot_connectome_exceptions_providing_node_info_with_kwargs(
271 node_kwargs, adjacency, node_coords, expected_error_node_kwargs
272):
273 """Tests that an error is raised when specifying node parameters \
274 via node_kwargs in plot_connectome.
275 """
276 with pytest.raises(ValueError, match=expected_error_node_kwargs):
277 plot_connectome(
278 adjacency, node_coords, node_kwargs=node_kwargs, display_mode="x"
279 )