Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/src/whatsnew/latest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,10 @@ This document explains the changes made to Iris for this release
✨ Features
===========

#. N/A

#. `@pp-mo`_ added a new utility function :func:`~iris.util.equalise_cubes`, to help
with aligning cubes so they can merge / concatenate.
(:issue:`6248`, :pull:`6257`)


#. `@fnattino`_ added the lazy median aggregator :class:`iris.analysis.MEDIAN`
based on the implementation discussed by `@rcomer`_ and `@stefsmeets`_ in
:issue:`4039` (:pull:`6167`).
Expand All @@ -51,6 +48,11 @@ This document explains the changes made to Iris for this release
However, :meth:`~iris.cube.Cube.transpose` will work, as will
:meth:`~iris.cube.Cube.copy`. Note that, ``cube.copy(data=iris.DATALESS)``
will provide a dataless copy of a cube. (:issue:`4447`, :pull:`6253`)

#. `@ESadek-MO`_ added the :mod:`iris.quickplot` ``footer`` kwarg to
render text in the bottom right of the plot figure.
(:issue:`6247`, :pull:`6332`)


🐛 Bugs Fixed
=============
Expand Down
37 changes: 35 additions & 2 deletions lib/iris/quickplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
These routines work much like their :mod:`iris.plot` counterparts, but they
automatically add a plot title, axis titles, and a colour bar when appropriate.

These also have the optional kwarg ``footer``, which adds text to the bottom right of
the plot figure.

See also: :ref:`matplotlib <matplotlib:users-guide-index>`.

"""

import cf_units
from matplotlib import patheffects
import matplotlib.pyplot as plt

import iris.config
Expand Down Expand Up @@ -139,6 +143,17 @@ def _label_1d_plot(*args, **kwargs):
axes.set_ylabel(ylabel)


def _footer(footer_text: str) -> None:
if footer_text:
text = plt.figtext(
x=0.99, y=0.01, s=footer_text, fontsize=12, ha="right", va="bottom"
)
text.set_path_effects(
[patheffects.Stroke(linewidth=3, foreground="white"), patheffects.Normal()]
)
plt.subplots_adjust(bottom=0.15, left=0.1)


def contour(cube, *args, **kwargs):
"""Draw contour lines on a labelled plot based on the given Cube.

Expand All @@ -165,8 +180,10 @@ def contour(cube, *args, **kwargs):
"""
coords = kwargs.get("coords")
axes = kwargs.get("axes")
footer = kwargs.pop("footer", None)
result = iplt.contour(cube, *args, **kwargs)
_label_with_points(cube, coords=coords, axes=axes)
_footer(footer)
return result


Expand Down Expand Up @@ -201,12 +218,14 @@ def contourf(cube, *args, **kwargs):
coords = kwargs.get("coords")
axes = kwargs.get("axes")
colorbar = kwargs.pop("colorbar", True)
footer = kwargs.pop("footer", None)
result = iplt.contourf(cube, *args, **kwargs)
_label_with_points(cube, result, coords=coords, axes=axes, colorbar=colorbar)
_footer(footer)
return result


def outline(cube, coords=None, color="k", linewidth=None, axes=None):
def outline(cube, coords=None, color="k", linewidth=None, axes=None, footer=None):
"""Draw cell outlines on a labelled plot based on the given Cube.

Parameters
Expand Down Expand Up @@ -234,6 +253,7 @@ def outline(cube, coords=None, color="k", linewidth=None, axes=None):
)

_label_with_bounds(cube, coords=coords, axes=axes)
_footer(footer)
return result


Expand All @@ -255,8 +275,10 @@ def pcolor(cube, *args, **kwargs):
coords = kwargs.get("coords")
axes = kwargs.get("axes")
colorbar = kwargs.pop("colorbar", True)
footer = kwargs.pop("footer", None)
result = iplt.pcolor(cube, *args, **kwargs)
_label_with_bounds(cube, result, coords=coords, axes=axes, colorbar=colorbar)
_footer(footer)
return result


Expand All @@ -279,8 +301,10 @@ def pcolormesh(cube, *args, **kwargs):
coords = kwargs.get("coords")
axes = kwargs.get("axes")
colorbar = kwargs.pop("colorbar", True)
footer = kwargs.pop("footer", None)
result = iplt.pcolormesh(cube, *args, **kwargs)
_label_with_bounds(cube, result, coords=coords, axes=axes, colorbar=colorbar)
_footer(footer)
return result


Expand All @@ -297,8 +321,10 @@ def points(cube, *args, **kwargs):
"""
coords = kwargs.get("coords")
axes = kwargs.get("axes")
footer = kwargs.pop("footer", None)
result = iplt.points(cube, *args, **kwargs)
_label_with_points(cube, coords=coords, axes=axes)
_footer(footer)
return result


Expand All @@ -315,8 +341,10 @@ def plot(*args, **kwargs):

"""
axes = kwargs.get("axes")
footer = kwargs.pop("footer", None)
result = iplt.plot(*args, **kwargs)
_label_1d_plot(*args, axes=axes)
_footer(footer)
return result


Expand All @@ -333,8 +361,10 @@ def scatter(x, y, *args, **kwargs):

"""
axes = kwargs.get("axes")
footer = kwargs.pop("footer", None)
result = iplt.scatter(x, y, *args, **kwargs)
_label_1d_plot(x, y, axes=axes)
_footer(footer)
return result


Expand All @@ -351,8 +381,10 @@ def fill_between(x, y1, y2, *args, **kwargs):

"""
axes = kwargs.get("axes")
footer = kwargs.pop("footer", None)
result = iplt.fill_between(x, y1, y2, *args, **kwargs)
_label_1d_plot(x, y1, axes=axes)
_footer(footer)
return result


Expand All @@ -369,6 +401,7 @@ def hist(x, *args, **kwargs):

"""
axes = kwargs.get("axes")
footer = kwargs.pop("footer", None)
result = iplt.hist(x, *args, **kwargs)
title = _title(x, with_units=False)
label = _title(x, with_units=True)
Expand All @@ -382,7 +415,7 @@ def hist(x, *args, **kwargs):
else:
axes.set_xlabel(label)
axes.set_title(title)

_footer(footer)
return result


Expand Down
10 changes: 10 additions & 0 deletions lib/iris/tests/test_quickplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,13 @@ def test_vertical(self):
cube = test_plot.simple_cube()[0]
qplt.hist(cube, bins=np.linspace(287.7, 288.2, 11), orientation="horizontal")
self.check_graphic()


@_shared_utils.skip_plot
class TestFooter:
def test__footer(self):
text = "Example"
qplt._footer(text)
fig = plt.gcf()
footer_text = fig.texts[0].get_text()
assert text == footer_text
Loading