diff --git a/doc/api/axes_api.rst b/doc/api/axes_api.rst index f97270713f5d..a4395bc06d84 100644 --- a/doc/api/axes_api.rst +++ b/doc/api/axes_api.rst @@ -587,7 +587,6 @@ non-rectilinear Axes. Axes.get_xaxis_transform Axes.get_yaxis_transform Axes.get_data_ratio - Axes.get_data_ratio_log Axes.get_xaxis_text1_transform Axes.get_xaxis_text2_transform diff --git a/doc/api/axis_api.rst b/doc/api/axis_api.rst index 620efbfffd53..4bc9ad0c6e89 100644 --- a/doc/api/axis_api.rst +++ b/doc/api/axis_api.rst @@ -226,8 +226,6 @@ Other Axis.limit_range_for_scale Axis.reset_ticks Axis.set_default_intervals - Axis.get_smart_bounds - Axis.set_smart_bounds Discouraged ----------- diff --git a/doc/api/next_api_changes/removals/18747-ES.rst b/doc/api/next_api_changes/removals/18747-ES.rst new file mode 100644 index 000000000000..8216000dd95d --- /dev/null +++ b/doc/api/next_api_changes/removals/18747-ES.rst @@ -0,0 +1,57 @@ +``Axes`` methods and properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``axes.Axes.get_data_ratio_log`` +- ``axes.SubplotBase.rowNum``; use ``ax.get_subplotspec().rowspan.start`` + instead +- ``axes.SubplotBase.colNum``; use ``ax.get_subplotspec().colspan.start`` + instead +- the *verts* parameter to ``scatter`` (use *marker* instead) +- Passing more than one positional argument to `~matplotlib.axes.Axes.axis` + will now raise an error. +- Passing ``"range"`` to the *whis* parameter of `.Axes.boxplot` and + `.cbook.boxplot_stats` to mean "the whole data range" is no longer + supported. +- Passing scalars to parameter *where* in `.axes.Axes.fill_between` and + `.axes.Axes.fill_betweenx` is no longer accepted and non-matching sizes now + raise a `ValueError`. + +``dates`` functions +~~~~~~~~~~~~~~~~~~~ +- ``dates.mx2num`` + +``quiver`` methods +~~~~~~~~~~~~~~~~~~ + +- ``quiver.QuiverKey.quiverkey_doc`` has been removed; use + ``quiver.QuiverKey.__init__.__doc__`` instead. + +Smart bounds +~~~~~~~~~~~~ + +The "smart bounds" functionality on `~.axis.Axis` and `.Spine` has been +deleted, and the following methods are removed: + +- ``Axis.set_smart_bounds`` and ``Axis.get_smart_bounds`` +- ``Spine.set_smart_bounds`` and ``Spine.get_smart_bounds`` + +Testing +~~~~~~~ +The *switch_backend_warn* parameter to ``matplotlib.test`` has no effect and +has been removed. + +``tight_layout()`` +~~~~~~~~~~~~~~~~~~ +The *renderer* parameter to `.Figure.tight_layout` has been removed; this +method now always uses the renderer instance cached on the `.Figure`. + +``axes_grid1`` +~~~~~~~~~~~~~~ +The ``mpl_toolkits.axes_grid1.colorbar`` module and its colorbar implementation +have been removed in favor of :mod:`matplotlib.colorbar`. Additionally: + +- The *locator* parameter to ``colorbar()`` has been removed in favor of its + synonym *ticks* (which already existed previously, and is consistent with + :mod:`matplotlib.colorbar`). +- The ``mpl_toolkits.legacy_colorbar`` rcParam has no effect and also has been + removed. diff --git a/doc/api/prev_api_changes/api_changes_3.2.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.2.0/deprecations.rst index 9ecabcb8af27..42de9ffccd77 100644 --- a/doc/api/prev_api_changes/api_changes_3.2.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.2.0/deprecations.rst @@ -142,6 +142,11 @@ Passing scalars to parameter *where* in ``fill_between()`` and broadcasted to the size of *x*. Non-matching sizes will raise a ``ValueError`` in the future. +``scatter()`` +~~~~~~~~~~~~~ +Passing the *verts* parameter to `.axes.Axes.scatter` is deprecated; use the +*marker* parameter instead. + ``tight_layout()`` ~~~~~~~~~~~~~~~~~~ The ``renderer`` parameter to `.Figure.tight_layout` is deprecated; this method @@ -255,8 +260,8 @@ both 1) matplotlib's conftests have not been called and 2) nose is in During the deprecation period, to force the generation of nose base tests, import nose first. -The ``switch_backend_warn`` parameter to ``matplotlib.test`` has no effect and -is deprecated. +The *switch_backend_warn* parameter to ``matplotlib.test`` has no effect and is +deprecated. ``testing.jpl_units.UnitDbl.UnitDbl.checkUnits`` is deprecated. diff --git a/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst index 850024c03f31..8e4c1e81f9ec 100644 --- a/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst +++ b/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst @@ -57,8 +57,7 @@ The following API elements have been removed: instead) - ``axisartist.axes_divider.Axes``, ``axisartist.axes_divider.LocatableAxes`` (use ``axisartist.axislines.Axes`` instead) -- the ``normed`` kwarg to ``hist`` (use ``density`` instead) -- the ``verts`` parameter to ``scatter`` (use ``marker`` instead) +- the *normed* keyword argument to ``hist`` (use *density* instead) - passing ``(verts, 0)`` or ``(..., 3)`` when specifying a marker to specify a path or a circle, respectively (instead, use ``verts`` or ``"o"``, respectively) diff --git a/doc/api/toolkits/axes_grid1.rst b/doc/api/toolkits/axes_grid1.rst index 0570e762b3f5..3abbaf8f22c0 100644 --- a/doc/api/toolkits/axes_grid1.rst +++ b/doc/api/toolkits/axes_grid1.rst @@ -29,7 +29,6 @@ See :ref:`axes_grid1_users-guide-index` for a guide on the usage of axes_grid1. axes_grid1.axes_grid axes_grid1.axes_rgb axes_grid1.axes_size - axes_grid1.colorbar axes_grid1.inset_locator axes_grid1.mpl_axes axes_grid1.parasite_axes diff --git a/doc/missing-references.json b/doc/missing-references.json index 1bb005c9a18a..8de8dbe7f2d4 100644 --- a/doc/missing-references.json +++ b/doc/missing-references.json @@ -191,9 +191,6 @@ "backend_qt5.FigureCanvasQTAgg": [ "doc/api/prev_api_changes/api_changes_2.2.0.rst:210" ], - "datetime": [ - "lib/matplotlib/dates.py:docstring of matplotlib.dates.mx2num:2" - ], "dateutil.rrule.rrulebase": [ "/rrule.py:docstring of matplotlib.dates.rrule:1" ], diff --git a/examples/axes_grid1/demo_axes_grid.py b/examples/axes_grid1/demo_axes_grid.py index 63f9a4edb722..57297ba77e6a 100644 --- a/examples/axes_grid1/demo_axes_grid.py +++ b/examples/axes_grid1/demo_axes_grid.py @@ -11,9 +11,6 @@ from mpl_toolkits.axes_grid1 import ImageGrid -plt.rcParams["mpl_toolkits.legacy_colorbar"] = False - - def get_demo_image(): z = cbook.get_sample_data("axes_grid/bivariate_normal.npy", np_load=True) # z is a numpy array of 15x15 diff --git a/examples/axes_grid1/demo_axes_grid2.py b/examples/axes_grid1/demo_axes_grid2.py index 90c816f4d6b1..b18648186c5d 100644 --- a/examples/axes_grid1/demo_axes_grid2.py +++ b/examples/axes_grid1/demo_axes_grid2.py @@ -13,9 +13,6 @@ from mpl_toolkits.axes_grid1 import ImageGrid -plt.rcParams["mpl_toolkits.legacy_colorbar"] = False - - def add_inner_title(ax, title, loc, **kwargs): from matplotlib.offsetbox import AnchoredText from matplotlib.patheffects import withStroke diff --git a/examples/axes_grid1/demo_edge_colorbar.py b/examples/axes_grid1/demo_edge_colorbar.py index 4e974a6e7984..74dc74c56965 100644 --- a/examples/axes_grid1/demo_edge_colorbar.py +++ b/examples/axes_grid1/demo_edge_colorbar.py @@ -12,9 +12,6 @@ from mpl_toolkits.axes_grid1 import AxesGrid -plt.rcParams["mpl_toolkits.legacy_colorbar"] = False - - def get_demo_image(): z = cbook.get_sample_data("axes_grid/bivariate_normal.npy", np_load=True) # z is a numpy array of 15x15 diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 6280208a9234..b8a747acafd6 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -569,6 +569,7 @@ def gen_candidates(): # rcParams deprecated; some can manually be mapped to another key. # Values are tuples of (version, new_name_or_None). _deprecated_ignore_map = { + 'mpl_toolkits.legacy_colorbar': ('3.4', None), } # rcParams deprecated; can use None to suppress warnings; remain actually @@ -811,7 +812,7 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False): elif key in _deprecated_ignore_map: version, alt_key = _deprecated_ignore_map[key] cbook.warn_deprecated( - version, name=key, alternative=alt_key, + version, name=key, alternative=alt_key, obj_type='rcparam', addendum="Please update your matplotlibrc.") else: version = 'master' if '.post' in __version__ else f'v{__version__}' @@ -1193,10 +1194,8 @@ def _init_tests(): "" if ft2font.__freetype_build_type__ == 'local' else "not ")) -@cbook._delete_parameter("3.2", "switch_backend_warn") @cbook._delete_parameter("3.3", "recursionlimit") -def test(verbosity=None, coverage=False, switch_backend_warn=True, - recursionlimit=0, **kwargs): +def test(verbosity=None, coverage=False, *, recursionlimit=0, **kwargs): """Run the matplotlib test suite.""" try: diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index db15030a464e..55e9566c5fad 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3472,7 +3472,6 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None, If a pair of floats, they indicate the percentiles at which to draw the whiskers (e.g., (5, 95)). In particular, setting this to (0, 100) results in whiskers covering the whole range of the data. - "range" is a deprecated synonym for (0, 100). In the edge case where ``Q1 == Q3``, *whis* is automatically set to (0, 100) (cover the whole range of the data) if *autorange* is @@ -4224,11 +4223,9 @@ def invalid_shape_exception(csize, xsize): "edgecolors", "c", "facecolor", "facecolors", "color"], label_namer="y") - @cbook._delete_parameter("3.2", "verts") def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, - vmin=None, vmax=None, alpha=None, linewidths=None, - verts=None, edgecolors=None, *, plotnonfinite=False, - **kwargs): + vmin=None, vmax=None, alpha=None, linewidths=None, *, + edgecolors=None, plotnonfinite=False, **kwargs): """ A scatter plot of *y* vs. *x* with varying marker size and/or color. @@ -5097,7 +5094,6 @@ def _fill_between_x_or_y( """ dep_dir = {"x": "y", "y": "x"}[ind_dir] - func_name = {"x": "fill_between", "y": "fill_betweenx"}[dep_dir] if not rcParams["_internal.classic_mode"]: kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection) @@ -5120,10 +5116,8 @@ def _fill_between_x_or_y( else: where = np.asarray(where, dtype=bool) if where.size != ind.size: - cbook.warn_deprecated( - "3.2", message=f"Since %(since)s, the parameter *where* " - f"must have the same size as {ind} in {func_name}(). This " - "will become an error %(removal)s.") + raise ValueError(f"where size ({where.size}) does not match " + f"{ind_dir} size ({ind.size})") where = where & ~functools.reduce( np.logical_or, map(np.ma.getmask, [ind, dep1, dep2])) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 444150748208..05c16fcfd457 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3,7 +3,6 @@ import inspect import itertools import logging -import math from numbers import Real from operator import attrgetter import types @@ -1602,23 +1601,6 @@ def get_data_ratio(self): ysize = max(abs(tymax - tymin), 1e-30) return ysize / xsize - @_api.deprecated("3.2") - def get_data_ratio_log(self): - """ - Return the aspect ratio of the raw data in log scale. - - Notes - ----- - Will be used when both axis are in log scale. - """ - xmin, xmax = self.get_xbound() - ymin, ymax = self.get_ybound() - - xsize = max(abs(math.log10(xmax) - math.log10(xmin)), 1e-30) - ysize = max(abs(math.log10(ymax) - math.log10(ymin)), 1e-30) - - return ysize / xsize - def apply_aspect(self, position=None): """ Adjust the Axes for a specified data aspect ratio. @@ -1799,7 +1781,10 @@ def axis(self, *args, emit=True, **kwargs): matplotlib.axes.Axes.set_xlim matplotlib.axes.Axes.set_ylim """ - if len(args) == 1 and isinstance(args[0], (str, bool)): + if len(args) > 1: + raise TypeError("axis() takes 0 or 1 positional arguments but " + f"{len(args)} were given") + elif len(args) == 1 and isinstance(args[0], (str, bool)): s = args[0] if s is True: s = 'on' @@ -1841,12 +1826,7 @@ def axis(self, *args, emit=True, **kwargs): raise ValueError('Unrecognized string %s to axis; ' 'try on or off' % s) else: - if len(args) >= 1: - if len(args) != 1: - cbook.warn_deprecated( - "3.2", message="Passing more than one positional " - "argument to axis() is deprecated and will raise a " - "TypeError %(removal)s.") + if len(args) == 1: limits = args[0] try: xmin, xmax, ymin, ymax = limits diff --git a/lib/matplotlib/axes/_subplots.py b/lib/matplotlib/axes/_subplots.py index 94c5264b369f..95bc5fb2c767 100644 --- a/lib/matplotlib/axes/_subplots.py +++ b/lib/matplotlib/axes/_subplots.py @@ -98,16 +98,6 @@ def update_params(self): # Now a no-op, as figbox/numRows/numCols are (deprecated) auto-updating # properties. - @_api.deprecated("3.2", alternative="ax.get_subplotspec().rowspan.start") - @property - def rowNum(self): - return self.get_subplotspec().rowspan.start - - @_api.deprecated("3.2", alternative="ax.get_subplotspec().colspan.start") - @property - def colNum(self): - return self.get_subplotspec().colspan.start - @_api.deprecated("3.4", alternative="ax.get_subplotspec().is_first_row()") def is_first_row(self): return self.get_subplotspec().rowspan.start == 0 diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 8c186cdf0f6f..1749b2e5a81b 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -673,7 +673,6 @@ def __init__(self, axes, pickradius=15): self.callbacks = cbook.CallbackRegistry() self._autolabelpos = True - self._smart_bounds = False # Deprecated in 3.2 self.label = mtext.Text( np.nan, np.nan, @@ -1010,17 +1009,6 @@ def get_ticklabel_extents(self, renderer): bbox2 = mtransforms.Bbox.from_extents(0, 0, 0, 0) return bbox, bbox2 - @_api.deprecated("3.2") - def set_smart_bounds(self, value): - """Set the axis to have smart bounds.""" - self._smart_bounds = value - self.stale = True - - @_api.deprecated("3.2") - def get_smart_bounds(self): - """Return whether the axis has smart bounds.""" - return self._smart_bounds - def _update_ticks(self): """ Update ticks (position and labels) using the current data interval of @@ -1048,36 +1036,6 @@ def _update_ticks(self): if view_low > view_high: view_low, view_high = view_high, view_low - if self._smart_bounds and ticks: # _smart_bounds is deprecated in 3.2 - # handle inverted limits - data_low, data_high = sorted(self.get_data_interval()) - locs = np.sort([tick.get_loc() for tick in ticks]) - if data_low <= view_low: - # data extends beyond view, take view as limit - ilow = view_low - else: - # data stops within view, take best tick - good_locs = locs[locs <= data_low] - if len(good_locs): - # last tick prior or equal to first data point - ilow = good_locs[-1] - else: - # No ticks (why not?), take first tick - ilow = locs[0] - if data_high >= view_high: - # data extends beyond view, take view as limit - ihigh = view_high - else: - # data stops within view, take best tick - good_locs = locs[locs >= data_high] - if len(good_locs): - # first tick after or equal to last data point - ihigh = good_locs[0] - else: - # No ticks (why not?), take last tick - ihigh = locs[-1] - ticks = [tick for tick in ticks if ilow <= tick.get_loc() <= ihigh] - interval_t = self.get_transform().transform([view_low, view_high]) ticks_to_draw = [] diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index 626d175d2ad3..d4344c80a840 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -1055,8 +1055,7 @@ def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None, If a pair of floats, they indicate the percentiles at which to draw the whiskers (e.g., (5, 95)). In particular, setting this to (0, 100) - results in whiskers covering the whole range of the data. "range" is - a deprecated synonym for (0, 100). + results in whiskers covering the whole range of the data. In the edge case where ``Q1 == Q3``, *whis* is automatically set to (0, 100) (cover the whole range of the data) if *autorange* is True. @@ -1199,22 +1198,13 @@ def _compute_conf_interval(data, med, iqr, bootstrap): ) # lowest/highest non-outliers - if np.isscalar(whis): - if np.isreal(whis): - loval = q1 - whis * stats['iqr'] - hival = q3 + whis * stats['iqr'] - elif whis in ['range', 'limit', 'limits', 'min/max']: - warn_deprecated( - "3.2", message=f"Setting whis to {whis!r} is deprecated " - "since %(since)s and support for it will be removed " - "%(removal)s; set it to [0, 100] to achieve the same " - "effect.") - loval = np.min(x) - hival = np.max(x) - else: - raise ValueError('whis must be a float or list of percentiles') - else: + if np.iterable(whis) and not isinstance(whis, str): loval, hival = np.percentile(x, whis) + elif np.isreal(whis): + loval = q1 - whis * stats['iqr'] + hival = q3 + whis * stats['iqr'] + else: + raise ValueError('whis must be a float or list of percentiles') # get high extreme wiskhi = x[x <= hival] diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py index cbd88800e6d2..b809c50de79a 100644 --- a/lib/matplotlib/dates.py +++ b/lib/matplotlib/dates.py @@ -166,8 +166,7 @@ from matplotlib import _api, cbook, ticker, units __all__ = ('datestr2num', 'date2num', 'num2date', 'num2timedelta', 'drange', - 'epoch2num', 'num2epoch', 'mx2num', 'set_epoch', - 'get_epoch', 'DateFormatter', + 'epoch2num', 'num2epoch', 'set_epoch', 'get_epoch', 'DateFormatter', 'ConciseDateFormatter', 'IndexDateFormatter', 'AutoDateFormatter', 'DateLocator', 'RRuleLocator', 'AutoDateLocator', 'YearLocator', 'MonthLocator', 'WeekdayLocator', @@ -1783,23 +1782,6 @@ def num2epoch(d): return np.asarray(d) * SEC_PER_DAY - dt -@_api.deprecated("3.2") -def mx2num(mxdates): - """ - Convert mx :class:`datetime` instance (or sequence of mx - instances) to the new date format. - """ - scalar = False - if not np.iterable(mxdates): - scalar = True - mxdates = [mxdates] - ret = epoch2num([m.ticks() for m in mxdates]) - if scalar: - return ret[0] - else: - return ret - - def date_ticker_factory(span, tz=None, numticks=5): """ Create a date locator with *numticks* (approx) and a date formatter diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 67436b15f444..51ff4d613d5c 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -3211,9 +3211,7 @@ def execute_constrained_layout(self, renderer=None): renderer = get_renderer(fig) do_constrained_layout(fig, renderer, h_pad, w_pad, hspace, wspace) - @cbook._delete_parameter("3.2", "renderer") - def tight_layout(self, renderer=None, pad=1.08, h_pad=None, w_pad=None, - rect=None): + def tight_layout(self, *, pad=1.08, h_pad=None, w_pad=None, rect=None): """ Adjust the padding between and around subplots. @@ -3223,8 +3221,6 @@ def tight_layout(self, renderer=None, pad=1.08, h_pad=None, w_pad=None, Parameters ---------- - renderer : subclass of `~.backend_bases.RendererBase`, optional - Defaults to the renderer for the figure. Deprecated. pad : float, default: 1.08 Padding between the figure edge and the edges of subplots, as a fraction of the font size. @@ -3250,8 +3246,7 @@ def tight_layout(self, renderer=None, pad=1.08, h_pad=None, w_pad=None, "compatible with tight_layout, so results " "might be incorrect.") - if renderer is None: - renderer = get_renderer(self) + renderer = get_renderer(self) ctx = (renderer._draw_disabled() if hasattr(renderer, '_draw_disabled') else suppress()) diff --git a/lib/matplotlib/pylab.py b/lib/matplotlib/pylab.py index 79a0c2c7668c..6b9f89d29ead 100644 --- a/lib/matplotlib/pylab.py +++ b/lib/matplotlib/pylab.py @@ -17,7 +17,7 @@ from matplotlib.dates import ( date2num, num2date, datestr2num, drange, epoch2num, - num2epoch, mx2num, DateFormatter, IndexDateFormatter, DateLocator, + num2epoch, DateFormatter, IndexDateFormatter, DateLocator, RRuleLocator, YearLocator, MonthLocator, WeekdayLocator, DayLocator, HourLocator, MinuteLocator, SecondLocator, rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY, diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 7b35433bd3c2..0d7d5641248f 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -2983,14 +2983,12 @@ def quiverkey(Q, X, Y, U, label, **kw): @_copy_docstring_and_deprecators(Axes.scatter) def scatter( x, y, s=None, c=None, marker=None, cmap=None, norm=None, - vmin=None, vmax=None, alpha=None, linewidths=None, - verts=_api.deprecation._deprecated_parameter, edgecolors=None, - *, plotnonfinite=False, data=None, **kwargs): + vmin=None, vmax=None, alpha=None, linewidths=None, *, + edgecolors=None, plotnonfinite=False, data=None, **kwargs): __ret = gca().scatter( x, y, s=s, c=c, marker=marker, cmap=cmap, norm=norm, vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths, - verts=verts, edgecolors=edgecolors, - plotnonfinite=plotnonfinite, + edgecolors=edgecolors, plotnonfinite=plotnonfinite, **({"data": data} if data is not None else {}), **kwargs) sci(__ret) return __ret diff --git a/lib/matplotlib/quiver.py b/lib/matplotlib/quiver.py index ae19fba35b00..7bfb76991a23 100644 --- a/lib/matplotlib/quiver.py +++ b/lib/matplotlib/quiver.py @@ -374,11 +374,6 @@ def contains(self, mouseevent): return True, {} return False, {} - @_api.deprecated("3.2") - @property - def quiverkey_doc(self): - return self.__init__.__doc__ - def _parse_args(*args, caller_name='function'): """ diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index e6c943fdac59..eb143ecda4c2 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -1441,8 +1441,6 @@ def _convert_validator_spec(key, conv): # Additional arguments for convert movie writer (using pipes) "animation.convert_args": validate_stringlist, - "mpl_toolkits.legacy_colorbar": validate_bool, - # Classic (pre 2.0) compatibility mode # This is used for things that are hard to make backward compatible # with a sane rcParam alone. This does *not* turn on classic mode diff --git a/lib/matplotlib/spines.py b/lib/matplotlib/spines.py index 76d0b5745024..cf342a86d89c 100644 --- a/lib/matplotlib/spines.py +++ b/lib/matplotlib/spines.py @@ -61,7 +61,6 @@ def __init__(self, axes, spine_type, path, **kwargs): self.set_transform(self.axes.transData) # default transform self._bounds = None # default bounds - self._smart_bounds = False # deprecated in 3.2 # Defer initial position determination. (Not much support for # non-rectangular axes is currently implemented, and this lets @@ -82,23 +81,6 @@ def __init__(self, axes, spine_type, path, **kwargs): # Note: This cannot be calculated until this is added to an Axes self._patch_transform = mtransforms.IdentityTransform() - @_api.deprecated("3.2") - def set_smart_bounds(self, value): - """Set the spine and associated axis to have smart bounds.""" - self._smart_bounds = value - - # also set the axis if possible - if self.spine_type in ('left', 'right'): - self.axes.yaxis.set_smart_bounds(value) - elif self.spine_type in ('top', 'bottom'): - self.axes.xaxis.set_smart_bounds(value) - self.stale = True - - @_api.deprecated("3.2") - def get_smart_bounds(self): - """Return whether the spine has smart bounds.""" - return self._smart_bounds - def set_patch_arc(self, center, radius, theta1, theta2): """Set the spine to be arc-like.""" self._patch_type = 'arc' @@ -247,64 +229,14 @@ def _adjust_location(self): if self.spine_type == 'circle': return - if self._bounds is None: - if self.spine_type in ('left', 'right'): - low, high = self.axes.viewLim.intervaly - elif self.spine_type in ('top', 'bottom'): - low, high = self.axes.viewLim.intervalx - else: - raise ValueError('unknown spine spine_type: %s' % - self.spine_type) - - if self._smart_bounds: # deprecated in 3.2 - # attempt to set bounds in sophisticated way - - # handle inverted limits - viewlim_low, viewlim_high = sorted([low, high]) - - if self.spine_type in ('left', 'right'): - datalim_low, datalim_high = self.axes.dataLim.intervaly - ticks = self.axes.get_yticks() - elif self.spine_type in ('top', 'bottom'): - datalim_low, datalim_high = self.axes.dataLim.intervalx - ticks = self.axes.get_xticks() - # handle inverted limits - ticks = np.sort(ticks) - datalim_low, datalim_high = sorted([datalim_low, datalim_high]) - - if datalim_low < viewlim_low: - # Data extends past view. Clip line to view. - low = viewlim_low - else: - # Data ends before view ends. - cond = (ticks <= datalim_low) & (ticks >= viewlim_low) - tickvals = ticks[cond] - if len(tickvals): - # A tick is less than or equal to lowest data point. - low = tickvals[-1] - else: - # No tick is available - low = datalim_low - low = max(low, viewlim_low) - - if datalim_high > viewlim_high: - # Data extends past view. Clip line to view. - high = viewlim_high - else: - # Data ends before view ends. - cond = (ticks >= datalim_high) & (ticks <= viewlim_high) - tickvals = ticks[cond] - if len(tickvals): - # A tick is greater than or equal to highest data - # point. - high = tickvals[0] - else: - # No tick is available - high = datalim_high - high = min(high, viewlim_high) - - else: + if self._bounds is not None: low, high = self._bounds + elif self.spine_type in ('left', 'right'): + low, high = self.axes.viewLim.intervaly + elif self.spine_type in ('top', 'bottom'): + low, high = self.axes.viewLim.intervalx + else: + raise ValueError(f'unknown spine spine_type: {self.spine_type}') if self._patch_type == 'arc': if self.spine_type in ('bottom', 'top'): diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 49627e9ce433..c2060470d69a 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5660,15 +5660,6 @@ def test_none_kwargs(): assert ln.get_linestyle() == '-' -def test_ls_ds_conflict(): - # Passing the drawstyle with the linestyle is deprecated since 3.1. - # We still need to test this until it's removed from the code. - # But we don't want to see the deprecation warning in the test. - with matplotlib._api.suppress_matplotlib_deprecation_warning(), \ - pytest.raises(ValueError): - plt.plot(range(32), linestyle='steps-pre:', drawstyle='steps-post') - - def test_bar_uint8(): xs = [0, 1, 2, 3] b = plt.bar(np.array(xs, dtype=np.uint8), [2, 3, 4, 5], align="edge") diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index 78a6ad8b104c..ed05ce8c7d35 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -1596,8 +1596,7 @@ def __init__(self, text, xy, Parameters ---------- text : str - The text of the annotation. *s* is a deprecated synonym for this - parameter. + The text of the annotation. xy : (float, float) The point *(x, y)* to annotate. The coordinate system is determined diff --git a/lib/mpl_toolkits/axes_grid/colorbar.py b/lib/mpl_toolkits/axes_grid/colorbar.py deleted file mode 100644 index cc5c252da896..000000000000 --- a/lib/mpl_toolkits/axes_grid/colorbar.py +++ /dev/null @@ -1,5 +0,0 @@ -from mpl_toolkits.axes_grid1.colorbar import ( - make_axes_kw_doc, colormap_kw_doc, colorbar_doc, - CbarAxesLocator, ColorbarBase, Colorbar, - make_axes, colorbar -) diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py index 88642035bd2e..f38e0643ed8d 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_grid.py +++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py @@ -4,7 +4,7 @@ import numpy as np import matplotlib as mpl -from matplotlib import _api, cbook, ticker +from matplotlib import _api, cbook from matplotlib.gridspec import SubplotSpec from .axes_divider import Size, SubplotDivider, Divider @@ -25,7 +25,6 @@ def __init__(self, *args, orientation, **kwargs): self._locator = None # deprecated. super().__init__(*args, **kwargs) - @cbook._rename_parameter("3.2", "locator", "ticks") def colorbar(self, mappable, *, ticks=None, **kwargs): if self.orientation in ["top", "bottom"]: @@ -33,27 +32,10 @@ def colorbar(self, mappable, *, ticks=None, **kwargs): else: orientation = "vertical" - if mpl.rcParams["mpl_toolkits.legacy_colorbar"]: - cbook.warn_deprecated( - "3.2", message="Since %(since)s, mpl_toolkits's own colorbar " - "implementation is deprecated; it will be removed " - "%(removal)s. Set the 'mpl_toolkits.legacy_colorbar' rcParam " - "to False to use Matplotlib's default colorbar implementation " - "and suppress this deprecation warning.") - if ticks is None: - ticks = ticker.MaxNLocator(5) # For backcompat. - from .colorbar import Colorbar - cb = Colorbar( - self, mappable, orientation=orientation, ticks=ticks, **kwargs) - self._cbid = mappable.callbacksSM.connect( - 'changed', cb.update_normal) - mappable.colorbar = cb - self._locator = cb.cbar_axis.get_major_locator() - else: - cb = mpl.colorbar.Colorbar( - self, mappable, orientation=orientation, ticks=ticks, **kwargs) - self._cbid = mappable.colorbar_cid # deprecated. - self._locator = cb.locator # deprecated. + cb = mpl.colorbar.Colorbar( + self, mappable, orientation=orientation, ticks=ticks, **kwargs) + self._cbid = mappable.colorbar_cid # deprecated in 3.3. + self._locator = cb.locator # deprecated in 3.3. self._config_axes() return cb diff --git a/lib/mpl_toolkits/axes_grid1/colorbar.py b/lib/mpl_toolkits/axes_grid1/colorbar.py deleted file mode 100644 index 77af5a1ab7fc..000000000000 --- a/lib/mpl_toolkits/axes_grid1/colorbar.py +++ /dev/null @@ -1,806 +0,0 @@ -""" -Colorbar toolkit with two classes and a function: - - :class:`ColorbarBase` - the base class with full colorbar drawing functionality. - It can be used as-is to make a colorbar for a given colormap; - a mappable object (e.g., image) is not needed. - - :class:`Colorbar` - the derived class for use with images or contour plots. - - :func:`make_axes` - a function for resizing an axes and adding a second axes - suitable for a colorbar - -The :meth:`~matplotlib.figure.Figure.colorbar` method uses :func:`make_axes` -and :class:`Colorbar`; the :func:`~matplotlib.pyplot.colorbar` function -is a thin wrapper over :meth:`~matplotlib.figure.Figure.colorbar`. -""" - -import numpy as np -import matplotlib as mpl -from matplotlib import cbook -import matplotlib.colors as colors -import matplotlib.cm as cm -from matplotlib import docstring -import matplotlib.ticker as ticker -import matplotlib.collections as collections -import matplotlib.contour as contour -from matplotlib.path import Path -from matplotlib.patches import PathPatch -from matplotlib.transforms import Bbox - - -cbook.warn_deprecated( - "3.2", name=__name__, obj_type="module", alternative="matplotlib.colorbar") - - -make_axes_kw_doc = ''' - - ============= ==================================================== - Property Description - ============= ==================================================== - *orientation* vertical or horizontal - *fraction* 0.15; fraction of original axes to use for colorbar - *pad* Defaults to 0.05 if vertical, 0.15 if horizontal; fraction - of original axes between colorbar and new image axes. - Defaults to 0.05 for both if - `.Figure.get_constrained_layout` is *True*. - *shrink* 1.0; fraction by which to shrink the colorbar - *aspect* 20; ratio of long to short dimensions - ============= ==================================================== - -''' - -colormap_kw_doc = ''' - - =========== ==================================================== - Property Description - =========== ==================================================== - *extend* [ 'neither' | 'both' | 'min' | 'max' ] - If not 'neither', make pointed end(s) for out-of- - range values. These are set for a given colormap - using the colormap set_under and set_over methods. - *spacing* [ 'uniform' | 'proportional' ] - Uniform spacing gives each discrete color the same - space; proportional makes the space proportional to - the data interval. - *ticks* [ None | list of ticks | Locator object ] - If None, ticks are determined automatically from the - input. - *format* [ None | format string | Formatter object ] - If None, the - :class:`~matplotlib.ticker.ScalarFormatter` is used. - If a format string is given, e.g., '%.3f', that is - used. An alternative - :class:`~matplotlib.ticker.Formatter` object may be - given instead. - *drawedges* bool - Whether to draw lines at color boundaries. - =========== ==================================================== - - The following will probably be useful only in the context of - indexed colors (that is, when the mappable has norm=NoNorm()), - or other unusual circumstances. - - ============ =================================================== - Property Description - ============ =================================================== - *boundaries* None or a sequence - *values* None or a sequence which must be of length 1 less - than the sequence of *boundaries*. For each region - delimited by adjacent entries in *boundaries*, the - colormapped to the corresponding value in values - will be used. - ============ =================================================== - -''' - -colorbar_doc = ''' - -Add a colorbar to a plot. - -Function signatures for the :mod:`~matplotlib.pyplot` interface; all -but the first are also method signatures for the -:meth:`~matplotlib.figure.Figure.colorbar` method:: - - colorbar(**kwargs) - colorbar(mappable, **kwargs) - colorbar(mappable, cax=cax, **kwargs) - colorbar(mappable, ax=ax, **kwargs) - -arguments: - - *mappable* - the :class:`~matplotlib.image.Image`, - :class:`~matplotlib.contour.ContourSet`, etc. to - which the colorbar applies; this argument is mandatory for the - :meth:`~matplotlib.figure.Figure.colorbar` method but optional for the - :func:`~matplotlib.pyplot.colorbar` function, which sets the - default to the current image. - -keyword arguments: - - *cax* - None | axes object into which the colorbar will be drawn - *ax* - None | parent axes object from which space for a new - colorbar axes will be stolen - - -Additional keyword arguments are of two kinds: - - axes properties: - %s - colorbar properties: - %s - -If *mappable* is a :class:`~matplotlib.contours.ContourSet`, its *extend* -kwarg is included automatically. - -Note that the *shrink* kwarg provides a simple way to keep a vertical -colorbar, for example, from being taller than the axes of the mappable -to which the colorbar is attached; but it is a manual method requiring -some trial and error. If the colorbar is too tall (or a horizontal -colorbar is too wide) use a smaller value of *shrink*. - -For more precise control, you can manually specify the positions of -the axes objects in which the mappable and the colorbar are drawn. In -this case, do not use any of the axes properties kwargs. - -It is known that some vector graphics viewer (svg and pdf) renders white gaps -between segments of the colorbar. This is due to bugs in the viewers not -matplotlib. As a workaround the colorbar can be rendered with overlapping -segments:: - - cbar = colorbar() - cbar.solids.set_edgecolor("face") - draw() - -However this has negative consequences in other circumstances. Particularly -with semi transparent images (alpha < 1) and colorbar extensions and is not -enabled by default see (issue #1188). - -returns: - :class:`~matplotlib.colorbar.Colorbar` instance; see also its base class, - :class:`~matplotlib.colorbar.ColorbarBase`. Call the - :meth:`~matplotlib.colorbar.ColorbarBase.set_label` method - to label the colorbar. - - -The transData of the *cax* is adjusted so that the limits in the -longest axis actually corresponds to the limits in colorbar range. On -the other hand, the shortest axis has a data limits of [1,2], whose -unconventional value is to prevent underflow when log scale is used. -''' % (make_axes_kw_doc, colormap_kw_doc) - -#docstring.interpd.update(colorbar_doc=colorbar_doc) - - -class CbarAxesLocator: - """ - CbarAxesLocator is a axes_locator for colorbar axes. It adjust the - position of the axes to make a room for extended ends, i.e., the - extended ends are located outside the axes area. - """ - - def __init__(self, locator=None, extend="neither", orientation="vertical"): - """ - *locator* : the bbox returned from the locator is used as a - initial axes location. If None, axes.bbox is used. - - *extend* : same as in ColorbarBase - *orientation* : same as in ColorbarBase - - """ - self._locator = locator - self.extesion_fraction = 0.05 - self.extend = extend - self.orientation = orientation - - def get_original_position(self, axes, renderer): - """Return the original position of the axes.""" - if self._locator is None: - bbox = axes.get_position(original=True) - else: - bbox = self._locator(axes, renderer) - return bbox - - def get_end_vertices(self): - """ - Return a tuple of two vertices for the colorbar extended ends. - - The first vertices is for the minimum end, and the second is for - the maximum end. - """ - # Note that concatenating two vertices needs to make a - # vertices for the frame. - extesion_fraction = self.extesion_fraction - - corx = extesion_fraction*2. - cory = 1./(1. - corx) - x1, y1, w, h = 0, 0, 1, 1 - x2, y2 = x1 + w, y1 + h - dw, dh = w*extesion_fraction, h*extesion_fraction*cory - - if self.extend in ["min", "both"]: - bottom = [(x1, y1), - (x1+w/2., y1-dh), - (x2, y1)] - else: - bottom = [(x1, y1), - (x2, y1)] - - if self.extend in ["max", "both"]: - top = [(x2, y2), - (x1+w/2., y2+dh), - (x1, y2)] - else: - top = [(x2, y2), - (x1, y2)] - - if self.orientation == "horizontal": - bottom = [(y, x) for (x, y) in bottom] - top = [(y, x) for (x, y) in top] - - return bottom, top - - def get_path_patch(self): - """Return the path for axes patch.""" - end1, end2 = self.get_end_vertices() - verts = [] + end1 + end2 + end1[:1] - return Path(verts) - - def get_path_ends(self): - """Return the paths for extended ends.""" - end1, end2 = self.get_end_vertices() - return Path(end1), Path(end2) - - def __call__(self, axes, renderer): - """Return the adjusted position of the axes.""" - bbox0 = self.get_original_position(axes, renderer) - bbox = bbox0 - - x1, y1, w, h = bbox.bounds - extesion_fraction = self.extesion_fraction - dw, dh = w*extesion_fraction, h*extesion_fraction - - if self.extend in ["min", "both"]: - if self.orientation == "horizontal": - x1 = x1 + dw - else: - y1 = y1+dh - - if self.extend in ["max", "both"]: - if self.orientation == "horizontal": - w = w-2*dw - else: - h = h-2*dh - - return Bbox.from_bounds(x1, y1, w, h) - - -class ColorbarBase(cm.ScalarMappable): - """ - Draw a colorbar in an existing axes. - - This is a base class for the :class:`Colorbar` class, which is the - basis for the :func:`~matplotlib.pyplot.colorbar` method and pyplot - function. - - It is also useful by itself for showing a colormap. If the *cmap* - kwarg is given but *boundaries* and *values* are left as None, - then the colormap will be displayed on a 0-1 scale. To show the - under- and over-value colors, specify the *norm* as:: - - colors.Normalize(clip=False) - - To show the colors versus index instead of on the 0-1 scale, - use:: - - norm=colors.NoNorm. - - Useful attributes: - - :attr:`ax` - the Axes instance in which the colorbar is drawn - - :attr:`lines` - a LineCollection if lines were drawn, otherwise None - - :attr:`dividers` - a LineCollection if *drawedges* is True, otherwise None - - Useful public methods are :meth:`set_label` and :meth:`add_lines`. - """ - - def __init__(self, ax, - cmap=None, - norm=None, - alpha=1.0, - values=None, - boundaries=None, - orientation='vertical', - extend='neither', - spacing='uniform', # uniform or proportional - ticks=None, - format=None, - drawedges=False, - filled=True, - ): - self.ax = ax - - if cmap is None: - cmap = cm.get_cmap() - if norm is None: - norm = colors.Normalize() - self.alpha = alpha - super().__init__(cmap=cmap, norm=norm) - self.values = values - self.boundaries = boundaries - self.extend = extend - self.spacing = spacing - self.orientation = orientation - self.drawedges = drawedges - self.filled = filled - - # artists - self.solids = None - self.lines = None - self.dividers = None - self.extension_patch1 = None - self.extension_patch2 = None - - if orientation == "vertical": - self.cbar_axis = self.ax.yaxis - else: - self.cbar_axis = self.ax.xaxis - - if format is None: - if isinstance(self.norm, colors.LogNorm): - # change both axis for proper aspect - self.ax.set_xscale("log") - self.ax.set_yscale("log") - self.cbar_axis.set_minor_locator(ticker.NullLocator()) - formatter = ticker.LogFormatter() - else: - formatter = None - elif isinstance(format, str): - formatter = ticker.FormatStrFormatter(format) - else: - formatter = format # Assume it is a Formatter - - if formatter is None: - formatter = self.cbar_axis.get_major_formatter() - else: - self.cbar_axis.set_major_formatter(formatter) - - if np.iterable(ticks): - self.cbar_axis.set_ticks(ticks) - elif ticks is not None: - self.cbar_axis.set_major_locator(ticks) - else: - self._select_locator() - - self._config_axes() - - self.update_artists() - - self.set_label_text('') - - def _get_colorbar_limits(self): - """ - initial limits for colorbar range. The returned min, max values - will be used to create colorbar solid(?) and etc. - """ - if self.boundaries is not None: - C = self.boundaries - if self.extend in ["min", "both"]: - C = C[1:] - - if self.extend in ["max", "both"]: - C = C[:-1] - return min(C), max(C) - else: - return self.get_clim() - - def _config_axes(self): - """ - Adjust the properties of the axes to be adequate for colorbar display. - """ - ax = self.ax - - axes_locator = CbarAxesLocator(ax.get_axes_locator(), - extend=self.extend, - orientation=self.orientation) - ax.set_axes_locator(axes_locator) - - # override the get_data_ratio for the aspect works. - def _f(): - return 1. - ax.get_data_ratio = _f - ax.get_data_ratio_log = _f - - ax.set_frame_on(True) - ax.set_navigate(False) - - self.ax.set_autoscalex_on(False) - self.ax.set_autoscaley_on(False) - - if self.orientation == 'horizontal': - ax.xaxis.set_label_position('bottom') - ax.set_yticks([]) - else: - ax.set_xticks([]) - ax.yaxis.set_label_position('right') - ax.yaxis.set_ticks_position('right') - - def update_artists(self): - """ - Update the colorbar associated artists, *filled* and - *ends*. Note that *lines* are not updated. This needs to be - called whenever clim of associated image changes. - """ - self._process_values() - self._add_ends() - - X, Y = self._mesh() - if self.filled: - C = self._values[:, np.newaxis] - self._add_solids(X, Y, C) - - ax = self.ax - vmin, vmax = self._get_colorbar_limits() - if self.orientation == 'horizontal': - ax.set_ylim(1, 2) - ax.set_xlim(vmin, vmax) - else: - ax.set_xlim(1, 2) - ax.set_ylim(vmin, vmax) - - def _add_ends(self): - """ - Create patches from extended ends and add them to the axes. - """ - - del self.extension_patch1 - del self.extension_patch2 - - path1, path2 = self.ax.get_axes_locator().get_path_ends() - fc = mpl.rcParams['axes.facecolor'] - ec = mpl.rcParams['axes.edgecolor'] - linewidths = 0.5 * mpl.rcParams['axes.linewidth'] - self.extension_patch1 = PathPatch(path1, - fc=fc, ec=ec, lw=linewidths, - zorder=2., - transform=self.ax.transAxes, - clip_on=False) - self.extension_patch2 = PathPatch(path2, - fc=fc, ec=ec, lw=linewidths, - zorder=2., - transform=self.ax.transAxes, - clip_on=False) - self.ax.add_artist(self.extension_patch1) - self.ax.add_artist(self.extension_patch2) - - def _set_label_text(self): - """Set the colorbar label.""" - self.cbar_axis.set_label_text(self._label, **self._labelkw) - - def set_label_text(self, label, **kw): - """Label the long axis of the colorbar.""" - self._label = label - self._labelkw = kw - self._set_label_text() - - def _edges(self, X, Y): - """Return the separator line segments; helper for _add_solids.""" - N = X.shape[0] - # Using the non-array form of these line segments is much - # simpler than making them into arrays. - if self.orientation == 'vertical': - return [list(zip(X[i], Y[i])) for i in range(1, N-1)] - else: - return [list(zip(Y[i], X[i])) for i in range(1, N-1)] - - def _add_solids(self, X, Y, C): - """ - Draw the colors using :meth:`~matplotlib.axes.Axes.pcolormesh`; - optionally add separators. - """ - ## Change to pcolorfast after fixing bugs in some backends... - - if self.extend in ["min", "both"]: - cc = self.to_rgba([C[0][0]]) - self.extension_patch1.set_facecolor(cc[0]) - X, Y, C = X[1:], Y[1:], C[1:] - - if self.extend in ["max", "both"]: - cc = self.to_rgba([C[-1][0]]) - self.extension_patch2.set_facecolor(cc[0]) - X, Y, C = X[:-1], Y[:-1], C[:-1] - - if self.orientation == 'vertical': - args = (X, Y, C) - else: - args = (np.transpose(Y), np.transpose(X), np.transpose(C)) - - del self.solids - del self.dividers - - col = self.ax.pcolormesh( - *args, - cmap=self.cmap, norm=self.norm, shading='flat', alpha=self.alpha) - - self.solids = col - if self.drawedges: - self.dividers = collections.LineCollection( - self._edges(X, Y), - colors=(mpl.rcParams['axes.edgecolor'],), - linewidths=(0.5*mpl.rcParams['axes.linewidth'],), - ) - self.ax.add_collection(self.dividers) - else: - self.dividers = None - - def add_lines(self, levels, colors, linewidths): - """Draw lines on the colorbar. It deletes preexisting lines.""" - X, Y = np.meshgrid([1, 2], levels) - if self.orientation == 'vertical': - xy = np.stack([X, Y], axis=-1) - else: - xy = np.stack([Y, X], axis=-1) - col = collections.LineCollection(xy, linewidths=linewidths) - self.lines = col - col.set_color(colors) - self.ax.add_collection(col) - - def _select_locator(self): - """Select a suitable locator.""" - if self.boundaries is None: - if isinstance(self.norm, colors.NoNorm): - nv = len(self._values) - base = 1 + int(nv/10) - locator = ticker.IndexLocator(base=base, offset=0) - elif isinstance(self.norm, colors.BoundaryNorm): - b = self.norm.boundaries - locator = ticker.FixedLocator(b, nbins=10) - elif isinstance(self.norm, colors.LogNorm): - locator = ticker.LogLocator() - else: - locator = ticker.MaxNLocator(nbins=5) - else: - b = self._boundaries[self._inside] - locator = ticker.FixedLocator(b) - - self.cbar_axis.set_major_locator(locator) - - def _process_values(self, b=None): - """ - Set the :attr:`_boundaries` and :attr:`_values` attributes - based on the input boundaries and values. Input boundaries - can be *self.boundaries* or the argument *b*. - """ - if b is None: - b = self.boundaries - if b is not None: - self._boundaries = np.asarray(b, dtype=float) - if self.values is None: - self._values = (self._boundaries[:-1] - + self._boundaries[1:]) / 2 - if isinstance(self.norm, colors.NoNorm): - self._values = (self._values + 0.00001).astype(np.int16) - return - self._values = np.array(self.values) - return - if self.values is not None: - self._values = np.array(self.values) - if self.boundaries is None: - b = np.zeros(len(self.values) + 1) - b[1:-1] = 0.5*(self._values[:-1] - self._values[1:]) - b[0] = 2.0*b[1] - b[2] - b[-1] = 2.0*b[-2] - b[-3] - self._boundaries = b - return - self._boundaries = np.array(self.boundaries) - return - # Neither boundaries nor values are specified; - # make reasonable ones based on cmap and norm. - if isinstance(self.norm, colors.NoNorm): - self._boundaries = ( - self._uniform_y(self.cmap.N + 1) * self.cmap.N - 0.5) - self._values = np.arange(self.cmap.N, dtype=np.int16) - return - elif isinstance(self.norm, colors.BoundaryNorm): - self._boundaries = np.array(self.norm.boundaries) - self._values = (self._boundaries[:-1] + self._boundaries[1:]) / 2 - return - else: - b = self._uniform_y(self.cmap.N + 1) - - self._process_values(b) - - def _uniform_y(self, N): - """ - Return colorbar data coordinates for *N* uniformly spaced boundaries. - """ - vmin, vmax = self._get_colorbar_limits() - if isinstance(self.norm, colors.LogNorm): - y = np.geomspace(vmin, vmax, N) - else: - y = np.linspace(vmin, vmax, N) - return y - - def _mesh(self): - """ - Return X,Y, the coordinate arrays for the colorbar pcolormesh. - These are suitable for a vertical colorbar; swapping and - transposition for a horizontal colorbar are done outside - this function. - """ - x = np.array([1.0, 2.0]) - if self.spacing == 'uniform': - y = self._uniform_y(len(self._boundaries)) - else: - y = self._boundaries - self._y = y - - X, Y = np.meshgrid(x, y) - return X, Y - - def set_alpha(self, alpha): - """Set the alpha value for transparency.""" - self.alpha = alpha - - -class Colorbar(ColorbarBase): - def __init__(self, ax, mappable, **kw): - # Ensure mappable.norm.vmin, vmax are set when colorbar is called, even - # if mappable.draw has not yet been called. This will not change vmin, - # vmax if they are already set. - mappable.autoscale_None() - - self.mappable = mappable - kw['cmap'] = mappable.cmap - kw['norm'] = mappable.norm - kw['alpha'] = mappable.get_alpha() - if isinstance(mappable, contour.ContourSet): - CS = mappable - kw['boundaries'] = CS._levels - kw['values'] = CS.cvalues - kw['extend'] = CS.extend - #kw['ticks'] = CS._levels - kw.setdefault('ticks', ticker.FixedLocator(CS.levels, nbins=10)) - kw['filled'] = CS.filled - super().__init__(ax, **kw) - if not CS.filled: - self.add_lines(CS) - else: - super().__init__(ax, **kw) - - def add_lines(self, CS): - """Add the lines from a non-filled `.ContourSet` to the colorbar.""" - if not isinstance(CS, contour.ContourSet) or CS.filled: - raise ValueError('add_lines is only for a ContourSet of lines') - tcolors = [c[0] for c in CS.tcolors] - tlinewidths = [t[0] for t in CS.tlinewidths] - # The following was an attempt to get the colorbar lines - # to follow subsequent changes in the contour lines, - # but more work is needed: specifically, a careful - # look at event sequences, and at how - # to make one object track another automatically. - #tcolors = [col.get_colors()[0] for col in CS.collections] - #tlinewidths = [col.get_linewidth()[0] for lw in CS.collections] - super().add_lines(CS.levels, tcolors, tlinewidths) - - def update_normal(self, mappable): - """ - Update solid patches, lines, etc. - - This is meant to be called when the norm of the image or contour plot - to which this colorbar belongs changes. - - If the norm on the mappable is different than before, this resets the - locator and formatter for the axis, so if these have been customized, - they will need to be customized again. However, if the norm only - changes values of *vmin*, *vmax* or *cmap* then the old formatter - and locator will be preserved. - """ - self.mappable = mappable - self.set_alpha(mappable.get_alpha()) - self.cmap = mappable.cmap - if mappable.norm != self.norm: - self.norm = mappable.norm - self._reset_locator_formatter_scale() - - self.draw_all() - if isinstance(self.mappable, contour.ContourSet): - CS = self.mappable - if not CS.filled: - self.add_lines(CS) - self.stale = True - - def update_bruteforce(self, mappable): - """ - Update the colorbar artists to reflect the change of the - associated mappable. - """ - self.update_artists() - - if isinstance(mappable, contour.ContourSet): - if not mappable.filled: - self.add_lines(mappable) - - -@docstring.Substitution(make_axes_kw_doc) -def make_axes(parent, *, fraction=0.15, shrink=1.0, aspect=20, **kw): - """ - Resize and reposition a parent axes, and return a child - axes suitable for a colorbar - - :: - - cax, kw = make_axes(parent, **kw) - - Keyword arguments may include the following (with defaults): - - *orientation* - 'vertical' or 'horizontal' - - %s - - All but the first of these are stripped from the input kw set. - - Returns (cax, kw), the child axes and the reduced kw dictionary. - """ - orientation = kw.setdefault('orientation', 'vertical') - #pb = transforms.PBox(parent.get_position()) - pb = parent.get_position(original=True).frozen() - if orientation == 'vertical': - pad = kw.pop('pad', 0.05) - x1 = 1.0-fraction - pb1, pbx, pbcb = pb.splitx(x1-pad, x1) - pbcb = pbcb.shrunk(1.0, shrink).anchored('C', pbcb) - anchor = (0.0, 0.5) - panchor = (1.0, 0.5) - else: - pad = kw.pop('pad', 0.15) - pbcb, pbx, pb1 = pb.splity(fraction, fraction+pad) - pbcb = pbcb.shrunk(shrink, 1.0).anchored('C', pbcb) - aspect = 1.0/aspect - anchor = (0.5, 1.0) - panchor = (0.5, 0.0) - parent.set_position(pb1) - parent.set_anchor(panchor) - fig = parent.get_figure() - cax = fig.add_axes(pbcb) - cax.set_aspect(aspect, anchor=anchor, adjustable='box') - return cax, kw - - -@docstring.Substitution(colorbar_doc) -def colorbar(mappable, cax=None, ax=None, **kw): - """ - Create a colorbar for a ScalarMappable instance. - - Documentation for the pyplot thin wrapper: - - %s - """ - import matplotlib.pyplot as plt - if ax is None: - ax = plt.gca() - if cax is None: - cax, kw = make_axes(ax, **kw) - cb = Colorbar(cax, mappable, **kw) - - def on_changed(m): - cb.set_cmap(m.get_cmap()) - cb.set_clim(m.get_clim()) - cb.update_bruteforce(m) - - mappable.callbacksSM.connect('changed', on_changed) - mappable.colorbar = cb - ax.figure.sca(ax) - return cb diff --git a/lib/mpl_toolkits/tests/test_axes_grid.py b/lib/mpl_toolkits/tests/test_axes_grid.py index 2c2a9e785a96..f789c31b7c67 100644 --- a/lib/mpl_toolkits/tests/test_axes_grid.py +++ b/lib/mpl_toolkits/tests/test_axes_grid.py @@ -1,7 +1,4 @@ -from contextlib import ExitStack - import numpy as np -import pytest import matplotlib as mpl from matplotlib.testing.decorators import image_comparison @@ -12,15 +9,12 @@ # The original version of this test relied on mpl_toolkits's slightly different # colorbar implementation; moving to matplotlib's own colorbar implementation # caused the small image comparison error. -@pytest.mark.parametrize("legacy_colorbar", [False, True]) @image_comparison(['imagegrid_cbar_mode.png'], remove_text=True, style='mpl20', tol=0.3) -def test_imagegrid_cbar_mode_edge(legacy_colorbar): +def test_imagegrid_cbar_mode_edge(): # Remove this line when this test image is regenerated. plt.rcParams['pcolormesh.snap'] = False - mpl.rcParams["mpl_toolkits.legacy_colorbar"] = legacy_colorbar - X, Y = np.meshgrid(np.linspace(0, 6, 30), np.linspace(0, 6, 30)) arr = np.sin(X) * np.cos(Y) + 1j*(np.sin(3*Y) * np.cos(Y/2.)) @@ -45,19 +39,16 @@ def test_imagegrid_cbar_mode_edge(legacy_colorbar): ax3.imshow(np.abs(arr), cmap='jet') ax4.imshow(np.arctan2(arr.imag, arr.real), cmap='hsv') - with (pytest.warns(mpl.MatplotlibDeprecationWarning) if legacy_colorbar - else ExitStack()): - # In each row/column, the "first" colorbars must be overwritten by - # the "second" ones. To achieve this, clear out the axes first. - for ax in grid: - ax.cax.cla() - cb = ax.cax.colorbar( - ax.images[0], - ticks=mpl.ticker.MaxNLocator(5)) # old default locator. + # In each row/column, the "first" colorbars must be overwritten by the + # "second" ones. To achieve this, clear out the axes first. + for ax in grid: + ax.cax.cla() + cb = ax.cax.colorbar( + ax.images[0], + ticks=mpl.ticker.MaxNLocator(5)) # old default locator. def test_imagegrid(): - mpl.rcParams["mpl_toolkits.legacy_colorbar"] = False fig = plt.figure() grid = ImageGrid(fig, 111, nrows_ncols=(1, 1)) ax = grid[0] diff --git a/lib/mpl_toolkits/tests/test_axes_grid1.py b/lib/mpl_toolkits/tests/test_axes_grid1.py index 5121b7e970a6..0e1602e81212 100644 --- a/lib/mpl_toolkits/tests/test_axes_grid1.py +++ b/lib/mpl_toolkits/tests/test_axes_grid1.py @@ -4,7 +4,6 @@ import matplotlib import matplotlib.pyplot as plt from matplotlib import cbook -from matplotlib.cbook import MatplotlibDeprecationWarning from matplotlib.backend_bases import MouseEvent from matplotlib.colors import LogNorm from matplotlib.transforms import Bbox, TransformedBbox @@ -83,10 +82,7 @@ def test_twin_axes_empty_and_removed(): plt.subplots_adjust(wspace=0.5, hspace=1) -@pytest.mark.parametrize("legacy_colorbar", [False, True]) -def test_axesgrid_colorbar_log_smoketest(legacy_colorbar): - matplotlib.rcParams["mpl_toolkits.legacy_colorbar"] = legacy_colorbar - +def test_axesgrid_colorbar_log_smoketest(): fig = plt.figure() grid = AxesGrid(fig, 111, # modified to be only subplot nrows_ncols=(1, 1), @@ -99,11 +95,7 @@ def test_axesgrid_colorbar_log_smoketest(legacy_colorbar): Z = 10000 * np.random.rand(10, 10) im = grid[0].imshow(Z, interpolation="nearest", norm=LogNorm()) - if legacy_colorbar: - with pytest.warns(MatplotlibDeprecationWarning): - grid.cbar_axes[0].colorbar(im) - else: - grid.cbar_axes[0].colorbar(im) + grid.cbar_axes[0].colorbar(im) @image_comparison(['inset_locator.png'], style='default', remove_text=True) diff --git a/matplotlibrc.template b/matplotlibrc.template index 2b45386b07df..79a85d951f78 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -761,5 +761,3 @@ #animation.convert_args: # Additional arguments to pass to convert #animation.embed_limit: 20.0 # Limit, in MB, of size of base64 encoded # animation in HTML (i.e. IPython notebook) - -#mpl_toolkits.legacy_colorbar: True