Working with REMO domains

The domain module should give some tools to work with preconfigured or user defined domains. Domains are defined as xarray datasets that will contain dimensions and coodinates according to CF-conventions. The pyremo domain module actually uses the py-cordex domains module in the background just with another set of tables.

NOTE: Please be aware that a remo domain is usually a little larger than the “official” cordex domain according to the archive specification since the regional model usually accounts for a “buffer” zone where the lateral boundary conditions are nudged.

Working with domain information

[1]:
import pyremo as pr

The domain module contains some useful functions to work with cordex meta data, e.g., you can get some domain grid information using

[2]:
pr.domain_info("EUR-11")
Downloading file 'domains.csv' from 'https://raw.githubusercontent.com/remo-rcm/tables/main/domains/domains.csv' to '/home/docs/.pyremo'.
[2]:
{'domain_id': 'EUR-11',
 'region': 4,
 'domain': 'Europe high-res.',
 'nlon': 433,
 'nlat': 433,
 'll_lon': -28.925,
 'll_lat': -23.925,
 'dlon': 0.11,
 'dlat': 0.11,
 'pollon': -162.0,
 'pollat': 39.25,
 'ur_lon': None,
 'ur_lat': None}

All available cordex domains are in this table:

[3]:
pr.domains.table
[3]:
region domain nlon nlat ll_lon ll_lat dlon dlat pollon pollat ur_lon ur_lat
domain_id
AFR-11 5 Africa 801 865 -26.23500 -49.33500 0.1100 0.1100 180.00 90.00 NaN NaN
AFR-22 5 Africa 401 433 -26.29000 -49.39000 0.2200 0.2200 180.00 90.00 NaN NaN
AFR-44 5 Africa 217 217 -29.92000 -49.28000 0.4400 0.4400 180.00 90.00 NaN NaN
AUS-11 9 Australasia 811 541 321.49000 -60.20000 0.1100 0.1100 141.38 60.31 NaN NaN
AUS-22 9 Australasia 433 271 138.31000 -24.53000 0.2200 0.2200 141.38 60.31 NaN NaN
AUS-44 9 Australasia 217 145 321.82000 -59.87000 0.4400 0.4400 141.38 60.31 NaN NaN
CAM-11 2 Central America 865 481 294.09000 -75.63000 0.1100 0.1100 113.98 75.74 NaN NaN
CAM-22 2 Central America 433 241 -54.45000 -30.47000 0.2200 0.2200 113.98 75.74 NaN NaN
CAM-44 2 Central America 241 129 -59.84000 -32.12000 0.4400 0.4400 113.98 75.74 NaN NaN
CAS-11 8 Central Asia 641 433 -36.02500 -22.60500 0.1100 0.1100 -103.39 43.48 NaN NaN
CAS-22 8 Central Asia 325 217 -36.63000 -22.77000 0.2200 0.2200 -103.39 43.48 NaN NaN
CAS-44 8 Central Asia 181 121 -40.48000 -25.52000 0.4400 0.4400 -103.39 43.48 NaN NaN
EAS-11 7 East Asia 811 513 116.41000 -60.89000 0.1100 0.1100 -63.70 61.00 NaN NaN
EAS-22 7 East Asia 433 271 -47.41000 -24.30000 0.2200 0.2200 296.30 61.00 NaN NaN
EAS-44 7 East Asia 201 163 476.74000 -60.56000 0.4400 0.4400 296.30 61.00 NaN NaN
EUR-11 4 Europe high-res. 433 433 -28.92500 -23.92500 0.1100 0.1100 -162.00 39.25 NaN NaN
EUR-22 4 Europe 241 217 -31.62000 -24.64000 0.2200 0.2200 -162.00 39.25 NaN NaN
EUR-44 4 Europe 129 121 -31.73000 -26.73000 0.4400 0.4400 -162.00 39.25 NaN NaN
NAM-11 3 North America 641 541 263.11000 -42.39000 0.1100 0.1100 83.00 42.50 NaN NaN
NAM-22 3 North America 321 271 -35.31000 -29.83000 0.2200 0.2200 83.00 42.50 NaN NaN
NAM-44 3 North America 181 151 -39.60000 -33.24000 0.4400 0.4400 83.00 42.50 NaN NaN
SAM-11 1 South America 601 721 124.05000 -70.49000 0.1100 0.1100 -56.06 70.60 NaN NaN
SAM-22 1 South America 301 361 142.71000 -41.47000 0.2200 0.2200 -56.06 70.60 NaN NaN
SAM-44 1 South America 161 181 140.40000 -41.36000 0.4400 0.4400 -56.06 70.60 NaN NaN
SEA-22 14 South East Asia 289 217 86.40000 -17.82000 0.2200 0.2200 180.00 90.00 NaN NaN
WAS-22 6 South Asia 401 271 -33.99000 -22.99000 0.2200 0.2200 -123.34 79.95 NaN NaN
EUR+NA-11 4 Europe + North Atlantic 649 433 18.11000 -39.14000 0.1100 0.1100 -162.00 39.25 NaN NaN
HUN-11 4 Hungary 301 145 360.11000 -89.89000 0.1100 0.1100 180.00 90.00 NaN NaN
SASSCAL-22 5 Southern Africa 433 433 360.22000 -89.78000 0.2200 0.2200 180.00 90.00 NaN NaN
GAR-11 4 Greater Alpine Region 145 129 -14.95500 -12.15500 0.1100 0.1100 -162.00 39.25 NaN NaN
EUN-0275 4 EUCP Northern Europe 649 811 -9.99125 -0.20625 0.0275 0.0275 -162.00 39.25 NaN NaN
EUC-0275 4 EUCP Central Europe 361 401 -9.52375 -5.29375 0.0275 0.0275 -162.00 39.25 NaN NaN
SGAR-0275 4 Greater Alpine Region 289 271 -9.38625 -9.66625 0.0275 0.0275 -162.00 39.25 NaN NaN
GAR-0275 4 Greater Alpine Region 501 481 -13.92375 -11.67375 0.0275 0.0275 -162.00 39.25 -0.17375 1.52625
MEU-11 4 Mid-Europe 121 121 -10.89000 -6.89000 0.1100 0.1100 -162.00 39.25 NaN NaN
WAF-11 5 Westafrica 361 271 -20.68000 2.64000 0.1100 0.1100 180.00 90.00 NaN NaN
MSEA-11 14 South East Asia Mainland 145 181 92.34000 7.12000 0.1100 0.1100 180.00 80.00 NaN NaN
MOMED-11 12 Mediterranean 487 321 -27.92500 -25.92500 0.1100 0.1100 198.00 39.25 NaN NaN
HYDRASIA-11 8 Central Asia 257 271 -20.02500 -20.60500 0.1100 0.1100 -103.39 43.48 NaN NaN
GUI-0275 5 Guinea 811 321 -17.03625 4.08375 0.0275 0.0275 180.00 90.00 5.23875 12.88375
ALPX-3 4 Extended Alpine Region 721 577 -18.62625 -11.20625 0.0275 0.0275 -162.00 39.25 NaN NaN
NSEA-3 4 North Sea 649 541 -15.98625 -0.97625 0.0275 0.0275 -162.00 39.25 NaN NaN

