Skip to content

Commit 26ce31c

Browse files
committed
Avoid 1-tick or 0-tick log-scaled axis.
... by switching to AutoLocator when the minor LogLocator would produce no more than one tick.
1 parent f8b425d commit 26ce31c

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

lib/matplotlib/tests/test_ticker.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import warnings
22

33
import numpy as np
4-
from numpy.testing import assert_almost_equal
4+
from numpy.testing import assert_almost_equal, assert_array_equal
55
import pytest
66

77
import matplotlib
@@ -179,6 +179,11 @@ def test_basic(self):
179179
test_value = np.array([0.5, 1., 2., 4., 8., 16., 32., 64., 128., 256.])
180180
assert_almost_equal(loc.tick_values(1, 100), test_value)
181181

182+
def test_switch_to_autolocator(self):
183+
loc = mticker.LogLocator(subs="all")
184+
assert_array_equal(loc.tick_values(0.45, 0.55),
185+
[0.44, 0.46, 0.48, 0.5 , 0.52, 0.54, 0.56])
186+
182187
def test_set_params(self):
183188
"""
184189
Create log locator with default value, base=10.0, subs=[1.0],

lib/matplotlib/ticker.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,13 +2165,13 @@ def tick_values(self, vmin, vmax):
21652165
"log-scaled.")
21662166

21672167
_log.debug('vmin %s vmax %s', vmin, vmax)
2168-
vmin = math.log(vmin) / math.log(b)
2169-
vmax = math.log(vmax) / math.log(b)
21702168

21712169
if vmax < vmin:
21722170
vmin, vmax = vmax, vmin
2171+
log_vmin = math.log(vmin) / math.log(b)
2172+
log_vmax = math.log(vmax) / math.log(b)
21732173

2174-
numdec = math.floor(vmax) - math.ceil(vmin)
2174+
numdec = math.floor(log_vmax) - math.ceil(log_vmin)
21752175

21762176
if isinstance(self._subs, str):
21772177
_first = 2.0 if self._subs == 'auto' else 1.0
@@ -2195,32 +2195,40 @@ def tick_values(self, vmin, vmax):
21952195
while numdec // stride + 1 > numticks:
21962196
stride += 1
21972197

2198-
# Does subs include anything other than 1?
2198+
# Does subs include anything other than 1? Essentially a hack to know
2199+
# whether we're a major or a minor locator.
21992200
have_subs = len(subs) > 1 or (len(subs) == 1 and subs[0] != 1.0)
22002201

2201-
decades = np.arange(math.floor(vmin) - stride,
2202-
math.ceil(vmax) + 2 * stride, stride)
2202+
decades = np.arange(math.floor(log_vmin) - stride,
2203+
math.ceil(log_vmax) + 2 * stride, stride)
22032204

22042205
if hasattr(self, '_transform'):
22052206
ticklocs = self._transform.inverted().transform(decades)
22062207
if have_subs:
22072208
if stride == 1:
22082209
ticklocs = np.ravel(np.outer(subs, ticklocs))
22092210
else:
2210-
# no ticklocs if we have more than one decade
2211-
# between major ticks.
2212-
ticklocs = []
2211+
# No ticklocs if we have >1 decade between major ticks.
2212+
ticklocs = np.array([])
22132213
else:
22142214
if have_subs:
2215-
ticklocs = []
22162215
if stride == 1:
2217-
for decadeStart in b ** decades:
2218-
ticklocs.extend(subs * decadeStart)
2216+
ticklocs = np.concatenate(
2217+
[subs * decade_start for decade_start in b ** decades])
2218+
else:
2219+
ticklocs = np.array([])
22192220
else:
22202221
ticklocs = b ** decades
22212222

22222223
_log.debug('ticklocs %r', ticklocs)
2223-
return self.raise_if_exceeds(np.asarray(ticklocs))
2224+
if (len(subs) > 1
2225+
and stride == 1
2226+
and ((vmin <= ticklocs) & (ticklocs <= vmax)).sum() <= 1):
2227+
# If we're a minor locator *that expects at least two ticks per
2228+
# decade* and the major locator stride is 1 and there's no more
2229+
# than one minor tick, switch to AutoLocator.
2230+
return AutoLocator().tick_values(vmin, vmax)
2231+
return self.raise_if_exceeds(ticklocs)
22242232

22252233
def view_limits(self, vmin, vmax):
22262234
'Try to choose the view limits intelligently'

0 commit comments

Comments
 (0)
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