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

Skip to content

Commit dce1871

Browse files
authored
Merge pull request #14575 from anntzer/ticklabel_format
Make ticklabel_format work both for 2D and 3D axes.
2 parents 623b333 + 7cf9bba commit dce1871

File tree

4 files changed

+91
-118
lines changed

4 files changed

+91
-118
lines changed

examples/ticks_and_spines/scalarformatter.py

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,36 @@
11
"""
2-
=========================================
3-
Tick formatting using the ScalarFormatter
4-
=========================================
2+
==========================
3+
The default tick formatter
4+
==========================
55
6-
The example shows use of ScalarFormatter with different settings.
6+
The example shows use of the default `ScalarFormatter` with different settings.
77
88
Example 1 : Default
99
1010
Example 2 : With no Numerical Offset
1111
1212
Example 3 : With Mathtext
1313
"""
14+
1415
import matplotlib.pyplot as plt
1516
import numpy as np
16-
from matplotlib.ticker import ScalarFormatter
1717

1818
###############################################################################
1919
# Example 1
2020

2121
x = np.arange(0, 1, .01)
2222
fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2, figsize=(6, 6))
23-
fig.text(0.5, 0.975, 'The new formatter, default settings',
23+
fig.text(0.5, 0.975, 'Default settings',
2424
horizontalalignment='center',
2525
verticalalignment='top')
2626

2727
ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5)
28-
ax1.xaxis.set_major_formatter(ScalarFormatter())
29-
ax1.yaxis.set_major_formatter(ScalarFormatter())
3028

3129
ax2.plot(x * 1e5, x * 1e-4)
32-
ax2.xaxis.set_major_formatter(ScalarFormatter())
33-
ax2.yaxis.set_major_formatter(ScalarFormatter())
3430

3531
ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10)
36-
ax3.xaxis.set_major_formatter(ScalarFormatter())
37-
ax3.yaxis.set_major_formatter(ScalarFormatter())
3832

3933
ax4.plot(-x * 1e5, -x * 1e-4)
40-
ax4.xaxis.set_major_formatter(ScalarFormatter())
41-
ax4.yaxis.set_major_formatter(ScalarFormatter())
4234

4335
fig.subplots_adjust(wspace=0.7, hspace=0.6)
4436

@@ -47,25 +39,21 @@
4739

4840
x = np.arange(0, 1, .01)
4941
fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2, figsize=(6, 6))
50-
fig.text(0.5, 0.975, 'The new formatter, no numerical offset',
42+
fig.text(0.5, 0.975, 'No numerical offset',
5143
horizontalalignment='center',
5244
verticalalignment='top')
5345

5446
ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5)
55-
ax1.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
56-
ax1.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
47+
ax1.ticklabel_format(useOffset=False)
5748

5849
ax2.plot(x * 1e5, x * 1e-4)
59-
ax2.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
60-
ax2.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
50+
ax2.ticklabel_format(useOffset=False)
6151

6252
ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10)
63-
ax3.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
64-
ax3.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
53+
ax3.ticklabel_format(useOffset=False)
6554

6655
ax4.plot(-x * 1e5, -x * 1e-4)
67-
ax4.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
68-
ax4.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
56+
ax4.ticklabel_format(useOffset=False)
6957

7058
fig.subplots_adjust(wspace=0.7, hspace=0.6)
7159

@@ -74,25 +62,21 @@
7462

7563
x = np.arange(0, 1, .01)
7664
fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2, figsize=(6, 6))
77-
fig.text(0.5, 0.975, 'The new formatter, with mathtext',
65+
fig.text(0.5, 0.975, 'With mathtext',
7866
horizontalalignment='center',
7967
verticalalignment='top')
8068

8169
ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5)
82-
ax1.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
83-
ax1.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
70+
ax1.ticklabel_format(useMathText=True)
8471

8572
ax2.plot(x * 1e5, x * 1e-4)
86-
ax2.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
87-
ax2.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
73+
ax2.ticklabel_format(useMathText=True)
8874

8975
ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10)
90-
ax3.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
91-
ax3.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
76+
ax3.ticklabel_format(useMathText=True)
9277

9378
ax4.plot(-x * 1e5, -x * 1e-4)
94-
ax4.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
95-
ax4.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
79+
ax4.ticklabel_format(useMathText=True)
9680

9781
fig.subplots_adjust(wspace=0.7, hspace=0.6)
9882

lib/matplotlib/axes/_base.py

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,6 +2460,24 @@ def tol(x): return 1e-5 * abs(x) + 1e-8
24602460
def _get_axis_list(self):
24612461
return (self.xaxis, self.yaxis)
24622462

