Regridding datasets#

Options:

import os
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import rasterio as rio
import xarray as xr
import xesmf as xe
import climag.climag as cplt
def plot_map(data, var, x, y, transform, cmap="Spectral_r", contour=False):
    """
    Helper function for plotting maps
    """

    plt.figure(figsize=(9, 7))
    ax = plt.axes(projection=cplt.projection_hiresireland)
    if contour:
        data.isel(time=180)[var].plot.contourf(
            ax=ax,
            x=x,
            y=y,
            levels=10,
            robust=True,
            transform=transform,
            cmap=cmap,
        )
    else:
        data.isel(time=180)[var].plot(
            ax=ax,
            x=x,
            y=y,
            levels=10,
            robust=True,
            transform=transform,
            cmap=cmap,
        )
    ax.gridlines(
        draw_labels=dict(bottom="x", left="y"),
        color="lightslategrey",
        linewidth=0.5,
        x_inline=False,
        y_inline=False,
    )
    ax.coastlines(resolution="10m", color="darkslategrey", linewidth=0.75)
    ax.set_title(str(data.isel(time=180)["time"].values))
    plt.tight_layout()
    plt.show()

Higher resolution observational dataset - MERA#

obs = os.path.join(
    "data", "ModVege", "MERA", "modvege_IE_MERA_FC3hr_3_day_1989.nc"
)
obs = xr.open_dataset(obs, decode_coords="all")
# reassign projection
obs.rio.write_crs(cplt.projection_lambert_conformal, inplace=True)
<xarray.Dataset>
Dimensions:            (x: 158, y: 166, time: 365)
Coordinates:
  * x                  (x) float64 4.15e+05 4.175e+05 ... 8.05e+05 8.075e+05
  * y                  (y) float64 4.075e+05 4.1e+05 ... 8.175e+05 8.2e+05
    height             float64 ...
    Lambert_Conformal  int64 ...
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    spatial_ref        int64 0
Data variables: (12/24)
    bm_gv              (time, y, x) float32 ...
    bm_gr              (time, y, x) float32 ...
    bm_dv              (time, y, x) float32 ...
    bm_dr              (time, y, x) float32 ...
    age_gv             (time, y, x) float32 ...
    age_gr             (time, y, x) float32 ...
    ...                 ...
    sen_gv             (time, y, x) float32 ...
    sen_gr             (time, y, x) float32 ...
    abs_dv             (time, y, x) float32 ...
    abs_dr             (time, y, x) float32 ...
    omd_gv             (time, y, x) float32 ...
    omd_gr             (time, y, x) float32 ...
Attributes:
    creation_date:  2023-03-26 08:56:21.004015+00:00
    contact:        nstreethran@ucc.ie
    frequency:      day
    references:     https://github.com/ClimAg
    input_dataset:  IE_MERA_FC3hr_3_day
plot_map(obs, "gro", "x", "y", cplt.projection_lambert_conformal, "BrBG")
../_images/e558f931ca12d0c8865e284ba4c8a9672543469156e33f7fc17bb656aceb7e18.png

Lower resolution climate model dataset - EURO-CORDEX#

clim = os.path.join(
    "data",
    "ModVege",
    "EURO-CORDEX",
    "historical",
    "EC-EARTH",
    "modvege_IE_EURO-CORDEX_RCA4_EC-EARTH_historical_1989.nc",
)
clim = xr.open_dataset(clim, decode_coords="all")
clim
<xarray.Dataset>
Dimensions:       (rlat: 33, rlon: 37, time: 365, bnds: 2)
Coordinates:
    lat           (rlat, rlon) float64 ...
    lon           (rlat, rlon) float64 ...
  * rlat          (rlat) float64 3.685 3.795 3.905 4.015 ... 6.985 7.095 7.205
  * rlon          (rlon) float64 -17.27 -17.16 -17.05 ... -13.53 -13.41 -13.3
  * time          (time) datetime64[ns] 1989-01-01T12:00:00 ... 1989-12-31T12...
    height        float64 ...
    rotated_pole  |S1 ...
    time_bnds     (time, bnds) datetime64[ns] ...
    spatial_ref   int64 ...
Dimensions without coordinates: bnds
Data variables: (12/24)
    bm_gv         (time, rlat, rlon) float32 ...
    bm_gr         (time, rlat, rlon) float32 ...
    bm_dv         (time, rlat, rlon) float32 ...
    bm_dr         (time, rlat, rlon) float32 ...
    age_gv        (time, rlat, rlon) float32 ...
    age_gr        (time, rlat, rlon) float32 ...
    ...            ...
    sen_gv        (time, rlat, rlon) float32 ...
    sen_gr        (time, rlat, rlon) float32 ...
    abs_dv        (time, rlat, rlon) float32 ...
    abs_dr        (time, rlat, rlon) float32 ...
    omd_gv        (time, rlat, rlon) float32 ...
    omd_gr        (time, rlat, rlon) float32 ...
Attributes:
    creation_date:  2023-03-11 01:33:28.094139+00:00
    contact:        nstreethran@ucc.ie
    frequency:      day
    references:     https://github.com/ClimAg
    input_dataset:  IE_EURO-CORDEX_RCA4_EC-EARTH_historical
plot_map(clim, "gro", "rlon", "rlat", cplt.projection_eurocordex, "BrBG")
../_images/9458bbe0f49666f64b296267c72d15320be4bd9617b044cb09db2dd23860e02a.png

xESMF’s Regridder#

# drop unnecessary coordinates and normalise to keep only date in time
clim2 = clim.drop(["lat", "lon", "time_bnds"])
clim2["time"] = clim2.indexes["time"].normalize()
# reproject to lat/lon degrees
obs2 = obs.rio.reproject(ccrs.PlateCarree())
clim2 = clim2.rio.reproject(ccrs.PlateCarree())
# rename dims
obs2 = obs2.rename({"x": "lon", "y": "lat"})
clim2 = clim2.rename({"x": "lon", "y": "lat"})
obs2
<xarray.Dataset>
Dimensions:            (lon: 211, lat: 130, time: 365)
Coordinates:
  * lon                (lon) float64 -11.79 -11.75 -11.72 ... -4.839 -4.806
  * lat                (lat) float64 55.58 55.55 55.51 ... 51.36 51.32 51.29
    Lambert_Conformal  int64 0
    height             float64 0.0
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    spatial_ref        int64 0
Data variables: (12/24)
    bm_gv              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_gr              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_dv              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_dr              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    age_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    age_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    ...                 ...
    sen_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    sen_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    abs_dv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    abs_dr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    omd_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    omd_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
Attributes:
    creation_date:  2023-03-26 08:56:21.004015+00:00
    contact:        nstreethran@ucc.ie
    frequency:      day
    references:     https://github.com/ClimAg
    input_dataset:  IE_MERA_FC3hr_3_day
clim2
<xarray.Dataset>
Dimensions:       (lon: 48, lat: 27, time: 365)
Coordinates:
  * lon           (lon) float64 -12.41 -12.24 -12.06 ... -4.5 -4.324 -4.148
  * lat           (lat) float64 55.77 55.6 55.42 55.25 ... 51.55 51.38 51.2
    height        float64 2.0
    rotated_pole  |S1 b''
  * time          (time) datetime64[ns] 1989-01-01 1989-01-02 ... 1989-12-31
    spatial_ref   int64 0
