Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ Where to store grids extracted from baseline datasets. When `baseline.name` is `

### paths.grids.forecast

Where to store grids extracted from netCDF or Zarr forecast datasets. GRIB forecast datasets currently must be local, and grids are processed directly from their containing files without being extracted into separate files.
Where to store grids extracted from netCDF or Zarr forecast datasets. GRIB forecast datasets currently must be local, and grids are processed directly from their containing files without being extracted into separate files. This value is required for netCDF and Zarr datasets, and ignored for local GRIB datasets.

### paths.grids.truth

Expand Down
2 changes: 1 addition & 1 deletion recipe/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@
"zarr ==3.1.*"
]
},
"version": "0.7.0"
"version": "0.7.1"
}
5 changes: 4 additions & 1 deletion src/wxvx/metconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,11 @@ def _top(k: str, v: Any, level: int) -> list[str]:
case MET.quality_mark_thresh:
return _kvpair(k, _bare(v), level)
# Scalar: quoted.
case MET.model | MET.obtype | MET.output_prefix | MET.tmp_dir:
case MET.obtype | MET.output_prefix | MET.tmp_dir:
return _kvpair(k, _quoted(v), level)
# Scalar: quoted with no whitespace.
case MET.model:
return _kvpair(k, _quoted(v.replace(" ", "_")), level)
Comment on lines +231 to +233
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MET doesn't allow whitespace in the model name, which is too bad because then the ugly name with an underscore shows up in the plot legend, but it might be tricky to change, because sometimes you might really have an underscore in a name and wouldn't want it converted to a space.

# Sequence: quoted.
case MET.message_type | MET.obs_bufr_var:
return _sequence(k, v, _quoted, level)
Expand Down
3 changes: 0 additions & 3 deletions src/wxvx/resources/config.jsonschema
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,6 @@
"type": "string"
}
},
"required": [
"forecast"
],
"type": "object"
},
"obs": {
Expand Down
2 changes: 1 addition & 1 deletion src/wxvx/resources/info.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"buildnum": "0",
"version": "0.7.0"
"version": "0.7.1"
}
1 change: 1 addition & 0 deletions src/wxvx/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class _S(_ValsMatchKeys):
Strings defined by wxvx, plus strings from various other sources.
"""

GDAS: str = _
GFS: str = _
HRRR: str = _
OBS: str = _
Expand Down
2 changes: 1 addition & 1 deletion src/wxvx/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def config_data():
[21.138123, 275.0],
[21.138123, 225.90452027],
],
S.name: "Forecast",
S.name: "Forecast Model",
S.path: "/path/to/forecast-{{ yyyymmdd }}-{{ hh }}-{{ '%03d' % fh }}.nc",
S.projection: {
"a": 6371229,
Expand Down
6 changes: 1 addition & 5 deletions src/wxvx/tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,8 @@ def test_schema_paths_grids(config_data, fs, logged):
for key in [S.forecast, S.truth]:
assert not ok(with_set(config, None, key))
assert logged("None is not of type 'string'")
# Some values are required:
for key in [S.forecast]:
assert not ok(with_del(config, key))
assert logged(f"'{key}' is a required property")
# Some values are optional:
for key in [S.baseline]:
for key in [S.baseline, S.forecast]:
assert ok(with_del(config, key))


Expand Down
2 changes: 1 addition & 1 deletion src/wxvx/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def test_types_Forecast(config_data, forecast):
assert obj.coords.time.inittime == "time"
assert obj.coords.time.leadtime == "lead_time"
assert obj.format is None
assert obj.name == "Forecast"
assert obj.name == "Forecast Model"
assert obj.path == "/path/to/forecast-{{ yyyymmdd }}-{{ hh }}-{{ '%03d' % fh }}.nc"
cfg = config_data[S.forecast]
other1 = types.Forecast(**cfg)
Expand Down
6 changes: 5 additions & 1 deletion src/wxvx/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,15 @@ def test_util_classify_data_format__pass_zarr(tmp_path):
("http://example.com/path/to/gfs.t00z.pgrb2.0p25.f001", util.Proximity.REMOTE),
("file:///path/to/gfs.t00z.pgrb2.0p25.f001", util.Proximity.LOCAL),
("/path/to/gfs.t00z.pgrb2.0p25.f001", util.Proximity.LOCAL),
("gfs.t00z.pgrb2.0p25.f001", util.Proximity.LOCAL),
],
)
def test_workflow_classify_url(expected_scheme, url):
scheme, _ = util.classify_url(url)
scheme, new = util.classify_url(url)
assert scheme == expected_scheme
if scheme == util.Proximity.LOCAL:
assert isinstance(new, Path)
assert new.is_absolute()


def test_workflow_classify_url_unsupported():
Expand Down
2 changes: 1 addition & 1 deletion src/wxvx/tests/test_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ class C1(B): ...
class C2(B): ...

assert variables.model_names(A) == {"B", "C1", "C2"}
assert variables.model_names() == {S.GFS, S.HRRR, S.PREPBUFR}
assert variables.model_names() == {S.GDAS, S.GFS, S.HRRR, S.PREPBUFR}


def test_variables__da_val__fail_unparesable(da_flat):
Expand Down
8 changes: 4 additions & 4 deletions src/wxvx/tests/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def test_workflow__config_point_stat__atm(c, fakefs, fmt, testvars, tidy):
val = "ADPSFC";
}
];
model = "Forecast";
model = "Forecast_Model";
obs = {
field = [
{
Expand Down Expand Up @@ -348,7 +348,7 @@ def test_workflow__config_point_stat__sfc(c, fakefs, fmt, testvars, tidy):
val = "ADPSFC";
}
];
model = "Forecast";
model = "Forecast_Model";
obs = {
field = [
{
Expand Down Expand Up @@ -879,7 +879,7 @@ def test_workflow__stat_reqs(baseline_name, c, statkit, cycle):
args = (c, statkit.varname, statkit.tc, statkit.var)
assert _stats_vs_grid.call_args_list[0].args == (
*args,
f"forecast_gh_{statkit.level_type}_{statkit.level:04d}",
f"forecast_model_gh_{statkit.level_type}_{statkit.level:04d}",
Source.FORECAST,
)

Expand Down Expand Up @@ -984,7 +984,7 @@ def statkit(tc, testvars):
return ns(
level=level,
level_type=level_type,
prefix=f"forecast_gh_{level_type}_{level:04d}",
prefix=f"forecast_model_gh_{level_type}_{level:04d}",
source=Source.FORECAST,
tc=tc,
var=testvars[EC.gh],
Expand Down
2 changes: 1 addition & 1 deletion src/wxvx/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def classify_url(url: str) -> tuple[Proximity, str | Path]:
if p.scheme in {"http", "https"}:
return Proximity.REMOTE, url
if p.scheme in {"file", ""}:
return Proximity.LOCAL, Path(p.path if p.scheme else url)
return Proximity.LOCAL, Path(p.path if p.scheme else url).resolve()
msg = f"Scheme '{p.scheme}' in '{url}' not supported."
raise WXVXError(msg)

Expand Down
6 changes: 6 additions & 0 deletions src/wxvx/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ def _levinfo(levstr: str) -> tuple[str, float | int | None]:
return (UNKNOWN, None)


class GDAS(GFS):
"""
A GDAS variable.
"""


class HRRR(GFS):
"""
A HRRR variable.
Expand Down
8 changes: 4 additions & 4 deletions src/wxvx/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def _netcdf_from_obs(c: Config, tc: TimeCoords):
yield {"cfgfile": cfgfile, "prepbufr": prepbufr}
runscript = cfgfile.ref.with_suffix(".sh")
content = "exec time pb2nc -v 4 {prepbufr} {netcdf} {config} >{log} 2>&1".format(
prepbufr=prepbufr.ref,
prepbufr=prepbufr.ref.resolve(),
netcdf=path,
config=cfgfile.ref,
log=f"{path.stem}.log",
Expand Down Expand Up @@ -515,7 +515,7 @@ def _stats_vs_grid(c: Config, varname: str, tc: TimeCoords, var: Var, prefix: st
export OMP_NUM_THREADS=1
exec time grid_stat -v 4 {fcst} {obs} {config} >{log} 2>&1
""".format(
fcst=fcst.ref,
fcst=fcst.ref.resolve(),
obs=obs.ref,
config=config.ref,
log=f"{path.stem}.log",
Expand Down Expand Up @@ -552,7 +552,7 @@ def _stats_vs_obs(c: Config, varname: str, tc: TimeCoords, var: Var, prefix: str
yield reqs
runscript = path.with_suffix(".sh")
content = "exec time point_stat -v 4 {fcst} {obs} {config} -outdir {rundir} >{log} 2>&1".format(
fcst=fcst.ref,
fcst=fcst.ref.resolve(),
obs=obs.ref,
config=config.ref,
rundir=rundir,
Expand Down Expand Up @@ -670,7 +670,7 @@ def _stat_args(
cycles = c.cycles
sections = {Source.BASELINE: c.baseline, Source.FORECAST: c.forecast, Source.TRUTH: c.truth}
name = cast(Named, sections[source]).name.lower()
prefix = lambda var: "%s_%s" % (name, str(var).replace("-", "_"))
prefix = lambda var: "%s_%s" % (name.replace(" ", "_"), str(var).replace("-", "_"))
args = [
(c, vn, tc, var, prefix(var), source)
for (var, vn), tc in product(_vxvars(c).items(), gen_timecoords(cycles, c.leadtimes))
Expand Down
Loading