Coverage for nilearn/plotting/tests/test_img_plotting/test_plot_stat_map.py: 0%

63 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-16 12:32 +0200

1"""Tests for :func:`nilearn.plotting.plot_stat_map`.""" 

2 

3# ruff: noqa: ARG001 

4 

5import matplotlib.pyplot as plt 

6import numpy as np 

7import pytest 

8from nibabel import Nifti1Image 

9 

10from nilearn.conftest import _rng 

11from nilearn.datasets import load_mni152_template 

12from nilearn.image import get_data 

13from nilearn.image.resampling import coord_transform 

14from nilearn.plotting import plot_stat_map 

15from nilearn.plotting.find_cuts import find_cut_slices 

16 

17 

18def test_plot_stat_map_bad_input(matplotlib_pyplot, img_3d_mni, tmp_path): 

19 """Test for bad input arguments (cf. #510).""" 

20 filename = tmp_path / "temp.png" 

21 

22 ax = plt.subplot(111, rasterized=True) 

23 

24 plot_stat_map( 

25 img_3d_mni, 

26 symmetric_cbar=True, 

27 output_file=filename, 

28 axes=ax, 

29 vmax=np.nan, 

30 ) 

31 

32 

33@pytest.mark.parametrize( 

34 "params", [{}, {"display_mode": "x", "cut_coords": 3}] 

35) 

36def test_save_plot_stat_map(matplotlib_pyplot, params, img_3d_mni, tmp_path): 

37 """Test saving figure to file in different ways.""" 

38 filename = tmp_path / "test.png" 

39 

40 display = plot_stat_map(img_3d_mni, output_file=filename, **params) 

41 

42 assert display is None 

43 

44 display = plot_stat_map(img_3d_mni, **params) 

45 

46 display.savefig(filename) 

47 

48 

49@pytest.mark.parametrize( 

50 "display_mode,cut_coords", 

51 [("ortho", (80, -120, -60)), ("y", 2), ("yx", None)], 

52) 

53def test_plot_stat_map_cut_coords_and_display_mode( 

54 matplotlib_pyplot, display_mode, cut_coords, img_3d_mni 

55): 

56 """Smoke-tests for plot_stat_map. 

57 

58 Tests different combinations of parameters `cut_coords` 

59 and `display_mode`. 

60 """ 

61 plot_stat_map( 

62 img_3d_mni, 

63 display_mode=display_mode, 

64 cut_coords=cut_coords, 

65 ) 

66 

67 

68def test_plot_stat_map_with_masked_image( 

69 matplotlib_pyplot, img_3d_mni, affine_mni 

70): 

71 """Smoke test coordinate finder with mask.""" 

72 masked_img = Nifti1Image( 

73 np.ma.masked_equal(get_data(img_3d_mni), 0), 

74 affine_mni, 

75 ) 

76 

77 plot_stat_map(masked_img, display_mode="x") 

78 

79 

80@pytest.mark.parametrize( 

81 "data", 

82 [ 

83 np.zeros((91, 109, 91)), 

84 _rng().standard_normal(size=(91, 109, 91)), 

85 ], 

86) 

87def test_plot_stat_map_threshold(matplotlib_pyplot, data, affine_eye): 

88 """Tests plot_stat_map with threshold (see #510).""" 

89 plot_stat_map(Nifti1Image(data, affine_eye), threshold=1000, colorbar=True) 

90 

91 

92def test_plot_stat_map_threshold_for_affine_with_rotation( 

93 matplotlib_pyplot, rng 

94): 

95 """Tests for plot_stat_map with thresholding and resampling. 

96 

97 Threshold was not being applied when affine has a rotation. 

98 See https://github.com/nilearn/nilearn/issues/599 for more details. 

99 """ 

100 data = rng.standard_normal(size=(10, 10, 10)) 

101 # matrix with rotation 

