Skip to content

Commit 27df784

Browse files
committed
Use FixedFormatter only with FixedLocator
1 parent ea79c2a commit 27df784

File tree

5 files changed

+55
-25
lines changed

5 files changed

+55
-25
lines changed

lib/matplotlib/axes/_base.py

+21-9
Original file line numberDiff line numberDiff line change
@@ -3412,10 +3412,15 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs):
34123412
"""
34133413
Set the x-tick labels with list of string labels.
34143414
3415+
.. warning::
3416+
This method should only be used after fixing the tick positions
3417+
using `~.axes.Axes.set_xticks`. Otherwise, the labels may end up
3418+
in unexpected positions.
3419+
34153420
Parameters
34163421
----------
3417-
labels : List[str]
3418-
List of string labels.
3422+
labels : list of str
3423+
The label texts.
34193424
34203425
fontdict : dict, optional
34213426
A dictionary controlling the appearance of the ticklabels.
@@ -3426,12 +3431,13 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs):
34263431
'verticalalignment': 'baseline',
34273432
'horizontalalignment': loc}
34283433
3429-
minor : bool, optional
3434+
minor : bool, default: False
34303435
Whether to set the minor ticklabels rather than the major ones.
34313436
34323437
Returns
34333438
-------
3434-
A list of `~.text.Text` instances.
3439+
labels
3440+
A list of `~.text.Text` instances.
34353441
34363442
Other Parameters
34373443
-----------------
@@ -3792,12 +3798,17 @@ def get_yticklabels(self, minor=False, which=None):
37923798

37933799
def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs):
37943800
"""
3795-
Set the y-tick labels with list of strings labels.
3801+
Set the y-tick labels with list of string labels.
3802+
3803+
.. warning::
3804+
This method should only be used after fixing the tick positions
3805+
using `~.axes.Axes.set_yticks`. Otherwise, the labels may end up
3806+
in unexpected positions.
37963807
37973808
Parameters
37983809
----------
3799-
labels : List[str]
3800-
list of string labels
3810+
labels : list of str
3811+
The label texts.
38013812
38023813
fontdict : dict, optional
38033814
A dictionary controlling the appearance of the ticklabels.
@@ -3808,12 +3819,13 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs):
38083819
'verticalalignment': 'baseline',
38093820
'horizontalalignment': loc}
38103821
3811-
minor : bool, optional
3822+
minor : bool, default: False
38123823
Whether to set the minor ticklabels rather than the major ones.
38133824
38143825
Returns
38153826
-------
3816-
A list of `~.text.Text` instances.
3827+
labels
3828+
A list of `~.text.Text` instances.
38173829
38183830
Other Parameters
38193831
----------------

lib/matplotlib/axis.py

+18-12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import datetime
66
import logging
7+
import warnings
78

89
import numpy as np
910

