+
+
+
+
+``Colormap.set_extremes`` and ``Colormap.with_extremes``
+--------------------------------------------------------
+
+Because the `.Colormap.set_bad`, `.Colormap.set_under` and `.Colormap.set_over`
+methods modify the colormap in place, the user must be careful to first make a
+copy of the colormap if setting the extreme colors e.g. for a builtin colormap.
+
+The new ``Colormap.with_extremes(bad=..., under=..., over=...)`` can be used to
+first copy the colormap and set the extreme colors on that copy.
+
+The new `.Colormap.set_extremes` method is provided for API symmetry with
+`.Colormap.with_extremes`, but note that it suffers from the same issue as the
+earlier individual setters.
+
+Get under/over/bad colors of Colormap objects
+---------------------------------------------
+
+`matplotlib.colors.Colormap` now has methods `~.colors.Colormap.get_under`,
+`~.colors.Colormap.get_over`, `~.colors.Colormap.get_bad` for the colors used
+for out-of-range and masked values.
+
+New ``cm.unregister_cmap`` function
+-----------------------------------
+
+`.cm.unregister_cmap` allows users to remove a colormap that they have
+previously registered.
+
+New ``CenteredNorm`` for symmetrical data around a center
+---------------------------------------------------------
+
+In cases where data is symmetrical around a center, for example, positive and
+negative anomalies around a center zero, `~.matplotlib.colors.CenteredNorm` is
+a new norm that automatically creates a symmetrical mapping around the center.
+This norm is well suited to be combined with a divergent colormap which uses an
+unsaturated color in its center.
+
+.. plot::
+
+ from matplotlib.colors import CenteredNorm
+
+ np.random.seed(20201004)
+ data = np.random.normal(size=(3, 4), loc=1)
+
+ fig, ax = plt.subplots()
+ pc = ax.pcolormesh(data, cmap=plt.get_cmap('RdGy'), norm=CenteredNorm())
+ fig.colorbar(pc)
+ ax.set_title('data centered around zero')
+
+ # add text annotation
+ for irow, data_row in enumerate(data):
+ for icol, val in enumerate(data_row):
+ ax.text(icol + 0.5, irow + 0.5, f'{val:.2f}', color='C0',
+ size=16, va='center', ha='center')
+ plt.show()
+
+If the center of symmetry is different from 0, it can be set with the *vcenter*
+argument. To manually set the range of `~.matplotlib.colors.CenteredNorm`, use
+the *halfrange* argument.
+
+See :doc:`/tutorials/colors/colormapnorms` for an example and more details
+about data normalization.
+
+New ``FuncNorm`` for arbitrary normalizations
+---------------------------------------------
+
+The `.FuncNorm` allows for arbitrary normalization using functions for the
+forward and inverse.
+
+.. plot::
+
+ from matplotlib.colors import FuncNorm
+
+ def forward(x):
+ return x**2
+ def inverse(x):
+ return np.sqrt(x)
+
+ norm = FuncNorm((forward, inverse), vmin=0, vmax=3)
+
+ np.random.seed(20201004)
+ data = np.random.normal(size=(3, 4), loc=1)
+
+ fig, ax = plt.subplots()
+ pc = ax.pcolormesh(data, norm=norm)
+ fig.colorbar(pc)
+ ax.set_title('squared normalization')
+
+ # add text annotation
+ for irow, data_row in enumerate(data):
+ for icol, val in enumerate(data_row):
+ ax.text(icol + 0.5, irow + 0.5, f'{val:.2f}', color='C0',
+ size=16, va='center', ha='center')
+ plt.show()
+
+See :doc:`/tutorials/colors/colormapnorms` for an example and more details
+about data normalization.
+
+GridSpec-based colorbars can now be positioned above or to the left of the main axes
+------------------------------------------------------------------------------------
+
+... by passing ``location="top"`` or ``location="left"`` to the ``colorbar()``
+call.
+
+
+Titles, ticks, and labels
+=========================
+
+supxlabel and supylabel
+-----------------------
+
+It is possible to add x- and y-labels to a whole figure, analogous to
+`.FigureBase.suptitle` using the new `.FigureBase.supxlabel` and
+`.FigureBase.supylabel` methods.
+
+.. plot::
+
+ np.random.seed(19680801)
+ fig, axs = plt.subplots(3, 2, figsize=(5, 5), constrained_layout=True,
+ sharex=True, sharey=True)
+
+ for nn, ax in enumerate(axs.flat):
+ ax.set_title(f'Channel {nn}')
+ ax.plot(np.cumsum(np.random.randn(50)))
+
+ fig.supxlabel('Time [s]')
+ fig.supylabel('Data [V]')
+
+Shared-axes ``subplots`` tick label visibility is now correct for top or left labels
+------------------------------------------------------------------------------------
+
+When calling ``subplots(..., sharex=True, sharey=True)``, Matplotlib
+automatically hides x tick labels for Axes not in the first column and y tick
+labels for Axes not in the last row. This behavior is incorrect if rcParams
+specify that Axes should be labeled on the top (``rcParams["xtick.labeltop"] =
+True``) or on the right (``rcParams["ytick.labelright"] = True``).
+
+Cases such as the following are now handled correctly (adjusting visibility as
+needed on the first row and last column of Axes):
+
+.. plot::
+ :include-source:
+
+ plt.rcParams["xtick.labelbottom"] = False
+ plt.rcParams["xtick.labeltop"] = True
+ plt.rcParams["ytick.labelleft"] = False
+ plt.rcParams["ytick.labelright"] = True
+
+ fig, axs = plt.subplots(2, 2, sharex=True, sharey=True)
+
+An iterable object with labels can be passed to `.Axes.plot`
+------------------------------------------------------------
+
+When plotting multiple datasets by passing 2D data as *y* value to
+`~.Axes.plot`, labels for the datasets can be passed as a list, the length
+matching the number of columns in *y*.
+
+.. plot::
+ :include-source:
+
+ x = [1, 2, 3]
+
+ y = [[1, 2],
+ [2, 5],
+ [4, 9]]
+
+ plt.plot(x, y, label=['low', 'high'])
+ plt.legend()
+
+
+Fonts and Text
+==============
+
+Text transform can rotate text direction
+----------------------------------------
+
+The new `.Text` parameter ``transform_rotates_text`` now sets whether rotations
+of the transform affect the text direction.
+
+.. figure:: /gallery/text_labels_and_annotations/images/sphx_glr_text_rotation_relative_to_line_001.png
+ :target: /gallery/text_labels_and_annotations/text_rotation_relative_to_line.html
+
+ Example of the new *transform_rotates_text* parameter
+
+``matplotlib.mathtext`` now supports *overset* and *underset* LaTeX symbols
+---------------------------------------------------------------------------
+
+`.mathtext` now supports *overset* and *underset*, called as
+``\overset{annotation}{body}`` or ``\underset{annotation}{body}``, where
+*annotation* is the text "above" or "below" the *body*.
+
+.. plot::
+
+ math_expr = r"$ x \overset{f}{\rightarrow} y \underset{f}{\leftarrow} z $"
+ plt.text(0.4, 0.5, math_expr, usetex=False)
+
+*math_fontfamily* parameter to change ``Text`` font family
+----------------------------------------------------------
+
+The new *math_fontfamily* parameter may be used to change the family of fonts
+for each individual text element in a plot. If no parameter is set, the global
+value :rc:`mathtext.fontset` will be used.
+
+.. figure:: /gallery/text_labels_and_annotations/images/sphx_glr_mathtext_fontfamily_example_001.png
+ :target: /gallery/text_labels_and_annotations/mathtext_fontfamily_example.html
+
+``TextArea``/``AnchoredText`` support *horizontalalignment*
+-----------------------------------------------------------
+
+The horizontal alignment of text in a `.TextArea` or `.AnchoredText` may now be
+specified, which is mostly effective for multiline text:
+
+.. plot::
+
+ from matplotlib.offsetbox import AnchoredText
+
+ fig, ax = plt.subplots()
+
+ text0 = AnchoredText("test\ntest long text", loc="center left",
+ pad=0.2, prop={"ha": "left"})
+ ax.add_artist(text0)
+
+ text1 = AnchoredText("test\ntest long text", loc="center",
+ pad=0.2, prop={"ha": "center"})
+ ax.add_artist(text1)
+
+ text2 = AnchoredText("test\ntest long text", loc="center right",
+ pad=0.2, prop={"ha": "right"})
+ ax.add_artist(text2)
+
+PDF supports URLs on ``Text`` artists
+-------------------------------------
+
+URLs on `.text.Text` artists (i.e., from `.Artist.set_url`) will now be saved
+in PDF files.
+
+
+rcParams improvements
+=====================
+
+New rcParams for dates: set converter and whether to use interval_multiples
+---------------------------------------------------------------------------
+
+The new :rc:`date.converter` allows toggling between
+`matplotlib.dates.DateConverter` and `matplotlib.dates.ConciseDateConverter`
+using the strings 'auto' and 'concise' respectively.
+
+The new :rc:`date.interval_multiples` allows toggling between the dates locator
+trying to pick ticks at set intervals (i.e., day 1 and 15 of the month), versus
+evenly spaced ticks that start wherever the timeseries starts:
+
+.. plot::
+ :include-source:
+
+ dates = np.arange('2001-01-10', '2001-05-23', dtype='datetime64[D]')
+ y = np.sin(dates.astype(float) / 10)
+ fig, axs = plt.subplots(nrows=2, constrained_layout=True)
+
+ plt.rcParams['date.converter'] = 'concise'
+ plt.rcParams['date.interval_multiples'] = True
+ axs[0].plot(dates, y)
+
+ plt.rcParams['date.converter'] = 'auto'
+ plt.rcParams['date.interval_multiples'] = False
+ axs[1].plot(dates, y)
+
+Date formatters now respect *usetex* rcParam
+--------------------------------------------
+
+The `.AutoDateFormatter` and `.ConciseDateFormatter` now respect
+:rc:`text.usetex`, and will thus use fonts consistent with TeX rendering of the
+default (non-date) formatter. TeX rendering may also be enabled/disabled by
+passing the *usetex* parameter when creating the formatter instance.
+
+In the following plot, both the x-axis (dates) and y-axis (numbers) now use the
+same (TeX) font:
+
+.. plot::
+
+ from datetime import datetime, timedelta
+ from matplotlib.dates import ConciseDateFormatter
+
+ plt.rc('text', usetex=True)
+
+ t0 = datetime(1968, 8, 1)
+ ts = [t0 + i * timedelta(days=1) for i in range(10)]
+
+ fig, ax = plt.subplots()
+ ax.plot(ts, range(10))
+ ax.xaxis.set_major_formatter(ConciseDateFormatter(ax.xaxis.get_major_locator()))
+ ax.set_xlabel('Date')
+ ax.set_ylabel('Value')
+
+Setting *image.cmap* to a ``Colormap``
+--------------------------------------
+
+It is now possible to set :rc:`image.cmap` to a `.Colormap` instance, such as a
+colormap created with the new `~.Colormap.set_extremes` above. (This can only
+be done from Python code, not from the :file:`matplotlibrc` file.)
+
+Tick and tick label colors can be set independently using rcParams
+------------------------------------------------------------------
+
+Previously, :rc:`xtick.color` defined both the tick color and the label color.
+The label color can now be set independently using :rc:`xtick.labelcolor`. It
+defaults to ``'inherit'`` which will take the value from :rc:`xtick.color`. The
+same holds for ``ytick.[label]color``. For instance, to set the ticks to light
+grey and the tick labels to black, one can use the following code in a script::
+
+ import matplotlib as mpl
+
+ mpl.rcParams['xtick.labelcolor'] = 'lightgrey'
+ mpl.rcParams['xtick.color'] = 'black'
+ mpl.rcParams['ytick.labelcolor'] = 'lightgrey'
+ mpl.rcParams['ytick.color'] = 'black'
+
+Or by adding the following lines to the :ref:`matplotlibrc
+
` file, or a Matplotlib style file:
+
+.. code-block:: none
+
+ xtick.labelcolor : lightgrey
+ xtick.color : black
+ ytick.labelcolor : lightgrey
+ ytick.color : black
+
+
+3D Axes improvements
+====================
+
+Errorbar method in 3D Axes
+--------------------------
+
+The errorbar function `.Axes.errorbar` is ported into the 3D Axes framework in
+its entirety, supporting features such as custom styling for error lines and
+cap marks, control over errorbar spacing, upper and lower limit marks.
+
+.. figure:: /gallery/mplot3d/images/sphx_glr_errorbar3d_001.png
+ :target: /gallery/mplot3d/errorbar3d.html
+
+Stem plots in 3D Axes
+---------------------
+
+Stem plots are now supported on 3D Axes. Much like 2D stems,
+`~.axes3d.Axes3D.stem3D` supports plotting the stems in various orientations:
+
+.. plot::
+
+ theta = np.linspace(0, 2*np.pi)
+ x = np.cos(theta - np.pi/2)
+ y = np.sin(theta - np.pi/2)
+ z = theta
+ directions = ['z', 'x', 'y']
+ names = [r'$\theta$', r'$\cos\theta$', r'$\sin\theta$']
+
+ fig, axs = plt.subplots(1, 3, figsize=(8, 4),
+ constrained_layout=True,
+ subplot_kw={'projection': '3d'})
+ for ax, zdir, name in zip(axs, directions, names):
+ ax.stem(x, y, z, orientation=zdir)
+ ax.set_title(name)
+ fig.suptitle(r'A parametric circle: $(x, y) = (\cos\theta, \sin\theta)$')
+
+See also the :doc:`/gallery/mplot3d/stem3d_demo` demo.
+
+3D Collection properties are now modifiable
+-------------------------------------------
+
+Previously, properties of a 3D Collection that were used for 3D effects (e.g.,
+colors were modified to produce depth shading) could not be changed after it
+was created.
+
+Now it is possible to modify all properties of 3D Collections at any time.
+
+Panning in 3D Axes
+------------------
+
+Click and drag with the middle mouse button to pan 3D Axes.
+
+
+Interactive tool improvements
+=============================
+
+New ``RangeSlider`` widget
+--------------------------
+
+`.widgets.RangeSlider` allows for creating a slider that defines
+a range rather than a single value.
+
+.. plot::
+
+ fig, ax = plt.subplots(2, 1, figsize=(5, 1))
+ fig.subplots_adjust(left=0.2, right=0.8)
+
+ from matplotlib.widgets import Slider, RangeSlider
+ Slider(ax[0], 'Slider', 0, 1)
+ RangeSlider(ax[1], 'RangeSlider', 0, 1)
+
+Sliders can now snap to arbitrary values
+----------------------------------------
+
+The `~matplotlib.widgets.Slider` UI widget now accepts arrays for *valstep*.
+This generalizes the previous behavior by allowing the slider to snap to
+arbitrary values.
+
+Pausing and Resuming Animations
+-------------------------------
+
+The `.animation.Animation.pause` and `.animation.Animation.resume` methods
+allow you to pause and resume animations. These methods can be used as
+callbacks for event listeners on UI elements so that your plots can have some
+playback control UI.
+
+
+Sphinx extensions
+=================
+
+``plot_directive`` *caption* option
+-----------------------------------
+
+Captions were previously supported when using the ``plot_directive`` directive
+with an external source file by specifying content::
+
+ .. plot:: path/to/plot.py
+
+ This is the caption for the plot.
+
+The ``:caption:`` option allows specifying the caption for both external::
+
+ .. plot:: path/to/plot.py
+ :caption: This is the caption for the plot.
+
+and inline plots::
+
+ .. plot::
+ :caption: This is a caption for the plot.
+
+ plt.plot([1, 2, 3])
+
+
+Backend-specific improvements
+=============================
+
+Consecutive rasterized draws now merged
+---------------------------------------
+
+Elements of a vector output can be individually set to rasterized, using the
+*rasterized* keyword argument, or `~.artist.Artist.set_rasterized()`. This can
+be useful to reduce file sizes. For figures with multiple raster elements they
+are now automatically merged into a smaller number of bitmaps where this will
+not effect the visual output. For cases with many elements this can result in
+significantly smaller file sizes.
+
+To ensure this happens do not place vector elements between raster ones.
+
+To inhibit this merging set ``Figure.suppressComposite`` to True.
+
+Support raw/rgba frame format in ``FFMpegFileWriter``
+-----------------------------------------------------
+
+When using `.FFMpegFileWriter`, the *frame_format* may now be set to ``"raw"``
+or ``"rgba"``, which may be slightly faster than an image format, as no
+encoding/decoding need take place between Matplotlib and FFmpeg.
+
+nbAgg/WebAgg support middle-click and double-click
+--------------------------------------------------
+
+Double click events are now supported by the nbAgg and WebAgg backends.
+Formerly, WebAgg would report middle-click events as right clicks, but now
+reports the correct button type.
+
+nbAgg support binary communication
+----------------------------------
+
+If the web browser and notebook support binary websockets, nbAgg will now use
+them for slightly improved transfer of figure display.
+
+Indexed color for PNG images in PDF files when possible
+-------------------------------------------------------
+
+When PNG images have 256 colors or fewer, they are converted to indexed color
+before saving them in a PDF. This can result in a significant reduction in file
+size in some cases. This is particularly true for raster data that uses a
+colormap but no interpolation, such as Healpy mollview plots. Currently, this
+is only done for RGB images.
+
+Improved font subsettings in PDF/PS
+-----------------------------------
+
+Font subsetting in PDF and PostScript has been re-written from the embedded
+``ttconv`` C code to Python. Some composite characters and outlines may have
+changed slightly. This fixes ttc subsetting in PDF, and adds support for
+subsetting of type 3 OTF fonts, resulting in smaller files (much smaller when
+using CJK fonts), and avoids running into issues with type 42 embedding and
+certain PDF readers such as Acrobat Reader.
+
+Kerning added to strings in PDFs
+--------------------------------
+
+As with text produced in the Agg backend (see :ref:`the previous what's new
+entry ` for examples), PDFs now include kerning in
+text strings.
+
+Fully-fractional HiDPI in QtAgg
+-------------------------------
+
+Fully-fractional HiDPI (that is, HiDPI ratios that are not whole integers) was
+added in Qt 5.14, and is now supported by the QtAgg backend when using this
+version of Qt or newer.
+
+wxAgg supports fullscreen toggle
+--------------------------------
+
+The wxAgg backend supports toggling fullscreen using the :kbd:`f` shortcut, or
+the manager function `.FigureManagerBase.full_screen_toggle`.
diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst
index 4131fccde0ba..776f477ce4d4 100644
--- a/doc/users/whats_new.rst
+++ b/doc/users/whats_new.rst
@@ -26,4 +26,4 @@ What's new?
next_whats_new/*
.. Be sure to update the version in `exclude_patterns` in conf.py.
-.. include:: prev_whats_new/whats_new_3.3.0.rst
+.. include:: prev_whats_new/whats_new_3.4.0.rst
diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py
index 28f9b747556d..7cc5fade3b2d 100644
--- a/lib/matplotlib/collections.py
+++ b/lib/matplotlib/collections.py
@@ -943,8 +943,11 @@ def update_from(self, other):
artist.Artist.update_from(self, other)
self._antialiaseds = other._antialiaseds
+ self._mapped_colors = other._mapped_colors
+ self._edge_is_mapped = other._edge_is_mapped
self._original_edgecolor = other._original_edgecolor
self._edgecolors = other._edgecolors
+ self._face_is_mapped = other._face_is_mapped
self._original_facecolor = other._original_facecolor
self._facecolors = other._facecolors
self._linewidths = other._linewidths
diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py
index 14b3f78f703b..98e2b5eb790a 100644
--- a/lib/matplotlib/image.py
+++ b/lib/matplotlib/image.py
@@ -1478,9 +1478,10 @@ def imread(fname, format=None):
if isinstance(fname, str):
parsed = parse.urlparse(fname)
if len(parsed.scheme) > 1: # Pillow doesn't handle URLs directly.
- cbook.warn_deprecated(
+ _api.warn_deprecated(
"3.4", message="Directly reading images from URLs is "
- "deprecated. Please open the URL for reading and pass the "
+ "deprecated since %(since)s and will no longer be supported "
+ "%(removal)s. Please open the URL for reading and pass the "
"result to Pillow, e.g. with "
"``PIL.Image.open(urllib.request.urlopen(url))``.")
# hide imports to speed initial import on systems with slow linkers
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index d8495c4f4a13..11091ff893ab 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -52,14 +52,16 @@ def test_get_labels():
@check_figures_equal()
def test_label_loc_vertical(fig_test, fig_ref):
ax = fig_test.subplots()
- sc = ax.scatter([1, 2], [1, 2], c=[1, 2])
+ sc = ax.scatter([1, 2], [1, 2], c=[1, 2], label='scatter')
+ ax.legend()
ax.set_ylabel('Y Label', loc='top')
ax.set_xlabel('X Label', loc='right')
cbar = fig_test.colorbar(sc)
cbar.set_label("Z Label", loc='top')
ax = fig_ref.subplots()
- sc = ax.scatter([1, 2], [1, 2], c=[1, 2])
+ sc = ax.scatter([1, 2], [1, 2], c=[1, 2], label='scatter')
+ ax.legend()
ax.set_ylabel('Y Label', y=1, ha='right')
ax.set_xlabel('X Label', x=1, ha='right')
cbar = fig_ref.colorbar(sc)
@@ -69,14 +71,16 @@ def test_label_loc_vertical(fig_test, fig_ref):
@check_figures_equal()
def test_label_loc_horizontal(fig_test, fig_ref):
ax = fig_test.subplots()
- sc = ax.scatter([1, 2], [1, 2], c=[1, 2])
+ sc = ax.scatter([1, 2], [1, 2], c=[1, 2], label='scatter')
+ ax.legend()
ax.set_ylabel('Y Label', loc='bottom')
ax.set_xlabel('X Label', loc='left')
cbar = fig_test.colorbar(sc, orientation='horizontal')
cbar.set_label("Z Label", loc='left')
ax = fig_ref.subplots()
- sc = ax.scatter([1, 2], [1, 2], c=[1, 2])
+ sc = ax.scatter([1, 2], [1, 2], c=[1, 2], label='scatter')
+ ax.legend()
ax.set_ylabel('Y Label', y=0, ha='left')
ax.set_xlabel('X Label', x=0, ha='left')
cbar = fig_ref.colorbar(sc, orientation='horizontal')
@@ -88,14 +92,16 @@ def test_label_loc_rc(fig_test, fig_ref):
with matplotlib.rc_context({"xaxis.labellocation": "right",
"yaxis.labellocation": "top"}):
ax = fig_test.subplots()
- sc = ax.scatter([1, 2], [1, 2], c=[1, 2])
+ sc = ax.scatter([1, 2], [1, 2], c=[1, 2], label='scatter')
+ ax.legend()
ax.set_ylabel('Y Label')
ax.set_xlabel('X Label')
cbar = fig_test.colorbar(sc, orientation='horizontal')
cbar.set_label("Z Label")
ax = fig_ref.subplots()
- sc = ax.scatter([1, 2], [1, 2], c=[1, 2])
+ sc = ax.scatter([1, 2], [1, 2], c=[1, 2], label='scatter')
+ ax.legend()
ax.set_ylabel('Y Label', y=1, ha='right')
ax.set_xlabel('X Label', x=1, ha='right')
cbar = fig_ref.colorbar(sc, orientation='horizontal')
diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py
index 4326b74260cb..e1c8ecf07bfa 100644
--- a/lib/mpl_toolkits/mplot3d/art3d.py
+++ b/lib/mpl_toolkits/mplot3d/art3d.py
@@ -555,7 +555,7 @@ def set_3d_properties(self, zs, zdir):
# depth-sorted version of that data into the private state used by the
# base collection class in its draw method.
#
- # grab the current sizes and linewidths to preserve them
+ # Grab the current sizes and linewidths to preserve them.
self._sizes3d = self._sizes
self._linewidths3d = self._linewidths
xs, ys, zs = self._offsets3d
@@ -639,8 +639,8 @@ def get_facecolor(self):
def get_edgecolor(self):
# We need this check here to make sure we do not double-apply the depth
- # based alpha shading when the edge color is "face" which means the
- # edge colour should be identical to the face colour.
+ # based alpha shading when the edge color is "face" which means the
+ # edge colour should be identical to the face colour.
if cbook._str_equal(self._edgecolors, 'face'):
return self.get_facecolor()
return self._maybe_depth_shade_and_sort_colors(super().get_edgecolor())
diff --git a/setup.cfg.template b/setup.cfg.template
index f203e7d3d051..6b40f29fc217 100644
--- a/setup.cfg.template
+++ b/setup.cfg.template
@@ -10,7 +10,7 @@ license_files = LICENSE/*
# often, and don't need the space saving/speedup.
#enable_lto = True
# By default, Matplotlib downloads and builds its own copies of FreeType and of
-# of Qhull. You may set the following to True to instead link against a system
+# Qhull. You may set the following to True to instead link against a system
# FreeType/Qhull. As an exception, Matplotlib defaults to the system version
# of FreeType on AIX.
#system_freetype = False
diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py
index 6a334a3bbd1b..d85c895592bc 100644
--- a/tools/cache_zenodo_svg.py
+++ b/tools/cache_zenodo_svg.py
@@ -62,6 +62,8 @@ def _get_xdg_cache_dir():
if __name__ == "__main__":
data = {
+ "v3.4.1": "4649959",
+ "v3.4.0": "4638398",
"v3.3.4": "4475376",
"v3.3.3": "4268928",
"v3.3.2": "4030140",