Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Add asinh axis scaling (*smooth* symmetric logscale)#21178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from26 commits
7ec127a
15ff4ec
9680432
3f69788
dd4f4d8
1ec0b22
2b0d588
2002cb3
070d984
8495f7b
279c38b
76d9b42
8143153
800ef38
0ad43a5
ba597de
80f2600
65eff09
8168e56
0249861
9fd8b0c
8d7c2ad
ae57d8d
b01d03c
e0dcff7
3d92406
7bec3f4
97693e8
a1af12c
4b23326
555bac1
545faf2
a2b210d
8a258cf
5a03297
de30538
3e487a6
c64d0c4
e43cbfd
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -21,6 +21,7 @@ Classes | ||
:toctree: _as_gen/ | ||
:template: autosummary.rst | ||
AsinhNorm | ||
BoundaryNorm | ||
Colormap | ||
CenteredNorm | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
New axis scale ``asinh`` | ||
------------------------ | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
The new ``asinh`` axis scale offers an alternative to ``symlog`` that | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
smoothly transitions between the quasi-linear and asymptotically logarithmic | ||
regions of the scale. This is based on an arcsinh transformation that | ||
allows plotting both positive and negative values that span many orders | ||
of magnitude. A scale parameter is provided to allow the user | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I don't know if we want to put in mention of the scale parameter in the release notes or not...? If so, we should probably use it in the example below? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Perhaps you're right that the scale-parameter is too much detail for inclusion the release notes. | ||
to tune the width of the linear region of the scale. | ||
.. plot:: | ||
import matplotlib.pyplot as plt | ||
import numpy | ||
fig, (ax0, ax1) = plt.subplots(1, 2, sharex=True) | ||
x = numpy.linspace(-3, 6, 100) | ||
QuLogic marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
ax0.plot(x, x) | ||
ax0.set_yscale('symlog') | ||
ax0.grid() | ||
ax0.set_title('symlog') | ||
ax1.plot(x, x) | ||
ax1.set_yscale('asinh') | ||
ax1.grid() | ||
ax1.set_title(r'$sinh^{-1}$') | ||
for p in (-2, 2): | ||
for ax in (ax0, ax1): | ||
c = plt.Circle((p, p), radius=0.5, fill=False, | ||
color='red', alpha=0.8, lw=3) | ||
ax.add_patch(c) | ||
QuLogic marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,85 @@ | ||
""" | ||
================================== | ||
Colormap NormalizationsSymLogNorm | ||
================================== | ||
Demonstration of using norm to map colormaps onto data in non-linear ways. | ||
.. redirect-from:: /gallery/userdemo/colormap_normalization_symlognorm | ||
""" | ||
######################################## | ||
QuLogic marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
# Synthetic dataset consisting of two humps, one negative and one positive, | ||
# the positive with 8-times the amplitude. | ||
# Linearly, the negative hump is almost invisible, | ||
# and it is very difficult to see any detail of its profile. | ||
# With the logarithmic scaling applied to both positive and negative values, | ||
# it is much easier to see the shape of each hump. | ||
# | ||
# See `~.colors.SymLogNorm`. | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
import matplotlib.colors as colors | ||
def rbf(x, y): | ||
return 1.0 / (1 + 5 * ((x ** 2) + (y ** 2))) | ||
N = 200 | ||
gain = 8 | ||
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)] | ||
Z1 = rbf(X + 0.5, Y + 0.5) | ||
Z2 = rbf(X - 0.5, Y - 0.5) | ||
Z = gain * Z1 - Z2 | ||
shadeopts = {'cmap': 'PRGn', 'shading': 'gouraud'} | ||
colormap = 'PRGn' | ||
lnrwidth = 0.2 | ||
fig, ax = plt.subplots(2, 1, sharex=True, sharey=True) | ||
pcm = ax[0].pcolormesh(X, Y, Z, | ||
norm=colors.SymLogNorm(linthresh=lnrwidth, linscale=1, | ||
vmin=-gain, vmax=gain, base=10), | ||
**shadeopts) | ||
fig.colorbar(pcm, ax=ax[0], extend='both') | ||
ax[0].text(-2.5, 1.5, 'symlog') | ||
pcm = ax[1].pcolormesh(X, Y, Z,vmin=-gain, vmax=gain, | ||
**shadeopts) | ||
fig.colorbar(pcm, ax=ax[1], extend='both') | ||
ax[1].text(-2.5, 1.5, 'linear') | ||
######################################## | ||
# Clearly, tt may be necessary to experiment with multiple different | ||
# colorscales in order to find the best visualization for | ||
# any particular dataset. | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
# As well as the `~.colors.SymLogNorm` scaling, there is also | ||
# the option of using the `~.colors.AsinhNorm`, which has a smoother | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
# transition between the linear and logarithmic regions of the transformation | ||
# applied to the "z" axis. | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
# In the plots below, it may be possible to see ring-like artifacts | ||
# in the lower-amplitude, negative, hump shown in purple despite | ||
# there being no sharp features in the dataset itself. | ||
# The ``asinh`` scaling shows a smoother shading of each hump. | ||
fig, ax = plt.subplots(2, 1, sharex=True, sharey=True) | ||
pcm = ax[0].pcolormesh(X, Y, Z, | ||
norm=colors.SymLogNorm(linthresh=lnrwidth, linscale=1, | ||
vmin=-2, vmax=gain, base=10), | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
**shadeopts) | ||
fig.colorbar(pcm, ax=ax[0], extend='both') | ||
ax[0].text(-2.5, 1.5, 'symlog') | ||
pcm = ax[1].pcolormesh(X, Y, Z, | ||
norm=colors.AsinhNorm(linear_width=lnrwidth, | ||
vmin=-2, vmax=gain), | ||
**shadeopts) | ||
fig.colorbar(pcm, ax=ax[1], extend='both') | ||
ax[1].text(-2.5, 1.5, 'asinh') | ||
plt.show() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
""" | ||
============ | ||
Asinh Demo | ||
============ | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
Illustration of the `asinh <.scale.AsinhScale>` axis scaling, | ||
which uses the transformation | ||
.. math:: | ||
a \\rightarrow a_0 \\sinh^{-1} (a / a_0) | ||
For coordinate values close to zero (i.e. much smaller than | ||
the "linear width" :math:`a_0`), this leaves values essentially unchanged: | ||
.. math:: | ||
a \\rightarrow a + {\\cal O}(a^3) | ||
but for larger values (i.e. :math:`|a| \\gg a_0`, this is asymptotically | ||
.. math:: | ||
a \\rightarrow a_0 \\, {\\rm sgn}(a) \\ln |a| + {\\cal O}(1) | ||
As with the `symlog <.scale.SymmetricalLogScale>` scaling, | ||
this allows one to plot quantities | ||
that cover a very wide dynamic range that includes both positive | ||
and negative values. However, ``symlog`` involves a transformation | ||
that has discontinuities in its gradient because it is built | ||
from *separate* linear and logarithmic transformations. | ||
The ``asinh`` scaling uses a transformation that is smooth | ||
for all (finite) values, which is both mathematically cleaner | ||
and reduces visual artifacts associated with an abrupt | ||
transition between linear and logarithmic regions of the plot. | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
See `~.scale.AsinhScale`, `~.scale.SymmetricalLogScale`. | ||
""" | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
# Prepare sample values for variations on y=x graph: | ||
x = np.linspace(-3, 6, 500) | ||
######################################## | ||
# Compare "symlog" and "asinh" behaviour on sample y=x graph, | ||
# where there is a discontinuous gradient in "symlog" near y=2: | ||
fig1 = plt.figure() | ||
ax0, ax1 = fig1.subplots(1, 2, sharex=True) | ||
ax0.plot(x, x) | ||
ax0.set_yscale('symlog') | ||
ax0.grid() | ||
ax0.set_title('symlog') | ||
ax1.plot(x, x) | ||
ax1.set_yscale('asinh') | ||
ax1.grid() | ||
ax1.set_title('asinh') | ||
######################################## | ||
# Compare "asinh" graphs with different scale parameter "linear_width": | ||
fig2 = plt.figure(constrained_layout=True) | ||
axs = fig2.subplots(1, 3, sharex=True) | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
for ax, (a0, base) in zip(axs, ((0.2, 2), (1.0, 0), (5.0, 3))): | ||
ax.set_title('linear_width={:.3g}'.format(a0)) | ||
ax.plot(x, x, label='y=x') | ||
ax.plot(x, 10*x, label='y=10x') | ||
ax.plot(x, 100*x, label='y=100x') | ||
ax.set_yscale('asinh', linear_width=a0, base=base) | ||
ax.grid() | ||
ax.legend(loc='best', fontsize='small') | ||
######################################## | ||
# Compare "symlog" and "asinh" scalings | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
# on 2D Cauchy-distributed random numbers, | ||
# where one may be able to see more subtle artifacts near y=2 | ||
# due to the gradient-discontinuity in "symlog": | ||
fig3 = plt.figure() | ||
ax = fig3.subplots(1, 1) | ||
r = 3 * np.tan(np.random.uniform(-np.pi / 2.02, np.pi / 2.02, | ||
size=(5000,))) | ||
th = np.random.uniform(0, 2*np.pi, size=r.shape) | ||
ax.scatter(r * np.cos(th), r * np.sin(th), s=4, alpha=0.5) | ||
ax.set_xscale('asinh') | ||
ax.set_yscale('symlog') | ||
ax.set_xlabel('asinh') | ||
ax.set_ylabel('symlog') | ||
ax.set_title('2D Cauchy random deviates') | ||
ax.set_xlim(-50, 50) | ||
ax.set_ylim(-50, 50) | ||
ax.grid() | ||
plt.show() | ||
######################################## | ||
# | ||
# .. admonition:: References | ||
# | ||
# - `matplotlib.scale.AsinhScale` | ||
# - `matplotlib.ticker.AsinhLocator` | ||
# - `matplotlib.scale.SymmetricalLogScale` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -33,3 +33,17 @@ | ||
fig.tight_layout() | ||
plt.show() | ||
######################################## | ||
# It should be noted that the coordinate transform used by ``symlog`` | ||
# has a discontinuous gradient at the transition between its linear | ||
# and logarithmic regions. The ``asinh`` axis scale is an alternative | ||
# technique that may avoid visual artifacts caused by these disconinuities. | ||
rwpenney marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
######################################## | ||
# | ||
# .. admonition:: References | ||
# | ||
# - `matplotlib.scale.SymmetricalLogScale` | ||
# - `matplotlib.ticker.SymmetricalLogLocator` | ||
# - `matplotlib.scale.AsinhScale` |
Uh oh!
There was an error while loading.Please reload this page.