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

95 statements  

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

1""" 

2Generation of the test data used to test scores.probability.crps 

3""" 

4 

5import numpy as np 

6import xarray as xr 

7from numpy import nan 

8 

9# pylint disable=no-name-in-module 

10from scores.probability.functions import add_thresholds 

11 

12DA_ISPL1 = xr.DataArray( # simple case, easy to calculate 

13 data=[[0, 1], [1, 1], [nan, 1]], 

14 dims=["station", "x"], 

15 coords={"station": [1001, 1002, 1003], "x": [0, 1]}, 

16) 

17 

18EXP_ISPL1 = xr.DataArray(data=[1 / 3, 1, nan], dims=["station"], coords={"station": [1001, 1002, 1003]}) 

19 

20DA_ISPL2 = xr.DataArray( # three thresholds, evenly spaced 

21 data=[[0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, nan]], 

22 dims=["station", "x"], 

23 coords={"station": [1001, 1002, 1003, 1004], "x": [0, 1, 2]}, 

24) 

25 

26EXP_ISPL2 = xr.DataArray( 

27 data=[2 / 3, 4 / 3, 8 / 3, 1 / 3], 

28 dims=["station"], 

29 coords={"station": [1001, 1002, 1003, 1004]}, 

30) 

31 

32DA_ISPL3 = xr.DataArray( # three thresholds, not evenly spaced 

33 data=[[0, 0.5, 2], [0, 0.5, 0.5]], 

34 dims=["station", "x"], 

35 coords={"station": [1001, 1002], "x": [0, 0.5, 2]}, 

36) 

37 

38EXP_ISPL3 = xr.DataArray( 

39 data=[8 / 3, 1 / 24 + 1.5 * 0.5**2], 

40 dims=["station"], 

41 coords={"station": [1001, 1002]}, 

42) 

43 

44DA_STEP_WEIGHT = xr.DataArray(data=[2.31, 5.76, 0.89], dims=["station"], coords={"station": [1001, 1002, 1003]}) 

45 

46EXP_STEP_WEIGHT_UPPER = xr.DataArray( 

47 data=[ 

48 [0, 0, 0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 

49 [0, 0, 0, 0, 0, 0, 0, 1.0, 1.0], 

50 [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 

51 ], 

52 dims=["station", "x"], 

53 coords={"x": [0.8, 1, 2, 2.4, 3, 4, 5, 5.8, 6], "station": [1001, 1002, 1003]}, 

54) 

55 

56EXP_STEP_WEIGHT_LOWER = xr.DataArray( 

57 data=[ 

58 [1.0, 1.0, 1.0, 0, 0, 0, 0, 0, 0], 

59 [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0], 

60 [0, 0, 0, 0, 0, 0, 0, 0, 0], 

61 ], 

62 dims=["station", "x"], 

63 coords={"x": [0.8, 1, 2, 2.4, 3, 4, 5, 5.8, 6], "station": [1001, 1002, 1003]}, 

64) 

65 

66DA_FCST_CRPS_EXACT = xr.DataArray( 

67 data=[ 

68 [0, 1, nan, 1], # fcst has nan 

69 [0, 1, 1, 1], # obs has nan 

70 [0, 1, 1, 1], # weight has nan 

71 [0.2, 0.5, 0.8, 1], # obs is .5, wts are 1 

72 [0.2, 0.5, 0.8, 1], # obs is .5, wts are 1 when threshold >= 1 

73 [0.2, 0.5, 0.8, 1], # obs is .5, wts are 1 when threshold < 1 

74 ], 

75 dims=["station", "x"], 

76 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006], "x": [0, 0.5, 1, 2]}, 

77) 

78 

79DA_WT_CRPS_EXACT = xr.DataArray( 

80 data=[ 

81 [1, 1, 1, 1], # fcst has nan 

82 [1, 1, 1, 1], # obs has nan 

83 [nan, 1, 1, 1], # weight has nan 

84 [1, 1, 1, 1], # obs is .5, wts are 1 

85 [0, 0, 1, 1], # obs is .5, wts are 1 when threshold >= 1 

86 [1, 1, 0, 0], # obs is .5, wts are 1 when threshold < 1 

87 ], 

88 dims=["station", "x"], 

89 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006], "x": [0, 0.5, 1, 2]}, 

