API Changes for 3.7.0#

Behaviour Changes#

All Axes have get_subplotspec and get_gridspec methods now, which returns None for Axes not positioned via a gridspec#

Previously, this method was only present for Axes positioned via a gridspec. Following this change, checking hasattr(ax, "get_gridspec") should now be replaced by ax.get_gridspec() is not None. For compatibility with older Matplotlib releases, one can also check hasattr(ax, "get_gridspec") and ax.get_gridspec() is not None.

HostAxesBase.get_aux_axes now defaults to using the same base axes class as the host axes#

If using an mpl_toolkits.axisartist-based host Axes, the parasite Axes will also be based on mpl_toolkits.axisartist. This behavior is consistent with HostAxesBase.twin, HostAxesBase.twinx, and HostAxesBase.twiny.

plt.get_cmap and matplotlib.cm.get_cmap return a copy#

Formerly, get_cmap and cm.get_cmap returned a global version of a Colormap. This was prone to errors as modification of the colormap would propagate from one location to another without warning. Now, a new copy of the colormap is returned.

TrapezoidMapTriFinder uses different random number generator#

The random number generator used to determine the order of insertion of triangle edges in TrapezoidMapTriFinder has changed. This can result in a different triangle index being returned for a point that lies exactly on an edge between two triangles. This can also affect triangulation interpolation and refinement algorithms that use TrapezoidMapTriFinder.


Passing save_count=None to FuncAnimation no longer limits the number of frames to 100. Make sure that it either can be inferred from frames or provide an integer save_count.

CenteredNorm halfrange is not modified when vcenter changes#

Previously, the halfrange would expand in proportion to the amount that vcenter was moved away from either vmin or vmax. Now, the halfrange remains fixed when vcenter is changed, and vmin and vmax are updated based on the vcenter and halfrange values.

For example, this is what the values were when changing vcenter previously.

norm = CenteredNorm(vcenter=0, halfrange=1)
# Move vcenter up by one
norm.vcenter = 1
# updates halfrange and vmax (vmin stays the same)
# norm.halfrange == 2, vmin == -1, vmax == 3

and now, with that same example

norm = CenteredNorm(vcenter=0, halfrange=1)
norm.vcenter = 1
# updates vmin and vmax (halfrange stays the same)
# norm.halfrange == 1, vmin == 0, vmax == 2

The halfrange can be set manually or norm.autoscale() can be used to automatically set the limits after setting vcenter.

fig.subplot_mosaic no longer passes the gridspec_kw args to nested gridspecs.#

For nested Figure.subplot_mosaic layouts, it is almost always inappropriate for gridspec_kw arguments to be passed to lower nest levels, and these arguments are incompatible with the lower levels in many cases. This dictionary is no longer passed to the inner layouts. Users who need to modify gridspec_kw at multiple levels should use Figure.subfigures to get nesting, and construct the inner layouts with Figure.subplots or Figure.subplot_mosaic.

HPacker alignment with bottom or top are now correct#

Previously, the bottom and top alignments were swapped. This has been corrected so that the alignments correspond appropriately.

On Windows only fonts known to the registry will be discovered#

Previously, Matplotlib would recursively walk user and system font directories to discover fonts, however this lead to a number of undesirable behaviors including finding deleted fonts. Now Matplotlib will only find fonts that are known to the Windows registry.

This means that any user installed fonts must go through the Windows font installer rather than simply being copied to the correct folder.

This only impacts the set of fonts Matplotlib will consider when using matplotlib.font_manager.findfont. To use an arbitrary font, directly pass the path to a font as shown in Using ttf font files.

QuadMesh.set_array now always raises ValueError for inputs with incorrect shapes#

It could previously also raise TypeError in some cases.

contour and contourf auto-select suitable levels when given boolean inputs#

If the height array given to Axes.contour or Axes.contourf is of bool dtype and levels is not specified, levels now defaults to [0.5] for contour and [0, 0.5, 1] for Axes.contourf.

contour no longer warns if no contour lines are drawn.#

This can occur if the user explicitly passes a levels array with no values

AxesImage.set_extent now raises TypeError for unknown keyword arguments#

It previously raised a ValueError.

etween z.min() and z.max(); or if z has the same value everywhere.

Change of legend(loc="best") behavior#

The algorithm of the auto-legend locator has been tweaked to better handle non rectangular patches. Additional details on this change can be found in #9580 and #9598.


Axes subclasses should override clear instead of cla#

For clarity, axes.Axes.clear is now preferred over Axes.cla. However, for backwards compatibility, the latter will remain as an alias for the former.

For additional compatibility with third-party libraries, Matplotlib will continue to call the cla method of any Axes subclasses if they define it. In the future, this will no longer occur, and Matplotlib will only call the clear method in Axes subclasses.

It is recommended to define only the clear method when on Matplotlib 3.6, and only cla for older versions.

rcParams type#

Relying on rcParams being a dict subclass is deprecated.

Nothing will change for regular users because rcParams will continue to be dict-like (technically fulfill the MutableMapping interface).

The RcParams class does validation checking on calls to .RcParams.__getitem__ and .RcParams.__setitem__. However, there are rare cases where we want to circumvent the validation logic and directly access the underlying data values. Previously, this could be accomplished via a call to the parent methods dict.__getitem__(rcParams, key) and dict.__setitem__(rcParams, key, val).

Matplotlib 3.7 introduces rcParams._set(key, val) and rcParams._get(key) as a replacement to calling the parent methods. They are intentionally marked private to discourage external use; However, if direct RcParams data access is needed, please switch from the dict functions to the new _get() and _set(). Even though marked private, we guarantee API stability for these methods and they are subject to Matplotlib's API and deprecation policy.

Please notify the Matplotlib developers if you rely on rcParams being a dict subclass in any other way, for which there is no migration path yet.

Deprecation aliases in cbook#

The module matplotlib.cbook.deprecation was previously deprecated in Matplotlib 3.4, along with deprecation-related API in matplotlib.cbook. Due to technical issues, matplotlib.cbook.MatplotlibDeprecationWarning and matplotlib.cbook.mplDeprecation did not raise deprecation warnings on use. Changes in Python have now made it possible to warn when these aliases are being used.

In order to avoid downstream breakage, these aliases will now warn, and their removal has been pushed from 3.6 to 3.8 to give time to notice said warnings. As replacement, please use matplotlib.MatplotlibDeprecationWarning.


... is deprecated as in most backends this is a redundant call. Use draw_gouraud_triangles instead. A draw_gouraud_triangle call in a custom Artist can readily be replaced as:

self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)),
                            colors.reshape((1, 3, 4)), trans)

A draw_gouraud_triangles method can be implemented from an existing draw_gouraud_triangle method as:

transform = transform.frozen()
for tri, col in zip(triangles_array, colors_array):
    self.draw_gouraud_triangle(gc, tri, col, transform)


... is a pending deprecation. This is considered internal and no end-user should need it.

matplotlib.tri submodules are deprecated#

The matplotlib.tri.* submodules are deprecated. All functionality is available in matplotlib.tri directly and should be imported from there.

Passing undefined label_mode to Grid#

... is deprecated. This includes mpl_toolkits.axes_grid1.axes_grid.Grid, mpl_toolkits.axes_grid1.axes_grid.AxesGrid, and mpl_toolkits.axes_grid1.axes_grid.ImageGrid as well as the corresponding classes imported from mpl_toolkits.axisartist.axes_grid.

Pass label_mode='keep' instead to get the previous behavior of not modifying labels.

Colorbars for orphaned mappables are deprecated, but no longer raise#

Before 3.6.0, Colorbars for mappables that do not have a parent axes would steal space from the current Axes. 3.6.0 raised an error on this, but without a deprecation cycle. For 3.6.1 this is reverted, the current axes is used, but a deprecation warning is shown instead. In this undetermined case users and libraries should explicitly specify what axes they want space to be stolen from: fig.colorbar(mappable, ax=plt.gca()).

Animation attributes#

The attributes repeat of TimedAnimation and subclasses and save_count of FuncAnimation are considered private and deprecated.

contour.ClabelText and ContourLabeler.set_label_props#

... are deprecated.

