API Changes for 3.11.0#

Behavior Changes#

pyplot.subplot and pyplot.subplot_mosaic raise ValueError on existing figures#

Passing a num argument to subplots or subplot_mosaic that refers to an existing figure or is a Figure instance now raises a ValueError.

These utility functions are intended strictly for the creation of new figures and subplots. Previously, they accidentally allowed the reuse of existing figures because they internally called figure. This change ensures that these functions strictly follow their documented purpose of creating new figures.

To reuse an existing figure, clear it first using clear=True:

fig, axs = plt.subplots(num=1, clear=True)
# or
fig, axd = plt.subplot_mosaic([['A', 'B']], num=1, clear=True)

If you have a Figure instance and want to add subplots to it, use the object-oriented API:

fig.subplots(nrows=2, ncols=2)
# or
fig.subplot_mosaic([['A', 'B']])

Complex layouts and constrained layout#

Constrained layout now produces smaller spacing between subplots in some circumstances. This should only affect complex layouts where rows or columns contain different numbers of subplots, for example a layout created with plt.subplot_mosaic('AC;BC', layout='constrained').

Bivariate colormaps now fully span the intended range of colors#

Bivariate colormaps generated by SegmentedBivarColormap (e.g., BiOrangeBlue) from a set of input colors now fully span that range of colors. There had been a bug with the numerical interpolation such that the colormap did not actually include the first or last colors.

Rendering of images now more accurate#

There have been several fixes to improve the accuracy of how images are resampled and placed during rendering. Some inaccuracies were up to a pixel off in the output. The most apparent improvement is that the alignment of data pixels with tick marks and grid lines is now reliable. Nearly all image output has changed, but often only at a subtle level that is not obvious qualitatively.

alpha parameter handling on images#

Prior to Matplotlib 3.10.1, when passing an array to imshow(..., alpha=...), the parameter was silently ignored if the image data was an RGB or RGBA image or if rcParams["image.interpolation_stage"] (default: 'auto') resolved to "rbga".

Matplotlib 3.10.1 changed this to apply the alpha array as the alpha channel, overwriting any existing transparency information in the image data. Matplotlib 3.11.0 further fixes the handling for RGBA images: the existing alpha channel is now multiplied by the alpha array, consistent with how scalar alpha values are handled.

Legend labels for plot#

Previously if a sequence was passed to the label parameter of plot when plotting a single dataset, the sequence was automatically cast to string for the legend label. Now, if the sequence length is not one an error is raised. To keep the old behavior, cast the sequence to string before passing.

Mixing positional and keyword arguments for legend handles and labels...#

... is no longer valid. If passing handles and labels to legend, they must now be passed either both positionally or both as keyword arguments.

Axes.add_collection(..., autolim=True) updates view limits#

Axes.add_collection(..., autolim=True) has so far only updated the data limits, and calling Axes.autoscale_view was also necessary to update the view limits. View limits are now updated as well if autolim=True, using a lazy internal update mechanism, so that the costs only apply once also if you add multiple collections.

relim() now accounts for Collection artists#

Previously, relim did not recalculate data limits for Collection artists (e.g. those created by scatter). Calling ax.relim() followed by ax.autoscale_view() now correctly includes scatter plots and other collections in the axes limits.

hist2d no longer forces axes limits#

Previously, Axes.hist2d would force the axes x and y limits to the extents of the histogrammed data, ignoring any other artists. Axes.hist2d now behaves similarly to Axes.imshow: axes limits are updated to fit the data, but autoscaling is not otherwise disabled.

Axes.violinplot and cbook.violin_stats ignore non-finite values#

violinplot and matplotlib.cbook.violin_stats now ignore masked and non-finite (NaN and inf) values.

Minor log tick labels are set by number of major log ticks, not number of decades spanned#

Previously, by default, on a log-scaled axis, the minor ticks would be unlabeled if the axis limits spanned more than one decade. The meaning of the minor_thresholds parameter to LogFormatter has been altered so that the decision of whether to label the minor ticks is now based on the number of major ticks drawn within the axis limits.

For example, for an axis spanning from 4 to 60 (with thus a single major log tick, at 10), minor ticks are now labeled, even though the axis spans more than one decade.

Setting titles of figures using webagg backend#

Previously when using the webagg backend the title of a figure was set using figure.set_label. Now it is set using figure.canvas.manager.set_window_title which is more consistent with other backends.

Default name of ListedColormap#

The default name of ListedColormap has changed from "from_list" to "unnamed".

font_manager.findfont logs if selected font weight does not match requested#

When searching for a font with a weight specified, if the best-matched font differs in weight, then a warning will be logged.

FT2Font no longer sets a default size#

In the interest of handling non-scalable fonts and reducing font initialization, the FT2Font constructor no longer sets a default size. Non-scalable fonts are sometimes used for bitmap-backed emoji fonts.

If metrics are important (i.e., if you are loading character glyphs, or setting a text string), then explicitly call FT2Font.set_size beforehand.

mathtext.VectorParse now includes glyph indices#

For a path-outputting MathTextParser, in the return value of parse, (a VectorParse), the glyphs field is now a list containing tuples of:

Specifically, the glyph index was added after the character code.

matplotlib.testing.check_figures_equal defaults to PNG only#

In most cases, checking that figures are equal with check_figures_equal does not depend on the file format. Consequently, the extensions parameter now defaults to ['png'] instead of ['png', 'pdf', 'svg'], reducing default test requirements.

Default style parameter of image_comparison#

The style parameter of the image_comparison decorator will become 'mpl20' in Matplotlib 3.13. Not passing it and relying on the previous default will warn until the change occurs.

Windows configuration directory location#

On Windows, the default configuration and cache directories now use %LOCALAPPDATA%\matplotlib instead of %USERPROFILE%\.matplotlib. This follows Windows application data storage conventions.

The MPLCONFIGDIR environment variable can still be used to override this default.

Deprecations#

In-place modification of colormaps#

Colormaps are planned to become immutable in the long term.

As a first step, in-place modifications of colormaps are now pending-deprecated. This affects the following methods of Colormap:

Use the respective Colormap.with_extremes and appropriate keyword arguments instead which returns a copy of the colormap (available since Matplotlib 3.4). Alternatively, if you create the colormap yourself, you can also pass the respective arguments to the constructor (available since Matplotlib 3.11).

Contour labelling on filled contours#

Using clabel to label filled contours created with contourf is deprecated. clabel() is designed to label contour lines (Axes.contour), and using it with filled contours can lead to inconsistent plots. If you want to add labels to filled contours, the recommended approach is to first create the filled contours with contourf, then overlay contour lines using contour, and finally apply clabel to those contour lines for labeling. For an example see Contourf demo.

boxplot and bxp vert parameter, and rcParams["boxplot.vertical"]#

The parameter vert: bool has been deprecated on boxplot and bxp. It is replaced by orientation: {"vertical", "horizontal"} for API consistency.

rcParams["boxplot.vertical"], which controlled the orientation of boxplot, is deprecated without replacement.

violinplot and violin vert parameter#

The parameter vert: bool has been deprecated on violinplot and violin. It will be replaced by orientation: {"vertical", "horizontal"} for API consistency.

Arbitrary code in axes.prop_cycle rcParam strings#

The axes.prop_cycle rcParam accepts Python expressions that are evaluated in a limited context. The evaluation context has been further limited and some expressions that previously worked (list comprehensions, for example) no longer will. This change is made without a deprecation period to improve security. The previously documented cycler operations at https://matplotlib.org/cycler/ are still supported.

Capitalization of None in matplotlibrc#

In matplotlibrc config files every capitalization of None was accepted for denoting the Python constant None. This is now deprecated, and the only accepted capitalization is None, i.e., starting with a capital letter and all other letters in lowercase.

Third-party scales no longer need to have an axis parameter#

Since Matplotlib 3.1 PR 12831 scale objects should be reusable and therefore independent of any particular Axis. Therefore, the use of the axis parameter in the __init__ had been discouraged. However, having that parameter in the signature was still necessary for API backwards-compatibility. This is no longer the case.

register_scale now accepts scale classes with or without this parameter.

The axis parameter is pending-deprecated. It will be deprecated in Matplotlib 3.13, and removed in Matplotlib 3.15.

Third-party scales are recommended to remove the axis parameter now if they can afford to restrict compatibility to Matplotlib >= 3.11 already. Otherwise, they may keep the axis parameter and remove it in time for Matplotlib 3.13.

matplotlib.style.core#

The matplotlib.style.core module is deprecated. All APIs intended for public use are now available in matplotlib.style directly (including USER_LIBRARY_PATHS, which was previously not reexported).

The following APIs of matplotlib.style.core have been deprecated with no replacement: BASE_LIBRARY_PATH, STYLE_EXTENSION, STYLE_BLACKLIST, update_user_library, read_style_directory, update_nested_dict.

Font hinting and kerning factors#

Due to internal changes to support complex text rendering, the hinting factor and kerning factor on fonts are no longer used. Setting the text.hinting_factor or text.kerning_factor rcParams (the latter of which existed only for backwards-compatibility) to any value other than None is deprecated, and they will be removed in the future.

