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
« 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"""
5import numpy as np
6import xarray as xr
7from numpy import nan
9# pylint disable=no-name-in-module
10from scores.probability.functions import add_thresholds
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)
18EXP_ISPL1 = xr.DataArray(data=[1 / 3, 1, nan], dims=["station"], coords={"station": [1001, 1002, 1003]})
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)
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)
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)
38EXP_ISPL3 = xr.DataArray(
39 data=[8 / 3, 1 / 24 + 1.5 * 0.5**2],
40 dims=["station"],
41 coords={"station": [1001, 1002]},
42)
44DA_STEP_WEIGHT = xr.DataArray(data=[2.31, 5.76, 0.89], dims=["station"], coords={"station": [1001, 1002, 1003]})
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)
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)
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)
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)
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)
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
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)
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)
125EXP_TOTAL_CRPS_EXACT = EXP_OVER_CRPS_EXACT + EXP_UNDER_CRPS_EXACT
127EXP_CRPS_EXACT = xr.merge([EXP_TOTAL_CRPS_EXACT.rename("total"), EXP_UNDER_CRPS_EXACT, EXP_OVER_CRPS_EXACT])
130NEW_THRESHOLDS = np.linspace(0, 2, 200001)
132DA_FCST_CRPS_DENSE = add_thresholds(DA_FCST_CRPS_EXACT, "x", NEW_THRESHOLDS, "linear").where(
133 DA_FCST_CRPS_EXACT["station"] != 1001
134)
136DA_OBS_CRPS_DENSE = add_thresholds(DA_OBS_CRPS_EXACT, "x", NEW_THRESHOLDS, "step").where(
137 DA_OBS_CRPS_EXACT["station"] != 1002
138)
140DA_WT_CRPS_DENSE = add_thresholds(DA_WT_CRPS_EXACT, "x", NEW_THRESHOLDS, "step").where(
141 DA_WT_CRPS_EXACT["station"] != 1003
142)
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)
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)
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)
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)
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)
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)
217EXP_REFORMAT1 = EXP_FCST_REFORMAT1, EXP_OBS_REFORMAT1, EXP_WT_REFORMAT1
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)
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)
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)
262EXP_REFORMAT2 = EXP_FCST_REFORMAT2, EXP_OBS_REFORMAT2, EXP_WT_REFORMAT2
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)
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)
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)
295EXP_REFORMAT3 = EXP_FCST_REFORMAT3, EXP_OBS_REFORMAT3, EXP_WT_REFORMAT3
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)
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)
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)
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)
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)
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)
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)
355DA_OBS_CHECK_CRPS2 = xr.DataArray(
356 data=[0.2],
357 dims=["station"],
358 coords={"station": [1001]},
359)
361DA_FCST_CRPS = DA_FCST_CRPS_EXACT.copy()
363DA_WT_CRPS = DA_WT_CRPS_EXACT.copy()
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)
371EXP_CRPS1 = EXP_CRPS_EXACT.copy()
373EXP_OVER_CRPS_MEAN = xr.DataArray(
374 data=(C2 + C3 + C3 + C2) / 3,
375 name="overforecast_penalty",
376)
378EXP_UNDER_CRPS_MEAN = xr.DataArray(
379 data=(C1 + C1) / 3,
380 name="underforecast_penalty",
381)
383EXP_TOTAL_CRPS_MEAN = EXP_OVER_CRPS_MEAN + EXP_UNDER_CRPS_MEAN
385EXP_CRPS2 = xr.merge([EXP_TOTAL_CRPS_MEAN.rename("total"), EXP_UNDER_CRPS_MEAN, EXP_OVER_CRPS_MEAN])
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)
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)
402EXP_TOTAL_CRPS3 = EXP_OVER_CRPS3 + EXP_UNDER_CRPS3
404EXP_CRPS3 = xr.merge([EXP_TOTAL_CRPS3.rename("total"), EXP_UNDER_CRPS3, EXP_OVER_CRPS3])
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)
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)
421EXP_TOTAL_CRPS4 = EXP_OVER_CRPS4 + EXP_UNDER_CRPS4
423EXP_CRPS4 = xr.merge([EXP_TOTAL_CRPS4.rename("total"), EXP_UNDER_CRPS4, EXP_OVER_CRPS4])
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)
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)
440EXP_TOTAL_CRPS5 = EXP_OVER_CRPS5 + EXP_UNDER_CRPS5
442EXP_CRPS5 = xr.merge([EXP_TOTAL_CRPS5.rename("total"), EXP_UNDER_CRPS5, EXP_OVER_CRPS5])
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)
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)
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)
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)
487DA_OBS_ADJUST2 = xr.DataArray(
488 data=[0.5, 0.5],
489 dims=["station"],
490 coords={"station": [1001, 1002]},
491)
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)
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)
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)
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)
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)
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)
535EXP_CRPS_BD1 = xr.merge([EXP_TOTAL_CRPS_BD1, EXP_UNDER_CRPS_BD1, EXP_OVER_CRPS_BD1])
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)
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)
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)
564EXP_CRPS_BD2 = xr.merge([EXP_TOTAL_CRPS_BD2, EXP_UNDER_CRPS_BD2, EXP_OVER_CRPS_BD2])
566# test data for CRPS for ensembles
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]})
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)
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")