HRDPS Data πŸ…±#

BETA Requires MetPy >=1.6

This demonstrates using data from Canada’s High Resolution Deterministic Prediction System (HRDPS).

HRDPS Model Description

Data Sources

prioriy=

Data source

Archive Duration

"mcs"

Meteorological Service of Canada

Last 24 hours

Model Initialization

Model cyles every hour.

Forecast Hour

For the most recent version of HRRR…

fxx=

Forecast lead time

0 through 48, step=1

hourly forecasts available

Products

product=

Product Description

"continental/2.5km"

Continental domain

Variable and Level

You will need to specify the variable and level for each request.

NOTE: The organization of these files is different than other NWP products.

  1. There are no index files provided.

  2. Each GRIB2 file only contains one message. The variable name and level is in the file’s name.

Herbie requires you provide a keyword argument for both variable and level. Pay special attention to model description (linked above) to understand how the model data is organized. If you don’t provide input for variable or level, Herbie will give you some ideas. For example, variable=TMP and level=AGL-2m will give you the filename that contains

TMP_AGL-2m

Note: This requires MetPy version 1.6 or greater which has the capability to parse the rotated latitude longitude map projection type (see MetPy/#3123).

[1]:
from herbie import Herbie
import xarray as xr
import numpy as np

import matplotlib.pyplot as plt
from toolbox import EasyMap, pc
import cartopy.crs as ccrs
import cartopy.feature as feature
import pandas as pd

recent = pd.Timestamp("now").floor("6H") - pd.Timedelta("6H")

Some Examples#

[2]:
# Some examples

H = Herbie(
    recent,  # Datetime
    model="hrdps",
    fxx=32,
    product="continental/2.5km",
    variable="TMP",
    level="AGL-2m",
)
H.grib
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F32 β”Š GRIB2 @ msc β”Š IDX @ None
[2]:
'https://dd.weather.gc.ca/model_hrdps/continental/2.5km/06/032/20230812T06Z_MSC_HRDPS_TMP_AGL-2m_RLatLon0.0225_PT032H.grib2'
[14]:
H = Herbie(
    recent,  # Datetime
    model="hrdps",
    fxx=12,
    product="continental/2.5km",
    variable="HGT",
    level="ISBL_0500",
)
H.grib
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F12 β”Š GRIB2 @ msc β”Š IDX @ None
[14]:
'https://dd.weather.gc.ca/model_hrdps/continental/2.5km/06/012/20230812T06Z_MSC_HRDPS_HGT_ISBL_0500_RLatLon0.0225_PT012H.grib2'

Get the 2-metre temperature#

[20]:
H = Herbie(
    recent,
    model="hrdps",
    fxx=0,
    product="continental/2.5km",
    variable="TMP",
    level="AGL-2m",
)
ds = H.xarray()
ds
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F00 β”Š GRIB2 @ local β”Š IDX @ None
/home/blaylock/GITHUB/Herbie/herbie/core.py:1058: UserWarning: Will not remove GRIB file because it previously existed.
  warnings.warn("Will not remove GRIB file because it previously existed.")
[20]:
<xarray.Dataset>
Dimensions:              (y: 1290, x: 2540)
Coordinates:
    time                 datetime64[ns] 2023-08-12T06:00:00
    step                 timedelta64[ns] 00:00:00
    heightAboveGround    float64 2.0
    latitude             (y, x) float64 ...
    longitude            (y, x) float64 ...
    valid_time           datetime64[ns] ...
Dimensions without coordinates: y, x
Data variables:
    t2m                  (y, x) float32 ...
    gribfile_projection  object None
Attributes:
    GRIB_edition:            2
    GRIB_centre:             cwao
    GRIB_centreDescription:  Canadian Meteorological Service - Montreal
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             Canadian Meteorological Service - Montreal
    model:                   hrdps
    product:                 continental/2.5km
    description:             Canada's High Resolution Deterministic Predictio...
    remote_grib:             /home/blaylock/data/hrdps/20230812/20230812T06Z_...
    local_grib:              /home/blaylock/data/hrdps/20230812/20230812T06Z_...
    searchString:            None
[3]:
ds.valid_time.dt.strftime("%Y-%m-%d %H:%M").item()
[3]:
'2023-08-12 06:00'
[ ]:

Plot data on Plate Carree projection#

[4]:
ax = EasyMap("50m").BORDERS().STATES(alpha=0.5).ax
p = ax.pcolormesh(ds.longitude, ds.latitude, ds.t2m, transform=pc, cmap="Spectral_r")
plt.colorbar(p, ax=ax, orientation="horizontal", pad=0.01, shrink=0.8)
ax.set_title(
    f"2-m Temperature\nValid {ds.valid_time.dt.strftime('%Y-%m-%d %H:%M').item()} UTC",
    loc="right",
    fontsize=10,
)
ax.set_title(f"{ds.model.upper()}: {H.product_description}", loc="left")
ax.gridlines()
[4]:
<cartopy.mpl.gridliner.Gridliner at 0x7fb114146310>
../../_images/user_guide__model_notebooks_hrdps_10_1.png

Plot data on model grid typel (rotated latitude longitude)#

[5]:
ax = EasyMap("50m", crs=ds.herbie.crs).BORDERS().STATES(alpha=0.5).ax
p = ax.pcolormesh(ds.longitude, ds.latitude, ds.t2m, transform=pc, cmap="Spectral_r")
plt.colorbar(p, ax=ax, orientation="horizontal", pad=0.01, shrink=0.8)
ax.set_title(
    f"2-m Temperature\nValid {ds.valid_time.dt.strftime('%Y-%m-%d %H:%M').item()} UTC",
    loc="right",
    fontsize=10,
)
ax.set_title(f"{ds.model.upper()}: {H.product_description}", loc="left")
ax.gridlines()
[5]:
<cartopy.mpl.gridliner.Gridliner at 0x7fb113fffa50>
../../_images/user_guide__model_notebooks_hrdps_12_1.png

Get 10-m U and 10-m V wind#

[13]:
# loading more than one variable requires a loop, because the
# data is stored in multiple files (and a Herbie object only
# represents a single file).

store = []
for var, lev in zip(["UGRD", "VGRD"], ["AGL-10m", "AGL-10m"]):
    _ds = Herbie(
        recent,
        model="hrdps",
        fxx=0,
        product="continental/2.5km",
        variable=var,
        level=lev,
    ).xarray()
    store.append(_ds)

ds = xr.merge(store)
ds
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F00 β”Š GRIB2 @ local β”Š IDX @ None
/home/blaylock/GITHUB/Herbie/herbie/core.py:1058: UserWarning: Will not remove GRIB file because it previously existed.
  warnings.warn("Will not remove GRIB file because it previously existed.")
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F00 β”Š GRIB2 @ local β”Š IDX @ None
/home/blaylock/GITHUB/Herbie/herbie/core.py:1058: UserWarning: Will not remove GRIB file because it previously existed.
  warnings.warn("Will not remove GRIB file because it previously existed.")
[13]:
<xarray.Dataset>
Dimensions:              (y: 1290, x: 2540)
Coordinates:
    time                 datetime64[ns] 2023-08-12T06:00:00
    step                 timedelta64[ns] 00:00:00
    heightAboveGround    float64 10.0
    latitude             (y, x) float64 39.63 39.63 39.64 ... 47.91 47.89 47.88
    longitude            (y, x) float64 -133.6 -133.6 -133.6 ... -40.73 -40.71
    valid_time           datetime64[ns] 2023-08-12T06:00:00
Dimensions without coordinates: y, x
Data variables:
    u10                  (y, x) float32 ...
    gribfile_projection  object None
    v10                  (y, x) float32 ...
Attributes:
    GRIB_edition:            2
    GRIB_centre:             cwao
    GRIB_centreDescription:  Canadian Meteorological Service - Montreal
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             Canadian Meteorological Service - Montreal
    model:                   hrdps
    product:                 continental/2.5km
    description:             Canada's High Resolution Deterministic Predictio...
    remote_grib:             /home/blaylock/data/hrdps/20230812/20230812T06Z_...
    local_grib:              /home/blaylock/data/hrdps/20230812/20230812T06Z_...
    searchString:            None
[14]:
# MetPy version >= 1.6 is required to parse the map projection
ds.herbie.crs
[14]:
2023-08-12T14:42:59.855304 image/svg+xml Matplotlib v3.7.2, https://matplotlib.org/
<cartopy.crs.RotatedPole object at 0x7fb110150690>
[16]:
ax = (
    EasyMap("50m", crs=ds.herbie.crs, figsize=8, linewidth=1, dark=True)
    .BORDERS()
    .STATES(alpha=0.5)
    .ax
)
p = ax.pcolormesh(
    ds.longitude,
    ds.latitude,
    np.hypot(ds.u10, ds.v10),  # Wind Speed
    transform=pc,
)
plt.colorbar(
    p, ax=ax, orientation="horizontal", pad=0.01, shrink=0.8, label="Wind speed (m/s)"
)

ax.set_title(
    f"10-m Wind Speed\nValid {ds.valid_time.dt.strftime('%Y-%m-%d %H:%M').item()} UTC",
    loc="center",
    fontsize=10,
)
ax.set_title(f"{ds.model.upper()}", loc="left")
ax.EasyMap.INSET_GLOBE()
[16]:
<GeoAxes: >
../../_images/user_guide__model_notebooks_hrdps_16_1.png

500 hPa Humidity and Geopotential Height#

[16]:
# loading more than one variable requires a loop, because the
# data is stored in multiple files (and a Herbie object only
# represents a single file).

store = []
for var, lev in zip(["HGT", "RH"], ["ISBL_0500", "ISBL_0500"]):
    _ds = Herbie(
        recent,
        model="hrdps",
        fxx=0,
        product="continental/2.5km",
        variable=var,
        level=lev,
    ).xarray()
    store.append(_ds)

ds = xr.merge(store)
ds
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F00 β”Š GRIB2 @ msc β”Š IDX @ None
/home/blaylock/GITHUB/Herbie/herbie/core.py:1063: UserWarning: Will not remove GRIB file because Herbie will only remove subsetted files (not full files).
  warnings.warn(
βœ… Found β”Š model=hrdps β”Š product=continental/2.5km β”Š 2023-Aug-12 06:00 UTC F00 β”Š GRIB2 @ msc β”Š IDX @ None
/home/blaylock/GITHUB/Herbie/herbie/core.py:1063: UserWarning: Will not remove GRIB file because Herbie will only remove subsetted files (not full files).
  warnings.warn(
[16]:
<xarray.Dataset>
Dimensions:              (y: 1290, x: 2540)
Coordinates:
    time                 datetime64[ns] 2023-08-12T06:00:00
    step                 timedelta64[ns] 00:00:00
    isobaricInhPa        float64 500.0
    latitude             (y, x) float64 39.63 39.63 39.64 ... 47.91 47.89 47.88
    longitude            (y, x) float64 -133.6 -133.6 -133.6 ... -40.73 -40.71
    valid_time           datetime64[ns] 2023-08-12T06:00:00
Dimensions without coordinates: y, x
Data variables:
    gh                   (y, x) float32 ...
    gribfile_projection  object None
    r                    (y, x) float32 ...
Attributes:
    GRIB_edition:            2
    GRIB_centre:             cwao
    GRIB_centreDescription:  Canadian Meteorological Service - Montreal
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             Canadian Meteorological Service - Montreal
    model:                   hrdps
    product:                 continental/2.5km
    description:             Canada's High Resolution Deterministic Predictio...
    remote_grib:             /home/blaylock/data/hrdps/20230812/20230812T06Z_...
    local_grib:              /home/blaylock/data/hrdps/20230812/20230812T06Z_...
    searchString:            None
[22]:
ax = (
    EasyMap("50m", crs=ds.herbie.crs, figsize=8, linewidth=1, dark=True)
    .BORDERS()
    .STATES(alpha=0.5)
    .ax
)

# Draw Relative Humidity
p = ax.pcolormesh(
    ds.longitude, ds.latitude, ds.r, transform=pc, cmap="BrBG", vmin=0, vmax=100
)
plt.colorbar(
    p,
    ax=ax,
    orientation="horizontal",
    pad=0.01,
    shrink=0.8,
    label="Relative Humidity (%)",
)

# Draw Geopential Height Contours
ax.contour(
    ds.longitude,
    ds.latitude,
    ds.gh,
    colors="k",
    transform=pc,
    levels=range(0, 6000, 40),
)

ax.set_title(
    f"500 hPa RH and Geopotential height\nValid {ds.valid_time.dt.strftime('%Y-%m-%d %H:%M').item()} UTC",
    loc="center",
    fontsize=10,
)
ax.set_title(f"{ds.model.upper()}", loc="left")
[22]:
Text(0.0, 1.0, 'HRDPS')
../../_images/user_guide__model_notebooks_hrdps_19_1.png
The Kernel crashed while executing code in the the current cell or a previous cell. Please review the code in the cell(s) to identify a possible cause of the failure. Click <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info. View Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details.

HRDPS North domain (experimental)#

[17]:
H = Herbie(
    recent.floor("12H"),  # only run every 00 anc 12 UTC
    model="hrdps_north",
    fxx=0,
    product="north/grib2",
    variable="TMP",
    level="TGL_2",
)
ds = H.xarray()
ds
βœ… Found β”Š model=hrdps_north β”Š product=north/grib2 β”Š 2023-Aug-12 00:00 UTC F00 β”Š GRIB2 @ local β”Š IDX @ None
/home/blaylock/GITHUB/Herbie/herbie/core.py:1058: UserWarning: Will not remove GRIB file because it previously existed.
  warnings.warn("Will not remove GRIB file because it previously existed.")
[17]:
<xarray.Dataset>
Dimensions:              (y: 825, x: 1465)
Coordinates:
    time                 datetime64[ns] 2023-08-12
    step                 timedelta64[ns] 00:00:00
    heightAboveGround    float64 2.0
    latitude             (y, x) float64 ...
    longitude            (y, x) float64 ...
    valid_time           datetime64[ns] ...
Dimensions without coordinates: y, x
Data variables:
    t2m                  (y, x) float32 ...
    gribfile_projection  object None
Attributes:
    GRIB_edition:            2
    GRIB_centre:             cwao
    GRIB_centreDescription:  Canadian Meteorological Service - Montreal
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             Canadian Meteorological Service - Montreal
    model:                   hrdps_north
    product:                 north/grib2
    description:             Canada's High Resolution Deterministic Predictio...
    remote_grib:             /home/blaylock/data/hrdps_north/20230812/CMC_hrd...
    local_grib:              /home/blaylock/data/hrdps_north/20230812/CMC_hrd...
    searchString:            None
[10]:
# This domain is run on a polar stereographic projection
ds.herbie.crs
[10]:
2023-08-12T14:42:00.814487 image/svg+xml Matplotlib v3.7.2, https://matplotlib.org/
<cartopy.crs.Stereographic object at 0x7fb113fc4910>
[19]:
ax = EasyMap("50m", crs=ds.herbie.crs).BORDERS().STATES(alpha=0.5).ax
p = ax.pcolormesh(
    ds.longitude, ds.latitude, ds.t2m - 273.15, transform=pc, cmap="Spectral_r"
)
plt.colorbar(
    p,
    ax=ax,
    orientation="horizontal",
    pad=0.01,
    shrink=0.8,
    label="2-m Temperature (C)",
)
ax.set_title(f"{ds.model.upper()}", loc="left")
ax.set_title(
    f"2-m Temperature\nValid {ds.valid_time.dt.strftime('%Y-%m-%d %H:%M').item()} UTC",
    loc="center",
    fontsize=10,
)
ax.gridlines()
ax.EasyMap.INSET_GLOBE()
[19]:
<GeoAxes: >
../../_images/user_guide__model_notebooks_hrdps_23_1.png