diff --git a/doc/api/next_api_changes/2018-01-30-AL.rst b/doc/api/next_api_changes/2018-01-30-AL.rst
new file mode 100644
index 000000000000..512cdbfbc764
--- /dev/null
+++ b/doc/api/next_api_changes/2018-01-30-AL.rst
@@ -0,0 +1,10 @@
+Minor Locator no longer try to avoid overstriking major Locators
+````````````````````````````````````````````````````````````````
+
+Previously, certain locator classes (`LogLocator`, `AutoMinorLocator`)
+contained custom logic to avoid emitting tick locations that collided with
+major ticks when they were used as minor locators.
+
+This logic has now moved to the Axis class; thus, for example,
+``xaxis.minor.locator()`` now includes positions that collide with
+``xaxis.major.locator()``, but ``xaxis.get_minorticklocs()`` does not.
diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py
index e8c60ee99573..3fb94e13ae14 100644
--- a/lib/matplotlib/axis.py
+++ b/lib/matplotlib/axis.py
@@ -1013,17 +1013,15 @@ def _set_artist_props(self, a):
def iter_ticks(self):
"""
- Iterate through all of the major and minor ticks.
+ Yield ``(Tick, location, label)`` tuples for major and minor ticks.
"""
- 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)
-
- minor_locs = self.minor.locator()
- minor_ticks = self.get_minor_ticks(len(minor_locs))
- minor_labels = self.minor.formatter.format_ticks(minor_locs)
-
+ major_ticks = self.get_major_ticks(len(major_locs))
yield from zip(major_ticks, major_locs, major_labels)
+ minor_locs = self.get_minorticklocs()
+ minor_labels = self.minor.formatter.format_ticks(minor_locs)
+ minor_ticks = self.get_minor_ticks(len(minor_locs))
yield from zip(minor_ticks, minor_locs, minor_labels)
def get_ticklabel_extents(self, renderer):
@@ -1304,18 +1302,29 @@ def get_ticklines(self, minor=False):
return self.get_majorticklines()
def get_majorticklocs(self):
- "Get the major tick locations in data coordinates as a numpy array"
+ """Get the array of major tick locations in data coordinates."""
return self.major.locator()
def get_minorticklocs(self):
- "Get the minor tick locations in data coordinates as a numpy array"
- return self.minor.locator()
+ """Get the array of minor tick locations in data coordinates."""
+ # Remove minor ticks duplicating major ticks.
+ major_locs = self.major.locator()
+ minor_locs = self.minor.locator()
+ transform = self._scale.get_transform()
+ tr_minor_locs = transform.transform(minor_locs)
+ tr_major_locs = transform.transform(major_locs)
+ lo, hi = sorted(transform.transform(self.get_view_interval()))
+ # 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()]
+ return minor_locs
def get_ticklocs(self, minor=False):
- "Get the tick locations in data coordinates as a numpy array"
- if minor:
- return self.minor.locator()
- return self.major.locator()
+ """Get the array of tick locations in data coordinates."""
+ return self.get_minorticklocs() if minor else self.get_majorticklocs()
def get_ticks_direction(self, minor=False):
"""
diff --git a/lib/matplotlib/tests/baseline_images/test_axes/symlog.png b/lib/matplotlib/tests/baseline_images/test_axes/symlog.png
deleted file mode 100644
index 4c20548006d3..000000000000
Binary files a/lib/matplotlib/tests/baseline_images/test_axes/symlog.png and /dev/null differ
diff --git a/lib/matplotlib/tests/baseline_images/test_axes/symlog.svg b/lib/matplotlib/tests/baseline_images/test_axes/symlog.svg
deleted file mode 100644
index 170ec4464325..000000000000
--- a/lib/matplotlib/tests/baseline_images/test_axes/symlog.svg
+++ /dev/null
@@ -1,679 +0,0 @@
-
-
-
-
diff --git a/lib/matplotlib/tests/baseline_images/test_axes/symlog2.png b/lib/matplotlib/tests/baseline_images/test_axes/symlog2.png
deleted file mode 100644
index 44e5cfa3025e..000000000000
Binary files a/lib/matplotlib/tests/baseline_images/test_axes/symlog2.png and /dev/null differ
diff --git a/lib/matplotlib/tests/baseline_images/test_axes/symlog2.svg b/lib/matplotlib/tests/baseline_images/test_axes/symlog2.svg
deleted file mode 100644
index 977f6ccdc084..000000000000
--- a/lib/matplotlib/tests/baseline_images/test_axes/symlog2.svg
+++ /dev/null
@@ -1,2143 +0,0 @@
-
-
-
-
diff --git a/lib/matplotlib/tests/baseline_images/test_scale/log_scales.pdf b/lib/matplotlib/tests/baseline_images/test_scale/log_scales.pdf
deleted file mode 100644
index 182416404c08..000000000000
Binary files a/lib/matplotlib/tests/baseline_images/test_scale/log_scales.pdf and /dev/null differ
diff --git a/lib/matplotlib/tests/baseline_images/test_scale/log_scales.png b/lib/matplotlib/tests/baseline_images/test_scale/log_scales.png
deleted file mode 100644
index 404023bce904..000000000000
Binary files a/lib/matplotlib/tests/baseline_images/test_scale/log_scales.png and /dev/null differ
diff --git a/lib/matplotlib/tests/baseline_images/test_scale/log_scales.svg b/lib/matplotlib/tests/baseline_images/test_scale/log_scales.svg
deleted file mode 100644
index 52dd71dc5d8b..000000000000
--- a/lib/matplotlib/tests/baseline_images/test_scale/log_scales.svg
+++ /dev/null
@@ -1,278 +0,0 @@
-
-
-
-
diff --git a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.pdf b/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.pdf
deleted file mode 100644
index 664c30a7b78e..000000000000
Binary files a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.pdf and /dev/null differ
diff --git a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.png b/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.png
deleted file mode 100644
index c34dc0bb9403..000000000000
Binary files a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.png and /dev/null differ
diff --git a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.svg b/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.svg
deleted file mode 100644
index 39c20581360b..000000000000
--- a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.svg
+++ /dev/null
@@ -1,1345 +0,0 @@
-
-
-
-
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index f9519f8074cc..1c657c4832a0 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -1064,7 +1064,10 @@ def test_fill_between_interpolate_decreasing():
ax.set_ylim(800, 600)
-@image_comparison(baseline_images=['symlog'])
+# test_symlog and test_symlog2 used to have baseline images in all three
+# formats, but the png and svg baselines got invalidated by the removal of
+# minor tick overstriking.
+@image_comparison(baseline_images=['symlog'], extensions=['pdf'])
def test_symlog():
x = np.array([0, 1, 2, 4, 6, 9, 12, 24])
y = np.array([1000000, 500000, 100000, 100, 5, 0, 0, 0])
@@ -1076,7 +1079,7 @@ def test_symlog():
ax.set_ylim(-1, 10000000)
-@image_comparison(baseline_images=['symlog2'],
+@image_comparison(baseline_images=['symlog2'], extensions=['pdf'],
remove_text=True)
def test_symlog2():
# Numbers from -50 to 50, with 0.1 as step
diff --git a/lib/matplotlib/tests/test_scale.py b/lib/matplotlib/tests/test_scale.py
index 26822a7adc69..75a61c310c1d 100644
--- a/lib/matplotlib/tests/test_scale.py
+++ b/lib/matplotlib/tests/test_scale.py
@@ -1,4 +1,4 @@
-from matplotlib.testing.decorators import image_comparison
+from matplotlib.testing.decorators import check_figures_equal, image_comparison
import matplotlib.pyplot as plt
from matplotlib.scale import Log10Transform, InvertedLog10Transform
@@ -8,12 +8,17 @@
import pytest
-@image_comparison(baseline_images=['log_scales'], remove_text=True)
-def test_log_scales():
- ax = plt.figure().add_subplot(122, yscale='log', xscale='symlog')
-
- ax.axvline(24.1)
- ax.axhline(24.1)
+@check_figures_equal()
+def test_log_scales(fig_test, fig_ref):
+ ax_test = fig_test.add_subplot(122, yscale='log', xscale='symlog')
+ ax_test.axvline(24.1)
+ ax_test.axhline(24.1)
+ xlim = ax_test.get_xlim()
+ ylim = ax_test.get_ylim()
+ ax_ref = fig_ref.add_subplot(122, yscale='log', xscale='symlog')
+ ax_ref.set(xlim=xlim, ylim=ylim)
+ ax_ref.plot([24.1, 24.1], ylim, 'b')
+ ax_ref.plot(xlim, [24.1, 24.1], 'b')
@image_comparison(baseline_images=['logit_scales'], remove_text=True,
diff --git a/lib/matplotlib/tests/test_tightlayout.py b/lib/matplotlib/tests/test_tightlayout.py
index 5898c1a94aeb..bae8951f8cd3 100644
--- a/lib/matplotlib/tests/test_tightlayout.py
+++ b/lib/matplotlib/tests/test_tightlayout.py
@@ -1,6 +1,7 @@
import warnings
import numpy as np
+from numpy.testing import assert_array_equal
from matplotlib.testing.decorators import image_comparison
import matplotlib.pyplot as plt
@@ -161,8 +162,6 @@ def test_tight_layout9():
plt.tight_layout()
-# The following test is misleading when the text is removed.
-@image_comparison(baseline_images=['outward_ticks'], remove_text=False)
def test_outward_ticks():
'Test automatic use of tight_layout'
fig = plt.figure()
@@ -173,8 +172,6 @@ def test_outward_ticks():
tickdir='out', length=32, width=3, tick1On=True, which='minor')
ax.yaxis.set_tick_params(
tickdir='out', length=32, width=3, tick1On=True, which='minor')
- # The following minor ticks are not labelled, and they
- # are drawn over the major ticks and labels--ugly!
ax.xaxis.set_ticks([0], minor=True)
ax.yaxis.set_ticks([0], minor=True)
ax = fig.add_subplot(222)
@@ -187,6 +184,14 @@ def test_outward_ticks():
ax.xaxis.set_tick_params(tickdir='out', length=32, width=3)
ax.yaxis.set_tick_params(tickdir='out', length=32, width=3)
plt.tight_layout()
+ assert_array_equal(
+ np.round([ax.get_position().get_points() for ax in fig.axes], 3),
+ # These values were obtained after visual checking that they correspond
+ # to a tight layouting that did take the ticks into account.
+ [[[0.091, 0.590], [0.437, 0.903]],
+ [[0.581, 0.590], [0.927, 0.903]],
+ [[0.091, 0.140], [0.437, 0.454]],
+ [[0.581, 0.140], [0.927, 0.454]]])
def add_offsetboxes(ax, size=10, margin=.1, color='black'):
diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py
index 290ce7a5f65c..90030a3415a7 100644
--- a/lib/matplotlib/ticker.py
+++ b/lib/matplotlib/ticker.py
@@ -2257,13 +2257,9 @@ def tick_values(self, vmin, vmax):
# If we're a minor locator *that expects at least two ticks per
# decade* and the major locator stride is 1 and there's no more
# than one minor tick, switch to AutoLocator.
- ticklocs = AutoLocator().tick_values(vmin, vmax)
- # Don't overstrike the major labels. Assumes major locs are
- # at b = self._base
- ticklocs = ticklocs[
- ~is_close_to_int(np.log(ticklocs) / np.log(b))]
- return ticklocs
- return self.raise_if_exceeds(ticklocs)
+ return AutoLocator().tick_values(vmin, vmax)
+ else:
+ return self.raise_if_exceeds(ticklocs)
def view_limits(self, vmin, vmax):
'Try to choose the view limits intelligently'
@@ -2644,10 +2640,6 @@ def __call__(self):
tmin = ((vmin - t0) // minorstep + 1) * minorstep
tmax = ((vmax - t0) // minorstep + 1) * minorstep
locs = np.arange(tmin, tmax, minorstep) + t0
- mod = np.abs((locs - t0) % majorstep)
- cond1 = mod > minorstep / 10.0
- cond2 = ~np.isclose(mod, majorstep, atol=0)
- locs = locs[cond1 & cond2]
return self.raise_if_exceeds(locs)