EUR-11 example

The heart of the module are some functions that create a dataset from the grid information, e.g.

[4]:
eur11 = pr.remo_domain("EUR-11", dummy="topo")
eur11
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:671: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  unused_keys = set(attribute.keys()) - set(inverted)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:672: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  for key, value in attribute.items():
[4]:
<xarray.Dataset> Size: 4MB
Dimensions:                     (rlon: 433, rlat: 433)
Coordinates:
  * rlon                        (rlon) float64 3kB -28.93 -28.82 ... 18.48 18.59
  * rlat                        (rlat) float64 3kB -23.93 -23.82 ... 23.48 23.59
    lon                         (rlat, rlon) float64 1MB -10.32 -10.23 ... 68.65
    lat                         (rlat, rlon) float64 1MB 21.28 21.32 ... 67.8
Data variables:
    rotated_latitude_longitude  int32 4B 0
    topo                        (rlat, rlon) float32 750kB 283.0 283.0 ... 44.67
Attributes:
    CORDEX_domain:  EUR-11

The dummy='topo' argument means, we want a dummy variable in the dataset to see how the domain looks like. For the dummy topography, we use the cdo topo operator in the background. So maybe you have to install python-cdo, e.g., conda install -c conda-forge python-cdo. Working with xarray datasets means, that we can use all the nice functions of xarray including plotting, e.g.,

[5]:
eur11.topo.plot(cmap="terrain")
Matplotlib is building the font cache; this may take a moment.
[5]:
<matplotlib.collections.QuadMesh at 0x7fa9e89c6fb0>
../_images/notebooks_domains_12_2.png
[6]:
eur11.topo.plot(x="lon", y="lat", cmap="terrain")
[6]:
<matplotlib.collections.QuadMesh at 0x7fa9e8885780>
../_images/notebooks_domains_13_1.png

Let’s define a slightly more sophisticated plotting function that uses cartopy for the right projection with a rotated pole:

[7]:
def plot(da, pole, vmin=None, vmax=None, borders=True, title=""):
    """plot a domain using the right projection with cartopy"""
    %matplotlib inline
    import cartopy.crs as ccrs
    import cartopy.feature as cf
    import matplotlib.pyplot as plt

    plt.figure(figsize=(20, 10))
    projection = ccrs.PlateCarree()
    transform = ccrs.RotatedPole(pole_latitude=pole[1], pole_longitude=pole[0])
    # ax = plt.axes(projection=projection)
    ax = plt.axes(projection=transform)
    # ax.set_extent([ds_sub.rlon.min(), ds_sub.rlon.max(), ds_sub.rlat.min(), ds_sub.rlat.max()], crs=transform)
    ax.gridlines(
        draw_labels=True,
        linewidth=0.5,
        color="gray",
        xlocs=range(-180, 180, 10),
        ylocs=range(-90, 90, 5),
    )
    da.plot(
        ax=ax,
        cmap="terrain",
        transform=transform,
        vmin=vmin,
        vmax=vmax,
        x="rlon",
        y="rlat",
    )
    ax.coastlines(resolution="50m", color="black", linewidth=1)
    if borders:
        ax.add_feature(cf.BORDERS)
    ax.set_title("")
