From 60a785dd2d18369d51843e1791e4e84acee35396 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger Date: Thu, 28 Nov 2019 22:41:05 +0100 Subject: [PATCH 1/2] Test geometry of step(filled) histograms --- lib/matplotlib/tests/test_axes.py | 130 ++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 9558e545c42d..c63196056496 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -3289,6 +3289,136 @@ def test_hist_step_bottom(): ax.hist(d1, bottom=np.arange(10), histtype="stepfilled") +def test_hist_stepfilled_geometry(): + bins = [0, 1, 2, 3] + data = [0, 0, 1, 1, 1, 2] + _, _, (polygon, ) = plt.hist(data, + bins=bins, + histtype='stepfilled') + xy = [[0, 0], [0, 2], [1, 2], [1, 3], [2, 3], [2, 1], [3, 1], + [3, 0], [2, 0], [2, 0], [1, 0], [1, 0], [0, 0]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_step_geometry(): + bins = [0, 1, 2, 3] + data = [0, 0, 1, 1, 1, 2] + _, _, (polygon, ) = plt.hist(data, + bins=bins, + histtype='step') + xy = [[0, 0], [0, 2], [1, 2], [1, 3], [2, 3], [2, 1], [3, 1], [3, 0]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_stepfilled_bottom_geometry(): + bins = [0, 1, 2, 3] + data = [0, 0, 1, 1, 1, 2] + _, _, (polygon, ) = plt.hist(data, + bins=bins, + bottom=[1, 2, 1.5], + histtype='stepfilled') + xy = [[0, 1], [0, 3], [1, 3], [1, 5], [2, 5], [2, 2.5], [3, 2.5], + [3, 1.5], [2, 1.5], [2, 2], [1, 2], [1, 1], [0, 1]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_step_bottom_geometry(): + bins = [0, 1, 2, 3] + data = [0, 0, 1, 1, 1, 2] + _, _, (polygon, ) = plt.hist(data, + bins=bins, + bottom=[1, 2, 1.5], + histtype='step') + xy = [[0, 1], [0, 3], [1, 3], [1, 5], [2, 5], [2, 2.5], [3, 2.5], [3, 1.5]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_stacked_stepfilled_geometry(): + bins = [0, 1, 2, 3] + data_1 = [0, 0, 1, 1, 1, 2] + data_2 = [0, 1, 2] + _, _, patches = plt.hist([data_1, data_2], + bins=bins, + stacked=True, + histtype='stepfilled') + + assert len(patches) == 2 + + polygon, = patches[0] + xy = [[0, 0], [0, 2], [1, 2], [1, 3], [2, 3], [2, 1], [3, 1], + [3, 0], [2, 0], [2, 0], [1, 0], [1, 0], [0, 0]] + assert_array_equal(polygon.get_xy(), xy) + + polygon, = patches[1] + xy = [[0, 2], [0, 3], [1, 3], [1, 4], [2, 4], [2, 2], [3, 2], + [3, 1], [2, 1], [2, 3], [1, 3], [1, 2], [0, 2]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_stacked_step_geometry(): + bins = [0, 1, 2, 3] + data_1 = [0, 0, 1, 1, 1, 2] + data_2 = [0, 1, 2] + _, _, patches = plt.hist([data_1, data_2], + bins=bins, + stacked=True, + histtype='step') + + assert len(patches) == 2 + + polygon, = patches[0] + xy = [[0, 0], [0, 2], [1, 2], [1, 3], [2, 3], [2, 1], [3, 1], [3, 0]] + assert_array_equal(polygon.get_xy(), xy) + + polygon, = patches[1] + xy = [[0, 2], [0, 3], [1, 3], [1, 4], [2, 4], [2, 2], [3, 2], [3, 1]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_stacked_stepfilled_bottom_geometry(): + bins = [0, 1, 2, 3] + data_1 = [0, 0, 1, 1, 1, 2] + data_2 = [0, 1, 2] + _, _, patches = plt.hist([data_1, data_2], + bins=bins, + stacked=True, + bottom=[1, 2, 1.5], + histtype='stepfilled') + + assert len(patches) == 2 + + polygon, = patches[0] + xy = [[0, 1], [0, 3], [1, 3], [1, 5], [2, 5], [2, 2.5], [3, 2.5], + [3, 1.5], [2, 1.5], [2, 2], [1, 2], [1, 1], [0, 1]] + assert_array_equal(polygon.get_xy(), xy) + + polygon, = patches[1] + xy = [[0, 3], [0, 4], [1, 4], [1, 6], [2, 6], [2, 3.5], [3, 3.5], + [3, 2.5], [2, 2.5], [2, 5], [1, 5], [1, 3], [0, 3]] + assert_array_equal(polygon.get_xy(), xy) + + +def test_hist_stacked_step_bottom_geometry(): + bins = [0, 1, 2, 3] + data_1 = [0, 0, 1, 1, 1, 2] + data_2 = [0, 1, 2] + _, _, patches = plt.hist([data_1, data_2], + bins=bins, + stacked=True, + bottom=[1, 2, 1.5], + histtype='step') + + assert len(patches) == 2 + + polygon, = patches[0] + xy = [[0, 1], [0, 3], [1, 3], [1, 5], [2, 5], [2, 2.5], [3, 2.5], [3, 1.5]] + assert_array_equal(polygon.get_xy(), xy) + + polygon, = patches[1] + xy = [[0, 3], [0, 4], [1, 4], [1, 6], [2, 6], [2, 3.5], [3, 3.5], [3, 2.5]] + assert_array_equal(polygon.get_xy(), xy) + + @image_comparison(['hist_stacked_bar']) def test_hist_stacked_bar(): # make some data From f40b0f8e39933e041164252e4d66e98b69f578a8 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger Date: Wed, 27 Nov 2019 23:52:23 +0100 Subject: [PATCH 2/2] Fix stepfilled histogram polygon bottom perimeter The polygon generated by hist() when histtype='stepfilled' and bottom is not None contained an invalid starting point with a y-value of zero resulting in a diagonal line at the bottom of the first bin. This commit fixes the computation of the starting point and thus removes the drawing artifacts from the first bin. --- lib/matplotlib/axes/_axes.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 5b120f637d7f..8e17e944c54d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -6796,13 +6796,18 @@ def hist(self, x, bins=None, range=None, density=False, weights=None, xvals, yvals = [], [] for m in tops: if stacked: - # starting point for drawing polygon - y[0] = y[1] # top of the previous polygon becomes the bottom y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1] # set the top of this polygon y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = (m + bottom, m + bottom) + + # The starting point of the polygon has not yet been + # updated. So far only the endpoint was adjusted. This + # assignment closes the polygon. The redundant endpoint is + # later discarded (for step and stepfilled). + y[0] = y[-1] + if orientation == 'horizontal': xvals.append(y.copy()) yvals.append(x.copy())