102 affine = np.array( 

103 [ 

104 [-3.0, 1.0, 0.0, 1.0], 

105 [-1.0, -3.0, 0.0, -2.0], 

106 [0.0, 0.0, 3.0, 3.0], 

107 [0.0, 0.0, 0.0, 1.0], 

108 ] 

109 ) 

110 img = Nifti1Image(data, affine) 

111 

112 display = plot_stat_map( 

113 img, bg_img=None, threshold=1.0, display_mode="z", cut_coords=1 

114 ) 

115 

116 # Next two lines retrieve the numpy array from the plot 

117 ax = next(iter(display.axes.values())).ax 

118 plotted_array = ax.images[0].get_array() 

119 # Given the high threshold the array should be partly masked 

120 assert plotted_array.mask.any() 

121 

122 

123@pytest.mark.parametrize( 

124 "params", 

125 [ 

126 {}, 

127 {"symmetric_cbar": True}, 

128 {"symmetric_cbar": False}, 

129 {"symmetric_cbar": False, "vmax": 10}, 

130 {"symmetric_cbar": True, "vmax": 10}, 

131 ], 

132) 

133def test_plot_stat_map_colorbar_variations( 

134 matplotlib_pyplot, params, img_3d_mni, affine_mni, rng 

135): 

136 """Smoke test for plot_stat_map with different colorbar configurations.""" 

137 data_positive = get_data(img_3d_mni) 

138 

139 data_negative = -data_positive 

140 img_negative = Nifti1Image(data_negative, affine_mni) 

141 

142 data_heterogeneous = data_positive * rng.standard_normal( 

143 size=data_positive.shape 

144 ) 

145 img_heterogeneous = Nifti1Image(data_heterogeneous, affine_mni) 

146 

147 for img in [img_3d_mni, img_negative, img_heterogeneous]: 

148 plot_stat_map(img, cut_coords=(80, -120, -60), **params) 

149 

150 

151@pytest.mark.parametrize( 

152 "shape,direction", [((1, 6, 7), "x"), ((5, 1, 7), "y"), ((5, 6, 1), "z")] 

153) 

154def test_plot_stat_map_singleton_ax_dim( 

155 matplotlib_pyplot, shape, direction, affine_eye 

156): 

157 """Tests for plot_stat_map and singleton display mode.""" 

158 plot_stat_map( 

159 Nifti1Image(np.ones(shape), affine_eye), None, display_mode=direction 

160 ) 

161 

162 

163def test_outlier_cut_coords(matplotlib_pyplot): 

164 """Test to plot a subset of a large set of cuts found for a small area.""" 

165 bg_img = load_mni152_template(resolution=2) 

166 data = np.zeros((79, 95, 79)) 

167 affine = np.array( 

168 [ 

169 [-2.0, 0.0, 0.0, 78.0], 

170 [0.0, 2.0, 0.0, -112.0], 

171 [0.0, 0.0, 2.0, -70.0], 

172 [0.0, 0.0, 0.0, 1.0], 

173 ] 

174 ) 

175 # Color a cube around a corner area: 

176 x, y, z = 20, 22, 60 

177 x_map, y_map, z_map = coord_transform(x, y, z, np.linalg.inv(affine)) 

178 data[ 

179 int(x_map) - 1 : int(x_map) + 1, 

180 int(y_map) - 1 : int(y_map) + 1, 

181 int(z_map) - 1 : int(z_map) + 1, 

182 ] = 1 

183 img = Nifti1Image(data, affine) 

184 cuts = find_cut_slices(img, n_cuts=20, direction="z") 

185 

186 plot_stat_map(img, display_mode="z", cut_coords=cuts[-4:], bg_img=bg_img) 

187 

188 

189def test_plotting_functions_with_dim_invalid_input( 

190 matplotlib_pyplot, img_3d_mni 

191): 

192 """Test whether error raises with bad error to input.""" 

193 with pytest.raises(ValueError): 

194 plot_stat_map(img_3d_mni, dim="-10")