API Changes

If updating Matplotlib breaks your scripts, this list may help you figure out what caused the breakage and how to fix it by updating your code.

For API changes in older versions see

Changes for the latest version are listed below. For new features that were added to Matplotlib, see What's new?

API Changes for 3.4.0

Behaviour changes

Constrained layout rewrite

The layout manager constrained_layout was re-written with different outer constraints that should be more robust to complicated subplot layouts. User-facing changes are:

  • some poorly constrained layouts will have different width/height plots than before.
  • colorbars now respect the anchor keyword argument of matplotlib.colorbar.make_axes
  • colorbars are wider.
  • colorbars in different rows or columns line up more robustly.
  • hspace and wspace options to Figure.set_constrained_layout_pads were twice as wide as the docs said they should be. So these now follow the docs.

This feature will remain "experimental" until the new changes have been used enough by users, so we anticipate version 3.5 or 3.6. On the other hand, constrained_layout is extensively tested and used in examples in the library, so using it should be safe, but layouts may not be exactly the same as more development takes place.

Details of using constrained_layout, and its algorithm are available at Constrained Layout Guide

plt.subplot re-selection without keyword arguments

The purpose of pyplot.subplot is to facilitate creating and re-selecting Axes in a Figure when working strictly in the implicit pyplot API. When creating new Axes it is possible to select the projection (e.g. polar, 3D, or various cartographic projections) as well as to pass additional keyword arguments through to the Axes-subclass that is created.

The first time pyplot.subplot is called for a given position in the Axes grid it always creates and returns a new Axes with the passed arguments and projection (defaulting to rectilinear). On subsequent calls to pyplot.subplot we have to determine if an existing Axes has a) equivalent parameters, in which case it should be selected as the current Axes and returned, or b) different parameters, in which case a new Axes is created and the existing Axes is removed. This leaves the question of what is "equivalent parameters".

Previously it was the case that an existing Axes subclass, except for Axes3D, would be considered equivalent to a 2D rectilinear Axes, despite having different projections, if the keyword arguments (other than projection) matched. Thus:

ax1 = plt.subplot(1, 1, 1, projection='polar')
ax2 =  plt.subplots(1, 1, 1)
ax1 is ax2

We are embracing this long standing behavior to ensure that in the case when no keyword arguments (of any sort) are passed to pyplot.subplot any existing Axes is returned, without consideration for keywords or projection used to initially create it. This will cause a change in behavior when additional keywords were passed to the original Axes:

ax1 = plt.subplot(111, projection='polar', theta_offset=.75)
ax2 = plt.subplots(1, 1, 1)
ax1 is ax2         # new behavior
# ax1 is not ax2   # old behavior, made a new axes

ax1 = plt.subplot(111, label='test')
ax2 = plt.subplots(1, 1, 1)
ax1 is ax2         # new behavior
# ax1 is not ax2   # old behavior, made a new axes

For the same reason, if there was an existing Axes that was not rectilinear, passing projection='rectilinear' would reuse the existing Axes

ax1 = plt.subplot(projection='polar')
ax2 = plt.subplot(projection='rectilinear')
ax1 is not ax2     # new behavior, makes new Axes
# ax1 is ax2       # old behavior

contrary to the user's request.

Previously Axes3D could not be re-selected with pyplot.subplot due to an unrelated bug (also fixed in Matplotlib 3.4). While Axes3D are now consistent with all other projections there is a change in behavior for

plt.subplot(projection='3d')  # create a 3D Axes

plt.subplot()                 # now returns existing 3D Axes, but
                              # previously created new 2D Axes

plt.subplot(projection='rectilinear')  # to get a new 2D Axes

ioff and ion can be used as context managers

pyplot.ion and pyplot.ioff may now be used as context managers to create a context with interactive mode on or off, respectively. The old behavior of calling these functions is maintained. To use the new functionality call as:

with plt.ioff():
   # non-interactive code

Locators and formatters must be in the class hierarchy

Axis locators and formatters must now be subclasses of Locator and Formatter respectively.

Date locator for DAILY interval now returns middle of month

