Skip to content

Commit b9cf638

Browse files
committed
Move major/minor tick overstrike logic to Axis.
The Axis knows what the major and the minor ticker are so it makes sense to let it handle the deduplication logic. Revert some heuristic deduplication logic from the Locators themselves (which effectively tests that the new code works).
1 parent 64c84b4 commit b9cf638

File tree

3 files changed

+36
-25
lines changed

3 files changed

+36
-25
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Minor Locator no longer try to avoid overstriking major Locators
2+
````````````````````````````````````````````````````````````````
3+
4+
Previously, various locator classes contained custom logic to detect whether
5+
they are used as minor locators, and, if so, attempted to avoid emitting tick
6+
locations that collided with major ticks.
7+
8+
This logic has now moved to the Axis class; thus, for example,
9+
``xaxis.minor.locator()`` now includes positions that collide with
10+
``xaxis.major.locator()``, but ``xaxis.get_minorticklocs()`` does not.

lib/matplotlib/axis.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -932,17 +932,15 @@ def iter_ticks(self):
932932
"""
933933
Iterate through all of the major and minor ticks.
934934
"""
935-
major_locs = self.major.locator()
936-
major_ticks = self.get_major_ticks(len(major_locs))
935+
major_locs = self.get_majorticklocs()
937936
self.major.formatter.set_locs(major_locs)
938937
major_labels = self.major.formatter.format_ticks(major_locs)
939-
940-
minor_locs = self.minor.locator()
941-
minor_ticks = self.get_minor_ticks(len(minor_locs))
938+
major_ticks = self.get_major_ticks(len(major_locs))
939+
yield from zip(major_ticks, major_locs, major_labels)
940+
minor_locs = self.get_minorticklocs()
942941
self.minor.formatter.set_locs(minor_locs)
943942
minor_labels = self.minor.formatter.format_ticks(minor_locs)
944-
945-
yield from zip(major_ticks, major_locs, major_labels)
943+
minor_ticks = self.get_minor_ticks(len(minor_locs))
946944
yield from zip(minor_ticks, minor_locs, minor_labels)
947945

948946
def get_ticklabel_extents(self, renderer):
@@ -1223,18 +1221,29 @@ def get_ticklines(self, minor=False):
12231221
return self.get_majorticklines()
12241222

12251223
def get_majorticklocs(self):
1226-
"Get the major tick locations in data coordinates as a numpy array"
1224+
"""Get the array of major tick locations in data coordinates."""
12271225
return self.major.locator()
12281226

12291227
def get_minorticklocs(self):
1230-
"Get the minor tick locations in data coordinates as a numpy array"
1231-
return self.minor.locator()
1228+
"""Get the array of minor tick locations in data coordinates."""
1229+
# Remove minor ticks duplicating major ticks.
1230+
major_locs = self.major.locator()
1231+
minor_locs = self.minor.locator()
1232+
transform = self._scale.get_transform()
1233+
tr_minor_locs = transform.transform(minor_locs)
1234+
tr_major_locs = transform.transform(major_locs)
1235+
lo, hi = sorted(transform.transform(self.get_view_interval()))
1236+
# Use the transformed view limits as scale. 1e-5 is the default rtol
1237+
# for np.isclose.
1238+
tol = (hi - lo) * 1e-5
1239+
minor_locs = [
1240+
loc for loc, tr_loc in zip(minor_locs, tr_minor_locs)
1241+
if not np.isclose(tr_loc, tr_major_locs, atol=tol, rtol=0).any()]
1242+
return minor_locs
12321243

12331244
def get_ticklocs(self, minor=False):
1234-
"Get the tick locations in data coordinates as a numpy array"
1235-
if minor:
1236-
return self.minor.locator()
1237-
return self.major.locator()
1245+
"""Get the array of tick locations in data coordinates."""
1246+
return self.get_minorticklocs() if minor else self.get_majorticklocs()
12381247

12391248
def get_ticks_direction(self, minor=False):
12401249
"""

lib/matplotlib/ticker.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,13 +2258,9 @@ def tick_values(self, vmin, vmax):
22582258
# If we're a minor locator *that expects at least two ticks per
22592259
# decade* and the major locator stride is 1 and there's no more
22602260
# than one minor tick, switch to AutoLocator.
2261-
ticklocs = AutoLocator().tick_values(vmin, vmax)
2262-
# Don't overstrike the major labels. Assumes major locs are
2263-
# at b = self._base
2264-
ticklocs = ticklocs[
2265-
~is_close_to_int(np.log(ticklocs) / np.log(b))]
2266-
return ticklocs
2267-
return self.raise_if_exceeds(ticklocs)
2261+
return AutoLocator().tick_values(vmin, vmax)
2262+
else:
2263+
return self.raise_if_exceeds(ticklocs)
22682264

22692265
def view_limits(self, vmin, vmax):
22702266
'Try to choose the view limits intelligently'
@@ -2643,10 +2639,6 @@ def __call__(self):
26432639
tmin = ((vmin - t0) // minorstep + 1) * minorstep
26442640
tmax = ((vmax - t0) // minorstep + 1) * minorstep
26452641
locs = np.arange(tmin, tmax, minorstep) + t0
2646-
mod = np.abs((locs - t0) % majorstep)
2647-
cond1 = mod > minorstep / 10.0
2648-
cond2 = ~np.isclose(mod, majorstep, atol=0)
2649-
locs = locs.compress(cond1 & cond2)
26502642

26512643
return self.raise_if_exceeds(np.array(locs))
26522644

0 commit comments

Comments
 (0)