Coverage for tests/probabilty/test_functions.py: 100%

55 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2024-02-28 12:51 +1100

1""" 

2This module contains unit tests for scores.probability.functions 

3""" 

4import numpy as np 

5import pytest 

6import xarray as xr 

7 

8import scores.probability.checks 

9import scores.probability.functions 

10from tests import assertions 

11from tests.probabilty import cdf_test_data, crps_test_data 

12from tests.probabilty import functions_test_data as ftd 

13 

14 

15def test_round_values_exception(): 

16 """Test rounding throws the right exceptions""" 

17 with pytest.raises(ValueError): 

18 scores.probability.functions.round_values(xr.DataArray(), -1, 5) 

19 

20 

21@pytest.mark.parametrize( 

22 ("array", "rounding_precision", "expected"), 

23 [ 

24 (ftd.DA_ROUND, 0, ftd.EXP_ROUND1), 

25 (ftd.DA_ROUND, 0.2, ftd.EXP_ROUND2), 

26 (ftd.DA_ROUND, 5, ftd.EXP_ROUND3), 

27 ], 

28) 

29def test_round_values(array, rounding_precision, expected): 

30 """Tests `round_values` with a variety of inputs.""" 

31 output_as = scores.probability.functions.round_values(array, rounding_precision) 

32 assertions.assert_dataarray_equal(output_as, expected, decimals=7) 

33 

34 

35def test_propagate_nan_error(): 

36 """Test propagating throws the right exceptions""" 

37 faulty_array = xr.Dataset({"lertitude": [1, 2, np.NaN, 4], "longitude": [20, 21, 22, 23, 24]}) 

38 with pytest.raises(ValueError): 

39 scores.probability.functions.propagate_nan(faulty_array, "latitude") 

40 

41 

42@pytest.mark.parametrize( 

43 ("dim", "expected"), 

44 [ 

45 ("x", cdf_test_data.EXP_PROPNAN_X), 

46 ("y", cdf_test_data.EXP_PROPNAN_Y), 

47 ], 

48) 

49def test_propagate_nan(dim, expected): 

50 """Tests `propagate_nan` with a variety of inputs.""" 

51 result = scores.probability.functions.propagate_nan(cdf_test_data.DA_PROPNAN, dim) 

52 assertions.assert_dataarray_equal(result, expected, decimals=7) 

53 

54 

55def test_observed_cdf_errors(): 

56 """Test `osbserved_cdf_errors` with a variety of inputs.""" 

57 obs = xr.DataArray.from_dict({"dims": "temp", "data": [np.NaN, np.NaN, np.NaN, np.NaN]}) 

58 threshold_dim = "irrelevant for test" 

59 threshold_values = None 

60 badprecision = -1 

61 

62 # Bad precision raises a value error 

63 with pytest.raises(ValueError): 

64 scores.probability.functions.observed_cdf(obs, threshold_dim, threshold_values, precision=badprecision) 

65 

66 # Null obs and a null threshold value raises a value error 

67 with pytest.raises(ValueError): 

68 scores.probability.functions.observed_cdf(obs, threshold_dim, threshold_values) 

69 

70 

71@pytest.mark.parametrize( 

72 ("function_values", "expected"), 

73 [ 

74 (crps_test_data.DA_ISPL1, crps_test_data.EXP_ISPL1), 

75 (crps_test_data.DA_ISPL2, crps_test_data.EXP_ISPL2), 

76 (crps_test_data.DA_ISPL3, crps_test_data.EXP_ISPL3), 

77 ], 

78) 

79def test_integrate_square_piecewise_linear(function_values, expected): 

80 """Tests `integrate_square_piecewise_linear` with a variety of inputs.""" 

81 result = scores.probability.functions.integrate_square_piecewise_linear(function_values, "x") 

82 assertions.assert_dataarray_equal(result, expected, decimals=7) 

83 

84 

85@pytest.mark.parametrize( 

86 ("method", "min_nonnan", "expected"), 

87 [ 

88 ("linear", 2, cdf_test_data.EXP_FILL_CDF1A), 

89 ("step", 1, cdf_test_data.EXP_FILL_CDF1B), 

90 ("step", 2, cdf_test_data.EXP_FILL_CDF1C), 

91 ("forward", 1, cdf_test_data.EXP_FILL_CDF1D), 

92 ("backward", 1, cdf_test_data.EXP_FILL_CDF1E), 

93 ], 

94) 

95def test_fill_cdf(method, min_nonnan, expected): 

96 """Tests `fill_cdf` with a variety of inputs.""" 

97 output = scores.probability.functions.fill_cdf(cdf_test_data.DA_FILL_CDF1, "x", method, min_nonnan) 

