10000 DOC: add scales to Axes docs · matplotlib/matplotlib@df413ef · GitHub
[go: up one dir, main page]

Skip to content

Commit df413ef

Browse files
committed
DOC: add scales to Axes docs
1 parent 71a0f4c commit df413ef

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

galleries/examples/scales/custom_scale.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""
2+
.. _custom_scale:
3+
24
============
35
Custom scale
46
============

galleries/users_explain/axes/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ annotations like x- and y-labels, titles, and legends.
3636
arranging_axes
3737
colorbar_placement
3838
Autoscaling axes <autoscale>
39+
scales
3940
Legends <legend_guide>
4041
Subplot mosaic <mosaic>
4142
Constrained layout guide <constrainedlayout_guide>
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
"""
2+
===========
3+
Axis scales
4+
===========
5+
6+
By default Matplotlib displays data on axis objects that have linear scales.
7+
This behavior can be changed, usually directly by using the
8+
`~.axes.Axes.set_xscale` or `~.axes.Axes.set_yscale` methods.
9+
10+
"""
11+
import matplotlib.pyplot as plt
12+
import numpy as np
13+
14+
import matplotlib.scale as mscale
15+
from matplotlib.ticker import FixedLocator, NullFormatter
16+
17+
fig, axs = plt.subplot_mosaic([['linear', 'linear-log'],
18+
['log-linear', 'log-log']], layout='constrained')
19+
20+
x = np.arange(0, 3*np.pi, 0.1)
21+
y = 2 * np.sin(x) + 3
22+
23+
ax = axs['linear']
24+
ax.plot(x, y)
25+
ax.set_xlabel('linear')
26+
ax.set_ylabel('linear')
27+
28+
ax = axs['linear-log']
29+
ax.plot(x, y)
30+
ax.set_yscale('log')
31+
ax.set_xlabel('linear')
32+
ax.set_ylabel('log')
33+
34+
ax = axs['log-linear']
35+
ax.plot(x, y)
36+
ax.set_xscale('log')
37+
ax.set_xlabel('log')
38+
ax.set_ylabel('linear')
39+
40+
ax = axs['log-log']
41+
ax.plot(x, y)
42+
ax.set_xscale('log')
43+
ax.set_yscale('log')
44+
ax.set_xlabel('log')
45+
ax.set_ylabel('log')
46+
47+
# %%
48+
# loglog and semilogx/y
49+
# =====================
50+
#
51+
# The logarithmic axis is used so often that there are a set
52+
# helper functions, that do the same thing: `~.axes.Axes.semilogy`,
53+
# `~.axes.Axes.semilogx`, and `~.axes.Axes.loglog`.
54+
55+
fig, axs = plt.subplot_mosaic([['linear', 'linear-log'],
56+
['log-linear', 'log-log']], layout='constrained')
57+
58+
x = np.arange(0, 3*np.pi, 0.1)
59+
y = 2 * np.sin(x) + 3
60+
61+
ax = axs['linear']
62+
ax.plot(x, y)
63+
ax.set_xlabel('linear')
64+
ax.set_ylabel('linear')
65+
ax.set_title('plot(x, y)')
66+
67+
ax = axs['linear-log']
68+
ax.semilogy(x, y)
69+
ax.set_xlabel('linear')
70+
ax.set_ylabel('log')
71+
ax.set_title('semilogy(x, y)')
72+
73+
ax = axs['log-linear']
74+
ax.semilogx(x, y)
75+
ax.set_xlabel('log')
76+
ax.set_ylabel('linear')
77+
ax.set_title('semilogx(x, y)')
78+
79+
ax = axs['log-log']
80+
ax.loglog(x, y)
81+
ax.set_xlabel('log')
82+
ax.set_ylabel('log')
83+
ax.set_title('loglog(x, y)')
84+
85+
# %%
86+
# Other built-in scales
87+
# =====================
88+
#
89+
# There are other scales that can be used. The list of registered
90+
# scales can be returned from `.scales.get_scale_names`:
91+
92+
print(mscale.get_scale_names())
93+
94+
# %%
95+
#
96+
97+
todo = ['asinh', 'symlog', 'log', 'logit', ]
98+
fig, axs = plt.subplot_mosaic([['asinh', 'symlog'],
99+
['log', 'logit']], layout='constrained')
100+
101+
x = np.arange(0, 1000)
102+
103+
for td in todo:
104+
ax = axs[td]
105+
if td in ['asinh', 'symlog']:
106+
yy = x - np.mean(x)
107+
elif td in ['logit']:
108+
yy = (x-np.min(x))
109+
yy = yy / np.max(np.abs(yy))
110+
else:
111+
yy = x
112+
113+
ax.plot(yy, yy)
114+
ax.set_yscale(td)
115+
ax.set_title(td)
116+
117+
# %%
118+
# Optional arguments for scales
119+
# =============================
120+
#
121+
# Some of the default scales have optional arguments. These are
122+
# documented in the API reference for the respective scales at
123+
# `~.matplotlib.scales`. One can change the base of the logarithm
124+
# being plotted (eg 2 below) or the linear threshold range
125+
# for ``'symlog'``.
126+
127+
fig, axs = plt.subplot_mosaic([['log', 'symlog']], layout='constrained',
128+
figsize=(6.4, 3))
129+
130+
for td in axs:
131+
ax = axs[td]
132+
if td in ['log']:
133+
ax.plot(x, x)
134+
ax.set_yscale('log', base=2)
135+
ax.set_title('log base=2')
136+
else:
137+
ax.plot(x - np.mean(x), x - np.mean(x))
138+
ax.set_yscale('symlog', linthresh=100)
139+
ax.set_title('symlog linthresh=100')
140+
141+
142+
# %%
143+
#
144+
# Arbitrary function scales
145+
# ============================
146+
#
147+
# Users can define a full scale class and pass that to `~.axes.Axes.set_xscale`
148+
# and `~.axes.Axes.set_yscale` (see :ref:`custom_scale`). A short cut for this
149+
# is to use the 'function' scale, and pass as extra arguments a ``forward`` and
150+
# an ``inverse`` function. The following performs a `Mercator transform
151+
# <https://en.wikipedia.org/wiki/Mercator_projection>`_ to the y-axis.
152+
153+
# Function Mercator transform
154+
def forward(a):
155+
a = np.deg2rad(a)
156+
return np.rad2deg(np.log(np.abs(np.tan(a) + 1.0 / np.cos(a))))
157+
158+
159+
def inverse(a):
160+
a = np.deg2rad(a)
161+
return np.rad2deg(np.arctan(np.sinh(a)))
162+
163+
164+
t = np.arange(0, 170.0, 0.1)
165+
s = t / 2.
166+
167+
fig, ax = plt.subplots(layout='constrained')
168+
ax.plot(t, s, '-', lw=2)
169+
170+
ax.set_yscale('function', functions=(forward, inverse))
171+
ax.set_title('function: Mercator')
172+
ax.grid(True)
173+
ax.set_xlim([0, 180])
174+
ax.yaxis.set_minor_formatter(NullFormatter())
175+
ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 90, 10)))
176+
177+
178+
# %%
179+
#
180+
# What is a "scale"?
181+
# ==================
182+
#
183+
# A scale is an object that gets attached to an axis. The class documentation
184+
# is at `~.scale`. `~.axes.Axes.set_xscale` and `~.axes.Axes.set_yscale` are
185+
# helper methods for `~.axis.Axis.set_scale`. You can also determine the scale
186+
# on an axis with:
187+
188+
fig, ax = plt.subplots(layout='constrained',
189+
figsize=(3.2, 3))
190+
ax.semilogy(x, x)
191+
192+
print(ax.xaxis.get_scale())
193+
print(ax.yaxis.get_scale())
194+
195+
# %%
196+
#
197+
# Setting a scale does three things. First it defines a transform on the axis
198+
# that maps between data values to position along the axis. This transform can
199+
# be accessed via `~.axis.Axis.get_transform`.
200+
201+
print(ax.yaxis.get_transform())
202+
203+
# %%
204+
#
205+
# Transforms on the axis are a relatively low-level concept, but is one of the
206+
# important roles played by ``set_scale``.
207+
#
208+
# Setting the scale also sets default tick locators (`~.ticker`) and tick
209+
# formatters appropriate for the scale. An axis with a 'log' scale has a
210+
# `~.ticker.LogLocator` to pick ticks at decade intervals, and a
211+
# `~.ticker.LogFormatter` to use scientific notation on the decades.
212+
213+
print('X axis')
214+
print(ax.xaxis.get_major_locator())
215+
print(ax.xaxis.get_major_formatter())
216+
217+
print('Y axis')
218+
print(ax.yaxis.get_major_locator())
219+
print(ax.yaxis.get_major_formatter())

0 commit comments

Comments
 (0)
0