From df133ef356d80e18726136db0c8c2865e08b67d7 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sat, 8 Apr 2017 14:51:47 -0700 Subject: [PATCH] Let imshow handle float128 data. --- lib/matplotlib/colors.py | 7 ++++++- lib/matplotlib/image.py | 16 ++++++++-------- lib/matplotlib/tests/test_image.py | 21 +++++++++++++-------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 59c17c8a9392..a97744611a3d 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -188,7 +188,7 @@ def _to_rgba_no_colorcycle(c, alpha=None): raise ValueError("Invalid RGBA argument: {!r}".format(orig_c)) # tuple color. c = np.array(c) - if not np.can_cast(c.dtype, float) or c.ndim != 1: + if not np.can_cast(c.dtype, float, "same_kind") or c.ndim != 1: # Test the dtype explicitly as `map(float, ...)`, `np.array(..., # float)` and `np.array(...).astype(float)` all convert "0.5" to 0.5. # Test dimensionality to reject single floats. @@ -934,6 +934,11 @@ def __call__(self, value, clip=None): resdat -= vmin resdat /= (vmax - vmin) result = np.ma.array(resdat, mask=result.mask, copy=False) + # Agg cannot handle float128. We actually only need 32-bit of + # precision, but on Windows, `np.dtype(np.longdouble) == np.float64`, + # so casting to float32 would lose precision on float64s as well. + if result.dtype == np.longdouble: + result = result.astype(np.float64) if is_scalar: result = result[0] return result diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 19dfb16615f3..6a4de30365f6 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -299,9 +299,9 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, space. """ if A is None: - raise RuntimeError('You must first set the image' - ' array or the image attribute') - if any(s == 0 for s in A.shape): + raise RuntimeError('You must first set the image ' + 'array or the image attribute') + if A.size == 0: raise RuntimeError("_make_image must get a non-empty image. " "Your Artist's draw method must filter before " "this method is called.") @@ -359,7 +359,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, created_rgba_mask = False if A.ndim not in (2, 3): - raise ValueError("Invalid dimensions, got %s" % (A.shape,)) + raise ValueError("Invalid dimensions, got {}".format(A.shape)) if A.ndim == 2: A = self.norm(A) @@ -589,11 +589,11 @@ def set_data(self, A): self._A = cbook.safe_masked_invalid(A, copy=True) if (self._A.dtype != np.uint8 and - not np.can_cast(self._A.dtype, float)): - raise TypeError("Image data can not convert to float") + not np.can_cast(self._A.dtype, float, "same_kind")): + raise TypeError("Image data cannot be converted to float") - if (self._A.ndim not in (2, 3) or - (self._A.ndim == 3 and self._A.shape[-1] not in (3, 4))): + if not (self._A.ndim == 2 + or self._A.ndim == 3 and self._A.shape[-1] in [3, 4]): raise TypeError("Invalid dimensions for image data") self._imcache = None diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index f6ead2c91db2..c94772924a75 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -505,9 +505,9 @@ def test_jpeg_alpha(): def test_nonuniformimage_setdata(): ax = plt.gca() im = NonUniformImage(ax) - x = np.arange(3, dtype=np.float64) - y = np.arange(4, dtype=np.float64) - z = np.arange(12, dtype=np.float64).reshape((4, 3)) + x = np.arange(3, dtype=float) + y = np.arange(4, dtype=float) + z = np.arange(12, dtype=float).reshape((4, 3)) im.set_data(x, y, z) x[0] = y[0] = z[0, 0] = 9.9 assert im._A[0, 0] == im._Ax[0] == im._Ay[0] == 0, 'value changed' @@ -516,7 +516,7 @@ def test_nonuniformimage_setdata(): def test_axesimage_setdata(): ax = plt.gca() im = AxesImage(ax) - z = np.arange(12, dtype=np.float64).reshape((4, 3)) + z = np.arange(12, dtype=float).reshape((4, 3)) im.set_data(z) z[0, 0] = 9.9 assert im._A[0, 0] == 0, 'value changed' @@ -525,7 +525,7 @@ def test_axesimage_setdata(): def test_figureimage_setdata(): fig = plt.gcf() im = FigureImage(fig) - z = np.arange(12, dtype=np.float64).reshape((4, 3)) + z = np.arange(12, dtype=float).reshape((4, 3)) im.set_data(z) z[0, 0] = 9.9 assert im._A[0, 0] == 0, 'value changed' @@ -534,9 +534,9 @@ def test_figureimage_setdata(): def test_pcolorimage_setdata(): ax = plt.gca() im = PcolorImage(ax) - x = np.arange(3, dtype=np.float64) - y = np.arange(4, dtype=np.float64) - z = np.arange(6, dtype=np.float64).reshape((3, 2)) + x = np.arange(3, dtype=float) + y = np.arange(4, dtype=float) + z = np.arange(6, dtype=float).reshape((3, 2)) im.set_data(x, y, z) x[0] = y[0] = z[0, 0] = 9.9 assert im._A[0, 0] == im._Ax[0] == im._Ay[0] == 0, 'value changed' @@ -778,3 +778,8 @@ def test_empty_imshow(): with pytest.raises(RuntimeError): im.make_image(fig._cachedRenderer) + + +def test_imshow_float128(): + fig, ax = plt.subplots() + ax.imshow(np.zeros((3, 3), dtype=np.longdouble))