90) 

91 

92DA_OBS_CRPS_EXACT = xr.DataArray( 

93 data=[ 

94 [0, 1, 1, 1], # fcst has nan 

95 [0, 1, nan, 1], # obs has a nan 

96 [0, 1, 1, 1], # weight has nan 

97 [0, 1, 1, 1], # obs is .5, wts are 1 

98 [0, 1, 1, 1], 

99 [0, 1, 1, 1], 

100 ], 

101 dims=["station", "x"], 

102 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006], "x": [0, 0.5, 1, 2]}, 

103) 

104 

105 

106# manually calculated expected outputs using calculus: 

107C1 = (0.5**3 - 0.2**3) / 1.8 # integral from 0 to .5 

108C2 = (0.5**3 - 0.2**3) / 1.8 # integral from .5 to 1 

109C3 = 0.2**2 / 3 # integral from 1 to 2 

110 

111EXP_OVER_CRPS_EXACT = xr.DataArray( 

112 data=[nan, nan, nan, C2 + C3, C3, C2], 

113 dims=["station"], 

114 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

115 name="overforecast_penalty", 

116) 

117 

118EXP_UNDER_CRPS_EXACT = xr.DataArray( 

119 data=[nan, nan, nan, C1, 0, C1], 

120 dims=["station"], 

121 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

122 name="underforecast_penalty", 

123) 

124 

125EXP_TOTAL_CRPS_EXACT = EXP_OVER_CRPS_EXACT + EXP_UNDER_CRPS_EXACT 

126 

127EXP_CRPS_EXACT = xr.merge([EXP_TOTAL_CRPS_EXACT.rename("total"), EXP_UNDER_CRPS_EXACT, EXP_OVER_CRPS_EXACT]) 

128 

129 

130NEW_THRESHOLDS = np.linspace(0, 2, 200001) 

131 

132DA_FCST_CRPS_DENSE = add_thresholds(DA_FCST_CRPS_EXACT, "x", NEW_THRESHOLDS, "linear").where( 

133 DA_FCST_CRPS_EXACT["station"] != 1001 

134) 

135 

136DA_OBS_CRPS_DENSE = add_thresholds(DA_OBS_CRPS_EXACT, "x", NEW_THRESHOLDS, "step").where( 

137 DA_OBS_CRPS_EXACT["station"] != 1002 

138) 

139 

140DA_WT_CRPS_DENSE = add_thresholds(DA_WT_CRPS_EXACT, "x", NEW_THRESHOLDS, "step").where( 

141 DA_WT_CRPS_EXACT["station"] != 1003 

142) 

143 

144 

145DA_FCST_REFORMAT1 = xr.DataArray( 

146 data=[ 

147 [[0, 0.2, 0.6, 0.9], [0.5, 0.7, 1, 1]], 

148 [[nan, nan, nan, nan], [0.5, 0.7, 1, 1]], 

149 [[0, 0.2, 0.6, 0.9], [0.5, 0.7, nan, 1]], 

150 ], 

151 dims=["station", "date", "x"], 

152 coords={"station": [1001, 1002, 1003], "date": [10, 11], "x": [0, 1, 2, 3]}, 

153) 

154 

155DA_OBS_REFORMAT1 = xr.DataArray( 

156 data=[ 

157 [1.0, 2.5], 

158 [3.0, nan], 

159 [0.0, 2.0], 

160 ], 

161 dims=["station", "date"], 

162 coords={"station": [1001, 1002, 1003], "date": [10, 11]}, 

163) 

164 

165DA_WT_REFORMAT1 = xr.DataArray( 

166 data=[ 

167 [0, 0, 0, 1.0], 

168 [0, 1.0, 1.0, 1.0], 

169 [0, 0, 1.0, 1.0], 

170 ], 

171 dims=["station", "x"], 

172 coords={"station": [1001, 1002, 1003], "x": [0, 0.5, 1, 2]}, 

173) 

174 

