From ca5b2e07ec183f7c1252fd3cfb3df58befa05bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=9F=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=BE=D0=BD=D0=BE=D0=B2?= Date: Thu, 11 Jan 2018 13:08:37 +0300 Subject: [PATCH 1/3] PowerNorm: do not clip negative values --- lib/matplotlib/colors.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 84d4bbcf1fb0..356e523a91a5 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -53,7 +53,6 @@ from collections import Sized import itertools import re -import warnings import numpy as np import matplotlib.cbook as cbook @@ -1177,7 +1176,7 @@ 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. + scaling. """ def __init__(self, gamma, vmin=None, vmax=None, clip=False): Normalize.__init__(self, vmin, vmax, clip) @@ -1197,7 +1196,6 @@ 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), @@ -1208,7 +1206,6 @@ def __call__(self, value, clip=None): 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 @@ -1230,10 +1227,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): @@ -1241,10 +1234,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() From 5a1ed892eadf86d606f8e5a9dbc244c107ac9a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=9F=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=BE=D0=BD=D0=BE=D0=B2?= Date: Mon, 15 Jan 2018 12:11:29 +0300 Subject: [PATCH 2/3] Fix PowerNorm description --- lib/matplotlib/colors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 356e523a91a5..c3c779b38266 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1175,8 +1175,8 @@ def autoscale_None(self, A): class PowerNorm(Normalize): """ - Normalize a given value to the ``[0, 1]`` interval with a power-law - scaling. + 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) From 0c1b027522e946a2e08ccbee30ed875acc5e8d55 Mon Sep 17 00:00:00 2001 From: Paramonov Andrey Date: Wed, 20 Jun 2018 23:58:51 +0300 Subject: [PATCH 3/3] Fix tests --- lib/matplotlib/colors.py | 1 + lib/matplotlib/tests/test_colors.py | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index c3c779b38266..03d3856a0b9b 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1202,6 +1202,7 @@ def __call__(self, value, clip=None): mask=mask) resdat = result.data resdat -= vmin + resdat[resdat < 0] = 0 np.power(resdat, gamma, resdat) resdat /= (vmax - vmin) ** gamma diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 3b507e8fbd21..90b11866fdc7 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -192,6 +192,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) @@ -711,13 +720,7 @@ def __add__(self, other): mcolors.SymLogNorm(3, vmax=5, linscale=1), mcolors.PowerNorm(1)]: assert_array_equal(norm(data.view(MyArray)), norm(data)) - 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()