Skip to content

Commit ec0ea84

Browse files
committed
Allow sharing locators across axises.
Locally changing the assigned axis seems to be the most practical solution, if not the most elegant.
1 parent c010a36 commit ec0ea84

File tree

4 files changed

+46
-12
lines changed

4 files changed

+46
-12
lines changed

lib/matplotlib/axis.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1527,14 +1527,14 @@ def get_ticklines(self, minor=False):
15271527

15281528
def get_majorticklocs(self):
15291529
"""Return this Axis' major tick locations in data coordinates."""
1530-
return self.major.locator()
1530+
return self.major.locator._call_with_axis(self)
15311531

15321532
def get_minorticklocs(self):
15331533
"""Return this Axis' minor tick locations in data coordinates."""
15341534
# Remove minor ticks duplicating major ticks.
1535-
minor_locs = np.asarray(self.minor.locator())
1535+
minor_locs = np.asarray(self.minor.locator._call_with_axis(self))
15361536
if self.remove_overlapping_locs:
1537-
major_locs = self.major.locator()
1537+
major_locs = self.major.locator._call_with_axis(self)
15381538
transform = self._scale.get_transform()
15391539
tr_minor_locs = transform.transform(minor_locs)
15401540
tr_major_locs = transform.transform(major_locs)

lib/matplotlib/tests/test_ticker.py

+13
Original file line numberDiff line numberDiff line change
@@ -1873,3 +1873,16 @@ def test_minorticks_on_multi_fig():
18731873

18741874
assert ax.get_xgridlines()
18751875
assert isinstance(ax.xaxis.get_minor_locator(), mpl.ticker.AutoMinorLocator)
1876+
1877+
1878+
def test_locator_reuse():
1879+
fig = plt.figure()
1880+
ax = fig.add_subplot(xlim=(.6, .8))
1881+
loc = mticker.AutoLocator()
1882+
ax.xaxis.set_major_locator(loc)
1883+
ax.yaxis.set_major_locator(loc)
1884+
fig.draw_without_rendering()
1885+
xticklabels = [l.get_text() for l in ax.get_xticklabels()]
1886+
yticklabels = [l.get_text() for l in ax.get_yticklabels()]
1887+
assert xticklabels == ["0.60", "0.65", "0.70", "0.75", "0.80"]
1888+
assert yticklabels == ["0.0", "0.2", "0.4", "0.6", "0.8", "1.0"]

lib/matplotlib/ticker.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -1629,11 +1629,28 @@ def set_params(self, **kwargs):
16291629
str(type(self)))
16301630

16311631
def __call__(self):
1632-
"""Return the locations of the ticks."""
1632+
"""
1633+
Return the locations of the ticks.
1634+
1635+
The returned locations depend on the locator's axis. If a locator
1636+
is used across multiple axises, make sure to (temporarily) set
1637+
``locator.axis`` to the correct axis before getting the tick locations.
1638+
"""
16331639
# note: some locators return data limits, other return view limits,
16341640
# hence there is no *one* interface to call self.tick_values.
16351641
raise NotImplementedError('Derived must override')
16361642

1643+
def _call_with_axis(self, axis):
1644+
"""
1645+
Get the tick locations while the locator's axis is temporarily set to *axis*.
1646+
"""
1647+
current = axis
1648+
try:
1649+
self.set_axis(axis)
1650+
return self()
1651+
finally:
1652+
self.set_axis(current)
1653+
16371654
def raise_if_exceeds(self, locs):
16381655
"""
16391656
Log at WARNING level if *locs* is longer than `Locator.MAXTICKS`.

lib/mpl_toolkits/axisartist/axislines.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,11 @@ def get_tick_iterators(self, axes):
185185
angle_normal, angle_tangent = {0: (90, 0), 1: (0, 90)}[self.nth_coord]
186186

187187
major = self.axis.major
188-
major_locs = major.locator()
188+
major_locs = major.locator._call_with_axis(self.axis)
189189
major_labels = major.formatter.format_ticks(major_locs)
190190

191191
minor = self.axis.minor
192-
minor_locs = minor.locator()
192+
minor_locs = minor.locator._call_with_axis(self.axis)
193193
minor_labels = minor.formatter.format_ticks(minor_locs)
194194

195195
tick_to_axes = self.get_tick_transform(axes) - axes.transAxes
@@ -246,11 +246,11 @@ def get_tick_iterators(self, axes):
246246
angle_normal, angle_tangent = {0: (90, 0), 1: (0, 90)}[self.nth_coord]
247247

248248
major = self.axis.major
249-
major_locs = major.locator()
249+
major_locs = major.locator._call_with_axis(self.axis)
250250
major_labels = major.formatter.format_ticks(major_locs)
251251

252252
minor = self.axis.minor
253-
minor_locs = minor.locator()
253+
minor_locs = minor.locator._call_with_axis(self.axis)
254254
minor_labels = minor.formatter.format_ticks(minor_locs)
255255

256256
data_to_axes = axes.transData - axes.transAxes
@@ -351,18 +351,22 @@ def get_gridlines(self, which="major", axis="both"):
351351
locs = []
352352
y1, y2 = self.axes.get_ylim()
353353
if which in ("both", "major"):
354-
locs.extend(self.axes.xaxis.major.locator())
354+
locs.extend(
355+
self.axes.xaxis.major.locator._call_with_axis(self.axes.xaxis))
355356
if which in ("both", "minor"):
356-
locs.extend(self.axes.xaxis.minor.locator())
357+
locs.extend(
358+
self.axes.xaxis.minor.locator._call_with_axis(self.axes.xaxis))
357359
gridlines.extend([[x, x], [y1, y2]] for x in locs)
358360

359361
if axis in ("both", "y"):
360362
x1, x2 = self.axes.get_xlim()
361363
locs = []
362364
if self.axes.yaxis._major_tick_kw["gridOn"]:
363-
locs.extend(self.axes.yaxis.major.locator())
365+
locs.extend(
366+
self.axes.yaxis.major.locator._call_with_axis(self.axes.yaxis))
364367
if self.axes.yaxis._minor_tick_kw["gridOn"]:
365-
locs.extend(self.axes.yaxis.minor.locator())
368+
locs.extend(
369+
self.axes.yaxis.minor.locator._call_with_axis(self.axis.yaxis))
366370
gridlines.extend([[x1, x2], [y, y]] for y in locs)
367371

368372
return gridlines

0 commit comments

Comments
 (0)