Use Text(..., transform_rotates_text=True) as a replacement for contour.ClabelText(...) and text.set(text=text, color=color, fontproperties=labeler.labelFontProps, clip_box=labeler.axes.bbox) as a replacement for the ContourLabeler.set_label_props(label, text, color).

ContourLabeler attributes#

The labelFontProps, labelFontSizeList, and labelTextsList attributes of ContourLabeler have been deprecated. Use the labelTexts attribute and the font properties of the corresponding text objects instead.

backend_ps.PsBackendHelper and backend_ps.ps_backend_helper#

... are deprecated with no replacement.

backend_webagg.ServerThread is deprecated#

... with no replacement.

parse_fontconfig_pattern will no longer ignore unknown constant names#

Previously, in a fontconfig pattern like DejaVu Sans:foo, the unknown foo constant name would be silently ignored. This now raises a warning, and will become an error in the future.

BufferRegion.to_string and BufferRegion.to_string_argb#

... are deprecated. Use np.asarray(buffer_region) to get an array view on a buffer region without making a copy; to convert that view from RGBA (the default) to ARGB, use np.take(..., [2, 1, 0, 3], axis=2).

num2julian, julian2num and JULIAN_OFFSET#

... of the dates module are deprecated without replacements. These are undocumented and not exported. If you rely on these, please make a local copy.

unit_cube, tunit_cube, and tunit_edges#

... of Axes3D are deprecated without replacements. If you rely on them, please copy the code of the corresponding private function (name starting with _).

Most arguments to widgets have been made keyword-only#

Passing all but the very few first arguments positionally in the constructors of Widgets is deprecated. Most arguments will become keyword-only in a future version.


