From b23a8748cd9f4a0a613e02b94c9aa783e34b16d1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 16 Oct 2020 18:54:25 -0400 Subject: [PATCH] FIX: make sure we have more than 1 tick with small log ranges If we have both a small target number of ticks and a small displayed range we would previously pick a tick stride that was the same size or bigger than the visible data range which would result in only 1 tick being visible on the axis. This patch ensures that, with a floor at 1, the stride is smaller than the estimated data range. re-closes #8768 (same symptoms, different cause) --- lib/matplotlib/tests/test_ticker.py | 10 ++++++++++ lib/matplotlib/ticker.py | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 27520f26b9b9..b564fb6df1b1 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -1362,3 +1362,13 @@ def test_bad_locator_subs(sub): ll = mticker.LogLocator() with pytest.raises(ValueError): ll.subs(sub) + + +@pytest.mark.parametrize('numticks', [1, 2, 3, 9]) +@pytest.mark.style('default') +def test_small_range_loglocator(numticks): + ll = mticker.LogLocator() + ll.set_params(numticks=numticks) + for top in [5, 7, 9, 11, 15, 50, 100, 1000]: + ticks = ll.tick_values(.5, top) + assert (np.diff(np.log10(ll.tick_values(6, 150))) == 1).all() diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index 07cc521a9401..7a5e3ea60501 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -2479,6 +2479,13 @@ def tick_values(self, vmin, vmax): if mpl.rcParams['_internal.classic_mode'] else (numdec + 1) // numticks + 1) + # if we have decided that the stride is as big or bigger than + # the range, clip the stride back to the available range - 1 + # with a floor of 1. This prevents getting axis with only 1 tick + # visible. + if stride >= numdec: + stride = max(1, numdec - 1) + # Does subs include anything other than 1? Essentially a hack to know # whether we're a major or a minor locator. have_subs = len(subs) > 1 or (len(subs) == 1 and subs[0] != 1.0)