Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2157863

Browse filesBrowse files
Kojoleytacaswell
authored andcommitted
Merge pull request #16404 from jklymak/fix-add-base-symlognorm
FIX: add base kwarg to symlognor Conflicts: doc/api/next_api_changes/behaviour.rst - moved to doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst and re-worded. lib/matplotlib/colors.py - implicitly backported converting the docstring to numpy doc style. Re-worded new docstring
1 parent 0900819 commit 2157863
Copy full SHA for 2157863

File tree

Expand file treeCollapse file tree

6 files changed

+74
-26
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+74
-26
lines changed

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

Copy file name to clipboardExpand all lines: doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst
+12Lines 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* kwarg 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

Copy file name to clipboardExpand all lines: examples/userdemo/colormap_normalizations.py
+1-1Lines 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

Copy file name to clipboardExpand all lines: examples/userdemo/colormap_normalizations_symlognorm.py
+1-1Lines 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

Copy file name to clipboardExpand all lines: lib/matplotlib/colors.py
+38-17Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,25 +1209,44 @@ 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*) to be
1222+
stretched relative to the logarithmic range. Its value is the
1223+
number of powers of *base* (decades for base 10) to use for each
1224+
half of the linear range. For example, when *linscale* == 1.0
1225+
(the default), the space used for the positive and negative halves
1226+
of the linear range will be equal to a decade in the logarithmic
1227+
range if ``base=10``.
1228+
base : float, default: None
1229+
If not given, defaults to ``np.e``, consistent with prior
1230+
behavior and warns.
1231+
1232+
In v3.3 the default value will change to 10 to be consistent with
1233+
`.SymLogNorm`.
1234+
1235+
To suppress the warning pass base as a kwarg.
1236+
12271237
"""
12281238
Normalize.__init__(self, vmin, vmax, clip)
1239+
if base is None:
1240+
self._base = np.e
1241+
cbook.warn_deprecated("3.3", message="default base may change "
1242+
"from np.e to 10. To suppress this warning specify the base "
1243+
"kwarg.")
1244+
else:
1245+
self._base = base
1246+
self._log_base = np.log(self._base)
1247+
12291248
self.linthresh = float(linthresh)
1230-
self._linscale_adj = (linscale / (1.0 - np.e ** -1))
1249+
self._linscale_adj = (linscale / (1.0 - self._base ** -1))
12311250
if vmin is not None and vmax is not None:
12321251
self._transform_vmin_vmax()
12331252

@@ -1262,7 +1281,8 @@ def _transform(self, a):
12621281
with np.errstate(invalid="ignore"):
12631282
masked = np.abs(a) > self.linthresh
12641283
sign = np.sign(a[masked])
1265-
log = (self._linscale_adj + np.log(np.abs(a[masked]) / self.linthresh))
1284+
log = (self._linscale_adj +
1285+
np.log(np.abs(a[masked]) / self.linthresh) / self._log_base)
12661286
log *= sign * self.linthresh
12671287
a[masked] = log
12681288
a[~masked] *= self._linscale_adj
@@ -1272,7 +1292,8 @@ def _inv_transform(self, a):
12721292
"""Inverse inplace Transformation."""
12731293
masked = np.abs(a) > (self.linthresh * self._linscale_adj)
12741294
sign = np.sign(a[masked])
1275-
exp = np.exp(sign * a[masked] / self.linthresh - self._linscale_adj)
1295+
exp = np.power(self._base,
1296+
sign * a[masked] / self.linthresh - self._linscale_adj)
12761297
exp *= sign * self.linthresh
12771298
a[masked] = exp
12781299
a[~masked] /= self._linscale_adj

‎lib/matplotlib/tests/test_colors.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_colors.py
+21-6Lines 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

Copy file name to clipboardExpand all lines: tutorials/colors/colormapnorms.py
+1-1Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.