175EXP_FCST_REFORMAT1 = xr.DataArray( # "linear" fill 

176 data=[ 

177 [[0, 0.1, 0.2, 0.6, 0.75, 0.9], [0.5, 0.6, 0.7, 1, 1, 1]], 

178 [[nan, nan, nan, nan, nan, nan], [0.5, 0.6, 0.7, 1, 1, 1]], 

179 [[0, 0.1, 0.2, 0.6, 0.75, 0.9], [0.5, 0.6, 0.7, 0.85, 0.925, 1]], 

180 ], 

181 dims=["station", "date", "x"], 

182 coords={ 

183 "station": [1001, 1002, 1003], 

184 "date": [10, 11], 

185 "x": [0, 0.5, 1, 2, 2.5, 3], 

186 }, 

187) 

188 

189EXP_OBS_REFORMAT1 = xr.DataArray( # "step" fill 

190 data=[ 

191 [[0, 0, 1.0, 1.0, 1.0, 1.0], [0, 0, 0, 0, 1.0, 1.0]], 

192 [[0, 0, 0, 0, 0, 1.0], [nan, nan, nan, nan, nan, nan]], 

193 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [0, 0, 0, 1.0, 1.0, 1.0]], 

194 ], 

195 dims=["station", "date", "x"], 

196 coords={ 

197 "station": [1001, 1002, 1003], 

198 "date": [10, 11], 

199 "x": [0, 0.5, 1, 2, 2.5, 3], 

200 }, 

201) 

202 

203EXP_WT_REFORMAT1 = xr.DataArray( # "forward" fill 

204 data=[ 

205 [[0, 0, 0, 1.0, 1.0, 1.0], [0, 0, 0, 1.0, 1.0, 1.0]], 

206 [[0, 1.0, 1.0, 1.0, 1.0, 1.0], [0, 1.0, 1.0, 1.0, 1.0, 1.0]], 

207 [[0, 0, 1.0, 1.0, 1.0, 1.0], [0, 0, 1.0, 1.0, 1.0, 1.0]], 

208 ], 

209 dims=["station", "date", "x"], 

210 coords={ 

211 "station": [1001, 1002, 1003], 

212 "date": [10, 11], 

213 "x": [0, 0.5, 1, 2, 2.5, 3], 

214 }, 

215) 

216 

217EXP_REFORMAT1 = EXP_FCST_REFORMAT1, EXP_OBS_REFORMAT1, EXP_WT_REFORMAT1 

218 

219# additional thresholds: [0, 1.5] 

220EXP_FCST_REFORMAT2 = xr.DataArray( # "linear" fill 

221 data=[ 

222 [[0, 0.1, 0.2, 0.4, 0.6, 0.75, 0.9], [0.5, 0.6, 0.7, 0.85, 1, 1, 1]], 

223 [[nan, nan, nan, nan, nan, nan, nan], [0.5, 0.6, 0.7, 0.85, 1, 1, 1]], 

224 [[0, 0.1, 0.2, 0.4, 0.6, 0.75, 0.9], [0.5, 0.6, 0.7, 0.775, 0.85, 0.925, 1]], 

225 ], 

226 dims=["station", "date", "x"], 

227 coords={ 

228 "station": [1001, 1002, 1003], 

229 "date": [10, 11], 

230 "x": [0, 0.5, 1, 1.5, 2, 2.5, 3], 

231 }, 

232) 

233 

234EXP_OBS_REFORMAT2 = xr.DataArray( # "step" fill 

235 data=[ 

236 [[0, 0, 1.0, 1.0, 1.0, 1.0, 1.0], [0, 0, 0, 0, 0, 1.0, 1.0]], 

237 [[0, 0, 0, 0, 0, 0, 1.0], [nan, nan, nan, nan, nan, nan, nan]], 

238 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [0, 0, 0, 0, 1.0, 1.0, 1.0]], 

239 ], 

240 dims=["station", "date", "x"], 

241 coords={ 

242 "station": [1001, 1002, 1003], 

243 "date": [10, 11], 

244 "x": [0, 0.5, 1, 1.5, 2, 2.5, 3], 

245 }, 

246) 

247 

248EXP_WT_REFORMAT2 = xr.DataArray( # "forward" fill 

249 data=[ 

250 [[0, 0, 0, 0, 1.0, 1.0, 1.0], [0, 0, 0, 0, 1.0, 1.0, 1.0]], 

251 [[0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], 

252 [[0, 0, 1.0, 1.0, 1.0, 1.0, 1.0], [0, 0, 1.0, 1.0, 1.0, 1.0, 1.0]], 

253 ], 

254 dims=["station", "date", "x"], 

255 coords={ 

256 "station": [1001, 1002, 1003], 

257 "date": [10, 11], 

258 "x": [0, 0.5, 1, 1.5, 2, 2.5, 3], 

259 }, 

260) 

261 

262EXP_REFORMAT2 = EXP_FCST_REFORMAT2, EXP_OBS_REFORMAT2, EXP_WT_REFORMAT2 

263 

264# weight = None 

265EXP_FCST_REFORMAT3 = xr.DataArray( # "linear" fill 

266 data=[ 

267 [[0, 0.2, 0.6, 0.75, 0.9], [0.5, 0.7, 1, 1, 1]], 

268 [[nan, nan, nan, nan, nan], [0.5, 0.7, 1, 1, 1]], 

269 [[0, 0.2, 0.6, 0.75, 0.9], [0.5, 0.7, 0.85, 0.925, 1]], 

270 ], 

271 dims=["station", "date", "x"], 

272 coords={"station": [1001, 1002, 1003], "date": [10, 11], "x": [0, 1, 2, 2.5, 3]}, 

273) 

274 

275EXP_OBS_REFORMAT3 = xr.DataArray( # "step" fill 

276 data=[ 

277 [[0, 1.0, 1.0, 1.0, 1.0], [0, 0, 0, 1.0, 1.0]], 

278 [[0, 0, 0, 0, 1.0], [nan, nan, nan, nan, nan]], 

279 [[1.0, 1.0, 1.0, 1.0, 1.0], [0, 0, 1.0, 1.0, 1.0]], 

280 ], 

281 dims=["station", "date", "x"], 

282 coords={"station": [1001, 1002, 1003], "date": [10, 11], "x": [0, 1, 2, 2.5, 3]}, 

283) 

284 

285EXP_WT_REFORMAT3 = xr.DataArray( # "forward" fill 

286 data=[ 

287 [[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0]], 

288 [[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0]], 

289 [[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0]], 

290 ], 

291 dims=["station", "date", "x"], 

292 coords={"station": [1001, 1002, 1003], "date": [10, 11], "x": [0, 1, 2, 2.5, 3]}, 

293) 

294 

295EXP_REFORMAT3 = EXP_FCST_REFORMAT3, EXP_OBS_REFORMAT3, EXP_WT_REFORMAT3 

296 

297DA_WT_CHECK_CRPS1 = xr.DataArray( 

298 data=[ 

299 [0, 0, 0, 1.0], 

300 [0, 1.0, 1.0, 1.0], 

301 [0, 0, 1.0, 1.0], 

302 ], 

303 dims=["station", "y"], 

304 coords={"station": [1001, 1002, 1003], "y": [0, 0.5, 1, 2]}, 

305) 

306 

307DA_WT_CHECK_CRPS2 = xr.DataArray( 

308 data=[ 

309 [0, 0, 0, 1.0], 

310 [0, 1.0, 1.0, 1.0], 

311 [0, 0, 1.0, 1.0], 

312 ], 

313 dims=["unicorns", "x"], 

314 coords={"unicorns": [1001, 1002, 1003], "x": [0, 0.5, 1, 2]}, 

315) 

316 

317DA_WT_CHECK_CRPS3 = xr.DataArray( # x not increasing 

318 data=[[0.2, -2.0, 0.8, 1]], 

319 dims=["station", "x"], 

320 coords={"station": [1001], "x": [0, 0.5, 1, 2]}, 

321) 

322 

323DA_OBS_CHECK_CRPS = xr.DataArray( 

324 data=[ 

325 [0, 0, 0, 1.0], 

326 [0, 1.0, 1.0, 1.0], 

327 [0, 0, 1.0, 1.0], 

328 ], 

329 dims=["vehicle", "station"], 

330 coords={"vehicle": [1001, 1002, 1003], "station": [0, 0.5, 1, 2]}, 

331) 

332 

333DA_FCST_CHECK_CRPS = xr.DataArray( 

334 data=[ 

335 [[0], [0.5]], 

336 [[nan], [0.5]], 

337 [[0], [0.5]], 

338 ], 

339 dims=["station", "date", "x"], 

340 coords={"station": [1001, 1002, 1003], "date": [10, 11], "x": [0]}, 

341) 

342 

343DA_FCST_CHECK_CRPS2 = xr.DataArray( # x not increasing 

344 data=[[0.2, 0.5, 0.8, 1]], 

345 dims=["station", "x"], 

346 coords={"station": [1001], "x": [0, 0.5, 10, 2]}, 

347) 

348 

349DA_FCST_CHECK_CRPS2A = xr.DataArray( # x not increasing 

350 data=[[0.2, 0.5, 0.8, 1]], 

351 dims=["station", "x"], 

352 coords={"station": [1001], "x": [0, 0.5, 1, 2]}, 

353) 

354 

355DA_OBS_CHECK_CRPS2 = xr.DataArray( 

356 data=[0.2], 

357 dims=["station"], 

358 coords={"station": [1001]}, 

359) 

360 

361DA_FCST_CRPS = DA_FCST_CRPS_EXACT.copy() 

362 

363DA_WT_CRPS = DA_WT_CRPS_EXACT.copy() 

364 

365DA_OBS_CRPS = xr.DataArray( 

366 data=[0.5, nan, 0.5, 0.5, 0.5, 0.5], 

367 dims=["station"], 

368 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

369) 

370 

371EXP_CRPS1 = EXP_CRPS_EXACT.copy() 

372 

373EXP_OVER_CRPS_MEAN = xr.DataArray( 

374 data=(C2 + C3 + C3 + C2) / 3, 

375 name="overforecast_penalty", 

376) 

377 

378EXP_UNDER_CRPS_MEAN = xr.DataArray( 

379 data=(C1 + C1) / 3, 

380 name="underforecast_penalty", 

381) 

382 

383EXP_TOTAL_CRPS_MEAN = EXP_OVER_CRPS_MEAN + EXP_UNDER_CRPS_MEAN 

384 

385EXP_CRPS2 = xr.merge([EXP_TOTAL_CRPS_MEAN.rename("total"), EXP_UNDER_CRPS_MEAN, EXP_OVER_CRPS_MEAN]) 

386 

387# weight = 1, propagate nans 

388EXP_OVER_CRPS3 = xr.DataArray( 

389 data=[nan, nan, 0, C2 + C3, C2 + C3, C2 + C3], 

390 dims=["station"], 

391 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

392 name="overforecast_penalty", 

393) 

394 

395EXP_UNDER_CRPS3 = xr.DataArray( 

396 data=[nan, nan, 1 / 6, C1, C1, C1], 

397 dims=["station"], 

398 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

399 name="underforecast_penalty", 

400) 

401 

402EXP_TOTAL_CRPS3 = EXP_OVER_CRPS3 + EXP_UNDER_CRPS3 

403 

404EXP_CRPS3 = xr.merge([EXP_TOTAL_CRPS3.rename("total"), EXP_UNDER_CRPS3, EXP_OVER_CRPS3]) 

405 

406# weight = 1, don't propagate nans 

407EXP_OVER_CRPS4 = xr.DataArray( 

408 data=[0, nan, 0, C2 + C3, C2 + C3, C2 + C3], 

409 dims=["station"], 

410 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

411 name="overforecast_penalty", 

412) 

413 

414EXP_UNDER_CRPS4 = xr.DataArray( 

415 data=[1 / 6, nan, 1 / 6, C1, C1, C1], 

416 dims=["station"], 

417 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

418 name="underforecast_penalty", 

419) 

420 

421EXP_TOTAL_CRPS4 = EXP_OVER_CRPS4 + EXP_UNDER_CRPS4 

422 

423EXP_CRPS4 = xr.merge([EXP_TOTAL_CRPS4.rename("total"), EXP_UNDER_CRPS4, EXP_OVER_CRPS4]) 

424 

425# don't propagate nans 

426EXP_OVER_CRPS5 = xr.DataArray( 

427 data=[0, nan, 0, C2 + C3, C3, C2], 

428 dims=["station"], 

429 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

430 name="overforecast_penalty", 

431) 

432 

433EXP_UNDER_CRPS5 = xr.DataArray( 

434 data=[1 / 6, nan, 1 / 6, C1, 0, C1], 

435 dims=["station"], 

436 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006]}, 

