From 28b4f51a6123e77d042db3e08ee87d804cedaeb7 Mon Sep 17 00:00:00 2001 From: Benjamin Congdon Date: Sat, 29 Oct 2016 20:20:41 -0500 Subject: [PATCH 1/5] Add appropriate error on color size mismatch in `scatter` --- lib/matplotlib/axes/_axes.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 41a4cf168fdd..b09167135404 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3974,14 +3974,15 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, else: try: c_array = np.asanyarray(c, dtype=float) - if c_array.size == x.size: - c = np.ma.ravel(c_array) - else: - # Wrong size; it must not be intended for mapping. - c_array = None except ValueError: # Failed to make a floating-point array; c must be color specs. c_array = None + else: + if c_array.size == x.size: + c = np.ma.ravel(c_array) + elif c_array.size not in (3, 4): + # Wrong size. Not a rgb/rgba and not same size as x + raise ValueError("x and c must be the same size") if c_array is None: colors = c # must be acceptable as PathCollection facecolors From e218bcfb31148f5d68e5bc75e4c802e69f1df140 Mon Sep 17 00:00:00 2001 From: Benjamin Congdon Date: Sun, 30 Oct 2016 05:52:11 -0500 Subject: [PATCH 2/5] Add scatter color len mismatch ValueError test --- lib/matplotlib/tests/test_axes.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 61bd016d1ce7..3edb48f7e70e 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4800,15 +4800,10 @@ def test_fillbetween_cycle(): @cleanup -def test_log_margins(): - plt.rcParams['axes.autolimit_mode'] = 'data' +def test_color_length_mismatch(): + N = 500 + x, y = np.random.rand(N), np.random.rand(N) + colors = np.random.rand(N+1) fig, ax = plt.subplots() - margin = 0.05 - ax.set_xmargin(margin) - ax.semilogx([1, 10], [1, 10]) - xlim0, xlim1 = ax.get_xlim() - transform = ax.xaxis.get_transform() - xlim0t, xlim1t = transform.transform([xlim0, xlim1]) - x0t, x1t = transform.transform([1, 10]) - delta = (x1t - x0t) * margin - assert_allclose([xlim0t + delta, xlim1t - delta], [x0t, x1t]) + with pytest.raises(ValueError): + ax.scatter(x, y, c=colors) From d03b0e0a2cb68d862072355d3a4c0f7d6587d8cd Mon Sep 17 00:00:00 2001 From: Benjamin Congdon Date: Mon, 31 Oct 2016 06:42:16 -0500 Subject: [PATCH 3/5] Refactor c_array checking; Lower N in color len mismatch test --- lib/matplotlib/axes/_axes.py | 17 +++++++++++------ lib/matplotlib/tests/test_axes.py | 9 ++++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index b09167135404..2b057c993a93 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3952,6 +3952,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, # np.ma.ravel yields an ndarray, not a masked array, # unless its argument is a masked array. + xy_shape = (np.shape(x), np.shape(y)) x = np.ma.ravel(x) y = np.ma.ravel(y) if x.size != y.size: @@ -3974,18 +3975,22 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, else: try: c_array = np.asanyarray(c, dtype=float) + if c_array.shape in xy_shape: + c = np.ma.ravel(c_array) + else: + # Wrong size; it must not be intended for mapping. + c_array = None except ValueError: # Failed to make a floating-point array; c must be color specs. c_array = None - else: - if c_array.size == x.size: - c = np.ma.ravel(c_array) - elif c_array.size not in (3, 4): - # Wrong size. Not a rgb/rgba and not same size as x - raise ValueError("x and c must be the same size") if c_array is None: colors = c # must be acceptable as PathCollection facecolors + try: + mcolors.to_rgba_array(colors) + except ValueError: + # c not acceptable as PathCollection facecolor + raise ValueError("c not acceptable as color sequence") else: colors = None # use cmap, norm after collection is created diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 3edb48f7e70e..dd9c298575dc 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4801,9 +4801,12 @@ def test_fillbetween_cycle(): @cleanup def test_color_length_mismatch(): - N = 500 - x, y = np.random.rand(N), np.random.rand(N) - colors = np.random.rand(N+1) + N = 5 + x, y = np.arange(N), np.arange(N) + colors = np.arange(N+1) fig, ax = plt.subplots() with pytest.raises(ValueError): ax.scatter(x, y, c=colors) + c_rgb = (0.5, 0.5, 0.5) + ax.scatter(x, y, c=c_rgb) + ax.scatter(x, y, c=[c_rgb] * N) \ No newline at end of file From 65e6a6463810b8ae1c2d0c9488e798511fd56394 Mon Sep 17 00:00:00 2001 From: Benjamin Congdon Date: Mon, 31 Oct 2016 09:14:48 -0500 Subject: [PATCH 4/5] Add c, x, y shapes to unacceptable color sequence ValueError message --- lib/matplotlib/axes/_axes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 2b057c993a93..c50e3e370c2c 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3990,7 +3990,9 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, mcolors.to_rgba_array(colors) except ValueError: # c not acceptable as PathCollection facecolor - raise ValueError("c not acceptable as color sequence") + msg = ("c of shape {0} not acceptable as a color sequence " + "for x with shape {1}, y with shape {2}") + raise ValueError(msg.format(c.shape, x.shape, y.shape)) else: colors = None # use cmap, norm after collection is created From 49e71560c08da9af1ac6d519bb55c96ca8a2edf6 Mon Sep 17 00:00:00 2001 From: Benjamin Congdon Date: Wed, 9 Nov 2016 06:03:52 -0600 Subject: [PATCH 5/5] Scatter color ValueError now reports size; More efficient color validation --- lib/matplotlib/axes/_axes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index c50e3e370c2c..c4f05f85df94 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3985,14 +3985,14 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, c_array = None if c_array is None: - colors = c # must be acceptable as PathCollection facecolors try: - mcolors.to_rgba_array(colors) + # must be acceptable as PathCollection facecolors + colors = mcolors.to_rgba_array(c) except ValueError: # c not acceptable as PathCollection facecolor msg = ("c of shape {0} not acceptable as a color sequence " - "for x with shape {1}, y with shape {2}") - raise ValueError(msg.format(c.shape, x.shape, y.shape)) + "for x with size {1}, y with size {2}") + raise ValueError(msg.format(c.shape, x.size, y.size)) else: colors = None # use cmap, norm after collection is created