Skip to content
Closed
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
19 changes: 17 additions & 2 deletions src/modelskill/matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,6 @@ def _match_single_obs(


def _get_global_start_end(idxs: Iterable[pd.DatetimeIndex]) -> Period:
assert all([len(x) > 0 for x in idxs]), "All datetime indices must be non-empty"

starts = [x[0] for x in idxs]
ends = [x[-1] for x in idxs]

Expand All @@ -408,6 +406,22 @@ def _check_timezone_compatibility(
)


def _check_model_results_not_empty(
observation: Observation,
raw_mod_data: Mapping[
str,
PointModelResult | TrackModelResult | VerticalModelResult | NodeModelResult,
],
) -> None:
for name, mr in raw_mod_data.items():
if len(mr.time) == 0:
raise ValueError(
f"Model result '{name}' has no data at observation '{observation.name}'. "
"Check that the observation is inside the model domain and that the "
"model has valid values there (e.g. the location is not dry)."
)


def _at_observation(mr: NodeModelResult, obs: TimeSeries) -> NodeModelResult:
"""The extracted model result, placed where the observation sits.

Expand All @@ -431,6 +445,7 @@ def _match_space_time(
obs_no_overlap: Literal["ignore", "error", "warn"],
) -> xr.Dataset | None:
_check_timezone_compatibility(observation, raw_mod_data)
_check_model_results_not_empty(observation, raw_mod_data)

idxs = [m.time for m in raw_mod_data.values()]
period = _get_global_start_end(idxs)
Expand Down
17 changes: 17 additions & 0 deletions tests/test_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,23 @@ def test_match_raises_clear_error_on_tz_aware_vs_naive_mismatch():
ms.match(obs, mr)


def test_match_raises_clear_error_when_model_result_is_empty():
"""An empty extraction (e.g. point outside domain or dry) must raise a clear error, not a bare assert."""
obs = ms.PointObservation(
data=pd.Series(
[1.0, 2.0, 3.0], index=pd.date_range("2020-01-01", periods=3, freq="h")
),
name="Station",
)
mr = ms.PointModelResult(
data=pd.Series([], dtype=float, index=pd.DatetimeIndex([])),
name="Model",
)

with pytest.raises(ValueError, match="'Model' has no data.*'Station'"):
ms.match(obs, mr)


def test_multiple_models_same_name(tmp_path: Path) -> None:
obs = ms.PointObservation(
"tests/testdata/SW/HKNA_Hm0.dfs0", item=0, x=4.2420, y=52.6887, name="HKNA"
Expand Down