diff --git a/doc/api/next_api_changes/behaviour.rst b/doc/api/next_api_changes/behaviour.rst index be394fbd4277..3cca24e94df7 100644 --- a/doc/api/next_api_changes/behaviour.rst +++ b/doc/api/next_api_changes/behaviour.rst @@ -85,3 +85,11 @@ Previously, rcParams entries whose values were color-like accepted "spurious" extra letters or characters in the "middle" of the string, e.g. ``"(0, 1a, '0.5')"`` would be interpreted as ``(0, 1, 0.5)``. These extra characters (including the internal quotes) now cause a ValueError to be raised. + +`.SymLogNorm` now has a *base* parameter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously, `.SymLogNorm` had no *base* kwarg, and defaulted to ``base=np.e`` +whereas the documentation said it was ``base=10``. In preparation to make +the default 10, calling `.SymLogNorm` without the new *base* kwarg emits a +deprecation warning. diff --git a/examples/userdemo/colormap_normalizations.py b/examples/userdemo/colormap_normalizations.py index 419a4b5051aa..2844fd9f9646 100644 --- a/examples/userdemo/colormap_normalizations.py +++ b/examples/userdemo/colormap_normalizations.py @@ -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') diff --git a/examples/userdemo/colormap_normalizations_symlognorm.py b/examples/userdemo/colormap_normalizations_symlognorm.py index 780381e43da8..b0fbf0dc30ea 100644 --- a/examples/userdemo/colormap_normalizations_symlognorm.py +++ b/examples/userdemo/colormap_normalizations_symlognorm.py @@ -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') diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 52d2b2438959..5b584cfac2b3 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1202,8 +1202,8 @@ 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): """ Parameters ---------- @@ -1213,14 +1213,29 @@ def __init__(self, linthresh, linscale=1.0, 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 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. + number of powers of *base* (decades for base 10) 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 a decade in the logarithmic + range if ``base=10``. + base : float, default: None + For v3.2 the default is the old value of ``np.e``, but that is + deprecated for v3.3 when base will default to 10. During the + transition, specify the *base* kwarg to avoid a deprecation + warning. """ Normalize.__init__(self, vmin, vmax, clip) + if base is None: + self._base = np.e + cbook.warn_deprecated("3.3", message="default base will change " + "from np.e to 10. To suppress this warning specify the base " + "kwarg.") + 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() @@ -1255,7 +1270,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 @@ -1265,7 +1281,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 diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 05a81e26def3..d1cedfeb141e 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -398,7 +398,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] @@ -408,16 +408,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) @@ -428,7 +442,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 @@ -905,9 +919,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() diff --git a/tutorials/colors/colormapnorms.py b/tutorials/colors/colormapnorms.py index 412278ac45cb..ea982b243207 100644 --- a/tutorials/colors/colormapnorms.py +++ b/tutorials/colors/colormapnorms.py @@ -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') pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy