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

Skip to content

Commit 5835396

Browse files
committed
DOC: Explain parameters linthresh and linscale of symlog scale
Closes #29335 via addressing #29335 (comment).
1 parent f8900ea commit 5835396

File tree

2 files changed

+84
-7
lines changed

2 files changed

+84
-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,11 +39,81 @@
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 (-x0, x0), so that
47+
# that range is mapped to a finite visual space.
48+
#
49+
# The symlog scale achieves this by defining a parameter *linthresh* and switching
50+
# to a linear mapping in the region *(-linthresh, linthresh)*.
51+
52+
def format_axes(ax, title=None):
53+
"""A helper function to better visualize properties of the symlog scale."""
54+
ax.xaxis.get_minor_locator().set_params(subs=[2, 3, 4, 5, 6, 7, 8, 9])
55+
ax.grid()
56+
ax.xaxis.grid(which='minor') # minor grid on too
57+
linthresh = ax.xaxis.get_transform().linthresh
58+
linscale = ax.xaxis.get_transform().linscale
59+
ax.axvspan(-linthresh, linthresh, color='0.9')
60+
if title:
61+
ax.set_title(title.format(linthresh=linthresh, linscale=linscale))
62+
63+
x = np.linspace(-60, 60, 201)
64+
y = np.linspace(0, 100.0, 201)
65+
66+
fig, (ax1, ax2) = plt.subplots(nrows=2, layout="constrained")
67+
68+
ax1.plot(x, y)
69+
ax1.set_xscale('symlog', linthresh=1)
70+
format_axes(ax1, title='Linear region: linthresh={linthresh}')
71+
72+
ax2.plot(x, y)
73+
ax2.set_xscale('symlog', linthresh=5)
74+
format_axes(ax2, title='Linear region: linthresh={linthresh}')
75+
76+
# %%
77+
# Generally, *linthresh* should be chosen so that no or only a few
78+
# data points are in the linear region. As a rule of thumb,
79+
# :math:`linthresh \approx min(abs(data))`.
80+
#
81+
#
82+
# Linear scale
83+
# ------------
84+
# Additionally, the *linscale* parameter determines how much visual space should be
85+
# used for the linear range. More precisely, it defines the ratio of visual space
86+
# of the region (0, linthresh) relative to one decade.
87+
88+
fig, (ax1, ax2) = plt.subplots(nrows=2, layout="constrained")
89+
90+
ax1.plot(x, y)
91+
ax1.set_xscale('symlog', linthresh=1)
92+
format_axes(ax1, title='Linear region: linthresh={linthresh}, linscale={linscale}')
93+
94+
ax2.plot(x, y)
95+
ax2.set_xscale('symlog', linthresh=1, linscale=0.1)
96+
format_axes(ax2, title='Linear region: linthresh={linthresh}, linscale={linscale}')
4197

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+
# The ``asinh`` axis scale is an alternative transfromation that supports a wide
114+
# dynamic range with a smooth gradient and thus may avoid such visual artifacts.
115+
# See :doc:`/gallery/scales/assinh_demo`.
116+
#
42117
# %%
43118
#
44119
# .. admonition:: References

lib/matplotlib/scale.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ class SymmetricalLogScale(ScaleBase):
412412
*linthresh* allows the user to specify the size of this range
413413
(-*linthresh*, *linthresh*).
414414
415+
See :doc:`/gallery/scales/symlog_demo` for a detailed description.
416+
415417
Parameters
416418
----------
417419
base : float, default: 10

0 commit comments

Comments
 (0)