2463+
def _get_axis_map(self):
2464+
"""
2465+
Return a mapping of `Axis` "names" to `Axis` instances.
2466+
2467+
The `Axis` name is derived from the attribute under which the instance
2468+
is stored, so e.g. for polar axes, the theta-axis is still named "x"
2469+
and the r-axis is still named "y" (for back-compatibility).
2470+
2471+
In practice, this means that the entries are typically "x" and "y", and
2472+
additionally "z" for 3D axes.
2473+
"""
2474+
d = {}
2475+
axis_list = self._get_axis_list()
2476+
for k, v in vars(self).items():
2477+
if k.endswith("axis") and v in axis_list:
2478+
d[k[:-len("axis")]] = v
2479+
return d
2480+
24632481
def _update_title_position(self, renderer):
24642482
"""
24652483
Update the title position based on the bounding box enclosing
@@ -2799,35 +2817,24 @@ def ticklabel_format(self, *, axis='both', style='', scilimits=None,
27992817
sb = None
28002818
else:
28012819
raise ValueError("%s is not a valid style value")
2820+
axis_map = {**{k: [v] for k, v in self._get_axis_map().items()},
2821+
'both': self._get_axis_list()}
2822+
axises = cbook._check_getitem(axis_map, axis=axis)
28022823
try:
2803-
if sb is not None:
2804-
if axis == 'both' or axis == 'x':
2805-
self.xaxis.major.formatter.set_scientific(sb)
2806-
if axis == 'both' or axis == 'y':
2807-
self.yaxis.major.formatter.set_scientific(sb)
2808-
if scilimits is not None:
2809-
if axis == 'both' or axis == 'x':
2810-
self.xaxis.major.formatter.set_powerlimits(scilimits)
2811-
if axis == 'both' or axis == 'y':
2812-
self.yaxis.major.formatter.set_powerlimits(scilimits)
2813-
if useOffset is not None:
2814-
if axis == 'both' or axis == 'x':
2815-
self.xaxis.major.formatter.set_useOffset(useOffset)
2816-
if axis == 'both' or axis == 'y':
2817-
self.yaxis.major.formatter.set_useOffset(useOffset)
2818-
if useLocale is not None:
2819-
if axis == 'both' or axis == 'x':
2820-
self.xaxis.major.formatter.set_useLocale(useLocale)
2821-
if axis == 'both' or axis == 'y':
2822-
self.yaxis.major.formatter.set_useLocale(useLocale)
2823-
if useMathText is not None:
2824-
if axis == 'both' or axis == 'x':
2825-
self.xaxis.major.formatter.set_useMathText(useMathText)
2826-
if axis == 'both' or axis == 'y':
2827-
self.yaxis.major.formatter.set_useMathText(useMathText)
2824+
for axis in axises:
2825+
if sb is not None:
2826+
axis.major.formatter.set_scientific(sb)
2827+
if scilimits is not None:
2828+
axis.major.formatter.set_powerlimits(scilimits)
2829+
if useOffset is not None:
2830+
axis.major.formatter.set_useOffset(useOffset)
2831+
if useLocale is not None:
2832+
axis.major.formatter.set_useLocale(useLocale)
2833+
if useMathText is not None:
2834+
axis.major.formatter.set_useMathText(useMathText)
28282835
except AttributeError:
28292836
raise AttributeError(
2830-
"This method only works with the ScalarFormatter.")
2837+
"This method only works with the ScalarFormatter")
28312838

28322839
def locator_params(self, axis='both', tight=None, **kwargs):
28332840
"""

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,63 +1295,6 @@ def grid(self, b=True, **kwargs):
12951295
self._draw_grid = b
12961296
self.stale = True
12971297

1298-
def ticklabel_format(
1299-
self, *, style='', scilimits=None, useOffset=None, axis='both'):
1300-
"""
1301-
Convenience method for manipulating the ScalarFormatter
1302-
used by default for linear axes in Axed3D objects.
1303-
1304-
See :meth:`matplotlib.axes.Axes.ticklabel_format` for full
1305-
documentation. Note that this version applies to all three
1306-
axes of the Axes3D object. Therefore, the *axis* argument
1307-
will also accept a value of 'z' and the value of 'both' will
1308-
apply to all three axes.
1309-
1310-
.. versionadded :: 1.1.0
1311-
This function was added, but not tested. Please report any bugs.
1312-
"""
1313-
style = style.lower()
1314-
axis = axis.lower()
1315-
if scilimits is not None:
1316-
try:
1317-
m, n = scilimits
1318-
m+n+1 # check that both are numbers
1319-
except (ValueError, TypeError):
1320-
raise ValueError("scilimits must be a sequence of 2 integers")
1321-
if style[:3] == 'sci':
1322-
sb = True
1323-
elif style == 'plain':
1324-
sb = False
1325-
elif style == '':
1326-
sb = None
1327-
else:
1328-
raise ValueError("%s is not a valid style value")
1329-
try:
1330-
if sb is not None:
1331-
if axis in ['both', 'z']:
1332-
self.xaxis.major.formatter.set_scientific(sb)
1333-
if axis in ['both', 'y']:
1334-
self.yaxis.major.formatter.set_scientific(sb)
1335-
if axis in ['both', 'z']:
1336-
self.zaxis.major.formatter.set_scientific(sb)
1337-
if scilimits is not None:
1338-
if axis in ['both', 'x']:
1339-
self.xaxis.major.formatter.set_powerlimits(scilimits)
1340-
if axis in ['both', 'y']:
1341-
self.yaxis.major.formatter.set_powerlimits(scilimits)
1342-
if axis in ['both', 'z']:
1343-
self.zaxis.major.formatter.set_powerlimits(scilimits)
1344-
if useOffset is not None:
1345-
if axis in ['both', 'x']:
1346-
self.xaxis.major.formatter.set_useOffset(useOffset)
1347-
if axis in ['both', 'y']:
1348-
self.yaxis.major.formatter.set_useOffset(useOffset)
1349-
if axis in ['both', 'z']:
1350-
self.zaxis.major.formatter.set_useOffset(useOffset)
1351-
except AttributeError:
1352-
raise AttributeError(
1353-
"This method only works with the ScalarFormatter.")
1354-
13551298
def locator_params(self, axis='both', tight=None, **kwargs):
13561299
"""
13571300
Convenience method for controlling tick locators.

lib/mpl_toolkits/tests/test_mplot3d.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from mpl_toolkits.mplot3d import Axes3D, axes3d, proj3d, art3d
4+
import matplotlib as mpl
45
from matplotlib import cm
56
from matplotlib import path as mpath
67
from matplotlib.testing.decorators import image_comparison, check_figures_equal
@@ -449,12 +450,10 @@ def test_poly3dcollection_alpha():
449450

450451
@image_comparison(['axes3d_labelpad.png'])
451452
def test_axes3d_labelpad():
452-
from matplotlib import rcParams
453-
454453
fig = plt.figure()
455454
ax = Axes3D(fig)
456455
# labelpad respects rcParams
457-
assert ax.xaxis.labelpad == rcParams['axes.labelpad']
456+
assert ax.xaxis.labelpad == mpl.rcParams['axes.labelpad']
458457
# labelpad can be set in set_label
459458
ax.set_xlabel('X LABEL', labelpad=10)
460459
assert ax.xaxis.labelpad == 10
@@ -903,3 +902,43 @@ def test_ax3d_tickcolour():
903902
assert tick.tick1line._color == 'red'
904903
for tick in ax.zaxis.get_major_ticks():
905904
assert tick.tick1line._color == 'red'
905+
906+
907+
@check_figures_equal(extensions=["png"])
908+
def test_ticklabel_format(fig_test, fig_ref):
909+
axs = fig_test.subplots(4, 5, subplot_kw={"projection": "3d"})
910+
for ax in axs.flat:
911+
ax.set_xlim(1e7, 1e7 + 10)
912+
for row, name in zip(axs, ["x", "y", "z", "both"]):
913+
row[0].ticklabel_format(
914+
axis=name, style="plain")
915+
row[1].ticklabel_format(
916+
axis=name, scilimits=(-2, 2))
917+
row[2].ticklabel_format(
918+
axis=name, useOffset=not mpl.rcParams["axes.formatter.useoffset"])
919+
row[3].ticklabel_format(
920+
axis=name, useLocale=not mpl.rcParams["axes.formatter.use_locale"])
921+
row[4].ticklabel_format(
922+
axis=name,
923+
useMathText=not mpl.rcParams["axes.formatter.use_mathtext"])
924+
925+
def get_formatters(ax, names):
926+
return [getattr(ax, name).get_major_formatter() for name in names]
927+
928+
axs = fig_ref.subplots(4, 5, subplot_kw={"projection": "3d"})
929+
for ax in axs.flat:
930+
ax.set_xlim(1e7, 1e7 + 10)
931+
for row, names in zip(
932+
axs, [["xaxis"], ["yaxis"], ["zaxis"], ["xaxis", "yaxis", "zaxis"]]
933+
):
934+
for fmt in get_formatters(row[0], names):
935+
fmt.set_scientific(False)
936+
for fmt in get_formatters(row[1], names):
937+
fmt.set_powerlimits((-2, 2))
938+
for fmt in get_formatters(row[2], names):
939+
fmt.set_useOffset(not mpl.rcParams["axes.formatter.useoffset"])
940+
for fmt in get_formatters(row[3], names):
941+
fmt.set_useLocale(not mpl.rcParams["axes.formatter.use_locale"])
942+
for fmt in get_formatters(row[4], names):
943+
fmt.set_useMathText(
944+
not mpl.rcParams["axes.formatter.use_mathtext"])

0 commit comments

Comments
 (0)