Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f0b32fb
fix: compute_climatology() now correctly handling leap years and star…
dsj976 Mar 8, 2026
6d776c2
update pydmd dependency URL to the official repository
dsj976 Mar 13, 2026
ea47a5a
feat: add compute_rmse function and corresponding tests for RMSE calc…
dsj976 Mar 14, 2026
e959ca5
Merge branch 'fix-compute-climatology' into implement/weather-utils
dsj976 Mar 15, 2026
bf97437
feat: implement compute_climatology function for climatological forec…
dsj976 Mar 15, 2026
985eb51
do not trigger Dask computation in compute_rmse()
dsj976 Mar 15, 2026
65b73a4
feat: add compute_energy_spectrum function using Weatherbench2 for zo…
dsj976 Mar 16, 2026
9410d6a
refactor: improve DataGenerator initialization and restructure RMSE t…
dsj976 Mar 16, 2026
28179ac
refactor: simplify latitude weighting in compute_rmse function
dsj976 Mar 17, 2026
b5e9bdf
reduce test dataset size in test_weather_utils
dsj976 Mar 17, 2026
0ccf572
check for expected rmse in test_compute_rmse
dsj976 Mar 17, 2026
6dce95b
drop time in climatology before new assignment to avoid deprecation w…
dsj976 Mar 17, 2026
1d09011
test for compute_climatology function
dsj976 Mar 17, 2026
060bb25
add test for compute_energy_spectrum function
dsj976 Mar 17, 2026
61b3a94
ignore PendingDeprecationWarning from weatherbench2 in pytest
dsj976 Mar 17, 2026
8662bdf
update climatology to be returned as a function of day of year and ho…
dsj976 Mar 18, 2026
d6b0256
add expand_time_climatology function to convert dayofyear and hour di…
dsj976 Mar 18, 2026
4bda48d
update compute_climatology: remove months parameter and do not drop 2…
dsj976 Mar 18, 2026
139967a
add pytest-dependency to development dependencies
dsj976 Mar 18, 2026
0f94491
fix bug in time vector generation in expand_time_climatology()
dsj976 Mar 18, 2026
065afdb
add test for expand_time_climatology function in test_weather_utils.py
dsj976 Mar 18, 2026
d486b76
feat: enhance compute_climatology with optional smoothing window
dsj976 Mar 21, 2026
e68c904
docs: update compute_climatology notes on smoothing performance and d…
dsj976 Mar 21, 2026
b0c5559
improve compute_rmse function to raise error in case of empty array
dsj976 Mar 22, 2026
6c18344
feat: add compute_crps_gaussian function for probabilistic forecast e…
dsj976 Mar 23, 2026
bfdc12e
fix: update compute_crps_gaussian to handle lat_weighting and dims ch…
dsj976 Mar 23, 2026
87011b8
add test for compute_crps_gaussian()
dsj976 Mar 23, 2026
3f723af
add compute_acc function for anomaly correlation calculation
dsj976 Mar 23, 2026
496e7de
add docstring and input checks to compute_acc function
dsj976 Mar 24, 2026
2d9eed6
fix bug in expand_time_climatology()
dsj976 Mar 24, 2026
6e3e656
add test for compute_acc function in weather_utils
dsj976 Mar 25, 2026
433e127
add input validation for compute_crps_gaussian to ensure arrays are a…
dsj976 Mar 25, 2026
9218df0
update Python version in CI configuration to 3.12
dsj976 Mar 25, 2026
8e0481a
update CI configuration to install optional dependencies (extras)
dsj976 Mar 25, 2026
1cb6c78
update compute_climatology to support probabilistic output and update…
dsj976 Mar 27, 2026
57898a8
add compute_mae function and corresponding tests for Mean Absolute Er…
dsj976 Mar 28, 2026
5334e14
make stricter input checks for compute_rmse()
dsj976 Mar 28, 2026
0fb5e87
use numpy sqrt directly instead of deprecated ufuncs
dsj976 Mar 29, 2026
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.12"
- uses: pre-commit/action@v3.0.0
with:
extra_args: --hook-stage manual --all-files
Expand All @@ -43,7 +43,7 @@ jobs:
allow-prereleases: true

- name: Install package
run: python -m pip install .[dev]
run: python -m pip install .[dev,extras]

