API Changes for 3.8.0#

Behaviour Changes#

Tk backend respects file format selection when saving figures#

When saving a figure from a Tkinter GUI to a filename without an extension, the file format is now selected based on the value of the dropdown menu, rather than defaulting to PNG. When the filename contains an extension, or the OS automatically appends one, the behavior remains unchanged.

Placing of maximum and minimum minor ticks#

Calculation of minor tick locations has been corrected to make the maximum and minimum minor ticks more consistent. In some cases this results in an extra minor tick on an Axis.

hexbin now defaults to rcParams["patch.linewidth"]#

The default value of the linewidths argument of Axes.hexbin has been changed from 1.0 to rcParams["patch.linewidth"] (default: 1.0). This improves the consistency with QuadMesh in Axes.pcolormesh and Axes.hist2d.

TwoSlopeNorm now auto-expands to always have two slopes#

In the case where either vmin or vmax are not manually specified to TwoSlopeNorm, and where the data it is scaling is all less than or greater than the center point, the limits are now auto-expanded so there are two symmetrically sized slopes either side of the center point.

Previously vmin and vmax were clipped at the center point, which caused issues when displaying color bars.

This does not affect behaviour when vmin and vmax are manually specified by the user.

Event objects emitted for axes_leave_event#

axes_leave_event now emits a synthetic LocationEvent, instead of reusing the last event object associated with a motion_notify_event.

Streamplot now draws streamlines as one piece if no width or no color variance#

Since there is no need to draw streamlines piece by piece if there is no color change or width change, now streamplot will draw each streamline in one piece.

The behavior for varying width or varying color is not changed, same logic is used for these kinds of streamplots.

canvas argument now required for FigureFrameWx#

FigureFrameWx now requires a keyword-only canvas argument when it is constructed.

ContourSet is now a single Collection#

Prior to this release, ContourSet (the object returned by contour) was a custom object holding multiple Collections (and not an Artist) -- one collection per level, each connected component of that level's contour being an entry in the corresponding collection.

ContourSet is now instead a plain Collection (and thus an Artist). The collection contains a single path per contour level; this path may be non-continuous in case there are multiple connected components.

Setting properties on the ContourSet can now usually be done using standard collection setters (cset.set_linewidth(3) to use the same linewidth everywhere or cset.set_linewidth([1, 2, 3, ...]) to set different linewidths on each level) instead of having to go through the individual sub-components (cset.collections[0].set_linewidth(...)). Note that during the transition period, it remains possible to access the (deprecated) .collections attribute; this causes the ContourSet to modify itself to use the old-style multi-Collection representation.

SubFigure default facecolor is now transparent#

Subfigures default facecolor changed to "none". Previously the default was the value of figure.facecolor.

Changes of API after deprecation#

Invalid types for Annotation xycoords now raise TypeError#

Previously, a RuntimeError would be raised in some cases.

Default antialiasing behavior changes for Text and Annotation#

matplotlib.pyplot.annotate() and matplotlib.pyplot.text() now support parameter antialiased when initializing. Examples:

mpl.text.Text(.5, .5, "foo\nbar", antialiased=True)
plt.text(0.5, 0.5, '6 inches x 2 inches', antialiased=True)
ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5), antialiased=False)

See "What's New" for more details on usage.

With this new feature, you may want to make sure that you are creating and saving/showing the figure under the same context:

# previously this was a no-op, now it is what works
with rccontext(text.antialiased=False):
    fig, ax = plt.subplots()
    ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5))

# previously this had an effect, now this is a no-op
fig, ax = plt.subplots()
ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5))
with rccontext(text.antialiased=False):

Also note that antialiasing for tick labels will be set with rcParams["text.antialiased"] (default: True) when they are created (usually when a Figure is created) - This means antialiasing for them can no longer be changed by modifying rcParams["text.antialiased"] (default: True).

ScalarMappable.to_rgba() now respects the mask of RGB(A) arrays#

Previously, the mask was ignored. Now the alpha channel is set to 0 if any component (R, G, B, or A) is masked.

Text.get_rotation_mode return value#

Passing None as rotation_mode to Text (the default value) or passing it to Text.set_rotation_mode will make Text.get_rotation_mode return "default" instead of None. The behaviour otherwise is the same.

PostScript paper type adds option to use figure size#

The rcParams["ps.papertype"] rcParam can now be set to 'figure', which will use a paper size that corresponds exactly with the size of the figure that is being saved.

hexbin mincnt parameter made consistently inclusive#

Previously, mincnt was inclusive with no C provided but exclusive when C is provided. It is now inclusive of mincnt in both cases.


Calling paths.get_path_collection_extents with empty offsets#