98 assertions.assert_dataarray_equal(output, expected, decimals=7) 

99 

100 

101@pytest.mark.parametrize( 

102 ( 

103 "cdf", 

104 "threshold_dim", 

105 "method", 

106 "min_nonnan", 

107 "error_class", 

108 "error_msg_snippet", 

109 ), 

110 [ 

111 ( # cdf values outside [0,1] 

112 cdf_test_data.DA_CDF_FROM_QUANTS4, 

113 "q_level", 

114 "linear", 

115 2, 

116 ValueError, 

117 "Input CDF has some values less than 0 or greater than 1.", 

118 ), 

119 ( 

120 cdf_test_data.DA_FILL_CDF1, 

121 "y", 

122 "linear", 

123 2, 

124 ValueError, 

125 "'y' is not a dimension of `cdf`", 

126 ), 

127 ( 

128 cdf_test_data.DA_FILL_CDF1, 

129 "x", 

130 "linear", 

131 1, 

132 ValueError, 

133 "`min_nonnan` must be at least 2 when `method='linear'`", 

134 ), 

135 ( 

136 cdf_test_data.DA_FILL_CDF1, 

137 "x", 

138 "step", 

139 0, 

140 ValueError, 

141 "`min_nonnan` must be at least 1 when `method='step'`", 

142 ), 

143 ( 

144 cdf_test_data.DA_FILL_CDF1, 

145 "x", 

146 "quad", 

147 0, 

148 ValueError, 

149 "`method` must be 'linear', 'step', 'forward' or 'backward'", 

150 ), 

151 ], 

152) 

153# pylint: disable=too-many-arguments 

154def test_fill_cdf_raises(cdf, threshold_dim, method, min_nonnan, error_class, error_msg_snippet): 

155 """`fill_cdf` raises an exception as expected.""" 

156 with pytest.raises(error_class, match=error_msg_snippet): 

157 scores.probability.functions.fill_cdf( 

158 cdf, 

159 threshold_dim, 

160 method, 

161 min_nonnan, 

162 ) 

163 

164 

165@pytest.mark.parametrize( 

166 ( 

167 "cdf", 

168 "threshold_dim", 

169 "tolerance", 

170 "error_msg_snippet", 

171 ), 

172 [ 

173 ( 

174 cdf_test_data.DA_DECREASING_CDFS1, 

175 "y", 

176 0, 

177 "'y' is not a dimension of `cdf`", 

178 ), 

179 ( 

180 cdf_test_data.DA_DECREASING_CDFS1, 

181 "x", 

182 -1, 

183 "`tolerance` must be nonnegative.", 

184 ), 

185 ( 

186 cdf_test_data.DA_CDF_ENVELOPE2, 

187 "y", 

188 0, 

189 "'y' is not a dimension of `cdf`", 

190 ), 

191 ( 

192 cdf_test_data.DA_CDF_ENVELOPE1, 

193 "x", 

194 0, 

195 "CDFs should have no NaNs or be all NaN along `threshold_dim`", 

196 ), 

197 ( 

198 cdf_test_data.DA_NAN_DECREASING_CDFS2, 

199 "x", 

200 0, 

201 "Coordinates along 'x' dimension should be increasing.", 

202 ), 

203 ], 

204) 

205def test_check_nan_decreasing_inputs(cdf, threshold_dim, tolerance, error_msg_snippet): 

206 """Tests that `_check_nan_decreasing_inputs` raises an exception as expected.""" 

207 with pytest.raises(ValueError, match=error_msg_snippet): 

208 scores.probability.checks.check_nan_decreasing_inputs(cdf, threshold_dim, tolerance) 

209 

210 

211@pytest.mark.parametrize( 

212 ("cdf"), 

213 [ 

214 (cdf_test_data.DA_CDF_ENVELOPE1), 

215 (cdf_test_data.DA_CDF_ENVELOPE2), 

216 ], 

217) 

218def test_cdf_envelope(cdf): 

219 """Tests `cdf_envelope` with a variety of inputs.""" 

220 result = scores.probability.functions.cdf_envelope(cdf, "x") 

221 assertions.assert_dataarray_equal(result, cdf_test_data.EXP_CDF_ENVELOPE1, decimals=7) 

222 

223 

224def test_cdf_envelope_raises(): 

225 """Tests that `cdf_envelope` raises the correct error.""" 

226 with pytest.raises(ValueError, match="'y' is not a dimension of `cdf`"): 

227 scores.probability.functions.cdf_envelope(cdf_test_data.DA_CDF_ENVELOPE1, "y")