- name: Test package
run: >-
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ repos:
- pydmd
- pandas
- pandas-stubs
- weatherbench2 @ git+https://github.com/google-research/weatherbench2.git
54 changes: 33 additions & 21 deletions demos/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import datetime, timedelta

import numpy as np
import pandas as pd
import xarray as xr
from dask.diagnostics import ProgressBar

Expand Down Expand Up @@ -144,7 +145,8 @@ def compute_climatology(
months: list[int],
) -> xr.DataArray:
"""Given observed data, compute a climatological forecast over
the specified year and months.
the specified year and months. Note 29 Feb is skipped on leap
years.

Examples
--------
Expand All @@ -158,23 +160,33 @@ def compute_climatology(
)
"""
months = sorted(months)
climatology = data.sel(time=data.time.dt.month.isin(months))
climatology = climatology.compute()
climatology = climatology.sel(
time=~((climatology.time.dt.month == 2) & (climatology.time.dt.day == 29))
) # drop 29th Feb for consistency
climatology = climatology.groupby(["time.dayofyear", "time.hour"]).mean()
hours = climatology.hour.values
days = climatology.dayofyear.values
t = []
for d in days:
for h in hours:
dt = timedelta(days=int(d - 1), hours=int(h))
t.append(np.timedelta64(dt, "h"))
t = np.array(t)
month = months[0]
month = f"0{month}" if month < 10 else str(month)
t = np.datetime64(f"{year}-{month}-01T00:00") + t
climatology = climatology.stack(time=("dayofyear", "hour"))
climatology = climatology.drop_vars(["time", "dayofyear", "hour"])
return climatology.assign_coords(time=t)

dt = (np.unique(np.diff(data.time.values))).astype("timedelta64[h]").astype(int)
if len(dt) > 1:
msg = "The time axis of the input data must have uniform spacing."
raise ValueError(msg)
dt = dt[0]
times = pd.date_range(
f"{year}-01-01", f"{year}-12-31 23:00", freq=timedelta(hours=int(dt))
)
times = times[times.month.isin(months)]
# drop 29 Feb for consistency
times = times[~((times.month == 2) & (times.day == 29))]

# handle 29 Feb on leap years
doy = data.time.dt.dayofyear
shift = data.time.dt.is_leap_year & (data.time.dt.month > 2)
doy_corrected = xr.where(shift, doy - 1, doy)
data = data.assign_coords(doy=("time", doy_corrected.data))
data = data.sel(time=~((data.time.dt.month == 2) & (data.time.dt.day == 29)))

# keep only the requested months
data = data.sel(time=data.time.dt.month.isin(months))
data = data.compute()

# now group by day of year and hour of day, and average
# to compute climatology
clim = data.groupby(["doy", "time.hour"]).mean()
clim = clim.stack(time=("doy", "hour"))
clim = clim.drop_vars(["doy", "hour"])
return clim.assign_coords(time=times)
8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,21 @@ dependencies = [
"zarr<=3.1.0",
"dask[complete]",
"xarray[complete]",
"pydmd @ git+https://github.com/ClimeTrend/PyDMD.git@parallel-bagging",
"pydmd @ git+https://github.com/PyDMD/PyDMD.git",
]

[project.optional-dependencies]
dev = [
"pytest >=6",
"pytest-cov >=3",
"pytest-dependency",
"pre-commit",
]
extras = [
"cartopy >= 0.24.1",
"gcsfs",
"weatherbench2 @ git+https://github.com/google-research/weatherbench2.git",
"properscoring @ git+https://github.com/SVDROM/properscoring.git",
]

[project.urls]
Expand All @@ -58,6 +61,7 @@ xfail_strict = true
filterwarnings = [
"error",
"ignore::UserWarning:pydmd",
"ignore::PendingDeprecationWarning:weatherbench2",
]
log_cli_level = "INFO"
testpaths = [
Expand All @@ -82,7 +86,7 @@ disallow_incomplete_defs = false
check_untyped_defs = true
strict = false
[[tool.mypy.overrides]]
module = ["pydmd.*"]
module = ["pydmd.*", "weatherbench2.*"]
follow_untyped_imports = true

[tool.ruff]
Expand Down
Loading
Loading