Plotting with Python
This tutorial is the third part of a series that shows how to process climate model data on distributed High Performance Computing (HPC) environments with state of the art python libraries. Visit the **Part 2** and **Part 1** to see how to read and remap the data.
In this tutorial we are going to plot the data that has been processed previously. Like in any other tutorial lets import the libraries we are going to use first using the python 3 unstable kernel:
from getpass import getuser # Libaray to copy things from pathlib import Path # Object oriented libary to deal with paths from cartopy import crs as ccrs # Cartography library from matplotlib import pyplot as plt # Standard Plotting library import numpy as np # Standard array library import pandas as pd # Libary to work with labeled data frames and time series import seaborn as sns # Makes plots more beautiful import xarray as xr # Libary to work with labeled n-dimensional data and dask
In **Part 2** of this tutorial we remapped the output of global storm resolving model simulations to a regular latitude-longitude grid and save the averages over time and space to file. We are now going to read the saved files and display the content:
scratch_dir = Path('/scratch') / getuser()[0] / getuser() # Define the users scratch dir out_file = Path(scratch_dir) / 'dpp0016_PreProc.nc' time_mean = xr.open_dataset(out_file, group='time_mean').load() field_mean = xr.open_dataset(out_file, group='field_mean').load()
time_mean
<xarray.Dataset> Dimensions: (lat: 1800, lon: 3600) Coordinates: * lon (lon) float64 -179.9 -179.8 -179.8 -179.6 ... 179.8 179.9 180.0 * lat (lat) float64 -89.95 -89.85 -89.75 -89.65 ... 89.75 89.85 89.95 Data variables: ts (lat, lon) float32 221.04167 221.04166 ... 257.14673 257.14676 rsus (lat, lon) float32 55.74567 55.745674 ... 56.61574 56.615986 rlus (lat, lon) float32 136.61485 136.6148 ... 253.50243 253.50249 rlds (lat, lon) float32 108.62206 108.622185 ... 232.81358 232.81357 rsds (lat, lon) float32 69.93069 69.930695 69.9307 ... 84.0771 84.07749 hfls (lat, lon) float32 0.0656544 0.06563331 ... -6.8061843 -6.806321 hfss (lat, lon) float32 10.846811 10.845357 ... 0.60061556 0.60098815 Attributes: CDI: Climate Data Interface version 1.8.3rc (http://mpim... Conventions: CF-1.6 number_of_grid_used: 15 grid_file_uri: http://icon-downloads.mpimet.mpg.de/grids/public/mp... uuidOfHGrid: 0f1e7d66-637e-11e8-913b-51232bb4d8f9 title: ICON simulation institution: Max Planck Institute for Meteorology/Deutscher Wett... source: git@gitlab.dkrz.de:icon/icon-aes.git@b582fb87edbd30... history: /work/mh0287/k203123/GIT/icon-aes-dyw_albW/bin/icon... references: see MPIM/DWD publications comment: Sapphire Dyamond (k203123) on m21322 (Linux 2.6.32-...
field_mean
<xarray.Dataset> Dimensions: (time: 304) Coordinates: * time (time) datetime64[ns] 2020-02-01 2020-02-02 ... 2020-11-30 Data variables: ts (time) float32 286.06442 285.98172 ... 287.01483 287.09506 rsus (time) float32 35.026955 35.132553 ... 38.266792 37.940987 rlus (time) float32 387.74957 387.44562 ... 392.57364 392.88156 rlds (time) float32 335.21866 334.84085 334.0962 ... 340.49408 341.90875 rsds (time) float32 200.44205 200.92815 ... 202.39125 201.83057 hfls (time) float32 -76.36643 -77.96001 ... -89.82848 -84.05612 hfss (time) float32 -22.51513 -23.409267 ... -24.214497 -22.375736 Attributes: CDI: Climate Data Interface version 1.8.3rc (http://mpim... Conventions: CF-1.6 number_of_grid_used: 15 grid_file_uri: http://icon-downloads.mpimet.mpg.de/grids/public/mp... uuidOfHGrid: 0f1e7d66-637e-11e8-913b-51232bb4d8f9 title: ICON simulation institution: Max Planck Institute for Meteorology/Deutscher Wett... source: git@gitlab.dkrz.de:icon/icon-aes.git@b582fb87edbd30... history: /work/mh0287/k203123/GIT/icon-aes-dyw_albW/bin/icon... references: see MPIM/DWD publications comment: Sapphire Dyamond (k203123) on m21322 (Linux 2.6.32-...
xarray has a powerful plot functionality that can be used to quickly plot and inspect the data:
time_mean['ts'].plot()
These plots are not very nice but we can make them much nicer by using cartopy to draw maps. Xarray supports subplots and fiddeling with the colorbar. Let's create a nicer plot of net surface energy using the cartopy library. Net surface energy is defined as the sum of net surface radiation, latent and surface heat fluxes:
time_mean['surf_energy'] = (time_mean['rsds'] - time_mean['rsus']) \ + (time_mean['rlds'] - time_mean['rlus']) \ + (time_mean['hfls'] + time_mean['hfss'])
proj = ccrs.Mollweide(50.) # Create Mollweide projections fig = plt.figure(figsize=(12, 8)) ax = fig.add_subplot(111, projection=proj) plot = time_mean['surf_energy'].plot( ax=ax, transform=ccrs.PlateCarree(), cmap='RdYlBu_r', vmin=-120, vmax=120, cbar_kwargs={'label': 'Net Surface Energy [W/m$^2$]', 'extend': 'both', 'shrink': .8, 'orientation': 'horizontal'}, ) ax.coastlines(resolution='10m', lw=0.51) ax.set_title(f'Net Surface Energy Feb. 2020 - Nov. 2020') _ = fig.subplots_adjust(left=0.01, right=0.98, hspace=0, wspace=0, top=0.9, bottom=0.25)
Time series plots can be done in a similar fashion:
field_mean['ts'].plot()
[<matplotlib.lines.Line2D at 0x2aec3b6f5d90>]
Let's make this plot a little more pretty. The Seaborn library provides a nice interface for that:
col_blind = sns.color_palette("colorblind", 10) sns.set_style('ticks') sns.set_palette(col_blind) sns.set_context("notebook", font_scale=1., rc={"lines.linewidth": 3.5})
Now let's create two plots showing the time series and zonal averages next to each other:
fig, axs = plt.subplots(1, 2,figsize=(12, 6), sharey=False) _ = (field_mean['ts'] - 273.15).plot.line(x='time', ax=axs[0], add_legend=False) axs[0].set_ylabel('Surface Temperature [$^\\circ$C]') _ = (time_mean['ts']-273.15).mean(dim='lon').plot.line(x='lat', ax=axs[1]) axs[-1].set_ylabel('') axs[-1].set_xlabel('Latitude [$^\\circ$N]') fig.suptitle('Surface temperature Feb 2020 - Nov 2020') fig.subplots_adjust(left=0.1, right=0.99, wspace=0.2, top=.95, bottom=0.3) sns.despine()