Skip to content

Commit c9bfaf5

Browse files
authored
Merge pull request matplotlib#26279 from jklymak/doc-user-axis
DOC: remove users_explain/axis
2 parents 109042c + 0cf751c commit c9bfaf5

File tree

11 files changed

+524
-25
lines changed

11 files changed

+524
-25
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/artists/artist_intro.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ Introduction to Artists
55

66
Almost all objects you interact with on a Matplotlib plot are called "Artist"
77
(and are subclasses of the `.Artist` class). :doc:`Figure <../figure/index>`
8-
and :doc:`Axes <../axes/index>` are Artists, and generally contain :doc:`Axis
9-
<../axis/index>` Artists and Artists that contain data or annotation
10-
information.
8+
and :doc:`Axes <../axes/index>` are Artists, and generally contain
9+
`~.axis.Axis` Artists and Artists that contain data or annotation information.
1110

1211

1312
Creating Artists

galleries/users_explain/artists/index.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ Artists
44

55
Almost all objects you interact with on a Matplotlib plot are called "Artist"
66
(and are subclasses of the `.Artist` class). :doc:`Figure <../figure/index>`
7-
and :doc:`Axes <../axes/index>` are Artists, and generally contain :doc:`Axis
8-
<../axis/index>` Artists and Artists that contain data or annotation
9-
information.
7+
and :doc:`Axes <../axes/index>` are Artists, and generally contain
8+
`~.axis.Axis` Artists and Artists that contain data or annotation information.
109

1110
.. toctree::
1211
:maxdepth: 2

galleries/users_explain/axes/axes_intro.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Introduction to Axes (or Subplots)
55

66
Matplotlib `~.axes.Axes` are the gateway to creating your data visualizations.
77
Once an Axes is placed on a figure there are many methods that can be used to
8-
add data to the Axes. An Axes typically has a pair of :doc:`Axis <../axis/index>`
8+
add data to the Axes. An Axes typically has a pair of `~.axis.Axis`
99
Artists that define the data coordinate system, and include methods to add
1010
annotations like x- and y-labels, titles, and legends.
1111

@@ -130,7 +130,7 @@ Note that text can also be added to axes using `~.axes.Axes.text`, and `~.axes.A
130130
Axes limits, scales, and ticking
131131
--------------------------------
132132

133-
Each Axes has two (or more) `~.axis.Axis` objects, that can be accessed via :attr:`~matplotlib.axes.Axes.xaxis` and :attr:`~matplotlib.axes.Axes.yaxis` properties. These have substantial number of methods on them, and for highly customizable Axis-es it is useful to read more about that API (:doc:`../axis/index`). However, the Axes class offers a number of helpers for the most common of these methods. Indeed, the `~.axes.Axes.set_xlabel`, discussed above, is a helper for the `~.Axis.set_label_text`.
133+
Each Axes has two (or more) `~.axis.Axis` objects, that can be accessed via :attr:`~matplotlib.axes.Axes.xaxis` and :attr:`~matplotlib.axes.Axes.yaxis` properties. These have substantial number of methods on them, and for highly customizable Axis-es it is useful to read the API at `~.axis.Axis`. However, the Axes class offers a number of helpers for the most common of these methods. Indeed, the `~.axes.Axes.set_xlabel`, discussed above, is a helper for the `~.Axis.set_label_text`.
134134

135135
Other important methods set the extent on the axes (`~.axes.Axes.set_xlim`, `~.axes.Axes.set_ylim`), or more fundamentally the scale of the axes. So for instance, we can make an Axis have a logarithmic scale, and zoom in on a sub-portion of the data:
136136

@@ -158,7 +158,7 @@ Many aspects of Axes ticks and tick labeling can be adjusted using `~.axes.Axes.
158158
labelcolor='green')
159159

160160

161-
More fine-grained control on ticks, setting scales, and controlling the Axis can be highly customized beyond these Axes-level helpers. An introduction to these methods can be found in :ref:`users_axis`, or the API reference for `.axis.Axis`.
161+
More fine-grained control on ticks, setting scales, and controlling the Axis can be highly customized beyond these Axes-level helpers.
162162

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

0 commit comments

Comments
 (0)