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

Skip to content

Enh control tick deconflict2 #13908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/api/axis_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Formatters and Locators
Axis.set_major_locator
Axis.set_minor_formatter
Axis.set_minor_locator

Axis.remove_overlapping_locs

Axis Label
----------
Expand Down
40 changes: 30 additions & 10 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,8 @@ def __init__(self, axes, pickradius=15):
`.Axis.contains`.
"""
martist.Artist.__init__(self)
self._remove_overlapping_locs = True

self.set_figure(axes.figure)

self.isDefault_label = True
Expand Down Expand Up @@ -754,6 +756,17 @@ def __init__(self, axes, pickradius=15):
majorTicks = _LazyTickList(major=True)
minorTicks = _LazyTickList(major=False)

def get_remove_overlapping_locs(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we decided not to bother with getter and setters?

return self._remove_overlapping_locs

def set_remove_overlapping_locs(self, val):
self._remove_overlapping_locs = bool(val)

remove_overlapping_locs = property(
get_remove_overlapping_locs, set_remove_overlapping_locs,
doc=('If minor ticker locations that overlap with major '
'ticker locations should be trimmed.'))

def set_label_coords(self, x, y, transform=None):
"""
Set the coordinates of the label.
Expand Down Expand Up @@ -1064,23 +1077,29 @@ def _update_ticks(self):
Update ticks (position and labels) using the current data interval of
the axes. Return the list of ticks that will be drawn.
"""

major_locs = self.major.locator()
major_ticks = self.get_major_ticks(len(major_locs))
major_locs = self.get_majorticklocs()
major_labels = self.major.formatter.format_ticks(major_locs)
major_ticks = self.get_major_ticks(len(major_locs))
self.major.formatter.set_locs(major_locs)
for tick, loc, label in zip(major_ticks, major_locs, major_labels):
tick.update_position(loc)
tick.set_label1(label)
tick.set_label2(label)
minor_locs = self.minor.locator()
minor_ticks = self.get_minor_ticks(len(minor_locs))
minor_locs = self.get_minorticklocs()
minor_labels = self.minor.formatter.format_ticks(minor_locs)
minor_ticks = self.get_minor_ticks(len(minor_locs))
self.minor.formatter.set_locs(minor_locs)
for tick, loc, label in zip(minor_ticks, minor_locs, minor_labels):
tick.update_position(loc)
tick.set_label1(label)
tick.set_label2(label)
ticks = [*major_ticks, *minor_ticks]

# mark the ticks that we will not be using as not visible
for t in (self.minorTicks[len(minor_locs):] +
self.majorTicks[len(major_locs):]):
t.set_visible(False)

view_low, view_high = self.get_view_interval()
if view_low > view_high:
view_low, view_high = view_high, view_low
Expand Down Expand Up @@ -1322,9 +1341,10 @@ def get_minorticklocs(self):
# Use the transformed view limits as scale. 1e-5 is the default rtol
# for np.isclose.
tol = (hi - lo) * 1e-5
minor_locs = [
loc for loc, tr_loc in zip(minor_locs, tr_minor_locs)
if not np.isclose(tr_loc, tr_major_locs, atol=tol, rtol=0).any()]
if self.remove_overlapping_locs:
minor_locs = [
loc for loc, tr_loc in zip(minor_locs, tr_minor_locs)
if ~np.isclose(tr_loc, tr_major_locs, atol=tol, rtol=0).any()]
return minor_locs

def get_ticklocs(self, minor=False):
Expand Down Expand Up @@ -1390,7 +1410,7 @@ def get_minor_formatter(self):
def get_major_ticks(self, numticks=None):
'Get the tick instances; grow as necessary.'
if numticks is None:
numticks = len(self.get_major_locator()())
numticks = len(self.get_majorticklocs())

while len(self.majorTicks) < numticks:
# Update the new tick label properties from the old.
Expand All @@ -1404,7 +1424,7 @@ def get_major_ticks(self, numticks=None):
def get_minor_ticks(self, numticks=None):
'Get the minor tick instances; grow as necessary.'
if numticks is None:
numticks = len(self.get_minor_locator()())
numticks = len(self.get_minorticklocs())

while len(self.minorTicks) < numticks:
# Update the new tick label properties from the old.
Expand Down
46 changes: 46 additions & 0 deletions lib/matplotlib/tests/test_ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -923,3 +923,49 @@ def minorticksubplot(xminor, yminor, i):
minorticksubplot(True, False, 2)
minorticksubplot(False, True, 3)
minorticksubplot(True, True, 4)


@pytest.mark.parametrize('remove_overlapping_locs, expected_num',
((True, 6),
(None, 6), # this tests the default
(False, 9)))
def test_remove_overlap(remove_overlapping_locs, expected_num):
import numpy as np
import matplotlib.dates as mdates

t = np.arange("2018-11-03", "2018-11-06", dtype="datetime64")
x = np.ones(len(t))

fig, ax = plt.subplots()
ax.plot(t, x)

ax.xaxis.set_major_locator(mdates.DayLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('\n%a'))

ax.xaxis.set_minor_locator(mdates.HourLocator((0, 6, 12, 18)))
ax.xaxis.set_minor_formatter(mdates.DateFormatter('%H:%M'))
# force there to be extra ticks
ax.xaxis.get_minor_ticks(15)
if remove_overlapping_locs is not None:
ax.xaxis.remove_overlapping_locs = remove_overlapping_locs

# check that getter/setter exists
current = ax.xaxis.remove_overlapping_locs
assert (current == ax.xaxis.get_remove_overlapping_locs())
plt.setp(ax.xaxis, remove_overlapping_locs=current)
new = ax.xaxis.remove_overlapping_locs
assert (new == ax.xaxis.remove_overlapping_locs)

# check that the accessors filter correctly
# this is the method that does the actual filtering
assert len(ax.xaxis.get_minorticklocs()) == expected_num
# these three are derivative
assert len(ax.xaxis.get_minor_ticks()) == expected_num
assert len(ax.xaxis.get_minorticklabels()) == expected_num
assert len(ax.xaxis.get_minorticklines()) == expected_num*2

# force a draw to call _update_ticks under the hood
fig.canvas.draw()
# check that the correct number of ticks report them selves as
# visible
assert sum(t.get_visible() for t in ax.xaxis.minorTicks) == expected_num