Calling get_path_collection_extents with an empty offsets parameter has an ambiguous interpretation and is therefore deprecated. When the deprecation period expires, this will produce an error.

axes_grid1.axes_divider API changes#

The AxesLocator class is deprecated. The new_locator method of divider instances now instead returns an opaque callable (which can still be passed to ax.set_axes_locator).

Divider.locate is deprecated; use Divider.new_locator(...)(ax, renderer) instead.

bbox.anchored() with no explicit container#

Not passing a container argument to BboxBase.anchored is now deprecated.

Functions in mpl_toolkits.mplot3d.proj3d#

The function transform is just an alias for proj_transform, use the latter instead.

The following functions are either unused (so no longer required in Matplotlib) or considered private. If you rely on them, please make a copy of the code, including all functions that starts with a _ (considered private).

  • ortho_transformation

  • persp_transformation

  • proj_points

  • proj_trans_points

  • rot_x

  • rotation_about_vector

  • view_transformation

Arguments other than renderer to get_tightbbox#

... are keyword-only arguments. This is for consistency and that different classes have different additional arguments.

The object returned by pcolor() has changed to a PolyQuadMesh class#

The old object was a PolyCollection with flattened vertices and array data. The new PolyQuadMesh class subclasses PolyCollection, but adds in better 2D coordinate and array handling in alignment with QuadMesh. Previously, if a masked array was input, the list of polygons within the collection would shrink to the size of valid polygons and users were required to keep track of which polygons were drawn and call set_array() with the smaller "compressed" array size. Passing the "compressed" and flattened array values is now deprecated and the full 2D array of values (including the mask) should be passed to PolyQuadMesh.set_array.


... is deprecated with no replacement.

allsegs, allkinds, tcolors and tlinewidths attributes of ContourSet#

These attributes are deprecated; if required, directly retrieve the vertices and codes of the Path objects from ContourSet.get_paths() and the colors and the linewidths via ContourSet.get_facecolor(), ContourSet.get_edgecolor() and ContourSet.get_linewidths().


... is deprecated. ContourSet is now implemented as a single Collection of paths, each path corresponding to a contour level, possibly including multiple unconnected components.

During the deprecation period, accessing ContourSet.collections will revert the current ContourSet instance to the old object layout, with a separate PathCollection per contour level.


These attributes are deprecated.


with no replacement. The Grouper class now cleans itself up automatically.


... is deprecated. Use grid_finder.extreme_finder(*[None] * 5) to get the extremes of the grid.

np_load parameter of cbook.get_sample_data#

This parameter is deprecated; get_sample_data now auto-loads numpy arrays. Use get_sample_data(..., asfileobj=False) instead to get the filename of the data file, which can then be passed to open, if desired.

RendererAgg.tostring_rgb and FigureCanvasAgg.tostring_rgb#

... are deprecated with no direct replacement. Consider using buffer_rgba instead, which should cover most use cases.

The parameter of Annotation.contains and Legend.contains is renamed to mouseevent#

... consistently with Artist.contains.

Accessing event.guiEvent after event handlers return#

... is deprecated: for some GUI toolkits, it is unsafe to do so. In the future, event.guiEvent will be set to None once the event handlers return; you may separately stash the object at your own risk.


The visible attribute getter of Selector widgets has been deprecated; use get_visible

Method parameters renamed to match base classes#

The only parameter of transform_affine and transform_non_affine in Transform subclasses is renamed to values.

The points parameter of transforms.IdentityTransform.transform is renamed to values.

The trans parameter of table.Cell.set_transform is renamed to t consistently with Artist.set_transform.

The clippath parameters of axis.Axis.set_clip_path and axis.Tick.set_clip_path are renamed to path consistently with Artist.set_clip_path.

The s parameter of images.NonUniformImage.set_filternorm is renamed to filternorm consistently with `_ImageBase.set_filternorm.

The s parameter of images.NonUniformImage.set_filterrad is renamed to filterrad consistently with `_ImageBase.set_filterrad.

numdecs parameter and attribute of LogLocator#

... are deprecated without replacement, because they have no effect.

ft2font.FT2Image.draw_rect and ft2font.FT2Font.get_xys#

... are deprecated as they are unused. If you rely on these, please let us know.


The psDefs module-level variable in backend_ps is deprecated with no replacement.

Callable axisartist Axes#

Calling an axisartist Axes to mean axis is deprecated; explicitly call the method instead.

AnchoredEllipse is deprecated#

Instead, directly construct an AnchoredOffsetbox, an AuxTransformBox, and an Ellipse, as demonstrated in Anchored Artists.

Automatic papersize selection in PostScript#

