Plotting¶
We often want to write a function which plots something. In order to be useful
in a large variety of scenarios, a good library plotting function should be
extremely flexible and support a large variety of options. We probably want to
support basically the same set of options for virtually every plotting function
we write. In order to avoid writing redundant code, we present the @plotter
decorator, which is found in lib5c.util.plotting
.
Design principles¶
We expect a generic plotting function plot_fn()
should take in some data and
plot it to the default pyplot
axis. We expect to be able to override some
details about the plot, including what axis should be plotted on, the plot
title, whether or not to add a legend, etc. Ideally, the function should return
the axis it plotted on, which would allow the caller to make further
modifications to the plot before saving to disk. However, many clients will
probably want to just save the figure to disk as fast as possible, so an
“automatic save” option should exist as well.
Examples¶
We consider the plotting function plot_fn()
:
import matplotlib.pyplot as plt
from lib5c.util.plotting import plotter
@plotter
def plot_fn(x, y, **kwargs):
plt.scatter(x, y)
Importantly, the @plotter
API requires client functions to accept arbitrary
**kwargs
in their signature.
A client may call
ax = plot_fn(x, y)
where the return value of plot_fn()
will simply be the axis that was plotted
on.
To plot to a specific axis called ax
, the client may call
ax = plot_fn(x, y, ax=ax)
To automatically save the figure to disk, the client may call
plot_fn(x, y, outfile='plot.png')
Plots will be automatically saved at 300 dpi, but this can be overriden by calling
plot_fn(x, y, outfile='plot.png', dpi=800)
Plots will be styled with seaborn
, using the 'ticks'
axis style. To use
a different seaborn
style, the client can call
plot_fn(x, y, style='darkgrid')
The @plotter
decorator will always automatically remove the seaborn
styles after the call completes, allowing future plotting calls to look
“normal”.
To avoid using the seaborn
styles and stick with matplotlib
defaults,
the client can call
plot_fn(x, y, style=None)
The plot will be despined with sns.despine()
by default. To disable this,
the client can call
plot_fn(x, y, despine=False)
The decorated plot_fn()
will accept a kwarg called legend
. By default,
this kwarg is None
, which leaves all decisions about the legend in the hands
of plot_fn()
. If plot_fn()
adds a legend to the plot, but you wish to
remove it, call
plot_fn(x, y, legend=False)
If plot_fn()
does not add a legend, but you wish to have one, call
plot_fn(x, y, legend=True)
If the legend is really large and you wish it to be added outside the plot area, you can call
plot_fn(x, y, legend='outside')
Other minor adjustments can be made to the plot with the kwargs illustrated in the following example call:
plot_fn(x, y, xlim=(0, 10), ylim=(-1, 1), xlabel='number of cows',
ylabel='relative change in grass', xticks=11, yticks=[-1, 0, 1],
title='cows vs grass')
Here we note that xticks
and yticks
can be passed as either an integer
(in which case the specified axis will have that many evenly-spaced ticks) or as
anything accepted by plt.xticks()
(in our example, a list of tick
locations).