437 name="underforecast_penalty", 

438) 

439 

440EXP_TOTAL_CRPS5 = EXP_OVER_CRPS5 + EXP_UNDER_CRPS5 

441 

442EXP_CRPS5 = xr.merge([EXP_TOTAL_CRPS5.rename("total"), EXP_UNDER_CRPS5, EXP_OVER_CRPS5]) 

443 

444DA_FCST_ADJUST1 = xr.DataArray( 

445 data=[ 

446 [0, 0.5, 1], 

447 [0, nan, 1], 

448 [1, 0.5, 0], 

449 [1, 0.5, 0], 

450 [1, 0.5, 0], 

451 [nan, nan, nan], 

452 [1, 0.5, 0], 

453 ], 

454 dims=["station", "x"], 

455 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006, 1007], "x": [0, 0.5, 1]}, 

456) 

457 

458DA_OBS_ADJUST1 = xr.DataArray( 

459 data=[0.5, 0.5, 0, 0.5, 1, 0.2, nan], 

460 dims=["station"], 

461 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006, 1007]}, 

462) 

463 

464EXP_FCST_ADJUST1 = xr.DataArray( # decreasing_tolerance=0 

465 data=[ 

466 [0, 0.5, 1], 

467 [nan, nan, nan], 

468 [0, 0, 0], 

469 [1, 0.5, 0], 

470 [1, 1, 1], 

471 [nan, nan, nan], 

472 [1, 0.5, 0], 

473 ], 

474 dims=["station", "x"], 

475 coords={"station": [1001, 1002, 1003, 1004, 1005, 1006, 1007], "x": [0, 0.5, 1]}, 

476) 

