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

Skip to content

Merge pull request #16404 from jklymak/fix-add-base-symlognorm #16541

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,15 @@ mplot3d auto-registration
longer necessary to import mplot3d to create 3d axes with ::

ax = fig.add_subplot(111, projection="3d")

`.SymLogNorm` now has a *base* parameter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Previously, `.SymLogNorm` had no *base* keyword argument and the base was
hard-coded to ``base=np.e``. This was inconsistent with the default
behavior of `.SymLogScale` (which defaults to ``base=10``) and the use
of the word "decade" in the documentation.

In preparation for changing the default base to 10, calling
`.SymLogNorm` without the new *base* kwarg emits a deprecation
warning.
2 changes: 1 addition & 1 deletion examples/userdemo/colormap_normalizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@

pcm = ax[0].pcolormesh(X, Y, Z1,
norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,
vmin=-1.0, vmax=1.0),
vmin=-1.0, vmax=1.0, base=10),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')

Expand Down
2 changes: 1 addition & 1 deletion examples/userdemo/colormap_normalizations_symlognorm.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

pcm = ax[0].pcolormesh(X, Y, Z,
norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,
vmin=-1.0, vmax=1.0),
vmin=-1.0, vmax=1.0, base=10),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')

Expand Down
58 changes: 41 additions & 17 deletions lib/matplotlib/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1209,25 +1209,47 @@ class SymLogNorm(Normalize):
*linthresh* allows the user to specify the size of this range
(-*linthresh*, *linthresh*).
"""
def __init__(self, linthresh, linscale=1.0,
vmin=None, vmax=None, clip=False):
def __init__(self, linthresh, linscale=1.0, vmin=None, vmax=None,
clip=False, *, base=None):
"""
*linthresh*:
The range within which the plot is linear (to
avoid having the plot go to infinity around zero).

*linscale*:
This allows the linear range (-*linthresh* to *linthresh*)
to be stretched relative to the logarithmic range. Its
value is the number of decades to use for each half of the
linear range. For example, when *linscale* == 1.0 (the
default), the space used for the positive and negative
halves of the linear range will be equal to one decade in
the logarithmic range. Defaults to 1.
Parameters
----------
linthresh : float
The range within which the plot is linear (to avoid having the plot
go to infinity around zero).
linscale : float, default: 1
This allows the linear range (-*linthresh* to *linthresh*)
to be stretched relative to the logarithmic range. Its
value is the number of powers of *base* to use for each
half of the linear range.

For example, when *linscale* == 1.0 (the default) and
``base=10``, then space used for the positive and negative
halves of the linear range will be equal to a decade in
the logarithmic.

base : float, default: None
If not given, defaults to ``np.e`` (consistent with prior
behavior) and warns.

In v3.3 the default value will change to 10 to be consistent with
`.SymLogNorm`.

To suppress the warning pass *base* as a keyword argument.

