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

Skip to content

Commit bebc51a

Browse files
authored
Merge pull request #16541 from tacaswell/auto-backport-of-pr-16404-on-v3.2.x
Merge pull request #16404 from jklymak/fix-add-base-symlognorm
2 parents d15be69 + 86c7e6c commit bebc51a

File tree

6 files changed

+77
-26
lines changed

6 files changed

+77
-26
lines changed

doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,15 @@ mplot3d auto-registration
307307
longer necessary to import mplot3d to create 3d axes with ::
308308

309309
ax = fig.add_subplot(111, projection="3d")
310+
311+
`.SymLogNorm` now has a *base* parameter
312+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
313+
314+
Previously, `.SymLogNorm` had no *base* keyword argument and the base was
315+
hard-coded to ``base=np.e``. This was inconsistent with the default
316+
behavior of `.SymLogScale` (which defaults to ``base=10``) and the use
317+
of the word "decade" in the documentation.
318+
319+
In preparation for changing the default base to 10, calling
320+
`.SymLogNorm` without the new *base* kwarg emits a deprecation
321+
warning.

examples/userdemo/colormap_normalizations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969

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

examples/userdemo/colormap_normalizations_symlognorm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

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

lib/matplotlib/colors.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,25 +1209,47 @@ class SymLogNorm(Normalize):
12091209
*linthresh* allows the user to specify the size of this range
12101210
(-*linthresh*, *linthresh*).
12111211
"""
1212-
def __init__(self, linthresh, linscale=1.0,
1213-
vmin=None, vmax=None, clip=False):
1212+
def __init__(self, linthresh, linscale=1.0, vmin=None, vmax=None,
1213+
clip=False, *, base=None):
12141214
"""
1215-
*linthresh*:
1216-
The range within which the plot is linear (to
1217-
avoid having the plot go to infinity around zero).
1218-
1219-
*linscale*:
1220-
This allows the linear range (-*linthresh* to *linthresh*)
1221-
to be stretched relative to the logarithmic range. Its
1222-
value is the number of decades to use for each half of the
1223-
linear range. For example, when *linscale* == 1.0 (the
1224-
default), the space used for the positive and negative
1225-
halves of the linear range will be equal to one decade in
1226-
the logarithmic range. Defaults to 1.
1215+
Parameters
1216+
----------
1217+
linthresh : float
1218+
The range within which the plot is linear (to avoid having the plot
1219+
go to infinity around zero).
1220+
linscale : float, default: 1
1221+
This allows the linear range (-*linthresh* to *linthresh*)
1222+
to be stretched relative to the logarithmic range. Its
1223+
value is the number of powers of *base* to use for each
1224+
half of the linear range.
1225+
1226+
For example, when *linscale* == 1.0 (the default) and
1227+
``base=10``, then space used for the positive and negative
1228+
halves of the linear range will be equal to a decade in
1229+
the logarithmic.
1230+
1231+
base : float, default: None
1232+
If not given, defaults to ``np.e`` (consistent with prior
1233+
behavior) and warns.
1234+
1235+
In v3.3 the default value will change to 10 to be consistent with
1236+
`.SymLogNorm`.
1237+
1238+
To suppress the warning pass *base* as a keyword argument.
1239+
12271240
"""
12281241
Normalize.__init__(self, vmin, vmax, clip)
1242+
if base is None:
1243+
self._base = np.e
1244+
cbook.warn_deprecated("3.3", message="default base may change "
1245+
"from np.e to 10. To suppress this warning specify the base "
1246+
"keyword argument.")
1247+
else:
1248+
self._base = base
1249+
self._log_base = np.log(self._base)
1250+
12291251
self.linthresh = float(linthresh)
1230-
self._linscale_adj = (linscale / (1.0 - np.e ** -1))
1252+
self._linscale_adj = (linscale / (1.0 - self._base ** -1))
12311253
if vmin is not None and vmax is not None:
12321254
self._transform_vmin_vmax()
12331255

@@ -1262,7 +1284,8 @@ def _transform(self, a):
12621284
with np.errstate(invalid="ignore"):
12631285
masked = np.abs(a) > self.linthresh
12641286
sign = np.sign(a[masked])
1265-
log = (self._linscale_adj + np.log(np.abs(a[masked]) / self.linthresh))
1287+
log = (self._linscale_adj +
1288+
np.log(np.abs(a[masked]) / self.linthresh) / self._log_base)
12661289
log *= sign * self.linthresh
12671290
a[masked] = log
12681291
a[~masked] *= self._linscale_adj
@@ -1272,7 +1295,8 @@ def _inv_transform(self, a):
12721295
"""Inverse inplace Transformation."""
12731296
masked = np.abs(a) > (self.linthresh * self._linscale_adj)
12741297
sign = np.sign(a[masked])
1275-
exp = np.exp(sign * a[masked] / self.linthresh - self._linscale_adj)
1298+
exp = np.power(self._base,
1299+
sign * a[masked] / self.linthresh - self._linscale_adj)
12761300
exp *= sign * self.linthresh
12771301
a[masked] = exp
12781302
a[~masked] /= self._linscale_adj

lib/matplotlib/tests/test_colors.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ def test_SymLogNorm():
388388
"""
389389
Test SymLogNorm behavior
390390
"""
391-
norm = mcolors.SymLogNorm(3, vmax=5, linscale=1.2)
391+
norm = mcolors.SymLogNorm(3, vmax=5, linscale=1.2, base=np.e)
392392
vals = np.array([-30, -1, 2, 6], dtype=float)
393393
normed_vals = norm(vals)
394394
expected = [0., 0.53980074, 0.826991, 1.02758204]
@@ -398,16 +398,30 @@ def test_SymLogNorm():
398398
_mask_tester(norm, vals)
399399

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

405+
# test something more easily checked.
406+
norm = mcolors.SymLogNorm(1, vmin=-np.e**3, vmax=np.e**3, base=np.e)
407+
nn = norm([-np.e**3, -np.e**2, -np.e**1, -1,
408+
0, 1, np.e**1, np.e**2, np.e**3])
409+
xx = np.array([0., 0.109123, 0.218246, 0.32737, 0.5, 0.67263,
410+
0.781754, 0.890877, 1.])
411+
assert_array_almost_equal(nn, xx)
412+
norm = mcolors.SymLogNorm(1, vmin=-10**3, vmax=10**3, base=10)
413+
nn = norm([-10**3, -10**2, -10**1, -1,
414+
0, 1, 10**1, 10**2, 10**3])
415+
xx = np.array([0., 0.121622, 0.243243, 0.364865, 0.5, 0.635135,
416+
0.756757, 0.878378, 1.])
417+
assert_array_almost_equal(nn, xx)
418+
405419

406420
def test_SymLogNorm_colorbar():
407421
"""
408422
Test un-called SymLogNorm in a colorbar.
409423
"""
410-
norm = mcolors.SymLogNorm(0.1, vmin=-1, vmax=1, linscale=1)
424+
norm = mcolors.SymLogNorm(0.1, vmin=-1, vmax=1, linscale=1, base=np.e)
411425
fig = plt.figure()
412426
mcolorbar.ColorbarBase(fig.add_subplot(111), norm=norm)
413427
plt.close(fig)
@@ -418,7 +432,7 @@ def test_SymLogNorm_single_zero():
418432
Test SymLogNorm to ensure it is not adding sub-ticks to zero label
419433
"""
420434
fig = plt.figure()
421-
norm = mcolors.SymLogNorm(1e-5, vmin=-1, vmax=1)
435+
norm = mcolors.SymLogNorm(1e-5, vmin=-1, vmax=1, base=np.e)
422436
cbar = mcolorbar.ColorbarBase(fig.add_subplot(111), norm=norm)
423437
ticks = cbar.get_ticks()
424438
assert sum(ticks == 0) == 1
@@ -895,9 +909,10 @@ def __add__(self, other):
895909
mydata = data.view(MyArray)
896910

897911
for norm in [mcolors.Normalize(), mcolors.LogNorm(),
898-
mcolors.SymLogNorm(3, vmax=5, linscale=1),
912+
mcolors.SymLogNorm(3, vmax=5, linscale=1, base=np.e),
899913
mcolors.Normalize(vmin=mydata.min(), vmax=mydata.max()),
900-
mcolors.SymLogNorm(3, vmin=mydata.min(), vmax=mydata.max()),
914+
mcolors.SymLogNorm(3, vmin=mydata.min(), vmax=mydata.max(),
915+
base=np.e),
901916
mcolors.PowerNorm(1)]:
902917
assert_array_equal(norm(mydata), norm(data))
903918
fig, ax = plt.subplots()

tutorials/colors/colormapnorms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898

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

0 commit comments

Comments
 (0)