From a918a131a42b853e86bf359e8345f780fa8a4df1 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 22 Nov 2018 17:41:09 +0100 Subject: [PATCH] Avoid 1-tick or 0-tick log-scaled axis. ... by switching to AutoLocator when the minor LogLocator would produce no more than one tick. --- doc/api/next_api_changes/2018-11-23-AL.rst | 6 ++++ lib/matplotlib/tests/test_ticker.py | 7 ++++- lib/matplotlib/ticker.py | 34 +++++++++++++--------- 3 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 doc/api/next_api_changes/2018-11-23-AL.rst diff --git a/doc/api/next_api_changes/2018-11-23-AL.rst b/doc/api/next_api_changes/2018-11-23-AL.rst new file mode 100644 index 000000000000..1936d3a8d97c --- /dev/null +++ b/doc/api/next_api_changes/2018-11-23-AL.rst @@ -0,0 +1,6 @@ +Log-scaled axes avoid having zero or only one tick +`````````````````````````````````````````````````` + +When the default `LogLocator` would generate no ticks for an axis (e.g., an +axis with limits from 0.31 to 0.39) or only a single tick, it now instead falls +back on the linear `AutoLocator` to pick reasonable tick positions. diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 69fa646f6b85..5a7b8f446349 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -1,7 +1,7 @@ import warnings import numpy as np -from numpy.testing import assert_almost_equal +from numpy.testing import assert_almost_equal, assert_array_equal import pytest import matplotlib @@ -179,6 +179,11 @@ def test_basic(self): test_value = np.array([0.5, 1., 2., 4., 8., 16., 32., 64., 128., 256.]) assert_almost_equal(loc.tick_values(1, 100), test_value) + def test_switch_to_autolocator(self): + loc = mticker.LogLocator(subs="all") + assert_array_equal(loc.tick_values(0.45, 0.55), + [0.44, 0.46, 0.48, 0.5, 0.52, 0.54, 0.56]) + def test_set_params(self): """ Create log locator with default value, base=10.0, subs=[1.0], diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index fb39bfba9dc7..3e299b31303b 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -2165,13 +2165,13 @@ def tick_values(self, vmin, vmax): "log-scaled.") _log.debug('vmin %s vmax %s', vmin, vmax) - vmin = math.log(vmin) / math.log(b) - vmax = math.log(vmax) / math.log(b) if vmax < vmin: vmin, vmax = vmax, vmin + log_vmin = math.log(vmin) / math.log(b) + log_vmax = math.log(vmax) / math.log(b) - numdec = math.floor(vmax) - math.ceil(vmin) + numdec = math.floor(log_vmax) - math.ceil(log_vmin) if isinstance(self._subs, str): _first = 2.0 if self._subs == 'auto' else 1.0 @@ -2195,11 +2195,12 @@ def tick_values(self, vmin, vmax): while numdec // stride + 1 > numticks: stride += 1 - # Does subs include anything other than 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) - decades = np.arange(math.floor(vmin) - stride, - math.ceil(vmax) + 2 * stride, stride) + decades = np.arange(math.floor(log_vmin) - stride, + math.ceil(log_vmax) + 2 * stride, stride) if hasattr(self, '_transform'): ticklocs = self._transform.inverted().transform(decades) @@ -2207,20 +2208,27 @@ def tick_values(self, vmin, vmax): if stride == 1: ticklocs = np.ravel(np.outer(subs, ticklocs)) else: - # no ticklocs if we have more than one decade - # between major ticks. - ticklocs = [] + # No ticklocs if we have >1 decade between major ticks. + ticklocs = np.array([]) else: if have_subs: - ticklocs = [] if stride == 1: - for decadeStart in b ** decades: - ticklocs.extend(subs * decadeStart) + ticklocs = np.concatenate( + [subs * decade_start for decade_start in b ** decades]) + else: + ticklocs = np.array([]) else: ticklocs = b ** decades _log.debug('ticklocs %r', ticklocs) - return self.raise_if_exceeds(np.asarray(ticklocs)) + if (len(subs) > 1 + and stride == 1 + and ((vmin <= ticklocs) & (ticklocs <= vmax)).sum() <= 1): + # If we're a minor locator *that expects at least two ticks per + # decade* and the major locator stride is 1 and there's no more + # than one minor tick, switch to AutoLocator. + return AutoLocator().tick_values(vmin, vmax) + return self.raise_if_exceeds(ticklocs) def view_limits(self, vmin, vmax): 'Try to choose the view limits intelligently' pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy