Multiple plots#
Figanos also creates xr.plot.facetgrid.FacetGrid due to being wrapped around xarray plotting functions. This allows for multiple plots to be created at once. The following example shows how to create multiple timeseries and maps plots.
[1]:
# import necessary libraries
import xarray as xr
import cartopy.crs as ccrs
import figanos.matplotlib as fg
import numpy as np
# use ouranos style
fg.utils.set_mpl_style('ouranos')
ERROR 1: PROJ: proj_create_from_database: Open of /home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/share/proj failed
Timeseries#
[2]:
# create xarray object from a NetCDF
url = 'https://pavics.ouranos.ca//twitcher/ows/proxy/thredds/dodsC/birdhouse/disk2/cccs_portal/indices/Final/BCCAQv2_CMIP6/tx_max/YS/ssp585/ensemble_percentiles/tx_max_ann_BCCAQ2v2+ANUSPLIN300_historical+ssp585_1950-2100_30ymean_percentiles.nc'
opened = xr.open_dataset(url, decode_timedelta=False)
[3]:
ds_time = opened.isel(lon=[500], lat=[150, 250])
im = fg.timeseries({'p50': ds_time.tx_max_p50, 'p90': ds_time.tx_max_p90},
plot_kw={'p50': {"col": "lat"}, 'p90': {"col": "lat"}},
fig_kw={'figsize':(10,4)},
legend="edge",
show_lat_lon=True)
[4]:
#creating fake scenarios
ds_time = ds_time[['tx_max_p10', 'tx_max_p50', 'tx_max_p90']]
data = {'tasmax_ssp434': ds_time,
'tasmax_ssp245': ds_time.copy()-10,
'tasmax_ssp585': ds_time.copy()+10}
fg.timeseries(data=data,
legend='facetgrid',
show_lat_lon=False,
fig_kw = {'figsize':(9,4)},
plot_kw={'tasmax_ssp434': {"col": "lat"}, 'tasmax_ssp245': {"col": "lat"}, "tasmax_ssp585": {"col": "lat"}}
)
[4]:
<xarray.plot.facetgrid.FacetGrid at 0x7f3fbb02e550>
Maps#
Create multiple maps plot with figanos wrapped around xr.plot.facetgrid.FacetGrid by passing the key row row
and col
in the argument plot_kw
.
[5]:
#Selecting a time and slicing our starting Dataset
ds_space = opened[['tx_max_p50']].isel(time=[0, 1, 2]).sel(lat=slice(40,65), lon=slice(-90,-55))
# defining our projection.
projection = ccrs.LambertConformal()
im = fg.gridmap(ds_space,
projection = projection,
plot_kw = {"col": "time"},
features = ['coastline','ocean'],
frame = False,
use_attrs={"suptitle": "description"},
)
[6]:
names = ['station_' + str(i) for i in np.arange(5)]
lat = 45 + np.random.rand(5)*3
lon = np.linspace(-76,-70, 5)
tas = np.array([[20, 25, 30, 15, 5], [5, 0, 10, 2, 3]])
yrs = np.array([[35, 65, 45, 25, 95],
[15, 75, 10, 15, 50]])
attrs = {'units': 'degC', 'standard_name': 'air_temperature', 'long_name': 'Near-Surface Daily Maximum Air Temperature'}
tas = xr.DataArray(data=tas,
coords={'season': ['DFJ', 'MAM'],
'station': names,
'lat':('station', lat),
'lon': ('station', lon),
'years': (('season', 'station'), yrs),
},
dims=['season', 'station'],
attrs=attrs)
obs = xr.Dataset({'tas': tas})
# plot
fg.scattermap(obs,
transform=ccrs.PlateCarree(),
sizes='years',
size_range=(25, 100),
plot_kw={
"xlim": (-77,-69),
"ylim":(43,50),
"col": "season",
},
features={
"land": {"color": "#f0f0f0"},
"rivers": {"edgecolor": "#cfd3d4"},
"lakes": {"facecolor": "#cfd3d4"},
"coastline": {"edgecolor": "black"},
},
fig_kw={"figsize": (7, 4)},
legend_kw={
'ncol':4,
'bbox_to_anchor':(0.15, 0.05)
},
)
[6]:
<xarray.plot.facetgrid.FacetGrid at 0x7f3fbb1f9850>
[7]:
from xclim import ensembles
sup_305k = ds_space.where(ds_space.tx_max_p50>305)
inf_300k = ds_space.where(ds_space.tx_max_p50<300)
im = fg.hatchmap({'sup_305k': sup_305k, 'inf_300k': inf_300k},
plot_kw={
'sup_305k': {
'hatches': '*',
'col': 'time',
"x": "lon",
"y": "lat"
},
'inf_300k': {
'hatches': 'x',
'col': 'time',
"x": "lon",
"y": "lat"
},
},
features = ['coastline','ocean'],
frame = True,
legend_kw = {'title': 'Ensemble change'})
im.fig.suptitle("Multiple hatchmaps", y=1.08)
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/figanos/matplotlib/plot.py:2193: UserWarning: Only first variable of Dataset is plotted.
warnings.warn("Only first variable of Dataset is plotted.")
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/figanos/matplotlib/utils.py:223: UserWarning: Attribute "long_name" not found.
warnings.warn(f'Attribute "{string}" not found.')
[7]:
Text(0.5, 1.08, 'Multiple hatchmaps')
Plot over each other#
To overlay two facetgrids plots, you can create the first facetgrid with col
or row
and then loop through the ax
of the first facetgrid and the xr.object
to plot the second facetgrid.
[8]:
names = ['station_' + str(i) for i in np.arange(5)]
lat = 45 + np.random.rand(5)*3
lon = np.linspace(-76,-70, 5)
tas = np.array([[290, 300, 295, 305, 301],
[275, 285, 277, 301, 345],
[302, 293, 295, 292, 280]])
attrs = {'units': 'degK', 'standard_name': 'air_temperature', 'long_name': ds_space.tx_max_p50.attrs['description']}
tas = xr.DataArray(data=tas,
coords={'time': ds_space.time.values,
'station': names,
'lat':('station', lat),
'lon': ('station', lon),
},
dims=['time', 'station'],
attrs=attrs)
obs2 = xr.Dataset({'tas': tas})
[9]:
vmin=280
vmax=310
ds_space = opened[['tx_max_p50']].isel(time=[0, 1, 2]).sel(lat=slice(40,65), lon=slice(-90,-55))
im = fg.gridmap(ds_space,
projection = projection,
plot_kw = {"col": "time",
"xlim": (-77,-69),
"ylim": (43,50),
"vmin": vmin, "vmax": vmax,
},
features = ['coastline','ocean'],
frame = False,
use_attrs={"suptitle": "description"}
)
for i, fax in enumerate(im.axs.flat):
fg.scattermap(obs2.isel(time=i),
ax=fax,
transform=ccrs.PlateCarree(),
plot_kw={'x':'lon',
'y':'lat',
'vmin': vmin,
'vmax': vmax,
'edgecolor':'grey',
'add_colorbar': False},
show_time=False
)
im.fig.suptitle('Scattermaps over gridmaps', x=0.45, y=0.95)
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/figanos/matplotlib/utils.py:223: UserWarning: Attribute "description" not found.
warnings.warn(f'Attribute "{string}" not found.')
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/figanos/matplotlib/utils.py:223: UserWarning: Attribute "description" not found.
warnings.warn(f'Attribute "{string}" not found.')
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/figanos/matplotlib/utils.py:223: UserWarning: Attribute "description" not found.
warnings.warn(f'Attribute "{string}" not found.')
[9]:
Text(0.45, 0.95, 'Scattermaps over gridmaps')
Limitations#
When the argument col_wrap
is used for a facetgrid whose number of plots is not a multiple of col_wrap
, no plot will be shown (see issue). set_extend
needs to be passed to every axis in the facetgrid to avoid this issue.
[10]:
#Selecting a time and slicing our starting Dataset
ds_space = opened[['tx_max_p50']].isel(time=[0, 1, 2]).sel(lat=slice(40,65), lon=slice(-90,-55))
im = fg.gridmap(ds_space,
projection = ccrs.LambertConformal(),
plot_kw = {"col": "time",
"col_wrap": 2},
features = ['coastline','ocean'],
frame = False,
use_attrs={"suptitle": "long_name"},
fig_kw = {"figsize": (6, 6)}
)
for i, fax in enumerate(im.axs.flat):
fax.set_extent([
ds_space.lon.min().item(),
ds_space.lon.max().item(),
ds_space.lat.min().item(),
ds_space.lat.max().item(),
]
)
Xarray plots by default facetgrid ylabels to the right (next to the colorbar). The example below shows how to move the xlabels to the left.
[11]:
import numpy as np
op = opened.isel(time=[0, 1])
data = xr.DataArray(
data=np.array([op.tx_max_p10.values, op.tx_max_p50.values, op.tx_max_p90.values]),
dims=['percentile', 'time', 'lat', 'lon'],
coords={'percentile': [10, 50, 90], 'time': op.time.values, 'lat': op.lat.values, 'lon': op.lon.values},
attrs = {'units': 'degC', 'standard_name': 'air_temperature', 'long_name': 'Near-Surface Daily Maximum Air Temperature'}
)
im = fg.gridmap(data,
projection = ccrs.LambertConformal(),
plot_kw = {"col": "time",
"row": "percentile",
},
features = ['coastline','ocean'],
frame = False,
use_attrs = {"suptitle": "long_name"},
fig_kw = {"figsize": (8, 7)},
)
# modify xlabels positions (hardcoded in xarray.plot)
for i, fax in enumerate(im.axs.flat):
for txt in fax.texts:
if len(txt.get_text()) > 0:
txt.set_x(-1.2)
txt.set_text('percentile ' + txt.get_text())
txt.set_rotation('vertical')
# txt.set_visible(False)
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/figanos/matplotlib/utils.py:862: UserWarning: Colormap warning: Variable group not found. Use the cmap argument.
warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_ocean.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)
/home/docs/checkouts/readthedocs.org/user_builds/figanos/conda/latest/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)