Setting rcParams["ps.papersize"] (default: 'letter') to 'auto' or passing papersize='auto' to Figure.savefig is deprecated. Either pass an explicit paper type name, or omit this parameter to use the default from the rcParam.

Tick.set_label1 and Tick.set_label2#

... are deprecated. Calling these methods from third-party code usually has no effect, as the labels are overwritten at draw time by the tick formatter.

Passing extra positional arguments to Figure.add_axes#

Positional arguments passed to Figure.add_axes other than a rect or an existing Axes are currently ignored, and doing so is now deprecated.


... is deprecated. Instead, use standard methods for manipulating colorbar labels (Colorbar.set_label) and tick labels (Axes.tick_params).


... is considered private and deprecated. The location of the cache directory is clarified in the doc-string.

Artists explicitly passed in will no longer be filtered by legend() based on their label#

Currently, artists explicitly passed to legend(handles=[...]) are filtered out if their label starts with an underscore. This behavior is deprecated; explicitly filter out such artists ([art for art in artists if not art.get_label().startswith('_')]) if necessary.


... is deprecated with no replacement.

cbook.Stack is deprecated#

... with no replacement.

inset_location.InsetPosition is deprecated#

Use inset_axes instead.

axisartist.axes_grid and axisartist.axes_rgb#

These modules, which provide wrappers combining the functionality of axes_grid1 and axisartist, are deprecated; directly use e.g. AxesGrid(..., axes_class=axislines.Axes) instead.


... is deprecated; use get_antialiased or set_antialiased instead. Note that get_antialiased returns an array.

Passing non-int or sequence of non-int to Table.auto_set_column_width#

Column numbers are ints, and formerly passing any other type was effectively ignored. This will become an error in the future.


A zero-page pdf is not valid, thus passing keep_empty=True to backend_pdf.PdfPages and backend_pgf.PdfPages, and the keep_empty attribute of these classes, are deprecated. Currently, these classes default to keeping empty outputs, but that behavior is deprecated too. Explicitly passing keep_empty=False remains supported for now to help transition to the new behavior.

Furthermore, backend_pdf.PdfPages no longer immediately creates the target file upon instantiation, but only when the first figure is saved. To fully control file creation, directly pass an opened file object as argument (with open(path, "wb") as file, PdfPages(file) as pdf: ...).

Auto-closing of figures when switching backend#

... is deprecated. Explicitly call plt.close("all") if necessary. In the future, allowable backend switches (i.e. those that do not swap a GUI event loop with another one) will not close existing figures.

Support for passing the "frac" key in annotate(..., arrowprops={"frac": ...})#

... has been removed. This key has had no effect since Matplotlib 1.5.


cbook removals#

  • matplotlib.cbook.MatplotlibDeprecationWarning and matplotlib.cbook.mplDeprecation are removed; use matplotlib.MatplotlibDeprecationWarning instead.

  • cbook.maxdict; use the standard library functools.lru_cache instead.

Groupers from get_shared_x_axes / get_shared_y_axes are immutable#

Modifications to the Groupers returned by get_shared_x_axes and get_shared_y_axes are no longer allowed. Note that previously, calling e.g. join() would already fail to set up the correct structures for sharing axes; use Axes.sharex or Axes.sharey instead.

Deprecated modules removed#

The following deprecated modules are removed:

  • afm

  • docstring

  • fontconfig_pattern

  • tight_bbox

  • tight_layout

  • type1font

Parameters to plt.figure() and the Figure constructor#

All parameters to pyplot.figure and the Figure constructor, other than num, figsize, and dpi, are now keyword-only.

stem(..., use_line_collection=False)#

... is no longer supported. This was a compatibility fallback to a former more inefficient representation of the stem lines.

Positional / keyword arguments#

Passing all but the very few first arguments positionally in the constructors of Artists is no longer possible. Most arguments are now keyword-only.

The emit and auto parameters of set_xlim, set_ylim, set_zlim, set_rlim are now keyword-only.

The transOffset parameter of Collection.set_offset_transform and the various create_collection methods of legend handlers has been renamed to offset_transform (consistently with the property name).

Axes.get_window_extent / Figure.get_window_extent accept only renderer. This aligns the API with the general Artist.get_window_extent API. All other parameters were ignored anyway.

Methods to set parameters in LogLocator and LogFormatter*#

In LogFormatter and derived subclasses, the methods base and label_minor for setting the respective parameter are removed and replaced by set_base and set_label_minor, respectively.

In LogLocator, the methods base and subs for setting the respective parameter are removed. Instead, use set_params(base=..., subs=...).