477 

478DA_FCST_ADJUST2 = xr.DataArray( 

479 data=[ 

480 [0, 0.5, 1], 

481 [1, 0.5, 0], 

482 ], 

483 dims=["station", "x"], 

484 coords={"station": [1001, 1002], "x": [0, 0.5, 1]}, 

485) 

486 

487DA_OBS_ADJUST2 = xr.DataArray( 

488 data=[0.5, 0.5], 

489 dims=["station"], 

490 coords={"station": [1001, 1002]}, 

491) 

492 

493EXP_FCST_ADJUST2 = xr.DataArray( # decreasing_tolerance=10 

494 data=[ 

495 [0, 0.5, 1], 

496 [1, 0.5, 0], 

497 ], 

498 dims=["station", "x"], 

499 coords={"station": [1001, 1002], "x": [0, 0.5, 1]}, 

500) 

501 

502DA_FCST_CRPS_BD = xr.DataArray( 

503 data=[[0, 0.5, 1], [0, 0.2, 0.6], [0.5, 1, 1], [1, 1, 1], [nan, 0.7, nan]], 

504 dims=["station", "x"], 

505 coords={"station": [1001, 1002, 1003, 1004, 1005], "x": [0, 0.5, 1]}, 

506) 

507 

508DA_OBS_CRPS_BD = xr.DataArray( 

509 data=[0, 0.5, 1, nan, 0], 

510 dims=["station"], 

511 coords={"station": [1001, 1002, 1003, 1004, 1005]}, 

512) 

513 

514EXP_UNDER_CRPS_BD1 = xr.DataArray( 

515 data=[(0 + 0 + 0.25) / 3, (0 + 0 + 1) / 3, (0 + 0 + 0) / 3], 

516 dims=["x"], 

517 coords={"x": [0, 0.5, 1]}, 

518 name="underforecast_penalty", 

519) 

520 

521EXP_OVER_CRPS_BD1 = xr.DataArray( 

522 data=[(1 + 0 + 0) / 3, (0.25 + 0.64 + 0) / 3, (0 + 0.16 + 0) / 3], 

523 dims=["x"], 

524 coords={"x": [0, 0.5, 1]}, 

525 name="overforecast_penalty", 

526) 

527 

