How-to: plots
module¶
glm-py's plots
module provides a series of classes for reading and plotting
GLM's various output files. They are:
LakePlotter
for plottinglake.csv
WQPlotter
for plotting the depth-specificWQ_*.csv
filesNCPlotter
for plottingoutput.nc
Each class has one or more methods, prefixed with plot_
, for creating
common GLM visualisations with Matplotlib. These methods implement the
following recommended signature function for wrapping the Matplotlib
library:
def my_plotter(ax, data, param_dict):
"""
A helper function to make a graph.
"""
out = ax.plot(data, **param_dict)
return out
Here, the parameter ax
is a matplotlib Axes
object, data
is the data to
plot, and param_dict
is a dictionary of keyword arguments that configure the
wrapped plot
method. This approach leaves the figure and axes creation to the
user and avoids adding unnecessary complexity to the wrapping function. See
example use below:
import numpy as np
import matplotlib.pyplot as plt
# Creates two arrays of random data
data1, data2 = np.random.randn(2, 25)
# Creates two subplots and returns the `Axes` object and the `Figure` object
fig, axs = plt.subplots(1, 2, figsize=(10, 2.7))
# Plots data1 to the first axes with 'x' markers
my_plotter(axs[0], data1, {'marker': 'x'})
# Plots data2 to the second axes with 'o' markers
my_plotter(axs[1], data2, {'marker': 'o'})
glm-py's plot_
methods do not have a data
parameter as reading the data
from file, and processing it, are handled by the class. Instead, some
methods require the user to provide a variable name to plot.
The plots
module aims to make as few opinionated plotting decisions for the
user as possible. Users seeking to further customise plots beyond using the
param_dict
parameter should refer to the
Matplotlib object-based API.
Plotting lake.csv
with LakePlotter
¶
Initialising LakePlotter
¶
LakePlotter
must be initialised with a path to a lake.csv
file:
The lake_csv_path
attribute can be changed at any time to read and plot a
separate lake.csv
file:
Lake plots¶
The LakePlotter
class provides the following methods for plotting the
lake.csv
file:
plot_temp()
- line plot of minimum and maximum lake temperature.plot_volume()
- line plot of lake volume.plot_surface_temp()
- line plot of lake surface temperature.plot_surface_area()
- line plot of lake surface area.plot_surface_height()
- line plot of lake surface height.plot_water_balance()
- line plot of lake water balance.plot_water_balance_comps()
- line plot of lake water balance components.plot_heat_balance_comps()
- line plot of lake heat balance components.
To make a plot, initialise LakePlotter
and create the Matplotlib Figure
(fig
) and Axes
(ax
) objects:
import matplotlib.pyplot as plt
from glmpy import plots
lake = plots.LakePlotter("sparkling_lake/output/lake.csv")
fig, ax = plt.subplots(figsize=(10, 5))
Next, call one of the plot_
methods and provide the Axes
object to plot
on. Here, a timeseries of the lake volume is plotted with plot_volume()
and
saved as a PNG:
LakePlotter
's plotting methods are easily customisable. The param_dict
parameter is used to pass a dictionary of keyword arguments to Matplotlib's
plot()
method. Further customisation can be achieved using the various getter
and setter methods of the Figure
and Axes
objects. Below, the lake water
balance is plotted with plot_water_balance()
. To customise the plot, the
line colour is changed with param_dict
parameter and a setter method is
called on the Axes
object to change the tick label formatter:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from glmpy import plots
lake = plots.LakePlotter("sparkling_lake/output/lake.csv")
# Create a new date formatter
date_formatter = mdates.DateFormatter("%b %Y")
fig, ax = plt.subplots(figsize=(10, 5))
# Change the line colour
lake.plot_water_balance(ax=ax, param_dict={"color": "tomato"})
# Set the new date formatter
ax.xaxis.set_major_formatter(date_formatter)
fig.savefig("water_balance.png")
LakePlotter
's plot_temp()
, plot_heat_balance_comps()
, and
plot_water_balance_comps()
methods plot two or more lines to an Axes
object. In order to customise each line (i.e., each call to Matplotlib's
plot()
method), multiple param_dict
parameters have been provided.
Plotting output.nc
with NCPlotter
¶
Initialising NCPlotter
¶
NCPlotter
must be initialised with a path to a GLM output NetCDF file.
The glm_nc_path
attribute can be changed at any time to read and plot a
separate NetCDF files:
Profile plots¶
NCPlotter
's plot_profile()
method plots a variable from the NetCDF for all
depth and timesteps. The example below plots temperature ("temp"
in the
NetCDF file) and saves the output as a PNG:
import matplotlib.pyplot as plt
from glmpy import plots
nc = plots.NCPlotter("sparkling_lake/output/output.nc")
fig, ax = plt.subplots(figsize=(10, 5))
nc.plot_profile(ax=ax, var_name="temp")
fig.savefig("temp.png")
To add a colour bar, the AxesImage
object returned by plot_profile()
can
be passed to the colorbar()
method of the Figure
object:
import matplotlib.pyplot as plt
from glmpy import plots
nc = plots.NCPlotter("sparkling_lake/output/output.nc")
fig, ax = plt.subplots(figsize=(10, 5))
out = nc.plot_profile(ax=ax, var_name="temp") # returns an instance of AxesImage
col_bar = fig.colorbar(out)
col_bar.set_label("Temperature (°C)")
fig.savefig("temp.png")
By default, plot_profile
will measure the lake depth from the bottom
(reference="bottom"
). To reference lake depth from the surface, set the
reference
to "surface"
:
import matplotlib.pyplot as plt
from glmpy import plots
nc = plots.NCPlotter("sparkling_lake/output/output.nc")
fig, ax = plt.subplots(figsize=(10, 5))
out = nc.plot_profile(ax=ax, var_name="temp", reference="surface")
col_bar = fig.colorbar(out)
col_bar.set_label("Temperature (°C)")
fig.savefig("temp.png")
plot_profile()
wraps matplotlib's imshow()
method. Just like the methods
of LakePlotter
, you can customise how plot_profile)_
plots by passing a
dictionary of imshow()
parameters to the param_dict
parameter. Here, a
profile plot of the lake salinity ("salt"
) is created with the colour map
changed to "viridis"
:
import matplotlib.pyplot as plt
from glmpy import plots
nc = plots.NCPlotter("sparkling_lake/output/output.nc")
fig, ax = plt.subplots(figsize=(10, 5))
params = {"cmap": "viridis"}
out = nc.plot_profile(ax=ax, var_name="salt", param_dict=params)
col_bar = fig.colorbar(out)
col_bar.set_label("Salinity (g/kg)")
fig.savefig("salt.png")
NCPlotter
provides a number of getter methods can assist when making plots
with profile_plot()
:
get_profile_var_names()
returns a list of variable names plottable withplot_profile()
.get_long_name()
returns the long name description of a variable.get_units()
returns the units of a variable.get_start_datetime()
returns the simulation start time.
from glmpy import plots
nc = plots.NCPlotter("sparkling_lake/output/output.nc")
vars = nc.get_profile_var_names()
print(vars)
These methods are useful automating the creation of profile plots:
import matplotlib.pyplot as plt
from glmpy import plots
nc = plots.NCPlotter("sparkling_lake/output/output.nc")
vars = nc.get_profile_var_names()
plot_vars = vars[3:5]
fig, axs = plt.subplots(nrows=2, ncols=1, figsize=(10, 10))
for idx, var, in enumerate(plot_vars):
out = nc.plot_profile(axs[idx], var)
long_name = nc.get_long_name(var)
units = nc.get_units(var)
col_bar = fig.colorbar(out)
col_bar.set_label(f"{long_name} ({units})")
fig.savefig("temp_salt_profiles.png")