8000 Merge pull request #29367 from meeseeksmachine/auto-backport-of-pr-29… · matplotlib/matplotlib@dd1e176 · GitHub
[go: up one dir, main page]

Skip to content

Commit dd1e176

Browse files
authored
Merge pull request #29367 from meeseeksmachine/auto-backport-of-pr-29347-on-v3.10.0-doc
Backport PR #29347 on branch v3.10.0-doc (DOC: Explain parameters linthresh and linscale of symlog scale)
2 parents c6afd1b + 2581353 commit dd1e176

File tree

1 file changed

+82
-7
lines changed

1 file changed

+82
-7
lines changed

galleries/examples/scales/symlog_demo.py

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
"""
2-
===========
3-
Symlog Demo
4-
===========
2+
============
3+
Symlog scale
4+
============
5+
6+
The symmetric logarithmic scale is an extension of the logarithmic scale that
7+
also covers negative values. As with the logarithmic scale, it is particularly
8+
useful for numerical data that spans a broad range of values, especially when there
9+
are significant differences between the magnitudes of the numbers involved.
510
611
Example use of symlog (symmetric log) axis scaling.
712
"""
@@ -34,12 +39,82 @@
3439
plt.show()
3540

3641
# %%
37-
# It should be noted that the coordinate transform used by ``symlog``
38-
# has a discontinuous gradient at the transition between its linear
39-
# and logarithmic regions. The ``asinh`` axis scale is an alternative
40-
# technique that may avoid visual artifacts caused by these discontinuities.
42+
# Linear threshold
43+
# ----------------
44+
# Since each decade on a logarithmic scale covers the same amount of visual space
45+
# and there are infinitely many decades between a given number and zero, the symlog
46+
# scale must deviate from logarithmic mapping in a small range
47+
# *(-linthresh, linthresh)*, so that the range is mapped to a finite visual space.
48+
49+
50+
def format_axes(ax, title=None):
51+
"""A helper function to better visualize properties of the symlog scale."""
52+
ax.xaxis.get_minor_locator().set_params(subs=[2, 3, 4, 5, 6, 7, 8, 9])
53+
ax.grid()
54+
ax.xaxis.grid(which='minor') # minor grid on too
55+
linthresh = ax.xaxis.get_transform().linthresh
56+
linscale = ax.xaxis.get_transform().linscale
57+
ax.axvspan(-linthresh, linthresh, color='0.9')
58+
if title:
59+
ax.set_title(title.format(linthresh=linthresh, linscale=linscale))
60+
61+
62+
x = np.linspace(-60, 60, 201)
63+
y = np.linspace(0, 100.0, 201)
64+
65+
fig, (ax1, ax2) = plt.subplots(nrows=2, layout="constrained")
66+
67+
ax1.plot(x, y)
68+
ax1.set_xscale('symlog', linthresh=1)
69+
format_axes(ax1, title='Linear region: linthresh={linthresh}')
70+
71+
ax2.plot(x, y)
72+
ax2.set_xscale('symlog', linthresh=5)
73+
format_axes(ax2, title='Linear region: linthresh={linthresh}')
74+
75+
# %%
76+
# Generally, *linthresh* should be chosen so that no or only a few
77+
# data points are in the linear region. As a rule of thumb,
78+
# :math:`linthresh \approx \mathrm{min} |x|`.
79+
#
80+
#
81+
# Linear scale
82+
# ------------
83+
# Additionally, the *linscale* parameter determines how much visual space should be
84+
# used for the linear range. More precisely, it defines the ratio of visual space
85+
# of the region (0, linthresh) relative to one decade.
86+
87+
fig, (ax1, ax2) = plt.subplots(nrows=2, layout="constrained")
88+
89+
ax1.plot(x, y)
90+
ax1.set_xscale('symlog', linthresh=1)
91+
format_axes(ax1, title='Linear region: linthresh={linthresh}, linscale={linscale}')
92+
93+
ax2.plot(x, y)
94+
ax2.set_xscale('symlog', linthresh=1, linscale=0.1)
95+
format_axes(ax2, title='Linear region: linthresh={linthresh}, linscale={linscale}')
4196

4297
# %%
98+
# The suitable value for linscale depends on the dynamic range of data. As most data
99+
# will be outside the linear region, you typically the linear region only to cover
100+
# a small fraction of the visual area.
101+
#
102+
# Limitations and alternatives
103+
# ----------------------------
104+
# The coordinate transform used by ``symlog`` has a discontinuous gradient at the
105+
# transition between its linear and logarithmic regions. Depending on data and
106+
# scaling, this will be more or less obvious in the plot.
107+
108+
fig, ax = plt.subplots()
109+
ax.plot(x, y)
110+
ax.set_xscale('symlog', linscale=0.05)
111+
format_axes(ax, title="Discontinuous gradient at linear/log transition")
112+
113+
# %%
114+
# The ``asinh`` axis scale is an alternative transformation that supports a wide
115+
# dynamic range with a smooth gradient and thus may avoid such visual artifacts.
116+
# See :doc:`/gallery/scales/asinh_demo`.
117+
#
43118
#
44119
# .. admonition:: References
45120
#

0 commit comments

Comments
 (0)
0