528EXP_TOTAL_CRPS_BD1 = xr.DataArray( 

529 data=[(1 + 0 + 0.25) / 3, (0.25 + 0.64 + 1) / 3, (0 + 0.16 + 0) / 3], 

530 dims=["x"], 

531 coords={"x": [0, 0.5, 1]}, 

532 name="total_penalty", 

533) 

534 

535EXP_CRPS_BD1 = xr.merge([EXP_TOTAL_CRPS_BD1, EXP_UNDER_CRPS_BD1, EXP_OVER_CRPS_BD1]) 

536 

537EXP_UNDER_CRPS_BD2 = xr.DataArray( # don't collapse station 

538 data=[[0, 0, 0], [0, 0, 0], [0.25, 1, 0], [nan, nan, nan], [nan, nan, nan]], 

539 dims=["station", "x"], 

540 coords={"station": [1001, 1002, 1003, 1004, 1005], "x": [0, 0.5, 1]}, 

541 name="underforecast_penalty", 

542) 

543 

544EXP_OVER_CRPS_BD2 = xr.DataArray( # don't collapse station 

545 data=[[1, 0.25, 0], [0, 0.64, 0.16], [0, 0, 0], [nan, nan, nan], [nan, nan, nan]], 

546 dims=["station", "x"], 

547 coords={"station": [1001, 1002, 1003, 1004, 1005], "x": [0, 0.5, 1]}, 

548 name="overforecast_penalty", 

549) 

550 

551EXP_TOTAL_CRPS_BD2 = xr.DataArray( # don't collapse station 

552 data=[ 

553 [1, 0.25, 0], 

554 [0, 0.64, 0.16], 

555 [0.25, 1, 0], 

556 [nan, nan, nan], 

557 [nan, nan, nan], 

558 ], 

559 dims=["station", "x"], 

560 coords={"station": [1001, 1002, 1003, 1004, 1005], "x": [0, 0.5, 1]}, 

561 name="total_penalty", 

562) 

563 

564EXP_CRPS_BD2 = xr.merge([EXP_TOTAL_CRPS_BD2, EXP_UNDER_CRPS_BD2, EXP_OVER_CRPS_BD2]) 

565 

566# test data for CRPS for ensembles 

567 

568DA_FCST_CRPSENS = xr.DataArray( 

569 data=[[0.0, 4, 3, 7], [1, -1, 2, 4], [0, 1, 4, np.nan], [2, 3, 4, 1], [2, np.nan, np.nan, np.nan]], 

570 dims=["stn", "ens_member"], 

571 coords={"stn": [101, 102, 103, 104, 105], "ens_member": [1, 2, 3, 4]}, 

572) 

573DA_OBS_CRPSENS = xr.DataArray(data=[2.0, 3, 1, np.nan, 4], dims=["stn"], coords={"stn": [101, 102, 103, 104, 105]}) 

574DA_WT_CRPSENS = xr.DataArray(data=[1, 2, 1, 0, 2], dims=["stn"], coords={"stn": [101, 102, 103, 104, 105]}) 

575 

576# first and second (spread) terms from crps for ensembles, "ecdf" and "fair" methods 

577FIRST_TERM = xr.DataArray( 

578 data=[10 / 4, 8 / 4, 4 / 3, np.nan, 2], dims=["stn"], coords={"stn": [101, 102, 103, 104, 105]} 

579) 

580SPREAD_ECDF = xr.DataArray( 

581 data=[(14 + 8 + 8 + 14) / 32, (6 + 10 + 6 + 10) / 32, (5 + 4 + 7) / 18, np.nan, 0], 

582 dims=["stn"], 

583 coords={"stn": [101, 102, 103, 104, 105]}, 

584) 

585SPREAD_FAIR = xr.DataArray( 

586 data=[(14 + 8 + 8 + 14) / 24, (6 + 10 + 6 + 10) / 24, (5 + 4 + 7) / 12, np.nan, np.nan], 

587 dims=["stn"], 

588 coords={"stn": [101, 102, 103, 104, 105]}, 

589) 

590 

591# expected results 

592EXP_CRPSENS_ECDF = FIRST_TERM - SPREAD_ECDF 

593EXP_CRPSENS_FAIR = FIRST_TERM - SPREAD_FAIR 

594EXP_CRPSENS_WT = (EXP_CRPSENS_ECDF * DA_WT_CRPSENS).mean("stn")