Likewise, passing the hinting_factor argument to the FT2Font constructor is deprecated.

FT2Image image buffer#

Use 2D uint8 ndarrays instead. In particular:

  • The FT2Image constructor took width, height as separate parameters but the ndarray constructor takes (height, width) as single tuple parameter.

  • FT2Font.draw_glyph_to_bitmap now (also) takes 2D uint8 arrays as input.

  • FT2Image.draw_rect_filled should be replaced by directly setting pixel values to black.

  • The image attribute of the object returned by MathTextParser("agg").parse is now a 2D uint8 array.

DviFont.widths#

... is deprecated with no replacement.

PdfFile internals#

The PdfFile.dviFontInfo, PdfFile.fontNames, PdfFile.multi_byte_charprocs, and PdfFile.type1Descriptors attributes are deprecated with no replacement.

The fontfile parameter of PdfFile.createType1Descriptor is deprecated; all relevant pieces of information are now directly extracted from the t1font argument.

Tfm's internal metrics#

Direct access to Tfm's widths, heights, depths dicts is deprecated; access a glyph's metrics with Tfm.get_metrics instead.

font_manager.is_opentype_cff_font is deprecated#

There is no replacement.

Axes.set_navigate_mode is deprecated#

... with no replacement.

Parameters Axes3D.set_aspect(..., anchor=..., share=...)#

The parameters anchor and share of Axes3D.set_aspect are deprecated. They had no effect on 3D axes and will be removed in a future version.

BezierSegment.point_at_t#

... is deprecated. Instead, it is possible to call the BezierSegment with an argument.

Formatter attributes#

These following attributes are considered internal and users should not have a need to access them:

Parameter ListedColormap(..., N=...)#

Passing the parameter N to ListedColormap is deprecated. Please preprocess the list colors yourself if needed.

kw, fontproperties, labelcolor, and verts attributes of QuiverKey#

These attributes are deprecated (note that modifying fontproperties, labelcolor, or verts after the first draw had no effect previously). Directly access the relevant attributes on the sub-artists QuiverKey.vector and QuiverKey.text, instead.

apply_theta_transforms option in PolarTransform#

Applying theta transforms in PolarTransform and InvertedPolarTransform has been removed, and the apply_theta_transforms keyword argument is deprecated for both classes.

If you need to retain the behaviour where theta values are transformed, chain the PolarTransform with a Affine2D transform that performs the theta shift and/or sign shift.

axes parameter of RadialLocator#

... is deprecated. RadialLocator now fetches the relevant information from the Axis' parent Axes.

Transform helper functions#

The following functions in the transforms module are deprecated, because they are considerer internal functionality and should not be used by end users:

  • matplotlib.transforms.nonsingular

  • matplotlib.transforms.interval_contains

  • matplotlib.transforms.interval_contains_open

InvertedSymmetricalLogTransform.invlinthresh#

The invlinthresh attribute of InvertedSymmetricalLogTransform is deprecated. Use the .inverted().transform(linthresh) method instead.

axisartist now uses more standard tick direction controls#

Previously, the position of axisartist ticks (inside or outside the axes) were set using set_tick_out(bool). They are now set using set_tick_direction("in") (or "out", or "inout"), and respect rcParams["xtick.direction"] (default: 'out') and rcParams["ytick.direction"] (default: 'out'). In particular, they default to pointing outwards, consistently with the rest of the library.

The tick_out parameter of Ticks has been deprecated (use tick_direction instead). The Ticks.get_tick_out method is deprecated (use Ticks.get_tick_direction instead).

The unused locs_angles_labels attribute of Ticks and LabelBase has also been deprecated.

GridFinder.get_grid_info now takes a single bbox as parameter#

Passing x1, y1, x2, y2 as separate parameters is deprecated.

GridFinder.transform_xy and GridFinder.inv_transform_xy#

... are deprecated. Directly use the standard transform returned by GridFinder.get_transform instead.

axes_grid.Grid.ngrids#

This attribute has been deprecated and renamed n_axes, consistently with the new name of the Grid constructor parameter that allows setting the actual number of axes in the grid (the old parameter, ngrids, did not actually work since Matplotlib 3.3).

The same change has been made in axes_grid.ImageGrid.

canvas parameter to MultiCursor#

... is deprecated. It has been unused for a while already.

Please remove the parameter and change the call from MultiCursor(canvas, axes) to MultiCursor(axes). Both calls are valid throughout the deprecation period.

CallbackRegistry.disconnect cid parameter renamed to cid_or_func#