The canvas now takes care of the renderer and whether to cache it or not, so the Axes.get_renderer_cache method is removed. The alternative is to call axes.figure.canvas.get_renderer().

Unused methods in Axis, Tick, XAxis, and YAxis#

Tick.label is now removed. Use Tick.label1 instead.

The following methods are no longer used and removed without a replacement:

  • Axis.get_ticklabel_extents

  • Tick.get_pad_pixels

  • XAxis.get_text_heights

  • YAxis.get_text_widths


... is removed. Use numpy.lib.stride_tricks.sliding_window_view instead.


The dist attribute has been privatized. Use the zoom keyword argument in Axes3D.set_box_aspect instead.

The w_xaxis, w_yaxis, and w_zaxis attributes are now removed. Instead use xaxis, yaxis, and zaxis.

3D Axis#

mplot3d.axis3d.Axis.set_pane_pos is removed. This is an internal method where the provided values are overwritten during drawing. Hence, it does not serve any purpose to be directly accessible.

The two helper functions mplot3d.axis3d.move_from_center and mplot3d.axis3d.tick_update_position are considered internal and deprecated. If these are required, please vendor the code from the corresponding private methods _move_from_center and _tick_update_position.

checkdep_usetex removed#

This method was only intended to disable tests in case no latex install was found. As such, it is considered to be private and for internal use only.

Please vendor the code from a previous version if you need this.

date_ticker_factory removed#

The date_ticker_factory method in the matplotlib.dates module is removed. Instead use AutoDateLocator and AutoDateFormatter for a more flexible and scalable locator and formatter.

If you need the exact date_ticker_factory behavior, please copy the code from a previous version.


... is removed in favor of directly calling the Affine2D constructor with no arguments.

Removals in testing.decorators#

The unused class CleanupTestCase and decorator cleanup are removed. The function check_freetype_version is considered internal and removed. Vendor the code from a previous version.


... is removed with no replacement. Copy the previous implementation if needed. Figure.callbacks is removed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Figure callbacks property has been removed. The only signal was "dpi_changed", which can be replaced by connecting to the "resize_event" on the canvas figure.canvas.mpl_connect("resize_event", func) instead.

Passing too many positional arguments to tripcolor#

... raises TypeError (extra arguments were previously ignored).

The filled argument to Colorbar is removed#

This behavior was already governed by the underlying ScalarMappable.


The visible attribute setter of Selector widgets has been removed; use set_visible The associated getter is also deprecated, but not yet expired.

Axes3D.set_frame_on and Axes3D.get_frame_on removed#

Axes3D.set_frame_on is documented as "Set whether the 3D axes panels are drawn.". However, it has no effect on 3D axes and is being removed in favor of Axes3D.set_axis_on and Axes3D.set_axis_off.

Miscellaneous internals#

  • axes_grid1.axes_size.AddList; use sum(sizes, start=Fixed(0)) (for example) to sum multiple size objects.

  • axes_size.Padded; use size + pad instead

  • axes_size.SizeFromFunc, axes_size.GetExtentHelper

  • AxisArtistHelper.delta1 and AxisArtistHelper.delta2

  • axislines.GridHelperBase.new_gridlines and axislines.Axes.new_gridlines

  • _DummyAxis.dataLim and _DummyAxis.viewLim; use get_data_interval(), set_data_interval(), get_view_interval(), and set_view_interval() instead.

  • ImageMagickBase.delay and ImageMagickBase.output_args

  • MathtextBackend, MathtextBackendAgg, MathtextBackendPath, MathTextWarning

  • TexManager.get_font_config; it previously returned an internal hashed key for used for caching purposes.

  • TextToPath.get_texmanager; directly construct a texmanager.TexManager instead.

  • ticker.is_close_to_int; use math.isclose(x, round(x)) instead.

  • ticker.is_decade; use y = numpy.log(x)/numpy.log(base); numpy.isclose(y, numpy.round(y)) instead.

Backend-specific removals#

  • backend_pdf.Name.hexify

  • backend_pdf.Operator and backend_pdf.Op.op are removed in favor of a single standard enum.Enum interface on backend_pdf.Op.

  • backend_pdf.fill; vendor the code of the similarly named private functions if you rely on these functions.

  • backend_pgf.LatexManager.texcommand and backend_pgf.LatexManager.latex_header

  • backend_pgf.NO_ESCAPE

  • backend_pgf.common_texification

  • backend_pgf.get_fontspec

  • backend_pgf.get_preamble

  • backend_pgf.re_mathsep

  • backend_pgf.writeln

  • backend_ps.convert_psfrags

  • backend_ps.quote_ps_string; vendor the code of the similarly named private functions if you rely on it.

  • backend_svg.escape_attrib; vendor the code of the similarly named private functions if you rely on it.

  • backend_svg.escape_cdata; vendor the code of the similarly named private functions if you rely on it.

  • backend_svg.escape_comment; vendor the code of the similarly named private functions if you rely on it.

  • backend_svg.short_float_fmt; vendor the code of the similarly named private functions if you rely on it.

  • backend_svg.generate_transform and backend_svg.generate_css

