From 52ac741787019e3f6511a5b0af494508e2a73bcc Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 17 Sep 2022 02:15:05 +0200 Subject: [PATCH 001/262] Backport PR #23912: FIX: only expect FigureCanvas on backend module if using new style --- lib/matplotlib/pyplot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index f5c86de1260b..1e94d90d1534 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -263,7 +263,6 @@ def switch_backend(newbackend): backend_mod = importlib.import_module( cbook._backend_module_name(newbackend)) - canvas_class = backend_mod.FigureCanvas required_framework = _get_required_interactive_framework(backend_mod) if required_framework is not None: @@ -293,6 +292,8 @@ class backend_mod(matplotlib.backend_bases._Backend): # also update backend_mod accordingly; also, per-backend customization of # draw_if_interactive is disabled. if new_figure_manager is None: + # only try to get the canvas class if have opted into the new scheme + canvas_class = backend_mod.FigureCanvas def new_figure_manager_given_figure(num, figure): return canvas_class.new_manager(figure, num) From ab9e12cd1098694aedd6cb36a9dfb84c74720ea9 Mon Sep 17 00:00:00 2001 From: hannah Date: Sun, 18 Sep 2022 13:20:59 -0400 Subject: [PATCH 002/262] Backport PR #23929: DOC: add animation example to show animated subplots --- examples/animation/multiple_axes.py | 79 +++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 examples/animation/multiple_axes.py diff --git a/examples/animation/multiple_axes.py b/examples/animation/multiple_axes.py new file mode 100644 index 000000000000..1fdc545d480d --- /dev/null +++ b/examples/animation/multiple_axes.py @@ -0,0 +1,79 @@ +""" +======================= +Multiple axes animation +======================= + +This example showcases: + +- how animation across multiple subplots works, +- using a figure artist in the animation. +""" + +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.animation as animation +from matplotlib.patches import ConnectionPatch + +fig, (axl, axr) = plt.subplots( + ncols=2, + sharey=True, + figsize=(6, 2), + gridspec_kw=dict(width_ratios=[1, 3], wspace=0), +) +axl.set_aspect(1) +axr.set_box_aspect(1 / 3) +axr.yaxis.set_visible(False) +axr.xaxis.set_ticks([0, np.pi, 2 * np.pi], ["0", r"$\pi$", r"$2\pi$"]) + +# draw circle with initial point in left Axes +x = np.linspace(0, 2 * np.pi, 50) +axl.plot(np.cos(x), np.sin(x), "k", lw=0.3) +point, = axl.plot(0, 0, "o") + +# draw full curve to set view limits in right Axes +sine, = axr.plot(x, np.sin(x)) + +# draw connecting line between both graphs +con = ConnectionPatch( + (1, 0), + (0, 0), + "data", + "data", + axesA=axl, + axesB=axr, + color="C0", + ls="dotted", +) +fig.add_artist(con) + + +def animate(i): + pos = np.cos(i), np.sin(i) + point.set_data(*pos) + x = np.linspace(0, i, int(i * 25 / np.pi)) + sine.set_data(x, np.sin(x)) + con.xy1 = pos + con.xy2 = i, pos[1] + return point, sine, con + + +ani = animation.FuncAnimation( + fig, + animate, + interval=50, + blit=False, # blitting can't be used with Figure artists + frames=x, + repeat_delay=100, +) + +plt.show() + +############################################################################# +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.patches.ConnectionPatch` +# - `matplotlib.animation.FuncAnimation` From e49b10c7eb6c1ead8ed91f9f16b789a5af1f5af1 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 18 Sep 2022 22:39:38 +0200 Subject: [PATCH 003/262] Backport PR #23919: DOC: remove dead "Show Source" links --- doc/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 67514c2d4057..112d9fdaf22c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -381,7 +381,8 @@ def js_tag_with_cache_busting(js): "logo": {"link": "index", "image_light": "images/logo2.svg", "image_dark": "images/logo_dark.svg"}, - "navbar_end": ["theme-switcher", "version-switcher", "mpl_icon_links"] + "navbar_end": ["theme-switcher", "version-switcher", "mpl_icon_links"], + "page_sidebar_items": "page-toc.html", } include_analytics = is_release_build if include_analytics: From 01f7b712c281b07d71905ae314474ed1fae9b3e3 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 19 Sep 2022 09:25:27 +0200 Subject: [PATCH 004/262] Backport PR #23941: consistent notation for minor/patch branches --- doc/devel/coding_guide.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/devel/coding_guide.rst b/doc/devel/coding_guide.rst index d3931b50fb53..cddb13539444 100644 --- a/doc/devel/coding_guide.rst +++ b/doc/devel/coding_guide.rst @@ -134,13 +134,13 @@ Milestones * Set the milestone according to these rules: * *New features and API changes* are milestoned for the next minor release - ``v3.X.0``. + ``v3.N.0``. * *Bugfixes and docstring changes* are milestoned for the next patch - release ``v3.X.Y`` + release ``v3.N.M`` * *Documentation changes* (all .rst files and examples) are milestoned - ``v3.X-doc`` + ``v3.N-doc`` If multiple rules apply, choose the first matching from the above list. From b92b6b9ebce3ecf8f283427542bf3414b7464072 Mon Sep 17 00:00:00 2001 From: hannah Date: Mon, 19 Sep 2022 09:32:24 -0400 Subject: [PATCH 005/262] Backport PR #23951: DOC: Make animation continuous --- examples/animation/dynamic_image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/animation/dynamic_image.py b/examples/animation/dynamic_image.py index 5543da039639..cbec62607b2c 100644 --- a/examples/animation/dynamic_image.py +++ b/examples/animation/dynamic_image.py @@ -23,8 +23,8 @@ def f(x, y): # each frame ims = [] for i in range(60): - x += np.pi / 15. - y += np.pi / 20. + x += np.pi / 15 + y += np.pi / 30 im = ax.imshow(f(x, y), animated=True) if i == 0: ax.imshow(f(x, y)) # show an initial one first From eac65ff9cbdc29034246c4d5200f329b0191a1e3 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 19 Sep 2022 16:43:36 -0400 Subject: [PATCH 006/262] Backport PR #23947: Fix building on MINGW --- src/_tkagg.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index bbca8e8d066c..663c06fd0474 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -231,13 +231,13 @@ bool load_tcl_tk(T lib) { // Try to fill Tcl/Tk global vars with function pointers. Return whether // all of them have been filled. - if (void* ptr = dlsym(lib, "Tcl_SetVar")) { + if (auto ptr = dlsym(lib, "Tcl_SetVar")) { TCL_SETVAR = (Tcl_SetVar_t)ptr; } - if (void* ptr = dlsym(lib, "Tk_FindPhoto")) { + if (auto ptr = dlsym(lib, "Tk_FindPhoto")) { TK_FIND_PHOTO = (Tk_FindPhoto_t)ptr; } - if (void* ptr = dlsym(lib, "Tk_PhotoPutBlock")) { + if (auto ptr = dlsym(lib, "Tk_PhotoPutBlock")) { TK_PHOTO_PUT_BLOCK = (Tk_PhotoPutBlock_t)ptr; } return TCL_SETVAR && TK_FIND_PHOTO && TK_PHOTO_PUT_BLOCK; From a186734892c53282ef684941fa3af7950d0addcd Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 20 Sep 2022 15:37:04 +0200 Subject: [PATCH 007/262] Backport PR #23957: Bump pypa/cibuildwheel from 2.9.0 to 2.10.1 --- .github/workflows/cibuildwheel.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 27a5e3a6014d..64f345c3a3f4 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -53,7 +53,7 @@ jobs: fetch-depth: 0 - name: Build wheels for CPython 3.11 - uses: pypa/cibuildwheel@v2.9.0 + uses: pypa/cibuildwheel@v2.10.1 env: CIBW_BUILD: "cp311-*" CIBW_SKIP: "*-musllinux*" @@ -66,7 +66,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.10 - uses: pypa/cibuildwheel@v2.9.0 + uses: pypa/cibuildwheel@v2.10.1 env: CIBW_BUILD: "cp310-*" CIBW_SKIP: "*-musllinux*" @@ -79,7 +79,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.9 - uses: pypa/cibuildwheel@v2.9.0 + uses: pypa/cibuildwheel@v2.10.1 env: CIBW_BUILD: "cp39-*" CIBW_SKIP: "*-musllinux*" @@ -92,7 +92,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.8 - uses: pypa/cibuildwheel@v2.9.0 + uses: pypa/cibuildwheel@v2.10.1 env: CIBW_BUILD: "cp38-*" CIBW_SKIP: "*-musllinux*" @@ -105,7 +105,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for PyPy - uses: pypa/cibuildwheel@v2.9.0 + uses: pypa/cibuildwheel@v2.10.1 env: CIBW_BUILD: "pp38-* pp39-*" CIBW_SKIP: "*-musllinux*" From 899983cf2a118946624536426b8807a2517b6660 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Tue, 20 Sep 2022 10:37:41 -0400 Subject: [PATCH 008/262] Backport PR #23930: Fix edge color, links, wording; closes matplotlib/matplotlib#23895 --- examples/mplot3d/contour3d_3.py | 20 +++++++++----------- examples/mplot3d/contourf3d_2.py | 20 +++++++++----------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/examples/mplot3d/contour3d_3.py b/examples/mplot3d/contour3d_3.py index 4b8c5ed77d71..c6a599328697 100644 --- a/examples/mplot3d/contour3d_3.py +++ b/examples/mplot3d/contour3d_3.py @@ -1,30 +1,28 @@ """ -======================================== -Projecting contour profiles onto a graph -======================================== - +===================================== +Project contour profiles onto a graph +===================================== Demonstrates displaying a 3D surface while also projecting contour 'profiles' onto the 'walls' of the graph. - -See contourf3d_demo2 for the filled version. +See :doc:`contourf3d_2` for the filled version. """ from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt -from matplotlib import cm ax = plt.figure().add_subplot(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) # Plot the 3D surface -ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3) +ax.plot_surface(X, Y, Z, edgecolor='royalblue', lw=0.5, rstride=8, cstride=8, + alpha=0.3) # Plot projections of the contours for each dimension. By choosing offsets # that match the appropriate axes limits, the projected contours will sit on # the 'walls' of the graph. -ax.contour(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm) -ax.contour(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm) -ax.contour(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm) +ax.contour(X, Y, Z, zdir='z', offset=-100, cmap='coolwarm') +ax.contour(X, Y, Z, zdir='x', offset=-40, cmap='coolwarm') +ax.contour(X, Y, Z, zdir='y', offset=40, cmap='coolwarm') ax.set(xlim=(-40, 40), ylim=(-40, 40), zlim=(-100, 100), xlabel='X', ylabel='Y', zlabel='Z') diff --git a/examples/mplot3d/contourf3d_2.py b/examples/mplot3d/contourf3d_2.py index e550d0ee5933..d0cb6d4ab79c 100644 --- a/examples/mplot3d/contourf3d_2.py +++ b/examples/mplot3d/contourf3d_2.py @@ -1,30 +1,28 @@ """ -====================================== -Projecting filled contour onto a graph -====================================== - +=================================== +Project filled contour onto a graph +=================================== Demonstrates displaying a 3D surface while also projecting filled contour 'profiles' onto the 'walls' of the graph. - -See contour3d_demo2 for the unfilled version. +See :doc:`contour3d_3` for the unfilled version. """ from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt -from matplotlib import cm ax = plt.figure().add_subplot(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) # Plot the 3D surface -ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3) +ax.plot_surface(X, Y, Z, edgecolor='royalblue', lw=0.5, rstride=8, cstride=8, + alpha=0.3) # Plot projections of the contours for each dimension. By choosing offsets # that match the appropriate axes limits, the projected contours will sit on # the 'walls' of the graph -ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm) -ax.contourf(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm) -ax.contourf(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm) +ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap='coolwarm') +ax.contourf(X, Y, Z, zdir='x', offset=-40, cmap='coolwarm') +ax.contourf(X, Y, Z, zdir='y', offset=40, cmap='coolwarm') ax.set(xlim=(-40, 40), ylim=(-40, 40), zlim=(-100, 100), xlabel='X', ylabel='Y', zlabel='Z') From 90b9497c5f966b198ae50f459a6bb180ea11f4b8 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 21 Sep 2022 00:18:00 +0200 Subject: [PATCH 009/262] Backport PR #23906: Edit mplot3d examples for correctness and consistency --- examples/mplot3d/2dcollections3d.py | 2 +- examples/mplot3d/contour3d.py | 6 +++--- examples/mplot3d/contour3d_2.py | 8 ++++---- examples/mplot3d/contourf3d.py | 8 ++++---- examples/mplot3d/hist3d.py | 2 +- examples/mplot3d/lines3d.py | 2 +- examples/mplot3d/lorenz_attractor.py | 2 +- examples/mplot3d/mixed_subplots.py | 6 +++--- examples/mplot3d/offset.py | 2 +- examples/mplot3d/rotate_axes3d_sgskip.py | 2 +- examples/mplot3d/surface3d.py | 4 ++-- examples/mplot3d/text3d.py | 8 ++++---- examples/mplot3d/trisurf3d_2.py | 2 +- examples/mplot3d/voxels_numpy_logo.py | 2 +- examples/mplot3d/voxels_rgb.py | 2 +- examples/mplot3d/wire3d_animation_sgskip.py | 6 +++--- examples/mplot3d/wire3d_zero_stride.py | 2 +- 17 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples/mplot3d/2dcollections3d.py b/examples/mplot3d/2dcollections3d.py index 5760d429775e..96183ddb9912 100644 --- a/examples/mplot3d/2dcollections3d.py +++ b/examples/mplot3d/2dcollections3d.py @@ -3,7 +3,7 @@ Plot 2D data on 3D plot ======================= -Demonstrates using ax.plot's zdir keyword to plot 2D data on +Demonstrates using ax.plot's *zdir* keyword to plot 2D data on selective axes of a 3D plot. """ diff --git a/examples/mplot3d/contour3d.py b/examples/mplot3d/contour3d.py index 2b0a2872d0cc..7b96980e3a73 100644 --- a/examples/mplot3d/contour3d.py +++ b/examples/mplot3d/contour3d.py @@ -1,7 +1,7 @@ """ -================================================== -Demonstrates plotting contour (level) curves in 3D -================================================== +================================= +Plot contour (level) curves in 3D +================================= This is like a contour plot in 2D except that the ``f(x, y)=c`` curve is plotted on the plane ``z=c``. diff --git a/examples/mplot3d/contour3d_2.py b/examples/mplot3d/contour3d_2.py index b6478bc79142..6dbc62eb9427 100644 --- a/examples/mplot3d/contour3d_2.py +++ b/examples/mplot3d/contour3d_2.py @@ -1,9 +1,9 @@ """ -============================================================================ -Demonstrates plotting contour (level) curves in 3D using the extend3d option -============================================================================ +=========================================================== +Plot contour (level) curves in 3D using the extend3d option +=========================================================== -This modification of the contour3d_demo example uses extend3d=True to +This modification of the :doc:`contour3d` example uses ``extend3d=True`` to extend the curves vertically into 'ribbons'. """ diff --git a/examples/mplot3d/contourf3d.py b/examples/mplot3d/contourf3d.py index c15ecdcfd6c0..6f0261ad0908 100644 --- a/examples/mplot3d/contourf3d.py +++ b/examples/mplot3d/contourf3d.py @@ -3,11 +3,11 @@ Filled contours =============== -contourf differs from contour in that it creates filled contours, ie. -a discrete number of colours are used to shade the domain. +`.Axes3D.contourf` differs from `.Axes3D.contour` in that it creates filled +contours, i.e. a discrete number of colours are used to shade the domain. -This is like a contourf plot in 2D except that the shaded region corresponding -to the level c is graphed on the plane z=c. +This is like a `.Axes.contourf` plot in 2D except that the shaded region +corresponding to the level c is graphed on the plane ``z=c``. """ from mpl_toolkits.mplot3d import axes3d diff --git a/examples/mplot3d/hist3d.py b/examples/mplot3d/hist3d.py index 6577a010c14a..e602f7f1e6c5 100644 --- a/examples/mplot3d/hist3d.py +++ b/examples/mplot3d/hist3d.py @@ -3,7 +3,7 @@ Create 3D histogram of 2D data ============================== -Demo of a histogram for 2 dimensional data as a bar graph in 3D. +Demo of a histogram for 2D data as a bar graph in 3D. """ import matplotlib.pyplot as plt diff --git a/examples/mplot3d/lines3d.py b/examples/mplot3d/lines3d.py index f7578d8657b4..c974bcbdff8d 100644 --- a/examples/mplot3d/lines3d.py +++ b/examples/mplot3d/lines3d.py @@ -1,6 +1,6 @@ """ ================ -Parametric Curve +Parametric curve ================ This example demonstrates plotting a parametric curve in 3D. diff --git a/examples/mplot3d/lorenz_attractor.py b/examples/mplot3d/lorenz_attractor.py index 7162c12d2dce..aad08a16439e 100644 --- a/examples/mplot3d/lorenz_attractor.py +++ b/examples/mplot3d/lorenz_attractor.py @@ -1,6 +1,6 @@ """ ================ -Lorenz Attractor +Lorenz attractor ================ This is an example of plotting Edward Lorenz's 1963 `"Deterministic Nonperiodic diff --git a/examples/mplot3d/mixed_subplots.py b/examples/mplot3d/mixed_subplots.py index df981ceee4ea..1ab91278a1d9 100644 --- a/examples/mplot3d/mixed_subplots.py +++ b/examples/mplot3d/mixed_subplots.py @@ -1,7 +1,7 @@ """ -================================= -2D and 3D *Axes* in same *Figure* -================================= +============================= +2D and 3D axes in same figure +============================= This example shows a how to plot a 2D and 3D plot on the same figure. """ diff --git a/examples/mplot3d/offset.py b/examples/mplot3d/offset.py index 56a14d69fa98..00adcc2f236d 100644 --- a/examples/mplot3d/offset.py +++ b/examples/mplot3d/offset.py @@ -1,6 +1,6 @@ """ ========================= -Automatic Text Offsetting +Automatic text offsetting ========================= This example demonstrates mplot3d's offset text display. diff --git a/examples/mplot3d/rotate_axes3d_sgskip.py b/examples/mplot3d/rotate_axes3d_sgskip.py index 8d27873c3b74..8967277ea5d7 100644 --- a/examples/mplot3d/rotate_axes3d_sgskip.py +++ b/examples/mplot3d/rotate_axes3d_sgskip.py @@ -3,7 +3,7 @@ Rotating a 3D plot ================== -A very simple animation of a rotating 3D plot about all 3 axes. +A very simple animation of a rotating 3D plot about all three axes. See :doc:`wire3d_animation_sgskip` for another example of animating a 3D plot. diff --git a/examples/mplot3d/surface3d.py b/examples/mplot3d/surface3d.py index 6a82631fc1ed..07019cb15e31 100644 --- a/examples/mplot3d/surface3d.py +++ b/examples/mplot3d/surface3d.py @@ -4,9 +4,9 @@ ===================== Demonstrates plotting a 3D surface colored with the coolwarm colormap. -The surface is made opaque by using antialiased=False. +The surface is made opaque by using ``antialiased=False``. -Also demonstrates using the LinearLocator and custom formatting for the +Also demonstrates using the `.LinearLocator` and custom formatting for the z axis tick labels. """ diff --git a/examples/mplot3d/text3d.py b/examples/mplot3d/text3d.py index 7f6a2858eb1f..922d161a9f89 100644 --- a/examples/mplot3d/text3d.py +++ b/examples/mplot3d/text3d.py @@ -7,10 +7,10 @@ Functionality shown: -- Using the text function with three types of 'zdir' values: None, an axis - name (ex. 'x'), or a direction tuple (ex. (1, 1, 0)). -- Using the text function with the color keyword. -- Using the text2D function to place text on a fixed position on the ax +- Using the `~.Axes3D.text` function with three types of *zdir* values: None, + an axis name (ex. 'x'), or a direction tuple (ex. (1, 1, 0)). +- Using the `~.Axes3D.text` function with the color keyword. +- Using the `.text2D` function to place text on a fixed position on the ax object. """ diff --git a/examples/mplot3d/trisurf3d_2.py b/examples/mplot3d/trisurf3d_2.py index 728698b7af69..8ed354d5e5e6 100644 --- a/examples/mplot3d/trisurf3d_2.py +++ b/examples/mplot3d/trisurf3d_2.py @@ -6,7 +6,7 @@ Two additional examples of plotting surfaces with triangular mesh. The first demonstrates use of plot_trisurf's triangles argument, and the -second sets a Triangulation object's mask and passes the object directly +second sets a `.Triangulation` object's mask and passes the object directly to plot_trisurf. """ diff --git a/examples/mplot3d/voxels_numpy_logo.py b/examples/mplot3d/voxels_numpy_logo.py index 8b790d073988..34eb48dcbe8a 100644 --- a/examples/mplot3d/voxels_numpy_logo.py +++ b/examples/mplot3d/voxels_numpy_logo.py @@ -1,6 +1,6 @@ """ =============================== -3D voxel plot of the numpy logo +3D voxel plot of the NumPy logo =============================== Demonstrates using `.Axes3D.voxels` with uneven coordinates. diff --git a/examples/mplot3d/voxels_rgb.py b/examples/mplot3d/voxels_rgb.py index 31bfcbca15a9..da27ad11f752 100644 --- a/examples/mplot3d/voxels_rgb.py +++ b/examples/mplot3d/voxels_rgb.py @@ -1,6 +1,6 @@ """ ========================================== -3D voxel / volumetric plot with rgb colors +3D voxel / volumetric plot with RGB colors ========================================== Demonstrates using `.Axes3D.voxels` to visualize parts of a color space. diff --git a/examples/mplot3d/wire3d_animation_sgskip.py b/examples/mplot3d/wire3d_animation_sgskip.py index b4f681e778f5..bfc76661ffd0 100644 --- a/examples/mplot3d/wire3d_animation_sgskip.py +++ b/examples/mplot3d/wire3d_animation_sgskip.py @@ -1,7 +1,7 @@ """ -============================= -Animating a 3D wireframe plot -============================= +=========================== +Animate a 3D wireframe plot +=========================== A very simple "animation" of a 3D plot. See also :doc:`rotate_axes3d_sgskip`. diff --git a/examples/mplot3d/wire3d_zero_stride.py b/examples/mplot3d/wire3d_zero_stride.py index 1ba406b753f4..f4c679300820 100644 --- a/examples/mplot3d/wire3d_zero_stride.py +++ b/examples/mplot3d/wire3d_zero_stride.py @@ -3,7 +3,7 @@ 3D wireframe plots in one direction =================================== -Demonstrates that setting rstride or cstride to 0 causes wires to not be +Demonstrates that setting *rstride* or *cstride* to 0 causes wires to not be generated in the corresponding direction. """ From 97ff8a9761af6ca4fbfc777c3a649062f354fdda Mon Sep 17 00:00:00 2001 From: hannah Date: Wed, 21 Sep 2022 13:22:36 -0400 Subject: [PATCH 010/262] Backport PR #23975: Reword docstring of reset_position. --- lib/matplotlib/axes/_base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index ebe1ef7911d4..4f805e017741 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1108,8 +1108,9 @@ def reset_position(self): """ Reset the active position to the original position. - This resets the possible position change due to aspect constraints. - For an explanation of the positions see `.set_position`. + This undoes changes to the active position (as defined in + `.set_position`) which may have been performed to satisfy fixed-aspect + constraints. """ for ax in self._twinned_axes.get_siblings(self): pos = ax.get_position(original=True) From 1455f9f0ee70f886a00fe335d7f7da4bbf001184 Mon Sep 17 00:00:00 2001 From: hannah Date: Wed, 21 Sep 2022 17:53:56 -0400 Subject: [PATCH 011/262] Backport PR #23980: DOC: Move Quick Start Tutorial to first position --- doc/sphinxext/gallery_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py index 589fed453f06..62b7803d0f8b 100644 --- a/doc/sphinxext/gallery_order.py +++ b/doc/sphinxext/gallery_order.py @@ -50,9 +50,9 @@ def __call__(self, item): list_all = [ # **Tutorials** # introductory - "usage", "pyplot", "sample_plots", "images", "lifecycle", "customizing", + "quick_start", "pyplot", "images", "lifecycle", "customizing", # intermediate - "artists", "legend_guide", "color_cycle", "gridspec", + "artists", "legend_guide", "color_cycle", "constrainedlayout_guide", "tight_layout_guide", # advanced # text From ef349f3db751c2b7de05e35e36f4f1caf291b55a Mon Sep 17 00:00:00 2001 From: hannah Date: Wed, 21 Sep 2022 17:53:56 -0400 Subject: [PATCH 012/262] Backport PR #23980: DOC: Move Quick Start Tutorial to first position --- doc/sphinxext/gallery_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py index 589fed453f06..62b7803d0f8b 100644 --- a/doc/sphinxext/gallery_order.py +++ b/doc/sphinxext/gallery_order.py @@ -50,9 +50,9 @@ def __call__(self, item): list_all = [ # **Tutorials** # introductory - "usage", "pyplot", "sample_plots", "images", "lifecycle", "customizing", + "quick_start", "pyplot", "images", "lifecycle", "customizing", # intermediate - "artists", "legend_guide", "color_cycle", "gridspec", + "artists", "legend_guide", "color_cycle", "constrainedlayout_guide", "tight_layout_guide", # advanced # text From 27523ad39c121ddc3b234b66aec8c6241b37d991 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 22 Sep 2022 19:50:15 -0700 Subject: [PATCH 013/262] Backport PR #23987: FIX: do not set constrained layout on false-y values --- lib/matplotlib/figure.py | 5 ++++- lib/matplotlib/tests/test_constrainedlayout.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 5bbb786984d2..447f508194a1 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2426,9 +2426,12 @@ def __init__(self, if isinstance(tight_layout, dict): self.get_layout_engine().set(**tight_layout) elif constrained_layout is not None: - self.set_layout_engine(layout='constrained') if isinstance(constrained_layout, dict): + self.set_layout_engine(layout='constrained') self.get_layout_engine().set(**constrained_layout) + elif constrained_layout: + self.set_layout_engine(layout='constrained') + else: # everything is None, so use default: self.set_layout_engine(layout=layout) diff --git a/lib/matplotlib/tests/test_constrainedlayout.py b/lib/matplotlib/tests/test_constrainedlayout.py index 35eb850fcd70..64906b74c3ff 100644 --- a/lib/matplotlib/tests/test_constrainedlayout.py +++ b/lib/matplotlib/tests/test_constrainedlayout.py @@ -656,3 +656,14 @@ def test_compressed1(): pos = axs[1, 2].get_position() np.testing.assert_allclose(pos.x1, 0.8618, atol=1e-3) np.testing.assert_allclose(pos.y0, 0.1934, atol=1e-3) + + +@pytest.mark.parametrize('arg, state', [ + (True, True), + (False, False), + ({}, True), + ({'rect': None}, True) +]) +def test_set_constrained_layout(arg, state): + fig, ax = plt.subplots(constrained_layout=arg) + assert fig.get_constrained_layout() is state From c6339567de1cbe1a75e97020ef93388364b0261b Mon Sep 17 00:00:00 2001 From: erykoff Date: Thu, 22 Sep 2022 21:39:13 -0700 Subject: [PATCH 014/262] Backport PR #23944: FIX: ValueError when hexbin is run with empty arrays and log scaling. --- lib/matplotlib/axes/_axes.py | 4 +++- lib/matplotlib/tests/test_axes.py | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 6327dde85276..c578765bfa1c 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4927,7 +4927,9 @@ def reduce_C_function(C: array) -> float # autoscale the norm with current accum values if it hasn't been set if norm is not None: if norm.vmin is None and norm.vmax is None: - norm.autoscale(accum) + norm.autoscale_None(accum) + norm.vmin = np.ma.masked if norm.vmin is None else norm.vmin + norm.vmax = np.ma.masked if norm.vmax is None else norm.vmax if bins is not None: if not np.iterable(bins): diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 628f9542aa42..b35b3feacf18 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -901,6 +901,14 @@ def test_hexbin_empty(): ax.hexbin([], []) +@image_comparison(['hexbin_empty.png'], remove_text=True) +def test_hexbin_log_empty(): + # From #23922: creating hexbin with log scaling from empty + # dataset raises ValueError + ax = plt.gca() + ax.hexbin([], [], bins='log') + + def test_hexbin_pickable(): # From #1973: Test that picking a hexbin collection works fig, ax = plt.subplots() From e9226ecca10638f39144b820d0d0e0c1bef6bb2d Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 23 Sep 2022 02:45:08 -0400 Subject: [PATCH 015/262] Backport PR #23978: DOC: Suppress IPython output in examples and tutorials where not needed --- doc/conf.py | 1 + tutorials/intermediate/artists.py | 1 + tutorials/intermediate/autoscale.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 112d9fdaf22c..5aa58a3aca5a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -198,6 +198,7 @@ def matplotlib_reduced_latex_scraper(block, block_vars, gallery_conf, 'subsection_order': gallery_order.sectionorder, 'thumbnail_size': (320, 224), 'within_subsection_order': gallery_order.subsectionorder, + 'capture_repr': (), } mathmpl_fontsize = 11.0 diff --git a/tutorials/intermediate/artists.py b/tutorials/intermediate/artists.py index f76c62d8462c..22793ddd5fd0 100644 --- a/tutorials/intermediate/artists.py +++ b/tutorials/intermediate/artists.py @@ -115,6 +115,7 @@ class in the Matplotlib API, and the one you will be working with most Try creating the figure below. """ +# sphinx_gallery_capture_repr = ('__repr__',) import numpy as np import matplotlib.pyplot as plt diff --git a/tutorials/intermediate/autoscale.py b/tutorials/intermediate/autoscale.py index 0f4dda87d183..3b563510aa1f 100644 --- a/tutorials/intermediate/autoscale.py +++ b/tutorials/intermediate/autoscale.py @@ -26,7 +26,7 @@ # ------- # The default margin around the data limits is 5%: -ax.margins() +print(ax.margins()) ############################################################################### # The margins can be made larger using `~matplotlib.axes.Axes.margins`: From 0524e4caeed0dfc5c7889043b4e5d29c3624f844 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 24 Sep 2022 04:55:18 -0400 Subject: [PATCH 016/262] Backport PR #23964: Fix issue with empty line in ps backend --- lib/matplotlib/backends/backend_ps.py | 5 +++-- lib/matplotlib/tests/test_backend_ps.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index f209e811f18b..67829c216f9a 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -665,8 +665,9 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): curr_stream[1].append( (item.x, item.ft_object.get_glyph_name(item.glyph_idx)) ) - # append the last entry - stream.append(curr_stream) + # append the last entry if exists + if curr_stream: + stream.append(curr_stream) self.set_color(*gc.get_rgb()) diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index a3a5a52e7977..a151dc4c4c90 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -254,6 +254,15 @@ def test_linedash(): assert buf.tell() > 0 +def test_empty_line(): + # Smoke-test for gh#23954 + figure = Figure() + figure.text(0.5, 0.5, "\nfoo\n\n") + buf = io.BytesIO() + figure.savefig(buf, format='eps') + figure.savefig(buf, format='ps') + + def test_no_duplicate_definition(): fig = Figure() From f5e6927586e2b67ccbd45e24c71d56c67ddb5820 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 25 Sep 2022 21:28:35 +0200 Subject: [PATCH 017/262] Backport PR #24004: Increase consistency in tutorials and examples --- examples/color/color_demo.py | 4 ++-- examples/color/custom_cmap.py | 2 +- examples/lines_bars_and_markers/cohere.py | 6 +++--- examples/lines_bars_and_markers/csd_demo.py | 2 +- examples/pyplots/fig_axes_labels_simple.py | 6 +++--- examples/pyplots/pyplot_mathtext.py | 4 ++-- tutorials/advanced/path_tutorial.py | 16 ++++++++-------- tutorials/intermediate/artists.py | 6 +++--- .../intermediate/constrainedlayout_guide.py | 2 +- tutorials/introductory/pyplot.py | 6 ++++-- tutorials/text/text_intro.py | 12 ++++++------ 11 files changed, 34 insertions(+), 32 deletions(-) diff --git a/examples/color/color_demo.py b/examples/color/color_demo.py index f46f52507352..8a161442184b 100644 --- a/examples/color/color_demo.py +++ b/examples/color/color_demo.py @@ -48,9 +48,9 @@ # 3) gray level string: ax.set_title('Voltage vs. time chart', color='0.7') # 4) single letter color string -ax.set_xlabel('time (s)', color='c') +ax.set_xlabel('Time [s]', color='c') # 5) a named color: -ax.set_ylabel('voltage (mV)', color='peachpuff') +ax.set_ylabel('Voltage [mV]', color='peachpuff') # 6) a named xkcd color: ax.plot(t, s, 'xkcd:crimson') # 7) Cn notation: diff --git a/examples/color/custom_cmap.py b/examples/color/custom_cmap.py index 21354fc3fd93..a99127d972e6 100644 --- a/examples/color/custom_cmap.py +++ b/examples/color/custom_cmap.py @@ -42,7 +42,7 @@ If, as in this example, there are no discontinuities in the r, g, and b components, then it is quite simple: the second and third element of -each tuple, above, is the same--call it "``y``". The first element ("``x``") +each tuple, above, is the same -- call it "``y``". The first element ("``x``") defines interpolation intervals over the full range of 0 to 1, and it must span that whole range. In other words, the values of ``x`` divide the 0-to-1 range into a set of segments, and ``y`` gives the end-point color diff --git a/examples/lines_bars_and_markers/cohere.py b/examples/lines_bars_and_markers/cohere.py index 370149695398..7881a0a31b1e 100644 --- a/examples/lines_bars_and_markers/cohere.py +++ b/examples/lines_bars_and_markers/cohere.py @@ -16,19 +16,19 @@ nse1 = np.random.randn(len(t)) # white noise 1 nse2 = np.random.randn(len(t)) # white noise 2 -# Two signals with a coherent part at 10Hz and a random part +# Two signals with a coherent part at 10 Hz and a random part s1 = np.sin(2 * np.pi * 10 * t) + nse1 s2 = np.sin(2 * np.pi * 10 * t) + nse2 fig, axs = plt.subplots(2, 1) axs[0].plot(t, s1, t, s2) axs[0].set_xlim(0, 2) -axs[0].set_xlabel('time') +axs[0].set_xlabel('Time') axs[0].set_ylabel('s1 and s2') axs[0].grid(True) cxy, f = axs[1].cohere(s1, s2, 256, 1. / dt) -axs[1].set_ylabel('coherence') +axs[1].set_ylabel('Coherence') fig.tight_layout() plt.show() diff --git a/examples/lines_bars_and_markers/csd_demo.py b/examples/lines_bars_and_markers/csd_demo.py index d4d1e1d7a967..8894333f94d0 100644 --- a/examples/lines_bars_and_markers/csd_demo.py +++ b/examples/lines_bars_and_markers/csd_demo.py @@ -33,7 +33,7 @@ ax1.plot(t, s1, t, s2) ax1.set_xlim(0, 5) -ax1.set_xlabel('time') +ax1.set_xlabel('Time') ax1.set_ylabel('s1 and s2') ax1.grid(True) diff --git a/examples/pyplots/fig_axes_labels_simple.py b/examples/pyplots/fig_axes_labels_simple.py index 41423b0b4845..353f09477dfd 100644 --- a/examples/pyplots/fig_axes_labels_simple.py +++ b/examples/pyplots/fig_axes_labels_simple.py @@ -11,8 +11,8 @@ fig = plt.figure() fig.subplots_adjust(top=0.8) ax1 = fig.add_subplot(211) -ax1.set_ylabel('volts') -ax1.set_title('a sine wave') +ax1.set_ylabel('Voltage [V]') +ax1.set_title('A sine wave') t = np.arange(0.0, 1.0, 0.01) s = np.sin(2 * np.pi * t) @@ -23,7 +23,7 @@ ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3]) n, bins, patches = ax2.hist(np.random.randn(1000), 50) -ax2.set_xlabel('time (s)') +ax2.set_xlabel('Time [s]') plt.show() diff --git a/examples/pyplots/pyplot_mathtext.py b/examples/pyplots/pyplot_mathtext.py index af4db39a4e95..a62dd6d95da0 100644 --- a/examples/pyplots/pyplot_mathtext.py +++ b/examples/pyplots/pyplot_mathtext.py @@ -16,8 +16,8 @@ plt.text(1, -0.6, r'$\sum_{i=0}^\infty x_i$', fontsize=20) plt.text(0.6, 0.6, r'$\mathcal{A}\mathrm{sin}(2 \omega t)$', fontsize=20) -plt.xlabel('time (s)') -plt.ylabel('volts (mV)') +plt.xlabel('Time [s]') +plt.ylabel('Voltage [mV]') plt.show() ############################################################################# diff --git a/tutorials/advanced/path_tutorial.py b/tutorials/advanced/path_tutorial.py index 19632ce42964..70bb5998cecb 100644 --- a/tutorials/advanced/path_tutorial.py +++ b/tutorials/advanced/path_tutorial.py @@ -76,11 +76,11 @@ # ============== # # Some of the path components require multiple vertices to specify them: -# for example CURVE 3 is a `bézier +# for example CURVE 3 is a `Bézier # `_ curve with one # control point and one end point, and CURVE4 has three vertices for the # two control points and the end point. The example below shows a -# CURVE4 Bézier spline -- the bézier curve will be contained in the +# CURVE4 Bézier spline -- the Bézier curve will be contained in the # convex hull of the start point, the two control points, and the end # point @@ -139,8 +139,8 @@ # for each histogram bar: the rectangle width is the bin width and the # rectangle height is the number of datapoints in that bin. First we'll # create some random normally distributed data and compute the -# histogram. Because numpy returns the bin edges and not centers, the -# length of ``bins`` is 1 greater than the length of ``n`` in the +# histogram. Because NumPy returns the bin edges and not centers, the +# length of ``bins`` is one greater than the length of ``n`` in the # example below:: # # # histogram our data with numpy @@ -159,10 +159,10 @@ # # Now we have to construct our compound path, which will consist of a # series of ``MOVETO``, ``LINETO`` and ``CLOSEPOLY`` for each rectangle. -# For each rectangle, we need 5 vertices: 1 for the ``MOVETO``, 3 for -# the ``LINETO``, and 1 for the ``CLOSEPOLY``. As indicated in the -# table above, the vertex for the closepoly is ignored but we still need -# it to keep the codes aligned with the vertices:: +# For each rectangle, we need five vertices: one for the ``MOVETO``, +# three for the ``LINETO``, and one for the ``CLOSEPOLY``. As indicated +# in the table above, the vertex for the closepoly is ignored but we still +# need it to keep the codes aligned with the vertices:: # # nverts = nrects*(1+3+1) # verts = np.zeros((nverts, 2)) diff --git a/tutorials/intermediate/artists.py b/tutorials/intermediate/artists.py index 22793ddd5fd0..e2cf55fd5992 100644 --- a/tutorials/intermediate/artists.py +++ b/tutorials/intermediate/artists.py @@ -123,8 +123,8 @@ class in the Matplotlib API, and the one you will be working with most fig = plt.figure() fig.subplots_adjust(top=0.8) ax1 = fig.add_subplot(211) -ax1.set_ylabel('volts') -ax1.set_title('a sine wave') +ax1.set_ylabel('Voltage [V]') +ax1.set_title('A sine wave') t = np.arange(0.0, 1.0, 0.01) s = np.sin(2*np.pi*t) @@ -136,7 +136,7 @@ class in the Matplotlib API, and the one you will be working with most ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3]) n, bins, patches = ax2.hist(np.random.randn(1000), 50, facecolor='yellow', edgecolor='yellow') -ax2.set_xlabel('time (s)') +ax2.set_xlabel('Time [s]') plt.show() diff --git a/tutorials/intermediate/constrainedlayout_guide.py b/tutorials/intermediate/constrainedlayout_guide.py index 84cbf8c0447f..3734df1bd5d6 100644 --- a/tutorials/intermediate/constrainedlayout_guide.py +++ b/tutorials/intermediate/constrainedlayout_guide.py @@ -263,7 +263,7 @@ def example_plot(ax, fontsize=12, hide_labels=False): ########################################## # If there are more than two columns, the *wspace* is shared between them, -# so here the wspace is divided in 2, with a *wspace* of 0.1 between each +# so here the wspace is divided in two, with a *wspace* of 0.1 between each # column: fig, axs = plt.subplots(2, 3, layout="constrained") diff --git a/tutorials/introductory/pyplot.py b/tutorials/introductory/pyplot.py index ebe49df9d3b0..9b15a956efb8 100644 --- a/tutorials/introductory/pyplot.py +++ b/tutorials/introductory/pyplot.py @@ -295,8 +295,10 @@ def f(t): # plt.figure(2) # a second figure # plt.plot([4, 5, 6]) # creates a subplot() by default # -# plt.figure(1) # figure 1 current; subplot(212) still current -# plt.subplot(211) # make subplot(211) in figure1 current +# plt.figure(1) # first figure current; +# # subplot(212) still current +# plt.subplot(211) # make subplot(211) in the first figure +# # current # plt.title('Easy as 1, 2, 3') # subplot 211 title # # You can clear the current figure with `~.pyplot.clf` diff --git a/tutorials/text/text_intro.py b/tutorials/text/text_intro.py index a32ddc800d10..1b0e60a37ab1 100644 --- a/tutorials/text/text_intro.py +++ b/tutorials/text/text_intro.py @@ -118,7 +118,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1) -ax.set_xlabel('time [s]') +ax.set_xlabel('Time [s]') ax.set_ylabel('Damped oscillation [V]') plt.show() @@ -131,7 +131,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1*10000) -ax.set_xlabel('time [s]') +ax.set_xlabel('Time [s]') ax.set_ylabel('Damped oscillation [V]') plt.show() @@ -144,7 +144,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1*10000) -ax.set_xlabel('time [s]') +ax.set_xlabel('Time [s]') ax.set_ylabel('Damped oscillation [V]', labelpad=18) plt.show() @@ -159,7 +159,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1) -ax.set_xlabel('time [s]', position=(0., 1e6), horizontalalignment='left') +ax.set_xlabel('Time [s]', position=(0., 1e6), horizontalalignment='left') ax.set_ylabel('Damped oscillation [V]') plt.show() @@ -179,7 +179,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1) -ax.set_xlabel('time [s]', fontsize='large', fontweight='bold') +ax.set_xlabel('Time [s]', fontsize='large', fontweight='bold') ax.set_ylabel('Damped oscillation [V]', fontproperties=font) plt.show() @@ -191,7 +191,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.2, left=0.2) ax.plot(x1, np.cumsum(y1**2)) -ax.set_xlabel('time [s] \n This was a long experiment') +ax.set_xlabel('Time [s] \n This was a long experiment') ax.set_ylabel(r'$\int\ Y^2\ dt\ \ [V^2 s]$') plt.show() From 4a6c18166fe206f372d5012fc1642d199a5c82c9 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 25 Sep 2022 21:28:35 +0200 Subject: [PATCH 018/262] Backport PR #24004: Increase consistency in tutorials and examples --- examples/color/color_demo.py | 4 ++-- examples/color/custom_cmap.py | 2 +- examples/lines_bars_and_markers/cohere.py | 6 +++--- examples/lines_bars_and_markers/csd_demo.py | 2 +- examples/pyplots/fig_axes_labels_simple.py | 6 +++--- examples/pyplots/pyplot_mathtext.py | 4 ++-- tutorials/advanced/path_tutorial.py | 16 ++++++++-------- tutorials/intermediate/artists.py | 6 +++--- .../intermediate/constrainedlayout_guide.py | 2 +- tutorials/introductory/pyplot.py | 6 ++++-- tutorials/text/text_intro.py | 12 ++++++------ 11 files changed, 34 insertions(+), 32 deletions(-) diff --git a/examples/color/color_demo.py b/examples/color/color_demo.py index f46f52507352..8a161442184b 100644 --- a/examples/color/color_demo.py +++ b/examples/color/color_demo.py @@ -48,9 +48,9 @@ # 3) gray level string: ax.set_title('Voltage vs. time chart', color='0.7') # 4) single letter color string -ax.set_xlabel('time (s)', color='c') +ax.set_xlabel('Time [s]', color='c') # 5) a named color: -ax.set_ylabel('voltage (mV)', color='peachpuff') +ax.set_ylabel('Voltage [mV]', color='peachpuff') # 6) a named xkcd color: ax.plot(t, s, 'xkcd:crimson') # 7) Cn notation: diff --git a/examples/color/custom_cmap.py b/examples/color/custom_cmap.py index 21354fc3fd93..a99127d972e6 100644 --- a/examples/color/custom_cmap.py +++ b/examples/color/custom_cmap.py @@ -42,7 +42,7 @@ If, as in this example, there are no discontinuities in the r, g, and b components, then it is quite simple: the second and third element of -each tuple, above, is the same--call it "``y``". The first element ("``x``") +each tuple, above, is the same -- call it "``y``". The first element ("``x``") defines interpolation intervals over the full range of 0 to 1, and it must span that whole range. In other words, the values of ``x`` divide the 0-to-1 range into a set of segments, and ``y`` gives the end-point color diff --git a/examples/lines_bars_and_markers/cohere.py b/examples/lines_bars_and_markers/cohere.py index 370149695398..7881a0a31b1e 100644 --- a/examples/lines_bars_and_markers/cohere.py +++ b/examples/lines_bars_and_markers/cohere.py @@ -16,19 +16,19 @@ nse1 = np.random.randn(len(t)) # white noise 1 nse2 = np.random.randn(len(t)) # white noise 2 -# Two signals with a coherent part at 10Hz and a random part +# Two signals with a coherent part at 10 Hz and a random part s1 = np.sin(2 * np.pi * 10 * t) + nse1 s2 = np.sin(2 * np.pi * 10 * t) + nse2 fig, axs = plt.subplots(2, 1) axs[0].plot(t, s1, t, s2) axs[0].set_xlim(0, 2) -axs[0].set_xlabel('time') +axs[0].set_xlabel('Time') axs[0].set_ylabel('s1 and s2') axs[0].grid(True) cxy, f = axs[1].cohere(s1, s2, 256, 1. / dt) -axs[1].set_ylabel('coherence') +axs[1].set_ylabel('Coherence') fig.tight_layout() plt.show() diff --git a/examples/lines_bars_and_markers/csd_demo.py b/examples/lines_bars_and_markers/csd_demo.py index d4d1e1d7a967..8894333f94d0 100644 --- a/examples/lines_bars_and_markers/csd_demo.py +++ b/examples/lines_bars_and_markers/csd_demo.py @@ -33,7 +33,7 @@ ax1.plot(t, s1, t, s2) ax1.set_xlim(0, 5) -ax1.set_xlabel('time') +ax1.set_xlabel('Time') ax1.set_ylabel('s1 and s2') ax1.grid(True) diff --git a/examples/pyplots/fig_axes_labels_simple.py b/examples/pyplots/fig_axes_labels_simple.py index 41423b0b4845..353f09477dfd 100644 --- a/examples/pyplots/fig_axes_labels_simple.py +++ b/examples/pyplots/fig_axes_labels_simple.py @@ -11,8 +11,8 @@ fig = plt.figure() fig.subplots_adjust(top=0.8) ax1 = fig.add_subplot(211) -ax1.set_ylabel('volts') -ax1.set_title('a sine wave') +ax1.set_ylabel('Voltage [V]') +ax1.set_title('A sine wave') t = np.arange(0.0, 1.0, 0.01) s = np.sin(2 * np.pi * t) @@ -23,7 +23,7 @@ ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3]) n, bins, patches = ax2.hist(np.random.randn(1000), 50) -ax2.set_xlabel('time (s)') +ax2.set_xlabel('Time [s]') plt.show() diff --git a/examples/pyplots/pyplot_mathtext.py b/examples/pyplots/pyplot_mathtext.py index af4db39a4e95..a62dd6d95da0 100644 --- a/examples/pyplots/pyplot_mathtext.py +++ b/examples/pyplots/pyplot_mathtext.py @@ -16,8 +16,8 @@ plt.text(1, -0.6, r'$\sum_{i=0}^\infty x_i$', fontsize=20) plt.text(0.6, 0.6, r'$\mathcal{A}\mathrm{sin}(2 \omega t)$', fontsize=20) -plt.xlabel('time (s)') -plt.ylabel('volts (mV)') +plt.xlabel('Time [s]') +plt.ylabel('Voltage [mV]') plt.show() ############################################################################# diff --git a/tutorials/advanced/path_tutorial.py b/tutorials/advanced/path_tutorial.py index 19632ce42964..70bb5998cecb 100644 --- a/tutorials/advanced/path_tutorial.py +++ b/tutorials/advanced/path_tutorial.py @@ -76,11 +76,11 @@ # ============== # # Some of the path components require multiple vertices to specify them: -# for example CURVE 3 is a `bézier +# for example CURVE 3 is a `Bézier # `_ curve with one # control point and one end point, and CURVE4 has three vertices for the # two control points and the end point. The example below shows a -# CURVE4 Bézier spline -- the bézier curve will be contained in the +# CURVE4 Bézier spline -- the Bézier curve will be contained in the # convex hull of the start point, the two control points, and the end # point @@ -139,8 +139,8 @@ # for each histogram bar: the rectangle width is the bin width and the # rectangle height is the number of datapoints in that bin. First we'll # create some random normally distributed data and compute the -# histogram. Because numpy returns the bin edges and not centers, the -# length of ``bins`` is 1 greater than the length of ``n`` in the +# histogram. Because NumPy returns the bin edges and not centers, the +# length of ``bins`` is one greater than the length of ``n`` in the # example below:: # # # histogram our data with numpy @@ -159,10 +159,10 @@ # # Now we have to construct our compound path, which will consist of a # series of ``MOVETO``, ``LINETO`` and ``CLOSEPOLY`` for each rectangle. -# For each rectangle, we need 5 vertices: 1 for the ``MOVETO``, 3 for -# the ``LINETO``, and 1 for the ``CLOSEPOLY``. As indicated in the -# table above, the vertex for the closepoly is ignored but we still need -# it to keep the codes aligned with the vertices:: +# For each rectangle, we need five vertices: one for the ``MOVETO``, +# three for the ``LINETO``, and one for the ``CLOSEPOLY``. As indicated +# in the table above, the vertex for the closepoly is ignored but we still +# need it to keep the codes aligned with the vertices:: # # nverts = nrects*(1+3+1) # verts = np.zeros((nverts, 2)) diff --git a/tutorials/intermediate/artists.py b/tutorials/intermediate/artists.py index f76c62d8462c..096a6757515c 100644 --- a/tutorials/intermediate/artists.py +++ b/tutorials/intermediate/artists.py @@ -122,8 +122,8 @@ class in the Matplotlib API, and the one you will be working with most fig = plt.figure() fig.subplots_adjust(top=0.8) ax1 = fig.add_subplot(211) -ax1.set_ylabel('volts') -ax1.set_title('a sine wave') +ax1.set_ylabel('Voltage [V]') +ax1.set_title('A sine wave') t = np.arange(0.0, 1.0, 0.01) s = np.sin(2*np.pi*t) @@ -135,7 +135,7 @@ class in the Matplotlib API, and the one you will be working with most ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3]) n, bins, patches = ax2.hist(np.random.randn(1000), 50, facecolor='yellow', edgecolor='yellow') -ax2.set_xlabel('time (s)') +ax2.set_xlabel('Time [s]') plt.show() diff --git a/tutorials/intermediate/constrainedlayout_guide.py b/tutorials/intermediate/constrainedlayout_guide.py index 84cbf8c0447f..3734df1bd5d6 100644 --- a/tutorials/intermediate/constrainedlayout_guide.py +++ b/tutorials/intermediate/constrainedlayout_guide.py @@ -263,7 +263,7 @@ def example_plot(ax, fontsize=12, hide_labels=False): ########################################## # If there are more than two columns, the *wspace* is shared between them, -# so here the wspace is divided in 2, with a *wspace* of 0.1 between each +# so here the wspace is divided in two, with a *wspace* of 0.1 between each # column: fig, axs = plt.subplots(2, 3, layout="constrained") diff --git a/tutorials/introductory/pyplot.py b/tutorials/introductory/pyplot.py index ebe49df9d3b0..9b15a956efb8 100644 --- a/tutorials/introductory/pyplot.py +++ b/tutorials/introductory/pyplot.py @@ -295,8 +295,10 @@ def f(t): # plt.figure(2) # a second figure # plt.plot([4, 5, 6]) # creates a subplot() by default # -# plt.figure(1) # figure 1 current; subplot(212) still current -# plt.subplot(211) # make subplot(211) in figure1 current +# plt.figure(1) # first figure current; +# # subplot(212) still current +# plt.subplot(211) # make subplot(211) in the first figure +# # current # plt.title('Easy as 1, 2, 3') # subplot 211 title # # You can clear the current figure with `~.pyplot.clf` diff --git a/tutorials/text/text_intro.py b/tutorials/text/text_intro.py index a32ddc800d10..1b0e60a37ab1 100644 --- a/tutorials/text/text_intro.py +++ b/tutorials/text/text_intro.py @@ -118,7 +118,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1) -ax.set_xlabel('time [s]') +ax.set_xlabel('Time [s]') ax.set_ylabel('Damped oscillation [V]') plt.show() @@ -131,7 +131,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1*10000) -ax.set_xlabel('time [s]') +ax.set_xlabel('Time [s]') ax.set_ylabel('Damped oscillation [V]') plt.show() @@ -144,7 +144,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1*10000) -ax.set_xlabel('time [s]') +ax.set_xlabel('Time [s]') ax.set_ylabel('Damped oscillation [V]', labelpad=18) plt.show() @@ -159,7 +159,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1) -ax.set_xlabel('time [s]', position=(0., 1e6), horizontalalignment='left') +ax.set_xlabel('Time [s]', position=(0., 1e6), horizontalalignment='left') ax.set_ylabel('Damped oscillation [V]') plt.show() @@ -179,7 +179,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.15, left=0.2) ax.plot(x1, y1) -ax.set_xlabel('time [s]', fontsize='large', fontweight='bold') +ax.set_xlabel('Time [s]', fontsize='large', fontweight='bold') ax.set_ylabel('Damped oscillation [V]', fontproperties=font) plt.show() @@ -191,7 +191,7 @@ fig, ax = plt.subplots(figsize=(5, 3)) fig.subplots_adjust(bottom=0.2, left=0.2) ax.plot(x1, np.cumsum(y1**2)) -ax.set_xlabel('time [s] \n This was a long experiment') +ax.set_xlabel('Time [s] \n This was a long experiment') ax.set_ylabel(r'$\int\ Y^2\ dt\ \ [V^2 s]$') plt.show() From 3d61e94e6fbe9faa08dd508a07cd89284148e82b Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 27 Sep 2022 03:44:09 -0400 Subject: [PATCH 019/262] Backport PR #24014: Bump pypa/cibuildwheel from 2.10.1 to 2.10.2 --- .github/workflows/cibuildwheel.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 64f345c3a3f4..32d3e10fdd3b 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -53,7 +53,7 @@ jobs: fetch-depth: 0 - name: Build wheels for CPython 3.11 - uses: pypa/cibuildwheel@v2.10.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BUILD: "cp311-*" CIBW_SKIP: "*-musllinux*" @@ -66,7 +66,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.10 - uses: pypa/cibuildwheel@v2.10.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BUILD: "cp310-*" CIBW_SKIP: "*-musllinux*" @@ -79,7 +79,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.9 - uses: pypa/cibuildwheel@v2.10.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BUILD: "cp39-*" CIBW_SKIP: "*-musllinux*" @@ -92,7 +92,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.8 - uses: pypa/cibuildwheel@v2.10.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BUILD: "cp38-*" CIBW_SKIP: "*-musllinux*" @@ -105,7 +105,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for PyPy - uses: pypa/cibuildwheel@v2.10.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BUILD: "pp38-* pp39-*" CIBW_SKIP: "*-musllinux*" From 1d5eff9568c678be07da731da0ffd229d7a67a63 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 24 Sep 2022 06:13:52 +0200 Subject: [PATCH 020/262] Backport PR #23904: added a reversing section to colormap reference --- examples/color/colormap_reference.py | 26 ++++++++++---- lib/matplotlib/colors.py | 14 ++++---- tutorials/colors/colormap-manipulation.py | 42 +++++++++++++++++++++++ 3 files changed, 69 insertions(+), 13 deletions(-) diff --git a/examples/color/colormap_reference.py b/examples/color/colormap_reference.py index d5320f94f0e6..549345edffab 100644 --- a/examples/color/colormap_reference.py +++ b/examples/color/colormap_reference.py @@ -6,16 +6,17 @@ Reference for colormaps included with Matplotlib. A reversed version of each of these colormaps is available by appending -``_r`` to the name, e.g., ``viridis_r``. +``_r`` to the name, as shown in :ref:`reverse-cmap`. See :doc:`/tutorials/colors/colormaps` for an in-depth discussion about -colormaps, including colorblind-friendliness. +colormaps, including colorblind-friendliness, and +:doc:`/tutorials/colors/colormap-manipulation` for a guide to creating +colormaps. """ import numpy as np import matplotlib.pyplot as plt - cmaps = [('Perceptually Uniform Sequential', [ 'viridis', 'plasma', 'inferno', 'magma', 'cividis']), ('Sequential', [ @@ -40,7 +41,6 @@ 'gist_rainbow', 'rainbow', 'jet', 'turbo', 'nipy_spectral', 'gist_ncar'])] - gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) @@ -52,7 +52,7 @@ def plot_color_gradients(cmap_category, cmap_list): fig, axs = plt.subplots(nrows=nrows, figsize=(6.4, figh)) fig.subplots_adjust(top=1-.35/figh, bottom=.15/figh, left=0.2, right=0.99) - axs[0].set_title(cmap_category + ' colormaps', fontsize=14) + axs[0].set_title(f"{cmap_category} colormaps", fontsize=14) for ax, cmap_name in zip(axs, cmap_list): ax.imshow(gradient, aspect='auto', cmap=cmap_name) @@ -67,7 +67,21 @@ def plot_color_gradients(cmap_category, cmap_list): for cmap_category, cmap_list in cmaps: plot_color_gradients(cmap_category, cmap_list) -plt.show() + +############################################################################### +# .. _reverse-cmap: +# +# Reversed colormaps +# ------------------ +# +# Append ``_r`` to the name of any built-in colormap to get the reversed +# version: + +plot_color_gradients("Original and reversed ", ['viridis', 'viridis_r']) + +# %% +# The built-in reversed colormaps are generated using `.Colormap.reversed`. +# For an example, see :ref:`reversing-colormap` ############################################################################# # diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 0d2233294113..5441b0d617b5 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -870,13 +870,13 @@ def reversed(self, name=None): """ Return a reversed instance of the Colormap. - .. note:: This function is not implemented for base class. + .. note:: This function is not implemented for the base class. Parameters ---------- name : str, optional - The name for the reversed colormap. If it's None the - name will be the name of the parent colormap + "_r". + The name for the reversed colormap. If None, the + name is set to ``self.name + "_r"``. See Also -------- @@ -1079,8 +1079,8 @@ def reversed(self, name=None): Parameters ---------- name : str, optional - The name for the reversed colormap. If it's None the - name will be the name of the parent colormap + "_r". + The name for the reversed colormap. If None, the + name is set to ``self.name + "_r"``. Returns ------- @@ -1179,8 +1179,8 @@ def reversed(self, name=None): Parameters ---------- name : str, optional - The name for the reversed colormap. If it's None the - name will be the name of the parent colormap + "_r". + The name for the reversed colormap. If None, the + name is set to ``self.name + "_r"``. Returns ------- diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py index 297506004861..8b2cbc784bc0 100644 --- a/tutorials/colors/colormap-manipulation.py +++ b/tutorials/colors/colormap-manipulation.py @@ -255,6 +255,48 @@ def plot_linearmap(cdict): plot_examples([cmap1, cmap2]) +############################################################################# +# .. _reversing-colormap: +# +# Reversing a colormap +# ==================== +# +# `.Colormap.reversed` creates a new colormap that is a reversed version of +# the original colormap. + +colors = ["#ffffcc", "#a1dab4", "#41b6c4", "#2c7fb8", "#253494"] +my_cmap = ListedColormap(colors, name="my_cmap") + +my_cmap_r = my_cmap.reversed() + +plot_examples([my_cmap, my_cmap_r]) +# %% +# If no name is passed in, ``.reversed`` also names the copy by +# :ref:`appending '_r' ` to the original colormap's +# name. + +############################################################################## +# .. _registering-colormap: +# +# Registering a colormap +# ====================== +# +# Colormaps can be added to the `matplotlib.colormaps` list of named colormaps. +# This allows the colormaps to be accessed by name in plotting functions: + +# my_cmap, my_cmap_r from reversing a colormap +mpl.colormaps.register(cmap=my_cmap) +mpl.colormaps.register(cmap=my_cmap_r) + +data = [[1, 2, 3, 4, 5]] + +fig, (ax1, ax2) = plt.subplots(nrows=2) + +ax1.imshow(data, cmap='my_cmap') +ax2.imshow(data, cmap='my_cmap_r') + +plt.show() + ############################################################################# # # .. admonition:: References From f3185cedafe5cc8fada3e01c518efc798fa97108 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 28 Sep 2022 13:57:58 +0200 Subject: [PATCH 021/262] Backport PR #24026: Don't modify Axes property cycle in stackplot --- lib/matplotlib/stackplot.py | 13 ++++++++----- lib/matplotlib/tests/test_axes.py | 5 +++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/stackplot.py b/lib/matplotlib/stackplot.py index c580043eebbc..c97a21e029f9 100644 --- a/lib/matplotlib/stackplot.py +++ b/lib/matplotlib/stackplot.py @@ -6,6 +6,8 @@ (https://stackoverflow.com/users/66549/doug) """ +import itertools + import numpy as np from matplotlib import _api @@ -70,7 +72,9 @@ def stackplot(axes, x, *args, labels = iter(labels) if colors is not None: - axes.set_prop_cycle(color=colors) + colors = itertools.cycle(colors) + else: + colors = (axes._get_lines.get_next_color() for _ in y) # Assume data passed has not been 'stacked', so stack it here. # We'll need a float buffer for the upcoming calculations. @@ -108,17 +112,16 @@ def stackplot(axes, x, *args, stack += first_line # Color between x = 0 and the first array. - color = axes._get_lines.get_next_color() coll = axes.fill_between(x, first_line, stack[0, :], - facecolor=color, label=next(labels, None), + facecolor=next(colors), label=next(labels, None), **kwargs) coll.sticky_edges.y[:] = [0] r = [coll] # Color between array i-1 and array i for i in range(len(y) - 1): - color = axes._get_lines.get_next_color() r.append(axes.fill_between(x, stack[i, :], stack[i + 1, :], - facecolor=color, label=next(labels, None), + facecolor=next(colors), + label=next(labels, None), **kwargs)) return r diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index b35b3feacf18..3864a39c274d 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2859,10 +2859,11 @@ def test_stackplot(): ax.set_xlim((0, 10)) ax.set_ylim((0, 70)) - # Reuse testcase from above for a labeled data test + # Reuse testcase from above for a test with labeled data and with colours + # from the Axes property cycle. data = {"x": x, "y1": y1, "y2": y2, "y3": y3} fig, ax = plt.subplots() - ax.stackplot("x", "y1", "y2", "y3", data=data) + ax.stackplot("x", "y1", "y2", "y3", data=data, colors=["C0", "C1", "C2"]) ax.set_xlim((0, 10)) ax.set_ylim((0, 70)) From 90672eefe3a7e92ecc11b754ee7ec0cc4f36080c Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 28 Sep 2022 14:00:21 +0200 Subject: [PATCH 022/262] Backport PR #24019: Don't require FigureCanvas on backend module more --- lib/matplotlib/pyplot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 1e94d90d1534..e5ae9a0cc11c 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -182,7 +182,8 @@ def findobj(o=None, match=None, include_self=True): def _get_required_interactive_framework(backend_mod): - if not hasattr(backend_mod.FigureCanvas, "required_interactive_framework"): + if not hasattr(getattr(backend_mod, "FigureCanvas", None), + "required_interactive_framework"): _api.warn_deprecated( "3.6", name="Support for FigureCanvases without a " "required_interactive_framework attribute") From 606b86e542f64e68719aaef19007061268c4dd20 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 28 Sep 2022 19:45:41 +0200 Subject: [PATCH 023/262] Backport PR #24032: Reword SpanSelector example. --- examples/widgets/span_selector.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/widgets/span_selector.py b/examples/widgets/span_selector.py index a9d0cc4960bb..940948719d82 100644 --- a/examples/widgets/span_selector.py +++ b/examples/widgets/span_selector.py @@ -3,9 +3,13 @@ Span Selector ============= -The SpanSelector is a mouse widget to select a xmin/xmax range and plot the -detail view of the selected region in the lower axes +The `.SpanSelector` is a mouse widget that enables selecting a range on an +axis. + +Here, an x-range can be selected on the upper axis; a detailed view of the +selected range is then plotted on the lower axis. """ + import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import SpanSelector From 9be6284db6b4d7769a78eca5152cc5d8f82f8f56 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 28 Sep 2022 19:45:41 +0200 Subject: [PATCH 024/262] Backport PR #24032: Reword SpanSelector example. --- examples/widgets/span_selector.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/widgets/span_selector.py b/examples/widgets/span_selector.py index a9d0cc4960bb..940948719d82 100644 --- a/examples/widgets/span_selector.py +++ b/examples/widgets/span_selector.py @@ -3,9 +3,13 @@ Span Selector ============= -The SpanSelector is a mouse widget to select a xmin/xmax range and plot the -detail view of the selected region in the lower axes +The `.SpanSelector` is a mouse widget that enables selecting a range on an +axis. + +Here, an x-range can be selected on the upper axis; a detailed view of the +selected range is then plotted on the lower axis. """ + import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import SpanSelector From d6b786c07394531faca1d706f684cb4cf5346c90 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 28 Sep 2022 19:56:33 -0400 Subject: [PATCH 025/262] Backport PR #24018: When comparing eps images, run ghostscript with -dEPSCrop. --- .github/workflows/tests.yml | 6 +++--- lib/matplotlib/testing/compare.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4e07aee580c2..0c5b7a08ced5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -146,10 +146,10 @@ jobs: ~/.cache/matplotlib !~/.cache/matplotlib/tex.cache !~/.cache/matplotlib/test_cache - key: 1-${{ runner.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-${{ github.sha }} + key: 2-${{ runner.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-${{ github.sha }} restore-keys: | - 1-${{ runner.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}- - 1-${{ runner.os }}-py${{ matrix.python-version }}-mpl- + 2-${{ runner.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}- + 2-${{ runner.os }}-py${{ matrix.python-version }}-mpl- - name: Install Python dependencies run: | diff --git a/lib/matplotlib/testing/compare.py b/lib/matplotlib/testing/compare.py index c2ed8247d93b..4c07c7ad7e09 100644 --- a/lib/matplotlib/testing/compare.py +++ b/lib/matplotlib/testing/compare.py @@ -103,7 +103,7 @@ def __call__(self, orig, dest): if not self._proc: self._proc = subprocess.Popen( [mpl._get_executable_info("gs").executable, - "-dNOSAFER", "-dNOPAUSE", "-sDEVICE=png16m"], + "-dNOSAFER", "-dNOPAUSE", "-dEPSCrop", "-sDEVICE=png16m"], # As far as I can see, ghostscript never outputs to stderr. stdin=subprocess.PIPE, stdout=subprocess.PIPE) try: From 649fa325d6350ab8875eed616af884c0e9f11b22 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 29 Sep 2022 06:59:06 +0200 Subject: [PATCH 026/262] Backport PR #24041: DOC: Fix incorrect redirect --- examples/text_labels_and_annotations/font_family_rc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/text_labels_and_annotations/font_family_rc.py b/examples/text_labels_and_annotations/font_family_rc.py index 6c8b06d88054..d840a8575920 100644 --- a/examples/text_labels_and_annotations/font_family_rc.py +++ b/examples/text_labels_and_annotations/font_family_rc.py @@ -24,7 +24,7 @@ rcParams['font.sans-serif'] = ['Tahoma', 'DejaVu Sans', 'Lucida Grande', 'Verdana'] -.. redirect-from:: /examples/font_family_rc_sgskip +.. redirect-from:: /gallery/font_family_rc_sgskip From 4bb89ee4ea2140d7eb3f6d798ebb490f02eb97c2 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 29 Sep 2022 06:59:06 +0200 Subject: [PATCH 027/262] Backport PR #24041: DOC: Fix incorrect redirect --- examples/text_labels_and_annotations/font_family_rc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/text_labels_and_annotations/font_family_rc.py b/examples/text_labels_and_annotations/font_family_rc.py index 6c8b06d88054..d840a8575920 100644 --- a/examples/text_labels_and_annotations/font_family_rc.py +++ b/examples/text_labels_and_annotations/font_family_rc.py @@ -24,7 +24,7 @@ rcParams['font.sans-serif'] = ['Tahoma', 'DejaVu Sans', 'Lucida Grande', 'Verdana'] -.. redirect-from:: /examples/font_family_rc_sgskip +.. redirect-from:: /gallery/font_family_rc_sgskip From 5f0631566ce674494ea0b36fba5b71b211020adf Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 29 Sep 2022 10:15:53 +0200 Subject: [PATCH 028/262] Backport PR #24045: Fix _FigureManagerGTK.resize on GTK4 --- lib/matplotlib/backends/_backend_gtk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/_backend_gtk.py b/lib/matplotlib/backends/_backend_gtk.py index a482480ce0c0..db5ca34cbf80 100644 --- a/lib/matplotlib/backends/_backend_gtk.py +++ b/lib/matplotlib/backends/_backend_gtk.py @@ -233,8 +233,8 @@ def resize(self, width, height): width = int(width / self.canvas.device_pixel_ratio) height = int(height / self.canvas.device_pixel_ratio) if self.toolbar: - toolbar_size = self.toolbar.size_request() - height += toolbar_size.height + min_size, nat_size = self.toolbar.get_preferred_size() + height += nat_size.height canvas_size = self.canvas.get_allocation() if self._gtk_ver >= 4 or canvas_size.width == canvas_size.height == 1: # A canvas size of (1, 1) cannot exist in most cases, because From 0e982d748ff8bcaf4d36c662ffaed878fc6cdd93 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 29 Sep 2022 18:07:39 +0200 Subject: [PATCH 029/262] Backport PR #24037: [DOC]: make spanselector example codeblock continuous --- examples/widgets/span_selector.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/widgets/span_selector.py b/examples/widgets/span_selector.py index 940948719d82..fa75a70d2863 100644 --- a/examples/widgets/span_selector.py +++ b/examples/widgets/span_selector.py @@ -8,6 +8,11 @@ Here, an x-range can be selected on the upper axis; a detailed view of the selected range is then plotted on the lower axis. + +.. note:: + + If the SpanSelector object is garbage collected you will lose the + interactivity. You must keep a hard reference to it to prevent this. """ import numpy as np @@ -44,14 +49,6 @@ def onselect(xmin, xmax): fig.canvas.draw_idle() -############################################################################# -# .. note:: -# -# If the SpanSelector object is garbage collected you will lose the -# interactivity. You must keep a hard reference to it to prevent this. -# - - span = SpanSelector( ax1, onselect, From c95a0a538a4ff7df2639325ee769debb502f78c8 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 30 Sep 2022 00:06:41 +0200 Subject: [PATCH 030/262] Backport PR #24046: Ignore 'CFMessagePort: bootstrap_register' messages --- lib/matplotlib/tests/test_backend_tk.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/tests/test_backend_tk.py b/lib/matplotlib/tests/test_backend_tk.py index 5ad3e3ff28b9..4d43e27aa4a4 100644 --- a/lib/matplotlib/tests/test_backend_tk.py +++ b/lib/matplotlib/tests/test_backend_tk.py @@ -53,11 +53,14 @@ def test_func(): + str(e.stderr)) else: # macOS may actually emit irrelevant errors about Accelerated - # OpenGL vs. software OpenGL, so suppress them. + # OpenGL vs. software OpenGL, or some permission error on Azure, so + # suppress them. # Asserting stderr first (and printing it on failure) should be # more helpful for debugging that printing a failed success count. + ignored_lines = ["OpenGL", "CFMessagePort: bootstrap_register", + "/usr/include/servers/bootstrap_defs.h"] assert not [line for line in proc.stderr.splitlines() - if "OpenGL" not in line] + if all(msg not in line for msg in ignored_lines)] assert proc.stdout.count("success") == success_count return test_func From bf16cb6145920d403e25841437da76cc0b195860 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 30 Sep 2022 18:27:48 -0400 Subject: [PATCH 031/262] Backport PR #23638: FIX: correctly handle generic font families in svg text-as-text mode --- lib/matplotlib/backends/backend_svg.py | 42 +++++++++++++++- lib/matplotlib/font_manager.py | 17 +++++-- lib/matplotlib/tests/test_backend_svg.py | 61 ++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py index 7d94c429eed7..738fe44c6f81 100644 --- a/lib/matplotlib/backends/backend_svg.py +++ b/lib/matplotlib/backends/backend_svg.py @@ -1151,10 +1151,48 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): weight = fm.weight_dict[prop.get_weight()] if weight != 400: font_parts.append(f'{weight}') + + def _format_font_name(fn): + normalize_names = { + 'sans': 'sans-serif', + 'sans serif': 'sans-serif' + } + # A generic font family. We need to do two things: + # 1. list all of the configured fonts with quoted names + # 2. append the generic name unquoted + if fn in fm.font_family_aliases: + # fix spelling of sans-serif + # we accept 3 ways CSS only supports 1 + fn = normalize_names.get(fn, fn) + # get all of the font names and fix spelling of sans-serif + # if it comes back + aliases = [ + normalize_names.get(_, _) for _ in + fm.FontManager._expand_aliases(fn) + ] + # make sure the generic name appears at least once + # duplicate is OK, next layer will deduplicate + aliases.append(fn) + + for a in aliases: + # generic font families must not be quoted + if a in fm.font_family_aliases: + yield a + # specific font families must be quoted + else: + yield repr(a) + # specific font families must be quoted + else: + yield repr(fn) + + def _get_all_names(prop): + for f in prop.get_family(): + yield from _format_font_name(f) + font_parts.extend([ f'{_short_float_fmt(prop.get_size())}px', - # ensure quoting - f'{", ".join(repr(f) for f in prop.get_family())}', + # ensure quoting and expansion of font names + ", ".join(dict.fromkeys(_get_all_names(prop))) ]) style['font'] = ' '.join(font_parts) if prop.get_stretch() != 'normal': diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 99e1fecabbeb..a5742ef88f61 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -1345,9 +1345,12 @@ def findfont(self, prop, fontext='ttf', directory=None, rc_params = tuple(tuple(mpl.rcParams[key]) for key in [ "font.serif", "font.sans-serif", "font.cursive", "font.fantasy", "font.monospace"]) - return self._findfont_cached( + ret = self._findfont_cached( prop, fontext, directory, fallback_to_default, rebuild_if_missing, rc_params) + if isinstance(ret, Exception): + raise ret + return ret def get_font_names(self): """Return the list of available fonts.""" @@ -1496,8 +1499,11 @@ def _findfont_cached(self, prop, fontext, directory, fallback_to_default, return self.findfont(default_prop, fontext, directory, fallback_to_default=False) else: - raise ValueError(f"Failed to find font {prop}, and fallback " - f"to the default font was disabled") + # This return instead of raise is intentional, as we wish to + # cache the resulting exception, which will not occur if it was + # actually raised. + return ValueError(f"Failed to find font {prop}, and fallback " + f"to the default font was disabled") else: _log.debug('findfont: Matching %s to %s (%r) with score of %f.', prop, best_font.name, best_font.fname, best_score) @@ -1516,7 +1522,10 @@ def _findfont_cached(self, prop, fontext, directory, fallback_to_default, return self.findfont( prop, fontext, directory, rebuild_if_missing=False) else: - raise ValueError("No valid font could be found") + # This return instead of raise is intentional, as we wish to + # cache the resulting exception, which will not occur if it was + # actually raised. + return ValueError("No valid font could be found") return _cached_realpath(result) diff --git a/lib/matplotlib/tests/test_backend_svg.py b/lib/matplotlib/tests/test_backend_svg.py index 7ea81730f20d..680efd67379b 100644 --- a/lib/matplotlib/tests/test_backend_svg.py +++ b/lib/matplotlib/tests/test_backend_svg.py @@ -527,3 +527,64 @@ def test_svg_escape(): fig.savefig(fd, format='svg') buf = fd.getvalue().decode() assert '<'"&>"' in buf + + +@pytest.mark.parametrize("font_str", [ + "'DejaVu Sans', 'WenQuanYi Zen Hei', 'Arial', sans-serif", + "'DejaVu Serif', 'WenQuanYi Zen Hei', 'Times New Roman', serif", + "'Arial', 'WenQuanYi Zen Hei', cursive", + "'Impact', 'WenQuanYi Zen Hei', fantasy", + "'DejaVu Sans Mono', 'WenQuanYi Zen Hei', 'Courier New', monospace", + # These do not work because the logic to get the font metrics will not find + # WenQuanYi as the fallback logic stops with the first fallback font: + # "'DejaVu Sans Mono', 'Courier New', 'WenQuanYi Zen Hei', monospace", + # "'DejaVu Sans', 'Arial', 'WenQuanYi Zen Hei', sans-serif", + # "'DejaVu Serif', 'Times New Roman', 'WenQuanYi Zen Hei', serif", +]) +@pytest.mark.parametrize("include_generic", [True, False]) +def test_svg_font_string(font_str, include_generic): + fp = fm.FontProperties(family=["WenQuanYi Zen Hei"]) + if Path(fm.findfont(fp)).name != "wqy-zenhei.ttc": + pytest.skip("Font may be missing") + + explicit, *rest, generic = map( + lambda x: x.strip("'"), font_str.split(", ") + ) + size = len(generic) + if include_generic: + rest = rest + [generic] + plt.rcParams[f"font.{generic}"] = rest + plt.rcParams["font.size"] = size + plt.rcParams["svg.fonttype"] = "none" + + fig, ax = plt.subplots() + if generic == "sans-serif": + generic_options = ["sans", "sans-serif", "sans serif"] + else: + generic_options = [generic] + + for generic_name in generic_options: + # test that fallback works + ax.text(0.5, 0.5, "There are 几个汉字 in between!", + family=[explicit, generic_name], ha="center") + # test deduplication works + ax.text(0.5, 0.1, "There are 几个汉字 in between!", + family=[explicit, *rest, generic_name], ha="center") + ax.axis("off") + + with BytesIO() as fd: + fig.savefig(fd, format="svg") + buf = fd.getvalue() + + tree = xml.etree.ElementTree.fromstring(buf) + ns = "http://www.w3.org/2000/svg" + text_count = 0 + for text_element in tree.findall(f".//{{{ns}}}text"): + text_count += 1 + font_info = dict( + map(lambda x: x.strip(), _.strip().split(":")) + for _ in dict(text_element.items())["style"].split(";") + )["font"] + + assert font_info == f"{size}px {font_str}" + assert text_count == len(ax.texts) From 9ab4b504695b5d26ec0e499263059ad171ade45e Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sun, 2 Oct 2022 12:21:32 +0200 Subject: [PATCH 032/262] Backport PR #24069: Clarification of marker size in scatter --- lib/matplotlib/axes/_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index c578765bfa1c..9df42e0c4d0b 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4402,7 +4402,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, The data positions. s : float or array-like, shape (n, ), optional - The marker size in points**2. + The marker size in points**2 (typographic points are 1/72 in.). Default is ``rcParams['lines.markersize'] ** 2``. c : array-like or list of colors or color, optional From 31ef9bceb7b69de0239a9b3534a05e8395f0e697 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sun, 2 Oct 2022 12:23:30 +0200 Subject: [PATCH 033/262] Backport PR #24070: DOC: colorbar may steal from array of axes --- lib/matplotlib/colorbar.py | 2 +- lib/matplotlib/figure.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index b9293fbd902e..ee47d2107fd6 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -1364,7 +1364,7 @@ def make_axes(parents, location=None, orientation=None, fraction=0.15, Parameters ---------- - parents : `~.axes.Axes` or list of `~.axes.Axes` + parents : `~.axes.Axes` or list or `numpy.ndarray` of `~.axes.Axes` The Axes to use as parents for placing the colorbar. %(_make_axes_kw_doc)s diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 447f508194a1..4aebc1696543 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1197,7 +1197,7 @@ def colorbar( cax : `~matplotlib.axes.Axes`, optional Axes into which the colorbar will be drawn. - ax : `~matplotlib.axes.Axes`, list of Axes, optional + ax : `~.axes.Axes` or list or `numpy.ndarray` of Axes, optional One or more parent axes from which space for a new colorbar axes will be stolen, if *cax* is None. This has no effect if *cax* is set. From 80698784acd6c5d9ff708ff5e0575803dfde532e Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 2 Oct 2022 18:37:58 +0200 Subject: [PATCH 034/262] Backport PR #24054: DOC: Move OO-examples from pyplot section --- doc/users/faq/howto_faq.rst | 6 +- examples/{pyplots => misc}/fig_x.py | 2 + examples/pyplots/boxplot_demo_pyplot.py | 89 ------------------- examples/pyplots/fig_axes_labels_simple.py | 42 --------- examples/pyplots/pyplot_formatstr.py | 21 ----- examples/pyplots/pyplot_simple.py | 9 +- examples/pyplots/text_layout.py | 63 ------------- examples/statistics/boxplot_demo.py | 2 + .../auto_subplots_adjust.py | 2 + .../align_ylabels.py | 1 + .../annotate_transform.py | 2 + .../annotation_basic.py | 2 + .../annotation_polar.py | 2 + .../text_alignment.py | 2 + .../text_commands.py | 2 + examples/{pyplots => ticks}/dollar_ticks.py | 2 + .../fig_axes_customize_simple.py | 2 + examples/ticks/tick-formatters.py | 1 + tutorials/intermediate/artists.py | 2 +- tutorials/text/annotations.py | 8 +- 20 files changed, 37 insertions(+), 225 deletions(-) rename examples/{pyplots => misc}/fig_x.py (93%) delete mode 100644 examples/pyplots/boxplot_demo_pyplot.py delete mode 100644 examples/pyplots/fig_axes_labels_simple.py delete mode 100644 examples/pyplots/pyplot_formatstr.py delete mode 100644 examples/pyplots/text_layout.py rename examples/{pyplots => subplots_axes_and_figures}/auto_subplots_adjust.py (98%) rename examples/{pyplots => text_labels_and_annotations}/align_ylabels.py (97%) rename examples/{pyplots => text_labels_and_annotations}/annotate_transform.py (96%) rename examples/{pyplots => text_labels_and_annotations}/annotation_basic.py (94%) rename examples/{pyplots => text_labels_and_annotations}/annotation_polar.py (95%) rename examples/{pyplots => text_labels_and_annotations}/text_commands.py (96%) rename examples/{pyplots => ticks}/dollar_ticks.py (94%) rename examples/{pyplots => ticks}/fig_axes_customize_simple.py (95%) diff --git a/doc/users/faq/howto_faq.rst b/doc/users/faq/howto_faq.rst index 4f60b9e14fe3..4ea220d969b0 100644 --- a/doc/users/faq/howto_faq.rst +++ b/doc/users/faq/howto_faq.rst @@ -187,7 +187,7 @@ multiple ways to fix this: - tight layout (:doc:`/tutorials/intermediate/tight_layout_guide`) - Calculate good values from the size of the plot elements yourself - (:doc:`/gallery/pyplots/auto_subplots_adjust`) + (:doc:`/gallery/subplots_axes_and_figures/auto_subplots_adjust`) .. _howto-align-label: @@ -203,8 +203,8 @@ behavior by specifying the coordinates of the label. The example below shows the default behavior in the left subplots, and the manual setting in the right subplots. -.. figure:: ../../gallery/pyplots/images/sphx_glr_align_ylabels_001.png - :target: ../../gallery/pyplots/align_ylabels.html +.. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_align_ylabels_001.png + :target: ../../gallery/text_labels_and_annotations/align_ylabels.html :align: center :scale: 50 diff --git a/examples/pyplots/fig_x.py b/examples/misc/fig_x.py similarity index 93% rename from examples/pyplots/fig_x.py rename to examples/misc/fig_x.py index 9ca5a3b13d8a..eaa16d80fa35 100644 --- a/examples/pyplots/fig_x.py +++ b/examples/misc/fig_x.py @@ -4,6 +4,8 @@ ======================= Adding lines to a figure without any axes. + +.. redirect-from:: /gallery/pyplots/fig_x """ import matplotlib.pyplot as plt diff --git a/examples/pyplots/boxplot_demo_pyplot.py b/examples/pyplots/boxplot_demo_pyplot.py deleted file mode 100644 index 501eb2cf3447..000000000000 --- a/examples/pyplots/boxplot_demo_pyplot.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -============ -Boxplot Demo -============ - -Example boxplot code -""" - -import numpy as np -import matplotlib.pyplot as plt - -# Fixing random state for reproducibility -np.random.seed(19680801) - -# fake up some data -spread = np.random.rand(50) * 100 -center = np.ones(25) * 50 -flier_high = np.random.rand(10) * 100 + 100 -flier_low = np.random.rand(10) * -100 -data = np.concatenate((spread, center, flier_high, flier_low)) - -############################################################################### - -fig1, ax1 = plt.subplots() -ax1.set_title('Basic Plot') -ax1.boxplot(data) - -############################################################################### - -fig2, ax2 = plt.subplots() -ax2.set_title('Notched boxes') -ax2.boxplot(data, notch=True) - -############################################################################### - -green_diamond = dict(markerfacecolor='g', marker='D') -fig3, ax3 = plt.subplots() -ax3.set_title('Changed Outlier Symbols') -ax3.boxplot(data, flierprops=green_diamond) - -############################################################################### - -fig4, ax4 = plt.subplots() -ax4.set_title('Hide Outlier Points') -ax4.boxplot(data, showfliers=False) - -############################################################################### - -red_square = dict(markerfacecolor='r', marker='s') -fig5, ax5 = plt.subplots() -ax5.set_title('Horizontal Boxes') -ax5.boxplot(data, vert=False, flierprops=red_square) - -############################################################################### - -fig6, ax6 = plt.subplots() -ax6.set_title('Shorter Whisker Length') -ax6.boxplot(data, flierprops=red_square, vert=False, whis=0.75) - -############################################################################### -# Fake up some more data - -spread = np.random.rand(50) * 100 -center = np.ones(25) * 40 -flier_high = np.random.rand(10) * 100 + 100 -flier_low = np.random.rand(10) * -100 -d2 = np.concatenate((spread, center, flier_high, flier_low)) - -############################################################################### -# Making a 2-D array only works if all the columns are the -# same length. If they are not, then use a list instead. -# This is actually more efficient because boxplot converts -# a 2-D array into a list of vectors internally anyway. - -data = [data, d2, d2[::2]] -fig7, ax7 = plt.subplots() -ax7.set_title('Multiple Samples with Different sizes') -ax7.boxplot(data) - -plt.show() - -############################################################################# -# -# .. admonition:: References -# -# The use of the following functions, methods, classes and modules is shown -# in this example: -# -# - `matplotlib.axes.Axes.boxplot` / `matplotlib.pyplot.boxplot` diff --git a/examples/pyplots/fig_axes_labels_simple.py b/examples/pyplots/fig_axes_labels_simple.py deleted file mode 100644 index 353f09477dfd..000000000000 --- a/examples/pyplots/fig_axes_labels_simple.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -================== -Simple axes labels -================== - -Label the axes of a plot. -""" -import numpy as np -import matplotlib.pyplot as plt - -fig = plt.figure() -fig.subplots_adjust(top=0.8) -ax1 = fig.add_subplot(211) -ax1.set_ylabel('Voltage [V]') -ax1.set_title('A sine wave') - -t = np.arange(0.0, 1.0, 0.01) -s = np.sin(2 * np.pi * t) -line, = ax1.plot(t, s, lw=2) - -# Fixing random state for reproducibility -np.random.seed(19680801) - -ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3]) -n, bins, patches = ax2.hist(np.random.randn(1000), 50) -ax2.set_xlabel('Time [s]') - -plt.show() - -############################################################################# -# -# .. admonition:: References -# -# The use of the following functions, methods, classes and modules is shown -# in this example: -# -# - `matplotlib.axes.Axes.set_xlabel` -# - `matplotlib.axes.Axes.set_ylabel` -# - `matplotlib.axes.Axes.set_title` -# - `matplotlib.axes.Axes.plot` -# - `matplotlib.axes.Axes.hist` -# - `matplotlib.figure.Figure.add_axes` diff --git a/examples/pyplots/pyplot_formatstr.py b/examples/pyplots/pyplot_formatstr.py deleted file mode 100644 index e9be3830ec98..000000000000 --- a/examples/pyplots/pyplot_formatstr.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -==================== -plot() format string -==================== - -Use a format string (here, 'ro') to set the color and markers of a -`~matplotlib.axes.Axes.plot`. -""" - -import matplotlib.pyplot as plt -plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro') -plt.show() - -############################################################################# -# -# .. admonition:: References -# -# The use of the following functions, methods, classes and modules is shown -# in this example: -# -# - `matplotlib.axes.Axes.plot` / `matplotlib.pyplot.plot` diff --git a/examples/pyplots/pyplot_simple.py b/examples/pyplots/pyplot_simple.py index 414e5ae4f7ab..1a3b457acedd 100644 --- a/examples/pyplots/pyplot_simple.py +++ b/examples/pyplots/pyplot_simple.py @@ -5,10 +5,15 @@ A very simple pyplot where a list of numbers are plotted against their index. Creates a straight line due to the rate of change being 1 for -both the X and Y axis. +both the X and Y axis. Use a format string (here, 'o-r') to set the +markers (circles), linestyle (solid line) and color (red). + +.. redirect-from:: /gallery/pyplots/fig_axes_labels_simple +.. redirect-from:: /gallery/pyplots/pyplot_formatstr """ import matplotlib.pyplot as plt -plt.plot([1, 2, 3, 4]) + +plt.plot([1, 2, 3, 4], 'o-r') plt.ylabel('some numbers') plt.show() diff --git a/examples/pyplots/text_layout.py b/examples/pyplots/text_layout.py deleted file mode 100644 index 641aa77320a5..000000000000 --- a/examples/pyplots/text_layout.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -=========== -Text Layout -=========== - -Create text with different alignment and rotation. -""" - -import matplotlib.pyplot as plt -import matplotlib.patches as patches - -fig = plt.figure() - -left, width = .25, .5 -bottom, height = .25, .5 -right = left + width -top = bottom + height - -# Draw a rectangle in figure coordinates ((0, 0) is bottom left and (1, 1) is -# upper right). -p = patches.Rectangle((left, bottom), width, height, fill=False) -fig.add_artist(p) - -# Figure.text (aka. plt.figtext) behaves like Axes.text (aka. plt.text), with -# the sole exception that the coordinates are relative to the figure ((0, 0) is -# bottom left and (1, 1) is upper right). -fig.text(left, bottom, 'left top', - horizontalalignment='left', verticalalignment='top') -fig.text(left, bottom, 'left bottom', - horizontalalignment='left', verticalalignment='bottom') -fig.text(right, top, 'right bottom', - horizontalalignment='right', verticalalignment='bottom') -fig.text(right, top, 'right top', - horizontalalignment='right', verticalalignment='top') -fig.text(right, bottom, 'center top', - horizontalalignment='center', verticalalignment='top') -fig.text(left, 0.5*(bottom+top), 'right center', - horizontalalignment='right', verticalalignment='center', - rotation='vertical') -fig.text(left, 0.5*(bottom+top), 'left center', - horizontalalignment='left', verticalalignment='center', - rotation='vertical') -fig.text(0.5*(left+right), 0.5*(bottom+top), 'middle', - horizontalalignment='center', verticalalignment='center', - fontsize=20, color='red') -fig.text(right, 0.5*(bottom+top), 'centered', - horizontalalignment='center', verticalalignment='center', - rotation='vertical') -fig.text(left, top, 'rotated\nwith newlines', - horizontalalignment='center', verticalalignment='center', - rotation=45) - -plt.show() - -############################################################################# -# -# .. admonition:: References -# -# The use of the following functions, methods, classes and modules is shown -# in this example: -# -# - `matplotlib.figure.Figure.add_artist` -# - `matplotlib.figure.Figure.text` diff --git a/examples/statistics/boxplot_demo.py b/examples/statistics/boxplot_demo.py index 0ad146aa1d2d..252ca25bd58d 100644 --- a/examples/statistics/boxplot_demo.py +++ b/examples/statistics/boxplot_demo.py @@ -8,6 +8,8 @@ The following examples show off how to visualize boxplots with Matplotlib. There are many options to control their appearance and the statistics that they use to summarize the data. + +.. redirect-from:: /gallery/pyplots/boxplot_demo_pyplot """ import matplotlib.pyplot as plt diff --git a/examples/pyplots/auto_subplots_adjust.py b/examples/subplots_axes_and_figures/auto_subplots_adjust.py similarity index 98% rename from examples/pyplots/auto_subplots_adjust.py rename to examples/subplots_axes_and_figures/auto_subplots_adjust.py index b4c731cb4cdc..bd6326b8291f 100644 --- a/examples/pyplots/auto_subplots_adjust.py +++ b/examples/subplots_axes_and_figures/auto_subplots_adjust.py @@ -36,6 +36,8 @@ This function is executed after the figure has been drawn. It can now check if the subplot leaves enough room for the text. If not, the subplot parameters are updated and second draw is triggered. + +.. redirect-from:: /gallery/pyplots/auto_subplots_adjust """ import matplotlib.pyplot as plt diff --git a/examples/pyplots/align_ylabels.py b/examples/text_labels_and_annotations/align_ylabels.py similarity index 97% rename from examples/pyplots/align_ylabels.py rename to examples/text_labels_and_annotations/align_ylabels.py index 3523e08f93fd..8e47909cc6c1 100644 --- a/examples/pyplots/align_ylabels.py +++ b/examples/text_labels_and_annotations/align_ylabels.py @@ -6,6 +6,7 @@ Two methods are shown here, one using a short call to `.Figure.align_ylabels` and the second a manual way to align the labels. +.. redirect-from:: /gallery/pyplots/align_ylabels """ import numpy as np import matplotlib.pyplot as plt diff --git a/examples/pyplots/annotate_transform.py b/examples/text_labels_and_annotations/annotate_transform.py similarity index 96% rename from examples/pyplots/annotate_transform.py rename to examples/text_labels_and_annotations/annotate_transform.py index 9d3d09f5a0ba..1145f7fdb9a2 100644 --- a/examples/pyplots/annotate_transform.py +++ b/examples/text_labels_and_annotations/annotate_transform.py @@ -6,6 +6,8 @@ This example shows how to use different coordinate systems for annotations. For a complete overview of the annotation capabilities, also see the :doc:`annotation tutorial`. + +.. redirect-from:: /gallery/pyplots/annotate_transform """ import numpy as np diff --git a/examples/pyplots/annotation_basic.py b/examples/text_labels_and_annotations/annotation_basic.py similarity index 94% rename from examples/pyplots/annotation_basic.py rename to examples/text_labels_and_annotations/annotation_basic.py index 5a6327b48748..d9ea9748197f 100644 --- a/examples/pyplots/annotation_basic.py +++ b/examples/text_labels_and_annotations/annotation_basic.py @@ -8,6 +8,8 @@ For a complete overview of the annotation capabilities, also see the :doc:`annotation tutorial`. + +.. redirect-from:: /gallery/pyplots/annotation_basic """ import numpy as np import matplotlib.pyplot as plt diff --git a/examples/pyplots/annotation_polar.py b/examples/text_labels_and_annotations/annotation_polar.py similarity index 95% rename from examples/pyplots/annotation_polar.py rename to examples/text_labels_and_annotations/annotation_polar.py index 24a3a20bc3fe..a7f8b764d914 100644 --- a/examples/pyplots/annotation_polar.py +++ b/examples/text_labels_and_annotations/annotation_polar.py @@ -7,6 +7,8 @@ For a complete overview of the annotation capabilities, also see the :doc:`annotation tutorial`. + +.. redirect-from:: /gallery/pyplots/annotation_polar """ import numpy as np import matplotlib.pyplot as plt diff --git a/examples/text_labels_and_annotations/text_alignment.py b/examples/text_labels_and_annotations/text_alignment.py index a12002972233..a748481d5261 100644 --- a/examples/text_labels_and_annotations/text_alignment.py +++ b/examples/text_labels_and_annotations/text_alignment.py @@ -6,6 +6,8 @@ Texts are aligned relative to their anchor point depending on the properties ``horizontalalignment`` and ``verticalalignment``. +.. redirect-from:: /gallery/pyplots/text_layout + .. plot:: import matplotlib.pyplot as plt diff --git a/examples/pyplots/text_commands.py b/examples/text_labels_and_annotations/text_commands.py similarity index 96% rename from examples/pyplots/text_commands.py rename to examples/text_labels_and_annotations/text_commands.py index a13532246f0a..cb6d5413f8d4 100644 --- a/examples/pyplots/text_commands.py +++ b/examples/text_labels_and_annotations/text_commands.py @@ -4,6 +4,8 @@ ============= Plotting text of many different kinds. + +.. redirect-from:: /gallery/pyplots/text_commands """ import matplotlib.pyplot as plt diff --git a/examples/pyplots/dollar_ticks.py b/examples/ticks/dollar_ticks.py similarity index 94% rename from examples/pyplots/dollar_ticks.py rename to examples/ticks/dollar_ticks.py index 1f99ccdd674d..694e613db08d 100644 --- a/examples/pyplots/dollar_ticks.py +++ b/examples/ticks/dollar_ticks.py @@ -4,6 +4,8 @@ ============ Use a `~.ticker.FormatStrFormatter` to prepend dollar signs on y axis labels. + +.. redirect-from:: /gallery/pyplots/dollar_ticks """ import numpy as np import matplotlib.pyplot as plt diff --git a/examples/pyplots/fig_axes_customize_simple.py b/examples/ticks/fig_axes_customize_simple.py similarity index 95% rename from examples/pyplots/fig_axes_customize_simple.py rename to examples/ticks/fig_axes_customize_simple.py index b557feb961aa..74742f718939 100644 --- a/examples/pyplots/fig_axes_customize_simple.py +++ b/examples/ticks/fig_axes_customize_simple.py @@ -4,6 +4,8 @@ ========================= Customize the background, labels and ticks of a simple plot. + +.. redirect-from:: /gallery/pyplots/fig_axes_customize_simple """ import matplotlib.pyplot as plt diff --git a/examples/ticks/tick-formatters.py b/examples/ticks/tick-formatters.py index ea9dc214fbb0..ac118cbfce03 100644 --- a/examples/ticks/tick-formatters.py +++ b/examples/ticks/tick-formatters.py @@ -7,6 +7,7 @@ is formatted as a string. This example illustrates the usage and effect of the most common formatters. + """ import matplotlib.pyplot as plt diff --git a/tutorials/intermediate/artists.py b/tutorials/intermediate/artists.py index e2cf55fd5992..0078813f9edd 100644 --- a/tutorials/intermediate/artists.py +++ b/tutorials/intermediate/artists.py @@ -719,6 +719,6 @@ class in the Matplotlib API, and the one you will be working with most # dollar signs and colors them green on the right side of the yaxis. # # -# .. include:: ../../gallery/pyplots/dollar_ticks.rst +# .. include:: ../../gallery/ticks/dollar_ticks.rst # :start-after: y axis labels. # :end-before: .. admonition:: References diff --git a/tutorials/text/annotations.py b/tutorials/text/annotations.py index df2dda7ad580..7ab582d9f20f 100644 --- a/tutorials/text/annotations.py +++ b/tutorials/text/annotations.py @@ -25,8 +25,8 @@ # *xy* and the location of the text *xytext*. Both of these # arguments are ``(x, y)`` tuples. # -# .. figure:: ../../gallery/pyplots/images/sphx_glr_annotation_basic_001.png -# :target: ../../gallery/pyplots/annotation_basic.html +# .. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_annotation_basic_001.png +# :target: ../../gallery/text_labels_and_annotations/annotation_basic.html # :align: center # # In this example, both the *xy* (arrow tip) and *xytext* locations @@ -86,8 +86,8 @@ # *fontsize* are passed from `~matplotlib.axes.Axes.annotate` to the # ``Text`` instance. # -# .. figure:: ../../gallery/pyplots/images/sphx_glr_annotation_polar_001.png -# :target: ../../gallery/pyplots/annotation_polar.html +# .. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_annotation_polar_001.png +# :target: ../../gallery/text_labels_and_annotations/annotation_polar.html # :align: center # # For more on all the wild and wonderful things you can do with From 2e351d150180eb4aaa1aa9244376c74c59ebe9e2 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 2 Oct 2022 22:09:58 +0200 Subject: [PATCH 035/262] Backport PR #24047: Revert #22360: Let TeX handle multiline strings itself --- lib/matplotlib/dates.py | 12 +++++- lib/matplotlib/dviread.py | 32 +++++++++++++- .../baseline_images/test_usetex/eqnarray.png | Bin 0 -> 1322 bytes lib/matplotlib/tests/test_dates.py | 40 +++++++++--------- lib/matplotlib/tests/test_text.py | 21 +++++++-- lib/matplotlib/tests/test_usetex.py | 15 +++++++ lib/matplotlib/texmanager.py | 3 +- lib/matplotlib/text.py | 3 +- 8 files changed, 97 insertions(+), 29 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_usetex/eqnarray.png diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py index ac1a7d03c687..672ea2c3b003 100644 --- a/lib/matplotlib/dates.py +++ b/lib/matplotlib/dates.py @@ -173,6 +173,7 @@ import functools import logging import math +import re from dateutil.rrule import (rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, @@ -597,7 +598,16 @@ def drange(dstart, dend, delta): def _wrap_in_tex(text): - return r"{\fontfamily{\familydefault}\selectfont " + text + "}" + p = r'([a-zA-Z]+)' + ret_text = re.sub(p, r'}$\1$\\mathdefault{', text) + + # Braces ensure symbols are not spaced like binary operators. + ret_text = ret_text.replace('-', '{-}').replace(':', '{:}') + # To not concatenate space between numbers. + ret_text = ret_text.replace(' ', r'\;') + ret_text = '$\\mathdefault{' + ret_text + '}$' + ret_text = ret_text.replace('$\\mathdefault{}$', '') + return ret_text ## date tickers and formatters ### diff --git a/lib/matplotlib/dviread.py b/lib/matplotlib/dviread.py index 8c83d8d6c508..296e67c4d5ff 100644 --- a/lib/matplotlib/dviread.py +++ b/lib/matplotlib/dviread.py @@ -352,10 +352,40 @@ def _read(self): Read one page from the file. Return True if successful, False if there were no more pages. """ + # Pages appear to start with the sequence + # bop (begin of page) + # xxx comment + # # if using chemformula + # down + # push + # down + # # if using xcolor + # down + # push + # down (possibly multiple) + # push <= here, v is the baseline position. + # etc. + # (dviasm is useful to explore this structure.) + # Thus, we use the vertical position at the first time the stack depth + # reaches 3, while at least three "downs" have been executed (excluding + # those popped out (corresponding to the chemformula preamble)), as the + # baseline (the "down" count is necessary to handle xcolor). + down_stack = [0] self._baseline_v = None while True: byte = self.file.read(1)[0] self._dtable[byte](self, byte) + name = self._dtable[byte].__name__ + if name == "_push": + down_stack.append(down_stack[-1]) + elif name == "_pop": + down_stack.pop() + elif name == "_down": + down_stack[-1] += 1 + if (self._baseline_v is None + and len(getattr(self, "stack", [])) == 3 + and down_stack[-1] >= 4): + self._baseline_v = self.v if byte == 140: # end of page return True if self.state is _dvistate.post_post: # end of file @@ -488,8 +518,6 @@ def _fnt_num(self, new_f): @_dispatch(min=239, max=242, args=('ulen1',)) def _xxx(self, datalen): special = self.file.read(datalen) - if special == b'matplotlibbaselinemarker': - self._baseline_v = self.v _log.debug( 'Dvi._xxx: encountered special: %s', ''.join([chr(ch) if 32 <= ch < 127 else '<%02x>' % ch diff --git a/lib/matplotlib/tests/baseline_images/test_usetex/eqnarray.png b/lib/matplotlib/tests/baseline_images/test_usetex/eqnarray.png new file mode 100644 index 0000000000000000000000000000000000000000..249f15d238ddacf216965801675667d6edb85da3 GIT binary patch literal 1322 zcmeAS@N?(olHy`uVBq!ia0vp^DImv~(l@_;SZF8i$S^J$mm}g-zS*UD3z4Tw8JdHArUurkeZhk1ec^Up8?SV6on+(UlN+ZFyYP4w^=jzVwKBY? zT>pOjC>S~I;nSzAd*jx>D(mA~I^kyx-&)gOf9-E|{rE$bd8wwe zeRZav{$K0CXVEAa)UtYN5XWJG$Z2oqOisO-pFNv#XaBk6#yAfFmJK@GQQ2E==lZBk zUMsyTLZ_gp&65Y~Jgof^CXZf+YHnhsK<8yukgjR(|ot6?ddpUVjaY zRfcQT&*nXU`0N?mfhrNn$f^@@*Q5 zmb~FUv(ZV{C428wBb{w!)qCS457p_PE}XOW|E62&Qzf$$-z(3be3E7JO`fe$yxVf$ zpJ2LX9+w>}XTS6!cXSIyry4Q;? zzYJI}J^KQ;rTL2GYl>Y6r2GK(r{{E4*ykMJuv|Vt#zF7N9jBrLoNwCa1bgr)$SdCG zJ(>G&-r3qR&QrA$-?u$!_-gh(!QjBtr>c`w93|S0@9VLD{Nw#@%Q+7Vc6|M|{r2tK ze;z(mJpcLY>S;2^HM0w4-q#jixP3eN=jWoGcYdAW_{;G#%VXVwi0Up8<=;^*+D~>X z?)2^2V7i;9A>zb+j+2bplCzbY|As!@;`GnWLyyNfW9{kWM2Ts^a@tq!JMR;obb1qy zqrigOZ<9=<60PPYna#dv-?UJysPBSb info.misses diff --git a/lib/matplotlib/tests/test_usetex.py b/lib/matplotlib/tests/test_usetex.py index 22309afdaf97..0f01ebaffb56 100644 --- a/lib/matplotlib/tests/test_usetex.py +++ b/lib/matplotlib/tests/test_usetex.py @@ -64,6 +64,21 @@ def test_mathdefault(): fig.canvas.draw() +@image_comparison(['eqnarray.png']) +def test_multiline_eqnarray(): + text = ( + r'\begin{eqnarray*}' + r'foo\\' + r'bar\\' + r'baz\\' + r'\end{eqnarray*}' + ) + + fig = plt.figure(figsize=(1, 1)) + fig.text(0.5, 0.5, text, usetex=True, + horizontalalignment='center', verticalalignment='center') + + @pytest.mark.parametrize("fontsize", [8, 10, 12]) def test_minus_no_descent(fontsize): # Test special-casing of minus descent in DviFont._height_depth_of, by diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index edac2fec9c79..f53377cf5597 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -230,8 +230,7 @@ def _get_tex_source(cls, tex, fontsize): r"% last line's baseline.", rf"\fontsize{{{fontsize}}}{{{baselineskip}}}%", r"\ifdefined\psfrag\else\hbox{}\fi%", - rf"{{\obeylines{fontcmd} {tex}}}%", - r"\special{matplotlibbaselinemarker}%", + rf"{{{fontcmd} {tex}}}%", r"\end{document}", ]) diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index 3c998d540c48..ccf6ce879b2a 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -302,8 +302,7 @@ def _get_layout(self, renderer): of a rotated text when necessary. """ thisx, thisy = 0.0, 0.0 - text = self.get_text() - lines = [text] if self.get_usetex() else text.split("\n") # Not empty. + lines = self.get_text().split("\n") # Ensures lines is not empty. ws = [] hs = [] From 8e840d7e3d4ec18b6c00ea3c52f23b71ad10e51b Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Mon, 3 Oct 2022 13:19:47 -0700 Subject: [PATCH 036/262] Backport PR #24084: Revert argument checking for label_mode --- lib/mpl_toolkits/axes_grid1/axes_grid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py index 2435f2258e25..b2fe5d249609 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_grid.py +++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py @@ -269,7 +269,6 @@ def set_label_mode(self, mode): - "1": Only the bottom left axes is labelled. - "all": all axes are labelled. """ - _api.check_in_list(["all", "L", "1"], mode=mode) if mode == "all": for ax in self.axes_all: _tick_only(ax, False, False) @@ -290,7 +289,7 @@ def set_label_mode(self, mode): ax = col[-1] _tick_only(ax, bottom_on=False, left_on=True) - else: # "1" + elif mode == "1": for ax in self.axes_all: _tick_only(ax, bottom_on=True, left_on=True) From fd4bd8002276d5c69a5b706ddeb82c0073979aa3 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 6 Oct 2022 04:37:27 -0400 Subject: [PATCH 037/262] Backport PR #23684: Fix rectangle and hatches for colorbar --- lib/matplotlib/colorbar.py | 17 +++++++--- .../test_colorbar/contourf_extend_patches.png | Bin 0 -> 65946 bytes lib/matplotlib/tests/test_colorbar.py | 30 ++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_colorbar/contourf_extend_patches.png diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index ee47d2107fd6..2983e3fa51ce 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -606,10 +606,13 @@ def _update_dividers(self): self.dividers.set_segments(segments) def _add_solids_patches(self, X, Y, C, mappable): - hatches = mappable.hatches * len(C) # Have enough hatches. + hatches = mappable.hatches * (len(C) + 1) # Have enough hatches. + if self._extend_lower(): + # remove first hatch that goes into the extend patch + hatches = hatches[1:] patches = [] for i in range(len(X) - 1): - xy = np.array([[X[i, 0], Y[i, 0]], + xy = np.array([[X[i, 0], Y[i, 1]], [X[i, 1], Y[i, 0]], [X[i + 1, 1], Y[i + 1, 0]], [X[i + 1, 0], Y[i + 1, 1]]]) @@ -661,9 +664,9 @@ def _do_extends(self, ax=None): mappable = getattr(self, 'mappable', None) if (isinstance(mappable, contour.ContourSet) and any(hatch is not None for hatch in mappable.hatches)): - hatches = mappable.hatches + hatches = mappable.hatches * (len(self._y) + 1) else: - hatches = [None] + hatches = [None] * (len(self._y) + 1) if self._extend_lower(): if not self.extendrect: @@ -687,6 +690,8 @@ def _do_extends(self, ax=None): zorder=np.nextafter(self.ax.patch.zorder, -np.inf)) self.ax.add_patch(patch) self._extend_patches.append(patch) + # remove first hatch that goes into the extend patch + hatches = hatches[1:] if self._extend_upper(): if not self.extendrect: # triangle @@ -699,10 +704,12 @@ def _do_extends(self, ax=None): # add the patch val = 0 if self._long_axis().get_inverted() else -1 color = self.cmap(self.norm(self._values[val])) + hatch_idx = len(self._y) - 1 patch = mpatches.PathPatch( mpath.Path(xy), facecolor=color, alpha=self.alpha, linewidth=0, antialiased=False, - transform=self.ax.transAxes, hatch=hatches[-1], clip_on=False, + transform=self.ax.transAxes, hatch=hatches[hatch_idx], + clip_on=False, # Place it right behind the standard patches, which is # needed if we updated the extends zorder=np.nextafter(self.ax.patch.zorder, -np.inf)) diff --git a/lib/matplotlib/tests/baseline_images/test_colorbar/contourf_extend_patches.png b/lib/matplotlib/tests/baseline_images/test_colorbar/contourf_extend_patches.png new file mode 100644 index 0000000000000000000000000000000000000000..0e5ef52cf549e15ae9ea2b49e81468db15b9c296 GIT binary patch literal 65946 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 Date: Thu, 6 Oct 2022 14:06:55 -0400 Subject: [PATCH 038/262] Backport PR #24088: MNT: make orphaned colorbar deprecate versus raise --- lib/matplotlib/figure.py | 6 ++++-- lib/matplotlib/tests/test_colorbar.py | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 4aebc1696543..1636e201019b 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1253,11 +1253,13 @@ def colorbar( # Store the value of gca so that we can set it back later on. if cax is None: if ax is None: - raise ValueError( + _api.warn_deprecated("3.6", message=( 'Unable to determine Axes to steal space for Colorbar. ' + 'Using gca(), but will raise in the future. ' 'Either provide the *cax* argument to use as the Axes for ' 'the Colorbar, provide the *ax* argument to steal space ' - 'from it, or add *mappable* to an Axes.') + 'from it, or add *mappable* to an Axes.')) + ax = self.gca() current_ax = self.gca() userax = False if (use_gridspec and isinstance(ax, SubplotBase)): diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index ee10c5b6befc..4336b761f698 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -1,10 +1,12 @@ import numpy as np import pytest +from matplotlib import _api from matplotlib import cm import matplotlib.colors as mcolors import matplotlib as mpl + from matplotlib import rc_context from matplotlib.testing.decorators import image_comparison import matplotlib.pyplot as plt @@ -319,7 +321,8 @@ def test_parentless_mappable(): pc = mpl.collections.PatchCollection([], cmap=plt.get_cmap('viridis')) pc.set_array([]) - with pytest.raises(ValueError, match='Unable to determine Axes to steal'): + with pytest.warns(_api.MatplotlibDeprecationWarning, + match='Unable to determine Axes to steal'): plt.colorbar(pc) From 688e3cab4b247d4bdc4a839d1ce01ee4667bd4cb Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 6 Oct 2022 23:07:24 -0400 Subject: [PATCH 039/262] Backport PR #24109: DOC: add API change note for colorbar deprecation --- doc/api/next_api_changes/deprecations/24088-JMK.rst | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/api/next_api_changes/deprecations/24088-JMK.rst diff --git a/doc/api/next_api_changes/deprecations/24088-JMK.rst b/doc/api/next_api_changes/deprecations/24088-JMK.rst new file mode 100644 index 000000000000..caa7e93a05b4 --- /dev/null +++ b/doc/api/next_api_changes/deprecations/24088-JMK.rst @@ -0,0 +1,9 @@ +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())``. From 0c248accc8f597ac8217ce9fe5bba049699b6194 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 7 Oct 2022 10:02:51 +0200 Subject: [PATCH 040/262] Backport PR #24115: Fix mask lookup in fill_between for NumPy 1.24+ --- lib/matplotlib/axes/_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 9df42e0c4d0b..e5e34c91257d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5256,7 +5256,7 @@ def _fill_between_x_or_y( raise ValueError(f"where size ({where.size}) does not match " f"{ind_dir} size ({ind.size})") where = where & ~functools.reduce( - np.logical_or, map(np.ma.getmask, [ind, dep1, dep2])) + np.logical_or, map(np.ma.getmaskarray, [ind, dep1, dep2])) ind, dep1, dep2 = np.broadcast_arrays( np.atleast_1d(ind), dep1, dep2, subok=True) From 305a146e7bcf28abe0decc67770f2bbfd39015f0 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 7 Oct 2022 10:04:16 +0200 Subject: [PATCH 041/262] Backport PR #24113: Add exception class to pytest.warns calls --- lib/matplotlib/tests/test_axes.py | 6 ++++-- lib/matplotlib/tests/test_colors.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 3864a39c274d..d6d44bcdb283 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -491,13 +491,15 @@ def test_subclass_clear_cla(): # Note, we cannot use mocking here as we want to be sure that the # superclass fallback does not recurse. - with pytest.warns(match='Overriding `Axes.cla`'): + with pytest.warns(PendingDeprecationWarning, + match='Overriding `Axes.cla`'): class ClaAxes(Axes): def cla(self): nonlocal called called = True - with pytest.warns(match='Overriding `Axes.cla`'): + with pytest.warns(PendingDeprecationWarning, + match='Overriding `Axes.cla`'): class ClaSuperAxes(Axes): def cla(self): nonlocal called diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index f0c23038e11a..6d618c1b847c 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -117,7 +117,7 @@ def test_double_register_builtin_cmap(): mpl.colormaps[name], name=name, force=True ) with pytest.raises(ValueError, match='A colormap named "viridis"'): - with pytest.warns(): + with pytest.warns(PendingDeprecationWarning): cm.register_cmap(name, mpl.colormaps[name]) with pytest.warns(UserWarning): # TODO is warning more than once! @@ -128,7 +128,7 @@ def test_unregister_builtin_cmap(): name = "viridis" match = f'cannot unregister {name!r} which is a builtin colormap.' with pytest.raises(ValueError, match=match): - with pytest.warns(): + with pytest.warns(PendingDeprecationWarning): cm.unregister_cmap(name) From 3863297228c2832770ab15dbc4b3406b19253eb7 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 8 Oct 2022 01:02:06 -0400 Subject: [PATCH 042/262] Backport PR #24111: FIX: add missing method to ColormapRegistry --- .../api_changes_3.6.0/deprecations.rst | 9 +++- lib/matplotlib/cm.py | 48 ++++++++++++++++--- lib/matplotlib/tests/test_colors.py | 20 ++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/doc/api/prev_api_changes/api_changes_3.6.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.6.0/deprecations.rst index d59077d2b2d2..3a9e91e12289 100644 --- a/doc/api/prev_api_changes/api_changes_3.6.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.6.0/deprecations.rst @@ -52,7 +52,12 @@ In Matplotlib 3.6 we have marked those top level functions as pending deprecation with the intention of deprecation in Matplotlib 3.7. The following functions have been marked for pending deprecation: -- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead +- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead if you + have a `str`. + + **Added 3.6.1** Use `matplotlib.cm.ColormapRegistry.get_cmap` if you + have a string, `None` or a `matplotlib.colors.Colormap` object that you want + to convert to a `matplotlib.colors.Colormap` instance. - ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register <.ColormapRegistry.register>` instead - ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister @@ -305,7 +310,7 @@ Backend-specific deprecations private functions if you rely on it. - ``backend_svg.generate_transform`` and ``backend_svg.generate_css`` - ``backend_tk.NavigationToolbar2Tk.lastrect`` and - ``backend_tk.RubberbandTk.lastrect`` + ``backend_tk.RubberbandTk.lastrect`` - ``backend_tk.NavigationToolbar2Tk.window``; use ``toolbar.master`` instead. - ``backend_tools.ToolBase.destroy``; To run code upon tool removal, connect to the ``tool_removed_event`` event. diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py index f6e5ee8b7156..ec0d472992ef 100644 --- a/lib/matplotlib/cm.py +++ b/lib/matplotlib/cm.py @@ -61,12 +61,6 @@ class ColormapRegistry(Mapping): r""" Container for colormaps that are known to Matplotlib by name. - .. admonition:: Experimental - - While we expect the API to be final, we formally mark it as - experimental for 3.5 because we want to keep the option to still adapt - the API for 3.6 should the need arise. - The universal registry instance is `matplotlib.colormaps`. There should be no need for users to instantiate `.ColormapRegistry` themselves. @@ -193,6 +187,38 @@ def unregister(self, name): "colormap.") self._cmaps.pop(name, None) + def get_cmap(self, cmap): + """ + Return a color map specified through *cmap*. + + Parameters + ---------- + cmap : str or `~matplotlib.colors.Colormap` or None + + - if a `.Colormap`, return it + - if a string, look it up in ``mpl.colormaps`` + - if None, return the Colormap defined in :rc:`image.cmap` + + Returns + ------- + Colormap + """ + # get the default color map + if cmap is None: + return self[mpl.rcParams["image.cmap"]] + + # if the user passed in a Colormap, simply return it + if isinstance(cmap, colors.Colormap): + return cmap + if isinstance(cmap, str): + _api.check_in_list(sorted(_colormaps), cmap=cmap) + # otherwise, it must be a string so look it up + return self[cmap] + raise TypeError( + 'get_cmap expects None or an instance of a str or Colormap . ' + + f'you passed {cmap!r} of type {type(cmap)}' + ) + # public access to the colormaps should be via `matplotlib.colormaps`. For now, # we still create the registry here, but that should stay an implementation @@ -281,7 +307,12 @@ def _get_cmap(name=None, lut=None): # pyplot. get_cmap = _api.deprecated( '3.6', - name='get_cmap', pending=True, alternative="``matplotlib.colormaps[name]``" + name='get_cmap', + pending=True, + alternative=( + "``matplotlib.colormaps[name]`` " + + "or ``matplotlib.colormaps.get_cmap(obj)``" + ) )(_get_cmap) @@ -687,6 +718,8 @@ def _ensure_cmap(cmap): """ Ensure that we have a `.Colormap` object. + For internal use to preserve type stability of errors. + Parameters ---------- cmap : None, str, Colormap @@ -698,6 +731,7 @@ def _ensure_cmap(cmap): Returns ------- Colormap + """ if isinstance(cmap, colors.Colormap): return cmap diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 6d618c1b847c..3adfce2833a6 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -109,6 +109,26 @@ def test_register_cmap(): cm.register_cmap('nome', cmap='not a cmap') +def test_colormaps_get_cmap(): + cr = mpl.colormaps + + # check str, and Colormap pass + assert cr.get_cmap('plasma') == cr["plasma"] + assert cr.get_cmap(cr["magma"]) == cr["magma"] + + # check default + assert cr.get_cmap(None) == cr[mpl.rcParams['image.cmap']] + + # check ValueError on bad name + bad_cmap = 'AardvarksAreAwkward' + with pytest.raises(ValueError, match=bad_cmap): + cr.get_cmap(bad_cmap) + + # check TypeError on bad type + with pytest.raises(TypeError, match='object'): + cr.get_cmap(object()) + + def test_double_register_builtin_cmap(): name = "viridis" match = f"Re-registering the builtin cmap {name!r}." From 746f3ce53d5cab0862b2a69f0a0473807d6eb514 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 8 Oct 2022 03:13:21 -0400 Subject: [PATCH 043/262] DOC: Update GitHub stats for 3.6.1 --- doc/users/github_stats.rst | 1383 ++--------------- .../prev_whats_new/github_stats_3.6.0.rst | 1292 +++++++++++++++ 2 files changed, 1409 insertions(+), 1266 deletions(-) create mode 100644 doc/users/prev_whats_new/github_stats_3.6.0.rst diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index e23d1e8f6fd0..7e5c3fe14a66 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -1,1295 +1,146 @@ .. _github-stats: -GitHub statistics for 3.6.0 (Sep 15, 2022) +GitHub statistics for 3.6.1 (Oct 08, 2022) ========================================== -GitHub statistics for 2021/11/16 (tag: v3.5.0) - 2022/09/15 +GitHub statistics for 2022/09/16 (tag: v3.6.0) - 2022/10/08 These lists are automatically generated, and may be incomplete or contain duplicates. -We closed 202 issues and merged 894 pull requests. -The full list can be seen `on GitHub `__ +We closed 22 issues and merged 80 pull requests. +The full list can be seen `on GitHub `__ -The following 174 authors contributed 4425 commits. +The following 19 authors contributed 129 commits. -* Abhishek K M -* Adeel Hassan -* agra -* Aitik Gupta -* ambi7 -* Andras Deak -* Andres Martinez -* Andrew Fennell -* andrzejnovak -* Andrés Martínez -* Anna Mastori -* AnnaMastori -* Ante Sikic * Antony Lee -* arndRemy -* Ben Root -* Biswapriyo Nath -* cavesdev -* Clément Phan -* Clément Walter -* code-review-doctor -* Connor Cozad -* Constantine Evans -* Croadden -* daniilS -* Danilo Palumbo -* David Gilbertson -* David Ketcheson -* David Matos -* David Poznik +* baharev * David Stansby -* Davide Sandonà * dependabot[bot] -* dermasugita -* Diego Solano -* Dimitri Papadopoulos -* dj4t9n -* Dmitriy Fishman -* DWesl -* Edouard Berthe -* eindH +* Eli Rykoff * Elliott Sales de Andrade -* Eric Firing -* Eric Larson -* Eric Prestat -* Federico Ariza -* Felix Nößler -* Fernando -* Gajendra Pal -* gajendra0180 -* GavinZhang +* erykoff * Greg Lucas * hannah -* Hansin Ahuja -* Harshal Prakash Patankar -* Hassan Kibirige -* Haziq Khurshid -* Henry -* henrybeUM -* Hood -* Hood Chatham * Ian Hunt-Isaak -* Ian Thomas -* igurin-invn -* ikhebgeenaccount -* Isha Mehta -* Jake Bowhay -* Jake Li -* Jake Lishman -* Jake VanderPlas -* Jakub Klus -* James Tocknell -* Jan-Hendrik Müller -* Jay Joshi -* Jay Stanley -* jayjoshi112711 -* Jeff Beck * Jody Klymak -* Joel Frederico -* Joseph Fox-Rabinovitz -* Josh Soref -* Jouni K. Seppänen -* Kayran Schmidt -* kdpenner -* Kian Eliasi -* Kinshuk Dua -* kislovskiy -* KIU Shueng Chuan -* kjain -* kolibril13 -* krassowski -* Krish-sysadmin -* Leeh Peter -* lgfunderburk -* Liam Toney -* Lucas Ricci -* Luke Davis -* luz paz -* mackopes -* MAKOMO -* MalikIdreesHasa -* Marcin Swaltek -* Mario -* Mario Sergio Valdés Tresanco -* martinRenou -* Matthew Feickert -* Matthias Bussonnier -* Mauricio Collares -* MeeseeksMachine * melissawm -* Mr-Milk -* Navid C. Constantinou -* Nickolaos Giannatos -* Nicolas P. Rougier -* Niyas Sait -* noatamir -* ojeda-e -* Olivier Gauthé * Oscar Gustafsson -* patquem -* Philipp Rohde -* Pieter Eendebak -* Pieter P -* Péter Leéh -* Qijia Liu -* Quentin Peter -* Raphael Quast -* rditlar9 -* Richard Penney -* richardsheridan -* Rike-Benjamin Schuppner -* Robert Cimrman -* Roberto Toro -* root * Ruth Comer -* Ruth G. N -* Ruth Nainggolan -* Ryan May -* Rémi Achard -* SaumyaBhushan -* Scott Jones -* Scott Shambaugh -* selormtamakloe -* Simon Hoxbro -* skywateryang -* Stefanie Molin +* slackline * Steffen Rehberg -* stone -* Sven Eschlbeck -* sveneschlbeck -* takimata -* tfpf * Thomas A Caswell * Tim Hoffmann -* Tobias Megies -* Tomas Hrnciar -* Tomasz Kuliński -* trichter -* unknown -* Uwe Hubert -* vfdev-5 -* Vishal Chandratreya -* Vishal Pankaj Chandratreya -* Vishnu V K -* vk0812 -* Vlad Korolev -* Will Qian -* William Qian -* wqh17101 -* wsykala -* yaaun -* Yannic Schroeder -* yuanx749 -* 渡邉 美希 +* مهدي شينون (Mehdi Chinoune) GitHub issues and pull requests: -Pull Requests (894): - -* :ghpull:`23814`: Consolidate release notes for 3.6 -* :ghpull:`23899`: Backport PR #23885 on branch v3.6.x (DOC: Rearrange navbar-end elements) -* :ghpull:`23898`: Backport PR #23892 on branch v3.6.x (DOC: Fix docs for linestyles in contour) -* :ghpull:`23885`: DOC: Rearrange navbar-end elements -* :ghpull:`23894`: Backport PR #23881 on branch v3.6.x (Fix Pillow compatibility in example) -* :ghpull:`23897`: Backport PR #23887 on branch v3.6.x (Add missing label argument to barh docs) -* :ghpull:`23892`: DOC: Fix docs for linestyles in contour -* :ghpull:`23887`: Add missing label argument to barh docs -* :ghpull:`23893`: Backport PR #23886 on branch v3.6.x (CI: prefer (older) binaries over (newer) sdists) -* :ghpull:`23881`: Fix Pillow compatibility in example -* :ghpull:`23886`: CI: prefer (older) binaries over (newer) sdists -* :ghpull:`23880`: Backport PR #23862 on branch v3.6.x (Remove triggering of deprecation warning in AnchoredEllipse) -* :ghpull:`23862`: Remove triggering of deprecation warning in AnchoredEllipse -* :ghpull:`23879`: Backport PR #23864 on branch v3.6.x (Correct and improve documentation for anchored artists) -* :ghpull:`23877`: Backport PR #23841 on branch v3.6.x (clarified that hist computes histogram on unbinned data) -* :ghpull:`23872`: Backport PR #23871 on branch v3.6.x (DOC: Fix formatting of pick event demo example) -* :ghpull:`23841`: clarified that hist computes histogram on unbinned data -* :ghpull:`23864`: Correct and improve documentation for anchored artists -* :ghpull:`23871`: DOC: Fix formatting of pick event demo example -* :ghpull:`23869`: Backport PR #23867 on branch v3.6.x (DOC: fix deprecation warnings in examples) -* :ghpull:`23867`: DOC: fix deprecation warnings in examples -* :ghpull:`23858`: Backport PR #23855 on branch v3.6.x (DOC: fix deprecation warnings) -* :ghpull:`23859`: Backport PR #23844 on branch v3.6.x (Further improve dev setup instructions) -* :ghpull:`23844`: Further improve dev setup instructions -* :ghpull:`23855`: DOC: fix deprecation warnings -* :ghpull:`23854`: Backport PR #23852 on branch v3.6.x (Fix cross-compiling internal freetype) -* :ghpull:`23852`: Fix cross-compiling internal freetype -* :ghpull:`23853`: Backport PR #23830 on branch v3.6.x (Start testing on Python 3.11) -* :ghpull:`23830`: Start testing on Python 3.11 -* :ghpull:`23851`: Backport PR #23850 on branch v3.6.x (removed single word in documenting doc) -* :ghpull:`23850`: removed single word in documenting doc -* :ghpull:`23848`: Backport PR #23843 on branch v3.6.x (Clarify that pycairo>=1.14.0 is needed.) -* :ghpull:`23843`: Clarify that pycairo>=1.14.0 is needed. -* :ghpull:`23842`: Backport PR #23840 on branch v3.6.x (Remove documentation for axes_grid) -* :ghpull:`23838`: Backport PR #23834 on branch v3.6.x (Revert "Refactor handling of tick and ticklabel visibility in Axis.clear") -* :ghpull:`23840`: Remove documentation for axes_grid -* :ghpull:`23837`: Backport PR #23833 on branch v3.6.x (Remove search field from sidebar) -* :ghpull:`23836`: Backport PR #23823 on branch v3.6.x ([DOC] Improve dev setup description) -* :ghpull:`23834`: Revert "Refactor handling of tick and ticklabel visibility in Axis.clear" -* :ghpull:`23833`: Remove search field from sidebar -* :ghpull:`23823`: [DOC] Improve dev setup description -* :ghpull:`23822`: Backport PR #23813 on branch v3.6.x (Triplot duplicated label) -* :ghpull:`23813`: Triplot duplicated label -* :ghpull:`23811`: Backport PR #23805 on branch v3.6.x (sphinxext: Do not copy plot_directive.css's metadata) -* :ghpull:`23805`: sphinxext: Do not copy plot_directive.css's metadata -* :ghpull:`23800`: Backport PR #23785 on branch v3.6.x (FIX: ensure type stability for missing cmaps in ``set_cmap``) -* :ghpull:`23799`: Backport PR #23790 on branch v3.6.x (DOC: Add cache busting to all static assets) -* :ghpull:`23785`: FIX: ensure type stability for missing cmaps in ``set_cmap`` -* :ghpull:`23790`: DOC: Add cache busting to all static assets -* :ghpull:`23791`: Backport PR #23774 on branch v3.6.x (Correct rcParams-name in AutoDateFormatter doc-string) -* :ghpull:`23792`: Backport PR #23781 on branch v3.6.x (ci: Add plot types to sphinx-gallery artifacts) -* :ghpull:`23789`: Backport PR #23786 on branch v3.6.x (DOC: fontfallback works for most of the backends) -* :ghpull:`23788`: Backport PR #23784 on branch v3.6.x (DOC: Fix num2date docstring) -* :ghpull:`23786`: DOC: fontfallback works for most of the backends -* :ghpull:`23784`: DOC: Fix num2date docstring -* :ghpull:`23781`: ci: Add plot types to sphinx-gallery artifacts -* :ghpull:`23783`: Backport PR #23782 on branch v3.6.x (Remove ``Axes.cla`` from examples) -* :ghpull:`23782`: Remove ``Axes.cla`` from examples -* :ghpull:`23774`: Correct rcParams-name in AutoDateFormatter doc-string -* :ghpull:`23773`: Backport PR #23772 on branch v3.6.x (3d plots what's new cleanups) -* :ghpull:`23772`: 3d plots what's new cleanups -* :ghpull:`23765`: Backport PR #23762 on branch v3.6.x (FIX: legend handler warning too liberal) -* :ghpull:`23762`: FIX: legend handler warning too liberal -* :ghpull:`23759`: Backport PR #23686 on branch v3.6.x (Improve matplotlib.pyplot importtime by caching ArtistInspector) -* :ghpull:`23686`: Improve matplotlib.pyplot importtime by caching ArtistInspector -* :ghpull:`23756`: Backport PR #23569 on branch v3.6.x (Fix hidden xlabel bug in colorbar) -* :ghpull:`23755`: Backport PR #23742 on branch v3.6.x (FIX: unbreak ipympl) -* :ghpull:`23569`: Fix hidden xlabel bug in colorbar -* :ghpull:`23742`: FIX: unbreak ipympl -* :ghpull:`23752`: Backport PR #23750 on branch v3.6.x (Fix rcParams documentation) -* :ghpull:`23749`: Backport PR #23735 on branch v3.6.x (Correctly handle Axes subclasses that override cla) -* :ghpull:`23735`: Correctly handle Axes subclasses that override cla -* :ghpull:`23748`: Backport PR #23746 on branch v3.6.x (DOC: add numpydoc docstring + commentary to Axis.get_ticklocs) -* :ghpull:`23747`: Backport PR #23721 on branch v3.6.x (3d plot view angle documentation) -* :ghpull:`23746`: DOC: add numpydoc docstring + commentary to Axis.get_ticklocs -* :ghpull:`23721`: 3d plot view angle documentation -* :ghpull:`23744`: Backport PR #23740 on branch v3.6.x (Clarify error for colorbar with unparented mappable) -* :ghpull:`23741`: Backport PR #23674 on branch v3.6.x (Re-rename builtin seaborn styles to not include a dot.) -* :ghpull:`23740`: Clarify error for colorbar with unparented mappable -* :ghpull:`23674`: Re-rename builtin seaborn styles to not include a dot. -* :ghpull:`23738`: Backport PR #23639 on branch v3.6.x (Adding the new contributor meeting) -* :ghpull:`23739`: Backport PR #23712 on branch v3.6.x (FIX: do not try to help CPython with garbage collection) -* :ghpull:`23712`: FIX: do not try to help CPython with garbage collection -* :ghpull:`23639`: Adding the new contributor meeting -* :ghpull:`23732`: Backport PR #23729 on branch v3.6.x (Use cleaner recursion check in PyQt FigureCanvas' resizeEvent.) -* :ghpull:`23734`: Backport PR #23733 on branch v3.6.x (DOC: Update theme configuration for upcoming changes) -* :ghpull:`23733`: DOC: Update theme configuration for upcoming changes -* :ghpull:`23728`: Backport PR #23722 on branch v3.6.x (Restore deprecation class aliases in cbook) -* :ghpull:`23729`: Use cleaner recursion check in PyQt FigureCanvas' resizeEvent. -* :ghpull:`23726`: Backport PR #23711 on branch v3.6.x (Fix deprecation messages for vendoring unused things) -* :ghpull:`23722`: Restore deprecation class aliases in cbook -* :ghpull:`23727`: Backport PR #23724 on branch v3.6.x (Fix/harmonize spacing in dependencies.rst.) -* :ghpull:`23724`: Fix/harmonize spacing in dependencies.rst. -* :ghpull:`23711`: Fix deprecation messages for vendoring unused things -* :ghpull:`23715`: Backport PR #23708 on branch v3.6.x (Loosen up test_Normalize test) -* :ghpull:`23713`: Backport PR #23710 on branch v3.6.x (Fix cmap deprecations) -* :ghpull:`23708`: Loosen up test_Normalize test -* :ghpull:`23710`: Fix cmap deprecations -* :ghpull:`23696`: Backport PR #23695 on branch v3.6.x (Document polar handling of _interpolation_steps.) -* :ghpull:`23706`: Backport PR #23705 on branch v3.6.x (DOC: Added link to class under discussion) -* :ghpull:`23705`: DOC: Added link to class under discussion -* :ghpull:`23695`: Document polar handling of _interpolation_steps. -* :ghpull:`23668`: Api deprecate cmap functions -* :ghpull:`23049`: Add ``minor`` keyword argument to ``plt.x/yticks`` -* :ghpull:`23665`: Harmonize docstrings for boxstyle/connectionstyle/arrowstyle. -* :ghpull:`23636`: FIX: macosx flush_events should process all events -* :ghpull:`23555`: Uncamelcase offsetTrans in draw_path_collection. -* :ghpull:`23682`: Fix generated documentation for deprecated modules -* :ghpull:`23678`: Get rcParams from mpl -* :ghpull:`23571`: Simplify _bind_draw_path_function. -* :ghpull:`23673`: DOC: Highlight information about avoiding labels in legend -* :ghpull:`22506`: Replace MathtextBackend mechanism. -* :ghpull:`23340`: Set correct path for Arc -* :ghpull:`23562`: Fix issue with get_edgecolor and get_facecolor in 3D plots -* :ghpull:`23634`: make.bat: Don't override SPHINXOPTS/O from the environment -* :ghpull:`23675`: Deprecate helper functions in axis3d -* :ghpull:`23676`: MNT: Get rcParams from mpl -* :ghpull:`23677`: TST: Use article class when checking for pgf -* :ghpull:`23669`: CI: Azure update from ubuntu-18.04 to ubuntu-latest and ubuntu-20.04 -* :ghpull:`23670`: Add bar color demo. -* :ghpull:`23644`: Standardize edge-on axis locations when viewing primary 3d axis planes -* :ghpull:`23563`: Fix issue with drawing 3D lines where points are from nparray -* :ghpull:`23666`: MNT: Deprecate macosx prepare subplots tool -* :ghpull:`23572`: Deprecate ``get_grid_positions(..., raw=True)``. -* :ghpull:`23525`: Add functionality to label individual bars with Axes.bar() -* :ghpull:`23667`: Fix flake8 errors introduced by crossed PRs -* :ghpull:`23554`: MNT: Remove unused imports -* :ghpull:`23659`: Simplify/fix save_diff_image. -* :ghpull:`23663`: Small cleanups to _find_fonts_by_props. -* :ghpull:`23662`: Add tolerance to test failing on ppc64le -* :ghpull:`23623`: MNT: remove _gridspecs attribute on Figure classes -* :ghpull:`23654`: Reverts macosx change to ARC -* :ghpull:`23661`: Remove unused fontsize argument from private mathtext _get_info. -* :ghpull:`23655`: Merge branch v3.5.x into main -* :ghpull:`23658`: Increase tolerance on multi-font tests -* :ghpull:`23657`: Add eps to extension list in image triager -* :ghpull:`23656`: Fix broken link to MathML torture tests. -* :ghpull:`23649`: CI: Use anaconda-client v1.10.0 for upload of nightlies -* :ghpull:`23647`: Allow any color format to be used for axis3d.Axis.set_pane_color -* :ghpull:`23643`: Enable wheels for PyPy 3.8+ -* :ghpull:`23621`: DOC: update and extend fonts explanation -* :ghpull:`23612`: CI: try installing a different version of noto on OSX -* :ghpull:`23619`: add pikepdf and visual c++ dependency -* :ghpull:`23631`: Leave out ``barh`` from the basic plot types. -* :ghpull:`23637`: BLD: Add Python 3.11 builds to CI -* :ghpull:`23632`: Add discouraged admonitions -* :ghpull:`23620`: Doc update deps -* :ghpull:`23627`: Bump pypa/cibuildwheel from 2.8.1 to 2.9.0 -* :ghpull:`23628`: Change Title Case to Upper lower in templates -* :ghpull:`23206`: Change exception type for incorrect SVG date metadata -* :ghpull:`23387`: Remove setuptools_scm_git_archive dependency and add sdist test -* :ghpull:`23605`: Fix issues in examples, docs, and tutorials -* :ghpull:`23618`: [Doc]: Document the position parameter in apply_aspect() -* :ghpull:`23355`: Revert "Try to unbreak CI by xfailing OSX Tk tests" -* :ghpull:`23610`: TST: be more forgiving about IDing Noto -* :ghpull:`23609`: print version number when building docs -* :ghpull:`20832`: Implement multi-font embedding for PS Backend -* :ghpull:`20804`: Implement multi-font embedding for PDF Backend -* :ghpull:`23202`: MNT: Remove cached renderer from figure -* :ghpull:`23497`: Avoid gridspec in more examples -* :ghpull:`23602`: Editing "issues for new contributors" -* :ghpull:`23600`: DOC: view_init docstring for 3d axes primary view angles -* :ghpull:`23587`: BUG:datetime list starting with none -* :ghpull:`23559`: re-base of font fallback for pdf and eps output + SVG support -* :ghpull:`23557`: BLD: update the manylinux versions used -* :ghpull:`23596`: Minor cleanup of axes_grid1 -* :ghpull:`23594`: Expire deprecation on passing bytes to FT2Font.set_text -* :ghpull:`23435`: Add conda env to setup instructions -* :ghpull:`23574`: Move colorbar() doc to method itself. -* :ghpull:`23584`: Bump Ubuntu to 20.04 on GitHub Actions -* :ghpull:`23561`: Clean up code in tri -* :ghpull:`23582`: Cleanup axis3d.Axis.draw -* :ghpull:`23510`: Refactor Widget tests -* :ghpull:`20718`: Circle: Build docs in parallel. -* :ghpull:`22452`: ENH: add ability to remove layout engine -* :ghpull:`23516`: warning when scatter plot color settings discarded -* :ghpull:`23577`: apply_aspect cleanups -* :ghpull:`23575`: Cleanup parasite_simple example. -* :ghpull:`23567`: Remove noop setattr_cm. -* :ghpull:`23412`: Fix dash offset bug in Patch -* :ghpull:`21756`: MNT: Clean up some UTF strings and memory autorelease -* :ghpull:`23558`: MNT: Use UTF-8 string in macosx backend -* :ghpull:`23550`: Change exception types, improve argument checking, and cleanups in mpl_toolkits -* :ghpull:`23196`: Unify set_pickradius argument -* :ghpull:`20740`: Implement Font-Fallback in Matplotlib -* :ghpull:`22566`: Add rcparam for figure label size and weight -* :ghpull:`23551`: Remove transform arguments from _iter_collection -* :ghpull:`23444`: Deduplicate common parts in LatexManager.{__init__,_setup_latex_process} -* :ghpull:`23017`: [ENH] : Provide axis('equal') for Axes3D (replace PR #22705) -* :ghpull:`22950`: Simplify definition of mathtext symbols & correctly end tokens in mathtext parsing -* :ghpull:`23409`: Provide axis('equal') for Axes3D (replaces PR #23017) -* :ghpull:`23434`: Fix array-like linewidth for 3d scatter -* :ghpull:`23500`: Move the common implementation of Axes.set_x/y/zscale to Axis. -* :ghpull:`23533`: Add tests for sankey and minor fixes -* :ghpull:`23535`: Make margins error as claimed in doc-string -* :ghpull:`23546`: Simplify impl. of functions optionally used as context managers. -* :ghpull:`23494`: Fix various issues from SonarQube -* :ghpull:`23529`: Add workflow dispatch GitHub CI -* :ghpull:`23539`: Small improvements to WebAgg example -* :ghpull:`23541`: Change doc-build CI install order -* :ghpull:`23526`: DOC: make "family" less ambiguous in FontProperties docs -* :ghpull:`23537`: Move the deprecated RendererGTK{3,4}Cairo to a single place. -* :ghpull:`23140`: [Features] Allow setting legend title alignment -* :ghpull:`23538`: Fix imprecise docs re: backend dependencies. -* :ghpull:`23532`: Add test for RGBAxes -* :ghpull:`23453`: Add more tests for mplot3d -* :ghpull:`23501`: Let Axes.clear iterate over Axises. -* :ghpull:`23469`: Inline _init_axis_artists & _init_gridlines into clear. -* :ghpull:`23475`: Add markerfacealt to pass-through arguments for error bar lines -* :ghpull:`23527`: STY: fix whitespace on an assert -* :ghpull:`23495`: Fix sgskip'd examples -* :ghpull:`23404`: Restore matplotlib.__doc__ in Sphinx docs -* :ghpull:`23507`: Add hint when More than {max_open_warning} figures have been opened -* :ghpull:`23499`: Fix outdated comment re: event handlers in test_backends_interactive. -* :ghpull:`23498`: Fix direct instantiation of webagg_core managers. -* :ghpull:`23504`: Clarify formatting of the code-for-reproduction field in bug reports. -* :ghpull:`23489`: Add missing test data to install -* :ghpull:`23482`: Mathtext spaces must be independent of font style. -* :ghpull:`23486`: Bump pypa/cibuildwheel from 2.8.0 to 2.8.1 -* :ghpull:`23461`: Tweak Axes repr. -* :ghpull:`16931`: Make it easier to improve UI event metadata. -* :ghpull:`23468`: Display grid in floating axes example. -* :ghpull:`23467`: Remove old handling for factor=None in axisartist. -* :ghpull:`23443`: Try running the pgf backend off the article class. -* :ghpull:`23373`: Fix pan/zoom crashing when widget lock is unavailable -* :ghpull:`23466`: Update filename in example. -* :ghpull:`23464`: Deprecate macos close handler. -* :ghpull:`23463`: Deprecate Tick.label -* :ghpull:`23455`: Deprecate properties w_xaxis, w_yaxis, and w_zaxis -* :ghpull:`23448`: Tweak callbacks to generate pick events. -* :ghpull:`23233`: Default stem marker color follows the linecolor -* :ghpull:`23452`: Generalize Axes __repr__ to 3D -* :ghpull:`23445`: Compare thread native ids when checking whether running on main thread. -* :ghpull:`20752`: Set norms using scale names. -* :ghpull:`23438`: DOC: numpydoc-ify date Locator classes -* :ghpull:`23427`: Tweak pgf escapes. -* :ghpull:`23432`: Fixed typo in docs animation api -* :ghpull:`23420`: Clean up test_chunksize_fails() -* :ghpull:`23415`: Minor improvements to units_sample example -* :ghpull:`21339`: Added linear scaling test to Hexbin marginals -* :ghpull:`23414`: Bump pypa/cibuildwheel from 2.7.0 to 2.8.0 -* :ghpull:`23413`: Combine chunk size tests into one -* :ghpull:`23403`: Small cleanup to VertexSelector. -* :ghpull:`23291`: In the new/simplified backend API, don't customize draw_if_interactive. -* :ghpull:`23350`: Fixed SVG-as-text image comparison tests. -* :ghpull:`23406`: DOC: Fix calculation of bin centers in multi-histogram -* :ghpull:`23407`: TST: Add missing warning type to pytest.warns -* :ghpull:`23402`: Link 3D animation examples to one another. -* :ghpull:`23401`: Upload wheel artifacts from the correct directory -* :ghpull:`23374`: GOV: point CoC reports at CoC steering council subcomittee mailing list -* :ghpull:`23393`: Clean up formatting of custom cmap example -* :ghpull:`23146`: Update cibuildwheel -* :ghpull:`23368`: Add a helper to generate closed paths. -* :ghpull:`20220`: DOC: add mission statement -* :ghpull:`22364`: Tweak mathtext/tex docs. -* :ghpull:`23377`: Use tick_params more often over tick iteration -* :ghpull:`22820`: [Doc] consolidate ``rect`` documentation -* :ghpull:`23371`: Default animation.convert_args to ["-layers", "OptimizePlus"]. -* :ghpull:`23148`: DOC: change address to send security issues to -* :ghpull:`23365`: DOC: add new showcase example, replace gendered one -* :ghpull:`23033`: Fix issue with tex-encoding on non-Unicode platforms -* :ghpull:`23358`: Shorten/clarify definition of extension types. -* :ghpull:`23370`: Small cleanups to animation. -* :ghpull:`23364`: Rename/change signature of PyGlyph_new. -* :ghpull:`23363`: Simplify FigureCanvas multiple inheritance init by swapping bases order. -* :ghpull:`23366`: MNT: use devel version of theme -* :ghpull:`23357`: Fixed decimal points not appearing at end of Mathtext string. -* :ghpull:`23351`: DOC/MNT install docs with dev version of sphinx theme -* :ghpull:`23349`: CI: Remove old scipy-wheels-nightly uploads to ensure space -* :ghpull:`23348`: Support multi-figure MultiCursor; prepare improving its signature. -* :ghpull:`23360`: embedding_in_tk_sgskip.py: use root.destroy -* :ghpull:`23354`: MNT: Use list comprehension -* :ghpull:`23299`: FIX/API: do not reset backend key in rc_context -* :ghpull:`23191`: ENH: add width_ratios and height_ratios to subplots -* :ghpull:`23060`: MNT: Change objective C code to Automatic Reference Counting (ARC) -* :ghpull:`23347`: Simplify/improve check for pycairo in Gtk-based backends. -* :ghpull:`23316`: DOC: improve spines crosslinking -* :ghpull:`23100`: Remove custom backend_nbagg.show(), putting logic in manager show. -* :ghpull:`23342`: FIX: make sure addFont test removes the test font -* :ghpull:`23266`: negative_linestyles kwarg in contour.py -* :ghpull:`23332`: Validate Text linespacing on input. -* :ghpull:`23336`: Remove ineffective exclusion of Arcs without parent Axes. -* :ghpull:`23341`: MNT: Use '--pytest-test-first' option for naming clarity -* :ghpull:`23337`: Remove now inexistent "datapath" rcParam from style blacklist. -* :ghpull:`22004`: Make RendererCairo auto-infer surface size. -* :ghpull:`23208`: ENH: enable stripey lines -* :ghpull:`23288`: Correct URL area with rotated texts in PDFs -* :ghpull:`23197`: Add tests for pan -* :ghpull:`22167`: Deprecate selector ``visible`` attribute -* :ghpull:`23322`: Cleanup FontProperties examples. -* :ghpull:`23321`: Tweak examples capitalization/punctuation. -* :ghpull:`23270`: Fix handling of nonmath hyphens in mathtext. -* :ghpull:`23310`: Move Cursor demo from examples/misc to examples/event_handling -* :ghpull:`23313`: Drop CSS styles that are in mpl-sphinx-theme -* :ghpull:`23314`: Don't draw invisible 3D Axes -* :ghpull:`23302`: Deprecate stem(..., use_line_collection=False) -* :ghpull:`23309`: Remove front page examples -* :ghpull:`23282`: Backport PR #22865 on branch v3.5.x (Fix issue with colorbar extend and drawedges) -* :ghpull:`23231`: Add pytest-xvfb as test dependency -* :ghpull:`23318`: No need to return OrderedDict from _gen_axes_spines. -* :ghpull:`23295`: Replace re.sub by the faster str.translate. -* :ghpull:`23300`: Modify example of "Fig Axes Customize Simple" -* :ghpull:`23014`: Improve consistency in LogLocator and LogFormatter API -* :ghpull:`23286`: Refactor URL handling in PDF backend -* :ghpull:`23065`: Fix test_image_comparison_expect_rms -* :ghpull:`23294`: Simplify binary data handling in ps backend. -* :ghpull:`23284`: DOC: Switch to HTML5 and cleanup CSS -* :ghpull:`23276`: Add get/set methods for DPI in SubFigure -* :ghpull:`23207`: Update build environment and improve test -* :ghpull:`23213`: DEV: Add name-tests-test to pre-commit hooks -* :ghpull:`23289`: Properly make Name.hexify go through a deprecation cycle. -* :ghpull:`23177`: Deprecate positional passing of most Artist constructor parameters -* :ghpull:`23287`: Minor tweaks to pdf Name. -* :ghpull:`23285`: In mathtext, replace manual caching (via ``glyphd``) by lru_cache. -* :ghpull:`23034`: Correctly read the 'style' argument while processing 'genfrac'. -* :ghpull:`23247`: Support inverted parentheses in mathtext. -* :ghpull:`23190`: Deprecate unused methods in axis.py -* :ghpull:`23219`: MNT: Rename example files with 'test' in name -* :ghpull:`23277`: MNT: Remove dead code in SVG backend -* :ghpull:`23261`: Bump actions/setup-python from 3 to 4 -* :ghpull:`23264`: Changing environment.yml for it to work on Windows -* :ghpull:`23269`: MNT: Remove dead code in Colorbar -* :ghpull:`23262`: Simplify qt_compat, in particular post-removal of qt4 support. -* :ghpull:`23263`: Private helper to get requested backend without triggering resolution. -* :ghpull:`23243`: Fix spacing after mathtext operators with sub/superscripts -* :ghpull:`22839`: Fix spacing after mathtext operators with sub/superscripts -* :ghpull:`23256`: DOC: Add note about Inkscape install on Windows -* :ghpull:`23258`: DOC: remove Blue Book url -* :ghpull:`23255`: Add a helper to generate mathtext error strings. -* :ghpull:`23246`: Fix argument checking for set_interpolation_stage -* :ghpull:`22881`: Support not embedding glyphs in svg mathtests. -* :ghpull:`23198`: Rename ncol parameter in legend to ncols -* :ghpull:`23251`: Small simplifications to mathtext tests. -* :ghpull:`23249`: Don't allow ``r"$\left\\|\right.$"``, as in TeX. -* :ghpull:`23248`: Rename test markers -* :ghpull:`22507`: Remove *math* parameter of various mathtext internal APIs. -* :ghpull:`23192`: Add tests, improve error messages in axis/_base, and code cleanup -* :ghpull:`23241`: Fix invalid value in radio buttons example -* :ghpull:`23187`: Correct docs and use keyword arguments in _mathtext.py -* :ghpull:`23045`: MNT: Merge locally defined test marks -* :ghpull:`22289`: ENH: compressed layout -* :ghpull:`23237`: Expire BoxStyle._Base deprecation. -* :ghpull:`23225`: DOC: Fix version switcher links to documentation -* :ghpull:`23221`: DOC: recommend numpy random number generator class -* :ghpull:`23223`: Changed offset reference, add small doc -* :ghpull:`23215`: DOC: link the transforms tutorial from the module -* :ghpull:`23201`: Rework tricontour and tricontourf documentation -* :ghpull:`23013`: Add tests for date module -* :ghpull:`23188`: Mnt new default dates -* :ghpull:`22745`: MNT: Don't require renderer for window_extent and tightbbox -* :ghpull:`23077`: MNT: Remove keyword arguments to gca() -* :ghpull:`23182`: Simplify webagg blitting. -* :ghpull:`23181`: Init FigureCanvasAgg._lastKey in ``__init__``. -* :ghpull:`23175`: Point the version switcher to a name listed in switcher.json -* :ghpull:`22669`: Cleanup documentation generation for pyplot -* :ghpull:`22519`: fix markevery plot option with nans in data -* :ghpull:`21584`: Move towards having get_shared_{x,y}_axes return immutable views. -* :ghpull:`23170`: ENH: update ticks when requesting labels -* :ghpull:`23169`: DOC: Migrate to sphinx-design -* :ghpull:`23180`: Improve docstring of triplot() and PatchCollection -* :ghpull:`23153`: Restore accidentally removed pytest.ini and tests.py. -* :ghpull:`23166`: Deprecate passing most Legend arguments positionally -* :ghpull:`23165`: DOCS Fix a few typos -* :ghpull:`23167`: DOCS fix typo -* :ghpull:`23062`: Add stackplot to plot types listing -* :ghpull:`23161`: Added my (open access) book -* :ghpull:`23141`: Minor fix for astropy units support broken in earlier PR -* :ghpull:`23156`: No longer call draw_if_interactive in parasite_axes. -* :ghpull:`23150`: DOC fix typo -* :ghpull:`23149`: DOCS remove duplicate text -* :ghpull:`23145`: Fix format error in switcher.json -* :ghpull:`21755`: MNT: Clean up macosx backend set_message -* :ghpull:`23128`: DOCS Fix typos -* :ghpull:`23130`: Drop pytest warning config in nightly tests -* :ghpull:`23135`: Unpin coverage again -* :ghpull:`23133`: Make module deprecation messages consistent -* :ghpull:`23134`: Remove newline from start of deprecation warnings -* :ghpull:`22964`: Fix spelling errors -* :ghpull:`22929`: Handle NaN in bar labels and error bars -* :ghpull:`23093`: MNT: Removing 3.4 deprecations -* :ghpull:`23090`: Derive new_figure_manager from FigureCanvas.new_manager. -* :ghpull:`23099`: Remove unneeded cutout for webagg in show(). -* :ghpull:`23097`: Tweak check for IPython pylab mode. -* :ghpull:`23088`: Improve error for invalid format strings / misspelled data keys. -* :ghpull:`23092`: Ensure updated monkey-patching of sphinx-gallery EXAMPLE_HEADER -* :ghpull:`23087`: Fix width/height inversion in dviread debug helper. -* :ghpull:`23089`: Normalize tk load failures to ImportErrors. -* :ghpull:`23091`: Move test that fig.add_axes() needs parameters -* :ghpull:`23067`: more explicit in windows doc build instructions -* :ghpull:`23081`: MNT: Deprecate date_ticker_factory -* :ghpull:`23079`: MNT: Remove key_press and button_press from FigureManager -* :ghpull:`23076`: MNT: Remove positional argument handling in LineCollection -* :ghpull:`23078`: MNT: Remove deprecated axis.cla() -* :ghpull:`23054`: Slightly simplify tcl/tk load in extension. -* :ghpull:`23073`: MNT: Remove dummy_threading because threading is always available -* :ghpull:`22405`: DOC: put the gallery keywords in the meta tag -* :ghpull:`23071`: Fix installing contourpy on CI -* :ghpull:`23068`: Slight refactor of _c_internal_utils to linewrap it better. -* :ghpull:`23070`: Pathlibify autotools invocation in build. -* :ghpull:`22755`: Maybe run autogen as part of freetype install -* :ghpull:`23063`: doc: mathtext example: use axhspan() instead of fill_between() for backdrop rectangle shading -* :ghpull:`23055`: Cleanup Annotation.update_position. -* :ghpull:`22567`: Use contourpy for quad contour calculations -* :ghpull:`22801`: TST: fully parameterize test_lazy_linux_headless -* :ghpull:`22180`: ENH: Use rcParams savefig.directory on macosx backend -* :ghpull:`23048`: Add rrulewrapper to docs -* :ghpull:`23047`: Fix issue with hist and float16 data -* :ghpull:`23044`: Fix missing section header for nightly builds -* :ghpull:`23029`: Demonstrate both usetex and non-usetex in demo_text_path.py. -* :ghpull:`23038`: Factor out errorevery parsing for 2D and 3D errorbars. -* :ghpull:`23036`: Suppress traceback chaining for tex subprocess failures. -* :ghpull:`23037`: Suppress exception chaining in FontProperties. -* :ghpull:`23020`: Add test to close legend issue -* :ghpull:`23031`: Specify that style files are utf-8. -* :ghpull:`22991`: Enable ``plt.sca`` on subfigure's axes -* :ghpull:`23030`: DOC: Fix charset declaration in redirects -* :ghpull:`23022`: Fix some possible encoding issues for non-utf8 systems. -* :ghpull:`23023`: Bump docker/setup-qemu-action from 1 to 2 -* :ghpull:`23024`: DOC: do not suggest to sudo pip install Matplotlib -* :ghpull:`23018`: Fix typo in font family -* :ghpull:`22627`: ENH: rect for constrained_layout -* :ghpull:`22891`: Font example monospace -* :ghpull:`23006`: docs: add subplot-mosaic string compact notation -* :ghpull:`23009`: Fixed installation guide command typo -* :ghpull:`22926`: Fix RangeSlider for same init values #22686 -* :ghpull:`22989`: Merge v3.5.x back into main -* :ghpull:`22993`: STY: Fix typos in colormap -* :ghpull:`22777`: DEV: Add codespell to pre-commit hooks -* :ghpull:`22940`: Fixed dpi bug in rainbow text example -* :ghpull:`22298`: MNT: Remove cmap_d colormap access -* :ghpull:`22387`: Add a registry for color sequences -* :ghpull:`21594`: Document text alignment -* :ghpull:`22967`: TST: Add some tests for QuadMesh contains function -* :ghpull:`22936`: ENH: Add full-screen toggle to the macosx backend -* :ghpull:`22886`: MNT: remove mpl_toolkits.axes_grid -* :ghpull:`22952`: Make MarkerStyle immutable -* :ghpull:`22953`: MNT: Move set_cursor to the FigureCanvas -* :ghpull:`18854`: Standardize creation of FigureManager from a given FigureCanvas class. -* :ghpull:`22925`: Standardize creation of FigureManager from a given FigureCanvas class. -* :ghpull:`22875`: Remove Forward definitions where possible. -* :ghpull:`22928`: ENH: Add option to disable raising the window for macosx -* :ghpull:`22912`: DOC: Better doc of colors -* :ghpull:`22931`: BUG: Fix regression with ls=(0, ()) -* :ghpull:`22909`: FIX: skip sub directories when finding fonts on windows -* :ghpull:`22911`: Clarify docstring of [un]install_repl_displayhook() -* :ghpull:`22919`: CI: Add concurrency skips for GH Actions -* :ghpull:`22899`: Fix documentation markup issues -* :ghpull:`22906`: Clarify logic for repl displayhook. -* :ghpull:`22892`: Remove support for IPython<4. -* :ghpull:`22896`: Remove python-dateutil as test requirement -* :ghpull:`22885`: Deprecate two-layered backend_pdf.Op enum. -* :ghpull:`22883`: Tweak argument checking in tripcolor(). -* :ghpull:`22884`: Missing ``f`` prefix on f-strings fix -* :ghpull:`22877`: Small cleanups to mathtext. -* :ghpull:`21374`: Snap selectors -* :ghpull:`22824`: Remove some unnecessary extra boundaries for colorbars with extensions. -* :ghpull:`21448`: Use named groups in mathtext parser. -* :ghpull:`22609`: Improve usability of dviread.Text by third parties. -* :ghpull:`22809`: STY: Apply pre-commit hooks to codebase -* :ghpull:`22730`: Fix removed cross-references -* :ghpull:`22857`: Slightly simplify twin axes detection in MEP22 zoom. -* :ghpull:`22813`: MNT: Deprecate figure callbacks -* :ghpull:`22802`: MNT: make Axes.cla an alias for Axes.clear in all cases -* :ghpull:`22855`: Remove non-needed remove_text=False. -* :ghpull:`22854`: TST: Avoid floating point errors in asinh ticker -* :ghpull:`22850`: Simplify tick creation -* :ghpull:`22841`: Fix Tk error when updating toolbar checkbutton images -* :ghpull:`22707`: Proposed ENH: Allow user to turn off breaking of streamlines in streamplot (rebased) -* :ghpull:`22826`: Bump actions/upload-artifact from 2 to 3 -* :ghpull:`22825`: Bump codecov/codecov-action from 2 to 3 -* :ghpull:`22821`: Use bool for bool keyword arguments -* :ghpull:`22815`: Fix pickling of globally available, dynamically generated norm classes. -* :ghpull:`22702`: Doc tweak transform tutorial -* :ghpull:`22613`: DOC: Add links to explicit vs implicit API everywhere "OO" is used -* :ghpull:`22712`: Use repr in error messages -* :ghpull:`22794`: Fix ps export of colored hatches with no linewidth -* :ghpull:`22797`: Deprecate functions in backends -* :ghpull:`22608`: Axes.inset_axes: enable Axes subclass creation -* :ghpull:`22795`: Replace "marker simplification" by "marker subsampling" in docs. -* :ghpull:`22768`: Fix inkscape tests -* :ghpull:`22791`: Tweak _ConverterError reporting. -* :ghpull:`22447`: Improve bar_label annotation -* :ghpull:`22710`: Fix the error- TypeError: 'float' object is not iterable -* :ghpull:`22444`: Revert "CI: skip test to work around gs bug" -* :ghpull:`22785`: CI: Update weekly dependency test job -* :ghpull:`22784`: Fix 'misspelled' transform variable -* :ghpull:`22778`: Fix LaTeX formatting in examples -* :ghpull:`22779`: Improve mlab documentation (and example) -* :ghpull:`22759`: MNT: Skip existing wheels during nightly wheel upload -* :ghpull:`22751`: BLD: do not put an upper bound on pyparsing -* :ghpull:`22752`: DOC: Correct nightly wheels pip install command -* :ghpull:`22742`: Fix deprecation of backend_tools.ToolBase.destroy -* :ghpull:`22725`: Move towards making texmanager stateless. -* :ghpull:`22734`: Added clim support to tripcolor -* :ghpull:`22733`: CI: Add GHA workflow to upload nightly wheels -* :ghpull:`21637`: Also upload a subset of nightly wheels -* :ghpull:`22698`: Correct cross-references in documentation -* :ghpull:`22263`: DOC: condense version switcher -* :ghpull:`22361`: Revert datetime usetex ticklabels to use default tex font. -* :ghpull:`22721`: Small style fixes. -* :ghpull:`22356`: Cleanup tripcolor() -* :ghpull:`22360`: Let TeX handle multiline strings itself. -* :ghpull:`22418`: Deprecate auto-removal of overlapping Axes by plt.subplot{,2grid}. -* :ghpull:`22722`: Rename confusingly-named cm_fallback. -* :ghpull:`22697`: Deprecate in testing.decorators -* :ghpull:`22556`: Add text.parse_math rcParams -* :ghpull:`22163`: Change colour of Tk toolbar icons on dark backgrounds -* :ghpull:`22704`: Small simplification to textpath. -* :ghpull:`22498`: TST: increase coverage on tk tests -* :ghpull:`21425`: Make Axis3D constructor signature closer to the one of 2D axis. -* :ghpull:`22665`: Improve error message for incorrect color string -* :ghpull:`22685`: Rewrite plot format detection from sphinx build target -* :ghpull:`22670`: Update deprecated vmImage 'vs2017-win2016' in azure pipelines -* :ghpull:`22503`: Deprecate backend_qt.qApp. -* :ghpull:`22683`: Add missing space before : for parameters -* :ghpull:`22591`: Fix Path/str-discrepancy in FontManager.addpath and improve documentation -* :ghpull:`22680`: Bump actions/cache from 2 to 3 -* :ghpull:`22659`: Add description on quiver head parameters -* :ghpull:`22668`: Raise on missing closing quotes in matplotlibrc -* :ghpull:`22675`: Tweak colorbar_placement example. -* :ghpull:`22276`: Merge "Scatter Symbol" and "Scatter Custom Symbol" examples -* :ghpull:`22658`: Remove reference to now-deleted reminder note. -* :ghpull:`22652`: Update documentation example and fix See also -* :ghpull:`22587`: Refactor handling of tick and ticklabel visibility in Axis.clear() -* :ghpull:`22148`: MNT: Deprecate ``docstring`` -* :ghpull:`22170`: Add example to polygon selector docstring showing how to set vertices programmatically -* :ghpull:`22650`: Fix new leak in ft2font introduced in #22604 -* :ghpull:`22644`: FIX: Flush events after closing figures in macosx backend -* :ghpull:`22643`: Suppress exception chaining in colormap lookup. -* :ghpull:`22639`: ENH: MacOSX backend to use sRGB instead of GenericRGB colorspace -* :ghpull:`22509`: Simplifications to ToolManager.{add,remove}_tool. -* :ghpull:`22633`: DOC: remove space in directive. -* :ghpull:`22631`: Add space between individual transform components in svg output. -* :ghpull:`22523`: MNT: Use a context manager to change the norm in colorbar code -* :ghpull:`22615`: FIX: Change get_axis_map to axis_map now -* :ghpull:`22508`: Move tracking of autoscale status to Axis. -* :ghpull:`22547`: Small cleanups around TexManager usage. -* :ghpull:`22511`: Remove redundant rcParam-lookup in patches -* :ghpull:`22516`: Expire deprecations in backends -* :ghpull:`22612`: Updated grammar to reflect more common usage of output vs outputted in animation.py -* :ghpull:`22589`: Support quoted strings in matplotlibrc -* :ghpull:`22604`: MNT: Fix types in C-code to reduce warnings -* :ghpull:`22610`: Fix alternative suggestion in epoch2num() deprecation -* :ghpull:`22554`: Prepare for making create_dummy_axis not necessary. -* :ghpull:`22607`: ENH: Add dark/light mode theme to the buttons -* :ghpull:`21790`: FIX: Update blitting and drawing on the macosx backend -* :ghpull:`22175`: FIX: Update macosx animation handling -* :ghpull:`22569`: Require non-zero dash value -* :ghpull:`22544`: Correct paper sizes -* :ghpull:`20470`: Issues warnings for legend handles without handlers -* :ghpull:`22558`: MNT: Simplify imports -* :ghpull:`22580`: fix doc for annotation_clip parameter -* :ghpull:`22581`: DOC: fix various typos -* :ghpull:`22573`: Bump actions/setup-python from 2 to 3 -* :ghpull:`22568`: Rename qhull source to _qhull_wrapper.cpp. -* :ghpull:`22561`: FIX: Handle stopped animation figure resize -* :ghpull:`22562`: TST: Add a frame test for animations -* :ghpull:`22514`: Expire deprecations in cbook.deprecation -* :ghpull:`22555`: Use picklable callbacks for DraggableBase. -* :ghpull:`22552`: Tweak dependency checking in doc/conf.py. -* :ghpull:`22550`: Require sphinx>=3 & numpydoc>=1.0 for building docs. -* :ghpull:`22539`: Deprecate toplevel mpl.text.get_rotation; normalize rotations early. -* :ghpull:`22502`: Cleanup unused imports and variables in backends -* :ghpull:`20071`: Document, test, and simplify impl. of auto_adjustable_area. -* :ghpull:`22366`: Deprecation removal/updates in axes3d -* :ghpull:`22484`: Simplify the internal API to connect picklable callbacks. -* :ghpull:`22417`: Support passing rgbaFace as an array to agg's draw_path. -* :ghpull:`22412`: Turn _get_axis_map() into a property and remove _get_axis_list() -* :ghpull:`22486`: Expire deprecations in lines and patches -* :ghpull:`22512`: Increase coverage -* :ghpull:`22504`: Simplify FontProperties init. -* :ghpull:`22497`: Remove entries of MathTextParser._backend_mapping deprecated in 3.4. -* :ghpull:`22487`: Don't key MathTextParser cache off a mutable FontProperties. -* :ghpull:`22468`: Turn _mathtext.ship into a plain function. -* :ghpull:`22490`: Deprecate unused, untested Affine2D.identity(). -* :ghpull:`22491`: Linewrap setupext to 79 character lines. -* :ghpull:`22488`: Some more maintenance for mathtext internal implementation. -* :ghpull:`22485`: Change string representation of AxesImage -* :ghpull:`22240`: Add minimum macosx version -* :ghpull:`22480`: Remove _point_size_reduction. -* :ghpull:`22204`: Cleanup _mathtext internal API -* :ghpull:`22469`: Improve readability of mathtext internal structures. -* :ghpull:`22477`: Un-pyplot some examples which were already explicitly referencing axes. -* :ghpull:`22467`: Small cleanup to font handling in agg. -* :ghpull:`21178`: Add asinh axis scaling (*smooth* symmetric logscale) -* :ghpull:`22411`: Move cbook._define_aliases() to _api.define_aliases() -* :ghpull:`22465`: Deprecate unused AddList. -* :ghpull:`22451`: Clarify error message for bad keyword arguments. -* :ghpull:`21267`: Cleanup AnnotationBbox. -* :ghpull:`22464`: Small improvements related to radar_chart example. -* :ghpull:`22421`: Make most params to figure()/Figure() kwonly. -* :ghpull:`22457`: Copy arrowprops argument to FancyAnnotationBbox. -* :ghpull:`22454`: move ``_toolbar_2`` from webagg_core to webagg -* :ghpull:`22413`: Remove some trivial private getters/setters in axisartist -* :ghpull:`21634`: TST: Add future dependency tests as a weekly CI job -* :ghpull:`22079`: Share FigureManager class between gtk3 and gtk4. -* :ghpull:`22440`: Clarify warning about labels with leading underscores. -* :ghpull:`17488`: Make error message explicit in legend.py -* :ghpull:`22453`: Simplify impl. of polar limits setting API. -* :ghpull:`22449`: Small cleanup to quiver. -* :ghpull:`22415`: Make emit and auto args of set_{x,y,z}lim keyword only. -* :ghpull:`22422`: Deprecate backend_ps.convert_psfrags. -* :ghpull:`22194`: Drop support for Python 3.7 -* :ghpull:`22234`: Partial fix for grid alpha -* :ghpull:`22433`: Fix ambiguous link targets in docs. -* :ghpull:`22420`: Update plt.figure() docstring. -* :ghpull:`22388`: Make signature of Axes.annotate() more explicit. -* :ghpull:`22419`: Remove "Matplotlib version" from docs issue template -* :ghpull:`22423`: Avoid indiscriminate glob-remove in xpdf_distill. -* :ghpull:`22406`: [DOC]: Removed a redundant 'The' -* :ghpull:`21442`: Factor out common limits handling for x/y/z axes. -* :ghpull:`22397`: Axes capitalization in widgets and axes3d -* :ghpull:`22394`: Tweak Axes3D docstrings that refer to 2D plotting methods. -* :ghpull:`22383`: TST: fix doc build -* :ghpull:`21877`: DOC: attempt to explain the main different APIs -* :ghpull:`21238`: Raise when unknown signals are connected to CallbackRegistries. -* :ghpull:`22345`: MNT: make layout deprecations pending -* :ghpull:`21597`: FIX: Remove the deepcopy override from transforms -* :ghpull:`22370`: Replace tabs with spaces in C code. -* :ghpull:`22371`: Corrected a mistake in comments (Issue #22369) -* :ghpull:`21352`: Refactor hexbin(). -* :ghpull:`19214`: Improve autoscaling for high order Bezier curves -* :ghpull:`22268`: Deprecated is_decade and is_close_to_int -* :ghpull:`22359`: Slightly refactor TeX source generation. -* :ghpull:`22365`: Remove deprecated ``MovieWriter.cleanup`` -* :ghpull:`22363`: Properly capitalize "Unicode". -* :ghpull:`22025`: Deprecate various custom FigureFrameWx attributes/methods. -* :ghpull:`21391`: Reuse imsave()'s background-blending code in FigureCanvasAgg.print_jpeg. -* :ghpull:`22026`: Simplify wxframe deletion. -* :ghpull:`22351`: Fix "trailing" whitespace in C docstrings. -* :ghpull:`22342`: Docstrings for _qhull. -* :ghpull:`21836`: Slightly shorten ft2font init. -* :ghpull:`21962`: Privatize various internal APIs of backend_pgf. -* :ghpull:`22114`: Rewrite AxesStack independently of cbook.Stack. -* :ghpull:`22332`: Let TransformedPatchPath inherit most functionality from TransformedPath. -* :ghpull:`22292`: Cleanup Axis._translate_tick_kw -* :ghpull:`22339`: wx.App() should be init'ed in new_figure_manager_given_figure -* :ghpull:`22315`: More standardization of floating point slop in mpl_toolkits. -* :ghpull:`22337`: DOC: More cleanup axes -> Axes -* :ghpull:`22323`: Replace sole use of maxdict by lru_cache. -* :ghpull:`22229`: FIX: make safe to add / remove artists during ArtistList iteration -* :ghpull:`22196`: ``dates`` classes and functions support ``tz`` both as string and ``tzinfo`` -* :ghpull:`22161`: Add box when setting ``PolygonSelector.verts`` -* :ghpull:`19368`: Raise warning and downsample if data given to _image.resample is too large -* :ghpull:`22250`: Unify toolbar init across backends. -* :ghpull:`22304`: Added tests for ContourSet.legend_elements -* :ghpull:`21583`: Add pre-commit config and dev instructions -* :ghpull:`21547`: Custom cap widths in box and whisker plots in bxp() and boxplot() -* :ghpull:`20887`: Implement a consistent behavior in TkAgg backend for bad blit bbox -* :ghpull:`22317`: Rename outdated seaborn styles. -* :ghpull:`22271`: Rework/fix Text layout cache. -* :ghpull:`22097`: In mpl_toolkits, use the same floating point slop as for standard ticks. -* :ghpull:`22295`: Display bad format string in error message. -* :ghpull:`22287`: Removed unused code and variables -* :ghpull:`22244`: MNT: colorbar locators properties -* :ghpull:`22270`: Expanded documentation of Axis.set_ticks as per discussion in issue #22262 -* :ghpull:`22280`: Simplify FontProperties.copy(). -* :ghpull:`22174`: Give the Tk toolbar buttons a flat look -* :ghpull:`22046`: Add the ability to change the focal length of the camera for 3D plots -* :ghpull:`22251`: Colorbar docstring reorg -* :ghpull:`21933`: MNT: privatize colorbar attr -* :ghpull:`22258`: DOC: fix version switcher -* :ghpull:`22261`: DOC: fix switcher json -* :ghpull:`22154`: Add some tests for minspan{x,y} in RectangleSelector -* :ghpull:`22246`: DOC: add dropdown -* :ghpull:`22133`: Deprecated ``afm``, ``fontconfig_pattern``, and ``type1font`` -* :ghpull:`22249`: DOC: More capitalization of Axes -* :ghpull:`22021`: Ensure that all toolbar (old/new) subclasses can be init'ed consistently -* :ghpull:`22213`: Improve ft2font error reporting. -* :ghpull:`22245`: Deprecate cleared kwarg to get_renderer. -* :ghpull:`22239`: Fix typos -* :ghpull:`22216`: turn off the grid after creating colorbar axes -* :ghpull:`22055`: FIX: Return value instead of enum in get_capstyle/_joinstyle -* :ghpull:`22228`: Remove some unnecessary getattrs. -* :ghpull:`20426`: ENH: Layout engine -* :ghpull:`22224`: Trivial doc fix to annotations tutorial. -* :ghpull:`21894`: Jointly track x and y in PolygonSelector. -* :ghpull:`22205`: Bump minimum NumPy to 1.19 -* :ghpull:`22203`: Factor out underline-thickness lookups in mathtext. -* :ghpull:`22189`: DOC: Add hatch API to reference -* :ghpull:`22084`: Clean up 3d plot box_aspect zooming -* :ghpull:`22098`: Expire axes_grid1/axisartist deprecations. -* :ghpull:`22013`: Use standard toolbar in wx. -* :ghpull:`22160`: Removed unused variables etc. -* :ghpull:`22179`: FIX: macosx check case-insensitive app name -* :ghpull:`22157`: Improved coverage of mathtext and removed unused code -* :ghpull:`21781`: Use a fixture to get widget testing axes -* :ghpull:`22140`: Ensure log formatters use Unicode minus -* :ghpull:`21342`: Fix drawing animated artists changed in selector callback -* :ghpull:`22134`: Deprecated ``tight_bbox`` and ``tight_layout`` modules -* :ghpull:`21965`: Switch transOffset to offset_transform. -* :ghpull:`22145`: Make Tk windows use the same icon as other backends -* :ghpull:`22107`: Expire mathttext-related deprecations -* :ghpull:`22139`: FIX: width/height were reversed in macosx rectangle creation -* :ghpull:`22123`: Deprecate accepting arbitrary parameters in some get_window_extent() methods -* :ghpull:`22122`: Hint at draw_without_rendering() in Text.get_window_extent -* :ghpull:`22120`: Drop dependency on scipy in the docs. -* :ghpull:`22063`: FIX: Autoposition title when yaxis has offset -* :ghpull:`22119`: Micro-optimize skew(). -* :ghpull:`22109`: Remove unnecessary null checks in macosx.m, and some more maintenance -* :ghpull:`21977`: Add corner coordinate helper methods to Ellipse/Rectangle -* :ghpull:`21830`: Add option of bounding box for PolygonSelector -* :ghpull:`22115`: Turn _localaxes into a plain list. -* :ghpull:`22108`: Micro-optimize rotation transform. -* :ghpull:`22043`: Cleanup differential equations examples. -* :ghpull:`22080`: Simple style(ish) fixes. -* :ghpull:`22110`: Right-aligned status text in backends -* :ghpull:`21873`: DOC: Update and consolidate Custom Tick Formatter for Time Series example -* :ghpull:`22112`: Fix a small typo -* :ghpull:`20117`: Very soft-deprecate AxesDivider.new_{horizontal,vertical}. -* :ghpull:`22034`: Update lines_with_ticks_demo.py -* :ghpull:`22102`: DOC: rename usage tutorial to quick_start -* :ghpull:`19228`: Validate text rotation in setter -* :ghpull:`22081`: Expire colorbar-related deprecations. -* :ghpull:`22008`: Added color keyword argument to math_to_image -* :ghpull:`22058`: Remove exprired mplot3d deprecations for 3.6 -* :ghpull:`22073`: DOC: Add new tutorial to external resources. -* :ghpull:`22054`: MNT: Set CapStyle member names automatically -* :ghpull:`22061`: De-duplicate mplot3D API docs -* :ghpull:`22075`: Remove unnecessary ``.figure`` qualifier in docs. -* :ghpull:`22051`: Make required_interactive_framework required on FigureCanvas. -* :ghpull:`22050`: Deprecate the noop, unused FigureCanvasBase.resize. -* :ghpull:`22030`: Add explanatory comments to "broken" horizontal bar plot example -* :ghpull:`22001`: Fix: [Bug]: triplot with 'ls' argument yields TypeError #21995 -* :ghpull:`22045`: Fill in missing Axes3D box_aspect argument docstring -* :ghpull:`22042`: Keep FontEntry helpers private. -* :ghpull:`21042`: Make rcParams.copy() return a new RcParams instance. -* :ghpull:`22032`: flipy only affects the drawing of texts, not of images. -* :ghpull:`21993`: Added docstring to rrulewrapper class -* :ghpull:`21935`: Significantly improve tight layout performance for cartopy axes -* :ghpull:`22000`: Some gtk cleanups. -* :ghpull:`21983`: Simplify canvas class control in FigureFrameWx. -* :ghpull:`21985`: Slightly tighten the _get_layout_cache_key API. -* :ghpull:`22020`: Simplify wx _print_image. -* :ghpull:`22010`: Fix syntax highlighting in contrib guide. -* :ghpull:`22003`: Initialize RendererCairo.{width,height} in constructor. -* :ghpull:`21992`: Use _make_classic_style_pseudo_toolbar more. -* :ghpull:`21916`: Fix picklability of make_norm_from_scale norms. -* :ghpull:`21981`: FigureCanvasCairo can init RendererCairo; kill RendererCairo subclasses. -* :ghpull:`21986`: InvLogTransform should only return masked arrays for masked inputs. -* :ghpull:`21991`: PEP8ify wx callback names. -* :ghpull:`21975`: DOC: remove experimental tag from CL -* :ghpull:`21989`: Autoinfer norm bounds. -* :ghpull:`21980`: Removed loaded modules logging -* :ghpull:`21982`: Deprecate duplicated FigureManagerGTK{3,4}Agg classes. -* :ghpull:`21963`: Clarify current behavior of draw_path_collection. -* :ghpull:`21974`: Reword inset axes example. -* :ghpull:`21835`: Small improvements to interactive examples -* :ghpull:`21050`: Store dash_pattern as single attribute, not two. -* :ghpull:`21557`: Fix transparency when exporting to png via pgf backend. -* :ghpull:`21904`: Added _repr_html_ for fonts -* :ghpull:`21696`: Use cycling iterators in RendererBase. -* :ghpull:`21955`: Refactor common parts of ImageMagick{,File}Writer. -* :ghpull:`21952`: Clarify coordinates for RectangleSelector properties -* :ghpull:`21964`: Fix some more missing references. -* :ghpull:`21516`: Make _request_autoscale_view more generalizable to 3D. -* :ghpull:`21947`: Slightly cleanup RendererBase docs. -* :ghpull:`21961`: Privatize various internal APIs of backend_pgf. -* :ghpull:`21956`: Remove tests for avconv animation writers. -* :ghpull:`21954`: DOC: Move Animation and MovieWriter inheritance diagrams ... -* :ghpull:`21780`: Add a click_and_move widget test helper -* :ghpull:`21941`: Merge branch v3.5.x into main -* :ghpull:`21936`: Small ``__getstate__`` cleanups. -* :ghpull:`21939`: Update comment re: register_at_fork. -* :ghpull:`21910`: Fold _rgbacache into _imcache. -* :ghpull:`21921`: Clean up RectangleSelector move code -* :ghpull:`21925`: Drop labelling from PR welcome action -* :ghpull:`14930`: Set Dock icon on the macosx backend -* :ghpull:`21920`: Improve square state calculation in RectangleSelector -* :ghpull:`21919`: Fix use_data_coordinates docstring -* :ghpull:`21881`: Add a PolygonSelector.verts setter -* :ghpull:`20839`: Fix centre and square state and add rotation for rectangle selector -* :ghpull:`21874`: DOC: Add Date Tick Locators and Formatters example -* :ghpull:`21799`: Added get_font_names() to fontManager -* :ghpull:`21871`: DOC: Code from markevery_prop_cycle moved to test. -* :ghpull:`21395`: Expire _check_savefig_extra_args-related deprecations. -* :ghpull:`21867`: Remove unused bbox arg to _convert_agg_to_wx_bitmap. -* :ghpull:`21868`: Use partialmethod for better signatures in backend_ps. -* :ghpull:`21520`: Shorten some inset_locator docstrings. -* :ghpull:`21737`: Update the "Rotating a 3D plot" gallery example to show all 3 rotation axes -* :ghpull:`21851`: Re-order a widget test function -* :ghpull:`10762`: Normalization of elevation and azimuth angles for surface plots -* :ghpull:`21426`: Add ability to roll the camera in 3D plots -* :ghpull:`21822`: Replace NSDictionary by switch-case. -* :ghpull:`21512`: MNT: Add modifier key press handling to macosx backend -* :ghpull:`21784`: Set macOS icon when using Qt backend -* :ghpull:`21748`: Shorten PyObjectType defs in macosx.m. -* :ghpull:`21809`: MNT: Turn all macosx warnings into errors while building -* :ghpull:`21792`: Fix missing return value in closeButtonPressed. -* :ghpull:`21767`: Inherit many macos backend docstrings. -* :ghpull:`21766`: Don't hide build log on GHA. -* :ghpull:`21728`: Factor out some macosx gil handling for py-method calls from callbacks. -* :ghpull:`21754`: Update gitattributes so that objc diffs are correctly contextualized. -* :ghpull:`21752`: Add a helper for directly output pdf streams. -* :ghpull:`21750`: Don't sort pdf dicts. -* :ghpull:`21745`: DOC: Clarify Coords Report Example -* :ghpull:`21746`: Fix/add docstring signatures to many C++ methods. -* :ghpull:`21631`: DOC: change gridspec tutorial to arranging_axes tutorial -* :ghpull:`21318`: FIX: better error message for shared axes and axis('equal') -* :ghpull:`21519`: mark_inset should manually unstale axes limits before drawing itself. -* :ghpull:`21724`: Fix copyright date with SOURCE_DATE_EPOCH set -* :ghpull:`21398`: FIX: logic of title repositioning -* :ghpull:`21717`: Simplify macosx toolbar init. -* :ghpull:`21690`: Whitespace/braces/#defines cleanup to macosx. -* :ghpull:`21695`: Use _api.check_shape more. -* :ghpull:`21698`: Small code cleanups and style fixes. -* :ghpull:`21529`: Delay-load keymaps in toolmanager. -* :ghpull:`21525`: Fix support for clim in scatter. -* :ghpull:`21697`: Drop non-significant zeros from ps output. -* :ghpull:`21692`: CI: Remove CI test runs from forks of matplotlib -* :ghpull:`21591`: Make ToolFullScreen a Tool, not a ToolToggle. -* :ghpull:`21677`: Simplify test for negative xerr/yerr. -* :ghpull:`21657`: Replace some image_comparisons by return-value-tests/check_figures_e… -* :ghpull:`21664`: Merge 3.5.x into main -* :ghpull:`21490`: Make Line2D copy its inputs -* :ghpull:`21639`: Skip some uses of packaging's PEP440 version for non-Python versions. -* :ghpull:`21604`: Fix centre square rectangle selector part 1 -* :ghpull:`21593`: Check for images added-and-modified in a same PR -* :ghpull:`20750`: Shorten issue templates -* :ghpull:`21590`: Make gtk3 full_screen_toggle more robust against external changes. -* :ghpull:`21582`: Organize checklist in PR template -* :ghpull:`21580`: Rename/remove _lastCursor, as needed. -* :ghpull:`21567`: Removed the range parameter from the validate_whiskers function's err… -* :ghpull:`21565`: Further remove remnants of offset_position. -* :ghpull:`21542`: [ENH]: Use new style format strings for colorbar ticks -* :ghpull:`21564`: Skip invisible artists when doing 3d projection. -* :ghpull:`21558`: Various small fixes for streamplot(). -* :ghpull:`21544`: Return minorticks as array, not as list. -* :ghpull:`21546`: Added links to the mosaic docs in figure and pyplot module docstrings -* :ghpull:`21545`: Turn mouseover into a mpl-style getset_property. -* :ghpull:`21537`: Remove unnecessary False arg when constructing wx.App. -* :ghpull:`21536`: Reword margins docstrings, and fix bounds on zmargin values. -* :ghpull:`21535`: typo-correction-on-line-185 -* :ghpull:`21534`: Do not use space in directive calling. -* :ghpull:`21494`: Adding tutorial links for blitting in widgets.py -* :ghpull:`21407`: Stash exceptions when FT2Font closes the underlying stream. -* :ghpull:`21431`: set_ticks([single_tick]) should also expand view limits. -* :ghpull:`21444`: Make pipong example self-contained. -* :ghpull:`21392`: Add label about workflow to new contributor PRs -* :ghpull:`21440`: Install sphinx-panels along with development setup -* :ghpull:`21434`: Remove coords_flat variable -* :ghpull:`21415`: Move gui_support.macosx option to packages section. -* :ghpull:`21412`: Privatize some SVG internal APIs. -* :ghpull:`21401`: Uncamelcase some internal variables in axis.py; rename _get_tick_bboxes. -* :ghpull:`21417`: Use Bbox.unit() more. -* :ghpull:`20253`: Simplify parameter handling in FloatingAxesBase. -* :ghpull:`21379`: Simplify filename tracking in FT2Font. -* :ghpull:`21278`: Clear findfont cache when calling addfont(). -* :ghpull:`21400`: Use bbox.{size,bounds,width,height,p0,...} where appropriate. -* :ghpull:`21408`: Reword annotations tutorial section titles. -* :ghpull:`21371`: Rename default branch -* :ghpull:`21389`: Log pixel coordinates in event_handling coords_demo example on terminal/console -* :ghpull:`21376`: Factor common parts of saving to different formats using pillow. -* :ghpull:`21377`: Enable tests for text path based markers -* :ghpull:`21283`: Demonstrate inset_axes in scatter_hist example. -* :ghpull:`21356`: Raise an exception when find_tex_file fails to find a file. -* :ghpull:`21362`: Simplify wording of allowed errorbar() error values -* :ghpull:`21274`: ENH: Add support to save images in WebP format -* :ghpull:`21289`: Simplify _init_legend_box. -* :ghpull:`21256`: Make image_comparison work even without the autoclose fixture. -* :ghpull:`21343`: Fix type1font docstring markup/punctuation. -* :ghpull:`21341`: Fix trivial docstring typo. -* :ghpull:`21301`: Simplify ``Colormap.__call__`` a bit. -* :ghpull:`21280`: Make ``Path.__deepcopy__`` interact better with subclasses, e.g. TextPath. -* :ghpull:`21266`: Fix #21101 Add validator to errorbar method -* :ghpull:`20921`: Fix problem with (deep)copy of TextPath -* :ghpull:`20914`: 19195 rotated markers -* :ghpull:`21276`: Add language about not assigning issues -* :ghpull:`20715`: Improve Type-1 font parsing -* :ghpull:`21218`: Parametrize/simplify test_missing_psfont. -* :ghpull:`21213`: Compress comments in make_image. -* :ghpull:`21187`: Deprecate error_msg_foo helpers. -* :ghpull:`21190`: Deprecate mlab.stride_windows. -* :ghpull:`21152`: Rename ``**kw`` to ``**kwargs``. -* :ghpull:`21087`: Move colormap examples from userdemo to images_contours_and_fields. -* :ghpull:`21074`: Deprecate MarkerStyle(None). -* :ghpull:`20990`: Explicit registration of canvas-specific tool subclasses. -* :ghpull:`21049`: Simplify setting Legend attributes -* :ghpull:`21056`: Deprecate support for no-args MarkerStyle(). -* :ghpull:`21059`: Remove dummy test command from setup.py -* :ghpull:`21015`: Prepare for rcParams.copy() returning a new RcParams instance in the future -* :ghpull:`21021`: Factor out for_layout_only backcompat support in get_tightlayout. -* :ghpull:`21023`: Inline ToolManager._trigger_tool to its sole call site. -* :ghpull:`21005`: Test the rcParams deprecation machinery. -* :ghpull:`21010`: Avoid TransformedBbox where unneeded. -* :ghpull:`21019`: Reword custom_ticker1 example. -* :ghpull:`20995`: Deprecate some backend_gtk3 helper globals. -* :ghpull:`21004`: Remove now-unused rcParams _deprecated entries. -* :ghpull:`20986`: Make HandlerLine2D{,Compound} inherit constructors from HandlerNpoints. -* :ghpull:`20974`: Rename symbol_name to glyph_name where appropriate. -* :ghpull:`20961`: Small cleanups to math_to_image. -* :ghpull:`20957`: legend_handler_map cleanups. -* :ghpull:`20955`: Remove unused HostAxes._get_legend_handles. -* :ghpull:`20851`: Try to install the Noto Sans CJK font - -Issues (202): - -* :ghissue:`23827`: backend_gtk3agg.py calls set_device_scale -* :ghissue:`23560`: [Doc]: mpl_toolkits.axes_grid still mentioned as maintained -* :ghissue:`23794`: [Doc]: Version switcher broken in devdocs -* :ghissue:`23806`: [Bug]: possible regression in axis ticks handling in matplotlib 3.6.0rc2 -* :ghissue:`22965`: [Bug]: triplot duplicates label legend -* :ghissue:`23807`: streamplot raises ValueError when the input is zeros -* :ghissue:`23761`: [Bug]: False positive legend handler warnings in 3.6.0.rc1 -* :ghissue:`23398`: [Bug]: Newer versions of matplotlib ignore xlabel on colorbar axis -* :ghissue:`23699`: [Bug]: Bug with toolbar instantiation in notebook -* :ghissue:`23745`: [Doc]: Minor rcParams/matplotlibrc doc issues -* :ghissue:`23717`: [Bug]: AxesSubplot.get_yticks not returning the actual printed ticks -* :ghissue:`21508`: [Doc]: Create diagram to show rotation directions for 3D plots -* :ghissue:`23709`: [Bug]: colorbar with unattached mappables can't steal space -* :ghissue:`23701`: [Bug]: plt.figure(), plt.close() leaks memory -* :ghissue:`22409`: [Bug]: AttributeError: 'QResizeEvent' object has no attribute 'pos' -* :ghissue:`19609`: DeprecationWarning when changing color maps -* :ghissue:`23716`: MatplotlibDeprecationWarning removal hard-breaks seaborn in 3.6rc1 -* :ghissue:`23719`: [Bug]: register_cmap deprecation message seems wrong -* :ghissue:`23707`: test_Normalize fails on aarch64/ppc64le/s390x -* :ghissue:`21107`: [MNT]: Should plt.xticks() get a minor keyword argument -* :ghissue:`23679`: [Doc]: Deprecated modules not in docs -* :ghissue:`19550`: Arc and pathpatch_2d_to_3d plots full ellipse -* :ghissue:`23329`: [Bug]: ``plt.autoscale()`` fails for partial ``Arc`` -* :ghissue:`11266`: Arc patch ignoring theta1/theta2 when added to Axes via PatchCollection -* :ghissue:`4067`: 'Poly3DCollection' object has no attribute '_facecolors2d' -* :ghissue:`23622`: [MNT]: make.bat not parsing sphinxopt -* :ghissue:`23459`: [Bug]: 'Line3D' object has no attribute '_verts3d' -* :ghissue:`23653`: [Bug]: macosx subplot tool causes segfault when window closed -* :ghissue:`23660`: [Bug]: Test test_figure.py::test_subfigure_ss[png] FAILED on ppc64le -* :ghissue:`23645`: [MNT]: Python 3.11 manylinux wheels -* :ghissue:`23650`: TTF fonts loaded from file are not embedded/displayed properly when saved to pdf -* :ghissue:`23583`: [Doc]: Document the position parameter in apply_aspect() -* :ghissue:`23386`: setuptools_scm-git-archive is obsolete -* :ghissue:`23220`: [Doc]: Clarify ``offset`` parameter in linestyle -* :ghissue:`22746`: [Doc]: Document that rcParams['font.family'] can be a list -* :ghissue:`8187`: Axes doesn't have ````legends```` attribute? -* :ghissue:`23580`: [Bug]: TypeError when plotting against list of datetime.date where 0th element of list is None -* :ghissue:`15514`: Relevant methods are only documented in base classes and thus not easily discoverable -* :ghissue:`21611`: DOC: Add conda environment instructions to developers guide -* :ghissue:`23487`: [Bug]: scatter plot color settings discarded unless c given -* :ghissue:`22977`: [Bug]: offset dash linestyle has no effect in patch objects -* :ghissue:`18883`: Matplotlib would not try to apply all the font in font list to draw all characters in the given string. -* :ghissue:`22570`: [ENH]: Provide ``axis('equal')`` for ``Axes3D``. -* :ghissue:`23433`: [Bug]: array-like linewidth raises an error for scatter3D -* :ghissue:`12388`: Legend Title Left Alignment -* :ghissue:`23375`: [Bug]: markerfacecoloralt not supported when drawing errorbars -* :ghissue:`17973`: DOC: matplotlib.__doc__ not included in online docs ? -* :ghissue:`23474`: [Bug]: ``\,`` and ``\mathrm{\,}`` are not identical in Mathtext when using CM and STIX -* :ghissue:`8715`: event handlers have different signatures across backends -* :ghissue:`18271`: PGF uses the minimal document class -* :ghissue:`23324`: [Bug]: Exception not handled in widgetlock() -* :ghissue:`15710`: doc for type of tz parameter is inconsistent throughout dates.py -* :ghissue:`21165`: Hexbin marginals need a test for linear scaling -* :ghissue:`23105`: [MNT]: Deprecate per-backend customization of draw_if_interactive -* :ghissue:`23147`: [Bug]: with setuptools>=60, cannot find msbuild -* :ghissue:`23379`: [Bug]: Offset notation on y-axis can overlap with a long title -* :ghissue:`22819`: [Doc]: Make rect argument consistent in the docstrings -* :ghissue:`23172`: [Bug]: Calling matplotlib.pyplot.show() outside of matplotlib.pyplot.rc_context no longer works -* :ghissue:`23019`: [Bug]: ``UnicodeDecodeError`` when using some special and accented characters in TeX -* :ghissue:`23334`: [Doc]: Tk embedding example crashes Spyder -* :ghissue:`23298`: [Bug]: get_backend() clears figures from Gcf.figs if they were created under rc_context -* :ghissue:`21942`: [ENH]: add width/height_ratios to subplots and friends -* :ghissue:`23028`: [ENH]: contour kwarg for negative_linestyle -* :ghissue:`19223`: Certain non-hashable parameters to text() give cryptic error messages -* :ghissue:`18351`: Add the ability to plot striped lines -* :ghissue:`23205`: [Bug]: URL-area not rotated in PDFs -* :ghissue:`23268`: [Bug]: hyphen renders different length depending on presence of MathText -* :ghissue:`23308`: [Bug]: set_visible() not working for 3d projection -* :ghissue:`23296`: Set_color method for line2d object in latest document not work -* :ghissue:`22992`: [Bug]: test_image_comparison_expect_rms nondeterministic failure -* :ghissue:`23008`: [ENH]: Use ``\genfrac`` in display style? -* :ghissue:`23214`: [MNT]: Rename examples with "test" in the name -* :ghissue:`17852`: Thin space missing after mathtext operators -* :ghissue:`12078`: Inconsistency in keyword-arguments ncol/ncols, nrow/nrows -* :ghissue:`23239`: [Doc]: steps is not implemented in line styles. -* :ghissue:`23151`: [MNT]: default date limits... -* :ghissue:`9462`: Misaligned bottoms of subplots for png output with bbox_inches='tight' -* :ghissue:`21369`: [Bug]: ax.invert_xaxis() and ax.invert_yaxis() both flip the X axis -* :ghissue:`20797`: ``macosx`` cursors break with images -* :ghissue:`23084`: [TST] Upcoming dependency test failures -* :ghissue:`22910`: [Bug]: bar_label fails with nan errorbar values -* :ghissue:`23074`: [Bug]: matplotlib crashes if ``_tkinter`` doesn't have ``__file__`` -* :ghissue:`23083`: [Bug]: Confusing error messages -* :ghissue:`22391`: [Doc]: Remove "keywords" line at the bottom of all examples -* :ghissue:`20202`: Daylocator causes frozen computer when used with FuncAnimation -* :ghissue:`22529`: Replace C++ quad contouring code with use of ContourPy -* :ghissue:`21710`: [ENH]: macosx backend does not respect rcParams["savefig.directory"] -* :ghissue:`21880`: [Doc]: rrulewrapper not included in API docs -* :ghissue:`22622`: [Bug]: Gaps and overlapping areas between bins when using float16 -* :ghissue:`23043`: [TST] Upcoming dependency test failures -* :ghissue:`17960`: Line2D object markers are lost when retrieved from legend.get_lines() when linestyle='None' -* :ghissue:`23026`: [MNT]: Require that matplotlibrc/style files use utf-8 (or have an encoding cookie) -* :ghissue:`22947`: [Bug]: Can't use ``plt.sca()`` on axes created using subfigures -* :ghissue:`22623`: [ENH]: support rect with constrained_layout ("layout only to part of the figure") -* :ghissue:`22917`: "ab;cd" missing in subplot_mosaic tutorial -* :ghissue:`22686`: [Bug]: can not give init value for RangeSlider widget -* :ghissue:`22740`: [MNT]: Add codespell to pre-commit hooks -* :ghissue:`22893`: rainbow text example is broken -* :ghissue:`21571`: [Doc]: Clarify text positioning -* :ghissue:`22092`: [Bug]: Configure subplots dialog freezes for TkAgg with toolmanager -* :ghissue:`22760`: [Bug]: Macosx legend picker doesn't work anymore -* :ghissue:`16369`: Call to input blocks slider input on osx with the default agg 'MacOSX'. It works fine on when TkAgg is used. -* :ghissue:`22915`: [Bug]: figure.raise_window rcParam does not work on MacOSX backend -* :ghissue:`22930`: [Bug]: Regression in dashes due to #22569 -* :ghissue:`22859`: [Bug]: findSystemFonts should not look in subdirectories of C:\Windows\Fonts\ -* :ghissue:`22882`: Missing ``f`` prefix on f-strings -* :ghissue:`22738`: [MNT]: make Axes.cla an alias for Axes.clear in all cases -* :ghissue:`22708`: [TST] Upcoming dependency test failures -* :ghissue:`8388`: Proposed ENH: Allow user to turn off breaking of streamlines in streamplot -* :ghissue:`20755`: [Bug]: make_norm_from_scale should create picklable classes even when used in-line. -* :ghissue:`18249`: Expand the explanation of the Object-Oriented interface -* :ghissue:`22792`: [Bug]: .eps greyscale hatching of patches when lw=0 -* :ghissue:`22630`: [ENH]: enable passing of projection keyword to Axes.inset_axes -* :ghissue:`22414`: [Bug]: bar_label overlaps bars when y-axis is inverted -* :ghissue:`22726`: [Bug]: tripcolor ignores clim -* :ghissue:`21635`: [ENH]: Add a nightly wheel build -* :ghissue:`9994`: document where nightly wheels are published -* :ghissue:`22350`: [Bug]: text.usetex Vs. DateFormatter -* :ghissue:`4976`: missing imshow() subplots when using tight_layout() -* :ghissue:`22150`: [ENH]: Tool icons are hardly visible in Tk when using a dark theme -* :ghissue:`22662`: Leave color parameter empty should be fine[ENH]: -* :ghissue:`22671`: [Doc]: plot_format adaption invalidates sphinx cache -* :ghissue:`22582`: [Bug]: FontManager.addfont doesn't accept pathlib.Path of TTF font -* :ghissue:`22657`: [ENH]: vector map -* :ghissue:`16181`: The great API cleanup -* :ghissue:`22636`: [Bug]: Infinite loop when there is single double quote in matplotlibrc -* :ghissue:`22266`: [Doc]: Improve examples in documentation -* :ghissue:`11861`: Figure does not close until script finishes execution -* :ghissue:`19288`: Escape # character in matplotlibrc -* :ghissue:`22579`: [Bug]: Replacement for epoch2num behaves differently (does not accept arrays) -* :ghissue:`22605`: [Bug]: Tool contrast low with dark theme on macosx backend -* :ghissue:`17642`: bring osx backend flush_events to feature parity with other backend -* :ghissue:`19268`: Drawing the canvas does not populate ticklabels on MacOSX backend -* :ghissue:`17445`: MacOSX does not render frames in which new artists are added when blitting -* :ghissue:`10980`: Current versions cannot reproduce rotate_axes_3d_demo.py -* :ghissue:`18451`: MacOSX backend fails with animation in certain scripts -* :ghissue:`22603`: [MNT]: Replace str(n)cpy etc with safe versions (C++) -* :ghissue:`19121`: Handle and label not created for Text with label -* :ghissue:`22563`: [Doc]: annotation_clip=None not correctly documented -* :ghissue:`12528`: Empty axes on draw after blitted animation finishes -* :ghissue:`20991`: [Bug]: Error when using path effect with a PolyCollection -* :ghissue:`19563`: path_effects kwarg triggers exception on 3D scatterplot -* :ghissue:`8650`: System Error in backend_agg. (with a fix!) -* :ghissue:`20294`: ``AxesImage.__str__`` is wrong if the image does not span the full Axes. -* :ghissue:`18066`: Document minimum supported OSX version for macos backend -* :ghissue:`17018`: Add documentation about transparency of frame -* :ghissue:`22403`: [MNT]: Confusing prompt in docs issue template -* :ghissue:`8839`: mpl_connect silently does nothing when passed an invalid event type string -* :ghissue:`22343`: [MNT]: Delay (or make pending) the deprecation of set_constrained_layout/set_tight_layout -* :ghissue:`21554`: [Bug]: ``ValueError`` upon deepcopy of a ``Figure`` object -* :ghissue:`22369`: [Doc]: Incorrect comment in example code for creating adjacent subplots -* :ghissue:`19174`: connectionstyle arc3 with high rad value pushes up data interval of x-axis and y-axis. -* :ghissue:`8351`: seaborn styles make "+", "x" markers invisible; proposed workaround for shipped styles -* :ghissue:`22278`: Deprecate/remove maxdict -* :ghissue:`19276`: imshow with very large arrays not working as expected -* :ghissue:`22035`: [ENH]: Specify a custom focal length / FOV for the 3d camera -* :ghissue:`22264`: [Bug]: new constrained_layout causes axes to go invisible(?) -* :ghissue:`21774`: [MNT]: Improvements to widget tests -* :ghissue:`18722`: Consider removing AFM+mathtext support -* :ghissue:`21540`: [Bug]: cm fontset in log scale does not use Unicode minus -* :ghissue:`22062`: [Bug]: Autopositioned title overlaps with offset text -* :ghissue:`22093`: [Bug]: AttributeError: 'AxesSubplot' object has no attribute 'add_text' -* :ghissue:`22012`: [Bug]: Mouseover coordinate/value text should be right aligned -* :ghissue:`21995`: [Bug]: triplot with 'ls' argument yields TypeError -* :ghissue:`20249`: MatplotlibDeprecationWarning when updating rcparams -* :ghissue:`15781`: MatplotlibDeprecationWarning examples.directory is deprecated -* :ghissue:`13118`: No MatplotlibDeprecationWarning for default rcParams -* :ghissue:`21978`: Remove logging debug of loaded modules -* :ghissue:`11738`: pgf backend doesn't make background transparent -* :ghissue:`18039`: Add ``_repr_html_`` for fonts -* :ghissue:`21970`: [Bug]: tight layout breaks with toolbar.push_current() -* :ghissue:`14850`: No icon showing up with macosx backend -* :ghissue:`17283`: Create Date Formatter/Locator Reference -* :ghissue:`21761`: [Doc]: add how to know available fonts... -* :ghissue:`21863`: [Doc]: Remove example "prop_cycle property markevery in rcParams" -* :ghissue:`10241`: Axes3D.view_init elevation issue between 270 and 360 degrees -* :ghissue:`14453`: add third angle to view_init() -* :ghissue:`20486`: Modifier key press events not recognized on MacOSX backend -* :ghissue:`9837`: MacOS: Key modifiers deprecated -* :ghissue:`11416`: RuntimeError: adjustable='datalim' is not allowed when both axes are shared. -* :ghissue:`17711`: inset_locator.mark_inset() misplaces box connectors -* :ghissue:`20854`: [Doc]: Incorrect copyright start year at the bottom of devdocs page -* :ghissue:`21394`: [Bug]: Subplot title does not obey padding -* :ghissue:`20998`: [Bug]: ToolManager does not respect rcParams["keymap."] set after import time -* :ghissue:`7075`: Superscripts in axis label cut when saving .eps with bbox_inches="tight" -* :ghissue:`21514`: [Doc]: Error message of validate_whiskers is not updated -* :ghissue:`21532`: [Doc]: subplot_mosaic docstring should link to the tutorial -* :ghissue:`16550`: Docs: performance discussion of tight_layout -* :ghissue:`21378`: [ENH]: use new style format strings for colorbar ticks -* :ghissue:`19323`: Streamplot color mapping fails on (near-)empty array. -* :ghissue:`19559`: Axes.get_xticks() returns a numpy array but Axes.get_xticks(minor=True) returns a plain list -* :ghissue:`21526`: [Doc]: Little Typo on Introductory Tutorial -* :ghissue:`19195`: Rotate Markers in functions like plot, scatter, etcetera -* :ghissue:`21364`: [Bug]: double free when FT2Font constructor is interrupted by KeyboardInterrupt -* :ghissue:`16581`: Can't not refresh new font in running interpreter -* :ghissue:`21162`: [ENH]: saving images in webp format -* :ghissue:`18168`: The example of the testing decorator does not work. -* :ghissue:`20943`: [Bug]: Deepcopy of TextPath fails -* :ghissue:`21101`: [Bug]: Errorbars separated from markers with negative errors -* :ghissue:`17986`: MEP22 per-backend tool registration -* :ghissue:`4938`: Feature request: add option to disable mathtext parsing -* :ghissue:`11435`: plt.subplot eats my subplots +Pull Requests (80): + +* :ghpull:`24124`: Backport PR #24111 on branch v3.6.x (FIX: add missing method to ColormapRegistry) +* :ghpull:`24111`: FIX: add missing method to ColormapRegistry +* :ghpull:`24117`: Backport PR #24113 on branch v3.6.x (Add exception class to pytest.warns calls) +* :ghpull:`24116`: Backport PR #24115 on branch v3.6.x (Fix mask lookup in fill_between for NumPy 1.24+) +* :ghpull:`24113`: Add exception class to pytest.warns calls +* :ghpull:`24115`: Fix mask lookup in fill_between for NumPy 1.24+ +* :ghpull:`24112`: Backport PR #24109 on branch v3.6.x (DOC: add API change note for colorbar deprecation) +* :ghpull:`24109`: DOC: add API change note for colorbar deprecation +* :ghpull:`24107`: Backport PR #24088 on branch v3.6.x (MNT: make orphaned colorbar deprecate versus raise) +* :ghpull:`24088`: MNT: make orphaned colorbar deprecate versus raise +* :ghpull:`24103`: Backport PR #23684 on branch v3.6.x (Fix rectangle and hatches for colorbar) +* :ghpull:`23684`: Fix rectangle and hatches for colorbar +* :ghpull:`24087`: Backport PR #24084 on branch v3.6.x (Revert argument checking for label_mode) +* :ghpull:`24084`: Revert argument checking for label_mode +* :ghpull:`24078`: Backport PR #24047 on branch v3.6.x (Revert #22360: Let TeX handle multiline strings itself) +* :ghpull:`24047`: Revert #22360: Let TeX handle multiline strings itself +* :ghpull:`24077`: Backport PR #24054 on branch v3.6.x ( DOC: Move OO-examples from pyplot section) +* :ghpull:`24054`: DOC: Move OO-examples from pyplot section +* :ghpull:`24072`: Backport PR #24069 on branch v3.6.x (Clarification of marker size in scatter) +* :ghpull:`24073`: Backport PR #24070 on branch v3.6.x (DOC: colorbar may steal from array of axes) +* :ghpull:`24070`: DOC: colorbar may steal from array of axes +* :ghpull:`24069`: Clarification of marker size in scatter +* :ghpull:`24059`: Backport PR #23638 on branch v3.6.x (FIX: correctly handle generic font families in svg text-as-text mode) +* :ghpull:`23638`: FIX: correctly handle generic font families in svg text-as-text mode +* :ghpull:`24048`: Backport PR #24045 on branch v3.6.x (Fix _FigureManagerGTK.resize on GTK4) +* :ghpull:`24055`: Backport PR #24046 on branch v3.6.x (Ignore 'CFMessagePort: bootstrap_register' messages) +* :ghpull:`24046`: Ignore 'CFMessagePort: bootstrap_register' messages +* :ghpull:`24051`: Backport PR #24037 on branch v3.6.x ([DOC]: make spanselector example codeblock continuous) +* :ghpull:`24037`: [DOC]: make spanselector example codeblock continuous +* :ghpull:`24045`: Fix _FigureManagerGTK.resize on GTK4 +* :ghpull:`24043`: Backport PR #24041 on branch v3.6.x (DOC: Fix incorrect redirect) +* :ghpull:`24030`: Backport PR #24019 on branch v3.6.x (Don't require FigureCanvas on backend module more) +* :ghpull:`24040`: Backport PR #24018 on branch v3.6.x (When comparing eps images, run ghostscript with -dEPSCrop.) +* :ghpull:`24018`: When comparing eps images, run ghostscript with -dEPSCrop. +* :ghpull:`24033`: Backport PR #24032 on branch v3.6.x (Reword SpanSelector example.) +* :ghpull:`24029`: Backport PR #24026 on branch v3.6.x (Don't modify Axes property cycle in stackplot) +* :ghpull:`23994`: Backport PR #23964 on branch v3.6.x (Fix issue with empty line in ps backend) +* :ghpull:`24019`: Don't require FigureCanvas on backend module more +* :ghpull:`24026`: Don't modify Axes property cycle in stackplot +* :ghpull:`24027`: Backport PR #23904 on branch v3.6.x (added a reversing section to colormap reference) +* :ghpull:`24017`: Backport PR #24014 on branch v3.6.x (Bump pypa/cibuildwheel from 2.10.1 to 2.10.2) +* :ghpull:`24014`: Bump pypa/cibuildwheel from 2.10.1 to 2.10.2 +* :ghpull:`24007`: Backport PR #24004 on branch v3.6.x (Increase consistency in tutorials and examples) +* :ghpull:`23964`: Fix issue with empty line in ps backend +* :ghpull:`23904`: added a reversing section to colormap reference +* :ghpull:`23990`: Backport PR #23978 on branch v3.6.x (DOC: Suppress IPython output in examples and tutorials where not needed) +* :ghpull:`23978`: DOC: Suppress IPython output in examples and tutorials where not needed +* :ghpull:`23916`: Backport PR #23912 on branch v3.6.x (FIX: only expect FigureCanvas on backend module if using new style) +* :ghpull:`23989`: Backport PR #23944 on branch v3.6.x (FIX: ValueError when hexbin is run with empty arrays and log scaling.) +* :ghpull:`23944`: FIX: ValueError when hexbin is run with empty arrays and log scaling. +* :ghpull:`23988`: Backport PR #23987 on branch v3.6.x (FIX: do not set constrained layout on false-y values) +* :ghpull:`23987`: FIX: do not set constrained layout on false-y values +* :ghpull:`23982`: Backport PR #23980 on branch v3.6.x (DOC: Move Quick Start Tutorial to first position) +* :ghpull:`23979`: Backport PR #23975 on branch v3.6.x (Reword docstring of reset_position.) +* :ghpull:`23975`: Reword docstring of reset_position. +* :ghpull:`23966`: Backport PR #23930 on branch v3.6.x (Fix edge color, links, wording; closes matplotlib/matplotlib#23895) +* :ghpull:`23971`: Backport PR #23906 on branch v3.6.x (Edit mplot3d examples for correctness and consistency) +* :ghpull:`23906`: Edit mplot3d examples for correctness and consistency +* :ghpull:`23963`: Backport PR #23957 on branch v3.6.x (Bump pypa/cibuildwheel from 2.9.0 to 2.10.1) +* :ghpull:`23930`: Fix edge color, links, wording; closes matplotlib/matplotlib#23895 +* :ghpull:`23910`: FIX: do not append None to stream in ps +* :ghpull:`23957`: Bump pypa/cibuildwheel from 2.9.0 to 2.10.1 +* :ghpull:`23960`: Backport PR #23947 on branch v3.6.x (Fix building on MINGW) +* :ghpull:`23942`: DOC: fix versions in v3.6.x doc switcher +* :ghpull:`23961`: Backport PR #23958 on branch v3.6.x (DOC: Remove Adding Animations section) +* :ghpull:`23958`: DOC: Remove Adding Animations section +* :ghpull:`23947`: Fix building on MINGW +* :ghpull:`23945`: Backport PR #23941 on branch v3.6.x (consistent notation for minor/patch branches) +* :ghpull:`23956`: Backport PR #23751 on branch v3.6.x (FIX: show bars when the first location is nan) +* :ghpull:`23751`: FIX: show bars when the first location is nan +* :ghpull:`23938`: Backport PR #23919 on branch v3.6.x (DOC: remove dead "Show Source" links) +* :ghpull:`23952`: Backport PR #23951 on branch v3.6.x (DOC: Make animation continuous) +* :ghpull:`23949`: DOC: Display "dev" instead of "devdocs" in the version switcher +* :ghpull:`23940`: Fix typos in github_stats.rst +* :ghpull:`23936`: Backport PR #23935 on branch v3.6.x (DOC: fix versions is doc switcher) +* :ghpull:`23933`: Backport PR #23932 on branch v3.6.x (DOC: Fix formatting in image tutorial) +* :ghpull:`23932`: DOC: Fix formatting in image tutorial +* :ghpull:`23926`: Backport PR #23925 on branch v3.6.x (FIX: use process_event in dpi changes on macosx backend) +* :ghpull:`23925`: FIX: use process_event in dpi changes on macosx backend +* :ghpull:`23912`: FIX: only expect FigureCanvas on backend module if using new style + +Issues (22): + +* :ghissue:`23981`: [ENH]: Default ``matplotlib.colormaps[None]`` to call ``matplotlib.colormaps[matplotlib.rcParams['image.cmap']]``? +* :ghissue:`24106`: [Bug]: fill_between gives IndexError with numpy 1.24.0.dev +* :ghissue:`24053`: Cartopy axes_grid_basic example broken by Matplotlib 3.6 +* :ghissue:`23977`: [Bug]: Eqnarray in AnchoredText results in misplaced text (new in v3.6.0) +* :ghissue:`23973`: [Bug]: ValueError: Unable to determine Axes to steal space for Colorbar. +* :ghissue:`23456`: [Bug]: Horizontal colorbars drawn incorrectly with hatches +* :ghissue:`15922`: Pyplot gallery section is mostly OO examples +* :ghissue:`23700`: [Doc]: scatter points +* :ghissue:`23492`: [Bug]: svg backend does not use configured generic family lists +* :ghissue:`22528`: [Bug]: problem with font property in text elements of svg figures +* :ghissue:`23911`: [Bug]: 3.6.0 doesn't interact well with pycharm throwing "backend_interagg" exception +* :ghissue:`24024`: stackplot should not change Axes cycler +* :ghissue:`23954`: [Bug]: Text label with empty line causes a "TypeError: cannot unpack non-iterable NoneType object" in PostScript backend +* :ghissue:`23922`: [Bug]: Refactor of hexbin for 3.6.0 crashes with empty arrays and log scaling +* :ghissue:`23986`: [Bug]: Constrained layout UserWarning even when False +* :ghissue:`23895`: [Bug]: 3D surface is not plotted for the contour3d_3 example in the gallery +* :ghissue:`23955`: [Doc]: Adding animations to Youtube channel +* :ghissue:`23943`: [Bug]: Couldn't build matplotlib 3.6.0 with both Clang-15 and GCC-12 +* :ghissue:`23687`: [Bug]: barplot does not show anything when x or bottom start and end with NaN +* :ghissue:`23876`: [Doc]: Missing source files +* :ghissue:`23909`: [Doc]: add animation examples to show animated subplots +* :ghissue:`23921`: [Bug]: resize_event deprecation warnings when creating figure on macOS with version 3.6.0 Previous GitHub statistics diff --git a/doc/users/prev_whats_new/github_stats_3.6.0.rst b/doc/users/prev_whats_new/github_stats_3.6.0.rst new file mode 100644 index 000000000000..aac0c0445fd3 --- /dev/null +++ b/doc/users/prev_whats_new/github_stats_3.6.0.rst @@ -0,0 +1,1292 @@ +.. _github-stats-3-6-0: + +GitHub statistics for 3.6.0 (Sep 15, 2022) +========================================== + +GitHub statistics for 2021/11/16 (tag: v3.5.0) - 2022/09/15 + +These lists are automatically generated, and may be incomplete or contain duplicates. + +We closed 202 issues and merged 894 pull requests. +The full list can be seen `on GitHub `__ + +The following 174 authors contributed 4425 commits. + +* Abhishek K M +* Adeel Hassan +* agra +* Aitik Gupta +* ambi7 +* Andras Deak +* Andres Martinez +* Andrew Fennell +* andrzejnovak +* Andrés Martínez +* Anna Mastori +* AnnaMastori +* Ante Sikic +* Antony Lee +* arndRemy +* Ben Root +* Biswapriyo Nath +* cavesdev +* Clément Phan +* Clément Walter +* code-review-doctor +* Connor Cozad +* Constantine Evans +* Croadden +* daniilS +* Danilo Palumbo +* David Gilbertson +* David Ketcheson +* David Matos +* David Poznik +* David Stansby +* Davide Sandonà +* dependabot[bot] +* dermasugita +* Diego Solano +* Dimitri Papadopoulos +* dj4t9n +* Dmitriy Fishman +* DWesl +* Edouard Berthe +* eindH +* Elliott Sales de Andrade +* Eric Firing +* Eric Larson +* Eric Prestat +* Federico Ariza +* Felix Nößler +* Fernando +* Gajendra Pal +* gajendra0180 +* GavinZhang +* Greg Lucas +* hannah +* Hansin Ahuja +* Harshal Prakash Patankar +* Hassan Kibirige +* Haziq Khurshid +* Henry +* henrybeUM +* Hood +* Hood Chatham +* Ian Hunt-Isaak +* Ian Thomas +* igurin-invn +* ikhebgeenaccount +* Isha Mehta +* Jake Bowhay +* Jake Li +* Jake Lishman +* Jake VanderPlas +* Jakub Klus +* James Tocknell +* Jan-Hendrik Müller +* Jay Joshi +* Jay Stanley +* jayjoshi112711 +* Jeff Beck +* Jody Klymak +* Joel Frederico +* Joseph Fox-Rabinovitz +* Josh Soref +* Jouni K. Seppänen +* Kayran Schmidt +* kdpenner +* Kian Eliasi +* Kinshuk Dua +* kislovskiy +* KIU Shueng Chuan +* kjain +* kolibril13 +* krassowski +* Krish-sysadmin +* Leeh Peter +* lgfunderburk +* Liam Toney +* Lucas Ricci +* Luke Davis +* luz paz +* mackopes +* MAKOMO +* MalikIdreesHasa +* Marcin Swaltek +* Mario +* Mario Sergio Valdés Tresanco +* martinRenou +* Matthew Feickert +* Matthias Bussonnier +* Mauricio Collares +* MeeseeksMachine +* melissawm +* Mr-Milk +* Navid C. Constantinou +* Nickolaos Giannatos +* Nicolas P. Rougier +* Niyas Sait +* noatamir +* ojeda-e +* Olivier Gauthé +* Oscar Gustafsson +* patquem +* Philipp Rohde +* Pieter Eendebak +* Pieter P +* Péter Leéh +* Qijia Liu +* Quentin Peter +* Raphael Quast +* rditlar9 +* Richard Penney +* richardsheridan +* Rike-Benjamin Schuppner +* Robert Cimrman +* Roberto Toro +* root +* Ruth Comer +* Ruth G. N +* Ruth Nainggolan +* Ryan May +* Rémi Achard +* SaumyaBhushan +* Scott Jones +* Scott Shambaugh +* selormtamakloe +* Simon Hoxbro +* skywateryang +* Stefanie Molin +* Steffen Rehberg +* stone +* Sven Eschlbeck +* sveneschlbeck +* takimata +* tfpf +* Thomas A Caswell +* Tim Hoffmann +* Tobias Megies +* Tomas Hrnciar +* Tomasz Kuliński +* trichter +* unknown +* Uwe Hubert +* vfdev-5 +* Vishal Chandratreya +* Vishal Pankaj Chandratreya +* Vishnu V K +* vk0812 +* Vlad Korolev +* Will Qian +* William Qian +* wqh17101 +* wsykala +* yaaun +* Yannic Schroeder +* yuanx749 +* 渡邉 美希 + +GitHub issues and pull requests: + +Pull Requests (894): + +* :ghpull:`23814`: Consolidate release notes for 3.6 +* :ghpull:`23899`: Backport PR #23885 on branch v3.6.x (DOC: Rearrange navbar-end elements) +* :ghpull:`23898`: Backport PR #23892 on branch v3.6.x (DOC: Fix docs for linestyles in contour) +* :ghpull:`23885`: DOC: Rearrange navbar-end elements +* :ghpull:`23894`: Backport PR #23881 on branch v3.6.x (Fix Pillow compatibility in example) +* :ghpull:`23897`: Backport PR #23887 on branch v3.6.x (Add missing label argument to barh docs) +* :ghpull:`23892`: DOC: Fix docs for linestyles in contour +* :ghpull:`23887`: Add missing label argument to barh docs +* :ghpull:`23893`: Backport PR #23886 on branch v3.6.x (CI: prefer (older) binaries over (newer) sdists) +* :ghpull:`23881`: Fix Pillow compatibility in example +* :ghpull:`23886`: CI: prefer (older) binaries over (newer) sdists +* :ghpull:`23880`: Backport PR #23862 on branch v3.6.x (Remove triggering of deprecation warning in AnchoredEllipse) +* :ghpull:`23862`: Remove triggering of deprecation warning in AnchoredEllipse +* :ghpull:`23879`: Backport PR #23864 on branch v3.6.x (Correct and improve documentation for anchored artists) +* :ghpull:`23877`: Backport PR #23841 on branch v3.6.x (clarified that hist computes histogram on unbinned data) +* :ghpull:`23872`: Backport PR #23871 on branch v3.6.x (DOC: Fix formatting of pick event demo example) +* :ghpull:`23841`: clarified that hist computes histogram on unbinned data +* :ghpull:`23864`: Correct and improve documentation for anchored artists +* :ghpull:`23871`: DOC: Fix formatting of pick event demo example +* :ghpull:`23869`: Backport PR #23867 on branch v3.6.x (DOC: fix deprecation warnings in examples) +* :ghpull:`23867`: DOC: fix deprecation warnings in examples +* :ghpull:`23858`: Backport PR #23855 on branch v3.6.x (DOC: fix deprecation warnings) +* :ghpull:`23859`: Backport PR #23844 on branch v3.6.x (Further improve dev setup instructions) +* :ghpull:`23844`: Further improve dev setup instructions +* :ghpull:`23855`: DOC: fix deprecation warnings +* :ghpull:`23854`: Backport PR #23852 on branch v3.6.x (Fix cross-compiling internal freetype) +* :ghpull:`23852`: Fix cross-compiling internal freetype +* :ghpull:`23853`: Backport PR #23830 on branch v3.6.x (Start testing on Python 3.11) +* :ghpull:`23830`: Start testing on Python 3.11 +* :ghpull:`23851`: Backport PR #23850 on branch v3.6.x (removed single word in documenting doc) +* :ghpull:`23850`: removed single word in documenting doc +* :ghpull:`23848`: Backport PR #23843 on branch v3.6.x (Clarify that pycairo>=1.14.0 is needed.) +* :ghpull:`23843`: Clarify that pycairo>=1.14.0 is needed. +* :ghpull:`23842`: Backport PR #23840 on branch v3.6.x (Remove documentation for axes_grid) +* :ghpull:`23838`: Backport PR #23834 on branch v3.6.x (Revert "Refactor handling of tick and ticklabel visibility in Axis.clear") +* :ghpull:`23840`: Remove documentation for axes_grid +* :ghpull:`23837`: Backport PR #23833 on branch v3.6.x (Remove search field from sidebar) +* :ghpull:`23836`: Backport PR #23823 on branch v3.6.x ([DOC] Improve dev setup description) +* :ghpull:`23834`: Revert "Refactor handling of tick and ticklabel visibility in Axis.clear" +* :ghpull:`23833`: Remove search field from sidebar +* :ghpull:`23823`: [DOC] Improve dev setup description +* :ghpull:`23822`: Backport PR #23813 on branch v3.6.x (Triplot duplicated label) +* :ghpull:`23813`: Triplot duplicated label +* :ghpull:`23811`: Backport PR #23805 on branch v3.6.x (sphinxext: Do not copy plot_directive.css's metadata) +* :ghpull:`23805`: sphinxext: Do not copy plot_directive.css's metadata +* :ghpull:`23800`: Backport PR #23785 on branch v3.6.x (FIX: ensure type stability for missing cmaps in ``set_cmap``) +* :ghpull:`23799`: Backport PR #23790 on branch v3.6.x (DOC: Add cache busting to all static assets) +* :ghpull:`23785`: FIX: ensure type stability for missing cmaps in ``set_cmap`` +* :ghpull:`23790`: DOC: Add cache busting to all static assets +* :ghpull:`23791`: Backport PR #23774 on branch v3.6.x (Correct rcParams-name in AutoDateFormatter doc-string) +* :ghpull:`23792`: Backport PR #23781 on branch v3.6.x (ci: Add plot types to sphinx-gallery artifacts) +* :ghpull:`23789`: Backport PR #23786 on branch v3.6.x (DOC: fontfallback works for most of the backends) +* :ghpull:`23788`: Backport PR #23784 on branch v3.6.x (DOC: Fix num2date docstring) +* :ghpull:`23786`: DOC: fontfallback works for most of the backends +* :ghpull:`23784`: DOC: Fix num2date docstring +* :ghpull:`23781`: ci: Add plot types to sphinx-gallery artifacts +* :ghpull:`23783`: Backport PR #23782 on branch v3.6.x (Remove ``Axes.cla`` from examples) +* :ghpull:`23782`: Remove ``Axes.cla`` from examples +* :ghpull:`23774`: Correct rcParams-name in AutoDateFormatter doc-string +* :ghpull:`23773`: Backport PR #23772 on branch v3.6.x (3d plots what's new cleanups) +* :ghpull:`23772`: 3d plots what's new cleanups +* :ghpull:`23765`: Backport PR #23762 on branch v3.6.x (FIX: legend handler warning too liberal) +* :ghpull:`23762`: FIX: legend handler warning too liberal +* :ghpull:`23759`: Backport PR #23686 on branch v3.6.x (Improve matplotlib.pyplot importtime by caching ArtistInspector) +* :ghpull:`23686`: Improve matplotlib.pyplot importtime by caching ArtistInspector +* :ghpull:`23756`: Backport PR #23569 on branch v3.6.x (Fix hidden xlabel bug in colorbar) +* :ghpull:`23755`: Backport PR #23742 on branch v3.6.x (FIX: unbreak ipympl) +* :ghpull:`23569`: Fix hidden xlabel bug in colorbar +* :ghpull:`23742`: FIX: unbreak ipympl +* :ghpull:`23752`: Backport PR #23750 on branch v3.6.x (Fix rcParams documentation) +* :ghpull:`23749`: Backport PR #23735 on branch v3.6.x (Correctly handle Axes subclasses that override cla) +* :ghpull:`23735`: Correctly handle Axes subclasses that override cla +* :ghpull:`23748`: Backport PR #23746 on branch v3.6.x (DOC: add numpydoc docstring + commentary to Axis.get_ticklocs) +* :ghpull:`23747`: Backport PR #23721 on branch v3.6.x (3d plot view angle documentation) +* :ghpull:`23746`: DOC: add numpydoc docstring + commentary to Axis.get_ticklocs +* :ghpull:`23721`: 3d plot view angle documentation +* :ghpull:`23744`: Backport PR #23740 on branch v3.6.x (Clarify error for colorbar with unparented mappable) +* :ghpull:`23741`: Backport PR #23674 on branch v3.6.x (Re-rename builtin seaborn styles to not include a dot.) +* :ghpull:`23740`: Clarify error for colorbar with unparented mappable +* :ghpull:`23674`: Re-rename builtin seaborn styles to not include a dot. +* :ghpull:`23738`: Backport PR #23639 on branch v3.6.x (Adding the new contributor meeting) +* :ghpull:`23739`: Backport PR #23712 on branch v3.6.x (FIX: do not try to help CPython with garbage collection) +* :ghpull:`23712`: FIX: do not try to help CPython with garbage collection +* :ghpull:`23639`: Adding the new contributor meeting +* :ghpull:`23732`: Backport PR #23729 on branch v3.6.x (Use cleaner recursion check in PyQt FigureCanvas' resizeEvent.) +* :ghpull:`23734`: Backport PR #23733 on branch v3.6.x (DOC: Update theme configuration for upcoming changes) +* :ghpull:`23733`: DOC: Update theme configuration for upcoming changes +* :ghpull:`23728`: Backport PR #23722 on branch v3.6.x (Restore deprecation class aliases in cbook) +* :ghpull:`23729`: Use cleaner recursion check in PyQt FigureCanvas' resizeEvent. +* :ghpull:`23726`: Backport PR #23711 on branch v3.6.x (Fix deprecation messages for vendoring unused things) +* :ghpull:`23722`: Restore deprecation class aliases in cbook +* :ghpull:`23727`: Backport PR #23724 on branch v3.6.x (Fix/harmonize spacing in dependencies.rst.) +* :ghpull:`23724`: Fix/harmonize spacing in dependencies.rst. +* :ghpull:`23711`: Fix deprecation messages for vendoring unused things +* :ghpull:`23715`: Backport PR #23708 on branch v3.6.x (Loosen up test_Normalize test) +* :ghpull:`23713`: Backport PR #23710 on branch v3.6.x (Fix cmap deprecations) +* :ghpull:`23708`: Loosen up test_Normalize test +* :ghpull:`23710`: Fix cmap deprecations +* :ghpull:`23696`: Backport PR #23695 on branch v3.6.x (Document polar handling of _interpolation_steps.) +* :ghpull:`23706`: Backport PR #23705 on branch v3.6.x (DOC: Added link to class under discussion) +* :ghpull:`23705`: DOC: Added link to class under discussion +* :ghpull:`23695`: Document polar handling of _interpolation_steps. +* :ghpull:`23668`: Api deprecate cmap functions +* :ghpull:`23049`: Add ``minor`` keyword argument to ``plt.x/yticks`` +* :ghpull:`23665`: Harmonize docstrings for boxstyle/connectionstyle/arrowstyle. +* :ghpull:`23636`: FIX: macosx flush_events should process all events +* :ghpull:`23555`: Uncamelcase offsetTrans in draw_path_collection. +* :ghpull:`23682`: Fix generated documentation for deprecated modules +* :ghpull:`23678`: Get rcParams from mpl +* :ghpull:`23571`: Simplify _bind_draw_path_function. +* :ghpull:`23673`: DOC: Highlight information about avoiding labels in legend +* :ghpull:`22506`: Replace MathtextBackend mechanism. +* :ghpull:`23340`: Set correct path for Arc +* :ghpull:`23562`: Fix issue with get_edgecolor and get_facecolor in 3D plots +* :ghpull:`23634`: make.bat: Don't override SPHINXOPTS/O from the environment +* :ghpull:`23675`: Deprecate helper functions in axis3d +* :ghpull:`23676`: MNT: Get rcParams from mpl +* :ghpull:`23677`: TST: Use article class when checking for pgf +* :ghpull:`23669`: CI: Azure update from ubuntu-18.04 to ubuntu-latest and ubuntu-20.04 +* :ghpull:`23670`: Add bar color demo. +* :ghpull:`23644`: Standardize edge-on axis locations when viewing primary 3d axis planes +* :ghpull:`23563`: Fix issue with drawing 3D lines where points are from nparray +* :ghpull:`23666`: MNT: Deprecate macosx prepare subplots tool +* :ghpull:`23572`: Deprecate ``get_grid_positions(..., raw=True)``. +* :ghpull:`23525`: Add functionality to label individual bars with Axes.bar() +* :ghpull:`23667`: Fix flake8 errors introduced by crossed PRs +* :ghpull:`23554`: MNT: Remove unused imports +* :ghpull:`23659`: Simplify/fix save_diff_image. +* :ghpull:`23663`: Small cleanups to _find_fonts_by_props. +* :ghpull:`23662`: Add tolerance to test failing on ppc64le +* :ghpull:`23623`: MNT: remove _gridspecs attribute on Figure classes +* :ghpull:`23654`: Reverts macosx change to ARC +* :ghpull:`23661`: Remove unused fontsize argument from private mathtext _get_info. +* :ghpull:`23655`: Merge branch v3.5.x into main +* :ghpull:`23658`: Increase tolerance on multi-font tests +* :ghpull:`23657`: Add eps to extension list in image triager +* :ghpull:`23656`: Fix broken link to MathML torture tests. +* :ghpull:`23649`: CI: Use anaconda-client v1.10.0 for upload of nightlies +* :ghpull:`23647`: Allow any color format to be used for axis3d.Axis.set_pane_color +* :ghpull:`23643`: Enable wheels for PyPy 3.8+ +* :ghpull:`23621`: DOC: update and extend fonts explanation +* :ghpull:`23612`: CI: try installing a different version of noto on OSX +* :ghpull:`23619`: add pikepdf and visual c++ dependency +* :ghpull:`23631`: Leave out ``barh`` from the basic plot types. +* :ghpull:`23637`: BLD: Add Python 3.11 builds to CI +* :ghpull:`23632`: Add discouraged admonitions +* :ghpull:`23620`: Doc update deps +* :ghpull:`23627`: Bump pypa/cibuildwheel from 2.8.1 to 2.9.0 +* :ghpull:`23628`: Change Title Case to Upper lower in templates +* :ghpull:`23206`: Change exception type for incorrect SVG date metadata +* :ghpull:`23387`: Remove setuptools_scm_git_archive dependency and add sdist test +* :ghpull:`23605`: Fix issues in examples, docs, and tutorials +* :ghpull:`23618`: [Doc]: Document the position parameter in apply_aspect() +* :ghpull:`23355`: Revert "Try to unbreak CI by xfailing OSX Tk tests" +* :ghpull:`23610`: TST: be more forgiving about IDing Noto +* :ghpull:`23609`: print version number when building docs +* :ghpull:`20832`: Implement multi-font embedding for PS Backend +* :ghpull:`20804`: Implement multi-font embedding for PDF Backend +* :ghpull:`23202`: MNT: Remove cached renderer from figure +* :ghpull:`23497`: Avoid gridspec in more examples +* :ghpull:`23602`: Editing "issues for new contributors" +* :ghpull:`23600`: DOC: view_init docstring for 3d axes primary view angles +* :ghpull:`23587`: BUG:datetime list starting with none +* :ghpull:`23559`: re-base of font fallback for pdf and eps output + SVG support +* :ghpull:`23557`: BLD: update the manylinux versions used +* :ghpull:`23596`: Minor cleanup of axes_grid1 +* :ghpull:`23594`: Expire deprecation on passing bytes to FT2Font.set_text +* :ghpull:`23435`: Add conda env to setup instructions +* :ghpull:`23574`: Move colorbar() doc to method itself. +* :ghpull:`23584`: Bump Ubuntu to 20.04 on GitHub Actions +* :ghpull:`23561`: Clean up code in tri +* :ghpull:`23582`: Cleanup axis3d.Axis.draw +* :ghpull:`23510`: Refactor Widget tests +* :ghpull:`20718`: Circle: Build docs in parallel. +* :ghpull:`22452`: ENH: add ability to remove layout engine +* :ghpull:`23516`: warning when scatter plot color settings discarded +* :ghpull:`23577`: apply_aspect cleanups +* :ghpull:`23575`: Cleanup parasite_simple example. +* :ghpull:`23567`: Remove noop setattr_cm. +* :ghpull:`23412`: Fix dash offset bug in Patch +* :ghpull:`21756`: MNT: Clean up some UTF strings and memory autorelease +* :ghpull:`23558`: MNT: Use UTF-8 string in macosx backend +* :ghpull:`23550`: Change exception types, improve argument checking, and cleanups in mpl_toolkits +* :ghpull:`23196`: Unify set_pickradius argument +* :ghpull:`20740`: Implement Font-Fallback in Matplotlib +* :ghpull:`22566`: Add rcparam for figure label size and weight +* :ghpull:`23551`: Remove transform arguments from _iter_collection +* :ghpull:`23444`: Deduplicate common parts in LatexManager.{__init__,_setup_latex_process} +* :ghpull:`23017`: [ENH] : Provide axis('equal') for Axes3D (replace PR #22705) +* :ghpull:`22950`: Simplify definition of mathtext symbols & correctly end tokens in mathtext parsing +* :ghpull:`23409`: Provide axis('equal') for Axes3D (replaces PR #23017) +* :ghpull:`23434`: Fix array-like linewidth for 3d scatter +* :ghpull:`23500`: Move the common implementation of Axes.set_x/y/zscale to Axis. +* :ghpull:`23533`: Add tests for sankey and minor fixes +* :ghpull:`23535`: Make margins error as claimed in doc-string +* :ghpull:`23546`: Simplify impl. of functions optionally used as context managers. +* :ghpull:`23494`: Fix various issues from SonarQube +* :ghpull:`23529`: Add workflow dispatch GitHub CI +* :ghpull:`23539`: Small improvements to WebAgg example +* :ghpull:`23541`: Change doc-build CI install order +* :ghpull:`23526`: DOC: make "family" less ambiguous in FontProperties docs +* :ghpull:`23537`: Move the deprecated RendererGTK{3,4}Cairo to a single place. +* :ghpull:`23140`: [Features] Allow setting legend title alignment +* :ghpull:`23538`: Fix imprecise docs re: backend dependencies. +* :ghpull:`23532`: Add test for RGBAxes +* :ghpull:`23453`: Add more tests for mplot3d +* :ghpull:`23501`: Let Axes.clear iterate over Axises. +* :ghpull:`23469`: Inline _init_axis_artists & _init_gridlines into clear. +* :ghpull:`23475`: Add markerfacealt to pass-through arguments for error bar lines +* :ghpull:`23527`: STY: fix whitespace on an assert +* :ghpull:`23495`: Fix sgskip'd examples +* :ghpull:`23404`: Restore matplotlib.__doc__ in Sphinx docs +* :ghpull:`23507`: Add hint when More than {max_open_warning} figures have been opened +* :ghpull:`23499`: Fix outdated comment re: event handlers in test_backends_interactive. +* :ghpull:`23498`: Fix direct instantiation of webagg_core managers. +* :ghpull:`23504`: Clarify formatting of the code-for-reproduction field in bug reports. +* :ghpull:`23489`: Add missing test data to install +* :ghpull:`23482`: Mathtext spaces must be independent of font style. +* :ghpull:`23486`: Bump pypa/cibuildwheel from 2.8.0 to 2.8.1 +* :ghpull:`23461`: Tweak Axes repr. +* :ghpull:`16931`: Make it easier to improve UI event metadata. +* :ghpull:`23468`: Display grid in floating axes example. +* :ghpull:`23467`: Remove old handling for factor=None in axisartist. +* :ghpull:`23443`: Try running the pgf backend off the article class. +* :ghpull:`23373`: Fix pan/zoom crashing when widget lock is unavailable +* :ghpull:`23466`: Update filename in example. +* :ghpull:`23464`: Deprecate macos close handler. +* :ghpull:`23463`: Deprecate Tick.label +* :ghpull:`23455`: Deprecate properties w_xaxis, w_yaxis, and w_zaxis +* :ghpull:`23448`: Tweak callbacks to generate pick events. +* :ghpull:`23233`: Default stem marker color follows the linecolor +* :ghpull:`23452`: Generalize Axes __repr__ to 3D +* :ghpull:`23445`: Compare thread native ids when checking whether running on main thread. +* :ghpull:`20752`: Set norms using scale names. +* :ghpull:`23438`: DOC: numpydoc-ify date Locator classes +* :ghpull:`23427`: Tweak pgf escapes. +* :ghpull:`23432`: Fixed typo in docs animation api +* :ghpull:`23420`: Clean up test_chunksize_fails() +* :ghpull:`23415`: Minor improvements to units_sample example +* :ghpull:`21339`: Added linear scaling test to Hexbin marginals +* :ghpull:`23414`: Bump pypa/cibuildwheel from 2.7.0 to 2.8.0 +* :ghpull:`23413`: Combine chunk size tests into one +* :ghpull:`23403`: Small cleanup to VertexSelector. +* :ghpull:`23291`: In the new/simplified backend API, don't customize draw_if_interactive. +* :ghpull:`23350`: Fixed SVG-as-text image comparison tests. +* :ghpull:`23406`: DOC: Fix calculation of bin centers in multi-histogram +* :ghpull:`23407`: TST: Add missing warning type to pytest.warns +* :ghpull:`23402`: Link 3D animation examples to one another. +* :ghpull:`23401`: Upload wheel artifacts from the correct directory +* :ghpull:`23374`: GOV: point CoC reports at CoC steering council subcomittee mailing list +* :ghpull:`23393`: Clean up formatting of custom cmap example +* :ghpull:`23146`: Update cibuildwheel +* :ghpull:`23368`: Add a helper to generate closed paths. +* :ghpull:`20220`: DOC: add mission statement +* :ghpull:`22364`: Tweak mathtext/tex docs. +* :ghpull:`23377`: Use tick_params more often over tick iteration +* :ghpull:`22820`: [Doc] consolidate ``rect`` documentation +* :ghpull:`23371`: Default animation.convert_args to ["-layers", "OptimizePlus"]. +* :ghpull:`23148`: DOC: change address to send security issues to +* :ghpull:`23365`: DOC: add new showcase example, replace gendered one +* :ghpull:`23033`: Fix issue with tex-encoding on non-Unicode platforms +* :ghpull:`23358`: Shorten/clarify definition of extension types. +* :ghpull:`23370`: Small cleanups to animation. +* :ghpull:`23364`: Rename/change signature of PyGlyph_new. +* :ghpull:`23363`: Simplify FigureCanvas multiple inheritance init by swapping bases order. +* :ghpull:`23366`: MNT: use devel version of theme +* :ghpull:`23357`: Fixed decimal points not appearing at end of Mathtext string. +* :ghpull:`23351`: DOC/MNT install docs with dev version of sphinx theme +* :ghpull:`23349`: CI: Remove old scipy-wheels-nightly uploads to ensure space +* :ghpull:`23348`: Support multi-figure MultiCursor; prepare improving its signature. +* :ghpull:`23360`: embedding_in_tk_sgskip.py: use root.destroy +* :ghpull:`23354`: MNT: Use list comprehension +* :ghpull:`23299`: FIX/API: do not reset backend key in rc_context +* :ghpull:`23191`: ENH: add width_ratios and height_ratios to subplots +* :ghpull:`23060`: MNT: Change objective C code to Automatic Reference Counting (ARC) +* :ghpull:`23347`: Simplify/improve check for pycairo in Gtk-based backends. +* :ghpull:`23316`: DOC: improve spines crosslinking +* :ghpull:`23100`: Remove custom backend_nbagg.show(), putting logic in manager show. +* :ghpull:`23342`: FIX: make sure addFont test removes the test font +* :ghpull:`23266`: negative_linestyles kwarg in contour.py +* :ghpull:`23332`: Validate Text linespacing on input. +* :ghpull:`23336`: Remove ineffective exclusion of Arcs without parent Axes. +* :ghpull:`23341`: MNT: Use '--pytest-test-first' option for naming clarity +* :ghpull:`23337`: Remove now inexistent "datapath" rcParam from style blacklist. +* :ghpull:`22004`: Make RendererCairo auto-infer surface size. +* :ghpull:`23208`: ENH: enable stripey lines +* :ghpull:`23288`: Correct URL area with rotated texts in PDFs +* :ghpull:`23197`: Add tests for pan +* :ghpull:`22167`: Deprecate selector ``visible`` attribute +* :ghpull:`23322`: Cleanup FontProperties examples. +* :ghpull:`23321`: Tweak examples capitalization/punctuation. +* :ghpull:`23270`: Fix handling of nonmath hyphens in mathtext. +* :ghpull:`23310`: Move Cursor demo from examples/misc to examples/event_handling +* :ghpull:`23313`: Drop CSS styles that are in mpl-sphinx-theme +* :ghpull:`23314`: Don't draw invisible 3D Axes +* :ghpull:`23302`: Deprecate stem(..., use_line_collection=False) +* :ghpull:`23309`: Remove front page examples +* :ghpull:`23282`: Backport PR #22865 on branch v3.5.x (Fix issue with colorbar extend and drawedges) +* :ghpull:`23231`: Add pytest-xvfb as test dependency +* :ghpull:`23318`: No need to return OrderedDict from _gen_axes_spines. +* :ghpull:`23295`: Replace re.sub by the faster str.translate. +* :ghpull:`23300`: Modify example of "Fig Axes Customize Simple" +* :ghpull:`23014`: Improve consistency in LogLocator and LogFormatter API +* :ghpull:`23286`: Refactor URL handling in PDF backend +* :ghpull:`23065`: Fix test_image_comparison_expect_rms +* :ghpull:`23294`: Simplify binary data handling in ps backend. +* :ghpull:`23284`: DOC: Switch to HTML5 and cleanup CSS +* :ghpull:`23276`: Add get/set methods for DPI in SubFigure +* :ghpull:`23207`: Update build environment and improve test +* :ghpull:`23213`: DEV: Add name-tests-test to pre-commit hooks +* :ghpull:`23289`: Properly make Name.hexify go through a deprecation cycle. +* :ghpull:`23177`: Deprecate positional passing of most Artist constructor parameters +* :ghpull:`23287`: Minor tweaks to pdf Name. +* :ghpull:`23285`: In mathtext, replace manual caching (via ``glyphd``) by lru_cache. +* :ghpull:`23034`: Correctly read the 'style' argument while processing 'genfrac'. +* :ghpull:`23247`: Support inverted parentheses in mathtext. +* :ghpull:`23190`: Deprecate unused methods in axis.py +* :ghpull:`23219`: MNT: Rename example files with 'test' in name +* :ghpull:`23277`: MNT: Remove dead code in SVG backend +* :ghpull:`23261`: Bump actions/setup-python from 3 to 4 +* :ghpull:`23264`: Changing environment.yml for it to work on Windows +* :ghpull:`23269`: MNT: Remove dead code in Colorbar +* :ghpull:`23262`: Simplify qt_compat, in particular post-removal of qt4 support. +* :ghpull:`23263`: Private helper to get requested backend without triggering resolution. +* :ghpull:`23243`: Fix spacing after mathtext operators with sub/superscripts +* :ghpull:`22839`: Fix spacing after mathtext operators with sub/superscripts +* :ghpull:`23256`: DOC: Add note about Inkscape install on Windows +* :ghpull:`23258`: DOC: remove Blue Book url +* :ghpull:`23255`: Add a helper to generate mathtext error strings. +* :ghpull:`23246`: Fix argument checking for set_interpolation_stage +* :ghpull:`22881`: Support not embedding glyphs in svg mathtests. +* :ghpull:`23198`: Rename ncol parameter in legend to ncols +* :ghpull:`23251`: Small simplifications to mathtext tests. +* :ghpull:`23249`: Don't allow ``r"$\left\\|\right.$"``, as in TeX. +* :ghpull:`23248`: Rename test markers +* :ghpull:`22507`: Remove *math* parameter of various mathtext internal APIs. +* :ghpull:`23192`: Add tests, improve error messages in axis/_base, and code cleanup +* :ghpull:`23241`: Fix invalid value in radio buttons example +* :ghpull:`23187`: Correct docs and use keyword arguments in _mathtext.py +* :ghpull:`23045`: MNT: Merge locally defined test marks +* :ghpull:`22289`: ENH: compressed layout +* :ghpull:`23237`: Expire BoxStyle._Base deprecation. +* :ghpull:`23225`: DOC: Fix version switcher links to documentation +* :ghpull:`23221`: DOC: recommend numpy random number generator class +* :ghpull:`23223`: Changed offset reference, add small doc +* :ghpull:`23215`: DOC: link the transforms tutorial from the module +* :ghpull:`23201`: Rework tricontour and tricontourf documentation +* :ghpull:`23013`: Add tests for date module +* :ghpull:`23188`: Mnt new default dates +* :ghpull:`22745`: MNT: Don't require renderer for window_extent and tightbbox +* :ghpull:`23077`: MNT: Remove keyword arguments to gca() +* :ghpull:`23182`: Simplify webagg blitting. +* :ghpull:`23181`: Init FigureCanvasAgg._lastKey in ``__init__``. +* :ghpull:`23175`: Point the version switcher to a name listed in switcher.json +* :ghpull:`22669`: Cleanup documentation generation for pyplot +* :ghpull:`22519`: fix markevery plot option with nans in data +* :ghpull:`21584`: Move towards having get_shared_{x,y}_axes return immutable views. +* :ghpull:`23170`: ENH: update ticks when requesting labels +* :ghpull:`23169`: DOC: Migrate to sphinx-design +* :ghpull:`23180`: Improve docstring of triplot() and PatchCollection +* :ghpull:`23153`: Restore accidentally removed pytest.ini and tests.py. +* :ghpull:`23166`: Deprecate passing most Legend arguments positionally +* :ghpull:`23165`: DOCS Fix a few typos +* :ghpull:`23167`: DOCS fix typo +* :ghpull:`23062`: Add stackplot to plot types listing +* :ghpull:`23161`: Added my (open access) book +* :ghpull:`23141`: Minor fix for astropy units support broken in earlier PR +* :ghpull:`23156`: No longer call draw_if_interactive in parasite_axes. +* :ghpull:`23150`: DOC fix typo +* :ghpull:`23149`: DOCS remove duplicate text +* :ghpull:`23145`: Fix format error in switcher.json +* :ghpull:`21755`: MNT: Clean up macosx backend set_message +* :ghpull:`23128`: DOCS Fix typos +* :ghpull:`23130`: Drop pytest warning config in nightly tests +* :ghpull:`23135`: Unpin coverage again +* :ghpull:`23133`: Make module deprecation messages consistent +* :ghpull:`23134`: Remove newline from start of deprecation warnings +* :ghpull:`22964`: Fix spelling errors +* :ghpull:`22929`: Handle NaN in bar labels and error bars +* :ghpull:`23093`: MNT: Removing 3.4 deprecations +* :ghpull:`23090`: Derive new_figure_manager from FigureCanvas.new_manager. +* :ghpull:`23099`: Remove unneeded cutout for webagg in show(). +* :ghpull:`23097`: Tweak check for IPython pylab mode. +* :ghpull:`23088`: Improve error for invalid format strings / misspelled data keys. +* :ghpull:`23092`: Ensure updated monkey-patching of sphinx-gallery EXAMPLE_HEADER +* :ghpull:`23087`: Fix width/height inversion in dviread debug helper. +* :ghpull:`23089`: Normalize tk load failures to ImportErrors. +* :ghpull:`23091`: Move test that fig.add_axes() needs parameters +* :ghpull:`23067`: more explicit in windows doc build instructions +* :ghpull:`23081`: MNT: Deprecate date_ticker_factory +* :ghpull:`23079`: MNT: Remove key_press and button_press from FigureManager +* :ghpull:`23076`: MNT: Remove positional argument handling in LineCollection +* :ghpull:`23078`: MNT: Remove deprecated axis.cla() +* :ghpull:`23054`: Slightly simplify tcl/tk load in extension. +* :ghpull:`23073`: MNT: Remove dummy_threading because threading is always available +* :ghpull:`22405`: DOC: put the gallery keywords in the meta tag +* :ghpull:`23071`: Fix installing contourpy on CI +* :ghpull:`23068`: Slight refactor of _c_internal_utils to linewrap it better. +* :ghpull:`23070`: Pathlibify autotools invocation in build. +* :ghpull:`22755`: Maybe run autogen as part of freetype install +* :ghpull:`23063`: doc: mathtext example: use axhspan() instead of fill_between() for backdrop rectangle shading +* :ghpull:`23055`: Cleanup Annotation.update_position. +* :ghpull:`22567`: Use contourpy for quad contour calculations +* :ghpull:`22801`: TST: fully parameterize test_lazy_linux_headless +* :ghpull:`22180`: ENH: Use rcParams savefig.directory on macosx backend +* :ghpull:`23048`: Add rrulewrapper to docs +* :ghpull:`23047`: Fix issue with hist and float16 data +* :ghpull:`23044`: Fix missing section header for nightly builds +* :ghpull:`23029`: Demonstrate both usetex and non-usetex in demo_text_path.py. +* :ghpull:`23038`: Factor out errorevery parsing for 2D and 3D errorbars. +* :ghpull:`23036`: Suppress traceback chaining for tex subprocess failures. +* :ghpull:`23037`: Suppress exception chaining in FontProperties. +* :ghpull:`23020`: Add test to close legend issue +* :ghpull:`23031`: Specify that style files are utf-8. +* :ghpull:`22991`: Enable ``plt.sca`` on subfigure's axes +* :ghpull:`23030`: DOC: Fix charset declaration in redirects +* :ghpull:`23022`: Fix some possible encoding issues for non-utf8 systems. +* :ghpull:`23023`: Bump docker/setup-qemu-action from 1 to 2 +* :ghpull:`23024`: DOC: do not suggest to sudo pip install Matplotlib +* :ghpull:`23018`: Fix typo in font family +* :ghpull:`22627`: ENH: rect for constrained_layout +* :ghpull:`22891`: Font example monospace +* :ghpull:`23006`: docs: add subplot-mosaic string compact notation +* :ghpull:`23009`: Fixed installation guide command typo +* :ghpull:`22926`: Fix RangeSlider for same init values #22686 +* :ghpull:`22989`: Merge v3.5.x back into main +* :ghpull:`22993`: STY: Fix typos in colormap +* :ghpull:`22777`: DEV: Add codespell to pre-commit hooks +* :ghpull:`22940`: Fixed dpi bug in rainbow text example +* :ghpull:`22298`: MNT: Remove cmap_d colormap access +* :ghpull:`22387`: Add a registry for color sequences +* :ghpull:`21594`: Document text alignment +* :ghpull:`22967`: TST: Add some tests for QuadMesh contains function +* :ghpull:`22936`: ENH: Add full-screen toggle to the macosx backend +* :ghpull:`22886`: MNT: remove mpl_toolkits.axes_grid +* :ghpull:`22952`: Make MarkerStyle immutable +* :ghpull:`22953`: MNT: Move set_cursor to the FigureCanvas +* :ghpull:`18854`: Standardize creation of FigureManager from a given FigureCanvas class. +* :ghpull:`22925`: Standardize creation of FigureManager from a given FigureCanvas class. +* :ghpull:`22875`: Remove Forward definitions where possible. +* :ghpull:`22928`: ENH: Add option to disable raising the window for macosx +* :ghpull:`22912`: DOC: Better doc of colors +* :ghpull:`22931`: BUG: Fix regression with ls=(0, ()) +* :ghpull:`22909`: FIX: skip sub directories when finding fonts on windows +* :ghpull:`22911`: Clarify docstring of [un]install_repl_displayhook() +* :ghpull:`22919`: CI: Add concurrency skips for GH Actions +* :ghpull:`22899`: Fix documentation markup issues +* :ghpull:`22906`: Clarify logic for repl displayhook. +* :ghpull:`22892`: Remove support for IPython<4. +* :ghpull:`22896`: Remove python-dateutil as test requirement +* :ghpull:`22885`: Deprecate two-layered backend_pdf.Op enum. +* :ghpull:`22883`: Tweak argument checking in tripcolor(). +* :ghpull:`22884`: Missing ``f`` prefix on f-strings fix +* :ghpull:`22877`: Small cleanups to mathtext. +* :ghpull:`21374`: Snap selectors +* :ghpull:`22824`: Remove some unnecessary extra boundaries for colorbars with extensions. +* :ghpull:`21448`: Use named groups in mathtext parser. +* :ghpull:`22609`: Improve usability of dviread.Text by third parties. +* :ghpull:`22809`: STY: Apply pre-commit hooks to codebase +* :ghpull:`22730`: Fix removed cross-references +* :ghpull:`22857`: Slightly simplify twin axes detection in MEP22 zoom. +* :ghpull:`22813`: MNT: Deprecate figure callbacks +* :ghpull:`22802`: MNT: make Axes.cla an alias for Axes.clear in all cases +* :ghpull:`22855`: Remove non-needed remove_text=False. +* :ghpull:`22854`: TST: Avoid floating point errors in asinh ticker +* :ghpull:`22850`: Simplify tick creation +* :ghpull:`22841`: Fix Tk error when updating toolbar checkbutton images +* :ghpull:`22707`: Proposed ENH: Allow user to turn off breaking of streamlines in streamplot (rebased) +* :ghpull:`22826`: Bump actions/upload-artifact from 2 to 3 +* :ghpull:`22825`: Bump codecov/codecov-action from 2 to 3 +* :ghpull:`22821`: Use bool for bool keyword arguments +* :ghpull:`22815`: Fix pickling of globally available, dynamically generated norm classes. +* :ghpull:`22702`: Doc tweak transform tutorial +* :ghpull:`22613`: DOC: Add links to explicit vs implicit API everywhere "OO" is used +* :ghpull:`22712`: Use repr in error messages +* :ghpull:`22794`: Fix ps export of colored hatches with no linewidth +* :ghpull:`22797`: Deprecate functions in backends +* :ghpull:`22608`: Axes.inset_axes: enable Axes subclass creation +* :ghpull:`22795`: Replace "marker simplification" by "marker subsampling" in docs. +* :ghpull:`22768`: Fix inkscape tests +* :ghpull:`22791`: Tweak _ConverterError reporting. +* :ghpull:`22447`: Improve bar_label annotation +* :ghpull:`22710`: Fix the error- TypeError: 'float' object is not iterable +* :ghpull:`22444`: Revert "CI: skip test to work around gs bug" +* :ghpull:`22785`: CI: Update weekly dependency test job +* :ghpull:`22784`: Fix 'misspelled' transform variable +* :ghpull:`22778`: Fix LaTeX formatting in examples +* :ghpull:`22779`: Improve mlab documentation (and example) +* :ghpull:`22759`: MNT: Skip existing wheels during nightly wheel upload +* :ghpull:`22751`: BLD: do not put an upper bound on pyparsing +* :ghpull:`22752`: DOC: Correct nightly wheels pip install command +* :ghpull:`22742`: Fix deprecation of backend_tools.ToolBase.destroy +* :ghpull:`22725`: Move towards making texmanager stateless. +* :ghpull:`22734`: Added clim support to tripcolor +* :ghpull:`22733`: CI: Add GHA workflow to upload nightly wheels +* :ghpull:`21637`: Also upload a subset of nightly wheels +* :ghpull:`22698`: Correct cross-references in documentation +* :ghpull:`22263`: DOC: condense version switcher +* :ghpull:`22361`: Revert datetime usetex ticklabels to use default tex font. +* :ghpull:`22721`: Small style fixes. +* :ghpull:`22356`: Cleanup tripcolor() +* :ghpull:`22360`: Let TeX handle multiline strings itself. +* :ghpull:`22418`: Deprecate auto-removal of overlapping Axes by plt.subplot{,2grid}. +* :ghpull:`22722`: Rename confusingly-named cm_fallback. +* :ghpull:`22697`: Deprecate in testing.decorators +* :ghpull:`22556`: Add text.parse_math rcParams +* :ghpull:`22163`: Change colour of Tk toolbar icons on dark backgrounds +* :ghpull:`22704`: Small simplification to textpath. +* :ghpull:`22498`: TST: increase coverage on tk tests +* :ghpull:`21425`: Make Axis3D constructor signature closer to the one of 2D axis. +* :ghpull:`22665`: Improve error message for incorrect color string +* :ghpull:`22685`: Rewrite plot format detection from sphinx build target +* :ghpull:`22670`: Update deprecated vmImage 'vs2017-win2016' in azure pipelines +* :ghpull:`22503`: Deprecate backend_qt.qApp. +* :ghpull:`22683`: Add missing space before : for parameters +* :ghpull:`22591`: Fix Path/str-discrepancy in FontManager.addpath and improve documentation +* :ghpull:`22680`: Bump actions/cache from 2 to 3 +* :ghpull:`22659`: Add description on quiver head parameters +* :ghpull:`22668`: Raise on missing closing quotes in matplotlibrc +* :ghpull:`22675`: Tweak colorbar_placement example. +* :ghpull:`22276`: Merge "Scatter Symbol" and "Scatter Custom Symbol" examples +* :ghpull:`22658`: Remove reference to now-deleted reminder note. +* :ghpull:`22652`: Update documentation example and fix See also +* :ghpull:`22587`: Refactor handling of tick and ticklabel visibility in Axis.clear() +* :ghpull:`22148`: MNT: Deprecate ``docstring`` +* :ghpull:`22170`: Add example to polygon selector docstring showing how to set vertices programmatically +* :ghpull:`22650`: Fix new leak in ft2font introduced in #22604 +* :ghpull:`22644`: FIX: Flush events after closing figures in macosx backend +* :ghpull:`22643`: Suppress exception chaining in colormap lookup. +* :ghpull:`22639`: ENH: MacOSX backend to use sRGB instead of GenericRGB colorspace +* :ghpull:`22509`: Simplifications to ToolManager.{add,remove}_tool. +* :ghpull:`22633`: DOC: remove space in directive. +* :ghpull:`22631`: Add space between individual transform components in svg output. +* :ghpull:`22523`: MNT: Use a context manager to change the norm in colorbar code +* :ghpull:`22615`: FIX: Change get_axis_map to axis_map now +* :ghpull:`22508`: Move tracking of autoscale status to Axis. +* :ghpull:`22547`: Small cleanups around TexManager usage. +* :ghpull:`22511`: Remove redundant rcParam-lookup in patches +* :ghpull:`22516`: Expire deprecations in backends +* :ghpull:`22612`: Updated grammar to reflect more common usage of output vs outputted in animation.py +* :ghpull:`22589`: Support quoted strings in matplotlibrc +* :ghpull:`22604`: MNT: Fix types in C-code to reduce warnings +* :ghpull:`22610`: Fix alternative suggestion in epoch2num() deprecation +* :ghpull:`22554`: Prepare for making create_dummy_axis not necessary. +* :ghpull:`22607`: ENH: Add dark/light mode theme to the buttons +* :ghpull:`21790`: FIX: Update blitting and drawing on the macosx backend +* :ghpull:`22175`: FIX: Update macosx animation handling +* :ghpull:`22569`: Require non-zero dash value +* :ghpull:`22544`: Correct paper sizes +* :ghpull:`20470`: Issues warnings for legend handles without handlers +* :ghpull:`22558`: MNT: Simplify imports +* :ghpull:`22580`: fix doc for annotation_clip parameter +* :ghpull:`22581`: DOC: fix various typos +* :ghpull:`22573`: Bump actions/setup-python from 2 to 3 +* :ghpull:`22568`: Rename qhull source to _qhull_wrapper.cpp. +* :ghpull:`22561`: FIX: Handle stopped animation figure resize +* :ghpull:`22562`: TST: Add a frame test for animations +* :ghpull:`22514`: Expire deprecations in cbook.deprecation +* :ghpull:`22555`: Use picklable callbacks for DraggableBase. +* :ghpull:`22552`: Tweak dependency checking in doc/conf.py. +* :ghpull:`22550`: Require sphinx>=3 & numpydoc>=1.0 for building docs. +* :ghpull:`22539`: Deprecate toplevel mpl.text.get_rotation; normalize rotations early. +* :ghpull:`22502`: Cleanup unused imports and variables in backends +* :ghpull:`20071`: Document, test, and simplify impl. of auto_adjustable_area. +* :ghpull:`22366`: Deprecation removal/updates in axes3d +* :ghpull:`22484`: Simplify the internal API to connect picklable callbacks. +* :ghpull:`22417`: Support passing rgbaFace as an array to agg's draw_path. +* :ghpull:`22412`: Turn _get_axis_map() into a property and remove _get_axis_list() +* :ghpull:`22486`: Expire deprecations in lines and patches +* :ghpull:`22512`: Increase coverage +* :ghpull:`22504`: Simplify FontProperties init. +* :ghpull:`22497`: Remove entries of MathTextParser._backend_mapping deprecated in 3.4. +* :ghpull:`22487`: Don't key MathTextParser cache off a mutable FontProperties. +* :ghpull:`22468`: Turn _mathtext.ship into a plain function. +* :ghpull:`22490`: Deprecate unused, untested Affine2D.identity(). +* :ghpull:`22491`: Linewrap setupext to 79 character lines. +* :ghpull:`22488`: Some more maintenance for mathtext internal implementation. +* :ghpull:`22485`: Change string representation of AxesImage +* :ghpull:`22240`: Add minimum macosx version +* :ghpull:`22480`: Remove _point_size_reduction. +* :ghpull:`22204`: Cleanup _mathtext internal API +* :ghpull:`22469`: Improve readability of mathtext internal structures. +* :ghpull:`22477`: Un-pyplot some examples which were already explicitly referencing axes. +* :ghpull:`22467`: Small cleanup to font handling in agg. +* :ghpull:`21178`: Add asinh axis scaling (*smooth* symmetric logscale) +* :ghpull:`22411`: Move cbook._define_aliases() to _api.define_aliases() +* :ghpull:`22465`: Deprecate unused AddList. +* :ghpull:`22451`: Clarify error message for bad keyword arguments. +* :ghpull:`21267`: Cleanup AnnotationBbox. +* :ghpull:`22464`: Small improvements related to radar_chart example. +* :ghpull:`22421`: Make most params to figure()/Figure() kwonly. +* :ghpull:`22457`: Copy arrowprops argument to FancyAnnotationBbox. +* :ghpull:`22454`: move ``_toolbar_2`` from webagg_core to webagg +* :ghpull:`22413`: Remove some trivial private getters/setters in axisartist +* :ghpull:`21634`: TST: Add future dependency tests as a weekly CI job +* :ghpull:`22079`: Share FigureManager class between gtk3 and gtk4. +* :ghpull:`22440`: Clarify warning about labels with leading underscores. +* :ghpull:`17488`: Make error message explicit in legend.py +* :ghpull:`22453`: Simplify impl. of polar limits setting API. +* :ghpull:`22449`: Small cleanup to quiver. +* :ghpull:`22415`: Make emit and auto args of set_{x,y,z}lim keyword only. +* :ghpull:`22422`: Deprecate backend_ps.convert_psfrags. +* :ghpull:`22194`: Drop support for Python 3.7 +* :ghpull:`22234`: Partial fix for grid alpha +* :ghpull:`22433`: Fix ambiguous link targets in docs. +* :ghpull:`22420`: Update plt.figure() docstring. +* :ghpull:`22388`: Make signature of Axes.annotate() more explicit. +* :ghpull:`22419`: Remove "Matplotlib version" from docs issue template +* :ghpull:`22423`: Avoid indiscriminate glob-remove in xpdf_distill. +* :ghpull:`22406`: [DOC]: Removed a redundant 'The' +* :ghpull:`21442`: Factor out common limits handling for x/y/z axes. +* :ghpull:`22397`: Axes capitalization in widgets and axes3d +* :ghpull:`22394`: Tweak Axes3D docstrings that refer to 2D plotting methods. +* :ghpull:`22383`: TST: fix doc build +* :ghpull:`21877`: DOC: attempt to explain the main different APIs +* :ghpull:`21238`: Raise when unknown signals are connected to CallbackRegistries. +* :ghpull:`22345`: MNT: make layout deprecations pending +* :ghpull:`21597`: FIX: Remove the deepcopy override from transforms +* :ghpull:`22370`: Replace tabs with spaces in C code. +* :ghpull:`22371`: Corrected a mistake in comments (Issue #22369) +* :ghpull:`21352`: Refactor hexbin(). +* :ghpull:`19214`: Improve autoscaling for high order Bezier curves +* :ghpull:`22268`: Deprecated is_decade and is_close_to_int +* :ghpull:`22359`: Slightly refactor TeX source generation. +* :ghpull:`22365`: Remove deprecated ``MovieWriter.cleanup`` +* :ghpull:`22363`: Properly capitalize "Unicode". +* :ghpull:`22025`: Deprecate various custom FigureFrameWx attributes/methods. +* :ghpull:`21391`: Reuse imsave()'s background-blending code in FigureCanvasAgg.print_jpeg. +* :ghpull:`22026`: Simplify wxframe deletion. +* :ghpull:`22351`: Fix "trailing" whitespace in C docstrings. +* :ghpull:`22342`: Docstrings for _qhull. +* :ghpull:`21836`: Slightly shorten ft2font init. +* :ghpull:`21962`: Privatize various internal APIs of backend_pgf. +* :ghpull:`22114`: Rewrite AxesStack independently of cbook.Stack. +* :ghpull:`22332`: Let TransformedPatchPath inherit most functionality from TransformedPath. +* :ghpull:`22292`: Cleanup Axis._translate_tick_kw +* :ghpull:`22339`: wx.App() should be init'ed in new_figure_manager_given_figure +* :ghpull:`22315`: More standardization of floating point slop in mpl_toolkits. +* :ghpull:`22337`: DOC: More cleanup axes -> Axes +* :ghpull:`22323`: Replace sole use of maxdict by lru_cache. +* :ghpull:`22229`: FIX: make safe to add / remove artists during ArtistList iteration +* :ghpull:`22196`: ``dates`` classes and functions support ``tz`` both as string and ``tzinfo`` +* :ghpull:`22161`: Add box when setting ``PolygonSelector.verts`` +* :ghpull:`19368`: Raise warning and downsample if data given to _image.resample is too large +* :ghpull:`22250`: Unify toolbar init across backends. +* :ghpull:`22304`: Added tests for ContourSet.legend_elements +* :ghpull:`21583`: Add pre-commit config and dev instructions +* :ghpull:`21547`: Custom cap widths in box and whisker plots in bxp() and boxplot() +* :ghpull:`20887`: Implement a consistent behavior in TkAgg backend for bad blit bbox +* :ghpull:`22317`: Rename outdated seaborn styles. +* :ghpull:`22271`: Rework/fix Text layout cache. +* :ghpull:`22097`: In mpl_toolkits, use the same floating point slop as for standard ticks. +* :ghpull:`22295`: Display bad format string in error message. +* :ghpull:`22287`: Removed unused code and variables +* :ghpull:`22244`: MNT: colorbar locators properties +* :ghpull:`22270`: Expanded documentation of Axis.set_ticks as per discussion in issue #22262 +* :ghpull:`22280`: Simplify FontProperties.copy(). +* :ghpull:`22174`: Give the Tk toolbar buttons a flat look +* :ghpull:`22046`: Add the ability to change the focal length of the camera for 3D plots +* :ghpull:`22251`: Colorbar docstring reorg +* :ghpull:`21933`: MNT: privatize colorbar attr +* :ghpull:`22258`: DOC: fix version switcher +* :ghpull:`22261`: DOC: fix switcher json +* :ghpull:`22154`: Add some tests for minspan{x,y} in RectangleSelector +* :ghpull:`22246`: DOC: add dropdown +* :ghpull:`22133`: Deprecated ``afm``, ``fontconfig_pattern``, and ``type1font`` +* :ghpull:`22249`: DOC: More capitalization of Axes +* :ghpull:`22021`: Ensure that all toolbar (old/new) subclasses can be init'ed consistently +* :ghpull:`22213`: Improve ft2font error reporting. +* :ghpull:`22245`: Deprecate cleared kwarg to get_renderer. +* :ghpull:`22239`: Fix typos +* :ghpull:`22216`: turn off the grid after creating colorbar axes +* :ghpull:`22055`: FIX: Return value instead of enum in get_capstyle/_joinstyle +* :ghpull:`22228`: Remove some unnecessary getattrs. +* :ghpull:`20426`: ENH: Layout engine +* :ghpull:`22224`: Trivial doc fix to annotations tutorial. +* :ghpull:`21894`: Jointly track x and y in PolygonSelector. +* :ghpull:`22205`: Bump minimum NumPy to 1.19 +* :ghpull:`22203`: Factor out underline-thickness lookups in mathtext. +* :ghpull:`22189`: DOC: Add hatch API to reference +* :ghpull:`22084`: Clean up 3d plot box_aspect zooming +* :ghpull:`22098`: Expire axes_grid1/axisartist deprecations. +* :ghpull:`22013`: Use standard toolbar in wx. +* :ghpull:`22160`: Removed unused variables etc. +* :ghpull:`22179`: FIX: macosx check case-insensitive app name +* :ghpull:`22157`: Improved coverage of mathtext and removed unused code +* :ghpull:`21781`: Use a fixture to get widget testing axes +* :ghpull:`22140`: Ensure log formatters use Unicode minus +* :ghpull:`21342`: Fix drawing animated artists changed in selector callback +* :ghpull:`22134`: Deprecated ``tight_bbox`` and ``tight_layout`` modules +* :ghpull:`21965`: Switch transOffset to offset_transform. +* :ghpull:`22145`: Make Tk windows use the same icon as other backends +* :ghpull:`22107`: Expire mathttext-related deprecations +* :ghpull:`22139`: FIX: width/height were reversed in macosx rectangle creation +* :ghpull:`22123`: Deprecate accepting arbitrary parameters in some get_window_extent() methods +* :ghpull:`22122`: Hint at draw_without_rendering() in Text.get_window_extent +* :ghpull:`22120`: Drop dependency on scipy in the docs. +* :ghpull:`22063`: FIX: Autoposition title when yaxis has offset +* :ghpull:`22119`: Micro-optimize skew(). +* :ghpull:`22109`: Remove unnecessary null checks in macosx.m, and some more maintenance +* :ghpull:`21977`: Add corner coordinate helper methods to Ellipse/Rectangle +* :ghpull:`21830`: Add option of bounding box for PolygonSelector +* :ghpull:`22115`: Turn _localaxes into a plain list. +* :ghpull:`22108`: Micro-optimize rotation transform. +* :ghpull:`22043`: Cleanup differential equations examples. +* :ghpull:`22080`: Simple style(ish) fixes. +* :ghpull:`22110`: Right-aligned status text in backends +* :ghpull:`21873`: DOC: Update and consolidate Custom Tick Formatter for Time Series example +* :ghpull:`22112`: Fix a small typo +* :ghpull:`20117`: Very soft-deprecate AxesDivider.new_{horizontal,vertical}. +* :ghpull:`22034`: Update lines_with_ticks_demo.py +* :ghpull:`22102`: DOC: rename usage tutorial to quick_start +* :ghpull:`19228`: Validate text rotation in setter +* :ghpull:`22081`: Expire colorbar-related deprecations. +* :ghpull:`22008`: Added color keyword argument to math_to_image +* :ghpull:`22058`: Remove exprired mplot3d deprecations for 3.6 +* :ghpull:`22073`: DOC: Add new tutorial to external resources. +* :ghpull:`22054`: MNT: Set CapStyle member names automatically +* :ghpull:`22061`: De-duplicate mplot3D API docs +* :ghpull:`22075`: Remove unnecessary ``.figure`` qualifier in docs. +* :ghpull:`22051`: Make required_interactive_framework required on FigureCanvas. +* :ghpull:`22050`: Deprecate the noop, unused FigureCanvasBase.resize. +* :ghpull:`22030`: Add explanatory comments to "broken" horizontal bar plot example +* :ghpull:`22001`: Fix: [Bug]: triplot with 'ls' argument yields TypeError #21995 +* :ghpull:`22045`: Fill in missing Axes3D box_aspect argument docstring +* :ghpull:`22042`: Keep FontEntry helpers private. +* :ghpull:`21042`: Make rcParams.copy() return a new RcParams instance. +* :ghpull:`22032`: flipy only affects the drawing of texts, not of images. +* :ghpull:`21993`: Added docstring to rrulewrapper class +* :ghpull:`21935`: Significantly improve tight layout performance for cartopy axes +* :ghpull:`22000`: Some gtk cleanups. +* :ghpull:`21983`: Simplify canvas class control in FigureFrameWx. +* :ghpull:`21985`: Slightly tighten the _get_layout_cache_key API. +* :ghpull:`22020`: Simplify wx _print_image. +* :ghpull:`22010`: Fix syntax highlighting in contrib guide. +* :ghpull:`22003`: Initialize RendererCairo.{width,height} in constructor. +* :ghpull:`21992`: Use _make_classic_style_pseudo_toolbar more. +* :ghpull:`21916`: Fix picklability of make_norm_from_scale norms. +* :ghpull:`21981`: FigureCanvasCairo can init RendererCairo; kill RendererCairo subclasses. +* :ghpull:`21986`: InvLogTransform should only return masked arrays for masked inputs. +* :ghpull:`21991`: PEP8ify wx callback names. +* :ghpull:`21975`: DOC: remove experimental tag from CL +* :ghpull:`21989`: Autoinfer norm bounds. +* :ghpull:`21980`: Removed loaded modules logging +* :ghpull:`21982`: Deprecate duplicated FigureManagerGTK{3,4}Agg classes. +* :ghpull:`21963`: Clarify current behavior of draw_path_collection. +* :ghpull:`21974`: Reword inset axes example. +* :ghpull:`21835`: Small improvements to interactive examples +* :ghpull:`21050`: Store dash_pattern as single attribute, not two. +* :ghpull:`21557`: Fix transparency when exporting to png via pgf backend. +* :ghpull:`21904`: Added _repr_html_ for fonts +* :ghpull:`21696`: Use cycling iterators in RendererBase. +* :ghpull:`21955`: Refactor common parts of ImageMagick{,File}Writer. +* :ghpull:`21952`: Clarify coordinates for RectangleSelector properties +* :ghpull:`21964`: Fix some more missing references. +* :ghpull:`21516`: Make _request_autoscale_view more generalizable to 3D. +* :ghpull:`21947`: Slightly cleanup RendererBase docs. +* :ghpull:`21961`: Privatize various internal APIs of backend_pgf. +* :ghpull:`21956`: Remove tests for avconv animation writers. +* :ghpull:`21954`: DOC: Move Animation and MovieWriter inheritance diagrams ... +* :ghpull:`21780`: Add a click_and_move widget test helper +* :ghpull:`21941`: Merge branch v3.5.x into main +* :ghpull:`21936`: Small ``__getstate__`` cleanups. +* :ghpull:`21939`: Update comment re: register_at_fork. +* :ghpull:`21910`: Fold _rgbacache into _imcache. +* :ghpull:`21921`: Clean up RectangleSelector move code +* :ghpull:`21925`: Drop labelling from PR welcome action +* :ghpull:`14930`: Set Dock icon on the macosx backend +* :ghpull:`21920`: Improve square state calculation in RectangleSelector +* :ghpull:`21919`: Fix use_data_coordinates docstring +* :ghpull:`21881`: Add a PolygonSelector.verts setter +* :ghpull:`20839`: Fix centre and square state and add rotation for rectangle selector +* :ghpull:`21874`: DOC: Add Date Tick Locators and Formatters example +* :ghpull:`21799`: Added get_font_names() to fontManager +* :ghpull:`21871`: DOC: Code from markevery_prop_cycle moved to test. +* :ghpull:`21395`: Expire _check_savefig_extra_args-related deprecations. +* :ghpull:`21867`: Remove unused bbox arg to _convert_agg_to_wx_bitmap. +* :ghpull:`21868`: Use partialmethod for better signatures in backend_ps. +* :ghpull:`21520`: Shorten some inset_locator docstrings. +* :ghpull:`21737`: Update the "Rotating a 3D plot" gallery example to show all 3 rotation axes +* :ghpull:`21851`: Re-order a widget test function +* :ghpull:`10762`: Normalization of elevation and azimuth angles for surface plots +* :ghpull:`21426`: Add ability to roll the camera in 3D plots +* :ghpull:`21822`: Replace NSDictionary by switch-case. +* :ghpull:`21512`: MNT: Add modifier key press handling to macosx backend +* :ghpull:`21784`: Set macOS icon when using Qt backend +* :ghpull:`21748`: Shorten PyObjectType defs in macosx.m. +* :ghpull:`21809`: MNT: Turn all macosx warnings into errors while building +* :ghpull:`21792`: Fix missing return value in closeButtonPressed. +* :ghpull:`21767`: Inherit many macos backend docstrings. +* :ghpull:`21766`: Don't hide build log on GHA. +* :ghpull:`21728`: Factor out some macosx gil handling for py-method calls from callbacks. +* :ghpull:`21754`: Update gitattributes so that objc diffs are correctly contextualized. +* :ghpull:`21752`: Add a helper for directly output pdf streams. +* :ghpull:`21750`: Don't sort pdf dicts. +* :ghpull:`21745`: DOC: Clarify Coords Report Example +* :ghpull:`21746`: Fix/add docstring signatures to many C++ methods. +* :ghpull:`21631`: DOC: change gridspec tutorial to arranging_axes tutorial +* :ghpull:`21318`: FIX: better error message for shared axes and axis('equal') +* :ghpull:`21519`: mark_inset should manually unstale axes limits before drawing itself. +* :ghpull:`21724`: Fix copyright date with SOURCE_DATE_EPOCH set +* :ghpull:`21398`: FIX: logic of title repositioning +* :ghpull:`21717`: Simplify macosx toolbar init. +* :ghpull:`21690`: Whitespace/braces/#defines cleanup to macosx. +* :ghpull:`21695`: Use _api.check_shape more. +* :ghpull:`21698`: Small code cleanups and style fixes. +* :ghpull:`21529`: Delay-load keymaps in toolmanager. +* :ghpull:`21525`: Fix support for clim in scatter. +* :ghpull:`21697`: Drop non-significant zeros from ps output. +* :ghpull:`21692`: CI: Remove CI test runs from forks of matplotlib +* :ghpull:`21591`: Make ToolFullScreen a Tool, not a ToolToggle. +* :ghpull:`21677`: Simplify test for negative xerr/yerr. +* :ghpull:`21657`: Replace some image_comparisons by return-value-tests/check_figures_e… +* :ghpull:`21664`: Merge 3.5.x into main +* :ghpull:`21490`: Make Line2D copy its inputs +* :ghpull:`21639`: Skip some uses of packaging's PEP440 version for non-Python versions. +* :ghpull:`21604`: Fix centre square rectangle selector part 1 +* :ghpull:`21593`: Check for images added-and-modified in a same PR +* :ghpull:`20750`: Shorten issue templates +* :ghpull:`21590`: Make gtk3 full_screen_toggle more robust against external changes. +* :ghpull:`21582`: Organize checklist in PR template +* :ghpull:`21580`: Rename/remove _lastCursor, as needed. +* :ghpull:`21567`: Removed the range parameter from the validate_whiskers function's err… +* :ghpull:`21565`: Further remove remnants of offset_position. +* :ghpull:`21542`: [ENH]: Use new style format strings for colorbar ticks +* :ghpull:`21564`: Skip invisible artists when doing 3d projection. +* :ghpull:`21558`: Various small fixes for streamplot(). +* :ghpull:`21544`: Return minorticks as array, not as list. +* :ghpull:`21546`: Added links to the mosaic docs in figure and pyplot module docstrings +* :ghpull:`21545`: Turn mouseover into a mpl-style getset_property. +* :ghpull:`21537`: Remove unnecessary False arg when constructing wx.App. +* :ghpull:`21536`: Reword margins docstrings, and fix bounds on zmargin values. +* :ghpull:`21535`: typo-correction-on-line-185 +* :ghpull:`21534`: Do not use space in directive calling. +* :ghpull:`21494`: Adding tutorial links for blitting in widgets.py +* :ghpull:`21407`: Stash exceptions when FT2Font closes the underlying stream. +* :ghpull:`21431`: set_ticks([single_tick]) should also expand view limits. +* :ghpull:`21444`: Make pipong example self-contained. +* :ghpull:`21392`: Add label about workflow to new contributor PRs +* :ghpull:`21440`: Install sphinx-panels along with development setup +* :ghpull:`21434`: Remove coords_flat variable +* :ghpull:`21415`: Move gui_support.macosx option to packages section. +* :ghpull:`21412`: Privatize some SVG internal APIs. +* :ghpull:`21401`: Uncamelcase some internal variables in axis.py; rename _get_tick_bboxes. +* :ghpull:`21417`: Use Bbox.unit() more. +* :ghpull:`20253`: Simplify parameter handling in FloatingAxesBase. +* :ghpull:`21379`: Simplify filename tracking in FT2Font. +* :ghpull:`21278`: Clear findfont cache when calling addfont(). +* :ghpull:`21400`: Use bbox.{size,bounds,width,height,p0,...} where appropriate. +* :ghpull:`21408`: Reword annotations tutorial section titles. +* :ghpull:`21371`: Rename default branch +* :ghpull:`21389`: Log pixel coordinates in event_handling coords_demo example on terminal/console +* :ghpull:`21376`: Factor common parts of saving to different formats using pillow. +* :ghpull:`21377`: Enable tests for text path based markers +* :ghpull:`21283`: Demonstrate inset_axes in scatter_hist example. +* :ghpull:`21356`: Raise an exception when find_tex_file fails to find a file. +* :ghpull:`21362`: Simplify wording of allowed errorbar() error values +* :ghpull:`21274`: ENH: Add support to save images in WebP format +* :ghpull:`21289`: Simplify _init_legend_box. +* :ghpull:`21256`: Make image_comparison work even without the autoclose fixture. +* :ghpull:`21343`: Fix type1font docstring markup/punctuation. +* :ghpull:`21341`: Fix trivial docstring typo. +* :ghpull:`21301`: Simplify ``Colormap.__call__`` a bit. +* :ghpull:`21280`: Make ``Path.__deepcopy__`` interact better with subclasses, e.g. TextPath. +* :ghpull:`21266`: Fix #21101 Add validator to errorbar method +* :ghpull:`20921`: Fix problem with (deep)copy of TextPath +* :ghpull:`20914`: 19195 rotated markers +* :ghpull:`21276`: Add language about not assigning issues +* :ghpull:`20715`: Improve Type-1 font parsing +* :ghpull:`21218`: Parametrize/simplify test_missing_psfont. +* :ghpull:`21213`: Compress comments in make_image. +* :ghpull:`21187`: Deprecate error_msg_foo helpers. +* :ghpull:`21190`: Deprecate mlab.stride_windows. +* :ghpull:`21152`: Rename ``**kw`` to ``**kwargs``. +* :ghpull:`21087`: Move colormap examples from userdemo to images_contours_and_fields. +* :ghpull:`21074`: Deprecate MarkerStyle(None). +* :ghpull:`20990`: Explicit registration of canvas-specific tool subclasses. +* :ghpull:`21049`: Simplify setting Legend attributes +* :ghpull:`21056`: Deprecate support for no-args MarkerStyle(). +* :ghpull:`21059`: Remove dummy test command from setup.py +* :ghpull:`21015`: Prepare for rcParams.copy() returning a new RcParams instance in the future +* :ghpull:`21021`: Factor out for_layout_only backcompat support in get_tightlayout. +* :ghpull:`21023`: Inline ToolManager._trigger_tool to its sole call site. +* :ghpull:`21005`: Test the rcParams deprecation machinery. +* :ghpull:`21010`: Avoid TransformedBbox where unneeded. +* :ghpull:`21019`: Reword custom_ticker1 example. +* :ghpull:`20995`: Deprecate some backend_gtk3 helper globals. +* :ghpull:`21004`: Remove now-unused rcParams _deprecated entries. +* :ghpull:`20986`: Make HandlerLine2D{,Compound} inherit constructors from HandlerNpoints. +* :ghpull:`20974`: Rename symbol_name to glyph_name where appropriate. +* :ghpull:`20961`: Small cleanups to math_to_image. +* :ghpull:`20957`: legend_handler_map cleanups. +* :ghpull:`20955`: Remove unused HostAxes._get_legend_handles. +* :ghpull:`20851`: Try to install the Noto Sans CJK font + +Issues (202): + +* :ghissue:`23827`: backend_gtk3agg.py calls set_device_scale +* :ghissue:`23560`: [Doc]: mpl_toolkits.axes_grid still mentioned as maintained +* :ghissue:`23794`: [Doc]: Version switcher broken in devdocs +* :ghissue:`23806`: [Bug]: possible regression in axis ticks handling in matplotlib 3.6.0rc2 +* :ghissue:`22965`: [Bug]: triplot duplicates label legend +* :ghissue:`23807`: streamplot raises ValueError when the input is zeros +* :ghissue:`23761`: [Bug]: False positive legend handler warnings in 3.6.0.rc1 +* :ghissue:`23398`: [Bug]: Newer versions of matplotlib ignore xlabel on colorbar axis +* :ghissue:`23699`: [Bug]: Bug with toolbar instantiation in notebook +* :ghissue:`23745`: [Doc]: Minor rcParams/matplotlibrc doc issues +* :ghissue:`23717`: [Bug]: AxesSubplot.get_yticks not returning the actual printed ticks +* :ghissue:`21508`: [Doc]: Create diagram to show rotation directions for 3D plots +* :ghissue:`23709`: [Bug]: colorbar with unattached mappables can't steal space +* :ghissue:`23701`: [Bug]: plt.figure(), plt.close() leaks memory +* :ghissue:`22409`: [Bug]: AttributeError: 'QResizeEvent' object has no attribute 'pos' +* :ghissue:`19609`: DeprecationWarning when changing color maps +* :ghissue:`23716`: MatplotlibDeprecationWarning removal hard-breaks seaborn in 3.6rc1 +* :ghissue:`23719`: [Bug]: register_cmap deprecation message seems wrong +* :ghissue:`23707`: test_Normalize fails on aarch64/ppc64le/s390x +* :ghissue:`21107`: [MNT]: Should plt.xticks() get a minor keyword argument +* :ghissue:`23679`: [Doc]: Deprecated modules not in docs +* :ghissue:`19550`: Arc and pathpatch_2d_to_3d plots full ellipse +* :ghissue:`23329`: [Bug]: ``plt.autoscale()`` fails for partial ``Arc`` +* :ghissue:`11266`: Arc patch ignoring theta1/theta2 when added to Axes via PatchCollection +* :ghissue:`4067`: 'Poly3DCollection' object has no attribute '_facecolors2d' +* :ghissue:`23622`: [MNT]: make.bat not parsing sphinxopt +* :ghissue:`23459`: [Bug]: 'Line3D' object has no attribute '_verts3d' +* :ghissue:`23653`: [Bug]: macosx subplot tool causes segfault when window closed +* :ghissue:`23660`: [Bug]: Test test_figure.py::test_subfigure_ss[png] FAILED on ppc64le +* :ghissue:`23645`: [MNT]: Python 3.11 manylinux wheels +* :ghissue:`23650`: TTF fonts loaded from file are not embedded/displayed properly when saved to pdf +* :ghissue:`23583`: [Doc]: Document the position parameter in apply_aspect() +* :ghissue:`23386`: setuptools_scm-git-archive is obsolete +* :ghissue:`23220`: [Doc]: Clarify ``offset`` parameter in linestyle +* :ghissue:`22746`: [Doc]: Document that rcParams['font.family'] can be a list +* :ghissue:`8187`: Axes doesn't have ````legends```` attribute? +* :ghissue:`23580`: [Bug]: TypeError when plotting against list of datetime.date where 0th element of list is None +* :ghissue:`15514`: Relevant methods are only documented in base classes and thus not easily discoverable +* :ghissue:`21611`: DOC: Add conda environment instructions to developers guide +* :ghissue:`23487`: [Bug]: scatter plot color settings discarded unless c given +* :ghissue:`22977`: [Bug]: offset dash linestyle has no effect in patch objects +* :ghissue:`18883`: Matplotlib would not try to apply all the font in font list to draw all characters in the given string. +* :ghissue:`22570`: [ENH]: Provide ``axis('equal')`` for ``Axes3D``. +* :ghissue:`23433`: [Bug]: array-like linewidth raises an error for scatter3D +* :ghissue:`12388`: Legend Title Left Alignment +* :ghissue:`23375`: [Bug]: markerfacecoloralt not supported when drawing errorbars +* :ghissue:`17973`: DOC: matplotlib.__doc__ not included in online docs ? +* :ghissue:`23474`: [Bug]: ``\,`` and ``\mathrm{\,}`` are not identical in Mathtext when using CM and STIX +* :ghissue:`8715`: event handlers have different signatures across backends +* :ghissue:`18271`: PGF uses the minimal document class +* :ghissue:`23324`: [Bug]: Exception not handled in widgetlock() +* :ghissue:`15710`: doc for type of tz parameter is inconsistent throughout dates.py +* :ghissue:`21165`: Hexbin marginals need a test for linear scaling +* :ghissue:`23105`: [MNT]: Deprecate per-backend customization of draw_if_interactive +* :ghissue:`23147`: [Bug]: with setuptools>=60, cannot find msbuild +* :ghissue:`23379`: [Bug]: Offset notation on y-axis can overlap with a long title +* :ghissue:`22819`: [Doc]: Make rect argument consistent in the docstrings +* :ghissue:`23172`: [Bug]: Calling matplotlib.pyplot.show() outside of matplotlib.pyplot.rc_context no longer works +* :ghissue:`23019`: [Bug]: ``UnicodeDecodeError`` when using some special and accented characters in TeX +* :ghissue:`23334`: [Doc]: Tk embedding example crashes Spyder +* :ghissue:`23298`: [Bug]: get_backend() clears figures from Gcf.figs if they were created under rc_context +* :ghissue:`21942`: [ENH]: add width/height_ratios to subplots and friends +* :ghissue:`23028`: [ENH]: contour kwarg for negative_linestyle +* :ghissue:`19223`: Certain non-hashable parameters to text() give cryptic error messages +* :ghissue:`18351`: Add the ability to plot striped lines +* :ghissue:`23205`: [Bug]: URL-area not rotated in PDFs +* :ghissue:`23268`: [Bug]: hyphen renders different length depending on presence of MathText +* :ghissue:`23308`: [Bug]: set_visible() not working for 3d projection +* :ghissue:`23296`: Set_color method for line2d object in latest document not work +* :ghissue:`22992`: [Bug]: test_image_comparison_expect_rms nondeterministic failure +* :ghissue:`23008`: [ENH]: Use ``\genfrac`` in display style? +* :ghissue:`23214`: [MNT]: Rename examples with "test" in the name +* :ghissue:`17852`: Thin space missing after mathtext operators +* :ghissue:`12078`: Inconsistency in keyword-arguments ncol/ncols, nrow/nrows +* :ghissue:`23239`: [Doc]: steps is not implemented in line styles. +* :ghissue:`23151`: [MNT]: default date limits... +* :ghissue:`9462`: Misaligned bottoms of subplots for png output with bbox_inches='tight' +* :ghissue:`21369`: [Bug]: ax.invert_xaxis() and ax.invert_yaxis() both flip the X axis +* :ghissue:`20797`: ``macosx`` cursors break with images +* :ghissue:`23084`: [TST] Upcoming dependency test failures +* :ghissue:`22910`: [Bug]: bar_label fails with nan errorbar values +* :ghissue:`23074`: [Bug]: matplotlib crashes if ``_tkinter`` doesn't have ``__file__`` +* :ghissue:`23083`: [Bug]: Confusing error messages +* :ghissue:`22391`: [Doc]: Remove "keywords" line at the bottom of all examples +* :ghissue:`20202`: Daylocator causes frozen computer when used with FuncAnimation +* :ghissue:`22529`: Replace C++ quad contouring code with use of ContourPy +* :ghissue:`21710`: [ENH]: macosx backend does not respect rcParams["savefig.directory"] +* :ghissue:`21880`: [Doc]: rrulewrapper not included in API docs +* :ghissue:`22622`: [Bug]: Gaps and overlapping areas between bins when using float16 +* :ghissue:`23043`: [TST] Upcoming dependency test failures +* :ghissue:`17960`: Line2D object markers are lost when retrieved from legend.get_lines() when linestyle='None' +* :ghissue:`23026`: [MNT]: Require that matplotlibrc/style files use utf-8 (or have an encoding cookie) +* :ghissue:`22947`: [Bug]: Can't use ``plt.sca()`` on axes created using subfigures +* :ghissue:`22623`: [ENH]: support rect with constrained_layout ("layout only to part of the figure") +* :ghissue:`22917`: "ab;cd" missing in subplot_mosaic tutorial +* :ghissue:`22686`: [Bug]: can not give init value for RangeSlider widget +* :ghissue:`22740`: [MNT]: Add codespell to pre-commit hooks +* :ghissue:`22893`: rainbow text example is broken +* :ghissue:`21571`: [Doc]: Clarify text positioning +* :ghissue:`22092`: [Bug]: Configure subplots dialog freezes for TkAgg with toolmanager +* :ghissue:`22760`: [Bug]: Macosx legend picker doesn't work anymore +* :ghissue:`16369`: Call to input blocks slider input on osx with the default agg 'MacOSX'. It works fine on when TkAgg is used. +* :ghissue:`22915`: [Bug]: figure.raise_window rcParam does not work on MacOSX backend +* :ghissue:`22930`: [Bug]: Regression in dashes due to #22569 +* :ghissue:`22859`: [Bug]: findSystemFonts should not look in subdirectories of C:\Windows\Fonts\ +* :ghissue:`22882`: Missing ``f`` prefix on f-strings +* :ghissue:`22738`: [MNT]: make Axes.cla an alias for Axes.clear in all cases +* :ghissue:`22708`: [TST] Upcoming dependency test failures +* :ghissue:`8388`: Proposed ENH: Allow user to turn off breaking of streamlines in streamplot +* :ghissue:`20755`: [Bug]: make_norm_from_scale should create picklable classes even when used in-line. +* :ghissue:`18249`: Expand the explanation of the Object-Oriented interface +* :ghissue:`22792`: [Bug]: .eps greyscale hatching of patches when lw=0 +* :ghissue:`22630`: [ENH]: enable passing of projection keyword to Axes.inset_axes +* :ghissue:`22414`: [Bug]: bar_label overlaps bars when y-axis is inverted +* :ghissue:`22726`: [Bug]: tripcolor ignores clim +* :ghissue:`21635`: [ENH]: Add a nightly wheel build +* :ghissue:`9994`: document where nightly wheels are published +* :ghissue:`22350`: [Bug]: text.usetex Vs. DateFormatter +* :ghissue:`4976`: missing imshow() subplots when using tight_layout() +* :ghissue:`22150`: [ENH]: Tool icons are hardly visible in Tk when using a dark theme +* :ghissue:`22662`: Leave color parameter empty should be fine[ENH]: +* :ghissue:`22671`: [Doc]: plot_format adaption invalidates sphinx cache +* :ghissue:`22582`: [Bug]: FontManager.addfont doesn't accept pathlib.Path of TTF font +* :ghissue:`22657`: [ENH]: vector map +* :ghissue:`16181`: The great API cleanup +* :ghissue:`22636`: [Bug]: Infinite loop when there is single double quote in matplotlibrc +* :ghissue:`22266`: [Doc]: Improve examples in documentation +* :ghissue:`11861`: Figure does not close until script finishes execution +* :ghissue:`19288`: Escape # character in matplotlibrc +* :ghissue:`22579`: [Bug]: Replacement for epoch2num behaves differently (does not accept arrays) +* :ghissue:`22605`: [Bug]: Tool contrast low with dark theme on macosx backend +* :ghissue:`17642`: bring osx backend flush_events to feature parity with other backend +* :ghissue:`19268`: Drawing the canvas does not populate ticklabels on MacOSX backend +* :ghissue:`17445`: MacOSX does not render frames in which new artists are added when blitting +* :ghissue:`10980`: Current versions cannot reproduce rotate_axes_3d_demo.py +* :ghissue:`18451`: MacOSX backend fails with animation in certain scripts +* :ghissue:`22603`: [MNT]: Replace str(n)cpy etc with safe versions (C++) +* :ghissue:`19121`: Handle and label not created for Text with label +* :ghissue:`22563`: [Doc]: annotation_clip=None not correctly documented +* :ghissue:`12528`: Empty axes on draw after blitted animation finishes +* :ghissue:`20991`: [Bug]: Error when using path effect with a PolyCollection +* :ghissue:`19563`: path_effects kwarg triggers exception on 3D scatterplot +* :ghissue:`8650`: System Error in backend_agg. (with a fix!) +* :ghissue:`20294`: ``AxesImage.__str__`` is wrong if the image does not span the full Axes. +* :ghissue:`18066`: Document minimum supported OSX version for macos backend +* :ghissue:`17018`: Add documentation about transparency of frame +* :ghissue:`22403`: [MNT]: Confusing prompt in docs issue template +* :ghissue:`8839`: mpl_connect silently does nothing when passed an invalid event type string +* :ghissue:`22343`: [MNT]: Delay (or make pending) the deprecation of set_constrained_layout/set_tight_layout +* :ghissue:`21554`: [Bug]: ``ValueError`` upon deepcopy of a ``Figure`` object +* :ghissue:`22369`: [Doc]: Incorrect comment in example code for creating adjacent subplots +* :ghissue:`19174`: connectionstyle arc3 with high rad value pushes up data interval of x-axis and y-axis. +* :ghissue:`8351`: seaborn styles make "+", "x" markers invisible; proposed workaround for shipped styles +* :ghissue:`22278`: Deprecate/remove maxdict +* :ghissue:`19276`: imshow with very large arrays not working as expected +* :ghissue:`22035`: [ENH]: Specify a custom focal length / FOV for the 3d camera +* :ghissue:`22264`: [Bug]: new constrained_layout causes axes to go invisible(?) +* :ghissue:`21774`: [MNT]: Improvements to widget tests +* :ghissue:`18722`: Consider removing AFM+mathtext support +* :ghissue:`21540`: [Bug]: cm fontset in log scale does not use Unicode minus +* :ghissue:`22062`: [Bug]: Autopositioned title overlaps with offset text +* :ghissue:`22093`: [Bug]: AttributeError: 'AxesSubplot' object has no attribute 'add_text' +* :ghissue:`22012`: [Bug]: Mouseover coordinate/value text should be right aligned +* :ghissue:`21995`: [Bug]: triplot with 'ls' argument yields TypeError +* :ghissue:`20249`: MatplotlibDeprecationWarning when updating rcparams +* :ghissue:`15781`: MatplotlibDeprecationWarning examples.directory is deprecated +* :ghissue:`13118`: No MatplotlibDeprecationWarning for default rcParams +* :ghissue:`21978`: Remove logging debug of loaded modules +* :ghissue:`11738`: pgf backend doesn't make background transparent +* :ghissue:`18039`: Add ``_repr_html_`` for fonts +* :ghissue:`21970`: [Bug]: tight layout breaks with toolbar.push_current() +* :ghissue:`14850`: No icon showing up with macosx backend +* :ghissue:`17283`: Create Date Formatter/Locator Reference +* :ghissue:`21761`: [Doc]: add how to know available fonts... +* :ghissue:`21863`: [Doc]: Remove example "prop_cycle property markevery in rcParams" +* :ghissue:`10241`: Axes3D.view_init elevation issue between 270 and 360 degrees +* :ghissue:`14453`: add third angle to view_init() +* :ghissue:`20486`: Modifier key press events not recognized on MacOSX backend +* :ghissue:`9837`: MacOS: Key modifiers deprecated +* :ghissue:`11416`: RuntimeError: adjustable='datalim' is not allowed when both axes are shared. +* :ghissue:`17711`: inset_locator.mark_inset() misplaces box connectors +* :ghissue:`20854`: [Doc]: Incorrect copyright start year at the bottom of devdocs page +* :ghissue:`21394`: [Bug]: Subplot title does not obey padding +* :ghissue:`20998`: [Bug]: ToolManager does not respect rcParams["keymap."] set after import time +* :ghissue:`7075`: Superscripts in axis label cut when saving .eps with bbox_inches="tight" +* :ghissue:`21514`: [Doc]: Error message of validate_whiskers is not updated +* :ghissue:`21532`: [Doc]: subplot_mosaic docstring should link to the tutorial +* :ghissue:`16550`: Docs: performance discussion of tight_layout +* :ghissue:`21378`: [ENH]: use new style format strings for colorbar ticks +* :ghissue:`19323`: Streamplot color mapping fails on (near-)empty array. +* :ghissue:`19559`: Axes.get_xticks() returns a numpy array but Axes.get_xticks(minor=True) returns a plain list +* :ghissue:`21526`: [Doc]: Little Typo on Introductory Tutorial +* :ghissue:`19195`: Rotate Markers in functions like plot, scatter, etcetera +* :ghissue:`21364`: [Bug]: double free when FT2Font constructor is interrupted by KeyboardInterrupt +* :ghissue:`16581`: Can't not refresh new font in running interpreter +* :ghissue:`21162`: [ENH]: saving images in webp format +* :ghissue:`18168`: The example of the testing decorator does not work. +* :ghissue:`20943`: [Bug]: Deepcopy of TextPath fails +* :ghissue:`21101`: [Bug]: Errorbars separated from markers with negative errors +* :ghissue:`17986`: MEP22 per-backend tool registration +* :ghissue:`4938`: Feature request: add option to disable mathtext parsing +* :ghissue:`11435`: plt.subplot eats my subplots From b92cccc19122a84c7fa340751ae5cd8003be4c1d Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 8 Oct 2022 03:41:02 -0400 Subject: [PATCH 044/262] Update release notes for 3.6.1 --- doc/_static/switcher.json | 2 +- .../next_api_changes/deprecations/24088-JMK.rst | 9 --------- doc/api/prev_api_changes/api_changes_3.6.1.rst | 15 +++++++++++++++ doc/users/release_notes.rst | 2 ++ 4 files changed, 18 insertions(+), 10 deletions(-) delete mode 100644 doc/api/next_api_changes/deprecations/24088-JMK.rst create mode 100644 doc/api/prev_api_changes/api_changes_3.6.1.rst diff --git a/doc/_static/switcher.json b/doc/_static/switcher.json index c72cbac2b27a..00dd1ffa6c68 100644 --- a/doc/_static/switcher.json +++ b/doc/_static/switcher.json @@ -1,6 +1,6 @@ [ { - "name": "3.6 (stable)", + "name": "3.6.1 (stable)", "version": "stable", "url": "https://matplotlib.org/stable/" }, diff --git a/doc/api/next_api_changes/deprecations/24088-JMK.rst b/doc/api/next_api_changes/deprecations/24088-JMK.rst deleted file mode 100644 index caa7e93a05b4..000000000000 --- a/doc/api/next_api_changes/deprecations/24088-JMK.rst +++ /dev/null @@ -1,9 +0,0 @@ -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())``. diff --git a/doc/api/prev_api_changes/api_changes_3.6.1.rst b/doc/api/prev_api_changes/api_changes_3.6.1.rst new file mode 100644 index 000000000000..ad929d426885 --- /dev/null +++ b/doc/api/prev_api_changes/api_changes_3.6.1.rst @@ -0,0 +1,15 @@ +API Changes for 3.6.1 +===================== + +Deprecations +------------ + +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())``. diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst index 40c286e06a84..5ec5d471142f 100644 --- a/doc/users/release_notes.rst +++ b/doc/users/release_notes.rst @@ -15,8 +15,10 @@ Version 3.6 :maxdepth: 1 prev_whats_new/whats_new_3.6.0.rst + ../api/prev_api_changes/api_changes_3.6.1.rst ../api/prev_api_changes/api_changes_3.6.0.rst github_stats.rst + prev_whats_new/github_stats_3.6.0.rst Version 3.5 =========== From 318b2348f7127efc3e28aadebf762aae32b6343c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 8 Oct 2022 03:41:19 -0400 Subject: [PATCH 045/262] REL: v3.6.1 This is the first bugfix release of the 3.6.x series. This release contains several bug-fixes and adjustments: * A warning is no longer raised when constrained layout explicitly disabled and tight layout is applied * Add missing `get_cmap` method to `ColormapRegistry` * Adding a colorbar on a `ScalarMappable` that is not attached to an `Axes` is now deprecated instead of raising a hard error * Fix `barplot` being empty when first element is NaN * Fix `FigureManager.resize` on GTK4 * Fix `fill_between` compatibility with NumPy 1.24 development version * Fix `hexbin` with empty arrays and log scaling * Fix `resize_event` deprecation warnings when creating figure on macOS * Fix build in mingw * Fix compatibility with PyCharm's interagg backend * Fix crash on empty `Text` in PostScript backend * Fix generic font families in SVG exports * Fix horizontal colorbars with hatches * Fix misplaced mathtext using `eqnarray` * `stackplot` no longer changes the Axes cycler From f4ecfa82d131f3da7818e3bc41e03651b594f0e9 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 8 Oct 2022 04:02:24 -0400 Subject: [PATCH 046/262] BLD: bump branch away from tag So the tarballs from GitHub are stable. From 5a2f8bab8346585e3f2349d04c16f35d1bc9e74c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 8 Oct 2022 05:52:09 -0400 Subject: [PATCH 047/262] DOC: Add Zenodo DOI for 3.6.1 --- doc/_static/zenodo_cache/7162185.svg | 35 ++++++++++++++++++++++++++++ doc/users/project/citing.rst | 3 +++ tools/cache_zenodo_svg.py | 1 + 3 files changed, 39 insertions(+) create mode 100644 doc/_static/zenodo_cache/7162185.svg diff --git a/doc/_static/zenodo_cache/7162185.svg b/doc/_static/zenodo_cache/7162185.svg new file mode 100644 index 000000000000..ea0966377194 --- /dev/null +++ b/doc/_static/zenodo_cache/7162185.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + DOI + + + DOI + + + 10.5281/zenodo.7162185 + + + 10.5281/zenodo.7162185 + + + \ No newline at end of file diff --git a/doc/users/project/citing.rst b/doc/users/project/citing.rst index 53c2591ebfbd..5dd7488e50b6 100644 --- a/doc/users/project/citing.rst +++ b/doc/users/project/citing.rst @@ -29,6 +29,9 @@ By version .. START OF AUTOGENERATED +v3.6.1 + .. image:: ../../_static/zenodo_cache/7162185.svg + :target: https://doi.org/10.5281/zenodo.7162185 v3.6.0 .. image:: ../../_static/zenodo_cache/7084615.svg :target: https://doi.org/10.5281/zenodo.7084615 diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py index 1a3d0493ed6d..f70c14e06c95 100644 --- a/tools/cache_zenodo_svg.py +++ b/tools/cache_zenodo_svg.py @@ -63,6 +63,7 @@ def _get_xdg_cache_dir(): if __name__ == "__main__": data = { + "v3.6.1": "7162185", "v3.6.0": "7084615", "v3.5.3": "6982547", "v3.5.2": "6513224", From a6bcc0a555570bfebbe29934caaef32795f1d881 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 9 Oct 2022 18:42:20 +0200 Subject: [PATCH 048/262] Backport PR #24130: DOC: align contour parameter doc with implementation --- lib/matplotlib/contour.py | 2 +- lib/matplotlib/tri/tricontour.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 6aab5222b783..2f8c934e70b9 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1600,7 +1600,7 @@ def _initialize_x_y(self, z): If an int *n*, use `~matplotlib.ticker.MaxNLocator`, which tries to automatically choose no more than *n+1* "nice" contour levels - between *vmin* and *vmax*. + between minimum and maximum numeric values of *Z*. If array-like, draw contour lines at the specified levels. The values must be in increasing order. diff --git a/lib/matplotlib/tri/tricontour.py b/lib/matplotlib/tri/tricontour.py index df3b44d941ef..ee9d85030c21 100644 --- a/lib/matplotlib/tri/tricontour.py +++ b/lib/matplotlib/tri/tricontour.py @@ -114,7 +114,7 @@ def _contour_args(self, args, kwargs): If an int *n*, use `~matplotlib.ticker.MaxNLocator`, which tries to automatically choose no more than *n+1* "nice" contour levels between - *vmin* and *vmax*. + between minimum and maximum numeric values of *Z*. If array-like, draw contour lines at the specified levels. The values must be in increasing order. From 3d2bbe3d677420f305fb5389703a0a29afad2030 Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Wed, 12 Oct 2022 19:47:38 +0200 Subject: [PATCH 049/262] Backport PR #24137: Add note about blitting and zorder in animations (#24146) Co-authored-by: Oscar Gustafsson --- doc/api/animation_api.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index 5a3d53442fde..132590456763 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -97,6 +97,11 @@ this hopefully minimalist example gives a sense of how ``init_func`` and ``func`` are used inside of `FuncAnimation` and the theory of how 'blitting' works. +.. note:: + + The zorder of artists is not taken into account when 'blitting' + because the 'blitted' artists are always drawn on top. + The expected signature on ``func`` and ``init_func`` is very simple to keep `FuncAnimation` out of your book keeping and plotting logic, but this means that the callable objects you pass in must know what From e6dd37b15d7c19a5c18dbc0678d4e79486a24966 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 13 Oct 2022 12:40:51 +0200 Subject: [PATCH 050/262] Backport PR #24149: FIX: handle input to ax.bar that is all nan --- lib/matplotlib/axes/_axes.py | 8 ++++++++ lib/matplotlib/tests/test_axes.py | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index e5e34c91257d..d8ac2bb829f3 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2182,11 +2182,19 @@ def _convert_dx(dx, x0, xconv, convert): x0 = cbook._safe_first_finite(x0) except (TypeError, IndexError, KeyError): pass + except StopIteration: + # this means we found no finite element, fall back to first + # element unconditionally + x0 = cbook.safe_first_element(x0) try: x = cbook._safe_first_finite(xconv) except (TypeError, IndexError, KeyError): x = xconv + except StopIteration: + # this means we found no finite element, fall back to first + # element unconditionally + x = cbook.safe_first_element(xconv) delist = False if not np.iterable(dx): diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index d6d44bcdb283..c238009b0be1 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -8144,3 +8144,16 @@ def test_bar_leading_nan(): for b in rest: assert np.isfinite(b.xy).all() assert np.isfinite(b.get_width()) + + +@check_figures_equal(extensions=["png"]) +def test_bar_all_nan(fig_test, fig_ref): + mpl.style.use("mpl20") + ax_test = fig_test.subplots() + ax_ref = fig_ref.subplots() + + ax_test.bar([np.nan], [np.nan]) + ax_test.bar([1], [1]) + + ax_ref.bar([1], [1]).remove() + ax_ref.bar([1], [1]) From 2a1958b9fa71437de308a63f2badd05d2f7f7f44 Mon Sep 17 00:00:00 2001 From: hannah Date: Fri, 14 Oct 2022 09:48:16 -0400 Subject: [PATCH 051/262] Backport PR #24164: Fix argument order in hist() docstring. --- lib/matplotlib/axes/_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index d8ac2bb829f3..a3acc5175b30 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -6432,7 +6432,7 @@ def hist(self, x, bins=None, range=None, density=False, weights=None, `~.stairs` to plot the distribution:: counts, bins = np.histogram(x) - plt.stairs(bins, counts) + plt.stairs(counts, bins) Alternatively, plot pre-computed bins and counts using ``hist()`` by treating each bin as a single point with a weight equal to its count:: From 4bac9112ad18cf74728fcbe6c8a42386e2b9364e Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 15 Oct 2022 02:31:22 -0400 Subject: [PATCH 052/262] Backport PR #24158: Fix Qt with PySide6 6.4.0 --- .github/workflows/tests.yml | 9 ++++++--- lib/matplotlib/backends/qt_compat.py | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0c5b7a08ced5..08766f006f5b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,6 +37,9 @@ jobs: python-version: 3.8 extra-requirements: '-c requirements/testing/minver.txt' pyqt5-ver: '==5.11.2 sip==5.0.0' # oldest versions with a Py3.8 wheel. + pyqt6-ver: '==6.1.0 PyQt6-Qt6==6.1.0' + pyside2-ver: '==5.14.0' # oldest version with working Py3.8 wheel. + pyside6-ver: '==6.0.0' delete-font-cache: true - os: ubuntu-20.04 python-version: 3.8 @@ -189,17 +192,17 @@ jobs: echo 'PyQt5 is available' || echo 'PyQt5 is not available' if [[ "${{ runner.os }}" != 'macOS' ]]; then - python -mpip install --upgrade pyside2 && + python -mpip install --upgrade pyside2${{ matrix.pyside2-ver }} && python -c 'import PySide2.QtCore' && echo 'PySide2 is available' || echo 'PySide2 is not available' fi if [[ "${{ matrix.os }}" = ubuntu-20.04 ]]; then - python -mpip install --upgrade pyqt6 && + python -mpip install --upgrade pyqt6${{ matrix.pyqt6-ver }} && python -c 'import PyQt6.QtCore' && echo 'PyQt6 is available' || echo 'PyQt6 is not available' - python -mpip install --upgrade pyside6 && + python -mpip install --upgrade pyside6${{ matrix.pyside6-ver }} && python -c 'import PySide6.QtCore' && echo 'PySide6 is available' || echo 'PySide6 is not available' diff --git a/lib/matplotlib/backends/qt_compat.py b/lib/matplotlib/backends/qt_compat.py index 6d1fc2f9ad2c..06db924feea3 100644 --- a/lib/matplotlib/backends/qt_compat.py +++ b/lib/matplotlib/backends/qt_compat.py @@ -69,7 +69,8 @@ def _setup_pyqt5plus(): - global QtCore, QtGui, QtWidgets, __version__, _isdeleted, _getSaveFileName + global QtCore, QtGui, QtWidgets, __version__ + global _getSaveFileName, _isdeleted, _to_int if QT_API == QT_API_PYQT6: from PyQt6 import QtCore, QtGui, QtWidgets, sip @@ -78,10 +79,15 @@ def _setup_pyqt5plus(): QtCore.Slot = QtCore.pyqtSlot QtCore.Property = QtCore.pyqtProperty _isdeleted = sip.isdeleted + _to_int = operator.attrgetter('value') elif QT_API == QT_API_PYSIDE6: from PySide6 import QtCore, QtGui, QtWidgets, __version__ import shiboken6 def _isdeleted(obj): return not shiboken6.isValid(obj) + if parse_version(__version__) >= parse_version('6.4'): + _to_int = operator.attrgetter('value') + else: + _to_int = int elif QT_API == QT_API_PYQT5: from PyQt5 import QtCore, QtGui, QtWidgets import sip @@ -90,11 +96,16 @@ def _isdeleted(obj): return not shiboken6.isValid(obj) QtCore.Slot = QtCore.pyqtSlot QtCore.Property = QtCore.pyqtProperty _isdeleted = sip.isdeleted + _to_int = int elif QT_API == QT_API_PYSIDE2: from PySide2 import QtCore, QtGui, QtWidgets, __version__ - import shiboken2 + try: + from PySide2 import shiboken2 + except ImportError: + import shiboken2 def _isdeleted(obj): return not shiboken2.isValid(obj) + _to_int = int else: raise AssertionError(f"Unexpected QT_API: {QT_API}") _getSaveFileName = QtWidgets.QFileDialog.getSaveFileName @@ -141,9 +152,6 @@ def _isdeleted(obj): # PyQt6 enum compat helpers. -_to_int = operator.attrgetter("value") if QT_API == "PyQt6" else int - - @functools.lru_cache(None) def _enum(name): # foo.bar.Enum.Entry (PyQt6) <=> foo.bar.Entry (non-PyQt6). From 90ce3ab8a63e251ca611cca12a02f4e3efe05600 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 15 Oct 2022 11:19:48 +0200 Subject: [PATCH 053/262] Backport PR #24171: Fix example where wrong variable was used --- examples/subplots_axes_and_figures/subplots_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/subplots_axes_and_figures/subplots_demo.py b/examples/subplots_axes_and_figures/subplots_demo.py index bbc8afa469fa..41b14dadd620 100644 --- a/examples/subplots_axes_and_figures/subplots_demo.py +++ b/examples/subplots_axes_and_figures/subplots_demo.py @@ -176,7 +176,7 @@ ax3.plot(x + 1, -y, 'tab:green') ax4.plot(x + 2, -y**2, 'tab:red') -for ax in axs.flat: +for ax in fig.get_axes(): ax.label_outer() ############################################################################### From cb372288fe2e4060cf1d1a0080039915bb149d80 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 15 Oct 2022 11:52:17 +0200 Subject: [PATCH 054/262] Backport PR #24167: FIX: turn off layout engine tightbbox --- lib/matplotlib/backend_bases.py | 2 +- .../test_bbox_tight/bbox_inches_fixed_aspect.png | Bin 0 -> 5293 bytes lib/matplotlib/tests/test_bbox_tight.py | 10 ++++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_bbox_tight/bbox_inches_fixed_aspect.png diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index bb17950b03f7..6e603cafbef0 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -2330,7 +2330,7 @@ def print_figure( _bbox_inches_restore = None # we have already done layout above, so turn it off: - stack.enter_context(self.figure._cm_set(layout_engine=None)) + stack.enter_context(self.figure._cm_set(layout_engine='none')) try: # _get_renderer may change the figure dpi (as vector formats # force the figure dpi to 72), so we need to set it again here. diff --git a/lib/matplotlib/tests/baseline_images/test_bbox_tight/bbox_inches_fixed_aspect.png b/lib/matplotlib/tests/baseline_images/test_bbox_tight/bbox_inches_fixed_aspect.png new file mode 100644 index 0000000000000000000000000000000000000000..0fd7a35e3303ba3de632aec6a5a6bb65ca9d86bb GIT binary patch literal 5293 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 Date: Sat, 15 Oct 2022 13:59:54 +0200 Subject: [PATCH 055/262] Backport PR #24173: TST: convert nose-style tests --- lib/matplotlib/tests/test_cbook.py | 4 ++-- lib/matplotlib/tests/test_mlab.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index 26748d1a5798..b18f4fdf113a 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -51,7 +51,7 @@ def test_rgba(self): class Test_boxplot_stats: - def setup(self): + def setup_method(self): np.random.seed(937) self.nrows = 37 self.ncols = 4 @@ -177,7 +177,7 @@ def test_boxplot_stats_autorange_false(self): class Test_callback_registry: - def setup(self): + def setup_method(self): self.signal = 'test' self.callbacks = cbook.CallbackRegistry() diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 75ca0648a4e1..86beb5c8c803 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -97,7 +97,7 @@ def test_window(): class TestDetrend: - def setup(self): + def setup_method(self): np.random.seed(0) n = 1000 x = np.linspace(0., 100, n) From 9696aebb9da65ca5a3c23407bbab0b91c6753935 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sat, 15 Oct 2022 15:17:30 +0200 Subject: [PATCH 056/262] Backport PR #24177: Don't simplify paths used for autoscaling --- lib/matplotlib/axes/_base.py | 2 +- lib/matplotlib/tests/test_axes.py | 52 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 4f805e017741..056ff7ea2ced 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2434,7 +2434,7 @@ def _update_patch_limits(self, patch): # Get all vertices on the path # Loop through each segment to get extrema for Bezier curve sections vertices = [] - for curve, code in p.iter_bezier(): + for curve, code in p.iter_bezier(simplify=False): # Get distance along the curve of any extrema _, dzeros = curve.axis_aligned_extrema() # Calculate vertices of start, end and any extrema in between diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index c238009b0be1..573ea9863b58 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -8114,6 +8114,58 @@ def test_bezier_autoscale(): assert ax.get_ylim()[0] == -0.5 +def test_small_autoscale(): + # Check that paths with small values autoscale correctly #24097. + verts = np.array([ + [-5.45, 0.00], [-5.45, 0.00], [-5.29, 0.00], [-5.29, 0.00], + [-5.13, 0.00], [-5.13, 0.00], [-4.97, 0.00], [-4.97, 0.00], + [-4.81, 0.00], [-4.81, 0.00], [-4.65, 0.00], [-4.65, 0.00], + [-4.49, 0.00], [-4.49, 0.00], [-4.33, 0.00], [-4.33, 0.00], + [-4.17, 0.00], [-4.17, 0.00], [-4.01, 0.00], [-4.01, 0.00], + [-3.85, 0.00], [-3.85, 0.00], [-3.69, 0.00], [-3.69, 0.00], + [-3.53, 0.00], [-3.53, 0.00], [-3.37, 0.00], [-3.37, 0.00], + [-3.21, 0.00], [-3.21, 0.01], [-3.05, 0.01], [-3.05, 0.01], + [-2.89, 0.01], [-2.89, 0.01], [-2.73, 0.01], [-2.73, 0.02], + [-2.57, 0.02], [-2.57, 0.04], [-2.41, 0.04], [-2.41, 0.04], + [-2.25, 0.04], [-2.25, 0.06], [-2.09, 0.06], [-2.09, 0.08], + [-1.93, 0.08], [-1.93, 0.10], [-1.77, 0.10], [-1.77, 0.12], + [-1.61, 0.12], [-1.61, 0.14], [-1.45, 0.14], [-1.45, 0.17], + [-1.30, 0.17], [-1.30, 0.19], [-1.14, 0.19], [-1.14, 0.22], + [-0.98, 0.22], [-0.98, 0.25], [-0.82, 0.25], [-0.82, 0.27], + [-0.66, 0.27], [-0.66, 0.29], [-0.50, 0.29], [-0.50, 0.30], + [-0.34, 0.30], [-0.34, 0.32], [-0.18, 0.32], [-0.18, 0.33], + [-0.02, 0.33], [-0.02, 0.32], [0.13, 0.32], [0.13, 0.33], [0.29, 0.33], + [0.29, 0.31], [0.45, 0.31], [0.45, 0.30], [0.61, 0.30], [0.61, 0.28], + [0.77, 0.28], [0.77, 0.25], [0.93, 0.25], [0.93, 0.22], [1.09, 0.22], + [1.09, 0.19], [1.25, 0.19], [1.25, 0.17], [1.41, 0.17], [1.41, 0.15], + [1.57, 0.15], [1.57, 0.12], [1.73, 0.12], [1.73, 0.10], [1.89, 0.10], + [1.89, 0.08], [2.05, 0.08], [2.05, 0.07], [2.21, 0.07], [2.21, 0.05], + [2.37, 0.05], [2.37, 0.04], [2.53, 0.04], [2.53, 0.02], [2.69, 0.02], + [2.69, 0.02], [2.85, 0.02], [2.85, 0.01], [3.01, 0.01], [3.01, 0.01], + [3.17, 0.01], [3.17, 0.00], [3.33, 0.00], [3.33, 0.00], [3.49, 0.00], + [3.49, 0.00], [3.65, 0.00], [3.65, 0.00], [3.81, 0.00], [3.81, 0.00], + [3.97, 0.00], [3.97, 0.00], [4.13, 0.00], [4.13, 0.00], [4.29, 0.00], + [4.29, 0.00], [4.45, 0.00], [4.45, 0.00], [4.61, 0.00], [4.61, 0.00], + [4.77, 0.00], [4.77, 0.00], [4.93, 0.00], [4.93, 0.00], + ]) + + minx = np.min(verts[:, 0]) + miny = np.min(verts[:, 1]) + maxx = np.max(verts[:, 0]) + maxy = np.max(verts[:, 1]) + + p = mpath.Path(verts) + + fig, ax = plt.subplots() + ax.add_patch(mpatches.PathPatch(p)) + ax.autoscale() + + assert ax.get_xlim()[0] <= minx + assert ax.get_xlim()[1] >= maxx + assert ax.get_ylim()[0] <= miny + assert ax.get_ylim()[1] >= maxy + + def test_get_xticklabel(): fig, ax = plt.subplots() ax.plot(np.arange(10)) From 7ac315eac1f23cd991f13e3a4173c6f467e1b041 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 15 Oct 2022 16:35:24 +0200 Subject: [PATCH 057/262] Backport PR #24178: Fall back to Python-level Thread for GUI warning --- lib/matplotlib/pyplot.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index e5ae9a0cc11c..6f757ae031ef 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -332,11 +332,21 @@ def draw_if_interactive(): def _warn_if_gui_out_of_main_thread(): - # This compares native thread ids because even if python-level Thread - # objects match, the underlying OS thread (which is what really matters) - # may be different on Python implementations with green threads. - if (_get_required_interactive_framework(_get_backend_mod()) and - threading.get_native_id() != threading.main_thread().native_id): + warn = False + if _get_required_interactive_framework(_get_backend_mod()): + if hasattr(threading, 'get_native_id'): + # This compares native thread ids because even if Python-level + # Thread objects match, the underlying OS thread (which is what + # really matters) may be different on Python implementations with + # green threads. + if threading.get_native_id() != threading.main_thread().native_id: + warn = True + else: + # Fall back to Python-level Thread if native IDs are unavailable, + # mainly for PyPy. + if threading.current_thread() is not threading.main_thread(): + warn = True + if warn: _api.warn_external( "Starting a Matplotlib GUI outside of the main thread will likely " "fail.") From 8a8bde3f5411a69f3aab425bee973ef95315b583 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 16 Oct 2022 13:44:14 +0200 Subject: [PATCH 058/262] Backport PR #24157: test only PR milestoning guidance --- doc/devel/coding_guide.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/devel/coding_guide.rst b/doc/devel/coding_guide.rst index cddb13539444..b30e1dd95bab 100644 --- a/doc/devel/coding_guide.rst +++ b/doc/devel/coding_guide.rst @@ -136,11 +136,11 @@ Milestones * *New features and API changes* are milestoned for the next minor release ``v3.N.0``. - * *Bugfixes and docstring changes* are milestoned for the next patch - release ``v3.N.M`` + * *Bugfixes, tests for released code, and docstring changes* are milestoned + for the next patch release ``v3.N.M``. * *Documentation changes* (all .rst files and examples) are milestoned - ``v3.N-doc`` + ``v3.N-doc``. If multiple rules apply, choose the first matching from the above list. From eaec5f5e5a1ffc7c6ed33f14368e19847fb1240a Mon Sep 17 00:00:00 2001 From: hannah Date: Sun, 16 Oct 2022 15:00:44 -0400 Subject: [PATCH 059/262] Update coding_guide.rst fix doc build --- doc/devel/coding_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devel/coding_guide.rst b/doc/devel/coding_guide.rst index b30e1dd95bab..33062aa445f5 100644 --- a/doc/devel/coding_guide.rst +++ b/doc/devel/coding_guide.rst @@ -137,7 +137,7 @@ Milestones ``v3.N.0``. * *Bugfixes, tests for released code, and docstring changes* are milestoned - for the next patch release ``v3.N.M``. + for the next patch release ``v3.N.M``. * *Documentation changes* (all .rst files and examples) are milestoned ``v3.N-doc``. From 8ec9e27288aabd61d6ab1333621add658cbdfc2a Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 16 Oct 2022 22:36:46 +0200 Subject: [PATCH 060/262] Backport PR #24187: DOC: Fix toc structure in explain/interactive --- doc/users/explain/interactive.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/users/explain/interactive.rst b/doc/users/explain/interactive.rst index 0fb0a0cdac51..3488580a75a6 100644 --- a/doc/users/explain/interactive.rst +++ b/doc/users/explain/interactive.rst @@ -8,9 +8,6 @@ Interactive figures =================== -.. toctree:: - - When working with data, interactivity can be invaluable. The pan/zoom and mouse-location tools built into the Matplotlib GUI windows are often sufficient, but you can also use the event system to build customized data exploration tools. From 5aed3769ba0a54630f131cb3ad4aa702b19985f4 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 17 Oct 2022 17:00:11 +0200 Subject: [PATCH 061/262] Backport PR #24193: DOC: Explain gridsize in hexbin() --- lib/matplotlib/axes/_axes.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index a3acc5175b30..dad927831790 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4681,7 +4681,31 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None, the hexagons are approximately regular. Alternatively, if a tuple (*nx*, *ny*), the number of hexagons - in the *x*-direction and the *y*-direction. + in the *x*-direction and the *y*-direction. In the + *y*-direction, counting is done along vertically aligned + hexagons, not along the zig-zag chains of hexagons; see the + following illustration. + + .. plot:: + + import numpy + import matplotlib.pyplot as plt + + np.random.seed(19680801) + n= 300 + x = np.random.standard_normal(n) + y = np.random.standard_normal(n) + + fig, ax = plt.subplots(figsize=(4, 4)) + h = ax.hexbin(x, y, gridsize=(5, 3)) + hx, hy = h.get_offsets().T + ax.plot(hx[24::3], hy[24::3], 'ro-') + ax.plot(hx[-3:], hy[-3:], 'ro-') + ax.set_title('gridsize=(5, 3)') + ax.axis('off') + + To get approximately regular hexagons, choose + :math:`n_x = \\sqrt{3}\\,n_y`. bins : 'log' or int or sequence, default: None Discretization of the hexagon values. From 5c09db2c8507ffd9df9f3590b62865082eb03bfa Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 17 Oct 2022 17:09:23 +0200 Subject: [PATCH 062/262] Backport PR #24194: DOC: Improve plot_directive documentation --- lib/matplotlib/sphinxext/plot_directive.py | 38 ++++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/lib/matplotlib/sphinxext/plot_directive.py b/lib/matplotlib/sphinxext/plot_directive.py index c646f7a63e99..9973e37ef28f 100644 --- a/lib/matplotlib/sphinxext/plot_directive.py +++ b/lib/matplotlib/sphinxext/plot_directive.py @@ -2,10 +2,13 @@ A directive for including a Matplotlib plot in a Sphinx document ================================================================ -By default, in HTML output, `plot` will include a .png file with a link to a -high-res .png and .pdf. In LaTeX output, it will include a .pdf. +This is a Sphinx extension providing a reStructuredText directive +``.. plot::`` for including a plot in a Sphinx document. -The source code for the plot may be included in one of three ways: +In HTML output, ``.. plot::`` will include a .png file with a link +to a high-res .png and .pdf. In LaTeX output, it will include a .pdf. + +The plot content may be defined in one of three ways: 1. **A path to a source file** as the argument to the directive:: @@ -28,10 +31,8 @@ .. plot:: import matplotlib.pyplot as plt - import matplotlib.image as mpimg - import numpy as np - img = mpimg.imread('_static/stinkbug.png') - imgplot = plt.imshow(img) + plt.plot([1, 2, 3], [4, 5, 6]) + plt.title("A plotting exammple") 3. Using **doctest** syntax:: @@ -44,22 +45,22 @@ Options ------- -The ``plot`` directive supports the following options: +The ``.. plot::`` directive supports the following options: - format : {'python', 'doctest'} + ``:format:`` : {'python', 'doctest'} The format of the input. If unset, the format is auto-detected. - include-source : bool + ``:include-source:`` : bool Whether to display the source code. The default can be changed using - the `plot_include_source` variable in :file:`conf.py` (which itself + the ``plot_include_source`` variable in :file:`conf.py` (which itself defaults to False). - encoding : str + ``:encoding:`` : str If this source file is in a non-UTF8 or non-ASCII encoding, the encoding must be specified using the ``:encoding:`` option. The encoding will not be inferred using the ``-*- coding -*-`` metacomment. - context : bool or str + ``:context:`` : bool or str If provided, the code will be run in the context of all previous plot directives for which the ``:context:`` option was specified. This only applies to inline code plot directives, not those run from files. If @@ -68,18 +69,19 @@ running the code. ``:context: close-figs`` keeps the context but closes previous figures before running the code. - nofigs : bool + ``:nofigs:`` : bool If specified, the code block will be run, but no figures will be inserted. This is usually useful with the ``:context:`` option. - caption : str + ``:caption:`` : str If specified, the option's argument will be used as a caption for the figure. This overwrites the caption given in the content, when the plot is generated from a file. -Additionally, this directive supports all of the options of the `image` -directive, except for *target* (since plot will add its own target). These -include *alt*, *height*, *width*, *scale*, *align* and *class*. +Additionally, this directive supports all the options of the `image directive +`_, +except for ``:target:`` (since plot will add its own target). These include +``:alt:``, ``:height:``, ``:width:``, ``:scale:``, ``:align:`` and ``:class:``. Configuration options --------------------- From de5022d829dc5f80fef1f4e0ce80272ba36fbc39 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 4 Oct 2022 02:15:59 -0400 Subject: [PATCH 063/262] Backport PR #24081: TST: force test with shared test image to run in serial --- lib/matplotlib/tests/test_axes.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index c238009b0be1..4e7d5103e6ad 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -896,18 +896,14 @@ def test_hexbin_extent(): ax.hexbin("x", "y", extent=[.1, .3, .6, .7], data=data) -@image_comparison(['hexbin_empty.png'], remove_text=True) +@image_comparison(['hexbin_empty.png', 'hexbin_empty.png'], remove_text=True) def test_hexbin_empty(): # From #3886: creating hexbin from empty dataset raises ValueError - ax = plt.gca() + fig, ax = plt.subplots() ax.hexbin([], []) - - -@image_comparison(['hexbin_empty.png'], remove_text=True) -def test_hexbin_log_empty(): + fig, ax = plt.subplots() # From #23922: creating hexbin with log scaling from empty # dataset raises ValueError - ax = plt.gca() ax.hexbin([], [], bins='log') From a4dd6fd4fcb7a4c53812ce8252c06a6d2da8d2ff Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 18 Oct 2022 14:53:29 +0200 Subject: [PATCH 064/262] Backport PR #24202: Bump pypa/cibuildwheel from 2.10.2 to 2.11.1 --- .github/workflows/cibuildwheel.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 32d3e10fdd3b..503984768512 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -53,7 +53,7 @@ jobs: fetch-depth: 0 - name: Build wheels for CPython 3.11 - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BUILD: "cp311-*" CIBW_SKIP: "*-musllinux*" @@ -66,7 +66,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.10 - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BUILD: "cp310-*" CIBW_SKIP: "*-musllinux*" @@ -79,7 +79,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.9 - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BUILD: "cp39-*" CIBW_SKIP: "*-musllinux*" @@ -92,7 +92,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.8 - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BUILD: "cp38-*" CIBW_SKIP: "*-musllinux*" @@ -105,7 +105,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for PyPy - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BUILD: "pp38-* pp39-*" CIBW_SKIP: "*-musllinux*" From 907ba56048b495c053cd450c00f1bb281621b09f Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 18 Oct 2022 16:03:06 +0200 Subject: [PATCH 065/262] Backport PR #24169: [DOC]: added parent link for `FuncAnimation` and `ArtistAnimation` --- lib/matplotlib/animation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index b2eca10aae6f..428e00904277 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -1426,7 +1426,8 @@ def _step(self, *args): class ArtistAnimation(TimedAnimation): """ - Animation using a fixed set of `.Artist` objects. + `TimedAnimation` subclass that creates an animation by using a fixed + set of `.Artist` objects. Before creating an instance, all plotting should have taken place and the relevant artists saved. @@ -1502,7 +1503,8 @@ def _draw_frame(self, artists): class FuncAnimation(TimedAnimation): """ - Makes an animation by repeatedly calling a function *func*. + `TimedAnimation` subclass that makes an animation by repeatedly calling + a function *func*. .. note:: From dd6309a2d79ad9ceef09ae163d57d34736b491ac Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 19 Oct 2022 10:16:22 +0200 Subject: [PATCH 066/262] Backport PR #23995: DOC: Lowercase some parameter names --- lib/matplotlib/tests/test_triangulation.py | 18 +++++----- lib/matplotlib/tri/tricontour.py | 24 ++++++------- lib/matplotlib/tri/tripcolor.py | 42 +++++++++++----------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/lib/matplotlib/tests/test_triangulation.py b/lib/matplotlib/tests/test_triangulation.py index 75b2a51dfaf9..4738b53c5358 100644 --- a/lib/matplotlib/tests/test_triangulation.py +++ b/lib/matplotlib/tests/test_triangulation.py @@ -243,7 +243,7 @@ def test_tripcolor_color(): fig, ax = plt.subplots() with pytest.raises(TypeError, match=r"tripcolor\(\) missing 1 required "): ax.tripcolor(x, y) - with pytest.raises(ValueError, match="The length of C must match either"): + with pytest.raises(ValueError, match="The length of c must match either"): ax.tripcolor(x, y, [1, 2, 3]) with pytest.raises(ValueError, match="length of facecolors must match .* triangles"): @@ -255,7 +255,7 @@ def test_tripcolor_color(): match="'gouraud' .* at the points.* not at the faces"): ax.tripcolor(x, y, [1, 2], shading='gouraud') # faces with pytest.raises(TypeError, - match="positional.*'C'.*keyword-only.*'facecolors'"): + match="positional.*'c'.*keyword-only.*'facecolors'"): ax.tripcolor(x, y, C=[1, 2, 3, 4]) # smoke test for valid color specifications (via C or facecolors) @@ -278,16 +278,16 @@ def test_tripcolor_clim(): def test_tripcolor_warnings(): x = [-1, 0, 1, 0] y = [0, -1, 0, 1] - C = [0.4, 0.5] + c = [0.4, 0.5] fig, ax = plt.subplots() # additional parameters with pytest.warns(DeprecationWarning, match="Additional positional param"): - ax.tripcolor(x, y, C, 'unused_positional') - # facecolors takes precedence over C - with pytest.warns(UserWarning, match="Positional parameter C .*no effect"): - ax.tripcolor(x, y, C, facecolors=C) - with pytest.warns(UserWarning, match="Positional parameter C .*no effect"): - ax.tripcolor(x, y, 'interpreted as C', facecolors=C) + ax.tripcolor(x, y, c, 'unused_positional') + # facecolors takes precedence over c + with pytest.warns(UserWarning, match="Positional parameter c .*no effect"): + ax.tripcolor(x, y, c, facecolors=c) + with pytest.warns(UserWarning, match="Positional parameter c .*no effect"): + ax.tripcolor(x, y, 'interpreted as c', facecolors=c) def test_no_modify(): diff --git a/lib/matplotlib/tri/tricontour.py b/lib/matplotlib/tri/tricontour.py index ee9d85030c21..666626157517 100644 --- a/lib/matplotlib/tri/tricontour.py +++ b/lib/matplotlib/tri/tricontour.py @@ -83,8 +83,8 @@ def _contour_args(self, args, kwargs): Call signatures:: - %%(func)s(triangulation, Z, [levels], ...) - %%(func)s(x, y, Z, [levels], *, [triangles=triangles], [mask=mask], ...) + %%(func)s(triangulation, z, [levels], ...) + %%(func)s(x, y, z, [levels], *, [triangles=triangles], [mask=mask], ...) The triangular grid can be specified either by passing a `.Triangulation` object as the first parameter, or by passing the points *x*, *y* and @@ -93,7 +93,7 @@ def _contour_args(self, args, kwargs): *triangles* are given, the triangulation is calculated on the fly. It is possible to pass *triangles* positionally, i.e. -``%%(func)s(x, y, triangles, Z, ...)``. However, this is discouraged. For more +``%%(func)s(x, y, triangles, z, ...)``. However, this is discouraged. For more clarity, pass *triangles* via keyword argument. Parameters @@ -105,7 +105,7 @@ def _contour_args(self, args, kwargs): Parameters defining the triangular grid. See `.Triangulation`. This is mutually exclusive with specifying *triangulation*. -Z : array-like +z : array-like The height values over which the contour is drawn. Color-mapping is controlled by *cmap*, *norm*, *vmin*, and *vmax*. @@ -157,20 +157,20 @@ def _contour_args(self, args, kwargs): This parameter is ignored if *colors* is set. origin : {*None*, 'upper', 'lower', 'image'}, default: None - Determines the orientation and exact position of *Z* by specifying the - position of ``Z[0, 0]``. This is only relevant, if *X*, *Y* are not given. + Determines the orientation and exact position of *z* by specifying the + position of ``z[0, 0]``. This is only relevant, if *X*, *Y* are not given. - - *None*: ``Z[0, 0]`` is at X=0, Y=0 in the lower left corner. - - 'lower': ``Z[0, 0]`` is at X=0.5, Y=0.5 in the lower left corner. - - 'upper': ``Z[0, 0]`` is at X=N+0.5, Y=0.5 in the upper left corner. + - *None*: ``z[0, 0]`` is at X=0, Y=0 in the lower left corner. + - 'lower': ``z[0, 0]`` is at X=0.5, Y=0.5 in the lower left corner. + - 'upper': ``z[0, 0]`` is at X=N+0.5, Y=0.5 in the upper left corner. - 'image': Use the value from :rc:`image.origin`. extent : (x0, x1, y0, y1), optional If *origin* is not *None*, then *extent* is interpreted as in `.imshow`: it - gives the outer pixel boundaries. In this case, the position of Z[0, 0] is + gives the outer pixel boundaries. In this case, the position of z[0, 0] is the center of the pixel, not a corner. If *origin* is *None*, then - (*x0*, *y0*) is the position of Z[0, 0], and (*x1*, *y1*) is the position - of Z[-1, -1]. + (*x0*, *y0*) is the position of z[0, 0], and (*x1*, *y1*) is the position + of z[-1, -1]. This argument is ignored if *X* and *Y* are specified in the call to contour. diff --git a/lib/matplotlib/tri/tripcolor.py b/lib/matplotlib/tri/tripcolor.py index f0155d2a29e8..c4865a393f99 100644 --- a/lib/matplotlib/tri/tripcolor.py +++ b/lib/matplotlib/tri/tripcolor.py @@ -13,8 +13,8 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None, Call signatures:: - tripcolor(triangulation, C, *, ...) - tripcolor(x, y, C, *, [triangles=triangles], [mask=mask], ...) + tripcolor(triangulation, c, *, ...) + tripcolor(x, y, c, *, [triangles=triangles], [mask=mask], ...) The triangular grid can be specified either by passing a `.Triangulation` object as the first parameter, or by passing the points *x*, *y* and @@ -22,12 +22,12 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None, explanation of these parameters. It is possible to pass the triangles positionally, i.e. - ``tripcolor(x, y, triangles, C, ...)``. However, this is discouraged. + ``tripcolor(x, y, triangles, c, ...)``. However, this is discouraged. For more clarity, pass *triangles* via keyword argument. If neither of *triangulation* or *triangles* are given, the triangulation is calculated on the fly. In this case, it does not make sense to provide - colors at the triangle faces via *C* or *facecolors* because there are + colors at the triangle faces via *c* or *facecolors* because there are multiple possible triangulations for a group of points and you don't know which triangles will be constructed. @@ -38,21 +38,21 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None, x, y, triangles, mask Parameters defining the triangular grid. See `.Triangulation`. This is mutually exclusive with specifying *triangulation*. - C : array-like + c : array-like The color values, either for the points or for the triangles. Which one - is automatically inferred from the length of *C*, i.e. does it match + is automatically inferred from the length of *c*, i.e. does it match the number of points or the number of triangles. If there are the same number of points and triangles in the triangulation it is assumed that color values are defined at points; to force the use of color values at - triangles use the keyword argument ``facecolors=C`` instead of just - ``C``. + triangles use the keyword argument ``facecolors=c`` instead of just + ``c``. This parameter is position-only. facecolors : array-like, optional - Can be used alternatively to *C* to specify colors at the triangle - faces. This parameter takes precedence over *C*. + Can be used alternatively to *c* to specify colors at the triangle + faces. This parameter takes precedence over *c*. shading : {'flat', 'gouraud'}, default: 'flat' - If 'flat' and the color values *C* are defined at points, the color - values used for each triangle are from the mean C of the triangle's + If 'flat' and the color values *c* are defined at points, the color + values used for each triangle are from the mean c of the triangle's three points. If *shading* is 'gouraud' then color values must be defined at points. other_parameters @@ -68,34 +68,34 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None, if facecolors is not None: if args: _api.warn_external( - "Positional parameter C has no effect when the keyword " + "Positional parameter c has no effect when the keyword " "facecolors is given") point_colors = None if len(facecolors) != len(tri.triangles): raise ValueError("The length of facecolors must match the number " "of triangles") else: - # Color from positional parameter C + # Color from positional parameter c if not args: raise TypeError( - "tripcolor() missing 1 required positional argument: 'C'; or " + "tripcolor() missing 1 required positional argument: 'c'; or " "1 required keyword-only argument: 'facecolors'") elif len(args) > 1: _api.warn_deprecated( "3.6", message=f"Additional positional parameters " f"{args[1:]!r} are ignored; support for them is deprecated " f"since %(since)s and will be removed %(removal)s") - C = np.asarray(args[0]) - if len(C) == len(tri.x): + c = np.asarray(args[0]) + if len(c) == len(tri.x): # having this before the len(tri.triangles) comparison gives # precedence to nodes if there are as many nodes as triangles - point_colors = C + point_colors = c facecolors = None - elif len(C) == len(tri.triangles): + elif len(c) == len(tri.triangles): point_colors = None - facecolors = C + facecolors = c else: - raise ValueError('The length of C must match either the number ' + raise ValueError('The length of c must match either the number ' 'of points or the number of triangles') # Handling of linewidths, shading, edgecolors and antialiased as From cddc06669d6fbe2f12a43444457f68238dd42839 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 19 Oct 2022 03:54:52 -0400 Subject: [PATCH 067/262] Backport PR #24184: Add tests for ToolManager --- lib/matplotlib/backend_managers.py | 5 +- lib/matplotlib/tests/test_backend_bases.py | 54 ++++++++++++++++++++-- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/backend_managers.py b/lib/matplotlib/backend_managers.py index 7c3f7b92106f..e7dd748325e5 100644 --- a/lib/matplotlib/backend_managers.py +++ b/lib/matplotlib/backend_managers.py @@ -185,7 +185,7 @@ def update_keymap(self, name, key): Keys to associate with the tool. """ if name not in self._tools: - raise KeyError(f'{name} not in Tools') + raise KeyError(f'{name!r} not in Tools') self._remove_keys(name) if isinstance(key, str): key = [key] @@ -404,6 +404,7 @@ def get_tool(self, name, warn=True): return name if name not in self._tools: if warn: - _api.warn_external(f"ToolManager does not control tool {name}") + _api.warn_external( + f"ToolManager does not control tool {name!r}") return None return self._tools[name] diff --git a/lib/matplotlib/tests/test_backend_bases.py b/lib/matplotlib/tests/test_backend_bases.py index 231a3e044705..96d2f3afcd55 100644 --- a/lib/matplotlib/tests/test_backend_bases.py +++ b/lib/matplotlib/tests/test_backend_bases.py @@ -4,6 +4,7 @@ from matplotlib.backend_bases import ( FigureCanvasBase, LocationEvent, MouseButton, MouseEvent, NavigationToolbar2, RendererBase) +from matplotlib.backend_tools import RubberbandBase from matplotlib.figure import Figure from matplotlib.testing._markers import needs_pgf_xelatex import matplotlib.pyplot as plt @@ -12,6 +13,12 @@ import pytest +_EXPECTED_WARNING_TOOLMANAGER = ( + r"Treat the new Tool classes introduced in " + r"v[0-9]*.[0-9]* as experimental for now; " + "the API and rcParam may change in future versions.") + + def test_uses_per_path(): id = transforms.Affine2D() paths = [path.Path.unit_regular_polygon(i) for i in range(3, 7)] @@ -247,11 +254,7 @@ def test_interactive_colorbar(plot_func, orientation, tool, button, expected): def test_toolbar_zoompan(): - expected_warning_regex = ( - r"Treat the new Tool classes introduced in " - r"v[0-9]*.[0-9]* as experimental for now; " - "the API and rcParam may change in future versions.") - with pytest.warns(UserWarning, match=expected_warning_regex): + with pytest.warns(UserWarning, match=_EXPECTED_WARNING_TOOLMANAGER): plt.rcParams['toolbar'] = 'toolmanager' ax = plt.gca() assert ax.get_navigate_mode() is None @@ -349,3 +352,44 @@ def test_interactive_pan(key, mouseend, expectedxlim, expectedylim): # Should be close, but won't be exact due to screen integer resolution assert tuple(ax.get_xlim()) == pytest.approx(expectedxlim, abs=0.02) assert tuple(ax.get_ylim()) == pytest.approx(expectedylim, abs=0.02) + + +def test_toolmanager_remove(): + with pytest.warns(UserWarning, match=_EXPECTED_WARNING_TOOLMANAGER): + plt.rcParams['toolbar'] = 'toolmanager' + fig = plt.gcf() + initial_len = len(fig.canvas.manager.toolmanager.tools) + assert 'forward' in fig.canvas.manager.toolmanager.tools + fig.canvas.manager.toolmanager.remove_tool('forward') + assert len(fig.canvas.manager.toolmanager.tools) == initial_len - 1 + assert 'forward' not in fig.canvas.manager.toolmanager.tools + + +def test_toolmanager_get_tool(): + with pytest.warns(UserWarning, match=_EXPECTED_WARNING_TOOLMANAGER): + plt.rcParams['toolbar'] = 'toolmanager' + fig = plt.gcf() + rubberband = fig.canvas.manager.toolmanager.get_tool('rubberband') + assert isinstance(rubberband, RubberbandBase) + assert fig.canvas.manager.toolmanager.get_tool(rubberband) is rubberband + with pytest.warns(UserWarning, + match="ToolManager does not control tool 'foo'"): + assert fig.canvas.manager.toolmanager.get_tool('foo') is None + assert fig.canvas.manager.toolmanager.get_tool('foo', warn=False) is None + + with pytest.warns(UserWarning, + match="ToolManager does not control tool 'foo'"): + assert fig.canvas.manager.toolmanager.trigger_tool('foo') is None + + +def test_toolmanager_update_keymap(): + with pytest.warns(UserWarning, match=_EXPECTED_WARNING_TOOLMANAGER): + plt.rcParams['toolbar'] = 'toolmanager' + fig = plt.gcf() + assert 'v' in fig.canvas.manager.toolmanager.get_tool_keymap('forward') + with pytest.warns(UserWarning, + match="Key c changed from back to forward"): + fig.canvas.manager.toolmanager.update_keymap('forward', 'c') + assert fig.canvas.manager.toolmanager.get_tool_keymap('forward') == ['c'] + with pytest.raises(KeyError, match="'foo' not in Tools"): + fig.canvas.manager.toolmanager.update_keymap('foo', 'c') From db433b536760a007c2d9a45a2a929b2e346a9531 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 20 Oct 2022 22:51:23 +0200 Subject: [PATCH 068/262] Backport PR #24229: FIX: do not mutate dictionaries passed in by user --- lib/matplotlib/figure.py | 5 ++--- lib/matplotlib/tests/test_figure.py | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 1636e201019b..92377bd690ed 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -878,8 +878,7 @@ def subplots(self, nrows=1, ncols=1, *, sharex=False, sharey=False, # Note that this is the same as fig.subplots(2, 2, sharex=True, sharey=True) """ - if gridspec_kw is None: - gridspec_kw = {} + gridspec_kw = dict(gridspec_kw or {}) if height_ratios is not None: if 'height_ratios' in gridspec_kw: raise ValueError("'height_ratios' must not be defined both as " @@ -1869,7 +1868,7 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, """ subplot_kw = subplot_kw or {} - gridspec_kw = gridspec_kw or {} + gridspec_kw = dict(gridspec_kw or {}) if height_ratios is not None: if 'height_ratios' in gridspec_kw: raise ValueError("'height_ratios' must not be defined both as " diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 48b4a880e089..cc5a3b9ae2ff 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -1412,3 +1412,11 @@ def test_unpickle_with_device_pixel_ratio(): assert fig.dpi == 42*7 fig2 = pickle.loads(pickle.dumps(fig)) assert fig2.dpi == 42 + + +def test_gridspec_no_mutate_input(): + gs = {'left': .1} + gs_orig = dict(gs) + plt.subplots(1, 2, width_ratios=[1, 2], gridspec_kw=gs) + assert gs == gs_orig + plt.subplot_mosaic('AB', width_ratios=[1, 2], gridspec_kw=gs) From 0b05b1fa3a3d0fc6d5f9bea43dd708540f5afee1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 20 Oct 2022 17:51:04 -0400 Subject: [PATCH 069/262] Backport PR #24009: Fix evaluating colormaps on non-numpy arrays --- lib/matplotlib/colors.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 5441b0d617b5..f8a18443c9e0 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -706,8 +706,12 @@ def __call__(self, X, alpha=None, bytes=False): if not self._isinit: self._init() - mask_bad = X.mask if np.ma.is_masked(X) else np.isnan(X) # Mask nan's. + # Take the bad mask from a masked array, or in all other cases defer + # np.isnan() to after we have converted to an array. + mask_bad = X.mask if np.ma.is_masked(X) else None xa = np.array(X, copy=True) + if mask_bad is None: + mask_bad = np.isnan(xa) if not xa.dtype.isnative: xa = xa.byteswap().newbyteorder() # Native byteorder is faster. if xa.dtype.kind == "f": From 1ae9f8cb6fc5224400a54a18b522185de95116b9 Mon Sep 17 00:00:00 2001 From: Kostya Farber <73378227+kostyafarber@users.noreply.github.com> Date: Thu, 20 Oct 2022 22:55:28 +0100 Subject: [PATCH 070/262] Backport PR #24096: [DOC]: Add simple animation scatter plot to the example documentation --- examples/animation/simple_scatter.py | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 examples/animation/simple_scatter.py diff --git a/examples/animation/simple_scatter.py b/examples/animation/simple_scatter.py new file mode 100644 index 000000000000..1d18039dcf11 --- /dev/null +++ b/examples/animation/simple_scatter.py @@ -0,0 +1,31 @@ +""" +============================= +Animated scatter saved as GIF +============================= + +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +fig, ax = plt.subplots() +ax.set_xlim([0, 10]) + +scat = ax.scatter(1, 0) +x = np.linspace(0, 10) + + +def animate(i): + scat.set_offsets((x[i], 0)) + return scat, + +ani = animation.FuncAnimation(fig, animate, repeat=True, + frames=len(x) - 1, interval=50) + +# To save the animation using Pillow as a gif +# writer = animation.PillowWriter(fps=15, +# metadata=dict(artist='Me'), +# bitrate=1800) +# ani.save('scatter.gif', writer=writer) + +plt.show() From abe4054a4f64a300231432e91f4057be286312b4 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 20 Oct 2022 17:56:04 -0400 Subject: [PATCH 071/262] Backport PR #23985: Improve rubberband rendering in wx and tk --- lib/matplotlib/backends/_backend_tk.py | 30 +++++++++++++++++--------- lib/matplotlib/backends/backend_wx.py | 12 ++++++----- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 5d92e35469c2..7617d76e2591 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -212,7 +212,8 @@ def filter_destroy(event): self._tkcanvas.focus_set() - self._rubberband_rect = None + self._rubberband_rect_black = None + self._rubberband_rect_white = None def _update_device_pixel_ratio(self, event=None): # Tk gives scaling with respect to 72 DPI, but Windows screens are @@ -667,21 +668,30 @@ def set_message(self, s): def draw_rubberband(self, event, x0, y0, x1, y1): # Block copied from remove_rubberband for backend_tools convenience. - if self.canvas._rubberband_rect: - self.canvas._tkcanvas.delete(self.canvas._rubberband_rect) + if self.canvas._rubberband_rect_white: + self.canvas._tkcanvas.delete(self.canvas._rubberband_rect_white) + if self.canvas._rubberband_rect_black: + self.canvas._tkcanvas.delete(self.canvas._rubberband_rect_black) height = self.canvas.figure.bbox.height y0 = height - y0 y1 = height - y1 - self.canvas._rubberband_rect = self.canvas._tkcanvas.create_rectangle( - x0, y0, x1, y1) + self.canvas._rubberband_rect_black = ( + self.canvas._tkcanvas.create_rectangle( + x0, y0, x1, y1)) + self.canvas._rubberband_rect_white = ( + self.canvas._tkcanvas.create_rectangle( + x0, y0, x1, y1, outline='white', dash=(3, 3))) def remove_rubberband(self): - if self.canvas._rubberband_rect: - self.canvas._tkcanvas.delete(self.canvas._rubberband_rect) - self.canvas._rubberband_rect = None + if self.canvas._rubberband_rect_white: + self.canvas._tkcanvas.delete(self.canvas._rubberband_rect_white) + self.canvas._rubberband_rect_white = None + if self.canvas._rubberband_rect_black: + self.canvas._tkcanvas.delete(self.canvas._rubberband_rect_black) + self.canvas._rubberband_rect_black = None lastrect = _api.deprecated("3.6")( - property(lambda self: self.canvas._rubberband_rect)) + property(lambda self: self.canvas._rubberband_rect_black)) def _set_image_for_button(self, button): """ @@ -907,7 +917,7 @@ def remove_rubberband(self): self._make_classic_style_pseudo_toolbar()) lastrect = _api.deprecated("3.6")( - property(lambda self: self.figure.canvas._rubberband_rect)) + property(lambda self: self.figure.canvas._rubberband_rect_black)) @_api.deprecated("3.5", alternative="ToolSetCursor") diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 952dd27a3903..4d88547b865d 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -508,6 +508,8 @@ def __init__(self, parent, id, figure=None): _log.debug("%s - __init__() - bitmap w:%d h:%d", type(self), w, h) self._isDrawn = False self._rubberband_rect = None + self._rubberband_pen_black = wx.Pen('BLACK', 1, wx.PENSTYLE_SHORT_DASH) + self._rubberband_pen_white = wx.Pen('WHITE', 1, wx.PENSTYLE_SOLID) self.Bind(wx.EVT_SIZE, self._on_size) self.Bind(wx.EVT_PAINT, self._on_paint) @@ -625,11 +627,11 @@ def gui_repaint(self, drawDC=None): drawDC.DrawBitmap(bmp, 0, 0) if self._rubberband_rect is not None: # Some versions of wx+python don't support numpy.float64 here. - x0, y0, x1, y1 = map(int, self._rubberband_rect) - drawDC.DrawLineList( - [(x0, y0, x1, y0), (x1, y0, x1, y1), - (x0, y0, x0, y1), (x0, y1, x1, y1)], - wx.Pen('BLACK', 1, wx.PENSTYLE_SHORT_DASH)) + x0, y0, x1, y1 = map(round, self._rubberband_rect) + rect = [(x0, y0, x1, y0), (x1, y0, x1, y1), + (x0, y0, x0, y1), (x0, y1, x1, y1)] + drawDC.DrawLineList(rect, self._rubberband_pen_white) + drawDC.DrawLineList(rect, self._rubberband_pen_black) filetypes = { **FigureCanvasBase.filetypes, From 1ad20273a320378f825adc2fd93a5497aa9bd341 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 20 Oct 2022 18:44:37 -0400 Subject: [PATCH 072/262] Backport PR #23607: DOC: document that appearance is part of our stable API --- doc/devel/color_changes.rst | 3 ++- doc/devel/contributing.rst | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/devel/color_changes.rst b/doc/devel/color_changes.rst index 24aa15f29abf..f7646ded7c14 100644 --- a/doc/devel/color_changes.rst +++ b/doc/devel/color_changes.rst @@ -4,7 +4,8 @@ Default color changes ********************* -As discussed at length elsewhere [insert links], ``jet`` is an +As discussed at length `elsewhere `__ , +``jet`` is an empirically bad colormap and should not be the default colormap. Due to the position that changing the appearance of the plot breaks backward compatibility, this change has been put off for far longer diff --git a/doc/devel/contributing.rst b/doc/devel/contributing.rst index 2743424423d3..362cf09c5f7e 100644 --- a/doc/devel/contributing.rst +++ b/doc/devel/contributing.rst @@ -331,6 +331,12 @@ API consistency and stability are of great value. Therefore, API changes (e.g. signature changes, behavior changes, removals) will only be conducted if the added benefit is worth the user effort for adapting. +Because we are a visualization library our primary output is the final +visualization the user sees. Thus it is our :ref:`long standing +` policy that the appearance of the figure is part of the API +and any changes, either semantic or esthetic, will be treated as a +backwards-incompatible API change. + API changes in Matplotlib have to be performed following the deprecation process below, except in very rare circumstances as deemed necessary by the development team. This ensures that users are notified before the change will take effect and thus From 4b7d84aaacf25ceab897556aa23527224a6fdb86 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 21 Oct 2022 02:40:34 -0400 Subject: [PATCH 073/262] Backport PR #24197: Properly set and inherit backend_version. --- lib/matplotlib/backends/_backend_gtk.py | 13 +++++++------ lib/matplotlib/backends/_backend_tk.py | 4 +--- lib/matplotlib/backends/backend_agg.py | 4 +--- lib/matplotlib/backends/backend_cairo.py | 4 +--- lib/matplotlib/backends/backend_gtk3.py | 1 - lib/matplotlib/backends/backend_gtk4.py | 1 - lib/matplotlib/backends/backend_ps.py | 4 ++-- lib/matplotlib/backends/backend_qt.py | 3 +-- lib/matplotlib/backends/backend_qt5.py | 2 +- lib/matplotlib/backends/backend_qt5agg.py | 3 +-- lib/matplotlib/backends/backend_qtagg.py | 2 +- lib/matplotlib/backends/backend_svg.py | 3 ++- 12 files changed, 18 insertions(+), 26 deletions(-) diff --git a/lib/matplotlib/backends/_backend_gtk.py b/lib/matplotlib/backends/_backend_gtk.py index db5ca34cbf80..7eda5b924268 100644 --- a/lib/matplotlib/backends/_backend_gtk.py +++ b/lib/matplotlib/backends/_backend_gtk.py @@ -24,12 +24,7 @@ raise ImportError("Gtk-based backends require cairo") from e _log = logging.getLogger(__name__) - -backend_version = "%s.%s.%s" % ( - Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) - -# Placeholder -_application = None +_application = None # Placeholder def _shutdown_application(app): @@ -305,6 +300,12 @@ def trigger(self, *args): class _BackendGTK(_Backend): + backend_version = "%s.%s.%s" % ( + Gtk.get_major_version(), + Gtk.get_minor_version(), + Gtk.get_micro_version(), + ) + @staticmethod def mainloop(): global _application diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 7617d76e2591..2aec1440f6c6 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -24,9 +24,6 @@ _log = logging.getLogger(__name__) - -backend_version = tk.TkVersion - cursord = { cursors.MOVE: "fleur", cursors.HAND: "hand2", @@ -1027,6 +1024,7 @@ def trigger(self, *args): @_Backend.export class _BackendTk(_Backend): + backend_version = tk.TkVersion FigureManager = FigureManagerTk @staticmethod diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py index 0d8a127dba8c..8fda2606b472 100644 --- a/lib/matplotlib/backends/backend_agg.py +++ b/lib/matplotlib/backends/backend_agg.py @@ -40,9 +40,6 @@ from matplotlib.backends._backend_agg import RendererAgg as _RendererAgg -backend_version = 'v2.2' - - def get_hinting_flag(): mapping = { 'default': LOAD_DEFAULT, @@ -563,5 +560,6 @@ def print_webp(self, filename_or_obj, *, pil_kwargs=None): @_Backend.export class _BackendAgg(_Backend): + backend_version = 'v2.2' FigureCanvas = FigureCanvasAgg FigureManager = FigureManagerBase diff --git a/lib/matplotlib/backends/backend_cairo.py b/lib/matplotlib/backends/backend_cairo.py index 3a0c96c92fba..3d6cec641884 100644 --- a/lib/matplotlib/backends/backend_cairo.py +++ b/lib/matplotlib/backends/backend_cairo.py @@ -34,9 +34,6 @@ from matplotlib.transforms import Affine2D -backend_version = cairo.version - - def _append_path(ctx, path, transform, clip=None): for points, code in path.iter_segments( transform, remove_nans=True, clip=clip): @@ -548,5 +545,6 @@ def set_context(self, ctx): @_Backend.export class _BackendCairo(_Backend): + backend_version = cairo.version FigureCanvas = FigureCanvasCairo FigureManager = FigureManagerBase diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index 89e92690c7eb..cb1062cf157c 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -31,7 +31,6 @@ _BackendGTK, _FigureManagerGTK, _NavigationToolbar2GTK, TimerGTK as TimerGTK3, ) -from ._backend_gtk import backend_version # noqa: F401 # pylint: disable=W0611 _log = logging.getLogger(__name__) diff --git a/lib/matplotlib/backends/backend_gtk4.py b/lib/matplotlib/backends/backend_gtk4.py index 41b028e6620a..923787150a8d 100644 --- a/lib/matplotlib/backends/backend_gtk4.py +++ b/lib/matplotlib/backends/backend_gtk4.py @@ -28,7 +28,6 @@ _BackendGTK, _FigureManagerGTK, _NavigationToolbar2GTK, TimerGTK as TimerGTK4, ) -from ._backend_gtk import backend_version # noqa: F401 # pylint: disable=W0611 class FigureCanvasGTK4(FigureCanvasBase, Gtk.DrawingArea): diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index 67829c216f9a..629f0133ed52 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -33,9 +33,8 @@ from matplotlib.backends.backend_mixed import MixedModeRenderer from . import _backend_pdf_ps -_log = logging.getLogger(__name__) -backend_version = 'Level II' +_log = logging.getLogger(__name__) debugPS = False @@ -1364,4 +1363,5 @@ def pstoeps(tmpfile, bbox=None, rotated=False): @_Backend.export class _BackendPS(_Backend): + backend_version = 'Level II' FigureCanvas = FigureCanvasPS diff --git a/lib/matplotlib/backends/backend_qt.py b/lib/matplotlib/backends/backend_qt.py index b91446c4e632..2afff892ad2e 100644 --- a/lib/matplotlib/backends/backend_qt.py +++ b/lib/matplotlib/backends/backend_qt.py @@ -20,8 +20,6 @@ ) -backend_version = __version__ - # SPECIAL_KEYS are Qt::Key that do *not* return their Unicode name # instead they have manually specified names. SPECIAL_KEYS = { @@ -1013,6 +1011,7 @@ def trigger(self, *args, **kwargs): @_Backend.export class _BackendQT(_Backend): + backend_version = __version__ FigureCanvas = FigureCanvasQT FigureManager = FigureManagerQT diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 3c6b2c66a845..b6f643a34aa9 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -4,7 +4,7 @@ from .backend_qt import ( # noqa - backend_version, SPECIAL_KEYS, + SPECIAL_KEYS, # Public API cursord, _create_qApp, _BackendQT, TimerQT, MainWindow, FigureCanvasQT, FigureManagerQT, ToolbarQt, NavigationToolbar2QT, SubplotToolQt, diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py index c81fa6f6ccb3..8a92fd5135d5 100644 --- a/lib/matplotlib/backends/backend_qt5agg.py +++ b/lib/matplotlib/backends/backend_qt5agg.py @@ -6,8 +6,7 @@ backends._QT_FORCE_QT5_BINDING = True from .backend_qtagg import ( # noqa: F401, E402 # pylint: disable=W0611 _BackendQTAgg, FigureCanvasQTAgg, FigureManagerQT, NavigationToolbar2QT, - backend_version, FigureCanvasAgg, FigureCanvasQT -) + FigureCanvasAgg, FigureCanvasQT) @_BackendQTAgg.export diff --git a/lib/matplotlib/backends/backend_qtagg.py b/lib/matplotlib/backends/backend_qtagg.py index 7860c2b3e5ac..dde185107e98 100644 --- a/lib/matplotlib/backends/backend_qtagg.py +++ b/lib/matplotlib/backends/backend_qtagg.py @@ -11,7 +11,7 @@ from .backend_agg import FigureCanvasAgg from .backend_qt import QtCore, QtGui, _BackendQT, FigureCanvasQT from .backend_qt import ( # noqa: F401 # pylint: disable=W0611 - FigureManagerQT, NavigationToolbar2QT, backend_version) + FigureManagerQT, NavigationToolbar2QT) class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT): diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py index 738fe44c6f81..9a472899c193 100644 --- a/lib/matplotlib/backends/backend_svg.py +++ b/lib/matplotlib/backends/backend_svg.py @@ -24,9 +24,9 @@ from matplotlib import _path from matplotlib.transforms import Affine2D, Affine2DBase + _log = logging.getLogger(__name__) -backend_version = mpl.__version__ # ---------------------------------------------------------------------- # SimpleXMLWriter class @@ -1426,4 +1426,5 @@ def draw(self): @_Backend.export class _BackendSVG(_Backend): + backend_version = mpl.__version__ FigureCanvas = FigureCanvasSVG From 5c661e3691e53a572e576f08890ad19477e7014b Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 22 Oct 2022 16:13:17 +0200 Subject: [PATCH 074/262] Backport PR #24250: Fix key reporting in pick events --- lib/matplotlib/figure.py | 6 ++---- lib/matplotlib/tests/test_backend_bases.py | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 92377bd690ed..e879549167cd 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2443,10 +2443,6 @@ def __init__(self, # pickling. self._canvas_callbacks = cbook.CallbackRegistry( signals=FigureCanvasBase.events) - self._button_pick_id = self._canvas_callbacks._connect_picklable( - 'button_press_event', self.pick) - self._scroll_pick_id = self._canvas_callbacks._connect_picklable( - 'scroll_event', self.pick) connect = self._canvas_callbacks._connect_picklable self._mouse_key_ids = [ connect('key_press_event', backend_bases._key_handler), @@ -2457,6 +2453,8 @@ def __init__(self, connect('scroll_event', backend_bases._mouse_handler), connect('motion_notify_event', backend_bases._mouse_handler), ] + self._button_pick_id = connect('button_press_event', self.pick) + self._scroll_pick_id = connect('scroll_event', self.pick) if figsize is None: figsize = mpl.rcParams['figure.figsize'] diff --git a/lib/matplotlib/tests/test_backend_bases.py b/lib/matplotlib/tests/test_backend_bases.py index 96d2f3afcd55..4cbd1bc98b67 100644 --- a/lib/matplotlib/tests/test_backend_bases.py +++ b/lib/matplotlib/tests/test_backend_bases.py @@ -2,7 +2,7 @@ from matplotlib import path, transforms from matplotlib.backend_bases import ( - FigureCanvasBase, LocationEvent, MouseButton, MouseEvent, + FigureCanvasBase, KeyEvent, LocationEvent, MouseButton, MouseEvent, NavigationToolbar2, RendererBase) from matplotlib.backend_tools import RubberbandBase from matplotlib.figure import Figure @@ -124,12 +124,18 @@ def test_pick(): fig = plt.figure() fig.text(.5, .5, "hello", ha="center", va="center", picker=True) fig.canvas.draw() + picks = [] - fig.canvas.mpl_connect("pick_event", lambda event: picks.append(event)) - start_event = MouseEvent( - "button_press_event", fig.canvas, *fig.transFigure.transform((.5, .5)), - MouseButton.LEFT) - fig.canvas.callbacks.process(start_event.name, start_event) + def handle_pick(event): + assert event.mouseevent.key == "a" + picks.append(event) + fig.canvas.mpl_connect("pick_event", handle_pick) + + KeyEvent("key_press_event", fig.canvas, "a")._process() + MouseEvent("button_press_event", fig.canvas, + *fig.transFigure.transform((.5, .5)), + MouseButton.LEFT)._process() + KeyEvent("key_release_event", fig.canvas, "a")._process() assert len(picks) == 1 From 69cd562658f188b6f4861cb3c32f326055b641e7 Mon Sep 17 00:00:00 2001 From: hannah Date: Sun, 23 Oct 2022 13:35:57 -0400 Subject: [PATCH 075/262] Backport PR #24108: Add 3D plots to plot_types doc page --- doc/sphinxext/gallery_order.py | 1 + plot_types/3D/README.rst | 6 ++++++ plot_types/3D/scatter3d_simple.py | 29 ++++++++++++++++++++++++++ plot_types/3D/surface3d_simple.py | 29 ++++++++++++++++++++++++++ plot_types/3D/trisurf3d_simple.py | 34 +++++++++++++++++++++++++++++++ plot_types/3D/voxels_simple.py | 31 ++++++++++++++++++++++++++++ plot_types/3D/wire3d_simple.py | 24 ++++++++++++++++++++++ 7 files changed, 154 insertions(+) create mode 100644 plot_types/3D/README.rst create mode 100644 plot_types/3D/scatter3d_simple.py create mode 100644 plot_types/3D/surface3d_simple.py create mode 100644 plot_types/3D/trisurf3d_simple.py create mode 100644 plot_types/3D/voxels_simple.py create mode 100644 plot_types/3D/wire3d_simple.py diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py index 62b7803d0f8b..3632666d336e 100644 --- a/doc/sphinxext/gallery_order.py +++ b/doc/sphinxext/gallery_order.py @@ -28,6 +28,7 @@ '../plot_types/arrays', '../plot_types/stats', '../plot_types/unstructured', + '../plot_types/3D', ] diff --git a/plot_types/3D/README.rst b/plot_types/3D/README.rst new file mode 100644 index 000000000000..e7157d4ba628 --- /dev/null +++ b/plot_types/3D/README.rst @@ -0,0 +1,6 @@ +.. _3D_plots: + +3D +-- + +3D plots using the `mpl_toolkits.mplot3d` library. diff --git a/plot_types/3D/scatter3d_simple.py b/plot_types/3D/scatter3d_simple.py new file mode 100644 index 000000000000..023a46448ccf --- /dev/null +++ b/plot_types/3D/scatter3d_simple.py @@ -0,0 +1,29 @@ +""" +============== +3D scatterplot +============== + +See `~mpl_toolkits.mplot3d.axes3d.Axes3D.scatter`. +""" +import matplotlib.pyplot as plt +import numpy as np + +plt.style.use('_mpl-gallery') + +# Make data +np.random.seed(19680801) +n = 100 +rng = np.random.default_rng() +xs = rng.uniform(23, 32, n) +ys = rng.uniform(0, 100, n) +zs = rng.uniform(-50, -25, n) + +# Plot +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) +ax.scatter(xs, ys, zs) + +ax.set(xticklabels=[], + yticklabels=[], + zticklabels=[]) + +plt.show() diff --git a/plot_types/3D/surface3d_simple.py b/plot_types/3D/surface3d_simple.py new file mode 100644 index 000000000000..b1aff7d23b12 --- /dev/null +++ b/plot_types/3D/surface3d_simple.py @@ -0,0 +1,29 @@ +""" +===================== +3D surface +===================== + +See `~mpl_toolkits.mplot3d.axes3d.Axes3D.plot_surface`. +""" +import matplotlib.pyplot as plt +from matplotlib import cm +import numpy as np + +plt.style.use('_mpl-gallery') + +# Make data +X = np.arange(-5, 5, 0.25) +Y = np.arange(-5, 5, 0.25) +X, Y = np.meshgrid(X, Y) +R = np.sqrt(X**2 + Y**2) +Z = np.sin(R) + +# Plot the surface +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) +ax.plot_surface(X, Y, Z, vmin=Z.min() * 2, cmap=cm.Blues) + +ax.set(xticklabels=[], + yticklabels=[], + zticklabels=[]) + +plt.show() diff --git a/plot_types/3D/trisurf3d_simple.py b/plot_types/3D/trisurf3d_simple.py new file mode 100644 index 000000000000..92832c1b5b3a --- /dev/null +++ b/plot_types/3D/trisurf3d_simple.py @@ -0,0 +1,34 @@ +""" +====================== +Triangular 3D surfaces +====================== + +See `~mpl_toolkits.mplot3d.axes3d.Axes3D.plot_trisurf`. +""" +import matplotlib.pyplot as plt +from matplotlib import cm +import numpy as np + +plt.style.use('_mpl-gallery') + +n_radii = 8 +n_angles = 36 + +# Make radii and angles spaces +radii = np.linspace(0.125, 1.0, n_radii) +angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)[..., np.newaxis] + +# Convert polar (radii, angles) coords to cartesian (x, y) coords. +x = np.append(0, (radii*np.cos(angles)).flatten()) +y = np.append(0, (radii*np.sin(angles)).flatten()) +z = np.sin(-x*y) + +# Plot +fig, ax = plt.subplots(subplot_kw={'projection': '3d'}) +ax.plot_trisurf(x, y, z, vmin=z.min() * 2, cmap=cm.Blues) + +ax.set(xticklabels=[], + yticklabels=[], + zticklabels=[]) + +plt.show() diff --git a/plot_types/3D/voxels_simple.py b/plot_types/3D/voxels_simple.py new file mode 100644 index 000000000000..c3473e108969 --- /dev/null +++ b/plot_types/3D/voxels_simple.py @@ -0,0 +1,31 @@ +""" +========================== +3D voxel / volumetric plot +========================== + +See `~mpl_toolkits.mplot3d.axes3d.Axes3D.voxels`. +""" +import matplotlib.pyplot as plt +import numpy as np + +plt.style.use('_mpl-gallery') + +# Prepare some coordinates +x, y, z = np.indices((8, 8, 8)) + +# Draw cuboids in the top left and bottom right corners +cube1 = (x < 3) & (y < 3) & (z < 3) +cube2 = (x >= 5) & (y >= 5) & (z >= 5) + +# Combine the objects into a single boolean array +voxelarray = cube1 | cube2 + +# Plot +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) +ax.voxels(voxelarray, edgecolor='k') + +ax.set(xticklabels=[], + yticklabels=[], + zticklabels=[]) + +plt.show() diff --git a/plot_types/3D/wire3d_simple.py b/plot_types/3D/wire3d_simple.py new file mode 100644 index 000000000000..c0eaf40210e8 --- /dev/null +++ b/plot_types/3D/wire3d_simple.py @@ -0,0 +1,24 @@ +""" +================= +3D wireframe plot +================= + +See `~mpl_toolkits.mplot3d.axes3d.Axes3D.plot_wireframe`. +""" +from mpl_toolkits.mplot3d import axes3d +import matplotlib.pyplot as plt + +plt.style.use('_mpl-gallery') + +# Make data +X, Y, Z = axes3d.get_test_data(0.05) + +# Plot +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) +ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) + +ax.set(xticklabels=[], + yticklabels=[], + zticklabels=[]) + +plt.show() From f7e47ac7c77c1fe6cbe568b32c345d42bb3a596a Mon Sep 17 00:00:00 2001 From: Jae-Joon Lee Date: Tue, 25 Oct 2022 14:57:57 +0900 Subject: [PATCH 076/262] Backport PR #24261: Fix pie chart in demo_agg_filter.py --- examples/misc/demo_agg_filter.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/examples/misc/demo_agg_filter.py b/examples/misc/demo_agg_filter.py index d03b5ae2ae3c..0cdbf81f50b5 100644 --- a/examples/misc/demo_agg_filter.py +++ b/examples/misc/demo_agg_filter.py @@ -99,8 +99,19 @@ def process_image(self, padded_src, dpi): class LightFilter(BaseFilter): - - def __init__(self, sigma, fraction=0.5): + """Apply LightSource filter""" + + def __init__(self, sigma, fraction=1): + """ + Parameters + ---------- + sigma : float + sigma for gaussian filter + fraction: number, default: 1 + Increases or decreases the contrast of the hillshade. + See `matplotlib.colors.LightSource` + + """ self.gauss_filter = GaussianFilter(sigma, alpha=1) self.light_source = LightSource() self.fraction = fraction @@ -114,7 +125,8 @@ def process_image(self, padded_src, dpi): rgb = padded_src[:, :, :3] alpha = padded_src[:, :, 3:] rgb2 = self.light_source.shade_rgb(rgb, elevation, - fraction=self.fraction) + fraction=self.fraction, + blend_mode="overlay") return np.concatenate([rgb2, alpha], -1) @@ -257,7 +269,7 @@ def drop_shadow_patches(ax): def light_filter_pie(ax): fracs = [15, 30, 45, 10] - explode = (0, 0.05, 0, 0) + explode = (0.1, 0.2, 0.1, 0.1) pies = ax.pie(fracs, explode=explode) light_filter = LightFilter(9) @@ -267,7 +279,7 @@ def light_filter_pie(ax): p.set(ec="none", lw=2) - gauss = DropShadowFilter(9, offsets=(3, 4), alpha=0.7) + gauss = DropShadowFilter(9, offsets=(3, -4), alpha=0.7) shadow = FilteredArtistList(pies[0], gauss) ax.add_artist(shadow) shadow.set_zorder(pies[0][0].get_zorder() - 0.1) From 1f5dd1d716ee2d78f224022fe9bf98b52f25fa7c Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 25 Oct 2022 16:31:20 +0200 Subject: [PATCH 077/262] Backport PR #24265: Restore (and warn on) seaborn styles in style.library --- lib/matplotlib/style/core.py | 69 ++++++++++++++++++------------ lib/matplotlib/tests/test_style.py | 2 + 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py index fb0a5426e61d..16d8af38f659 100644 --- a/lib/matplotlib/style/core.py +++ b/lib/matplotlib/style/core.py @@ -43,6 +43,32 @@ class __getattr__: 'toolbar', 'timezone', 'figure.max_open_warning', 'figure.raise_window', 'savefig.directory', 'tk.window_focus', 'docstring.hardcopy', 'date.epoch'} +_DEPRECATED_SEABORN_STYLES = { + s: s.replace("seaborn", "seaborn-v0_8") + for s in [ + "seaborn", + "seaborn-bright", + "seaborn-colorblind", + "seaborn-dark", + "seaborn-darkgrid", + "seaborn-dark-palette", + "seaborn-deep", + "seaborn-muted", + "seaborn-notebook", + "seaborn-paper", + "seaborn-pastel", + "seaborn-poster", + "seaborn-talk", + "seaborn-ticks", + "seaborn-white", + "seaborn-whitegrid", + ] +} +_DEPRECATED_SEABORN_MSG = ( + "The seaborn styles shipped by Matplotlib are deprecated since %(since)s, " + "as they no longer correspond to the styles shipped by seaborn. However, " + "they will remain available as 'seaborn-v0_8- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index 5d761c9e9c21..3da06a7d27d0 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -8,7 +8,7 @@ assert_array_almost_equal, assert_array_almost_equal_nulp) import matplotlib as mpl from matplotlib.testing.decorators import image_comparison -from matplotlib import pyplot as plt, rc_context +from matplotlib import pyplot as plt, rc_context, ticker from matplotlib.colors import LogNorm, same_color import pytest @@ -155,6 +155,28 @@ def test_given_colors_levels_and_extends(): plt.colorbar(c, ax=ax) +@image_comparison(['contour_log_locator.svg'], style='mpl20', + remove_text=False) +def test_log_locator_levels(): + + fig, ax = plt.subplots() + + N = 100 + x = np.linspace(-3.0, 3.0, N) + y = np.linspace(-2.0, 2.0, N) + + X, Y = np.meshgrid(x, y) + + Z1 = np.exp(-X**2 - Y**2) + Z2 = np.exp(-(X * 10)**2 - (Y * 10)**2) + data = Z1 + 50 * Z2 + + c = ax.contourf(data, locator=ticker.LogLocator()) + assert_array_almost_equal(c.levels, np.power(10.0, np.arange(-6, 3))) + cb = fig.colorbar(c, ax=ax) + assert_array_almost_equal(cb.ax.get_yticks(), c.levels) + + @image_comparison(['contour_datetime_axis.png'], style='mpl20') def test_contour_datetime_axis(): fig = plt.figure() From 88a15373ec4fead581dea278dda5907ac5c0bca1 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 10 Jan 2023 21:42:41 -0500 Subject: [PATCH 198/262] Backport PR #23390: FIX: colorbar contour with log norm should default to log locator and formatter... --- lib/matplotlib/colorbar.py | 6 +- .../test_contour/contour_log_locator.svg | 3375 +++++++++++++++++ lib/matplotlib/tests/test_contour.py | 24 +- 3 files changed, 3403 insertions(+), 2 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_contour/contour_log_locator.svg diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 99c14245c7e3..8f0c1ff7b576 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -1167,7 +1167,11 @@ def _reset_locator_formatter_scale(self): self._minorlocator = None self._formatter = None self._minorformatter = None - if (self.boundaries is not None or + if (isinstance(self.mappable, contour.ContourSet) and + isinstance(self.norm, colors.LogNorm)): + # if contours have lognorm, give them a log scale... + self._set_scale('log') + elif (self.boundaries is not None or isinstance(self.norm, colors.BoundaryNorm)): if self.spacing == 'uniform': funcs = (self._forward_boundaries, self._inverse_boundaries) diff --git a/lib/matplotlib/tests/baseline_images/test_contour/contour_log_locator.svg b/lib/matplotlib/tests/baseline_images/test_contour/contour_log_locator.svg new file mode 100644 index 000000000000..a4a397104ef7 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_contour/contour_log_locator.svg @@ -0,0 +1,3375 @@ + + + + + + + + 2022-12-11T14:01:58.700972 + image/svg+xml + + + Matplotlib v3.6.0.dev2642+g907c10911d.d20221211, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index 8bf77f0d5470..90783990d50a 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -8,7 +8,7 @@ assert_array_almost_equal, assert_array_almost_equal_nulp) import matplotlib as mpl from matplotlib.testing.decorators import image_comparison -from matplotlib import pyplot as plt, rc_context +from matplotlib import pyplot as plt, rc_context, ticker from matplotlib.colors import LogNorm, same_color import pytest @@ -155,6 +155,28 @@ def test_given_colors_levels_and_extends(): plt.colorbar(c, ax=ax) +@image_comparison(['contour_log_locator.svg'], style='mpl20', + remove_text=False) +def test_log_locator_levels(): + + fig, ax = plt.subplots() + + N = 100 + x = np.linspace(-3.0, 3.0, N) + y = np.linspace(-2.0, 2.0, N) + + X, Y = np.meshgrid(x, y) + + Z1 = np.exp(-X**2 - Y**2) + Z2 = np.exp(-(X * 10)**2 - (Y * 10)**2) + data = Z1 + 50 * Z2 + + c = ax.contourf(data, locator=ticker.LogLocator()) + assert_array_almost_equal(c.levels, np.power(10.0, np.arange(-6, 3))) + cb = fig.colorbar(c, ax=ax) + assert_array_almost_equal(cb.ax.get_yticks(), c.levels) + + @image_comparison(['contour_datetime_axis.png'], style='mpl20') def test_contour_datetime_axis(): fig = plt.figure() From 73dde94e313ee3faea32e339dc64d0870e0429b3 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 11 Jan 2023 03:48:40 -0500 Subject: [PATCH 199/262] Backport PR #24655: Update font_manager to only use registry on Win --- doc/api/next_api_changes/behavior/24655-AK.rst | 15 +++++++++++++++ lib/matplotlib/font_manager.py | 17 ++++++----------- lib/matplotlib/tests/test_font_manager.py | 2 +- 3 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 doc/api/next_api_changes/behavior/24655-AK.rst diff --git a/doc/api/next_api_changes/behavior/24655-AK.rst b/doc/api/next_api_changes/behavior/24655-AK.rst new file mode 100644 index 000000000000..04b4141e4517 --- /dev/null +++ b/doc/api/next_api_changes/behavior/24655-AK.rst @@ -0,0 +1,15 @@ +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 +:doc:`/gallery/text_labels_and_annotations/font_file`. diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index c775a09136d6..8a4b52e96f32 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -186,16 +186,11 @@ def list_fonts(directory, extensions): recursively under the directory. """ extensions = ["." + ext for ext in extensions] - if sys.platform == 'win32' and directory == win32FontDirectory(): - return [os.path.join(directory, filename) - for filename in os.listdir(directory) - if os.path.isfile(os.path.join(directory, filename))] - else: - return [os.path.join(dirpath, filename) - # os.walk ignores access errors, unlike Path.glob. - for dirpath, _, filenames in os.walk(directory) - for filename in filenames - if Path(filename).suffix.lower() in extensions] + return [os.path.join(dirpath, filename) + # os.walk ignores access errors, unlike Path.glob. + for dirpath, _, filenames in os.walk(directory) + for filename in filenames + if Path(filename).suffix.lower() in extensions] def win32FontDirectory(): @@ -275,7 +270,7 @@ def findSystemFonts(fontpaths=None, fontext='ttf'): if fontpaths is None: if sys.platform == 'win32': installed_fonts = _get_win32_installed_fonts() - fontpaths = MSUserFontDirectories + [win32FontDirectory()] + fontpaths = [] else: installed_fonts = _get_fontconfig_fonts() if sys.platform == 'darwin': diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 6fd1097ce196..3724db1e1b43 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -200,7 +200,7 @@ def test_user_fonts_win32(): pytest.xfail("This test should only run on CI (appveyor or azure) " "as the developer's font directory should remain " "unchanged.") - + pytest.xfail("We need to update the registry for this test to work") font_test_file = 'mpltest.ttf' # Precondition: the test font should not be available From dc455fcd7a595ec319d02fdd3acd5e8bcdf5295e Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 11 Jan 2023 12:20:15 -0600 Subject: [PATCH 200/262] Backport PR #24940: [MNT] specify which gallery sections come last --- doc/sphinxext/gallery_order.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py index e839d10360f9..82c721f3c220 100644 --- a/doc/sphinxext/gallery_order.py +++ b/doc/sphinxext/gallery_order.py @@ -6,7 +6,7 @@ from sphinx_gallery.sorting import ExplicitOrder # Gallery sections shall be displayed in the following order. -# Non-matching sections are appended. +# Non-matching sections are inserted at UNSORTED explicit_order_folders = [ '../examples/lines_bars_and_markers', '../examples/images_contours_and_fields', @@ -29,6 +29,9 @@ '../plot_types/stats', '../plot_types/unstructured', '../plot_types/3D', + 'UNSORTED', + '../examples/userdemo', + '../tutorials/provisional', ] @@ -37,11 +40,9 @@ class MplExplicitOrder(ExplicitOrder): def __call__(self, item): """Return a string determining the sort order.""" if item in self.ordered_list: - return "{:04d}".format(self.ordered_list.index(item)) + return f"{self.ordered_list.index(item):04d}" else: - # ensure not explicitly listed items come last. - return "zzz" + item - + return f"{self.ordered_list.index('UNSORTED'):04d}{item}" # Subsection order: # Subsections are ordered by filename, unless they appear in the following From 91f3bc4e23d61f2bb52c8427772c8c84284d12e0 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 11 Jan 2023 15:07:34 -0500 Subject: [PATCH 201/262] DOC: fix tense in documentation --- examples/animation/animate_decay.py | 2 +- examples/animation/animated_histogram.py | 2 +- examples/animation/animation_demo.py | 2 +- examples/animation/bayes_update.py | 2 +- examples/animation/double_pendulum.py | 2 +- examples/animation/dynamic_image.py | 2 +- examples/animation/frame_grabbing_sgskip.py | 2 +- examples/animation/multiple_axes.py | 2 +- examples/animation/pause_resume.py | 2 +- examples/animation/rain.py | 2 +- examples/animation/random_walk.py | 2 +- examples/animation/simple_anim.py | 2 +- examples/animation/simple_scatter.py | 2 +- examples/animation/strip_chart.py | 2 +- examples/animation/unchained.py | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/animation/animate_decay.py b/examples/animation/animate_decay.py index a96dd2a5952a..cfd95e4e5c29 100644 --- a/examples/animation/animate_decay.py +++ b/examples/animation/animate_decay.py @@ -8,7 +8,7 @@ - using a generator to drive an animation, - changing axes limits during an animation. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import itertools diff --git a/examples/animation/animated_histogram.py b/examples/animation/animated_histogram.py index 254155b62a5e..3b242c4ce4cc 100644 --- a/examples/animation/animated_histogram.py +++ b/examples/animation/animated_histogram.py @@ -45,7 +45,7 @@ def animate(frame_number): # ``prepare_animation`` will define ``animate`` function working with supplied # `.BarContainer`, all this is used to setup `.FuncAnimation`. -# Output generate via `matplotlib.animation.Animation.to_jshtml`. +# Output generated via `matplotlib.animation.Animation.to_jshtml`. fig, ax = plt.subplots() _, _, bar_container = ax.hist(data, HIST_BINS, lw=1, diff --git a/examples/animation/animation_demo.py b/examples/animation/animation_demo.py index d9d0225ebb00..d2de7c43e7b5 100644 --- a/examples/animation/animation_demo.py +++ b/examples/animation/animation_demo.py @@ -11,7 +11,7 @@ Note that calling `time.sleep` instead of `~.pyplot.pause` would *not* work. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import matplotlib.pyplot as plt diff --git a/examples/animation/bayes_update.py b/examples/animation/bayes_update.py index 3874cef5aa9b..1b56b74f656a 100644 --- a/examples/animation/bayes_update.py +++ b/examples/animation/bayes_update.py @@ -8,7 +8,7 @@ The vertical line represents the theoretical value to which the plotted distribution should converge. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import math diff --git a/examples/animation/double_pendulum.py b/examples/animation/double_pendulum.py index 6009245d12df..8f055be79286 100644 --- a/examples/animation/double_pendulum.py +++ b/examples/animation/double_pendulum.py @@ -8,7 +8,7 @@ Double pendulum formula translated from the C code at http://www.physics.usyd.edu.au/~wheat/dpend_html/solve_dpend.c -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ from numpy import sin, cos diff --git a/examples/animation/dynamic_image.py b/examples/animation/dynamic_image.py index 41bc7e54e908..d74e8bc8c1a9 100644 --- a/examples/animation/dynamic_image.py +++ b/examples/animation/dynamic_image.py @@ -3,7 +3,7 @@ Animated image using a precomputed list of images ================================================= -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/frame_grabbing_sgskip.py b/examples/animation/frame_grabbing_sgskip.py index 1cdd47f0d70a..3a3d5d39c04d 100644 --- a/examples/animation/frame_grabbing_sgskip.py +++ b/examples/animation/frame_grabbing_sgskip.py @@ -7,7 +7,7 @@ file. This avoids any event loop integration, and thus works even with the Agg backend. This is not recommended for use in an interactive setting. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/multiple_axes.py b/examples/animation/multiple_axes.py index 4a45aa28ea8c..f3c246d151ac 100644 --- a/examples/animation/multiple_axes.py +++ b/examples/animation/multiple_axes.py @@ -8,7 +8,7 @@ - how animation across multiple subplots works, - using a figure artist in the animation. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/pause_resume.py b/examples/animation/pause_resume.py index 4f9dc3c39d99..4d6f281a7e0f 100644 --- a/examples/animation/pause_resume.py +++ b/examples/animation/pause_resume.py @@ -16,7 +16,7 @@ You can copy and paste individual parts, or download the entire example using the link at the bottom of the page. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import matplotlib.pyplot as plt diff --git a/examples/animation/rain.py b/examples/animation/rain.py index affa1d33867c..e5c2a467dbc0 100644 --- a/examples/animation/rain.py +++ b/examples/animation/rain.py @@ -8,7 +8,7 @@ Author: Nicolas P. Rougier -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/random_walk.py b/examples/animation/random_walk.py index e7e539f8884e..83cd530f6b42 100644 --- a/examples/animation/random_walk.py +++ b/examples/animation/random_walk.py @@ -3,7 +3,7 @@ Animated 3D random walk ======================= -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/simple_anim.py b/examples/animation/simple_anim.py index 4fe404521b7c..54480bc4ae6e 100644 --- a/examples/animation/simple_anim.py +++ b/examples/animation/simple_anim.py @@ -3,7 +3,7 @@ Animated line plot ================== -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/simple_scatter.py b/examples/animation/simple_scatter.py index c0bfa8bfa535..a0583c81e740 100644 --- a/examples/animation/simple_scatter.py +++ b/examples/animation/simple_scatter.py @@ -3,7 +3,7 @@ Animated scatter saved as GIF ============================= -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np import matplotlib.pyplot as plt diff --git a/examples/animation/strip_chart.py b/examples/animation/strip_chart.py index 77ea65b35fc2..9467ed3249b5 100644 --- a/examples/animation/strip_chart.py +++ b/examples/animation/strip_chart.py @@ -5,7 +5,7 @@ Emulates an oscilloscope. -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np diff --git a/examples/animation/unchained.py b/examples/animation/unchained.py index 8a241ebfd61c..3915f55dedd4 100644 --- a/examples/animation/unchained.py +++ b/examples/animation/unchained.py @@ -8,7 +8,7 @@ Author: Nicolas P. Rougier -Output generate via `matplotlib.animation.Animation.to_jshtml`. +Output generated via `matplotlib.animation.Animation.to_jshtml`. """ import numpy as np From 53e3c72064dca3c9cb44157bf3ef07b5cacaa278 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 11 Jan 2023 14:59:38 -0600 Subject: [PATCH 202/262] Backport PR #24918: DOC: animation faster --- tutorials/introductory/animation_tutorial.py | 37 +++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tutorials/introductory/animation_tutorial.py b/tutorials/introductory/animation_tutorial.py index 6f9a59e19071..a736580a36e4 100644 --- a/tutorials/introductory/animation_tutorial.py +++ b/tutorials/introductory/animation_tutorial.py @@ -87,32 +87,37 @@ # # Covering the set methods for all types of artists is beyond the scope of this # tutorial but can be found in their respective documentations. An example of -# such update methods in use for `.Axes.scatter` is as follows. - +# such update methods in use for `.Axes.scatter` and `.Axes.plot` is as follows. fig, ax = plt.subplots() -t = np.linspace(-np.pi, np.pi, 400) -a, b = 3, 2 -delta = np.pi / 2 +t = np.linspace(0, 3, 40) +g = -9.81 +v0 = 12 +z = g * t**2 / 2 + v0 * t + +v02 = 5 +z2 = g * t**2 / 2 + v02 * t -scat = ax.scatter(np.sin(a * t[0] + delta), np.sin(b * t[0]), c="b", s=2) -ax.set_xlim(-1.5, 1.5) -ax.set_ylim(-1.5, 1.5) +scat = ax.scatter(t[0], z[0], c="b", s=5, label=f'v0 = {v0} m/s') +line2 = ax.plot(t[0], z2[0], label=f'v0 = {v02} m/s')[0] +ax.set(xlim=[0, 3], ylim=[-4, 10], xlabel='Time [s]', ylabel='Z [m]') +ax.legend() def update(frame): - # .set_offsets replaces the offset data for the entire collection with - # the new values. Therefore, to also carry forward the previously - # calculated information, we use the data from the first to the current - # frame to set the new offsets. - x = np.sin(a * t[:frame] + delta) - y = np.sin(b * t[:frame]) + # for each frame, update the data stored on each artist. + x = t[:frame] + y = z[:frame] + # update the scatter plot: data = np.stack([x, y]).T scat.set_offsets(data) - return (scat,) + # update the line plot: + line2.set_xdata(t[:frame]) + line2.set_ydata(z2[:frame]) + return (scat, line2) -ani = animation.FuncAnimation(fig=fig, func=update, frames=400, interval=30) +ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=30) plt.show() From e45012855f26113068e22a535b68dbf32dddd0be Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 11 Jan 2023 16:02:09 -0500 Subject: [PATCH 203/262] DOC: Update GitHub stats for 3.6.3 --- doc/users/github_stats.rst | 272 +++++++++--------- .../prev_whats_new/github_stats_3.6.2.rst | 151 ++++++++++ 2 files changed, 294 insertions(+), 129 deletions(-) create mode 100644 doc/users/prev_whats_new/github_stats_3.6.2.rst diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index 3aa48834b0f3..d3dc01201d2f 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -1,154 +1,168 @@ .. _github-stats: -GitHub statistics for 3.6.2 (Nov 02, 2022) +GitHub statistics for 3.6.3 (Jan 11, 2023) ========================================== -GitHub statistics for 2022/10/08 (tag: v3.6.1) - 2022/11/02 +GitHub statistics for 2022/11/02 (tag: v3.6.2) - 2023/01/11 These lists are automatically generated, and may be incomplete or contain duplicates. -We closed 21 issues and merged 86 pull requests. -The full list can be seen `on GitHub `__ +We closed 16 issues and merged 107 pull requests. +The full list can be seen `on GitHub `__ -The following 22 authors contributed 27 commits. +The following 20 authors contributed 198 commits. * Antony Lee -* Carsten Schnober -* dependabot[bot] +* Chahak Mehta +* David Stansby * Elliott Sales de Andrade +* Eric Larson * hannah -* j1642 -* Jaco Verster -* jacoverster -* Jae-Joon Lee -* Jeffrey Aaron Paul -* jeffreypaul15 +* iofall * Jody Klymak -* Kostya Farber +* Kaidong Hu * Kyle Sunden -* Martok +* matt statham +* Matthias Bussonnier * Muhammad Abdur Rakib * Oscar Gustafsson -* Pavel Grunt +* ramvikrams * Ruth Comer +* Steffen Rehberg * Thomas A Caswell -* Tiger Nie * Tim Hoffmann +* yuanx749 GitHub issues and pull requests: -Pull Requests (86): - -* :ghpull:`24341`: Backport PR #24301 on branch v3.6.x (Restore get_renderer function in deprecated tight_layout) -* :ghpull:`24301`: Restore get_renderer function in deprecated tight_layout -* :ghpull:`24337`: Backport PR #24238 on branch v3.6.x (Update example and docstring to encourage the use of functools.partial in FuncAnimation) -* :ghpull:`24336`: Backport PR #24335 on branch v3.6.x (Fix missing word in ImageMagickWriter docstring.) -* :ghpull:`20358`: Updates example and docstring to encourage the use of functools.partial in FuncAnimation -* :ghpull:`24238`: Update example and docstring to encourage the use of functools.partial in FuncAnimation -* :ghpull:`24335`: Fix missing word in ImageMagickWriter docstring. -* :ghpull:`24330`: Backport PR #24282 on branch v3.6.x (Fix some minor docstring typos) -* :ghpull:`24323`: Backport PR #24320 on branch v3.6.x (DOC: add warning note to imsave) -* :ghpull:`24282`: Fix some minor docstring typos -* :ghpull:`24327`: Backport PR #24310 on branch v3.6.x (show axes changing in animate decay example) -* :ghpull:`24310`: show axes changing in animate decay example -* :ghpull:`24324`: Backport PR #24259 on branch v3.6.x (Move empty hexbin fix to make_norm_from_scale.) -* :ghpull:`24325`: Backport PR #24095 on branch v3.6.x (nb/webagg: Move mouse events to outer canvas div) -* :ghpull:`24326`: Backport PR #24318 on branch v3.6.x (Bump pypa/cibuildwheel from 2.11.1 to 2.11.2) -* :ghpull:`24318`: Bump pypa/cibuildwheel from 2.11.1 to 2.11.2 -* :ghpull:`24095`: nb/webagg: Move mouse events to outer canvas div -* :ghpull:`24259`: Move empty hexbin fix to make_norm_from_scale. -* :ghpull:`24320`: DOC: add warning note to imsave -* :ghpull:`24297`: Backport PR #24294 on branch v3.6.x (Run test if fontconfig is present) -* :ghpull:`24294`: Run test if fontconfig is present -* :ghpull:`24286`: Backport PR #24284 on branch v3.6.x (Remove comment about cmap from voxels docstring) -* :ghpull:`24284`: Remove comment about cmap from voxels docstring -* :ghpull:`24280`: Backport PR #24145 on branch v3.6.x (Updated Angles on Bracket arrow styles example to make angles clear #23176) -* :ghpull:`24145`: Updated Angles on Bracket arrow styles example to make angles clear #23176 -* :ghpull:`24270`: Backport PR #24265 on branch v3.6.x (Restore (and warn on) seaborn styles in style.library) -* :ghpull:`24271`: Backport PR #24266 on branch v3.6.x (TST: Increase fp tolerance on more tests for new NumPy) -* :ghpull:`24266`: TST: Increase fp tolerance on more tests for new NumPy -* :ghpull:`24265`: Restore (and warn on) seaborn styles in style.library -* :ghpull:`24267`: Backport PR #24261 on branch v3.6.x (Fix pie chart in demo_agg_filter.py) -* :ghpull:`24261`: Fix pie chart in demo_agg_filter.py -* :ghpull:`24258`: Backport PR #24108 on branch v3.6.x (Add 3D plots to plot_types doc page) -* :ghpull:`24108`: Add 3D plots to plot_types doc page -* :ghpull:`24255`: Backport PR #24250 on branch v3.6.x (Fix key reporting in pick events) -* :ghpull:`24250`: Fix key reporting in pick events -* :ghpull:`24237`: Backport PR #24197 on branch v3.6.x (Properly set and inherit backend_version.) -* :ghpull:`24197`: Properly set and inherit backend_version. -* :ghpull:`24234`: Backport PR #23607 on branch v3.6.x (DOC: document that appearance is part of our stable API) -* :ghpull:`24233`: Backport PR #23985 on branch v3.6.x (Improve rubberband rendering in wx and tk) -* :ghpull:`24232`: Backport PR #24096 on branch v3.6.x ([DOC]: Add simple animation scatter plot to the example documentation) -* :ghpull:`24231`: Backport PR #24009 on branch v3.6.x (Fix evaluating colormaps on non-numpy arrays) -* :ghpull:`24230`: Backport PR #24229 on branch v3.6.x (FIX: do not mutate dictionaries passed in by user) -* :ghpull:`23607`: DOC: document that appearance is part of our stable API -* :ghpull:`23985`: Improve rubberband rendering in wx and tk -* :ghpull:`24096`: [DOC]: Add simple animation scatter plot to the example documentation -* :ghpull:`24009`: Fix evaluating colormaps on non-numpy arrays -* :ghpull:`24229`: FIX: do not mutate dictionaries passed in by user -* :ghpull:`24223`: Backport PR #24184 on branch v3.6.x (Add tests for ToolManager) -* :ghpull:`24219`: Backport PR #23995 on branch v3.6.x (DOC: Lowercase some parameter names) -* :ghpull:`23995`: DOC: Lowercase some parameter names -* :ghpull:`24184`: Add tests for ToolManager -* :ghpull:`24211`: Backport PR #24202 on branch v3.6.x (Bump pypa/cibuildwheel from 2.10.2 to 2.11.1) -* :ghpull:`24214`: Backport PR #24169 on branch v3.6.x ([DOC]: added parent link for ``FuncAnimation`` and ``ArtistAnimation``) -* :ghpull:`24169`: [DOC]: add parent link for ``FuncAnimation`` and ``ArtistAnimation`` -* :ghpull:`24202`: Bump pypa/cibuildwheel from 2.10.2 to 2.11.1 -* :ghpull:`24206`: Backport PR #24081 on branch v3.6.x (TST: force test with shared test image to run in serial) -* :ghpull:`24181`: Backport PR #24177 on branch v3.6.x (Don't simplify paths used for autoscaling) -* :ghpull:`24200`: Backport PR #24193 on branch v3.6.x (DOC: Explain gridsize in hexbin()) -* :ghpull:`24201`: Backport PR #24194 on branch v3.6.x (DOC: Improve plot_directive documentation) -* :ghpull:`24194`: DOC: Improve plot_directive documentation -* :ghpull:`24193`: DOC: Explain gridsize in hexbin() -* :ghpull:`24192`: Backport PR #24187 on branch v3.6.x (DOC: Fix toc structure in explain/interactive) -* :ghpull:`24186`: Backport PR #24157 on branch v3.6.x (test only PR milestoning guidance) -* :ghpull:`24187`: DOC: Fix toc structure in explain/interactive -* :ghpull:`24190`: DOC: fix markup -* :ghpull:`24157`: test only PR milestoning guidance -* :ghpull:`24183`: Backport PR #24178 on branch v3.6.x (Fall back to Python-level Thread for GUI warning) -* :ghpull:`24180`: Backport PR #24173 on branch v3.6.x (TST: convert nose-style tests) -* :ghpull:`24178`: Fall back to Python-level Thread for GUI warning -* :ghpull:`24177`: Don't simplify paths used for autoscaling -* :ghpull:`24173`: TST: convert nose-style tests -* :ghpull:`24174`: Backport PR #24171 on branch v3.6.x (Fix example where wrong variable was used) -* :ghpull:`24176`: Backport PR #24167 on branch v3.6.x (FIX: turn off layout engine tightbbox) -* :ghpull:`24167`: FIX: turn off layout engine tightbbox -* :ghpull:`24171`: Fix example where wrong variable was used -* :ghpull:`24172`: Backport PR #24158 on branch v3.6.x (Fix Qt with PySide6 6.4.0) -* :ghpull:`24158`: Fix Qt with PySide6 6.4.0 -* :ghpull:`24165`: Backport PR #24164 on branch v3.6.x (Fix argument order in hist() docstring.) -* :ghpull:`24164`: Fix argument order in hist() docstring. -* :ghpull:`24151`: Backport PR #24149 on branch v3.6.x (FIX: handle input to ax.bar that is all nan) -* :ghpull:`24149`: FIX: handle input to ax.bar that is all nan -* :ghpull:`24146`: Backport PR #24137 on branch v3.6.x (Add note about blitting and zorder in animations) -* :ghpull:`24137`: Add note about blitting and zorder in animations -* :ghpull:`24134`: Backport PR #24130 on branch v3.6.x (DOC: align contour parameter doc with implementation) -* :ghpull:`24130`: DOC: align contour parameter doc with implementation -* :ghpull:`24081`: TST: force test with shared test image to run in serial - -Issues (21): - -* :ghissue:`20326`: FuncAnimation Named Arguments -* :ghissue:`24332`: [Bug]: backend bug in matplotlib==3.6.1 with python3.11 and PySide6==6.4.0.1 -* :ghissue:`24296`: [Doc]: Axes limits not updated in animate decay -* :ghissue:`24089`: [Bug]: Resizing does not work in WebAgg backend in Safari -* :ghissue:`3657`: matplotlib.pyplot.imsave colormaps some grayscale images before saving them -* :ghissue:`24060`: [TST] Upcoming dependency test failures -* :ghissue:`24264`: [Bug]: Setting matplotlib.pyplot.style.library['seaborn-colorblind'] result in key error on matplotlib v3.6.1 -* :ghissue:`23900`: [Doc]: Adding some 3D plots to plot gallery -* :ghissue:`24199`: [Bug]: pick events do not forward mouseevent-key on Linux -* :ghissue:`23969`: [ENH]: Make rubber band more visible -* :ghissue:`23132`: [Bug]: call cmap object on torch.tensor will output first element all 0 -* :ghissue:`21349`: [Bug]: Hexbin gridsize interpreted differently for x and y -* :ghissue:`22905`: [Doc]: Duplicated toc entries -* :ghissue:`24094`: [Bug]: macOS: PyPy 3.8 (v7.3.9) threading get_native_id Broken -* :ghissue:`24097`: [Bug]: ax.hist density not auto-scaled when using histtype='step' -* :ghissue:`24148`: remove nose-style test classes -* :ghissue:`24133`: [Bug]: Incorrect crop after constrained layout with equal aspect ratio and bbox_inches = tight -* :ghissue:`24155`: [Bug]: TypeError: int() argument must be a string, a bytes-like object or a number, not 'KeyboardModifier' -* :ghissue:`24127`: [Bug]: ax.bar raises for all-nan data on matplotlib 3.6.1 -* :ghissue:`2959`: artists zorder is ignored during animations -* :ghissue:`24121`: [Doc]: Contour functions: auto-generated levels +Pull Requests (107): + +* :ghpull:`24939`: Backport PR #23390 on branch v3.6.x (FIX: colorbar contour with log norm should default to log locator and formatter...) +* :ghpull:`24936`: Backport PR #24927 on branch v3.6.x (DOC: Remove space after directive name, before double-colon) +* :ghpull:`23390`: FIX: colorbar contour with log norm should default to log locator and formatter... +* :ghpull:`24932`: Backport PR #24783 on branch v3.6.x (inset locator fix with tests added) +* :ghpull:`24783`: inset locator fix with tests added +* :ghpull:`24927`: DOC: Remove space after directive name, before double-colon +* :ghpull:`24881`: Backport PR #24880 on branch v3.6.x (Minor cleanups to named colors example.) +* :ghpull:`24876`: Backport PR #24873 on branch v3.6.x (Copy-edit fonts docs.) +* :ghpull:`24857`: Backport PR #24856 on branch v3.6.x (fix typo) +* :ghpull:`24852`: Backport PR #24843 on branch v3.6.x (Show that fill_between and span_where provide similar functionalities.) +* :ghpull:`24808`: Backport PR #24807 on branch v3.6.x (Axes.stem docstring document orientation as literals) +* :ghpull:`24807`: Axes.stem docstring document orientation as literals +* :ghpull:`24791`: Backport PR #24785 on branch v3.6.x (Fix random generation of single floats) +* :ghpull:`24777`: Backport PR #24772 on branch v3.6.x (Fix Left ventricle bullseye example) +* :ghpull:`24775`: Backport PR #24774 on branch v3.6.x (DOC: fix strip_chart example with numpy 1.24) +* :ghpull:`24765`: Backport PR #24764 on branch v3.6.x (DOC: ``subplot_mosaic`` tutorial - clarify ratios keywords used directly) +* :ghpull:`24739`: Backport PR #24732 on branch v3.6.x (Use masked stack to preserve mask info) +* :ghpull:`24738`: Backport PR #24735 on branch v3.6.x (Correct note about aspect) +* :ghpull:`24732`: Use masked stack to preserve mask info +* :ghpull:`24735`: Correct note about aspect +* :ghpull:`24729`: Backport PR #24715 on branch v3.6.x (Add note that users do not instantiate Axes directly) +* :ghpull:`24715`: Add note that users do not instantiate Axes directly +* :ghpull:`24721`: Backport PR #24607 on branch v3.6.x (DOC: tweak wording on Figure.show warning) +* :ghpull:`24607`: DOC: tweak wording on Figure.show warning +* :ghpull:`24694`: Backport PR #24692 on branch v3.6.x (Avoid rgba8888->argb32 conversion if qt can do it for us.) +* :ghpull:`24692`: Avoid rgba8888->argb32 conversion if qt can do it for us. +* :ghpull:`24684`: Backport PR #24654: Don't manually invalidate cached lines in _update_transScale +* :ghpull:`24687`: Backport PR #24003 on branch v3.6.x (Fix wording and links lifecycle tutorial) +* :ghpull:`24685`: Backport PR #23974 on branch v3.6.x (Fix repeated word typos) +* :ghpull:`24680`: Backport PR #24677 on branch v3.6.x (FIX: do not replace the Axes._children list object) +* :ghpull:`24677`: FIX: do not replace the Axes._children list object +* :ghpull:`24659`: Backport PR #24657 on branch v3.6.x (BUG: Fix bug with mutable input modification) +* :ghpull:`24657`: BUG: Fix bug with mutable input modification +* :ghpull:`24654`: Don't manually invalidate cached lines in _update_transScale. +* :ghpull:`24650`: Backport PR #24645 on branch v3.6.x (Removed 'above' wording from Input hook integration docs (#24632)) +* :ghpull:`24647`: Backport PR #24643 on branch v3.6.x (DOC: annotation coords are not floats) +* :ghpull:`24643`: DOC: annotation coords are not floats +* :ghpull:`24625`: Backport PR #24606: FIX: do not use deprecated API in gtk4 backend +* :ghpull:`24633`: Backport PR #24592 on branch v3.6.x (DOC: Don't try to link paths that are on a different drive) +* :ghpull:`24592`: DOC: Don't try to link paths that are on a different drive +* :ghpull:`24628`: Backport PR #24584 on branch v3.6.x (DOC: add "See Also: draw_idle" reference to pyplot.draw) +* :ghpull:`24584`: DOC: add "See Also: draw_idle" reference to pyplot.draw +* :ghpull:`24601`: Backport PR #24600 on branch v3.6.x (Fix: Gracefully fail the string validator for tuple inputs) +* :ghpull:`24609`: Backport PR #24595 on branch v3.6.x (ci: Stop building wheels on AppVeyor) +* :ghpull:`24616`: Backport PR #24397 on branch v3.6.x (Simplify appveyor to only use conda) +* :ghpull:`24615`: Backport PR #24598 on branch v3.6.x (Check for errors/warnings on failed doc-builds) +* :ghpull:`24606`: FIX: do not use deprecated API in gtk4 backend +* :ghpull:`24612`: Backport PR #23868 on branch v3.6.x (Show errors and warnings in doc CI after build.) +* :ghpull:`24595`: ci: Stop building wheels on AppVeyor +* :ghpull:`24600`: Fix: Gracefully fail the string validator for tuple inputs +* :ghpull:`24593`: Backport PR #24580 on branch v3.6.x (Update the polar transform information in doc #24499) +* :ghpull:`24587`: Backport PR #24579: Add explicit permissions to GitHub Actions +* :ghpull:`24579`: Add explicit permissions to GitHub Actions +* :ghpull:`24561`: Backport PR #24540 on branch v3.6.x (DOC: add note about enabling c++11 support for old gcc) +* :ghpull:`24559`: Backport PR #24299 on branch v3.6.x (Rework style sheet reference example to cycle props) +* :ghpull:`24551`: Backport PR #24548 on branch v3.6.x (DOC: improved the doc for layout_engine.py) +* :ghpull:`24548`: DOC: improved the doc for layout_engine.py +* :ghpull:`24535`: Backport PR #24514 on branch v3.6.x (Fix potential issue in contour) +* :ghpull:`24534`: Backport PR #24521 on branch v3.6.x (Doc: improve spelling and grammar) +* :ghpull:`24533`: Backport PR #24517 on branch v3.6.x (DOC: improve grammar and consistency) +* :ghpull:`24532`: Backport PR #24520 on branch v3.6.x (Doc: Fix grammar and spelling) +* :ghpull:`24514`: Fix potential issue in contour +* :ghpull:`24521`: Doc: improve spelling and grammar +* :ghpull:`24517`: DOC: improve grammar and consistency +* :ghpull:`24520`: Doc: Fix grammar and spelling +* :ghpull:`24515`: Backport PR #24512 on branch v3.6.x (Tweak markup in toolkits tutorials.) +* :ghpull:`24503`: Backport PR #24502 on branch v3.6.x (Remove link from demo_floating_axes title.) +* :ghpull:`24505`: Backport PR #24482 on branch v3.6.x (Use relative frame path in HTMLWriter) +* :ghpull:`24506`: Backport of PR#24488 (Update for pydata-sphinx-theme 0.12.0) +* :ghpull:`24482`: Use relative frame path in HTMLWriter +* :ghpull:`24496`: Backport PR #24495 on branch v3.6.x (Update adding of google analytics key for docs) +* :ghpull:`24495`: Update adding of google analytics key for docs +* :ghpull:`24488`: Update for pydata-sphinx-theme 0.12.0 +* :ghpull:`24485`: Backport PR #24481 on branch v3.6.x (Fix floating-point drift in oscilloscope example) +* :ghpull:`24475`: DOC: Fix examples gallery layout issues +* :ghpull:`24478`: Backport PR #24444 on branch v3.6.x (DOC: AnnotationBbox keyword descriptions) +* :ghpull:`24444`: DOC: AnnotationBbox keyword descriptions +* :ghpull:`24468`: Backport PR #24429 on branch v3.6.x (DOC: Clarify transparency in colors) +* :ghpull:`24466`: Backport PR #24460 on branch v3.6.x (Define autoscale() based on autoscale_None().) +* :ghpull:`24460`: Define autoscale() based on autoscale_None(). +* :ghpull:`24463`: Backport PR #24459 on branch v3.6.x (removed unused variable and fixed text in doc) +* :ghpull:`24459`: removed unused variable and fixed text in doc +* :ghpull:`24458`: Backport PR #24434 on branch v3.6.x (Fix pyplot.figlegend docstring) +* :ghpull:`24434`: Fix pyplot.figlegend docstring +* :ghpull:`24456`: Backport PR #24402 on branch v3.6.x (DOC: Fix title formats in backend api docs) +* :ghpull:`24438`: Backport PR #24435 on branch v3.6.x (Minor improvements to LogLocator docstring) +* :ghpull:`24435`: Minor improvements to LogLocator docstring +* :ghpull:`24426`: Backport PR #24422 on branch v3.6.x (Make QT_API a link in the qt embedding example.) +* :ghpull:`24411`: Backport PR #24407 on branch v3.6.x (Reword "Reordering is not commutative" phrase in tutorial.) +* :ghpull:`24400`: Backport PR #24399 on branch v3.6.x (Fix docstring of Figure.subfigures.) +* :ghpull:`24399`: Fix docstring of Figure.subfigures. +* :ghpull:`24391`: Backport PR #24380 on branch v3.6.x (DOC: Remove the example "Pythonic Matplotlib") +* :ghpull:`24384`: Backport PR #24377 on branch v3.6.x (DOC: Cleanup Spine placement example) +* :ghpull:`24381`: Backport PR #24366 on branch v3.6.x (DOC: Improve Image Slices Viewer example) +* :ghpull:`24382`: Backport PR #24378 on branch v3.6.x (DOC: Cleanup spines usage in examples) +* :ghpull:`24378`: DOC: Cleanup spines usage in examples +* :ghpull:`24366`: DOC: Improve Image Slices Viewer example +* :ghpull:`24370`: Backport PR #24368 on branch v3.6.x (DOC: Install dev dependencies before building matplotlib) +* :ghpull:`24368`: DOC: Install dev dependencies before building matplotlib +* :ghpull:`24365`: Backport PR #24363 on branch v3.6.x (DOC: Fix syntax of suggestion) +* :ghpull:`24358`: Backport PR #24354 on branch v3.6.x (DOC: clarify rc_context resets all rcParams changes) +* :ghpull:`24354`: DOC: clarify rc_context resets all rcParams changes +* :ghpull:`24353`: Backport PR #24343 on branch v3.6.x (Emit "axes not compatible with tight_layout" in a single place.) +* :ghpull:`24343`: Emit "axes not compatible with tight_layout" in a single place. +* :ghpull:`24346`: Backport PR #24344 on branch v3.6.x (Add test for colorbar extend alpha) +* :ghpull:`24344`: Add test for colorbar extend alpha +* :ghpull:`23974`: Fix repeated word typos + +Issues (16): + +* :ghissue:`23389`: [Bug]: Colorbar with log scales wrong format +* :ghissue:`24589`: [Bug]: inset_locator is broken when used with subfigures +* :ghissue:`10160`: Low resolution (dpi problem) with Qt5 backend on new iMac Pro Retina +* :ghissue:`24545`: [Bug]: ``matplotlib.pyplot.scatter`` does not respect mask rules with ``datetime`` +* :ghissue:`24639`: [Bug]: The Axes3D does not work as expected. +* :ghissue:`22169`: [Doc]: figure.show works beyond what is documented +* :ghissue:`23968`: [Bug]: Zoom rubber band lags in larger window +* :ghissue:`24574`: [Bug]: Extension error (sphinx.ext.linkcode) while building docs +* :ghissue:`24602`: ``close_event`` deprecated warning. +* :ghissue:`24518`: [Doc]: ``layout_engine`` description +* :ghissue:`23581`: [BUG]: frame paths relative to the html file when saving an animation to html +* :ghissue:`23976`: [Doc]: Examples Gallery Layout changed to one or two columns +* :ghissue:`24390`: [Doc]: alpha setting for annotation ``TextArea`` +* :ghissue:`24433`: [Doc]: figlegend examples call ``fig.figlegend`` instead of ``plt.figlegend`` or ``fig.legend`` +* :ghissue:`24360`: [ENH]: imshow support for multiple slice image volume +* :ghissue:`24359`: [Bug]: Documentation not so clear that a C/C++-compiler is required to install from source Previous GitHub statistics diff --git a/doc/users/prev_whats_new/github_stats_3.6.2.rst b/doc/users/prev_whats_new/github_stats_3.6.2.rst new file mode 100644 index 000000000000..f633448aeaf1 --- /dev/null +++ b/doc/users/prev_whats_new/github_stats_3.6.2.rst @@ -0,0 +1,151 @@ +.. _github-stats-3-6-2: + +GitHub statistics for 3.6.2 (Nov 02, 2022) +========================================== + +GitHub statistics for 2022/10/08 (tag: v3.6.1) - 2022/11/02 + +These lists are automatically generated, and may be incomplete or contain duplicates. + +We closed 21 issues and merged 86 pull requests. +The full list can be seen `on GitHub `__ + +The following 22 authors contributed 27 commits. + +* Antony Lee +* Carsten Schnober +* dependabot[bot] +* Elliott Sales de Andrade +* hannah +* j1642 +* Jaco Verster +* jacoverster +* Jae-Joon Lee +* Jeffrey Aaron Paul +* jeffreypaul15 +* Jody Klymak +* Kostya Farber +* Kyle Sunden +* Martok +* Muhammad Abdur Rakib +* Oscar Gustafsson +* Pavel Grunt +* Ruth Comer +* Thomas A Caswell +* Tiger Nie +* Tim Hoffmann + +GitHub issues and pull requests: + +Pull Requests (86): + +* :ghpull:`24341`: Backport PR #24301 on branch v3.6.x (Restore get_renderer function in deprecated tight_layout) +* :ghpull:`24301`: Restore get_renderer function in deprecated tight_layout +* :ghpull:`24337`: Backport PR #24238 on branch v3.6.x (Update example and docstring to encourage the use of functools.partial in FuncAnimation) +* :ghpull:`24336`: Backport PR #24335 on branch v3.6.x (Fix missing word in ImageMagickWriter docstring.) +* :ghpull:`20358`: Updates example and docstring to encourage the use of functools.partial in FuncAnimation +* :ghpull:`24238`: Update example and docstring to encourage the use of functools.partial in FuncAnimation +* :ghpull:`24335`: Fix missing word in ImageMagickWriter docstring. +* :ghpull:`24330`: Backport PR #24282 on branch v3.6.x (Fix some minor docstring typos) +* :ghpull:`24323`: Backport PR #24320 on branch v3.6.x (DOC: add warning note to imsave) +* :ghpull:`24282`: Fix some minor docstring typos +* :ghpull:`24327`: Backport PR #24310 on branch v3.6.x (show axes changing in animate decay example) +* :ghpull:`24310`: show axes changing in animate decay example +* :ghpull:`24324`: Backport PR #24259 on branch v3.6.x (Move empty hexbin fix to make_norm_from_scale.) +* :ghpull:`24325`: Backport PR #24095 on branch v3.6.x (nb/webagg: Move mouse events to outer canvas div) +* :ghpull:`24326`: Backport PR #24318 on branch v3.6.x (Bump pypa/cibuildwheel from 2.11.1 to 2.11.2) +* :ghpull:`24318`: Bump pypa/cibuildwheel from 2.11.1 to 2.11.2 +* :ghpull:`24095`: nb/webagg: Move mouse events to outer canvas div +* :ghpull:`24259`: Move empty hexbin fix to make_norm_from_scale. +* :ghpull:`24320`: DOC: add warning note to imsave +* :ghpull:`24297`: Backport PR #24294 on branch v3.6.x (Run test if fontconfig is present) +* :ghpull:`24294`: Run test if fontconfig is present +* :ghpull:`24286`: Backport PR #24284 on branch v3.6.x (Remove comment about cmap from voxels docstring) +* :ghpull:`24284`: Remove comment about cmap from voxels docstring +* :ghpull:`24280`: Backport PR #24145 on branch v3.6.x (Updated Angles on Bracket arrow styles example to make angles clear #23176) +* :ghpull:`24145`: Updated Angles on Bracket arrow styles example to make angles clear #23176 +* :ghpull:`24270`: Backport PR #24265 on branch v3.6.x (Restore (and warn on) seaborn styles in style.library) +* :ghpull:`24271`: Backport PR #24266 on branch v3.6.x (TST: Increase fp tolerance on more tests for new NumPy) +* :ghpull:`24266`: TST: Increase fp tolerance on more tests for new NumPy +* :ghpull:`24265`: Restore (and warn on) seaborn styles in style.library +* :ghpull:`24267`: Backport PR #24261 on branch v3.6.x (Fix pie chart in demo_agg_filter.py) +* :ghpull:`24261`: Fix pie chart in demo_agg_filter.py +* :ghpull:`24258`: Backport PR #24108 on branch v3.6.x (Add 3D plots to plot_types doc page) +* :ghpull:`24108`: Add 3D plots to plot_types doc page +* :ghpull:`24255`: Backport PR #24250 on branch v3.6.x (Fix key reporting in pick events) +* :ghpull:`24250`: Fix key reporting in pick events +* :ghpull:`24237`: Backport PR #24197 on branch v3.6.x (Properly set and inherit backend_version.) +* :ghpull:`24197`: Properly set and inherit backend_version. +* :ghpull:`24234`: Backport PR #23607 on branch v3.6.x (DOC: document that appearance is part of our stable API) +* :ghpull:`24233`: Backport PR #23985 on branch v3.6.x (Improve rubberband rendering in wx and tk) +* :ghpull:`24232`: Backport PR #24096 on branch v3.6.x ([DOC]: Add simple animation scatter plot to the example documentation) +* :ghpull:`24231`: Backport PR #24009 on branch v3.6.x (Fix evaluating colormaps on non-numpy arrays) +* :ghpull:`24230`: Backport PR #24229 on branch v3.6.x (FIX: do not mutate dictionaries passed in by user) +* :ghpull:`23607`: DOC: document that appearance is part of our stable API +* :ghpull:`23985`: Improve rubberband rendering in wx and tk +* :ghpull:`24096`: [DOC]: Add simple animation scatter plot to the example documentation +* :ghpull:`24009`: Fix evaluating colormaps on non-numpy arrays +* :ghpull:`24229`: FIX: do not mutate dictionaries passed in by user +* :ghpull:`24223`: Backport PR #24184 on branch v3.6.x (Add tests for ToolManager) +* :ghpull:`24219`: Backport PR #23995 on branch v3.6.x (DOC: Lowercase some parameter names) +* :ghpull:`23995`: DOC: Lowercase some parameter names +* :ghpull:`24184`: Add tests for ToolManager +* :ghpull:`24211`: Backport PR #24202 on branch v3.6.x (Bump pypa/cibuildwheel from 2.10.2 to 2.11.1) +* :ghpull:`24214`: Backport PR #24169 on branch v3.6.x ([DOC]: added parent link for ``FuncAnimation`` and ``ArtistAnimation``) +* :ghpull:`24169`: [DOC]: add parent link for ``FuncAnimation`` and ``ArtistAnimation`` +* :ghpull:`24202`: Bump pypa/cibuildwheel from 2.10.2 to 2.11.1 +* :ghpull:`24206`: Backport PR #24081 on branch v3.6.x (TST: force test with shared test image to run in serial) +* :ghpull:`24181`: Backport PR #24177 on branch v3.6.x (Don't simplify paths used for autoscaling) +* :ghpull:`24200`: Backport PR #24193 on branch v3.6.x (DOC: Explain gridsize in hexbin()) +* :ghpull:`24201`: Backport PR #24194 on branch v3.6.x (DOC: Improve plot_directive documentation) +* :ghpull:`24194`: DOC: Improve plot_directive documentation +* :ghpull:`24193`: DOC: Explain gridsize in hexbin() +* :ghpull:`24192`: Backport PR #24187 on branch v3.6.x (DOC: Fix toc structure in explain/interactive) +* :ghpull:`24186`: Backport PR #24157 on branch v3.6.x (test only PR milestoning guidance) +* :ghpull:`24187`: DOC: Fix toc structure in explain/interactive +* :ghpull:`24190`: DOC: fix markup +* :ghpull:`24157`: test only PR milestoning guidance +* :ghpull:`24183`: Backport PR #24178 on branch v3.6.x (Fall back to Python-level Thread for GUI warning) +* :ghpull:`24180`: Backport PR #24173 on branch v3.6.x (TST: convert nose-style tests) +* :ghpull:`24178`: Fall back to Python-level Thread for GUI warning +* :ghpull:`24177`: Don't simplify paths used for autoscaling +* :ghpull:`24173`: TST: convert nose-style tests +* :ghpull:`24174`: Backport PR #24171 on branch v3.6.x (Fix example where wrong variable was used) +* :ghpull:`24176`: Backport PR #24167 on branch v3.6.x (FIX: turn off layout engine tightbbox) +* :ghpull:`24167`: FIX: turn off layout engine tightbbox +* :ghpull:`24171`: Fix example where wrong variable was used +* :ghpull:`24172`: Backport PR #24158 on branch v3.6.x (Fix Qt with PySide6 6.4.0) +* :ghpull:`24158`: Fix Qt with PySide6 6.4.0 +* :ghpull:`24165`: Backport PR #24164 on branch v3.6.x (Fix argument order in hist() docstring.) +* :ghpull:`24164`: Fix argument order in hist() docstring. +* :ghpull:`24151`: Backport PR #24149 on branch v3.6.x (FIX: handle input to ax.bar that is all nan) +* :ghpull:`24149`: FIX: handle input to ax.bar that is all nan +* :ghpull:`24146`: Backport PR #24137 on branch v3.6.x (Add note about blitting and zorder in animations) +* :ghpull:`24137`: Add note about blitting and zorder in animations +* :ghpull:`24134`: Backport PR #24130 on branch v3.6.x (DOC: align contour parameter doc with implementation) +* :ghpull:`24130`: DOC: align contour parameter doc with implementation +* :ghpull:`24081`: TST: force test with shared test image to run in serial + +Issues (21): + +* :ghissue:`20326`: FuncAnimation Named Arguments +* :ghissue:`24332`: [Bug]: backend bug in matplotlib==3.6.1 with python3.11 and PySide6==6.4.0.1 +* :ghissue:`24296`: [Doc]: Axes limits not updated in animate decay +* :ghissue:`24089`: [Bug]: Resizing does not work in WebAgg backend in Safari +* :ghissue:`3657`: matplotlib.pyplot.imsave colormaps some grayscale images before saving them +* :ghissue:`24060`: [TST] Upcoming dependency test failures +* :ghissue:`24264`: [Bug]: Setting matplotlib.pyplot.style.library['seaborn-colorblind'] result in key error on matplotlib v3.6.1 +* :ghissue:`23900`: [Doc]: Adding some 3D plots to plot gallery +* :ghissue:`24199`: [Bug]: pick events do not forward mouseevent-key on Linux +* :ghissue:`23969`: [ENH]: Make rubber band more visible +* :ghissue:`23132`: [Bug]: call cmap object on torch.tensor will output first element all 0 +* :ghissue:`21349`: [Bug]: Hexbin gridsize interpreted differently for x and y +* :ghissue:`22905`: [Doc]: Duplicated toc entries +* :ghissue:`24094`: [Bug]: macOS: PyPy 3.8 (v7.3.9) threading get_native_id Broken +* :ghissue:`24097`: [Bug]: ax.hist density not auto-scaled when using histtype='step' +* :ghissue:`24148`: remove nose-style test classes +* :ghissue:`24133`: [Bug]: Incorrect crop after constrained layout with equal aspect ratio and bbox_inches = tight +* :ghissue:`24155`: [Bug]: TypeError: int() argument must be a string, a bytes-like object or a number, not 'KeyboardModifier' +* :ghissue:`24127`: [Bug]: ax.bar raises for all-nan data on matplotlib 3.6.1 +* :ghissue:`2959`: artists zorder is ignored during animations +* :ghissue:`24121`: [Doc]: Contour functions: auto-generated levels From abcbf3d11524fa53b08243bc0aa85dd942439454 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 11 Jan 2023 16:59:52 -0500 Subject: [PATCH 204/262] DOC: Update switcher versions --- doc/_static/switcher.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/_static/switcher.json b/doc/_static/switcher.json index 53ca35b763bc..3a0636e13056 100644 --- a/doc/_static/switcher.json +++ b/doc/_static/switcher.json @@ -1,6 +1,6 @@ [ { - "name": "3.6.2 (stable)", + "name": "3.6.3 (stable)", "version": "stable", "url": "https://matplotlib.org/stable/" }, From c23ccdde6f0f8c071b09a88770e24452f2859e99 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 11 Jan 2023 17:29:27 -0500 Subject: [PATCH 205/262] REL: v3.6.3 This is the third bugfix release of the 3.6.x series. This release contains several bug-fixes and adjustments: * Fix Artist removal from `axes_grid1` Axes classes * Fix `inset_locator` in subfigures * Fix `scatter` on masked arrays with units * Fix colorbar ticks with log norm contours * Fix deprecation warnings in GTK4 backend * Fix using relative paths in `HTMLWriter` * Improve failure message from rcParams string validation for tuple inputs * Improve performance of QtAgg backends * No longer modify `pil_kwargs` argument to `imsave` and `savefig` From dbbd55546790ebc1fcab522843a494424e0fca76 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 11 Jan 2023 17:45:01 -0500 Subject: [PATCH 206/262] BLD: bump branch away from tag So the tarballs from GitHub are stable. From 11878dd10289356dfca9b33fd753022f6eb3944c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 11 Jan 2023 21:27:59 -0500 Subject: [PATCH 207/262] DOC: Add Zenodo DOI for 3.6.3 --- doc/_static/zenodo_cache/7527665.svg | 35 ++++++++++++++++++++++++++++ doc/users/project/citing.rst | 3 +++ tools/cache_zenodo_svg.py | 1 + 3 files changed, 39 insertions(+) create mode 100644 doc/_static/zenodo_cache/7527665.svg diff --git a/doc/_static/zenodo_cache/7527665.svg b/doc/_static/zenodo_cache/7527665.svg new file mode 100644 index 000000000000..3c3e0b7a8b2a --- /dev/null +++ b/doc/_static/zenodo_cache/7527665.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + DOI + + + DOI + + + 10.5281/zenodo.7527665 + + + 10.5281/zenodo.7527665 + + + \ No newline at end of file diff --git a/doc/users/project/citing.rst b/doc/users/project/citing.rst index b36562014b23..74f9fe13b56f 100644 --- a/doc/users/project/citing.rst +++ b/doc/users/project/citing.rst @@ -29,6 +29,9 @@ By version .. START OF AUTOGENERATED +v3.6.3 + .. image:: ../../_static/zenodo_cache/7527665.svg + :target: https://doi.org/10.5281/zenodo.7527665 v3.6.2 .. image:: ../../_static/zenodo_cache/7275322.svg :target: https://doi.org/10.5281/zenodo.7275322 diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py index 88355ddf9be9..8a3c0450d626 100644 --- a/tools/cache_zenodo_svg.py +++ b/tools/cache_zenodo_svg.py @@ -63,6 +63,7 @@ def _get_xdg_cache_dir(): if __name__ == "__main__": data = { + "v3.6.3": "7527665", "v3.6.2": "7275322", "v3.6.1": "7162185", "v3.6.0": "7084615", From 655f616e86e2c0f7724d7c88717d4ac4eb438c57 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 12 Jan 2023 04:44:59 -0500 Subject: [PATCH 208/262] Add missing 3.6.2 GitHub stats to release notes --- doc/users/release_notes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst index 8e4d8c1d3e63..cd60add5fef1 100644 --- a/doc/users/release_notes.rst +++ b/doc/users/release_notes.rst @@ -18,6 +18,7 @@ Version 3.6 ../api/prev_api_changes/api_changes_3.6.1.rst ../api/prev_api_changes/api_changes_3.6.0.rst github_stats.rst + prev_whats_new/github_stats_3.6.2.rst prev_whats_new/github_stats_3.6.1.rst prev_whats_new/github_stats_3.6.0.rst From 0d39834ce0c1d579703672e3890b42806eda2121 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 12 Jan 2023 16:56:16 +0100 Subject: [PATCH 209/262] Backport PR #24955: Cleanup bullseye plot example. --- ...e_bulleye.py => leftventricle_bullseye.py} | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) rename examples/specialty_plots/{leftventricle_bulleye.py => leftventricle_bullseye.py} (88%) diff --git a/examples/specialty_plots/leftventricle_bulleye.py b/examples/specialty_plots/leftventricle_bullseye.py similarity index 88% rename from examples/specialty_plots/leftventricle_bulleye.py rename to examples/specialty_plots/leftventricle_bullseye.py index c0deecd6fd5c..169c08447ad1 100644 --- a/examples/specialty_plots/leftventricle_bulleye.py +++ b/examples/specialty_plots/leftventricle_bullseye.py @@ -5,6 +5,8 @@ This example demonstrates how to create the 17 segment model for the left ventricle recommended by the American Heart Association (AHA). + +.. redirect-from:: /gallery/specialty_plots/leftventricle_bulleye """ import numpy as np @@ -135,15 +137,11 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None): # Make a figure and axes with dimensions as desired. -fig, ax = plt.subplots(figsize=(12, 8), nrows=1, ncols=3, - subplot_kw=dict(projection='polar')) +fig = plt.figure(figsize=(10, 5), layout="constrained") +fig.get_layout_engine().set(wspace=.1, w_pad=.2) +axs = fig.subplots(1, 3, subplot_kw=dict(projection='polar')) fig.canvas.manager.set_window_title('Left Ventricle Bulls Eyes (AHA)') -# Create the axis for the colorbars -axl = fig.add_axes([0.14, 0.15, 0.2, 0.05]) -axl2 = fig.add_axes([0.41, 0.15, 0.2, 0.05]) -axl3 = fig.add_axes([0.69, 0.15, 0.2, 0.05]) - # Set the colormap and norm to correspond to the data for which # the colorbar will be used. @@ -152,14 +150,16 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None): # Create an empty ScalarMappable to set the colorbar's colormap and norm. # The following gives a basic continuous colorbar with ticks and labels. fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm), - cax=axl, orientation='horizontal', label='Some Units') + cax=axs[0].inset_axes([0, -.15, 1, .1]), + orientation='horizontal', label='Some Units') # And again for the second colorbar. cmap2 = mpl.cm.cool norm2 = mpl.colors.Normalize(vmin=1, vmax=17) fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap2, norm=norm2), - cax=axl2, orientation='horizontal', label='Some other units') + cax=axs[1].inset_axes([0, -.15, 1, .1]), + orientation='horizontal', label='Some other units') # The second example illustrates the use of a ListedColormap, a @@ -173,7 +173,7 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None): bounds = [2, 3, 7, 9, 15] norm3 = mpl.colors.BoundaryNorm(bounds, cmap3.N) fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap3, norm=norm3), - cax=axl3, + cax=axs[2].inset_axes([0, -.15, 1, .1]), extend='both', ticks=bounds, # optional spacing='proportional', @@ -182,14 +182,14 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None): # Create the 17 segment model -bullseye_plot(ax[0], data, cmap=cmap, norm=norm) -ax[0].set_title('Bulls Eye (AHA)') +bullseye_plot(axs[0], data, cmap=cmap, norm=norm) +axs[0].set_title('Bulls Eye (AHA)') -bullseye_plot(ax[1], data, cmap=cmap2, norm=norm2) -ax[1].set_title('Bulls Eye (AHA)') +bullseye_plot(axs[1], data, cmap=cmap2, norm=norm2) +axs[1].set_title('Bulls Eye (AHA)') -bullseye_plot(ax[2], data, seg_bold=[3, 5, 6, 11, 12, 16], +bullseye_plot(axs[2], data, seg_bold=[3, 5, 6, 11, 12, 16], cmap=cmap3, norm=norm3) -ax[2].set_title('Segments [3, 5, 6, 11, 12, 16] in bold') +axs[2].set_title('Segments [3, 5, 6, 11, 12, 16] in bold') plt.show() From cb4569a31173553ab742620f48e314e2521be1bb Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 12 Jan 2023 21:16:09 +0100 Subject: [PATCH 210/262] Backport PR #24254: Expire deprecations in widgets and keyword only arguments for Selectors --- .../deprecations/24254-OG.rst | 6 + .../next_api_changes/removals/24254-OG.rst | 64 ++++++ lib/matplotlib/tests/test_widgets.py | 21 +- lib/matplotlib/widgets.py | 196 ++++-------------- 4 files changed, 119 insertions(+), 168 deletions(-) create mode 100644 doc/api/next_api_changes/deprecations/24254-OG.rst create mode 100644 doc/api/next_api_changes/removals/24254-OG.rst diff --git a/doc/api/next_api_changes/deprecations/24254-OG.rst b/doc/api/next_api_changes/deprecations/24254-OG.rst new file mode 100644 index 000000000000..d6e4882a774b --- /dev/null +++ b/doc/api/next_api_changes/deprecations/24254-OG.rst @@ -0,0 +1,6 @@ +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. diff --git a/doc/api/next_api_changes/removals/24254-OG.rst b/doc/api/next_api_changes/removals/24254-OG.rst new file mode 100644 index 000000000000..f29d1e0662cd --- /dev/null +++ b/doc/api/next_api_changes/removals/24254-OG.rst @@ -0,0 +1,64 @@ +Removal of deprecations in the Selector widget API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +RectangleSelector and EllipseSelector +..................................... + +The *drawtype* keyword argument to `~matplotlib.widgets.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 +`~matplotlib.widgets.RectangleSelector` is also removed. + +To retain the behaviour of ``drawtype='none'``, use ``rectprops={'visible': +False}`` to make the drawn `~matplotlib.patches.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. + +PolygonSelector +............... + +- 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. + +SpanSelector +............ + +- 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. + +LassoSelector +............. + +- 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. diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index c01e1ef171bf..76dbeb2addc5 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -1,4 +1,3 @@ -from contextlib import nullcontext import functools from unittest import mock @@ -24,22 +23,16 @@ def ax(): return get_ax() -@pytest.mark.parametrize('kwargs, warning_msg', [ - (dict(), None), - (dict(drawtype='line', useblit=False), - "Support for drawtype='line' is deprecated"), - (dict(useblit=True, button=1), None), - (dict(drawtype='none', minspanx=10, minspany=10), - "Support for drawtype='none' is deprecated"), - (dict(minspanx=10, minspany=10, spancoords='pixels'), None), - (dict(props=dict(fill=True)), None), +@pytest.mark.parametrize('kwargs', [ + dict(), + dict(useblit=True, button=1), + dict(minspanx=10, minspany=10, spancoords='pixels'), + dict(props=dict(fill=True)), ]) -def test_rectangle_selector(ax, kwargs, warning_msg): +def test_rectangle_selector(ax, kwargs): onselect = mock.Mock(spec=noop, return_value=None) - with (pytest.warns(MatplotlibDeprecationWarning, match=warning_msg) - if warning_msg else nullcontext()): - tool = widgets.RectangleSelector(ax, onselect, **kwargs) + tool = widgets.RectangleSelector(ax, onselect, **kwargs) do_event(tool, 'press', xdata=100, ydata=100, button=1) do_event(tool, 'onmove', xdata=199, ydata=199, button=1) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 8ca7a52a86d4..745f57f10ec5 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -325,6 +325,7 @@ class Slider(SliderBase): Slider value. """ + @_api.make_keyword_only("3.7", name="valinit") def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, closedmin=True, closedmax=True, slidermin=None, slidermax=None, dragging=True, valstep=None, @@ -597,6 +598,7 @@ class RangeSlider(SliderBase): Slider value. """ + @_api.make_keyword_only("3.7", name="valinit") def __init__( self, ax, @@ -1221,8 +1223,7 @@ class TextBox(AxesWidget): The color of the text box when hovering. """ - DIST_FROM_LEFT = _api.deprecate_privatize_attribute("3.5") - + @_api.make_keyword_only("3.7", name="color") def __init__(self, ax, label, initial='', color='.95', hovercolor='1', label_pad=.01, textalignment="left"): @@ -1246,8 +1247,6 @@ def __init__(self, ax, label, initial='', """ super().__init__(ax) - self._DIST_FROM_LEFT = .05 - self._text_position = _api.check_getitem( {"left": 0.05, "center": 0.5, "right": 0.95}, textalignment=textalignment) @@ -1727,7 +1726,7 @@ class Cursor(AxesWidget): -------- See :doc:`/gallery/widgets/cursor`. """ - + @_api.make_keyword_only("3.7", "horizOn") def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, **lineprops): super().__init__(ax) @@ -1981,9 +1980,6 @@ def __init__(self, ax, onselect, useblit=False, button=None, self._prev_event = None self._state = set() - eventpress = _api.deprecate_privatize_attribute("3.5") - eventrelease = _api.deprecate_privatize_attribute("3.5") - state = _api.deprecate_privatize_attribute("3.5") state_modifier_keys = _api.deprecate_privatize_attribute("3.6") def set_active(self, active): @@ -2408,8 +2404,7 @@ def on_select(min: float, max: float) -> Any See also: :doc:`/gallery/widgets/span_selector` """ - @_api.rename_parameter("3.5", "rectprops", "props") - @_api.rename_parameter("3.5", "span_stays", "interactive") + @_api.make_keyword_only("3.7", name="minspan") def __init__(self, ax, onselect, direction, minspan=0, useblit=False, props=None, onmove_callback=None, interactive=False, button=None, handle_props=None, grab_range=10, @@ -2465,24 +2460,6 @@ def __init__(self, ax, onselect, direction, minspan=0, useblit=False, # prev attribute is deprecated but we still need to maintain it self._prev = (0, 0) - rect = _api.deprecated("3.5")( - property(lambda self: self._selection_artist) - ) - - rectprops = _api.deprecated("3.5")( - property(lambda self: self._props) - ) - - active_handle = _api.deprecate_privatize_attribute("3.5") - - pressv = _api.deprecate_privatize_attribute("3.5") - - span_stays = _api.deprecated("3.5")( - property(lambda self: self._interactive) - ) - - prev = _api.deprecate_privatize_attribute("3.5") - def new_axes(self, ax): """Set SpanSelector to operate on a new Axes.""" self.ax = ax @@ -2784,6 +2761,7 @@ class ToolLineHandles: for details. """ + @_api.make_keyword_only("3.7", "line_props") def __init__(self, ax, positions, direction, line_props=None, useblit=True): self.ax = ax @@ -2894,6 +2872,7 @@ class ToolHandles: for details. """ + @_api.make_keyword_only("3.7", "marker") def __init__(self, ax, x, y, marker='o', marker_props=None, useblit=True): self.ax = ax props = {'marker': marker, 'markersize': 7, 'markerfacecolor': 'w', @@ -3059,18 +3038,11 @@ class RectangleSelector(_SelectorWidget): See also: :doc:`/gallery/widgets/rectangle_selector` """ - @_api.rename_parameter("3.5", "maxdist", "grab_range") - @_api.rename_parameter("3.5", "marker_props", "handle_props") - @_api.rename_parameter("3.5", "rectprops", "props") - @_api.delete_parameter("3.5", "drawtype") - @_api.delete_parameter("3.5", "lineprops") - def __init__(self, ax, onselect, drawtype='box', - minspanx=0, minspany=0, useblit=False, - lineprops=None, props=None, spancoords='data', - button=None, grab_range=10, handle_props=None, - interactive=False, state_modifier_keys=None, - drag_from_anywhere=False, ignore_event_outside=False, - use_data_coordinates=False): + def __init__(self, ax, onselect, *, minspanx=0, minspany=0, useblit=False, + props=None, spancoords='data', button=None, grab_range=10, + handle_props=None, interactive=False, + state_modifier_keys=None, drag_from_anywhere=False, + ignore_event_outside=False, use_data_coordinates=False): super().__init__(ax, onselect, useblit=useblit, button=button, state_modifier_keys=state_modifier_keys, use_data_coordinates=use_data_coordinates) @@ -3086,34 +3058,13 @@ def __init__(self, ax, onselect, drawtype='box', # interactive bounding box to allow the polygon to be easily resized self._allow_creation = True - if drawtype == 'none': # draw a line but make it invisible - _api.warn_deprecated( - "3.5", message="Support for drawtype='none' is deprecated " - "since %(since)s and will be removed " - "%(removal)s." - "Use props=dict(visible=False) instead.") - drawtype = 'line' - self._visible = False - - if drawtype == 'box': - if props is None: - props = dict(facecolor='red', edgecolor='black', - alpha=0.2, fill=True) - self._props = {**props, 'animated': self.useblit} - self._visible = self._props.pop('visible', self._visible) - to_draw = self._init_shape(**self._props) - self.ax.add_patch(to_draw) - if drawtype == 'line': - _api.warn_deprecated( - "3.5", message="Support for drawtype='line' is deprecated " - "since %(since)s and will be removed " - "%(removal)s.") - if lineprops is None: - lineprops = dict(color='black', linestyle='-', - linewidth=2, alpha=0.5) - self._props = {**lineprops, 'animated': self.useblit} - to_draw = Line2D([0, 0], [0, 0], visible=False, **self._props) - self.ax.add_line(to_draw) + if props is None: + props = dict(facecolor='red', edgecolor='black', + alpha=0.2, fill=True) + self._props = {**props, 'animated': self.useblit} + self._visible = self._props.pop('visible', self._visible) + to_draw = self._init_shape(**self._props) + self.ax.add_patch(to_draw) self._selection_artist = to_draw self._set_aspect_ratio_correction() @@ -3123,7 +3074,6 @@ def __init__(self, ax, onselect, drawtype='box', _api.check_in_list(['data', 'pixels'], spancoords=spancoords) self.spancoords = spancoords - self._drawtype = drawtype self.grab_range = grab_range @@ -3154,20 +3104,6 @@ def __init__(self, ax, onselect, drawtype='box', self._extents_on_press = None - to_draw = _api.deprecated("3.5")( - property(lambda self: self._selection_artist) - ) - - drawtype = _api.deprecate_privatize_attribute("3.5") - - active_handle = _api.deprecate_privatize_attribute("3.5") - - interactive = _api.deprecate_privatize_attribute("3.5") - - maxdist = _api.deprecated("3.5", name="maxdist", alternative="grab_range")( - property(lambda self: self.grab_range, - lambda self, value: setattr(self, "grab_range", value))) - @property def _handles_artists(self): return (*self._center_handle.artists, *self._corner_handles.artists, @@ -3240,8 +3176,7 @@ def _release(self, event): spancoords=self.spancoords) # check if drawn distance (if it exists) is not too small in # either x or y-direction - minspanxy = (spanx <= self.minspanx or spany <= self.minspany) - if (self._drawtype != 'none' and minspanxy): + if spanx <= self.minspanx or spany <= self.minspany: if self._selection_completed: # Call onselect, only when the selection is already existing self.onselect(self._eventpress, self._eventrelease) @@ -3405,13 +3340,7 @@ def _onmove(self, event): @property def _rect_bbox(self): - if self._drawtype == 'box': - return self._selection_artist.get_bbox().bounds - else: - x, y = self._selection_artist.get_data() - x0, x1 = min(x), max(x) - y0, y1 = min(y), max(y) - return x0, y0, x1 - x0, y1 - y0 + return self._selection_artist.get_bbox().bounds def _set_aspect_ratio_correction(self): aspect_ratio = self.ax._get_aspect_ratio() @@ -3510,8 +3439,6 @@ def rotation(self, value): # call extents setter to draw shape and update handles positions self.extents = self.extents - draw_shape = _api.deprecate_privatize_attribute('3.5') - def _draw_shape(self, extents): x0, x1, y0, y1 = extents xmin, xmax = sorted([x0, x1]) @@ -3524,15 +3451,11 @@ def _draw_shape(self, extents): xmax = min(xmax, xlim[1]) ymax = min(ymax, ylim[1]) - if self._drawtype == 'box': - self._selection_artist.set_x(xmin) - self._selection_artist.set_y(ymin) - self._selection_artist.set_width(xmax - xmin) - self._selection_artist.set_height(ymax - ymin) - self._selection_artist.set_angle(self.rotation) - - elif self._drawtype == 'line': - self._selection_artist.set_data([xmin, xmax], [ymin, ymax]) + self._selection_artist.set_x(xmin) + self._selection_artist.set_y(ymin) + self._selection_artist.set_width(xmax - xmin) + self._selection_artist.set_height(ymax - ymin) + self._selection_artist.set_angle(self.rotation) def _set_active_handle(self, event): """Set active handle based on the location of the mouse event.""" @@ -3600,9 +3523,6 @@ class EllipseSelector(RectangleSelector): -------- :doc:`/gallery/widgets/rectangle_selector` """ - - draw_shape = _api.deprecate_privatize_attribute('3.5') - def _init_shape(self, **props): return Ellipse((0, 0), 0, 1, visible=False, **props) @@ -3614,29 +3534,17 @@ def _draw_shape(self, extents): a = (xmax - xmin) / 2. b = (ymax - ymin) / 2. - if self._drawtype == 'box': - self._selection_artist.center = center - self._selection_artist.width = 2 * a - self._selection_artist.height = 2 * b - self._selection_artist.angle = self.rotation - else: - rad = np.deg2rad(np.arange(31) * 12) - x = a * np.cos(rad) + center[0] - y = b * np.sin(rad) + center[1] - self._selection_artist.set_data(x, y) + self._selection_artist.center = center + self._selection_artist.width = 2 * a + self._selection_artist.height = 2 * b + self._selection_artist.angle = self.rotation @property def _rect_bbox(self): - if self._drawtype == 'box': - x, y = self._selection_artist.center - width = self._selection_artist.width - height = self._selection_artist.height - return x - width / 2., y - height / 2., width, height - else: - x, y = self._selection_artist.get_data() - x0, x1 = min(x), max(x) - y0, y1 = min(y), max(y) - return x0, y0, x1 - x0, y1 - y0 + x, y = self._selection_artist.center + width = self._selection_artist.width + height = self._selection_artist.height + return x - width / 2., y - height / 2., width, height class LassoSelector(_SelectorWidget): @@ -3680,9 +3588,8 @@ def onselect(verts): which corresponds to all buttons. """ - @_api.rename_parameter("3.5", "lineprops", "props") - def __init__(self, ax, onselect=None, useblit=True, props=None, - button=None): + @_api.make_keyword_only("3.7", name="useblit") + def __init__(self, ax, onselect, useblit=True, props=None, button=None): super().__init__(ax, onselect, useblit=useblit, button=button) self.verts = None props = { @@ -3695,18 +3602,10 @@ def __init__(self, ax, onselect=None, useblit=True, props=None, self.ax.add_line(line) self._selection_artist = line - @_api.deprecated("3.5", alternative="press") - def onpress(self, event): - self.press(event) - def _press(self, event): self.verts = [self._get_data(event)] self._selection_artist.set_visible(True) - @_api.deprecated("3.5", alternative="release") - def onrelease(self, event): - self.release(event) - def _release(self, event): if self.verts is not None: self.verts.append(self._get_data(event)) @@ -3801,9 +3700,7 @@ class PolygonSelector(_SelectorWidget): point. """ - @_api.rename_parameter("3.5", "lineprops", "props") - @_api.rename_parameter("3.5", "markerprops", "handle_props") - @_api.rename_parameter("3.5", "vertex_select_radius", "grab_range") + @_api.make_keyword_only("3.7", name="useblit") def __init__(self, ax, onselect, useblit=False, props=None, handle_props=None, grab_range=10, *, draw_bounding_box=False, box_handle_props=None, @@ -3910,16 +3807,6 @@ def _scale_polygon(self, event): self._draw_polygon() self._old_box_extents = self._box.extents - line = _api.deprecated("3.5")( - property(lambda self: self._selection_artist) - ) - - vertex_select_radius = _api.deprecated("3.5", name="vertex_select_radius", - alternative="grab_range")( - property(lambda self: self.grab_range, - lambda self, value: setattr(self, "grab_range", value)) - ) - @property def _handles_artists(self): return self._polygon_handles.artists @@ -4111,16 +3998,17 @@ class Lasso(AxesWidget): The parent Axes for the widget. xy : (float, float) Coordinates of the start of the lasso. + callback : callable + Whenever the lasso is released, the *callback* function is called and + passed the vertices of the selected path. useblit : bool, default: True Whether to use blitting for faster drawing (if supported by the backend). See the tutorial :doc:`/tutorials/advanced/blitting` for details. - callback : callable - Whenever the lasso is released, the *callback* function is called and - passed the vertices of the selected path. """ - def __init__(self, ax, xy, callback=None, useblit=True): + @_api.make_keyword_only("3.7", name="useblit") + def __init__(self, ax, xy, callback, useblit=True): super().__init__(ax) self.useblit = useblit and self.canvas.supports_blit From 9b30fdf522d6915771f4977df703bc431fda9968 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 12 Jan 2023 21:39:08 +0100 Subject: [PATCH 211/262] Backport PR #24825: Allow non-default scales on polar axes --- lib/matplotlib/projections/polar.py | 47 ++++++++++++++---- .../baseline_images/test_polar/polar_log.png | Bin 0 -> 41668 bytes lib/matplotlib/tests/test_polar.py | 12 +++++ 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_polar/polar_log.png diff --git a/lib/matplotlib/projections/polar.py b/lib/matplotlib/projections/polar.py index 3fbb4d2b9cfd..3243c76d8661 100644 --- a/lib/matplotlib/projections/polar.py +++ b/lib/matplotlib/projections/polar.py @@ -16,13 +16,18 @@ class PolarTransform(mtransforms.Transform): - """ + r""" The base polar transform. - This transform maps polar coordinates ``(theta, r)`` into Cartesian - coordinates ``(x, y) = (r * cos(theta), r * sin(theta))`` (but does not + This transform maps polar coordinates :math:`\theta, r` into Cartesian + coordinates :math:`x, y = r \cos(\theta), r \sin(\theta)` + (but does not fully transform into Axes coordinates or handle positioning in screen space). + This transformation is designed to be applied to data after any scaling + along the radial axis (e.g. log-scaling) has been applied to the input + data. + Path segments at a fixed radius are automatically transformed to circular arcs as long as ``path._interpolation_steps > 1``. """ @@ -30,7 +35,7 @@ class PolarTransform(mtransforms.Transform): input_dims = output_dims = 2 def __init__(self, axis=None, use_rmin=True, - _apply_theta_transforms=True): + _apply_theta_transforms=True, *, scale_transform=None): """ Parameters ---------- @@ -46,12 +51,18 @@ def __init__(self, axis=None, use_rmin=True, self._axis = axis self._use_rmin = use_rmin self._apply_theta_transforms = _apply_theta_transforms + self._scale_transform = scale_transform __str__ = mtransforms._make_str_method( "_axis", use_rmin="_use_rmin", _apply_theta_transforms="_apply_theta_transforms") + def _get_rorigin(self): + # Get lower r limit after being scaled by the radial scale transform + return self._scale_transform.transform( + (0, self._axis.get_rorigin()))[1] + def transform_non_affine(self, tr): # docstring inherited theta, r = np.transpose(tr) @@ -61,7 +72,7 @@ def transform_non_affine(self, tr): theta *= self._axis.get_theta_direction() theta += self._axis.get_theta_offset() if self._use_rmin and self._axis is not None: - r = (r - self._axis.get_rorigin()) * self._axis.get_rsign() + r = (r - self._get_rorigin()) * self._axis.get_rsign() r = np.where(r >= 0, r, np.nan) return np.column_stack([r * np.cos(theta), r * np.sin(theta)]) @@ -85,7 +96,7 @@ def transform_path_non_affine(self, path): # that behavior here. last_td, td = np.rad2deg([last_t, t]) if self._use_rmin and self._axis is not None: - r = ((r - self._axis.get_rorigin()) + r = ((r - self._get_rorigin()) * self._axis.get_rsign()) if last_td <= td: while td - last_td > 360: @@ -877,7 +888,9 @@ def _set_lim_and_transforms(self): # data. This one is aware of rmin self.transProjection = self.PolarTransform( self, - _apply_theta_transforms=False) + _apply_theta_transforms=False, + scale_transform=self.transScale + ) # Add dependency on rorigin. self.transProjection.set_children(self._originViewLim) @@ -888,9 +901,25 @@ def _set_lim_and_transforms(self): # The complete data transformation stack -- from data all the # way to display coordinates + # + # 1. Remove any radial axis scaling (e.g. log scaling) + # 2. Shift data in the theta direction + # 3. Project the data from polar to cartesian values + # (with the origin in the same place) + # 4. Scale and translate the cartesian values to Axes coordinates + # (here the origin is moved to the lower left of the Axes) + # 5. Move and scale to fill the Axes + # 6. Convert from Axes coordinates to Figure coordinates self.transData = ( - self.transScale + self.transShift + self.transProjection + - (self.transProjectionAffine + self.transWedge + self.transAxes)) + self.transScale + + self.transShift + + self.transProjection + + ( + self.transProjectionAffine + + self.transWedge + + self.transAxes + ) + ) # This is the transform for theta-axis ticks. It is # equivalent to transData, except it always puts r == 0.0 and r == 1.0 diff --git a/lib/matplotlib/tests/baseline_images/test_polar/polar_log.png b/lib/matplotlib/tests/baseline_images/test_polar/polar_log.png new file mode 100644 index 0000000000000000000000000000000000000000..ab8e20b482a50f651e2ffbb5e6af864f1fdfa8f4 GIT binary patch literal 41668 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 Date: Thu, 12 Jan 2023 21:57:34 +0100 Subject: [PATCH 212/262] Backport PR #24948: Remove remaining deprecations from 3.5 --- .../next_api_changes/removals/24948-ES.rst | 104 ++++++++++++++++++ .../api_changes_3.5.0/deprecations.rst | 2 +- .../api_changes_3.5.0/removals.rst | 2 +- doc/api/testing_api.rst | 5 - lib/matplotlib/__init__.py | 58 ---------- lib/matplotlib/axes/_axes.py | 14 --- lib/matplotlib/axes/_base.py | 97 +++------------- lib/matplotlib/backend_bases.py | 15 +-- lib/matplotlib/category.py | 11 -- lib/matplotlib/legend_handler.py | 26 +---- lib/matplotlib/pyplot.py | 11 -- lib/matplotlib/rcsetup.py | 7 +- lib/matplotlib/scale.py | 5 - lib/matplotlib/testing/conftest.py | 40 +------ lib/matplotlib/tests/test_axes.py | 71 ++---------- lib/matplotlib/tests/test_category.py | 12 -- lib/matplotlib/tests/test_rcparams.py | 2 - lib/matplotlib/units.py | 19 +--- lib/mpl_toolkits/axes_grid1/axes_divider.py | 36 +----- lib/mpl_toolkits/axes_grid1/axes_grid.py | 1 - 20 files changed, 146 insertions(+), 392 deletions(-) create mode 100644 doc/api/next_api_changes/removals/24948-ES.rst diff --git a/doc/api/next_api_changes/removals/24948-ES.rst b/doc/api/next_api_changes/removals/24948-ES.rst new file mode 100644 index 000000000000..23ca84dd3202 --- /dev/null +++ b/doc/api/next_api_changes/removals/24948-ES.rst @@ -0,0 +1,104 @@ + +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 :ref:`testing` for more details. + + + +Auto-removal of grids by `~.Axes.pcolor` and `~.Axes.pcolormesh` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`~.Axes.pcolor` and `~.Axes.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 :ref:`Behavioural API Changes 3.5 - Axes children combined` 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. + + + +``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, )``). 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. diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst index 7ce5132bc7fa..7bb9009fbe77 100644 --- a/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst @@ -162,7 +162,7 @@ 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 deprecated. Likewise, the -`.ConversionInterface.is_numlike` helper is deprecated. +``.ConversionInterface.is_numlike`` helper is deprecated. Consider calling `.Axis.convert_units` instead, which still supports unitless values. diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst index ce9ddef5ba5f..45b574e04cf5 100644 --- a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst +++ b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst @@ -282,7 +282,7 @@ Arguments - The *dummy* parameter of `.RendererPgf` has been removed. - The *props* parameter of `.Shadow` has been removed; use keyword arguments instead. -- The *recursionlimit* parameter of `matplotlib.test` has been removed. +- The *recursionlimit* parameter of ``matplotlib.test`` has been removed. - The *label* parameter of `.Tick` has no effect and has been removed. - `~.ticker.MaxNLocator` no longer accepts a positional parameter and the keyword argument *nbins* simultaneously because they specify the same diff --git a/doc/api/testing_api.rst b/doc/api/testing_api.rst index 808d2b870109..7731d4510b27 100644 --- a/doc/api/testing_api.rst +++ b/doc/api/testing_api.rst @@ -3,11 +3,6 @@ ********************** -:func:`matplotlib.test` -======================= - -.. autofunction:: matplotlib.test - :mod:`matplotlib.testing` ========================= diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 4289eb1702eb..b279c465163e 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1278,12 +1278,6 @@ def is_interactive(): return rcParams['interactive'] -default_test_modules = [ - 'matplotlib.tests', - 'mpl_toolkits.tests', -] - - def _init_tests(): # The version of FreeType to install locally for running the # tests. This must match the value in `setupext.py` @@ -1302,58 +1296,6 @@ def _init_tests(): "" if ft2font.__freetype_build_type__ == 'local' else "not ")) -@_api.deprecated("3.5", alternative='pytest') -def test(verbosity=None, coverage=False, **kwargs): - """Run the matplotlib test suite.""" - - try: - import pytest - except ImportError: - print("matplotlib.test requires pytest to run.") - return -1 - - if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')): - print("Matplotlib test data is not installed") - return -1 - - old_backend = get_backend() - try: - use('agg') - - args = kwargs.pop('argv', []) - provide_default_modules = True - use_pyargs = True - for arg in args: - if any(arg.startswith(module_path) - for module_path in default_test_modules): - provide_default_modules = False - break - if os.path.exists(arg): - provide_default_modules = False - use_pyargs = False - break - if use_pyargs: - args += ['--pyargs'] - if provide_default_modules: - args += default_test_modules - - if coverage: - args += ['--cov'] - - if verbosity: - args += ['-' + 'v' * verbosity] - - retcode = pytest.main(args, **kwargs) - finally: - if old_backend.lower() != 'agg': - use(old_backend) - - return retcode - - -test.__test__ = False # pytest: this function is not a test - - def _replacer(data, value): """ Either returns ``data[value]`` or passes ``data`` back, converts either to diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index a6fecd374fba..a3ec2914a777 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5792,18 +5792,6 @@ def _interp_grid(X): C = cbook.safe_masked_invalid(C) return X, Y, C, shading - def _pcolor_grid_deprecation_helper(self): - grid_active = any(axis._major_tick_kw["gridOn"] - for axis in self._axis_map.values()) - # explicit is-True check because get_axisbelow() can also be 'line' - grid_hidden_by_pcolor = self.get_axisbelow() is True - if grid_active and not grid_hidden_by_pcolor: - _api.warn_deprecated( - "3.5", message="Auto-removal of grids by pcolor() and " - "pcolormesh() is deprecated since %(since)s and will be " - "removed %(removal)s; please call grid(False) first.") - self.grid(False) - @_preprocess_data() @_docstring.dedent_interpd def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, @@ -6008,7 +5996,6 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, collection = mcoll.PolyCollection( verts, array=C, cmap=cmap, norm=norm, alpha=alpha, **kwargs) collection._scale_norm(norm, vmin, vmax) - self._pcolor_grid_deprecation_helper() x = X.compressed() y = Y.compressed() @@ -6242,7 +6229,6 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, coords, antialiased=antialiased, shading=shading, array=C, cmap=cmap, norm=norm, alpha=alpha, **kwargs) collection._scale_norm(norm, vmin, vmax) - self._pcolor_grid_deprecation_helper() coords = coords.reshape(-1, 2) # flatten the grid structure; keep x, y diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 53f5607f41d1..0bf5b71860a0 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1,4 +1,4 @@ -from collections.abc import Iterable, MutableSequence +from collections.abc import Iterable, Sequence from contextlib import ExitStack import functools import inspect @@ -1403,18 +1403,15 @@ def cla(self): else: self.clear() - class ArtistList(MutableSequence): + class ArtistList(Sequence): """ A sublist of Axes children based on their type. - The type-specific children sublists will become immutable in - Matplotlib 3.7. Then, these artist lists will likely be replaced by - tuples. Use as if this is a tuple already. - - This class exists only for the transition period to warn on the - deprecated modification of artist lists. + The type-specific children sublists were made immutable in Matplotlib + 3.7. In the future these artist lists may be replaced by tuples. Use + as if this is a tuple already. """ - def __init__(self, axes, prop_name, add_name, + def __init__(self, axes, prop_name, valid_types=None, invalid_types=None): """ Parameters @@ -1425,9 +1422,6 @@ def __init__(self, axes, prop_name, add_name, prop_name : str The property name used to access this sublist from the Axes; used to generate deprecation warnings. - add_name : str - The method name used to add Artists of this sublist's type to - the Axes; used to generate deprecation warnings. valid_types : list of type, optional A list of types that determine which children will be returned by this sublist. If specified, then the Artists in the sublist @@ -1442,7 +1436,6 @@ def __init__(self, axes, prop_name, add_name, """ self._axes = axes self._prop_name = prop_name - self._add_name = add_name self._type_check = lambda artist: ( (not valid_types or isinstance(artist, valid_types)) and (not invalid_types or not isinstance(artist, invalid_types)) @@ -1468,103 +1461,47 @@ def __getitem__(self, key): def __add__(self, other): if isinstance(other, (list, _AxesBase.ArtistList)): return [*self, *other] + if isinstance(other, (tuple, _AxesBase.ArtistList)): + return (*self, *other) return NotImplemented def __radd__(self, other): if isinstance(other, list): return other + list(self) + if isinstance(other, tuple): + return other + tuple(self) return NotImplemented - def insert(self, index, item): - _api.warn_deprecated( - '3.5', - name=f'modification of the Axes.{self._prop_name}', - obj_type='property', - alternative=f'Axes.{self._add_name}') - try: - index = self._axes._children.index(self[index]) - except IndexError: - index = None - getattr(self._axes, self._add_name)(item) - if index is not None: - # Move new item to the specified index, if there's something to - # put it before. - self._axes._children[index:index] = self._axes._children[-1:] - del self._axes._children[-1] - - def __setitem__(self, key, item): - _api.warn_deprecated( - '3.5', - name=f'modification of the Axes.{self._prop_name}', - obj_type='property', - alternative=f'Artist.remove() and Axes.f{self._add_name}') - del self[key] - if isinstance(key, slice): - key = key.start - if not np.iterable(item): - self.insert(key, item) - return - - try: - index = self._axes._children.index(self[key]) - except IndexError: - index = None - for i, artist in enumerate(item): - getattr(self._axes, self._add_name)(artist) - if index is not None: - # Move new items to the specified index, if there's something - # to put it before. - i = -(i + 1) - self._axes._children[index:index] = self._axes._children[i:] - del self._axes._children[i:] - - def __delitem__(self, key): - _api.warn_deprecated( - '3.5', - name=f'modification of the Axes.{self._prop_name}', - obj_type='property', - alternative='Artist.remove()') - if isinstance(key, slice): - for artist in self[key]: - artist.remove() - else: - self[key].remove() - @property def artists(self): - return self.ArtistList(self, 'artists', 'add_artist', invalid_types=( + return self.ArtistList(self, 'artists', invalid_types=( mcoll.Collection, mimage.AxesImage, mlines.Line2D, mpatches.Patch, mtable.Table, mtext.Text)) @property def collections(self): - return self.ArtistList(self, 'collections', 'add_collection', + return self.ArtistList(self, 'collections', valid_types=mcoll.Collection) @property def images(self): - return self.ArtistList(self, 'images', 'add_image', - valid_types=mimage.AxesImage) + return self.ArtistList(self, 'images', valid_types=mimage.AxesImage) @property def lines(self): - return self.ArtistList(self, 'lines', 'add_line', - valid_types=mlines.Line2D) + return self.ArtistList(self, 'lines', valid_types=mlines.Line2D) @property def patches(self): - return self.ArtistList(self, 'patches', 'add_patch', - valid_types=mpatches.Patch) + return self.ArtistList(self, 'patches', valid_types=mpatches.Patch) @property def tables(self): - return self.ArtistList(self, 'tables', 'add_table', - valid_types=mtable.Table) + return self.ArtistList(self, 'tables', valid_types=mtable.Table) @property def texts(self): - return self.ArtistList(self, 'texts', 'add_artist', - valid_types=mtext.Text) + return self.ArtistList(self, 'texts', valid_types=mtext.Text) def get_facecolor(self): """Get the facecolor of the Axes.""" diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 16ce51cd600e..c573c369e9e3 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1969,7 +1969,7 @@ def leave_notify_event(self, guiEvent=None): @_api.deprecated("3.6", alternative=( "callbacks.process('enter_notify_event', LocationEvent(...))")) - def enter_notify_event(self, guiEvent=None, xy=None): + def enter_notify_event(self, guiEvent=None, *, xy): """ Callback processing for the mouse cursor entering the canvas. @@ -1983,18 +1983,7 @@ def enter_notify_event(self, guiEvent=None, xy=None): xy : (float, float) The coordinate location of the pointer when the canvas is entered. """ - if xy is not None: - x, y = xy - self._lastx, self._lasty = x, y - else: - x = None - y = None - _api.warn_deprecated( - '3.0', removal='3.5', name='enter_notify_event', - message='Since %(since)s, %(name)s expects a location but ' - 'your backend did not pass one. This will become an error ' - '%(removal)s.') - + self._lastx, self._lasty = x, y = xy event = LocationEvent('figure_enter_event', self, x, y, guiEvent) self.callbacks.process('figure_enter_event', event) diff --git a/lib/matplotlib/category.py b/lib/matplotlib/category.py index 280a9802f2fb..4ac2379ea5f5 100644 --- a/lib/matplotlib/category.py +++ b/lib/matplotlib/category.py @@ -53,17 +53,6 @@ def convert(value, unit, axis): StrCategoryConverter._validate_unit(unit) # dtype = object preserves numerical pass throughs values = np.atleast_1d(np.array(value, dtype=object)) - # pass through sequence of non binary numbers - with _api.suppress_matplotlib_deprecation_warning(): - is_numlike = all(units.ConversionInterface.is_numlike(v) - and not isinstance(v, (str, bytes)) - for v in values) - if values.size and is_numlike: - _api.warn_deprecated( - "3.5", message="Support for passing numbers through unit " - "converters is deprecated since %(since)s and support will be " - "removed %(removal)s; use Axis.convert_units instead.") - return np.asarray(values, dtype=float) # force an update so it also does type checking unit.update(values) return np.vectorize(unit._mapping.__getitem__, otypes=[float])(values) diff --git a/lib/matplotlib/legend_handler.py b/lib/matplotlib/legend_handler.py index cc39cd39cd6d..849644145856 100644 --- a/lib/matplotlib/legend_handler.py +++ b/lib/matplotlib/legend_handler.py @@ -27,7 +27,6 @@ def legend_artist(self, legend, orig_handle, fontsize, handlebox) """ -from collections.abc import Sequence from itertools import cycle import numpy as np @@ -132,9 +131,6 @@ def legend_artist(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, handlebox.get_transform()) - if isinstance(artists, _Line2DHandleList): - artists = [artists[0]] - # create_artists will return a list of artists. for a in artists: handlebox.add_artist(a) @@ -277,24 +273,6 @@ def create_artists(self, legend, orig_handle, return [legline, legline_marker] -class _Line2DHandleList(Sequence): - def __init__(self, legline): - self._legline = legline - - def __len__(self): - return 2 - - def __getitem__(self, index): - if index != 0: - # Make HandlerLine2D return [self._legline] directly after - # deprecation elapses. - _api.warn_deprecated( - "3.5", message="Access to the second element returned by " - "HandlerLine2D is deprecated since %(since)s; it will be " - "removed %(removal)s.") - return [self._legline, self._legline][index] - - class HandlerLine2D(HandlerNpoints): """ Handler for `.Line2D` instances. @@ -331,7 +309,7 @@ def create_artists(self, legend, orig_handle, legline.set_transform(trans) - return _Line2DHandleList(legline) + return [legline] class HandlerPatch(HandlerBase): @@ -790,8 +768,6 @@ def create_artists(self, legend, orig_handle, _a_list = handler.create_artists( legend, handle1, next(xds_cycle), ydescent, width, height, fontsize, trans) - if isinstance(_a_list, _Line2DHandleList): - _a_list = [_a_list[0]] a_list.extend(_a_list) return a_list diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index acd187d5d1c9..04b9bdb79ab2 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -1070,17 +1070,6 @@ def axes(arg=None, **kwargs): %(Axes:kwdoc)s - Notes - ----- - If the figure already has an Axes with key (*args*, - *kwargs*) then it will simply make that axes current and - return it. This behavior is deprecated. Meanwhile, if you do - not want this behavior (i.e., you want to force the creation of a - new axes), you must use a unique set of args and kwargs. The Axes - *label* attribute has been exposed for this purpose: if you want - two Axes that are otherwise identical to be added to the figure, - make sure you give them unique labels. - See Also -------- .Figure.add_axes diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 7d0425196d78..22b11f44e8b5 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -182,10 +182,7 @@ def validator(s): (s is None or isinstance(s, str) and s.lower() == "none")): return None if cls is str and not isinstance(s, str): - _api.warn_deprecated( - "3.5", message="Support for setting an rcParam that expects a " - "str value to a non-str value is deprecated since %(since)s " - "and support will be removed %(removal)s.") + raise ValueError(f'Could not convert {s!r} to str') try: return cls(s) except (TypeError, ValueError) as e: @@ -218,7 +215,7 @@ def _validate_pathlike(s): # between "" (cwd) and "." (cwd, but gets updated by user selections). return os.fsdecode(s) else: - return validate_string(s) # Emit deprecation warning. + return validate_string(s) def validate_fonttype(s): diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 534165cc72e5..01e09f11b444 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -710,11 +710,6 @@ def scale_factory(scale, axis, **kwargs): scale : {%(names)s} axis : `matplotlib.axis.Axis` """ - if scale != scale.lower(): - _api.warn_deprecated( - "3.5", message="Support for case-insensitive scales is deprecated " - "since %(since)s and support will be removed %(removal)s.") - scale = scale.lower() scale_cls = _api.check_getitem(_scale_mapping, scale=scale) return scale_cls(axis, **kwargs) diff --git a/lib/matplotlib/testing/conftest.py b/lib/matplotlib/testing/conftest.py index 21f6c707ecf8..41ed522b72d9 100644 --- a/lib/matplotlib/testing/conftest.py +++ b/lib/matplotlib/testing/conftest.py @@ -1,7 +1,7 @@ import pytest import sys import matplotlib -from matplotlib import _api, cbook +from matplotlib import _api def pytest_configure(config): @@ -13,8 +13,6 @@ def pytest_configure(config): ("markers", "flaky: (Provided by pytest-rerunfailures.)"), ("markers", "timeout: (Provided by pytest-timeout.)"), ("markers", "backend: Set alternate Matplotlib backend temporarily."), - ("markers", - "style: Set alternate Matplotlib style temporarily (deprecated)."), ("markers", "baseline_images: Compare output against references."), ("markers", "pytz: Tests that require pytz to be installed."), ("filterwarnings", "error"), @@ -56,16 +54,6 @@ def mpl_test_settings(request): if any(sys.modules.get(k) for k in ('PyQt4', 'PySide')): pytest.skip('Qt4 binding already imported') - # Default of cleanup and image_comparison too. - style = ["classic", "_classic_test_patch"] - style_marker = request.node.get_closest_marker('style') - if style_marker is not None: - assert len(style_marker.args) == 1, \ - "Marker 'style' must specify 1 style." - _api.warn_deprecated("3.5", name="style", obj_type="pytest marker", - alternative="@mpl.style.context(...)") - style, = style_marker.args - matplotlib.testing.setup() with _api.suppress_matplotlib_deprecation_warning(): if backend is not None: @@ -82,36 +70,14 @@ def mpl_test_settings(request): .format(backend, exc)) else: raise - matplotlib.style.use(style) + # Default of cleanup and image_comparison too. + matplotlib.style.use(["classic", "_classic_test_patch"]) try: yield finally: matplotlib.use(prev_backend) -@pytest.fixture -@_api.deprecated("3.5", alternative="none") -def mpl_image_comparison_parameters(request, extension): - # This fixture is applied automatically by the image_comparison decorator. - # - # The sole purpose of this fixture is to provide an indirect method of - # obtaining parameters *without* modifying the decorated function - # signature. In this way, the function signature can stay the same and - # pytest won't get confused. - # We annotate the decorated function with any parameters captured by this - # fixture so that they can be used by the wrapper in image_comparison. - baseline_images, = request.node.get_closest_marker('baseline_images').args - if baseline_images is None: - # Allow baseline image list to be produced on the fly based on current - # parametrization. - baseline_images = request.getfixturevalue('baseline_images') - - func = request.function - with cbook._setattr_cm(func.__wrapped__, - parameters=(baseline_images, extension)): - yield - - @pytest.fixture def pd(): """Fixture to import and configure pandas.""" diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 642316e4c000..bcbee036ce2b 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -8115,19 +8115,13 @@ def test_artist_sublists(): with pytest.raises(IndexError, match='out of range'): ax.lines[len(lines) + 1] - # Deleting items (multiple or single) should warn. - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[-1] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[-1:] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[1:] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - del ax.lines[0] + # Adding to other lists should produce a regular list. + assert ax.lines + [1, 2, 3] == [*lines, 1, 2, 3] + assert [1, 2, 3] + ax.lines == [1, 2, 3, *lines] + + # Adding to other tuples should produce a regular tuples. + assert ax.lines + (1, 2, 3) == (*lines, 1, 2, 3) + assert (1, 2, 3) + ax.lines == (1, 2, 3, *lines) # Lists should be empty after removing items. col.remove() @@ -8136,59 +8130,10 @@ def test_artist_sublists(): assert not ax.images patch.remove() assert not ax.patches + assert not ax.tables text.remove() assert not ax.texts - # Everything else should remain empty. - assert not ax.lines - assert not ax.tables - - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.texts property'): - ax.texts.append(text) - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.collections property'): - ax.collections.append(col) - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.images property'): - ax.images.append(im) - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.patches property'): - ax.patches.append(patch) - # verify things are back - assert list(ax.collections) == [col] - assert list(ax.images) == [im] - assert list(ax.patches) == [patch] - assert list(ax.texts) == [text] - - # Adding items should warn. - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines.append(lines[-2]) - assert list(ax.lines) == [lines[-2]] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines.append(lines[-1]) - assert list(ax.lines) == lines[-2:] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines.insert(-2, lines[0]) - assert list(ax.lines) == [lines[0], lines[-2], lines[-1]] - - # Modifying items should warn. - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines[0] = lines[0] - assert list(ax.lines) == [lines[0], lines[-2], lines[-1]] - with pytest.warns(MatplotlibDeprecationWarning, - match='modification of the Axes.lines property'): - ax.lines[1:1] = lines[1:-2] - assert list(ax.lines) == lines - - # Adding to other lists should produce a regular list. - assert ax.lines + [1, 2, 3] == [*lines, 1, 2, 3] - assert [1, 2, 3] + ax.lines == [1, 2, 3, *lines] - for ln in ax.lines: ln.remove() assert len(ax.lines) == 0 diff --git a/lib/matplotlib/tests/test_category.py b/lib/matplotlib/tests/test_category.py index 6eb590d6e82d..87dece6346f7 100644 --- a/lib/matplotlib/tests/test_category.py +++ b/lib/matplotlib/tests/test_category.py @@ -3,7 +3,6 @@ import numpy as np import matplotlib as mpl -from matplotlib._api import MatplotlibDeprecationWarning from matplotlib.axes import Axes import matplotlib.pyplot as plt import matplotlib.category as cat @@ -101,17 +100,6 @@ def test_convert(self, vals): def test_convert_one_string(self, value): assert self.cc.convert(value, self.unit, self.ax) == 0 - def test_convert_one_number(self): - with pytest.warns(MatplotlibDeprecationWarning): - actual = self.cc.convert(0.0, self.unit, self.ax) - np.testing.assert_allclose(actual, np.array([0.])) - - def test_convert_float_array(self): - data = np.array([1, 2, 3], dtype=float) - with pytest.warns(MatplotlibDeprecationWarning): - actual = self.cc.convert(data, self.unit, self.ax) - np.testing.assert_allclose(actual, np.array([1., 2., 3.])) - @pytest.mark.parametrize("fvals", fvalues, ids=fids) def test_convert_fail(self, fvals): with pytest.raises(TypeError): diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index 8a7c1028574b..c17e88aee1ac 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -230,8 +230,6 @@ def generate_validator_testcases(valid): ), 'fail': ((set(), ValueError), (1, ValueError), - ((1, 2), _api.MatplotlibDeprecationWarning), - (np.array([1, 2]), _api.MatplotlibDeprecationWarning), ) }, {'validator': _listify_validator(validate_int, n=2), diff --git a/lib/matplotlib/units.py b/lib/matplotlib/units.py index 2bcfcaf2eb12..e3480f228bb4 100644 --- a/lib/matplotlib/units.py +++ b/lib/matplotlib/units.py @@ -46,7 +46,7 @@ def default_units(x, axis): import numpy as np from numpy import ma -from matplotlib import _api, cbook +from matplotlib import cbook class ConversionError(TypeError): @@ -131,23 +131,6 @@ def convert(obj, unit, axis): """ return obj - @staticmethod - @_api.deprecated("3.5") - def is_numlike(x): - """ - The Matplotlib datalim, autoscaling, locators etc work with scalars - which are the units converted to floats given the current unit. The - converter may be passed these floats, or arrays of them, even when - units are set. - """ - if np.iterable(x): - for thisx in x: - if thisx is ma.masked: - continue - return isinstance(thisx, Number) - else: - return isinstance(x, Number) - class DecimalConverter(ConversionInterface): """Converter for decimal.Decimal data to float.""" diff --git a/lib/mpl_toolkits/axes_grid1/axes_divider.py b/lib/mpl_toolkits/axes_grid1/axes_divider.py index 143a2f35cb19..2a6bd0d5da08 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_divider.py +++ b/lib/mpl_toolkits/axes_grid1/axes_divider.py @@ -202,17 +202,9 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None): x0, y0 = x, y if nx1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing nx1=None to mean nx+1 is " - "deprecated since %(since)s; in a future version, nx1=None " - "will mean 'up to the last cell'.") - nx1 = nx + 1 + nx1 = -1 if ny1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing ny1=None to mean ny+1 is " - "deprecated since %(since)s; in a future version, ny1=None " - "will mean 'up to the last cell'.") - ny1 = ny + 1 + ny1 = -1 x1, w1 = x0 + ox[nx] / fig_w, (ox[nx1] - ox[nx]) / fig_w y1, h1 = y0 + oy[ny] / fig_h, (oy[ny1] - oy[ny]) / fig_h @@ -299,17 +291,9 @@ def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None): self._nx, self._ny = nx - _xrefindex, ny - _yrefindex if nx1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing nx1=None to mean nx+1 is " - "deprecated since %(since)s; in a future version, nx1=None " - "will mean 'up to the last cell'.") - nx1 = nx + 1 + nx1 = len(self._axes_divider) if ny1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing ny1=None to mean ny+1 is " - "deprecated since %(since)s; in a future version, ny1=None " - "will mean 'up to the last cell'.") - ny1 = ny + 1 + ny1 = len(self._axes_divider[0]) self._nx1 = nx1 - _xrefindex self._ny1 = ny1 - _yrefindex @@ -600,11 +584,7 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None): x0, y0, ox, hh = _locate( x, y, w, h, summed_ws, equal_hs, fig_w, fig_h, self.get_anchor()) if nx1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing nx1=None to mean nx+1 is " - "deprecated since %(since)s; in a future version, nx1=None " - "will mean 'up to the last cell'.") - nx1 = nx + 1 + nx1 = -1 x1, w1 = x0 + ox[nx] / fig_w, (ox[nx1] - ox[nx]) / fig_w y1, h1 = y0, hh return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) @@ -639,11 +619,7 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None): y0, x0, oy, ww = _locate( y, x, h, w, summed_hs, equal_ws, fig_h, fig_w, self.get_anchor()) if ny1 is None: - _api.warn_deprecated( - "3.5", message="Support for passing ny1=None to mean ny+1 is " - "deprecated since %(since)s; in a future version, ny1=None " - "will mean 'up to the last cell'.") - ny1 = ny + 1 + ny1 = -1 x1, w1 = x0, ww y1, h1 = y0 + oy[ny] / fig_h, (oy[ny1] - oy[ny]) / fig_h return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py index 51925bfde5e3..1d6d6265e86f 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_grid.py +++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py @@ -20,7 +20,6 @@ def _tick_only(ax, bottom_on, left_on): class CbarAxesBase: def __init__(self, *args, orientation, **kwargs): self.orientation = orientation - self._locator = None # deprecated. super().__init__(*args, **kwargs) def colorbar(self, mappable, *, ticks=None, **kwargs): From 8ee20a506bc7e257ae67b753b01e134c7be94fb4 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 12 Jan 2023 13:17:39 -0800 Subject: [PATCH 213/262] Backport PR #24957: DOC: Enable Opensearch --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index dd7ba1cebf9e..2b5bc9f2bb6f 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -458,7 +458,7 @@ def js_tag_with_cache_busting(js): # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. -html_use_opensearch = 'False' +html_use_opensearch = 'https://matplotlib.org/stable' # Output file base name for HTML help builder. htmlhelp_basename = 'Matplotlibdoc' From 9dd122303a54fee1b61c8cb0bdad057cf3f4d061 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 12 Jan 2023 22:56:53 +0100 Subject: [PATCH 214/262] Backport PR #24912: Remove contour warning for "no-valid-levels". --- .../next_api_changes/behavior/24912-AL.rst | 4 ++ lib/matplotlib/contour.py | 10 ----- lib/matplotlib/tests/test_contour.py | 44 ++++--------------- 3 files changed, 13 insertions(+), 45 deletions(-) create mode 100644 doc/api/next_api_changes/behavior/24912-AL.rst diff --git a/doc/api/next_api_changes/behavior/24912-AL.rst b/doc/api/next_api_changes/behavior/24912-AL.rst new file mode 100644 index 000000000000..3a87ed217f9f --- /dev/null +++ b/doc/api/next_api_changes/behavior/24912-AL.rst @@ -0,0 +1,4 @@ +``contour`` no longer warns if no contour lines are drawn. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This can occur if the user explicitly passes a ``levels`` array with no values +between ``z.min()`` and ``z.max()``; or if ``z`` has the same value everywhere. diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index bbcc2a9ce433..42096958bb93 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1137,18 +1137,8 @@ def _process_contour_level_args(self, args, z_dtype): self.levels = self._autolev(levels_arg) else: self.levels = np.asarray(levels_arg, np.float64) - - if not self.filled: - inside = (self.levels > self.zmin) & (self.levels < self.zmax) - levels_in = self.levels[inside] - if len(levels_in) == 0: - self.levels = [self.zmin] - _api.warn_external( - "No contour levels were found within the data range.") - if self.filled and len(self.levels) < 2: raise ValueError("Filled contours require at least 2 levels.") - if len(self.levels) > 1 and np.min(np.diff(self.levels)) <= 0.0: raise ValueError("Contour levels must be increasing") diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index 3da06a7d27d0..41d4dc8501bd 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -62,15 +62,16 @@ def test_contour_shape_error(args, message): ax.contour(*args) -def test_contour_empty_levels(): - - x = np.arange(9) - z = np.random.random((9, 9)) - +def test_contour_no_valid_levels(): fig, ax = plt.subplots() - with pytest.warns(UserWarning) as record: - ax.contour(x, x, z, levels=[]) - assert len(record) == 1 + # no warning for empty levels. + ax.contour(np.random.rand(9, 9), levels=[]) + # no warning if levels is given and is not within the range of z. + cs = ax.contour(np.arange(81).reshape((9, 9)), levels=[100]) + # ... and if fmt is given. + ax.clabel(cs, fmt={100: '%1.2f'}) + # no warning if z is uniform. + ax.contour(np.ones((9, 9))) def test_contour_Nlevels(): @@ -84,33 +85,6 @@ def test_contour_Nlevels(): assert (cs1.levels == cs2.levels).all() -def test_contour_badlevel_fmt(): - # Test edge case from https://github.com/matplotlib/matplotlib/issues/9742 - # User supplied fmt for each level as a dictionary, but Matplotlib changed - # the level to the minimum data value because no contours possible. - # This was fixed in https://github.com/matplotlib/matplotlib/pull/9743 - x = np.arange(9) - z = np.zeros((9, 9)) - - fig, ax = plt.subplots() - fmt = {1.: '%1.2f'} - with pytest.warns(UserWarning) as record: - cs = ax.contour(x, x, z, levels=[1.]) - ax.clabel(cs, fmt=fmt) - assert len(record) == 1 - - -def test_contour_uniform_z(): - - x = np.arange(9) - z = np.ones((9, 9)) - - fig, ax = plt.subplots() - with pytest.warns(UserWarning) as record: - ax.contour(x, x, z) - assert len(record) == 1 - - @image_comparison(['contour_manual_labels'], remove_text=True, style='mpl20') def test_contour_manual_labels(): x, y = np.meshgrid(np.arange(0, 10), np.arange(0, 10)) From 566dee83742e603cb49461fde0ccc5e426b989bc Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 13 Jan 2023 10:11:49 +0100 Subject: [PATCH 215/262] Backport PR #24965: Remove additional deprecations from 3.5 --- .../next_api_changes/removals/24948-ES.rst | 11 ++++++++ .../next_api_changes/removals/24965-ES.rst | 5 ++++ lib/matplotlib/axes/_base.py | 27 +++++-------------- .../backends/backend_webagg_core.py | 3 --- lib/matplotlib/colorbar.py | 8 ++---- lib/matplotlib/tests/test_widgets.py | 12 ++++++--- lib/matplotlib/widgets.py | 4 +-- 7 files changed, 34 insertions(+), 36 deletions(-) create mode 100644 doc/api/next_api_changes/removals/24965-ES.rst diff --git a/doc/api/next_api_changes/removals/24948-ES.rst b/doc/api/next_api_changes/removals/24948-ES.rst index 23ca84dd3202..38ed70792f26 100644 --- a/doc/api/next_api_changes/removals/24948-ES.rst +++ b/doc/api/next_api_changes/removals/24948-ES.rst @@ -44,6 +44,17 @@ information; modification of the following sublists is no longer supported: 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. + +- `.Axes.add_collection` +- `.Axes.add_image` +- `.Axes.add_line` +- `.Axes.add_patch` +- `.Axes.add_table` ``ConversionInterface.convert`` no longer accepts unitless values diff --git a/doc/api/next_api_changes/removals/24965-ES.rst b/doc/api/next_api_changes/removals/24965-ES.rst new file mode 100644 index 000000000000..96089f463e64 --- /dev/null +++ b/doc/api/next_api_changes/removals/24965-ES.rst @@ -0,0 +1,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. diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 0bf5b71860a0..d10b4e020056 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2203,20 +2203,6 @@ def has_data(self): mlines.Line2D, mpatches.Patch)) for a in self._children) - def _deprecate_noninstance(self, _name, _types, **kwargs): - """ - For each *key, value* pair in *kwargs*, check that *value* is an - instance of one of *_types*; if not, raise an appropriate deprecation. - """ - for key, value in kwargs.items(): - if not isinstance(value, _types): - _api.warn_deprecated( - '3.5', name=_name, - message=f'Passing argument *{key}* of unexpected type ' - f'{type(value).__qualname__} to %(name)s which only ' - f'accepts {_types} is deprecated since %(since)s and will ' - 'become an error %(removal)s.') - def add_artist(self, a): """ Add an `.Artist` to the Axes; return the artist. @@ -2260,8 +2246,7 @@ def add_collection(self, collection, autolim=True): """ Add a `.Collection` to the Axes; return the collection. """ - self._deprecate_noninstance('add_collection', mcoll.Collection, - collection=collection) + _api.check_isinstance(mcoll.Collection, collection=collection) label = collection.get_label() if not label: collection.set_label(f'_child{len(self._children)}') @@ -2294,7 +2279,7 @@ def add_image(self, image): """ Add an `.AxesImage` to the Axes; return the image. """ - self._deprecate_noninstance('add_image', mimage.AxesImage, image=image) + _api.check_isinstance(mimage.AxesImage, image=image) self._set_artist_props(image) if not image.get_label(): image.set_label(f'_child{len(self._children)}') @@ -2311,7 +2296,7 @@ def add_line(self, line): """ Add a `.Line2D` to the Axes; return the line. """ - self._deprecate_noninstance('add_line', mlines.Line2D, line=line) + _api.check_isinstance(mlines.Line2D, line=line) self._set_artist_props(line) if line.get_clip_path() is None: line.set_clip_path(self.patch) @@ -2328,7 +2313,7 @@ def _add_text(self, txt): """ Add a `.Text` to the Axes; return the text. """ - self._deprecate_noninstance('_add_text', mtext.Text, txt=txt) + _api.check_isinstance(mtext.Text, txt=txt) self._set_artist_props(txt) self._children.append(txt) txt._remove_method = self._children.remove @@ -2387,7 +2372,7 @@ def add_patch(self, p): """ Add a `.Patch` to the Axes; return the patch. """ - self._deprecate_noninstance('add_patch', mpatches.Patch, p=p) + _api.check_isinstance(mpatches.Patch, p=p) self._set_artist_props(p) if p.get_clip_path() is None: p.set_clip_path(self.patch) @@ -2440,7 +2425,7 @@ def add_table(self, tab): """ Add a `.Table` to the Axes; return the table. """ - self._deprecate_noninstance('add_table', mtable.Table, tab=tab) + _api.check_isinstance(mtable.Table, tab=tab) self._set_artist_props(tab) self._children.append(tab) tab.set_clip_path(self.patch) diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index 232fa10616b4..57cfa311b8f7 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -390,11 +390,8 @@ class NavigationToolbar2WebAgg(backend_bases.NavigationToolbar2): if name_of_method in _ALLOWED_TOOL_ITEMS ] - cursor = _api.deprecate_privatize_attribute("3.5") - def __init__(self, canvas): self.message = '' - self._cursor = None # Remove with deprecation. super().__init__(canvas) def set_message(self, message): diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 0a8b23251e6a..966eb0760b47 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -875,9 +875,7 @@ def _get_ticker_locator_formatter(self): self._minorlocator = minorlocator _log.debug('locator: %r', locator) - @_api.delete_parameter("3.5", "update_ticks") - def set_ticks(self, ticks, update_ticks=True, labels=None, *, - minor=False, **kwargs): + def set_ticks(self, ticks, *, labels=None, minor=False, **kwargs): """ Set tick locations. @@ -916,9 +914,7 @@ def get_ticks(self, minor=False): else: return self._long_axis().get_majorticklocs() - @_api.delete_parameter("3.5", "update_ticks") - def set_ticklabels(self, ticklabels, update_ticks=True, *, minor=False, - **kwargs): + def set_ticklabels(self, ticklabels, *, minor=False, **kwargs): """ [*Discouraged*] Set tick labels. diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index 76dbeb2addc5..4c4f2fdc240f 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -999,11 +999,13 @@ def test_check_radio_buttons_image(): rax1 = plt.axes([0.05, 0.7, 0.15, 0.15]) rax2 = plt.axes([0.05, 0.2, 0.15, 0.15]) rb = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3')) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The circles attribute was deprecated'): rb.circles # Trigger the old-style elliptic radiobuttons. cb = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'), (False, True, True)) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The rectangles attribute was deprecated'): cb.rectangles # Trigger old-style Rectangle check boxes @@ -1034,7 +1036,8 @@ def test_check_buttons_rectangles(fig_test, fig_ref): # Test should be removed once .rectangles is removed cb = widgets.CheckButtons(fig_test.subplots(), ["", ""], [False, False]) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The rectangles attribute was deprecated'): cb.rectangles ax = fig_ref.add_subplot(xticks=[], yticks=[]) ys = [2/3, 1/3] @@ -1056,7 +1059,8 @@ def test_check_buttons_rectangles(fig_test, fig_ref): def test_check_buttons_lines(fig_test, fig_ref): # Test should be removed once .lines is removed cb = widgets.CheckButtons(fig_test.subplots(), ["", ""], [True, True]) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, + match='The lines attribute was deprecated'): cb.lines for rectangle in cb._rectangles: rectangle.set_visible(False) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 745f57f10ec5..1dc1dd5f77ae 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -1192,8 +1192,8 @@ def lines(self): l1.set_visible(current_status[i]) l2.set_visible(current_status[i]) self._lines.append((l1, l2)) - self.ax.add_patch(l1) - self.ax.add_patch(l2) + self.ax.add_line(l1) + self.ax.add_line(l2) if not hasattr(self, "_rectangles"): with _api.suppress_matplotlib_deprecation_warning(): _ = self.rectangles From 239a93c27fe45eeeca2735165b117db54a4c2100 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 13 Jan 2023 13:51:25 -0500 Subject: [PATCH 216/262] Backport PR #24973: MNT: Fix double % signs in matplotlibrc --- lib/matplotlib/mpl-data/matplotlibrc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index 28dad0f392a5..26c78658f4e0 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -237,7 +237,7 @@ ## ## The font.variant property has two values: normal or small-caps. For ## TrueType fonts, which are scalable fonts, small-caps is equivalent -## to using a font size of 'smaller', or about 83%% of the current font +## to using a font size of 'smaller', or about 83 % of the current font ## size. ## ## The font.weight property has effectively 13 values: normal, bold, @@ -445,9 +445,9 @@ ## These control the default format strings used in AutoDateFormatter. ## Any valid format datetime format string can be used (see the python ## `datetime` for details). For example, by using: -## - '%%x' will use the locale date representation -## - '%%X' will use the locale time representation -## - '%%c' will use the full locale datetime representation +## - '%x' will use the locale date representation +## - '%X' will use the locale time representation +## - '%c' will use the full locale datetime representation ## These values map to the scales: ## {'year': 365, 'month': 30, 'day': 1, 'hour': 1/24, 'minute': 1 / (24 * 60)} From 11fdbbda7647683a3600341ab91ff1e0604121e1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 13 Jan 2023 14:29:17 -0500 Subject: [PATCH 217/262] Backport PR #24971: FIX: adjust_bbox should not modify layout engine --- lib/matplotlib/_tight_bbox.py | 3 --- lib/matplotlib/tests/test_figure.py | 7 +++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/_tight_bbox.py b/lib/matplotlib/_tight_bbox.py index b2147b960735..e0fba389d120 100644 --- a/lib/matplotlib/_tight_bbox.py +++ b/lib/matplotlib/_tight_bbox.py @@ -17,8 +17,6 @@ def adjust_bbox(fig, bbox_inches, fixed_dpi=None): """ origBbox = fig.bbox origBboxInches = fig.bbox_inches - orig_layout = fig.get_layout_engine() - fig.set_layout_engine(None) _boxout = fig.transFigure._boxout old_aspect = [] @@ -46,7 +44,6 @@ def restore_bbox(): fig.bbox = origBbox fig.bbox_inches = origBboxInches - fig.set_layout_engine(orig_layout) fig.transFigure._boxout = _boxout fig.transFigure.invalidate() fig.patch.set_bounds(0, 0, 1, 1) diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 065e0f728536..f3ece07660e3 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -532,6 +532,13 @@ def test_savefig_pixel_ratio(backend): assert ratio1 == ratio2 +def test_savefig_preserve_layout_engine(tmp_path): + fig = plt.figure(layout='compressed') + fig.savefig(tmp_path / 'foo.png', bbox_inches='tight') + + assert fig.get_layout_engine()._compress + + def test_figure_repr(): fig = plt.figure(figsize=(10, 20), dpi=10) assert repr(fig) == "
" From bbedbf9a9326e4861520045687aff4986ae0a438 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 13 Jan 2023 20:17:17 -0500 Subject: [PATCH 218/262] Backport PR #24970: FIX: Handle uint8 indices properly for colormap lookups --- lib/matplotlib/colors.py | 21 +++++++++++---------- lib/matplotlib/tests/test_colors.py | 7 +++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 2d3072da04de..ab0d73c4b5fb 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -715,16 +715,17 @@ def __call__(self, X, alpha=None, bytes=False): if not xa.dtype.isnative: xa = xa.byteswap().newbyteorder() # Native byteorder is faster. if xa.dtype.kind == "f": - with np.errstate(invalid="ignore"): - xa *= self.N - # Negative values are out of range, but astype(int) would - # truncate them towards zero. - xa[xa < 0] = -1 - # xa == 1 (== N after multiplication) is not out of range. - xa[xa == self.N] = self.N - 1 - # Avoid converting large positive values to negative integers. - np.clip(xa, -1, self.N, out=xa) - xa = xa.astype(int) + xa *= self.N + # Negative values are out of range, but astype(int) would + # truncate them towards zero. + xa[xa < 0] = -1 + # xa == 1 (== N after multiplication) is not out of range. + xa[xa == self.N] = self.N - 1 + # Avoid converting large positive values to negative integers. + np.clip(xa, -1, self.N, out=xa) + with np.errstate(invalid="ignore"): + # We need this cast for unsigned ints as well as floats + xa = xa.astype(int) # Set the over-range indices before the under-range; # otherwise the under-range values get converted to over-range. xa[xa > self.N - 1] = self._i_over diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index ff893e71acdb..a5809f0fa89f 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -30,6 +30,13 @@ def test_create_lookup_table(N, result): assert_array_almost_equal(mcolors._create_lookup_table(N, data), result) +@pytest.mark.parametrize("dtype", [np.uint8, int, np.float16, float]) +def test_index_dtype(dtype): + # We use subtraction in the indexing, so need to verify that uint8 works + cm = mpl.colormaps["viridis"] + assert_array_equal(cm(dtype(0)), cm(0)) + + def test_resampled(): """ GitHub issue #6025 pointed to incorrect ListedColormap.resampled; From 1b9750c98c25212f80517ff09ad23d8f2c2c0a50 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Mon, 16 Jan 2023 07:48:24 -0800 Subject: [PATCH 219/262] Backport PR #25000: Update matplotlibrc urls --- lib/matplotlib/mpl-data/matplotlibrc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index 26c78658f4e0..2380eaff2d24 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -111,7 +111,7 @@ ## *************************************************************************** ## * LINES * ## *************************************************************************** -## See https://matplotlib.org/api/artist_api.html#module-matplotlib.lines +## See https://matplotlib.org/stable/api/artist_api.html#module-matplotlib.lines ## for more information on line properties. #lines.linewidth: 1.5 # line width in points #lines.linestyle: - # solid line @@ -144,7 +144,7 @@ ## * PATCHES * ## *************************************************************************** ## Patches are graphical objects that fill 2D space, like polygons or circles. -## See https://matplotlib.org/api/artist_api.html#module-matplotlib.patches +## See https://matplotlib.org/stable/api/artist_api.html#module-matplotlib.patches ## for more information on patch properties. #patch.linewidth: 1.0 # edge width in points. #patch.facecolor: C0 @@ -212,7 +212,7 @@ ## * FONT * ## *************************************************************************** ## The font properties used by `text.Text`. -## See https://matplotlib.org/api/font_manager_api.html for more information +## See https://matplotlib.org/stable/api/font_manager_api.html for more information ## on font properties. The 6 font properties used for font matching are ## given below with their default values. ## @@ -277,7 +277,7 @@ ## * TEXT * ## *************************************************************************** ## The text properties used by `text.Text`. -## See https://matplotlib.org/api/artist_api.html#module-matplotlib.text +## See https://matplotlib.org/stable/api/artist_api.html#module-matplotlib.text ## for more information on text properties #text.color: black @@ -309,7 +309,7 @@ ## * LaTeX * ## *************************************************************************** ## For more information on LaTeX properties, see -## https://matplotlib.org/tutorials/text/usetex.html +## https://matplotlib.org/stable/tutorials/text/usetex.html #text.usetex: False # use latex for all text handling. The following fonts # are supported through the usual rc parameter settings: # new century schoolbook, bookman, times, palatino, @@ -361,7 +361,7 @@ ## *************************************************************************** ## Following are default face and edge colors, default tick sizes, ## default font sizes for tick labels, and so on. See -## https://matplotlib.org/api/axes_api.html#module-matplotlib.axes +## https://matplotlib.org/stable/api/axes_api.html#module-matplotlib.axes #axes.facecolor: white # axes background color #axes.edgecolor: black # axes edge color #axes.linewidth: 0.8 # edge line width @@ -417,7 +417,7 @@ # As opposed to all other parameters in this file, the color # values must be enclosed in quotes for this parameter, # e.g. '1f77b4', instead of 1f77b4. - # See also https://matplotlib.org/tutorials/intermediate/color_cycle.html + # See also https://matplotlib.org/stable/tutorials/intermediate/color_cycle.html # for more details on prop_cycle usage. #axes.xmargin: .05 # x margin. See `axes.Axes.margins` #axes.ymargin: .05 # y margin. See `axes.Axes.margins` @@ -459,7 +459,7 @@ #date.autoformatter.second: %H:%M:%S #date.autoformatter.microsecond: %M:%S.%f ## The reference date for Matplotlib's internal date representation -## See https://matplotlib.org/examples/ticks_and_spines/date_precision_and_epochs.py +## See https://matplotlib.org/stable/gallery/ticks/date_precision_and_epochs.html #date.epoch: 1970-01-01T00:00:00 ## 'auto', 'concise': #date.converter: auto @@ -469,7 +469,7 @@ ## *************************************************************************** ## * TICKS * ## *************************************************************************** -## See https://matplotlib.org/api/axis_api.html#matplotlib.axis.Tick +## See https://matplotlib.org/stable/api/axis_api.html#matplotlib.axis.Tick #xtick.top: False # draw ticks on the top side #xtick.bottom: True # draw ticks on the bottom side #xtick.labeltop: False # draw label on the top @@ -553,7 +553,7 @@ ## *************************************************************************** ## * FIGURE * ## *************************************************************************** -## See https://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure +## See https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure #figure.titlesize: large # size of the figure title (``Figure.suptitle()``) #figure.titleweight: normal # weight of the figure title #figure.labelsize: large # size of the figure label (``Figure.sup[x|y]label()``) @@ -726,7 +726,7 @@ #svg.hashsalt: None # If not None, use this string as hash salt instead of uuid4 ### pgf parameter -## See https://matplotlib.org/tutorials/text/pgf.html for more information. +## See https://matplotlib.org/stable/tutorials/text/pgf.html for more information. #pgf.rcfonts: True #pgf.preamble: # See text.latex.preamble for documentation #pgf.texsystem: xelatex From bb1511abd38f2bb8314c39a204e923d647c1cd71 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 16 Jan 2023 18:04:06 -0500 Subject: [PATCH 220/262] Backport PR #25004: Bump pypa/cibuildwheel from 2.11.4 to 2.12.0 --- .github/workflows/cibuildwheel.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 9e55193f82d2..982536ec73ec 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -62,7 +62,7 @@ jobs: fetch-depth: 0 - name: Build wheels for CPython 3.11 - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BUILD: "cp311-*" CIBW_SKIP: "*-musllinux*" @@ -75,7 +75,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.10 - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BUILD: "cp310-*" CIBW_SKIP: "*-musllinux*" @@ -88,7 +88,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.9 - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BUILD: "cp39-*" CIBW_SKIP: "*-musllinux*" @@ -114,7 +114,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for PyPy - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BUILD: "pp38-* pp39-*" CIBW_SKIP: "*-musllinux*" From 567dfa085f44a42859dad7a9e7ec94ce9d77aae8 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 16 Jan 2023 18:54:10 -0600 Subject: [PATCH 221/262] Backport PR #24989: Suppress pyparsing warning --- lib/matplotlib/_fontconfig_pattern.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/_fontconfig_pattern.py b/lib/matplotlib/_fontconfig_pattern.py index efc1c9304f52..f0ed155c2d62 100644 --- a/lib/matplotlib/_fontconfig_pattern.py +++ b/lib/matplotlib/_fontconfig_pattern.py @@ -13,7 +13,7 @@ import re from pyparsing import ( - Optional, ParseException, Regex, StringEnd, Suppress, ZeroOrMore) + Group, Optional, ParseException, Regex, StringEnd, Suppress, ZeroOrMore) from matplotlib import _api @@ -64,7 +64,7 @@ def comma_separated(elem): name = Regex(r"[a-z]+") value = Regex(r"([^%s]|(\\[%s]))*" % (_value_punc, _value_punc)) # replace trailing `| name` by oneOf(_CONSTANTS) in mpl 3.9. - prop = (name + Suppress("=") + comma_separated(value)) | name + prop = Group((name + Suppress("=") + comma_separated(value)) | name) return ( Optional(comma_separated(family)("families")) + Optional("-" + comma_separated(size)("sizes")) From 383587fd3704219fbb6cb99718895610aa916f75 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 18 Jan 2023 20:58:07 -0500 Subject: [PATCH 222/262] Backport PR #25017: Capitalize headings in example Gallery --- examples/axes_grid1/README.txt | 4 ++-- examples/axisartist/README.txt | 4 ++-- examples/pyplots/README.txt | 4 ++-- examples/specialty_plots/README.txt | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/axes_grid1/README.txt b/examples/axes_grid1/README.txt index e9afa00b9a72..42cc4b5af75c 100644 --- a/examples/axes_grid1/README.txt +++ b/examples/axes_grid1/README.txt @@ -2,5 +2,5 @@ .. _axes_grid1-examples-index: -axes_grid1 -========== +The axes_grid1 module +===================== diff --git a/examples/axisartist/README.txt b/examples/axisartist/README.txt index dc7c87d3a608..6cc9325d1027 100644 --- a/examples/axisartist/README.txt +++ b/examples/axisartist/README.txt @@ -2,5 +2,5 @@ .. _axisartist-examples-index: -axisartist -========== +The axisartist module +===================== diff --git a/examples/pyplots/README.txt b/examples/pyplots/README.txt index 30c7d60fdb36..ff10c9fd6b1a 100644 --- a/examples/pyplots/README.txt +++ b/examples/pyplots/README.txt @@ -1,4 +1,4 @@ .. _pyplots_examples: -pyplot -====== +The pyplot module +================= diff --git a/examples/specialty_plots/README.txt b/examples/specialty_plots/README.txt index d186022d93db..fc1bf44d3b92 100644 --- a/examples/specialty_plots/README.txt +++ b/examples/specialty_plots/README.txt @@ -1,4 +1,4 @@ .. _specialty_plots_examples: -Specialty Plots +Specialty plots =============== From fca4a5f6f8df0f620f77536f5a8d747da414001f Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 19 Jan 2023 10:40:05 +0100 Subject: [PATCH 223/262] Backport PR #25019: Tweak titles pyplot examples. --- .flake8 | 1 + examples/pyplots/axline.py | 1 + examples/pyplots/pyplot_mathtext.py | 30 ------------------- examples/pyplots/pyplot_simple.py | 12 ++++---- examples/pyplots/pyplot_text.py | 38 ++++++++++++------------- examples/pyplots/pyplot_three.py | 9 +++--- examples/pyplots/pyplot_two_subplots.py | 9 +++--- tutorials/text/mathtext.py | 4 +-- 8 files changed, 39 insertions(+), 65 deletions(-) delete mode 100644 examples/pyplots/pyplot_mathtext.py diff --git a/.flake8 b/.flake8 index a7b8a4464424..ef1333dbf4c0 100644 --- a/.flake8 +++ b/.flake8 @@ -84,6 +84,7 @@ per-file-ignores = tutorials/introductory/quick_start.py: E703 tutorials/introductory/animation_tutorial.py: E501 tutorials/text/annotations.py: E402, E501 + tutorials/text/mathtext.py: E501 tutorials/text/text_intro.py: E402 tutorials/text/text_props.py: E501 tutorials/text/usetex.py: E501 diff --git a/examples/pyplots/axline.py b/examples/pyplots/axline.py index 68149eaafc4f..5da9dc1a68ef 100644 --- a/examples/pyplots/axline.py +++ b/examples/pyplots/axline.py @@ -10,6 +10,7 @@ `~.axes.Axes.axline` draws infinite straight lines in arbitrary directions. """ + import numpy as np import matplotlib.pyplot as plt diff --git a/examples/pyplots/pyplot_mathtext.py b/examples/pyplots/pyplot_mathtext.py deleted file mode 100644 index a62dd6d95da0..000000000000 --- a/examples/pyplots/pyplot_mathtext.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -=============== -Pyplot Mathtext -=============== - -Use mathematical expressions in text labels. For an overview over MathText -see :doc:`/tutorials/text/mathtext`. -""" -import numpy as np -import matplotlib.pyplot as plt -t = np.arange(0.0, 2.0, 0.01) -s = np.sin(2*np.pi*t) - -plt.plot(t, s) -plt.title(r'$\alpha_i > \beta_i$', fontsize=20) -plt.text(1, -0.6, r'$\sum_{i=0}^\infty x_i$', fontsize=20) -plt.text(0.6, 0.6, r'$\mathcal{A}\mathrm{sin}(2 \omega t)$', - fontsize=20) -plt.xlabel('Time [s]') -plt.ylabel('Voltage [mV]') -plt.show() - -############################################################################# -# -# .. admonition:: References -# -# The use of the following functions, methods, classes and modules is shown -# in this example: -# -# - `matplotlib.axes.Axes.text` / `matplotlib.pyplot.text` diff --git a/examples/pyplots/pyplot_simple.py b/examples/pyplots/pyplot_simple.py index 1a3b457acedd..096323b626dc 100644 --- a/examples/pyplots/pyplot_simple.py +++ b/examples/pyplots/pyplot_simple.py @@ -1,16 +1,16 @@ """ -============= -Pyplot Simple -============= +=========== +Simple plot +=========== -A very simple pyplot where a list of numbers are plotted against their -index. Creates a straight line due to the rate of change being 1 for -both the X and Y axis. Use a format string (here, 'o-r') to set the +A simple plot where a list of numbers are plotted against their index, +resulting in a straight line. Use a format string (here, 'o-r') to set the markers (circles), linestyle (solid line) and color (red). .. redirect-from:: /gallery/pyplots/fig_axes_labels_simple .. redirect-from:: /gallery/pyplots/pyplot_formatstr """ + import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4], 'o-r') diff --git a/examples/pyplots/pyplot_text.py b/examples/pyplots/pyplot_text.py index e50e9038827a..00e738ef414b 100644 --- a/examples/pyplots/pyplot_text.py +++ b/examples/pyplots/pyplot_text.py @@ -1,29 +1,29 @@ """ -=========== -Pyplot Text -=========== +============================== +Text and mathtext using pyplot +============================== -""" -import numpy as np -import matplotlib.pyplot as plt +Set the special text objects `~.pyplot.title`, `~.pyplot.xlabel`, and +`~.pyplot.ylabel` through the dedicated pyplot functions. Additional text +objects can be placed in the axes using `~.pyplot.text`. -# Fixing random state for reproducibility -np.random.seed(19680801) +You can use TeX-like mathematical typesetting in all texts; see also +:doc:`/tutorials/text/mathtext`. -mu, sigma = 100, 15 -x = mu + sigma * np.random.randn(10000) +.. redirect-from:: /gallery/pyplots/pyplot_mathtext +""" -# the histogram of the data -n, bins, patches = plt.hist(x, 50, density=True, facecolor='g', alpha=0.75) +import numpy as np +import matplotlib.pyplot as plt +t = np.arange(0.0, 2.0, 0.01) +s = np.sin(2*np.pi*t) -plt.xlabel('Smarts') -plt.ylabel('Probability') -plt.title('Histogram of IQ') -plt.text(60, .025, r'$\mu=100,\ \sigma=15$') -plt.xlim(40, 160) -plt.ylim(0, 0.03) -plt.grid(True) +plt.plot(t, s) +plt.text(0, -1, r'Hello, world!', fontsize=15) +plt.title(r'$\mathcal{A}\sin(\omega t)$', fontsize=20) +plt.xlabel('Time [s]') +plt.ylabel('Voltage [mV]') plt.show() ############################################################################# diff --git a/examples/pyplots/pyplot_three.py b/examples/pyplots/pyplot_three.py index 476796b45f81..7dfcddb7bb94 100644 --- a/examples/pyplots/pyplot_three.py +++ b/examples/pyplots/pyplot_three.py @@ -1,10 +1,11 @@ """ -============ -Pyplot Three -============ +=========================== +Multiple lines using pyplot +=========================== -Plot three line plots in a single call to `~matplotlib.pyplot.plot`. +Plot three datasets with a single call to `~matplotlib.pyplot.plot`. """ + import numpy as np import matplotlib.pyplot as plt diff --git a/examples/pyplots/pyplot_two_subplots.py b/examples/pyplots/pyplot_two_subplots.py index 5280fb0bb37a..d316da2fc930 100644 --- a/examples/pyplots/pyplot_two_subplots.py +++ b/examples/pyplots/pyplot_two_subplots.py @@ -1,10 +1,11 @@ """ -=================== -Pyplot Two Subplots -=================== +========================= +Two subplots using pyplot +========================= -Create a figure with two subplots with `.pyplot.subplot`. +Create a figure with two subplots using `.pyplot.subplot`. """ + import numpy as np import matplotlib.pyplot as plt diff --git a/tutorials/text/mathtext.py b/tutorials/text/mathtext.py index 72a2cebb2b2c..2be0d67ca3b0 100644 --- a/tutorials/text/mathtext.py +++ b/tutorials/text/mathtext.py @@ -354,7 +354,7 @@ ------- Here is an example illustrating many of these features in context. -.. figure:: ../../gallery/pyplots/images/sphx_glr_pyplot_mathtext_001.png - :target: ../../gallery/pyplots/pyplot_mathtext.html +.. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_mathtext_demo_001.png + :target: ../../gallery/text_labels_and_annotations/mathtext_demo.html :align: center """ From dd2c3fb55acd4aaef88e42637b4b6e3c710ae1f5 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 19 Jan 2023 20:53:44 -0500 Subject: [PATCH 224/262] Backport PR #24812: [Doc] expanded basic pie example --- examples/pie_and_polar_charts/pie_features.py | 108 ++++++++++++++---- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/examples/pie_and_polar_charts/pie_features.py b/examples/pie_and_polar_charts/pie_features.py index d25ce839bf62..d27ed6a03545 100644 --- a/examples/pie_and_polar_charts/pie_features.py +++ b/examples/pie_and_polar_charts/pie_features.py @@ -1,40 +1,100 @@ """ -=============== -Basic pie chart -=============== +========== +Pie charts +========== -Demo of a basic pie chart plus a few additional features. +Demo of plotting a pie chart. -In addition to the basic pie chart, this demo shows a few optional features: - -* slice labels -* auto-labeling the percentage -* offsetting a slice with "explode" -* drop-shadow -* custom start angle +This example illustrates various parameters of `~matplotlib.axes.Axes.pie`. +""" -Note about the custom start angle: +# %% +# Label slices +# ------------ +# +# Plot a pie chart of animals and label the slices. To add +# labels, pass a list of labels to the *labels* parameter -The default ``startangle`` is 0, which would start the "Frogs" slice on the -positive x-axis. This example sets ``startangle = 90`` such that everything is -rotated counter-clockwise by 90 degrees, and the frog slice starts on the -positive y-axis. -""" import matplotlib.pyplot as plt - -# Pie chart, where the slices will be ordered and plotted counter-clockwise: labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' sizes = [15, 30, 45, 10] + +fig, ax = plt.subplots() +ax.pie(sizes, labels=labels) + +# %% +# Each slice of the pie chart is a `.patches.Wedge` object; therefore in +# addition to the customizations shown here, each wedge can be customized using +# the *wedgeprops* argument, as demonstrated in +# :doc:`/gallery/pie_and_polar_charts/nested_pie`. +# +# Auto-label slices +# ----------------- +# +# Pass a function or format string to *autopct* to label slices. + +fig, ax = plt.subplots() +ax.pie(sizes, labels=labels, autopct='%1.1f%%') + +# %% +# By default, the label values are obtained from the percent size of the slice. +# +# Color slices +# ------------ +# +# Pass a list of colors to *colors* to set the color of each slice. + +fig, ax = plt.subplots() +ax.pie(sizes, labels=labels, + colors=['olivedrab', 'rosybrown', 'gray', 'saddlebrown']) + +# %% +# Hatch slices +# ------------ +# +# Pass a list of hatch patterns to *hatch* to set the pattern of each slice. + +fig, ax = plt.subplots() +ax.pie(sizes, labels=labels, hatch=['**O', 'oO', 'O.O', '.||.']) + +# %% +# Swap label and autopct text positions +# ------------------------------------- +# Use the *labeldistance* and *pctdistance* parameters to position the *labels* +# and *autopct* text respectively. + +fig, ax = plt.subplots() +ax.pie(sizes, labels=labels, autopct='%1.1f%%', + pctdistance=1.25, labeldistance=.6) + +# %% +# *labeldistance* and *pctdistance* are ratios of the radius; therefore they +# vary between ``0`` for the center of the pie and ``1`` for the edge of the +# pie, and can be set to greater than ``1`` to place text outside the pie. +# +# Explode, shade, and rotate slices +# --------------------------------- +# +# In addition to the basic pie chart, this demo shows a few optional features: +# +# * offsetting a slice using *explode* +# * add a drop-shadow using *shadow* +# * custom start angle using *startangle* +# +# This example orders the slices, separates (explodes) them, and rotates them. + explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs') -fig1, ax1 = plt.subplots() -ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', +fig, ax = plt.subplots() +ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90) -ax1.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle. - plt.show() -############################################################################# +# %% +# The default *startangle* is 0, which would start the first slice ("Frogs") on +# the positive x-axis. This example sets ``startangle = 90`` such that all the +# slices are rotated counter-clockwise by 90 degrees, and the frog slice starts +# on the positive y-axis. # # .. admonition:: References # From 162444e927003e2bce89020b25e2f0ef80ad14ce Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 20 Jan 2023 04:15:54 -0500 Subject: [PATCH 225/262] Backport PR #25018: Simplify "artist reference" example. --- .../artist_reference.py | 120 +++++------------- .../patch_collection.py | 3 + 2 files changed, 37 insertions(+), 86 deletions(-) diff --git a/examples/shapes_and_collections/artist_reference.py b/examples/shapes_and_collections/artist_reference.py index 054c1f1e088a..4ab6d67c0542 100644 --- a/examples/shapes_and_collections/artist_reference.py +++ b/examples/shapes_and_collections/artist_reference.py @@ -3,66 +3,25 @@ Reference for Matplotlib artists ================================ -This example displays several of Matplotlib's graphics primitives (artists) -drawn using matplotlib API. A full list of artists and the documentation is -available at :ref:`the artist API `. +This example displays several of Matplotlib's graphics primitives (artists). +A full list of artists is documented at :ref:`the artist API `. + +See also :doc:`/gallery/shapes_and_collections/patch_collection`, which groups +all artists into a single `.PatchCollection` instead. Copyright (c) 2010, Bartosz Telenczuk BSD License """ -import matplotlib.pyplot as plt -import numpy as np -import matplotlib.path as mpath + +import matplotlib as mpl import matplotlib.lines as mlines import matplotlib.patches as mpatches -from matplotlib.collections import PatchCollection - - -def label(xy, text): - y = xy[1] - 0.15 # shift y-value for label so that it's below the artist - plt.text(xy[0], y, text, ha="center", family='sans-serif', size=14) - - -fig, ax = plt.subplots() -# create 3x3 grid to plot the artists -grid = np.mgrid[0.2:0.8:3j, 0.2:0.8:3j].reshape(2, -1).T - -patches = [] - -# add a circle -circle = mpatches.Circle(grid[0], 0.1, ec="none") -patches.append(circle) -label(grid[0], "Circle") - -# add a rectangle -rect = mpatches.Rectangle(grid[1] - [0.025, 0.05], 0.05, 0.1, ec="none") -patches.append(rect) -label(grid[1], "Rectangle") - -# add a wedge -wedge = mpatches.Wedge(grid[2], 0.1, 30, 270, ec="none") -patches.append(wedge) -label(grid[2], "Wedge") - -# add a Polygon -polygon = mpatches.RegularPolygon(grid[3], 5, radius=0.1) -patches.append(polygon) -label(grid[3], "Polygon") - -# add an ellipse -ellipse = mpatches.Ellipse(grid[4], 0.2, 0.1) -patches.append(ellipse) -label(grid[4], "Ellipse") - -# add an arrow -arrow = mpatches.Arrow(grid[5, 0] - 0.05, grid[5, 1] - 0.05, 0.1, 0.1, - width=0.1) -patches.append(arrow) -label(grid[5], "Arrow") +import matplotlib.path as mpath +import matplotlib.pyplot as plt -# add a path patch +# Prepare the data for the PathPatch below. Path = mpath.Path -path_data = [ +codes, verts = zip(*[ (Path.MOVETO, [0.018, -0.11]), (Path.CURVE4, [-0.031, -0.051]), (Path.CURVE4, [-0.115, 0.073]), @@ -71,35 +30,28 @@ def label(xy, text): (Path.CURVE4, [0.043, 0.121]), (Path.CURVE4, [0.075, -0.005]), (Path.CURVE4, [0.035, -0.027]), - (Path.CLOSEPOLY, [0.018, -0.11])] -codes, verts = zip(*path_data) -path = mpath.Path(verts + grid[6], codes) -patch = mpatches.PathPatch(path) -patches.append(patch) -label(grid[6], "PathPatch") - -# add a fancy box -fancybox = mpatches.FancyBboxPatch( - grid[7] - [0.025, 0.05], 0.05, 0.1, - boxstyle=mpatches.BoxStyle("Round", pad=0.02)) -patches.append(fancybox) -label(grid[7], "FancyBboxPatch") - -# add a line -x, y = ([-0.06, 0.0, 0.1], [0.05, -0.05, 0.05]) -line = mlines.Line2D(x + grid[8, 0], y + grid[8, 1], lw=5., alpha=0.3) -label(grid[8], "Line2D") - -colors = np.linspace(0, 1, len(patches)) -collection = PatchCollection(patches, cmap=plt.cm.hsv, alpha=0.3) -collection.set_array(colors) -ax.add_collection(collection) -ax.add_line(line) - -plt.axis('equal') -plt.axis('off') -plt.tight_layout() - + (Path.CLOSEPOLY, [0.018, -0.11])]) + +artists = [ + mpatches.Circle((0, 0), 0.1, ec="none"), + mpatches.Rectangle((-0.025, -0.05), 0.05, 0.1, ec="none"), + mpatches.Wedge((0, 0), 0.1, 30, 270, ec="none"), + mpatches.RegularPolygon((0, 0), 5, radius=0.1), + mpatches.Ellipse((0, 0), 0.2, 0.1), + mpatches.Arrow(-0.05, -0.05, 0.1, 0.1, width=0.1), + mpatches.PathPatch(mpath.Path(verts, codes), ec="none"), + mpatches.FancyBboxPatch((-0.025, -0.05), 0.05, 0.1, ec="none", + boxstyle=mpatches.BoxStyle("Round", pad=0.02)), + mlines.Line2D([-0.06, 0.0, 0.1], [0.05, -0.05, 0.05], lw=5), +] + +axs = plt.figure(figsize=(6, 6), layout="constrained").subplots(3, 3) +for i, (ax, artist) in enumerate(zip(axs.flat, artists)): + artist.set(color=mpl.colormaps["hsv"](i / len(artists))) + ax.add_artist(artist) + ax.set(title=type(artist).__name__, + aspect=1, xlim=(-.2, .2), ylim=(-.2, .2)) + ax.set_axis_off() plt.show() ############################################################################# @@ -122,8 +74,4 @@ def label(xy, text): # - `matplotlib.patches.PathPatch` # - `matplotlib.patches.FancyBboxPatch` # - `matplotlib.patches.RegularPolygon` -# - `matplotlib.collections` -# - `matplotlib.collections.PatchCollection` -# - `matplotlib.cm.ScalarMappable.set_array` -# - `matplotlib.axes.Axes.add_collection` -# - `matplotlib.axes.Axes.add_line` +# - `matplotlib.axes.Axes.add_artist` diff --git a/examples/shapes_and_collections/patch_collection.py b/examples/shapes_and_collections/patch_collection.py index cdd9f4687619..98533c451cd1 100644 --- a/examples/shapes_and_collections/patch_collection.py +++ b/examples/shapes_and_collections/patch_collection.py @@ -4,6 +4,9 @@ ============================ This example demonstrates how to use `.collections.PatchCollection`. + +See also :doc:`/gallery/shapes_and_collections/artist_reference`, which instead +adds each artist separately to its own axes. """ import numpy as np From 2273b6bc1d36554955dfb54b58201b043533dd90 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 21 Jan 2023 08:18:41 +0100 Subject: [PATCH 226/262] Backport PR #25047: Remove dead code from deprecated-and-removed block --- lib/matplotlib/widgets.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 1dc1dd5f77ae..f3f99b3753af 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -3344,12 +3344,6 @@ def _rect_bbox(self): def _set_aspect_ratio_correction(self): aspect_ratio = self.ax._get_aspect_ratio() - if not hasattr(self._selection_artist, '_aspect_ratio_correction'): - # Aspect ratio correction is not supported with deprecated - # drawtype='line'. Remove this block in matplotlib 3.7 - self._aspect_ratio_correction = 1 - return - self._selection_artist._aspect_ratio_correction = aspect_ratio if self._use_data_coordinates: self._aspect_ratio_correction = 1 From b5083a5b95ba59b80a168140edf64d68040b7758 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sun, 22 Jan 2023 00:26:57 +0100 Subject: [PATCH 227/262] Backport PR #25055: Reword awkward sentence in FAQ. --- doc/users/faq/howto_faq.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/users/faq/howto_faq.rst b/doc/users/faq/howto_faq.rst index 4ea220d969b0..fd4e81f32d00 100644 --- a/doc/users/faq/howto_faq.rst +++ b/doc/users/faq/howto_faq.rst @@ -89,8 +89,8 @@ way of defining empty, and checking the above is only rarely necessary. Usually the user or program handling the figure know if they have added something to the figure. -Checking whether a figure would render empty cannot be reliably checked except -by actually rendering the figure and investigating the rendered result. +The only reliable way to check whether a figure would render empty is to +actually perform such a rendering and inspect the result. .. _howto-findobj: From c7db8e1945cadc4d5fc9294c9626335a6c0c9d00 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 23 Jan 2023 15:00:09 -0600 Subject: [PATCH 228/262] Backport PR #24838: Add styling support to Check and Radio buttons --- .../next_whats_new/widget_button_styling.rst | 31 ++ examples/widgets/check_buttons.py | 12 +- examples/widgets/radio_buttons.py | 20 +- .../test_widgets/check_radio_buttons.png | Bin 14567 -> 24315 bytes lib/matplotlib/tests/test_widgets.py | 95 +++++- lib/matplotlib/widgets.py | 318 +++++++++++++++--- 6 files changed, 408 insertions(+), 68 deletions(-) create mode 100644 doc/users/next_whats_new/widget_button_styling.rst diff --git a/doc/users/next_whats_new/widget_button_styling.rst b/doc/users/next_whats_new/widget_button_styling.rst new file mode 100644 index 000000000000..4307e6977fc5 --- /dev/null +++ b/doc/users/next_whats_new/widget_button_styling.rst @@ -0,0 +1,31 @@ +Custom styling of button widgets +-------------------------------- + +Additional custom styling of button widgets may be achieved via the +*label_props* and *radio_props* arguments to `.RadioButtons`; and the +*label_props*, *frame_props*, and *check_props* arguments to `.CheckButtons`. + +.. plot:: + + from matplotlib.widgets import CheckButtons, RadioButtons + + fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(5, 2), width_ratios=[1, 2]) + default_rb = RadioButtons(ax[0, 0], ['Apples', 'Oranges']) + styled_rb = RadioButtons(ax[0, 1], ['Apples', 'Oranges'], + label_props={'color': ['red', 'orange'], + 'fontsize': [16, 20]}, + radio_props={'edgecolor': ['red', 'orange'], + 'facecolor': ['mistyrose', 'peachpuff']}) + + default_cb = CheckButtons(ax[1, 0], ['Apples', 'Oranges'], + actives=[True, True]) + styled_cb = CheckButtons(ax[1, 1], ['Apples', 'Oranges'], + actives=[True, True], + label_props={'color': ['red', 'orange'], + 'fontsize': [16, 20]}, + frame_props={'edgecolor': ['red', 'orange'], + 'facecolor': ['mistyrose', 'peachpuff']}, + check_props={'color': ['darkred', 'darkorange']}) + + ax[0, 0].set_title('Default') + ax[0, 1].set_title('Stylized') diff --git a/examples/widgets/check_buttons.py b/examples/widgets/check_buttons.py index 493ac4c3e79a..b96ffb51c0af 100644 --- a/examples/widgets/check_buttons.py +++ b/examples/widgets/check_buttons.py @@ -20,19 +20,23 @@ s2 = np.sin(6*np.pi*t) fig, ax = plt.subplots() -l0, = ax.plot(t, s0, visible=False, lw=2, color='k', label='2 Hz') -l1, = ax.plot(t, s1, lw=2, color='r', label='4 Hz') -l2, = ax.plot(t, s2, lw=2, color='g', label='6 Hz') +l0, = ax.plot(t, s0, visible=False, lw=2, color='black', label='1 Hz') +l1, = ax.plot(t, s1, lw=2, color='red', label='2 Hz') +l2, = ax.plot(t, s2, lw=2, color='green', label='3 Hz') fig.subplots_adjust(left=0.2) lines_by_label = {l.get_label(): l for l in [l0, l1, l2]} +line_colors = [l.get_color() for l in lines_by_label.values()] # Make checkbuttons with all plotted lines with correct visibility rax = fig.add_axes([0.05, 0.4, 0.1, 0.15]) check = CheckButtons( ax=rax, labels=lines_by_label.keys(), - actives=[l.get_visible() for l in lines_by_label.values()] + actives=[l.get_visible() for l in lines_by_label.values()], + label_props={'color': line_colors}, + frame_props={'edgecolor': line_colors}, + check_props={'facecolor': line_colors}, ) diff --git a/examples/widgets/radio_buttons.py b/examples/widgets/radio_buttons.py index 28e446fc5b80..4d3c93e579b6 100644 --- a/examples/widgets/radio_buttons.py +++ b/examples/widgets/radio_buttons.py @@ -25,23 +25,31 @@ axcolor = 'lightgoldenrodyellow' rax = fig.add_axes([0.05, 0.7, 0.15, 0.15], facecolor=axcolor) -radio = RadioButtons(rax, ('2 Hz', '4 Hz', '8 Hz')) +radio = RadioButtons(rax, ('1 Hz', '2 Hz', '4 Hz'), + label_props={'color': 'cmy', 'fontsize': [12, 14, 16]}, + radio_props={'s': [16, 32, 64]}) def hzfunc(label): - hzdict = {'2 Hz': s0, '4 Hz': s1, '8 Hz': s2} + hzdict = {'1 Hz': s0, '2 Hz': s1, '4 Hz': s2} ydata = hzdict[label] l.set_ydata(ydata) - plt.draw() + fig.canvas.draw() radio.on_clicked(hzfunc) rax = fig.add_axes([0.05, 0.4, 0.15, 0.15], facecolor=axcolor) -radio2 = RadioButtons(rax, ('red', 'blue', 'green')) +radio2 = RadioButtons( + rax, ('red', 'blue', 'green'), + label_props={'color': ['red', 'blue', 'green']}, + radio_props={ + 'facecolor': ['red', 'blue', 'green'], + 'edgecolor': ['darkred', 'darkblue', 'darkgreen'], + }) def colorfunc(label): l.set_color(label) - plt.draw() + fig.canvas.draw() radio2.on_clicked(colorfunc) rax = fig.add_axes([0.05, 0.1, 0.15, 0.15], facecolor=axcolor) @@ -50,7 +58,7 @@ def colorfunc(label): def stylefunc(label): l.set_linestyle(label) - plt.draw() + fig.canvas.draw() radio3.on_clicked(stylefunc) plt.show() diff --git a/lib/matplotlib/tests/baseline_images/test_widgets/check_radio_buttons.png b/lib/matplotlib/tests/baseline_images/test_widgets/check_radio_buttons.png index e96085d9bffd7a38297b14b2011a7061beb2a287..d6e6004a1732e7f6c449ce3ce7cc87b70743acc7 100644 GIT binary patch literal 24315 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 z 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 RQh=I=7#W%vR9tX;@NW~Cpx*!h literal 14567 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 diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index 4c4f2fdc240f..5eb32e69901a 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -992,21 +992,38 @@ def test_TextBox(ax, toolbar): @image_comparison(['check_radio_buttons.png'], style='mpl20', remove_text=True) def test_check_radio_buttons_image(): ax = get_ax() - # Remove this line when this test image is regenerated. - plt.rcParams['text.kerning_factor'] = 6 + fig = ax.figure + fig.subplots_adjust(left=0.3) - plt.subplots_adjust(left=0.3) - rax1 = plt.axes([0.05, 0.7, 0.15, 0.15]) - rax2 = plt.axes([0.05, 0.2, 0.15, 0.15]) - rb = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3')) + rax1 = fig.add_axes([0.05, 0.7, 0.2, 0.15]) + rb1 = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3')) with pytest.warns(DeprecationWarning, match='The circles attribute was deprecated'): - rb.circles # Trigger the old-style elliptic radiobuttons. - cb = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'), - (False, True, True)) + rb1.circles # Trigger the old-style elliptic radiobuttons. + + rax2 = fig.add_axes([0.05, 0.5, 0.2, 0.15]) + cb1 = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'), + (False, True, True)) with pytest.warns(DeprecationWarning, match='The rectangles attribute was deprecated'): - cb.rectangles # Trigger old-style Rectangle check boxes + cb1.rectangles # Trigger old-style Rectangle check boxes + + rax3 = fig.add_axes([0.05, 0.3, 0.2, 0.15]) + rb3 = widgets.RadioButtons( + rax3, ('Radio 1', 'Radio 2', 'Radio 3'), + label_props={'fontsize': [8, 12, 16], + 'color': ['red', 'green', 'blue']}, + radio_props={'edgecolor': ['red', 'green', 'blue'], + 'facecolor': ['mistyrose', 'palegreen', 'lightblue']}) + + rax4 = fig.add_axes([0.05, 0.1, 0.2, 0.15]) + cb4 = widgets.CheckButtons( + rax4, ('Check 1', 'Check 2', 'Check 3'), (False, True, True), + label_props={'fontsize': [8, 12, 16], + 'color': ['red', 'green', 'blue']}, + frame_props={'edgecolor': ['red', 'green', 'blue'], + 'facecolor': ['mistyrose', 'palegreen', 'lightblue']}, + check_props={'color': ['red', 'green', 'blue']}) @check_figures_equal(extensions=["png"]) @@ -1019,6 +1036,41 @@ def test_radio_buttons(fig_test, fig_ref): ax.text(.25, 1/3, "coffee", transform=ax.transAxes, va="center") +@check_figures_equal(extensions=['png']) +def test_radio_buttons_props(fig_test, fig_ref): + label_props = {'color': ['red'], 'fontsize': [24]} + radio_props = {'facecolor': 'green', 'edgecolor': 'blue', 'linewidth': 2} + + widgets.RadioButtons(fig_ref.subplots(), ['tea', 'coffee'], + label_props=label_props, radio_props=radio_props) + + cb = widgets.RadioButtons(fig_test.subplots(), ['tea', 'coffee']) + cb.set_label_props(label_props) + # Setting the label size automatically increases default marker size, so we + # need to do that here as well. + cb.set_radio_props({**radio_props, 's': (24 / 2)**2}) + + +def test_radio_button_active_conflict(ax): + with pytest.warns(UserWarning, + match=r'Both the \*activecolor\* parameter'): + rb = widgets.RadioButtons(ax, ['tea', 'coffee'], activecolor='red', + radio_props={'facecolor': 'green'}) + # *radio_props*' facecolor wins over *activecolor* + assert mcolors.same_color(rb._buttons.get_facecolor(), ['green', 'none']) + + +@check_figures_equal(extensions=['png']) +def test_radio_buttons_activecolor_change(fig_test, fig_ref): + widgets.RadioButtons(fig_ref.subplots(), ['tea', 'coffee'], + activecolor='green') + + # Test property setter. + cb = widgets.RadioButtons(fig_test.subplots(), ['tea', 'coffee'], + activecolor='red') + cb.activecolor = 'green' + + @check_figures_equal(extensions=["png"]) def test_check_buttons(fig_test, fig_ref): widgets.CheckButtons(fig_test.subplots(), ["tea", "coffee"], [True, True]) @@ -1031,6 +1083,29 @@ def test_check_buttons(fig_test, fig_ref): ax.text(.25, 1/3, "coffee", transform=ax.transAxes, va="center") +@check_figures_equal(extensions=['png']) +def test_check_button_props(fig_test, fig_ref): + label_props = {'color': ['red'], 'fontsize': [24]} + frame_props = {'facecolor': 'green', 'edgecolor': 'blue', 'linewidth': 2} + check_props = {'facecolor': 'red', 'linewidth': 2} + + widgets.CheckButtons(fig_ref.subplots(), ['tea', 'coffee'], [True, True], + label_props=label_props, frame_props=frame_props, + check_props=check_props) + + cb = widgets.CheckButtons(fig_test.subplots(), ['tea', 'coffee'], + [True, True]) + cb.set_label_props(label_props) + # Setting the label size automatically increases default marker size, so we + # need to do that here as well. + cb.set_frame_props({**frame_props, 's': (24 / 2)**2}) + # FIXME: Axes.scatter promotes facecolor to edgecolor on unfilled markers, + # but Collection.update doesn't do that (it forgot the marker already). + # This means we cannot pass facecolor to both setters directly. + check_props['edgecolor'] = check_props.pop('facecolor') + cb.set_check_props({**check_props, 's': (24 / 2)**2}) + + @check_figures_equal(extensions=["png"]) def test_check_buttons_rectangles(fig_test, fig_ref): # Test should be removed once .rectangles is removed diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index f3f99b3753af..d169cb488eb9 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -11,13 +11,15 @@ from contextlib import ExitStack import copy +import itertools from numbers import Integral, Number +from cycler import cycler import numpy as np import matplotlib as mpl -from . import (_api, _docstring, backend_tools, cbook, colors, ticker, - transforms) +from . import (_api, _docstring, backend_tools, cbook, collections, colors, + text as mtext, ticker, transforms) from .lines import Line2D from .patches import Circle, Rectangle, Ellipse, Polygon from .transforms import TransformedPatchPath, Affine2D @@ -966,6 +968,11 @@ def on_changed(self, func): return self._observers.connect('changed', lambda val: func(val)) +def _expand_text_props(props): + props = cbook.normalize_kwargs(props, mtext.Text) + return cycler(**props)() if props else itertools.repeat({}) + + class CheckButtons(AxesWidget): r""" A GUI neutral set of check buttons. @@ -989,7 +996,8 @@ class CheckButtons(AxesWidget): each box, but have ``set_visible(False)`` when its box is not checked. """ - def __init__(self, ax, labels, actives=None, *, useblit=True): + def __init__(self, ax, labels, actives=None, *, useblit=True, + label_props=None, frame_props=None, check_props=None): """ Add check buttons to `matplotlib.axes.Axes` instance *ax*. @@ -1005,9 +1013,28 @@ def __init__(self, ax, labels, actives=None, *, useblit=True): useblit : bool, default: True Use blitting for faster drawing if supported by the backend. See the tutorial :doc:`/tutorials/advanced/blitting` for details. + label_props : dict, optional + Dictionary of `.Text` properties to be used for the labels. + + .. versionadded:: 3.7 + frame_props : dict, optional + Dictionary of scatter `.Collection` properties to be used for the + check button frame. Defaults (label font size / 2)**2 size, black + edgecolor, no facecolor, and 1.0 linewidth. + + .. versionadded:: 3.7 + check_props : dict, optional + Dictionary of scatter `.Collection` properties to be used for the + check button check. Defaults to (label font size / 2)**2 size, + black color, and 1.0 linewidth. + + .. versionadded:: 3.7 """ super().__init__(ax) + _api.check_isinstance((dict, None), label_props=label_props, + frame_props=frame_props, check_props=check_props) + ax.set_xticks([]) ax.set_yticks([]) ax.set_navigate(False) @@ -1019,22 +1046,39 @@ def __init__(self, ax, labels, actives=None, *, useblit=True): self._background = None ys = np.linspace(1, 0, len(labels)+2)[1:-1] - text_size = mpl.rcParams["font.size"] / 2 + label_props = _expand_text_props(label_props) self.labels = [ ax.text(0.25, y, label, transform=ax.transAxes, - horizontalalignment="left", verticalalignment="center") - for y, label in zip(ys, labels)] - - self._squares = ax.scatter( - [0.15] * len(ys), ys, marker='s', s=text_size**2, - c="none", linewidth=1, transform=ax.transAxes, edgecolor="k" - ) - self._crosses = ax.scatter( - [0.15] * len(ys), ys, marker='x', linewidth=1, s=text_size**2, - c=["k" if active else "none" for active in actives], - transform=ax.transAxes, animated=self._useblit, - ) + horizontalalignment="left", verticalalignment="center", + **props) + for y, label, props in zip(ys, labels, label_props)] + text_size = np.array([text.get_fontsize() for text in self.labels]) / 2 + + frame_props = { + 's': text_size**2, + 'linewidth': 1, + **cbook.normalize_kwargs(frame_props, collections.PathCollection), + 'marker': 's', + 'transform': ax.transAxes, + } + frame_props.setdefault('facecolor', frame_props.get('color', 'none')) + frame_props.setdefault('edgecolor', frame_props.pop('color', 'black')) + self._frames = ax.scatter([0.15] * len(ys), ys, **frame_props) + check_props = { + 'linewidth': 1, + 's': text_size**2, + **cbook.normalize_kwargs(check_props, collections.PathCollection), + 'marker': 'x', + 'transform': ax.transAxes, + 'animated': self._useblit, + } + check_props.setdefault('facecolor', check_props.pop('color', 'black')) + self._checks = ax.scatter([0.15] * len(ys), ys, **check_props) + # The user may have passed custom colours in check_props, so we need to + # create the checks (above), and modify the visibility after getting + # whatever the user set. + self._init_status(actives) self.connect_event('button_press_event', self._clicked) if self._useblit: @@ -1047,7 +1091,7 @@ def _clear(self, event): if self.ignore(event): return self._background = self.canvas.copy_from_bbox(self.ax.bbox) - self.ax.draw_artist(self._crosses) + self.ax.draw_artist(self._checks) if hasattr(self, '_lines'): for l1, l2 in self._lines: self.ax.draw_artist(l1) @@ -1066,18 +1110,71 @@ def _clicked(self, event): and y0 <= pclicked[1] <= y0 + p.get_height())): distances[i] = np.linalg.norm(pclicked - p.get_center()) else: - _, square_inds = self._squares.contains(event) - coords = self._squares.get_offset_transform().transform( - self._squares.get_offsets() + _, frame_inds = self._frames.contains(event) + coords = self._frames.get_offset_transform().transform( + self._frames.get_offsets() ) for i, t in enumerate(self.labels): - if (i in square_inds["ind"] + if (i in frame_inds["ind"] or t.get_window_extent().contains(event.x, event.y)): distances[i] = np.linalg.norm(pclicked - coords[i]) if len(distances) > 0: closest = min(distances, key=distances.get) self.set_active(closest) + def set_label_props(self, props): + """ + Set properties of the `.Text` labels. + + .. versionadded:: 3.7 + + Parameters + ---------- + props : dict + Dictionary of `.Text` properties to be used for the labels. + """ + _api.check_isinstance(dict, props=props) + props = _expand_text_props(props) + for text, prop in zip(self.labels, props): + text.update(prop) + + def set_frame_props(self, props): + """ + Set properties of the check button frames. + + .. versionadded:: 3.7 + + Parameters + ---------- + props : dict + Dictionary of `.Collection` properties to be used for the check + button frames. + """ + _api.check_isinstance(dict, props=props) + if 's' in props: # Keep API consistent with constructor. + props['sizes'] = np.broadcast_to(props.pop('s'), len(self.labels)) + self._frames.update(props) + + def set_check_props(self, props): + """ + Set properties of the check button checks. + + .. versionadded:: 3.7 + + Parameters + ---------- + props : dict + Dictionary of `.Collection` properties to be used for the check + button check. + """ + _api.check_isinstance(dict, props=props) + if 's' in props: # Keep API consistent with constructor. + props['sizes'] = np.broadcast_to(props.pop('s'), len(self.labels)) + actives = self.get_status() + self._checks.update(props) + # If new colours are supplied, then we must re-apply the status. + self._init_status(actives) + def set_active(self, index): """ Toggle (activate or deactivate) a check button by index. @@ -1097,15 +1194,15 @@ def set_active(self, index): if index not in range(len(self.labels)): raise ValueError(f'Invalid CheckButton index: {index}') - cross_facecolors = self._crosses.get_facecolor() - cross_facecolors[index] = colors.to_rgba( - "black" - if colors.same_color( - cross_facecolors[index], colors.to_rgba("none") - ) - else "none" + invisible = colors.to_rgba('none') + + facecolors = self._checks.get_facecolor() + facecolors[index] = ( + self._active_check_colors[index] + if colors.same_color(facecolors[index], invisible) + else invisible ) - self._crosses.set_facecolor(cross_facecolors) + self._checks.set_facecolor(facecolors) if hasattr(self, "_lines"): l1, l2 = self._lines[index] @@ -1116,7 +1213,7 @@ def set_active(self, index): if self._useblit: if self._background is not None: self.canvas.restore_region(self._background) - self.ax.draw_artist(self._crosses) + self.ax.draw_artist(self._checks) if hasattr(self, "_lines"): for l1, l2 in self._lines: self.ax.draw_artist(l1) @@ -1128,12 +1225,28 @@ def set_active(self, index): if self.eventson: self._observers.process('clicked', self.labels[index].get_text()) + def _init_status(self, actives): + """ + Initialize properties to match active status. + + The user may have passed custom colours in *check_props* to the + constructor, or to `.set_check_props`, so we need to modify the + visibility after getting whatever the user set. + """ + self._active_check_colors = self._checks.get_facecolor() + if len(self._active_check_colors) == 1: + self._active_check_colors = np.repeat(self._active_check_colors, + len(actives), axis=0) + self._checks.set_facecolor( + [ec if active else "none" + for ec, active in zip(self._active_check_colors, actives)]) + def get_status(self): """ Return a list of the status (True/False) of all of the check buttons. """ return [not colors.same_color(color, colors.to_rgba("none")) - for color in self._crosses.get_facecolors()] + for color in self._checks.get_facecolors()] def on_clicked(self, func): """ @@ -1147,7 +1260,8 @@ def disconnect(self, cid): """Remove the observer with connection id *cid*.""" self._observers.disconnect(cid) - @_api.deprecated("3.7") + @_api.deprecated("3.7", + addendum="Any custom property styling may be lost.") @property def rectangles(self): if not hasattr(self, "_rectangles"): @@ -1162,7 +1276,7 @@ def rectangles(self): ) for i, y in enumerate(ys) ] - self._squares.set_visible(False) + self._frames.set_visible(False) for rectangle in rectangles: self.ax.add_patch(rectangle) if not hasattr(self, "_lines"): @@ -1170,12 +1284,13 @@ def rectangles(self): _ = self.lines return self._rectangles - @_api.deprecated("3.7") + @_api.deprecated("3.7", + addendum="Any custom property styling may be lost.") @property def lines(self): if not hasattr(self, "_lines"): ys = np.linspace(1, 0, len(self.labels)+2)[1:-1] - self._crosses.set_visible(False) + self._checks.set_visible(False) dy = 1. / (len(self.labels) + 1) w, h = dy / 2, dy / 2 self._lines = [] @@ -1484,8 +1599,8 @@ class RadioButtons(AxesWidget): The label text of the currently selected button. """ - def __init__(self, ax, labels, active=0, activecolor='blue', *, - useblit=True): + def __init__(self, ax, labels, active=0, activecolor=None, *, + useblit=True, label_props=None, radio_props=None): """ Add radio buttons to an `~.axes.Axes`. @@ -1498,13 +1613,44 @@ def __init__(self, ax, labels, active=0, activecolor='blue', *, active : int The index of the initially selected button. activecolor : color - The color of the selected button. + The color of the selected button. The default is ``'blue'`` if not + specified here or in *radio_props*. useblit : bool, default: True Use blitting for faster drawing if supported by the backend. See the tutorial :doc:`/tutorials/advanced/blitting` for details. + label_props : dict or list of dict, optional + Dictionary of `.Text` properties to be used for the labels. + + .. versionadded:: 3.7 + radio_props : dict, optional + Dictionary of scatter `.Collection` properties to be used for the + radio buttons. Defaults to (label font size / 2)**2 size, black + edgecolor, and *activecolor* facecolor (when active). + + .. note:: + If a facecolor is supplied in *radio_props*, it will override + *activecolor*. This may be used to provide an active color per + button. + + .. versionadded:: 3.7 """ super().__init__(ax) - self.activecolor = activecolor + + _api.check_isinstance((dict, None), label_props=label_props, + radio_props=radio_props) + + radio_props = cbook.normalize_kwargs(radio_props, + collections.PathCollection) + if activecolor is not None: + if 'facecolor' in radio_props: + _api.warn_external( + 'Both the *activecolor* parameter and the *facecolor* ' + 'key in the *radio_props* parameter has been specified. ' + '*activecolor* will be ignored.') + else: + activecolor = 'blue' # Default. + + self._activecolor = activecolor self.value_selected = labels[active] ax.set_xticks([]) @@ -1512,19 +1658,39 @@ def __init__(self, ax, labels, active=0, activecolor='blue', *, ax.set_navigate(False) ys = np.linspace(1, 0, len(labels) + 2)[1:-1] - text_size = mpl.rcParams["font.size"] / 2 self._useblit = useblit and self.canvas.supports_blit self._background = None + label_props = _expand_text_props(label_props) self.labels = [ ax.text(0.25, y, label, transform=ax.transAxes, - horizontalalignment="left", verticalalignment="center") - for y, label in zip(ys, labels)] - self._buttons = ax.scatter( - [.15] * len(ys), ys, transform=ax.transAxes, s=text_size**2, - c=[activecolor if i == active else "none" for i in range(len(ys))], - edgecolor="black", animated=self._useblit) + horizontalalignment="left", verticalalignment="center", + **props) + for y, label, props in zip(ys, labels, label_props)] + text_size = np.array([text.get_fontsize() for text in self.labels]) / 2 + + radio_props = { + 's': text_size**2, + **radio_props, + 'marker': 'o', + 'transform': ax.transAxes, + 'animated': self._useblit, + } + radio_props.setdefault('edgecolor', radio_props.get('color', 'black')) + radio_props.setdefault('facecolor', + radio_props.pop('color', activecolor)) + self._buttons = ax.scatter([.15] * len(ys), ys, **radio_props) + # The user may have passed custom colours in radio_props, so we need to + # create the radios, and modify the visibility after getting whatever + # the user set. + self._active_colors = self._buttons.get_facecolor() + if len(self._active_colors) == 1: + self._active_colors = np.repeat(self._active_colors, len(labels), + axis=0) + self._buttons.set_facecolor( + [activecolor if i == active else "none" + for i, activecolor in enumerate(self._active_colors)]) self.connect_event('button_press_event', self._clicked) if self._useblit: @@ -1564,6 +1730,61 @@ def _clicked(self, event): closest = min(distances, key=distances.get) self.set_active(closest) + def set_label_props(self, props): + """ + Set properties of the `.Text` labels. + + .. versionadded:: 3.7 + + Parameters + ---------- + props : dict + Dictionary of `.Text` properties to be used for the labels. + """ + _api.check_isinstance(dict, props=props) + props = _expand_text_props(props) + for text, prop in zip(self.labels, props): + text.update(prop) + + def set_radio_props(self, props): + """ + Set properties of the `.Text` labels. + + .. versionadded:: 3.7 + + Parameters + ---------- + props : dict + Dictionary of `.Collection` properties to be used for the radio + buttons. + """ + _api.check_isinstance(dict, props=props) + if 's' in props: # Keep API consistent with constructor. + props['sizes'] = np.broadcast_to(props.pop('s'), len(self.labels)) + self._buttons.update(props) + self._active_colors = self._buttons.get_facecolor() + if len(self._active_colors) == 1: + self._active_colors = np.repeat(self._active_colors, + len(self.labels), axis=0) + self._buttons.set_facecolor( + [activecolor if text.get_text() == self.value_selected else "none" + for text, activecolor in zip(self.labels, self._active_colors)]) + + @property + def activecolor(self): + return self._activecolor + + @activecolor.setter + def activecolor(self, activecolor): + colors._check_color_like(activecolor=activecolor) + self._activecolor = activecolor + self.set_radio_props({'facecolor': activecolor}) + # Make sure the deprecated version is updated. + # Remove once circles is removed. + labels = [label.get_text() for label in self.labels] + with cbook._setattr_cm(self, eventson=False): + self.set_active(labels.index(self.value_selected)) + def set_active(self, index): """ Select button with number *index*. @@ -1575,7 +1796,7 @@ def set_active(self, index): self.value_selected = self.labels[index].get_text() button_facecolors = self._buttons.get_facecolor() button_facecolors[:] = colors.to_rgba("none") - button_facecolors[index] = colors.to_rgba(self.activecolor) + button_facecolors[index] = colors.to_rgba(self._active_colors[index]) self._buttons.set_facecolor(button_facecolors) if hasattr(self, "_circles"): # Remove once circles is removed. for i, p in enumerate(self._circles): @@ -1609,7 +1830,8 @@ def disconnect(self, cid): """Remove the observer with connection id *cid*.""" self._observers.disconnect(cid) - @_api.deprecated("3.7") + @_api.deprecated("3.7", + addendum="Any custom property styling may be lost.") @property def circles(self): if not hasattr(self, "_circles"): From 1849a6a41c308b898690c3832154d925c37b0a18 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 23 Jan 2023 15:17:04 -0600 Subject: [PATCH 229/262] Backport PR #24999: DOC: figure explanation --- doc/users/explain/figures.rst | 215 ++++++++++++++++++++++++++++++++++ doc/users/explain/index.rst | 1 + lib/matplotlib/figure.py | 3 + 3 files changed, 219 insertions(+) create mode 100644 doc/users/explain/figures.rst diff --git a/doc/users/explain/figures.rst b/doc/users/explain/figures.rst new file mode 100644 index 000000000000..ffba58bac0b1 --- /dev/null +++ b/doc/users/explain/figures.rst @@ -0,0 +1,215 @@ + +.. _figure_explanation: + +================================================ +Creating, viewing, and saving Matplotlib Figures +================================================ + +.. plot:: + :include-source: + + fig = plt.figure(figsize=(2, 2), facecolor='lightskyblue', + layout='constrained') + fig.suptitle('Figure') + ax = fig.add_subplot() + ax.set_title('Axes', loc='left', fontstyle='oblique', fontsize='medium') + +When looking at Matplotlib visualization, you are almost always looking at +Artists placed on a `~.Figure`. In the example above, the figure is the +blue region and `~.Figure.add_subplot` has added an `~.axes.Axes` artist to the +`~.Figure` (see :ref:`figure_parts`). A more complicated visualization can add +multiple Axes to the Figure, colorbars, legends, annotations, and the Axes +themselves can have multiple Artists added to them +(e.g. ``ax.plot`` or ``ax.imshow``). + +.. _viewing_figures: + +Viewing Figures +================ + +We will discuss how to create Figures in more detail below, but first it is +helpful to understand how to view a Figure. This varies based on how you are +using Matplotlib, and what :ref:`Backend ` you are using. + +Notebooks and IDEs +------------------ + +If you are using a Notebook (e.g. `Jupyter `_) or an IDE +that renders Notebooks (PyCharm, VSCode, etc), then they have a backend that +will render the Matplotlib Figure when a code cell is executed. One thing to +be aware of is that the default Jupyter backend (``%matplotlib inline``) will +by default trim or expand the figure size to have a tight box around Artists +added to the Figure (see :ref:`saving_figures`, below). + +Standalone scripts and interactive use +-------------------------------------- + +If the user is on a client with a windowing system, there are a number of +:ref:`Backends ` that can be used to render the Figure to +the screen, usually using a Python Qt, Tk, or Wx toolkit, though there is a native +MacOS backend as well. These are typically chosen either in the user's +:ref:`matplotlibrc `, or by calling +``matplotlib.use('QtAgg')`` at the beginning of a session or script. + +When run from a script, or interactively (e.g. from an +`iPython shell `_) the Figure +will not be shown until we call ``plt.show()``. The Figure will appear in +a new GUI window, and usually will have a toolbar with Zoom, Pan, and other tools +for interacting with the Figure. By default, ``plt.show()`` blocks +further interaction from the script or shell until the Figure window is closed, +though that can be toggled off for some purposes. For more details, please see +:ref:`controlling-interactive`. + +Note that if you are on a client that does not have access to a windowing +system, the Figure will fallback to being drawn using the "Agg" backend, and +cannot be viewed, though it can be :ref:`saved `. + +.. _creating_figures: + +Creating Figures +================ + +By far the most common way to create a figure is using the +:doc:`pyplot ` interface. As noted in +:ref:`api_interfaces`, the pyplot interface serves two purposes. One is to spin +up the Backend and keep track of GUI windows. The other is a global state for +Axes and Artists that allow a short-form API to plotting methods. In the +example above, we use pyplot for the first purpose, and create the Figure object, +``fig``. As a side effect ``fig`` is also added to pyplot's global state, and +can be accessed via `~.pyplot.gcf`. + +Users typically want an Axes or a grid of Axes when they create a Figure, so in +addition to `~.pyplot.figure`, there are convenience methods that return both +a Figure and some Axes. A simple grid of Axes can be achieved with +`.pyplot.subplots` (which +simply wraps `.Figure.subplots`): + +.. plot:: + :include-source: + + fig, axs = plt.subplots(2, 2, figsize=(4, 3), layout='constrained') + +More complex grids can be achieved with `.pyplot.subplot_mosaic` (which wraps +`.Figure.subplot_mosaic`): + +.. plot:: + :include-source: + + fig, axs = plt.subplot_mosaic([['A', 'right'], ['B', 'right']], + figsize=(4, 3), layout='constrained') + for ax_name in axs: + axs[ax_name].text(0.5, 0.5, ax_name, ha='center', va='center') + +Sometimes we want to have a nested layout in a Figure, with two or more sets of +Axes that do not share the same subplot grid. +We can use `~.Figure.add_subfigure` or `~.Figure.subfigures` to create virtual +figures inside a parent Figure; see +:doc:`/gallery/subplots_axes_and_figures/subfigures` for more details. + +.. plot:: + :include-source: + + fig = plt.figure(layout='constrained', facecolor='lightskyblue') + fig.suptitle('Figure') + figL, figR = fig.subfigures(1, 2) + figL.set_facecolor('thistle') + axL = figL.subplots(2, 1, sharex=True) + axL[1].set_xlabel('x [m]') + figL.suptitle('Left subfigure') + figR.set_facecolor('paleturquoise') + axR = figR.subplots(1, 2, sharey=True) + axR[0].set_title('Axes 1') + figR.suptitle('Right subfigure') + +It is possible to directly instantiate a `.Figure` instance without using the +pyplot interface. This is usually only necessary if you want to create your +own GUI application or service that you do not want carrying the pyplot global +state. See the embedding examples in :doc:`/gallery/user_interfaces/index` for +examples of how to do this. + +Figure options +-------------- + +There are a few options available when creating figures. The Figure size on +the screen is set by *figsize* and *dpi*. *figsize* is the ``(width, height)`` +of the Figure in inches (or, if preferred, units of 72 typographic points). *dpi* +are how many pixels per inch the figure will be rendered at. To make your Figures +appear on the screen at the physical size you requested, you should set *dpi* +to the same *dpi* as your graphics system. Note that many graphics systems now use +a "dpi ratio" to specify how many screen pixels are used to represent a graphics +pixel. Matplotlib applies the dpi ratio to the *dpi* passed to the figure to make +it have higher resolution, so you should pass the lower number to the figure. + +The *facecolor*, *edgecolor*, *linewidth*, and *frameon* options all change the appearance of the +figure in expected ways, with *frameon* making the figure transparent if set to *False*. + +Finally, the user can specify a layout engine for the figure with the *layout* +parameter. Currently Matplotlib supplies +:doc:`"constrained" `, +:ref:`"compressed" ` and +:doc:`"tight" ` layout engines. These +rescale axes inside the Figure to prevent overlap of ticklabels, and try and align +axes, and can save significant manual adjustment of artists on a Figure for many +common cases. + +Adding Artists +-------------- + +The `~.FigureBase` class has a number of methods to add artists to a `~.Figure` or +a `~.SubFigure`. By far the most common are to add Axes of various configurations +(`~.FigureBase.add_axes`, `~.FigureBase.add_subplot`, `~.FigureBase.subplots`, +`~.FigureBase.subplot_mosaic`) and subfigures (`~.FigureBase.subfigures`). Colorbars +are added to Axes or group of Axes at the Figure level (`~.FigureBase.colorbar`). +It is also possible to have a Figure-level legend (`~.FigureBase.legend`). +Other Artists include figure-wide labels (`~.FigureBase.suptitle`, +`~.FigureBase.supxlabel`, `~.FigureBase.supylabel`) and text (`~.FigureBase.text`). +Finally, low-level Artists can be added directly using `~.FigureBase.add_artist` +usually with care being taken to use the appropriate transform. Usually these +include ``Figure.transFigure`` which ranges from 0 to 1 in each direction, and +represents the fraction of the current Figure size, or ``Figure.dpi_scale_trans`` +which will be in physical units of inches from the bottom left corner of the Figure +(see :doc:`/tutorials/advanced/transforms_tutorial` for more details). + + +.. _saving_figures: + +Saving Figures +============== + +Finally, Figures can be saved to disk using the `~.Figure.savefig` method. +``fig.savefig('MyFigure.png', dpi=200)`` will save a PNG formatted figure to +the file ``MyFigure.png`` in the current directory on disk with 200 dots-per-inch +resolution. Note that the filename can include a relative or absolute path to +any place on the file system. + +Many types of output are supported, including raster formats like PNG, GIF, JPEG, +TIFF and vector formats like PDF, EPS, and SVG. + +By default, the size of the saved Figure is set by the Figure size (in inches) and, for the raster +formats, the *dpi*. If *dpi* is not set, then the *dpi* of the Figure is used. +Note that *dpi* still has meaning for vector formats like PDF if the Figure includes +Artists that have been :doc:`rasterized `; the +*dpi* specified will be the resolution of the rasterized objects. + +It is possible to change the size of the Figure using the *bbox_inches* argument +to savefig. This can be specified manually, again in inches. However, by far +the most common use is ``bbox_inches='tight'``. This option "shrink-wraps", trimming +or expanding as needed, the size of the figure so that it is tight around all the artists +in a figure, with a small pad that can be specified by *pad_inches*, which defaults to +0.1 inches. The dashed box in the plot below shows the portion of the figure that +would be saved if ``bbox_inches='tight'`` were used in savefig. + +.. plot:: + + import matplotlib.pyplot as plt + from matplotlib.patches import FancyBboxPatch + + fig, ax = plt.subplots(figsize=(4, 2), facecolor='lightskyblue') + ax.set_position([0.1, 0.2, 0.8, 0.7]) + ax.set_aspect(1) + bb = ax.get_tightbbox() + bb = bb.padded(10) + fancy = FancyBboxPatch(bb.p0, bb.width, bb.height, fc='none', + ec=(0, 0.0, 0, 0.5), lw=2, linestyle='--', + transform=None, clip_on=False) + ax.add_patch(fancy) diff --git a/doc/users/explain/index.rst b/doc/users/explain/index.rst index 4aaf21494f1a..d70886dc6878 100644 --- a/doc/users/explain/index.rst +++ b/doc/users/explain/index.rst @@ -9,6 +9,7 @@ Explanations :maxdepth: 2 api_interfaces.rst + figures.rst backends.rst writing_a_backend_pyplot_interface.rst interactive.rst diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 7b273cf9fb81..27b16b17a86b 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -12,6 +12,9 @@ `SubplotParams` Control the default spacing between subplots. + +See :ref:`figure_explanation` for narrative on how figures are used in +Matplotlib. """ from contextlib import ExitStack From 118d48d8a70bc6440a57084cb45cdbf2795c86db Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 23 Jan 2023 18:06:02 -0500 Subject: [PATCH 230/262] Backport PR #25054: Remove note that mathtext.fontset = "custom" is unsupported. --- lib/matplotlib/mpl-data/matplotlibrc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index 2380eaff2d24..bf3aab7949ff 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -335,8 +335,7 @@ ## The following settings allow you to select the fonts in math mode. #mathtext.fontset: dejavusans # Should be 'dejavusans' (default), # 'dejavuserif', 'cm' (Computer Modern), 'stix', - # 'stixsans' or 'custom' (unsupported, may go - # away in the future) + # 'stixsans' or 'custom' ## "mathtext.fontset: custom" is defined by the mathtext.bf, .cal, .it, ... ## settings which map a TeX font name to a fontconfig font pattern. (These ## settings are not used for other font sets.) From fb4a40c5ea3023bb121e9b7e433a7929e5a13a18 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Tue, 24 Jan 2023 09:03:38 -0800 Subject: [PATCH 231/262] Backport PR #25058: fix for pcolormesh doesn't allow shading = 'flat' in the option --- lib/matplotlib/axes/_axes.py | 7 ++++--- lib/matplotlib/tests/test_axes.py | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index a3ec2914a777..9129e83ac008 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5748,9 +5748,10 @@ def _pcolorargs(self, funcname, *args, shading='auto', **kwargs): if shading == 'flat': if (Nx, Ny) != (ncols + 1, nrows + 1): - raise TypeError('Dimensions of C %s are incompatible with' - ' X (%d) and/or Y (%d); see help(%s)' % ( - C.shape, Nx, Ny, funcname)) + raise TypeError(f"Dimensions of C {C.shape} should" + f" be one smaller than X({Nx}) and Y({Ny})" + f" while using shading='flat'" + f" see help({funcname})") else: # ['nearest', 'gouraud']: if (Nx, Ny) != (ncols, nrows): raise TypeError('Dimensions of C %s are incompatible with' diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index bcbee036ce2b..8bf6051b3e8a 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -1439,6 +1439,14 @@ def test_pcolorflaterror(): ax.pcolormesh(x, y, Z, shading='flat') +def test_samesizepcolorflaterror(): + fig, ax = plt.subplots() + x, y = np.meshgrid(np.arange(5), np.arange(3)) + Z = x + y + with pytest.raises(TypeError, match=r".*one smaller than X"): + ax.pcolormesh(x, y, Z, shading='flat') + + @pytest.mark.parametrize('snap', [False, True]) @check_figures_equal(extensions=["png"]) def test_pcolorauto(fig_test, fig_ref, snap): From 66953b72816b242629379253974981529481d987 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Tue, 24 Jan 2023 18:37:21 -0600 Subject: [PATCH 232/262] Backport PR #25039: Updated WebAgg JS to check and send request over wss if using HTTPS --- lib/matplotlib/backends/web_backend/all_figures.html | 4 +++- lib/matplotlib/backends/web_backend/single_figure.html | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/backends/web_backend/all_figures.html b/lib/matplotlib/backends/web_backend/all_figures.html index f52b75237327..62f04b65c9bf 100644 --- a/lib/matplotlib/backends/web_backend/all_figures.html +++ b/lib/matplotlib/backends/web_backend/all_figures.html @@ -24,7 +24,9 @@ figure_div.id = "figure-div"; main_div.appendChild(figure_div); var websocket_type = mpl.get_websocket_type(); - var websocket = new websocket_type("{{ ws_uri }}" + fig_id + "/ws"); + var uri = "{{ ws_uri }}" + fig_id + "/ws"; + if (window.location.protocol === "https:") uri = uri.replace('ws:', 'wss:') + var websocket = new websocket_type(uri); var fig = new mpl.figure(fig_id, websocket, mpl_ondownload, figure_div); fig.focus_on_mouseover = true; diff --git a/lib/matplotlib/backends/web_backend/single_figure.html b/lib/matplotlib/backends/web_backend/single_figure.html index 22bd697fbe7d..ceaaab00669f 100644 --- a/lib/matplotlib/backends/web_backend/single_figure.html +++ b/lib/matplotlib/backends/web_backend/single_figure.html @@ -19,8 +19,9 @@ ready( function () { var websocket_type = mpl.get_websocket_type(); - var websocket = new websocket_type( - "{{ ws_uri }}" + {{ str(fig_id) }} + "/ws"); + var uri = "{{ ws_uri }}" + {{ str(fig_id) }} + "/ws"; + if (window.location.protocol === 'https:') uri = uri.replace('ws:', 'wss:') + var websocket = new websocket_type(uri); var fig = new mpl.figure( {{ str(fig_id) }}, websocket, mpl_ondownload, document.getElementById("figure")); From 8560ba79ab3ee4b732a171fba7e8024ac86fdb2f Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 25 Jan 2023 02:50:25 -0500 Subject: [PATCH 233/262] DOC: Update GitHub stats for 3.7.0rc1 --- doc/users/github_stats.rst | 724 ++++++++++++++---- .../prev_whats_new/github_stats_3.6.3.rst | 165 ++++ 2 files changed, 754 insertions(+), 135 deletions(-) create mode 100644 doc/users/prev_whats_new/github_stats_3.6.3.rst diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index d3dc01201d2f..78476e969866 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -1,168 +1,622 @@ .. _github-stats: -GitHub statistics for 3.6.3 (Jan 11, 2023) +GitHub statistics for 3.7.0 (Jan 25, 2023) ========================================== -GitHub statistics for 2022/11/02 (tag: v3.6.2) - 2023/01/11 +GitHub statistics for 2022/09/16 (tag: v3.6.0) - 2023/01/25 These lists are automatically generated, and may be incomplete or contain duplicates. -We closed 16 issues and merged 107 pull requests. -The full list can be seen `on GitHub `__ +We closed 110 issues and merged 380 pull requests. +The full list can be seen `on GitHub `__ -The following 20 authors contributed 198 commits. +The following 107 authors contributed 2268 commits. +* Abhijnan Bajpai +* Adrien F. Vincent +* Ahoy Ahoy +* Akshit Tyagi +* Ali Meshkat +* Almar Klein +* Andrés Martínez +* Ante Sikic * Antony Lee +* Augustin LAVILLE +* baharev +* cargobuild +* Carsten Schnober * Chahak Mehta +* Charisma Kausar * David Stansby +* dependabot[bot] +* DerWeh * Elliott Sales de Andrade * Eric Larson +* erykoff +* EunHo Lee +* Greg Lucas * hannah +* Ian Hunt-Isaak +* Ian Thomas +* intellizEHL * iofall +* j1642 +* jacoverster +* Jae-Joon Lee +* Jakub Klus +* James Braza +* Jay Stanley +* Jef Myers +* jeffreypaul15 +* Jefro * Jody Klymak +* John Paul Jepko +* Joseph Fox-Rabinovitz +* Joshua Barrass +* Junaid Khan +* Justin Tracey * Kaidong Hu +* Kanza +* Karan +* Kian Eliasi +* kolibril13 +* Kostya Farber +* Krutarth Patel * Kyle Sunden -* matt statham -* Matthias Bussonnier +* Leo Singer +* Lucas Ricci +* luke +* Marc Van den Bossche +* Martok +* Marvvxi +* Matthew Feickert +* Mauricio Collares +* MeeseeksMachine +* melissawm +* Mikhail Ryazanov * Muhammad Abdur Rakib +* noatamir +* NRaudseps +* Olivier Castany * Oscar Gustafsson +* parthpankajtiwary +* Paul Seyfert +* Pavel Grunt +* Pieter Eendebak +* PIotr Strzelczyk +* Pratim Ugale +* pre-commit-ci[bot] * ramvikrams * Ruth Comer +* Ryan May +* saranti +* Scott Shambaugh +* Shabnam Sadegh +* Shawn Zhong +* Simon Waldherr +* Skhaki18 +* slackline +* Snipeur060 +* Sourajita Dewasi +* SourajitaDewasi +* Stefanie Molin * Steffen Rehberg +* Sven Eschlbeck +* sveneschlbeck +* takimata +* tfpf * Thomas A Caswell +* Tiger Nie * Tim Hoffmann +* Tom +* Tortar +* tsumli +* tybeller +* vdbma +* Vishal Pankaj Chandratreya +* vivekvedant +* whyvra * yuanx749 +* zhizheng1 +* مهدي شينون (Mehdi Chinoune) GitHub issues and pull requests: -Pull Requests (107): - -* :ghpull:`24939`: Backport PR #23390 on branch v3.6.x (FIX: colorbar contour with log norm should default to log locator and formatter...) -* :ghpull:`24936`: Backport PR #24927 on branch v3.6.x (DOC: Remove space after directive name, before double-colon) -* :ghpull:`23390`: FIX: colorbar contour with log norm should default to log locator and formatter... -* :ghpull:`24932`: Backport PR #24783 on branch v3.6.x (inset locator fix with tests added) -* :ghpull:`24783`: inset locator fix with tests added -* :ghpull:`24927`: DOC: Remove space after directive name, before double-colon -* :ghpull:`24881`: Backport PR #24880 on branch v3.6.x (Minor cleanups to named colors example.) -* :ghpull:`24876`: Backport PR #24873 on branch v3.6.x (Copy-edit fonts docs.) -* :ghpull:`24857`: Backport PR #24856 on branch v3.6.x (fix typo) -* :ghpull:`24852`: Backport PR #24843 on branch v3.6.x (Show that fill_between and span_where provide similar functionalities.) -* :ghpull:`24808`: Backport PR #24807 on branch v3.6.x (Axes.stem docstring document orientation as literals) -* :ghpull:`24807`: Axes.stem docstring document orientation as literals -* :ghpull:`24791`: Backport PR #24785 on branch v3.6.x (Fix random generation of single floats) -* :ghpull:`24777`: Backport PR #24772 on branch v3.6.x (Fix Left ventricle bullseye example) -* :ghpull:`24775`: Backport PR #24774 on branch v3.6.x (DOC: fix strip_chart example with numpy 1.24) -* :ghpull:`24765`: Backport PR #24764 on branch v3.6.x (DOC: ``subplot_mosaic`` tutorial - clarify ratios keywords used directly) -* :ghpull:`24739`: Backport PR #24732 on branch v3.6.x (Use masked stack to preserve mask info) -* :ghpull:`24738`: Backport PR #24735 on branch v3.6.x (Correct note about aspect) -* :ghpull:`24732`: Use masked stack to preserve mask info -* :ghpull:`24735`: Correct note about aspect -* :ghpull:`24729`: Backport PR #24715 on branch v3.6.x (Add note that users do not instantiate Axes directly) -* :ghpull:`24715`: Add note that users do not instantiate Axes directly -* :ghpull:`24721`: Backport PR #24607 on branch v3.6.x (DOC: tweak wording on Figure.show warning) -* :ghpull:`24607`: DOC: tweak wording on Figure.show warning -* :ghpull:`24694`: Backport PR #24692 on branch v3.6.x (Avoid rgba8888->argb32 conversion if qt can do it for us.) -* :ghpull:`24692`: Avoid rgba8888->argb32 conversion if qt can do it for us. -* :ghpull:`24684`: Backport PR #24654: Don't manually invalidate cached lines in _update_transScale -* :ghpull:`24687`: Backport PR #24003 on branch v3.6.x (Fix wording and links lifecycle tutorial) -* :ghpull:`24685`: Backport PR #23974 on branch v3.6.x (Fix repeated word typos) -* :ghpull:`24680`: Backport PR #24677 on branch v3.6.x (FIX: do not replace the Axes._children list object) -* :ghpull:`24677`: FIX: do not replace the Axes._children list object -* :ghpull:`24659`: Backport PR #24657 on branch v3.6.x (BUG: Fix bug with mutable input modification) -* :ghpull:`24657`: BUG: Fix bug with mutable input modification -* :ghpull:`24654`: Don't manually invalidate cached lines in _update_transScale. -* :ghpull:`24650`: Backport PR #24645 on branch v3.6.x (Removed 'above' wording from Input hook integration docs (#24632)) -* :ghpull:`24647`: Backport PR #24643 on branch v3.6.x (DOC: annotation coords are not floats) -* :ghpull:`24643`: DOC: annotation coords are not floats -* :ghpull:`24625`: Backport PR #24606: FIX: do not use deprecated API in gtk4 backend -* :ghpull:`24633`: Backport PR #24592 on branch v3.6.x (DOC: Don't try to link paths that are on a different drive) -* :ghpull:`24592`: DOC: Don't try to link paths that are on a different drive -* :ghpull:`24628`: Backport PR #24584 on branch v3.6.x (DOC: add "See Also: draw_idle" reference to pyplot.draw) -* :ghpull:`24584`: DOC: add "See Also: draw_idle" reference to pyplot.draw -* :ghpull:`24601`: Backport PR #24600 on branch v3.6.x (Fix: Gracefully fail the string validator for tuple inputs) -* :ghpull:`24609`: Backport PR #24595 on branch v3.6.x (ci: Stop building wheels on AppVeyor) -* :ghpull:`24616`: Backport PR #24397 on branch v3.6.x (Simplify appveyor to only use conda) -* :ghpull:`24615`: Backport PR #24598 on branch v3.6.x (Check for errors/warnings on failed doc-builds) -* :ghpull:`24606`: FIX: do not use deprecated API in gtk4 backend -* :ghpull:`24612`: Backport PR #23868 on branch v3.6.x (Show errors and warnings in doc CI after build.) -* :ghpull:`24595`: ci: Stop building wheels on AppVeyor -* :ghpull:`24600`: Fix: Gracefully fail the string validator for tuple inputs -* :ghpull:`24593`: Backport PR #24580 on branch v3.6.x (Update the polar transform information in doc #24499) -* :ghpull:`24587`: Backport PR #24579: Add explicit permissions to GitHub Actions -* :ghpull:`24579`: Add explicit permissions to GitHub Actions -* :ghpull:`24561`: Backport PR #24540 on branch v3.6.x (DOC: add note about enabling c++11 support for old gcc) -* :ghpull:`24559`: Backport PR #24299 on branch v3.6.x (Rework style sheet reference example to cycle props) -* :ghpull:`24551`: Backport PR #24548 on branch v3.6.x (DOC: improved the doc for layout_engine.py) -* :ghpull:`24548`: DOC: improved the doc for layout_engine.py -* :ghpull:`24535`: Backport PR #24514 on branch v3.6.x (Fix potential issue in contour) -* :ghpull:`24534`: Backport PR #24521 on branch v3.6.x (Doc: improve spelling and grammar) -* :ghpull:`24533`: Backport PR #24517 on branch v3.6.x (DOC: improve grammar and consistency) -* :ghpull:`24532`: Backport PR #24520 on branch v3.6.x (Doc: Fix grammar and spelling) -* :ghpull:`24514`: Fix potential issue in contour -* :ghpull:`24521`: Doc: improve spelling and grammar -* :ghpull:`24517`: DOC: improve grammar and consistency -* :ghpull:`24520`: Doc: Fix grammar and spelling -* :ghpull:`24515`: Backport PR #24512 on branch v3.6.x (Tweak markup in toolkits tutorials.) -* :ghpull:`24503`: Backport PR #24502 on branch v3.6.x (Remove link from demo_floating_axes title.) -* :ghpull:`24505`: Backport PR #24482 on branch v3.6.x (Use relative frame path in HTMLWriter) -* :ghpull:`24506`: Backport of PR#24488 (Update for pydata-sphinx-theme 0.12.0) -* :ghpull:`24482`: Use relative frame path in HTMLWriter -* :ghpull:`24496`: Backport PR #24495 on branch v3.6.x (Update adding of google analytics key for docs) -* :ghpull:`24495`: Update adding of google analytics key for docs -* :ghpull:`24488`: Update for pydata-sphinx-theme 0.12.0 -* :ghpull:`24485`: Backport PR #24481 on branch v3.6.x (Fix floating-point drift in oscilloscope example) -* :ghpull:`24475`: DOC: Fix examples gallery layout issues -* :ghpull:`24478`: Backport PR #24444 on branch v3.6.x (DOC: AnnotationBbox keyword descriptions) -* :ghpull:`24444`: DOC: AnnotationBbox keyword descriptions -* :ghpull:`24468`: Backport PR #24429 on branch v3.6.x (DOC: Clarify transparency in colors) -* :ghpull:`24466`: Backport PR #24460 on branch v3.6.x (Define autoscale() based on autoscale_None().) -* :ghpull:`24460`: Define autoscale() based on autoscale_None(). -* :ghpull:`24463`: Backport PR #24459 on branch v3.6.x (removed unused variable and fixed text in doc) -* :ghpull:`24459`: removed unused variable and fixed text in doc -* :ghpull:`24458`: Backport PR #24434 on branch v3.6.x (Fix pyplot.figlegend docstring) -* :ghpull:`24434`: Fix pyplot.figlegend docstring -* :ghpull:`24456`: Backport PR #24402 on branch v3.6.x (DOC: Fix title formats in backend api docs) -* :ghpull:`24438`: Backport PR #24435 on branch v3.6.x (Minor improvements to LogLocator docstring) -* :ghpull:`24435`: Minor improvements to LogLocator docstring -* :ghpull:`24426`: Backport PR #24422 on branch v3.6.x (Make QT_API a link in the qt embedding example.) -* :ghpull:`24411`: Backport PR #24407 on branch v3.6.x (Reword "Reordering is not commutative" phrase in tutorial.) -* :ghpull:`24400`: Backport PR #24399 on branch v3.6.x (Fix docstring of Figure.subfigures.) -* :ghpull:`24399`: Fix docstring of Figure.subfigures. -* :ghpull:`24391`: Backport PR #24380 on branch v3.6.x (DOC: Remove the example "Pythonic Matplotlib") -* :ghpull:`24384`: Backport PR #24377 on branch v3.6.x (DOC: Cleanup Spine placement example) -* :ghpull:`24381`: Backport PR #24366 on branch v3.6.x (DOC: Improve Image Slices Viewer example) -* :ghpull:`24382`: Backport PR #24378 on branch v3.6.x (DOC: Cleanup spines usage in examples) -* :ghpull:`24378`: DOC: Cleanup spines usage in examples -* :ghpull:`24366`: DOC: Improve Image Slices Viewer example -* :ghpull:`24370`: Backport PR #24368 on branch v3.6.x (DOC: Install dev dependencies before building matplotlib) -* :ghpull:`24368`: DOC: Install dev dependencies before building matplotlib -* :ghpull:`24365`: Backport PR #24363 on branch v3.6.x (DOC: Fix syntax of suggestion) -* :ghpull:`24358`: Backport PR #24354 on branch v3.6.x (DOC: clarify rc_context resets all rcParams changes) -* :ghpull:`24354`: DOC: clarify rc_context resets all rcParams changes -* :ghpull:`24353`: Backport PR #24343 on branch v3.6.x (Emit "axes not compatible with tight_layout" in a single place.) -* :ghpull:`24343`: Emit "axes not compatible with tight_layout" in a single place. -* :ghpull:`24346`: Backport PR #24344 on branch v3.6.x (Add test for colorbar extend alpha) -* :ghpull:`24344`: Add test for colorbar extend alpha -* :ghpull:`23974`: Fix repeated word typos - -Issues (16): - -* :ghissue:`23389`: [Bug]: Colorbar with log scales wrong format -* :ghissue:`24589`: [Bug]: inset_locator is broken when used with subfigures -* :ghissue:`10160`: Low resolution (dpi problem) with Qt5 backend on new iMac Pro Retina -* :ghissue:`24545`: [Bug]: ``matplotlib.pyplot.scatter`` does not respect mask rules with ``datetime`` -* :ghissue:`24639`: [Bug]: The Axes3D does not work as expected. -* :ghissue:`22169`: [Doc]: figure.show works beyond what is documented -* :ghissue:`23968`: [Bug]: Zoom rubber band lags in larger window -* :ghissue:`24574`: [Bug]: Extension error (sphinx.ext.linkcode) while building docs -* :ghissue:`24602`: ``close_event`` deprecated warning. -* :ghissue:`24518`: [Doc]: ``layout_engine`` description -* :ghissue:`23581`: [BUG]: frame paths relative to the html file when saving an animation to html -* :ghissue:`23976`: [Doc]: Examples Gallery Layout changed to one or two columns -* :ghissue:`24390`: [Doc]: alpha setting for annotation ``TextArea`` -* :ghissue:`24433`: [Doc]: figlegend examples call ``fig.figlegend`` instead of ``plt.figlegend`` or ``fig.legend`` -* :ghissue:`24360`: [ENH]: imshow support for multiple slice image volume -* :ghissue:`24359`: [Bug]: Documentation not so clear that a C/C++-compiler is required to install from source +Pull Requests (380): + +* :ghpull:`25072`: Merge v3.6.x into v3.7.x +* :ghpull:`25071`: Backport PR #25039 on branch v3.7.x (Updated WebAgg JS to check and send request over wss if using HTTPS) +* :ghpull:`25039`: Updated WebAgg JS to check and send request over wss if using HTTPS +* :ghpull:`25070`: Backport PR #25058 on branch v3.7.x (fix for pcolormesh doesn't allow shading = 'flat' in the option) +* :ghpull:`25058`: fix for pcolormesh doesn't allow shading = 'flat' in the option +* :ghpull:`25067`: Backport PR #25054 on branch v3.7.x (Remove note that mathtext.fontset = "custom" is unsupported.) +* :ghpull:`25066`: Backport PR #24999 on branch v3.7.x (DOC: figure explanation) +* :ghpull:`25054`: Remove note that mathtext.fontset = "custom" is unsupported. +* :ghpull:`25065`: Backport PR #24838 on branch v3.7.x (Add styling support to Check and Radio buttons ) +* :ghpull:`24999`: DOC: figure explanation +* :ghpull:`24838`: Add styling support to Check and Radio buttons +* :ghpull:`25056`: Backport PR #25055 on branch v3.7.x (Reword awkward sentence in FAQ.) +* :ghpull:`25055`: Reword awkward sentence in FAQ. +* :ghpull:`25049`: Backport PR #25047 on branch v3.7.x (Remove dead code from deprecated-and-removed block) +* :ghpull:`25047`: Remove dead code from deprecated-and-removed block +* :ghpull:`25037`: Backport PR #25018 on branch v3.7.x (Simplify "artist reference" example.) +* :ghpull:`25018`: Simplify "artist reference" example. +* :ghpull:`25034`: Backport PR #24812 on branch v3.7.x ([Doc] expanded basic pie example) +* :ghpull:`24812`: [Doc] expanded basic pie example +* :ghpull:`25029`: Backport PR #25019 on branch v3.7.x (Tweak titles pyplot examples.) +* :ghpull:`25019`: Tweak titles pyplot examples. +* :ghpull:`25026`: Backport PR #25017 on branch v3.7.x (Capitalize headings in example Gallery) +* :ghpull:`25017`: Capitalize headings in example Gallery +* :ghpull:`25010`: Backport PR #24989 on branch v3.7.x (Suppress pyparsing warning) +* :ghpull:`25008`: Backport PR #25004 on branch v3.7.x (Bump pypa/cibuildwheel from 2.11.4 to 2.12.0) +* :ghpull:`24989`: Suppress pyparsing warning +* :ghpull:`25004`: Bump pypa/cibuildwheel from 2.11.4 to 2.12.0 +* :ghpull:`25001`: Backport PR #25000 on branch v3.7.x (Update matplotlibrc urls) +* :ghpull:`25000`: Update matplotlibrc urls +* :ghpull:`24977`: Backport PR #24970 on branch v3.7.x (FIX: Handle uint8 indices properly for colormap lookups) +* :ghpull:`24970`: FIX: Handle uint8 indices properly for colormap lookups +* :ghpull:`24975`: Backport PR #24971 on branch v3.7.x (FIX: adjust_bbox should not modify layout engine) +* :ghpull:`24974`: Backport PR #24973 on branch v3.7.x (MNT: Fix double % signs in matplotlibrc) +* :ghpull:`24966`: Backport PR #24965 on branch v3.7.x (Remove additional deprecations from 3.5) +* :ghpull:`24971`: FIX: adjust_bbox should not modify layout engine +* :ghpull:`24973`: MNT: Fix double % signs in matplotlibrc +* :ghpull:`24965`: Remove additional deprecations from 3.5 +* :ghpull:`24963`: Backport PR #24912 on branch v3.7.x (Remove contour warning for "no-valid-levels".) +* :ghpull:`24962`: Backport PR #24957 on branch v3.7.x (DOC: Enable Opensearch) +* :ghpull:`24961`: Backport PR #24948 on branch v3.7.x (Remove remaining deprecations from 3.5) +* :ghpull:`24959`: Backport PR #24254 on branch v3.7.x (Expire deprecations in widgets and keyword only arguments for Selectors) +* :ghpull:`24912`: Remove contour warning for "no-valid-levels". +* :ghpull:`24960`: Backport PR #24825 on branch v3.7.x (Allow non-default scales on polar axes) +* :ghpull:`24957`: DOC: Enable Opensearch +* :ghpull:`24948`: Remove remaining deprecations from 3.5 +* :ghpull:`24825`: Allow non-default scales on polar axes +* :ghpull:`24254`: Expire deprecations in widgets and keyword only arguments for Selectors +* :ghpull:`24956`: Backport PR #24955 on branch v3.7.x (Cleanup bullseye plot example.) +* :ghpull:`24955`: Cleanup bullseye plot example. +* :ghpull:`24949`: Backport PR #24918 on branch v3.7.x (DOC: animation faster) +* :ghpull:`24947`: Auto backport of pr 24897 on v3.7.x +* :ghpull:`24945`: Backport PR #24940 on branch v3.7.x ([MNT] specify which gallery sections come last) +* :ghpull:`24918`: DOC: animation faster +* :ghpull:`24917`: Backport PR #24897: DOC: Add ref for every under examples/animation +* :ghpull:`24940`: [MNT] specify which gallery sections come last +* :ghpull:`24941`: Backport PR #24655 on branch v3.7.x (Update font_manager to only use registry on Win) +* :ghpull:`24655`: Update font_manager to only use registry on Win +* :ghpull:`24937`: Backport PR #24470 on branch v3.7.x ([ENH] hatch keyword for pie + some pie documentation) +* :ghpull:`24938`: Backport PR #23390 on branch v3.7.x (FIX: colorbar contour with log norm should default to log locator and formatter...) +* :ghpull:`24935`: Backport PR #24934 on branch v3.7.x (Swap ipython directives for code-block directives) +* :ghpull:`24470`: [ENH] hatch keyword for pie + some pie documentation +* :ghpull:`24933`: Backport PR #24924 on branch v3.7.x (Fix toggling layout engines) +* :ghpull:`24934`: Swap ipython directives for code-block directives +* :ghpull:`24931`: Backport PR #24783 on branch v3.7.x (inset locator fix with tests added) +* :ghpull:`24924`: Fix toggling layout engines +* :ghpull:`24928`: Backport PR #24927 on branch v3.7.x (DOC: Remove space after directive name, before double-colon) +* :ghpull:`24926`: Backport PR #24925 on branch v3.7.x (DOC: Improve documentation for set_loglevel) +* :ghpull:`24925`: DOC: Improve documentation for set_loglevel +* :ghpull:`24922`: Backport PR #24921 on branch v3.7.x (Pin sphinx != 6.1.2) +* :ghpull:`24921`: Pin sphinx != 6.1.2 +* :ghpull:`24911`: Backport PR #24904 on branch v3.7.x (Deprecate AxisArtistHelpers with inconsistent loc/nth_coord.) +* :ghpull:`24897`: DOC: Add ref for every under examples/animation +* :ghpull:`24904`: Deprecate AxisArtistHelpers with inconsistent loc/nth_coord. +* :ghpull:`22314`: Add a helper to generate xy coordinates for AxisArtistHelper. +* :ghpull:`24841`: changed method in animation tutorial table of methods +* :ghpull:`24902`: Remove provisional note from pyplot.subplot_mosaic +* :ghpull:`24891`: DOC: mark mosaic as no longer provisional +* :ghpull:`24889`: Harmonize exceptions for unknown keyword arguments. +* :ghpull:`24085`: Set facecolor of FilledArrow axisline style and fix tight layout +* :ghpull:`19743`: ENH: allow fig.legend outside axes... +* :ghpull:`24887`: [MNT] Bump NumPy to 1.20 +* :ghpull:`24896`: changed contribute docs link to writing docs +* :ghpull:`24894`: DOC: explain clipbox a bit better +* :ghpull:`24864`: Deprecate BrokenBarHCollection. +* :ghpull:`24869`: Skip displaying pan/zoom navigate mode in toolbar. +* :ghpull:`24892`: FIX: error in formatting in error string in redirect extension +* :ghpull:`24895`: add new & improved doc notices to what's new +* :ghpull:`24888`: update install instructions for conda +* :ghpull:`24886`: CI: rotate the circleci deploy key +* :ghpull:`24879`: Document "." as a filled marker. +* :ghpull:`24870`: Better default bool contour levels. +* :ghpull:`24786`: Increase a few test tolerances on some arches +* :ghpull:`24863`: Add parameter doc to PolarTransform +* :ghpull:`24845`: Fix toggling of MultiCursor.{horizOn,vertOn} +* :ghpull:`24862`: Fix argument checking in ``Axes3D.quiver`` +* :ghpull:`24868`: [pre-commit.ci] pre-commit autoupdate +* :ghpull:`24840`: Simplify/robustify segment-point distance calculation. +* :ghpull:`24850`: Improve PolarAffine docstring +* :ghpull:`24851`: Variable rename t > theta +* :ghpull:`24763`: Allow polar scales where zero is not in valid interval +* :ghpull:`24846`: Promote pending cm deprecations to full deprecations +* :ghpull:`24848`: ``Collection.set_linestyle``: remove redundant string handling +* :ghpull:`24839`: Move geo/polar projections to their own pages +* :ghpull:`24727`: Handle argument "facecolors=None" correctly in plot_surface() +* :ghpull:`24847`: Avoid extra copy initializing empty Affine2D +* :ghpull:`24837`: DOC: Replace .format by f-strings in examples +* :ghpull:`24604`: Enh/extend mosaic kwargs +* :ghpull:`24131`: Deprecate attributes and expire deprecation in animation +* :ghpull:`23457`: Add blitting support to button widgets +* :ghpull:`24832`: [MNT] Improve variable naming in bar +* :ghpull:`24829`: Simplify shape-checking in QuadMesh.set_array. +* :ghpull:`24835`: Delay nightly wheel builds by 2 hours +* :ghpull:`24831`: [Doc] Fix ndarray-links for arguments +* :ghpull:`24824`: Fix incorrect method in doc +* :ghpull:`24826`: space in version added for reverse in legend +* :ghpull:`24819`: Bump pypa/cibuildwheel from 2.11.3 to 2.11.4 +* :ghpull:`24811`: removed casting handles to list in legend +* :ghpull:`24759`: Reverse legend +* :ghpull:`24465`: Reparametrize offsetbox calculations in terms of bboxes. +* :ghpull:`22316`: Arbitrary figure customization hooks. +* :ghpull:`22329`: Enforce that Line data modifications are sequences +* :ghpull:`24730`: Data access API for rcParams +* :ghpull:`24699`: Implement nested four-level TeX cache +* :ghpull:`24752`: DOC: Make event handling table scrollable +* :ghpull:`24637`: Fixes #20044 pass AnnotationBbox to renderer +* :ghpull:`24810`: Don't modify dictionary input to widgets +* :ghpull:`24769`: Improve matplotlib.axes documentation +* :ghpull:`24806`: Deprecate 'x' argument for widgets.TextBox.begin_typing +* :ghpull:`24293`: Handle rasterization start & stop only from Artist +* :ghpull:`24768`: Fix/zorder rasterization +* :ghpull:`24474`: Use scatter for check boxes and set facecolors correctly in check boxes and radio buttons +* :ghpull:`24262`: Fix issue with space allocated for single tick that should not be there +* :ghpull:`24780`: Update environment.yml +* :ghpull:`23576`: Soft deprecate the textpath module (import from text instead) +* :ghpull:`24750`: Fix deprecations of \*Cursor widget event handlers +* :ghpull:`24757`: Allow using masked in ``set_offsets`` +* :ghpull:`21661`: Fix plot directive with func calls +* :ghpull:`24803`: Correct type in docstring of zorder for streamplot and LineCollection +* :ghpull:`24801`: Correct docstring of RangeSlider.on_changed +* :ghpull:`24802`: Correct docstring of CheckButtons.get_status +* :ghpull:`24758`: MNT: Simplify code related to masked arrays +* :ghpull:`24756`: DOC: Simplify some table markup +* :ghpull:`24795`: DOC: Fix duplicate redirect +* :ghpull:`24782`: DOC: update typos and grammar errors +* :ghpull:`24794`: Update README.md +* :ghpull:`24071`: Deprecate undefined label_mode to Grid +* :ghpull:`24724`: Run delvewheel on Windows for wheels +* :ghpull:`24538`: [Doc] Document legend_handles and legend_handlers +* :ghpull:`24751`: DOC: Update Artist inheritance diagram +* :ghpull:`24761`: Don't set the never-used Line2D._contains in set_picker. +* :ghpull:`24760`: Remove unused dicts from backend_cairo. +* :ghpull:`24736`: DOC: simplify CheckButton example +* :ghpull:`22700`: MAINT: Move docstring of ``LogLocator`` to class +* :ghpull:`19763`: Remove visibility changes in draw for \*Cursor widgets +* :ghpull:`23473`: Separately track modifier keys for mouse events. +* :ghpull:`24748`: DOC: remove research notice +* :ghpull:`24734`: Support masked dates +* :ghpull:`24737`: MNT: make fig.colorbar(..., ax=INPUT) even more forgiving +* :ghpull:`24120`: don't try to start a new event loop in WebAgg when in an ipykernel +* :ghpull:`24362`: Allow bool-like values for sharex/sharey +* :ghpull:`24740`: Minor redundancy cleanup of code which sets 3D aspect 3D +* :ghpull:`22273`: Improve inheritance diagrams +* :ghpull:`24668`: Add test for remaining axis options +* :ghpull:`9598`: ENH: rely on non-rectangular patch paths rather than bboxes for legend auto-placing (fix #9580) +* :ghpull:`22920`: Mnt deprecate mlab +* :ghpull:`24408`: Fix: restore make_axes to accept a tuple of axes +* :ghpull:`24731`: DOC: Post warnings as reviews on PRs +* :ghpull:`24652`: Offsetbox default arguments +* :ghpull:`24720`: FIX: be more forgiving in default draw wrapper +* :ghpull:`24719`: Remove quotes from EngFormatter.format_eng example +* :ghpull:`24718`: Remove refresh function from polar ThetaLocator +* :ghpull:`24710`: Drop support for Qt<5.10. +* :ghpull:`24509`: Factor out & improve accuracy of derivatives calculations in axisartist. +* :ghpull:`19591`: reverse order in which stackplot elements are added to axes +* :ghpull:`24367`: STY: Update macosx zoom rect styling +* :ghpull:`24706`: Bump pypa/cibuildwheel from 2.11.2 to 2.11.3 +* :ghpull:`24705`: Cleanup a few examples. +* :ghpull:`21096`: FIX: improve symlog ticker +* :ghpull:`24498`: DOC: Update multiple category bar chart examples +* :ghpull:`24688`: Deprecate quiver_doc and barbs_doc class members +* :ghpull:`24526`: [Doc] Fix spelling and grammar in tutorials +* :ghpull:`24675`: TST: set style in mpl_toolkits to ease later transition +* :ghpull:`24484`: Artist's draw method prevents rasterization by default +* :ghpull:`24667`: Test scroll zoom bbox update +* :ghpull:`24662`: Doc/git force +* :ghpull:`24664`: Deprecate offsetbox.bbox_artist +* :ghpull:`24670`: Tiny capitalization fix. +* :ghpull:`24596`: ENH: Add ellipse class for annotation box styles +* :ghpull:`24249`: Add legend tests for 3D plots +* :ghpull:`24627`: MNT: when clearing an Axes via clear/cla fully detach children +* :ghpull:`24653`: Directly call _long_axis()._set_axes_scale in Colorbar. +* :ghpull:`24640`: Small TransformWrapper cleanups. +* :ghpull:`24528`: BUG: Warn when an existing layout manager changes to tight layout +* :ghpull:`24635`: Remove unneeded _update_transScale calls in _init_axis. +* :ghpull:`24641`: Fix that font files never pass the test on Win +* :ghpull:`24522`: Use pybind11 for tri module +* :ghpull:`24603`: Shorten the definition of sawtooth boxstyle. +* :ghpull:`24630`: Improve error message for gridspec when the index is not an integer. +* :ghpull:`24634`: Init axes._children early enough to avoid need for some getattr calls. +* :ghpull:`24629`: Doc/gitwash redirects +* :ghpull:`24624`: Expire FancyBboxPatch deprecations. +* :ghpull:`24619`: ENH: Allow RGB(A) arrays for pcolormesh +* :ghpull:`23588`: Refactoring gitwash +* :ghpull:`21549`: Unifying the Figure getter/setter interface to match its constructor +* :ghpull:`24582`: Shorten demo_axes_grid example. +* :ghpull:`24577`: Fold _set_ticklabels into set_ticklabels. +* :ghpull:`24581`: Simplify implementation of _is_sorted. +* :ghpull:`24575`: Use std::isnan and fix compiler warning +* :ghpull:`24570`: FIX: VPacker and HPacker bottom/top alignment +* :ghpull:`23812`: Ci add codeql +* :ghpull:`24556`: Fix incorrect window_extent of AxesImage +* :ghpull:`24566`: Improve argument checking for set_xticks(). +* :ghpull:`24544`: DOC: Add links to supported file formats in animations tutorial +* :ghpull:`24511`: Add test for mutating input arrays #8990 +* :ghpull:`24558`: In mplot3d, fix a doc typo and autogen zaxis_inverted. +* :ghpull:`24555`: ENH: Add warning for SymLogScale when values in linear scale range +* :ghpull:`23417`: Consistently set label on axis with units +* :ghpull:`24542`: DOC: Clarify supported animation formats in animation tutorial +* :ghpull:`23685`: Add mathtext support for ``\middle`` and correct rendering of ``\|`` +* :ghpull:`24539`: Fix misnamed api changes entry. +* :ghpull:`23692`: Add ``Axes.get_tick_params()`` method. +* :ghpull:`24132`: CenteredNorm changes +* :ghpull:`24529`: Transform ParasiteAxesBase._update_viewlim into standard callback. +* :ghpull:`24304`: Simplify some patches path definitions. +* :ghpull:`24431`: FIX: Support passing one alpha per event sequence to eventplot() +* :ghpull:`24527`: Fix testing of whether backends use the new pyplot_show API. +* :ghpull:`24537`: Fix triage tool due to test reorganization +* :ghpull:`21831`: FIX: pre-composite animation frames to white background +* :ghpull:`24205`: Plot directive: delegate file handling to Sphinx +* :ghpull:`24274`: Animation Tutorial +* :ghpull:`24519`: MNT: remove unused arguments to private methods and minor doc fixes +* :ghpull:`24525`: [Doc] Fix spelling and grammar in examples +* :ghpull:`24523`: [Doc] fix more spelling and grammar +* :ghpull:`24218`: Document what pyplot expects from a backend. +* :ghpull:`24513`: Modernize a bit floating_axes tests. +* :ghpull:`24491`: Make Path3DCollection store indexed offset, and only apply z-ordered offset during draw +* :ghpull:`24500`: DOC: Removed matplotlib from mission statement title +* :ghpull:`24490`: DOC: Remove text rotation example +* :ghpull:`24487`: Update tests to run with 3.11 (not rc) +* :ghpull:`24439`: Remove custom polar behaviour in LogLocator +* :ghpull:`24461`: Shorten and explain more calculations in axes_divider. +* :ghpull:`24472`: [DOC] removed flake8 from PR template +* :ghpull:`24467`: [DOC] swapped params in fig_compare_error msg +* :ghpull:`24455`: Draw RadioButtons using scatter to ensure circular buttons. +* :ghpull:`24462`: Don't pass unused xdescent to _get_packed_offsets. +* :ghpull:`24446`: Remove axis() manual argument parsing. +* :ghpull:`24334`: ENH: Check labels arg when kwargs passed in Axis.set_ticks() +* :ghpull:`24430`: MNT: Issue a warning instead of logging if RGB(A) passed to scatter(..., c) +* :ghpull:`24397`: Simplify appveyor to only use conda +* :ghpull:`24447`: Factor out error generation for function calls with wrong nargs. +* :ghpull:`24441`: DOC: Fix example for what's new imshow so it isn't cut off or crowded. +* :ghpull:`24443`: Add valid values to ``get_*axis_transform`` docstring +* :ghpull:`24440`: DOC: Fix colorbar what's new entry so it isn't cut off. +* :ghpull:`23787`: Use pybind11 for C/C++ extensions +* :ghpull:`24247`: Split toolkit tests into their toolkits +* :ghpull:`24432`: DOC: Fix What's New entry for bar_label() formatting. +* :ghpull:`23101`: Move show() to somewhere naturally inheritable / document what pyplot expects from a backend. +* :ghpull:`24215`: Add :shows-source-link: option to Sphinx plot directive +* :ghpull:`24423`: Tighten the Qt binding selection docs. +* :ghpull:`24403`: Use ``repr`` in error message Addresses #21959 +* :ghpull:`24415`: made f2tfont error message explicit that it needs path to file +* :ghpull:`24329`: Kill FontconfigPatternParser. +* :ghpull:`23267`: Add location keyword argument to Colorbar +* :ghpull:`24375`: DOC: Group pyplot plotting commands +* :ghpull:`24307`: DOC: Organize Axes3D methods into sections +* :ghpull:`22230`: FIX: add support for imshow extent to have units +* :ghpull:`24252`: Change default rotation mode for 3D labels to 'anchor' +* :ghpull:`24356`: Expire QuadMesh old signature deprecation +* :ghpull:`24355`: Expire unused positional parameters in canvas subclasses +* :ghpull:`24257`: Load style files from third-party packages. +* :ghpull:`24279`: Cleanup BboxImage example. +* :ghpull:`24342`: Use HTML5 for webagg files +* :ghpull:`24339`: DOC: Minor cleanup in "Writing documentation" +* :ghpull:`24338`: DOC: Group pyplot commands by category +* :ghpull:`24314`: Minor improvements to Annotations Tutorial +* :ghpull:`23914`: Add shading of Poly3DCollection +* :ghpull:`24322`: GOV: change security reporting to use tidelift +* :ghpull:`24305`: Unify logic of ConnectionStyle._Base.{_clip,_shrink}. +* :ghpull:`24303`: Simplify generate_fontconfig_pattern. +* :ghpull:`24319`: Bump mamba-org/provision-with-micromamba from 13 to 14 +* :ghpull:`24239`: Fix mathtext rendering of ``\|`` and sizing of ``|`` and ``\|`` +* :ghpull:`23606`: added offset section & restructured annotations tutorial +* :ghpull:`24125`: Expire miscellaneous deprecations from 3.5 +* :ghpull:`24306`: Remove unnecessary/replaceable explicit str calls. +* :ghpull:`24295`: Remove unnecessary np.{,as}array / astype calls. +* :ghpull:`24302`: MNT: Remove redundant int after round +* :ghpull:`24290`: Cleanup Barbs._find_tails. +* :ghpull:`24298`: List all the places to update when adding a dependency. +* :ghpull:`24289`: Cleanup image_zcoord example. +* :ghpull:`23865`: Add test and example for VBoxDivider +* :ghpull:`24287`: Simplifying glyph stream logic in ps backend +* :ghpull:`24291`: Rely on builtin round() instead of manual rounding. +* :ghpull:`24062`: Replaced std::random_shuffle with std::shuffle in tri +* :ghpull:`24278`: Use oldest-supported-numpy for build +* :ghpull:`24161`: Versioning directives policy +* :ghpull:`24013`: Deprecate matplotlib.tri.* submodules +* :ghpull:`24031`: Add rcParams for 3D pane color +* :ghpull:`24220`: Simplify and tighten parse_fontconfig_pattern. +* :ghpull:`24251`: Expire deprecation for ``auto_add_to_figure=True`` in ``Axes3D`` +* :ghpull:`24160`: sample versioning directives, empty + description +* :ghpull:`24253`: Expire deprecation of grid argument name +* :ghpull:`14471`: FIX: don't close figures if switch_backend is a no-op +* :ghpull:`24240`: Deprecate unit_cube-related methods in Axes3D +* :ghpull:`24244`: Clarify that z must be finite for tricountour(f) +* :ghpull:`23536`: Improve mpl_toolkit documentation +* :ghpull:`24243`: Improve documentation for ticker +* :ghpull:`24189`: Do not pass gridspec_kw to inner layouts in subplot_mosaic +* :ghpull:`24242`: Add information about environment variables in matplotlib.__doc__ +* :ghpull:`24241`: Small animation docs/style fixes. +* :ghpull:`24236`: DOC: Mark SubplotBase removals in code style +* :ghpull:`24141`: Set figure options dynamically +* :ghpull:`23796`: Remove useless semicolons in "Introductory / Basic Usage" tutorial +* :ghpull:`23573`: Merge SubplotBase into AxesBase. +* :ghpull:`23931`: Raise ValueError on negative number inputs for set_aspect +* :ghpull:`24065`: Fixed the positioning of cursor in Textbox: no approximation +* :ghpull:`24122`: Add textcolor to legend based on labelcolor string +* :ghpull:`24182`: MNT: Remove redundant method, fix signature and add doc-string to ``draw_tex`` +* :ghpull:`24224`: Deprecate Julian date-related functions and constant +* :ghpull:`24196`: MNT: Update pre-commit hooks +* :ghpull:`24221`: Deprecate BufferRegion.to_string{,_argb}. +* :ghpull:`23683`: Simplify/add pyparsing error messages on mathtext/fontconfig errors. +* :ghpull:`24210`: Small cleanups to axislines docs. +* :ghpull:`24213`: Cleanup make_compound_path_from_poly doc, example. +* :ghpull:`24208`: Deprecate backend_webagg.ServerThread. +* :ghpull:`24207`: Recommend multiple_yaxis_with_spines over parasite axes. +* :ghpull:`24156`: Automatically update rebase label +* :ghpull:`24198`: Deprecate unused backend_ps.{PsBackendHelper,ps_backend_helper}. +* :ghpull:`24129`: Expire cursor-related deprecations +* :ghpull:`24179`: MNT: Refactor ``Renderer.get_text_width_height_descent`` +* :ghpull:`24191`: BLD: be more cautious about checking editable mode +* :ghpull:`24000`: Generalize validation that pyplot commands are documented +* :ghpull:`24144`: Deprecate some label-related attributes on ContourLabeler. +* :ghpull:`24162`: windows doc build parity +* :ghpull:`24102`: Simplest pyproject.toml containing build-system only +* :ghpull:`24091`: MNT: Clean up code in SecondaryAxis +* :ghpull:`24140`: Replace ClabelText by set_transform_rotates_text. +* :ghpull:`24143`: Add QuadContourSet.remove. +* :ghpull:`24138`: [DOC] Fix some documentation typos +* :ghpull:`24128`: Expire deprecations in dates and ticker +* :ghpull:`23907`: Inherit OffsetBox.get_window_extent. +* :ghpull:`23449`: Add pan and zoom toolbar handling to 3D Axes (Replaces PR#22614) +* :ghpull:`24126`: Bump version when invalid hatches error +* :ghpull:`23874`: Expire parameter renaming and deletion and attribute privatization from 3.5 +* :ghpull:`23592`: Polar errcaps +* :ghpull:`24083`: Enable interactive figure resizing for webagg and nbagg backends +* :ghpull:`24110`: test readme rendering +* :ghpull:`24067`: README.rst to README.md +* :ghpull:`23702`: Get Mathtext ``\times`` symbol from ``cmsy10`` when using ``cmr10``. +* :ghpull:`24066`: Simplify svg font expansion logic. +* :ghpull:`23730`: [DOC]: Add grid to style sheets +* :ghpull:`24020`: [DOC]: adding a grid to the style sheet reference. +* :ghpull:`23579`: Remove direct manipulation of HostAxes.parasites by end users. +* :ghpull:`23553`: Add tests for ImageGrid +* :ghpull:`23918`: Merge v3.6.x branch to main +* :ghpull:`23902`: Add test and improve examples for mpl_toolkits +* :ghpull:`23950`: DOC: Don't import doctest because we're not using it +* :ghpull:`21006`: Rotate errorbar caps in polar plots +* :ghpull:`23870`: Implement Sphinx-Gallery's ``make html-noplot`` +* :ghpull:`23905`: made explict that install link is install docs in readme +* :ghpull:`23824`: Deprecate draw_gouraud_triangle +* :ghpull:`23913`: Add draggable as param to Legend init +* :ghpull:`23896`: Inline AnchoredOffsetBox._update_offset_func. +* :ghpull:`23889`: Update image tutorial. +* :ghpull:`23861`: Move axes_grid tests to axes_grid1 +* :ghpull:`23254`: Add PathCollection test for ps backend +* :ghpull:`23542`: Add even more mplot3d tests +* :ghpull:`23698`: Fix bug in ``Axes.bar_label(label_type='center')`` for non-linear scales. +* :ghpull:`23767`: DEV: add flake8-force plugin +* :ghpull:`23835`: Fix version switcher links +* :ghpull:`23832`: Improve skip message for image comparison tests +* :ghpull:`23690`: Add new-style string formatting option and callable option to ``fmt`` in ``Axes.bar_label()``. +* :ghpull:`23804`: Fix TexManager's support for ``openin_any = p`` +* :ghpull:`23737`: Update grammar +* :ghpull:`23552`: Provide ``adjustable='box'`` to 3D axes aspect ratio setting +* :ghpull:`23769`: Bump mamba-org/provision-with-micromamba from 12 to 13 +* :ghpull:`23590`: Changing bar examples to tea and coffee +* :ghpull:`21253`: Fix: axis, ticks are set to defaults fontsize after ax.clear() +* :ghpull:`21968`: Changed fstring to make error clearer +* :ghpull:`22614`: ENH: Add pan and zoom toolbar handling to 3D Axes +* :ghpull:`21562`: Add a test for Hexbin Linear + +Issues (110): + +* :ghissue:`23999`: [Bug]: Annotation misplaced when rasterizing and saving as PDF +* :ghissue:`25040`: [Bug]: Request to insecure websocket endpoint is blocked by browser +* :ghissue:`24678`: [Bug]: pcolormesh doesn't allow shading = 'flat' in the option +* :ghissue:`15388`: matplotlib.collections.QuadMesh.set_array() input arg format is weird and undocumented +* :ghissue:`23779`: [ENH]: control the size of the tex cache +* :ghissue:`24583`: [ENH]: provide public API for styling radio buttons +* :ghissue:`21895`: [Bug]: slow rendering of multiple axes (time scales as 2nd power of label count) +* :ghissue:`4781`: Add API to register styles +* :ghissue:`24972`: [MNT]: UserWarning from pyparsing upon immediate import +* :ghissue:`24865`: [Bug]: NumPy 1.24 deprecation warnings +* :ghissue:`24954`: [Bug]: compressed layout setting can be forgotten on second save +* :ghissue:`23778`: [ENH]: Allow override of contour level autoscaling +* :ghissue:`20203`: contour edge case with all data below levels and a surrounding field of zeros +* :ghissue:`12803`: pcolormesh in log polar coordinates +* :ghissue:`24383`: log scale and polar broken +* :ghissue:`22847`: [Bug]: Cannot toggle set_tight_layout +* :ghissue:`23646`: [Bug]: matplotlib.set_loglevel() adds a console handler +* :ghissue:`24673`: [Doc]: animation examples show controls; source does not reproduce them +* :ghissue:`7617`: set_ylabel does not work as expected with SubplotZero +* :ghissue:`13023`: constrained_layout support for figure.legend +* :ghissue:`15973`: span_where fails with timeseries on the x-axis +* :ghissue:`24867`: [Bug]: controlling text on toolbar in wx +* :ghissue:`24421`: [Doc]: change to install from conda forge +* :ghissue:`24890`: [Bug]: Clipping mask can shift in PDF and SVG file outputs when Bbox is adjusted +* :ghissue:`23849`: [Bug]: The point marker is not actually unfilled +* :ghissue:`24321`: [ENH]: Auto-detect bool arrays passed to contour()? +* :ghissue:`24842`: axes3d.quiver() fails when providing args to Line3DCollection +* :ghissue:`24093`: [Bug]: CenteredNorm gets stuck in infinite recusion when given all zeros +* :ghissue:`24571`: [ENH]: gridspec_mosaic +* :ghissue:`24815`: [TST] Upcoming dependency test failures +* :ghissue:`24712`: [ENH]: Reverse legend +* :ghissue:`22308`: [Bug] set_3d_properties type error in Matplotlib 3.5.1 +* :ghissue:`24741`: [Doc]: tables in "notes" cut off content +* :ghissue:`20044`: AnnotationBbox gid not passed to renderer +* :ghissue:`24762`: [Doc]: Development workflow doc has lots of typos and clunky sentences +* :ghissue:`24235`: [Bug]: pcolormesh(rasterized=True) conflicts with set_rasterization_zorder() +* :ghissue:`24471`: [Bug]: CheckBoxes should be square, not rectangular +* :ghissue:`18804`: bugged pads on savefig +* :ghissue:`20656`: Sphinx extension plot_directive not able to detect function +* :ghissue:`24704`: [Bug]: ImportError: DLL load failed on Windows +* :ghissue:`20639`: document Legend.legendHandles +* :ghissue:`19633`: Multicursor disappears when not moving on nbagg with useblit=False + burns CPU +* :ghissue:`24717`: Update Research Notice on README.md +* :ghissue:`22754`: [Bug]: It is recommended for you to run autogen before configuring freetype +* :ghissue:`24349`: [Bug]: sharex and sharey don't accept 0 and 1 as bool values +* :ghissue:`20577`: Using ``legend(labelcolor="markerfacecolor")`` with a scatter plot throws an error +* :ghissue:`24424`: [Doc]: Inheritance diagrams +* :ghissue:`9580`: Broken legend auto-position with step*-type histograms +* :ghissue:`22176`: [MNT]: Write a bot to post doc build issues +* :ghissue:`24623`: [Bug]: ``offsetbox`` classes have optional arguments that are really not optional +* :ghissue:`24693`: [MNT]: Update minver policy re: GUI toolkits +* :ghissue:`23566`: [ENH]: Z-axis/3D support for Figure options +* :ghissue:`23777`: [ENH] Interactive Zoom Rectangle Color Review for MACOSX backend +* :ghissue:`24676`: [Doc]: quiver_doc etc leads to documentation of the documentation string +* :ghissue:`24568`: [ENH]: Ellipse annotation +* :ghissue:`6982`: cla(), clf() should unset the ``.axes`` and ``.figure`` attributes of deparented artists +* :ghissue:`11227`: fig.set_dpi() does not set the dpi correctly +* :ghissue:`24418`: [ENH]: rgp or rgba option for pyplot pcolormesh and/or pcolor +* :ghissue:`22236`: [Bug]: integer colours for pcolorfast / quadmesh +* :ghissue:`4277`: RGB not supported in pcolormesh +* :ghissue:`23155`: [ENH]: do_3d_projection could restore original verts order after draw() finishes +* :ghissue:`24386`: [Bug]: ``align`` in ``HPacker`` is reversed +* :ghissue:`23803`: Static code analysis +* :ghissue:`8990`: Surprising behaviour of mutating input arrays to Axes.plot vs Axes3D.plot +* :ghissue:`24550`: [ENH]: Warn when a SymLogScale receives values that are all in the linear regime +* :ghissue:`23416`: [Bug]: Inconsistent y-axis unit label with plot/scatter +* :ghissue:`23603`: [MNT]: Only a subset of attributes set via ``Axes.tick_params()`` are accessible via public methods and attributes +* :ghissue:`13858`: matplotlib.sphinxext.plot_directive generates incorrect links when using dirhtml builder +* :ghissue:`19376`: eventplot: allow a list of alpha channels as in the case with colors +* :ghissue:`24508`: [Bug]: Re-organization of mpl_toolkits tests broke tools/triage_tests.py +* :ghissue:`19040`: v3.3.0 Regression, Animation draws artists multiple times. +* :ghissue:`12324`: DOC: Write a unified backend doc +* :ghissue:`24464`: Issue with legend labelcolor='linecolor' for errorbar plots +* :ghissue:`24273`: [ENH]: Axes.set_xticks/Axis.set_ticks only validates kwargs if ticklabels are set, but they should +* :ghissue:`24454`: [Bug]: "import matplotlib.pyplot" gives ModuleNotFoundError +* :ghissue:`24394`: [TST]: Appveyor Qt tests failing +* :ghissue:`21959`: [ENH]: Use ``repr`` instead of ``str`` in the error message +* :ghissue:`22676`: [ENH]: Colorbar should support location kwarg that sets both orientation and ticklocation +* :ghissue:`23901`: [Doc]: add summary table to Axes3D similar to Axes +* :ghissue:`22105`: [Bug]: imshow extents can't have units? +* :ghissue:`21878`: [MNT]: make axis labels of 3d axis anchor-rotate +* :ghissue:`17978`: Document how to distribute style files in python packages +* :ghissue:`23965`: Simplify glyph stream logic in ps backend +* :ghissue:`19509`: Adding lightsource when plotting Poly3DCollection +* :ghissue:`17523`: Unclear if no gallery argument for doc builds works +* :ghissue:`23250`: [Bug]: Incorrect mathtext rendering of ``r"$\|$"`` with default (dejavu) math fontfamily +* :ghissue:`24010`: c++17 removed random_shuffle +* :ghissue:`20424`: function shadowing their own definition modules +* :ghissue:`20781`: Make the pane color in 3d plots configurable +* :ghissue:`14426`: Existing FigureCanvasQT objects destroyed by call to plt.figure +* :ghissue:`5908`: Unclear Documentation ticker class +* :ghissue:`24099`: [Bug]: Error using width_ratios with nested mosaic in subplot_mosaic() +* :ghissue:`6893`: List environment variables in matplotlib.__doc__ +* :ghissue:`11445`: The axes module structure +* :ghissue:`23847`: [Bug]: set_aspect with negative argument leads to infinite loop +* :ghissue:`24136`: [Doc]: document ``julian2num`` and ``num2julian``? +* :ghissue:`5332`: QuadContourSet lacks remove method +* :ghissue:`110`: pan and zoom are broken for mplot3d +* :ghissue:`441`: Polar plot error bars don't rotate with angle +* :ghissue:`24064`: Convert readme.rst to readme.md +* :ghissue:`10029`: \times in minor ticklabels not recognized due to \mathdefault +* :ghissue:`24080`: verify quoting method in svg backend for font names +* :ghissue:`23601`: [Doc]: add gridlines to style sheet reference +* :ghissue:`24075`: [ENH]: Resizing the figure with webagg backend by dragging the corner +* :ghissue:`23352`: [Doc]: bar examples should probably not have "score by ... gender" in them... +* :ghissue:`23819`: [MNT]: Make draw_gouraud_triangle optional +* :ghissue:`9181`: legend draggable as keyword +* :ghissue:`23688`: [Bug]: ``Axes.bar_label()`` on log scale does not center the label. +* :ghissue:`23689`: [ENH]: Add f-string formatting to labels in ``Axes.bar_label()`` +* :ghissue:`23718`: [Bug]: Installing from source fails during Freetype compilation with spaces in working directory filepath Previous GitHub statistics diff --git a/doc/users/prev_whats_new/github_stats_3.6.3.rst b/doc/users/prev_whats_new/github_stats_3.6.3.rst new file mode 100644 index 000000000000..b1d17a791c87 --- /dev/null +++ b/doc/users/prev_whats_new/github_stats_3.6.3.rst @@ -0,0 +1,165 @@ +.. _github-stats-3-6-3: + +GitHub statistics for 3.6.3 (Jan 11, 2023) +========================================== + +GitHub statistics for 2022/11/02 (tag: v3.6.2) - 2023/01/11 + +These lists are automatically generated, and may be incomplete or contain duplicates. + +We closed 16 issues and merged 107 pull requests. +The full list can be seen `on GitHub `__ + +The following 20 authors contributed 198 commits. + +* Antony Lee +* Chahak Mehta +* David Stansby +* Elliott Sales de Andrade +* Eric Larson +* hannah +* iofall +* Jody Klymak +* Kaidong Hu +* Kyle Sunden +* matt statham +* Matthias Bussonnier +* Muhammad Abdur Rakib +* Oscar Gustafsson +* ramvikrams +* Ruth Comer +* Steffen Rehberg +* Thomas A Caswell +* Tim Hoffmann +* yuanx749 + +GitHub issues and pull requests: + +Pull Requests (107): + +* :ghpull:`24939`: Backport PR #23390 on branch v3.6.x (FIX: colorbar contour with log norm should default to log locator and formatter...) +* :ghpull:`24936`: Backport PR #24927 on branch v3.6.x (DOC: Remove space after directive name, before double-colon) +* :ghpull:`23390`: FIX: colorbar contour with log norm should default to log locator and formatter... +* :ghpull:`24932`: Backport PR #24783 on branch v3.6.x (inset locator fix with tests added) +* :ghpull:`24783`: inset locator fix with tests added +* :ghpull:`24927`: DOC: Remove space after directive name, before double-colon +* :ghpull:`24881`: Backport PR #24880 on branch v3.6.x (Minor cleanups to named colors example.) +* :ghpull:`24876`: Backport PR #24873 on branch v3.6.x (Copy-edit fonts docs.) +* :ghpull:`24857`: Backport PR #24856 on branch v3.6.x (fix typo) +* :ghpull:`24852`: Backport PR #24843 on branch v3.6.x (Show that fill_between and span_where provide similar functionalities.) +* :ghpull:`24808`: Backport PR #24807 on branch v3.6.x (Axes.stem docstring document orientation as literals) +* :ghpull:`24807`: Axes.stem docstring document orientation as literals +* :ghpull:`24791`: Backport PR #24785 on branch v3.6.x (Fix random generation of single floats) +* :ghpull:`24777`: Backport PR #24772 on branch v3.6.x (Fix Left ventricle bullseye example) +* :ghpull:`24775`: Backport PR #24774 on branch v3.6.x (DOC: fix strip_chart example with numpy 1.24) +* :ghpull:`24765`: Backport PR #24764 on branch v3.6.x (DOC: ``subplot_mosaic`` tutorial - clarify ratios keywords used directly) +* :ghpull:`24739`: Backport PR #24732 on branch v3.6.x (Use masked stack to preserve mask info) +* :ghpull:`24738`: Backport PR #24735 on branch v3.6.x (Correct note about aspect) +* :ghpull:`24732`: Use masked stack to preserve mask info +* :ghpull:`24735`: Correct note about aspect +* :ghpull:`24729`: Backport PR #24715 on branch v3.6.x (Add note that users do not instantiate Axes directly) +* :ghpull:`24715`: Add note that users do not instantiate Axes directly +* :ghpull:`24721`: Backport PR #24607 on branch v3.6.x (DOC: tweak wording on Figure.show warning) +* :ghpull:`24607`: DOC: tweak wording on Figure.show warning +* :ghpull:`24694`: Backport PR #24692 on branch v3.6.x (Avoid rgba8888->argb32 conversion if qt can do it for us.) +* :ghpull:`24692`: Avoid rgba8888->argb32 conversion if qt can do it for us. +* :ghpull:`24684`: Backport PR #24654: Don't manually invalidate cached lines in _update_transScale +* :ghpull:`24687`: Backport PR #24003 on branch v3.6.x (Fix wording and links lifecycle tutorial) +* :ghpull:`24685`: Backport PR #23974 on branch v3.6.x (Fix repeated word typos) +* :ghpull:`24680`: Backport PR #24677 on branch v3.6.x (FIX: do not replace the Axes._children list object) +* :ghpull:`24677`: FIX: do not replace the Axes._children list object +* :ghpull:`24659`: Backport PR #24657 on branch v3.6.x (BUG: Fix bug with mutable input modification) +* :ghpull:`24657`: BUG: Fix bug with mutable input modification +* :ghpull:`24654`: Don't manually invalidate cached lines in _update_transScale. +* :ghpull:`24650`: Backport PR #24645 on branch v3.6.x (Removed 'above' wording from Input hook integration docs (#24632)) +* :ghpull:`24647`: Backport PR #24643 on branch v3.6.x (DOC: annotation coords are not floats) +* :ghpull:`24643`: DOC: annotation coords are not floats +* :ghpull:`24625`: Backport PR #24606: FIX: do not use deprecated API in gtk4 backend +* :ghpull:`24633`: Backport PR #24592 on branch v3.6.x (DOC: Don't try to link paths that are on a different drive) +* :ghpull:`24592`: DOC: Don't try to link paths that are on a different drive +* :ghpull:`24628`: Backport PR #24584 on branch v3.6.x (DOC: add "See Also: draw_idle" reference to pyplot.draw) +* :ghpull:`24584`: DOC: add "See Also: draw_idle" reference to pyplot.draw +* :ghpull:`24601`: Backport PR #24600 on branch v3.6.x (Fix: Gracefully fail the string validator for tuple inputs) +* :ghpull:`24609`: Backport PR #24595 on branch v3.6.x (ci: Stop building wheels on AppVeyor) +* :ghpull:`24616`: Backport PR #24397 on branch v3.6.x (Simplify appveyor to only use conda) +* :ghpull:`24615`: Backport PR #24598 on branch v3.6.x (Check for errors/warnings on failed doc-builds) +* :ghpull:`24606`: FIX: do not use deprecated API in gtk4 backend +* :ghpull:`24612`: Backport PR #23868 on branch v3.6.x (Show errors and warnings in doc CI after build.) +* :ghpull:`24595`: ci: Stop building wheels on AppVeyor +* :ghpull:`24600`: Fix: Gracefully fail the string validator for tuple inputs +* :ghpull:`24593`: Backport PR #24580 on branch v3.6.x (Update the polar transform information in doc #24499) +* :ghpull:`24587`: Backport PR #24579: Add explicit permissions to GitHub Actions +* :ghpull:`24579`: Add explicit permissions to GitHub Actions +* :ghpull:`24561`: Backport PR #24540 on branch v3.6.x (DOC: add note about enabling c++11 support for old gcc) +* :ghpull:`24559`: Backport PR #24299 on branch v3.6.x (Rework style sheet reference example to cycle props) +* :ghpull:`24551`: Backport PR #24548 on branch v3.6.x (DOC: improved the doc for layout_engine.py) +* :ghpull:`24548`: DOC: improved the doc for layout_engine.py +* :ghpull:`24535`: Backport PR #24514 on branch v3.6.x (Fix potential issue in contour) +* :ghpull:`24534`: Backport PR #24521 on branch v3.6.x (Doc: improve spelling and grammar) +* :ghpull:`24533`: Backport PR #24517 on branch v3.6.x (DOC: improve grammar and consistency) +* :ghpull:`24532`: Backport PR #24520 on branch v3.6.x (Doc: Fix grammar and spelling) +* :ghpull:`24514`: Fix potential issue in contour +* :ghpull:`24521`: Doc: improve spelling and grammar +* :ghpull:`24517`: DOC: improve grammar and consistency +* :ghpull:`24520`: Doc: Fix grammar and spelling +* :ghpull:`24515`: Backport PR #24512 on branch v3.6.x (Tweak markup in toolkits tutorials.) +* :ghpull:`24503`: Backport PR #24502 on branch v3.6.x (Remove link from demo_floating_axes title.) +* :ghpull:`24505`: Backport PR #24482 on branch v3.6.x (Use relative frame path in HTMLWriter) +* :ghpull:`24506`: Backport of PR#24488 (Update for pydata-sphinx-theme 0.12.0) +* :ghpull:`24482`: Use relative frame path in HTMLWriter +* :ghpull:`24496`: Backport PR #24495 on branch v3.6.x (Update adding of google analytics key for docs) +* :ghpull:`24495`: Update adding of google analytics key for docs +* :ghpull:`24488`: Update for pydata-sphinx-theme 0.12.0 +* :ghpull:`24485`: Backport PR #24481 on branch v3.6.x (Fix floating-point drift in oscilloscope example) +* :ghpull:`24475`: DOC: Fix examples gallery layout issues +* :ghpull:`24478`: Backport PR #24444 on branch v3.6.x (DOC: AnnotationBbox keyword descriptions) +* :ghpull:`24444`: DOC: AnnotationBbox keyword descriptions +* :ghpull:`24468`: Backport PR #24429 on branch v3.6.x (DOC: Clarify transparency in colors) +* :ghpull:`24466`: Backport PR #24460 on branch v3.6.x (Define autoscale() based on autoscale_None().) +* :ghpull:`24460`: Define autoscale() based on autoscale_None(). +* :ghpull:`24463`: Backport PR #24459 on branch v3.6.x (removed unused variable and fixed text in doc) +* :ghpull:`24459`: removed unused variable and fixed text in doc +* :ghpull:`24458`: Backport PR #24434 on branch v3.6.x (Fix pyplot.figlegend docstring) +* :ghpull:`24434`: Fix pyplot.figlegend docstring +* :ghpull:`24456`: Backport PR #24402 on branch v3.6.x (DOC: Fix title formats in backend api docs) +* :ghpull:`24438`: Backport PR #24435 on branch v3.6.x (Minor improvements to LogLocator docstring) +* :ghpull:`24435`: Minor improvements to LogLocator docstring +* :ghpull:`24426`: Backport PR #24422 on branch v3.6.x (Make QT_API a link in the qt embedding example.) +* :ghpull:`24411`: Backport PR #24407 on branch v3.6.x (Reword "Reordering is not commutative" phrase in tutorial.) +* :ghpull:`24400`: Backport PR #24399 on branch v3.6.x (Fix docstring of Figure.subfigures.) +* :ghpull:`24399`: Fix docstring of Figure.subfigures. +* :ghpull:`24391`: Backport PR #24380 on branch v3.6.x (DOC: Remove the example "Pythonic Matplotlib") +* :ghpull:`24384`: Backport PR #24377 on branch v3.6.x (DOC: Cleanup Spine placement example) +* :ghpull:`24381`: Backport PR #24366 on branch v3.6.x (DOC: Improve Image Slices Viewer example) +* :ghpull:`24382`: Backport PR #24378 on branch v3.6.x (DOC: Cleanup spines usage in examples) +* :ghpull:`24378`: DOC: Cleanup spines usage in examples +* :ghpull:`24366`: DOC: Improve Image Slices Viewer example +* :ghpull:`24370`: Backport PR #24368 on branch v3.6.x (DOC: Install dev dependencies before building matplotlib) +* :ghpull:`24368`: DOC: Install dev dependencies before building matplotlib +* :ghpull:`24365`: Backport PR #24363 on branch v3.6.x (DOC: Fix syntax of suggestion) +* :ghpull:`24358`: Backport PR #24354 on branch v3.6.x (DOC: clarify rc_context resets all rcParams changes) +* :ghpull:`24354`: DOC: clarify rc_context resets all rcParams changes +* :ghpull:`24353`: Backport PR #24343 on branch v3.6.x (Emit "axes not compatible with tight_layout" in a single place.) +* :ghpull:`24343`: Emit "axes not compatible with tight_layout" in a single place. +* :ghpull:`24346`: Backport PR #24344 on branch v3.6.x (Add test for colorbar extend alpha) +* :ghpull:`24344`: Add test for colorbar extend alpha +* :ghpull:`23974`: Fix repeated word typos + +Issues (16): + +* :ghissue:`23389`: [Bug]: Colorbar with log scales wrong format +* :ghissue:`24589`: [Bug]: inset_locator is broken when used with subfigures +* :ghissue:`10160`: Low resolution (dpi problem) with Qt5 backend on new iMac Pro Retina +* :ghissue:`24545`: [Bug]: ``matplotlib.pyplot.scatter`` does not respect mask rules with ``datetime`` +* :ghissue:`24639`: [Bug]: The Axes3D does not work as expected. +* :ghissue:`22169`: [Doc]: figure.show works beyond what is documented +* :ghissue:`23968`: [Bug]: Zoom rubber band lags in larger window +* :ghissue:`24574`: [Bug]: Extension error (sphinx.ext.linkcode) while building docs +* :ghissue:`24602`: ``close_event`` deprecated warning. +* :ghissue:`24518`: [Doc]: ``layout_engine`` description +* :ghissue:`23581`: [BUG]: frame paths relative to the html file when saving an animation to html +* :ghissue:`23976`: [Doc]: Examples Gallery Layout changed to one or two columns +* :ghissue:`24390`: [Doc]: alpha setting for annotation ``TextArea`` +* :ghissue:`24433`: [Doc]: figlegend examples call ``fig.figlegend`` instead of ``plt.figlegend`` or ``fig.legend`` +* :ghissue:`24360`: [ENH]: imshow support for multiple slice image volume +* :ghissue:`24359`: [Bug]: Documentation not so clear that a C/C++-compiler is required to install from source From 5f86f41b13b5e97967c42e0792136e0e5c83321c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 25 Jan 2023 03:40:06 -0500 Subject: [PATCH 234/262] REL: v3.7.0rc1 First release candidate for 3.7.0. From d790a8f59630838995831eb2a9f47db0a4ccfa5c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 25 Jan 2023 03:44:24 -0500 Subject: [PATCH 235/262] BLD: bump branch away from tag So the tarballs from GitHub are stable. From fcdcbeeb5038e8c9bb2cb4156038850dabf5746b Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 25 Jan 2023 14:24:00 -0600 Subject: [PATCH 236/262] Backport PR #25079: FIX: Only send one update signal when autoscaling norms --- lib/matplotlib/colors.py | 8 ++++++-- lib/matplotlib/tests/test_colors.py | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index ab0d73c4b5fb..9c0725c8888a 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1372,8 +1372,12 @@ def inverse(self, value): def autoscale(self, A): """Set *vmin*, *vmax* to min, max of *A*.""" - self.vmin = self.vmax = None - self.autoscale_None(A) + with self.callbacks.blocked(): + # Pause callbacks while we are updating so we only get + # a single update signal at the end + self.vmin = self.vmax = None + self.autoscale_None(A) + self._changed() def autoscale_None(self, A): """If vmin or vmax are not set, use the min/max of *A* to set them.""" diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index a5809f0fa89f..e40796caa7cc 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -1493,6 +1493,11 @@ def test_norm_callback(): norm.vmax = 5 assert increment.call_count == 2 + # We only want autoscale() calls to send out one update signal + increment.call_count = 0 + norm.autoscale([0, 1, 2]) + assert increment.call_count == 1 + def test_scalarmappable_norm_update(): norm = mcolors.Normalize() From 5329101cafe765fd94a0cf3c28429ea2d454e9f9 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 25 Jan 2023 15:31:44 -0500 Subject: [PATCH 237/262] Backport PR #25074: Revert "Use system distutils instead of the setuptools copy" --- azure-pipelines.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 640136a00e9b..a9b080ed7efc 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -130,8 +130,7 @@ stages: displayName: 'Install dependencies with pip' - bash: | - # Due to https://github.com/pypa/setuptools/pull/2896 - SETUPTOOLS_USE_DISTUTILS=stdlib python -m pip install -ve . || + python -m pip install -ve . || [[ "$PYTHON_VERSION" = 'Pre' ]] displayName: "Install self" From 3b89bae8b54b405b339c82afb1107f19def00557 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 25 Jan 2023 15:44:20 -0500 Subject: [PATCH 238/262] DOC: Fix typos in GitHub stats --- doc/users/github_stats.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index 78476e969866..cde7ccfe38e2 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -482,7 +482,7 @@ Pull Requests (380): * :ghpull:`23950`: DOC: Don't import doctest because we're not using it * :ghpull:`21006`: Rotate errorbar caps in polar plots * :ghpull:`23870`: Implement Sphinx-Gallery's ``make html-noplot`` -* :ghpull:`23905`: made explict that install link is install docs in readme +* :ghpull:`23905`: made explicit that install link is install docs in readme * :ghpull:`23824`: Deprecate draw_gouraud_triangle * :ghpull:`23913`: Add draggable as param to Legend init * :ghpull:`23896`: Inline AnchoredOffsetBox._update_offset_func. @@ -534,7 +534,7 @@ Issues (110): * :ghissue:`23849`: [Bug]: The point marker is not actually unfilled * :ghissue:`24321`: [ENH]: Auto-detect bool arrays passed to contour()? * :ghissue:`24842`: axes3d.quiver() fails when providing args to Line3DCollection -* :ghissue:`24093`: [Bug]: CenteredNorm gets stuck in infinite recusion when given all zeros +* :ghissue:`24093`: [Bug]: CenteredNorm gets stuck in infinite recursion when given all zeros * :ghissue:`24571`: [ENH]: gridspec_mosaic * :ghissue:`24815`: [TST] Upcoming dependency test failures * :ghissue:`24712`: [ENH]: Reverse legend From eaa60b2d40c98d551aba0bce4a72db030ad0b2c0 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Thu, 26 Jan 2023 12:40:24 +0000 Subject: [PATCH 239/262] Backport PR #25088: DOC: Fix broken cross-reference when building PDF --- doc/users/explain/figures.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/users/explain/figures.rst b/doc/users/explain/figures.rst index ffba58bac0b1..a26f10712fe0 100644 --- a/doc/users/explain/figures.rst +++ b/doc/users/explain/figures.rst @@ -124,8 +124,8 @@ figures inside a parent Figure; see It is possible to directly instantiate a `.Figure` instance without using the pyplot interface. This is usually only necessary if you want to create your own GUI application or service that you do not want carrying the pyplot global -state. See the embedding examples in :doc:`/gallery/user_interfaces/index` for -examples of how to do this. +state. See the embedding examples in :ref:`user_interfaces` for examples of +how to do this. Figure options -------------- From 3436c3b05ddbc8ac30ba1310ffffd2c3ff3760e5 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 26 Jan 2023 14:46:36 -0600 Subject: [PATCH 240/262] Backport PR #25092: Fix distribution of test data --- setupext.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setupext.py b/setupext.py index 4d41bdd44a89..a898d642d631 100644 --- a/setupext.py +++ b/setupext.py @@ -495,12 +495,12 @@ def get_package_data(self): 'tests/test_*.ipynb', ], 'mpl_toolkits': [ - *_pkg_data_helper('mpl_toolkits/axes_grid1', - 'tests/baseline_images'), - *_pkg_data_helper('mpl_toolkits/axisartist' - 'tests/baseline_images'), - *_pkg_data_helper('mpl_toolkits/mplot3d' - 'tests/baseline_images'), + *_pkg_data_helper('mpl_toolkits', + 'axes_grid1/tests/baseline_images'), + *_pkg_data_helper('mpl_toolkits', + 'axisartist/tests/baseline_images'), + *_pkg_data_helper('mpl_toolkits', + 'mplot3d/tests/baseline_images'), ] } From b7b2e447807625736b1f13fb0b48668973ed035e Mon Sep 17 00:00:00 2001 From: David Stansby Date: Sat, 28 Jan 2023 10:35:44 +0000 Subject: [PATCH 241/262] Backport PR #25098: Correctly pass valinit as keyword in SliderTool. --- lib/matplotlib/widgets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index d169cb488eb9..9668c0233d9f 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -1873,8 +1873,8 @@ def __init__(self, targetfig, toolfig): # The last subplot, removed below, keeps space for the "Reset" button. for name, ax in zip(names, toolfig.subplots(len(names) + 1)): ax.set_navigate(False) - slider = Slider(ax, name, - 0, 1, getattr(targetfig.subplotpars, name)) + slider = Slider(ax, name, 0, 1, + valinit=getattr(targetfig.subplotpars, name)) slider.on_changed(self._on_slider_changed) self._sliders.append(slider) toolfig.axes[-1].remove() From 2d0a5b4159156ef73d96d70d42216bc8e4c91968 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 30 Jan 2023 16:59:23 -0600 Subject: [PATCH 242/262] Backport PR #25110: Stop recommending `ncol` in legend examples --- .../lines_bars_and_markers/horizontal_barchart_distribution.py | 2 +- examples/text_labels_and_annotations/legend_demo.py | 2 +- examples/user_interfaces/mplcvd.py | 2 +- examples/userdemo/simple_legend01.py | 2 +- tutorials/intermediate/legend_guide.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/lines_bars_and_markers/horizontal_barchart_distribution.py b/examples/lines_bars_and_markers/horizontal_barchart_distribution.py index 3a22ce3ed4ae..3ec12ba00e8d 100644 --- a/examples/lines_bars_and_markers/horizontal_barchart_distribution.py +++ b/examples/lines_bars_and_markers/horizontal_barchart_distribution.py @@ -60,7 +60,7 @@ def survey(results, category_names): r, g, b, _ = color text_color = 'white' if r * g * b < 0.5 else 'darkgrey' ax.bar_label(rects, label_type='center', color=text_color) - ax.legend(ncol=len(category_names), bbox_to_anchor=(0, 1), + ax.legend(ncols=len(category_names), bbox_to_anchor=(0, 1), loc='lower left', fontsize='small') return fig, ax diff --git a/examples/text_labels_and_annotations/legend_demo.py b/examples/text_labels_and_annotations/legend_demo.py index 0dc0858f3cc4..11df93095fe4 100644 --- a/examples/text_labels_and_annotations/legend_demo.py +++ b/examples/text_labels_and_annotations/legend_demo.py @@ -47,7 +47,7 @@ for n in range(1, 5): ax0.plot(x, x**n, label=f"{n=}") leg = ax0.legend(loc="upper left", bbox_to_anchor=[0, 1], - ncol=2, shadow=True, title="Legend", fancybox=True) + ncols=2, shadow=True, title="Legend", fancybox=True) leg.get_title().set_color("red") # Demonstrate some more complex labels. diff --git a/examples/user_interfaces/mplcvd.py b/examples/user_interfaces/mplcvd.py index e65cb7d26a3b..8eaa22a8977a 100644 --- a/examples/user_interfaces/mplcvd.py +++ b/examples/user_interfaces/mplcvd.py @@ -295,5 +295,5 @@ def _setup_wx(tb): th = np.linspace(0, 2*np.pi, 1024) for j in [1, 2, 4, 6]: axd['lines'].plot(th, np.sin(th * j), label=f'$\\omega={j}$') - axd['lines'].legend(ncol=2, loc='upper right') + axd['lines'].legend(ncols=2, loc='upper right') plt.show() diff --git a/examples/userdemo/simple_legend01.py b/examples/userdemo/simple_legend01.py index c80488d1ad2d..2aaac1424558 100644 --- a/examples/userdemo/simple_legend01.py +++ b/examples/userdemo/simple_legend01.py @@ -15,7 +15,7 @@ # Place a legend above this subplot, expanding itself to # fully use the given bounding box. ax.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left', - ncol=2, mode="expand", borderaxespad=0.) + ncols=2, mode="expand", borderaxespad=0.) ax = fig.add_subplot(223) ax.plot([1, 2, 3], label="test1") diff --git a/tutorials/intermediate/legend_guide.py b/tutorials/intermediate/legend_guide.py index 338fca72fbf1..0fbe4b2d3526 100644 --- a/tutorials/intermediate/legend_guide.py +++ b/tutorials/intermediate/legend_guide.py @@ -127,7 +127,7 @@ # Place a legend above this subplot, expanding itself to # fully use the given bounding box. ax_dict['top'].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left', - ncol=2, mode="expand", borderaxespad=0.) + ncols=2, mode="expand", borderaxespad=0.) ax_dict['bottom'].plot([1, 2, 3], label="test1") ax_dict['bottom'].plot([3, 2, 1], label="test2") From c7e815b042fd6738c53101740d49e0bd20104fdd Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 31 Jan 2023 20:01:23 +0000 Subject: [PATCH 243/262] Backport PR #25113: Fix outdated comment re: _update_label_position. --- lib/matplotlib/axis.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index fff753704cea..0b4646cd5df7 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1374,12 +1374,8 @@ def draw(self, renderer, *args, **kwargs): for tick in ticks_to_draw: tick.draw(renderer) - # Scale up the axis label box to also find the neighbors, not just the - # tick labels that actually overlap. We need a *copy* of the axis - # label box because we don't want to scale the actual bbox. - + # Shift label away from axes to avoid overlapping ticklabels. self._update_label_position(renderer) - self.label.draw(renderer) self._update_offset_text_position(tlb1, tlb2) From 446b1455a17c2bca36d7fb4b2f018b689c8f2e3f Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 2 Feb 2023 13:24:03 -0500 Subject: [PATCH 244/262] Backport PR #24993: [DOC] GitHub spelling and links --- doc/devel/contributing.rst | 4 ++-- doc/devel/dependencies.rst | 12 ++++++++---- doc/devel/development_workflow.rst | 6 +++--- doc/devel/maintainer_workflow.rst | 4 ++-- doc/devel/triage.rst | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/devel/contributing.rst b/doc/devel/contributing.rst index 17a7e3e9dfe3..6026c7b4d443 100644 --- a/doc/devel/contributing.rst +++ b/doc/devel/contributing.rst @@ -38,7 +38,7 @@ Contributor incubator The incubator is our non-public communication channel for new contributors. It is a private gitter room moderated by core Matplotlib developers where you can get guidance and support for your first few PRs. It's a place you can ask -questions about anything: how to use git, github, how our PR review process +questions about anything: how to use git, GitHub, how our PR review process works, technical questions about the code, what makes for good documentation or a blog post, how to get involved in community work, or get "pre-review" on your PR. @@ -57,7 +57,7 @@ Among our attendees are fellow new contributors, as well as maintainers, and veteran contributors, who are keen to support onboarding of new folks and share their experience. You can find our community calendar link at the `Scientific Python website `_, and -you can browse previous meeting notes on `github +you can browse previous meeting notes on `GitHub `_. We recommend joining the meeting to clarify any doubts, or lingering diff --git a/doc/devel/dependencies.rst b/doc/devel/dependencies.rst index 4463b10b679a..da67cae0061e 100644 --- a/doc/devel/dependencies.rst +++ b/doc/devel/dependencies.rst @@ -215,10 +215,13 @@ Matplotlib requires a C++ compiler that supports C++11. - `gcc 4.8.1 `_ or higher. For gcc <6.5 you will need to set ``$CFLAGS=-std=c++11`` to enable C++11 support. -- `clang 3.3 `_ or higher + `Installing GCC: Binaries `_. +- `clang 3.3 `_ or higher. + `LLVM Download Page `_. - `Visual Studio 2015 `_ - (aka VS 14.0) or higher + (aka VS 14.0) or higher. A free version of Build Tools for Visual Studio is available for + `download `_. .. _test-dependencies: @@ -304,9 +307,10 @@ Additional external dependencies -------------------------------- Required: -* a minimal working LaTeX distribution +* a minimal working LaTeX distribution, e.g., `TeX Live `_ or + `MikTeX `_ * `Graphviz `_ -* the following LaTeX packages (if your OS bundles TeXLive, the +* the following LaTeX packages (if your OS bundles TeX Live, the "complete" version of the installer, e.g. "texlive-full" or "texlive-all", will often automatically include these packages): diff --git a/doc/devel/development_workflow.rst b/doc/devel/development_workflow.rst index e465fb0acc1d..2635787f997c 100644 --- a/doc/devel/development_workflow.rst +++ b/doc/devel/development_workflow.rst @@ -28,10 +28,10 @@ why you did it, we recommend the following: .. note:: It may sound strange, but deleting your own ``main`` branch can help reduce - confusion about which branch you are on. See `deleting main on github`_ for + confusion about which branch you are on. See `deleting main on GitHub`_ for details. -.. _deleting main on github: https://matthew-brett.github.io/pydagogue/gh_delete_master.html +.. _deleting main on GitHub: https://matthew-brett.github.io/pydagogue/gh_delete_master.html .. _update-mirror-main: @@ -134,7 +134,7 @@ In more detail description in the `tangled working copy problem`_. The `git commit `_ manual page might also be useful. -#. To push the changes up to your forked repo on github, do a ``git +#. To push the changes up to your forked repo on GitHub, do a ``git push``. .. _why the -a flag?: http://gitready.com/beginner/2009/01/18/the-staging-area.html diff --git a/doc/devel/maintainer_workflow.rst b/doc/devel/maintainer_workflow.rst index f11375e26d1b..7723e6cb8c0c 100644 --- a/doc/devel/maintainer_workflow.rst +++ b/doc/devel/maintainer_workflow.rst @@ -50,7 +50,7 @@ If there are only a few commits, consider rebasing to upstream:: git rebase upstream-rw/main Remember that, if you do a rebase, and push that, you'll have to close any -github pull requests manually, because github will not be able to detect the +GitHub pull requests manually, because GitHub will not be able to detect the changes have already been merged. A long series of commits @@ -61,7 +61,7 @@ If there are a longer series of related commits, consider a merge instead:: git fetch upstream-rw git merge --no-ff upstream-rw/main -The merge will be detected by github, and should close any related pull requests +The merge will be detected by GitHub, and should close any related pull requests automatically. Note the ``--no-ff`` above. This forces git to make a merge commit, rather than diff --git a/doc/devel/triage.rst b/doc/devel/triage.rst index 7b09da2488f7..2106ac99c606 100755 --- a/doc/devel/triage.rst +++ b/doc/devel/triage.rst @@ -87,7 +87,7 @@ Triaging operations for members of the core and triage teams In addition to the above, members of the core team and the triage team can do the following important tasks: -- Update labels for issues and PRs: see the list of `available github +- Update labels for issues and PRs: see the list of `available GitHub labels `_. - Triage issues: From ba1b912700ad68ea44ac3dc4790a0f10d748508c Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 2 Feb 2023 21:41:43 +0100 Subject: [PATCH 245/262] Backport PR #25126: FIX: fully invalidate TransformWrapper parents before swapping --- lib/matplotlib/tests/test_transforms.py | 16 +++++++++++++++- lib/matplotlib/transforms.py | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_transforms.py b/lib/matplotlib/tests/test_transforms.py index 1501a918b9c8..064a7240c39d 100644 --- a/lib/matplotlib/tests/test_transforms.py +++ b/lib/matplotlib/tests/test_transforms.py @@ -10,7 +10,7 @@ import matplotlib.patches as mpatches import matplotlib.transforms as mtransforms from matplotlib.path import Path -from matplotlib.testing.decorators import image_comparison +from matplotlib.testing.decorators import image_comparison, check_figures_equal def test_non_affine_caching(): @@ -730,3 +730,17 @@ def test_transformwrapper(): r"The input and output dims of the new child \(1, 1\) " r"do not match those of current child \(2, 2\)")): t.set(scale.LogTransform(10)) + + +@check_figures_equal(extensions=["png"]) +def test_scale_swapping(fig_test, fig_ref): + np.random.seed(19680801) + samples = np.random.normal(size=10) + x = np.linspace(-5, 5, 10) + + for fig, log_state in zip([fig_test, fig_ref], [True, False]): + ax = fig.subplots() + ax.hist(samples, log=log_state, density=True) + ax.plot(x, np.exp(-(x**2) / 2) / np.sqrt(2 * np.pi)) + fig.canvas.draw() + ax.set_yscale('linear') diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index 7a2d20b21bc7..c5c051be570f 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -1719,6 +1719,7 @@ def set(self, child): dimensions as the current child. """ if hasattr(self, "_child"): # Absent during init. + self.invalidate() new_dims = (child.input_dims, child.output_dims) old_dims = (self._child.input_dims, self._child.output_dims) if new_dims != old_dims: From 4edbfd8df22308e76914b29b31ec1f7ed2cafc24 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Sat, 4 Feb 2023 21:35:56 +0000 Subject: [PATCH 246/262] Backport PR #25151: Increase timeout to GitHub API --- examples/lines_bars_and_markers/timeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lines_bars_and_markers/timeline.py b/examples/lines_bars_and_markers/timeline.py index 2b4f7d81d059..e13bab115a30 100644 --- a/examples/lines_bars_and_markers/timeline.py +++ b/examples/lines_bars_and_markers/timeline.py @@ -23,7 +23,7 @@ url = 'https://api.github.com/repos/matplotlib/matplotlib/releases' url += '?per_page=100' - data = json.loads(urllib.request.urlopen(url, timeout=.4).read().decode()) + data = json.loads(urllib.request.urlopen(url, timeout=1).read().decode()) dates = [] names = [] From 99a2c5f68cab3f67f4dbdf8d318c802bd9066760 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 6 Feb 2023 14:09:33 +0100 Subject: [PATCH 247/262] Backport PR #25129: Undeprecate Cursor event handlers --- examples/event_handling/cursor_demo.py | 21 ++++++++++++ examples/widgets/annotated_cursor.py | 14 ++++++++ lib/matplotlib/tests/test_widgets.py | 8 +++-- lib/matplotlib/widgets.py | 44 ++++++-------------------- 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/examples/event_handling/cursor_demo.py b/examples/event_handling/cursor_demo.py index 30604b549542..7f17113c87f5 100644 --- a/examples/event_handling/cursor_demo.py +++ b/examples/event_handling/cursor_demo.py @@ -28,6 +28,8 @@ import matplotlib.pyplot as plt import numpy as np +from matplotlib.backend_bases import MouseEvent + class Cursor: """ @@ -71,6 +73,11 @@ def on_mouse_move(self, event): cursor = Cursor(ax) fig.canvas.mpl_connect('motion_notify_event', cursor.on_mouse_move) +# Simulate a mouse move to (0.5, 0.5), needed for online docs +t = ax.transData +MouseEvent( + "motion_notify_event", ax.figure.canvas, *t.transform((0.5, 0.5)) +)._process() ############################################################################## # Faster redrawing using blitting @@ -85,6 +92,7 @@ def on_mouse_move(self, event): # created whenever the figure changes. This is achieved by connecting to the # ``'draw_event'``. + class BlittedCursor: """ A cross-hair cursor using blitting for faster redraw. @@ -152,6 +160,11 @@ def on_mouse_move(self, event): blitted_cursor = BlittedCursor(ax) fig.canvas.mpl_connect('motion_notify_event', blitted_cursor.on_mouse_move) +# Simulate a mouse move to (0.5, 0.5), needed for online docs +t = ax.transData +MouseEvent( + "motion_notify_event", ax.figure.canvas, *t.transform((0.5, 0.5)) +)._process() ############################################################################## # Snapping to data points @@ -165,6 +178,7 @@ def on_mouse_move(self, event): # the lag due to many redraws. Of course, blitting could still be added on top # for additional speedup. + class SnappingCursor: """ A cross-hair cursor that snaps to the data point of a line, which is @@ -218,4 +232,11 @@ def on_mouse_move(self, event): line, = ax.plot(x, y, 'o') snap_cursor = SnappingCursor(ax, line) fig.canvas.mpl_connect('motion_notify_event', snap_cursor.on_mouse_move) + +# Simulate a mouse move to (0.5, 0.5), needed for online docs +t = ax.transData +MouseEvent( + "motion_notify_event", ax.figure.canvas, *t.transform((0.5, 0.5)) +)._process() + plt.show() diff --git a/examples/widgets/annotated_cursor.py b/examples/widgets/annotated_cursor.py index 3601a37fe54a..3fb21b1f2302 100644 --- a/examples/widgets/annotated_cursor.py +++ b/examples/widgets/annotated_cursor.py @@ -24,6 +24,8 @@ import numpy as np import matplotlib.pyplot as plt +from matplotlib.backend_bases import MouseEvent + class AnnotatedCursor(Cursor): """ @@ -312,6 +314,12 @@ def _update(self): color='red', linewidth=2) +# Simulate a mouse move to (-2, 10), needed for online docs +t = ax.transData +MouseEvent( + "motion_notify_event", ax.figure.canvas, *t.transform((-2, 10)) +)._process() + plt.show() ############################################################################### @@ -339,4 +347,10 @@ def _update(self): useblit=True, color='red', linewidth=2) +# Simulate a mouse move to (-2, 10), needed for online docs +t = ax.transData +MouseEvent( + "motion_notify_event", ax.figure.canvas, *t.transform((-2, 10)) +)._process() + plt.show() diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index 5eb32e69901a..f49132a44364 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -1654,7 +1654,9 @@ def test_MultiCursor(horizOn, vertOn): # Can't use `do_event` as that helper requires the widget # to have a single .ax attribute. event = mock_event(ax1, xdata=.5, ydata=.25) - multi._onmove(event) + multi.onmove(event) + # force a draw + draw event to exercise clear + ax1.figure.canvas.draw() # the lines in the first two ax should both move for l in multi.vlines: @@ -1671,7 +1673,7 @@ def test_MultiCursor(horizOn, vertOn): multi.horizOn = not multi.horizOn multi.vertOn = not multi.vertOn event = mock_event(ax1, xdata=.5, ydata=.25) - multi._onmove(event) + multi.onmove(event) assert len([line for line in multi.vlines if line.get_visible()]) == ( 0 if vertOn else 2) assert len([line for line in multi.hlines if line.get_visible()]) == ( @@ -1680,7 +1682,7 @@ def test_MultiCursor(horizOn, vertOn): # test a move event in an Axes not part of the MultiCursor # the lines in ax1 and ax2 should not have moved. event = mock_event(ax3, xdata=.75, ydata=.75) - multi._onmove(event) + multi.onmove(event) for l in multi.vlines: assert l.get_xdata() == (.5, .5) for l in multi.hlines: diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 9668c0233d9f..6315450a1573 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -1953,8 +1953,8 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, **lineprops): super().__init__(ax) - self.connect_event('motion_notify_event', self._onmove) - self.connect_event('draw_event', self._clear) + self.connect_event('motion_notify_event', self.onmove) + self.connect_event('draw_event', self.clear) self.visible = True self.horizOn = horizOn @@ -1967,29 +1967,16 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, self.linev = ax.axvline(ax.get_xbound()[0], visible=False, **lineprops) self.background = None - self._needclear = False - - needclear = _api.deprecate_privatize_attribute("3.7") + self.needclear = False - @_api.deprecated('3.7') def clear(self, event): - """Internal event handler to clear the cursor.""" - self._clear(event) - if self.ignore(event): - return - self.linev.set_visible(False) - self.lineh.set_visible(False) - - def _clear(self, event): """Internal event handler to clear the cursor.""" if self.ignore(event): return if self.useblit: self.background = self.canvas.copy_from_bbox(self.ax.bbox) - onmove = _api.deprecate_privatize_attribute('3.7') - - def _onmove(self, event): + def onmove(self, event): """Internal event handler to draw the cursor when the mouse moves.""" if self.ignore(event): return @@ -1999,11 +1986,11 @@ def _onmove(self, event): self.linev.set_visible(False) self.lineh.set_visible(False) - if self._needclear: + if self.needclear: self.canvas.draw() - self._needclear = False + self.needclear = False return - self._needclear = True + self.needclear = True self.linev.set_xdata((event.xdata, event.xdata)) self.linev.set_visible(self.visible and self.vertOn) @@ -2106,8 +2093,8 @@ def connect(self): """Connect events.""" for canvas, info in self._canvas_infos.items(): info["cids"] = [ - canvas.mpl_connect('motion_notify_event', self._onmove), - canvas.mpl_connect('draw_event', self._clear), + canvas.mpl_connect('motion_notify_event', self.onmove), + canvas.mpl_connect('draw_event', self.clear), ] def disconnect(self): @@ -2117,16 +2104,7 @@ def disconnect(self): canvas.mpl_disconnect(cid) info["cids"].clear() - @_api.deprecated('3.7') def clear(self, event): - """Clear the cursor.""" - if self.ignore(event): - return - self._clear(event) - for line in self.vlines + self.hlines: - line.set_visible(False) - - def _clear(self, event): """Clear the cursor.""" if self.ignore(event): return @@ -2134,9 +2112,7 @@ def _clear(self, event): for canvas, info in self._canvas_infos.items(): info["background"] = canvas.copy_from_bbox(canvas.figure.bbox) - onmove = _api.deprecate_privatize_attribute('3.7') - - def _onmove(self, event): + def onmove(self, event): if (self.ignore(event) or event.inaxes not in self.axes or not event.canvas.widgetlock.available(self)): From 613845b35360527327f946289b7a4e97c574ff3e Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 6 Feb 2023 09:51:15 -0600 Subject: [PATCH 248/262] Backport PR #25158: Disconnect SubplotTool destroyer callback on tool_fig close --- lib/matplotlib/backend_bases.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index c573c369e9e3..6ce8ce61a119 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -3357,10 +3357,14 @@ def configure_subplots(self, *args): tool_fig = manager.canvas.figure tool_fig.subplots_adjust(top=0.9) self.subplot_tool = widgets.SubplotTool(self.canvas.figure, tool_fig) - tool_fig.canvas.mpl_connect( - "close_event", lambda e: delattr(self, "subplot_tool")) - self.canvas.mpl_connect( + cid = self.canvas.mpl_connect( "close_event", lambda e: manager.destroy()) + + def on_tool_fig_close(e): + self.canvas.mpl_disconnect(cid) + del self.subplot_tool + + tool_fig.canvas.mpl_connect("close_event", on_tool_fig_close) manager.show() return self.subplot_tool From 6a3209c0e87963fec2cf8f1a91791184ebb2a51b Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sun, 29 Jan 2023 19:52:04 +0100 Subject: [PATCH 249/262] Fix cursor_demo wrt. Line2D.set_x/ydata not accepting scalars anymore. Trying to run the example prior to the PR would result in exceptions being thrown on mouse moves. Manual backport of #25106 rolled into backport of #25129 (backport pr #25160) --- examples/event_handling/cursor_demo.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/event_handling/cursor_demo.py b/examples/event_handling/cursor_demo.py index 7f17113c87f5..e4acd77bce2f 100644 --- a/examples/event_handling/cursor_demo.py +++ b/examples/event_handling/cursor_demo.py @@ -58,8 +58,8 @@ def on_mouse_move(self, event): self.set_cross_hair_visible(True) x, y = event.xdata, event.ydata # update the line positions - self.horizontal_line.set_ydata(y) - self.vertical_line.set_xdata(x) + self.horizontal_line.set_ydata([y]) + self.vertical_line.set_xdata([x]) self.text.set_text('x=%1.2f, y=%1.2f' % (x, y)) self.ax.figure.canvas.draw() @@ -140,8 +140,8 @@ def on_mouse_move(self, event): self.set_cross_hair_visible(True) # update the line positions x, y = event.xdata, event.ydata - self.horizontal_line.set_ydata(y) - self.vertical_line.set_xdata(x) + self.horizontal_line.set_ydata([y]) + self.vertical_line.set_xdata([x]) self.text.set_text('x=%1.2f, y=%1.2f' % (x, y)) self.ax.figure.canvas.restore_region(self.background) @@ -218,8 +218,8 @@ def on_mouse_move(self, event): x = self.x[index] y = self.y[index] # update the line positions - self.horizontal_line.set_ydata(y) - self.vertical_line.set_xdata(x) + self.horizontal_line.set_ydata([y]) + self.vertical_line.set_xdata([x]) self.text.set_text('x=%1.2f, y=%1.2f' % (x, y)) self.ax.figure.canvas.draw() From 0b4e200435e59d245b862a46894d4c33a3c0acce Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 7 Feb 2023 12:03:49 +0100 Subject: [PATCH 250/262] Backport PR #25122: FIX: scaling factor for window with negative value --- lib/matplotlib/mlab.py | 8 ++++---- lib/matplotlib/tests/test_mlab.py | 31 +++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/mlab.py b/lib/matplotlib/mlab.py index 5e85a9c1194f..059cf0f1624b 100644 --- a/lib/matplotlib/mlab.py +++ b/lib/matplotlib/mlab.py @@ -395,12 +395,12 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None, elif mode == 'psd': result = np.conj(result) * result elif mode == 'magnitude': - result = np.abs(result) / np.abs(window).sum() + result = np.abs(result) / window.sum() elif mode == 'angle' or mode == 'phase': # we unwrap the phase later to handle the onesided vs. twosided case result = np.angle(result) elif mode == 'complex': - result /= np.abs(window).sum() + result /= window.sum() if mode == 'psd': @@ -424,10 +424,10 @@ def _spectral_helper(x, y=None, NFFT=None, Fs=None, detrend_func=None, result /= Fs # Scale the spectrum by the norm of the window to compensate for # windowing loss; see Bendat & Piersol Sec 11.5.2. - result /= (np.abs(window)**2).sum() + result /= (window**2).sum() else: # In this case, preserve power in the segment, not amplitude - result /= np.abs(window).sum()**2 + result /= window.sum()**2 t = np.arange(NFFT/2, len(x) - NFFT/2 + 1, NFFT - noverlap)/Fs diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 86beb5c8c803..9cd1b44cc1e2 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -615,7 +615,7 @@ def test_psd_window_hanning(self): noverlap=0, sides=self.sides, window=mlab.window_none) - spec_c *= len(ycontrol1)/(np.abs(windowVals)**2).sum() + spec_c *= len(ycontrol1)/(windowVals**2).sum() assert_array_equal(fsp_g, fsp_c) assert_array_equal(fsp_b, fsp_c) assert_allclose(spec_g, spec_c, atol=1e-08) @@ -662,7 +662,7 @@ def test_psd_window_hanning_detrend_linear(self): noverlap=0, sides=self.sides, window=mlab.window_none) - spec_c *= len(ycontrol1)/(np.abs(windowVals)**2).sum() + spec_c *= len(ycontrol1)/(windowVals**2).sum() assert_array_equal(fsp_g, fsp_c) assert_array_equal(fsp_b, fsp_c) assert_allclose(spec_g, spec_c, atol=1e-08) @@ -670,6 +670,33 @@ def test_psd_window_hanning_detrend_linear(self): with pytest.raises(AssertionError): assert_allclose(spec_b, spec_c, atol=1e-08) + def test_psd_window_flattop(self): + # flattop window + # adaption from https://github.com/scipy/scipy/blob\ + # /v1.10.0/scipy/signal/windows/_windows.py#L562-L622 + a = [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368] + fac = np.linspace(-np.pi, np.pi, self.NFFT_density_real) + win = np.zeros(self.NFFT_density_real) + for k in range(len(a)): + win += a[k] * np.cos(k * fac) + + spec, fsp = mlab.psd(x=self.y, + NFFT=self.NFFT_density, + Fs=self.Fs, + noverlap=0, + sides=self.sides, + window=win, + scale_by_freq=False) + spec_a, fsp_a = mlab.psd(x=self.y, + NFFT=self.NFFT_density, + Fs=self.Fs, + noverlap=0, + sides=self.sides, + window=win) + assert_allclose(spec*win.sum()**2, + spec_a*self.Fs*(win**2).sum(), + atol=1e-08) + def test_psd_windowarray(self): freqs = self.freqs_density spec, fsp = mlab.psd(x=self.y, From 9ddd37a2132fdc064d537f67f7a85d714abd84bb Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Tue, 7 Feb 2023 11:28:04 -0600 Subject: [PATCH 251/262] Backport PR #25097: fix FigureCanvasTkAgg memory leak via weakrefs --- lib/matplotlib/backends/_backend_tk.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index bdbbd6ad6c77..3199ff1e8083 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -1,4 +1,5 @@ import uuid +import weakref from contextlib import contextmanager import logging import math @@ -198,14 +199,33 @@ def __init__(self, figure=None, master=None): # event to the window containing the canvas instead. # See https://wiki.tcl-lang.org/3893 (mousewheel) for details root = self._tkcanvas.winfo_toplevel() - root.bind("", self.scroll_event_windows, "+") + + # Prevent long-lived references via tkinter callback structure GH-24820 + weakself = weakref.ref(self) + weakroot = weakref.ref(root) + + def scroll_event_windows(event): + self = weakself() + if self is None: + root = weakroot() + if root is not None: + root.unbind("", scroll_event_windows_id) + return + return self.scroll_event_windows(event) + scroll_event_windows_id = root.bind("", scroll_event_windows, "+") # Can't get destroy events by binding to _tkcanvas. Therefore, bind # to the window and filter. def filter_destroy(event): + self = weakself() + if self is None: + root = weakroot() + if root is not None: + root.unbind("", filter_destroy_id) + return if event.widget is self._tkcanvas: CloseEvent("close_event", self)._process() - root.bind("", filter_destroy, "+") + filter_destroy_id = root.bind("", filter_destroy, "+") self._tkcanvas.focus_set() From 3670d41ca2a6e1acb74eacda6361f96dffc5d455 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Thu, 9 Feb 2023 18:51:27 +0000 Subject: [PATCH 252/262] Backport PR #25052: Support both Bbox and list for bbox to table/Table --- lib/matplotlib/table.py | 9 ++++++--- lib/matplotlib/tests/test_table.py | 30 +++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/table.py b/lib/matplotlib/table.py index d9f614532693..a431eaf618ca 100644 --- a/lib/matplotlib/table.py +++ b/lib/matplotlib/table.py @@ -285,7 +285,7 @@ def __init__(self, ax, loc=None, bbox=None, **kwargs): loc : str The position of the cell with respect to *ax*. This must be one of the `~.Table.codes`. - bbox : `.Bbox` or None + bbox : `.Bbox` or [xmin, ymin, width, height], optional A bounding box to draw the table into. If this is not *None*, this overrides *loc*. @@ -595,7 +595,10 @@ def _update_positions(self, renderer): if self._bbox is not None: # Position according to bbox - rl, rb, rw, rh = self._bbox + if isinstance(self._bbox, Bbox): + rl, rb, rw, rh = self._bbox.bounds + else: + rl, rb, rw, rh = self._bbox self.scale(rw / w, rh / h) ox = rl - l oy = rb - b @@ -710,7 +713,7 @@ def table(ax, The position of the cell with respect to *ax*. This must be one of the `~.Table.codes`. - bbox : `.Bbox`, optional + bbox : `.Bbox` or [xmin, ymin, width, height], optional A bounding box to draw the table into. If this is not *None*, this overrides *loc*. diff --git a/lib/matplotlib/tests/test_table.py b/lib/matplotlib/tests/test_table.py index d4f68ea1805d..9b2cb96ea037 100644 --- a/lib/matplotlib/tests/test_table.py +++ b/lib/matplotlib/tests/test_table.py @@ -1,9 +1,10 @@ import matplotlib.pyplot as plt import numpy as np -from matplotlib.testing.decorators import image_comparison +from matplotlib.testing.decorators import image_comparison, check_figures_equal from matplotlib.table import CustomCell, Table from matplotlib.path import Path +from matplotlib.transforms import Bbox def test_non_square(): @@ -194,3 +195,30 @@ def test_table_cells(): # properties and setp table.properties() plt.setp(table) + + +@check_figures_equal(extensions=["png"]) +def test_table_bbox(fig_test, fig_ref): + data = [[2, 3], + [4, 5]] + + col_labels = ('Foo', 'Bar') + row_labels = ('Ada', 'Bob') + + cell_text = [[f"{x}" for x in row] for row in data] + + ax_list = fig_test.subplots() + ax_list.table(cellText=cell_text, + rowLabels=row_labels, + colLabels=col_labels, + loc='center', + bbox=[0.1, 0.2, 0.8, 0.6] + ) + + ax_bbox = fig_ref.subplots() + ax_bbox.table(cellText=cell_text, + rowLabels=row_labels, + colLabels=col_labels, + loc='center', + bbox=Bbox.from_extents(0.1, 0.2, 0.9, 0.8) + ) From 322a3e2c627f1a72643a7034acd4642d13f886dd Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 9 Feb 2023 14:42:55 -0500 Subject: [PATCH 253/262] Backport PR #25174: Accept LA icons for the toolbar --- lib/matplotlib/backends/_backend_tk.py | 2 + lib/matplotlib/backends/backend_wx.py | 4 +- lib/matplotlib/tests/test_backend_tk.py | 3 +- .../tests/test_backends_interactive.py | 43 ++++++++++++++++--- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index bdbbd6ad6c77..38c59bc67b13 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -745,6 +745,8 @@ def _recolor_icon(image, color): # Use the high-resolution (48x48 px) icon if it exists and is needed with Image.open(path_large if (size > 24 and path_large.exists()) else path_regular) as im: + # assure a RGBA image as foreground color is RGB + im = im.convert("RGBA") image = ImageTk.PhotoImage(im.resize((size, size)), master=self) button._ntimage = image diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 8de879a3c02d..eeed515aafa2 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1112,7 +1112,9 @@ def _icon(name): *name*, including the extension and relative to Matplotlib's "images" data directory. """ - image = np.array(PIL.Image.open(cbook._get_data_path("images", name))) + pilimg = PIL.Image.open(cbook._get_data_path("images", name)) + # ensure RGBA as wx BitMap expects RGBA format + image = np.array(pilimg.convert("RGBA")) try: dark = wx.SystemSettings.GetAppearance().IsDark() except AttributeError: # wxpython < 4.1 diff --git a/lib/matplotlib/tests/test_backend_tk.py b/lib/matplotlib/tests/test_backend_tk.py index 4d43e27aa4a4..55a7ae0b51aa 100644 --- a/lib/matplotlib/tests/test_backend_tk.py +++ b/lib/matplotlib/tests/test_backend_tk.py @@ -7,8 +7,9 @@ import pytest -from matplotlib.testing import subprocess_run_helper from matplotlib import _c_internal_utils +from matplotlib.testing import subprocess_run_helper + _test_timeout = 60 # A reasonably safe value for slower architectures. diff --git a/lib/matplotlib/tests/test_backends_interactive.py b/lib/matplotlib/tests/test_backends_interactive.py index f0d19842e439..c3b7ed206d18 100644 --- a/lib/matplotlib/tests/test_backends_interactive.py +++ b/lib/matplotlib/tests/test_backends_interactive.py @@ -7,13 +7,17 @@ import signal import subprocess import sys +import tempfile import time import urllib.request +from PIL import Image + import pytest import matplotlib as mpl from matplotlib import _c_internal_utils +from matplotlib.backend_tools import ToolToggleBase from matplotlib.testing import subprocess_run_helper as _run_helper @@ -71,6 +75,24 @@ def _get_testable_interactive_backends(): _test_timeout = 60 # A reasonably safe value for slower architectures. +def _test_toolbar_button_la_mode_icon(fig): + # test a toolbar button icon using an image in LA mode (GH issue 25174) + # create an icon in LA mode + with tempfile.TemporaryDirectory() as tempdir: + img = Image.new("LA", (26, 26)) + tmp_img_path = os.path.join(tempdir, "test_la_icon.png") + img.save(tmp_img_path) + + class CustomTool(ToolToggleBase): + image = tmp_img_path + description = "" # gtk3 backend does not allow None + + toolmanager = fig.canvas.manager.toolmanager + toolbar = fig.canvas.manager.toolbar + toolmanager.add_tool("test", CustomTool) + toolbar.add_tool("test", "group") + + # The source of this function gets extracted and run in another process, so it # must be fully self-contained. # Using a timer not only allows testing of timers (on other backends), but is @@ -122,7 +144,6 @@ def check_alt_backend(alt_backend): if importlib.util.find_spec("cairocffi"): check_alt_backend(backend[:-3] + "cairo") check_alt_backend("svg") - mpl.use(backend, force=True) fig, ax = plt.subplots() @@ -130,6 +151,10 @@ def check_alt_backend(alt_backend): type(fig.canvas).__module__, "matplotlib.backends.backend_{}".format(backend)) + if mpl.rcParams["toolbar"] == "toolmanager": + # test toolbar button icon LA mode see GH issue 25174 + _test_toolbar_button_la_mode_icon(fig) + ax.plot([0, 1], [2, 3]) if fig.canvas.toolbar: # i.e toolbar2. fig.canvas.toolbar.draw_rubberband(None, 1., 1, 2., 2) @@ -168,11 +193,17 @@ def test_interactive_backend(env, toolbar): pytest.skip("toolmanager is not implemented for macosx.") if env["MPLBACKEND"] == "wx": pytest.skip("wx backend is deprecated; tests failed on appveyor") - proc = _run_helper(_test_interactive_impl, - json.dumps({"toolbar": toolbar}), - timeout=_test_timeout, - extra_env=env) - + try: + proc = _run_helper( + _test_interactive_impl, + json.dumps({"toolbar": toolbar}), + timeout=_test_timeout, + extra_env=env, + ) + except subprocess.CalledProcessError as err: + pytest.fail( + "Subprocess failed to test intended behavior\n" + + str(err.stderr)) assert proc.stdout.count("CloseEvent") == 1 From 6e51d121fc9add5677d8ce8107bd514d0dc7e77b Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 9 Feb 2023 15:16:36 -0600 Subject: [PATCH 254/262] Backport PR #25183: FIX: do not use deprecated API internally --- lib/matplotlib/backends/backend_nbagg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_nbagg.py b/lib/matplotlib/backends/backend_nbagg.py index 712f45735940..f4ee4b1179f3 100644 --- a/lib/matplotlib/backends/backend_nbagg.py +++ b/lib/matplotlib/backends/backend_nbagg.py @@ -14,7 +14,7 @@ from matplotlib import is_interactive from matplotlib._pylab_helpers import Gcf -from matplotlib.backend_bases import _Backend, NavigationToolbar2 +from matplotlib.backend_bases import _Backend, CloseEvent, NavigationToolbar2 from .backend_webagg_core import ( FigureCanvasWebAggCore, FigureManagerWebAgg, NavigationToolbar2WebAgg) from .backend_webagg_core import ( # noqa: F401 # pylint: disable=W0611 @@ -149,7 +149,7 @@ def clearup_closed(self): if socket.is_open()} if len(self.web_sockets) == 0: - self.canvas.close_event() + CloseEvent("close_event", self.canvas)._process() def remove_comm(self, comm_id): self.web_sockets = {socket for socket in self.web_sockets From 3c42ab042132de385203951cfc05528ab92e18fe Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 26 Jan 2023 22:53:06 +0100 Subject: [PATCH 255/262] Backport PR #24893: STY: make allowed line length 9 longer to 88 from 79 --- .flake8 | 2 +- doc/api/next_api_changes/development/24893-KS.rst | 8 ++++++++ doc/devel/MEP/MEP08.rst | 5 ++++- doc/devel/coding_guide.rst | 8 +++++++- 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 doc/api/next_api_changes/development/24893-KS.rst diff --git a/.flake8 b/.flake8 index ef1333dbf4c0..490ea57d9891 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -max-line-length = 79 +max-line-length = 88 select = # flake8 default C90, E, F, W, diff --git a/doc/api/next_api_changes/development/24893-KS.rst b/doc/api/next_api_changes/development/24893-KS.rst new file mode 100644 index 000000000000..382f0c1c5cc1 --- /dev/null +++ b/doc/api/next_api_changes/development/24893-KS.rst @@ -0,0 +1,8 @@ +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 `_. diff --git a/doc/devel/MEP/MEP08.rst b/doc/devel/MEP/MEP08.rst index 67ce5d3d76ef..18419ac2bf11 100644 --- a/doc/devel/MEP/MEP08.rst +++ b/doc/devel/MEP/MEP08.rst @@ -9,7 +9,10 @@ Status ====== -**Completed** +**Superseded** + +Current guidelines for style, including usage of pep8 are maintained +in `our pull request guidelines `_. We are currently enforcing a sub-set of pep8 on new code contributions. diff --git a/doc/devel/coding_guide.rst b/doc/devel/coding_guide.rst index 3e9788ade101..d584a1c986e7 100644 --- a/doc/devel/coding_guide.rst +++ b/doc/devel/coding_guide.rst @@ -30,7 +30,8 @@ rules before submitting a pull request: for more details. * Formatting should follow the recommendations of PEP8_, as enforced by - flake8_. You can check flake8 compliance from the command line with :: + flake8_. Matplotlib modifies PEP8 to extend the maximum line length to 88 + characters. You can check flake8 compliance from the command line with :: python -m pip install flake8 flake8 /path/to/module.py @@ -156,6 +157,11 @@ Content topics: * Does the PR conform with the :ref:`coding_guidelines`? * Is the :ref:`documentation ` (docstrings, examples, what's new, API changes) updated? +* Is the change purely stylistic? Generally, such changes are discouraged when + not part of other non-stylistic work because it obscures the git history of + functional changes to the code. Reflowing a method or docstring as part of a + larger refactor/rewrite is acceptable. + Organizational topics: From f8ecdaf942a76c82410f19d9ca3edfb18b552bf0 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 9 Feb 2023 18:14:06 -0500 Subject: [PATCH 256/262] Backport PR #25085: FIX: only try to update blit caches if the canvas we expect --- lib/matplotlib/tests/test_widgets.py | 40 ++++++++++++++++++++++++++++ lib/matplotlib/widgets.py | 28 ++++++++++++++++--- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index f49132a44364..ce942964a313 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -1,4 +1,5 @@ import functools +import io from unittest import mock from matplotlib._api.deprecation import MatplotlibDeprecationWarning @@ -23,6 +24,45 @@ def ax(): return get_ax() +def test_save_blitted_widget_as_pdf(): + from matplotlib.widgets import CheckButtons, RadioButtons + from matplotlib.cbook import _get_running_interactive_framework + if _get_running_interactive_framework() not in ['headless', None]: + pytest.xfail("Callback exceptions are not raised otherwise.") + + fig, ax = plt.subplots( + nrows=2, ncols=2, figsize=(5, 2), width_ratios=[1, 2] + ) + default_rb = RadioButtons(ax[0, 0], ['Apples', 'Oranges']) + styled_rb = RadioButtons( + ax[0, 1], ['Apples', 'Oranges'], + label_props={'color': ['red', 'orange'], + 'fontsize': [16, 20]}, + radio_props={'edgecolor': ['red', 'orange'], + 'facecolor': ['mistyrose', 'peachpuff']} + ) + + default_cb = CheckButtons(ax[1, 0], ['Apples', 'Oranges'], + actives=[True, True]) + styled_cb = CheckButtons( + ax[1, 1], ['Apples', 'Oranges'], + actives=[True, True], + label_props={'color': ['red', 'orange'], + 'fontsize': [16, 20]}, + frame_props={'edgecolor': ['red', 'orange'], + 'facecolor': ['mistyrose', 'peachpuff']}, + check_props={'color': ['darkred', 'darkorange']} + ) + + ax[0, 0].set_title('Default') + ax[0, 1].set_title('Stylized') + # force an Agg render + fig.canvas.draw() + # force a pdf save + with io.BytesIO() as result_after: + fig.savefig(result_after, format='pdf') + + @pytest.mark.parametrize('kwargs', [ dict(), dict(useblit=True, button=1), diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 6315450a1573..dfc0450132c6 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -90,6 +90,22 @@ def ignore(self, event): """ return not self.active + def _changed_canvas(self): + """ + Someone has switched the canvas on us! + + This happens if `savefig` needs to save to a format the previous + backend did not support (e.g. saving a figure using an Agg based + backend saved to a vector format). + + Returns + ------- + bool + True if the canvas has been changed. + + """ + return self.canvas is not self.ax.figure.canvas + class AxesWidget(Widget): """ @@ -1088,7 +1104,7 @@ def __init__(self, ax, labels, actives=None, *, useblit=True, def _clear(self, event): """Internal event handler to clear the buttons.""" - if self.ignore(event): + if self.ignore(event) or self._changed_canvas(): return self._background = self.canvas.copy_from_bbox(self.ax.bbox) self.ax.draw_artist(self._checks) @@ -1700,7 +1716,7 @@ def __init__(self, ax, labels, active=0, activecolor=None, *, def _clear(self, event): """Internal event handler to clear the buttons.""" - if self.ignore(event): + if self.ignore(event) or self._changed_canvas(): return self._background = self.canvas.copy_from_bbox(self.ax.bbox) self.ax.draw_artist(self._buttons) @@ -1971,7 +1987,7 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, def clear(self, event): """Internal event handler to clear the cursor.""" - if self.ignore(event): + if self.ignore(event) or self._changed_canvas(): return if self.useblit: self.background = self.canvas.copy_from_bbox(self.ax.bbox) @@ -2110,6 +2126,12 @@ def clear(self, event): return if self.useblit: for canvas, info in self._canvas_infos.items(): + # someone has switched the canvas on us! This happens if + # `savefig` needs to save to a format the previous backend did + # not support (e.g. saving a figure using an Agg based backend + # saved to a vector format). + if canvas is not canvas.figure.canvas: + continue info["background"] = canvas.copy_from_bbox(canvas.figure.bbox) def onmove(self, event): From 3e0e0b3ef883b0ea1f5438445847dfee874fee39 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sat, 11 Feb 2023 12:13:57 +0100 Subject: [PATCH 257/262] Backport PR #25193: Fix displacement of colorbar for eps with bbox_inches='tight' --- lib/matplotlib/backends/backend_ps.py | 5 +- .../test_backend_ps/colorbar_shift.eps | 897 ++++++++++++++++++ lib/matplotlib/tests/test_backend_ps.py | 10 + 3 files changed, 910 insertions(+), 2 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_backend_ps/colorbar_shift.eps diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index 7c1a45d385cb..68dd61e6f126 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -825,7 +825,7 @@ def get_default_filetype(self): def _print_ps( self, fmt, outfile, *, metadata=None, papertype=None, orientation='portrait', - **kwargs): + bbox_inches_restore=None, **kwargs): dpi = self.figure.dpi self.figure.dpi = 72 # Override the dpi kwarg @@ -860,7 +860,8 @@ def _print_ps( if mpl.rcParams['text.usetex'] else self._print_figure) printer(fmt, outfile, dpi=dpi, dsc_comments=dsc_comments, - orientation=orientation, papertype=papertype, **kwargs) + orientation=orientation, papertype=papertype, + bbox_inches_restore=bbox_inches_restore, **kwargs) def _print_figure( self, fmt, outfile, *, diff --git a/lib/matplotlib/tests/baseline_images/test_backend_ps/colorbar_shift.eps b/lib/matplotlib/tests/baseline_images/test_backend_ps/colorbar_shift.eps new file mode 100644 index 000000000000..b88e23a33c42 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_backend_ps/colorbar_shift.eps @@ -0,0 +1,897 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: colorbar_shift.eps +%%Creator: Matplotlib v3.7.0.dev1597+g613b343238.d20230210, https://matplotlib.org/ +%%CreationDate: Fri Feb 10 16:16:04 2023 +%%Orientation: portrait +%%BoundingBox: 110 245 502 547 +%%HiResBoundingBox: 110.097762 245.509625 501.902238 546.490375 +%%EndComments +%%BeginProlog +/mpldict 11 dict def +mpldict begin +/_d { bind def } bind def +/m { moveto } _d +/l { lineto } _d +/r { rlineto } _d +/c { curveto } _d +/cl { closepath } _d +/ce { closepath eofill } _d +/box { + m + 1 index 0 r + 0 exch r + neg 0 r + cl + } _d +/clipbox { + box + clip + newpath + } _d +/sc { setcachedevice } _d +%!PS-Adobe-3.0 Resource-Font +%%Creator: Converted from TrueType to Type 3 by Matplotlib. +10 dict begin +/FontName /DejaVuSans def +/PaintType 0 def +/FontMatrix [0.00048828125 0 0 0.00048828125 0 0] def +/FontBBox [-2090 -948 3673 2524] def +/FontType 3 def +/Encoding [/period /zero /one /two /minus /four /five /six /eight /nine] def +/CharStrings 11 dict dup begin +/.notdef 0 def +/period{651 0 219 0 430 254 sc +219 254 m +430 254 l +430 0 l +219 0 l +219 254 l + +ce} _d +/zero{1303 0 135 -29 1167 1520 sc +651 1360 m +547 1360 469 1309 416 1206 c +364 1104 338 950 338 745 c +338 540 364 387 416 284 c +469 182 547 131 651 131 c +756 131 834 182 886 284 c +939 387 965 540 965 745 c +965 950 939 1104 886 1206 c +834 1309 756 1360 651 1360 c + +651 1520 m +818 1520 946 1454 1034 1321 c +1123 1189 1167 997 1167 745 c +1167 494 1123 302 1034 169 c +946 37 818 -29 651 -29 c +484 -29 356 37 267 169 c +179 302 135 494 135 745 c +135 997 179 1189 267 1321 c +356 1454 484 1520 651 1520 c + +ce} _d +/one{1303 0 225 0 1114 1493 sc +254 170 m +584 170 l +584 1309 l +225 1237 l +225 1421 l +582 1493 l +784 1493 l +784 170 l +1114 170 l +1114 0 l +254 0 l +254 170 l + +ce} _d +/two{1303 0 150 0 1098 1520 sc +393 170 m +1098 170 l +1098 0 l +150 0 l +150 170 l +227 249 331 356 463 489 c +596 623 679 709 713 748 c +778 821 823 882 848 932 c +874 983 887 1032 887 1081 c +887 1160 859 1225 803 1275 c +748 1325 675 1350 586 1350 c +523 1350 456 1339 385 1317 c +315 1295 240 1262 160 1217 c +160 1421 l +241 1454 317 1478 388 1495 c +459 1512 523 1520 582 1520 c +737 1520 860 1481 952 1404 c +1044 1327 1090 1223 1090 1094 c +1090 1033 1078 974 1055 919 c +1032 864 991 800 930 725 c +913 706 860 650 771 557 c +682 465 556 336 393 170 c + +ce} _d +/minus{1716 0 217 557 1499 727 sc +217 727 m +1499 727 l +1499 557 l +217 557 l +217 727 l + +ce} _d +/four{1303 0 100 0 1188 1493 sc +774 1317 m +264 520 l +774 520 l +774 1317 l + +721 1493 m +975 1493 l +975 520 l +1188 520 l +1188 352 l +975 352 l +975 0 l +774 0 l +774 352 l +100 352 l +100 547 l +721 1493 l + +ce} _d +/five{1303 0 158 -29 1124 1493 sc +221 1493 m +1014 1493 l +1014 1323 l +406 1323 l +406 957 l +435 967 465 974 494 979 c +523 984 553 987 582 987 c +749 987 881 941 978 850 c +1075 759 1124 635 1124 479 c +1124 318 1074 193 974 104 c +874 15 733 -29 551 -29 c +488 -29 424 -24 359 -13 c +294 -2 227 14 158 35 c +158 238 l +218 205 280 181 344 165 c +408 149 476 141 547 141 c +662 141 754 171 821 232 c +888 293 922 375 922 479 c +922 583 888 665 821 726 c +754 787 662 817 547 817 c +493 817 439 811 385 799 c +332 787 277 768 221 743 c +221 1493 l + +ce} _d +/six{1303 0 143 -29 1174 1520 sc +676 827 m +585 827 513 796 460 734 c +407 672 381 587 381 479 c +381 372 407 287 460 224 c +513 162 585 131 676 131 c +767 131 838 162 891 224 c +944 287 971 372 971 479 c +971 587 944 672 891 734 c +838 796 767 827 676 827 c + +1077 1460 m +1077 1276 l +1026 1300 975 1318 923 1331 c +872 1344 821 1350 770 1350 c +637 1350 535 1305 464 1215 c +394 1125 354 989 344 807 c +383 865 433 909 492 940 c +551 971 617 987 688 987 c +838 987 956 941 1043 850 c +1130 759 1174 636 1174 479 c +1174 326 1129 203 1038 110 c +947 17 827 -29 676 -29 c +503 -29 371 37 280 169 c +189 302 143 494 143 745 c +143 981 199 1169 311 1309 c +423 1450 573 1520 762 1520 c +813 1520 864 1515 915 1505 c +967 1495 1021 1480 1077 1460 c + +ce} _d +/eight{1303 0 139 -29 1163 1520 sc +651 709 m +555 709 479 683 424 632 c +369 581 342 510 342 420 c +342 330 369 259 424 208 c +479 157 555 131 651 131 c +747 131 823 157 878 208 c +933 260 961 331 961 420 c +961 510 933 581 878 632 c +823 683 748 709 651 709 c + +449 795 m +362 816 295 857 246 916 c +198 975 174 1048 174 1133 c +174 1252 216 1347 301 1416 c +386 1485 503 1520 651 1520 c +800 1520 916 1485 1001 1416 c +1086 1347 1128 1252 1128 1133 c +1128 1048 1104 975 1055 916 c +1007 857 940 816 854 795 c +951 772 1027 728 1081 662 c +1136 596 1163 515 1163 420 c +1163 275 1119 164 1030 87 c +942 10 816 -29 651 -29 c +486 -29 360 10 271 87 c +183 164 139 275 139 420 c +139 515 166 596 221 662 c +276 728 352 772 449 795 c + +375 1114 m +375 1037 399 976 447 933 c +496 890 564 868 651 868 c +738 868 805 890 854 933 c +903 976 928 1037 928 1114 c +928 1191 903 1252 854 1295 c +805 1338 738 1360 651 1360 c +564 1360 496 1338 447 1295 c +399 1252 375 1191 375 1114 c + +ce} _d +/nine{1303 0 129 -29 1159 1520 sc +225 31 m +225 215 l +276 191 327 173 379 160 c +431 147 482 141 532 141 c +665 141 767 186 837 275 c +908 365 948 501 958 684 c +919 627 870 583 811 552 c +752 521 686 506 614 506 c +465 506 346 551 259 641 c +172 732 129 855 129 1012 c +129 1165 174 1288 265 1381 c +356 1474 476 1520 627 1520 c +800 1520 931 1454 1022 1321 c +1113 1189 1159 997 1159 745 c +1159 510 1103 322 991 181 c +880 41 730 -29 541 -29 c +490 -29 439 -24 387 -14 c +335 -4 281 11 225 31 c + +627 664 m +718 664 789 695 842 757 c +895 819 922 904 922 1012 c +922 1119 895 1204 842 1266 c +789 1329 718 1360 627 1360 c +536 1360 464 1329 411 1266 c +358 1204 332 1119 332 1012 c +332 904 358 819 411 757 c +464 695 536 664 627 664 c + +ce} _d +end readonly def + +/BuildGlyph { + exch begin + CharStrings exch + 2 copy known not {pop /.notdef} if + true 3 1 roll get exec + end +} _d + +/BuildChar { + 1 index /Encoding get exch get + 1 index /BuildGlyph get exec +} _d + +FontName currentdict end definefont pop +end +%%EndProlog +mpldict begin +110.098 245.51 translate +391.804 300.981 0 0 clipbox +gsave +0 0 m +391.804475 0 l +391.804475 300.98075 l +0 300.98075 l +cl +1.000 setgray +fill +grestore +gsave +36.465625 23.871875 m +322.161625 23.871875 l +322.161625 289.983875 l +36.465625 289.983875 l +cl +1.000 setgray +fill +grestore +/p0_0 { +newpath +translate +0 -3 m +0.795609 -3 1.55874 -2.683901 2.12132 -2.12132 c +2.683901 -1.55874 3 -0.795609 3 0 c +3 0.795609 2.683901 1.55874 2.12132 2.12132 c +1.55874 2.683901 0.795609 3 0 3 c +-0.795609 3 -1.55874 2.683901 -2.12132 2.12132 c +-2.683901 1.55874 -3 0.795609 -3 0 c +-3 -0.795609 -2.683901 -1.55874 -2.12132 -2.12132 c +-1.55874 -2.683901 -0.795609 -3 0 -3 c +cl + +} bind def +1.000 setlinewidth +1 setlinejoin +0 setlinecap +[] 0 setdash +0.000 0.500 0.000 setrgbcolor +gsave +285.696 266.112 36.466 23.872 clipbox +49.4518 156.928 p0_0 +gsave +fill +grestore +stroke +grestore +0.000 0.000 1.000 setrgbcolor +gsave +285.696 266.112 36.466 23.872 clipbox +309.175 156.928 p0_0 +gsave +fill +grestore +stroke +grestore +0.800 setlinewidth +0.000 setgray +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +0 -3.5 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +49.4518 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +41.4987 9.27812 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +0 -3.5 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +101.397 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +93.4434 9.27812 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /two glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +0 -3.5 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +153.341 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +145.388 9.27812 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /four glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +0 -3.5 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +205.286 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +197.333 9.27812 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /six glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +0 -3.5 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +257.231 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +249.278 9.27812 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /eight glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +0 -3.5 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +309.175 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +301.222 9.27812 translate +0 rotate +0 0 m /one glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +-0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +36.4656 60.1599 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +7.2 56.363 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /nine glyphshow +15.9033 0 m /six glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +-0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +36.4656 108.544 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +7.2 104.747 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /nine glyphshow +15.9033 0 m /eight glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +-0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +36.4656 156.928 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +7.2 153.131 translate +0 rotate +0 0 m /one glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /zero glyphshow +15.9033 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +-0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +36.4656 205.312 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +7.2 201.515 translate +0 rotate +0 0 m /one glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /zero glyphshow +15.9033 0 m /two glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +-0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +36.4656 253.696 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +7.2 249.899 translate +0 rotate +0 0 m /one glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /zero glyphshow +15.9033 0 m /four glyphshow +grestore +0 setlinejoin +2 setlinecap +gsave +36.465625 23.871875 m +36.465625 289.983875 l +stroke +grestore +gsave +322.161625 23.871875 m +322.161625 289.983875 l +stroke +grestore +gsave +36.465625 23.871875 m +322.161625 23.871875 l +stroke +grestore +gsave +36.465625 289.983875 m +322.161625 289.983875 l +stroke +grestore +gsave +340.017625 23.871875 m +353.323225 23.871875 l +353.323225 289.983875 l +340.017625 289.983875 l +cl +1.000 setgray +fill +grestore +gsave +13.306 266.112 340.018 23.872 clipbox +340.017625 23.871875 m +353.323225 23.871875 l +353.323225 112.575875 l +340.017625 112.575875 l +340.017625 23.871875 l +1.000 0.000 0.000 setrgbcolor +fill +grestore +gsave +13.306 266.112 340.018 23.872 clipbox +340.017625 112.575875 m +353.323225 112.575875 l +353.323225 201.279875 l +340.017625 201.279875 l +340.017625 112.575875 l +0.000 0.500 0.000 setrgbcolor +fill +grestore +gsave +13.306 266.112 340.018 23.872 clipbox +340.017625 201.279875 m +353.323225 201.279875 l +353.323225 289.983875 l +340.017625 289.983875 l +340.017625 201.279875 l +0.000 0.000 1.000 setrgbcolor +fill +grestore +1 setlinejoin +0 setlinecap +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +353.323 23.8719 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +360.323 20.075 translate +0 rotate +0 0 m /minus glyphshow +8.37891 0 m /one glyphshow +14.7412 0 m /period glyphshow +17.9199 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +353.323 112.576 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +360.323 108.779 translate +0 rotate +0 0 m /minus glyphshow +8.37891 0 m /zero glyphshow +14.7412 0 m /period glyphshow +17.9199 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +353.323 201.28 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +360.323 197.483 translate +0 rotate +0 0 m /zero glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin + +0 setlinecap + +0 0 m +3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +353.323 289.984 o +grestore +/DejaVuSans 10.000 selectfont +gsave + +360.323 286.187 translate +0 rotate +0 0 m /one glyphshow +6.3623 0 m /period glyphshow +9.54102 0 m /zero glyphshow +grestore +0 setlinejoin +2 setlinecap +gsave +340.017625 23.871875 m +346.670425 23.871875 l +353.323225 23.871875 l +353.323225 289.983875 l +346.670425 289.983875 l +340.017625 289.983875 l +340.017625 23.871875 l +cl +stroke +grestore + +end +showpage diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index b3e933a89a25..57d1172126f8 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -15,6 +15,7 @@ from matplotlib.testing.decorators import check_figures_equal, image_comparison import matplotlib as mpl import matplotlib.collections as mcollections +import matplotlib.colors as mcolors import matplotlib.pyplot as plt @@ -327,3 +328,12 @@ def test_path_collection(): facecolors='yellow', offsets=offsets) ax.add_collection(pc) ax.set_xlim(0, 1) + + +@image_comparison(["colorbar_shift.eps"], savefig_kwarg={"bbox_inches": "tight"}, + style="mpl20") +def test_colorbar_shift(tmp_path): + cmap = mcolors.ListedColormap(["r", "g", "b"]) + norm = mcolors.BoundaryNorm([-1, -0.5, 0.5, 1], cmap.N) + plt.scatter([0, 1], [1, 1], c=[0, 1], cmap=cmap, norm=norm) + plt.colorbar() From f78e8eccfc96674be027019c1549c778fba96d44 Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Sun, 12 Feb 2023 23:56:33 +0100 Subject: [PATCH 258/262] Backport PR #25196: Add deprecation for setting data with non sequence type in `Line2D` (#25201) Co-authored-by: Oscar Gustafsson --- .../next_api_changes/deprecations/25196-EP.rst | 4 ++++ lib/matplotlib/lines.py | 18 ++++++++++++++++-- lib/matplotlib/tests/test_lines.py | 8 ++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 doc/api/next_api_changes/deprecations/25196-EP.rst diff --git a/doc/api/next_api_changes/deprecations/25196-EP.rst b/doc/api/next_api_changes/deprecations/25196-EP.rst new file mode 100644 index 000000000000..99f55401976d --- /dev/null +++ b/doc/api/next_api_changes/deprecations/25196-EP.rst @@ -0,0 +1,4 @@ +``Line2D`` +~~~~~~~~~~ +When creating a Line2D or using `.Line2D.set_xdata` and `.Line2D.set_ydata`, +passing x/y data as non sequence is deprecated. diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index f843ccd49fee..db0ce3ba0cea 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -1275,7 +1275,14 @@ def set_xdata(self, x): x : 1D array """ if not np.iterable(x): - raise RuntimeError('x must be a sequence') + # When deprecation cycle is completed + # raise RuntimeError('x must be a sequence') + _api.warn_deprecated( + since=3.7, + message="Setting data with a non sequence type " + "is deprecated since %(since)s and will be " + "remove %(removal)s") + x = [x, ] self._xorig = copy.copy(x) self._invalidx = True self.stale = True @@ -1289,7 +1296,14 @@ def set_ydata(self, y): y : 1D array """ if not np.iterable(y): - raise RuntimeError('y must be a sequence') + # When deprecation cycle is completed + # raise RuntimeError('y must be a sequence') + _api.warn_deprecated( + since=3.7, + message="Setting data with a non sequence type " + "is deprecated since %(since)s and will be " + "remove %(removal)s") + y = [y, ] self._yorig = copy.copy(y) self._invalidy = True self.stale = True diff --git a/lib/matplotlib/tests/test_lines.py b/lib/matplotlib/tests/test_lines.py index 1f25b84d8081..7eecf5675a4b 100644 --- a/lib/matplotlib/tests/test_lines.py +++ b/lib/matplotlib/tests/test_lines.py @@ -20,6 +20,7 @@ import matplotlib.pyplot as plt import matplotlib.transforms as mtransforms from matplotlib.testing.decorators import image_comparison, check_figures_equal +from matplotlib._api.deprecation import MatplotlibDeprecationWarning def test_segment_hits(): @@ -91,9 +92,12 @@ def test_invalid_line_data(): mlines.Line2D([], 1) line = mlines.Line2D([], []) - with pytest.raises(RuntimeError, match='x must be'): + # when deprecation cycle is completed + # with pytest.raises(RuntimeError, match='x must be'): + with pytest.warns(MatplotlibDeprecationWarning): line.set_xdata(0) - with pytest.raises(RuntimeError, match='y must be'): + # with pytest.raises(RuntimeError, match='y must be'): + with pytest.warns(MatplotlibDeprecationWarning): line.set_ydata(0) From 769865b35dcd2b4efa28d9198f8ab83161e8bfd0 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 10 Feb 2023 14:35:14 -0500 Subject: [PATCH 259/262] DOC: Prepare release notes for 3.7.0 DOC: updated the supported versions of Matplotlib DOC: re-run the github status DOC: start to merge the whats_new DOC: re-arrange whats new DOC: add top-level rst TOC for 3.7 docs DOC: fix markup in github stats 3.7.0 behavior and deprecation release notes 3.7.0 removals DOC: merge up development API changes DOC: spell behaviour britishly Remove files, add last release note DOC: update switcher.json Fix broken links DOC: fix internal links DOC: more links fix version number in dependency version list Last couple release notes Update github stats --- SECURITY.md | 3 +- doc/_static/switcher.json | 9 +- .../next_api_changes/behavior/23573-AL.rst | 7 - .../next_api_changes/behavior/23579-AL.rst | 5 - .../next_api_changes/behavior/23710-ES.rst | 7 - .../next_api_changes/behavior/24062-tb.rst | 8 - .../next_api_changes/behavior/24131-OG.rst | 6 - .../next_api_changes/behavior/24132-GL.rst | 29 -- .../next_api_changes/behavior/24189-JB.rst | 10 - .../next_api_changes/behavior/24570-GL.rst | 5 - .../next_api_changes/behavior/24655-AK.rst | 15 - .../next_api_changes/behavior/24829-AL.rst | 3 - .../next_api_changes/behavior/24870-AL.rst | 5 - .../next_api_changes/behavior/24889-AL.rst | 3 - .../next_api_changes/behavior/24912-AL.rst | 4 - .../next_api_changes/behavior/9598-AFV.rst | 6 - .../deprecations/19763-ES.rst | 5 - .../deprecations/22314-AL.rst | 3 - .../deprecations/23449-SS.rst | 3 - .../deprecations/23720-RS.rst | 13 - .../deprecations/23735-ES.rst | 13 - .../deprecations/23824-OG.rst | 16 - .../deprecations/24000-TH.rst | 5 - .../deprecations/24013-TH.rst | 5 - .../deprecations/24071-OG.rst | 9 - .../deprecations/24088-JMK.rst | 9 - .../deprecations/24131-OG.rst | 5 - .../deprecations/24140-AL.rst | 8 - .../deprecations/24144-AL.rst | 5 - .../deprecations/24198-AL.rst | 3 - .../deprecations/24208-AL.rst | 3 - .../deprecations/24220-AL.rst | 5 - .../deprecations/24221-AL.rst | 5 - .../deprecations/24224-OG.rst | 5 - .../deprecations/24240-OG.rst | 6 - .../deprecations/24254-OG.rst | 6 - .../deprecations/24305-AL.rst | 5 - .../deprecations/24455-AL.rst | 3 - .../deprecations/24465-AL.rst | 10 - .../deprecations/24474_CM.rst | 4 - .../deprecations/24538-OG.rst | 4 - .../deprecations/24577-AL.rst | 2 - .../deprecations/24664-OG.rst | 5 - .../deprecations/24688-OG.rst | 5 - .../deprecations/24730-TH.rst | 24 - .../deprecations/24806-KS.rst | 4 - .../deprecations/24846-ES.rst | 30 -- .../deprecations/24864-AL.rst | 10 - .../deprecations/24904-AL.rst | 4 - .../deprecations/25196-EP.rst | 4 - .../next_api_changes/development/23683-AL.rst | 2 - .../next_api_changes/development/24257-AL.rst | 2 - .../next_api_changes/development/24710-AL.rst | 4 - .../next_api_changes/development/24724-ES.rst | 5 - .../next_api_changes/development/24887-OG.rst | 2 - .../next_api_changes/development/24893-KS.rst | 8 - .../next_api_changes/removals/21661-TAC.rst | 12 - .../next_api_changes/removals/24125-OG.rst | 68 --- .../next_api_changes/removals/24128-OG.rst | 17 - .../next_api_changes/removals/24129-OG.rst | 33 -- .../next_api_changes/removals/24251-OG.rst | 4 - .../next_api_changes/removals/24253-OG.rst | 5 - .../next_api_changes/removals/24254-OG.rst | 64 --- .../next_api_changes/removals/24257-AL.rst | 4 - .../next_api_changes/removals/24355-OG.rst | 6 - .../next_api_changes/removals/24356-OG.rst | 19 - .../next_api_changes/removals/24624-AL.rst | 10 - .../next_api_changes/removals/24948-ES.rst | 115 ----- .../next_api_changes/removals/24965-ES.rst | 5 - .../prev_api_changes/api_changes_3.7.0.rst | 14 + .../api_changes_3.7.0/behaviour.rst | 136 ++++++ .../api_changes_3.7.0/deprecations.rst | 291 +++++++++++ .../api_changes_3.7.0/development.rst | 49 ++ .../api_changes_3.7.0/removals.rst | 369 ++++++++++++++ doc/devel/development_setup.rst | 2 +- doc/devel/development_workflow.rst | 4 +- doc/index.rst | 2 +- doc/users/explain/figures.rst | 2 +- doc/users/github_stats.rst | 80 +++- .../next_whats_new/3d_pane_color_rcparams.rst | 18 - .../3d_plot_aspects_adjustable_keyword.rst | 34 -- doc/users/next_whats_new/3d_plot_pan_zoom.rst | 8 - .../next_whats_new/bar_label_formatting.rst | 33 -- .../colorbar_has_location_argument.rst | 25 - doc/users/next_whats_new/documentation.rst | 6 - .../next_whats_new/ellipse_annotation.rst | 15 - doc/users/next_whats_new/figure_hooks.rst | 8 - .../next_whats_new/imshow_extent_units.rst | 20 - .../next_whats_new/legend-figure-outside.rst | 8 - .../next_whats_new/per_subplot_mosaic.rst | 30 -- doc/users/next_whats_new/pie_hatch.rst | 18 - .../next_whats_new/polar_errorbar_caps.rst | 7 - doc/users/next_whats_new/reverse_legend.rst | 4 - doc/users/next_whats_new/rgba_pcolormesh.rst | 16 - .../next_whats_new/shade_poly3dcollection.rst | 33 -- .../show_source_links_directive_option.rst | 7 - .../next_whats_new/styles_from_packages.rst | 11 - .../view_current_axis_format.rst | 29 -- doc/users/next_whats_new/widget_blitting.rst | 7 - .../next_whats_new/widget_button_styling.rst | 31 -- doc/users/prev_whats_new/whats_new_3.7.0.rst | 450 ++++++++++++++++++ doc/users/release_notes.rst | 13 +- examples/README.txt | 6 +- lib/matplotlib/path.py | 2 +- tutorials/README.txt | 6 +- 105 files changed, 1412 insertions(+), 1138 deletions(-) delete mode 100644 doc/api/next_api_changes/behavior/23573-AL.rst delete mode 100644 doc/api/next_api_changes/behavior/23579-AL.rst delete mode 100644 doc/api/next_api_changes/behavior/23710-ES.rst delete mode 100644 doc/api/next_api_changes/behavior/24062-tb.rst delete mode 100644 doc/api/next_api_changes/behavior/24131-OG.rst delete mode 100644 doc/api/next_api_changes/behavior/24132-GL.rst delete mode 100644 doc/api/next_api_changes/behavior/24189-JB.rst delete mode 100644 doc/api/next_api_changes/behavior/24570-GL.rst delete mode 100644 doc/api/next_api_changes/behavior/24655-AK.rst delete mode 100644 doc/api/next_api_changes/behavior/24829-AL.rst delete mode 100644 doc/api/next_api_changes/behavior/24870-AL.rst delete mode 100644 doc/api/next_api_changes/behavior/24889-AL.rst delete mode 100644 doc/api/next_api_changes/behavior/24912-AL.rst delete mode 100644 doc/api/next_api_changes/behavior/9598-AFV.rst delete mode 100644 doc/api/next_api_changes/deprecations/19763-ES.rst delete mode 100644 doc/api/next_api_changes/deprecations/22314-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/23449-SS.rst delete mode 100644 doc/api/next_api_changes/deprecations/23720-RS.rst delete mode 100644 doc/api/next_api_changes/deprecations/23735-ES.rst delete mode 100644 doc/api/next_api_changes/deprecations/23824-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24000-TH.rst delete mode 100644 doc/api/next_api_changes/deprecations/24013-TH.rst delete mode 100644 doc/api/next_api_changes/deprecations/24071-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24088-JMK.rst delete mode 100644 doc/api/next_api_changes/deprecations/24131-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24140-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24144-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24198-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24208-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24220-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24221-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24224-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24240-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24254-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24305-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24455-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24465-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24474_CM.rst delete mode 100644 doc/api/next_api_changes/deprecations/24538-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24577-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24664-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24688-OG.rst delete mode 100644 doc/api/next_api_changes/deprecations/24730-TH.rst delete mode 100644 doc/api/next_api_changes/deprecations/24806-KS.rst delete mode 100644 doc/api/next_api_changes/deprecations/24846-ES.rst delete mode 100644 doc/api/next_api_changes/deprecations/24864-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/24904-AL.rst delete mode 100644 doc/api/next_api_changes/deprecations/25196-EP.rst delete mode 100644 doc/api/next_api_changes/development/23683-AL.rst delete mode 100644 doc/api/next_api_changes/development/24257-AL.rst delete mode 100644 doc/api/next_api_changes/development/24710-AL.rst delete mode 100644 doc/api/next_api_changes/development/24724-ES.rst delete mode 100644 doc/api/next_api_changes/development/24887-OG.rst delete mode 100644 doc/api/next_api_changes/development/24893-KS.rst delete mode 100644 doc/api/next_api_changes/removals/21661-TAC.rst delete mode 100644 doc/api/next_api_changes/removals/24125-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24128-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24129-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24251-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24253-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24254-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24257-AL.rst delete mode 100644 doc/api/next_api_changes/removals/24355-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24356-OG.rst delete mode 100644 doc/api/next_api_changes/removals/24624-AL.rst delete mode 100644 doc/api/next_api_changes/removals/24948-ES.rst delete mode 100644 doc/api/next_api_changes/removals/24965-ES.rst create mode 100644 doc/api/prev_api_changes/api_changes_3.7.0.rst create mode 100644 doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst create mode 100644 doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst create mode 100644 doc/api/prev_api_changes/api_changes_3.7.0/development.rst create mode 100644 doc/api/prev_api_changes/api_changes_3.7.0/removals.rst delete mode 100644 doc/users/next_whats_new/3d_pane_color_rcparams.rst delete mode 100644 doc/users/next_whats_new/3d_plot_aspects_adjustable_keyword.rst delete mode 100644 doc/users/next_whats_new/3d_plot_pan_zoom.rst delete mode 100644 doc/users/next_whats_new/bar_label_formatting.rst delete mode 100644 doc/users/next_whats_new/colorbar_has_location_argument.rst delete mode 100644 doc/users/next_whats_new/documentation.rst delete mode 100644 doc/users/next_whats_new/ellipse_annotation.rst delete mode 100644 doc/users/next_whats_new/figure_hooks.rst delete mode 100644 doc/users/next_whats_new/imshow_extent_units.rst delete mode 100644 doc/users/next_whats_new/legend-figure-outside.rst delete mode 100644 doc/users/next_whats_new/per_subplot_mosaic.rst delete mode 100644 doc/users/next_whats_new/pie_hatch.rst delete mode 100644 doc/users/next_whats_new/polar_errorbar_caps.rst delete mode 100644 doc/users/next_whats_new/reverse_legend.rst delete mode 100644 doc/users/next_whats_new/rgba_pcolormesh.rst delete mode 100644 doc/users/next_whats_new/shade_poly3dcollection.rst delete mode 100644 doc/users/next_whats_new/show_source_links_directive_option.rst delete mode 100644 doc/users/next_whats_new/styles_from_packages.rst delete mode 100644 doc/users/next_whats_new/view_current_axis_format.rst delete mode 100644 doc/users/next_whats_new/widget_blitting.rst delete mode 100644 doc/users/next_whats_new/widget_button_styling.rst create mode 100644 doc/users/prev_whats_new/whats_new_3.7.0.rst diff --git a/SECURITY.md b/SECURITY.md index 73ec8fdb3a38..1de4c3d8e4a3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,8 +8,9 @@ versions. | Version | Supported | | ------- | ------------------ | +| 3.7.x | :white_check_mark: | | 3.6.x | :white_check_mark: | -| 3.5.x | :white_check_mark: | +| 3.5.x | :x: | | 3.4.x | :x: | | 3.3.x | :x: | | < 3.3 | :x: | diff --git a/doc/_static/switcher.json b/doc/_static/switcher.json index c72cbac2b27a..b96977bdd725 100644 --- a/doc/_static/switcher.json +++ b/doc/_static/switcher.json @@ -1,14 +1,19 @@ [ { - "name": "3.6 (stable)", + "name": "3.7 (stable)", "version": "stable", "url": "https://matplotlib.org/stable/" }, { - "name": "3.7 (dev)", + "name": "3.8 (dev)", "version": "dev", "url": "https://matplotlib.org/devdocs/" }, + { + "name": "3.6", + "version": "3.6.3", + "url": "https://matplotlib.org/3.6.3/" + }, { "name": "3.5", "version": "3.5.3", diff --git a/doc/api/next_api_changes/behavior/23573-AL.rst b/doc/api/next_api_changes/behavior/23573-AL.rst deleted file mode 100644 index f388b414ae9a..000000000000 --- a/doc/api/next_api_changes/behavior/23573-AL.rst +++ /dev/null @@ -1,7 +0,0 @@ -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``. diff --git a/doc/api/next_api_changes/behavior/23579-AL.rst b/doc/api/next_api_changes/behavior/23579-AL.rst deleted file mode 100644 index dd79e4e25be7..000000000000 --- a/doc/api/next_api_changes/behavior/23579-AL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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``. diff --git a/doc/api/next_api_changes/behavior/23710-ES.rst b/doc/api/next_api_changes/behavior/23710-ES.rst deleted file mode 100644 index 6b417167a149..000000000000 --- a/doc/api/next_api_changes/behavior/23710-ES.rst +++ /dev/null @@ -1,7 +0,0 @@ -``plt.get_cmap`` and ``matplotlib.cm.get_cmap`` return a copy -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Formerly, `~.pyplot.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. diff --git a/doc/api/next_api_changes/behavior/24062-tb.rst b/doc/api/next_api_changes/behavior/24062-tb.rst deleted file mode 100644 index 7e5beaecba53..000000000000 --- a/doc/api/next_api_changes/behavior/24062-tb.rst +++ /dev/null @@ -1,8 +0,0 @@ -``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``. diff --git a/doc/api/next_api_changes/behavior/24131-OG.rst b/doc/api/next_api_changes/behavior/24131-OG.rst deleted file mode 100644 index cfeb62440fc0..000000000000 --- a/doc/api/next_api_changes/behavior/24131-OG.rst +++ /dev/null @@ -1,6 +0,0 @@ -``FuncAnimation(save_count=None)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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*. diff --git a/doc/api/next_api_changes/behavior/24132-GL.rst b/doc/api/next_api_changes/behavior/24132-GL.rst deleted file mode 100644 index 0ad50ad899c4..000000000000 --- a/doc/api/next_api_changes/behavior/24132-GL.rst +++ /dev/null @@ -1,29 +0,0 @@ -``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. - -.. code-block:: - - 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 - -.. code-block:: - - 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**. diff --git a/doc/api/next_api_changes/behavior/24189-JB.rst b/doc/api/next_api_changes/behavior/24189-JB.rst deleted file mode 100644 index 378390557f49..000000000000 --- a/doc/api/next_api_changes/behavior/24189-JB.rst +++ /dev/null @@ -1,10 +0,0 @@ -``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`. diff --git a/doc/api/next_api_changes/behavior/24570-GL.rst b/doc/api/next_api_changes/behavior/24570-GL.rst deleted file mode 100644 index 4ab0f5d1bcdb..000000000000 --- a/doc/api/next_api_changes/behavior/24570-GL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/doc/api/next_api_changes/behavior/24655-AK.rst b/doc/api/next_api_changes/behavior/24655-AK.rst deleted file mode 100644 index 04b4141e4517..000000000000 --- a/doc/api/next_api_changes/behavior/24655-AK.rst +++ /dev/null @@ -1,15 +0,0 @@ -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 -:doc:`/gallery/text_labels_and_annotations/font_file`. diff --git a/doc/api/next_api_changes/behavior/24829-AL.rst b/doc/api/next_api_changes/behavior/24829-AL.rst deleted file mode 100644 index 31e822821878..000000000000 --- a/doc/api/next_api_changes/behavior/24829-AL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``QuadMesh.set_array`` now always raises ``ValueError`` for inputs with incorrect shapes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It could previously also raise `TypeError` in some cases. diff --git a/doc/api/next_api_changes/behavior/24870-AL.rst b/doc/api/next_api_changes/behavior/24870-AL.rst deleted file mode 100644 index a7fdeeb23b77..000000000000 --- a/doc/api/next_api_changes/behavior/24870-AL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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 -`~.Axes.contour` and ``[0, 0.5, 1]`` for `.Axes.contourf`. diff --git a/doc/api/next_api_changes/behavior/24889-AL.rst b/doc/api/next_api_changes/behavior/24889-AL.rst deleted file mode 100644 index 95fb0c1cd5d8..000000000000 --- a/doc/api/next_api_changes/behavior/24889-AL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``AxesImage.set_extent`` now raises ``TypeError`` for unknown keyword arguments -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It previously raised a `ValueError`. diff --git a/doc/api/next_api_changes/behavior/24912-AL.rst b/doc/api/next_api_changes/behavior/24912-AL.rst deleted file mode 100644 index 3a87ed217f9f..000000000000 --- a/doc/api/next_api_changes/behavior/24912-AL.rst +++ /dev/null @@ -1,4 +0,0 @@ -``contour`` no longer warns if no contour lines are drawn. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This can occur if the user explicitly passes a ``levels`` array with no values -between ``z.min()`` and ``z.max()``; or if ``z`` has the same value everywhere. diff --git a/doc/api/next_api_changes/behavior/9598-AFV.rst b/doc/api/next_api_changes/behavior/9598-AFV.rst deleted file mode 100644 index 4edb930fe432..000000000000 --- a/doc/api/next_api_changes/behavior/9598-AFV.rst +++ /dev/null @@ -1,6 +0,0 @@ -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 -:ghissue:`9580` and :ghissue:`9598`. diff --git a/doc/api/next_api_changes/deprecations/19763-ES.rst b/doc/api/next_api_changes/deprecations/19763-ES.rst deleted file mode 100644 index a7dc880a60c3..000000000000 --- a/doc/api/next_api_changes/deprecations/19763-ES.rst +++ /dev/null @@ -1,5 +0,0 @@ -``Cursor`` and ``MultiCursor`` event handlers are now private -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Access to the event handlers for the `.Cursor` and `.MultiCursor` widgets is -now deprecated. The related *needclear* attribute is also deprecated. diff --git a/doc/api/next_api_changes/deprecations/22314-AL.rst b/doc/api/next_api_changes/deprecations/22314-AL.rst deleted file mode 100644 index bea929019865..000000000000 --- a/doc/api/next_api_changes/deprecations/22314-AL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``passthru_pt`` -~~~~~~~~~~~~~~~ -This attribute of ``AxisArtistHelper``\s is deprecated. diff --git a/doc/api/next_api_changes/deprecations/23449-SS.rst b/doc/api/next_api_changes/deprecations/23449-SS.rst deleted file mode 100644 index cc5123fc0b7d..000000000000 --- a/doc/api/next_api_changes/deprecations/23449-SS.rst +++ /dev/null @@ -1,3 +0,0 @@ -``axes3d.vvec``, ``axes3d.eye``, ``axes3d.sx``, and ``axes3d.sy`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -... are deprecated without replacement. diff --git a/doc/api/next_api_changes/deprecations/23720-RS.rst b/doc/api/next_api_changes/deprecations/23720-RS.rst deleted file mode 100644 index 9e771009aa15..000000000000 --- a/doc/api/next_api_changes/deprecations/23720-RS.rst +++ /dev/null @@ -1,13 +0,0 @@ -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`. diff --git a/doc/api/next_api_changes/deprecations/23735-ES.rst b/doc/api/next_api_changes/deprecations/23735-ES.rst deleted file mode 100644 index 075abf73d9d4..000000000000 --- a/doc/api/next_api_changes/deprecations/23735-ES.rst +++ /dev/null @@ -1,13 +0,0 @@ -``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.Axes` subclasses if they -define it. In the future, this will no longer occur, and Matplotlib will only -call the ``clear`` method in `~.axes.Axes` subclasses. - -It is recommended to define only the ``clear`` method when on Matplotlib 3.6, -and only ``cla`` for older versions. diff --git a/doc/api/next_api_changes/deprecations/23824-OG.rst b/doc/api/next_api_changes/deprecations/23824-OG.rst deleted file mode 100644 index 3b229725b113..000000000000 --- a/doc/api/next_api_changes/deprecations/23824-OG.rst +++ /dev/null @@ -1,16 +0,0 @@ -``draw_gouraud_triangle`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -... is deprecated as in most backends this is a redundant call. Use -`~.RendererBase.draw_gouraud_triangles` instead. A ``draw_gouraud_triangle`` -call in a custom `~matplotlib.artist.Artist` can readily be replaced as:: - - self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)), - colors.reshape((1, 3, 4)), trans) - -A `~.RendererBase.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) diff --git a/doc/api/next_api_changes/deprecations/24000-TH.rst b/doc/api/next_api_changes/deprecations/24000-TH.rst deleted file mode 100644 index d1025d1fbb95..000000000000 --- a/doc/api/next_api_changes/deprecations/24000-TH.rst +++ /dev/null @@ -1,5 +0,0 @@ -``matplotlib.pyplot.get_plot_commands`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -... is a pending deprecation. This is considered internal and no end-user -should need it. diff --git a/doc/api/next_api_changes/deprecations/24013-TH.rst b/doc/api/next_api_changes/deprecations/24013-TH.rst deleted file mode 100644 index 8870e2d58caa..000000000000 --- a/doc/api/next_api_changes/deprecations/24013-TH.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/doc/api/next_api_changes/deprecations/24071-OG.rst b/doc/api/next_api_changes/deprecations/24071-OG.rst deleted file mode 100644 index 2ac7fb1a0711..000000000000 --- a/doc/api/next_api_changes/deprecations/24071-OG.rst +++ /dev/null @@ -1,9 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/deprecations/24088-JMK.rst b/doc/api/next_api_changes/deprecations/24088-JMK.rst deleted file mode 100644 index caa7e93a05b4..000000000000 --- a/doc/api/next_api_changes/deprecations/24088-JMK.rst +++ /dev/null @@ -1,9 +0,0 @@ -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())``. diff --git a/doc/api/next_api_changes/deprecations/24131-OG.rst b/doc/api/next_api_changes/deprecations/24131-OG.rst deleted file mode 100644 index 835a2a5e0ef9..000000000000 --- a/doc/api/next_api_changes/deprecations/24131-OG.rst +++ /dev/null @@ -1,5 +0,0 @@ -``Animation`` attributes -~~~~~~~~~~~~~~~~~~~~~~~~ - -The attributes ``repeat`` of `.TimedAnimation` and subclasses and -``save_count`` of `.FuncAnimation` are considered private and deprecated. diff --git a/doc/api/next_api_changes/deprecations/24140-AL.rst b/doc/api/next_api_changes/deprecations/24140-AL.rst deleted file mode 100644 index afe10ddc6475..000000000000 --- a/doc/api/next_api_changes/deprecations/24140-AL.rst +++ /dev/null @@ -1,8 +0,0 @@ -``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)``. diff --git a/doc/api/next_api_changes/deprecations/24144-AL.rst b/doc/api/next_api_changes/deprecations/24144-AL.rst deleted file mode 100644 index 1f94bb572c83..000000000000 --- a/doc/api/next_api_changes/deprecations/24144-AL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/doc/api/next_api_changes/deprecations/24198-AL.rst b/doc/api/next_api_changes/deprecations/24198-AL.rst deleted file mode 100644 index 574000883146..000000000000 --- a/doc/api/next_api_changes/deprecations/24198-AL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``backend_ps.PsBackendHelper`` and ``backend_ps.ps_backend_helper`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -... are deprecated with no replacement. diff --git a/doc/api/next_api_changes/deprecations/24208-AL.rst b/doc/api/next_api_changes/deprecations/24208-AL.rst deleted file mode 100644 index f53bcde077c8..000000000000 --- a/doc/api/next_api_changes/deprecations/24208-AL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``backend_webagg.ServerThread`` is deprecated -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -... with no replacement. diff --git a/doc/api/next_api_changes/deprecations/24220-AL.rst b/doc/api/next_api_changes/deprecations/24220-AL.rst deleted file mode 100644 index ff95f9b8ca52..000000000000 --- a/doc/api/next_api_changes/deprecations/24220-AL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/doc/api/next_api_changes/deprecations/24221-AL.rst b/doc/api/next_api_changes/deprecations/24221-AL.rst deleted file mode 100644 index 0e19e11a6f63..000000000000 --- a/doc/api/next_api_changes/deprecations/24221-AL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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)``. diff --git a/doc/api/next_api_changes/deprecations/24224-OG.rst b/doc/api/next_api_changes/deprecations/24224-OG.rst deleted file mode 100644 index 9d06a3467a6a..000000000000 --- a/doc/api/next_api_changes/deprecations/24224-OG.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/doc/api/next_api_changes/deprecations/24240-OG.rst b/doc/api/next_api_changes/deprecations/24240-OG.rst deleted file mode 100644 index 8b1609d88b3d..000000000000 --- a/doc/api/next_api_changes/deprecations/24240-OG.rst +++ /dev/null @@ -1,6 +0,0 @@ -``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 ``_``). diff --git a/doc/api/next_api_changes/deprecations/24254-OG.rst b/doc/api/next_api_changes/deprecations/24254-OG.rst deleted file mode 100644 index d6e4882a774b..000000000000 --- a/doc/api/next_api_changes/deprecations/24254-OG.rst +++ /dev/null @@ -1,6 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/deprecations/24305-AL.rst b/doc/api/next_api_changes/deprecations/24305-AL.rst deleted file mode 100644 index e08727f9cbf6..000000000000 --- a/doc/api/next_api_changes/deprecations/24305-AL.rst +++ /dev/null @@ -1,5 +0,0 @@ -``SimpleEvent`` -~~~~~~~~~~~~~~~ -The ``SimpleEvent`` nested class (previously accessible via the public -subclasses of ``ConnectionStyle._Base``, such as `.ConnectionStyle.Arc`, has -been deprecated. diff --git a/doc/api/next_api_changes/deprecations/24455-AL.rst b/doc/api/next_api_changes/deprecations/24455-AL.rst deleted file mode 100644 index 8a8f3e497260..000000000000 --- a/doc/api/next_api_changes/deprecations/24455-AL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``RadioButtons.circles`` -~~~~~~~~~~~~~~~~~~~~~~~~ -... is deprecated. (RadioButtons now draws itself using `~.Axes.scatter`.) diff --git a/doc/api/next_api_changes/deprecations/24465-AL.rst b/doc/api/next_api_changes/deprecations/24465-AL.rst deleted file mode 100644 index 95acc8e2cb46..000000000000 --- a/doc/api/next_api_changes/deprecations/24465-AL.rst +++ /dev/null @@ -1,10 +0,0 @@ -``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 `~.OffsetBox.get_offset` on each children after triggering a draw. diff --git a/doc/api/next_api_changes/deprecations/24474_CM.rst b/doc/api/next_api_changes/deprecations/24474_CM.rst deleted file mode 100644 index 7e12ded0fdbf..000000000000 --- a/doc/api/next_api_changes/deprecations/24474_CM.rst +++ /dev/null @@ -1,4 +0,0 @@ -``CheckButtons.rectangles`` and ``CheckButtons.lines`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``CheckButtons.rectangles`` and ``CheckButtons.lines`` are deprecated. -(``CheckButtons`` now draws itself using `~.Axes.scatter`.) diff --git a/doc/api/next_api_changes/deprecations/24538-OG.rst b/doc/api/next_api_changes/deprecations/24538-OG.rst deleted file mode 100644 index a587dd82c09a..000000000000 --- a/doc/api/next_api_changes/deprecations/24538-OG.rst +++ /dev/null @@ -1,4 +0,0 @@ -``legend.legendHandles`` -~~~~~~~~~~~~~~~~~~~~~~~~ - -... was undocumented and has been renamed to ``legend_handles``. Using ``legendHandles`` is deprecated. diff --git a/doc/api/next_api_changes/deprecations/24577-AL.rst b/doc/api/next_api_changes/deprecations/24577-AL.rst deleted file mode 100644 index 68c80a4310ef..000000000000 --- a/doc/api/next_api_changes/deprecations/24577-AL.rst +++ /dev/null @@ -1,2 +0,0 @@ -``ticklabels`` parameter of `.Axis.set_ticklabels` renamed to ``labels`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/next_api_changes/deprecations/24664-OG.rst b/doc/api/next_api_changes/deprecations/24664-OG.rst deleted file mode 100644 index b40f4e9f6d6e..000000000000 --- a/doc/api/next_api_changes/deprecations/24664-OG.rst +++ /dev/null @@ -1,5 +0,0 @@ -``offsetbox.bbox_artist`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -... 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. diff --git a/doc/api/next_api_changes/deprecations/24688-OG.rst b/doc/api/next_api_changes/deprecations/24688-OG.rst deleted file mode 100644 index 12bed4f04e52..000000000000 --- a/doc/api/next_api_changes/deprecations/24688-OG.rst +++ /dev/null @@ -1,5 +0,0 @@ -``Quiver.quiver_doc`` and ``Barbs.barbs_doc`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -... are deprecated. These are the doc-string and should not be accessible as -a named class member. diff --git a/doc/api/next_api_changes/deprecations/24730-TH.rst b/doc/api/next_api_changes/deprecations/24730-TH.rst deleted file mode 100644 index 0edb329e7bc6..000000000000 --- a/doc/api/next_api_changes/deprecations/24730-TH.rst +++ /dev/null @@ -1,24 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/deprecations/24806-KS.rst b/doc/api/next_api_changes/deprecations/24806-KS.rst deleted file mode 100644 index 4d7b1d75249b..000000000000 --- a/doc/api/next_api_changes/deprecations/24806-KS.rst +++ /dev/null @@ -1,4 +0,0 @@ -Deprecate unused parameter *x* to ``TextBox.begin_typing`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This parameter was unused in the method, but was a required argument. diff --git a/doc/api/next_api_changes/deprecations/24846-ES.rst b/doc/api/next_api_changes/deprecations/24846-ES.rst deleted file mode 100644 index c70168706afb..000000000000 --- a/doc/api/next_api_changes/deprecations/24846-ES.rst +++ /dev/null @@ -1,30 +0,0 @@ -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: - -- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead if you - have a `str`. - - **Added 3.6.1** Use `matplotlib.cm.ColormapRegistry.get_cmap` if you - have a string, `None` or a `matplotlib.colors.Colormap` object that you want - to convert to a `matplotlib.colors.Colormap` instance. -- ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register - <.ColormapRegistry.register>` instead -- ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister - <.ColormapRegistry.unregister>` instead -- ``matplotlib.pyplot.register_cmap``; use `matplotlib.colormaps.register - <.ColormapRegistry.register>` instead - -The `matplotlib.pyplot.get_cmap` function will stay available for backward -compatibility. diff --git a/doc/api/next_api_changes/deprecations/24864-AL.rst b/doc/api/next_api_changes/deprecations/24864-AL.rst deleted file mode 100644 index bdeba7a85e65..000000000000 --- a/doc/api/next_api_changes/deprecations/24864-AL.rst +++ /dev/null @@ -1,10 +0,0 @@ -``BrokenBarHCollection`` is deprecated -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It was just a thin wrapper inheriting from `.PolyCollection`; -`~.Axes.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 `~.Axes.fill_between` as a replacement; see -:doc:`/gallery/lines_bars_and_markers/span_regions` for an example. diff --git a/doc/api/next_api_changes/deprecations/24904-AL.rst b/doc/api/next_api_changes/deprecations/24904-AL.rst deleted file mode 100644 index cbd04aadd3d8..000000000000 --- a/doc/api/next_api_changes/deprecations/24904-AL.rst +++ /dev/null @@ -1,4 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/deprecations/25196-EP.rst b/doc/api/next_api_changes/deprecations/25196-EP.rst deleted file mode 100644 index 99f55401976d..000000000000 --- a/doc/api/next_api_changes/deprecations/25196-EP.rst +++ /dev/null @@ -1,4 +0,0 @@ -``Line2D`` -~~~~~~~~~~ -When creating a Line2D or using `.Line2D.set_xdata` and `.Line2D.set_ydata`, -passing x/y data as non sequence is deprecated. diff --git a/doc/api/next_api_changes/development/23683-AL.rst b/doc/api/next_api_changes/development/23683-AL.rst deleted file mode 100644 index fe3fab885f1a..000000000000 --- a/doc/api/next_api_changes/development/23683-AL.rst +++ /dev/null @@ -1,2 +0,0 @@ -pyparsing>=2.3.1 is now required -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/next_api_changes/development/24257-AL.rst b/doc/api/next_api_changes/development/24257-AL.rst deleted file mode 100644 index 584420df8fd7..000000000000 --- a/doc/api/next_api_changes/development/24257-AL.rst +++ /dev/null @@ -1,2 +0,0 @@ -importlib_resources>=2.3.0 is now required on Python<3.10 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/next_api_changes/development/24710-AL.rst b/doc/api/next_api_changes/development/24710-AL.rst deleted file mode 100644 index 2f26f494a1ed..000000000000 --- a/doc/api/next_api_changes/development/24710-AL.rst +++ /dev/null @@ -1,4 +0,0 @@ -Support for Qt<5.10 has been dropped -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -... as there are no wheels or conda packages that support both Qt 5.9 (or -older) and Python 3.8 (or newer). diff --git a/doc/api/next_api_changes/development/24724-ES.rst b/doc/api/next_api_changes/development/24724-ES.rst deleted file mode 100644 index 5a4f992174d6..000000000000 --- a/doc/api/next_api_changes/development/24724-ES.rst +++ /dev/null @@ -1,5 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/development/24887-OG.rst b/doc/api/next_api_changes/development/24887-OG.rst deleted file mode 100644 index 22adf3937e7b..000000000000 --- a/doc/api/next_api_changes/development/24887-OG.rst +++ /dev/null @@ -1,2 +0,0 @@ -numpy>=1.20 is now required -~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/next_api_changes/development/24893-KS.rst b/doc/api/next_api_changes/development/24893-KS.rst deleted file mode 100644 index 382f0c1c5cc1..000000000000 --- a/doc/api/next_api_changes/development/24893-KS.rst +++ /dev/null @@ -1,8 +0,0 @@ -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 `_. diff --git a/doc/api/next_api_changes/removals/21661-TAC.rst b/doc/api/next_api_changes/removals/21661-TAC.rst deleted file mode 100644 index 78c8837d6a8d..000000000000 --- a/doc/api/next_api_changes/removals/21661-TAC.rst +++ /dev/null @@ -1,12 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/removals/24125-OG.rst b/doc/api/next_api_changes/removals/24125-OG.rst deleted file mode 100644 index d6487090044a..000000000000 --- a/doc/api/next_api_changes/removals/24125-OG.rst +++ /dev/null @@ -1,68 +0,0 @@ -Miscellaneous removals -~~~~~~~~~~~~~~~~~~~~~~ - -- ``is_url`` and ``URL_REGEX`` are removed. (They were previously defined in - the toplevel :mod:`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 :rc:`image.lut` 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. diff --git a/doc/api/next_api_changes/removals/24128-OG.rst b/doc/api/next_api_changes/removals/24128-OG.rst deleted file mode 100644 index 2a17a6c54689..000000000000 --- a/doc/api/next_api_changes/removals/24128-OG.rst +++ /dev/null @@ -1,17 +0,0 @@ -``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.utcfromtimestamp`, or to use NumPy `~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 -`.Locator`\s and `.Formatter`\s (and their common base class, TickHelper) are -removed. Directly manipulate the view and data intervals on the underlying -axis instead. diff --git a/doc/api/next_api_changes/removals/24129-OG.rst b/doc/api/next_api_changes/removals/24129-OG.rst deleted file mode 100644 index 28894274263d..000000000000 --- a/doc/api/next_api_changes/removals/24129-OG.rst +++ /dev/null @@ -1,33 +0,0 @@ -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. - -``NavigationToolbar2.set_cursor`` and ``backend_tools.SetCursorBase.set_cursor`` -................................................................................ - -Instead, use the `.FigureCanvasBase.set_cursor` method on the canvas (available -as the ``canvas`` attribute on the toolbar or the Figure.) - -``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. diff --git a/doc/api/next_api_changes/removals/24251-OG.rst b/doc/api/next_api_changes/removals/24251-OG.rst deleted file mode 100644 index fbd095ab8912..000000000000 --- a/doc/api/next_api_changes/removals/24251-OG.rst +++ /dev/null @@ -1,4 +0,0 @@ -``auto_add_to_figure=True`` for ``Axes3D`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -... is no longer supported. Instead use ``fig.add_axes(ax)``. diff --git a/doc/api/next_api_changes/removals/24253-OG.rst b/doc/api/next_api_changes/removals/24253-OG.rst deleted file mode 100644 index 0c80d33f79a7..000000000000 --- a/doc/api/next_api_changes/removals/24253-OG.rst +++ /dev/null @@ -1,5 +0,0 @@ -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)``. diff --git a/doc/api/next_api_changes/removals/24254-OG.rst b/doc/api/next_api_changes/removals/24254-OG.rst deleted file mode 100644 index f29d1e0662cd..000000000000 --- a/doc/api/next_api_changes/removals/24254-OG.rst +++ /dev/null @@ -1,64 +0,0 @@ -Removal of deprecations in the Selector widget API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -RectangleSelector and EllipseSelector -..................................... - -The *drawtype* keyword argument to `~matplotlib.widgets.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 -`~matplotlib.widgets.RectangleSelector` is also removed. - -To retain the behaviour of ``drawtype='none'``, use ``rectprops={'visible': -False}`` to make the drawn `~matplotlib.patches.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. - -PolygonSelector -............... - -- 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. - -SpanSelector -............ - -- 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. - -LassoSelector -............. - -- 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. diff --git a/doc/api/next_api_changes/removals/24257-AL.rst b/doc/api/next_api_changes/removals/24257-AL.rst deleted file mode 100644 index 490519c2c650..000000000000 --- a/doc/api/next_api_changes/removals/24257-AL.rst +++ /dev/null @@ -1,4 +0,0 @@ -``backend_template.show`` -~~~~~~~~~~~~~~~~~~~~~~~~~ -... has been removed, in order to better demonstrate the new backend definition -API. diff --git a/doc/api/next_api_changes/removals/24355-OG.rst b/doc/api/next_api_changes/removals/24355-OG.rst deleted file mode 100644 index 305abcd6d074..000000000000 --- a/doc/api/next_api_changes/removals/24355-OG.rst +++ /dev/null @@ -1,6 +0,0 @@ -Unused positional parameters to ``print_`` methods -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -None of the ``print_`` methods implemented by canvas subclasses used -positional arguments other that the first (the output filename or file-like), -so these extra parameters are removed. diff --git a/doc/api/next_api_changes/removals/24356-OG.rst b/doc/api/next_api_changes/removals/24356-OG.rst deleted file mode 100644 index a69256f9aca2..000000000000 --- a/doc/api/next_api_changes/removals/24356-OG.rst +++ /dev/null @@ -1,19 +0,0 @@ -``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. diff --git a/doc/api/next_api_changes/removals/24624-AL.rst b/doc/api/next_api_changes/removals/24624-AL.rst deleted file mode 100644 index d79db9d2ae5b..000000000000 --- a/doc/api/next_api_changes/removals/24624-AL.rst +++ /dev/null @@ -1,10 +0,0 @@ -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. diff --git a/doc/api/next_api_changes/removals/24948-ES.rst b/doc/api/next_api_changes/removals/24948-ES.rst deleted file mode 100644 index 38ed70792f26..000000000000 --- a/doc/api/next_api_changes/removals/24948-ES.rst +++ /dev/null @@ -1,115 +0,0 @@ - -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 :ref:`testing` for more details. - - - -Auto-removal of grids by `~.Axes.pcolor` and `~.Axes.pcolormesh` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -`~.Axes.pcolor` and `~.Axes.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 :ref:`Behavioural API Changes 3.5 - Axes children combined` 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. - -- `.Axes.add_collection` -- `.Axes.add_image` -- `.Axes.add_line` -- `.Axes.add_patch` -- `.Axes.add_table` - - -``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, )``). 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. diff --git a/doc/api/next_api_changes/removals/24965-ES.rst b/doc/api/next_api_changes/removals/24965-ES.rst deleted file mode 100644 index 96089f463e64..000000000000 --- a/doc/api/next_api_changes/removals/24965-ES.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/doc/api/prev_api_changes/api_changes_3.7.0.rst b/doc/api/prev_api_changes/api_changes_3.7.0.rst new file mode 100644 index 000000000000..932a4ba34452 --- /dev/null +++ b/doc/api/prev_api_changes/api_changes_3.7.0.rst @@ -0,0 +1,14 @@ +API Changes for 3.7.0 +===================== + +.. contents:: + :local: + :depth: 1 + +.. include:: /api/prev_api_changes/api_changes_3.7.0/behaviour.rst + +.. include:: /api/prev_api_changes/api_changes_3.7.0/deprecations.rst + +.. include:: /api/prev_api_changes/api_changes_3.7.0/removals.rst + +.. include:: /api/prev_api_changes/api_changes_3.7.0/development.rst diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst b/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst new file mode 100644 index 000000000000..6057bfa9af4c --- /dev/null +++ b/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst @@ -0,0 +1,136 @@ +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, `~.pyplot.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``. + +``FuncAnimation(save_count=None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +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. + +.. code-block:: + + 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 + +.. code-block:: + + 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 +:doc:`/gallery/text_labels_and_annotations/font_file`. + +``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 +`~.Axes.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 +:ghissue:`9580` and :ghissue:`9598`. diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst new file mode 100644 index 000000000000..dd6d9d8e0894 --- /dev/null +++ b/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst @@ -0,0 +1,291 @@ +Deprecations +------------ + +``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.Axes` subclasses if they +define it. In the future, this will no longer occur, and Matplotlib will only +call the ``clear`` method in `~.axes.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`. + +``draw_gouraud_triangle`` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +... is deprecated as in most backends this is a redundant call. Use +`~.RendererBase.draw_gouraud_triangles` instead. A ``draw_gouraud_triangle`` +call in a custom `~matplotlib.artist.Artist` can readily be replaced as:: + + self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)), + colors.reshape((1, 3, 4)), trans) + +A `~.RendererBase.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) + +``matplotlib.pyplot.get_plot_commands`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +... 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. + +``SimpleEvent`` +~~~~~~~~~~~~~~~ + +The ``SimpleEvent`` nested class (previously accessible via the public +subclasses of ``ConnectionStyle._Base``, such as `.ConnectionStyle.Arc`, has +been deprecated. + +``RadioButtons.circles`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +... is deprecated. (RadioButtons now draws itself using `~.Axes.scatter`.) + +``CheckButtons.rectangles`` and ``CheckButtons.lines`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``CheckButtons.rectangles`` and ``CheckButtons.lines`` are deprecated. +(``CheckButtons`` now draws itself using `~.Axes.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 `~.OffsetBox.get_offset` on each children after triggering a draw. + +``legend.legendHandles`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +... was undocumented and has been renamed to ``legend_handles``. Using ``legendHandles`` is deprecated. + +``ticklabels`` parameter of `.Axis.set_ticklabels` renamed to ``labels`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``offsetbox.bbox_artist`` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +... 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: + +- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead if you + have a `str`. + + **Added 3.6.1** Use `matplotlib.cm.ColormapRegistry.get_cmap` if you + have a string, `None` or a `matplotlib.colors.Colormap` object that you want + to convert to a `matplotlib.colors.Colormap` instance. +- ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register + <.ColormapRegistry.register>` instead +- ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister + <.ColormapRegistry.unregister>` instead +- ``matplotlib.pyplot.register_cmap``; use `matplotlib.colormaps.register + <.ColormapRegistry.register>` instead + +The `matplotlib.pyplot.get_cmap` function will stay available for backward +compatibility. + +``BrokenBarHCollection`` is deprecated +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It was just a thin wrapper inheriting from `.PolyCollection`; +`~.Axes.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 `~.Axes.fill_between` as a replacement; see +:doc:`/gallery/lines_bars_and_markers/span_regions` 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. + +``passthru_pt`` +~~~~~~~~~~~~~~~ + +This attribute of ``AxisArtistHelper``\s is deprecated. + +``axes3d.vvec``, ``axes3d.eye``, ``axes3d.sx``, and ``axes3d.sy`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +... are deprecated without replacement. + +``Line2D`` +~~~~~~~~~~ + +When creating a Line2D or using `.Line2D.set_xdata` and `.Line2D.set_ydata`, +passing x/y data as non sequence is deprecated. diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/development.rst b/doc/api/prev_api_changes/api_changes_3.7.0/development.rst new file mode 100644 index 000000000000..c2ae35970524 --- /dev/null +++ b/doc/api/prev_api_changes/api_changes_3.7.0/development.rst @@ -0,0 +1,49 @@ +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 :ref:`minimum supported versions ` are +being bumped: + ++------------+-----------------+---------------+ +| Dependency | min in mpl3.6 | min in mpl3.7 | ++============+=================+===============+ +| NumPy | 1.19 | 1.20 | ++------------+-----------------+---------------+ +| pyparsing | 2.2.1 | 2.3.1 | ++------------+-----------------+---------------+ +| Qt | | 5.10 | ++------------+-----------------+---------------+ + +- 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 :ref:`min_deps_policy` and `NEP29 +`__ + + +New dependencies +~~~~~~~~~~~~~~~~ + +* `importlib-resources `_ + (>= 3.2.0; only required on Python < 3.10) + +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 `_. diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst new file mode 100644 index 000000000000..c8f499666525 --- /dev/null +++ b/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst @@ -0,0 +1,369 @@ +Removals +-------- + +``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.utcfromtimestamp`, or to use NumPy `~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 +`.Locator`\s and `.Formatter`\s (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. + +``NavigationToolbar2.set_cursor`` and ``backend_tools.SetCursorBase.set_cursor`` +................................................................................ + +Instead, use the `.FigureCanvasBase.set_cursor` method on the canvas (available +as the ``canvas`` attribute on the toolbar or the Figure.) + +``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 `~matplotlib.widgets.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 +`~matplotlib.widgets.RectangleSelector` is also removed. + +To retain the behaviour of ``drawtype='none'``, use ``rectprops={'visible': +False}`` to make the drawn `~matplotlib.patches.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. + +PolygonSelector +............... + +- 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. + +SpanSelector +............ + +- 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. + +LassoSelector +............. + +- 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. + +``backend_template.show`` +~~~~~~~~~~~~~~~~~~~~~~~~~ +... has been removed, in order to better demonstrate the new backend definition +API. + +Unused positional parameters to ``print_`` methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +None of the ``print_`` 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 :ref:`testing` for more details. + +Auto-removal of grids by `~.Axes.pcolor` and `~.Axes.pcolormesh` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`~.Axes.pcolor` and `~.Axes.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 :ref:`Behavioural API Changes 3.5 - Axes children combined` 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. + +- `.Axes.add_collection` +- `.Axes.add_image` +- `.Axes.add_line` +- `.Axes.add_patch` +- `.Axes.add_table` + + +``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, )``). 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 :mod:`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 :rc:`image.lut` 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. + diff --git a/doc/devel/development_setup.rst b/doc/devel/development_setup.rst index 5ce0898e0146..afcd63b3bf15 100644 --- a/doc/devel/development_setup.rst +++ b/doc/devel/development_setup.rst @@ -72,7 +72,7 @@ Change into this directory before continuing:: * `Git documentation `_ * `GitHub-Contributing to a Project `_ - * `Introduction to GitHub `_ + * `GitHub Skills `_ * :ref:`using-git` * :ref:`git-resources` * `Installing git `_ diff --git a/doc/devel/development_workflow.rst b/doc/devel/development_workflow.rst index 2635787f997c..cd902f3f30e5 100644 --- a/doc/devel/development_workflow.rst +++ b/doc/devel/development_workflow.rst @@ -130,15 +130,13 @@ In more detail ``git commit -am 'A commit message'``. Note the ``-am`` options to ``commit``. The ``m`` flag just signals that you're going to type a message on the command line. The ``a`` flag — you can just take on - faith — or see `why the -a flag?`_ — and the helpful use-case - description in the `tangled working copy problem`_. The + faith — or see `why the -a flag?`_. The `git commit `_ manual page might also be useful. #. To push the changes up to your forked repo on GitHub, do a ``git push``. .. _why the -a flag?: http://gitready.com/beginner/2009/01/18/the-staging-area.html -.. _tangled working copy problem: http://2ndscale.com/rtomayko/2008/the-thing-about-git Open a pull request diff --git a/doc/index.rst b/doc/index.rst index fc911ea12296..1c608c0d62cb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -51,7 +51,7 @@ Learning resources - :doc:`Quick-start guide ` - :doc:`Plot types ` - - `Introductory tutorials <../tutorials/index.html#introductory>`_ + - :ref:`Introductory tutorials ` - :doc:`External learning resources ` .. grid-item-card:: diff --git a/doc/users/explain/figures.rst b/doc/users/explain/figures.rst index a26f10712fe0..f5fb3142d297 100644 --- a/doc/users/explain/figures.rst +++ b/doc/users/explain/figures.rst @@ -52,7 +52,7 @@ MacOS backend as well. These are typically chosen either in the user's ``matplotlib.use('QtAgg')`` at the beginning of a session or script. When run from a script, or interactively (e.g. from an -`iPython shell `_) the Figure +`iPython shell `_) the Figure will not be shown until we call ``plt.show()``. The Figure will appear in a new GUI window, and usually will have a toolbar with Zoom, Pan, and other tools for interacting with the Figure. By default, ``plt.show()`` blocks diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index cde7ccfe38e2..cbeb72270f2e 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -1,16 +1,16 @@ .. _github-stats: -GitHub statistics for 3.7.0 (Jan 25, 2023) -========================================== +GitHub statistics (Feb 13, 2023) +================================ -GitHub statistics for 2022/09/16 (tag: v3.6.0) - 2023/01/25 +GitHub statistics for 2022/09/16 (tag: v3.6.0) - 2023/02/13 These lists are automatically generated, and may be incomplete or contain duplicates. -We closed 110 issues and merged 380 pull requests. +We closed 120 issues and merged 427 pull requests. The full list can be seen `on GitHub `__ -The following 107 authors contributed 2268 commits. +The following 112 authors contributed 1962 commits. * Abhijnan Bajpai * Adrien F. Vincent @@ -30,10 +30,13 @@ The following 107 authors contributed 2268 commits. * David Stansby * dependabot[bot] * DerWeh +* Eero Vaher * Elliott Sales de Andrade * Eric Larson +* Eric Prestat * erykoff * EunHo Lee +* Felix Goudreault * Greg Lucas * hannah * Ian Hunt-Isaak @@ -53,6 +56,7 @@ The following 107 authors contributed 2268 commits. * John Paul Jepko * Joseph Fox-Rabinovitz * Joshua Barrass +* Julian Chen * Junaid Khan * Justin Tracey * Kaidong Hu @@ -87,6 +91,7 @@ The following 107 authors contributed 2268 commits. * Pratim Ugale * pre-commit-ci[bot] * ramvikrams +* richardsheridan * Ruth Comer * Ryan May * saranti @@ -122,8 +127,55 @@ The following 107 authors contributed 2268 commits. GitHub issues and pull requests: -Pull Requests (380): +Pull Requests (427): +* :ghpull:`25201`: Backport PR #25196 on branch v3.7.x (Add deprecation for setting data with non sequence type in ``Line2D``) +* :ghpull:`25196`: Add deprecation for setting data with non sequence type in ``Line2D`` +* :ghpull:`25197`: Backport PR #25193 on branch v3.7.x (Fix displacement of colorbar for eps with bbox_inches='tight') +* :ghpull:`25193`: Fix displacement of colorbar for eps with bbox_inches='tight' +* :ghpull:`24781`: DOC: restore SHA to footer +* :ghpull:`25188`: Backport PR #25085 on branch v3.7.x (FIX: only try to update blit caches if the canvas we expect) +* :ghpull:`25170`: Backport PR #25097 on branch v3.7.x (fix FigureCanvasTkAgg memory leak via weakrefs) +* :ghpull:`25186`: Backport PR #24893 on branch v3.7.x (STY: make allowed line length 9 longer to 88 from 79) +* :ghpull:`25185`: Backport PR #25183 on branch v3.7.x (FIX: do not use deprecated API internally) +* :ghpull:`25184`: Backport PR #25174 on branch v3.7.x (Accept LA icons for the toolbar) +* :ghpull:`25085`: FIX: only try to update blit caches if the canvas we expect +* :ghpull:`25183`: FIX: do not use deprecated API internally +* :ghpull:`25182`: Backport PR #25052 on branch v3.7.x (Support both Bbox and list for bbox to table/Table) +* :ghpull:`25174`: Accept LA icons for the toolbar +* :ghpull:`25052`: Support both Bbox and list for bbox to table/Table +* :ghpull:`25095`: Backport PR #23442 on branch v3.7.x (Remove need to detect math mode in pgf strings) +* :ghpull:`25097`: fix FigureCanvasTkAgg memory leak via weakrefs +* :ghpull:`25167`: Backport PR #25122 on branch v3.7.x (FIX: scaling factor for window with negative value) +* :ghpull:`25122`: FIX: scaling factor for window with negative value +* :ghpull:`25161`: Backport PR #25158 on branch v3.7.x (Disconnect SubplotTool destroyer callback on tool_fig close) +* :ghpull:`25160`: Backport PR #25129 on branch v3.7.x (Undeprecate Cursor event handlers) +* :ghpull:`25158`: Disconnect SubplotTool destroyer callback on tool_fig close +* :ghpull:`25129`: Undeprecate Cursor event handlers +* :ghpull:`25154`: Backport PR #25151 on branch v3.7.x (Increase timeout to GitHub API) +* :ghpull:`25151`: Increase timeout to GitHub API +* :ghpull:`25136`: Backport PR #25126 on branch v3.7.x (FIX: fully invalidate TransformWrapper parents before swapping) +* :ghpull:`25132`: Backport PR #24993 on branch v3.7.x ([DOC] GitHub spelling and links) +* :ghpull:`25126`: FIX: fully invalidate TransformWrapper parents before swapping +* :ghpull:`24993`: [DOC] GitHub spelling and links +* :ghpull:`25118`: Backport PR #25113 on branch v3.7.x (Fix outdated comment re: _update_label_position.) +* :ghpull:`25113`: Fix outdated comment re: _update_label_position. +* :ghpull:`25111`: Backport PR #25110 on branch v3.7.x (Stop recommending ``ncol`` in legend examples) +* :ghpull:`25110`: Stop recommending ``ncol`` in legend examples +* :ghpull:`25106`: Fix cursor_demo wrt. Line2D.set_x/ydata not accepting scalars anymore. +* :ghpull:`25103`: Backport PR #25098 on branch v3.7.x (Correctly pass valinit as keyword in SliderTool.) +* :ghpull:`25098`: Correctly pass valinit as keyword in SliderTool. +* :ghpull:`23442`: Remove need to detect math mode in pgf strings +* :ghpull:`25093`: Backport PR #25092 on branch v3.7.x (Fix distribution of test data) +* :ghpull:`24893`: STY: make allowed line length 9 longer to 88 from 79 +* :ghpull:`25092`: Fix distribution of test data +* :ghpull:`25089`: Backport PR #25088 on branch v3.7.x (DOC: Fix broken cross-reference when building PDF) +* :ghpull:`25088`: DOC: Fix broken cross-reference when building PDF +* :ghpull:`25083`: Backport PR #25074 on branch v3.7.x (Revert "Use system distutils instead of the setuptools copy") +* :ghpull:`25082`: Backport PR #25079 on branch v3.7.x (FIX: Only send one update signal when autoscaling norms) +* :ghpull:`25084`: DOC: Fix typos in GitHub stats +* :ghpull:`25074`: Revert "Use system distutils instead of the setuptools copy" +* :ghpull:`25079`: FIX: Only send one update signal when autoscaling norms * :ghpull:`25072`: Merge v3.6.x into v3.7.x * :ghpull:`25071`: Backport PR #25039 on branch v3.7.x (Updated WebAgg JS to check and send request over wss if using HTTPS) * :ghpull:`25039`: Updated WebAgg JS to check and send request over wss if using HTTPS @@ -414,7 +466,7 @@ Pull Requests (380): * :ghpull:`24298`: List all the places to update when adding a dependency. * :ghpull:`24289`: Cleanup image_zcoord example. * :ghpull:`23865`: Add test and example for VBoxDivider -* :ghpull:`24287`: Simplifying glyph stream logic in ps backend +* :ghpull:`24287`: Simplifying glyph stream logic in ps backend * :ghpull:`24291`: Rely on builtin round() instead of manual rounding. * :ghpull:`24062`: Replaced std::random_shuffle with std::shuffle in tri * :ghpull:`24278`: Use oldest-supported-numpy for build @@ -478,7 +530,7 @@ Pull Requests (380): * :ghpull:`23579`: Remove direct manipulation of HostAxes.parasites by end users. * :ghpull:`23553`: Add tests for ImageGrid * :ghpull:`23918`: Merge v3.6.x branch to main -* :ghpull:`23902`: Add test and improve examples for mpl_toolkits +* :ghpull:`23902`: Add test and improve examples for mpl_toolkits * :ghpull:`23950`: DOC: Don't import doctest because we're not using it * :ghpull:`21006`: Rotate errorbar caps in polar plots * :ghpull:`23870`: Implement Sphinx-Gallery's ``make html-noplot`` @@ -505,8 +557,18 @@ Pull Requests (380): * :ghpull:`22614`: ENH: Add pan and zoom toolbar handling to 3D Axes * :ghpull:`21562`: Add a test for Hexbin Linear -Issues (110): +Issues (120): +* :ghissue:`25176`: [Bug]: Colorbar is displaced when saving as .eps with bbox_inches='tight' +* :ghissue:`25075`: [Bug]: Widget blitting broken when saving as PDF +* :ghissue:`25181`: unavoidable warnings in nbagg on ``plt.close`` +* :ghissue:`25134`: [Doc]: pyplot.boxplot whisker length wrong docs +* :ghissue:`24395`: Any resizing of the plot after plt.show results in an error when closing the window +* :ghissue:`25107`: [Doc]: annotated_cursor example seems broken +* :ghissue:`25124`: [Bug]: ax.plot(x,y) disappears after changing y_scale +* :ghissue:`8278`: FuncAnimation with generator defaults to arbitrary save_count=100 +* :ghissue:`22765`: Document distutil vs setuptools issues or fix usage +* :ghissue:`25077`: [Bug]: Setting norm with existing colorbar fails with 3.6.3 * :ghissue:`23999`: [Bug]: Annotation misplaced when rasterizing and saving as PDF * :ghissue:`25040`: [Bug]: Request to insecure websocket endpoint is blocked by browser * :ghissue:`24678`: [Bug]: pcolormesh doesn't allow shading = 'flat' in the option diff --git a/doc/users/next_whats_new/3d_pane_color_rcparams.rst b/doc/users/next_whats_new/3d_pane_color_rcparams.rst deleted file mode 100644 index 949b75a322c8..000000000000 --- a/doc/users/next_whats_new/3d_pane_color_rcparams.rst +++ /dev/null @@ -1,18 +0,0 @@ -rcParam for 3D pane color -------------------------- - -The rcParams :rc:`axes3d.xaxis.panecolor`, :rc:`axes3d.yaxis.panecolor`, -:rc:`axes3d.zaxis.panecolor` can be used to change the color of the background -panes in 3D plots. Note that it is often beneficial to give them slightly -different shades to obtain a "3D effect" and to make them slightly transparent -(alpha < 1). - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - with plt.rc_context({'axes3d.xaxis.panecolor': (0.9, 0.0, 0.0, 0.5), - 'axes3d.yaxis.panecolor': (0.7, 0.0, 0.0, 0.5), - 'axes3d.zaxis.panecolor': (0.8, 0.0, 0.0, 0.5)}): - fig = plt.figure() - fig.add_subplot(projection='3d') diff --git a/doc/users/next_whats_new/3d_plot_aspects_adjustable_keyword.rst b/doc/users/next_whats_new/3d_plot_aspects_adjustable_keyword.rst deleted file mode 100644 index 5a231024a759..000000000000 --- a/doc/users/next_whats_new/3d_plot_aspects_adjustable_keyword.rst +++ /dev/null @@ -1,34 +0,0 @@ -*adjustable* keyword argument for setting equal aspect ratios in 3D -------------------------------------------------------------------- - -While setting equal aspect ratios for 3D plots, users can choose to modify -either the data limits or the bounding box. - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - import numpy as np - from itertools import combinations, product - - aspects = ('auto', 'equal', 'equalxy', 'equalyz', 'equalxz') - fig, axs = plt.subplots(1, len(aspects), subplot_kw={'projection': '3d'}, - figsize=(12, 6)) - - # Draw rectangular cuboid with side lengths [4, 3, 5] - r = [0, 1] - scale = np.array([4, 3, 5]) - pts = combinations(np.array(list(product(r, r, r))), 2) - for start, end in pts: - if np.sum(np.abs(start - end)) == r[1] - r[0]: - for ax in axs: - ax.plot3D(*zip(start*scale, end*scale), color='C0') - - # Set the aspect ratios - for i, ax in enumerate(axs): - ax.set_aspect(aspects[i], adjustable='datalim') - # Alternatively: ax.set_aspect(aspects[i], adjustable='box') - # which will change the box aspect ratio instead of axis data limits. - ax.set_title(f"set_aspect('{aspects[i]}')") - - plt.show() diff --git a/doc/users/next_whats_new/3d_plot_pan_zoom.rst b/doc/users/next_whats_new/3d_plot_pan_zoom.rst deleted file mode 100644 index a94dfe4c207d..000000000000 --- a/doc/users/next_whats_new/3d_plot_pan_zoom.rst +++ /dev/null @@ -1,8 +0,0 @@ -3D plot pan and zoom buttons ----------------------------- - -The pan and zoom buttons in the toolbar of 3D plots are now enabled. -Unselect both to rotate the plot. When the zoom button is pressed, -zoom in by using the left mouse button to draw a bounding box, and -out by using the right mouse button to draw the box. When zooming a -3D plot, the current view aspect ratios are kept fixed. diff --git a/doc/users/next_whats_new/bar_label_formatting.rst b/doc/users/next_whats_new/bar_label_formatting.rst deleted file mode 100644 index 90b3d088ff84..000000000000 --- a/doc/users/next_whats_new/bar_label_formatting.rst +++ /dev/null @@ -1,33 +0,0 @@ -Additional format string options in `~matplotlib.axes.Axes.bar_label` ---------------------------------------------------------------------- - -The ``fmt`` argument of `~matplotlib.axes.Axes.bar_label` now accepts -{}-style format strings: - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - - fruit_names = ['Coffee', 'Salted Caramel', 'Pistachio'] - fruit_counts = [4000, 2000, 7000] - - fig, ax = plt.subplots() - bar_container = ax.bar(fruit_names, fruit_counts) - ax.set(ylabel='pints sold', title='Gelato sales by flavor', ylim=(0, 8000)) - ax.bar_label(bar_container, fmt='{:,.0f}') - -It also accepts callables: - -.. plot:: - :include-source: true - - animal_names = ['Lion', 'Gazelle', 'Cheetah'] - mph_speed = [50, 60, 75] - - fig, ax = plt.subplots() - bar_container = ax.bar(animal_names, mph_speed) - ax.set(ylabel='speed in MPH', title='Running speeds', ylim=(0, 80)) - ax.bar_label( - bar_container, fmt=lambda x: '{:.1f} km/h'.format(x * 1.61) - ) diff --git a/doc/users/next_whats_new/colorbar_has_location_argument.rst b/doc/users/next_whats_new/colorbar_has_location_argument.rst deleted file mode 100644 index 5eb02e8be689..000000000000 --- a/doc/users/next_whats_new/colorbar_has_location_argument.rst +++ /dev/null @@ -1,25 +0,0 @@ -``colorbar`` now has a *location* keyword argument -================================================== - -The ``colorbar`` method now supports a *location* keyword argument to more -easily position the color bar. This is useful when providing your own inset -axes using the *cax* keyword argument and behaves similar to the case where -axes are not provided (where the *location* keyword is passed through). -*orientation* and *ticklocation* are no longer required as they are -determined by *location*. *ticklocation* can still be provided if the -automatic setting is not preferred. (*orientation* can also be provided but -must be compatible with the *location*.) - -An example is: - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - import numpy as np - rng = np.random.default_rng(19680801) - imdata = rng.random((10, 10)) - fig, ax = plt.subplots(layout='constrained') - im = ax.imshow(imdata) - fig.colorbar(im, cax=ax.inset_axes([0, 1.05, 1, 0.05]), - location='top') diff --git a/doc/users/next_whats_new/documentation.rst b/doc/users/next_whats_new/documentation.rst deleted file mode 100644 index 9e7625a09d0d..000000000000 --- a/doc/users/next_whats_new/documentation.rst +++ /dev/null @@ -1,6 +0,0 @@ -New & Improved Narrative Documentation -====================================== -* Brand new :doc:`Animations ` tutorial. -* New grouped and stacked `bar chart <../../gallery/index.html#lines_bars_and_markers>`_ examples. -* New section for new contributors and reorganized git instructions in the :ref:`contributing guide`. -* Restructured :doc:`/tutorials/text/annotations` tutorial. diff --git a/doc/users/next_whats_new/ellipse_annotation.rst b/doc/users/next_whats_new/ellipse_annotation.rst deleted file mode 100644 index d6a989e77a5b..000000000000 --- a/doc/users/next_whats_new/ellipse_annotation.rst +++ /dev/null @@ -1,15 +0,0 @@ -``ellipse`` boxstyle option for annotations -------------------------------------------- - -The ``'ellipse'`` option for boxstyle can now be used to create annotations -with an elliptical outline. It can be used as a closed curve shape for -longer texts instead of the ``'circle'`` boxstyle which can get quite big. - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - fig, ax = plt.subplots(figsize=(5, 5)) - t = ax.text(0.5, 0.5, "elliptical box", - ha="center", size=15, - bbox=dict(boxstyle="ellipse,pad=0.3")) diff --git a/doc/users/next_whats_new/figure_hooks.rst b/doc/users/next_whats_new/figure_hooks.rst deleted file mode 100644 index 7132e4875f92..000000000000 --- a/doc/users/next_whats_new/figure_hooks.rst +++ /dev/null @@ -1,8 +0,0 @@ -Figure hooks -~~~~~~~~~~~~ -The new :rc:`figure.hooks` provides a mechanism to register -arbitrary customizations on pyplot figures; it is a list of -"dotted.module.name:dotted.callable.name" strings specifying functions -that are called on each figure created by `.pyplot.figure`; these -functions can e.g. attach callbacks or modify the toolbar. See -:doc:`/gallery/user_interfaces/mplcvd` for an example of toolbar customization. diff --git a/doc/users/next_whats_new/imshow_extent_units.rst b/doc/users/next_whats_new/imshow_extent_units.rst deleted file mode 100644 index fac21b043fa4..000000000000 --- a/doc/users/next_whats_new/imshow_extent_units.rst +++ /dev/null @@ -1,20 +0,0 @@ -The *extent* of ``imshow`` can now be expressed with units ----------------------------------------------------------- -The *extent* parameter of `~.axes.Axes.imshow` and `~.AxesImage.set_extent` -can now be expressed with units. - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - import numpy as np - - fig, ax = plt.subplots(layout='constrained') - date_first = np.datetime64('2020-01-01', 'D') - date_last = np.datetime64('2020-01-11', 'D') - - arr = [[i+j for i in range(10)] for j in range(10)] - - ax.imshow(arr, origin='lower', extent=[0, 10, date_first, date_last]) - - plt.show() diff --git a/doc/users/next_whats_new/legend-figure-outside.rst b/doc/users/next_whats_new/legend-figure-outside.rst deleted file mode 100644 index a78725b4e2b6..000000000000 --- a/doc/users/next_whats_new/legend-figure-outside.rst +++ /dev/null @@ -1,8 +0,0 @@ -Figure legends can be placed outside figures using constrained_layout ---------------------------------------------------------------------- -Constrained layout will make space for Figure legends if they are specified -by a *loc* keyword argument that starts with the string "outside". The -codes are unique from axes codes, in that "outside upper right" will -make room at the top of the figure for the legend, whereas -"outside right upper" will make room on the right-hand side of the figure. -See :doc:`/tutorials/intermediate/legend_guide` for details. diff --git a/doc/users/next_whats_new/per_subplot_mosaic.rst b/doc/users/next_whats_new/per_subplot_mosaic.rst deleted file mode 100644 index f62e231d2665..000000000000 --- a/doc/users/next_whats_new/per_subplot_mosaic.rst +++ /dev/null @@ -1,30 +0,0 @@ -``subplot_mosaic`` no longer provisional ----------------------------------------- - -The API on `.Figure.subplot_mosaic` and `.pyplot.subplot_mosaic` are now -considered stable and will change under Matplotlib's normal deprecation -process. - - -Per-subplot keyword arguments in ``subplot_mosaic`` ----------------------------------------------------- - -It is now possible to pass keyword arguments through to Axes creation in each -specific call to ``add_subplot`` in `.Figure.subplot_mosaic` and -`.pyplot.subplot_mosaic` : - -.. plot:: - :include-source: true - - fig, axd = plt.subplot_mosaic( - "AB;CD", - per_subplot_kw={ - "A": {"projection": "polar"}, - ("C", "D"): {"xscale": "log"}, - "B": {"projection": "3d"}, - }, - ) - - -This is particularly useful for creating mosaics with mixed projections, but -any keyword arguments can be passed through. diff --git a/doc/users/next_whats_new/pie_hatch.rst b/doc/users/next_whats_new/pie_hatch.rst deleted file mode 100644 index f54def10e954..000000000000 --- a/doc/users/next_whats_new/pie_hatch.rst +++ /dev/null @@ -1,18 +0,0 @@ -``hatch`` parameter for pie -------------------------------------------- - -`~matplotlib.axes.Axes.pie` now accepts a *hatch* keyword that takes as input -a hatch or list of hatches: - -.. plot:: - :include-source: true - :alt: Two pie charts, identified as ax1 and ax2, both have a small blue slice, a medium orange slice, and a large green slice. ax1 has a dot hatching on the small slice, a small open circle hatching on the medium slice, and a large open circle hatching on the large slice. ax2 has the same large open circle with a dot hatch on every slice. - - fig, (ax1, ax2) = plt.subplots(ncols=2) - x = [10, 30, 60] - - ax1.pie(x, hatch=['.', 'o', 'O']) - ax2.pie(x, hatch='.O') - - ax1.set_title("hatch=['.', 'o', 'O']") - ax2.set_title("hatch='.O'") diff --git a/doc/users/next_whats_new/polar_errorbar_caps.rst b/doc/users/next_whats_new/polar_errorbar_caps.rst deleted file mode 100644 index 1066a2aaaf11..000000000000 --- a/doc/users/next_whats_new/polar_errorbar_caps.rst +++ /dev/null @@ -1,7 +0,0 @@ -Fixed errorbars in polar plots ------------------------------- -Caps and error lines are now drawn with respect to polar coordinates, -when plotting errorbars on polar plots. - -.. figure:: /gallery/pie_and_polar_charts/images/sphx_glr_polar_error_caps_001.png - :target: ../../gallery/pie_and_polar_charts/polar_error_caps.html diff --git a/doc/users/next_whats_new/reverse_legend.rst b/doc/users/next_whats_new/reverse_legend.rst deleted file mode 100644 index 00f2c0dbeac7..000000000000 --- a/doc/users/next_whats_new/reverse_legend.rst +++ /dev/null @@ -1,4 +0,0 @@ -Reversed order of legend entries --------------------------------- -The order of legend entries can now be reversed by passing ``reverse=True`` to -`~.Axes.legend`. diff --git a/doc/users/next_whats_new/rgba_pcolormesh.rst b/doc/users/next_whats_new/rgba_pcolormesh.rst deleted file mode 100644 index 4088677867c0..000000000000 --- a/doc/users/next_whats_new/rgba_pcolormesh.rst +++ /dev/null @@ -1,16 +0,0 @@ -``pcolormesh`` accepts RGB(A) colors ------------------------------------- - -The `~.Axes.pcolormesh` method can now handle explicit colors -specified with RGB(A) values. To specify colors, the array must be 3D -with a shape of ``(M, N, [3, 4])``. - -.. plot:: - :include-source: true - - import matplotlib.pyplot as plt - import numpy as np - - colors = np.linspace(0, 1, 90).reshape((5, 6, 3)) - plt.pcolormesh(colors) - plt.show() diff --git a/doc/users/next_whats_new/shade_poly3dcollection.rst b/doc/users/next_whats_new/shade_poly3dcollection.rst deleted file mode 100644 index 4a9199eb8c49..000000000000 --- a/doc/users/next_whats_new/shade_poly3dcollection.rst +++ /dev/null @@ -1,33 +0,0 @@ -``Poly3DCollection`` supports shading -------------------------------------- - -It is now possible to shade a `.Poly3DCollection`. This is useful if the -polygons are obtained from e.g. a 3D model. - -.. plot:: - :include-source: true - - import numpy as np - import matplotlib.pyplot as plt - from mpl_toolkits.mplot3d.art3d import Poly3DCollection - - # Define 3D shape - block = np.array([ - [[1, 1, 0], - [1, 0, 0], - [0, 1, 0]], - [[1, 1, 0], - [1, 1, 1], - [1, 0, 0]], - [[1, 1, 0], - [1, 1, 1], - [0, 1, 0]], - [[1, 0, 0], - [1, 1, 1], - [0, 1, 0]] - ]) - - ax = plt.subplot(projection='3d') - pc = Poly3DCollection(block, facecolors='b', shade=True) - ax.add_collection(pc) - plt.show() diff --git a/doc/users/next_whats_new/show_source_links_directive_option.rst b/doc/users/next_whats_new/show_source_links_directive_option.rst deleted file mode 100644 index 8beb233f32e8..000000000000 --- a/doc/users/next_whats_new/show_source_links_directive_option.rst +++ /dev/null @@ -1,7 +0,0 @@ -Source links can be shown or hidden for each Sphinx plot directive ------------------------------------------------------------------- -The :doc:`Sphinx plot directive ` -(``.. plot::``) now supports a ``:show-source-link:`` option to show or hide -the link to the source code for each plot. The default is set using the -``plot_html_show_source_link`` variable in :file:`conf.py` (which -defaults to True). diff --git a/doc/users/next_whats_new/styles_from_packages.rst b/doc/users/next_whats_new/styles_from_packages.rst deleted file mode 100644 index d129bb356fa7..000000000000 --- a/doc/users/next_whats_new/styles_from_packages.rst +++ /dev/null @@ -1,11 +0,0 @@ -Style files can be imported from third-party packages ------------------------------------------------------ - -Third-party packages can now distribute style files that are globally available -as follows. Assume that a package is importable as ``import mypackage``, with -a ``mypackage/__init__.py`` module. Then a ``mypackage/presentation.mplstyle`` -style sheet can be used as ``plt.style.use("mypackage.presentation")``. - -The implementation does not actually import ``mypackage``, making this process -safe against possible import-time side effects. Subpackages (e.g. -``dotted.package.name``) are also supported. diff --git a/doc/users/next_whats_new/view_current_axis_format.rst b/doc/users/next_whats_new/view_current_axis_format.rst deleted file mode 100644 index eb7e03600f0e..000000000000 --- a/doc/users/next_whats_new/view_current_axis_format.rst +++ /dev/null @@ -1,29 +0,0 @@ -View current appearance settings for ticks, tick labels, and gridlines ----------------------------------------------------------------------- - -The new `~matplotlib.axis.Axis.get_tick_params` method can be used to -retrieve the appearance settings that will be applied to any -additional ticks, tick labels, and gridlines added to the plot: - -.. code-block:: pycon - - >>> import matplotlib.pyplot as plt - - >>> fig, ax = plt.subplots() - >>> ax.yaxis.set_tick_params(labelsize=30, labelcolor='red', - ... direction='out', which='major') - >>> ax.yaxis.get_tick_params(which='major') - {'direction': 'out', - 'left': True, - 'right': False, - 'labelleft': True, - 'labelright': False, - 'gridOn': False, - 'labelsize': 30, - 'labelcolor': 'red'} - >>> ax.yaxis.get_tick_params(which='minor') - {'left': True, - 'right': False, - 'labelleft': True, - 'labelright': False, - 'gridOn': False} diff --git a/doc/users/next_whats_new/widget_blitting.rst b/doc/users/next_whats_new/widget_blitting.rst deleted file mode 100644 index 129ce8953d6f..000000000000 --- a/doc/users/next_whats_new/widget_blitting.rst +++ /dev/null @@ -1,7 +0,0 @@ -Blitting in Button widgets --------------------------- - -The `.Button`, `.CheckButtons`, and `.RadioButtons` widgets now support -blitting for faster rendering, on backends that support it, by passing -``useblit=True`` to the constructor. Blitting is enabled by default on -supported backends. diff --git a/doc/users/next_whats_new/widget_button_styling.rst b/doc/users/next_whats_new/widget_button_styling.rst deleted file mode 100644 index 4307e6977fc5..000000000000 --- a/doc/users/next_whats_new/widget_button_styling.rst +++ /dev/null @@ -1,31 +0,0 @@ -Custom styling of button widgets --------------------------------- - -Additional custom styling of button widgets may be achieved via the -*label_props* and *radio_props* arguments to `.RadioButtons`; and the -*label_props*, *frame_props*, and *check_props* arguments to `.CheckButtons`. - -.. plot:: - - from matplotlib.widgets import CheckButtons, RadioButtons - - fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(5, 2), width_ratios=[1, 2]) - default_rb = RadioButtons(ax[0, 0], ['Apples', 'Oranges']) - styled_rb = RadioButtons(ax[0, 1], ['Apples', 'Oranges'], - label_props={'color': ['red', 'orange'], - 'fontsize': [16, 20]}, - radio_props={'edgecolor': ['red', 'orange'], - 'facecolor': ['mistyrose', 'peachpuff']}) - - default_cb = CheckButtons(ax[1, 0], ['Apples', 'Oranges'], - actives=[True, True]) - styled_cb = CheckButtons(ax[1, 1], ['Apples', 'Oranges'], - actives=[True, True], - label_props={'color': ['red', 'orange'], - 'fontsize': [16, 20]}, - frame_props={'edgecolor': ['red', 'orange'], - 'facecolor': ['mistyrose', 'peachpuff']}, - check_props={'color': ['darkred', 'darkorange']}) - - ax[0, 0].set_title('Default') - ax[0, 1].set_title('Stylized') diff --git a/doc/users/prev_whats_new/whats_new_3.7.0.rst b/doc/users/prev_whats_new/whats_new_3.7.0.rst new file mode 100644 index 000000000000..cbbcd50c7e6a --- /dev/null +++ b/doc/users/prev_whats_new/whats_new_3.7.0.rst @@ -0,0 +1,450 @@ +============================================= +What's new in Matplotlib 3.7.0 (Feb 10, 2023) +============================================= + +For a list of all of the issues and pull requests since the last revision, see +the :ref:`github-stats`. + +.. contents:: Table of Contents + :depth: 4 + +.. toctree:: + :maxdepth: 4 + +Plotting and Annotation improvements +==================================== + + +``hatch`` parameter for pie +--------------------------- + +`~matplotlib.axes.Axes.pie` now accepts a *hatch* keyword that takes as input +a hatch or list of hatches: + +.. plot:: + :include-source: true + :alt: Two pie charts, identified as ax1 and ax2, both have a small blue slice, a medium orange slice, and a large green slice. ax1 has a dot hatching on the small slice, a small open circle hatching on the medium slice, and a large open circle hatching on the large slice. ax2 has the same large open circle with a dot hatch on every slice. + + fig, (ax1, ax2) = plt.subplots(ncols=2) + x = [10, 30, 60] + + ax1.pie(x, hatch=['.', 'o', 'O']) + ax2.pie(x, hatch='.O') + + ax1.set_title("hatch=['.', 'o', 'O']") + ax2.set_title("hatch='.O'") + + +Polar plot errors drawn in polar coordinates +-------------------------------------------- +Caps and error lines are now drawn with respect to polar coordinates, +when plotting errorbars on polar plots. + +.. figure:: /gallery/pie_and_polar_charts/images/sphx_glr_polar_error_caps_001.png + :target: ../../gallery/pie_and_polar_charts/polar_error_caps.html + + + +Additional format string options in `~matplotlib.axes.Axes.bar_label` +--------------------------------------------------------------------- + +The ``fmt`` argument of `~matplotlib.axes.Axes.bar_label` now accepts +{}-style format strings: + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + + fruit_names = ['Coffee', 'Salted Caramel', 'Pistachio'] + fruit_counts = [4000, 2000, 7000] + + fig, ax = plt.subplots() + bar_container = ax.bar(fruit_names, fruit_counts) + ax.set(ylabel='pints sold', title='Gelato sales by flavor', ylim=(0, 8000)) + ax.bar_label(bar_container, fmt='{:,.0f}') + +It also accepts callables: + +.. plot:: + :include-source: true + + animal_names = ['Lion', 'Gazelle', 'Cheetah'] + mph_speed = [50, 60, 75] + + fig, ax = plt.subplots() + bar_container = ax.bar(animal_names, mph_speed) + ax.set(ylabel='speed in MPH', title='Running speeds', ylim=(0, 80)) + ax.bar_label( + bar_container, fmt=lambda x: '{:.1f} km/h'.format(x * 1.61) + ) + + + +``ellipse`` boxstyle option for annotations +------------------------------------------- + +The ``'ellipse'`` option for boxstyle can now be used to create annotations +with an elliptical outline. It can be used as a closed curve shape for +longer texts instead of the ``'circle'`` boxstyle which can get quite big. + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + fig, ax = plt.subplots(figsize=(5, 5)) + t = ax.text(0.5, 0.5, "elliptical box", + ha="center", size=15, + bbox=dict(boxstyle="ellipse,pad=0.3")) + + +The *extent* of ``imshow`` can now be expressed with units +---------------------------------------------------------- +The *extent* parameter of `~.axes.Axes.imshow` and `~.AxesImage.set_extent` +can now be expressed with units. + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + fig, ax = plt.subplots(layout='constrained') + date_first = np.datetime64('2020-01-01', 'D') + date_last = np.datetime64('2020-01-11', 'D') + + arr = [[i+j for i in range(10)] for j in range(10)] + + ax.imshow(arr, origin='lower', extent=[0, 10, date_first, date_last]) + + plt.show() + +Reversed order of legend entries +-------------------------------- +The order of legend entries can now be reversed by passing ``reverse=True`` to +`~.Axes.legend`. + + +``pcolormesh`` accepts RGB(A) colors +------------------------------------ + +The `~.Axes.pcolormesh` method can now handle explicit colors +specified with RGB(A) values. To specify colors, the array must be 3D +with a shape of ``(M, N, [3, 4])``. + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + colors = np.linspace(0, 1, 90).reshape((5, 6, 3)) + plt.pcolormesh(colors) + plt.show() + + + + +View current appearance settings for ticks, tick labels, and gridlines +---------------------------------------------------------------------- + +The new `~matplotlib.axis.Axis.get_tick_params` method can be used to +retrieve the appearance settings that will be applied to any +additional ticks, tick labels, and gridlines added to the plot: + +.. code-block:: pycon + + >>> import matplotlib.pyplot as plt + + >>> fig, ax = plt.subplots() + >>> ax.yaxis.set_tick_params(labelsize=30, labelcolor='red', + ... direction='out', which='major') + >>> ax.yaxis.get_tick_params(which='major') + {'direction': 'out', + 'left': True, + 'right': False, + 'labelleft': True, + 'labelright': False, + 'gridOn': False, + 'labelsize': 30, + 'labelcolor': 'red'} + >>> ax.yaxis.get_tick_params(which='minor') + {'left': True, + 'right': False, + 'labelleft': True, + 'labelright': False, + 'gridOn': False} + + + +Style files can be imported from third-party packages +----------------------------------------------------- + +Third-party packages can now distribute style files that are globally available +as follows. Assume that a package is importable as ``import mypackage``, with +a ``mypackage/__init__.py`` module. Then a ``mypackage/presentation.mplstyle`` +style sheet can be used as ``plt.style.use("mypackage.presentation")``. + +The implementation does not actually import ``mypackage``, making this process +safe against possible import-time side effects. Subpackages (e.g. +``dotted.package.name``) are also supported. + + +Improvements to 3D Plotting +=========================== + + +3D plot pan and zoom buttons +---------------------------- + +The pan and zoom buttons in the toolbar of 3D plots are now enabled. +Unselect both to rotate the plot. When the zoom button is pressed, +zoom in by using the left mouse button to draw a bounding box, and +out by using the right mouse button to draw the box. When zooming a +3D plot, the current view aspect ratios are kept fixed. + + +*adjustable* keyword argument for setting equal aspect ratios in 3D +------------------------------------------------------------------- + +While setting equal aspect ratios for 3D plots, users can choose to modify +either the data limits or the bounding box in parity with 2D Axes. + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + from itertools import combinations, product + + aspects = ('auto', 'equal', 'equalxy', 'equalyz', 'equalxz') + fig, axs = plt.subplots(1, len(aspects), subplot_kw={'projection': '3d'}, + figsize=(12, 6)) + + # Draw rectangular cuboid with side lengths [4, 3, 5] + r = [0, 1] + scale = np.array([4, 3, 5]) + pts = combinations(np.array(list(product(r, r, r))), 2) + for start, end in pts: + if np.sum(np.abs(start - end)) == r[1] - r[0]: + for ax in axs: + ax.plot3D(*zip(start*scale, end*scale), color='C0') + + # Set the aspect ratios + for i, ax in enumerate(axs): + ax.set_aspect(aspects[i], adjustable='datalim') + # Alternatively: ax.set_aspect(aspects[i], adjustable='box') + # which will change the box aspect ratio instead of axis data limits. + ax.set_title(f"set_aspect('{aspects[i]}')") + + plt.show() + + +``Poly3DCollection`` supports shading +------------------------------------- + +It is now possible to shade a `.Poly3DCollection`. This is useful if the +polygons are obtained from e.g. a 3D model. + +.. plot:: + :include-source: true + + import numpy as np + import matplotlib.pyplot as plt + from mpl_toolkits.mplot3d.art3d import Poly3DCollection + + # Define 3D shape + block = np.array([ + [[1, 1, 0], + [1, 0, 0], + [0, 1, 0]], + [[1, 1, 0], + [1, 1, 1], + [1, 0, 0]], + [[1, 1, 0], + [1, 1, 1], + [0, 1, 0]], + [[1, 0, 0], + [1, 1, 1], + [0, 1, 0]] + ]) + + ax = plt.subplot(projection='3d') + pc = Poly3DCollection(block, facecolors='b', shade=True) + ax.add_collection(pc) + plt.show() + + + +rcParam for 3D pane color +------------------------- + +The rcParams :rc:`axes3d.xaxis.panecolor`, :rc:`axes3d.yaxis.panecolor`, +:rc:`axes3d.zaxis.panecolor` can be used to change the color of the background +panes in 3D plots. Note that it is often beneficial to give them slightly +different shades to obtain a "3D effect" and to make them slightly transparent +(alpha < 1). + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + with plt.rc_context({'axes3d.xaxis.panecolor': (0.9, 0.0, 0.0, 0.5), + 'axes3d.yaxis.panecolor': (0.7, 0.0, 0.0, 0.5), + 'axes3d.zaxis.panecolor': (0.8, 0.0, 0.0, 0.5)}): + fig = plt.figure() + fig.add_subplot(projection='3d') + + + + +Figure and Axes Layout +====================== + +``colorbar`` now has a *location* keyword argument +-------------------------------------------------- + +The ``colorbar`` method now supports a *location* keyword argument to more +easily position the color bar. This is useful when providing your own inset +axes using the *cax* keyword argument and behaves similar to the case where +axes are not provided (where the *location* keyword is passed through). +*orientation* and *ticklocation* are no longer required as they are +determined by *location*. *ticklocation* can still be provided if the +automatic setting is not preferred. (*orientation* can also be provided but +must be compatible with the *location*.) + +An example is: + +.. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + rng = np.random.default_rng(19680801) + imdata = rng.random((10, 10)) + fig, ax = plt.subplots(layout='constrained') + im = ax.imshow(imdata) + fig.colorbar(im, cax=ax.inset_axes([0, 1.05, 1, 0.05]), + location='top') + + + +Figure legends can be placed outside figures using constrained_layout +--------------------------------------------------------------------- +Constrained layout will make space for Figure legends if they are specified +by a *loc* keyword argument that starts with the string "outside". The +codes are unique from axes codes, in that "outside upper right" will +make room at the top of the figure for the legend, whereas +"outside right upper" will make room on the right-hand side of the figure. +See :doc:`/tutorials/intermediate/legend_guide` for details. + + +Per-subplot keyword arguments in ``subplot_mosaic`` +---------------------------------------------------- + +It is now possible to pass keyword arguments through to Axes creation in each +specific call to ``add_subplot`` in `.Figure.subplot_mosaic` and +`.pyplot.subplot_mosaic` : + +.. plot:: + :include-source: true + + fig, axd = plt.subplot_mosaic( + "AB;CD", + per_subplot_kw={ + "A": {"projection": "polar"}, + ("C", "D"): {"xscale": "log"}, + "B": {"projection": "3d"}, + }, + ) + + +This is particularly useful for creating mosaics with mixed projections, but +any keyword arguments can be passed through. + + +``subplot_mosaic`` no longer provisional +---------------------------------------- + +The API on `.Figure.subplot_mosaic` and `.pyplot.subplot_mosaic` are now +considered stable and will change under Matplotlib's normal deprecation +process. + + +Widget Improvements +=================== + + +Custom styling of button widgets +-------------------------------- + +Additional custom styling of button widgets may be achieved via the +*label_props* and *radio_props* arguments to `.RadioButtons`; and the +*label_props*, *frame_props*, and *check_props* arguments to `.CheckButtons`. + +.. plot:: + + from matplotlib.widgets import CheckButtons, RadioButtons + + fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(5, 2), width_ratios=[1, 2]) + default_rb = RadioButtons(ax[0, 0], ['Apples', 'Oranges']) + styled_rb = RadioButtons(ax[0, 1], ['Apples', 'Oranges'], + label_props={'color': ['red', 'orange'], + 'fontsize': [16, 20]}, + radio_props={'edgecolor': ['red', 'orange'], + 'facecolor': ['mistyrose', 'peachpuff']}) + + default_cb = CheckButtons(ax[1, 0], ['Apples', 'Oranges'], + actives=[True, True]) + styled_cb = CheckButtons(ax[1, 1], ['Apples', 'Oranges'], + actives=[True, True], + label_props={'color': ['red', 'orange'], + 'fontsize': [16, 20]}, + frame_props={'edgecolor': ['red', 'orange'], + 'facecolor': ['mistyrose', 'peachpuff']}, + check_props={'color': ['darkred', 'darkorange']}) + + ax[0, 0].set_title('Default') + ax[0, 1].set_title('Stylized') + + +Blitting in Button widgets +-------------------------- + +The `.Button`, `.CheckButtons`, and `.RadioButtons` widgets now support +blitting for faster rendering, on backends that support it, by passing +``useblit=True`` to the constructor. Blitting is enabled by default on +supported backends. + + +Other Improvements +================== + + +Source links can be shown or hidden for each Sphinx plot directive +------------------------------------------------------------------ +The :doc:`Sphinx plot directive ` +(``.. plot::``) now supports a ``:show-source-link:`` option to show or hide +the link to the source code for each plot. The default is set using the +``plot_html_show_source_link`` variable in :file:`conf.py` (which +defaults to True). + + + +Figure hooks +------------ + +The new :rc:`figure.hooks` provides a mechanism to register +arbitrary customizations on pyplot figures; it is a list of +"dotted.module.name:dotted.callable.name" strings specifying functions +that are called on each figure created by `.pyplot.figure`; these +functions can e.g. attach callbacks or modify the toolbar. See +:doc:`/gallery/user_interfaces/mplcvd` for an example of toolbar customization. + + +New & Improved Narrative Documentation +====================================== +* Brand new :doc:`Animations ` tutorial. +* New grouped and stacked `bar chart <../../gallery/index.html#lines_bars_and_markers>`_ examples. +* New section for new contributors and reorganized git instructions in the :ref:`contributing guide`. +* Restructured :doc:`/tutorials/text/annotations` tutorial. diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst index 393efc88b711..cf41d6de8a06 100644 --- a/doc/users/release_notes.rst +++ b/doc/users/release_notes.rst @@ -9,6 +9,17 @@ Release notes .. include from another document so that it's easy to exclude this for releases .. include:: release_notes_next.rst + +Version 3.7 +=========== +.. toctree:: + :maxdepth: 1 + + prev_whats_new/whats_new_3.7.0.rst + ../api/prev_api_changes/api_changes_3.7.0.rst + github_stats.rst + + Version 3.6 =========== .. toctree:: @@ -17,7 +28,7 @@ Version 3.6 prev_whats_new/whats_new_3.6.0.rst ../api/prev_api_changes/api_changes_3.6.1.rst ../api/prev_api_changes/api_changes_3.6.0.rst - github_stats.rst + prev_whats_new/github_stats_3.6.3.rst prev_whats_new/github_stats_3.6.2.rst prev_whats_new/github_stats_3.6.1.rst prev_whats_new/github_stats_3.6.0.rst diff --git a/examples/README.txt b/examples/README.txt index 87098fb881ce..8e41fb83d300 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -9,6 +9,6 @@ Examples This page contains example plots. Click on any image to see the full image and source code. -For longer tutorials, see our `tutorials page <../tutorials/index.html>`_. -You can also find `external resources <../users/resources/index.html>`_ and -a `FAQ <../users/faq/index.html>`_ in our `user guide <../users/index.html>`_. +For longer tutorials, see our :ref:`tutorials page `. +You can also find :ref:`external resources ` and +a :ref:`FAQ ` in our :ref:`user guide `. diff --git a/lib/matplotlib/path.py b/lib/matplotlib/path.py index 75ef7fc4589a..1f65632c2d62 100644 --- a/lib/matplotlib/path.py +++ b/lib/matplotlib/path.py @@ -937,7 +937,7 @@ def arc(cls, theta1, theta2, n=None, is_wedge=False): Masionobe, L. 2003. `Drawing an elliptical arc using polylines, quadratic or cubic Bezier curves - `_. + `_. """ halfpi = np.pi * 0.5 diff --git a/tutorials/README.txt b/tutorials/README.txt index 74d339265bdb..da744b3224c7 100644 --- a/tutorials/README.txt +++ b/tutorials/README.txt @@ -7,6 +7,6 @@ This page contains more in-depth guides for using Matplotlib. It is broken up into beginner, intermediate, and advanced sections, as well as sections covering specific topics. -For shorter examples, see our `examples page <../gallery/index.html>`_. -You can also find `external resources <../resources/index.html>`_ and -a `FAQ <../faq/index.html>`_ in our `user guide <../contents.html>`_. +For shorter examples, see our :ref:`examples page `. +You can also find :ref:`external resources ` and +a :ref:`FAQ ` in our :ref:`user guide `. From 1b5c3fb2d7cfb449434bb944c9b3ebe46f89f66e Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 10 Feb 2023 15:23:50 -0600 Subject: [PATCH 260/262] Merge pull request #24781 from tacaswell/mnt/restore_doc_sha DOC: restore SHA to footer (cherry picked from commit 73909bcb408886a22e2b84581d6b9e6d9907c813) --- doc/conf.py | 6 ++++++ requirements/doc/doc-requirements.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 2b5bc9f2bb6f..b77dfa3ba85f 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -270,6 +270,11 @@ def gallery_image_warning_filter(record): except (subprocess.CalledProcessError, FileNotFoundError): SHA = matplotlib.__version__ + +html_context = { + "doc_version": SHA, +} + project = 'Matplotlib' copyright = ( '2002–2012 John Hunter, Darren Dale, Eric Firing, Michael Droettboom ' @@ -404,6 +409,7 @@ def js_tag_with_cache_busting(js): "image_dark": "images/logo_dark.svg"}, "navbar_end": ["theme-switcher", "version-switcher", "mpl_icon_links"], "secondary_sidebar_items": "page-toc.html", + "footer_items": ["copyright", "sphinx-version", "doc_version"], } include_analytics = is_release_build if include_analytics: diff --git a/requirements/doc/doc-requirements.txt b/requirements/doc/doc-requirements.txt index f4db1699fc5c..9622bdab289f 100644 --- a/requirements/doc/doc-requirements.txt +++ b/requirements/doc/doc-requirements.txt @@ -14,7 +14,7 @@ ipywidgets numpydoc>=1.0 packaging>=20 pydata-sphinx-theme>=0.12.0 -mpl-sphinx-theme +mpl-sphinx-theme>=3.7.0 sphinxcontrib-svg2pdfconverter>=1.1.0 sphinx-gallery>=0.10 sphinx-copybutton From ddef53603582c3ccc4a3130df25df5183d5d0e6c Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 13 Feb 2023 14:22:13 -0600 Subject: [PATCH 261/262] DOC: update what's new date for final release date --- doc/users/prev_whats_new/whats_new_3.7.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/users/prev_whats_new/whats_new_3.7.0.rst b/doc/users/prev_whats_new/whats_new_3.7.0.rst index cbbcd50c7e6a..af464da50969 100644 --- a/doc/users/prev_whats_new/whats_new_3.7.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.7.0.rst @@ -1,5 +1,5 @@ ============================================= -What's new in Matplotlib 3.7.0 (Feb 10, 2023) +What's new in Matplotlib 3.7.0 (Feb 13, 2023) ============================================= For a list of all of the issues and pull requests since the last revision, see From d6dd1b79142e4e2483244c25ff1e3ddb664722d3 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 13 Feb 2023 14:37:33 -0600 Subject: [PATCH 262/262] REL: v3.7.0 Highlights of this release include: - Plotting and Annotation improvements - ``hatch`` parameter for pie - Polar plot errors drawn in polar coordinates - Additional format string options in `~matplotlib.axes.Axes.bar_label` - ``ellipse`` boxstyle option for annotations - The *extent* of ``imshow`` can now be expressed with units - Reversed order of legend entries - ``pcolormesh`` accepts RGB(A) colors - View current appearance settings for ticks, tick labels, and gridlines - Style files can be imported from third-party packages - Improvements to 3D Plotting - 3D plot pan and zoom buttons - *adjustable* keyword argument for setting equal aspect ratios in 3D - ``Poly3DCollection`` supports shading - rcParam for 3D pane color - Figure and Axes Layout - ``colorbar`` now has a *location* keyword argument - Figure legends can be placed outside figures using constrained_layout - Per-subplot keyword arguments in ``subplot_mosaic`` - ``subplot_mosaic`` no longer provisional - Widget Improvements - Custom styling of button widgets - Blitting in Button widgets - Other Improvements - Source links can be shown or hidden for each Sphinx plot directive - Figure hooks - New & Improved Narrative Documentation - Brand new :doc:`Animations ` tutorial. - New grouped and stacked `bar chart <../../gallery/index.html#lines_bars_and_markers>`_ examples. - New section for new contributors and reorganized git instructions in the :ref:`contributing guide`. - Restructured :doc:`/tutorials/text/annotations` tutorial.