Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 138fd55

Browse files
author
Jakub Klus
committed
Add tutorial about autoscaling
1 parent 5ba3911 commit 138fd55

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

tutorials/intermediate/autoscale.py

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
"""
2+
Autoscaling
3+
===========
4+
5+
Axis scales define the overall look of a plot, there are some default options
6+
that scale ranges automatically with respect to supplied data - autoscaling.
7+
This tutorial shows concepts of individual autoscaling options and
8+
investigates cornerstone examples regarding needs of manual adjustments.
9+
"""
10+
11+
###############################################################################
12+
# We will start with a simple line plot showing that the autoscaling feature
13+
# extends the visible range slightly beyond real data range (-2π, 2π).
14+
15+
import numpy as np
16+
import matplotlib as mpl
17+
import matplotlib.pyplot as plt
18+
19+
x = np.linspace(-2 * np.pi, 2 * np.pi, 100)
20+
y = np.sinc(x)
21+
22+
fig, ax = plt.subplots()
23+
ax.plot(x, y)
24+
fig.show()
25+
26+
###############################################################################
27+
# Margins
28+
# -------
29+
# The relative measure of extend is called margin and can be set by
30+
# :func:`~matplotlib.axes.Axes.margins`.
31+
# We can check that default value is (0.05, 0.05).
32+
33+
ax.margins()
34+
35+
###############################################################################
36+
# Margin scales with respect to the data interval so setting larger margin
37+
# ensures more space between acutal data and plot edges, hence plotted curve
38+
# will appear smaller.
39+
40+
fig, ax = plt.subplots()
41+
ax.plot(x, y)
42+
ax.margins(0.2, 0.2)
43+
fig.show()
44+
45+
###############################################################################
46+
# In general, margins shall be in range (-0.5, ∞), negative margins crop the
47+
# plot showing only a part of the data. Using a single number for margins
48+
# affects both axes, single margin can be customized by means of keyword
49+
# arguments ``x`` or ``y``, but positional and keyword interface cannot be
50+
# combined
51+
52+
fig, ax = plt.subplots()
53+
ax.plot(x, y)
54+
ax.margins(y=-0.2)
55+
fig.show()
56+
57+
###############################################################################
58+
# There is a last keyword argument for margins call, the ``tight`` option. In
59+
# case of simple :func:`~matplotlib.axes.Axes.plot` call, this parameter does
60+
# not change anything, it is passed to the
61+
# :meth:`~matplotlib.axes.Axes.autoscale_view`, which requires more advanced
62+
# discussion.
63+
#
64+
# Margins can behave differently for certain plots, this is determined by
65+
# sticky edges property, which is of interest in next section.
66+
#
67+
# Sticky edges
68+
# ------------
69+
# Margin must not be applied for certain :class:`.Artist`, for example setting
70+
# ``margin=0.2`` on ``plt.imshow`` does not affect the resulting plot.
71+
#
72+
73+
xx, yy = np.meshgrid(x, x)
74+
zz = np.sinc(np.sqrt((xx - 1)**2 + (yy - 1)**2))
75+
76+
fig, ax = plt.subplots(ncols=2, figsize=(12, 8))
77+
ax[0].imshow(zz)
78+
ax[0].set_title("margins unchanged")
79+
ax[1].imshow(zz)
80+
ax[1].margins(0.2)
81+
ax[1].set_title("margins(0.2)")
82+
fig.show()
83+
84+
###############################################################################
85+
# This override of margins is determined by so-called sticky edges. That is a
86+
# property of :class:`.Artist` class, which can suppress adding margins to data
87+
# limits. The effect of sticky edges can be disabled by changing
88+
# :class:`~matplotlib.axes.Axes` property
89+
# `~matplotlib.axes.Axes.use_sticky_edges`.
90+
#
91+
# Settings of sticky edges of individual artists can be investigating by
92+
# accessing them directly, `.Artist.sticky_edges`. Moreover, values of sticky
93+
# edges can be changed by writing to ``Artist.sticky_edges.x`` or
94+
# ``.Artist.sticky_edges.y``
95+
#
96+
# Following example shows how overriding works and when it is needed.
97+
98+
fig, ax = plt.subplots(ncols=3, figsize=(16, 10))
99+
ax[0].imshow(zz)
100+
ax[0].margins(0.2)
101+
ax[0].set_title("use_sticky_edges unchanged\nmargins(0.2)")
102+
ax[1].imshow(zz)
103+
ax[1].margins(0.2)
104+
ax[1].use_sticky_edges = False
105+
ax[1].set_title("use_sticky_edges=False\nmargins(0.2)")
106+
ax[2].imshow(zz)
107+
ax[2].margins(-0.2)
108+
ax[2].set_title("use_sticky_edges unchanged\nmargins(-0.2)")
109+
fig.show()
110+
111+
###############################################################################
112+
# We can see that setting ``use_sticky_edges`` to False renders the image with
113+
# requested margins. Additionally, as is stated, sticky edges count for adding
114+
# a margin, therefore negative margin is not affected by its state, rendering
115+
# the third image within narrower limits and without changing the
116+
# `~matplotlib.axes.Axes.use_sticky_edges` property.
117+
#
118+
# Controlling autoscale
119+
# ---------------------
120+
#
121+
# We have figured out how to control the margins of the plot. Now, we will
122+
# investigate how to disable autoscaling. By default, the scales are
123+
# recalculated every time you add a new curve to the plot (see next figure).
124+
# This ensures visibility of the data. However, there are cases when you
125+
# don't want to automatically adjust viewport to data.
126+
127+
fig, ax = plt.subplots(ncols=2, figsize=(12, 8))
128+
ax[0].plot(x, y)
129+
ax[0].set_title("Single curve")
130+
ax[1].plot(x, y)
131+
ax[1].plot(x * 2.0, y)
132+
ax[1].set_title("Two curves")
133+
fig.show()
134+
135+
136+
###############################################################################
137+
# There are multiple reasons to do that so there are multiple ways of
138+
# disabling the autoscale feature. One of the cases is manually setting the
139+
# axis limit. Let's say that we want to see only a part of the data in
140+
# greater detail. Setting the ``xlim`` persists even if we add more curves to
141+
# the data. To recalcuate the new limits we shall call `.Axes.autoscale`
142+
# manually to toggle the functionality.
143+
144+
fig, ax = plt.subplots(ncols=2, figsize=(12, 8))
145+
ax[0].plot(x, y)
146+
ax[0].set_xlim(left=-1, right=1)
147+
ax[0].plot(x + np.pi * 0.5, y)
148+
ax[0].set_title("set_xlim(left=-1, right=1)\n")
149+
ax[1].plot(x, y)
150+
ax[1].set_xlim(left=-1, right=1)
151+
ax[1].plot(x + np.pi * 0.5, y)
152+
ax[1].autoscale()
153+
ax[1].set_title("set_xlim(left=-1, right=1)\nautoscale()")
154+
fig.show()
155+
156+
###############################################################################
157+
# We can check that first plot has autoscale disabled and that the second plot
158+
# has it enabled again by using `.Axes.get_autoscale_on()`:
159+
160+
print(ax[0].get_autoscale_on()) # False means disabled
161+
print(ax[1].get_autoscale_on()) # True means enabled -> recalculated
162+
163+
###############################################################################
164+
# Arguments of the autoscale function give us precise control over the process
165+
# of autoscaling. Combination of arguments ``enable``, and ``axis`` sets the
166+
# autoscaling feature for selected axis (or both). The argument ``tight`` sets
167+
# the margin of the selected axis to zero. To preserve settings of either
168+
# ``enable`` or ``tight`` you can set the opposite one to None, that way
169+
# it should not be modified. However, setting ``enable`` to None and tight
170+
# to True affects both axes regardless of the ``axis`` argument.
171+
172+
fig, ax = plt.subplots()
173+
ax.plot(x, y)
174+
ax.margins(0.2, 0.2)
175+
ax.autoscale(enable=None, axis="x", tight=True)
176+
fig.show()
177+
print(ax.margins())
178+
179+
###############################################################################
180+
# Working with collections
181+
# ------------------------
182+
# Autoscale works out of the box for all lines, patches and images added to
183+
# the axes. One of artists that it won't work is `.Collection`. After adding
184+
# a collection to the axes, one has to manually trigger the
185+
# :func:`~matplotlib.axes.Axes.autoscale_view()` to popagate recalculated
186+
# limits to the figure.
187+
188+
fig, ax = plt.subplots()
189+
collection = mpl.collections.StarPolygonCollection(5, 0, [250, ],
190+
offsets=np.column_stack([x, y]), # Set the positions
191+
transOffset=ax.transData, # Propagate transformations of the Axes
192+
)
193+
ax.add_collection(collection)
194+
ax.autoscale_view()
195+
fig.show()

0 commit comments

Comments
 (0)