The cid parameter of CallbackRegistry.disconnect has been renamed to cid_or_func. The method now also accepts a callable, which will disconnect that callback from all signals or from a specific signal if the signal keyword argument is provided.

cbook.normalize_kwargs only supports passing artists and artist classes as second argument#

Support for directly passing an alias mapping or None as second argument to cbook.normalize_kwargs has been deprecated.

backend_svg.XMLWriter is deprecated#

It is an internal helper not intended for external use.

image.thumbnail#

... is deprecated without replacement. Use Pillow's thumbnail method instead. See also the Pillow tutorial.

testing.widgets.mock_event and testing.widgets.do_event#

... are deprecated. Directly construct Event objects (typically MouseEvent or KeyEvent) and pass them to canvas.callbacks.process() instead.

Removals#

matplotlib.cm.get_cmap#

Colormaps are now available through the ColormapRegistry accessible via matplotlib.colormaps or matplotlib.pyplot.colormaps.

If you have the name of a colormap as a string, you can use a direct lookup, matplotlib.colormaps[name] or matplotlib.pyplot.colormaps[name]. Alternatively, matplotlib.colormaps.get_cmap will maintain the existing behavior of additionally passing through Colormap instances and converting None to the default colormap. matplotlib.pyplot.get_cmap will stay as a shortcut to matplotlib.colormaps.get_cmap.

boxplot tick labels#

The parameter labels has been removed in favour of tick_labels for clarity and consistency with bar.

plot_date#

Use of plot_date has been discouraged since Matplotlib 3.5 and deprecated since 3.9. The plot_date function has now been removed.

  • datetime-like data should directly be plotted using plot.

  • If you need to plot plain numeric data as Matplotlib date format or need to set a timezone, call ax.xaxis.axis_date / ax.yaxis.axis_date before plot. See Axis.axis_date.

GridHelperCurveLinear.get_tick_iterator#

... is removed with no replacement.

nth_coord parameter to axisartist helpers for fixed axis#

Helper APIs in axisartist for generating a "fixed" axis on rectilinear axes (FixedAxisArtistHelperRectilinear) no longer take a nth_coord parameter. That parameter is entirely inferred from the (required) loc parameter.

For curvilinear axes, the nth_coord parameter remains supported (it affects the ticks, not the axis position itself), but it is now keyword-only.

rcsetup.interactive_bk, rcsetup.non_interactive_bk and rcsetup.all_backends#

... are removed and replaced by matplotlib.backends.backend_registry.list_builtin with the following arguments

  • matplotlib.backends.BackendFilter.INTERACTIVE

  • matplotlib.backends.BackendFilter.NON_INTERACTIVE

  • None

interval parameter of TimerBase.start#

The timer interval parameter can no longer be set while starting it. The interval can be specified instead in the timer constructor, or by setting the timer.interval attribute.

TransformNode.is_bbox#

... is removed. Instead check the object using isinstance(..., BboxBase).

BboxTransformToMaxOnly#

... is removed. It can be replaced by BboxTransformTo(LockableBbox(bbox, x0=0, y0=0)).

Image path semantics of toolmanager-based tools#

Previously, MEP22 ("toolmanager-based") Tools would try to load their icon (tool.image) relative to the current working directory, or, as a fallback, from Matplotlib's own image directory. Because both approaches are problematic for third-party tools (the end-user may change the current working directory at any time, and third-parties cannot add new icons in Matplotlib's image directory), this behavior has been removed; instead, tool.image is now interpreted relative to the directory containing the source file where the Tool.image class attribute is defined. (Defining tool.image as an absolute path also works and is compatible with both the old and the new semantics.)

Development changes#

Increase to minimum supported versions of dependencies#

For Matplotlib 3.11, the minimum supported versions are being bumped:

Dependency

min in mpl3.10

min in mpl3.11

Python

3.10

3.11

NumPy

1.23

1.25

pyparsing

2.3.1

3.0.0

This is consistent with our Dependency version policy and SPEC0

pip 25.1 suggested for development#

Dependencies for development (build and testing) are now specified as Dependency Groups instead of individual requirements files.

Consequently, a version of pip that supports Dependency Groups is suggested, namely version 25.1 or higher. Note that if you install build/testing dependencies manually (by copying the list from pyproject.toml), then an older version of pip is sufficient.

Glyph indices now typed distinctly from character codes#

Previously, character codes and glyph indices were both typed as int, which means you could mix and match them erroneously. While the character code can't be made a distinct type (because it's used for chr/ord), typing glyph indices as a distinct type means these can't be fully swapped.