In [ ]:
%matplotlib inline
%config InlineBackend.figure_format = "retina"
from matplotlib import rcParams
rcParams["savefig.dpi"] = 200
rcParams["font.size"] = 8
import warnings
warnings.filterwarnings("ignore")
Import regionmask and check the version:
In [ ]:
import regionmask
regionmask.__version__
Load xarray and the tutorial data:
In [ ]:
import xarray as xr
import numpy as np
In [ ]:
lon = np.arange(-179.5, 180)
lat = np.arange(-89.5, 90)
We will create a mask with the SREX regions (Seneviratne et al., 2012).
In [ ]:
regionmask.defined_regions.srex
The function mask
determines which gripoints lie within the polygon making up the each region:
In [ ]:
mask = regionmask.defined_regions.srex.mask(lon, lat)
mask
mask
is now a xarray.Dataset
with shape lat x lon
(if you need a numpy array use mask.values
). Gridpoints that do not fall in a region are NaN
, the gridpoints that fall in a region are encoded with the number of the region (here 1 to 26).
We can now plot the mask
:
In [ ]:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
f, ax = plt.subplots(subplot_kw=dict(projection=ccrs.PlateCarree()))
ax.coastlines()
mask.plot(ax=ax, transform=ccrs.PlateCarree(), add_colorbar=False);
In [ ]:
airtemps = xr.tutorial.load_dataset("air_temperature")
The example data is a temperature field over North America. Let's plot the first time step:
In [ ]:
# choose a good projection for regional maps
proj = ccrs.LambertConformal(central_longitude=-100)
ax = plt.subplot(111, projection=proj)
airtemps.isel(time=1).air.plot.pcolormesh(ax=ax, transform=ccrs.PlateCarree())
ax.coastlines();
Conviniently we can directly pass an xarray object to the mask
function. It gets the longitude and latitude from the DataArray
/ Dataset
and creates the mask
. If the longitude and latitude in the xarray object are not called "lon"
and "lat"
, respectively; you can pass their name via the lon_name
and lat_name
keyword.
In [ ]:
mask = regionmask.defined_regions.srex.mask(airtemps)
In [ ]:
lon = airtemps.lon.values
print("Grid extent: {:3.0f}°E to {:3.0f}°E".format(lon.min(), lon.max()))
bounds = regionmask.defined_regions.srex.bounds_global
print("Region extent: {:3.0f}°E to {:3.0f}°E".format(bounds[0], bounds[2]))
Let's plot the mask of the regions:
In [ ]:
proj = ccrs.LambertConformal(central_longitude=-100)
ax = plt.subplot(111, projection=proj)
low = mask.min()
high = mask.max()
levels = np.arange(low - 0.5, high + 1)
h = mask.plot.pcolormesh(
ax=ax, transform=ccrs.PlateCarree(), levels=levels, add_colorbar=False
)
# for colorbar: find abbreviations of all regions that were selected
reg = np.unique(mask.values)
reg = reg[~np.isnan(reg)]
abbrevs = regionmask.defined_regions.srex[reg].abbrevs
cbar = plt.colorbar(h, orientation="horizontal", fraction=0.075, pad=0.05)
cbar.set_ticks(reg)
cbar.set_ticklabels(abbrevs)
cbar.set_label("Region")
ax.coastlines()
# fine tune the extent
ax.set_extent([200, 330, 10, 75], crs=ccrs.PlateCarree())
We want to select the region 'Central North America'. Thus we first need to find out which number this is:
In [ ]:
CNA_index = regionmask.defined_regions.srex.map_keys("C. North America")
CNA_index
xarray
provides the handy where
function:
In [ ]:
airtemps_CNA = airtemps.where(mask == CNA_index)
Check everything went well by repeating the first plot with the selected region:
In [ ]:
# choose a good projection for regional maps
proj = ccrs.LambertConformal(central_longitude=-100)
ax = plt.subplot(111, projection=proj)
regionmask.defined_regions.srex[["CNA"]].plot(ax=ax, add_label=False)
airtemps_CNA.isel(time=1).air.plot.pcolormesh(ax=ax, transform=ccrs.PlateCarree())
ax.coastlines();
In [ ]:
weights = np.cos(np.deg2rad(airtemps.lat))
ts_airtemps_CNA = airtemps_CNA.weighted(weights).mean(dim=("lat", "lon")) - 273.15
We plot the resulting time series:
In [ ]:
f, ax = plt.subplots()
ts_airtemps_CNA.air.plot.line(ax=ax, label="Central North America")
ax.axhline(0, color="0.1", lw=0.5)
plt.legend();
In [ ]:
# you can group over all integer values of the mask
airtemps_all = airtemps.groupby(mask).mean()
airtemps_all
Regionmask can also handle mutltidimensional longitude/ latitude grids (e.g. from a regional climate model). As xarray provides such an example dataset, we will use it to illustrate it. See also in the xarray documentation.
Load the tutorial data:
In [ ]:
rasm = xr.tutorial.load_dataset("rasm")
The example data is a temperature field over the Northern Hemisphere. Let's plot the first time step:
In [ ]:
# choose a projection
proj = ccrs.NorthPolarStereo()
ax = plt.subplot(111, projection=proj)
ax.set_global()
rasm.isel(time=1).Tair.plot.pcolormesh(
ax=ax, x="xc", y="yc", transform=ccrs.PlateCarree()
)
# add the abbreviation of the regions
regionmask.defined_regions.srex.plot(
ax=ax, regions=[1, 2, 11, 12, 18], coastlines=False, label="abbrev"
)
ax.set_extent([-180, 180, 43, 90], ccrs.PlateCarree())
ax.coastlines();
Again we pass the xarray object to regionmask. We have to specify "xc"
and "yc"
as the longitude and latitude coordinates of the array:
In [ ]:
mask = regionmask.defined_regions.srex.mask(rasm, lon_name="xc", lat_name="yc")
mask
In [ ]:
rasm_NAS = rasm.where(mask == regionmask.defined_regions.srex.map_keys("NAS"))
Check everything went well by repeating the first plot with the selected region:
In [ ]:
# choose a projection
proj = ccrs.NorthPolarStereo()
ax = plt.subplot(111, projection=proj)
ax.set_global()
rasm_NAS.isel(time=1).Tair.plot.pcolormesh(
ax=ax, x="xc", y="yc", transform=ccrs.PlateCarree()
)
# add the abbreviation of the regions
regionmask.defined_regions.srex.plot(
ax=ax, regions=["NAS"], coastlines=False, label="abbrev"
)
ax.set_extent([-180, 180, 45, 90], ccrs.PlateCarree())
ax.coastlines();
In [ ]: