Skip to content

Commit 387a34e

Browse files
committed
New Formatter API.
A back-compatibility layer is missing. The LogFormatter and variants classes could use some improvement. Assigment to `Axes.fmt_{x,y}data` has been removed as assignment to `Axes.format_{x,y}data` does exactly the same.
1 parent 2a4863c commit 387a34e

36 files changed

+897
-1057
lines changed

doc/users/recipes.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ the x locations are formatted the same way the tick labels are, e.g.,
139139
a higher degree of precision, e.g., giving us the exact date out mouse is
140140
hovering over. To fix the first problem, we can use
141141
:func:`matplotlib.figure.Figure.autofmt_xdate` and to fix the second
142-
problem we can use the ``ax.fmt_xdata`` attribute which can be set to
142+
problem we can use the ``ax.format_xdata`` attribute which can be set to
143143
any function that takes a scalar and returns a string. matplotlib has
144144
a number of date formatters built in, so we'll use one of those.
145145

@@ -157,7 +157,7 @@ a number of date formatters built in, so we'll use one of those.
157157
# use a more precise date string for the x axis locations in the
158158
# toolbar
159159
import matplotlib.dates as mdates
160-
ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')
160+
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d').format_for_cursor
161161
plt.title('fig.autofmt_xdate fixes the labels')
162162

163163
Now when you hover your mouse over the plotted data, you'll see date

examples/api/custom_projection_example.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,12 @@ class DegreeFormatter(Formatter):
291291
"""
292292

293293
def __init__(self, round_to=1.0):
294+
super(HammerAxes.DegreeFormatter, self).__init__()
294295
self._round_to = round_to
295296

296-
def __call__(self, x, pos=None):
297+
def format_for_tick(self, x, pos=None):
297298
degrees = np.round(np.degrees(x) / self._round_to) * self._round_to
298-
# \u00b0 : degree symbol
299-
return "%d\u00b0" % degrees
299+
return "%d\N{DEGREE SIGN}" % degrees
300300

301301
def set_longitude_grid(self, degrees):
302302
"""

examples/api/custom_scale_example.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,8 @@ def set_default_locators_and_formatters(self, axis):
7070
value::
7171
"""
7272
class DegreeFormatter(Formatter):
73-
def __call__(self, x, pos=None):
74-
# \u00b0 : degree symbol
75-
return "%d\u00b0" % (np.degrees(x))
73+
def format_for_tick(self, x, pos=None):
74+
return "%d\N{DEGREE SIGN}" % (np.degrees(x))
7675

7776
axis.set_major_locator(FixedLocator(
7877
np.radians(np.arange(-90, 90, 10))))

examples/api/date_demo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
# format the coords message box
5353
def price(x):
5454
return '$%1.2f' % x
55-
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')
55+
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d').format_for_cursor
5656
ax.format_ydata = price
5757
ax.grid(True)
5858

examples/pylab_examples/contour_label_demo.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ def __repr__(self):
8080

8181
CS = plt.contour(X, Y, 100**Z, locator=plt.LogLocator())
8282
fmt = ticker.LogFormatterMathtext()
83-
fmt.create_dummy_axis()
84-
plt.clabel(CS, CS.levels, fmt=fmt)
83+
plt.clabel(CS, CS.levels, fmt=fmt.format_for_tick)
8584
plt.title("$100^Z$")
8685

8786
plt.show()

examples/pylab_examples/date_demo1.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@
4545
# format the coords message box
4646
def price(x):
4747
return '$%1.2f' % x
48-
ax.fmt_xdata = DateFormatter('%Y-%m-%d')
49-
ax.fmt_ydata = price
48+
ax.format_xdata = DateFormatter('%Y-%m-%d').format_for_cursor
49+
ax.format_ydata = price
5050
ax.grid(True)
5151

5252
fig.autofmt_xdate()

examples/pylab_examples/date_demo_convert.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
ax.xaxis.set_minor_locator(HourLocator(arange(0, 25, 6)))
2828
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
2929

30-
ax.fmt_xdata = DateFormatter('%Y-%m-%d %H:%M:%S')
30+
ax.format_xdata = DateFormatter('%Y-%m-%d %H:%M:%S').format_for_cursor
3131
fig.autofmt_xdate()
3232

3333
plt.show()

examples/pylab_examples/date_index_formatter.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222

2323
class MyFormatter(Formatter):
2424
def __init__(self, dates, fmt='%Y-%m-%d'):
25+
super(MyFormatter, self).__init__()
2526
self.dates = dates
2627
self.fmt = fmt
2728

28-
def __call__(self, x, pos=0):
29+
def format_for_tick(self, x, pos=0):
2930
'Return the label for time x at position pos'
3031
ind = int(round(x))
3132
if ind >= len(self.dates) or ind < 0:

examples/pylab_examples/demo_ribbon_box.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def draw(self, renderer, *args, **kwargs):
104104
]
105105
heights = np.random.random(years.shape) * 7000 + 3000
106106

107-
fmt = ScalarFormatter(useOffset=False)
107+
fmt = ScalarFormatter(use_offset=False)
108108
ax.xaxis.set_major_formatter(fmt)
109109

110110
for year, h, bc in zip(years, heights, box_colors):

examples/pylab_examples/finance_work2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def moving_average_convergence(x, nslow=26, nfast=12):
186186
label.set_rotation(30)
187187
label.set_horizontalalignment('right')
188188

189-
ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')
189+
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d').format_for_cursor
190190

191191

192192
class MyLocator(mticker.MaxNLocator):
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,6 @@
11
import matplotlib.pyplot as plt
22
import numpy as np
3-
from matplotlib.ticker import OldScalarFormatter, ScalarFormatter
4-
5-
# Example 1
6-
x = np.arange(0, 1, .01)
7-
fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2, figsize=(6, 6))
8-
fig.text(0.5, 0.975, 'The old formatter',
9-
horizontalalignment='center', verticalalignment='top')
10-
ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5)
11-
ax1.xaxis.set_major_formatter(OldScalarFormatter())
12-
ax1.yaxis.set_major_formatter(OldScalarFormatter())
13-
14-
ax2.plot(x * 1e5, x * 1e-4)
15-
ax2.xaxis.set_major_formatter(OldScalarFormatter())
16-
ax2.yaxis.set_major_formatter(OldScalarFormatter())
17-
18-
ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10)
19-
ax3.xaxis.set_major_formatter(OldScalarFormatter())
20-
ax3.yaxis.set_major_formatter(OldScalarFormatter())
21-
22-
ax4.plot(-x * 1e5, -x * 1e-4)
23-
ax4.xaxis.set_major_formatter(OldScalarFormatter())
24-
ax4.yaxis.set_major_formatter(OldScalarFormatter())
3+
from matplotlib.ticker import ScalarFormatter
254

265
# Example 2
276
x = np.arange(0, 1, .01)
@@ -54,20 +33,20 @@
5433
verticalalignment='top')
5534

5635
ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5)
57-
ax1.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
58-
ax1.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
36+
ax1.xaxis.set_major_formatter(ScalarFormatter(use_offset=False))
37+
ax1.yaxis.set_major_formatter(ScalarFormatter(use_offset=False))
5938

6039
ax2.plot(x * 1e5, x * 1e-4)
61-
ax2.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
62-
ax2.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
40+
ax2.xaxis.set_major_formatter(ScalarFormatter(use_offset=False))
41+
ax2.yaxis.set_major_formatter(ScalarFormatter(use_offset=False))
6342

6443
ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10)
65-
ax3.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
66-
ax3.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
44+
ax3.xaxis.set_major_formatter(ScalarFormatter(use_offset=False))
45+
ax3.yaxis.set_major_formatter(ScalarFormatter(use_offset=False))
6746

6847
ax4.plot(-x * 1e5, -x * 1e-4)
69-
ax4.xaxis.set_major_formatter(ScalarFormatter(useOffset=False))
70-
ax4.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
48+
ax4.xaxis.set_major_formatter(ScalarFormatter(use_offset=False))
49+
ax4.yaxis.set_major_formatter(ScalarFormatter(use_offset=False))
7150

7251
# Example 4
7352
x = np.arange(0, 1, .01)
@@ -77,18 +56,18 @@
7756
verticalalignment='top')
7857

7958
ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5)
80-
ax1.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
81-
ax1.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
59+
ax1.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
60+
ax1.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
8261

8362
ax2.plot(x * 1e5, x * 1e-4)
84-
ax2.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
85-
ax2.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
63+
ax2.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
64+
ax2.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
8665

8766
ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10)
88-
ax3.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
89-
ax3.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
67+
ax3.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
68+
ax3.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
9069

9170
ax4.plot(-x * 1e5, -x * 1e-4)
92-
ax4.xaxis.set_major_formatter(ScalarFormatter(useMathText=True))
93-
ax4.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
71+
ax4.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
72+
ax4.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True))
9473
plt.show()

lib/matplotlib/axes/_base.py

+8-31
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,6 @@ def __init__(self, fig, rect,
523523
self._hold = rcParams['axes.hold']
524524
self._connected = {} # a dict from events to (id, func)
525525
self.cla()
526-
# funcs used to format x and y - fall back on major formatters
527-
self.fmt_xdata = None
528-
self.fmt_ydata = None
529526

530527
self.set_cursor_props((1, 'k')) # set the cursor properties for axes
531528

@@ -2566,19 +2563,19 @@ def ticklabel_format(self, **kwargs):
25662563
self.yaxis.major.formatter.set_scientific(sb)
25672564
if scilimits is not None:
25682565
if axis == 'both' or axis == 'x':
2569-
self.xaxis.major.formatter.set_powerlimits(scilimits)
2566+
self.xaxis.major.formatter.powerlimits = scilimits
25702567
if axis == 'both' or axis == 'y':
2571-
self.yaxis.major.formatter.set_powerlimits(scilimits)
2568+
self.yaxis.major.formatter.powerlimits = scilimits
25722569
if useOffset is not None:
25732570
if axis == 'both' or axis == 'x':
2574-
self.xaxis.major.formatter.set_useOffset(useOffset)
2571+
self.xaxis.major.formatter.use_offset = useOffset
25752572
if axis == 'both' or axis == 'y':
2576-
self.yaxis.major.formatter.set_useOffset(useOffset)
2573+
self.yaxis.major.formatter.use_offset = useOffset
25772574
if useLocale is not None:
25782575
if axis == 'both' or axis == 'x':
2579-
self.xaxis.major.formatter.set_useLocale(useLocale)
2576+
self.xaxis.major.formatter.use_locale = useLocale
25802577
if axis == 'both' or axis == 'y':
2581-
self.yaxis.major.formatter.set_useLocale(useLocale)
2578+
self.yaxis.major.formatter.use_locale = useLocale
25822579
except AttributeError:
25832580
raise AttributeError(
25842581
"This method only works with the ScalarFormatter.")
@@ -3268,30 +3265,10 @@ def yaxis_date(self, tz=None):
32683265
self.yaxis.axis_date(tz)
32693266

32703267
def format_xdata(self, x):
3271-
"""
3272-
Return *x* string formatted. This function will use the attribute
3273-
self.fmt_xdata if it is callable, else will fall back on the xaxis
3274-
major formatter
3275-
"""
3276-
try:
3277-
return self.fmt_xdata(x)
3278-
except TypeError:
3279-
func = self.xaxis.get_major_formatter().format_data_short
3280-
val = func(x)
3281-
return val
3268+
return self.xaxis.get_major_formatter().format_for_cursor(x)
32823269

32833270
def format_ydata(self, y):
3284-
"""
3285-
Return y string formatted. This function will use the
3286-
:attr:`fmt_ydata` attribute if it is callable, else will fall
3287-
back on the yaxis major formatter
3288-
"""
3289-
try:
3290-
return self.fmt_ydata(y)
3291-
except TypeError:
3292-
func = self.yaxis.get_major_formatter().format_data_short
3293-
val = func(y)
3294-
return val
3271+
return self.yaxis.get_major_formatter().format_for_cursor(y)
32953272

32963273
def format_coord(self, x, y):
32973274
"""Return a format string formatting the *x*, *y* coord"""

lib/matplotlib/axis.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -901,14 +901,14 @@ def iter_ticks(self):
901901
"""
902902
majorLocs = self.major.locator()
903903
majorTicks = self.get_major_ticks(len(majorLocs))
904-
self.major.formatter.set_locs(majorLocs)
905-
majorLabels = [self.major.formatter(val, i)
904+
self.major.formatter.locs = majorLocs
905+
majorLabels = [self.major.formatter.format_for_tick(val, i)
906906
for i, val in enumerate(majorLocs)]
907907

908908
minorLocs = self.minor.locator()
909909
minorTicks = self.get_minor_ticks(len(minorLocs))
910-
self.minor.formatter.set_locs(minorLocs)
911-
minorLabels = [self.minor.formatter(val, i)
910+
self.minor.formatter.locs = minorLocs
911+
minorLabels = [self.minor.formatter.format_for_tick(val, i)
912912
for i, val in enumerate(minorLocs)]
913913

914914
major_minor = [
@@ -1087,7 +1087,7 @@ def get_tightbbox(self, renderer):
10871087
self._update_label_position(ticklabelBoxes, ticklabelBoxes2)
10881088

10891089
self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)
1090-
self.offsetText.set_text(self.major.formatter.get_offset())
1090+
self.offsetText.set_text(self.major.formatter.offset_text)
10911091

10921092
bb = []
10931093

@@ -1140,7 +1140,7 @@ def draw(self, renderer, *args, **kwargs):
11401140
self.label.draw(renderer)
11411141

11421142
self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)
1143-
self.offsetText.set_text(self.major.formatter.get_offset())
1143+
self.offsetText.set_text(self.major.formatter.offset_text)
11441144
self.offsetText.draw(renderer)
11451145

11461146
if 0: # draw the bounding boxes around the text for debug

lib/matplotlib/colorbar.py

+12-13
Original file line numberDiff line numberDiff line change
@@ -370,16 +370,16 @@ def update_ticks(self):
370370
called whenever the tick locator and/or tick formatter changes.
371371
"""
372372
ax = self.ax
373-
ticks, ticklabels, offset_string = self._ticker()
373+
ticks, ticklabels, offset_text = self._ticker()
374374
if self.orientation == 'vertical':
375375
ax.yaxis.set_ticks(ticks)
376376
ax.set_yticklabels(ticklabels)
377-
ax.yaxis.get_major_formatter().set_offset_string(offset_string)
377+
ax.yaxis.get_major_formatter().offset_text = offset_text
378378

379379
else:
380380
ax.xaxis.set_ticks(ticks)
381381
ax.set_xticklabels(ticklabels)
382-
ax.xaxis.get_major_formatter().set_offset_string(offset_string)
382+
ax.xaxis.get_major_formatter().offset_text = offset_text
383383

384384
def set_ticks(self, ticks, update_ticks=True):
385385
"""
@@ -584,12 +584,12 @@ def _ticker(self):
584584
intv = self._values[0], self._values[-1]
585585
else:
586586
intv = self.vmin, self.vmax
587-
locator.create_dummy_axis(minpos=intv[0])
588-
formatter.create_dummy_axis(minpos=intv[0])
589-
locator.set_view_interval(*intv)
590-
locator.set_data_interval(*intv)
591-
formatter.set_view_interval(*intv)
592-
formatter.set_data_interval(*intv)
587+
locator.set_axis({"minpos": intv[0]})
588+
formatter.set_axis({"minpos": intv[0]})
589+
locator.axis.set_view_interval(*intv)
590+
locator.axis.set_data_interval(*intv)
591+
formatter.axis.set_view_interval(*intv)
592+
formatter.axis.set_data_interval(*intv)
593593

594594
b = np.array(locator())
595595
if isinstance(locator, ticker.LogLocator):
@@ -599,10 +599,9 @@ def _ticker(self):
599599
eps = (intv[1] - intv[0]) * 1e-10
600600
b = b[(b <= intv[1] + eps) & (b >= intv[0] - eps)]
601601
ticks = self._locate(b)
602-
formatter.set_locs(b)
603-
ticklabels = [formatter(t, i) for i, t in enumerate(b)]
604-
offset_string = formatter.get_offset()
605-
return ticks, ticklabels, offset_string
602+
formatter.locs = b
603+
ticklabels = [formatter.format_for_tick(t, i) for i, t in enumerate(b)]
604+
return ticks, ticklabels, formatter.offset_text
606605

607606
def _process_values(self, b=None):
608607
'''

0 commit comments

Comments
 (0)