The matplotlib.dates.AutoDateLocator has a default of interval_multiples=True that attempts to align ticks with the start of meaningful intervals like the start of the month, or start of the day, etc. That lead to approximately 140-day intervals being mapped to the first and 22nd of the month. This has now been changed so that it chooses the first and 15th of the month, which is probably what most people want.

ScalarFormatter useLocale option obeys grouping

When the ScalarFormatter option useLocale is enabled (or rcParams["axes.formatter.use_locale"] (default: False) is True) and the configured locale uses grouping, a separator will be added as described in locale.format_string.

Axes.errorbar cycles non-color properties correctly

Formerly, Axes.errorbar incorrectly skipped the Axes property cycle if a color was explicitly specified, even if the property cycler was for other properties (such as line style). Now, Axes.errorbar will advance the Axes property cycle as done for Axes.plot, i.e., as long as all properties in the cycler are not explicitly passed.

pyplot.specgram always uses origin='upper'

Previously if rcParams["image.origin"] (default: 'upper') was set to something other than 'upper' or if the origin keyword argument was passed with a value other than 'upper', the spectrogram itself would flip, but the Axes would remain oriented for an origin value of 'upper', so that the resulting plot was incorrectly labelled.

Now, the origin keyword argument is not supported and the image.origin rcParam is ignored. The function matplotlib.pyplot.specgram is forced to use origin='upper', so that the Axes are correct for the plotted spectrogram.

xunits=None and yunits=None passed as keyword arguments are treated as "no action"

Many (but not all) of the methods on Axes take the (undocumented) keyword arguments xunits and yunits that will update the units on the given Axis by calling Axis.set_units and Axis.update_units.

Previously if None was passed it would clear the value stored in .Axis.units which will in turn break converters which rely on the value in .Axis.units to work properly (notably StrCategoryConverter).

This changes the semantics of ax.meth(..., xunits=None, yunits=None) from "please clear the units" to "do the default thing as if they had not been passed" which is consistent with the standard behavior of Matplotlib keyword arguments.

If you were relying on passing xunits=None to plotting methods to clear the .Axes.units attribute, directly call Axis.set_units (and Axis.update_units if you also require the converter to be updated).

Annotations with annotation_clip no longer affect tight_layout

Previously, text.Annotation.get_tightbbox always returned the full text.Annotation.get_window_extent of the object, independent of the value of annotation_clip. text.Annotation.get_tightbbox now correctly takes this extra clipping box into account, meaning that Annotations that are not drawn because of annotation_clip will not count towards the Axes bounding box calculations, such as those done by tight_layout.

This is now consistent with the API described in Artist, which specifies that get_window_extent should return the full extents and get_tightbbox should "account for any clipping".

Parasite Axes pcolor and pcolormesh now defaults to placing grid edges at integers, not half-integers

This is consistent with pcolor and pcolormesh.

Colorbar outline is now a Spine

The outline of Colorbar is now a Spine and drawn as one, instead of a Polygon drawn as an artist. This ensures it will always be drawn after (i.e., on top of) all artists, consistent with Spines on normal Axes.

Colorbar.dividers changes

This attribute is now always a LineCollection -- an empty one if drawedges is False. Its default colors and linewidth (rcParams["axes.edgecolor"] (default: 'black'), rcParams["axes.linewidth"] (default: 0.8)) are now resolved at instantiation time, not at draw time.

Raise or warn on registering a colormap twice

When using matplotlib.cm.register_cmap to register a user provided or third-party colormap it will now raise a ValueError if trying to over-write one of the built in colormaps and warn if trying to over write a user registered colormap. This may raise for user-registered colormaps in the future.

Consecutive rasterized draws now merged

Tracking of depth of raster draws has moved from backend_mixed.MixedModeRenderer.start_rasterizing and backend_mixed.MixedModeRenderer.stop_rasterizing into artist.allow_rasterization. This means the start and stop functions are only called when the rasterization actually needs to be started and stopped.

The output of vector backends will change in the case that rasterized elements are merged. This should not change the appearance of outputs.

The renders in 3rd party backends are now expected to have self._raster_depth and self._rasterizing initialized to 0 and False respectively.

Consistent behavior of draw_if_interactive() across backends

pyplot.draw_if_interactive no longer shows the window (if it was previously unshown) on the Tk and nbAgg backends, consistently with all other backends.

The Artist property rasterized cannot be None anymore

It is now a boolean only. Before the default was None and Artist.set_rasterized was documented to accept None. However, None did not have a special meaning and was treated as False.

Canvas's callback registry now stored on Figure

The canonical location of the CallbackRegistry used to handle Figure/Canvas events has been moved from the Canvas to the Figure. This change should be transparent to almost all users, however if you are swapping switching the Figure out from on top of a Canvas or visa versa you may see a change in behavior.

Harmonized key event data across backends

The different backends with key translation support, now handle "Shift" as a sometimes modifier, where the 'shift+' prefix won't be added if a key translation was made.

In the Qt5 backend, the matplotlib.backends.backend_qt5.SPECIAL_KEYS dictionary contains keys that do not return their unicode name instead they have manually specified names. The name for QtCore.Qt.Key_Meta has changed to 'meta' to be consistent with the other GUI backends.

The WebAgg backend now handles key translations correctly on non-US keyboard layouts.

In the GTK and Tk backends, the handling of non-ASCII keypresses (as reported in the KeyEvent passed to key_press_event-handlers) now correctly reports Unicode characters (e.g., €), and better respects NumLock on the numpad.

In the GTK and Tk backends, the following key names have changed; the new names are consistent with those reported by the Qt backends:

  • The "Break/Pause" key (keysym 0xff13) is now reported as "pause" instead of "break" (this is also consistent with the X key name).
  • The numpad "delete" key is now reported as "delete" instead of "dec".

WebAgg backend no longer reports a middle click as a right click

Previously when using the WebAgg backend the event passed to a callback by fig.canvas.mpl_connect('mouse_button_event', callback) on a middle click would report MouseButton.RIGHT instead of MouseButton.MIDDLE.

ID attribute of XML tags in SVG files now based on SHA256 rather than MD5

Matplotlib generates unique ID attributes for various tags in SVG files. Matplotlib previously generated these unique IDs using the first 10 characters of an MD5 hash. The MD5 hashing algorithm is not available in Python on systems with Federal Information Processing Standards (FIPS) enabled. Matplotlib now uses the first 10 characters of an SHA256 hash instead. SVG files that would otherwise match those saved with earlier versions of matplotlib, will have different ID attributes.

RendererPS.set_font is no longer a no-op in AFM mode

RendererPS.set_font now sets the current PostScript font in all cases.

Autoscaling in Axes3D

In Matplotlib 3.2.0, autoscaling was made lazier for 2D Axes, i.e., limits would only be recomputed when actually rendering the canvas, or when the user queries the Axes limits. This performance improvement is now extended to Axes3D. This also fixes some issues with autoscaling being triggered unexpectedly in Axes3D.

Please see the API change for 2D Axes for further details.

Axes3D automatically adding itself to Figure is deprecated

New Axes3D objects previously added themselves to figures when they were created, unlike all other Axes classes, which lead to them being added twice if fig.add_subplot(111, projection='3d') was called.

This behavior is now deprecated and will warn. The new keyword argument auto_add_to_figure controls the behavior and can be used to suppress the warning. The default value will change to False in Matplotlib 3.5, and any non-False value will be an error in Matplotlib 3.6.

In the future, Axes3D will need to be explicitly added to the figure

fig = Figure()
# create Axes3D
ax = Axes3d(fig)
# add to Figure

as needs to be done for other axes.Axes sub-classes. Or, a 3D projection can be made via:


mplot3d.art3d.get_dir_vector always returns NumPy arrays

For consistency, get_dir_vector now always returns NumPy arrays, even if the input is a 3-element iterable.

Changed cursive and fantasy font definitions

The Comic Sans and Comic Neue fonts were moved from the default rcParams["font.fantasy"] (default: ['Chicago', 'Charcoal', 'Impact', 'Western', 'Humor Sans', 'xkcd', 'fantasy']) list to the default rcParams["font.cursive"] (default: ['Apple Chancery', 'Textile', 'Zapf Chancery', 'Sand', 'Script MT', 'Felipa', 'Comic Neue', 'Comic Sans MS', 'cursive']) setting, in accordance with the CSS font families example and in order to provide a cursive font present in Microsoft's Core Fonts set.

