Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8f40a1c

Browse files
committed
Label log minor ticks if only one log major tick is drawn.
In general, avoiding axis with a single labeled tick seems to be a good idea. Previously, a log axis spanning from 4 to 60 would have its minor ticks unlabeled, LogFormatter making that choice based on the fact that the axis spans more than one decade (60/4>10). Instead, change the interpretation of the first item in `minor_thresholds` to label the minor ticks (by default) if there is only one (or zero) major tick drawn (as is the case for the above axis limits).
1 parent 202a277 commit 8f40a1c

File tree

3 files changed

+54
-28
lines changed

3 files changed

+54
-28
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Minor tick labels are set depending on number of major log ticks, not on number of decades spanned
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, by default, on a log-scaled axis, the minor ticks would be
4+
unlabeled if the axis limits spanned more than one decade. The meaning of the
5+
``minor_thresholds`` parameter to `.LogFormatter` has been altered so that the
6+
decision of whether to label the minor ticks is now based on the number of
7+
major ticks drawn within the axis limits.
8+
9+
For example, for an axis spanning from 4 to 60 (with thus a single major log
10+
tick, at 10), minor ticks are now labeled, even though the axis spans more than
11+
one decade.

lib/matplotlib/tests/test_ticker.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,11 +1235,16 @@ def test_sublabel(self):
12351235
ax.set_xlim(1, 80)
12361236
self._sub_labels(ax.xaxis, subs=[])
12371237

1238-
# axis range at 0.4 to 1 decades, label subs 2, 3, 4, 6
1238+
# axis range slightly more than 1 decade, but spanning a single major
1239+
# tick, label subs 2, 3, 4, 6
1240+
ax.set_xlim(.8, 9)
1241+
self._sub_labels(ax.xaxis, subs=[2, 3, 4, 6])
1242+
1243+
# axis range at 0.4 to 1 decade, label subs 2, 3, 4, 6
12391244
ax.set_xlim(1, 8)
12401245
self._sub_labels(ax.xaxis, subs=[2, 3, 4, 6])
12411246

1242-
# axis range at 0 to 0.4 decades, label all
1247+
# axis range at 0 to 0.4 decade, label all
12431248
ax.set_xlim(0.5, 0.9)
12441249
self._sub_labels(ax.xaxis, subs=np.arange(2, 10, dtype=int))
12451250

lib/matplotlib/ticker.py

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -847,20 +847,23 @@ class LogFormatter(Formatter):
847847
848848
labelOnlyBase : bool, default: False
849849
If True, label ticks only at integer powers of base.
850-
This is normally True for major ticks and False for
851-
minor ticks.
850+
This is normally True for major ticks and False for minor ticks.
852851
853852
minor_thresholds : (subset, all), default: (1, 0.4)
854853
If labelOnlyBase is False, these two numbers control
855854
the labeling of ticks that are not at integer powers of
856-
base; normally these are the minor ticks. The controlling
857-
parameter is the log of the axis data range. In the typical
858-
case where base is 10 it is the number of decades spanned
859-
by the axis, so we can call it 'numdec'. If ``numdec <= all``,
860-
all minor ticks will be labeled. If ``all < numdec <= subset``,
861-
then only a subset of minor ticks will be labeled, so as to
862-
avoid crowding. If ``numdec > subset`` then no minor ticks will
863-
be labeled.
855+
base; normally these are the minor ticks.
856+
857+
The first number (*subset*) is the largest number of major ticks for
858+
which minor ticks are labeled; e.g., the default, 1, means that minor
859+
ticks are labeled as long as there is no more than 1 major tick. (It
860+
is assumed that major ticks are at integer powers of *base*.)
861+
862+
The second number (*all*) is a threshold, in log-units of the axis
863+
limit range, over which only a subset of the minor ticks are labeled,
864+
so as to avoid crowding; e.g., with the default value (0.4) and the
865+
usual ``base=10``, all minor ticks are shown only if the axis limit
866+
range spans less than 0.4 decades.
864867
865868
linthresh : None or float, default: None
866869
If a symmetric log scale is in use, its ``linthresh``
@@ -884,12 +887,9 @@ class LogFormatter(Formatter):
884887
885888
Examples
886889
--------
887-
To label a subset of minor ticks when the view limits span up
888-
to 2 decades, and all of the ticks when zoomed in to 0.5 decades
889-
or less, use ``minor_thresholds=(2, 0.5)``.
890-
891-
To label all minor ticks when the view limits span up to 1.5
892-
decades, use ``minor_thresholds=(1.5, 1.5)``.
890+
To label a subset of minor ticks when there are up to 2 major ticks,
891+
and all of the ticks when zoomed in to 0.5 decades or less, use
892+
``minor_thresholds=(2, 0.5)``.
893893
"""
894894

895895
def __init__(self, base=10.0, labelOnlyBase=False,
@@ -957,22 +957,32 @@ def set_locs(self, locs=None):
957957
return
958958

959959
b = self._base
960+
960961
if linthresh is not None: # symlog
961-
# Only compute the number of decades in the logarithmic part of the
962-
# axis
963-
numdec = 0
962+
# Only count ticks and decades in the logarithmic part of the axis.
963+
numdec = numticks = 0
964964
if vmin < -linthresh:
965965
rhs = min(vmax, -linthresh)
966-
numdec += math.log(vmin / rhs) / math.log(b)
966+
numticks += (
967+
math.floor(math.log(abs(rhs), b))
968+
- math.floor(math.nextafter(math.log(abs(vmin), b), -math.inf)))
969+
numdec += math.log(vmin / rhs, b)
967970
if vmax > linthresh:
968971
lhs = max(vmin, linthresh)
969-
numdec += math.log(vmax / lhs) / math.log(b)
972+
numticks += (
973+
math.floor(math.log(vmax, b))
974+
- math.floor(math.nextafter(math.log(lhs, b), -math.inf)))
975+
numdec += math.log(vmax / lhs, b)
970976
else:
971-
vmin = math.log(vmin) / math.log(b)
972-
vmax = math.log(vmax) / math.log(b)
973-
numdec = abs(vmax - vmin)
974-
975-
if numdec > self.minor_thresholds[0]:
977+
lmin = math.log(vmin, b)
978+
lmax = math.log(vmax, b)
979+
# The nextafter call handles the case where vmin is exactly at a
980+
# decade (e.g. there's one major tick between 1 and 5).
981+
numticks = (math.floor(lmax)
982+
- math.floor(math.nextafter(lmin, -math.inf)))
983+
numdec = abs(lmax - lmin)
984+
985+
if numticks > self.minor_thresholds[0]:
976986
# Label only bases
977987
self._sublabels = {1}
978988
elif numdec > self.minor_thresholds[1]:

0 commit comments

Comments
 (0)