From 387a34eb7a1d3ed23f60ff3459e098ece670eaf0 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 5 Jan 2016 00:35:04 -0800 Subject: [PATCH 1/3] 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. --- doc/users/recipes.rst | 4 +- examples/api/custom_projection_example.py | 6 +- examples/api/custom_scale_example.py | 5 +- examples/api/date_demo.py | 2 +- examples/pylab_examples/contour_label_demo.py | 3 +- examples/pylab_examples/date_demo1.py | 4 +- examples/pylab_examples/date_demo_convert.py | 2 +- .../pylab_examples/date_index_formatter.py | 3 +- examples/pylab_examples/demo_ribbon_box.py | 2 +- examples/pylab_examples/finance_work2.py | 2 +- .../pylab_examples/newscalarformatter_demo.py | 55 +- lib/matplotlib/axes/_base.py | 39 +- lib/matplotlib/axis.py | 12 +- lib/matplotlib/colorbar.py | 25 +- lib/matplotlib/dates.py | 22 +- lib/matplotlib/projections/geo.py | 3 +- lib/matplotlib/projections/polar.py | 2 +- lib/matplotlib/pyplot.py | 2 +- .../testing/jpl_units/StrConverter.py | 1 - .../testing/jpl_units/UnitDblConverter.py | 2 +- .../testing/jpl_units/UnitDblFormatter.py | 28 +- .../test_axes/formatter_large_small.pdf | Bin 7331 -> 7533 bytes .../test_axes/formatter_large_small.png | Bin 23432 -> 26168 bytes .../test_axes/formatter_large_small.svg | 214 +++-- .../test_subplots/subplots_offset_text.pdf | Bin 9260 -> 9597 bytes .../test_subplots/subplots_offset_text.png | Bin 35250 -> 37080 bytes .../test_subplots/subplots_offset_text.svg | 518 +++++----- lib/matplotlib/tests/test_dates.py | 8 +- lib/matplotlib/tests/test_ticker.py | 21 +- lib/matplotlib/ticker.py | 901 ++++++++---------- lib/mpl_toolkits/axes_grid1/axes_grid.py | 6 +- lib/mpl_toolkits/axisartist/axis_artist.py | 2 +- lib/mpl_toolkits/axisartist/axislines.py | 16 +- lib/mpl_toolkits/axisartist/grid_finder.py | 16 +- lib/mpl_toolkits/mplot3d/axes3d.py | 18 +- lib/mpl_toolkits/mplot3d/axis3d.py | 10 +- 36 files changed, 897 insertions(+), 1057 deletions(-) diff --git a/doc/users/recipes.rst b/doc/users/recipes.rst index 174241b79e7b..891b9d02beca 100644 --- a/doc/users/recipes.rst +++ b/doc/users/recipes.rst @@ -139,7 +139,7 @@ the x locations are formatted the same way the tick labels are, e.g., a higher degree of precision, e.g., giving us the exact date out mouse is hovering over. To fix the first problem, we can use :func:`matplotlib.figure.Figure.autofmt_xdate` and to fix the second -problem we can use the ``ax.fmt_xdata`` attribute which can be set to +problem we can use the ``ax.format_xdata`` attribute which can be set to any function that takes a scalar and returns a string. matplotlib has a number of date formatters built in, so we'll use one of those. @@ -157,7 +157,7 @@ a number of date formatters built in, so we'll use one of those. # use a more precise date string for the x axis locations in the # toolbar import matplotlib.dates as mdates - ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') + ax.format_xdata = mdates.DateFormatter('%Y-%m-%d').format_for_cursor plt.title('fig.autofmt_xdate fixes the labels') Now when you hover your mouse over the plotted data, you'll see date diff --git a/examples/api/custom_projection_example.py b/examples/api/custom_projection_example.py index 32018c534604..d0fba4a7c17f 100644 --- a/examples/api/custom_projection_example.py +++ b/examples/api/custom_projection_example.py @@ -291,12 +291,12 @@ class DegreeFormatter(Formatter): """ def __init__(self, round_to=1.0): + super(HammerAxes.DegreeFormatter, self).__init__() self._round_to = round_to - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): degrees = np.round(np.degrees(x) / self._round_to) * self._round_to - # \u00b0 : degree symbol - return "%d\u00b0" % degrees + return "%d\N{DEGREE SIGN}" % degrees def set_longitude_grid(self, degrees): """ diff --git a/examples/api/custom_scale_example.py b/examples/api/custom_scale_example.py index df8fe46d2737..dfd3aae59a2e 100644 --- a/examples/api/custom_scale_example.py +++ b/examples/api/custom_scale_example.py @@ -70,9 +70,8 @@ def set_default_locators_and_formatters(self, axis): value:: """ class DegreeFormatter(Formatter): - def __call__(self, x, pos=None): - # \u00b0 : degree symbol - return "%d\u00b0" % (np.degrees(x)) + def format_for_tick(self, x, pos=None): + return "%d\N{DEGREE SIGN}" % (np.degrees(x)) axis.set_major_locator(FixedLocator( np.radians(np.arange(-90, 90, 10)))) diff --git a/examples/api/date_demo.py b/examples/api/date_demo.py index 7e419bb9ee44..0f7702ea0b5b 100644 --- a/examples/api/date_demo.py +++ b/examples/api/date_demo.py @@ -52,7 +52,7 @@ # format the coords message box def price(x): return '$%1.2f' % x -ax.format_xdata = mdates.DateFormatter('%Y-%m-%d') +ax.format_xdata = mdates.DateFormatter('%Y-%m-%d').format_for_cursor ax.format_ydata = price ax.grid(True) diff --git a/examples/pylab_examples/contour_label_demo.py b/examples/pylab_examples/contour_label_demo.py index 42eb8f579406..d12a5508b47b 100644 --- a/examples/pylab_examples/contour_label_demo.py +++ b/examples/pylab_examples/contour_label_demo.py @@ -80,8 +80,7 @@ def __repr__(self): CS = plt.contour(X, Y, 100**Z, locator=plt.LogLocator()) fmt = ticker.LogFormatterMathtext() -fmt.create_dummy_axis() -plt.clabel(CS, CS.levels, fmt=fmt) +plt.clabel(CS, CS.levels, fmt=fmt.format_for_tick) plt.title("$100^Z$") plt.show() diff --git a/examples/pylab_examples/date_demo1.py b/examples/pylab_examples/date_demo1.py index 45fbf128840e..8e16c7db635e 100644 --- a/examples/pylab_examples/date_demo1.py +++ b/examples/pylab_examples/date_demo1.py @@ -45,8 +45,8 @@ # format the coords message box def price(x): return '$%1.2f' % x -ax.fmt_xdata = DateFormatter('%Y-%m-%d') -ax.fmt_ydata = price +ax.format_xdata = DateFormatter('%Y-%m-%d').format_for_cursor +ax.format_ydata = price ax.grid(True) fig.autofmt_xdate() diff --git a/examples/pylab_examples/date_demo_convert.py b/examples/pylab_examples/date_demo_convert.py index 693a6752a3ca..50b6f9befc9a 100644 --- a/examples/pylab_examples/date_demo_convert.py +++ b/examples/pylab_examples/date_demo_convert.py @@ -27,7 +27,7 @@ ax.xaxis.set_minor_locator(HourLocator(arange(0, 25, 6))) ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d')) -ax.fmt_xdata = DateFormatter('%Y-%m-%d %H:%M:%S') +ax.format_xdata = DateFormatter('%Y-%m-%d %H:%M:%S').format_for_cursor fig.autofmt_xdate() plt.show() diff --git a/examples/pylab_examples/date_index_formatter.py b/examples/pylab_examples/date_index_formatter.py index 1234bb5b5850..d66d5c1fc673 100644 --- a/examples/pylab_examples/date_index_formatter.py +++ b/examples/pylab_examples/date_index_formatter.py @@ -22,10 +22,11 @@ class MyFormatter(Formatter): def __init__(self, dates, fmt='%Y-%m-%d'): + super(MyFormatter, self).__init__() self.dates = dates self.fmt = fmt - def __call__(self, x, pos=0): + def format_for_tick(self, x, pos=0): 'Return the label for time x at position pos' ind = int(round(x)) if ind >= len(self.dates) or ind < 0: diff --git a/examples/pylab_examples/demo_ribbon_box.py b/examples/pylab_examples/demo_ribbon_box.py index df39dede071a..280f1320ef02 100644 --- a/examples/pylab_examples/demo_ribbon_box.py +++ b/examples/pylab_examples/demo_ribbon_box.py @@ -104,7 +104,7 @@ def draw(self, renderer, *args, **kwargs): ] heights = np.random.random(years.shape) * 7000 + 3000 - fmt = ScalarFormatter(useOffset=False) + fmt = ScalarFormatter(use_offset=False) ax.xaxis.set_major_formatter(fmt) for year, h, bc in zip(years, heights, box_colors): diff --git a/examples/pylab_examples/finance_work2.py b/examples/pylab_examples/finance_work2.py index 6fa0f3244e58..162bcad34fab 100644 --- a/examples/pylab_examples/finance_work2.py +++ b/examples/pylab_examples/finance_work2.py @@ -186,7 +186,7 @@ def moving_average_convergence(x, nslow=26, nfast=12): label.set_rotation(30) label.set_horizontalalignment('right') - ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') + ax.format_xdata = mdates.DateFormatter('%Y-%m-%d').format_for_cursor class MyLocator(mticker.MaxNLocator): diff --git a/examples/pylab_examples/newscalarformatter_demo.py b/examples/pylab_examples/newscalarformatter_demo.py index 1e525ad8cb6e..fc42c6462f66 100644 --- a/examples/pylab_examples/newscalarformatter_demo.py +++ b/examples/pylab_examples/newscalarformatter_demo.py @@ -1,27 +1,6 @@ import matplotlib.pyplot as plt import numpy as np -from matplotlib.ticker import OldScalarFormatter, ScalarFormatter - -# Example 1 -x = np.arange(0, 1, .01) -fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2, figsize=(6, 6)) -fig.text(0.5, 0.975, 'The old formatter', - horizontalalignment='center', verticalalignment='top') -ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5) -ax1.xaxis.set_major_formatter(OldScalarFormatter()) -ax1.yaxis.set_major_formatter(OldScalarFormatter()) - -ax2.plot(x * 1e5, x * 1e-4) -ax2.xaxis.set_major_formatter(OldScalarFormatter()) -ax2.yaxis.set_major_formatter(OldScalarFormatter()) - -ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10) -ax3.xaxis.set_major_formatter(OldScalarFormatter()) -ax3.yaxis.set_major_formatter(OldScalarFormatter()) - -ax4.plot(-x * 1e5, -x * 1e-4) -ax4.xaxis.set_major_formatter(OldScalarFormatter()) -ax4.yaxis.set_major_formatter(OldScalarFormatter()) +from matplotlib.ticker import ScalarFormatter # Example 2 x = np.arange(0, 1, .01) @@ -54,20 +33,20 @@ verticalalignment='top') ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5) -ax1.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) -ax1.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax1.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax1.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) ax2.plot(x * 1e5, x * 1e-4) -ax2.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) -ax2.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax2.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax2.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10) -ax3.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) -ax3.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax3.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax3.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) ax4.plot(-x * 1e5, -x * 1e-4) -ax4.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) -ax4.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax4.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax4.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) # Example 4 x = np.arange(0, 1, .01) @@ -77,18 +56,18 @@ verticalalignment='top') ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5) -ax1.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) -ax1.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax1.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax1.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) ax2.plot(x * 1e5, x * 1e-4) -ax2.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) -ax2.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax2.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax2.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10) -ax3.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) -ax3.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax3.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax3.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) ax4.plot(-x * 1e5, -x * 1e-4) -ax4.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) -ax4.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax4.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax4.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) plt.show() diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 6e9cddbd0445..0d191c19b9c6 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -523,9 +523,6 @@ def __init__(self, fig, rect, self._hold = rcParams['axes.hold'] self._connected = {} # a dict from events to (id, func) self.cla() - # funcs used to format x and y - fall back on major formatters - self.fmt_xdata = None - self.fmt_ydata = None self.set_cursor_props((1, 'k')) # set the cursor properties for axes @@ -2566,19 +2563,19 @@ def ticklabel_format(self, **kwargs): self.yaxis.major.formatter.set_scientific(sb) if scilimits is not None: if axis == 'both' or axis == 'x': - self.xaxis.major.formatter.set_powerlimits(scilimits) + self.xaxis.major.formatter.powerlimits = scilimits if axis == 'both' or axis == 'y': - self.yaxis.major.formatter.set_powerlimits(scilimits) + self.yaxis.major.formatter.powerlimits = scilimits if useOffset is not None: if axis == 'both' or axis == 'x': - self.xaxis.major.formatter.set_useOffset(useOffset) + self.xaxis.major.formatter.use_offset = useOffset if axis == 'both' or axis == 'y': - self.yaxis.major.formatter.set_useOffset(useOffset) + self.yaxis.major.formatter.use_offset = useOffset if useLocale is not None: if axis == 'both' or axis == 'x': - self.xaxis.major.formatter.set_useLocale(useLocale) + self.xaxis.major.formatter.use_locale = useLocale if axis == 'both' or axis == 'y': - self.yaxis.major.formatter.set_useLocale(useLocale) + self.yaxis.major.formatter.use_locale = useLocale except AttributeError: raise AttributeError( "This method only works with the ScalarFormatter.") @@ -3268,30 +3265,10 @@ def yaxis_date(self, tz=None): self.yaxis.axis_date(tz) def format_xdata(self, x): - """ - Return *x* string formatted. This function will use the attribute - self.fmt_xdata if it is callable, else will fall back on the xaxis - major formatter - """ - try: - return self.fmt_xdata(x) - except TypeError: - func = self.xaxis.get_major_formatter().format_data_short - val = func(x) - return val + return self.xaxis.get_major_formatter().format_for_cursor(x) def format_ydata(self, y): - """ - Return y string formatted. This function will use the - :attr:`fmt_ydata` attribute if it is callable, else will fall - back on the yaxis major formatter - """ - try: - return self.fmt_ydata(y) - except TypeError: - func = self.yaxis.get_major_formatter().format_data_short - val = func(y) - return val + return self.yaxis.get_major_formatter().format_for_cursor(y) def format_coord(self, x, y): """Return a format string formatting the *x*, *y* coord""" diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 8062ebc66e4a..76b2b9100e39 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -901,14 +901,14 @@ def iter_ticks(self): """ majorLocs = self.major.locator() majorTicks = self.get_major_ticks(len(majorLocs)) - self.major.formatter.set_locs(majorLocs) - majorLabels = [self.major.formatter(val, i) + self.major.formatter.locs = majorLocs + majorLabels = [self.major.formatter.format_for_tick(val, i) for i, val in enumerate(majorLocs)] minorLocs = self.minor.locator() minorTicks = self.get_minor_ticks(len(minorLocs)) - self.minor.formatter.set_locs(minorLocs) - minorLabels = [self.minor.formatter(val, i) + self.minor.formatter.locs = minorLocs + minorLabels = [self.minor.formatter.format_for_tick(val, i) for i, val in enumerate(minorLocs)] major_minor = [ @@ -1087,7 +1087,7 @@ def get_tightbbox(self, renderer): self._update_label_position(ticklabelBoxes, ticklabelBoxes2) self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2) - self.offsetText.set_text(self.major.formatter.get_offset()) + self.offsetText.set_text(self.major.formatter.offset_text) bb = [] @@ -1140,7 +1140,7 @@ def draw(self, renderer, *args, **kwargs): self.label.draw(renderer) self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2) - self.offsetText.set_text(self.major.formatter.get_offset()) + self.offsetText.set_text(self.major.formatter.offset_text) self.offsetText.draw(renderer) if 0: # draw the bounding boxes around the text for debug diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index ad6a145a9d12..0dd9a3599683 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -370,16 +370,16 @@ def update_ticks(self): called whenever the tick locator and/or tick formatter changes. """ ax = self.ax - ticks, ticklabels, offset_string = self._ticker() + ticks, ticklabels, offset_text = self._ticker() if self.orientation == 'vertical': ax.yaxis.set_ticks(ticks) ax.set_yticklabels(ticklabels) - ax.yaxis.get_major_formatter().set_offset_string(offset_string) + ax.yaxis.get_major_formatter().offset_text = offset_text else: ax.xaxis.set_ticks(ticks) ax.set_xticklabels(ticklabels) - ax.xaxis.get_major_formatter().set_offset_string(offset_string) + ax.xaxis.get_major_formatter().offset_text = offset_text def set_ticks(self, ticks, update_ticks=True): """ @@ -584,12 +584,12 @@ def _ticker(self): intv = self._values[0], self._values[-1] else: intv = self.vmin, self.vmax - locator.create_dummy_axis(minpos=intv[0]) - formatter.create_dummy_axis(minpos=intv[0]) - locator.set_view_interval(*intv) - locator.set_data_interval(*intv) - formatter.set_view_interval(*intv) - formatter.set_data_interval(*intv) + locator.set_axis({"minpos": intv[0]}) + formatter.set_axis({"minpos": intv[0]}) + locator.axis.set_view_interval(*intv) + locator.axis.set_data_interval(*intv) + formatter.axis.set_view_interval(*intv) + formatter.axis.set_data_interval(*intv) b = np.array(locator()) if isinstance(locator, ticker.LogLocator): @@ -599,10 +599,9 @@ def _ticker(self): eps = (intv[1] - intv[0]) * 1e-10 b = b[(b <= intv[1] + eps) & (b >= intv[0] - eps)] ticks = self._locate(b) - formatter.set_locs(b) - ticklabels = [formatter(t, i) for i, t in enumerate(b)] - offset_string = formatter.get_offset() - return ticks, ticklabels, offset_string + formatter.locs = b + ticklabels = [formatter.format_for_tick(t, i) for i, t in enumerate(b)] + return ticks, ticklabels, formatter.offset_text def _process_values(self, b=None): ''' diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py index fbd0bf480cda..29e3c9c1e2a9 100755 --- a/lib/matplotlib/dates.py +++ b/lib/matplotlib/dates.py @@ -470,12 +470,13 @@ def __init__(self, fmt, tz=None): *fmt* is a :func:`strftime` format string; *tz* is the :class:`tzinfo` instance. """ + super(DateFormatter, self).__init__() if tz is None: tz = _get_rc_timezone() self.fmt = fmt self.tz = tz - def __call__(self, x, pos=0): + def format_for_tick(self, x, pos=0): if x == 0: raise ValueError('DateFormatter found a value of x=0, which is ' 'an illegal date. This usually occurs because ' @@ -601,13 +602,14 @@ def __init__(self, t, fmt, tz=None): *t* is a sequence of dates (floating point days). *fmt* is a :func:`strftime` format string. """ + super(IndexDateFormatter, self).__init__() if tz is None: tz = _get_rc_timezone() self.t = t self.fmt = fmt self.tz = tz - def __call__(self, x, pos=0): + def format_for_tick(self, x, pos=0): 'Return the label for time *x* at position *pos*' ind = int(np.round(x)) if ind >= len(self.t) or ind <= 0: @@ -681,6 +683,7 @@ def __init__(self, locator, tz=None, defaultfmt='%Y-%m-%d'): if none of the values in ``self.scaled`` are greater than the unit returned by ``locator._get_unit()``. """ + super(AutoDateFormatter, self).__init__() self._locator = locator self._tz = tz self.defaultfmt = defaultfmt @@ -694,7 +697,7 @@ def __init__(self, locator, tz=None, defaultfmt='%Y-%m-%d'): 1. / (SEC_PER_DAY): rcParams['date.autoformatter.second']} - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): locator_unit_scale = float(self._locator._get_unit()) fmt = self.defaultfmt @@ -706,7 +709,7 @@ def __call__(self, x, pos=None): if isinstance(fmt, six.string_types): self._formatter = DateFormatter(fmt, self._tz) - result = self._formatter(x, pos) + result = self._formatter.format_for_tick(x, pos) elif six.callable(fmt): result = fmt(x, pos) else: @@ -1130,9 +1133,6 @@ def get_locator(self, dmin, dmax): locator = MicrosecondLocator(interval, tz=self.tz) locator.set_axis(self.axis) - - locator.set_view_interval(*self.axis.get_view_interval()) - locator.set_data_interval(*self.axis.get_data_interval()) return locator @@ -1357,14 +1357,6 @@ def set_axis(self, axis): self._wrapped_locator.set_axis(axis) return DateLocator.set_axis(self, axis) - def set_view_interval(self, vmin, vmax): - self._wrapped_locator.set_view_interval(vmin, vmax) - return DateLocator.set_view_interval(self, vmin, vmax) - - def set_data_interval(self, vmin, vmax): - self._wrapped_locator.set_data_interval(vmin, vmax) - return DateLocator.set_data_interval(self, vmin, vmax) - def __call__(self): # if no data have been set, this will tank with a ValueError try: diff --git a/lib/matplotlib/projections/geo.py b/lib/matplotlib/projections/geo.py index 338deec8279d..504a0ebc9d98 100644 --- a/lib/matplotlib/projections/geo.py +++ b/lib/matplotlib/projections/geo.py @@ -30,9 +30,10 @@ class ThetaFormatter(Formatter): unit of radians into degrees and adds a degree symbol. """ def __init__(self, round_to=1.0): + super(GeoAxes.ThetaFormatter, self).__init__() self._round_to = round_to - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): degrees = (x / np.pi) * 180.0 degrees = np.round(degrees / self._round_to) * self._round_to if rcParams['text.usetex'] and not rcParams['text.latex.unicode']: diff --git a/lib/matplotlib/projections/polar.py b/lib/matplotlib/projections/polar.py index a52e343bb07e..db9a359f5ffa 100644 --- a/lib/matplotlib/projections/polar.py +++ b/lib/matplotlib/projections/polar.py @@ -171,7 +171,7 @@ class ThetaFormatter(Formatter): Used to format the *theta* tick labels. Converts the native unit of radians into degrees and adds a degree symbol. """ - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): # \u00b0 : degree symbol if rcParams['text.usetex'] and not rcParams['text.latex.unicode']: return r"$%0.0f^\circ$" % ((x / np.pi) * 180.0) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 23feaf7f57be..c0ec1a8a5c01 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -59,7 +59,7 @@ from matplotlib.patches import Polygon, Rectangle, Circle, Arrow from matplotlib.widgets import SubplotTool, Button, Slider, Widget -from .ticker import TickHelper, Formatter, FixedFormatter, NullFormatter,\ +from .ticker import Formatter, FixedFormatter, NullFormatter,\ FuncFormatter, FormatStrFormatter, ScalarFormatter,\ LogFormatter, LogFormatterExponent, LogFormatterMathtext,\ Locator, IndexLocator, FixedLocator, NullLocator,\ diff --git a/lib/matplotlib/testing/jpl_units/StrConverter.py b/lib/matplotlib/testing/jpl_units/StrConverter.py index cdf44d903b07..9aa7750e7a2e 100644 --- a/lib/matplotlib/testing/jpl_units/StrConverter.py +++ b/lib/matplotlib/testing/jpl_units/StrConverter.py @@ -127,7 +127,6 @@ def convert( value, unit, axis ): axis.set_ticklabels( labels ) # we have to do the following lines to make ax.autoscale_view work loc = axis.get_major_locator() - loc.set_bounds( ticks[0], ticks[-1] ) if ( isXAxis ): ax.set_xlim( ticks[0], ticks[-1] ) diff --git a/lib/matplotlib/testing/jpl_units/UnitDblConverter.py b/lib/matplotlib/testing/jpl_units/UnitDblConverter.py index c5e3307e1d66..5fb407766a70 100644 --- a/lib/matplotlib/testing/jpl_units/UnitDblConverter.py +++ b/lib/matplotlib/testing/jpl_units/UnitDblConverter.py @@ -89,7 +89,7 @@ def axisinfo( unit, axis ): # If we want degrees for a polar plot, use the PolarPlotFormatter majfmt = polar.PolarAxes.ThetaFormatter() else: - majfmt = U.UnitDblFormatter( useOffset = False ) + majfmt = U.UnitDblFormatter() return units.AxisInfo( majfmt = majfmt, label = label ) diff --git a/lib/matplotlib/testing/jpl_units/UnitDblFormatter.py b/lib/matplotlib/testing/jpl_units/UnitDblFormatter.py index b4ccb1d21b09..8b186162a4cd 100644 --- a/lib/matplotlib/testing/jpl_units/UnitDblFormatter.py +++ b/lib/matplotlib/testing/jpl_units/UnitDblFormatter.py @@ -23,25 +23,9 @@ __all__ = [ 'UnitDblFormatter' ] #=========================================================================== -class UnitDblFormatter( ticker.ScalarFormatter ): - """The formatter for UnitDbl data types. This allows for formatting - with the unit string. - """ - def __init__( self, *args, **kwargs ): - 'The arguments are identical to matplotlib.ticker.ScalarFormatter.' - ticker.ScalarFormatter.__init__( self, *args, **kwargs ) - - def __call__( self, x, pos = None ): - 'Return the format for tick val x at position pos' - if len(self.locs) == 0: - return '' - else: - return str(x) - - def format_data_short( self, value ): - "Return the value formatted in 'short' format." - return str(value) - - def format_data( self, value ): - "Return the value formatted into a string." - return str(value) +class UnitDblFormatter(ticker.Formatter): + """The formatter for UnitDbl data types. This allows for formatting + with the unit string. + """ + def format_for_tick(self, value, pos=None): + return str(value) diff --git a/lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.pdf b/lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.pdf index ec3ad7f1ce74ea9a37e3d433cd08c33116f2a4ef..f199a3f75e79b15e014079d11946b48d9ae22596 100644 GIT binary patch delta 2783 zcmaJ@c~nzZ8lSLKd4viwKmtmymEeMqw`D_ILXbsKwqc#3K9Wa>gcnR68mVL41|6xR z_=b$0qMkYghf-Txv~&io3$z}FcItxFbFe**I+L-ML2T`4JyYhsmmr&``6uuG-o4-V zyT5$j_sgF&1Bv@*II<}tZ38$!K`xO0YEv~0e@1!Ik zPqi>CAUyl?Dky`AF#@G$nN6`QZDoMMvna4_Og}2VG+2v7tHk*!-*i2CU)%AE&eK63+OD{Y zceLmt*x&S>{rlYB1G4_Z-1(C!Irp-hPa-aA!MEBA+m5Q1-h9{|vFG(PD(ceU@&8nj z>sLG;Jer)e`?{?2$W8t1$UCA8>g8HfnY(qcV$kJ|Ug&a^tA_orlKR&k5(SA*&h8j| zC~jMUTnP9WzYOC|&7P`?Dk>fLDe3D$Mp^mMlJ!NcPmW`=B>KequBNP8dn)a%JLgDS5XQs8?xe}mtUkLx(nq!al zu9lS@t6AQ?#*zF^$H^bJZ}sb+@{jb$wksv|XNF2Lt{2_>DfpG_xA&b~blzQ6CtmB* z^+Q*#@83%2RWe zyh?m$IMMjaI}b7oieCEQ!oi;9*YHE`V`caa(vaGDzr5#ErNb4t%avhp$+)mjQwk1+ z_ngu@m)8A$$(oh_GWP7bc*ObRQf2FKL(GB$(yG5A4_BF1$fRfUM0dBpCj;C{WJ|NC z-cay#)Uf51-Ae8!|6Szo3{!aI`Plkq`KK3g-*R2?C%PLHN zw|CuNqT}9`CNvIL%_yY&E}!^*%l;EjOYipWj;T3%#u9P=y9&R#Go2yXr$1KVfqORc*~9on}1;!~Ax*O_m2 zJ_|2iyxH*Yet%u`Ua_l7dP#J+k6C;0#veDk({{45_u8VC_=>xX_l#l6u1(#WqvMA6 zpQDFX$nHPdP+ISBY9GJGt@n%aRcbWcKEJR4Z=n+^SmY7h+2EiAM4p^%vBP$X$50#t z@uZRfm`Xze3?~TKW8OyhHYg_w(S`9%I-zq&4c|3faKK7#^^~BIG-^~pe-~hmz+TX9 z1jf?{Z?B(HEaFN7o*&a-JUp%i6?;2F&ZARxueV&D8vF+K>|Ur( z^9Tek1a9|vsZ^9tj-jKgpsf5 z^CnP=cuQ>=qqhiF0cWs0)nxTXK}SkaAU$e0*jUw9Qg(qCzz7oe7|=vwK%N0T%cR#j z7^9hn5<${7J?|FrIH80Y&6Lpw2=D2i)dI-1o|76}!+T+MI&CsmumDBmMI(>!<}6)R zz~}K;CQqNwX!SQ$vleUnkQS%$Q(8T+J0r(v$QQz(&X~v$JV=EX4{&D%WCww|SkGzugPBabHPNLPv`tzRJYF zESQo@kY)ys84278X;LVfP;IfX7>cRmj4HJOBS}3sAeAH`avgMH)?{H)_{?)t5^)q$ zq8O?`6_}dD<5ATd6rD3~jJeybbUA_o0_CKUs8NYS>G%&|03tk~N)mPK$5*QrP6XU_6_hM?B=E`l5hM!xb9^R3#TVjuj6_K|t|nlZ z2F@yUEksAJqg0O7hqY2BGi?<{b)Kn~hQBzF=UOZ*ELovhGMI8$;!qXXIl_NB%E}7G Pp;RkKL?&C7m5TfyFpQFL delta 2620 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 ab4y$OPf?Qr(}U#l7)Or9wjBQa+kXKo1l4c= diff --git a/lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.svg b/lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.svg index 20b200e11b39..b46dda5771bd 100644 --- a/lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.svg +++ b/lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.svg @@ -27,7 +27,7 @@ z " style="fill:#ffffff;"/> - @@ -57,20 +57,20 @@ L 518.400024 43.2 +" id="md6960c55f4" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="me8e5a1c3e0" style="stroke:#000000;stroke-width:0.5;"/> - + @@ -115,22 +115,22 @@ Q 6.59375 54.828125 13.0625 64.515625 Q 19.53125 74.21875 31.78125 74.21875 " id="DejaVuSans-30"/> - + - - + + - + - + @@ -160,22 +160,22 @@ Q 44.1875 33.984375 37.640625 27.21875 Q 31.109375 20.453125 19.1875 8.296875 " id="DejaVuSans-32"/> - + - - + + - + - + @@ -199,22 +199,22 @@ L 4.890625 26.703125 z " id="DejaVuSans-34"/> - + - - + + - + - + @@ -249,22 +249,22 @@ Q 40.921875 74.21875 44.703125 73.484375 Q 48.484375 72.75 52.59375 71.296875 " id="DejaVuSans-36"/> - + - - + + - + - + @@ -307,56 +307,70 @@ Q 25.390625 66.40625 21.84375 63.234375 Q 18.3125 60.0625 18.3125 54.390625 " id="DejaVuSans-38"/> - + - - + + - + - + - + - - + + - + - + - + - - + + - + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -472,152 +495,153 @@ z +" id="me44b38b30c" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="mda8a1b39f7" style="stroke:#000000;stroke-width:0.5;"/> - + - + - - - + + + - + - + - + - - - + + + - + - + - + - - - + + + - + - + - + - - - + + + - + - + - + - - - + + + - + - + - + - - - + + + - - - - - - + + + + + + + - - + + diff --git a/lib/matplotlib/tests/baseline_images/test_subplots/subplots_offset_text.pdf b/lib/matplotlib/tests/baseline_images/test_subplots/subplots_offset_text.pdf index e871bd270bf231861331a0f8d31f40d605cca68f..980ebc1fe85402e2476b7bc858a5e4404be5d5d6 100644 GIT binary patch delta 4340 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 literal 35250 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 - +" id="m75a748e1cc" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="m0255bfac70" style="stroke:#000000;stroke-width:0.5;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -197,20 +197,20 @@ L 0 4 +" id="mb9b80b1413" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="mc0c71078d8" style="stroke:#000000;stroke-width:0.5;"/> - + @@ -236,7 +236,7 @@ Q 6.59375 54.828125 13.0625 64.515625 Q 19.53125 74.21875 31.78125 74.21875 " id="DejaVuSans-30"/> - + @@ -244,12 +244,12 @@ Q 19.53125 74.21875 31.78125 74.21875 - + - + @@ -269,7 +269,7 @@ L 12.40625 0 z " id="DejaVuSans-31"/> - + @@ -277,12 +277,12 @@ z - + - + @@ -312,7 +312,7 @@ Q 44.1875 33.984375 37.640625 27.21875 Q 31.109375 20.453125 19.1875 8.296875 " id="DejaVuSans-32"/> - + @@ -320,12 +320,12 @@ Q 31.109375 20.453125 19.1875 8.296875 - + - + @@ -363,7 +363,7 @@ Q 53.90625 49.265625 50.4375 45.09375 Q 46.96875 40.921875 40.578125 39.3125 " id="DejaVuSans-33"/> - + @@ -371,12 +371,12 @@ Q 46.96875 40.921875 40.578125 39.3125 - + - + @@ -400,7 +400,7 @@ L 4.890625 26.703125 z " id="DejaVuSans-34"/> - + @@ -408,12 +408,12 @@ z - + - + @@ -444,7 +444,7 @@ Q 14.890625 38.140625 10.796875 36.28125 z " id="DejaVuSans-35"/> - + @@ -452,12 +452,12 @@ z - + - + @@ -492,7 +492,7 @@ Q 40.921875 74.21875 44.703125 73.484375 Q 48.484375 72.75 52.59375 71.296875 " id="DejaVuSans-36"/> - + @@ -500,12 +500,12 @@ Q 48.484375 72.75 52.59375 71.296875 - + - + @@ -521,7 +521,7 @@ L 8.203125 64.59375 z " id="DejaVuSans-37"/> - + @@ -529,12 +529,12 @@ z - + - + @@ -577,7 +577,7 @@ Q 25.390625 66.40625 21.84375 63.234375 Q 18.3125 60.0625 18.3125 54.390625 " id="DejaVuSans-38"/> - + @@ -585,12 +585,12 @@ Q 18.3125 60.0625 18.3125 54.390625 - + - + @@ -625,14 +625,28 @@ Q 16.21875 41.5 20.09375 36.953125 Q 23.96875 32.421875 30.609375 32.421875 " id="DejaVuSans-39"/> - + - + + - - - - + + + + + @@ -675,7 +690,7 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -833,120 +848,120 @@ L 518.4 43.2 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -962,7 +977,7 @@ z " style="fill:#ffffff;"/> - - + - + - + @@ -1016,17 +1031,17 @@ L 274.909091 231.709091 - + - + - + @@ -1034,17 +1049,17 @@ L 274.909091 231.709091 - + - + - + @@ -1052,17 +1067,17 @@ L 274.909091 231.709091 - + - + - + @@ -1070,17 +1085,17 @@ L 274.909091 231.709091 - + - + - + @@ -1088,17 +1103,17 @@ L 274.909091 231.709091 - + - + - + @@ -1106,17 +1121,17 @@ L 274.909091 231.709091 - + - + - + @@ -1124,17 +1139,17 @@ L 274.909091 231.709091 - + - + - + @@ -1142,17 +1157,17 @@ L 274.909091 231.709091 - + - + - + @@ -1160,27 +1175,28 @@ L 274.909091 231.709091 - + - + - + - - - - - + + + + + + @@ -1188,17 +1204,17 @@ L 274.909091 231.709091 - + - + - + @@ -1206,17 +1222,17 @@ L 274.909091 231.709091 - + - + - + @@ -1224,17 +1240,17 @@ L 274.909091 231.709091 - + - + - + @@ -1242,17 +1258,17 @@ L 274.909091 231.709091 - + - + - + @@ -1260,17 +1276,17 @@ L 274.909091 231.709091 - + - + - + @@ -1278,17 +1294,17 @@ L 274.909091 231.709091 - + - + - + @@ -1296,17 +1312,17 @@ L 274.909091 231.709091 - + - + - + @@ -1314,17 +1330,17 @@ L 274.909091 231.709091 - + - + - + @@ -1332,17 +1348,17 @@ L 274.909091 231.709091 - + - + - + @@ -1350,27 +1366,28 @@ L 274.909091 231.709091 - + - + - + - - - - - + + + + + + @@ -1385,7 +1402,7 @@ z " style="fill:#ffffff;"/> - - + - + - + @@ -1439,176 +1456,176 @@ L 518.4 231.709091 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - + - - - + + + + + + + + @@ -1637,120 +1665,120 @@ z - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1758,17 +1786,17 @@ z - - + + - - + + - - + + - - + + diff --git a/lib/matplotlib/tests/test_dates.py b/lib/matplotlib/tests/test_dates.py index 54afc633bf7e..c830c488d90c 100644 --- a/lib/matplotlib/tests/test_dates.py +++ b/lib/matplotlib/tests/test_dates.py @@ -216,7 +216,7 @@ def test_date_formatter_callable(): formatter = mdates.AutoDateFormatter(locator) formatter.scaled[-10] = callable_formatting_function - assert_equal(formatter([datetime.datetime(2014, 12, 25)]), + assert_equal(formatter.format_for_tick([datetime.datetime(2014, 12, 25)]), ['25-12//2014']) @@ -271,9 +271,9 @@ def test_empty_date_with_year_formatter(): def test_auto_date_locator(): def _create_auto_date_locator(date1, date2): locator = mdates.AutoDateLocator() - locator.create_dummy_axis() - locator.set_view_interval(mdates.date2num(date1), - mdates.date2num(date2)) + locator.set_axis({}) + locator.axis.set_view_interval(mdates.date2num(date1), + mdates.date2num(date2)) return locator d1 = datetime.datetime(1990, 1, 1) diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 438be20aa7ce..557fd3607e09 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -161,7 +161,8 @@ def test_SymmetricalLogLocator_set_params(): def _logfe_helper(formatter, base, locs, i, expected_result): vals = base**locs - labels = [formatter(x, pos) for (x, pos) in zip(vals, i)] + labels = [formatter.format_for_tick(x, pos).replace("\N{MINUS SIGN}", "-") + for (x, pos) in zip(vals, i)] nose.tools.assert_equal(labels, expected_result) @@ -182,31 +183,31 @@ def get_view_interval(self): formatter.axis = FakeAxis(1, base**4) yield _logfe_helper, formatter, base, i, i, expected_result - # Should be a blank string for non-integer powers if labelOnlyBase=True - formatter = mticker.LogFormatterExponent(base=10, labelOnlyBase=True) + # Should be a blank string for non-integer powers if label_minor is False. + formatter = mticker.LogFormatterExponent(base=10, label_minor=False) formatter.axis = FakeAxis() - nose.tools.assert_equal(formatter(10**0.1), '') + nose.tools.assert_equal(formatter.format_for_tick(10**0.1), '') # Otherwise, non-integer powers should be nicely formatted locs = np.array([0.1, 0.00001, np.pi, 0.2, -0.2, -0.00001]) i = range(len(locs)) expected_result = ['0.1', '1e-05', '3.14', '0.2', '-0.2', '-1e-05'] for base in [2, 5, 10, np.pi, np.e]: - formatter = mticker.LogFormatterExponent(base, labelOnlyBase=False) + formatter = mticker.LogFormatterExponent(base, label_minor=True) formatter.axis = FakeAxis(1, base**10) yield _logfe_helper, formatter, base, locs, i, expected_result expected_result = ['3', '5', '12', '42'] locs = np.array([3, 5, 12, 42], dtype='float') for base in [2, 5.0, 10.0, np.pi, np.e]: - formatter = mticker.LogFormatterExponent(base, labelOnlyBase=False) + formatter = mticker.LogFormatterExponent(base, label_minor=True) formatter.axis = FakeAxis(1, base**50) yield _logfe_helper, formatter, base, locs, i, expected_result def _pprint_helper(value, domain, expected): fmt = mticker.LogFormatter() - label = fmt.pprint_val(value, domain) + label = fmt._pprint_val(value, domain) nose.tools.assert_equal(label, expected) @@ -354,17 +355,17 @@ def test_use_offset(): for use_offset in [True, False]: with matplotlib.rc_context({'axes.formatter.useoffset': use_offset}): tmp_form = mticker.ScalarFormatter() - nose.tools.assert_equal(use_offset, tmp_form.get_useOffset()) + nose.tools.assert_equal(use_offset, tmp_form._use_offset) def test_formatstrformatter(): # test % style formatter tmp_form = mticker.FormatStrFormatter('%05d') - nose.tools.assert_equal('00002', tmp_form(2)) + nose.tools.assert_equal('00002', tmp_form.format_for_tick(2)) # test str.format() style formatter tmp_form = mticker.StrMethodFormatter('{x:05d}') - nose.tools.assert_equal('00002', tmp_form(2)) + nose.tools.assert_equal('00002', tmp_form.format_for_tick(2)) if __name__ == '__main__': import nose diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index 7455d03365a2..6e32ccf17a78 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -24,7 +24,7 @@ formatter:: - ax.get_xaxis().get_major_formatter().set_useOffset(False) + ax.get_xaxis().get_major_formatter().use_offset = False set the rcParam ``axes.formatter.useoffset=False`` to turn it off globally, or set a different formatter. @@ -157,13 +157,13 @@ import decimal import locale import math +import warnings + import numpy as np from matplotlib import rcParams from matplotlib import cbook from matplotlib import transforms as mtransforms -import warnings - if six.PY3: long = int @@ -175,10 +175,15 @@ def _mathdefault(s): math font already matches the default font, so we don't need to do that anymore. """ - if rcParams['_internal.classic_mode']: - return '\\mathdefault{%s}' % s + assert s[0] == s[-1] == "$" + if rcParams["_internal.classic_mode"] and not rcParams["text.usetex"]: + return r"$\mathdefault{{{}}}$".format(s[1:-1]) else: - return '{%s}' % s + return s + + +def _unicode_minus(s): + return s.replace("-", "\N{MINUS SIGN}") class _DummyAxis(object): @@ -207,534 +212,399 @@ def get_tick_space(self): return 9 -class TickHelper(object): - axis = None - - def set_axis(self, axis): - self.axis = axis - - def create_dummy_axis(self, **kwargs): - if self.axis is None: - self.axis = _DummyAxis(**kwargs) - - def set_view_interval(self, vmin, vmax): - self.axis.set_view_interval(vmin, vmax) +class _TickHelper(object): + def __init__(self): + self.axis = None - def set_data_interval(self, vmin, vmax): - self.axis.set_data_interval(vmin, vmax) + def set_axis(self, axis_or_kw): + if isinstance(axis_or_kw, dict): + self.axis = _DummyAxis(**axis_or_kw) + else: + self.axis = axis_or_kw - def set_bounds(self, vmin, vmax): - self.set_view_interval(vmin, vmax) - self.set_data_interval(vmin, vmax) +class Formatter(_TickHelper): + def __init__(self): + super(Formatter, self).__init__() + self._locs = [] + self._offset_text = "" -class Formatter(TickHelper): - """ - Convert the tick location to a string - """ - # some classes want to see all the locs to help format - # individual ones - locs = [] + @property + def locs(self): + return self._locs - def __call__(self, x, pos=None): - """Return the format for tick val x at position pos; pos=None - indicated unspecified""" - raise NotImplementedError('Derived must override') + @locs.setter + def locs(self, locs): + self._locs = np.asarray(locs) - def format_data(self, value): - return self.__call__(value) + @property + def offset_text(self): + return self._offset_text - def format_data_short(self, value): - """return a short string version""" - return self.format_data(value) + @offset_text.setter + def offset_text(self, s): + self._offset_text = s - def get_offset(self): - return '' + def format_for_tick(self, value, pos=None): + return "" - def set_locs(self, locs): - self.locs = locs - - def fix_minus(self, s): - """ - Some classes may want to replace a hyphen for minus with the - proper unicode symbol (U+2212) for typographical correctness. - The default is to not replace it. - - Note, if you use this method, e.g., in :meth:`format_data` or - call, you probably don't want to use it for - :meth:`format_data_short` since the toolbar uses this for - interactive coord reporting and I doubt we can expect GUIs - across platforms will handle the unicode correctly. So for - now the classes that override :meth:`fix_minus` should have an - explicit :meth:`format_data_short` method - """ - return s - - -class IndexFormatter(Formatter): - """ - format the position x to the nearest i-th label where i=int(x+0.5) - """ - def __init__(self, labels): - self.labels = labels - self.n = len(labels) - - def __call__(self, x, pos=None): - """Return the format for tick val x at position pos; pos=None - indicated unspecified""" - i = int(x + 0.5) - if i < 0: - return '' - elif i >= self.n: - return '' - else: - return self.labels[i] + def format_for_cursor(self, value): + return self.format_for_tick(value) class NullFormatter(Formatter): - 'Always return the empty string' - - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - return '' + """Always return the empty string. + """ class FixedFormatter(Formatter): - 'Return fixed strings for tick labels' - def __init__(self, seq): - """ - *seq* is a sequence of strings. For positions ``i < len(seq)`` return - *seq[i]* regardless of *x*. Otherwise return '' - """ - self.seq = seq - self.offset_string = '' - - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - if pos is None or pos >= len(self.seq): - return '' - else: - return self.seq[pos] + """Return fixed strings for tick labels. + """ - def get_offset(self): - return self.offset_string + def __init__(self, seq): + super(FixedFormatter, self).__init__() + self._seq = seq - def set_offset_string(self, ofs): - self.offset_string = ofs + def format_for_tick(self, x, pos=None): + """Return the format for tick val *x* at position *pos*. + """ + return self._seq[pos] if pos < len(self._seq) else "" class FuncFormatter(Formatter): - """ - User defined function for formatting + """User defined function for formatting. The function should take in two inputs (tick value *x* and position *pos*) - and return a string + and return a string. """ - def __init__(self, func): - self.func = func - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - return self.func(x, pos) + def __init__(self, func): + super(FuncFormatter, self).__init__() + self.format_for_tick = func class FormatStrFormatter(Formatter): + """Use an old-style ('%' operator) format string to format the tick. """ - Use an old-style ('%' operator) format string to format the tick - """ - def __init__(self, fmt): - self.fmt = fmt - - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - return self.fmt % x - -class StrMethodFormatter(Formatter): - """ - Use a new-style format string (as used by `str.format()`) - to format the tick. The field formatting must be labeled `x`. - """ def __init__(self, fmt): - self.fmt = fmt + super(FormatStrFormatter, self).__init__() + self._fmt = fmt - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - return self.fmt.format(x=x) + def format_for_tick(self, x, pos=None): + return self._fmt % x -class OldScalarFormatter(Formatter): - """ - Tick location is a plain old number. +class StrMethodFormatter(Formatter): + """Use a new-style format string (as used by `str.format()`) to + format the tick. The field formatting must be labeled `x` and/or + `pos`. """ - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - xmin, xmax = self.axis.get_view_interval() - d = abs(xmax - xmin) - - return self.pprint_val(x, d) - - def pprint_val(self, x, d): - #if the number is not too big and it's an int, format it as an - #int - if abs(x) < 1e4 and x == int(x): - return '%d' % x + def __init__(self, fmt): + super(StrMethodFormatter, self).__init__() + self._fmt = fmt - if d < 1e-2: - fmt = '%1.3e' - elif d < 1e-1: - fmt = '%1.3f' - elif d > 1e5: - fmt = '%1.1e' - elif d > 10: - fmt = '%1.1f' - elif d > 1: - fmt = '%1.2f' - else: - fmt = '%1.3f' - s = fmt % x - #print d, x, fmt, s - tup = s.split('e') - if len(tup) == 2: - mantissa = tup[0].rstrip('0').rstrip('.') - sign = tup[1][0].replace('+', '') - exponent = tup[1][1:].lstrip('0') - s = '%se%s%s' % (mantissa, sign, exponent) - else: - s = s.rstrip('0').rstrip('.') - return s + def format_for_tick(self, x, pos=None): + return self._fmt.format(x=x, pos=pos) class ScalarFormatter(Formatter): - """ - Tick location is a plain old number. If useOffset==True and the data range - is much smaller than the data average, then an offset will be determined - such that the tick labels are meaningful. Scientific notation is used for - data < 10^-n or data >= 10^m, where n and m are the power limits set using + """Tick location is a plain old number. If use_offset==True + and the data range is much smaller than the data average, then + an offset will be determined such that the tick labels are + meaningful. Scientific notation is used for data < 10^-n or + data >= 10^m, where n and m are the power limits set using set_powerlimits((n,m)). The defaults for these are controlled by the axes.formatter.limits rc parameter. - """ - def __init__(self, useOffset=None, useMathText=None, useLocale=None): - # useOffset allows plotting small data ranges with large offsets: for - # example: [1+1e-9,1+2e-9,1+3e-9] useMathText will render the offset - # and scientific notation in mathtext - - if useOffset is None: - useOffset = rcParams['axes.formatter.useoffset'] - self.set_useOffset(useOffset) - self._usetex = rcParams['text.usetex'] - if useMathText is None: - useMathText = rcParams['axes.formatter.use_mathtext'] - self._useMathText = useMathText - self.orderOfMagnitude = 0 - self.format = '' + def __init__(self, *args, **kwargs): + # Keyword-only arguments. + use_offset = kwargs.pop("use_offset", None) + use_mathtext = kwargs.pop("use_mathtext", None) + use_locale = kwargs.pop("use_locale", None) + super(ScalarFormatter, self).__init__(*args, **kwargs) + self._use_offset = (use_offset if use_offset is not None + else rcParams["axes.formatter.useoffset"]) + self._usetex = rcParams["text.usetex"] + self._use_mathtext = (use_mathtext if use_mathtext is not None + else rcParams["axes.formatter.use_mathtext"]) + self._use_locale = (use_locale if use_locale is not None + else rcParams["axes.formatter.use_locale"]) self._scientific = True self._powerlimits = rcParams['axes.formatter.limits'] - if useLocale is None: - useLocale = rcParams['axes.formatter.use_locale'] - self._useLocale = useLocale - - def get_useOffset(self): - return self._useOffset - - def set_useOffset(self, val): - if val in [True, False]: - self.offset = 0 - self._useOffset = val - else: - self._useOffset = False - self.offset = val - - useOffset = property(fget=get_useOffset, fset=set_useOffset) - - def get_useLocale(self): - return self._useLocale - - def set_useLocale(self, val): - if val is None: - self._useLocale = rcParams['axes.formatter.use_locale'] - else: - self._useLocale = val - - useLocale = property(fget=get_useLocale, fset=set_useLocale) - - def fix_minus(self, s): - """use a unicode minus rather than hyphen""" - if rcParams['text.usetex'] or not rcParams['axes.unicode_minus']: - return s - else: - return s.replace('-', '\u2212') - - def __call__(self, x, pos=None): - 'Return the format for tick val *x* at position *pos*' - if len(self.locs) == 0: - return '' - else: - s = self.pprint_val(x) - return self.fix_minus(s) - - def set_scientific(self, b): - '''True or False to turn scientific notation on or off - see also :meth:`set_powerlimits` - ''' - self._scientific = bool(b) - - def set_powerlimits(self, lims): - ''' - Sets size thresholds for scientific notation. - - e.g., ``formatter.set_powerlimits((-3, 4))`` sets the pre-2007 default - in which scientific notation is used for numbers less than 1e-3 or - greater than 1e4. - See also :meth:`set_scientific`. - ''' - if len(lims) != 2: - raise ValueError("'lims' must be a sequence of length 2") + self._offset = 0 + self._oom = self._tick_precision = self._cursor_precision = None + + def _format_maybe_locale(self, fmt, *args): + return (locale.format_string(fmt, *args) if self._use_locale + else fmt % args) + + @property + def locs(self): + return self._locs + + @locs.setter + def locs(self, locs): + self._locs = np.asarray(locs) + self._update() + + @property + def use_offset(self): + return self._use_offset + + @use_offset.setter + def use_offset(self, b): + self._use_offset = b + self._update() + + @property + def use_locale(self): + return self._use_locale + + @use_locale.setter + def use_locale(self, b): + self._use_locale = b + self._update() + + @property + def scientific(self): + return self._scientific + + @scientific.setter + def scientific(self, b): + self._scientific = b + self._update() + + @property + def powerlimits(self): + return self._powerlimits + + @powerlimits.setter + def powerlimits(self, lims): self._powerlimits = lims + self._update() - def format_data_short(self, value): - """return a short formatted string representation of a number""" - if self._useLocale: - return locale.format_string('%-12g', (value,)) - else: - return '%-12g' % value + def _update(self): + self._set_offset() + self._set_oom() + self._set_precision() - def format_data(self, value): - 'return a formatted string representation of a number' - if self._useLocale: - s = locale.format_string('%1.10e', (value,)) - else: - s = '%1.10e' % value - s = self._formatSciNotation(s) - return self.fix_minus(s) - - def get_offset(self): - """Return scientific notation, plus offset""" - if len(self.locs) == 0: - return '' - s = '' - if self.orderOfMagnitude or self.offset: - offsetStr = '' - sciNotStr = '' - if self.offset: - offsetStr = self.format_data(self.offset) - if self.offset > 0: - offsetStr = '+' + offsetStr - if self.orderOfMagnitude: - if self._usetex or self._useMathText: - sciNotStr = self.format_data(10 ** self.orderOfMagnitude) + def _set_offset(self): + locs = self.locs + if not len(locs) or not self._use_offset: + self._offset = 0 + return + # Restrict to visible ticks. + vmin, vmax = sorted(self.axis.get_view_interval()) + locs = locs[(vmin <= locs) & (locs <= vmax)] + lmin, lmax = locs.min(), locs.max() + # min, max comparing absolute values (we want division to round towards + # zero so we work on absolute values). + abs_min, abs_max = sorted(map(abs, [lmin, lmax])) + # Only use offset if there are at least two ticks, every tick has the + # same sign, and if the span is small compared to the absolute values. + if (lmin == lmax or lmin <= 0 <= lmax or + (abs_max - abs_min) / abs_max >= 1e-2): + self._offset = 0 + return + sign = math.copysign(1, lmin) + # What is the smallest power of ten such that abs_min and abs_max are + # equal up to that precision? + oom = 10. ** math.ceil(math.log10(abs_max)) + while True: + if abs_min // oom != abs_max // oom: + oom *= 10 + break + oom /= 10 + if (abs_max - abs_min) / oom <= 1e-2: + # Handle the case of straddling a multiple of a large power of ten + # (relative to the span). + # What is the smallest power of ten such that abs_min and abs_max + # at most 1 apart? + oom = 10. ** math.ceil(math.log10(abs_max)) + while True: + if abs_max // oom - abs_min // oom > 1: + oom *= 10 + break + oom /= 10 + self._offset = sign * (abs_max // oom) * oom + + def _set_oom(self): + # If scientific notation is to be used, find the appropriate exponent. + # If using an offset, find the exponent after applying the offset. + if self._scientific: + locs = self.locs + vmin, vmax = sorted(self.axis.get_view_interval()) + # Restrict to visible ticks. + locs = locs[(vmin <= locs) & (locs <= vmax)] + if len(locs): + deltas = np.abs(locs - self._offset) + # Don't take tiny, nonzero tick values into account. + deltas = deltas[deltas > 1e-10 * deltas.max()] + if len(deltas): + oom = int(math.floor(math.log10(deltas.min()))) + self._oom = (oom if (oom <= self._powerlimits[0] or + oom >= self._powerlimits[1]) + else 0) else: - sciNotStr = '1e%d' % self.orderOfMagnitude - if self._useMathText: - if sciNotStr != '': - sciNotStr = r'\times%s' % _mathdefault(sciNotStr) - s = ''.join(('$', sciNotStr, _mathdefault(offsetStr), '$')) - elif self._usetex: - if sciNotStr != '': - sciNotStr = r'\times%s' % sciNotStr - s = ''.join(('$', sciNotStr, offsetStr, '$')) + self._oom = 0 else: - s = ''.join((sciNotStr, offsetStr)) - - return self.fix_minus(s) - - def set_locs(self, locs): - 'set the locations of the ticks' - self.locs = locs - if len(self.locs) > 0: - vmin, vmax = self.axis.get_view_interval() - d = abs(vmax - vmin) - if self._useOffset: - self._set_offset(d) - self._set_orderOfMagnitude(d) - self._set_format(vmin, vmax) + self._oom = 0 + else: + self._oom = 0 - def _set_offset(self, range): - # offset of 20,001 is 20,000, for example + def _set_precision(self): locs = self.locs - - if locs is None or not len(locs) or range == 0: - self.offset = 0 - return vmin, vmax = sorted(self.axis.get_view_interval()) - locs = np.asarray(locs) + # Restrict to visible ticks. locs = locs[(vmin <= locs) & (locs <= vmax)] - ave_loc = np.mean(locs) - if len(locs) and ave_loc: # dont want to take log10(0) - ave_oom = math.floor(math.log10(np.mean(np.absolute(locs)))) - range_oom = math.floor(math.log10(range)) - - if np.absolute(ave_oom - range_oom) >= 3: # four sig-figs - p10 = 10 ** range_oom - if ave_loc < 0: - self.offset = (math.ceil(np.max(locs) / p10) * p10) - else: - self.offset = (math.floor(np.min(locs) / p10) * p10) + # Tick precision. + if len(locs): + ticks = np.abs(locs - self._offset) / 10. ** self._oom + # Don't take tiny, nonzero tick values into account. + ticks = ticks[ticks > 1e-10 * ticks.max()] + if len(ticks): + thresh = 10. ** (math.floor(math.log10(ticks.min())) - 3) + precision = 0 + while (np.abs(np.round(ticks, precision) - ticks).max() > + thresh): + precision += 1 + # Work around rounding errors, e.g. test_formatter_large_small: + # increase scale and recompute precision. + if (self._oom and + np.abs(np.round(ticks, precision)).min() >= 10): + self._oom += 1 + self._set_precision() + return + self._tick_precision = precision else: - self.offset = 0 - - def _set_orderOfMagnitude(self, range): - # if scientific notation is to be used, find the appropriate exponent - # if using an numerical offset, find the exponent after applying the - # offset - if not self._scientific: - self.orderOfMagnitude = 0 - return - locs = np.absolute(self.locs) - if self.offset: - oom = math.floor(math.log10(range)) + self._tick_precision = 0 else: - if locs[0] > locs[-1]: - val = locs[0] + self._tick_precision = 0 + # Cursor precision. + self._cursor_precision = ( + 3 - int(math.floor(math.log10(vmax - vmin)))) if vmax > vmin else 0 + + @property + def offset_text(self): + if self._oom or self._offset: + if self._offset: + offset_str = self._format_offset() else: - val = locs[-1] - if val == 0: - oom = 0 + offset_str = "" + if self._oom: + if self._use_mathtext or rcParams["text.usetex"]: + sci_not_str = "$10^{{{}}}$".format(self._oom) + else: + sci_not_str = "1e{}".format(self._oom) else: - oom = math.floor(math.log10(val)) - if oom <= self._powerlimits[0]: - self.orderOfMagnitude = oom - elif oom >= self._powerlimits[1]: - self.orderOfMagnitude = oom - else: - self.orderOfMagnitude = 0 - - def _set_format(self, vmin, vmax): - # set the format string to format all the ticklabels - if len(self.locs) < 2: - # Temporarily augment the locations with the axis end points. - _locs = list(self.locs) + [vmin, vmax] - else: - _locs = self.locs - locs = (np.asarray(_locs) - self.offset) / 10. ** self.orderOfMagnitude - loc_range = np.ptp(locs) - # Curvilinear coordinates can yield two identical points. - if loc_range == 0: - loc_range = np.max(np.abs(locs)) - # Both points might be zero. - if loc_range == 0: - loc_range = 1 - if len(self.locs) < 2: - # We needed the end points only for the loc_range calculation. - locs = locs[:-2] - loc_range_oom = int(math.floor(math.log10(loc_range))) - # first estimate: - sigfigs = max(0, 3 - loc_range_oom) - # refined estimate: - thresh = 1e-3 * 10 ** loc_range_oom - while sigfigs >= 0: - if np.abs(locs - np.round(locs, decimals=sigfigs)).max() < thresh: - sigfigs -= 1 + sci_not_str = "" + if self._use_mathtext or rcParams["text.usetex"]: + assert offset_str[0] == offset_str[-1] == "$" + if sci_not_str: + assert sci_not_str[0] == sci_not_str[-1] == "$" + s = r"$\times {} {}$".format( + sci_not_str[1:-1], offset_str[1:-1]) + else: + s = offset_str + return _mathdefault(s) else: - break - sigfigs += 1 - self.format = '%1.' + str(sigfigs) + 'f' - if self._usetex: - self.format = '$%s$' % self.format - elif self._useMathText: - self.format = '$%s$' % _mathdefault(self.format) - - def pprint_val(self, x): - xp = (x - self.offset) / (10. ** self.orderOfMagnitude) - if np.absolute(xp) < 1e-8: - xp = 0 - if self._useLocale: - return locale.format_string(self.format, (xp,)) - else: - return self.format % xp - - def _formatSciNotation(self, s): - # transform 1e+004 into 1e4, for example - if self._useLocale: - decimal_point = locale.localeconv()['decimal_point'] - positive_sign = locale.localeconv()['positive_sign'] - else: - decimal_point = '.' - positive_sign = '+' - tup = s.split('e') - try: - significand = tup[0].rstrip('0').rstrip(decimal_point) - sign = tup[1][0].replace(positive_sign, '') - exponent = tup[1][1:].lstrip('0') - if self._useMathText or self._usetex: - if significand == '1' and exponent != '': - # reformat 1x10^y as 10^y - significand = '' - if exponent: - exponent = '10^{%s%s}' % (sign, exponent) - if significand and exponent: - return r'%s{\times}%s' % (significand, exponent) + if sci_not_str: + s = "\N{MULTIPLICATION SIGN}{}{}".format( + sci_not_str, offset_str) else: - return r'%s%s' % (significand, exponent) + s = offset_str + return _unicode_minus(s) + else: + return "" + + def _format_offset(self): + offset = self._offset + # How many significant digits are needed to represent offset to + # 10 ** (oom - tick_precision)? + precision = ( + (int(math.floor(math.log10(abs(offset)))) if offset else 0) + + self._tick_precision - self._oom + 1) + if .0001 <= abs(offset) < 10000 or offset == 0: + # %g doesn't use scientific notation in this range. + s = (self._format_maybe_locale("%#-+.*g", precision, offset). + rstrip(locale.localeconv()["decimal_point"] + if self._use_locale else ".")) + if self._use_mathtext or rcParams["text.usetex"]: + return "${}$".format(s) else: - s = ('%se%s%s' % (significand, sign, exponent)).rstrip('e') return s - except IndexError: - return s + exp = int(math.floor(math.log10(abs(offset)))) + significand = offset / 10. ** exp + # 1 digit before decimal point, (precision - 1) after. + significand_s = self._format_maybe_locale( + "%-+.*f", precision - 1, significand) + if self._use_mathtext or rcParams["text.usetex"]: + return r"${} \times 10^{{{}}}$".format(significand_s, exp) + else: + return "{}e{}".format(significand_s, exp) + + def format_for_tick(self, value, pos=None): + # Get rid of signed zeros (sic). + scaled = round((value - self._offset) / 10. ** self._oom, + self._tick_precision) + if scaled == 0: + scaled = 0 + s = self._format_maybe_locale("%-.*f", self._tick_precision, scaled) + if self._use_mathtext or rcParams["text.usetex"]: + return _mathdefault("${}$".format(s)) + else: + return _unicode_minus(s) + + def format_for_cursor(self, value): + # How many significant digits needed to represent value to + # 10 ** -cursor_precision? + precision = ( + math.floor(math.log10(abs(value))) + self._cursor_precision + if value else self._cursor_precision) + 1 + return _unicode_minus( + self._format_maybe_locale("%#-.*g", precision, value)) class LogFormatter(Formatter): + """Format values for log axis. """ - Format values for log axis; - """ - def __init__(self, base=10.0, labelOnlyBase=True): + def __init__(self, base=10., label_minor=False): """ - *base* is used to locate the decade tick, - which will be the only one to be labeled if *labelOnlyBase* - is ``False`` + *base* is used to locate the decade tick, which will be the only + one to be labeled if *label_minor* is ``False``. """ - self._base = base + 0.0 - self.labelOnlyBase = labelOnlyBase + super(LogFormatter, self).__init__() + self.base = base + self.label_minor = label_minor - def base(self, base): - """change the *base* for labeling - warning: should always match the - base used for :class:`LogLocator`""" - self._base = base - - def label_minor(self, labelOnlyBase): - 'switch on/off minor ticks labeling' - self.labelOnlyBase = labelOnlyBase - - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): """Return the format for tick val *x* at position *pos*""" - vmin, vmax = self.axis.get_view_interval() - d = abs(vmax - vmin) - b = self._base + vmin, vmax = sorted(self.axis.get_view_interval()) + d = vmax - vmin + b = self.base if x == 0.0: return '0' sign = np.sign(x) # only label the decades fx = math.log(abs(x)) / math.log(b) - isDecade = is_close_to_int(fx) - if not isDecade and self.labelOnlyBase: - s = '' + is_decade = is_close_to_int(fx) + if not (is_decade or self.label_minor): + s = "" elif x > 10000: s = '%1.0e' % x elif x < 1: s = '%1.0e' % x else: - s = self.pprint_val(x, d) + s = self._pprint_val(x, d) if sign == -1: s = '-%s' % s + return _unicode_minus(s) - return self.fix_minus(s) - - def format_data(self, value): - b = self.labelOnlyBase - self.labelOnlyBase = False - value = cbook.strip_math(self.__call__(value)) - self.labelOnlyBase = b - return value - - def format_data_short(self, value): - 'return a short formatted string representation of a number' - return '%-12g' % value - - def pprint_val(self, x, d): + def _pprint_val(self, x, d): #if the number is not too big and it's an int, format it as an #int if abs(x) < 1e4 and x == int(x): @@ -766,38 +636,39 @@ def pprint_val(self, x, d): s = s.rstrip('0').rstrip('.') return s + def format_for_cursor(self, value): + 'return a short formatted string representation of a number' + return '%-12g' % value + class LogFormatterExponent(LogFormatter): """ Format values for log axis; using ``exponent = log_base(value)`` """ - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): """Return the format for tick val *x* at position *pos*""" vmin, vmax = self.axis.get_view_interval() vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=0.05) d = abs(vmax - vmin) - b = self._base + b = self.base if x == 0: return '0' sign = np.sign(x) # only label the decades fx = math.log(abs(x)) / math.log(b) - isDecade = is_close_to_int(fx) - if not isDecade and self.labelOnlyBase: - s = '' - elif abs(fx) > 10000: - s = '%1.0g' % fx - elif abs(fx) < 1: + is_decade = is_close_to_int(fx) + if not (is_decade or self.label_minor): + s = "" + elif abs(fx) < 1 or abs(fx) > 10000: s = '%1.0g' % fx else: fd = math.log(abs(d)) / math.log(b) - s = self.pprint_val(fx, fd) + s = self._pprint_val(fx, fd) if sign == -1: s = '-%s' % s - - return self.fix_minus(s) + return _unicode_minus(s) class LogFormatterMathtext(LogFormatter): @@ -805,22 +676,18 @@ class LogFormatterMathtext(LogFormatter): Format values for log axis; using ``exponent = log_base(value)`` """ - def __call__(self, x, pos=None): + def format_for_tick(self, x, pos=None): 'Return the format for tick val *x* at position *pos*' - b = self._base - usetex = rcParams['text.usetex'] + b = self.base # only label the decades if x == 0: - if usetex: - return '$0$' - else: - return '$%s$' % _mathdefault('0') + return _mathdefault("$0$") fx = math.log(abs(x)) / math.log(b) is_decade = is_close_to_int(fx) - sign_string = '-' if x < 0 else '' + sign_string = '-' if x < 0 else "" # use string formatting of the base if it is not an integer if b % 1 == 0.0: @@ -828,46 +695,35 @@ def __call__(self, x, pos=None): else: base = '%s' % b - if not is_decade and self.labelOnlyBase: - return '' + if not (is_decade or self.label_minor): + return "" elif not is_decade: - if usetex: - return (r'$%s%s^{%.2f}$') % \ - (sign_string, base, fx) - else: - return ('$%s$' % _mathdefault( - '%s%s^{%.2f}' % - (sign_string, base, fx))) + return _mathdefault(r"$%s%s^{%.2f}$" % + (sign_string, base, fx)) else: - if usetex: - return (r'$%s%s^{%d}$') % (sign_string, - base, - nearest_long(fx)) - else: - return ('$%s$' % _mathdefault( - '%s%s^{%d}' % - (sign_string, base, nearest_long(fx)))) + return _mathdefault(r"$%s%s^{%d}$" % + (sign_string, base, round(fx))) class LogitFormatter(Formatter): - '''Probability formatter (using Math text)''' - def __call__(self, x, pos=None): - s = '' + ""'Probability formatter (using Math text)""' + def format_for_tick(self, x, pos=None): + s = "" if 0.01 <= x <= 0.99: s = '{:.2f}'.format(x) elif x < 0.01: if is_decade(x): - s = '$10^{{{:.0f}}}$'.format(np.log10(x)) + s = _mathdefault('$10^{{{:.0f}}}$'.format(np.log10(x))) else: - s = '${:.5f}$'.format(x) + s = _mathdefault('${:.5f}$'.format(x)) else: # x > 0.99 if is_decade(1-x): - s = '$1-10^{{{:.0f}}}$'.format(np.log10(1-x)) + s = _mathdefault('$1-10^{{{:.0f}}}$'.format(np.log10(1-x))) else: - s = '$1-{:.5f}$'.format(1-x) + s = _mathdefault('$1-{:.5f}$'.format(1-x)) return s - def format_data_short(self, value): + def format_for_cursor(self, value): 'return a short formatted string representation of a number' return '%-12g' % value @@ -878,10 +734,6 @@ class EngFormatter(Formatter): plus a specified unit, e.g., 10 MHz instead of 1e7. """ - # the unicode for -6 is the greek letter mu - # commeted here due to bug in pep8 - # (https://github.com/jcrocholl/pep8/issues/271) - # The SI engineering prefixes ENG_PREFIXES = { -24: "y", @@ -890,7 +742,7 @@ class EngFormatter(Formatter): -15: "f", -12: "p", -9: "n", - -6: "\u03bc", + -6: "\N{MICRO SIGN}", -3: "m", 0: "", 3: "k", @@ -904,14 +756,18 @@ class EngFormatter(Formatter): } def __init__(self, unit="", places=None): + super(EngFormatter, self).__init__() self.unit = unit self.places = places - def __call__(self, x, pos=None): - s = "%s%s" % (self.format_eng(x), self.unit) - return self.fix_minus(s) + def format_for_tick(self, x, pos=None): + s = "%s%s" % (self._format_eng(x), self.unit) + if rcParams["text.usetex"]: + return _mathdefault(s) + else: + return _unicode_minus(s) - def format_eng(self, num): + def _format_eng(self, num): """ Formats a number in engineering notation, appending a letter representing the power of 1000 of the original number. Some examples: @@ -963,7 +819,7 @@ def format_eng(self, num): return formatted.strip() -class Locator(TickHelper): +class Locator(_TickHelper): """ Determine the tick locations; @@ -1072,6 +928,7 @@ class IndexLocator(Locator): """ def __init__(self, base, offset): 'place ticks on the i-th data points where (i-offset)%base==0' + super(IndexLocator, self).__init__() self._base = base self.offset = offset @@ -1104,6 +961,7 @@ class FixedLocator(Locator): """ def __init__(self, locs, nbins=None): + super(FixedLocator, self).__init__() self.locs = np.asarray(locs) self.nbins = nbins if self.nbins is not None: @@ -1172,6 +1030,7 @@ def __init__(self, numticks=None, presets=None): """ Use presets to set locs based on lom. A dict mapping vmin, vmax->locs """ + super(LinearLocator, self).__init__() self.numticks = numticks if presets is None: self.presets = {} @@ -1286,6 +1145,7 @@ class MultipleLocator(Locator): """ def __init__(self, base=1.0): + super(MultipleLocator, self).__init__() self._base = Base(base) def set_params(self, base): @@ -1391,6 +1251,7 @@ def __init__(self, *args, **kwargs): # I left "trim" out; it defaults to True, and it is not # clear that there is any use case for False, so we may # want to remove that kwarg. EF 2010/04/18 + super(MaxNLocator, self).__init__() if args: kwargs['nbins'] = args[0] if len(args) > 1: @@ -1507,15 +1368,6 @@ def decade_up(x, base=10): return base ** lx -def nearest_long(x): - if x == 0: - return long(0) - elif x > 0: - return long(x + 0.5) - else: - return long(x - 0.5) - - def is_decade(x, base=10): if not np.isfinite(x): return False @@ -1528,7 +1380,7 @@ def is_decade(x, base=10): def is_close_to_int(x): if not np.isfinite(x): return False - return abs(x - nearest_long(x)) < 1e-10 + return abs(x - round(x)) < 1e-10 class LogLocator(Locator): @@ -1540,6 +1392,7 @@ def __init__(self, base=10.0, subs=[1.0], numdecs=4, numticks=15): """ place ticks on the location= base**i*subs[j] """ + super(LogLocator, self).__init__() self.base(base) self.subs(subs) self.numticks = numticks @@ -1678,6 +1531,7 @@ def __init__(self, transform, subs=None): """ place ticks on the location= base**i*subs[j] """ + super(SymmetricalLogLocator, self).__init__() self._transform = transform if subs is None: self._subs = [1.0] @@ -1840,6 +1694,7 @@ def __init__(self, minor=False): """ place ticks on the logit locations """ + super(LogitLocator, self).__init__() self.minor = minor def set_params(self, minor=None): @@ -1924,7 +1779,7 @@ def __init__(self): nbins = 9 else: nbins = 'auto' - MaxNLocator.__init__(self, nbins=nbins, steps=[1, 2, 5, 10]) + super(AutoLocator, self).__init__(nbins=nbins, steps=[1, 2, 5, 10]) class AutoMinorLocator(Locator): @@ -1941,6 +1796,7 @@ def __init__(self, n=None): If *n* is omitted or None, it will be set to 5 or 4. """ + super(AutoMinorLocator, self).__init__() self.ndivs = n def __call__(self): @@ -1998,6 +1854,7 @@ class OldAutoLocator(Locator): """ def __init__(self): + super(OldAutoLocator, self).__init__() self._locator = LinearLocator() def __call__(self): @@ -2052,11 +1909,9 @@ def get_locator(self, d): return locator -__all__ = ('TickHelper', 'Formatter', 'FixedFormatter', - 'NullFormatter', 'FuncFormatter', 'FormatStrFormatter', - 'StrMethodFormatter', 'ScalarFormatter', 'LogFormatter', - 'LogFormatterExponent', 'LogFormatterMathtext', 'Locator', - 'IndexLocator', 'FixedLocator', 'NullLocator', - 'LinearLocator', 'LogLocator', 'AutoLocator', - 'MultipleLocator', 'MaxNLocator', 'AutoMinorLocator', - 'SymmetricalLogLocator') +__all__ = ['Formatter', 'FixedFormatter', 'NullFormatter', 'FuncFormatter', + 'FormatStrFormatter', 'StrMethodFormatter', 'ScalarFormatter', + 'LogFormatter', 'LogFormatterExponent', 'LogFormatterMathtext', + 'Locator', 'IndexLocator', 'FixedLocator', 'NullLocator', + 'LinearLocator', 'LogLocator', 'AutoLocator', 'MultipleLocator', + 'MaxNLocator', 'AutoMinorLocator', 'SymmetricalLogLocator'] diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py index 6f07a196ca7b..5903f7ad7d46 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_grid.py +++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py @@ -61,17 +61,17 @@ def _config_axes_deprecated(self, X, Y): linewidth=0.01, zorder=-1) ax.add_artist(self.patch) - ticks, ticklabels, offset_string = self._ticker() + ticks, ticklabels, offset_text = self._ticker() if self.orientation == 'vertical': ax.set_yticks(ticks) ax.set_yticklabels(ticklabels) - ax.yaxis.get_major_formatter().set_offset_string(offset_string) + ax.yaxis.get_major_formatter().offset_text = offset_text else: ax.set_xticks(ticks) ax.set_xticklabels(ticklabels) - ax.xaxis.get_major_formatter().set_offset_string(offset_string) + ax.xaxis.get_major_formatter().offset_text = offset_text class CbarAxesBase(object): diff --git a/lib/mpl_toolkits/axisartist/axis_artist.py b/lib/mpl_toolkits/axisartist/axis_artist.py index 6b1904673f71..a78ccb0835c2 100644 --- a/lib/mpl_toolkits/axisartist/axis_artist.py +++ b/lib/mpl_toolkits/axisartist/axis_artist.py @@ -1376,7 +1376,7 @@ def _init_offsetText(self, direction): def _update_offsetText(self): - self.offsetText.set_text( self.axis.major.formatter.get_offset() ) + self.offsetText.set_text(self.axis.major.formatter.offset_text) self.offsetText.set_size(self.major_ticklabels.get_size()) offset = self.major_ticklabels.get_pad() + self.major_ticklabels.get_size() + 2. self.offsetText.xyann= (0, offset) diff --git a/lib/mpl_toolkits/axisartist/axislines.py b/lib/mpl_toolkits/axisartist/axislines.py index 83d65db86055..80fb45a55b05 100644 --- a/lib/mpl_toolkits/axisartist/axislines.py +++ b/lib/mpl_toolkits/axisartist/axislines.py @@ -275,13 +275,13 @@ def get_tick_iterators(self, axes): major = self.axis.major majorLocs = major.locator() - major.formatter.set_locs(majorLocs) - majorLabels = [major.formatter(val, i) for i, val in enumerate(majorLocs)] + major.formatter.locs = majorLocs + majorLabels = [major.formatter.format_for_tick(val, i) for i, val in enumerate(majorLocs)] minor = self.axis.minor minorLocs = minor.locator() - minor.formatter.set_locs(minorLocs) - minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] + minor.formatter.locs = minorLocs + minorLabels = [minor.formatter.format_for_tick(val, i) for i, val in enumerate(minorLocs)] trans_tick = self.get_tick_transform(axes) @@ -386,13 +386,13 @@ def get_tick_iterators(self, axes): major = self.axis.major majorLocs = major.locator() - major.formatter.set_locs(majorLocs) - majorLabels = [major.formatter(val, i) for i, val in enumerate(majorLocs)] + major.formatter.locs = majorLocs + majorLabels = [major.formatter.format_for_tick(val, i) for i, val in enumerate(majorLocs)] minor = self.axis.minor minorLocs = minor.locator() - minor.formatter.set_locs(minorLocs) - minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] + minor.formatter.locs = minorLocs + minorLabels = [minor.formatter.format_for_tick(val, i) for i, val in enumerate(minorLocs)] tr2ax = axes.transData + axes.transAxes.inverted() diff --git a/lib/mpl_toolkits/axisartist/grid_finder.py b/lib/mpl_toolkits/axisartist/grid_finder.py index 5f882d697ac2..f1afc8e8576d 100644 --- a/lib/mpl_toolkits/axisartist/grid_finder.py +++ b/lib/mpl_toolkits/axisartist/grid_finder.py @@ -264,16 +264,18 @@ def __init__(self, nbins = 10, steps = None, mticker.MaxNLocator.__init__(self, nbins, steps=steps, trim=trim, integer=integer, symmetric=symmetric, prune=prune) - self.create_dummy_axis() + self.set_axis({}) self._factor = None def __call__(self, v1, v2): if self._factor is not None: - self.set_bounds(v1*self._factor, v2*self._factor) + self.axis.set_data_interval(v1*self._factor, v2*self._factor) + self.axis.set_view_interval(v1*self._factor, v2*self._factor) locs = mticker.MaxNLocator.__call__(self) return np.array(locs), len(locs), self._factor else: - self.set_bounds(v1, v2) + self.axis.set_data_interval(v1, v2) + self.axis.set_view_interval(v1, v2) locs = mticker.MaxNLocator.__call__(self) return np.array(locs), len(locs), None @@ -304,8 +306,8 @@ def set_factor(self, f): class FormatterPrettyPrint(object): def __init__(self, useMathText=True): - self._fmt = mticker.ScalarFormatter(useMathText=useMathText, useOffset=False) - self._fmt.create_dummy_axis() + self._fmt = mticker.ScalarFormatter(use_mathtext=useMathText, use_offset=False) + self._fmt.set_axis({}) self._ignore_factor = True def __call__(self, direction, factor, values): @@ -314,8 +316,8 @@ def __call__(self, direction, factor, values): factor = 1. values = [v/factor for v in values] #values = [v for v in values] - self._fmt.set_locs(values) - return [self._fmt(v) for v in values] + self._fmt.locs = values + return [self._fmt.format_for_tick(v) for v in values] class DictFormatter(object): diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 1e2fc5b19829..5b0f078f619f 100755 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -1323,25 +1323,25 @@ def ticklabel_format(self, **kwargs) : try: if sb is not None: if axis in ['both', 'z']: - self.xaxis.major.formatter.set_scientific(sb) + self.xaxis.major.formatter.scientific = sb if axis in ['both', 'y']: - self.yaxis.major.formatter.set_scientific(sb) + self.yaxis.major.formatter.scientific = sb if axis in ['both', 'z'] : - self.zaxis.major.formatter.set_scientific(sb) + self.zaxis.major.formatter.scientific = sb if scilimits is not None: if axis in ['both', 'x']: - self.xaxis.major.formatter.set_powerlimits(scilimits) + self.xaxis.major.formatter.powerlimits = scilimits if axis in ['both', 'y']: - self.yaxis.major.formatter.set_powerlimits(scilimits) + self.yaxis.major.formatter.powerlimits = scilimits if axis in ['both', 'z']: - self.zaxis.major.formatter.set_powerlimits(scilimits) + self.zaxis.major.formatter.powerlimits = scilimits if useOffset is not None: if axis in ['both', 'x']: - self.xaxis.major.formatter.set_useOffset(useOffset) + self.xaxis.major.formatter.use_offset = useOffset if axis in ['both', 'y']: - self.yaxis.major.formatter.set_useOffset(useOffset) + self.yaxis.major.formatter.use_offset = useOffset if axis in ['both', 'z']: - self.zaxis.major.formatter.set_useOffset(useOffset) + self.zaxis.major.formatter.use_offset = useOffset except AttributeError: raise AttributeError( "This method only works with the ScalarFormatter.") diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index ad07fea32160..9d20e35a0588 100755 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -123,8 +123,8 @@ def init3d(self): def get_tick_positions(self): majorLocs = self.major.locator() - self.major.formatter.set_locs(majorLocs) - majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)] + self.major.formatter.locs = majorLocs + majorLabels = [self.major.formatter.format_for_tick(val, i) for i, val in enumerate(majorLocs)] return majorLabels, majorLocs def get_major_ticks(self, numticks=None): @@ -224,8 +224,8 @@ def draw(self, renderer): # Rudimentary clipping majorLocs = [loc for loc in majorLocs if locmin <= loc <= locmax] - self.major.formatter.set_locs(majorLocs) - majorLabels = [self.major.formatter(val, i) + self.major.formatter.locs = majorLocs + majorLabels = [self.major.formatter.format_for_tick(val, i) for i, val in enumerate(majorLocs)] mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer) @@ -302,7 +302,7 @@ def draw(self, renderer): pos = copy.copy(outeredgep) pos = move_from_center(pos, centers, labeldeltas, axmask) olx, oly, olz = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M) - self.offsetText.set_text( self.major.formatter.get_offset() ) + self.offsetText.set_text(self.major.formatter.offset_text) self.offsetText.set_position( (olx, oly) ) angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx))) self.offsetText.set_rotation(angle) From 277574f7f2689c6585d57882a46a1b8283101942 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 27 Jan 2016 12:24:01 -0800 Subject: [PATCH 2/3] Restore some backcompat. --- examples/pylab_examples/demo_ribbon_box.py | 2 +- .../pylab_examples/newscalarformatter_demo.py | 32 +++++++++---------- lib/matplotlib/axes/_base.py | 9 ++++-- lib/matplotlib/ticker.py | 19 ++++++----- lib/mpl_toolkits/axisartist/grid_finder.py | 3 +- 5 files changed, 35 insertions(+), 30 deletions(-) diff --git a/examples/pylab_examples/demo_ribbon_box.py b/examples/pylab_examples/demo_ribbon_box.py index 280f1320ef02..df39dede071a 100644 --- a/examples/pylab_examples/demo_ribbon_box.py +++ b/examples/pylab_examples/demo_ribbon_box.py @@ -104,7 +104,7 @@ def draw(self, renderer, *args, **kwargs): ] heights = np.random.random(years.shape) * 7000 + 3000 - fmt = ScalarFormatter(use_offset=False) + fmt = ScalarFormatter(useOffset=False) ax.xaxis.set_major_formatter(fmt) for year, h, bc in zip(years, heights, box_colors): diff --git a/examples/pylab_examples/newscalarformatter_demo.py b/examples/pylab_examples/newscalarformatter_demo.py index fc42c6462f66..b17c42c63632 100644 --- a/examples/pylab_examples/newscalarformatter_demo.py +++ b/examples/pylab_examples/newscalarformatter_demo.py @@ -33,20 +33,20 @@ verticalalignment='top') ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5) -ax1.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) -ax1.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax1.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax1.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) ax2.plot(x * 1e5, x * 1e-4) -ax2.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) -ax2.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax2.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax2.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10) -ax3.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) -ax3.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax3.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax3.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) ax4.plot(-x * 1e5, -x * 1e-4) -ax4.xaxis.set_major_formatter(ScalarFormatter(use_offset=False)) -ax4.yaxis.set_major_formatter(ScalarFormatter(use_offset=False)) +ax4.xaxis.set_major_formatter(ScalarFormatter(useOffset=False)) +ax4.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) # Example 4 x = np.arange(0, 1, .01) @@ -56,18 +56,18 @@ verticalalignment='top') ax1.plot(x * 1e5 + 1e10, x * 1e-10 + 1e-5) -ax1.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) -ax1.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax1.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax1.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) ax2.plot(x * 1e5, x * 1e-4) -ax2.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) -ax2.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax2.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax2.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) ax3.plot(-x * 1e5 - 1e10, -x * 1e-5 - 1e-10) -ax3.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) -ax3.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax3.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax3.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) ax4.plot(-x * 1e5, -x * 1e-4) -ax4.xaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) -ax4.yaxis.set_major_formatter(ScalarFormatter(use_mathtext=True)) +ax4.xaxis.set_major_formatter(ScalarFormatter(useMathText=True)) +ax4.yaxis.set_major_formatter(ScalarFormatter(useMathText=True)) plt.show() diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 0d191c19b9c6..969a598cb674 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -523,6 +523,9 @@ def __init__(self, fig, rect, self._hold = rcParams['axes.hold'] self._connected = {} # a dict from events to (id, func) self.cla() + # funcs used to format x and y - fall back on major formatters + self.fmt_xdata = None + self.fmt_ydata = None self.set_cursor_props((1, 'k')) # set the cursor properties for axes @@ -3265,10 +3268,12 @@ def yaxis_date(self, tz=None): self.yaxis.axis_date(tz) def format_xdata(self, x): - return self.xaxis.get_major_formatter().format_for_cursor(x) + return (self.fmt_xdata(x) if self.fmt_xdata is not None + else self.xaxis.get_major_formatter().format_for_cursor(x)) def format_ydata(self, y): - return self.yaxis.get_major_formatter().format_for_cursor(y) + return (self.fmt_ydata(y) if self.fmt_ydata is not None + else self.yaxis.get_major_formatter().format_for_cursor(y)) def format_coord(self, x, y): """Return a format string formatting the *x*, *y* coord""" diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index 6e32ccf17a78..5781e70eb93b 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -319,18 +319,14 @@ class ScalarFormatter(Formatter): axes.formatter.limits rc parameter. """ - def __init__(self, *args, **kwargs): - # Keyword-only arguments. - use_offset = kwargs.pop("use_offset", None) - use_mathtext = kwargs.pop("use_mathtext", None) - use_locale = kwargs.pop("use_locale", None) - super(ScalarFormatter, self).__init__(*args, **kwargs) - self._use_offset = (use_offset if use_offset is not None + def __init__(self, useOffset=None, useMathText=None, useLocale=None): + super(ScalarFormatter, self).__init__() + self._use_offset = (useOffset if useOffset is not None else rcParams["axes.formatter.useoffset"]) self._usetex = rcParams["text.usetex"] - self._use_mathtext = (use_mathtext if use_mathtext is not None + self._use_mathtext = (useMathText if useMathText is not None else rcParams["axes.formatter.use_mathtext"]) - self._use_locale = (use_locale if use_locale is not None + self._use_locale = (useLocale if useLocale is not None else rcParams["axes.formatter.use_locale"]) self._scientific = True self._powerlimits = rcParams['axes.formatter.limits'] @@ -393,12 +389,15 @@ def _update(self): def _set_offset(self): locs = self.locs - if not len(locs) or not self._use_offset: + if not self._use_offset: self._offset = 0 return # Restrict to visible ticks. vmin, vmax = sorted(self.axis.get_view_interval()) locs = locs[(vmin <= locs) & (locs <= vmax)] + if not len(locs): + self._offset = 0 + return lmin, lmax = locs.min(), locs.max() # min, max comparing absolute values (we want division to round towards # zero so we work on absolute values). diff --git a/lib/mpl_toolkits/axisartist/grid_finder.py b/lib/mpl_toolkits/axisartist/grid_finder.py index f1afc8e8576d..6293de69ec47 100644 --- a/lib/mpl_toolkits/axisartist/grid_finder.py +++ b/lib/mpl_toolkits/axisartist/grid_finder.py @@ -306,7 +306,8 @@ def set_factor(self, f): class FormatterPrettyPrint(object): def __init__(self, useMathText=True): - self._fmt = mticker.ScalarFormatter(use_mathtext=useMathText, use_offset=False) + self._fmt = mticker.ScalarFormatter( + useMathText=useMathText, useOffset=False) self._fmt.set_axis({}) self._ignore_factor = True From 288bcc12d945a7081bde7abdb67b8f83e3770255 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 28 Jan 2016 13:39:57 -0800 Subject: [PATCH 3/3] Clarify a few tests. --- lib/matplotlib/tests/test_backend_ps.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index ab346a4d0a41..b92479bd49fa 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -13,6 +13,8 @@ from matplotlib import patheffects from matplotlib.testing.decorators import cleanup, knownfailureif +from nose.tools import assert_equal + needs_ghostscript = knownfailureif( matplotlib.checkdep_ghostscript()[0] is None, @@ -51,8 +53,8 @@ def _test_savefig_to_stringio(format='ps', use_log=False): # could change from run to run, such as the time. values = [re.sub(b'%%.*?\n', b'', x) for x in values] - assert values[0] == values[1] - assert values[1] == values[2].replace(b'\r\n', b'\n') + assert_equal(values[0], values[1]) + assert_equal(values[1], values[2].replace(b'\r\n', b'\n')) for buffer in buffers: buffer.close() @@ -112,13 +114,13 @@ def test_composite_image(): fig.savefig(ps, format="ps") ps.seek(0) buff = ps.read() - assert buff.count(six.b(' colorimage')) == 1 + assert_equal(buff.count(six.b(' colorimage')), 1) plt.rcParams['image.composite_image'] = False with io.BytesIO() as ps: fig.savefig(ps, format="ps") ps.seek(0) buff = ps.read() - assert buff.count(six.b(' colorimage')) == 2 + assert_equal(buff.count(six.b(' colorimage')), 2) @cleanup