"""
Normalize.__init__(self, vmin, vmax, clip)
if base is None:
self._base = np.e
cbook.warn_deprecated("3.3", message="default base may change "
"from np.e to 10. To suppress this warning specify the base "
"keyword argument.")
else:
self._base = base
self._log_base = np.log(self._base)

self.linthresh = float(linthresh)
self._linscale_adj = (linscale / (1.0 - np.e ** -1))
self._linscale_adj = (linscale / (1.0 - self._base ** -1))
if vmin is not None and vmax is not None:
self._transform_vmin_vmax()

Expand Down Expand Up @@ -1262,7 +1284,8 @@ def _transform(self, a):
with np.errstate(invalid="ignore"):
masked = np.abs(a) > self.linthresh
sign = np.sign(a[masked])
log = (self._linscale_adj + np.log(np.abs(a[masked]) / self.linthresh))
log = (self._linscale_adj +
np.log(np.abs(a[masked]) / self.linthresh) / self._log_base)
log *= sign * self.linthresh
a[masked] = log
a[~masked] *= self._linscale_adj
Expand All @@ -1272,7 +1295,8 @@ def _inv_transform(self, a):
"""Inverse inplace Transformation."""
masked = np.abs(a) > (self.linthresh * self._linscale_adj)
sign = np.sign(a[masked])
exp = np.exp(sign * a[masked] / self.linthresh - self._linscale_adj)
exp = np.power(self._base,
sign * a[masked] / self.linthresh - self._linscale_adj)
exp *= sign * self.linthresh
a[masked] = exp
a[~masked] /= self._linscale_adj
Expand Down
27 changes: 21 additions & 6 deletions lib/matplotlib/tests/test_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ def test_SymLogNorm():
"""
Test SymLogNorm behavior
"""
norm = mcolors.SymLogNorm(3, vmax=5, linscale=1.2)
norm = mcolors.SymLogNorm(3, vmax=5, linscale=1.2, base=np.e)
vals = np.array([-30, -1, 2, 6], dtype=float)
normed_vals = norm(vals)
expected = [0., 0.53980074, 0.826991, 1.02758204]
Expand All @@ -398,16 +398,30 @@ def test_SymLogNorm():
_mask_tester(norm, vals)

# Ensure that specifying vmin returns the same result as above
norm = mcolors.SymLogNorm(3, vmin=-30, vmax=5, linscale=1.2)
norm = mcolors.SymLogNorm(3, vmin=-30, vmax=5, linscale=1.2, base=np.e)
normed_vals = norm(vals)
assert_array_almost_equal(normed_vals, expected)

# test something more easily checked.
norm = mcolors.SymLogNorm(1, vmin=-np.e**3, vmax=np.e**3, base=np.e)
nn = norm([-np.e**3, -np.e**2, -np.e**1, -1,
0, 1, np.e**1, np.e**2, np.e**3])
xx = np.array([0., 0.109123, 0.218246, 0.32737, 0.5, 0.67263,
0.781754, 0.890877, 1.])
assert_array_almost_equal(nn, xx)
norm = mcolors.SymLogNorm(1, vmin=-10**3, vmax=10**3, base=10)
nn = norm([-10**3, -10**2, -10**1, -1,
0, 1, 10**1, 10**2, 10**3])
xx = np.array([0., 0.121622, 0.243243, 0.364865, 0.5, 0.635135,
0.756757, 0.878378, 1.])
assert_array_almost_equal(nn, xx)


def test_SymLogNorm_colorbar():
"""
Test un-called SymLogNorm in a colorbar.
"""
norm = mcolors.SymLogNorm(0.1, vmin=-1, vmax=1, linscale=1)
norm = mcolors.SymLogNorm(0.1, vmin=-1, vmax=1, linscale=1, base=np.e)
fig = plt.figure()
mcolorbar.ColorbarBase(fig.add_subplot(111), norm=norm)
plt.close(fig)
Expand All @@ -418,7 +432,7 @@ def test_SymLogNorm_single_zero():
Test SymLogNorm to ensure it is not adding sub-ticks to zero label
"""
fig = plt.figure()
norm = mcolors.SymLogNorm(1e-5, vmin=-1, vmax=1)
norm = mcolors.SymLogNorm(1e-5, vmin=-1, vmax=1, base=np.e)
cbar = mcolorbar.ColorbarBase(fig.add_subplot(111), norm=norm)
ticks = cbar.get_ticks()
assert sum(ticks == 0) == 1
Expand Down Expand Up @@ -895,9 +909,10 @@ def __add__(self, other):
mydata = data.view(MyArray)

for norm in [mcolors.Normalize(), mcolors.LogNorm(),
mcolors.SymLogNorm(3, vmax=5, linscale=1),
mcolors.SymLogNorm(3, vmax=5, linscale=1, base=np.e),
mcolors.Normalize(vmin=mydata.min(), vmax=mydata.max()),
mcolors.SymLogNorm(3, vmin=mydata.min(), vmax=mydata.max()),
mcolors.SymLogNorm(3, vmin=mydata.min(), vmax=mydata.max(),
base=np.e),
mcolors.PowerNorm(1)]:
assert_array_equal(norm(mydata), norm(data))
fig, ax = plt.subplots()
Expand Down
2 changes: 1 addition & 1 deletion tutorials/colors/colormapnorms.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@

pcm = ax[0].pcolormesh(X, Y, Z,
norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,
vmin=-1.0, vmax=1.0),
vmin=-1.0, vmax=1.0, base=10),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')

Expand Down