From 36af98e371ed4af49b98488385cef3ab88ca2d19 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:40:37 +0200 Subject: [PATCH 1/2] DOC: Add a plot to margins() to visualize the effect --- lib/matplotlib/axes/_base.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 52963c1d1ff5..7d72b8caedfa 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2745,6 +2745,34 @@ def margins(self, *margins, x=None, y=None, tight=True): arguments (positional or otherwise) are provided, the current margins will remain unchanged and simply be returned. + .. plot:: + + import numpy as np + import matplotlib.pyplot as plt + + x, y = np.meshgrid(np.linspace(0, 1, 10), np.linspace(0, 1, 10)) + fig, ax = plt.subplots() + ax.plot(x, y, 'o', color='lightblue') + ax.margins(1.5, 0.5) + ax.set_title("margins(x=1.5, y=0.5)") + + def arrow(p1, p2, **props): + ax.annotate("", p1, p2, + arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0, **props)) + + arrow((-1.5, 0), (0, 0), color="orange") + arrow((0, 0), (1, 0), color="sienna") + arrow((1, 0), (2.5, 0), color="orange") + ax.text(-0.75, -0.1, "x margin * x data range", ha="center", + color="orange") + ax.text(0.5, -0.1, "x data range", ha="center", color="sienna") + + arrow((1, -0.5), (1, 0), color="tab:green") + arrow((1, 0), (1, 1), color="darkgreen") + arrow((1, 1), (1, 1.5), color="tab:green") + ax.text(1.1, 1.25, "y margin * y data range", color="tab:green") + ax.text(1.1, 0.5, "y data range", color="darkgreen") + Specifying any margin changes only the autoscaling; for example, if *xmargin* is not None, then *xmargin* times the X data interval will be added to each end of that interval before From 8ea86fed13b656ef0bbadceada10255e0d17b35a Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 13 Sep 2024 01:29:21 +0200 Subject: [PATCH 2/2] DOC: Add a plot to margins() to visualize the effect --- doc/_embedded_plots/axes_margins.py | 42 +++++++++++++++++++++ lib/matplotlib/axes/_base.py | 57 +++++++++-------------------- 2 files changed, 60 insertions(+), 39 deletions(-) create mode 100644 doc/_embedded_plots/axes_margins.py diff --git a/doc/_embedded_plots/axes_margins.py b/doc/_embedded_plots/axes_margins.py new file mode 100644 index 000000000000..d026840c3c15 --- /dev/null +++ b/doc/_embedded_plots/axes_margins.py @@ -0,0 +1,42 @@ +import numpy as np +import matplotlib.pyplot as plt + +fig, ax = plt.subplots(figsize=(6.5, 4)) +x = np.linspace(0, 1, 33) +y = -np.sin(x * 2*np.pi) +ax.plot(x, y, 'o') +ax.margins(0.5, 0.2) +ax.set_title("margins(x=0.5, y=0.2)") + +# fix the Axes limits so that the following helper drawings +# cannot change them further. +ax.set(xlim=ax.get_xlim(), ylim=ax.get_ylim()) + + +def arrow(p1, p2, **props): + ax.annotate("", p1, p2, + arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0, **props)) + + +axmin, axmax = ax.get_xlim() +aymin, aymax = ax.get_ylim() +xmin, xmax = x.min(), x.max() +ymin, ymax = y.min(), y.max() + +y0 = -0.8 +ax.axvspan(axmin, xmin, color=("orange", 0.1)) +ax.axvspan(xmax, axmax, color=("orange", 0.1)) +arrow((xmin, y0), (xmax, y0), color="sienna") +arrow((xmax, y0), (axmax, y0), color="orange") +ax.text((xmax + axmax)/2, y0+0.05, "x margin\n* x data range", + ha="center", va="bottom", color="orange") +ax.text(0.55, y0+0.1, "x data range", va="bottom", color="sienna") + +x0 = 0.1 +ax.axhspan(aymin, ymin, color=("tab:green", 0.1)) +ax.axhspan(ymax, aymax, color=("tab:green", 0.1)) +arrow((x0, ymin), (x0, ymax), color="darkgreen") +arrow((x0, ymax), (x0, aymax), color="tab:green") +ax.text(x0, (ymax + aymax) / 2, " y margin * y data range", + va="center", color="tab:green") +ax.text(x0, 0.5, " y data range", color="darkgreen") diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 7d72b8caedfa..18cfec831af4 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2736,47 +2736,22 @@ def set_ymargin(self, m): def margins(self, *margins, x=None, y=None, tight=True): """ - Set or retrieve autoscaling margins. + Set or retrieve margins around the data for autoscaling axis limits. - The padding added to each limit of the Axes is the *margin* - times the data interval. All input parameters must be floats - greater than -0.5. Passing both positional and keyword - arguments is invalid and will raise a TypeError. If no - arguments (positional or otherwise) are provided, the current - margins will remain unchanged and simply be returned. - - .. plot:: - - import numpy as np - import matplotlib.pyplot as plt - - x, y = np.meshgrid(np.linspace(0, 1, 10), np.linspace(0, 1, 10)) - fig, ax = plt.subplots() - ax.plot(x, y, 'o', color='lightblue') - ax.margins(1.5, 0.5) - ax.set_title("margins(x=1.5, y=0.5)") + This allows to configure the padding around the data without having to + set explicit limits using `~.Axes.set_xlim` / `~.Axes.set_ylim`. - def arrow(p1, p2, **props): - ax.annotate("", p1, p2, - arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0, **props)) + Autoscaling determines the axis limits by adding *margin* times the + data interval as padding around the data. See the following illustration: - arrow((-1.5, 0), (0, 0), color="orange") - arrow((0, 0), (1, 0), color="sienna") - arrow((1, 0), (2.5, 0), color="orange") - ax.text(-0.75, -0.1, "x margin * x data range", ha="center", - color="orange") - ax.text(0.5, -0.1, "x data range", ha="center", color="sienna") + .. plot:: _embedded_plots/axes_margins.py - arrow((1, -0.5), (1, 0), color="tab:green") - arrow((1, 0), (1, 1), color="darkgreen") - arrow((1, 1), (1, 1.5), color="tab:green") - ax.text(1.1, 1.25, "y margin * y data range", color="tab:green") - ax.text(1.1, 0.5, "y data range", color="darkgreen") + All input parameters must be floats greater than -0.5. Passing both + positional and keyword arguments is invalid and will raise a TypeError. + If no arguments (positional or otherwise) are provided, the current + margins will remain unchanged and simply be returned. - Specifying any margin changes only the autoscaling; for example, - if *xmargin* is not None, then *xmargin* times the X data - interval will be added to each end of that interval before - it is used in autoscaling. + The default margins are :rc:`axes.xmargin` and :rc:`axes.ymargin`. Parameters ---------- @@ -2808,10 +2783,14 @@ def arrow(p1, p2, **props): Notes ----- If a previously used Axes method such as :meth:`pcolor` has set - :attr:`use_sticky_edges` to `True`, only the limits not set by - the "sticky artists" will be modified. To force all of the - margins to be set, set :attr:`use_sticky_edges` to `False` + `~.Axes.use_sticky_edges` to `True`, only the limits not set by + the "sticky artists" will be modified. To force all + margins to be set, set `~.Axes.use_sticky_edges` to `False` before calling :meth:`margins`. + + See Also + -------- + .Axes.set_xmargin, .Axes.set_ymargin """ if margins and (x is not None or y is not None):
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: