From 930503fce16be4ed4700cf62340d3e78c9489992 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Sun, 23 Feb 2025 19:17:11 +0000 Subject: [PATCH 1/6] quickplot footer --- lib/iris/quickplot.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index c1ca7f733f..7ec621f3f9 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -139,6 +139,12 @@ def _label_1d_plot(*args, **kwargs): axes.set_ylabel(ylabel) +def _footer(text): + if text: + plt.figtext(x=.99, y=.01, s=text, fontsize=12, ha="right") + 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. @@ -165,8 +171,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 @@ -201,12 +209,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 @@ -234,6 +244,7 @@ def outline(cube, coords=None, color="k", linewidth=None, axes=None): ) _label_with_bounds(cube, coords=coords, axes=axes) + _footer(footer) return result @@ -255,8 +266,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 @@ -279,8 +292,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 @@ -297,8 +312,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 @@ -315,8 +332,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 @@ -333,8 +352,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 @@ -351,8 +372,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 @@ -369,6 +392,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) @@ -382,7 +406,7 @@ def hist(x, *args, **kwargs): else: axes.set_xlabel(label) axes.set_title(title) - + _footer(footer) return result From 488795ccd914b16dbac3923a232993cc3919315c Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Sun, 23 Feb 2025 19:28:01 +0000 Subject: [PATCH 2/6] docs --- lib/iris/quickplot.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index 7ec621f3f9..7ee9b5feaa 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -7,6 +7,9 @@ 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. + See also: :ref:`matplotlib `. """ From f5a01ea112489f2c26c5ba5c0f907b75f2bf2207 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Sun, 23 Feb 2025 19:37:32 +0000 Subject: [PATCH 3/6] readme --- docs/src/whatsnew/latest.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 68737d86cc..f7447b68ae 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -30,8 +30,6 @@ 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`) @@ -41,6 +39,10 @@ This document explains the changes made to Iris for this release based on the implementation discussed by `@rcomer`_ and `@stefsmeets`_ in :issue:`4039` (:pull:`6167`). +#. `@ESadek-MO`_ added a convenience kwarg to :mod:`iris.quickplot` to + add a consisently laid-out footer to plots. + (:issue:`6247`, :pull:`6332`) + 🐛 Bugs Fixed ============= From 0ea6a8b977c85669fc7c18d1c0df1329b887eefb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 23 Feb 2025 19:40:48 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- lib/iris/quickplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index 7ee9b5feaa..86bb4a8146 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -144,7 +144,7 @@ def _label_1d_plot(*args, **kwargs): def _footer(text): if text: - plt.figtext(x=.99, y=.01, s=text, fontsize=12, ha="right") + plt.figtext(x=0.99, y=0.01, s=text, fontsize=12, ha="right") plt.subplots_adjust(bottom=0.15, left=0.1) From d489793667f79fd7e08b98f9c8b332d5959e17b4 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Thu, 27 Feb 2025 15:54:51 +0000 Subject: [PATCH 5/6] added test, and white background for text --- lib/iris/quickplot.py | 10 +++++++--- lib/iris/tests/test_quickplot.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index 7ee9b5feaa..f3dc9dd5de 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -15,6 +15,7 @@ """ import cf_units +from matplotlib import patheffects import matplotlib.pyplot as plt import iris.config @@ -142,9 +143,12 @@ def _label_1d_plot(*args, **kwargs): axes.set_ylabel(ylabel) -def _footer(text): - if text: - plt.figtext(x=.99, y=.01, s=text, fontsize=12, ha="right") +def _footer(footer_text): + if footer_text: + text = plt.figtext(x=0.99, y=0.01, s=footer_text, fontsize=12, ha="right") + text.set_path_effects( + [patheffects.Stroke(linewidth=3, foreground="white"), patheffects.Normal()] + ) plt.subplots_adjust(bottom=0.15, left=0.1) diff --git a/lib/iris/tests/test_quickplot.py b/lib/iris/tests/test_quickplot.py index 17ef68e64b..52e0fad18d 100644 --- a/lib/iris/tests/test_quickplot.py +++ b/lib/iris/tests/test_quickplot.py @@ -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 From 37d2bb46ffc50188b3cb9c4fb0b05fb15828185b Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Thu, 27 Feb 2025 16:42:42 +0000 Subject: [PATCH 6/6] review comments --- docs/src/whatsnew/latest.rst | 4 ++-- lib/iris/quickplot.py | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 340896a9d8..39bc555043 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -49,8 +49,8 @@ This document explains the changes made to Iris for this release :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 a convenience kwarg to :mod:`iris.quickplot` to - add a consisently laid-out footer to plots. +#. `@ESadek-MO`_ added the :mod:`iris.quickplot` ``footer`` kwarg to + render text in the bottom right of the plot figure. (:issue:`6247`, :pull:`6332`) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index f3dc9dd5de..431c71cd8e 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -7,8 +7,8 @@ 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. +These also have the optional kwarg ``footer``, which adds text to the bottom right of +the plot figure. See also: :ref:`matplotlib `. @@ -143,9 +143,11 @@ def _label_1d_plot(*args, **kwargs): axes.set_ylabel(ylabel) -def _footer(footer_text): +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") + 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()] )