Skip to content

Commit

Permalink
Fixed verif
Browse files Browse the repository at this point in the history
  • Loading branch information
tnipen committed Jan 13, 2025
1 parent 2a8740b commit a97d828
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 21 deletions.
9 changes: 7 additions & 2 deletions bris/outputs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import numpy as np


from bris import sources
from bris.predict_metadata import PredictMetadata

Expand All @@ -13,11 +15,14 @@ def instantiate(name: str, predict_metadata: PredictMetadata, workdir: str, init
if name == "verif":
# Parse obs sources
obs_sources = list()

# Convert to dict, since iverriding obs_sources doesn't seem to work with OmegaConf
args = dict(**init_args)
for s in init_args["obs_sources"]:
for name, opts in s.items():
obs_sources += [sources.instantiate(name, opts)]
init_args["obs_sources"] = obs_sources
return Verif(predict_metadata, workdir, **init_args)
args["obs_sources"] = obs_sources
return Verif(predict_metadata, workdir, **args)

elif name == "netcdf":
return Netcdf(predict_metadata, workdir, **init_args)
Expand Down
12 changes: 12 additions & 0 deletions bris/outputs/intermediate.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ def get_forecast(self, forecast_reference_time, ensemble_member=None):

return pred

@property
def num_members(self):
filenames = self.get_filenames()

members = list()
max_member = 0
for filename in filenames:
_, member = filename.split("/")[-1].split(".npy")[0].split("_")
max_member = max(int(member), max_member)

return max_member + 1

def get_filenames(self):
return glob.glob(f"{self.workdir}/*_*.npy")

Expand Down
28 changes: 22 additions & 6 deletions bris/outputs/verif.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def _add_forecast(self, times: list, ensemble_member: int, pred: np.array):
] # Add in variable dimension
else:
pred = pred[..., 0]
interpolated_pred = gridpp.simple_gradient(self.ipoints, self.opoints, pred)
# TODO: Do linear interpolation here with scipy
interpolated_pred = gridpp.nearest(self.ipoints, self.opoints, pred)

if self.elev_gradient is not None:
interpolated_elevs = gridpp.nearest(
Expand All @@ -117,12 +118,16 @@ def _add_forecast(self, times: list, ensemble_member: int, pred: np.array):

@property
def _is_gridded_input(self):
return self.pm.field_shape is not None
return self.pm.is_gridded

@property
def _num_locations(self):
return self.opoints.size()

@property
def num_members(self):
return self.intermediate.num_members

def finalize(self):
"""Write forecasts and observations to file"""

Expand All @@ -149,6 +154,13 @@ def finalize(self):
self.obs_elevs,
cf.get_attributes("surface_altitude"),
)
"""
coords["ensemble_member"] = (
["ensemble_member"],
self.ensemble_members,
cf.get_attributes("ensemble_member"),
)
"""
if len(self.thresholds) > 0:
coords["threshold"] = (
["threshold"],
Expand Down Expand Up @@ -180,7 +192,7 @@ def finalize(self):
self.ds["fcst"] = (["time", "leadtime", "location"], fcst)

# Load threshold forecasts
if len(self.thresholds) > 0:
if len(self.thresholds) > 0 and self.num_members > 1:
cdf = np.nan * np.zeros(
[
len(frts),
Expand All @@ -198,7 +210,7 @@ def finalize(self):
self.ds["cdf"] = (["time", "leadtime", "location", "threshold"], cdf)

# Load quantile forecasts
if len(self.quantile_levels) > 0:
if len(self.quantile_levels) > 0 and self.num_members > 1:
x = np.nan * np.zeros(
[
len(frts),
Expand Down Expand Up @@ -231,7 +243,12 @@ def finalize(self):

start_time = int(np.min(unique_valid_times))
end_time = int(np.max(unique_valid_times))
frequency = int(np.min(np.diff(unique_valid_times)))

if start_time == end_time:
# Any number will do
frequency = 3600
else:
frequency = int(np.min(np.diff(unique_valid_times)))

# Fill in retrieved observations into our obs array.
obs = np.nan * np.zeros(
Expand Down Expand Up @@ -295,7 +312,6 @@ def compute_quantile(self, ar, level, fair=True):
num_members = ar.shape[-1]
lower = 0.5 * 1 / num_members
upper = 1 - lower

percentile = (level - lower) / (upper - lower) * 100
percentile = max(min(percentile, 100), 0)
else:
Expand Down
64 changes: 51 additions & 13 deletions bris/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,71 @@
"type": "object",
"definitions": {
"VerifOutput": {
"description": "Verif-compatible Netcdf output file",
"type": "object",
"properties": {
"verif": {
"type": "object",
"properties": {
"filename": {"type": "string"},
"variable": {"type": "string"},
"threhsolds": {"type": "array", "items": {"type": "number"}},
"thresholds": {"type": "array", "items": {"type": "number"}},
"quantiles": {"type": "array", "items": {"type": "number", "minimum": 0, "maximum": 1}},
"obs": {
"obs_sources": {
"type": "array",
"items": {
"oneOf": [
{"$ref": "#/definitions/NetcdfSource"},
{"$ref": "#/definitions/VerifSource"},
{"$ref": "#/definitions/FrostSource"}
]
}
}
},
"required": ["filename", "variable", "obs"]
"required": ["filename", "variable", "obs_sources"]
}
},
"required": ["verif"]
},

"NetcdfOutput": {
"description": "Netcdf output file with MET Norway conventions",
"type": "object",
"properties": {
"netcdf": {
"type": "object",
"properties": {
"filename_pattern": {"type": "string"},
"variables": {"type": "array", "items": {"type": "string"}}
"filename_pattern": {
"description": "Where to write the output file. Time tokens allowed (e.g. %Y%m%d)",
"type": "string"
},
"variables": {
"description": "What variables to output? Leave empty to write all",
"type": "array",
"items": {"type": "string"}
}
},
"required": ["filename_pattern"]
}
},
"required": ["netcdf"]
},

"NetcdfSource": {
"VerifSource": {
"description": "Observations stored in a Netcdf verif file",
"type": "object",
"properties": {
"netcdf": {
"verif": {
"type": "object",
"properties": {
"path": {"type": "string"}
"filename": {
"description": "Where the file is located",
"type": "string"
}
},
"required": ["path"]
"required": ["filename"]
}
},
"required": ["netcdf"]
"required": ["verif"]
},

"FrostSource": {
Expand All @@ -73,7 +86,31 @@
}
},
"properties": {
"leadtimes": {"type": "integer", "minimum": 1},
"start_date": {
"description": "First date to produce a forecast. E.g. 2023-11-24T12:00:00",
"format": "date-time"
},
"end_date": {
"description": "Last date to produce a forecast. E.g. 2023-11-24T12:00:00",
"format": "date-time"
},
"frequency": {
"description": "How often to make forecast runs? E.g. 6h",
"type": "string"
},
"leadtimes": {
"description": "What leadtimes should be provided in the output?",
"type": "integer",
"minimum": 1
},
"timestep": {
"description": "What is the timestep between each leadtime? E.g. 6h",
"type": "string"
},
"release_cache": {
"description": "This option releases unused cached/memory used by torch",
"type": "boolean"
},
"routing": {
"type": "array",
"items": {
Expand All @@ -93,5 +130,6 @@
}
}
}
}
},
"required": ["leadtimes", "frequency", "timestep", "release_cache"]
}

0 comments on commit a97d828

Please sign in to comment.