Skip to content

Commit 243f26c

Browse files
Merge pull request #231 from metno/227-store-analysis-in-verif-files
Store analysis in verif files
2 parents f8f5631 + 0a418d0 commit 243f26c

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

bris/outputs/verif.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,13 @@ def finalize(self) -> None:
225225
frts = self.intermediate.get_forecast_reference_times()
226226
frts_unix = utils.datetime_to_unixtime(frts).astype(np.double)
227227

228+
leadtimes_seconds = self.intermediate.pm.leadtimes.astype(np.float32)
229+
228230
coords = {}
229231
coords["time"] = (["time"], frts_unix, cf.get_attributes("time"))
230232
coords["leadtime"] = (
231233
["leadtime"],
232-
self.intermediate.pm.leadtimes.astype(np.float32) / 3600,
234+
leadtimes_seconds / 3600,
233235
{"units": "hour"},
234236
)
235237
assert len(self.obs_ids) == len(self.opoints.get_lats()), (
@@ -345,15 +347,14 @@ def finalize(self) -> None:
345347
self.ds["x"] = (["time", "leadtime", "location", "quantile"], x)
346348

347349
# Find which valid times we need observations for
348-
frts_ut = utils.datetime_to_unixtime(frts)
349-
a, b = np.meshgrid(frts_ut, np.array(self.intermediate.pm.leadtimes))
350+
# Build a 2D array of valid times for (init_time, leadtime)
351+
a, b = np.meshgrid(frts_unix, np.array(self.intermediate.pm.leadtimes))
350352
valid_times = a + b
351353
valid_times = valid_times.transpose()
352354
if len(valid_times) == 0:
353355
utils.LOGGER.warning("Could not finalize verif, no valid times")
354356
return
355357

356-
# valid_times = np.sort(np.unique(valid_times.flatten()))
357358
unique_valid_times = np.sort(np.unique(valid_times.flatten()))
358359

359360
start_time = int(np.min(unique_valid_times))
@@ -387,6 +388,22 @@ def finalize(self) -> None:
387388

388389
self.ds["obs"] = (["time", "leadtime", "location"], obs)
389390

391+
if int(leadtimes_seconds[0]) == 0:
392+
# Store the analysis state from "fcst", where it is available. Note: this picks the first
393+
# forecast leadtime, which isn't necesssarily going to be an analysis.
394+
analysis = self.create_nan_array(fcst_shape)
395+
396+
for _t, valid_time in enumerate(frts_unix):
397+
Itimes, Ileadtimes = np.where(valid_times == valid_time)
398+
for i in range(len(Itimes)):
399+
analysis[Itimes[i], Ileadtimes[i], :] = fcst[_t, 0, :]
400+
401+
self.ds["analysis"] = (["time", "leadtime", "location"], analysis)
402+
else:
403+
utils.LOGGER.warning(
404+
"Not writing analysis to verif file. The first forecast leadtime isn't 0"
405+
)
406+
390407
if self.num_members > 1:
391408
crps = self.compute_crps(ens, obs, self.fair_crps)
392409
self.ds["ensemble_crps"] = (["time", "leadtime", "location"], crps)
@@ -399,6 +416,7 @@ def finalize(self) -> None:
399416

400417
data_variables = [
401418
"obs",
419+
"analysis",
402420
"fcst",
403421
"ensemble",
404422
"ensemble_mean",

tests/test_outputs_verif.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import numpy as np
55
import pytest
6+
import xarray as xr
67

78
from bris.outputs import Verif
89
from bris.predict_metadata import PredictMetadata
@@ -64,6 +65,7 @@ def test_1():
6465
output.add_forecast(times, member, pred)
6566

6667
output.finalize()
68+
check_expected_variable(ofilename)
6769

6870
altitudes = np.arange(len(lats))
6971
pm = PredictMetadata(
@@ -90,6 +92,23 @@ def test_1():
9092
output.add_forecast(times, member, pred)
9193

9294
output.finalize()
95+
check_expected_variable(ofilename)
96+
97+
98+
def check_expected_variable(filename):
99+
expected_variables = [
100+
"analysis",
101+
"fcst",
102+
"obs",
103+
"ensemble",
104+
"ensemble_mean",
105+
"ensemble_variance",
106+
"ensemble_crps",
107+
]
108+
109+
with xr.open_dataset(filename) as file:
110+
for variable in expected_variables:
111+
assert variable in file, variable
93112

94113

95114
def test_2():

0 commit comments

Comments
 (0)