From 1a2c4b08bd098501cc8cf89274449632936c162e Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 26 Jul 2016 02:45:03 -0700 Subject: [PATCH 1/2] Fix Normalize(). Basically, everything needs to be cast to a float early enough. --- lib/matplotlib/colors.py | 7 +++++-- lib/matplotlib/tests/test_colors.py | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 73e0c8570794..cb2e12e7afd9 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -903,7 +903,9 @@ def __call__(self, value, clip=None): result, is_scalar = self.process_value(value) self.autoscale_None(result) - vmin, vmax = self.vmin, self.vmax + # Convert at least to float, without losing precision. + (vmin,), _ = self.process_value(self.vmin) + (vmax,), _ = self.process_value(self.vmax) if vmin == vmax: result.fill(0) # Or should it be all masked? Or 0.5? elif vmin > vmax: @@ -927,7 +929,8 @@ def __call__(self, value, clip=None): def inverse(self, value): if not self.scaled(): raise ValueError("Not invertible until scaled") - vmin, vmax = self.vmin, self.vmax + (vmin,), _ = self.process_value(self.vmin) + (vmax,), _ = self.process_value(self.vmax) if cbook.iterable(value): val = np.ma.asarray(value) diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 5d2fa68b0161..5f5c4855e446 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -194,6 +194,12 @@ def test_Normalize(): _scalar_tester(norm, vals) _mask_tester(norm, vals) + # Handle integer input correctly (don't overflow when computing max-min, + # i.e. 127-(-128) here). + vals = np.array([-128, 127], dtype=np.int8) + norm = mcolors.Normalize(vals.min(), vals.max()) + assert_array_equal(np.asarray(norm(vals)), [0, 1]) + # Don't lose precision on longdoubles (float128 on Linux): # for array inputs... vals = np.array([1.2345678901, 9.8765432109], dtype=np.longdouble) From ac0c85ad1ac902024aedb8cef01c5473571d6cf9 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 26 Jul 2016 16:59:59 -0700 Subject: [PATCH 2/2] Fix float normalization too (float32->float32). --- lib/matplotlib/colors.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index cb2e12e7afd9..8a7e99faa988 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -884,8 +884,9 @@ def process_value(value): if is_scalar: value = [value] dtype = np.min_scalar_type(value) - dtype = (np.float32 if dtype.itemsize <= 2 - else np.promote_types(dtype, float)) + if np.issubdtype(dtype, np.integer) or dtype.type is np.bool_: + # bool_/int8/int16 -> float32; int32/int64 -> float64 + dtype = np.promote_types(dtype, np.float32) result = np.ma.array(value, dtype=dtype, copy=True) return result, is_scalar