@@ -1632,6 +1633,11 @@ def set_major_formatter(self, formatter):
16321633
formatter : `~matplotlib.ticker.Formatter`
16331634
"""
16341635
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1636+
if (isinstance(formatter, mticker.FixedFormatter)
1637+
and len(formatter.seq) > 0
1638+
and not isinstance(self.major.locator, mticker.FixedLocator)):
1639+
warnings.warn('FixedFormatter should only be used together with '
1640+
'FixedLocator', stacklevel=2)
16351641
self.isDefault_majfmt = False
16361642
self.major.formatter = formatter
16371643
formatter.set_axis(self)
@@ -1646,6 +1652,11 @@ def set_minor_formatter(self, formatter):
16461652
formatter : `~matplotlib.ticker.Formatter`
16471653
"""
16481654
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1655+
if (isinstance(formatter, mticker.FixedFormatter)
1656+
and len(formatter.seq) > 0
1657+
and not isinstance(self.minor.locator, mticker.FixedLocator)):
1658+
warnings.warn('FixedFormatter should only be used together with '
1659+
'FixedLocator', stacklevel=2)
16491660
self.isDefault_minfmt = False
16501661
self.minor.formatter = formatter
16511662
formatter.set_axis(self)
@@ -1697,6 +1708,11 @@ def set_ticklabels(self, ticklabels, *args, minor=False, **kwargs):
16971708
r"""
16981709
Set the text values of the tick labels.
16991710
1711+
.. warning::
1712+
This method should only be used after fixing the tick positions
1713+
using `.Axis.set_ticks`. Otherwise, the labels may end up in
1714+
unexpected positions.
1715+
17001716
Parameters
17011717
----------
17021718
ticklabels : sequence of str or of `Text`\s
@@ -1718,18 +1734,8 @@ def set_ticklabels(self, ticklabels, *args, minor=False, **kwargs):
17181734
"3.1", message="Additional positional arguments to "
17191735
"set_ticklabels are ignored, and deprecated since Matplotlib "
17201736
"3.1; passing them will raise a TypeError in Matplotlib 3.3.")
1721-
get_labels = []
1722-
for t in ticklabels:
1723-
# try calling get_text() to check whether it is Text object
1724-
# if it is Text, get label content
1725-
try:
1726-
get_labels.append(t.get_text())
1727-
# otherwise add the label to the list directly
1728-
except AttributeError:
1729-
get_labels.append(t)
1730-
# replace the ticklabels list with the processed one
1731-
ticklabels = get_labels
1732-
1737+
ticklabels = [t.get_text() if hasattr(t, 'get_text') else t
1738+
for t in ticklabels]
17331739
if minor:
17341740
self.set_minor_formatter(mticker.FixedFormatter(ticklabels))
17351741
ticks = self.get_minor_ticks()

lib/matplotlib/tests/test_axes.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -5064,15 +5064,18 @@ def test_set_get_ticklabels():
50645064
ax[1].set_title(ha[1])
50655065

50665066
# set ticklabel to 1 plot in normal way
5067-
ax[0].set_xticklabels(('a', 'b', 'c', 'd'))
5068-
ax[0].set_yticklabels(('11', '12', '13', '14'))
5067+
ax[0].set_xticks(range(10))
5068+
ax[0].set_yticks(range(10))
5069+
ax[0].set_xticklabels(['a', 'b', 'c', 'd'])
5070+
ax[0].set_yticklabels(['11', '12', '13', '14'])
50695071

50705072
# set ticklabel to the other plot, expect the 2 plots have same label
50715073
# setting pass get_ticklabels return value as ticklabels argument
5074+
ax[1].set_xticks(ax[0].get_xticks())
5075+
ax[1].set_yticks(ax[0].get_yticks())
50725076
ax[1].set_xticklabels(ax[0].get_xticklabels())
50735077
ax[1].set_yticklabels(ax[0].get_yticklabels())
50745078

5075-
50765079
@image_comparison(['retain_tick_visibility.png'])
50775080
def test_retain_tick_visibility():
50785081
fig, ax = plt.subplots()

lib/matplotlib/tests/test_figure.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import datetime
22
from pathlib import Path
33
import platform
4+
import warnings
45

56
from matplotlib import rcParams
67
from matplotlib.testing.decorators import image_comparison, check_figures_equal
@@ -317,7 +318,10 @@ def test_autofmt_xdate(which):
317318
ax.xaxis_date()
318319

319320
ax.xaxis.set_minor_locator(AutoMinorLocator(2))
320-
ax.xaxis.set_minor_formatter(FixedFormatter(minors))
321+
with warnings.filterwarnings(
322+
'ignore',
323+
'FixedFormatter should only be used together with FixedLocator')
324+
ax.xaxis.set_minor_formatter(FixedFormatter(minors))
321325

322326
fig.autofmt_xdate(0.2, angle, 'right', which)
323327

lib/matplotlib/ticker.py

+5
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,11 @@ def __call__(self, x, pos=None):
345345
class FixedFormatter(Formatter):
346346
"""
347347
Return fixed strings for tick labels based only on position, not value.
348+
349+
.. note::
350+
`.FixedFormatter` should only be used together with `.FixedLocator`.
351+
Otherwise, the labels may end up in unexpected positions.
352+
348353
"""
349354
def __init__(self, seq):
350355
"""

0 commit comments

Comments
 (0)