Data variables: (12/24)
    bm_gv         (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    bm_gr         (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    bm_dv         (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    bm_dr         (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    age_gv        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    age_gr        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    ...            ...
    sen_gv        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    sen_gr        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    abs_dv        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    abs_dr        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    omd_gv        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
    omd_gr        (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
Attributes:
    creation_date:  2023-03-11 01:33:28.094139+00:00
    contact:        nstreethran@ucc.ie
    frequency:      day
    references:     https://github.com/ClimAg
    input_dataset:  IE_EURO-CORDEX_RCA4_EC-EARTH_historical
plot_map(obs2, "gro", "lon", "lat", ccrs.PlateCarree(), "BrBG")
../_images/de8e536bb0730281ce7cb8ae6c94d50e55b395bd634d803b5d377f7edfdda7b3.png
plot_map(clim2, "gro", "lon", "lat", ccrs.PlateCarree(), "BrBG")
../_images/e446f0b7fe396164aa8bd0ff9142511af9e371ac3d000623299b3f6fc1177bda.png
regridder = xe.Regridder(clim2, obs2, "bilinear")
regridder
xESMF Regridder 
Regridding algorithm:       bilinear 
Weight filename:            bilinear_27x48_130x211.nc 
Reuse pre-computed weights? False 
Input grid shape:           (27, 48) 
Output grid shape:          (130, 211) 
Periodic in longitude?      False
clim2 = regridder(clim2)
clim2
<xarray.Dataset>
Dimensions:            (time: 365, lat: 130, lon: 211)
Coordinates:
    height             float64 0.0
    rotated_pole       |S1 b''
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    spatial_ref        int64 0
    Lambert_Conformal  int64 0
  * lon                (lon) float64 -11.79 -11.75 -11.72 ... -4.839 -4.806
  * lat                (lat) float64 55.58 55.55 55.51 ... 51.36 51.32 51.29
Data variables: (12/24)
    bm_gv              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_gr              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_dv              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_dr              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    age_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    age_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    ...                 ...
    sen_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    sen_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    abs_dv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    abs_dr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    omd_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    omd_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
Attributes:
    regrid_method:  bilinear
plot_map(clim2, "gro", "lon", "lat", ccrs.PlateCarree(), "BrBG")
../_images/818a59bcda1e778ac5ce31ab733b74fd04cd2f4e92d7bb647d4d44c5318464bb.png

Difference#

diff = clim2 - obs2
diff
<xarray.Dataset>
Dimensions:            (time: 365, lon: 211, lat: 130)
Coordinates:
    height             float64 0.0
    rotated_pole       |S1 b''
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    spatial_ref        int64 0
    Lambert_Conformal  int64 0
  * lon                (lon) float64 -11.79 -11.75 -11.72 ... -4.839 -4.806
  * lat                (lat) float64 55.58 55.55 55.51 ... 51.36 51.32 51.29
Data variables: (12/24)
    bm_gv              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_gr              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_dv              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    bm_dr              (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    age_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    age_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    ...                 ...
    sen_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    sen_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    abs_dv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    abs_dr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    omd_gv             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
    omd_gr             (time, lat, lon) float32 nan nan nan nan ... nan nan nan
plot_map(diff, "gro", "lon", "lat", ccrs.PlateCarree(), "RdBu_r")
../_images/eddda9715835745b5cec341447f2815433702923d244ff9323de7b5f4c42901f.png
plot_map(diff, "gro", "lon", "lat", ccrs.PlateCarree(), "RdBu_r", contour=True)
../_images/771eb1ce35a3fb214019d4fdef1e135195e91bbdcc62ebd295b3b017d789cfab.png

Xarray’s interp_like#

# drop unnecessary coordinates and normalise to keep only date in time
clim2 = clim.drop(["lat", "lon", "time_bnds"])
clim2["time"] = clim2.indexes["time"].normalize()

# reproject to observational data's CRS
clim2 = clim2.rio.reproject(cplt.projection_lambert_conformal)
# interpolate
clim2 = clim2.interp_like(obs)
clim2
<xarray.Dataset>
Dimensions:       (time: 365, y: 166, x: 158)
Coordinates:
    height        float64 2.0
    rotated_pole  |S1 b''
    spatial_ref   int64 0
  * x             (x) float64 4.15e+05 4.175e+05 4.2e+05 ... 8.05e+05 8.075e+05
  * y             (y) float64 4.075e+05 4.1e+05 4.125e+05 ... 8.175e+05 8.2e+05
  * time          (time) datetime64[ns] 1989-01-01 1989-01-02 ... 1989-12-31
Data variables: (12/24)
    bm_gv         (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    bm_gr         (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    bm_dv         (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    bm_dr         (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    age_gv        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    age_gr        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    ...            ...
    sen_gv        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    sen_gr        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    abs_dv        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    abs_dr        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    omd_gv        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
    omd_gr        (time, y, x) float64 nan nan nan nan nan ... nan nan nan nan
Attributes:
    creation_date:  2023-03-11 01:33:28.094139+00:00
    contact:        nstreethran@ucc.ie
    frequency:      day
    references:     https://github.com/ClimAg
    input_dataset:  IE_EURO-CORDEX_RCA4_EC-EARTH_historical
plot_map(clim2, "gro", "x", "y", cplt.projection_lambert_conformal, "BrBG")
../_images/58ba2d4c3b67566db9a69c94ad1ae85a2ebd0cf9911a6e2aa0ef9e035ce18264.png

Difference#

diff = clim2 - obs
diff
<xarray.Dataset>
Dimensions:            (x: 158, y: 166, time: 365)
Coordinates:
    rotated_pole       |S1 b''
    spatial_ref        int64 0
  * x                  (x) float64 4.15e+05 4.175e+05 ... 8.05e+05 8.075e+05
  * y                  (y) float64 4.075e+05 4.1e+05 ... 8.175e+05 8.2e+05
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    Lambert_Conformal  int64 0
Data variables: (12/24)
    bm_gv              (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    bm_gr              (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    bm_dv              (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    bm_dr              (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    age_gv             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    age_gr             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    ...                 ...
    sen_gv             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    sen_gr             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    abs_dv             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    abs_dr             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    omd_gv             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
    omd_gr             (time, y, x) float64 nan nan nan nan ... nan nan nan nan
plot_map(diff, "gro", "x", "y", cplt.projection_lambert_conformal, "RdBu_r")
../_images/94c2a411395554cfa65e0fc0f6afa2f57060eccc70c6a8966c51ef4d024a5ef7.png
plot_map(
    diff,
    "gro",
    "x",
    "y",
    cplt.projection_lambert_conformal,
    "RdBu_r",
    contour=True,
)
../_images/8c5d9f5053cef2500f59ed5b5ee68be379722b0b6711b2016d97c613206b3a30.png

Rioxarray’s reproject_match#

# drop unnecessary coordinates and normalise to keep only date in time
clim2 = clim.drop(["lat", "lon", "time_bnds"])
clim2["time"] = clim2.indexes["time"].normalize()

clim2 = clim2.rename({"rlon": "x", "rlat": "y"})
clim2 = clim2.rio.reproject_match(
    obs, resampling=rio.enums.Resampling.bilinear
)
clim2 = clim2.assign_coords({"x": obs["x"], "y": obs["y"]})
clim2
<xarray.Dataset>
Dimensions:            (x: 158, y: 166, time: 365)
Coordinates:
  * x                  (x) float64 4.15e+05 4.175e+05 ... 8.05e+05 8.075e+05
  * y                  (y) float64 4.075e+05 4.1e+05 ... 8.175e+05 8.2e+05
    rotated_pole       |S1 b''
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    height             float64 0.0
    spatial_ref        int64 0
    Lambert_Conformal  int64 0
Data variables: (12/24)
    bm_gv              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    bm_gr              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    bm_dv              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    bm_dr              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    age_gv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    age_gr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    ...                 ...
    sen_gv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    sen_gr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    abs_dv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    abs_dr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    omd_gv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    omd_gr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
Attributes:
    creation_date:  2023-03-11 01:33:28.094139+00:00
    contact:        nstreethran@ucc.ie
    frequency:      day
    references:     https://github.com/ClimAg
    input_dataset:  IE_EURO-CORDEX_RCA4_EC-EARTH_historical
plot_map(clim2, "gro", "x", "y", cplt.projection_lambert_conformal, "BrBG")
../_images/9138ec8209f0a639100c4d75e750ccd89e24e2dea6ca5b4a6a6430495780f436.png

Difference#

diff = clim2 - obs
diff
<xarray.Dataset>
Dimensions:            (x: 158, y: 166, time: 365)
Coordinates:
  * x                  (x) float64 4.15e+05 4.175e+05 ... 8.05e+05 8.075e+05
  * y                  (y) float64 4.075e+05 4.1e+05 ... 8.175e+05 8.2e+05
    rotated_pole       |S1 b''
  * time               (time) datetime64[ns] 1989-01-01 ... 1989-12-31
    height             float64 0.0
    spatial_ref        int64 0
    Lambert_Conformal  int64 0
Data variables: (12/24)
    bm_gv              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    bm_gr              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    bm_dv              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    bm_dr              (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    age_gv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    age_gr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    ...                 ...
    sen_gv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    sen_gr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    abs_dv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    abs_dr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    omd_gv             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
    omd_gr             (time, y, x) float32 nan nan nan nan ... nan nan nan nan
plot_map(diff, "gro", "x", "y", cplt.projection_lambert_conformal, "RdBu_r")
../_images/1f8dcb897de0e88a2dd166050926876139314ba713c90f310161f2f6688651d5.png
plot_map(
    diff,
    "gro",
    "x",
    "y",
    cplt.projection_lambert_conformal,
    "RdBu_r",
    contour=True,
)
../_images/18789bf7235e2218e9b90c328199743a8c8aa4d8ac0cd498933e8a2f65f334a1.png