diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 12df09ff5f58..f7cfb0786539 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -47,7 +47,6 @@ from collections import Sized import itertools import re -import warnings import numpy as np import matplotlib.cbook as cbook @@ -1170,8 +1169,8 @@ def autoscale_None(self, A): class PowerNorm(Normalize): """ - Normalize a given value to the ``[0, 1]`` interval with a power-law - scaling. This will clip any negative data points to 0. + Linearly map a given value to the 0-1 range and then apply + a power-law normalization over that range. """ def __init__(self, gamma, vmin=None, vmax=None, clip=False): Normalize.__init__(self, vmin, vmax, clip) @@ -1191,18 +1190,17 @@ def __call__(self, value, clip=None): elif vmin == vmax: result.fill(0) else: - res_mask = result.data < 0 if clip: mask = np.ma.getmask(result) result = np.ma.array(np.clip(result.filled(vmax), vmin, vmax), mask=mask) resdat = result.data resdat -= vmin + resdat[resdat < 0] = 0 np.power(resdat, gamma, resdat) resdat /= (vmax - vmin) ** gamma result = np.ma.array(resdat, mask=result.mask, copy=False) - result[res_mask] = 0 if is_scalar: result = result[0] return result @@ -1224,10 +1222,6 @@ def autoscale(self, A): Set *vmin*, *vmax* to min, max of *A*. """ self.vmin = np.ma.min(A) - if self.vmin < 0: - self.vmin = 0 - warnings.warn("Power-law scaling on negative values is " - "ill-defined, clamping to 0.") self.vmax = np.ma.max(A) def autoscale_None(self, A): @@ -1235,10 +1229,6 @@ def autoscale_None(self, A): A = np.asanyarray(A) if self.vmin is None and A.size: self.vmin = A.min() - if self.vmin < 0: - self.vmin = 0 - warnings.warn("Power-law scaling on negative values is " - "ill-defined, clamping to 0.") if self.vmax is None and A.size: self.vmax = A.max() diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index bbbc712c7399..2f221f07d036 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -186,6 +186,15 @@ def test_PowerNorm(): assert pnorm(a[-1], clip=True) == expected[-1] +def test_PowerNorm_translation_invariance(): + a = np.array([0, 1/2, 1], dtype=float) + expected = [0, 1/8, 1] + pnorm = mcolors.PowerNorm(vmin=0, vmax=1, gamma=3) + assert_array_almost_equal(pnorm(a), expected) + pnorm = mcolors.PowerNorm(vmin=-2, vmax=-1, gamma=3) + assert_array_almost_equal(pnorm(a - 2), expected) + + def test_Normalize(): norm = mcolors.Normalize() vals = np.arange(-10, 10, 1, dtype=float) @@ -697,13 +706,7 @@ def __add__(self, other): fig, ax = plt.subplots() ax.imshow(mydata, norm=norm) fig.canvas.draw() - if isinstance(norm, mcolors.PowerNorm): - assert len(recwarn) == 1 - warn = recwarn.pop(UserWarning) - assert ('Power-law scaling on negative values is ill-defined' - in str(warn.message)) - else: - assert len(recwarn) == 0 + assert len(recwarn) == 0 recwarn.clear()