docstring.Substitution now always dedents docstrings before string interpolation


Extra parameters to Axes constructor

Parameters of the Axes constructor other than fig and rect will become keyword-only in a future version.

pyplot.gca and Figure.gca keyword arguments

Passing keyword arguments to pyplot.gca or figure.Figure.gca will not be supported in a future release.

Axis.cla, RadialAxis.cla, ThetaAxis.cla and Spine.cla

These methods are deprecated in favor of the respective clear() methods.

Invalid hatch pattern characters are no longer ignored

When specifying hatching patterns, characters that are not recognized will raise a deprecation warning. In the future, this will become a hard error.

imread reading from URLs

Passing a URL to imread() is deprecated. Please open the URL for reading and directly use the Pillow API (PIL.Image.open(urllib.request.urlopen(url)), or PIL.Image.open(io.BytesIO(requests.get(url).content))) instead.

is_url and URL_REGEX

... are deprecated. (They were previously defined in the toplevel matplotlib module.)

matplotlib.style.core deprecations

STYLE_FILE_PATTERN, load_base_library, and iter_user_libraries are deprecated.

Tick.apply_tickdir is deprecated

apply_tickdir didn't actually update the tick markers on the existing Line2D objects used to draw the ticks; use Axis.set_tick_params instead.

dpi_cor property of FancyArrowPatch

This parameter is considered internal and deprecated.

Passing boxstyle="custom", bbox_transmuter=... to FancyBboxPatch

In order to use a custom boxstyle, directly pass it as the boxstyle argument to FancyBboxPatch. This was previously already possible, and is consistent with custom arrow styles and connection styles.

BoxStyles are now called without passing the mutation_aspect parameter

Mutation aspect is now handled by the artist itself. Hence the mutation_aspect parameter of BoxStyle._Base.__call__ is deprecated, and custom boxstyles should be implemented to not require this parameter (it can be left as a parameter defaulting to 1 for back-compatibility).

ContourLabeler.get_label_coords is deprecated

It is considered an internal helper.

Line2D and Patch no longer duplicate validJoin and validCap

Validation of joinstyle and capstyles is now centralized in rcsetup.

Setting a Line2D's pickradius via set_picker is undeprecated

This cancels the deprecation introduced in Matplotlib 3.3.0.

MarkerStyle is considered immutable

MarkerStyle.set_fillstyle() and MarkerStyle.set_marker() are deprecated. Create a new MarkerStyle with the respective parameters instead.

MovieWriter.cleanup is deprecated

Cleanup logic is now fully implemented in MovieWriter.finish. Third-party movie writers should likewise move the relevant cleanup logic there, as overridden cleanups will no longer be called in the future.

minimumdescent parameter/property of TextArea

offsetbox.TextArea has behaved as if minimumdescent was always True (regardless of the value to which it was set) since Matplotlib 1.3, so the parameter/property is deprecated.

colorbar now warns when the mappable's Axes is different from the current Axes

Currently, Figure.colorbar and pyplot.colorbar steal space by default from the current Axes to place the colorbar. In a future version, they will steal space from the mappable's Axes instead. In preparation for this change, Figure.colorbar and pyplot.colorbar now emits a warning when the current Axes is not the same as the mappable's Axes.

Colorbar docstrings

The following globals in matplotlib.colorbar are deprecated: colorbar_doc, colormap_kw_doc, make_axes_kw_doc.

ColorbarPatch and colorbar_factory are deprecated

All the relevant functionality has been moved to the Colorbar class.

Backend deprecations

  • FigureCanvasBase.get_window_title and FigureCanvasBase.set_window_title are deprecated. Use the corresponding methods on the FigureManager if using pyplot, or GUI-specific methods if embedding.
  • The resize_callback parameter to FigureCanvasTk was never used internally and is deprecated. Tk-level custom event handlers for resize events can be added to a FigureCanvasTk using e.g. get_tk_widget().bind('<Configure>', ..., True).
  • The key_press and button_press methods of FigureManagerBase, which incorrectly did nothing when using toolmanager, are deprecated in favor of directly passing the event to the CallbackRegistry via self.canvas.callbacks.process(event.name, event).
  • RendererAgg.get_content_extents and RendererAgg.tostring_rgba_minimized are deprecated.
  • backend_pgf.TmpDirCleaner is deprecated, with no replacement.
  • GraphicsContextPS is deprecated. The PostScript backend now uses GraphicsContextBase.

wx backend cleanups

The origin parameter to _FigureCanvasWxBase.gui_repaint is deprecated with no replacement; gui_repaint now automatically detects the case where it is used with the wx renderer.

The NavigationToolbar2Wx.get_canvas method is deprecated; directly instantiate a canvas (FigureCanvasWxAgg(frame, -1, figure)) if needed.

Unused positional parameters to print_<fmt> methods are deprecated

None of the print_<fmt> methods implemented by canvas subclasses used positional arguments other that the first (the output filename or file-like), so these extra parameters are deprecated.

The dpi parameter of FigureCanvas.print_foo printers is deprecated

The savefig machinery already took care of setting the figure DPI to the desired value, so print_foo can directly read it from there. Not passing dpi to print_foo allows clearer detection of unused parameters passed to savefig.

Passing bytes to FT2Font.set_text

... is deprecated, pass str instead.

ps.useafm deprecated for mathtext

Outputting mathtext using only standard PostScript fonts has likely been broken for a while (issue #18722). In Matplotlib 3.5, the setting rcParams["ps.useafm"] (default: False) will have no effect on mathtext.

MathTextParser("bitmap") is deprecated

The associated APIs MathtextBackendBitmap, MathTextParser.to_mask, MathTextParser.to_rgba, MathTextParser.to_png, and MathTextParser.get_depth are likewise deprecated.

To convert a text string to an image, either directly draw the text to an empty Figure and save the figure using a tight bbox, as demonstrated in Convert texts to images, or use mathtext.math_to_image.

When using math_to_image, text color can be set with e.g.:

with plt.rc_context({"text.color": "tab:blue"}):
    mathtext.math_to_image(text, filename)

and an RGBA array can be obtained with e.g.:

from io import BytesIO
buf = BytesIO()
mathtext.math_to_image(text, buf, format="png")
rgba = plt.imread(buf)

Deprecation of mathtext internals

The following API elements previously exposed by the mathtext module are considered to be implementation details and public access to them is deprecated:

  • Fonts and all its subclasses,
  • FontConstantsBase and all its subclasses,
  • Node and all its subclasses,
  • Ship, ship,
  • Error,
  • Parser,
  • latex_to_bakoma, latex_to_cmex, latex_to_standard,
  • stix_virtual_fonts,
  • tex2uni.

Deprecation of various mathtext helpers

The MathtextBackendPdf, MathtextBackendPs, MathtextBackendSvg, and MathtextBackendCairo classes from the mathtext module, as well as the corresponding .mathtext_parser attributes on RendererPdf, RendererPS, RendererSVG, and RendererCairo, are deprecated. The MathtextBackendPath class can be used to obtain a list of glyphs and rectangles in a mathtext expression, and renderer-specific logic should be directly implemented in the renderer.

StandardPsFonts.pswriter is unused and deprecated.

Widget class internals

Several widgets.Widget class internals have been privatized and deprecated:

  • AxesWidget.cids
  • Button.cnt and Button.observers
  • CheckButtons.cnt and CheckButtons.observers
  • RadioButtons.cnt and RadioButtons.observers
  • Slider.cnt and Slider.observers
  • TextBox.cnt, TextBox.change_observers and TextBox.submit_observers

3D properties on renderers

The properties of the 3D Axes that were placed on the Renderer during draw are now deprecated:

  • renderer.M
  • renderer.eye
  • renderer.vvec
  • renderer.get_axis_position

These attributes are all available via Axes3D, which can be accessed via self.axes on all Artists.

renderer argument of do_3d_projection method for Collection3D/Patch3D

The renderer argument for the do_3d_projection method on Collection3D and Patch3D is no longer necessary, and passing it during draw is deprecated.

project argument of draw method for Line3DCollection

The project argument for the draw method on Line3DCollection is deprecated. Call Line3DCollection.do_3d_projection explicitly instead.

Extra positional parameters to plot_surface and plot_wireframe

Positional parameters to plot_surface and plot_wireframe other than X, Y, and Z are deprecated. Pass additional artist properties as keyword arguments instead.

ParasiteAxesAuxTransBase class

The functionality of that mixin class has been moved to the base ParasiteAxesBase class. Thus, ParasiteAxesAuxTransBase, ParasiteAxesAuxTrans, and parasite_axes_auxtrans_class_factory are deprecated.

In general, it is suggested to use HostAxes.get_aux_axes to create parasite Axes, as this saves the need of manually appending the parasite to host.parasites and makes sure that their remove() method works properly.

AxisArtist.ZORDER attribute

Use AxisArtist.zorder instead.

GridHelperBase invalidation

The GridHelperBase.invalidate, GridHelperBase.valid, and axislines.Axes.invalidate_grid_helper methods are considered internal and deprecated.


... is deprecated. Use docutils.parsers.rst.directives.images.Image.align instead.


The following deprecated APIs have been removed:

Removed behaviour

  • The "smart bounds" functionality on Axis and Spine has been deleted, and the related methods have been removed.
  • Converting a string with single color characters (e.g. 'cymk') in to_rgba_array is no longer supported. Instead, the colors can be passed individually in a list (e.g. ['c', 'y', 'm', 'k']).
  • Returning a factor equal to None from mpl_toolkits.axisartist Locators (which are not the same as "standard" tick Locators), or passing a factor equal to None to axisartist Formatters (which are not the same as "standard" tick Formatters) is no longer supported. Pass a factor equal to 1 instead.


  • The entire matplotlib.testing.disable_internet module has been removed. The pytest-remotedata package can be used instead.
  • The mpl_toolkits.axes_grid1.colorbar module and its colorbar implementation have been removed in favor of matplotlib.colorbar.

Classes, methods and attributes

  • The animation.MovieWriterRegistry methods .set_dirty(), .ensure_not_dirty(), and .reset_available_writers() do nothing and have been removed. The .avail() method has been removed; use .list() instead to get a list of available writers.
  • The matplotlib.artist.Artist.eventson and matplotlib.container.Container.eventson attributes have no effect and have been removed.
  • matplotlib.axes.Axes.get_data_ratio_log has been removed.
  • matplotlib.axes.SubplotBase.rowNum; use ax.get_subplotspec().rowspan.start instead.
  • matplotlib.axes.SubplotBase.colNum; use ax.get_subplotspec().colspan.start instead.
  • matplotlib.axis.Axis.set_smart_bounds and matplotlib.axis.Axis.get_smart_bounds have been removed.
  • matplotlib.colors.DivergingNorm has been renamed to TwoSlopeNorm.
  • matplotlib.figure.AxesStack has been removed.
  • matplotlib.font_manager.JSONEncoder has been removed; use font_manager.json_dump to dump a FontManager instance.
  • The matplotlib.ft2font.FT2Image methods .as_array(), .as_rgba_str(), .as_str(), .get_height() and .get_width() have been removed. Convert the FT2Image to a NumPy array with np.asarray before processing it.
  • matplotlib.quiver.QuiverKey.quiverkey_doc has been removed; use matplotlib.quiver.QuiverKey.__init__.__doc__ instead.
  • matplotlib.spines.Spine.set_smart_bounds and matplotlib.spines.Spine.get_smart_bounds have been removed.
  • matplotlib.testing.jpl_units.UnitDbl.checkUnits has been removed; use units not in self.allowed instead.
  • The unused matplotlib.ticker.Locator.autoscale method has been removed (pass the axis limits to Locator.view_limits instead). The derived methods Locator.autoscale, AutoDateLocator.autoscale, RRuleLocator.autoscale, RadialLocator.autoscale, ThetaLocator.autoscale, and YearLocator.autoscale have also been removed.
  • matplotlib.transforms.BboxBase.is_unit has been removed; check the Bbox extents if needed.
  • matplotlib.transforms.Affine2DBase.matrix_from_values(...) has been removed; use (for example) Affine2D.from_values(...).get_matrix() instead.
  • matplotlib.backend_bases.FigureCanvasBase.draw_cursor has been removed.
  • matplotlib.backends.backend_gtk.ConfigureSubplotsGTK3.destroy and matplotlib.backends.backend_gtk.ConfigureSubplotsGTK3.init_window methods have been removed.
  • matplotlib.backends.backend_gtk.ConfigureSubplotsGTK3.window property has been removed.
  • matplotlib.backends.backend_macosx.FigureCanvasMac.invalidate has been removed.
  • matplotlib.backends.backend_pgf.RendererPgf.latexManager has been removed.
  • matplotlib.backends.backend_wx.FigureFrameWx.statusbar, matplotlib.backends.backend_wx.NavigationToolbar2Wx.set_status_bar, and matplotlib.backends.backend_wx.NavigationToolbar2Wx.statbar have been removed. The status bar can be retrieved by calling standard wx methods (frame.GetStatusBar() and toolbar.GetTopLevelParent().GetStatusBar()).
  • matplotlib.backends.backend_wx.ConfigureSubplotsWx.configure_subplots and matplotlib.backends.backend_wx.ConfigureSubplotsWx.get_canvas have been removed.
  • mpl_toolkits.axisartist.grid_finder.GridFinderBase has been removed; use GridFinder instead.
  • mpl_toolkits.axisartist.axis_artist.BezierPath has been removed; use patches.PathPatch instead.


  • matplotlib.backends.backend_pgf.repl_escapetext and matplotlib.backends.backend_pgf.repl_mathdefault have been removed.
  • matplotlib.checkdep_ps_distiller has been removed.
  • matplotlib.cm.revcmap has been removed; use Colormap.reversed instead.
  • matplotlib.colors.makeMappingArray has been removed.
  • matplotlib.compare_versions has been removed; use comparison of distutils.version.LooseVersions instead.
  • matplotlib.dates.mx2num has been removed.
  • matplotlib.font_manager.createFontList has been removed; font_manager.FontManager.addfont is now available to register a font at a given path.
  • matplotlib.get_home has been removed; use standard library instead.
  • matplotlib.mlab.apply_window and matplotlib.mlab.stride_repeat have been removed.
  • matplotlib.rcsetup.update_savefig_format has been removed; this just replaced 'auto' with 'png', so do the same.
  • matplotlib.rcsetup.validate_animation_writer_path has been removed.
  • matplotlib.rcsetup.validate_path_exists has been removed; use os.path.exists or pathlib.Path.exists instead.
  • matplotlib.style.core.is_style_file and matplotlib.style.core.iter_style_files have been removed.
  • matplotlib.testing.is_called_from_pytest has been removed.
  • mpl_toolkits.mplot3d.axes3d.unit_bbox has been removed; use Bbox.unit instead.



sample_data removals

The sample datasets listed below have been removed. Suggested replacements for demonstration purposes are listed in parentheses.

  • None_vs_nearest-pdf.png,
  • aapl.npz (use goog.npz),
  • ada.png, grace_hopper.png (use grace_hopper.jpg),
  • ct.raw.gz (use s1045.ima.gz),
  • damodata.csv (use msft.csv).

Development changes

Increase to minimum supported versions of Python and dependencies

For Maptlotlib 3.4, the minimum supported versions are being bumped:

Dependency min in mpl3.3 min in mpl3.4
Python 3.6 3.7
dateutil 2.1 2.7
numpy 1.15 1.16
pyparsing 2.0.3 2.2.1

This is consistent with our Minimum Version of Dependencies Policy and NEP29

Qhull downloaded at build-or-sdist time

Much like FreeType, Qhull is now downloaded at build time, or upon creation of the sdist. To link against system Qhull, set the system_qhull option to True in the setup.cfg file. Note that Matplotlib now requires the re-entrant version of Qhull (qhull_r).

FigureBase class added, and Figure class made a child

The new subfigure feature motivated some re-organization of the figure.Figure class, so that the new figure.SubFigure class could have all the capabilities of a figure.

The figure.Figure class is now a subclass of figure.FigureBase, where figure.FigureBase contains figure-level artist addition routines, and the figure.Figure subclass just contains features that are unique to the outer figure.

Note that there is a new transSubfigure transform associated with the subfigure. This transform also exists for a Figure instance, and is equal to transFigure in that case, so code that uses the transform stack that wants to place objects on either the parent figure or one of the subfigures should use transSubfigure.