Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Colormap byteorder bug #1095

Merged
merged 4 commits into from

2 participants

@efiring
Owner

Closes #1005.
I considered trying to work around the underlying putmask problem by modifying our putmask, but concluded this was more trouble than it was worth; the bug seems to involve only the most special and obscure circumstances, which we happened to be triggering when substituting the number slightly less than unity for values of 1.0, and only when the input byte order is not native.
The solution in this pull request is to change the byte order to native before proceding with the putmask and other calculations in the Colormap.__call_
() method

@mdboom
Owner

+1

@efiring efiring merged commit f927517 into matplotlib:master
@efiring efiring deleted the efiring:colormap_byteorder_bug branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
1  lib/matplotlib/__init__.py
@@ -1008,6 +1008,7 @@ def tk_window_focus():
'matplotlib.tests.test_basic',
'matplotlib.tests.test_cbook',
'matplotlib.tests.test_colorbar',
+ 'matplotlib.tests.test_colors',
'matplotlib.tests.test_dates',
'matplotlib.tests.test_delaunay',
'matplotlib.tests.test_figure',
View
13 lib/matplotlib/colors.py
@@ -515,10 +515,17 @@ def __call__(self, X, alpha=None, bytes=False):
xa = xma.filled() # Fill to avoid infs, etc.
del xma
- if xa.dtype.char in np.typecodes['Float']:
+ # Calculations with native byteorder are faster, and avoid a
+ # bug that otherwise can occur with putmask when the last
+ # argument is a numpy scalar.
+ if not xa.dtype.isnative:
+ xa = xa.byteswap().newbyteorder()
+
+ if xa.dtype.kind == "f":
# Treat 1.0 as slightly less than 1.
- cbook._putmask(xa, xa==1.0, np.nextafter(xa.dtype.type(1),
- xa.dtype.type(0)))
+ vals = np.array([1, 0], dtype=xa.dtype)
+ almost_one = np.nextafter(*vals)
+ cbook._putmask(xa, xa==1.0, almost_one)
# The following clip is fast, and prevents possible
# conversion of large positive values to negative integers.
View
26 lib/matplotlib/tests/test_colors.py
@@ -0,0 +1,26 @@
+"""
+Tests for the colors module.
+"""
+
+from __future__ import print_function
+import numpy as np
+from numpy.testing.utils import assert_array_equal
+import matplotlib.colors as mcolors
+import matplotlib.cm as cm
+
+def test_colormap_endian():
+ """
+ Github issue #1005: a bug in putmask caused erroneous
+ mapping of 1.0 when input from a non-native-byteorder
+ array.
+ """
+ cmap = cm.get_cmap("jet")
+ # Test under, over, and invalid along with values 0 and 1.
+ a = [-0.5, 0, 0.5, 1, 1.5, np.nan]
+ for dt in ["f2", "f4", "f8"]:
+ anative = np.ma.masked_invalid(np.array(a, dtype=dt))
+ aforeign = anative.byteswap().newbyteorder()
+ #print(anative.dtype.isnative, aforeign.dtype.isnative)
+ assert_array_equal(cmap(anative), cmap(aforeign))
+
+
Something went wrong with that request. Please try again.