Coverage for nilearn/glm/tests/test_model.py: 0%

79 statements  

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

1"""Testing models module.""" 

2 

3import numpy as np 

4import pytest 

5from numpy.testing import assert_array_almost_equal 

6 

7from nilearn.glm import OLSModel 

8 

9N = 10 

10X = np.c_[np.linspace(-1, 1, N), np.ones((N,))] 

11Y = np.r_[range(5), range(1, 6)] 

12MODEL = OLSModel(X) 

13RESULTS = MODEL.fit(Y) 

14 

15""" R script 

16 

17:: 

18 

19 X = cbind(0:9 * 2/9 -1, 1) 

20 Y = as.matrix(c(0:4, 1:5)) 

21 results = lm(Y ~ X-1) 

22 print(results) 

23 print(summary(results)) 

24 

25gives:: 

26 

27 Call: 

28 lm(formula = Y ~ X - 1) 

29 

30 Coefficients: 

31 X1 X2 

32 1.773 2.500 

33 

34 Residuals: 

35 Min 1Q Median 3Q Max 

36 -1.6970 -0.6667 0.0000 0.6667 1.6970 

37 

38 Coefficients: 

39 Estimate Std. Error t value Pr(>|t|) 

40 X1 1.7727 0.5455 3.250 0.0117 * 

41 X2 2.5000 0.3482 7.181 9.42e-05 *** 

42 --- 

43 

44 Residual standard error: 1.101 on 8 degrees of freedom 

45 Multiple R-squared: 0.8859, Adjusted R-squared: 0.8574 

46 F-statistic: 31.06 on 2 and 8 DF, p-value: 0.0001694 

47""" 

48 

49 

50def test_model(): 

51 # Check basics about the model fit 

52 # Check we fit the mean 

53 assert_array_almost_equal(RESULTS.theta[1], np.mean(Y)) 

54 # Check we get the same as R 

55 assert_array_almost_equal(RESULTS.theta, [1.773, 2.5], 3) 

56 percentile = np.percentile 

57 pcts = percentile(RESULTS.residuals, [0, 25, 50, 75, 100]) 

58 assert_array_almost_equal(pcts, [-1.6970, -0.6667, 0, 0.6667, 1.6970], 4) 

59 

60 

61def test_t_contrast(): 

62 # Test individual t against R 

63 assert_array_almost_equal(RESULTS.t(0), 3.25) 

64 assert_array_almost_equal(RESULTS.t(1), 7.181, 3) 

65 # And contrast 

66 assert_array_almost_equal(RESULTS.Tcontrast([1, 0]).t, 3.25) 

67 assert_array_almost_equal(RESULTS.Tcontrast([0, 1]).t, 7.181, 3) 

68 

69 

70def test_t_contrast_errors(): 

71 match = "t contrasts should be of length P=.*, but it has length .*" 

72 with pytest.warns(UserWarning, match=match): 

73 RESULTS.Tcontrast([1]) 

74 with pytest.raises(ValueError, match=match): 

75 RESULTS.Tcontrast([1, 0, 0]) 

76 # And shape 

77 with pytest.raises( 

78 ValueError, match="t contrasts should have only one row" 

79 ): 

80 RESULTS.Tcontrast(np.array([1, 0])[:, None]) 

81 

82 

83def test_t_output(): 

84 # Check we get required outputs 

85 exp_t = RESULTS.t(0) 

86 exp_effect = RESULTS.theta[0] 

87 exp_sd = exp_effect / exp_t 

88 

89 res = RESULTS.Tcontrast([1, 0]) 

90 

91 assert_array_almost_equal(res.t, exp_t) 

92 assert_array_almost_equal(res.effect, exp_effect) 

93 assert_array_almost_equal(res.sd, exp_sd) 

94 

95 res = RESULTS.Tcontrast([1, 0], store=("effect",)) 

96 

97 assert res.t is None 

98 assert_array_almost_equal(res.effect, exp_effect) 

99 assert res.sd is None 

100 

101 res = RESULTS.Tcontrast([1, 0], store=("t",)) 

102 

103 assert_array_almost_equal(res.t, exp_t) 

104 assert res.effect is None 

105 assert res.sd is None 

106 

107 res = RESULTS.Tcontrast([1, 0], store=("sd",)) 

108 

109 assert res.t is None 

110 assert res.effect is None 

111 assert_array_almost_equal(res.sd, exp_sd) 

112 

113 res = RESULTS.Tcontrast([1, 0], store=("effect", "sd")) 

114 

115 assert res.t is None 

116 assert_array_almost_equal(res.effect, exp_effect) 

117 assert_array_almost_equal(res.sd, exp_sd) 

118 

119 

120def test_f_output(): 

121 # Test f_output 

122 res = RESULTS.Fcontrast([1, 0]) 

123 exp_f = RESULTS.t(0) ** 2 

124 

125 assert_array_almost_equal(exp_f, res.F) 

126 

127 # Test arrays work as well as lists 

128 res = RESULTS.Fcontrast(np.array([1, 0])) 

129 

130 assert_array_almost_equal(exp_f, res.F) 

131 

132 # Test with matrix against R 

133 res = RESULTS.Fcontrast(np.eye(2)) 

134 

135 assert_array_almost_equal(31.06, res.F, 2) 

136 

137 

138def test_f_output_errors(): 

139 # Input matrix checked for size 

140 match = ( 

141 r"F contrasts should have shape\[1\]=.*, but this has shape\[1\]=.*" 

142 ) 

143 with pytest.raises(ValueError, match=match): 

144 RESULTS.Fcontrast([1]) 

145 with pytest.raises(ValueError, match=match): 

146 RESULTS.Fcontrast([1, 0, 0]) 

147 # And shape 

148 with pytest.raises(ValueError, match=match): 

149 RESULTS.Fcontrast(np.array([1, 0])[:, None]) 

150 

151 

152def test_f_output_new_api(): 

153 res = RESULTS.Fcontrast([1, 0]) 

154 

155 assert_array_almost_equal(res.effect, RESULTS.theta[0]) 

156 assert_array_almost_equal(res.covariance, RESULTS.vcov()[0][0]) 

157 

158 

159def test_conf_int(): 

160 lower_, upper_ = RESULTS.conf_int() 

161 

162 assert (lower_ < upper_).all() 

163 assert (lower_ > upper_ - 10).all() 

164 

165 lower_, upper_ = RESULTS.conf_int(cols=[1]).T 

166 

167 assert lower_ < upper_ 

168 assert lower_ > upper_ - 10