Removal of deprecated APIs#

The following deprecated APIs have been removed. Unless a replacement is stated, please vendor the previous implementation if needed.

  • The following methods of FigureCanvasBase: pick (use Figure.pick instead), resize, draw_event, resize_event, close_event, key_press_event, key_release_event, pick_event, scroll_event, button_press_event, button_release_event, motion_notify_event, leave_notify_event, enter_notify_event (for all the foo_event methods, construct the relevant Event object and call canvas.callbacks.process(event.name, event) instead).

  • ToolBase.destroy (connect to tool_removed_event instead).

  • The cleared parameter to FigureCanvasAgg.get_renderer (call renderer.clear() instead).

  • The following methods of RendererCairo: set_ctx_from_surface and set_width_height (use set_context instead, which automatically infers the canvas size).

  • The window or win parameters and/or attributes of NavigationToolbar2Tk, NavigationToolbar2GTK3, and NavigationToolbar2GTK4, and the lastrect attribute of NavigationToolbar2Tk

  • The error_msg_gtk function and the icon_filename and window_icon globals in backend_gtk3; the error_msg_wx function in backend_wx.

  • FigureManagerGTK3Agg and FigureManagerGTK4Agg (use FigureManagerGTK3 instead); RendererGTK3Cairo and RendererGTK4Cairo.

  • NavigationToolbar2Mac.prepare_configure_subplots (use configure_subplots instead).

  • FigureManagerMac.close.

  • The qApp global in backend_qt (use QtWidgets.QApplication.instance() instead).

  • The offset_text_height method of RendererWx; the sizer, figmgr, num, toolbar, toolmanager, get_canvas, and get_figure_manager attributes or methods of FigureFrameWx (use frame.GetSizer(), frame.canvas.manager, frame.canvas.manager.num, frame.GetToolBar(), frame.canvas.manager.toolmanager, the canvas_class constructor parameter, and frame.canvas.manager, respectively, instead).

  • FigureFrameWxAgg and FigureFrameWxCairo (use FigureFrameWx(..., canvas_class=FigureCanvasWxAgg) and FigureFrameWx(..., canvas_class=FigureCanvasWxCairo), respectively, instead).

  • The filled attribute and the draw_all method of Colorbar (instead of draw_all, use figure.draw_without_rendering).

  • Calling MarkerStyle without setting the marker parameter or setting it to None (use MarkerStyle("") instead).

  • Support for third-party canvas classes without a required_interactive_framework attribute (this can only occur if the canvas class does not inherit from FigureCanvasBase).

  • The canvas and background attributes of MultiCursor; the state_modifier_keys attribute of selector widgets.

  • Passing useblit, horizOn, or vertOn positionally to MultiCursor.

  • Support for the seaborn-<foo> styles; use seaborn-v0_8-<foo> instead, or directly use the seaborn API.

Development changes#

Increase to minimum supported versions of dependencies#

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


min in mpl3.7

min in mpl3.8













This is consistent with our Dependency version policy and NEP29

Increase to minimum supported optional dependencies#

For Matplotlib 3.8, the minimum supported versions of optional dependencies are being bumped:


min in mpl3.7

min in mpl3.8







  • There are no wheels or conda packages that support both Qt 5.11 (or older) and Python 3.9 (or newer).

This is consistent with our Dependency version policy

Provisional support for PEP484 Type Hint Annotations#

New public API should be type hinted in .pyi stub files (except pyplot and tests which are typed in-line). Tests should be type hinted minimally, essentially only when mypy generates errors.

CI and configuration for running mypy have been added.

Generation of pyplot.py requires black#

The autogenerated portions of pyplot.py use black autoformatting to ensure syntax-correct, readable output code.

As such black is now a development and test requirement (for the test which regenerates pyplot).

Wheels for some systems are no longer distributed#

Pre-compiled wheels for 32-bit Linux and Windows are no longer provided on PyPI since Matplotlib 3.8.

Multi-architecture universal2 wheels for macOS are no longer provided on PyPI since Matplotlib 3.8. In general, pip will always prefer the architecture-specific (amd64- or arm64-only) wheels, so these provided little benefit.

New wheel architectures#

Wheels have been added for:

  • musl based systems