[8]:
pole_eur = (
    eur11.rotated_latitude_longitude.grid_north_pole_longitude,
    eur11.rotated_latitude_longitude.grid_north_pole_latitude,
)
pole_eur
[8]:
(-162.0, 39.25)
[9]:
plot(eur11.topo, pole_eur)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_cultural/ne_110m_admin_0_boundary_lines_land.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
../_images/notebooks_domains_17_1.png

User defined domain

The domains are created using the create_dataset function from the `py-cordex <https://py-cordex.readthedocs.io>`__ package, e.g.:

[10]:
from cordex import create_dataset

Let’s create the EUR-11 domain manually from the numbers in the table:

[11]:
eur11_user = create_dataset(
    nlon=433,
    nlat=433,
    dlon=0.11,
    dlat=0.11,
    ll_lon=-28.925,
    ll_lat=-23.925,
    pollon=-162.00,
    pollat=39.25,
    dummy="topo",
)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:671: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  unused_keys = set(attribute.keys()) - set(inverted)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:672: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  for key, value in attribute.items():

We can check that this gives the same result as our preconfigured domain.

[12]:
eur11_user.equals(eur11)
[12]:
True

You can now use the create_dataset function to create any domain as an xarray dataset.

[13]:
afr11 = pr.remo_domain("AFR-11", dummy="topo")
afr11
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:671: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  unused_keys = set(attribute.keys()) - set(inverted)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:672: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  for key, value in attribute.items():
[13]:
<xarray.Dataset> Size: 14MB
Dimensions:                     (rlon: 801, rlat: 865)
Coordinates:
  * rlon                        (rlon) float64 6kB -26.23 -26.12 ... 61.66 61.77
  * rlat                        (rlat) float64 7kB -49.34 -49.23 ... 45.6 45.71
    lon                         (rlat, rlon) float64 6MB -26.23 -26.13 ... 61.77
    lat                         (rlat, rlon) float64 6MB -49.34 -49.34 ... 45.71
Data variables:
    rotated_latitude_longitude  int32 4B 0
    topo                        (rlat, rlon) float32 3MB -4.646e+03 ... 56.0
Attributes:
    CORDEX_domain:  AFR-11
[14]:
pole_afr = (
    afr11.rotated_latitude_longitude.grid_north_pole_longitude,
    afr11.rotated_latitude_longitude.grid_north_pole_latitude,
)
pole_afr
[14]:
(180.0, 90.0)
[15]:
plot(afr11.topo, pole_afr)
../_images/notebooks_domains_28_0.png

Cropping the REMO domain

Sometimes it might be neccessary to crop the REMO data to the official CORDEX grid size, e.g., for cmorization. This can now easily be done like this:

[16]:
import numpy as np
from cordex import cordex_domain

eur11_cordex = cordex_domain("EUR-11", dummy="topo")
Downloading file 'rotated-latitude-longitude.csv' from 'https://raw.githubusercontent.com/WCRP-CORDEX/domain-tables/main/rotated-latitude-longitude.csv' to '/home/docs/.py-cordex'.
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:671: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  unused_keys = set(attribute.keys()) - set(inverted)
/home/docs/checkouts/readthedocs.org/user_builds/pyremo/conda/latest/lib/python3.10/site-packages/cf_xarray/accessor.py:672: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  for key, value in attribute.items():
[17]:
# crop = eur11.sel(rlon=slice(eur11_cordex.rlon.min(), eur11_cordex.rlon.max()), rlat=slice(eur11_cordex.rlat.min(), eur11_cordex.rlat.max()))
crop = eur11.sel(rlon=eur11_cordex.rlon, rlat=eur11_cordex.rlat, method="nearest")
[18]:
plot(crop.topo, pole_eur)
../_images/notebooks_domains_33_0.png
[19]:
crop
[19]:
<xarray.Dataset> Size: 4MB
Dimensions:                     (rlon: 424, rlat: 412)
Coordinates:
  * rlon                        (rlon) float64 3kB -28.38 -28.27 ... 18.05 18.16
  * rlat                        (rlat) float64 3kB -23.38 -23.27 ... 21.73 21.84
    lon                         (rlat, rlon) float64 1MB -10.06 -9.964 ... 64.96
    lat                         (rlat, rlon) float64 1MB 21.99 22.03 ... 66.69
Data variables:
    rotated_latitude_longitude  int32 4B 0
    topo                        (rlat, rlon) float32 699kB 284.0 246.0 ... 509.0
Attributes:
    CORDEX_domain:  EUR-11