-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Description
Bug summary
In investigating #25894 I discovered that despite being documented as:
To disable labeling of minor ticks when 'labelOnlyBase' is False, use
minor_thresholds=(0, 0)
. This is the default for the "classic" style.
It actually only removes some minor tick labels (e.g. with base of 10: 11-14 will get labels, but 16-19 (15 is edge case, dependent on floating point rounding, 1.4, or 140 also similar))
Code for reproduction
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
fig, ax = plt.subplots()
ax.set_yscale("log")
formatter = mticker.LogFormatter(minor_thresholds=(0,0))
ax.yaxis.set_minor_formatter(formatter)
ax.set_ylim(10, 20)
plt.show()
Actual outcome
formatter(10) # '10'
formatter(11) # '11'
formatter(12) # '12'
formatter(13) # '13'
formatter(14) # '14'
formatter(15) # '15'
formatter(16) # ''
Expected outcome
formatter(10) # ''
formatter(11) # ''
formatter(12) # ''
formatter(13) # ''
formatter(14) # ''
formatter(15) # ''
formatter(16) # ''
Additional information
Only really affects plots that are zoomed in to much less than one decade, which arguably doesn't make sense to use a log scale, but still seems incongruous with the documented "this turns off minor ticks".
Has to do with when coeff
rounds down to 1
in:
matplotlib/lib/matplotlib/ticker.py
Lines 980 to 988 in f051d94
fx = math.log(x) / math.log(b) | |
is_x_decade = _is_close_to_int(fx) | |
exponent = round(fx) if is_x_decade else np.floor(fx) | |
coeff = round(b ** (fx - exponent)) | |
if self.labelOnlyBase and not is_x_decade: | |
return '' | |
if self._sublabels is not None and coeff not in self._sublabels: | |
return '' |
I'm not quite sure what the proper solution is, perhaps making self._sublabels=set()
instead?
Operating system
Linux
Matplotlib Version
3.8 (main)
Matplotlib Backend
No response
Python version
3.11
Jupyter version
No response
Installation
git checkout