From a305c536c4138eb779cbd2e222b5487b162b6835 Mon Sep 17 00:00:00 2001 From: Paul Hobson Date: Fri, 2 Nov 2018 08:23:57 -0700 Subject: [PATCH 1/2] Merge pull request #12673 from esvhd/axes_iob Fix for _axes.scatter() array index out of bound error --- lib/matplotlib/axes/_axes.py | 5 +-- lib/matplotlib/tests/test_axes.py | 17 +++++++++- lib/matplotlib/tests/test_cbook.py | 51 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 3dfd5502778b..8ec650d9eeae 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4199,8 +4199,9 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, if (c_none or co is not None or isinstance(c, str) or - (isinstance(c, collections.abc.Iterable) and - isinstance(c[0], str))): + (isinstance(c, collections.Iterable) and + len(c) > 0 and + isinstance(cbook.safe_first_element(c), str))): c_array = None else: try: # First, does 'c' look suitable for value-mapping? diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 6a4900dc3408..629517406799 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5820,7 +5820,7 @@ def test_spines_properbbox_after_zoom(): bb = ax.spines['bottom'].get_window_extent(fig.canvas.get_renderer()) # this is what zoom calls: ax._set_view_from_bbox((320, 320, 500, 500), 'in', - None, False, False) + None, False, False) bb2 = ax.spines['bottom'].get_window_extent(fig.canvas.get_renderer()) np.testing.assert_allclose(bb.get_points(), bb2.get_points(), rtol=1e-6) @@ -5848,3 +5848,18 @@ def test_gettightbbox_ignoreNaN(): t = ax.text(np.NaN, 1, 'Boo') renderer = fig.canvas.get_renderer() np.testing.assert_allclose(ax.get_tightbbox(renderer).width, 532.444444) + + +def test_scatter_series_non_zero_index(pd): + # create non-zero index + ids = range(10, 18) + x = pd.Series(np.random.uniform(size=8), index=ids) + y = pd.Series(np.random.uniform(size=8), index=ids) + c = pd.Series([1, 1, 1, 1, 1, 0, 0, 0], index=ids) + plt.scatter(x, y, c) + + +def test_scatter_empty_data(): + # making sure this does not raise an exception + plt.scatter([], []) + plt.scatter([], [], s=[], c=[]) diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index 745844fb6a1c..69b887020d91 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -482,3 +482,54 @@ def test_flatiter(): assert 0 == next(it) assert 1 == next(it) + + +def test_reshape2d(): + class dummy(): + pass + x = [dummy() for j in range(5)] + xnew = cbook._reshape_2D(x, 'x') + assert np.shape(xnew) == (1, 5) + + x = np.arange(5) + xnew = cbook._reshape_2D(x, 'x') + assert np.shape(xnew) == (1, 5) + + x = [[dummy() for j in range(5)] for i in range(3)] + xnew = cbook._reshape_2D(x, 'x') + assert np.shape(xnew) == (3, 5) + + # this is strange behaviour, but... + x = np.random.rand(3, 5) + xnew = cbook._reshape_2D(x, 'x') + assert np.shape(xnew) == (5, 3) + + +def test_contiguous_regions(): + a, b, c = 3, 4, 5 + # Starts and ends with True + mask = [True]*a + [False]*b + [True]*c + expected = [(0, a), (a+b, a+b+c)] + assert cbook.contiguous_regions(mask) == expected + d, e = 6, 7 + # Starts with True ends with False + mask = mask + [False]*e + assert cbook.contiguous_regions(mask) == expected + # Starts with False ends with True + mask = [False]*d + mask[:-e] + expected = [(d, d+a), (d+a+b, d+a+b+c)] + assert cbook.contiguous_regions(mask) == expected + # Starts and ends with False + mask = mask + [False]*e + assert cbook.contiguous_regions(mask) == expected + # No True in mask + assert cbook.contiguous_regions([False]*5) == [] + # Empty mask + assert cbook.contiguous_regions([]) == [] + + +def test_safe_first_element_pandas_series(pd): + # delibrately create a pandas series with index not starting from 0 + s = pd.Series(range(5), index=range(10, 15)) + actual = cbook.safe_first_element(s) + assert actual == 0 From 9129737175ee33ab7faa6492a7f80159ed1d74e6 Mon Sep 17 00:00:00 2001 From: Elan Ernest <23121882+ImportanceOfBeingErnest@users.noreply.github.com> Date: Tue, 6 Nov 2018 23:50:06 +0100 Subject: [PATCH 2/2] Update test_cbook.py --- lib/matplotlib/tests/test_cbook.py | 44 ------------------------------ 1 file changed, 44 deletions(-) diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index 69b887020d91..243bca3731d6 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -484,50 +484,6 @@ def test_flatiter(): assert 1 == next(it) -def test_reshape2d(): - class dummy(): - pass - x = [dummy() for j in range(5)] - xnew = cbook._reshape_2D(x, 'x') - assert np.shape(xnew) == (1, 5) - - x = np.arange(5) - xnew = cbook._reshape_2D(x, 'x') - assert np.shape(xnew) == (1, 5) - - x = [[dummy() for j in range(5)] for i in range(3)] - xnew = cbook._reshape_2D(x, 'x') - assert np.shape(xnew) == (3, 5) - - # this is strange behaviour, but... - x = np.random.rand(3, 5) - xnew = cbook._reshape_2D(x, 'x') - assert np.shape(xnew) == (5, 3) - - -def test_contiguous_regions(): - a, b, c = 3, 4, 5 - # Starts and ends with True - mask = [True]*a + [False]*b + [True]*c - expected = [(0, a), (a+b, a+b+c)] - assert cbook.contiguous_regions(mask) == expected - d, e = 6, 7 - # Starts with True ends with False - mask = mask + [False]*e - assert cbook.contiguous_regions(mask) == expected - # Starts with False ends with True - mask = [False]*d + mask[:-e] - expected = [(d, d+a), (d+a+b, d+a+b+c)] - assert cbook.contiguous_regions(mask) == expected - # Starts and ends with False - mask = mask + [False]*e - assert cbook.contiguous_regions(mask) == expected - # No True in mask - assert cbook.contiguous_regions([False]*5) == [] - # Empty mask - assert cbook.contiguous_regions([]) == [] - - def test_safe_first_element_pandas_series(pd): # delibrately create a pandas series with index not starting from 0 s = pd.Series(range(5), index=range(10, 15))