From 103267d74660d5949abc4e202d6ab525024ace00 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 15 Jun 2020 19:21:59 +0200 Subject: [PATCH] Fix autoscaling with tiny sticky values. --- lib/matplotlib/axes/_base.py | 14 ++++++++------ lib/matplotlib/tests/test_axes.py | 8 ++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index da9ddeebe6d4..e83f69f54445 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2545,15 +2545,17 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval, locator = axis.get_major_locator() x0, x1 = locator.nonsingular(x0, x1) - # Prevent margin addition from crossing a sticky value. Small - # tolerances (whose values come from isclose()) must be used due to - # floating point issues with streamplot. - def tol(x): return 1e-5 * abs(x) + 1e-8 + # Prevent margin addition from crossing a sticky value. A small + # tolerance must be added due to floating point issues with + # streamplot; it is defined relative to x0, x1, x1-x0 but has + # no absolute term (e.g. "+1e-8") to avoid issues when working with + # datasets where all values are tiny (less than 1e-8). + tol = 1e-5 * max(abs(x0), abs(x1), abs(x1 - x0)) # Index of largest element < x0 + tol, if any. - i0 = stickies.searchsorted(x0 + tol(x0)) - 1 + i0 = stickies.searchsorted(x0 + tol) - 1 x0bound = stickies[i0] if i0 != -1 else None # Index of smallest element > x1 - tol, if any. - i1 = stickies.searchsorted(x1 - tol(x1)) + i1 = stickies.searchsorted(x1 - tol) x1bound = stickies[i1] if i1 != len(stickies) else None # Add the margin in figure space and then transform back, to handle diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 178aba05b071..2a61b232f463 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -6314,3 +6314,11 @@ def test_polar_interpolation_steps_variable_r(fig_test, fig_ref): l.get_path()._interpolation_steps = 100 fig_ref.add_subplot(projection="polar").plot( np.linspace(0, np.pi/2, 101), np.linspace(1, 2, 101)) + + +@pytest.mark.style('default') +def test_autoscale_tiny_sticky(): + fig, ax = plt.subplots() + ax.bar(0, 1e-9) + fig.canvas.draw() + assert ax.get_ylim() == (0, 1.05e-9)