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

Skip to content

Commit 35c95de

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 851442c commit 35c95de

File tree

3 files changed

+40
-24
lines changed

3 files changed

+40
-24
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: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -930,16 +930,25 @@ def iter_ticks(self):
930930
Iterate through all of the major and minor ticks.
931931
"""
932932
major_locs = self.major.locator()
933-
major_ticks = self.get_major_ticks(len(major_locs))
934933
self.major.formatter.set_locs(major_locs)
935934
major_labels = self.major.formatter.format_ticks(major_locs)
936-
937-
minor_locs = self.minor.locator()
938-
minor_ticks = self.get_minor_ticks(len(minor_locs))
935+
major_ticks = self.get_major_ticks(len(major_locs))
936+
yield from zip(major_ticks, major_locs, major_labels)
937+
# Remove minor ticks duplicating major ticks; use the range of major
938+
# tick values to set the scale. 1e-5 is the default rtol for isclose.
939+
# If there are no major_locs, tol doesn't matter.
940+
# Ideally, we would like to apply e.g. ax.get_xaxis_transform() to
941+
# the tick locs and decide based on screen-space proximity, but as
942+
# of now the axis object doesn't know whether it is associated with
943+
# ax.get_xaxis_transform(), ax.get_yaxis_transform(), or something
944+
# else.
945+
tol = np.abs(major_locs).ptp() * 1e-5 if len(major_locs) else 0
946+
minor_locs = [
947+
loc for loc in self.minor.locator()
948+
if not np.isclose(loc, major_locs, atol=tol, rtol=0).any()]
939949
self.minor.formatter.set_locs(minor_locs)
940950
minor_labels = self.minor.formatter.format_ticks(minor_locs)
941-
942-
yield from zip(major_ticks, major_locs, major_labels)
951+
minor_ticks = self.get_minor_ticks(len(minor_locs))
943952
yield from zip(minor_ticks, minor_locs, minor_labels)
944953

945954
def get_ticklabel_extents(self, renderer):
@@ -1220,18 +1229,23 @@ def get_ticklines(self, minor=False):
12201229
return self.get_majorticklines()
12211230

12221231
def get_majorticklocs(self):
1223-
"Get the major tick locations in data coordinates as a numpy array"
1232+
"Get the major tick locations in data coordinates as a numpy array."
12241233
return self.major.locator()
12251234

12261235
def get_minorticklocs(self):
1227-
"Get the minor tick locations in data coordinates as a numpy array"
1228-
return self.minor.locator()
1236+
"Get the minor tick locations in data coordinates as a numpy array."
1237+
# See rationale for tol in iter_ticks (which does not reuse this
1238+
# implementation to avoid calling the major locator twice).
1239+
major_locs = self.major.locator()
1240+
tol = np.abs(major_locs).ptp() * 1e-5 if major_locs.size else 0
1241+
minor_locs = [
1242+
loc for loc in self.minor.locator()
1243+
if not np.isclose(loc, major_locs, atol=tol, rtol=0).any()]
1244+
return minor_locs
12291245

12301246
def get_ticklocs(self, minor=False):
1231-
"Get the tick locations in data coordinates as a numpy array"
1232-
if minor:
1233-
return self.minor.locator()
1234-
return self.major.locator()
1247+
"Get the tick locations in data coordinates as a numpy array."
1248+
return self.get_minorticklocs() if minor else self.get_majorticklocs()
12351249

12361250
def get_ticks_direction(self, minor=False):
12371251
"""

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)