The SimpleEvent nested class (previously accessible via the public subclasses of ConnectionStyle._Base, such as ConnectionStyle.Arc, has been deprecated.


... is deprecated. (RadioButtons now draws itself using scatter.)

CheckButtons.rectangles and CheckButtons.lines#

CheckButtons.rectangles and CheckButtons.lines are deprecated. (CheckButtons now draws itself using scatter.)

OffsetBox.get_extent_offsets and OffsetBox.get_extent#

... are deprecated; these methods are also deprecated on all subclasses of OffsetBox.

To get the offsetbox extents, instead of get_extent, use OffsetBox.get_bbox, which directly returns a Bbox instance.

To also get the child offsets, instead of get_extent_offsets, separately call get_offset on each children after triggering a draw.


... was undocumented and has been renamed to legend_handles. Using legendHandles is deprecated.

ticklabels parameter of Axis.set_ticklabels renamed to labels#


... is deprecated. This is just a wrapper to call patches.bbox_artist if a flag is set in the file, so use that directly if you need the behavior.

Quiver.quiver_doc and Barbs.barbs_doc#

... are deprecated. These are the doc-string and should not be accessible as a named class member.

Deprecate unused parameter x to TextBox.begin_typing#

This parameter was unused in the method, but was a required argument.

Deprecation of top-level cmap registration and access functions in mpl.cm#

As part of a multi-step process we are refactoring the global state for managing the registered colormaps.

In Matplotlib 3.5 we added a ColormapRegistry class and exposed an instance at the top level as matplotlib.colormaps. The existing top level functions in matplotlib.cm (get_cmap, register_cmap, unregister_cmap) were changed to be aliases around the same instance. In Matplotlib 3.6 we have marked those top level functions as pending deprecation.

In Matplotlib 3.7, the following functions have been marked for deprecation:

The matplotlib.pyplot.get_cmap function will stay available for backward compatibility.

BrokenBarHCollection is deprecated#

It was just a thin wrapper inheriting from PolyCollection; broken_barh has now been changed to return a PolyCollection instead.

The BrokenBarHCollection.span_where helper is likewise deprecated; for the duration of the deprecation it has been moved to the parent PolyCollection class. Use fill_between as a replacement; see Shade regions defined by a logical mask using fill_between for an example.

Passing inconsistent loc and nth_coord to axisartist helpers#

Trying to construct for example a "top y-axis" or a "left x-axis" is now deprecated.


This attribute of AxisArtistHelpers is deprecated.

axes3d.vvec, axes3d.eye, axes3d.sx, and axes3d.sy#

... are deprecated without replacement.


When creating a Line2D or using Line2D.set_xdata and Line2D.set_ydata, passing x/y data as non sequence is deprecated.


epoch2num and num2epoch are removed#

These methods convert from unix timestamps to matplotlib floats, but are not used internally to Matplotlib, and should not be needed by end users. To convert a unix timestamp to datetime, simply use datetime.datetime.fromtimestamp, or to use NumPy datetime64 dt = np.datetime64(e*1e6, 'us').

Locator and Formatter wrapper methods#

The set_view_interval, set_data_interval and set_bounds methods of Locators and Formatters (and their common base class, TickHelper) are removed. Directly manipulate the view and data intervals on the underlying axis instead.

Interactive cursor details#

Setting a mouse cursor on a window has been moved from the toolbar to the canvas. Consequently, several implementation details on toolbars and within backends have been removed.

backend_tools.SetCursorBase and subclasses#

backend_tools.SetCursorBase was subclassed to provide backend-specific implementations of set_cursor. As that is now removed, the subclassing is no longer necessary. Consequently, the following subclasses are also removed:

  • matplotlib.backends.backend_gtk3.SetCursorGTK3

  • matplotlib.backends.backend_qt5.SetCursorQt

  • matplotlib.backends._backend_tk.SetCursorTk

  • matplotlib.backends.backend_wx.SetCursorWx

Instead, use the backend_tools.ToolSetCursor class.

cursord in GTK and wx backends#

The backend_gtk3.cursord and backend_wx.cursord dictionaries are removed. This makes the GTK module importable on headless environments.

auto_add_to_figure=True for Axes3D#

... is no longer supported. Instead use fig.add_axes(ax).

The first parameter of Axes.grid and Axis.grid has been renamed to visible#

The parameter was previously named b. This name change only matters if that parameter was passed using a keyword argument, e.g. grid(b=False).

Removal of deprecations in the Selector widget API#

RectangleSelector and EllipseSelector#

The drawtype keyword argument to RectangleSelector is removed. From now on, the only behaviour will be drawtype='box'.

Support for drawtype=line is removed altogether. As a result, the lineprops keyword argument to RectangleSelector is also removed.

To retain the behaviour of drawtype='none', use rectprops={'visible': False} to make the drawn Rectangle invisible.

Cleaned up attributes and arguments are:

  • The active_handle attribute has been privatized and removed.

  • The drawtype attribute has been privatized and removed.

  • The eventpress attribute has been privatized and removed.

  • The eventrelease attribute has been privatized and removed.

  • The interactive attribute has been privatized and removed.

  • The marker_props argument is removed, use handle_props instead.

  • The maxdist argument is removed, use grab_range instead.

  • The rectprops argument is removed, use props instead.

  • The rectprops attribute has been privatized and removed.

  • The state attribute has been privatized and removed.

  • The to_draw attribute has been privatized and removed.


  • The line attribute is removed. If you want to change the selector artist properties, use the set_props or set_handle_props methods.

  • The lineprops argument is removed, use props instead.

  • The markerprops argument is removed, use handle_props instead.

  • The maxdist argument and attribute is removed, use grab_range instead.

  • The vertex_select_radius argument and attribute is removed, use grab_range instead.


  • The active_handle attribute has been privatized and removed.

  • The eventpress attribute has been privatized and removed.

  • The eventrelease attribute has been privatized and removed.

  • The pressv attribute has been privatized and removed.

  • The prev attribute has been privatized and removed.

  • The rect attribute has been privatized and removed.

  • The rectprops parameter has been renamed to props.

  • The rectprops attribute has been privatized and removed.

  • The span_stays parameter has been renamed to interactive.

  • The span_stays attribute has been privatized and removed.

  • The state attribute has been privatized and removed.


  • The lineprops argument is removed, use props instead.

  • The onpress and onrelease methods are removed. They are straight aliases for press and release.

  • The matplotlib.widgets.TextBox.DIST_FROM_LEFT attribute has been removed. It was marked as private in 3.5.


... has been removed, in order to better demonstrate the new backend definition API.

Unused positional parameters to print_<fmt> methods#

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 removed.

QuadMesh signature#

The QuadMesh signature

def __init__(meshWidth, meshHeight, coordinates,
             antialiased=True, shading='flat', **kwargs)

is removed and replaced by the new signature

def __init__(coordinates, *, antialiased=True, shading='flat', **kwargs)

In particular:

  • The coordinates argument must now be a (M, N, 2) array-like. Previously, the grid shape was separately specified as (meshHeight + 1, meshWidth + 1) and coordinates could be an array-like of any shape with M * N * 2 elements.

  • All parameters except coordinates are keyword-only now.

Expiration of FancyBboxPatch deprecations#

The FancyBboxPatch constructor no longer accepts the bbox_transmuter parameter, nor can the boxstyle parameter be set to "custom" -- instead, directly set boxstyle to the relevant boxstyle instance. The mutation_scale and mutation_aspect parameters have also become keyword-only.

The mutation_aspect parameter is now handled internally and no longer passed to the boxstyle callables when mutating the patch path.

Testing support#

matplotlib.test() has been removed#

Run tests using pytest from the commandline instead. The variable matplotlib.default_test_modules was only used for matplotlib.test() and is thus removed as well.

To test an installed copy, be sure to specify both matplotlib and mpl_toolkits with --pyargs:

python -m pytest --pyargs matplotlib.tests mpl_toolkits.tests

See Testing for more details.

Auto-removal of grids by pcolor and pcolormesh#

pcolor and pcolormesh previously remove any visible axes major grid. This behavior is removed; please explicitly call ax.grid(False) to remove the grid.

Modification of Axes children sublists#

See Axes children are no longer separated by type for more information; modification of the following sublists is no longer supported:

  • Axes.artists

  • Axes.collections

  • Axes.images

  • Axes.lines

  • Axes.patches

  • Axes.tables

  • Axes.texts

To remove an Artist, use its Artist.remove method. To add an Artist, use the corresponding Axes.add_* method.

Passing incorrect types to Axes.add_* methods#

The following Axes.add_* methods will now raise if passed an unexpected type. See their documentation for the types they expect.

ConversionInterface.convert no longer accepts unitless values#

Previously, custom subclasses of units.ConversionInterface needed to implement a convert method that not only accepted instances of the unit, but also unitless values (which are passed through as is). This is no longer the case (convert is never called with a unitless value), and such support in .StrCategoryConverter is removed. Likewise, the .ConversionInterface.is_numlike helper is removed.

Consider calling Axis.convert_units instead, which still supports unitless values.

Normal list of Artist objects now returned by HandlerLine2D.create_artists#

For Matplotlib 3.5 and 3.6 a proxy list was returned that simulated the return of HandlerLine2DCompound.create_artists. Now a list containing only the single artist is return.

rcParams will no longer cast inputs to str#

rcParams that expect a (non-pathlike) str no longer cast non-str inputs using str. This will avoid confusing errors in subsequent code if e.g. a list input gets implicitly cast to a str.

Case-insensitive scales#

Previously, scales could be set case-insensitively (e.g., set_xscale("LoG")). Now all builtin scales use lowercase names.

Support for nx1 = None or ny1 = None in AxesLocator and Divider.locate#

In axes_grid1.axes_divider, various internal APIs no longer supports passing nx1 = None or ny1 = None to mean nx + 1 or ny + 1, in preparation for a possible future API which allows indexing and slicing of dividers (possibly divider[a:b] == divider.new_locator(a, b), but also divider[a:] == divider.new_locator(a, <end>)). The user-facing Divider.new_locator API is unaffected -- it correctly normalizes nx1 = None and ny1 = None as needed.

change signature of .FigureCanvasBase.enter_notify_event#

The xy parameter is now required and keyword only. This was deprecated in 3.0 and originally slated to be removed in 3.5.

Colorbar tick update parameters#

The update_ticks parameter of Colorbar.set_ticks and Colorbar.set_ticklabels was ignored since 3.5 and has been removed.

plot directive removals#

The public methods:

  • matplotlib.sphinxext.split_code_at_show

  • matplotlib.sphinxext.unescape_doctest

  • matplotlib.sphinxext.run_code

have been removed.

The deprecated encoding option to the plot directive has been removed.

Miscellaneous removals#

  • is_url and URL_REGEX are removed. (They were previously defined in the toplevel matplotlib module.)

  • The ArrowStyle.beginarrow and ArrowStyle.endarrow attributes are removed; use the arrow attribute to define the desired heads and tails of the arrow.

  • backend_pgf.LatexManager.str_cache is removed.

  • backends.qt_compat.ETS and backends.qt_compat.QT_RC_MAJOR_VERSION are removed, with no replacement.

  • The blocking_input module is removed. Instead, use canvas.start_event_loop() and canvas.stop_event_loop() while connecting event callbacks as needed.

  • cbook.report_memory is removed; use psutil.virtual_memory instead.

  • cm.LUTSIZE is removed. Use rcParams["image.lut"] (default: 256) instead. This value only affects colormap quantization levels for default colormaps generated at module import time.

  • Colorbar.patch is removed; this attribute was not correctly updated anymore.

  • ContourLabeler.get_label_width is removed.

  • Dvi.baseline is removed (with no replacement).

  • The format parameter of dviread.find_tex_file is removed (with no replacement).

  • FancyArrowPatch.get_path_in_displaycoord and ConnectionPath.get_path_in_displaycoord are removed. The path in display coordinates can still be obtained, as for other patches, using patch.get_transform().transform_path(patch.get_path()).

  • The font_manager.win32InstalledFonts and font_manager.get_fontconfig_fonts helper functions are removed.

  • All parameters of imshow starting from aspect are keyword-only.

  • QuadMesh.convert_mesh_to_paths and QuadMesh.convert_mesh_to_triangles are removed. QuadMesh.get_paths() can be used as an alternative for the former; there is no replacement for the latter.

  • ScalarMappable.callbacksSM is removed. Use ScalarMappable.callbacks instead.

  • streamplot.get_integrator is removed.

  • style.core.STYLE_FILE_PATTERN, style.core.load_base_library, and style.core.iter_user_libraries are removed.

  • SubplotParams.validate is removed. Use SubplotParams.update to change SubplotParams while always keeping it in a valid state.

  • The grey_arrayd, font_family, font_families, and font_info attributes of TexManager are removed.

  • Text.get_prop_tup is removed with no replacements (because the Text class cannot know whether a backend needs to update cache e.g. when the text's color changes).

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

  • tight_layout.auto_adjust_subplotpars is removed.

  • The grid_info attribute of axisartist classes has been removed.

  • axes_grid1.axes_grid.CbarAxes and axisartist.axes_grid.CbarAxes are removed (they are now dynamically generated based on the owning axes class).

  • The axes_grid1.Divider.get_vsize_hsize and axes_grid1.Grid.get_vsize_hsize methods are removed.

  • AxesDivider.append_axes(..., add_to_figure=False) is removed. Use ax.remove() to remove the Axes from the figure if needed.

  • FixedAxisArtistHelper.change_tick_coord is removed with no replacement.

  • floating_axes.GridHelperCurveLinear.get_boundary is removed with no replacement.

  • ParasiteAxesBase.get_images_artists is removed.

  • The "units finalize" signal (previously emitted by Axis instances) is removed. Connect to "units" instead.

  • Passing formatting parameters positionally to stem() is no longer possible.

  • axisartist.clip_path is removed with no replacement.

Development changes#

Windows wheel runtime bundling#

Wheels built for Windows now bundle the MSVC runtime DLL msvcp140.dll. This enables importing Matplotlib on systems that do not have the runtime installed.

Increase to minimum supported versions of dependencies#

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


min in mpl3.6

min in mpl3.7









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

This is consistent with our Dependency version policy and NEP29

New dependencies#

Maximum line length increased to 88 characters#

The maximum line length for new contributions has been extended from 79 characters to 88 characters. This change provides an extra 9 characters to allow code which is a single idea to fit on fewer lines (often a single line). The chosen length is the same as black.