Skip to content

Instantly share code, notes, and snippets.

@sieste
Created April 28, 2026 11:19
Show Gist options
  • Select an option

  • Save sieste/68c0370881fb7cd9e592d3347483370e to your computer and use it in GitHub Desktop.

Select an option

Save sieste/68c0370881fb7cd9e592d3347483370e to your computer and use it in GitHub Desktop.
CDS API code to download ERA5 windspeed data
# load venv_cdsapi, which is a standard python venv plus `pip install cdsapi`
# and also needs ~/.cdsapirc with lines:
# url: https://cds.climate.copernicus.eu/api
# key: <CDS API KEY>
import os
import numpy as np
import cdsapi
import xarray as xr
for year in range(2000,2021):
for month in ["01", "02", "03", "04", "05", "06",
"07", "08", "09", "10", "11", "12"]:
# year = 2000
# month = "01"
#
nc_file = f"era5_uv850_6hourly_global1deg_{year}{month}.nc"
if os.path.exists(nc_file):
print(f"skip existing {nc_file}")
continue
#
print(f"requesting year {year} month {month} from CDS")
dataset = 'reanalysis-era5-pressure-levels'
request = {
"product_type": ["reanalysis"],
"variable": ["u_component_of_wind", "v_component_of_wind"],
"year": [year],
"month": [month],
"day": ["01", "02", "03", "04", "05", "06", "07", "08", "09",
"10", "11", "12", "13", "14", "15", "16", "17", "18",
"19", "20", "21", "22", "23", "24", "25", "26", "27",
"28", "29", "30", "31"],
"time": ["00:00", "06:00", "12:00", "18:00"],
"pressure_level": ["850"],
"data_format": "grib",
"download_format": "unarchived"
}
target = 'tmp_download.grib' # about 500Mb, won't be stored
client = cdsapi.Client()
client.retrieve(dataset, request, target)
#
# coarsen to 1 degree resolution by averaging over 4x4 patches
uv850 = xr.load_dataset(target)
uv850_1deg = uv850.coarsen(longitude=4, latitude=4, boundary="trim").mean()
#
# store as 0.1 m/s in int32, reduces file size
uv850_1deg_int = np.round(10 * uv850_1deg)
# TODO: update uv850_1deg['u'].attrs (GRIB_NX/NY/units)
#
# save integer data to netcdf with compression
uv850_1deg_int = uv850_1deg_int.astype("int32")
encoding = {
"u": {"dtype": "int32", "zlib": True, "complevel": 4},
"v": {"dtype": "int32", "zlib": True, "complevel": 4}
}
uv850_1deg_int.to_netcdf(nc_file, encoding=encoding)
# clean up
if os.path.exists(target):
os.remove(target)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment