From 436c943778ce342c89665dbaeb56033a35ec9402 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 13 Dec 2024 23:39:18 -0600 Subject: [PATCH 01/73] Update zenodo fo v3.10.0 --- doc/_static/zenodo_cache/14464227.svg | 35 +++++++++++++++++++++++++++ doc/project/citing.rst | 3 +++ tools/cache_zenodo_svg.py | 1 + 3 files changed, 39 insertions(+) create mode 100644 doc/_static/zenodo_cache/14464227.svg diff --git a/doc/_static/zenodo_cache/14464227.svg b/doc/_static/zenodo_cache/14464227.svg new file mode 100644 index 000000000000..7126d239d6a5 --- /dev/null +++ b/doc/_static/zenodo_cache/14464227.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + DOI + + + DOI + + + 10.5281/zenodo.14464227 + + + 10.5281/zenodo.14464227 + + + \ No newline at end of file diff --git a/doc/project/citing.rst b/doc/project/citing.rst index be58473a26e4..2cd317906bb5 100644 --- a/doc/project/citing.rst +++ b/doc/project/citing.rst @@ -32,6 +32,9 @@ By version .. START OF AUTOGENERATED +v3.10.0 + .. image:: ../_static/zenodo_cache/14464227.svg + :target: https://doi.org/10.5281/zenodo.14464227 v3.9.4 .. image:: ../_static/zenodo_cache/14436121.svg :target: https://doi.org/10.5281/zenodo.14436121 diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py index 6e31c2a70011..3be7d6ca21e4 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.10.0": "14464227", "v3.9.4": "14436121", "v3.9.3": "14249941", "v3.9.2": "13308876", From 63d01499896f2205d1636a2502469775be9feb5f Mon Sep 17 00:00:00 2001 From: saikarna913 Date: Sat, 14 Dec 2024 13:52:09 +0530 Subject: [PATCH 02/73] Backport PR #29292: Update dependencies.rst --- doc/install/dependencies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/dependencies.rst b/doc/install/dependencies.rst index b8f54f346186..3034a64a3361 100644 --- a/doc/install/dependencies.rst +++ b/doc/install/dependencies.rst @@ -256,7 +256,7 @@ source files. .. tab-item:: Linux On some Linux systems, you can install a meta-build package. For example, - on Ubuntu ``apt install build-essential`` + on Ubuntu ``apt install build-essential`` with elevated privileges. Otherwise, use the system distribution's package manager to install :ref:`gcc `. From 5c590cb73d4e820cfd0dcae5ccd7ee856e78b460 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 14 Dec 2024 20:20:58 +0100 Subject: [PATCH 03/73] Backport PR #29314: DOC: fix footnote in choosing colormaps guide --- galleries/users_explain/colors/colormaps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/galleries/users_explain/colors/colormaps.py b/galleries/users_explain/colors/colormaps.py index ff146cacf170..026ffc9922e2 100644 --- a/galleries/users_explain/colors/colormaps.py +++ b/galleries/users_explain/colors/colormaps.py @@ -178,7 +178,7 @@ def plot_color_gradients(category, cmap_list): # # Berlin, Managua, and Vanimo are dark-mode diverging colormaps, with minimum # lightness at the center, and maximum at the extremes. These are taken from -# F. Crameri's [scientific colour maps]_ version 8.0.1. +# F. Crameri's [scientific-colour-maps]_ version 8.0.1. plot_color_gradients('Diverging', ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu', @@ -446,4 +446,4 @@ def plot_color_gradients(cmap_category, cmap_list): # .. [colorblindness] http://www.color-blindness.com/ # .. [IBM] https://doi.org/10.1109/VISUAL.1995.480803 # .. [turbo] https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html -# .. [scientific colour maps] https://doi.org/10.5281/zenodo.1243862 +# .. [scientific-colour-maps] https://doi.org/10.5281/zenodo.1243862 From 35f47f72415d2cd211fdf19fab5e7910632b7ee6 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 16 Dec 2024 18:52:04 -0500 Subject: [PATCH 04/73] Backport PR #29321: DOC: List min. Python version for Matplotlib 3.10 --- doc/devel/min_dep_policy.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/devel/min_dep_policy.rst b/doc/devel/min_dep_policy.rst index 6ff083ca6dc1..e9e18ed391dc 100644 --- a/doc/devel/min_dep_policy.rst +++ b/doc/devel/min_dep_policy.rst @@ -115,6 +115,7 @@ specification of the dependencies. ========== ======== ====== Matplotlib Python NumPy ========== ======== ====== +`3.10`_ 3.10 1.23.0 `3.9`_ 3.9 1.23.0 `3.8`_ 3.9 1.21.0 `3.7`_ 3.8 1.20.0 @@ -136,6 +137,7 @@ Matplotlib Python NumPy 1.0 2.4 1.1 ========== ======== ====== +.. _`3.10`: https://matplotlib.org/3.10.0/devel/dependencies.html .. _`3.9`: https://matplotlib.org/3.9.0/devel/dependencies.html .. _`3.8`: https://matplotlib.org/3.8.0/devel/dependencies.html .. _`3.7`: https://matplotlib.org/3.7.0/devel/dependencies.html From 0545b012fbb9407372f4f7e1eb26a6919a1eed04 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 19 Dec 2024 17:02:52 -0500 Subject: [PATCH 05/73] Backport PR #29348: DOC: Cleanup scales examples --- galleries/examples/scales/asinh_demo.py | 6 ++--- galleries/examples/scales/log_bar.py | 29 ------------------------- galleries/examples/scales/logit_demo.py | 6 ++--- galleries/examples/scales/scales.py | 6 ++--- 4 files changed, 9 insertions(+), 38 deletions(-) delete mode 100644 galleries/examples/scales/log_bar.py diff --git a/galleries/examples/scales/asinh_demo.py b/galleries/examples/scales/asinh_demo.py index a464d4546ea8..bc8b010c47ce 100644 --- a/galleries/examples/scales/asinh_demo.py +++ b/galleries/examples/scales/asinh_demo.py @@ -1,7 +1,7 @@ """ -============ -Asinh Demo -============ +=========== +Asinh scale +=========== Illustration of the `asinh <.scale.AsinhScale>` axis scaling, which uses the transformation diff --git a/galleries/examples/scales/log_bar.py b/galleries/examples/scales/log_bar.py deleted file mode 100644 index 239069806c5c..000000000000 --- a/galleries/examples/scales/log_bar.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -======= -Log Bar -======= - -Plotting a bar chart with a logarithmic y-axis. -""" -import matplotlib.pyplot as plt -import numpy as np - -data = ((3, 1000), (10, 3), (100, 30), (500, 800), (50, 1)) - -dim = len(data[0]) -w = 0.75 -dimw = w / dim - -fig, ax = plt.subplots() -x = np.arange(len(data)) -for i in range(len(data[0])): - y = [d[i] for d in data] - b = ax.bar(x + i * dimw, y, dimw, bottom=0.001) - -ax.set_xticks(x + dimw / 2, labels=map(str, x)) -ax.set_yscale('log') - -ax.set_xlabel('x') -ax.set_ylabel('y') - -plt.show() diff --git a/galleries/examples/scales/logit_demo.py b/galleries/examples/scales/logit_demo.py index a21abf5b64fb..22a56433ccd7 100644 --- a/galleries/examples/scales/logit_demo.py +++ b/galleries/examples/scales/logit_demo.py @@ -1,7 +1,7 @@ """ -================ -Logit Demo -================ +=========== +Logit scale +=========== Examples of plots with logit axes. """ diff --git a/galleries/examples/scales/scales.py b/galleries/examples/scales/scales.py index 8df4d2fdd4a9..e932609bb7f9 100644 --- a/galleries/examples/scales/scales.py +++ b/galleries/examples/scales/scales.py @@ -1,7 +1,7 @@ """ -====== -Scales -====== +=============== +Scales overview +=============== Illustrate the scale transformations applied to axes, e.g. log, symlog, logit. From 2581353927aa9a0684f04cfcd1bcc997bd667079 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 21 Dec 2024 08:03:54 +0100 Subject: [PATCH 06/73] Backport PR #29347: DOC: Explain parameters linthresh and linscale of symlog scale --- galleries/examples/scales/symlog_demo.py | 89 ++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/galleries/examples/scales/symlog_demo.py b/galleries/examples/scales/symlog_demo.py index e50be0d0c8a8..47742b853cc9 100644 --- a/galleries/examples/scales/symlog_demo.py +++ b/galleries/examples/scales/symlog_demo.py @@ -1,7 +1,12 @@ """ -=========== -Symlog Demo -=========== +============ +Symlog scale +============ + +The symmetric logarithmic scale is an extension of the logarithmic scale that +also covers negative values. As with the logarithmic scale, it is particularly +useful for numerical data that spans a broad range of values, especially when there +are significant differences between the magnitudes of the numbers involved. Example use of symlog (symmetric log) axis scaling. """ @@ -34,12 +39,82 @@ plt.show() # %% -# It should be noted that the coordinate transform used by ``symlog`` -# has a discontinuous gradient at the transition between its linear -# and logarithmic regions. The ``asinh`` axis scale is an alternative -# technique that may avoid visual artifacts caused by these discontinuities. +# Linear threshold +# ---------------- +# Since each decade on a logarithmic scale covers the same amount of visual space +# and there are infinitely many decades between a given number and zero, the symlog +# scale must deviate from logarithmic mapping in a small range +# *(-linthresh, linthresh)*, so that the range is mapped to a finite visual space. + + +def format_axes(ax, title=None): + """A helper function to better visualize properties of the symlog scale.""" + ax.xaxis.get_minor_locator().set_params(subs=[2, 3, 4, 5, 6, 7, 8, 9]) + ax.grid() + ax.xaxis.grid(which='minor') # minor grid on too + linthresh = ax.xaxis.get_transform().linthresh + linscale = ax.xaxis.get_transform().linscale + ax.axvspan(-linthresh, linthresh, color='0.9') + if title: + ax.set_title(title.format(linthresh=linthresh, linscale=linscale)) + + +x = np.linspace(-60, 60, 201) +y = np.linspace(0, 100.0, 201) + +fig, (ax1, ax2) = plt.subplots(nrows=2, layout="constrained") + +ax1.plot(x, y) +ax1.set_xscale('symlog', linthresh=1) +format_axes(ax1, title='Linear region: linthresh={linthresh}') + +ax2.plot(x, y) +ax2.set_xscale('symlog', linthresh=5) +format_axes(ax2, title='Linear region: linthresh={linthresh}') + +# %% +# Generally, *linthresh* should be chosen so that no or only a few +# data points are in the linear region. As a rule of thumb, +# :math:`linthresh \approx \mathrm{min} |x|`. +# +# +# Linear scale +# ------------ +# Additionally, the *linscale* parameter determines how much visual space should be +# used for the linear range. More precisely, it defines the ratio of visual space +# of the region (0, linthresh) relative to one decade. + +fig, (ax1, ax2) = plt.subplots(nrows=2, layout="constrained") + +ax1.plot(x, y) +ax1.set_xscale('symlog', linthresh=1) +format_axes(ax1, title='Linear region: linthresh={linthresh}, linscale={linscale}') + +ax2.plot(x, y) +ax2.set_xscale('symlog', linthresh=1, linscale=0.1) +format_axes(ax2, title='Linear region: linthresh={linthresh}, linscale={linscale}') # %% +# The suitable value for linscale depends on the dynamic range of data. As most data +# will be outside the linear region, you typically the linear region only to cover +# a small fraction of the visual area. +# +# Limitations and alternatives +# ---------------------------- +# The coordinate transform used by ``symlog`` has a discontinuous gradient at the +# transition between its linear and logarithmic regions. Depending on data and +# scaling, this will be more or less obvious in the plot. + +fig, ax = plt.subplots() +ax.plot(x, y) +ax.set_xscale('symlog', linscale=0.05) +format_axes(ax, title="Discontinuous gradient at linear/log transition") + +# %% +# The ``asinh`` axis scale is an alternative transformation that supports a wide +# dynamic range with a smooth gradient and thus may avoid such visual artifacts. +# See :doc:`/gallery/scales/asinh_demo`. +# # # .. admonition:: References # From f9e3c747fd658fbd0e878aeec20c3f68aef66039 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh <14363975+scottshambaugh@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:42:57 -0700 Subject: [PATCH 07/73] Backport PR #29382: Fix title position for polar plots --- lib/matplotlib/axes/_base.py | 5 ++--- .../test_polar/polar_title_position.png | Bin 0 -> 47252 bytes lib/matplotlib/tests/test_polar.py | 7 +++++++ 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_polar/polar_title_position.png diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 4c5b18e9e843..2ff37d96021a 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3071,9 +3071,8 @@ def _update_title_position(self, renderer): top = -np.inf for ax in axs: bb = None - xticklabel_top = any(tick.label2.get_visible() for tick in - [ax.xaxis.majorTicks[0], ax.xaxis.minorTicks[0]]) - if (xticklabel_top or ax.xaxis.get_label_position() == 'top'): + if (ax.xaxis.get_ticks_position() in ['top', 'unknown'] or + ax.xaxis.get_label_position() == 'top'): bb = ax.xaxis.get_tightbbox(renderer) if bb is None: # Extent of the outline for colorbars, of the axes otherwise. diff --git a/lib/matplotlib/tests/baseline_images/test_polar/polar_title_position.png b/lib/matplotlib/tests/baseline_images/test_polar/polar_title_position.png new file mode 100644 index 0000000000000000000000000000000000000000..4a8786b1f892cc313a43158b1e115ada0a7b3323 GIT binary patch literal 47252 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.OAPP(AwaD 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 Date: Mon, 6 Jan 2025 19:46:35 +0100 Subject: [PATCH 08/73] Backport PR #29409: Fixed test case(test_axes.py) failing on ppc64le --- lib/matplotlib/tests/test_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 618e8462c340..575945cf5ff4 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -9085,7 +9085,7 @@ def test_zorder_and_explicit_rasterization(): @image_comparison(["preset_clip_paths.png"], remove_text=True, style="mpl20", - tol=0.027 if platform.machine() == "arm64" else 0) + tol=0.027 if platform.machine() in ("arm64", "ppc64le") else 0) def test_preset_clip_paths(): fig, ax = plt.subplots() From 05ebb73208e7f948fe8691fa867a9997fd412e4e Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 7 Jan 2025 00:05:20 -0500 Subject: [PATCH 09/73] Backport PR #29406: DOC: Update scales overview --- doc/sphinxext/gallery_order.py | 2 + galleries/examples/scales/scales.py | 100 ++++++++-------------------- 2 files changed, 31 insertions(+), 71 deletions(-) diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py index 378cb394d37b..99b90062a42a 100644 --- a/doc/sphinxext/gallery_order.py +++ b/doc/sphinxext/gallery_order.py @@ -86,6 +86,8 @@ def __call__(self, item): "color_demo", # pies "pie_features", "pie_demo2", + # scales + "scales", # Scales overview # **Plot Types # Basic diff --git a/galleries/examples/scales/scales.py b/galleries/examples/scales/scales.py index e932609bb7f9..6c4556c9c1d3 100644 --- a/galleries/examples/scales/scales.py +++ b/galleries/examples/scales/scales.py @@ -5,56 +5,42 @@ Illustrate the scale transformations applied to axes, e.g. log, symlog, logit. -The last two examples are examples of using the ``'function'`` scale by -supplying forward and inverse functions for the scale transformation. +See `matplotlib.scale` for a full list of built-in scales, and +:doc:`/gallery/scales/custom_scale` for how to create your own scale. """ import matplotlib.pyplot as plt import numpy as np -from matplotlib.ticker import FixedLocator, NullFormatter +x = np.arange(400) +y = np.linspace(0.002, 1, 400) -# Fixing random state for reproducibility -np.random.seed(19680801) - -# make up some data in the interval ]0, 1[ -y = np.random.normal(loc=0.5, scale=0.4, size=1000) -y = y[(y > 0) & (y < 1)] -y.sort() -x = np.arange(len(y)) - -# plot with various axes scales fig, axs = plt.subplots(3, 2, figsize=(6, 8), layout='constrained') -# linear -ax = axs[0, 0] -ax.plot(x, y) -ax.set_yscale('linear') -ax.set_title('linear') -ax.grid(True) - +axs[0, 0].plot(x, y) +axs[0, 0].set_yscale('linear') +axs[0, 0].set_title('linear') +axs[0, 0].grid(True) -# log -ax = axs[0, 1] -ax.plot(x, y) -ax.set_yscale('log') -ax.set_title('log') -ax.grid(True) +axs[0, 1].plot(x, y) +axs[0, 1].set_yscale('log') +axs[0, 1].set_title('log') +axs[0, 1].grid(True) +axs[1, 0].plot(x, y - y.mean()) +axs[1, 0].set_yscale('symlog', linthresh=0.02) +axs[1, 0].set_title('symlog') +axs[1, 0].grid(True) -# symmetric log -ax = axs[1, 1] -ax.plot(x, y - y.mean()) -ax.set_yscale('symlog', linthresh=0.02) -ax.set_title('symlog') -ax.grid(True) +axs[1, 1].plot(x, y) +axs[1, 1].set_yscale('logit') +axs[1, 1].set_title('logit') +axs[1, 1].grid(True) -# logit -ax = axs[1, 0] -ax.plot(x, y) -ax.set_yscale('logit') -ax.set_title('logit') -ax.grid(True) +axs[2, 0].plot(x, y - y.mean()) +axs[2, 0].set_yscale('asinh', linear_width=0.01) +axs[2, 0].set_title('asinh') +axs[2, 0].grid(True) # Function x**(1/2) @@ -66,38 +52,11 @@ def inverse(x): return x**2 -ax = axs[2, 0] -ax.plot(x, y) -ax.set_yscale('function', functions=(forward, inverse)) -ax.set_title('function: $x^{1/2}$') -ax.grid(True) -ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 1, 0.2)**2)) -ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 1, 0.2))) - - -# Function Mercator transform -def forward(a): - a = np.deg2rad(a) - return np.rad2deg(np.log(np.abs(np.tan(a) + 1.0 / np.cos(a)))) - - -def inverse(a): - a = np.deg2rad(a) - return np.rad2deg(np.arctan(np.sinh(a))) - -ax = axs[2, 1] - -t = np.arange(0, 170.0, 0.1) -s = t / 2. - -ax.plot(t, s, '-', lw=2) - -ax.set_yscale('function', functions=(forward, inverse)) -ax.set_title('function: Mercator') -ax.grid(True) -ax.set_xlim([0, 180]) -ax.yaxis.set_minor_formatter(NullFormatter()) -ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 90, 10))) +axs[2, 1].plot(x, y) +axs[2, 1].set_yscale('function', functions=(forward, inverse)) +axs[2, 1].set_title('function: $x^{1/2}$') +axs[2, 1].grid(True) +axs[2, 1].set_yticks(np.arange(0, 1.2, 0.2)) plt.show() @@ -110,7 +69,6 @@ def inverse(a): # # - `matplotlib.axes.Axes.set_xscale` # - `matplotlib.axes.Axes.set_yscale` -# - `matplotlib.axis.Axis.set_major_locator` # - `matplotlib.scale.LinearScale` # - `matplotlib.scale.LogScale` # - `matplotlib.scale.SymmetricalLogScale` From 2bfd3eed48908205f5268bdee2fdffaa44b8fbf1 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 7 Jan 2025 00:05:20 -0500 Subject: [PATCH 10/73] Backport PR #29406: DOC: Update scales overview --- doc/sphinxext/gallery_order.py | 2 + galleries/examples/scales/scales.py | 100 ++++++++-------------------- 2 files changed, 31 insertions(+), 71 deletions(-) diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py index 378cb394d37b..99b90062a42a 100644 --- a/doc/sphinxext/gallery_order.py +++ b/doc/sphinxext/gallery_order.py @@ -86,6 +86,8 @@ def __call__(self, item): "color_demo", # pies "pie_features", "pie_demo2", + # scales + "scales", # Scales overview # **Plot Types # Basic diff --git a/galleries/examples/scales/scales.py b/galleries/examples/scales/scales.py index e932609bb7f9..6c4556c9c1d3 100644 --- a/galleries/examples/scales/scales.py +++ b/galleries/examples/scales/scales.py @@ -5,56 +5,42 @@ Illustrate the scale transformations applied to axes, e.g. log, symlog, logit. -The last two examples are examples of using the ``'function'`` scale by -supplying forward and inverse functions for the scale transformation. +See `matplotlib.scale` for a full list of built-in scales, and +:doc:`/gallery/scales/custom_scale` for how to create your own scale. """ import matplotlib.pyplot as plt import numpy as np -from matplotlib.ticker import FixedLocator, NullFormatter +x = np.arange(400) +y = np.linspace(0.002, 1, 400) -# Fixing random state for reproducibility -np.random.seed(19680801) - -# make up some data in the interval ]0, 1[ -y = np.random.normal(loc=0.5, scale=0.4, size=1000) -y = y[(y > 0) & (y < 1)] -y.sort() -x = np.arange(len(y)) - -# plot with various axes scales fig, axs = plt.subplots(3, 2, figsize=(6, 8), layout='constrained') -# linear -ax = axs[0, 0] -ax.plot(x, y) -ax.set_yscale('linear') -ax.set_title('linear') -ax.grid(True) - +axs[0, 0].plot(x, y) +axs[0, 0].set_yscale('linear') +axs[0, 0].set_title('linear') +axs[0, 0].grid(True) -# log -ax = axs[0, 1] -ax.plot(x, y) -ax.set_yscale('log') -ax.set_title('log') -ax.grid(True) +axs[0, 1].plot(x, y) +axs[0, 1].set_yscale('log') +axs[0, 1].set_title('log') +axs[0, 1].grid(True) +axs[1, 0].plot(x, y - y.mean()) +axs[1, 0].set_yscale('symlog', linthresh=0.02) +axs[1, 0].set_title('symlog') +axs[1, 0].grid(True) -# symmetric log -ax = axs[1, 1] -ax.plot(x, y - y.mean()) -ax.set_yscale('symlog', linthresh=0.02) -ax.set_title('symlog') -ax.grid(True) +axs[1, 1].plot(x, y) +axs[1, 1].set_yscale('logit') +axs[1, 1].set_title('logit') +axs[1, 1].grid(True) -# logit -ax = axs[1, 0] -ax.plot(x, y) -ax.set_yscale('logit') -ax.set_title('logit') -ax.grid(True) +axs[2, 0].plot(x, y - y.mean()) +axs[2, 0].set_yscale('asinh', linear_width=0.01) +axs[2, 0].set_title('asinh') +axs[2, 0].grid(True) # Function x**(1/2) @@ -66,38 +52,11 @@ def inverse(x): return x**2 -ax = axs[2, 0] -ax.plot(x, y) -ax.set_yscale('function', functions=(forward, inverse)) -ax.set_title('function: $x^{1/2}$') -ax.grid(True) -ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 1, 0.2)**2)) -ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 1, 0.2))) - - -# Function Mercator transform -def forward(a): - a = np.deg2rad(a) - return np.rad2deg(np.log(np.abs(np.tan(a) + 1.0 / np.cos(a)))) - - -def inverse(a): - a = np.deg2rad(a) - return np.rad2deg(np.arctan(np.sinh(a))) - -ax = axs[2, 1] - -t = np.arange(0, 170.0, 0.1) -s = t / 2. - -ax.plot(t, s, '-', lw=2) - -ax.set_yscale('function', functions=(forward, inverse)) -ax.set_title('function: Mercator') -ax.grid(True) -ax.set_xlim([0, 180]) -ax.yaxis.set_minor_formatter(NullFormatter()) -ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 90, 10))) +axs[2, 1].plot(x, y) +axs[2, 1].set_yscale('function', functions=(forward, inverse)) +axs[2, 1].set_title('function: $x^{1/2}$') +axs[2, 1].grid(True) +axs[2, 1].set_yticks(np.arange(0, 1.2, 0.2)) plt.show() @@ -110,7 +69,6 @@ def inverse(a): # # - `matplotlib.axes.Axes.set_xscale` # - `matplotlib.axes.Axes.set_yscale` -# - `matplotlib.axis.Axis.set_major_locator` # - `matplotlib.scale.LinearScale` # - `matplotlib.scale.LogScale` # - `matplotlib.scale.SymmetricalLogScale` From 5357f0d2a87eef8cabd9b6965b6c2d2ca34030fa Mon Sep 17 00:00:00 2001 From: "Nathan G. Wiseman" <55075327+NGWi@users.noreply.github.com> Date: Fri, 3 Jan 2025 09:34:38 -0500 Subject: [PATCH 11/73] Backport PR #29130: Raise warning if both c and facecolors are used in scatter plot (... and related improvements in the test suite). --- lib/matplotlib/axes/_axes.py | 8 ++++ lib/matplotlib/tests/test_axes.py | 61 ++++++++++++++++++++++++++--- lib/matplotlib/tests/test_legend.py | 5 +-- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 87e9401bb294..bf4e0b031b59 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4675,6 +4675,14 @@ def _parse_scatter_color_args(c, edgecolors, kwargs, xsize, if edgecolors is None and not mpl.rcParams['_internal.classic_mode']: edgecolors = mpl.rcParams['scatter.edgecolors'] + # Raise a warning if both `c` and `facecolor` are set (issue #24404). + if c is not None and facecolors is not None: + _api.warn_external( + "You passed both c and facecolor/facecolors for the markers. " + "c has precedence over facecolor/facecolors. " + "This behavior may change in the future." + ) + c_was_none = c is None if c is None: c = (facecolors if facecolors is not None diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 575945cf5ff4..991e8689a360 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2942,7 +2942,7 @@ def test_scatter_different_shapes(self, fig_test, fig_ref): @pytest.mark.parametrize('c_case, re_key', params_test_scatter_c) def test_scatter_c(self, c_case, re_key): - def get_next_color(): + def get_next_color(): # pragma: no cover return 'blue' # currently unused xsize = 4 @@ -3036,7 +3036,7 @@ def _params(c=None, xsize=2, *, edgecolors=None, **kwargs): _result(c=['b', 'g'], colors=np.array([[0, 0, 1, 1], [0, .5, 0, 1]]))), ]) def test_parse_scatter_color_args(params, expected_result): - def get_next_color(): + def get_next_color(): # pragma: no cover return 'blue' # currently unused c, colors, _edgecolors = mpl.axes.Axes._parse_scatter_color_args( @@ -3063,7 +3063,7 @@ def get_next_color(): (dict(color='r', edgecolor='g'), 'g'), ]) def test_parse_scatter_color_args_edgecolors(kwargs, expected_edgecolors): - def get_next_color(): + def get_next_color(): # pragma: no cover return 'blue' # currently unused c = kwargs.pop('c', None) @@ -3075,7 +3075,7 @@ def get_next_color(): def test_parse_scatter_color_args_error(): - def get_next_color(): + def get_next_color(): # pragma: no cover return 'blue' # currently unused with pytest.raises(ValueError, @@ -3085,6 +3085,55 @@ def get_next_color(): c, None, kwargs={}, xsize=2, get_next_color_func=get_next_color) +# Warning message tested in the next two tests. +WARN_MSG = ( + "You passed both c and facecolor/facecolors for the markers. " + "c has precedence over facecolor/facecolors. This behavior may " + "change in the future." +) +# Test cases shared between direct and integration tests +COLOR_TEST_CASES = [ + ('red', 'blue'), + (['red', 'blue'], ['green', 'yellow']), + ([[1, 0, 0], [0, 1, 0]], [[0, 0, 1], [1, 1, 0]]) +] + + +@pytest.mark.parametrize('c, facecolor', COLOR_TEST_CASES) +def test_parse_c_facecolor_warning_direct(c, facecolor): + """Test the internal _parse_scatter_color_args method directly.""" + def get_next_color(): # pragma: no cover + return 'blue' # currently unused + + # Test with facecolors (plural) + with pytest.warns(UserWarning, match=WARN_MSG): + mpl.axes.Axes._parse_scatter_color_args( + c=c, edgecolors=None, kwargs={'facecolors': facecolor}, + xsize=2, get_next_color_func=get_next_color) + + # Test with facecolor (singular) + with pytest.warns(UserWarning, match=WARN_MSG): + mpl.axes.Axes._parse_scatter_color_args( + c=c, edgecolors=None, kwargs={'facecolor': facecolor}, + xsize=2, get_next_color_func=get_next_color) + + +@pytest.mark.parametrize('c, facecolor', COLOR_TEST_CASES) +def test_scatter_c_facecolor_warning_integration(c, facecolor): + """Test the warning through the actual scatter plot creation.""" + fig, ax = plt.subplots() + x = [0, 1] if isinstance(c, (list, tuple)) else [0] + y = x + + # Test with facecolors (plural) + with pytest.warns(UserWarning, match=WARN_MSG): + ax.scatter(x, y, c=c, facecolors=facecolor) + + # Test with facecolor (singular) + with pytest.warns(UserWarning, match=WARN_MSG): + ax.scatter(x, y, c=c, facecolor=facecolor) + + def test_as_mpl_axes_api(): # tests the _as_mpl_axes api class Polar: @@ -9064,8 +9113,8 @@ def test_child_axes_removal(): def test_scatter_color_repr_error(): - def get_next_color(): - return 'blue' # pragma: no cover + def get_next_color(): # pragma: no cover + return 'blue' # currently unused msg = ( r"'c' argument must be a color, a sequence of colors" r", or a sequence of numbers, not 'red\\n'" diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 67b10fb2a365..2d92db4008e4 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -970,13 +970,12 @@ def test_legend_pathcollection_labelcolor_markfacecolor_cmap(): # test the labelcolor for labelcolor='markerfacecolor' on PathCollection # with colormaps fig, ax = plt.subplots() - facecolors = mpl.cm.viridis(np.random.rand(10)) + colors = mpl.cm.viridis(np.random.rand(10)) ax.scatter( np.arange(10), np.arange(10), label='#1', - c=np.arange(10), - facecolor=facecolors + c=colors ) leg = ax.legend(labelcolor='markerfacecolor') From a639861103b94135d0b8911735c9cf13576bfd60 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 8 Jan 2025 10:18:57 +0100 Subject: [PATCH 12/73] Backport PR #29431: ft2font: Split named instance count from style flags --- galleries/examples/misc/ftface_props.py | 13 +++++++------ lib/matplotlib/ft2font.pyi | 2 ++ lib/matplotlib/tests/test_ft2font.py | 3 +++ src/ft2font_wrapper.cpp | 10 +++++++++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/galleries/examples/misc/ftface_props.py b/galleries/examples/misc/ftface_props.py index 8306e142c144..ec26dff5bf6a 100644 --- a/galleries/examples/misc/ftface_props.py +++ b/galleries/examples/misc/ftface_props.py @@ -18,12 +18,13 @@ os.path.join(matplotlib.get_data_path(), 'fonts/ttf/DejaVuSans-Oblique.ttf')) -print('Num faces: ', font.num_faces) # number of faces in file -print('Num glyphs: ', font.num_glyphs) # number of glyphs in the face -print('Family name:', font.family_name) # face family name -print('Style name: ', font.style_name) # face style name -print('PS name: ', font.postscript_name) # the postscript name -print('Num fixed: ', font.num_fixed_sizes) # number of embedded bitmaps +print('Num instances: ', font.num_named_instances) # number of named instances in file +print('Num faces: ', font.num_faces) # number of faces in file +print('Num glyphs: ', font.num_glyphs) # number of glyphs in the face +print('Family name: ', font.family_name) # face family name +print('Style name: ', font.style_name) # face style name +print('PS name: ', font.postscript_name) # the postscript name +print('Num fixed: ', font.num_fixed_sizes) # number of embedded bitmaps # the following are only available if face.scalable if font.scalable: diff --git a/lib/matplotlib/ft2font.pyi b/lib/matplotlib/ft2font.pyi index 811f82f95963..37281afeaafa 100644 --- a/lib/matplotlib/ft2font.pyi +++ b/lib/matplotlib/ft2font.pyi @@ -265,6 +265,8 @@ class FT2Font(Buffer): @property def num_glyphs(self) -> int: ... @property + def num_named_instances(self) -> int: ... + @property def postscript_name(self) -> str: ... @property def scalable(self) -> bool: ... diff --git a/lib/matplotlib/tests/test_ft2font.py b/lib/matplotlib/tests/test_ft2font.py index 7dc851b2c9cf..6ba23bab347e 100644 --- a/lib/matplotlib/tests/test_ft2font.py +++ b/lib/matplotlib/tests/test_ft2font.py @@ -40,6 +40,7 @@ def test_ft2font_dejavu_attrs(): assert font.family_name == 'DejaVu Sans' assert font.style_name == 'Book' assert font.num_faces == 1 # Single TTF. + assert font.num_named_instances == 0 # Not a variable font. assert font.num_glyphs == 6241 # From compact encoding view in FontForge. assert font.num_fixed_sizes == 0 # All glyphs are scalable. assert font.num_charmaps == 5 @@ -73,6 +74,7 @@ def test_ft2font_cm_attrs(): assert font.family_name == 'cmtt10' assert font.style_name == 'Regular' assert font.num_faces == 1 # Single TTF. + assert font.num_named_instances == 0 # Not a variable font. assert font.num_glyphs == 133 # From compact encoding view in FontForge. assert font.num_fixed_sizes == 0 # All glyphs are scalable. assert font.num_charmaps == 2 @@ -105,6 +107,7 @@ def test_ft2font_stix_bold_attrs(): assert font.family_name == 'STIXSizeTwoSym' assert font.style_name == 'Bold' assert font.num_faces == 1 # Single TTF. + assert font.num_named_instances == 0 # Not a variable font. assert font.num_glyphs == 20 # From compact encoding view in FontForge. assert font.num_fixed_sizes == 0 # All glyphs are scalable. assert font.num_charmaps == 3 diff --git a/src/ft2font_wrapper.cpp b/src/ft2font_wrapper.cpp index 7e1b3948a00e..9b54721810d6 100644 --- a/src/ft2font_wrapper.cpp +++ b/src/ft2font_wrapper.cpp @@ -1475,7 +1475,13 @@ PyFT2Font_face_flags(PyFT2Font *self) static StyleFlags PyFT2Font_style_flags(PyFT2Font *self) { - return static_cast(self->x->get_face()->style_flags); + return static_cast(self->x->get_face()->style_flags & 0xffff); +} + +static FT_Long +PyFT2Font_num_named_instances(PyFT2Font *self) +{ + return (self->x->get_face()->style_flags & 0x7fff0000) >> 16; } static FT_Long @@ -1766,6 +1772,8 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used()) "Face flags; see `.FaceFlags`.") .def_property_readonly("style_flags", &PyFT2Font_style_flags, "Style flags; see `.StyleFlags`.") + .def_property_readonly("num_named_instances", &PyFT2Font_num_named_instances, + "Number of named instances in the face.") .def_property_readonly("num_glyphs", &PyFT2Font_num_glyphs, "Number of glyphs in the face.") .def_property_readonly("num_fixed_sizes", &PyFT2Font_num_fixed_sizes, From 80309eecc2486df65aae00bd53dcf484b48d2b3a Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:41:13 +0100 Subject: [PATCH 13/73] Backport PR #29407: DOC: Improve log scale example --- galleries/examples/scales/log_demo.py | 94 +++++++++++++++------- galleries/examples/scales/semilogx_demo.py | 23 ------ 2 files changed, 65 insertions(+), 52 deletions(-) delete mode 100644 galleries/examples/scales/semilogx_demo.py diff --git a/galleries/examples/scales/log_demo.py b/galleries/examples/scales/log_demo.py index debbad258bc6..ce0c77551c0a 100644 --- a/galleries/examples/scales/log_demo.py +++ b/galleries/examples/scales/log_demo.py @@ -1,47 +1,83 @@ """ -======== -Log Demo -======== +========= +Log scale +========= Examples of plots with logarithmic axes. + +You can set the x/y axes to be logarithmic by passing "log" to `~.Axes.set_xscale` / +`~.Axes.set_yscale`. + +Convenience functions ``semilogx``, ``semilogy``, and ``loglog`` +---------------------------------------------------------------- +Since plotting data on semi-logarithmic or double-logarithmic scales is very common, +the functions `~.Axes.semilogx`, `~.Axes.semilogy`, and `~.Axes.loglog` are shortcuts +for setting the scale and plotting data; e.g. ``ax.semilogx(x, y)`` is equivalent to +``ax.set_xscale('log'); ax.plot(x, y)``. """ import matplotlib.pyplot as plt import numpy as np -# Data for plotting -t = np.arange(0.01, 20.0, 0.01) - -# Create figure -fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) - -# log y axis -ax1.semilogy(t, np.exp(-t / 5.0)) -ax1.set(title='semilogy') +fig, (ax1, ax2, ax3) = plt.subplots(1, 3, layout='constrained', figsize=(7, 7/3)) +# log x axis +t = np.arange(0.01, 10.0, 0.01) +ax1.semilogx(t, np.sin(2 * np.pi * t)) +ax1.set(title='semilogx') ax1.grid() +ax1.grid(which="minor", color="0.9") -# log x axis -ax2.semilogx(t, np.sin(2 * np.pi * t)) -ax2.set(title='semilogx') +# log y axis +x = np.arange(4) +ax2.semilogy(4*x, 10**x, 'o--') +ax2.set(title='semilogy') ax2.grid() +ax2.grid(which="minor", color="0.9") # log x and y axis -ax3.loglog(t, 20 * np.exp(-t / 10.0)) -ax3.set_xscale('log', base=2) -ax3.set(title='loglog base 2 on x') +x = np.array([1, 10, 100, 1000]) +ax3.loglog(x, 5 * x, 'o--') +ax3.set(title='loglog') ax3.grid() +ax3.grid(which="minor", color="0.9") + +# %% +# Logarithms with other bases +# --------------------------- +# By default, the log scale is to the base 10. One can change this via the *base* +# parameter. +fig, ax = plt.subplots() +ax.bar(["L1 cache", "L2 cache", "L3 cache", "RAM", "SSD"], + [32, 1_000, 32_000, 16_000_000, 512_000_000]) +ax.set_yscale('log', base=2) +ax.set_yticks([1, 2**10, 2**20, 2**30], labels=['kB', 'MB', 'GB', 'TB']) +ax.set_title("Typical memory sizes") +ax.yaxis.grid() + +# %% +# Dealing with negative values +# ---------------------------- +# Non-positive values cannot be displayed on a log scale. The scale has two options +# to handle these. Either mask the values so that they are ignored, or clip them +# to a small positive value. Which one is more suited depends on the type of the +# data and the visualization. +# +# The following example contains errorbars going negative. If we mask these values, +# the bar vanishes, which is not desirable. In contrast, clipping makes the value +# small positive (but well below the used scale) so that the error bar is drawn +# to the edge of the Axes. +x = np.linspace(0.0, 2.0, 10) +y = 10**x +yerr = 1.75 + 0.75*y -# With errorbars: clip non-positive values -# Use new data for plotting -x = 10.0**np.linspace(0.0, 2.0, 20) -y = x**2.0 +fig, (ax1, ax2) = plt.subplots(1, 2, layout="constrained", figsize=(6, 3)) +fig.suptitle("errorbars going negative") +ax1.set_yscale("log", nonpositive='mask') +ax1.set_title('nonpositive="mask"') +ax1.errorbar(x, y, yerr=yerr, fmt='o', capsize=5) -ax4.set_xscale("log", nonpositive='clip') -ax4.set_yscale("log", nonpositive='clip') -ax4.set(title='Errorbars go negative') -ax4.errorbar(x, y, xerr=0.1 * x, yerr=5.0 + 0.75 * y) -# ylim must be set after errorbar to allow errorbar to autoscale limits -ax4.set_ylim(bottom=0.1) +ax2.set_yscale("log", nonpositive='clip') +ax2.set_title('nonpositive="clip"') +ax2.errorbar(x, y, yerr=yerr, fmt='o', capsize=5) -fig.tight_layout() plt.show() diff --git a/galleries/examples/scales/semilogx_demo.py b/galleries/examples/scales/semilogx_demo.py deleted file mode 100644 index 00c708a03479..000000000000 --- a/galleries/examples/scales/semilogx_demo.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -======== -Log Axis -======== - -.. redirect-from:: /gallery/scales/log_test - -This is an example of assigning a log-scale for the x-axis using -`~.axes.Axes.semilogx`. -""" - -import matplotlib.pyplot as plt -import numpy as np - -fig, ax = plt.subplots() - -dt = 0.01 -t = np.arange(dt, 20.0, dt) - -ax.semilogx(t, np.exp(-t / 5.0)) -ax.grid() - -plt.show() From 873b2fa51fb138bde5c779a7facd5f83b8f4fc3f Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:41:13 +0100 Subject: [PATCH 14/73] Backport PR #29407: DOC: Improve log scale example --- galleries/examples/scales/log_demo.py | 94 +++++++++++++++------- galleries/examples/scales/semilogx_demo.py | 23 ------ 2 files changed, 65 insertions(+), 52 deletions(-) delete mode 100644 galleries/examples/scales/semilogx_demo.py diff --git a/galleries/examples/scales/log_demo.py b/galleries/examples/scales/log_demo.py index debbad258bc6..ce0c77551c0a 100644 --- a/galleries/examples/scales/log_demo.py +++ b/galleries/examples/scales/log_demo.py @@ -1,47 +1,83 @@ """ -======== -Log Demo -======== +========= +Log scale +========= Examples of plots with logarithmic axes. + +You can set the x/y axes to be logarithmic by passing "log" to `~.Axes.set_xscale` / +`~.Axes.set_yscale`. + +Convenience functions ``semilogx``, ``semilogy``, and ``loglog`` +---------------------------------------------------------------- +Since plotting data on semi-logarithmic or double-logarithmic scales is very common, +the functions `~.Axes.semilogx`, `~.Axes.semilogy`, and `~.Axes.loglog` are shortcuts +for setting the scale and plotting data; e.g. ``ax.semilogx(x, y)`` is equivalent to +``ax.set_xscale('log'); ax.plot(x, y)``. """ import matplotlib.pyplot as plt import numpy as np -# Data for plotting -t = np.arange(0.01, 20.0, 0.01) - -# Create figure -fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) - -# log y axis -ax1.semilogy(t, np.exp(-t / 5.0)) -ax1.set(title='semilogy') +fig, (ax1, ax2, ax3) = plt.subplots(1, 3, layout='constrained', figsize=(7, 7/3)) +# log x axis +t = np.arange(0.01, 10.0, 0.01) +ax1.semilogx(t, np.sin(2 * np.pi * t)) +ax1.set(title='semilogx') ax1.grid() +ax1.grid(which="minor", color="0.9") -# log x axis -ax2.semilogx(t, np.sin(2 * np.pi * t)) -ax2.set(title='semilogx') +# log y axis +x = np.arange(4) +ax2.semilogy(4*x, 10**x, 'o--') +ax2.set(title='semilogy') ax2.grid() +ax2.grid(which="minor", color="0.9") # log x and y axis -ax3.loglog(t, 20 * np.exp(-t / 10.0)) -ax3.set_xscale('log', base=2) -ax3.set(title='loglog base 2 on x') +x = np.array([1, 10, 100, 1000]) +ax3.loglog(x, 5 * x, 'o--') +ax3.set(title='loglog') ax3.grid() +ax3.grid(which="minor", color="0.9") + +# %% +# Logarithms with other bases +# --------------------------- +# By default, the log scale is to the base 10. One can change this via the *base* +# parameter. +fig, ax = plt.subplots() +ax.bar(["L1 cache", "L2 cache", "L3 cache", "RAM", "SSD"], + [32, 1_000, 32_000, 16_000_000, 512_000_000]) +ax.set_yscale('log', base=2) +ax.set_yticks([1, 2**10, 2**20, 2**30], labels=['kB', 'MB', 'GB', 'TB']) +ax.set_title("Typical memory sizes") +ax.yaxis.grid() + +# %% +# Dealing with negative values +# ---------------------------- +# Non-positive values cannot be displayed on a log scale. The scale has two options +# to handle these. Either mask the values so that they are ignored, or clip them +# to a small positive value. Which one is more suited depends on the type of the +# data and the visualization. +# +# The following example contains errorbars going negative. If we mask these values, +# the bar vanishes, which is not desirable. In contrast, clipping makes the value +# small positive (but well below the used scale) so that the error bar is drawn +# to the edge of the Axes. +x = np.linspace(0.0, 2.0, 10) +y = 10**x +yerr = 1.75 + 0.75*y -# With errorbars: clip non-positive values -# Use new data for plotting -x = 10.0**np.linspace(0.0, 2.0, 20) -y = x**2.0 +fig, (ax1, ax2) = plt.subplots(1, 2, layout="constrained", figsize=(6, 3)) +fig.suptitle("errorbars going negative") +ax1.set_yscale("log", nonpositive='mask') +ax1.set_title('nonpositive="mask"') +ax1.errorbar(x, y, yerr=yerr, fmt='o', capsize=5) -ax4.set_xscale("log", nonpositive='clip') -ax4.set_yscale("log", nonpositive='clip') -ax4.set(title='Errorbars go negative') -ax4.errorbar(x, y, xerr=0.1 * x, yerr=5.0 + 0.75 * y) -# ylim must be set after errorbar to allow errorbar to autoscale limits -ax4.set_ylim(bottom=0.1) +ax2.set_yscale("log", nonpositive='clip') +ax2.set_title('nonpositive="clip"') +ax2.errorbar(x, y, yerr=yerr, fmt='o', capsize=5) -fig.tight_layout() plt.show() diff --git a/galleries/examples/scales/semilogx_demo.py b/galleries/examples/scales/semilogx_demo.py deleted file mode 100644 index 00c708a03479..000000000000 --- a/galleries/examples/scales/semilogx_demo.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -======== -Log Axis -======== - -.. redirect-from:: /gallery/scales/log_test - -This is an example of assigning a log-scale for the x-axis using -`~.axes.Axes.semilogx`. -""" - -import matplotlib.pyplot as plt -import numpy as np - -fig, ax = plt.subplots() - -dt = 0.01 -t = np.arange(dt, 20.0, dt) - -ax.semilogx(t, np.exp(-t / 5.0)) -ax.grid() - -plt.show() From c72371172bab55aba70e0334a4360ea11b91a166 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 9 Jan 2025 15:22:21 -0500 Subject: [PATCH 15/73] Backport PR #29442: DOC: put section headings in 3.10 whats new --- doc/users/prev_whats_new/whats_new_3.10.0.rst | 223 ++++++++++-------- 1 file changed, 130 insertions(+), 93 deletions(-) diff --git a/doc/users/prev_whats_new/whats_new_3.10.0.rst b/doc/users/prev_whats_new/whats_new_3.10.0.rst index bc160787aebc..2a6e55f7c3cb 100644 --- a/doc/users/prev_whats_new/whats_new_3.10.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.10.0.rst @@ -1,3 +1,20 @@ +============================================= +What's new in Matplotlib 3.10.0 (Dec 14, 2024) +============================================= + +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 + +Accessible Colors +================= + + New more-accessible color cycle ------------------------------- @@ -43,6 +60,12 @@ colour maps version 8.0.1 (DOI: https://doi.org/10.5281/zenodo.1243862). ax[1].imshow(img, cmap=plt.cm.managua) ax[2].imshow(img, cmap=plt.cm.vanimo) + + +Plotting and Annotation improvements +==================================== + + Specifying a single color in ``contour`` and ``contourf`` --------------------------------------------------------- @@ -65,66 +88,6 @@ may be passed. plt.show() -Exception handling control --------------------------- - -The exception raised when an invalid keyword parameter is passed now includes -that parameter name as the exception's ``name`` property. This provides more -control for exception handling: - - -.. code-block:: python - - import matplotlib.pyplot as plt - - def wobbly_plot(args, **kwargs): - w = kwargs.pop('wobble_factor', None) - - try: - plt.plot(args, **kwargs) - except AttributeError as e: - raise AttributeError(f'wobbly_plot does not take parameter {e.name}') from e - - - wobbly_plot([0, 1], wibble_factor=5) - -.. code-block:: - - AttributeError: wobbly_plot does not take parameter wibble_factor - -Preliminary support for free-threaded CPython 3.13 --------------------------------------------------- - -Matplotlib 3.10 has preliminary support for the free-threaded build of CPython 3.13. See -https://py-free-threading.github.io, `PEP 703 `_ and -the `CPython 3.13 release notes -`_ for more detail -about free-threaded Python. - -Support for free-threaded Python does not mean that Matplotlib is wholly thread safe. We -expect that use of a Figure within a single thread will work, and though input data is -usually copied, modification of data objects used for a plot from another thread may -cause inconsistencies in cases where it is not. Use of any global state (such as the -``pyplot`` module) is highly discouraged and unlikely to work consistently. Also note -that most GUI toolkits expect to run on the main thread, so interactive usage may be -limited or unsupported from other threads. - -If you are interested in free-threaded Python, for example because you have a -multiprocessing-based workflow that you are interested in running with Python threads, we -encourage testing and experimentation. If you run into problems that you suspect are -because of Matplotlib, please open an issue, checking first if the bug also occurs in the -“regular” non-free-threaded CPython 3.13 build. - -Increased Figure limits with Agg renderer ------------------------------------------ - -Figures using the Agg renderer are now limited to 2**23 pixels in each -direction, instead of 2**16. Additionally, bugs that caused artists to not -render past 2**15 pixels horizontally have been fixed. - -Note that if you are using a GUI backend, it may have its own smaller limits -(which may themselves depend on screen size.) - Vectorized ``hist`` style parameters ------------------------------------ @@ -259,39 +222,6 @@ Subfigures are now added in row-major order ax.set_yticks([]) plt.show() -``svg.id`` rcParam ------------------- - -:rc:`svg.id` lets you insert an ``id`` attribute into the top-level ```` tag. - -e.g. ``rcParams["svg.id"] = "svg1"`` results in -default), no ``id`` tag is included - -.. code-block:: XML - - - -This is useful if you would like to link the entire matplotlib SVG file within -another SVG file with the ```` tag. - -.. code-block:: XML - - - - -Where the ``#svg1`` indicator will now refer to the top level ```` tag, and -will hence result in the inclusion of the entire file. ``boxplot`` and ``bxp`` orientation parameter --------------------------------------------- @@ -361,6 +291,11 @@ the ``set_data`` method, enabling e.g. resampling coll.set_data(t, -t**4, t**4) fig.savefig("after.png") + +3D plotting improvements +======================== + + Fill between 3D lines --------------------- @@ -471,6 +406,108 @@ view box is a limitation of the current renderer. ax.legend(['axlim_clip=False (default)', 'axlim_clip=True']) +Preliminary support for free-threaded CPython 3.13 +================================================== + +Matplotlib 3.10 has preliminary support for the free-threaded build of CPython 3.13. See +https://py-free-threading.github.io, `PEP 703 `_ and +the `CPython 3.13 release notes +`_ for more detail +about free-threaded Python. + +Support for free-threaded Python does not mean that Matplotlib is wholly thread safe. We +expect that use of a Figure within a single thread will work, and though input data is +usually copied, modification of data objects used for a plot from another thread may +cause inconsistencies in cases where it is not. Use of any global state (such as the +``pyplot`` module) is highly discouraged and unlikely to work consistently. Also note +that most GUI toolkits expect to run on the main thread, so interactive usage may be +limited or unsupported from other threads. + +If you are interested in free-threaded Python, for example because you have a +multiprocessing-based workflow that you are interested in running with Python threads, we +encourage testing and experimentation. If you run into problems that you suspect are +because of Matplotlib, please open an issue, checking first if the bug also occurs in the +“regular” non-free-threaded CPython 3.13 build. + + + +Other Improvements +================== + +``svg.id`` rcParam +------------------ + +:rc:`svg.id` lets you insert an ``id`` attribute into the top-level ```` tag. + +e.g. ``rcParams["svg.id"] = "svg1"`` results in + +.. code-block:: XML + + + +This is useful if you would like to link the entire matplotlib SVG file within +another SVG file with the ```` tag. + +.. code-block:: XML + + + + +Where the ``#svg1`` indicator will now refer to the top level ```` tag, and +will hence result in the inclusion of the entire file. + +By default, no ``id`` tag is included. + +Exception handling control +-------------------------- + +The exception raised when an invalid keyword parameter is passed now includes +that parameter name as the exception's ``name`` property. This provides more +control for exception handling: + + +.. code-block:: python + + import matplotlib.pyplot as plt + + def wobbly_plot(args, **kwargs): + w = kwargs.pop('wobble_factor', None) + + try: + plt.plot(args, **kwargs) + except AttributeError as e: + raise AttributeError(f'wobbly_plot does not take parameter {e.name}') from e + + + wobbly_plot([0, 1], wibble_factor=5) + +.. code-block:: + + AttributeError: wobbly_plot does not take parameter wibble_factor + +Increased Figure limits with Agg renderer +----------------------------------------- + +Figures using the Agg renderer are now limited to 2**23 pixels in each +direction, instead of 2**16. Additionally, bugs that caused artists to not +render past 2**15 pixels horizontally have been fixed. + +Note that if you are using a GUI backend, it may have its own smaller limits +(which may themselves depend on screen size.) + + + Miscellaneous Changes --------------------- From 2dc6f6b08c3f2d800f5453a8abc062cdde8166fc Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 9 Jan 2025 15:22:21 -0500 Subject: [PATCH 16/73] Backport PR #29442: DOC: put section headings in 3.10 whats new --- doc/users/prev_whats_new/whats_new_3.10.0.rst | 223 ++++++++++-------- 1 file changed, 130 insertions(+), 93 deletions(-) diff --git a/doc/users/prev_whats_new/whats_new_3.10.0.rst b/doc/users/prev_whats_new/whats_new_3.10.0.rst index bc160787aebc..2a6e55f7c3cb 100644 --- a/doc/users/prev_whats_new/whats_new_3.10.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.10.0.rst @@ -1,3 +1,20 @@ +============================================= +What's new in Matplotlib 3.10.0 (Dec 14, 2024) +============================================= + +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 + +Accessible Colors +================= + + New more-accessible color cycle ------------------------------- @@ -43,6 +60,12 @@ colour maps version 8.0.1 (DOI: https://doi.org/10.5281/zenodo.1243862). ax[1].imshow(img, cmap=plt.cm.managua) ax[2].imshow(img, cmap=plt.cm.vanimo) + + +Plotting and Annotation improvements +==================================== + + Specifying a single color in ``contour`` and ``contourf`` --------------------------------------------------------- @@ -65,66 +88,6 @@ may be passed. plt.show() -Exception handling control --------------------------- - -The exception raised when an invalid keyword parameter is passed now includes -that parameter name as the exception's ``name`` property. This provides more -control for exception handling: - - -.. code-block:: python - - import matplotlib.pyplot as plt - - def wobbly_plot(args, **kwargs): - w = kwargs.pop('wobble_factor', None) - - try: - plt.plot(args, **kwargs) - except AttributeError as e: - raise AttributeError(f'wobbly_plot does not take parameter {e.name}') from e - - - wobbly_plot([0, 1], wibble_factor=5) - -.. code-block:: - - AttributeError: wobbly_plot does not take parameter wibble_factor - -Preliminary support for free-threaded CPython 3.13 --------------------------------------------------- - -Matplotlib 3.10 has preliminary support for the free-threaded build of CPython 3.13. See -https://py-free-threading.github.io, `PEP 703 `_ and -the `CPython 3.13 release notes -`_ for more detail -about free-threaded Python. - -Support for free-threaded Python does not mean that Matplotlib is wholly thread safe. We -expect that use of a Figure within a single thread will work, and though input data is -usually copied, modification of data objects used for a plot from another thread may -cause inconsistencies in cases where it is not. Use of any global state (such as the -``pyplot`` module) is highly discouraged and unlikely to work consistently. Also note -that most GUI toolkits expect to run on the main thread, so interactive usage may be -limited or unsupported from other threads. - -If you are interested in free-threaded Python, for example because you have a -multiprocessing-based workflow that you are interested in running with Python threads, we -encourage testing and experimentation. If you run into problems that you suspect are -because of Matplotlib, please open an issue, checking first if the bug also occurs in the -“regular” non-free-threaded CPython 3.13 build. - -Increased Figure limits with Agg renderer ------------------------------------------ - -Figures using the Agg renderer are now limited to 2**23 pixels in each -direction, instead of 2**16. Additionally, bugs that caused artists to not -render past 2**15 pixels horizontally have been fixed. - -Note that if you are using a GUI backend, it may have its own smaller limits -(which may themselves depend on screen size.) - Vectorized ``hist`` style parameters ------------------------------------ @@ -259,39 +222,6 @@ Subfigures are now added in row-major order ax.set_yticks([]) plt.show() -``svg.id`` rcParam ------------------- - -:rc:`svg.id` lets you insert an ``id`` attribute into the top-level ```` tag. - -e.g. ``rcParams["svg.id"] = "svg1"`` results in -default), no ``id`` tag is included - -.. code-block:: XML - - - -This is useful if you would like to link the entire matplotlib SVG file within -another SVG file with the ```` tag. - -.. code-block:: XML - - - - -Where the ``#svg1`` indicator will now refer to the top level ```` tag, and -will hence result in the inclusion of the entire file. ``boxplot`` and ``bxp`` orientation parameter --------------------------------------------- @@ -361,6 +291,11 @@ the ``set_data`` method, enabling e.g. resampling coll.set_data(t, -t**4, t**4) fig.savefig("after.png") + +3D plotting improvements +======================== + + Fill between 3D lines --------------------- @@ -471,6 +406,108 @@ view box is a limitation of the current renderer. ax.legend(['axlim_clip=False (default)', 'axlim_clip=True']) +Preliminary support for free-threaded CPython 3.13 +================================================== + +Matplotlib 3.10 has preliminary support for the free-threaded build of CPython 3.13. See +https://py-free-threading.github.io, `PEP 703 `_ and +the `CPython 3.13 release notes +`_ for more detail +about free-threaded Python. + +Support for free-threaded Python does not mean that Matplotlib is wholly thread safe. We +expect that use of a Figure within a single thread will work, and though input data is +usually copied, modification of data objects used for a plot from another thread may +cause inconsistencies in cases where it is not. Use of any global state (such as the +``pyplot`` module) is highly discouraged and unlikely to work consistently. Also note +that most GUI toolkits expect to run on the main thread, so interactive usage may be +limited or unsupported from other threads. + +If you are interested in free-threaded Python, for example because you have a +multiprocessing-based workflow that you are interested in running with Python threads, we +encourage testing and experimentation. If you run into problems that you suspect are +because of Matplotlib, please open an issue, checking first if the bug also occurs in the +“regular” non-free-threaded CPython 3.13 build. + + + +Other Improvements +================== + +``svg.id`` rcParam +------------------ + +:rc:`svg.id` lets you insert an ``id`` attribute into the top-level ```` tag. + +e.g. ``rcParams["svg.id"] = "svg1"`` results in + +.. code-block:: XML + + + +This is useful if you would like to link the entire matplotlib SVG file within +another SVG file with the ```` tag. + +.. code-block:: XML + + + + +Where the ``#svg1`` indicator will now refer to the top level ```` tag, and +will hence result in the inclusion of the entire file. + +By default, no ``id`` tag is included. + +Exception handling control +-------------------------- + +The exception raised when an invalid keyword parameter is passed now includes +that parameter name as the exception's ``name`` property. This provides more +control for exception handling: + + +.. code-block:: python + + import matplotlib.pyplot as plt + + def wobbly_plot(args, **kwargs): + w = kwargs.pop('wobble_factor', None) + + try: + plt.plot(args, **kwargs) + except AttributeError as e: + raise AttributeError(f'wobbly_plot does not take parameter {e.name}') from e + + + wobbly_plot([0, 1], wibble_factor=5) + +.. code-block:: + + AttributeError: wobbly_plot does not take parameter wibble_factor + +Increased Figure limits with Agg renderer +----------------------------------------- + +Figures using the Agg renderer are now limited to 2**23 pixels in each +direction, instead of 2**16. Additionally, bugs that caused artists to not +render past 2**15 pixels horizontally have been fixed. + +Note that if you are using a GUI backend, it may have its own smaller limits +(which may themselves depend on screen size.) + + + Miscellaneous Changes --------------------- From fe02b3b28686101df7fdbd7e8e6b425f6fd693bd Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 10 Jan 2025 11:28:19 -0500 Subject: [PATCH 17/73] Backport PR #29449: ci: Install libnotify4 on all Ubuntu --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 27aab4b392ee..d42ac6ea00a2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -155,6 +155,7 @@ jobs: libffi-dev \ libgeos-dev \ libgirepository1.0-dev \ + libnotify4 \ libsdl2-2.0-0 \ libxkbcommon-x11-0 \ libxcb-cursor0 \ @@ -178,8 +179,7 @@ jobs: if [[ "${{ matrix.os }}" = ubuntu-20.04 ]]; then sudo apt-get install -yy --no-install-recommends libopengl0 else # ubuntu-22.04 - sudo apt-get install -yy --no-install-recommends \ - gir1.2-gtk-4.0 libnotify4 + sudo apt-get install -yy --no-install-recommends gir1.2-gtk-4.0 fi ;; macOS) From b365e090897d4ee8d9e3b241150b520b37afc01f Mon Sep 17 00:00:00 2001 From: hu-xiaonan <152783907+hu-xiaonan@users.noreply.github.com> Date: Sat, 11 Jan 2025 02:33:44 +0800 Subject: [PATCH 18/73] Backport PR #29411: fix #29410 Modifying Axes' position also alters the original Bbox object used for initialization --- lib/matplotlib/axes/_base.py | 2 +- lib/matplotlib/tests/test_axes.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 2ff37d96021a..e45957fdd591 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -648,7 +648,7 @@ def __init__(self, fig, args = (rect,) subplotspec = None if len(args) == 1 and isinstance(args[0], mtransforms.Bbox): - self._position = args[0] + self._position = args[0].frozen() elif len(args) == 1 and np.iterable(args[0]): self._position = mtransforms.Bbox.from_bounds(*args[0]) else: diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 991e8689a360..435a1462d2ee 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -9580,3 +9580,14 @@ def test_bar_color_precedence(): bars = ax.bar([31, 32, 33], [4, 5, 6], color='red', facecolor='green') for bar in bars: assert mcolors.same_color(bar.get_facecolor(), 'green') + + +@check_figures_equal(extensions=['png']) +def test_axes_set_position_external_bbox_unchanged(fig_test, fig_ref): + # From #29410: Modifying Axes' position also alters the original Bbox + # object used for initialization + bbox = mtransforms.Bbox([[0.0, 0.0], [1.0, 1.0]]) + ax_test = fig_test.add_axes(bbox) + ax_test.set_position([0.25, 0.25, 0.5, 0.5]) + assert (bbox.x0, bbox.y0, bbox.width, bbox.height) == (0.0, 0.0, 1.0, 1.0) + ax_ref = fig_ref.add_axes([0.25, 0.25, 0.5, 0.5]) From 9b990102ece96844cf20f0b474ef95ee97b62a70 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:13:08 +0000 Subject: [PATCH 19/73] Backport PR #29457: DOC: Use float instead for scalar for type descriptions in docstrings --- lib/matplotlib/artist.py | 4 ++-- lib/matplotlib/axes/_axes.py | 12 ++++++------ lib/matplotlib/backend_bases.py | 4 ++-- lib/matplotlib/backends/backend_mixed.py | 4 ++-- lib/matplotlib/colors.py | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index 17724c8b027a..c87c789048c4 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -1016,7 +1016,7 @@ def set_alpha(self, alpha): Parameters ---------- - alpha : scalar or None + alpha : float or None *alpha* must be within the 0-1 range, inclusive. """ if alpha is not None and not isinstance(alpha, Real): @@ -1035,7 +1035,7 @@ def _set_alpha_for_array(self, alpha): Parameters ---------- - alpha : array-like or scalar or None + alpha : array-like or float or None All values must be within the 0-1 range, inclusive. Masked values and nans are not supported. """ diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index bf4e0b031b59..ed0ec5412955 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -1618,7 +1618,7 @@ def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs): Parameters ---------- - x, y : array-like or scalar + x, y : array-like or float The horizontal / vertical coordinates of the data points. *x* values are optional and default to ``range(len(y))``. @@ -4250,13 +4250,13 @@ def bxp(self, bxpstats, positions=None, widths=None, vert=None, A list of dictionaries containing stats for each boxplot. Required keys are: - - ``med``: Median (scalar). - - ``q1``, ``q3``: First & third quartiles (scalars). - - ``whislo``, ``whishi``: Lower & upper whisker positions (scalars). + - ``med``: Median (float). + - ``q1``, ``q3``: First & third quartiles (float). + - ``whislo``, ``whishi``: Lower & upper whisker positions (float). Optional keys are: - - ``mean``: Mean (scalar). Needed if ``showmeans=True``. + - ``mean``: Mean (float). Needed if ``showmeans=True``. - ``fliers``: Data beyond the whiskers (array-like). Needed if ``showfliers=True``. - ``cilo``, ``cihi``: Lower & upper confidence intervals @@ -6891,7 +6891,7 @@ def hist(self, x, bins=None, range=None, density=False, weights=None, ``True``, then the histogram is normalized such that the first bin equals 1. - bottom : array-like, scalar, or None, default: None + bottom : array-like or float, default: 0 Location of the bottom of each bin, i.e. bins are drawn from ``bottom`` to ``bottom + hist(x, bins)`` If a scalar, the bottom of each bin is shifted by the same amount. If an array, each bin diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index d39fc0a1288b..0843796bad5a 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -428,11 +428,11 @@ def draw_image(self, gc, x, y, im, transform=None): gc : `.GraphicsContextBase` A graphics context with clipping information. - x : scalar + x : float The distance in physical units (i.e., dots or pixels) from the left hand side of the canvas. - y : scalar + y : float The distance in physical units (i.e., dots or pixels) from the bottom side of the canvas. diff --git a/lib/matplotlib/backends/backend_mixed.py b/lib/matplotlib/backends/backend_mixed.py index 6571d1928c0d..971d73cdb448 100644 --- a/lib/matplotlib/backends/backend_mixed.py +++ b/lib/matplotlib/backends/backend_mixed.py @@ -21,9 +21,9 @@ def __init__(self, figure, width, height, dpi, vector_renderer, ---------- figure : `~matplotlib.figure.Figure` The figure instance. - width : scalar + width : float The width of the canvas in logical units - height : scalar + height : float The height of the canvas in logical units dpi : float The dpi of the canvas diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 5f909d07c190..e881af04508c 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -717,7 +717,7 @@ def __call__(self, X, alpha=None, bytes=False): r""" Parameters ---------- - X : float or int, `~numpy.ndarray` or scalar + X : float or int or array-like The data value(s) to convert to RGBA. For floats, *X* should be in the interval ``[0.0, 1.0]`` to return the RGBA values ``X*100`` percent along the Colormap line. @@ -745,7 +745,7 @@ def _get_rgba_and_mask(self, X, alpha=None, bytes=False): r""" Parameters ---------- - X : float or int, `~numpy.ndarray` or scalar + X : float or int or array-like The data value(s) to convert to RGBA. For floats, *X* should be in the interval ``[0.0, 1.0]`` to return the RGBA values ``X*100`` percent along the Colormap line. @@ -1566,7 +1566,7 @@ def __call__(self, X, alpha=None, bytes=False): r""" Parameters ---------- - X : tuple (X0, X1), X0 and X1: float or int `~numpy.ndarray` or scalar + X : tuple (X0, X1), X0 and X1: float or int or array-like The data value(s) to convert to RGBA. - For floats, *X* should be in the interval ``[0.0, 1.0]`` to From c8d6b41c81fe9a585e2845c5d35989fe3b464de9 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:16:38 +0000 Subject: [PATCH 20/73] Backport PR #29456: DOC: Fix type descriptions in fill_between docstring --- lib/matplotlib/axes/_axes.py | 8 ++++---- lib/matplotlib/collections.py | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index bf4e0b031b59..b83ead051b12 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5599,16 +5599,16 @@ def _fill_between_x_or_y( Parameters ---------- - {ind} : array (length N) + {ind} : array-like The {ind} coordinates of the nodes defining the curves. - {dep}1 : array (length N) or scalar + {dep}1 : array-like or float The {dep} coordinates of the nodes defining the first curve. - {dep}2 : array (length N) or scalar, default: 0 + {dep}2 : array-like or float, default: 0 The {dep} coordinates of the nodes defining the second curve. - where : array of bool (length N), optional + where : array-like of bool, optional Define *where* to exclude some {dir} regions from being filled. The filled regions are defined by the coordinates ``{ind}[where]``. More precisely, fill between ``{ind}[i]`` and ``{ind}[i+1]`` if diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index f18d5a4c3a8c..b94410bcc140 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -1282,16 +1282,16 @@ def __init__( - 'x': the curves are ``(t, f1)`` and ``(t, f2)``. - 'y': the curves are ``(f1, t)`` and ``(f2, t)``. - t : array (length N) + t : array-like The ``t_direction`` coordinates of the nodes defining the curves. - f1 : array (length N) or scalar + f1 : array-like or float The other coordinates of the nodes defining the first curve. - f2 : array (length N) or scalar + f2 : array-like or float The other coordinates of the nodes defining the second curve. - where : array of bool (length N), optional + where : array-like of bool, optional Define *where* to exclude some {dir} regions from being filled. The filled regions are defined by the coordinates ``t[where]``. More precisely, fill between ``t[i]`` and ``t[i+1]`` if @@ -1362,16 +1362,16 @@ def set_data(self, t, f1, f2, *, where=None): Parameters ---------- - t : array (length N) + t : array-like The ``self.t_direction`` coordinates of the nodes defining the curves. - f1 : array (length N) or scalar + f1 : array-like or float The other coordinates of the nodes defining the first curve. - f2 : array (length N) or scalar + f2 : array-like or float The other coordinates of the nodes defining the second curve. - where : array of bool (length N), optional + where : array-like of bool, optional Define *where* to exclude some {dir} regions from being filled. The filled regions are defined by the coordinates ``t[where]``. More precisely, fill between ``t[i]`` and ``t[i+1]`` if From bed82812593795bcf91bcc6c7f8050a8d0a4025f Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 12 Jan 2025 00:25:43 +0100 Subject: [PATCH 21/73] Backport PR #29404: DOC: scales - built in options and custom scale usefulness --- galleries/examples/scales/custom_scale.py | 24 ++++++++++++++++------ lib/matplotlib/axis.py | 25 +++++++---------------- lib/matplotlib/scale.py | 4 +++- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/galleries/examples/scales/custom_scale.py b/galleries/examples/scales/custom_scale.py index 0023bbcfbcae..0eedb16ec5cf 100644 --- a/galleries/examples/scales/custom_scale.py +++ b/galleries/examples/scales/custom_scale.py @@ -5,13 +5,25 @@ Custom scale ============ -Create a custom scale, by implementing the scaling use for latitude data in a -Mercator Projection. +Custom scales can be created in two ways + +#. For simple cases, use `~.scale.FuncScale` and the ``'function'`` option of + `~.Axes.set_xscale` and `~.Axes.set_yscale`. See the last example in + :doc:`/gallery/scales/scales`. + +#. Create a custom scale class such as the one in this example, which implements + the scaling use for latitude data in a Mercator Projection. This more complicated + approach is useful when + + * You are making special use of the `.Transform` class, such as the special + handling of values beyond the threshold in ``MercatorLatitudeTransform`` + below. + + * You want to override the default locators and formatters for the axis + (``set_default_locators_and_formatters`` below). + + * You want to limit the range of the the axis (``limit_range_for_scale`` below). -Unless you are making special use of the `.Transform` class, you probably -don't need to use this verbose method, and instead can use `~.scale.FuncScale` -and the ``'function'`` option of `~.Axes.set_xscale` and `~.Axes.set_yscale`. -See the last example in :doc:`/gallery/scales/scales`. """ import numpy as np diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 56eeb0e4169b..714fb08f55be 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -777,26 +777,15 @@ def _set_axes_scale(self, value, **kwargs): Parameters ---------- - value : {"linear", "log", "symlog", "logit", ...} or `.ScaleBase` - The axis scale type to apply. + value : str or `.ScaleBase` + The axis scale type to apply. Valid string values are the names of scale + classes ("linear", "log", "function",...). These may be the names of any + of the :ref:`built-in scales` or of any custom scales + registered using `matplotlib.scale.register_scale`. **kwargs - Different keyword arguments are accepted, depending on the scale. - See the respective class keyword arguments: - - - `matplotlib.scale.LinearScale` - - `matplotlib.scale.LogScale` - - `matplotlib.scale.SymmetricalLogScale` - - `matplotlib.scale.LogitScale` - - `matplotlib.scale.FuncScale` - - `matplotlib.scale.AsinhScale` - - Notes - ----- - By default, Matplotlib supports the above-mentioned scales. - Additionally, custom scales may be registered using - `matplotlib.scale.register_scale`. These scales can then also - be used here. + If *value* is a string, keywords are passed to the instantiation method of + the respective class. """ name = self._get_axis_name() old_default_lims = (self.get_major_locator() diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index a63294406b56..7630ba6e54b9 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -3,7 +3,9 @@ The mapping is implemented through `.Transform` subclasses. -The following scales are builtin: +The following scales are built-in: + +.. _builtin_scales: ============= ===================== ================================ ================================= Name Class Transform Inverted transform From 572d522157aaf3c505aafc5142ca5debc63c786a Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:20:59 +0100 Subject: [PATCH 22/73] Backport PR #29476: ci: Enable native ARM builders for wheels --- .github/workflows/cibuildwheel.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 9dc5e01cca58..79d770d0c8f4 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -115,13 +115,12 @@ jobs: CIBW_TEST_COMMAND: >- python {package}/ci/check_version_number.py MACOSX_DEPLOYMENT_TARGET: "10.12" - MPL_DISABLE_FH4: "yes" strategy: matrix: include: - os: ubuntu-latest cibw_archs: "x86_64" - - os: ubuntu-latest + - os: ubuntu-24.04-arm cibw_archs: "aarch64" - os: windows-latest cibw_archs: "auto64" @@ -131,12 +130,6 @@ jobs: cibw_archs: "arm64" steps: - - name: Set up QEMU - if: matrix.cibw_archs == 'aarch64' - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - with: - platforms: arm64 - - name: Download sdist uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: From 4f89d4bd0c99ab2abeedf118033180c97ffe8efe Mon Sep 17 00:00:00 2001 From: hannah Date: Wed, 22 Jan 2025 03:47:19 -0500 Subject: [PATCH 23/73] Backport PR #29488: DOC: Update broken_barh example --- .../lines_bars_and_markers/broken_barh.py | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/broken_barh.py b/galleries/examples/lines_bars_and_markers/broken_barh.py index e1550385155a..c400c67cffe4 100644 --- a/galleries/examples/lines_bars_and_markers/broken_barh.py +++ b/galleries/examples/lines_bars_and_markers/broken_barh.py @@ -1,27 +1,34 @@ """ -=========== -Broken Barh -=========== +====================== +Broken horizontal bars +====================== -Make a "broken" horizontal bar plot, i.e., one with gaps +`~.Axes.broken_barh` creates sequences of horizontal bars. This example shows +a timing diagram. """ import matplotlib.pyplot as plt +import numpy as np + +# data is a sequence of (start, duration) tuples +cpu_1 = [(0, 3), (3.5, 1), (5, 5)] +cpu_2 = np.column_stack([np.linspace(0, 9, 10), np.full(10, 0.5)]) +cpu_3 = np.column_stack([10*np.random.random(61), np.full(61, 0.05)]) +cpu_4 = [(2, 1.7), (7, 1.2)] +disk = [(1, 1.5)] +network = np.column_stack([10*np.random.random(10), np.full(10, 0.05)]) -# Horizontal bar plot with gaps fig, ax = plt.subplots() -ax.broken_barh([(110, 30), (150, 10)], (10, 9), facecolors='tab:blue') -ax.broken_barh([(10, 50), (100, 20), (130, 10)], (20, 9), - facecolors=('tab:orange', 'tab:green', 'tab:red')) -ax.set_ylim(5, 35) -ax.set_xlim(0, 200) -ax.set_xlabel('seconds since start') -ax.set_yticks([15, 25], labels=['Bill', 'Jim']) # Modify y-axis tick labels -ax.grid(True) # Make grid lines visible -ax.annotate('race interrupted', (61, 25), - xytext=(0.8, 0.9), textcoords='axes fraction', - arrowprops=dict(facecolor='black', shrink=0.05), - fontsize=16, - horizontalalignment='right', verticalalignment='top') +# broken_barh(xranges, (ymin, height)) +ax.broken_barh(cpu_1, (5.8, 0.4)) +ax.broken_barh(cpu_2, (4.8, 0.4)) +ax.broken_barh(cpu_3, (3.8, 0.4)) +ax.broken_barh(cpu_4, (2.8, 0.4)) +ax.broken_barh(disk, (1.8, 0.4), color="tab:orange") +ax.broken_barh(network, (0.8, 0.4), color="tab:green") +ax.set_xlim(0, 10) +ax.set_yticks([6, 5, 4, 3, 2, 1], + labels=["CPU 1", "CPU 2", "CPU 3", "CPU 4", "disk", "network"]) +ax.set_title("Resource usage") plt.show() From e6bc47fddafa774ae17b234ae28e2429325000f1 Mon Sep 17 00:00:00 2001 From: hannah Date: Wed, 22 Jan 2025 03:47:19 -0500 Subject: [PATCH 24/73] Backport PR #29488: DOC: Update broken_barh example --- .../lines_bars_and_markers/broken_barh.py | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/broken_barh.py b/galleries/examples/lines_bars_and_markers/broken_barh.py index e1550385155a..c400c67cffe4 100644 --- a/galleries/examples/lines_bars_and_markers/broken_barh.py +++ b/galleries/examples/lines_bars_and_markers/broken_barh.py @@ -1,27 +1,34 @@ """ -=========== -Broken Barh -=========== +====================== +Broken horizontal bars +====================== -Make a "broken" horizontal bar plot, i.e., one with gaps +`~.Axes.broken_barh` creates sequences of horizontal bars. This example shows +a timing diagram. """ import matplotlib.pyplot as plt +import numpy as np + +# data is a sequence of (start, duration) tuples +cpu_1 = [(0, 3), (3.5, 1), (5, 5)] +cpu_2 = np.column_stack([np.linspace(0, 9, 10), np.full(10, 0.5)]) +cpu_3 = np.column_stack([10*np.random.random(61), np.full(61, 0.05)]) +cpu_4 = [(2, 1.7), (7, 1.2)] +disk = [(1, 1.5)] +network = np.column_stack([10*np.random.random(10), np.full(10, 0.05)]) -# Horizontal bar plot with gaps fig, ax = plt.subplots() -ax.broken_barh([(110, 30), (150, 10)], (10, 9), facecolors='tab:blue') -ax.broken_barh([(10, 50), (100, 20), (130, 10)], (20, 9), - facecolors=('tab:orange', 'tab:green', 'tab:red')) -ax.set_ylim(5, 35) -ax.set_xlim(0, 200) -ax.set_xlabel('seconds since start') -ax.set_yticks([15, 25], labels=['Bill', 'Jim']) # Modify y-axis tick labels -ax.grid(True) # Make grid lines visible -ax.annotate('race interrupted', (61, 25), - xytext=(0.8, 0.9), textcoords='axes fraction', - arrowprops=dict(facecolor='black', shrink=0.05), - fontsize=16, - horizontalalignment='right', verticalalignment='top') +# broken_barh(xranges, (ymin, height)) +ax.broken_barh(cpu_1, (5.8, 0.4)) +ax.broken_barh(cpu_2, (4.8, 0.4)) +ax.broken_barh(cpu_3, (3.8, 0.4)) +ax.broken_barh(cpu_4, (2.8, 0.4)) +ax.broken_barh(disk, (1.8, 0.4), color="tab:orange") +ax.broken_barh(network, (0.8, 0.4), color="tab:green") +ax.set_xlim(0, 10) +ax.set_yticks([6, 5, 4, 3, 2, 1], + labels=["CPU 1", "CPU 2", "CPU 3", "CPU 4", "disk", "network"]) +ax.set_title("Resource usage") plt.show() From a6dc6a8a66ff5bd527d04dee8dce6d70236eeed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trygve=20Magnus=20R=C3=A6der?= Date: Wed, 22 Jan 2025 11:19:46 +0100 Subject: [PATCH 25/73] Backport PR #29478: DOC: Added blurb for colorizer objects in what's new for 3.10 --- doc/users/prev_whats_new/whats_new_3.10.0.rst | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/doc/users/prev_whats_new/whats_new_3.10.0.rst b/doc/users/prev_whats_new/whats_new_3.10.0.rst index 2a6e55f7c3cb..78d4d3c30662 100644 --- a/doc/users/prev_whats_new/whats_new_3.10.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.10.0.rst @@ -292,6 +292,62 @@ the ``set_data`` method, enabling e.g. resampling fig.savefig("after.png") +``matplotlib.colorizer.Colorizer`` as container for ``norm`` and ``cmap`` +------------------------------------------------------------------------- + + `matplotlib.colorizer.Colorizer` encapsulates the data-to-color pipeline. It makes reuse of colormapping easier, e.g. across multiple images. Plotting methods that support *norm* and *cmap* keyword arguments now also accept a *colorizer* keyword argument. + +In the following example the norm and cmap are changed on multiple plots simultaneously: + + +.. plot:: + :include-source: true + :alt: Example use of a matplotlib.colorizer.Colorizer object + + import matplotlib.pyplot as plt + import matplotlib as mpl + import numpy as np + + x = np.linspace(-2, 2, 50)[np.newaxis, :] + y = np.linspace(-2, 2, 50)[:, np.newaxis] + im_0 = 1 * np.exp( - (x**2 + y**2 - x * y)) + im_1 = 2 * np.exp( - (x**2 + y**2 + x * y)) + + colorizer = mpl.colorizer.Colorizer() + fig, axes = plt.subplots(1, 2, figsize=(6, 2)) + cim_0 = axes[0].imshow(im_0, colorizer=colorizer) + fig.colorbar(cim_0) + cim_1 = axes[1].imshow(im_1, colorizer=colorizer) + fig.colorbar(cim_1) + + colorizer.vmin = 0.5 + colorizer.vmax = 2 + colorizer.cmap = 'RdBu' + +All plotting methods that use a data-to-color pipeline now create a colorizer object if one is not provided. This can be re-used by subsequent artists such that they will share a single data-to-color pipeline: + +.. plot:: + :include-source: true + :alt: Example of how artists that share a ``colorizer`` have coupled colormaps + + import matplotlib.pyplot as plt + import matplotlib as mpl + import numpy as np + + x = np.linspace(-2, 2, 50)[np.newaxis, :] + y = np.linspace(-2, 2, 50)[:, np.newaxis] + im_0 = 1 * np.exp( - (x**2 + y**2 - x * y)) + im_1 = 2 * np.exp( - (x**2 + y**2 + x * y)) + + fig, axes = plt.subplots(1, 2, figsize=(6, 2)) + + cim_0 = axes[0].imshow(im_0, cmap='RdBu', vmin=0.5, vmax=2) + fig.colorbar(cim_0) + cim_1 = axes[1].imshow(im_1, colorizer=cim_0.colorizer) + fig.colorbar(cim_1) + + cim_1.cmap = 'rainbow' + 3D plotting improvements ======================== From 874af205576f46c637ab248ceabf9ae28c2190fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trygve=20Magnus=20R=C3=A6der?= Date: Wed, 22 Jan 2025 11:19:46 +0100 Subject: [PATCH 26/73] Backport PR #29478: DOC: Added blurb for colorizer objects in what's new for 3.10 --- doc/users/prev_whats_new/whats_new_3.10.0.rst | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/doc/users/prev_whats_new/whats_new_3.10.0.rst b/doc/users/prev_whats_new/whats_new_3.10.0.rst index 2a6e55f7c3cb..78d4d3c30662 100644 --- a/doc/users/prev_whats_new/whats_new_3.10.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.10.0.rst @@ -292,6 +292,62 @@ the ``set_data`` method, enabling e.g. resampling fig.savefig("after.png") +``matplotlib.colorizer.Colorizer`` as container for ``norm`` and ``cmap`` +------------------------------------------------------------------------- + + `matplotlib.colorizer.Colorizer` encapsulates the data-to-color pipeline. It makes reuse of colormapping easier, e.g. across multiple images. Plotting methods that support *norm* and *cmap* keyword arguments now also accept a *colorizer* keyword argument. + +In the following example the norm and cmap are changed on multiple plots simultaneously: + + +.. plot:: + :include-source: true + :alt: Example use of a matplotlib.colorizer.Colorizer object + + import matplotlib.pyplot as plt + import matplotlib as mpl + import numpy as np + + x = np.linspace(-2, 2, 50)[np.newaxis, :] + y = np.linspace(-2, 2, 50)[:, np.newaxis] + im_0 = 1 * np.exp( - (x**2 + y**2 - x * y)) + im_1 = 2 * np.exp( - (x**2 + y**2 + x * y)) + + colorizer = mpl.colorizer.Colorizer() + fig, axes = plt.subplots(1, 2, figsize=(6, 2)) + cim_0 = axes[0].imshow(im_0, colorizer=colorizer) + fig.colorbar(cim_0) + cim_1 = axes[1].imshow(im_1, colorizer=colorizer) + fig.colorbar(cim_1) + + colorizer.vmin = 0.5 + colorizer.vmax = 2 + colorizer.cmap = 'RdBu' + +All plotting methods that use a data-to-color pipeline now create a colorizer object if one is not provided. This can be re-used by subsequent artists such that they will share a single data-to-color pipeline: + +.. plot:: + :include-source: true + :alt: Example of how artists that share a ``colorizer`` have coupled colormaps + + import matplotlib.pyplot as plt + import matplotlib as mpl + import numpy as np + + x = np.linspace(-2, 2, 50)[np.newaxis, :] + y = np.linspace(-2, 2, 50)[:, np.newaxis] + im_0 = 1 * np.exp( - (x**2 + y**2 - x * y)) + im_1 = 2 * np.exp( - (x**2 + y**2 + x * y)) + + fig, axes = plt.subplots(1, 2, figsize=(6, 2)) + + cim_0 = axes[0].imshow(im_0, cmap='RdBu', vmin=0.5, vmax=2) + fig.colorbar(cim_0) + cim_1 = axes[1].imshow(im_1, colorizer=cim_0.colorizer) + fig.colorbar(cim_1) + + cim_1.cmap = 'rainbow' + 3D plotting improvements ======================== From e6a9e25f650d175e0767b4ffb7043fdf165a7778 Mon Sep 17 00:00:00 2001 From: Khushi_29 <121342846+Khushikela29@users.noreply.github.com> Date: Fri, 24 Jan 2025 19:19:28 +0530 Subject: [PATCH 27/73] Backport PR #29471: Fix subplot docs --- doc/api/axes_api.rst | 1 + lib/matplotlib/pyplot.py | 14 ++++---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/doc/api/axes_api.rst b/doc/api/axes_api.rst index 6afdad4e768e..bf2e30ea983c 100644 --- a/doc/api/axes_api.rst +++ b/doc/api/axes_api.rst @@ -616,5 +616,6 @@ Other Axes.get_transformed_clip_path_and_affine Axes.has_data Axes.set + Axes.remove .. autoclass:: matplotlib.axes.Axes.ArtistList diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index ba7a5e32f5d0..12aedf5157ca 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -1449,16 +1449,10 @@ def subplot(*args, **kwargs) -> Axes: Notes ----- - Creating a new Axes will delete any preexisting Axes that - overlaps with it beyond sharing a boundary:: - - import matplotlib.pyplot as plt - # plot a line, implicitly creating a subplot(111) - plt.plot([1, 2, 3]) - # now create a subplot which represents the top plot of a grid - # with 2 rows and 1 column. Since this subplot will overlap the - # first, the plot (and its Axes) previously created, will be removed - plt.subplot(211) + .. versionchanged:: 3.8 + In versions prior to 3.8, any preexisting Axes that overlap with the new Axes + beyond sharing a boundary was deleted. Deletion does not happen in more + recent versions anymore. Use `.Axes.remove` explicitly if needed. If you do not want this behavior, use the `.Figure.add_subplot` method or the `.pyplot.axes` function instead. From de3cbd2e988c16a40a8ee2fb68d8670d8f76a264 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 24 Jan 2025 16:47:08 +0100 Subject: [PATCH 28/73] Backport PR #29511: DOC: Document the behavior of bar() for categorical x data --- lib/matplotlib/axes/_axes.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index efadb88f2518..564783a6352c 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2391,6 +2391,17 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center", The x coordinates of the bars. See also *align* for the alignment of the bars to the coordinates. + Bars are often used for categorical data, i.e. string labels below + the bars. You can provide a list of strings directly to *x*. + ``bar(['A', 'B', 'C'], [1, 2, 3])`` is often a shorter and more + convenient notation compared to + ``bar(range(3), [1, 2, 3], tick_label=['A', 'B', 'C'])``. They are + equivalent as long as the names are unique. The explicit *tick_label* + notation draws the names in the sequence given. However, when having + duplicate values in categorical *x* data, these values map to the same + numerical x coordinate, and hence the corresponding bars are drawn on + top of each other. + height : float or array-like The height(s) of the bars. @@ -2706,6 +2717,17 @@ def barh(self, y, width, height=0.8, left=None, *, align="center", The y coordinates of the bars. See also *align* for the alignment of the bars to the coordinates. + Bars are often used for categorical data, i.e. string labels below + the bars. You can provide a list of strings directly to *y*. + ``barh(['A', 'B', 'C'], [1, 2, 3])`` is often a shorter and more + convenient notation compared to + ``barh(range(3), [1, 2, 3], tick_label=['A', 'B', 'C'])``. They are + equivalent as long as the names are unique. The explicit *tick_label* + notation draws the names in the sequence given. However, when having + duplicate values in categorical *y* data, these values map to the same + numerical y coordinate, and hence the corresponding bars are drawn on + top of each other. + width : float or array-like The width(s) of the bars. From 8f94213c83c4512aebc8a7b9c110c60cdd57f32c Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 24 Jan 2025 14:13:32 -0600 Subject: [PATCH 29/73] Fix toctrees for 3.10 release notes --- doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst | 4 ++++ .../prev_api_changes/api_changes_3.10.0/deprecations.rst | 4 ++++ .../prev_api_changes/api_changes_3.10.0/development.rst | 3 +++ doc/api/prev_api_changes/api_changes_3.10.0/removals.rst | 4 ++++ doc/users/prev_whats_new/whats_new_3.10.0.rst | 9 +++------ doc/users/prev_whats_new/whats_new_3.9.0.rst | 2 +- doc/users/release_notes.rst | 2 +- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst b/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst index 87da6568a860..ae50371fa7aa 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst @@ -1,3 +1,7 @@ +Behavior Changes +---------------- + + onselect argument to selector widgets made optional ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst index ad344b37d069..2be32c30ea2f 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst @@ -1,3 +1,7 @@ +Deprecations +------------ + + Positional parameters in plotting functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/development.rst b/doc/api/prev_api_changes/api_changes_3.10.0/development.rst index 58ece9877912..329256b466b5 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0/development.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0/development.rst @@ -1,3 +1,6 @@ +Development changes +------------------- + Documentation-specific custom Sphinx roles are now semi-public ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst index e535123c7016..7ed06e7446ef 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst @@ -1,3 +1,7 @@ +Removals +-------- + + ttconv removed ~~~~~~~~~~~~~~ diff --git a/doc/users/prev_whats_new/whats_new_3.10.0.rst b/doc/users/prev_whats_new/whats_new_3.10.0.rst index 78d4d3c30662..6172fe1953ff 100644 --- a/doc/users/prev_whats_new/whats_new_3.10.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.10.0.rst @@ -1,6 +1,6 @@ -============================================= -What's new in Matplotlib 3.10.0 (Dec 14, 2024) -============================================= +=================================================== +What's new in Matplotlib 3.10.0 (December 13, 2024) +=================================================== For a list of all of the issues and pull requests since the last revision, see the :ref:`github-stats`. @@ -11,9 +11,6 @@ For a list of all of the issues and pull requests since the last revision, see t .. toctree:: :maxdepth: 4 -Accessible Colors -================= - New more-accessible color cycle ------------------------------- diff --git a/doc/users/prev_whats_new/whats_new_3.9.0.rst b/doc/users/prev_whats_new/whats_new_3.9.0.rst index e0190cca3f27..85fabf86efbe 100644 --- a/doc/users/prev_whats_new/whats_new_3.9.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.9.0.rst @@ -3,7 +3,7 @@ What's new in Matplotlib 3.9.0 (May 15, 2024) ============================================= For a list of all of the issues and pull requests since the last revision, see the -:ref:`github-stats`. +:ref:`github-stats-3-9-0`. .. contents:: Table of Contents :depth: 4 diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst index 3bb30bf2fa49..045132e50ac8 100644 --- a/doc/users/release_notes.rst +++ b/doc/users/release_notes.rst @@ -19,7 +19,7 @@ Version 3.10 prev_whats_new/whats_new_3.10.0.rst ../api/prev_api_changes/api_changes_3.10.0.rst - prev_whats_new/github_stats_3.10.0.rst + github_stats.rst Version 3.9 ^^^^^^^^^^^ From 30dc9735fd98be0017b91f6f34718ab5a6661297 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Sat, 25 Jan 2025 20:40:38 +0000 Subject: [PATCH 30/73] Backport PR #29509: MNT: Discourage arrow() --- lib/matplotlib/axes/_axes.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 564783a6352c..96946fba1e92 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5471,10 +5471,22 @@ def on_changed(collection): @_docstring.interpd def arrow(self, x, y, dx, dy, **kwargs): """ - Add an arrow to the Axes. + [*Discouraged*] Add an arrow to the Axes. This draws an arrow from ``(x, y)`` to ``(x+dx, y+dy)``. + .. admonition:: Discouraged + + The use of this method is discouraged because it is not guaranteed + that the arrow renders reasonably. For example, the resulting arrow + is affected by the Axes aspect ratio and limits, which may distort + the arrow. + + Consider using `~.Axes.annotate` without a text instead, e.g. :: + + ax.annotate("", xytext=(0, 0), xy=(0.5, 0.5), + arrowprops=dict(arrowstyle="->")) + Parameters ---------- %(FancyArrow)s @@ -5483,17 +5495,6 @@ def arrow(self, x, y, dx, dy, **kwargs): ------- `.FancyArrow` The created `.FancyArrow` object. - - Notes - ----- - The resulting arrow is affected by the Axes aspect ratio and limits. - This may produce an arrow whose head is not square with its stem. To - create an arrow whose head is square with its stem, - use :meth:`annotate` for example: - - >>> ax.annotate("", xy=(0.5, 0.5), xytext=(0, 0), - ... arrowprops=dict(arrowstyle="->")) - """ # Strip away units for the underlying patch since units # do not make sense to most patch-like code From 11df01145dea9a7afbcf9cec3f6bd0587f970f3b Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 28 Jan 2025 00:29:21 +0100 Subject: [PATCH 31/73] Backport PR #29520: FIX: Correct variable name from _frame to _frames in PillowWriter class --- lib/matplotlib/animation.py | 2 +- lib/matplotlib/tests/test_animation.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index 2be61284073a..a87f00201124 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -496,7 +496,7 @@ def grab_frame(self, **savefig_kwargs): "RGBA", self.frame_size, buf.getbuffer(), "raw", "RGBA", 0, 1) if im.getextrema()[3][0] < 255: # This frame has transparency, so we'll just add it as is. - self._frame.append(im) + self._frames.append(im) else: # Without transparency, we switch to RGB mode, which converts to P mode a # little better if needed (specifically, this helps with GIF output.) diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index d026dae59533..e3382f662c73 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -13,6 +13,7 @@ import matplotlib as mpl from matplotlib import pyplot as plt from matplotlib import animation +from matplotlib.animation import PillowWriter from matplotlib.testing.decorators import check_figures_equal @@ -551,3 +552,20 @@ def test_movie_writer_invalid_path(anim): with pytest.raises(FileNotFoundError, match=match_str): anim.save("/foo/bar/aardvark/thiscannotreallyexist.mp4", writer=animation.FFMpegFileWriter()) + + +def test_animation_with_transparency(): + """Test animation exhaustion with transparency using PillowWriter directly""" + fig, ax = plt.subplots() + rect = plt.Rectangle((0, 0), 1, 1, color='red', alpha=0.5) + ax.add_patch(rect) + ax.set_xlim(0, 1) + ax.set_ylim(0, 1) + + writer = PillowWriter(fps=30) + writer.setup(fig, 'unused.gif', dpi=100) + writer.grab_frame(transparent=True) + frame = writer._frames[-1] + # Check that the alpha channel is not 255, so frame has transparency + assert frame.getextrema()[3][0] < 255 + plt.close(fig) From 73f0b40a254f141261f47d71eab4a140e1aa3cff Mon Sep 17 00:00:00 2001 From: Scott Shambaugh <14363975+scottshambaugh@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:49:56 -0700 Subject: [PATCH 32/73] Backport PR #29536: Fix typo in solarized example plot. --- galleries/examples/style_sheets/plot_solarizedlight2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/style_sheets/plot_solarizedlight2.py b/galleries/examples/style_sheets/plot_solarizedlight2.py index c1d37422216a..a6434f5ef04a 100644 --- a/galleries/examples/style_sheets/plot_solarizedlight2.py +++ b/galleries/examples/style_sheets/plot_solarizedlight2.py @@ -32,7 +32,7 @@ plt.plot(x, np.sin(x) + x + np.random.randn(50)) plt.plot(x, np.sin(x) + 2 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 3 * x + np.random.randn(50)) - plt.plot(x, np.sin(x) + 4 + np.random.randn(50)) + plt.plot(x, np.sin(x) + 4 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 5 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 6 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 7 * x + np.random.randn(50)) From a645e726f8b9533ecb1140c8782a48791516f480 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh <14363975+scottshambaugh@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:49:56 -0700 Subject: [PATCH 33/73] Backport PR #29536: Fix typo in solarized example plot. --- galleries/examples/style_sheets/plot_solarizedlight2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/style_sheets/plot_solarizedlight2.py b/galleries/examples/style_sheets/plot_solarizedlight2.py index c1d37422216a..a6434f5ef04a 100644 --- a/galleries/examples/style_sheets/plot_solarizedlight2.py +++ b/galleries/examples/style_sheets/plot_solarizedlight2.py @@ -32,7 +32,7 @@ plt.plot(x, np.sin(x) + x + np.random.randn(50)) plt.plot(x, np.sin(x) + 2 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 3 * x + np.random.randn(50)) - plt.plot(x, np.sin(x) + 4 + np.random.randn(50)) + plt.plot(x, np.sin(x) + 4 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 5 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 6 * x + np.random.randn(50)) plt.plot(x, np.sin(x) + 7 * x + np.random.randn(50)) From dc0026686874076685b721ace1bf04e9c2a05eff Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 29 Jan 2025 23:23:51 -0500 Subject: [PATCH 34/73] Backport PR #29543: DOC: Minor improvement on broken_barh() --- .../lines_bars_and_markers/broken_barh.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/broken_barh.py b/galleries/examples/lines_bars_and_markers/broken_barh.py index c400c67cffe4..3714ca7c748d 100644 --- a/galleries/examples/lines_bars_and_markers/broken_barh.py +++ b/galleries/examples/lines_bars_and_markers/broken_barh.py @@ -19,20 +19,30 @@ fig, ax = plt.subplots() # broken_barh(xranges, (ymin, height)) -ax.broken_barh(cpu_1, (5.8, 0.4)) -ax.broken_barh(cpu_2, (4.8, 0.4)) -ax.broken_barh(cpu_3, (3.8, 0.4)) +ax.broken_barh(cpu_1, (-0.2, 0.4)) +ax.broken_barh(cpu_2, (0.8, 0.4)) +ax.broken_barh(cpu_3, (1.8, 0.4)) ax.broken_barh(cpu_4, (2.8, 0.4)) -ax.broken_barh(disk, (1.8, 0.4), color="tab:orange") -ax.broken_barh(network, (0.8, 0.4), color="tab:green") +ax.broken_barh(disk, (3.8, 0.4), color="tab:orange") +ax.broken_barh(network, (4.8, 0.4), color="tab:green") ax.set_xlim(0, 10) -ax.set_yticks([6, 5, 4, 3, 2, 1], +ax.set_yticks(range(6), labels=["CPU 1", "CPU 2", "CPU 3", "CPU 4", "disk", "network"]) +ax.invert_yaxis() ax.set_title("Resource usage") plt.show() - # %% +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.broken_barh` / `matplotlib.pyplot.broken_barh` +# - `matplotlib.axes.Axes.invert_yaxis` +# - `matplotlib.axes.Axes.set_yticks` +# # .. tags:: # # component: annotation From bfd73a19dc332c47739c8657a8f840a87d505dfa Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 29 Jan 2025 23:23:51 -0500 Subject: [PATCH 35/73] Backport PR #29543: DOC: Minor improvement on broken_barh() --- .../lines_bars_and_markers/broken_barh.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/broken_barh.py b/galleries/examples/lines_bars_and_markers/broken_barh.py index c400c67cffe4..3714ca7c748d 100644 --- a/galleries/examples/lines_bars_and_markers/broken_barh.py +++ b/galleries/examples/lines_bars_and_markers/broken_barh.py @@ -19,20 +19,30 @@ fig, ax = plt.subplots() # broken_barh(xranges, (ymin, height)) -ax.broken_barh(cpu_1, (5.8, 0.4)) -ax.broken_barh(cpu_2, (4.8, 0.4)) -ax.broken_barh(cpu_3, (3.8, 0.4)) +ax.broken_barh(cpu_1, (-0.2, 0.4)) +ax.broken_barh(cpu_2, (0.8, 0.4)) +ax.broken_barh(cpu_3, (1.8, 0.4)) ax.broken_barh(cpu_4, (2.8, 0.4)) -ax.broken_barh(disk, (1.8, 0.4), color="tab:orange") -ax.broken_barh(network, (0.8, 0.4), color="tab:green") +ax.broken_barh(disk, (3.8, 0.4), color="tab:orange") +ax.broken_barh(network, (4.8, 0.4), color="tab:green") ax.set_xlim(0, 10) -ax.set_yticks([6, 5, 4, 3, 2, 1], +ax.set_yticks(range(6), labels=["CPU 1", "CPU 2", "CPU 3", "CPU 4", "disk", "network"]) +ax.invert_yaxis() ax.set_title("Resource usage") plt.show() - # %% +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.broken_barh` / `matplotlib.pyplot.broken_barh` +# - `matplotlib.axes.Axes.invert_yaxis` +# - `matplotlib.axes.Axes.set_yticks` +# # .. tags:: # # component: annotation From edf807667a60118a6fb3e31c4ea276c8e2826fce Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 31 Jan 2025 07:53:01 -0500 Subject: [PATCH 36/73] Backport PR #29546: FIX: pyplot.matshow figure handling --- lib/matplotlib/pyplot.py | 18 +++++++++++------- lib/matplotlib/tests/test_pyplot.py | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 12aedf5157ca..48aea1b3bd9c 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -994,8 +994,8 @@ def figure( root_fig = num.get_figure(root=True) if root_fig.canvas.manager is None: raise ValueError("The passed figure is not managed by pyplot") - elif any([figsize, dpi, facecolor, edgecolor, not frameon, - kwargs]) and root_fig.canvas.manager.num in allnums: + elif (any(param is not None for param in [figsize, dpi, facecolor, edgecolor]) + or not frameon or kwargs) and root_fig.canvas.manager.num in allnums: _api.warn_external( "Ignoring specified arguments in this call because figure " f"with num: {root_fig.canvas.manager.num} already exists") @@ -1007,8 +1007,8 @@ def figure( if num is None: num = next_num else: - if any([figsize, dpi, facecolor, edgecolor, not frameon, - kwargs]) and num in allnums: + if (any(param is not None for param in [figsize, dpi, facecolor, edgecolor]) + or not frameon or kwargs) and num in allnums: _api.warn_external( "Ignoring specified arguments in this call " f"because figure with num: {num} already exists") @@ -2662,9 +2662,13 @@ def matshow(A: ArrayLike, fignum: None | int = None, **kwargs) -> AxesImage: if fignum == 0: ax = gca() else: - # Extract actual aspect ratio of array and make appropriately sized - # figure. - fig = figure(fignum, figsize=figaspect(A)) + if fignum is not None and fignum_exists(fignum): + # Do not try to set a figure size. + figsize = None + else: + # Extract actual aspect ratio of array and make appropriately sized figure. + figsize = figaspect(A) + fig = figure(fignum, figsize=figsize) ax = fig.add_axes((0.15, 0.09, 0.775, 0.775)) im = ax.matshow(A, **kwargs) sci(im) diff --git a/lib/matplotlib/tests/test_pyplot.py b/lib/matplotlib/tests/test_pyplot.py index 21036e177045..1aaa8dd93ca2 100644 --- a/lib/matplotlib/tests/test_pyplot.py +++ b/lib/matplotlib/tests/test_pyplot.py @@ -459,13 +459,13 @@ def test_figure_hook(): def test_multiple_same_figure_calls(): - fig = mpl.pyplot.figure(1, figsize=(1, 2)) + fig = plt.figure(1, figsize=(1, 2)) with pytest.warns(UserWarning, match="Ignoring specified arguments in this call"): - fig2 = mpl.pyplot.figure(1, figsize=(3, 4)) + fig2 = plt.figure(1, figsize=np.array([3, 4])) with pytest.warns(UserWarning, match="Ignoring specified arguments in this call"): - mpl.pyplot.figure(fig, figsize=(5, 6)) + plt.figure(fig, figsize=np.array([5, 6])) assert fig is fig2 - fig3 = mpl.pyplot.figure(1) # Checks for false warnings + fig3 = plt.figure(1) # Checks for false warnings assert fig is fig3 @@ -475,3 +475,11 @@ def test_close_all_warning(): # Check that the warning is issued when 'all' is passed to plt.figure with pytest.warns(UserWarning, match="closes all existing figures"): fig2 = plt.figure("all") + + +def test_matshow(): + fig = plt.figure() + arr = [[0, 1], [1, 2]] + + # Smoke test that matshow does not ask for a new figsize on the existing figure + plt.matshow(arr, fignum=fig.number) From a04d1144af69201763da026032d32884f421f7c4 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 31 Jan 2025 07:23:12 -0500 Subject: [PATCH 37/73] Backport PR #29518: TST: Increase tolerance on more arches Merge pull request #29518 from QuLogic/arch-tolerance TST: Increase tolerance on more arches (cherry picked from commit 8c3f4eca28ddc7e47675cfeafe38ca6c85853313) --- lib/matplotlib/tests/test_arrow_patches.py | 4 +- lib/matplotlib/tests/test_axes.py | 37 +++++++++---------- lib/matplotlib/tests/test_bbox_tight.py | 2 +- lib/matplotlib/tests/test_collections.py | 2 +- .../tests/test_constrainedlayout.py | 2 +- lib/matplotlib/tests/test_contour.py | 8 ++-- lib/matplotlib/tests/test_figure.py | 2 +- lib/matplotlib/tests/test_legend.py | 8 ++-- lib/matplotlib/tests/test_lines.py | 7 ++-- lib/matplotlib/tests/test_patches.py | 4 +- lib/matplotlib/tests/test_path.py | 4 +- lib/matplotlib/tests/test_patheffects.py | 5 ++- lib/matplotlib/tests/test_simplification.py | 2 +- lib/matplotlib/tests/test_skew.py | 2 +- lib/matplotlib/tests/test_subplots.py | 2 +- .../axes_grid1/tests/test_axes_grid1.py | 2 +- lib/mpl_toolkits/mplot3d/tests/test_axes3d.py | 9 ++--- .../mplot3d/tests/test_legend3d.py | 2 +- 18 files changed, 50 insertions(+), 54 deletions(-) diff --git a/lib/matplotlib/tests/test_arrow_patches.py b/lib/matplotlib/tests/test_arrow_patches.py index 254b86cb54d6..431d1eb6eaf6 100644 --- a/lib/matplotlib/tests/test_arrow_patches.py +++ b/lib/matplotlib/tests/test_arrow_patches.py @@ -12,7 +12,7 @@ def draw_arrow(ax, t, r): @image_comparison(['fancyarrow_test_image'], - tol=0.012 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.012) def test_fancyarrow(): # Added 0 to test division by zero error described in issue 3930 r = [0.4, 0.3, 0.2, 0.1, 0] @@ -149,7 +149,7 @@ def test_arrow_styles(): @image_comparison(['connection_styles.png'], style='mpl20', remove_text=True, - tol=0.013 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.013) def test_connection_styles(): styles = mpatches.ConnectionStyle.get_styles() diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 435a1462d2ee..cd5cd08fbf74 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -243,7 +243,7 @@ def test_matshow(fig_test, fig_ref): 'formatter_ticker_004', 'formatter_ticker_005', ], - tol=0.031 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.031) def test_formatter_ticker(): import matplotlib.testing.jpl_units as units units.register() @@ -444,7 +444,7 @@ def test_twin_logscale(fig_test, fig_ref, twin): @image_comparison(['twin_autoscale.png'], - tol=0.009 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.009) def test_twinx_axis_scales(): x = np.array([0, 0.5, 1]) y = 0.5 * x @@ -1218,9 +1218,8 @@ def test_imshow(): ax.imshow("r", data=data) -@image_comparison( - ['imshow_clip'], style='mpl20', - tol=1.24 if platform.machine() in ('aarch64', 'arm64', 'ppc64le', 's390x') else 0) +@image_comparison(['imshow_clip'], style='mpl20', + tol=0 if platform.machine() == 'x86_64' else 1.24) def test_imshow_clip(): # As originally reported by Gellule Xg # use former defaults to match existing baseline image @@ -1299,7 +1298,7 @@ def test_fill_betweenx_input(y, x1, x2): @image_comparison(['fill_between_interpolate'], remove_text=True, - tol=0.012 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.012) def test_fill_between_interpolate(): x = np.arange(0.0, 2, 0.02) y1 = np.sin(2*np.pi*x) @@ -1727,7 +1726,8 @@ def test_pcolorauto(fig_test, fig_ref, snap): ax.pcolormesh(x2, y2, Z, snap=snap) -@image_comparison(['canonical'], tol=0.02 if platform.machine() == 'arm64' else 0) +@image_comparison(['canonical'], + tol=0 if platform.machine() == 'x86_64' else 0.02) def test_canonical(): fig, ax = plt.subplots() ax.plot([1, 2, 3]) @@ -2652,9 +2652,8 @@ def test_contour_hatching(): extend='both', alpha=0.5) -@image_comparison( - ['contour_colorbar'], style='mpl20', - tol=0.54 if platform.machine() in ('aarch64', 'arm64', 'ppc64le', 's390x') else 0) +@image_comparison(['contour_colorbar'], style='mpl20', + tol=0 if platform.machine() == 'x86_64' else 0.54) def test_contour_colorbar(): x, y, z = contour_dat() @@ -3232,7 +3231,7 @@ def test_log_scales_invalid(): @image_comparison(['stackplot_test_image', 'stackplot_test_image'], - tol=0.031 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.031) def test_stackplot(): fig = plt.figure() x = np.linspace(0, 10, 10) @@ -5126,7 +5125,7 @@ def test_marker_styles(): @image_comparison(['rc_markerfill.png'], - tol=0.037 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.037) def test_markers_fillstyle_rcparams(): fig, ax = plt.subplots() x = np.arange(7) @@ -5709,7 +5708,7 @@ def test_twin_remove(fig_test, fig_ref): @image_comparison(['twin_spines.png'], remove_text=True, - tol=0.022 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.022) def test_twin_spines(): def make_patch_spines_invisible(ax): @@ -6306,7 +6305,7 @@ def test_pie_hatch_multi(fig_test, fig_ref): @image_comparison(['set_get_ticklabels.png'], - tol=0.025 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.025) def test_set_get_ticklabels(): # test issue 2246 fig, ax = plt.subplots(2) @@ -6899,7 +6898,7 @@ def test_loglog(): @image_comparison(["test_loglog_nonpos.png"], remove_text=True, style='mpl20', - tol=0.029 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.029) def test_loglog_nonpos(): fig, axs = plt.subplots(3, 3) x = np.arange(1, 11) @@ -7839,7 +7838,7 @@ def test_scatter_empty_data(): @image_comparison(['annotate_across_transforms.png'], style='mpl20', remove_text=True, - tol=0.025 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.025) def test_annotate_across_transforms(): x = np.linspace(0, 10, 200) y = np.exp(-x) * np.sin(x) @@ -7870,7 +7869,7 @@ def inverted(self): @image_comparison(['secondary_xy.png'], style='mpl20', - tol=0.027 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.027) def test_secondary_xy(): fig, axs = plt.subplots(1, 2, figsize=(10, 5), constrained_layout=True) @@ -9134,7 +9133,7 @@ def test_zorder_and_explicit_rasterization(): @image_comparison(["preset_clip_paths.png"], remove_text=True, style="mpl20", - tol=0.027 if platform.machine() in ("arm64", "ppc64le") else 0) + tol=0 if platform.machine() == 'x86_64' else 0.027) def test_preset_clip_paths(): fig, ax = plt.subplots() @@ -9467,7 +9466,7 @@ def test_boxplot_orientation(fig_test, fig_ref): @image_comparison(["use_colorizer_keyword.png"], - tol=0.05 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.05) def test_use_colorizer_keyword(): # test using the colorizer keyword np.random.seed(0) diff --git a/lib/matplotlib/tests/test_bbox_tight.py b/lib/matplotlib/tests/test_bbox_tight.py index 5f2b397b650d..7a2809931757 100644 --- a/lib/matplotlib/tests/test_bbox_tight.py +++ b/lib/matplotlib/tests/test_bbox_tight.py @@ -45,7 +45,7 @@ def test_bbox_inches_tight(): @image_comparison(['bbox_inches_tight_suptile_legend'], savefig_kwarg={'bbox_inches': 'tight'}, - tol=0.02 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.02) def test_bbox_inches_tight_suptile_legend(): plt.plot(np.arange(10), label='a straight line') plt.legend(bbox_to_anchor=(0.9, 1), loc='upper left') diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index 11934cfca2c3..db9c4be81a44 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -391,7 +391,7 @@ def test_barb_limits(): @image_comparison(['EllipseCollection_test_image.png'], remove_text=True, - tol=0.021 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.021) def test_EllipseCollection(): # Test basic functionality fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_constrainedlayout.py b/lib/matplotlib/tests/test_constrainedlayout.py index e42e2ee9bfd8..77f9f34bc2d8 100644 --- a/lib/matplotlib/tests/test_constrainedlayout.py +++ b/lib/matplotlib/tests/test_constrainedlayout.py @@ -198,7 +198,7 @@ def test_constrained_layout9(): @image_comparison(['constrained_layout10.png'], - tol=0.032 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.032) def test_constrained_layout10(): """Test for handling legend outside axis""" fig, axs = plt.subplots(2, 2, layout="constrained") diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index e0ea82973af7..543cff18c697 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -140,7 +140,7 @@ def test_contour_label_with_disconnected_segments(): @image_comparison(['contour_manual_colors_and_levels.png'], remove_text=True, - tol=0.018 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.018) def test_given_colors_levels_and_extends(): # Remove this line when this test image is regenerated. plt.rcParams['pcolormesh.snap'] = False @@ -416,10 +416,8 @@ def test_contourf_log_extension(): cb = plt.colorbar(c3, ax=ax3) -@image_comparison( - ['contour_addlines.png'], remove_text=True, style='mpl20', - tol=0.15 if platform.machine() in ('aarch64', 'arm64', 'ppc64le', 's390x') - else 0.03) +@image_comparison(['contour_addlines.png'], remove_text=True, style='mpl20', + tol=0.03 if platform.machine() == 'x86_64' else 0.15) # tolerance is because image changed minutely when tick finding on # colorbars was cleaned up... def test_contour_addlines(): diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index edf5ea05f119..c80f53413181 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -210,7 +210,7 @@ def test_clf_keyword(): @image_comparison(['figure_today'], - tol=0.015 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.015) def test_figure(): # named figure support fig = plt.figure('today') diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 2d92db4008e4..8baa7bb0f7d9 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -140,7 +140,7 @@ def test_various_labels(): @image_comparison(['legend_labels_first.png'], remove_text=True, - tol=0.013 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.013) def test_labels_first(): # test labels to left of markers fig, ax = plt.subplots() @@ -151,7 +151,7 @@ def test_labels_first(): @image_comparison(['legend_multiple_keys.png'], remove_text=True, - tol=0.013 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.013) def test_multiple_keys(): # test legend entries with multiple keys fig, ax = plt.subplots() @@ -514,7 +514,7 @@ def test_figure_legend_outside(): @image_comparison(['legend_stackplot.png'], - tol=0.031 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.031) def test_legend_stackplot(): """Test legend for PolyCollection using stackplot.""" # related to #1341, #1943, and PR #3303 @@ -650,7 +650,7 @@ def test_empty_bar_chart_with_legend(): @image_comparison(['shadow_argument_types.png'], remove_text=True, style='mpl20', - tol=0.028 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.028) def test_shadow_argument_types(): # Test that different arguments for shadow work as expected fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_lines.py b/lib/matplotlib/tests/test_lines.py index ee8b5b4aaa9e..bbaea2510215 100644 --- a/lib/matplotlib/tests/test_lines.py +++ b/lib/matplotlib/tests/test_lines.py @@ -140,7 +140,7 @@ def test_valid_linestyles(): @image_comparison(['drawstyle_variants.png'], remove_text=True, - tol=0.03 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.03) def test_drawstyle_variants(): fig, axs = plt.subplots(6) dss = ["default", "steps-mid", "steps-pre", "steps-post", "steps", None] @@ -183,9 +183,8 @@ def test_set_drawstyle(): assert len(line.get_path().vertices) == len(x) -@image_comparison( - ['line_collection_dashes'], remove_text=True, style='mpl20', - tol=0 if platform.machine() == 'x86_64' else 0.65) +@image_comparison(['line_collection_dashes'], remove_text=True, style='mpl20', + tol=0 if platform.machine() == 'x86_64' else 0.65) def test_set_line_coll_dash_image(): fig, ax = plt.subplots() np.random.seed(0) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 9cb67616a96b..2ea0df2540eb 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -438,7 +438,7 @@ def test_wedge_movement(): @image_comparison(['wedge_range'], remove_text=True, - tol=0.009 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.009) def test_wedge_range(): ax = plt.axes() @@ -564,7 +564,7 @@ def test_units_rectangle(): @image_comparison(['connection_patch.png'], style='mpl20', remove_text=True, - tol=0.024 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.024) def test_connection_patch(): fig, (ax1, ax2) = plt.subplots(1, 2) diff --git a/lib/matplotlib/tests/test_path.py b/lib/matplotlib/tests/test_path.py index 2c4df6ea3b39..5424160dad93 100644 --- a/lib/matplotlib/tests/test_path.py +++ b/lib/matplotlib/tests/test_path.py @@ -151,7 +151,7 @@ def test_nonlinear_containment(): @image_comparison(['arrow_contains_point.png'], remove_text=True, style='mpl20', - tol=0.027 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.027) def test_arrow_contains_point(): # fix bug (#8384) fig, ax = plt.subplots() @@ -283,7 +283,7 @@ def test_marker_paths_pdf(): @image_comparison(['nan_path'], style='default', remove_text=True, extensions=['pdf', 'svg', 'eps', 'png'], - tol=0.009 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.009) def test_nan_isolated_points(): y0 = [0, np.nan, 2, np.nan, 4, 5, 6] diff --git a/lib/matplotlib/tests/test_patheffects.py b/lib/matplotlib/tests/test_patheffects.py index bf067b2abbfd..6c89d1c531e0 100644 --- a/lib/matplotlib/tests/test_patheffects.py +++ b/lib/matplotlib/tests/test_patheffects.py @@ -30,7 +30,7 @@ def test_patheffect1(): @image_comparison(['patheffect2'], remove_text=True, style='mpl20', - tol=0.06 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.06) def test_patheffect2(): ax2 = plt.subplot() @@ -45,7 +45,8 @@ def test_patheffect2(): foreground="w")]) -@image_comparison(['patheffect3'], tol=0.019 if platform.machine() == 'arm64' else 0) +@image_comparison(['patheffect3'], + tol=0 if platform.machine() == 'x86_64' else 0.019) def test_patheffect3(): p1, = plt.plot([1, 3, 5, 4, 3], 'o-b', lw=4) p1.set_path_effects([path_effects.SimpleLineShadow(), diff --git a/lib/matplotlib/tests/test_simplification.py b/lib/matplotlib/tests/test_simplification.py index a052c24cb655..58b4d7a9b24f 100644 --- a/lib/matplotlib/tests/test_simplification.py +++ b/lib/matplotlib/tests/test_simplification.py @@ -29,7 +29,7 @@ def test_clipping(): @image_comparison(['overflow'], remove_text=True, - tol=0.007 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.007) def test_overflow(): x = np.array([1.0, 2.0, 3.0, 2.0e5]) y = np.arange(len(x)) diff --git a/lib/matplotlib/tests/test_skew.py b/lib/matplotlib/tests/test_skew.py index fd7e7cebfacb..20ec6bf32b06 100644 --- a/lib/matplotlib/tests/test_skew.py +++ b/lib/matplotlib/tests/test_skew.py @@ -146,7 +146,7 @@ def test_set_line_coll_dash_image(): @image_comparison(['skew_rects'], remove_text=True, - tol=0.009 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.009) def test_skew_rectangle(): fix, axes = plt.subplots(5, 5, sharex=True, sharey=True, figsize=(8, 8)) diff --git a/lib/matplotlib/tests/test_subplots.py b/lib/matplotlib/tests/test_subplots.py index 70215c9531ba..9fd887831106 100644 --- a/lib/matplotlib/tests/test_subplots.py +++ b/lib/matplotlib/tests/test_subplots.py @@ -175,7 +175,7 @@ def test_exceptions(): @image_comparison(['subplots_offset_text'], - tol=0.028 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.028) def test_subplots_offsettext(): x = np.arange(0, 1e10, 1e9) y = np.arange(0, 100, 10)+1e4 diff --git a/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py b/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py index 778bd9ca04d0..b045e8dc8756 100644 --- a/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py +++ b/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py @@ -346,7 +346,7 @@ def test_fill_facecolor(): # Update style when regenerating the test image @image_comparison(['zoomed_axes.png', 'inverted_zoomed_axes.png'], style=('classic', '_classic_test_patch'), - tol=0.02 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.02) def test_zooming_with_inverted_axes(): fig, ax = plt.subplots() ax.plot([1, 2, 3], [1, 2, 3]) diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index ad952e4395af..b30c2556b105 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -221,9 +221,8 @@ def test_bar3d_lightsource(): np.testing.assert_array_max_ulp(color, collection._facecolor3d[1::6], 4) -@mpl3d_image_comparison( - ['contour3d.png'], style='mpl20', - tol=0.002 if platform.machine() in ('aarch64', 'arm64', 'ppc64le', 's390x') else 0) +@mpl3d_image_comparison(['contour3d.png'], style='mpl20', + tol=0 if platform.machine() == 'x86_64' else 0.002) def test_contour3d(): plt.rcParams['axes3d.automargin'] = True # Remove when image is regenerated fig = plt.figure() @@ -1713,7 +1712,7 @@ def test_errorbar3d_errorevery(): @mpl3d_image_comparison(['errorbar3d.png'], style='mpl20', - tol=0.02 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.02) def test_errorbar3d(): """Tests limits, color styling, and legend for 3D errorbars.""" fig = plt.figure() @@ -1729,7 +1728,7 @@ def test_errorbar3d(): ax.legend() -@image_comparison(['stem3d.png'], style='mpl20', tol=0.008) +@image_comparison(['stem3d.png'], style='mpl20', tol=0.009) def test_stem3d(): plt.rcParams['axes3d.automargin'] = True # Remove when image is regenerated fig, axs = plt.subplots(2, 3, figsize=(8, 6), diff --git a/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py b/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py index 0935bbe7f6b0..7fd676df1e31 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py @@ -28,7 +28,7 @@ def test_legend_bar(): @image_comparison(['fancy.png'], remove_text=True, style='mpl20', - tol=0.011 if platform.machine() == 'arm64' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.011) def test_fancy(): fig, ax = plt.subplots(subplot_kw=dict(projection='3d')) ax.plot(np.arange(10), np.full(10, 5), np.full(10, 5), 'o--', label='line') From 75b7bdfceb3219dd002b107c230736d5ea8d1338 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 2 Feb 2025 17:24:11 +0100 Subject: [PATCH 38/73] Backport PR #29563: DOC: add color sequences reference example --- galleries/examples/color/color_sequences.py | 65 +++++++++++++++++++ .../color/individual_colors_from_cmap.py | 4 +- lib/matplotlib/colors.py | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 galleries/examples/color/color_sequences.py diff --git a/galleries/examples/color/color_sequences.py b/galleries/examples/color/color_sequences.py new file mode 100644 index 000000000000..9a2fd04a53d0 --- /dev/null +++ b/galleries/examples/color/color_sequences.py @@ -0,0 +1,65 @@ +""" +===================== +Named color sequences +===================== + +Matplotlib's `~matplotlib.colors.ColorSequenceRegistry` allows access to +predefined lists of colors by name e.g. +``colors = matplotlib.color_sequences['Set1']``. This example shows all of the +built in color sequences. + +User-defined sequences can be added via `.ColorSequenceRegistry.register`. +""" + +import matplotlib.pyplot as plt +import numpy as np + +import matplotlib as mpl + + +def plot_color_sequences(names, ax): + # Display each named color sequence horizontally on the supplied axes. + + for n, name in enumerate(names): + colors = mpl.color_sequences[name] + n_colors = len(colors) + x = np.arange(n_colors) + y = np.full_like(x, n) + + ax.scatter(x, y, facecolor=colors, edgecolor='dimgray', s=200, zorder=2) + + ax.set_yticks(range(len(names)), labels=names) + ax.grid(visible=True, axis='y') + ax.yaxis.set_inverted(True) + ax.xaxis.set_visible(False) + ax.spines[:].set_visible(False) + ax.tick_params(left=False) + + +built_in_color_sequences = [ + 'tab10', 'tab20', 'tab20b', 'tab20c', 'Pastel1', 'Pastel2', 'Paired', + 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', 'petroff10'] + + +fig, ax = plt.subplots(figsize=(6.4, 9.6), layout='constrained') + +plot_color_sequences(built_in_color_sequences, ax) +ax.set_title('Built In Color Sequences') + +plt.show() + + +# %% +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.colors.ColorSequenceRegistry` +# - `matplotlib.axes.Axes.scatter` +# +# .. tags:: +# +# styling: color +# purpose: reference diff --git a/galleries/examples/color/individual_colors_from_cmap.py b/galleries/examples/color/individual_colors_from_cmap.py index cdd176eb3be1..8d2b41eb02fb 100644 --- a/galleries/examples/color/individual_colors_from_cmap.py +++ b/galleries/examples/color/individual_colors_from_cmap.py @@ -38,7 +38,9 @@ # Extracting colors from a discrete colormap # ------------------------------------------ # The list of all colors in a `.ListedColormap` is available as the ``colors`` -# attribute. +# attribute. Note that all the colors from Matplotlib's qualitative color maps +# are also available as color sequences, so may be accessed more directly from +# the color sequence registry. See :doc:`/gallery/color/color_sequences`. colors = mpl.colormaps['Dark2'].colors diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index e881af04508c..aa53b575b737 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -108,6 +108,7 @@ class ColorSequenceRegistry(Mapping): import matplotlib as mpl colors = mpl.color_sequences['tab10'] + For a list of built in color sequences, see :doc:`/gallery/color/color_sequences`. The returned lists are copies, so that their modification does not change the global definition of the color sequence. From c56f44d075f8f262a712ecd2001e50a141a27f71 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:40:45 +0000 Subject: [PATCH 39/73] Backport PR #29576: Remove documentation for no-longer existent ContourSet attributes. --- lib/matplotlib/contour.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 6b685fa0ed6a..f7318d578121 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -539,13 +539,6 @@ def _find_closest_point_on_path(xys, p): _docstring.interpd.register(contour_set_attributes=r""" Attributes ---------- -ax : `~matplotlib.axes.Axes` - The Axes object in which the contours are drawn. - -collections : `.silent_list` of `.PathCollection`\s - The `.Artist`\s representing the contour. This is a list of - `.PathCollection`\s for both line and filled contours. - levels : array The values of the contour levels. From a71b43482409692832cb089b6e219dffac05527e Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 6 Feb 2025 22:15:08 -0500 Subject: [PATCH 40/73] Backport PR #25801: Remove some examples from Userdemo --- doc/users/prev_whats_new/whats_new_1.0.rst | 4 ++-- .../gridspec_customization.py} | 8 +++++--- .../subplot2grid.py} | 11 +++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) rename galleries/examples/{userdemo/demo_gridspec03.py => subplots_axes_and_figures/gridspec_customization.py} (88%) rename galleries/examples/{userdemo/demo_gridspec01.py => subplots_axes_and_figures/subplot2grid.py} (77%) diff --git a/doc/users/prev_whats_new/whats_new_1.0.rst b/doc/users/prev_whats_new/whats_new_1.0.rst index c8da886c9097..772f241f4b23 100644 --- a/doc/users/prev_whats_new/whats_new_1.0.rst +++ b/doc/users/prev_whats_new/whats_new_1.0.rst @@ -26,8 +26,8 @@ doing complex subplot layouts, featuring row and column spans and more. See :ref:`arranging_axes` for a tutorial overview. -.. figure:: ../../gallery/userdemo/images/sphx_glr_demo_gridspec01_001.png - :target: ../../gallery/userdemo/demo_gridspec01.html +.. figure:: ../../gallery/subplots_axes_and_figures/images/sphx_glr_subplot2grid_001.png + :target: ../../gallery/subplots_axes_and_figures/subplot2grid.html :align: center :scale: 50 diff --git a/galleries/examples/userdemo/demo_gridspec03.py b/galleries/examples/subplots_axes_and_figures/gridspec_customization.py similarity index 88% rename from galleries/examples/userdemo/demo_gridspec03.py rename to galleries/examples/subplots_axes_and_figures/gridspec_customization.py index 63951ef7d563..08b2dfd45474 100644 --- a/galleries/examples/userdemo/demo_gridspec03.py +++ b/galleries/examples/subplots_axes_and_figures/gridspec_customization.py @@ -1,13 +1,15 @@ """ -============= -GridSpec demo -============= +======================================== +GridSpec with variable sizes and spacing +======================================== This example demonstrates the use of `.GridSpec` to generate subplots, the control of the relative sizes of subplots with *width_ratios* and *height_ratios*, and the control of the spacing around and between subplots using subplot params (*left*, *right*, *bottom*, *top*, *wspace*, and *hspace*). + +.. redirect-from:: /gallery/userdemo/demo_gridspec03 """ import matplotlib.pyplot as plt diff --git a/galleries/examples/userdemo/demo_gridspec01.py b/galleries/examples/subplots_axes_and_figures/subplot2grid.py similarity index 77% rename from galleries/examples/userdemo/demo_gridspec01.py rename to galleries/examples/subplots_axes_and_figures/subplot2grid.py index 7153b136f080..cd500ccf65b2 100644 --- a/galleries/examples/userdemo/demo_gridspec01.py +++ b/galleries/examples/subplots_axes_and_figures/subplot2grid.py @@ -1,11 +1,14 @@ """ -================= -subplot2grid demo -================= +============ +subplot2grid +============ This example demonstrates the use of `.pyplot.subplot2grid` to generate subplots. Using `.GridSpec`, as demonstrated in -:doc:`/gallery/userdemo/demo_gridspec03` is generally preferred. +:doc:`/gallery/subplots_axes_and_figures/gridspec_customization` is +generally preferred. + +.. redirect-from:: /gallery/userdemo/demo_gridspec01 """ import matplotlib.pyplot as plt From f15ad26829373c0eab6441ec4990cccf7c0074a4 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 6 Feb 2025 22:15:08 -0500 Subject: [PATCH 41/73] Backport PR #25801: Remove some examples from Userdemo --- doc/users/prev_whats_new/whats_new_1.0.rst | 4 ++-- .../gridspec_customization.py} | 8 +++++--- .../subplot2grid.py} | 11 +++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) rename galleries/examples/{userdemo/demo_gridspec03.py => subplots_axes_and_figures/gridspec_customization.py} (88%) rename galleries/examples/{userdemo/demo_gridspec01.py => subplots_axes_and_figures/subplot2grid.py} (77%) diff --git a/doc/users/prev_whats_new/whats_new_1.0.rst b/doc/users/prev_whats_new/whats_new_1.0.rst index c8da886c9097..772f241f4b23 100644 --- a/doc/users/prev_whats_new/whats_new_1.0.rst +++ b/doc/users/prev_whats_new/whats_new_1.0.rst @@ -26,8 +26,8 @@ doing complex subplot layouts, featuring row and column spans and more. See :ref:`arranging_axes` for a tutorial overview. -.. figure:: ../../gallery/userdemo/images/sphx_glr_demo_gridspec01_001.png - :target: ../../gallery/userdemo/demo_gridspec01.html +.. figure:: ../../gallery/subplots_axes_and_figures/images/sphx_glr_subplot2grid_001.png + :target: ../../gallery/subplots_axes_and_figures/subplot2grid.html :align: center :scale: 50 diff --git a/galleries/examples/userdemo/demo_gridspec03.py b/galleries/examples/subplots_axes_and_figures/gridspec_customization.py similarity index 88% rename from galleries/examples/userdemo/demo_gridspec03.py rename to galleries/examples/subplots_axes_and_figures/gridspec_customization.py index 63951ef7d563..08b2dfd45474 100644 --- a/galleries/examples/userdemo/demo_gridspec03.py +++ b/galleries/examples/subplots_axes_and_figures/gridspec_customization.py @@ -1,13 +1,15 @@ """ -============= -GridSpec demo -============= +======================================== +GridSpec with variable sizes and spacing +======================================== This example demonstrates the use of `.GridSpec` to generate subplots, the control of the relative sizes of subplots with *width_ratios* and *height_ratios*, and the control of the spacing around and between subplots using subplot params (*left*, *right*, *bottom*, *top*, *wspace*, and *hspace*). + +.. redirect-from:: /gallery/userdemo/demo_gridspec03 """ import matplotlib.pyplot as plt diff --git a/galleries/examples/userdemo/demo_gridspec01.py b/galleries/examples/subplots_axes_and_figures/subplot2grid.py similarity index 77% rename from galleries/examples/userdemo/demo_gridspec01.py rename to galleries/examples/subplots_axes_and_figures/subplot2grid.py index 7153b136f080..cd500ccf65b2 100644 --- a/galleries/examples/userdemo/demo_gridspec01.py +++ b/galleries/examples/subplots_axes_and_figures/subplot2grid.py @@ -1,11 +1,14 @@ """ -================= -subplot2grid demo -================= +============ +subplot2grid +============ This example demonstrates the use of `.pyplot.subplot2grid` to generate subplots. Using `.GridSpec`, as demonstrated in -:doc:`/gallery/userdemo/demo_gridspec03` is generally preferred. +:doc:`/gallery/subplots_axes_and_figures/gridspec_customization` is +generally preferred. + +.. redirect-from:: /gallery/userdemo/demo_gridspec01 """ import matplotlib.pyplot as plt From 134ef5a943a7e30b7359d9ad403584c8c8f30ddc Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Fri, 7 Feb 2025 20:20:51 +0000 Subject: [PATCH 42/73] Backport PR #29585: DOC: Document that tight_layout may not converge --- galleries/users_explain/axes/tight_layout_guide.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/galleries/users_explain/axes/tight_layout_guide.py b/galleries/users_explain/axes/tight_layout_guide.py index dcffa7437b94..455bb57de126 100644 --- a/galleries/users_explain/axes/tight_layout_guide.py +++ b/galleries/users_explain/axes/tight_layout_guide.py @@ -165,6 +165,10 @@ def example_plot(ax, fontsize=12): # a limitation of the current algorithm, and it is not clear why it # happens. Meanwhile, use of pad larger than 0.3 is recommended. # +# * The algorithm of ``tight_layout`` does not necessarily converge, +# i.e. calling ``tight_layout`` multiple times can lead to slight +# variations in the layout between the calls. +# # Use with GridSpec # ================= # From 4f5ceb7562af85a619227bc15a8fcbac4ddca919 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 10 Feb 2025 13:33:48 +0100 Subject: [PATCH 43/73] Backport PR #29597: Fix typo in deprecation notes for 3.10.0 --- doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst index ad344b37d069..013a5ff6ca8e 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst @@ -5,6 +5,7 @@ Many plotting functions will restrict positional arguments to the first few para in the future. All further configuration parameters will have to be passed as keyword arguments. This is to enforce better code and and allow for future changes with reduced risk of breaking existing code. + Changing ``Figure.number`` ~~~~~~~~~~~~~~~~~~~~~~~~~~ From 0c24a21734b0bcf28976e4d07deb0aeeba41ce8e Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 10 Feb 2025 13:33:48 +0100 Subject: [PATCH 44/73] Backport PR #29597: Fix typo in deprecation notes for 3.10.0 --- doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst index 2be32c30ea2f..383c19f3c811 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst @@ -9,6 +9,7 @@ Many plotting functions will restrict positional arguments to the first few para in the future. All further configuration parameters will have to be passed as keyword arguments. This is to enforce better code and and allow for future changes with reduced risk of breaking existing code. + Changing ``Figure.number`` ~~~~~~~~~~~~~~~~~~~~~~~~~~ From 466a46871ac3452131e637d48be7ebe5b5474382 Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 11 Feb 2025 13:54:19 -0500 Subject: [PATCH 45/73] Backport PR #29601: DOC: Duplicate catergorial values are mapped to the same position --- .../examples/lines_bars_and_markers/categorical_variables.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/galleries/examples/lines_bars_and_markers/categorical_variables.py b/galleries/examples/lines_bars_and_markers/categorical_variables.py index 4cceb38fbd4d..a19a30eda2b2 100644 --- a/galleries/examples/lines_bars_and_markers/categorical_variables.py +++ b/galleries/examples/lines_bars_and_markers/categorical_variables.py @@ -20,7 +20,10 @@ # %% -# This works on both Axes: +# Categorical values are a mapping from names to positions. This means that +# values that occur multiple times are mapped to the same position. See the +# ``cat`` and ``dog`` values "happy" and "bored" on the y-axis in the following +# example. cat = ["bored", "happy", "bored", "bored", "happy", "bored"] dog = ["happy", "happy", "happy", "happy", "bored", "bored"] From 71dd07bd3b021c3081efbd0f9439d295cc3d9580 Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 11 Feb 2025 13:54:19 -0500 Subject: [PATCH 46/73] Backport PR #29601: DOC: Duplicate catergorial values are mapped to the same position --- .../examples/lines_bars_and_markers/categorical_variables.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/galleries/examples/lines_bars_and_markers/categorical_variables.py b/galleries/examples/lines_bars_and_markers/categorical_variables.py index 4cceb38fbd4d..a19a30eda2b2 100644 --- a/galleries/examples/lines_bars_and_markers/categorical_variables.py +++ b/galleries/examples/lines_bars_and_markers/categorical_variables.py @@ -20,7 +20,10 @@ # %% -# This works on both Axes: +# Categorical values are a mapping from names to positions. This means that +# values that occur multiple times are mapped to the same position. See the +# ``cat`` and ``dog`` values "happy" and "bored" on the y-axis in the following +# example. cat = ["bored", "happy", "bored", "bored", "happy", "bored"] dog = ["happy", "happy", "happy", "happy", "bored", "bored"] From df643efae781e134a23d45e20b209768134c184c Mon Sep 17 00:00:00 2001 From: "G. D. McBain" Date: Wed, 12 Feb 2025 13:48:19 +1100 Subject: [PATCH 47/73] Backport PR #29607: Correct doc for axvline arg x which sets x not y --- 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 96946fba1e92..eebbdcaed459 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -823,7 +823,7 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs): Parameters ---------- x : float, default: 0 - y position in :ref:`data coordinates `. + x position in :ref:`data coordinates `. ymin : float, default: 0 The start y-position in :ref:`axes coordinates `. From 5f311c2189b15b3a0d0eab5653759ba3363575b6 Mon Sep 17 00:00:00 2001 From: "G. D. McBain" Date: Wed, 12 Feb 2025 13:48:19 +1100 Subject: [PATCH 48/73] Backport PR #29607: Correct doc for axvline arg x which sets x not y --- 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 679499a4eab3..b6d4aa50b2bc 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -823,7 +823,7 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs): Parameters ---------- x : float, default: 0 - y position in :ref:`data coordinates `. + x position in :ref:`data coordinates `. ymin : float, default: 0 The start y-position in :ref:`axes coordinates `. From 5b3d177e17cf813fe79e286d6399de3b5367c357 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 12 Feb 2025 10:21:11 -0500 Subject: [PATCH 49/73] Backport PR #29608: Remove md5 usage to prevent issues on FIPS enabled systems (closes #29603) --- lib/matplotlib/sphinxext/mathmpl.py | 5 ++++- lib/matplotlib/testing/compare.py | 12 +++++------- lib/matplotlib/texmanager.py | 5 ++++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/sphinxext/mathmpl.py b/lib/matplotlib/sphinxext/mathmpl.py index 3e0d562e2d15..30f024524258 100644 --- a/lib/matplotlib/sphinxext/mathmpl.py +++ b/lib/matplotlib/sphinxext/mathmpl.py @@ -146,7 +146,10 @@ def latex2html(node, source): fontset = node['fontset'] fontsize = node['fontsize'] name = 'math-{}'.format( - hashlib.md5(f'{latex}{fontset}{fontsize}'.encode()).hexdigest()[-10:]) + hashlib.sha256( + f'{latex}{fontset}{fontsize}'.encode(), + usedforsecurity=False, + ).hexdigest()[-10:]) destdir = Path(setup.app.builder.outdir, '_images', 'mathmpl') destdir.mkdir(parents=True, exist_ok=True) diff --git a/lib/matplotlib/testing/compare.py b/lib/matplotlib/testing/compare.py index 0f252bc1da8e..3aeddcbe2b5e 100644 --- a/lib/matplotlib/testing/compare.py +++ b/lib/matplotlib/testing/compare.py @@ -46,22 +46,20 @@ def get_cache_dir(): def get_file_hash(path, block_size=2 ** 20): - md5 = hashlib.md5() + sha256 = hashlib.sha256(usedforsecurity=False) with open(path, 'rb') as fd: while True: data = fd.read(block_size) if not data: break - md5.update(data) + sha256.update(data) if Path(path).suffix == '.pdf': - md5.update(str(mpl._get_executable_info("gs").version) - .encode('utf-8')) + sha256.update(str(mpl._get_executable_info("gs").version).encode('utf-8')) elif Path(path).suffix == '.svg': - md5.update(str(mpl._get_executable_info("inkscape").version) - .encode('utf-8')) + sha256.update(str(mpl._get_executable_info("inkscape").version).encode('utf-8')) - return md5.hexdigest() + return sha256.hexdigest() class _ConverterError(Exception): diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index a374bfba8cab..2083510396f1 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -168,7 +168,10 @@ def get_basefile(cls, tex, fontsize, dpi=None): Return a filename based on a hash of the string, fontsize, and dpi. """ src = cls._get_tex_source(tex, fontsize) + str(dpi) - filehash = hashlib.md5(src.encode('utf-8')).hexdigest() + filehash = hashlib.sha256( + src.encode('utf-8'), + usedforsecurity=False + ).hexdigest() filepath = Path(cls._texcache) num_letters, num_levels = 2, 2 From e1dbace478f869d51fa5a09afb873c06bf288ecf Mon Sep 17 00:00:00 2001 From: hannah Date: Thu, 13 Feb 2025 19:20:12 -0500 Subject: [PATCH 50/73] Backport PR #29616: FIX: Fix unit example so that we can unpin numpy<2.1 --- .circleci/config.yml | 2 +- environment.yml | 2 +- galleries/examples/units/basic_units.py | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e7348b868d4b..40ba933cf0d9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -98,7 +98,7 @@ commands: parameters: numpy_version: type: string - default: "~=2.0.0" + default: "" steps: - run: name: Install Python dependencies diff --git a/environment.yml b/environment.yml index 4a36f76031ea..8c4221d0a0fa 100644 --- a/environment.yml +++ b/environment.yml @@ -18,7 +18,7 @@ dependencies: - kiwisolver>=1.3.1 - pybind11>=2.13.2 - meson-python>=0.13.1 - - numpy<2.1 + - numpy - pillow>=8 - pkg-config - pygobject diff --git a/galleries/examples/units/basic_units.py b/galleries/examples/units/basic_units.py index 3f64d145b65e..486918a8eafc 100644 --- a/galleries/examples/units/basic_units.py +++ b/galleries/examples/units/basic_units.py @@ -193,6 +193,11 @@ def get_unit(self): class BasicUnit: + # numpy scalars convert eager and np.float64(2) * BasicUnit('cm') + # would thus return a numpy scalar. To avoid this, we increase the + # priority of the BasicUnit. + __array_priority__ = np.float64(0).__array_priority__ + 1 + def __init__(self, name, fullname=None): self.name = name if fullname is None: From eb5eb5b26ff4c3ee01c37d0f02374a717f45a4c1 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Fri, 14 Feb 2025 16:13:28 +0000 Subject: [PATCH 51/73] Backport PR #29621: DOC: Cleanup text rotation in data coordinates example --- .../text_rotation_relative_to_line.py | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py b/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py index ae29385e8a6d..78bc9a647af9 100644 --- a/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py +++ b/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py @@ -15,28 +15,18 @@ """ import matplotlib.pyplot as plt -import numpy as np fig, ax = plt.subplots() -# Plot diagonal line (45 degrees) -h = ax.plot(range(0, 10), range(0, 10)) - -# set limits so that it no longer looks on screen to be 45 degrees -ax.set_xlim([-10, 20]) - -# Locations to plot text -l1 = np.array((1, 1)) -l2 = np.array((5, 5)) - -# Rotate angle -angle = 45 +# Plot diagonal line (45 degrees in data coordinates) +ax.plot(range(0, 8), range(0, 8)) +ax.set_xlim([-10, 10]) # Plot text -th1 = ax.text(*l1, 'text not rotated correctly', fontsize=16, - rotation=angle, rotation_mode='anchor') -th2 = ax.text(*l2, 'text rotated correctly', fontsize=16, - rotation=angle, rotation_mode='anchor', - transform_rotates_text=True) +ax.text(-8, 0, 'text 45° in screen coordinates', fontsize=18, + rotation=45, rotation_mode='anchor') +ax.text(0, 0, 'text 45° in data coordinates', fontsize=18, + rotation=45, rotation_mode='anchor', + transform_rotates_text=True) plt.show() From 6314d30e4cad3b0437ad10b85b8bf5eff64f7f44 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Fri, 14 Feb 2025 16:13:28 +0000 Subject: [PATCH 52/73] Backport PR #29621: DOC: Cleanup text rotation in data coordinates example --- .../text_rotation_relative_to_line.py | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py b/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py index ae29385e8a6d..78bc9a647af9 100644 --- a/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py +++ b/galleries/examples/text_labels_and_annotations/text_rotation_relative_to_line.py @@ -15,28 +15,18 @@ """ import matplotlib.pyplot as plt -import numpy as np fig, ax = plt.subplots() -# Plot diagonal line (45 degrees) -h = ax.plot(range(0, 10), range(0, 10)) - -# set limits so that it no longer looks on screen to be 45 degrees -ax.set_xlim([-10, 20]) - -# Locations to plot text -l1 = np.array((1, 1)) -l2 = np.array((5, 5)) - -# Rotate angle -angle = 45 +# Plot diagonal line (45 degrees in data coordinates) +ax.plot(range(0, 8), range(0, 8)) +ax.set_xlim([-10, 10]) # Plot text -th1 = ax.text(*l1, 'text not rotated correctly', fontsize=16, - rotation=angle, rotation_mode='anchor') -th2 = ax.text(*l2, 'text rotated correctly', fontsize=16, - rotation=angle, rotation_mode='anchor', - transform_rotates_text=True) +ax.text(-8, 0, 'text 45° in screen coordinates', fontsize=18, + rotation=45, rotation_mode='anchor') +ax.text(0, 0, 'text 45° in data coordinates', fontsize=18, + rotation=45, rotation_mode='anchor', + transform_rotates_text=True) plt.show() From 1af4b2e485673cb462d7de7e4877c41661e4aaa6 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 14 Feb 2025 22:04:45 +0100 Subject: [PATCH 53/73] Backport PR #29622: DOC: Move "Infinite lines" example from section "pyplot" to "Lines, bars and markers --- .../axline.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) rename galleries/examples/{pyplots => lines_bars_and_markers}/axline.py (64%) diff --git a/galleries/examples/pyplots/axline.py b/galleries/examples/lines_bars_and_markers/axline.py similarity index 64% rename from galleries/examples/pyplots/axline.py rename to galleries/examples/lines_bars_and_markers/axline.py index 71c9994072a1..11e8c646fe41 100644 --- a/galleries/examples/pyplots/axline.py +++ b/galleries/examples/lines_bars_and_markers/axline.py @@ -9,6 +9,8 @@ sigmoid function. `~.axes.Axes.axline` draws infinite straight lines in arbitrary directions. + +.. redirect-from:: /gallery/pyplot/axline """ import matplotlib.pyplot as plt @@ -17,28 +19,28 @@ t = np.linspace(-10, 10, 100) sig = 1 / (1 + np.exp(-t)) -plt.axhline(y=0, color="black", linestyle="--") -plt.axhline(y=0.5, color="black", linestyle=":") -plt.axhline(y=1.0, color="black", linestyle="--") -plt.axvline(color="grey") -plt.axline((0, 0.5), slope=0.25, color="black", linestyle=(0, (5, 5))) -plt.plot(t, sig, linewidth=2, label=r"$\sigma(t) = \frac{1}{1 + e^{-t}}$") -plt.xlim(-10, 10) -plt.xlabel("t") -plt.legend(fontsize=14) +fig, ax = plt.subplots() +ax.axhline(y=0, color="black", linestyle="--") +ax.axhline(y=0.5, color="black", linestyle=":") +ax.axhline(y=1.0, color="black", linestyle="--") +ax.axvline(color="grey") +ax.axline((0, 0.5), slope=0.25, color="black", linestyle=(0, (5, 5))) +ax.plot(t, sig, linewidth=2, label=r"$\sigma(t) = \frac{1}{1 + e^{-t}}$") +ax.set(xlim=(-10, 10), xlabel="t") +ax.legend(fontsize=14) plt.show() # %% -# `~.axes.Axes.axline` can also be used with a ``transform`` parameter, which +# `~.axes.Axes.axline` can also be used with a *transform* parameter, which # applies to the point, but not to the slope. This can be useful for drawing # diagonal grid lines with a fixed slope, which stay in place when the # plot limits are moved. +fig, ax = plt.subplots() for pos in np.linspace(-2, 1, 10): - plt.axline((pos, 0), slope=0.5, color='k', transform=plt.gca().transAxes) + ax.axline((pos, 0), slope=0.5, color='k', transform=ax.transAxes) -plt.ylim([0, 1]) -plt.xlim([0, 1]) +ax.set(xlim=(0, 1), ylim=(0, 1)) plt.show() # %% @@ -57,3 +59,5 @@ # # `~.Axes.axhspan`, `~.Axes.axvspan` draw rectangles that span the Axes in one # direction and are bounded in the other direction. +# +# .. tags:: component: annotation From a20f40edaa8f80477d4d48fa854918db5bf71003 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 14 Feb 2025 22:04:45 +0100 Subject: [PATCH 54/73] Backport PR #29622: DOC: Move "Infinite lines" example from section "pyplot" to "Lines, bars and markers --- .../axline.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) rename galleries/examples/{pyplots => lines_bars_and_markers}/axline.py (64%) diff --git a/galleries/examples/pyplots/axline.py b/galleries/examples/lines_bars_and_markers/axline.py similarity index 64% rename from galleries/examples/pyplots/axline.py rename to galleries/examples/lines_bars_and_markers/axline.py index 71c9994072a1..11e8c646fe41 100644 --- a/galleries/examples/pyplots/axline.py +++ b/galleries/examples/lines_bars_and_markers/axline.py @@ -9,6 +9,8 @@ sigmoid function. `~.axes.Axes.axline` draws infinite straight lines in arbitrary directions. + +.. redirect-from:: /gallery/pyplot/axline """ import matplotlib.pyplot as plt @@ -17,28 +19,28 @@ t = np.linspace(-10, 10, 100) sig = 1 / (1 + np.exp(-t)) -plt.axhline(y=0, color="black", linestyle="--") -plt.axhline(y=0.5, color="black", linestyle=":") -plt.axhline(y=1.0, color="black", linestyle="--") -plt.axvline(color="grey") -plt.axline((0, 0.5), slope=0.25, color="black", linestyle=(0, (5, 5))) -plt.plot(t, sig, linewidth=2, label=r"$\sigma(t) = \frac{1}{1 + e^{-t}}$") -plt.xlim(-10, 10) -plt.xlabel("t") -plt.legend(fontsize=14) +fig, ax = plt.subplots() +ax.axhline(y=0, color="black", linestyle="--") +ax.axhline(y=0.5, color="black", linestyle=":") +ax.axhline(y=1.0, color="black", linestyle="--") +ax.axvline(color="grey") +ax.axline((0, 0.5), slope=0.25, color="black", linestyle=(0, (5, 5))) +ax.plot(t, sig, linewidth=2, label=r"$\sigma(t) = \frac{1}{1 + e^{-t}}$") +ax.set(xlim=(-10, 10), xlabel="t") +ax.legend(fontsize=14) plt.show() # %% -# `~.axes.Axes.axline` can also be used with a ``transform`` parameter, which +# `~.axes.Axes.axline` can also be used with a *transform* parameter, which # applies to the point, but not to the slope. This can be useful for drawing # diagonal grid lines with a fixed slope, which stay in place when the # plot limits are moved. +fig, ax = plt.subplots() for pos in np.linspace(-2, 1, 10): - plt.axline((pos, 0), slope=0.5, color='k', transform=plt.gca().transAxes) + ax.axline((pos, 0), slope=0.5, color='k', transform=ax.transAxes) -plt.ylim([0, 1]) -plt.xlim([0, 1]) +ax.set(xlim=(0, 1), ylim=(0, 1)) plt.show() # %% @@ -57,3 +59,5 @@ # # `~.Axes.axhspan`, `~.Axes.axvspan` draw rectangles that span the Axes in one # direction and are bounded in the other direction. +# +# .. tags:: component: annotation From c3dc3a29f3569fa47455b9fa868ded9f635b4bc7 Mon Sep 17 00:00:00 2001 From: "Lumberbot (aka Jack)" <39504233+meeseeksmachine@users.noreply.github.com> Date: Fri, 14 Feb 2025 22:03:52 -0800 Subject: [PATCH 55/73] Backport PR #29617: DOC: Add docstrings to matplotlib.cbook.GrouperView (#29627) Co-authored-by: Christine P. Chai --- lib/matplotlib/cbook.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/cbook.py b/lib/matplotlib/cbook.py index da7a122b0968..bb2ea311430e 100644 --- a/lib/matplotlib/cbook.py +++ b/lib/matplotlib/cbook.py @@ -880,8 +880,18 @@ class GrouperView: def __init__(self, grouper): self._grouper = grouper def __contains__(self, item): return item in self._grouper def __iter__(self): return iter(self._grouper) - def joined(self, a, b): return self._grouper.joined(a, b) - def get_siblings(self, a): return self._grouper.get_siblings(a) + + def joined(self, a, b): + """ + Return whether *a* and *b* are members of the same set. + """ + return self._grouper.joined(a, b) + + def get_siblings(self, a): + """ + Return all of the items joined with *a*, including itself. + """ + return self._grouper.get_siblings(a) def simple_linear_interpolation(a, steps): From 3e3799d4bfdcda8e03513d5af42c48663f9ccb51 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:43:10 +0100 Subject: [PATCH 56/73] Backport PR #29631: Add inline notebook to test data --- lib/matplotlib/tests/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/matplotlib/tests/meson.build b/lib/matplotlib/tests/meson.build index e4a00e850f7f..05336496969f 100644 --- a/lib/matplotlib/tests/meson.build +++ b/lib/matplotlib/tests/meson.build @@ -103,6 +103,7 @@ install_data( 'cmr10.pfb', 'mpltest.ttf', 'test_nbagg_01.ipynb', + 'test_inline_01.ipynb', install_tag: 'tests', install_dir: py3.get_install_dir(subdir: 'matplotlib/tests/')) From d88d5d2ceda9416f2276353d758a8f72898f6694 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 20 Feb 2025 22:04:19 -0500 Subject: [PATCH 57/73] Backport PR #29650: Copy-edit "interactive figures & async programming" guide. --- .../figure/interactive_guide.rst | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/galleries/users_explain/figure/interactive_guide.rst b/galleries/users_explain/figure/interactive_guide.rst index b08231e84f7e..5cc55edc0955 100644 --- a/galleries/users_explain/figure/interactive_guide.rst +++ b/galleries/users_explain/figure/interactive_guide.rst @@ -11,7 +11,7 @@ Interactive figures and asynchronous programming Matplotlib supports rich interactive figures by embedding figures into a GUI window. The basic interactions of panning and zooming in an -Axes to inspect your data is 'baked in' to Matplotlib. This is +Axes to inspect your data is "baked in" to Matplotlib. This is supported by a full mouse and keyboard event handling system that you can use to build sophisticated interactive graphs. @@ -54,7 +54,7 @@ user hits the 'z' key, please run this other function". This allows users to write reactive, event-driven, programs without having to delve into the nitty-gritty [#f3]_ details of I/O. The core event loop is sometimes referred to as "the main loop" and is typically started, -depending on the library, by methods with names like ``_exec``, +depending on the library, by methods with names like ``exec``, ``run``, or ``start``. @@ -83,7 +83,7 @@ for user input and lets us register functions to be run when that happens. However, if we want to do both we have a problem: the prompt and the GUI event loop are both infinite loops that each think *they* are in charge! In order for both the prompt and the GUI windows to be -responsive we need a method to allow the loops to 'timeshare' : +responsive we need a method to allow the loops to "timeshare" : 1. let the GUI main loop block the python process when you want interactive windows @@ -109,7 +109,7 @@ Blocking the prompt The simplest "integration" is to start the GUI event loop in -'blocking' mode and take over the CLI. While the GUI event loop is +"blocking" mode and take over the CLI. While the GUI event loop is running you cannot enter new commands into the prompt (your terminal may echo the characters typed into the terminal, but they will not be sent to the Python interpreter because it is busy running the GUI @@ -147,7 +147,7 @@ While running the GUI event loop in a blocking mode or explicitly handling UI events is useful, we can do better! We really want to be able to have a usable prompt **and** interactive figure windows. -We can do this using the 'input hook' feature of the interactive +We can do this using the "input hook" feature of the interactive prompt. This hook is called by the prompt as it waits for the user to type (even for a fast typist the prompt is mostly waiting for the human to think and move their fingers). Although the details vary @@ -386,8 +386,8 @@ sure that you are locking in the critical sections. -Eventloop integration mechanism -=============================== +Event loop integration mechanism +================================ CPython / readline ------------------ @@ -404,7 +404,7 @@ run the event loop until a key is pressed on stdin. Matplotlib does not currently do any management of :c:data:`PyOS_InputHook` due to the wide range of ways that Matplotlib is used. This management is left to downstream libraries -- either user code or the shell. Interactive figures, -even with Matplotlib in 'interactive mode', may not work in the vanilla python +even with Matplotlib in "interactive mode", may not work in the vanilla python repl if an appropriate :c:data:`PyOS_InputHook` is not registered. Input hooks, and helpers to install them, are usually included with @@ -433,9 +433,9 @@ method. The source for the ``prompt_toolkit`` input hooks lives at then the loop would look something like :: fds = [...] - while True: # Loop - inp = select(fds).read() # Read - eval(inp) # Evaluate / Print + while True: # Loop + inp = select(fds).read() # Read + eval(inp) # Evaluate / Print .. [#f2] Or you can `write your own `__ if you must. From 55bd05629deb6436e1cddf712ac01a96ea12c126 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 21 Feb 2025 13:03:20 -0600 Subject: [PATCH 58/73] Backport PR #28437: Respect array alpha with interpolation_stage='rgba' in _Imagebase::_make_image --- .../next_api_changes/behavior/28437-CH.rst | 8 ++++ lib/matplotlib/image.py | 32 ++++++++----- lib/matplotlib/tests/test_image.py | 46 +++++++++++++++++++ 3 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 doc/api/next_api_changes/behavior/28437-CH.rst diff --git a/doc/api/next_api_changes/behavior/28437-CH.rst b/doc/api/next_api_changes/behavior/28437-CH.rst new file mode 100644 index 000000000000..6121dfec8163 --- /dev/null +++ b/doc/api/next_api_changes/behavior/28437-CH.rst @@ -0,0 +1,8 @@ +*alpha* parameter handling on images +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When passing and array to ``imshow(..., alpha=...)``, the parameter was silently ignored +if the image data was a RGB or RBGA image or if :rc:`interpolation_state` +resolved to "rbga". + +This is now fixed, and the alpha array overwrites any previous transparency information. diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 37a1d11678fa..1cbd3c14c135 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -501,17 +501,27 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, if A.ndim == 2: # interpolation_stage = 'rgba' self.norm.autoscale_None(A) A = self.to_rgba(A) - alpha = self._get_scalar_alpha() - if A.shape[2] == 3: - # No need to resample alpha or make a full array; NumPy will expand - # this out and cast to uint8 if necessary when it's assigned to the - # alpha channel below. - output_alpha = (255 * alpha) if A.dtype == np.uint8 else alpha - else: - output_alpha = _resample( # resample alpha channel - self, A[..., 3], out_shape, t, alpha=alpha) - output = _resample( # resample rgb channels - self, _rgb_to_rgba(A[..., :3]), out_shape, t, alpha=alpha) + alpha = self.get_alpha() + if alpha is None: # alpha parameter not specified + if A.shape[2] == 3: # image has no alpha channel + output_alpha = 255 if A.dtype == np.uint8 else 1.0 + else: + output_alpha = _resample( # resample alpha channel + self, A[..., 3], out_shape, t) + output = _resample( # resample rgb channels + self, _rgb_to_rgba(A[..., :3]), out_shape, t) + elif np.ndim(alpha) > 0: # Array alpha + # user-specified array alpha overrides the existing alpha channel + output_alpha = _resample(self, alpha, out_shape, t) + output = _resample( + self, _rgb_to_rgba(A[..., :3]), out_shape, t) + else: # Scalar alpha + if A.shape[2] == 3: # broadcast scalar alpha + output_alpha = (255 * alpha) if A.dtype == np.uint8 else alpha + else: # or apply scalar alpha to existing alpha channel + output_alpha = _resample(self, A[..., 3], out_shape, t) * alpha + output = _resample( + self, _rgb_to_rgba(A[..., :3]), out_shape, t) output[..., 3] = output_alpha # recombine rgb and alpha # output is now either a 2D array of normed (int or float) data diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 24a0ab929bbf..bc98bdb3900c 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -1711,3 +1711,49 @@ def test_resample_dtypes(dtype, ndim): axes_image = ax.imshow(data) # Before fix the following raises ValueError for some dtypes. axes_image.make_image(None)[0] + + +@pytest.mark.parametrize('intp_stage', ('data', 'rgba')) +@check_figures_equal() +def test_interpolation_stage_rgba_respects_alpha_param(fig_test, fig_ref, intp_stage): + axs_tst = fig_test.subplots(2, 3) + axs_ref = fig_ref.subplots(2, 3) + ny, nx = 3, 3 + scalar_alpha = 0.5 + array_alpha = np.random.rand(ny, nx) + + # When the image does not have an alpha channel, alpha should be specified + # by the user or default to 1.0 + im_rgb = np.random.rand(ny, nx, 3) + im_concat_default_a = np.ones((ny, nx, 1)) # alpha defaults to 1.0 + im_rgba = np.concatenate( # combine rgb channels with array alpha + (im_rgb, array_alpha.reshape((ny, nx, 1))), axis=-1 + ) + axs_tst[0][0].imshow(im_rgb) + axs_ref[0][0].imshow(np.concatenate((im_rgb, im_concat_default_a), axis=-1)) + axs_tst[0][1].imshow(im_rgb, interpolation_stage=intp_stage, alpha=scalar_alpha) + axs_ref[0][1].imshow( + np.concatenate( # combine rgb channels with broadcasted scalar alpha + (im_rgb, scalar_alpha * im_concat_default_a), axis=-1 + ), interpolation_stage=intp_stage + ) + axs_tst[0][2].imshow(im_rgb, interpolation_stage=intp_stage, alpha=array_alpha) + axs_ref[0][2].imshow(im_rgba, interpolation_stage=intp_stage) + + # When the image already has an alpha channel, multiply it by the + # scalar alpha param, or replace it by the array alpha param + axs_tst[1][0].imshow(im_rgba) + axs_ref[1][0].imshow(im_rgb, alpha=array_alpha) + axs_tst[1][1].imshow(im_rgba, interpolation_stage=intp_stage, alpha=scalar_alpha) + axs_ref[1][1].imshow( + np.concatenate( # combine rgb channels with scaled array alpha + (im_rgb, scalar_alpha * array_alpha.reshape((ny, nx, 1))), axis=-1 + ), interpolation_stage=intp_stage + ) + new_array_alpha = np.random.rand(ny, nx) + axs_tst[1][2].imshow(im_rgba, interpolation_stage=intp_stage, alpha=new_array_alpha) + axs_ref[1][2].imshow( + np.concatenate( # combine rgb channels with new array alpha + (im_rgb, new_array_alpha.reshape((ny, nx, 1))), axis=-1 + ), interpolation_stage=intp_stage + ) From 3845aefa26a4a013ac2aeb8dca82d0f87c9a8349 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 22 Feb 2025 08:38:44 +0100 Subject: [PATCH 59/73] Backport PR #29652: Reorder kwonly kwargs in Colorbar & related docs. --- lib/matplotlib/colorbar.py | 71 ++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 51ada59a21a0..8775f44b70aa 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -226,15 +226,26 @@ class Colorbar: mappable : `.ScalarMappable` The mappable whose colormap and norm will be used. - To show the under- and over- value colors, the mappable's norm should - be specified as :: + To show the colors versus index instead of on a 0-1 scale, set the + mappable's norm to ``colors.NoNorm()``. - norm = colors.Normalize(clip=False) + alpha : float + The colorbar transparency between 0 (transparent) and 1 (opaque). + + location : None or {'left', 'right', 'top', 'bottom'} + Set the colorbar's *orientation* and *ticklocation*. Colorbars on + the left and right are vertical, colorbars at the top and bottom + are horizontal. The *ticklocation* is the same as *location*, so if + *location* is 'top', the ticks are on the top. *orientation* and/or + *ticklocation* can be provided as well and overrides the value set by + *location*, but there will be an error for incompatible combinations. - To show the colors versus index instead of on a 0-1 scale, use:: + .. versionadded:: 3.7 - norm=colors.NoNorm() + %(_colormap_kw_doc)s + Other Parameters + ---------------- cmap : `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` The colormap to use. This parameter is ignored, unless *mappable* is None. @@ -243,9 +254,6 @@ class Colorbar: The normalization to use. This parameter is ignored, unless *mappable* is None. - alpha : float - The colorbar transparency between 0 (transparent) and 1 (opaque). - orientation : None or {'vertical', 'horizontal'} If None, use the value determined by *location*. If both *orientation* and *location* are None then defaults to 'vertical'. @@ -257,40 +265,27 @@ class Colorbar: *location*, so a colorbar to the left will have ticks to the left. If *location* is None, the ticks will be at the bottom for a horizontal colorbar and at the right for a vertical. - - %(_colormap_kw_doc)s - - location : None or {'left', 'right', 'top', 'bottom'} - Set the *orientation* and *ticklocation* of the colorbar using a - single argument. Colorbars on the left and right are vertical, - colorbars at the top and bottom are horizontal. The *ticklocation* is - the same as *location*, so if *location* is 'top', the ticks are on - the top. *orientation* and/or *ticklocation* can be provided as well - and overrides the value set by *location*, but there will be an error - for incompatible combinations. - - .. versionadded:: 3.7 """ n_rasterize = 50 # rasterize solids if number of colors >= n_rasterize - def __init__(self, ax, mappable=None, *, cmap=None, - norm=None, - alpha=None, - values=None, - boundaries=None, - orientation=None, - ticklocation='auto', - extend=None, - spacing='uniform', # uniform or proportional - ticks=None, - format=None, - drawedges=False, - extendfrac=None, - extendrect=False, - label='', - location=None, - ): + def __init__( + self, ax, mappable=None, *, + alpha=None, + location=None, + extend=None, + extendfrac=None, + extendrect=False, + ticks=None, + format=None, + values=None, + boundaries=None, + spacing='uniform', + drawedges=False, + label='', + cmap=None, norm=None, # redundant with *mappable* + orientation=None, ticklocation='auto', # redundant with *location* + ): if mappable is None: mappable = cm.ScalarMappable(norm=norm, cmap=cmap) From 46a33f6b2e7b18d4bdc65ed1a9ea85c741422267 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 21 Feb 2025 20:12:46 -0500 Subject: [PATCH 60/73] Backport PR #29075: Add xaxis and yaxis attributes to Axes docs --- doc/api/axes_api.rst | 6 ++++++ lib/matplotlib/axes/_base.py | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/doc/api/axes_api.rst b/doc/api/axes_api.rst index bf2e30ea983c..06893dd95c57 100644 --- a/doc/api/axes_api.rst +++ b/doc/api/axes_api.rst @@ -262,6 +262,7 @@ Property cycle Axes.set_prop_cycle +.. _axes-api-axis: Axis / limits ============= @@ -269,11 +270,16 @@ Axis / limits .. For families of methods of the form {get,set}_{x,y}foo, try to list them in the order set_xfoo, get_xfoo, set_yfoo, get_yfoo +Axis access +----------- + .. autosummary:: :toctree: _as_gen :template: autosummary.rst :nosignatures: + Axes.xaxis + Axes.yaxis Axes.get_xaxis Axes.get_yaxis diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index e45957fdd591..61d67d2791b4 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -566,6 +566,36 @@ class _AxesBase(martist.Artist): dataLim: mtransforms.Bbox """The bounding `.Bbox` enclosing all data displayed in the Axes.""" + xaxis: maxis.XAxis + """ + The `.XAxis` instance. + + Common axis-related configuration can be achieved through high-level wrapper + methods on Axes; e.g. `ax.set_xticks <.Axes.set_xticks>` is a shortcut for + `ax.xaxis.set_ticks <.Axis.set_ticks>`. The *xaxis* attribute gives direct + direct access to the underlying `~.axis.Axis` if you need more control. + + See also + + - :ref:`Axis wrapper methods on Axes ` + - :doc:`Axis API ` + """ + + yaxis: maxis.YAxis + """ + The `.YAxis` instance. + + Common axis-related configuration can be achieved through high-level wrapper + methods on Axes; e.g. `ax.set_yticks <.Axes.set_yticks>` is a shortcut for + `ax.yaxis.set_ticks <.Axis.set_ticks>`. The *yaxis* attribute gives direct + access to the underlying `~.axis.Axis` if you need more control. + + See also + + - :ref:`Axis wrapper methods on Axes ` + - :doc:`Axis API ` + """ + @property def _axis_map(self): """A mapping of axis names, e.g. 'x', to `Axis` instances.""" @@ -2218,7 +2248,7 @@ def get_xaxis(self): .. admonition:: Discouraged The use of this function is discouraged. You should instead - directly access the attribute ``ax.xaxis``. + directly access the attribute `~.Axes.xaxis`. """ return self.xaxis @@ -2229,7 +2259,7 @@ def get_yaxis(self): .. admonition:: Discouraged The use of this function is discouraged. You should instead - directly access the attribute ``ax.yaxis``. + directly access the attribute `~.Axes.yaxis`. """ return self.yaxis From af95fef7b49d6aeaded89ce347d75d47693b2958 Mon Sep 17 00:00:00 2001 From: "Christine P. Chai" Date: Sat, 22 Feb 2025 05:00:05 -0800 Subject: [PATCH 61/73] Backport PR #29642: DOC: Add docstrings to get_usetex and set_usetex in ticker.py --- lib/matplotlib/ticker.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index 801359555a69..3d0059e5aca3 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -465,9 +465,11 @@ def __init__(self, useOffset=None, useMathText=None, useLocale=None, *, self.set_useLocale(useLocale) def get_usetex(self): + """Return whether TeX's math mode is enabled for rendering.""" return self._usetex def set_usetex(self, val): + """Set whether to use TeX's math mode for rendering numbers in the formatter.""" self._usetex = mpl._val_or_rc(val, 'text.usetex') usetex = property(fget=get_usetex, fset=set_usetex) From 13af51b6a5433d35a4e37fbb762ebccc0b66c0a1 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 22 Feb 2025 21:20:11 +0100 Subject: [PATCH 62/73] Backport PR #29667: DOC: remove redundant gridspec from example --- galleries/examples/lines_bars_and_markers/scatter_hist.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/scatter_hist.py b/galleries/examples/lines_bars_and_markers/scatter_hist.py index 505edf6d627f..0a97fef5e44c 100644 --- a/galleries/examples/lines_bars_and_markers/scatter_hist.py +++ b/galleries/examples/lines_bars_and_markers/scatter_hist.py @@ -90,11 +90,10 @@ def scatter_hist(x, y, ax, ax_histx, ax_histy): # Create a Figure, which doesn't have to be square. fig = plt.figure(layout='constrained') -# Create the main Axes, leaving 25% of the figure space at the top and on the -# right to position marginals. -ax = fig.add_gridspec(top=0.75, right=0.75).subplots() +# Create the main Axes. +ax = fig.add_subplot() # The main Axes' aspect can be fixed. -ax.set(aspect=1) +ax.set_aspect('equal') # Create marginal Axes, which have 25% of the size of the main Axes. Note that # the inset Axes are positioned *outside* (on the right and the top) of the # main Axes, by specifying axes coordinates greater than 1. Axes coordinates From a21811c5482d07101ff2c9e056df89701654b405 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 22 Feb 2025 21:20:11 +0100 Subject: [PATCH 63/73] Backport PR #29667: DOC: remove redundant gridspec from example --- galleries/examples/lines_bars_and_markers/scatter_hist.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/scatter_hist.py b/galleries/examples/lines_bars_and_markers/scatter_hist.py index 505edf6d627f..0a97fef5e44c 100644 --- a/galleries/examples/lines_bars_and_markers/scatter_hist.py +++ b/galleries/examples/lines_bars_and_markers/scatter_hist.py @@ -90,11 +90,10 @@ def scatter_hist(x, y, ax, ax_histx, ax_histy): # Create a Figure, which doesn't have to be square. fig = plt.figure(layout='constrained') -# Create the main Axes, leaving 25% of the figure space at the top and on the -# right to position marginals. -ax = fig.add_gridspec(top=0.75, right=0.75).subplots() +# Create the main Axes. +ax = fig.add_subplot() # The main Axes' aspect can be fixed. -ax.set(aspect=1) +ax.set_aspect('equal') # Create marginal Axes, which have 25% of the size of the main Axes. Note that # the inset Axes are positioned *outside* (on the right and the top) of the # main Axes, by specifying axes coordinates greater than 1. Axes coordinates From 4b39940771ec8e2f4b8b31cef6e10cc7706ef7c2 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 24 Jan 2025 16:24:37 -0600 Subject: [PATCH 64/73] Spelling --- doc/api/prev_api_changes/api_changes_3.10.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/prev_api_changes/api_changes_3.10.0.rst b/doc/api/prev_api_changes/api_changes_3.10.0.rst index 83bde66213f3..ac4e4e981b21 100644 --- a/doc/api/prev_api_changes/api_changes_3.10.0.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.0.rst @@ -5,7 +5,7 @@ API Changes for 3.10.0 :local: :depth: 1 -.. include:: /api/prev_api_changes/api_changes_3.10.0/behaviour.rst +.. include:: /api/prev_api_changes/api_changes_3.10.0/behavior.rst .. include:: /api/prev_api_changes/api_changes_3.10.0/deprecations.rst From 74676ef13525e6990fa0ff3814668255bbf87aa1 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 24 Feb 2025 19:33:12 -0500 Subject: [PATCH 65/73] Backport PR #29662: DOC: Move Colorbar parameters to __init__ --- lib/matplotlib/colorbar.py | 98 +++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 8775f44b70aa..624e2250303c 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -217,54 +217,6 @@ class Colorbar: A list of `.LineCollection` (empty if no lines were drawn). dividers : `.LineCollection` A LineCollection (empty if *drawedges* is ``False``). - - Parameters - ---------- - ax : `~matplotlib.axes.Axes` - The `~.axes.Axes` instance in which the colorbar is drawn. - - mappable : `.ScalarMappable` - The mappable whose colormap and norm will be used. - - To show the colors versus index instead of on a 0-1 scale, set the - mappable's norm to ``colors.NoNorm()``. - - alpha : float - The colorbar transparency between 0 (transparent) and 1 (opaque). - - location : None or {'left', 'right', 'top', 'bottom'} - Set the colorbar's *orientation* and *ticklocation*. Colorbars on - the left and right are vertical, colorbars at the top and bottom - are horizontal. The *ticklocation* is the same as *location*, so if - *location* is 'top', the ticks are on the top. *orientation* and/or - *ticklocation* can be provided as well and overrides the value set by - *location*, but there will be an error for incompatible combinations. - - .. versionadded:: 3.7 - - %(_colormap_kw_doc)s - - Other Parameters - ---------------- - cmap : `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - The colormap to use. This parameter is ignored, unless *mappable* is - None. - - norm : `~matplotlib.colors.Normalize` - The normalization to use. This parameter is ignored, unless *mappable* - is None. - - orientation : None or {'vertical', 'horizontal'} - If None, use the value determined by *location*. If both - *orientation* and *location* are None then defaults to 'vertical'. - - ticklocation : {'auto', 'left', 'right', 'top', 'bottom'} - The location of the colorbar ticks. The *ticklocation* must match - *orientation*. For example, a horizontal colorbar can only have ticks - at the top or the bottom. If 'auto', the ticks will be the same as - *location*, so a colorbar to the left will have ticks to the left. If - *location* is None, the ticks will be at the bottom for a horizontal - colorbar and at the right for a vertical. """ n_rasterize = 50 # rasterize solids if number of colors >= n_rasterize @@ -286,7 +238,55 @@ def __init__( cmap=None, norm=None, # redundant with *mappable* orientation=None, ticklocation='auto', # redundant with *location* ): - + """ + Parameters + ---------- + ax : `~matplotlib.axes.Axes` + The `~.axes.Axes` instance in which the colorbar is drawn. + + mappable : `.ScalarMappable` + The mappable whose colormap and norm will be used. + + To show the colors versus index instead of on a 0-1 scale, set the + mappable's norm to ``colors.NoNorm()``. + + alpha : float + The colorbar transparency between 0 (transparent) and 1 (opaque). + + location : None or {'left', 'right', 'top', 'bottom'} + Set the colorbar's *orientation* and *ticklocation*. Colorbars on + the left and right are vertical, colorbars at the top and bottom + are horizontal. The *ticklocation* is the same as *location*, so if + *location* is 'top', the ticks are on the top. *orientation* and/or + *ticklocation* can be provided as well and overrides the value set by + *location*, but there will be an error for incompatible combinations. + + .. versionadded:: 3.7 + + %(_colormap_kw_doc)s + + Other Parameters + ---------------- + cmap : `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` + The colormap to use. This parameter is ignored, unless *mappable* is + None. + + norm : `~matplotlib.colors.Normalize` + The normalization to use. This parameter is ignored, unless *mappable* + is None. + + orientation : None or {'vertical', 'horizontal'} + If None, use the value determined by *location*. If both + *orientation* and *location* are None then defaults to 'vertical'. + + ticklocation : {'auto', 'left', 'right', 'top', 'bottom'} + The location of the colorbar ticks. The *ticklocation* must match + *orientation*. For example, a horizontal colorbar can only have ticks + at the top or the bottom. If 'auto', the ticks will be the same as + *location*, so a colorbar to the left will have ticks to the left. If + *location* is None, the ticks will be at the bottom for a horizontal + colorbar and at the right for a vertical. + """ if mappable is None: mappable = cm.ScalarMappable(norm=norm, cmap=cmap) From bdb728fa11c697531d0f3b0e315083b31b7619eb Mon Sep 17 00:00:00 2001 From: "Christine P. Chai" Date: Tue, 25 Feb 2025 01:52:40 -0800 Subject: [PATCH 66/73] Backport PR #29666: DOC: Revising the Figure Legend Demo Example --- .../figlegend_demo.py | 48 +++++-------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/figlegend_demo.py b/galleries/examples/text_labels_and_annotations/figlegend_demo.py index f6f74b837c10..50b3eeabc085 100644 --- a/galleries/examples/text_labels_and_annotations/figlegend_demo.py +++ b/galleries/examples/text_labels_and_annotations/figlegend_demo.py @@ -3,51 +3,25 @@ Figure legend demo ================== -Instead of plotting a legend on each axis, a legend for all the artists on all -the sub-axes of a figure can be plotted instead. +Rather than plotting a legend on each axis, a legend for all the artists +on all the sub-axes of a figure can be plotted instead. """ import matplotlib.pyplot as plt import numpy as np -fig, axs = plt.subplots(1, 2) - -x = np.arange(0.0, 2.0, 0.02) -y1 = np.sin(2 * np.pi * x) -y2 = np.exp(-x) -l1, = axs[0].plot(x, y1) -l2, = axs[0].plot(x, y2, marker='o') +fig, axs = plt.subplots(1, 2, layout='constrained') -y3 = np.sin(4 * np.pi * x) -y4 = np.exp(-2 * x) -l3, = axs[1].plot(x, y3, color='tab:green') -l4, = axs[1].plot(x, y4, color='tab:red', marker='^') +x = np.arange(0.0, 4*np.pi, 0.2) +axs[0].plot(x, np.sin(x), label='Line 1') +axs[0].plot(x, np.exp(-x/2), marker='o', label='Line 2') +axs[1].plot(x, np.sin(x), color='tab:green', label='Line 3') +axs[1].plot(x, np.exp(-x/4), color='tab:red', marker='^', label='Line 4') -fig.legend((l1, l2), ('Line 1', 'Line 2'), loc='upper left') -fig.legend((l3, l4), ('Line 3', 'Line 4'), loc='upper right') +fig.legend(loc='outside right upper') -plt.tight_layout() plt.show() # %% -# Sometimes we do not want the legend to overlap the Axes. If you use -# *constrained layout* you can specify "outside right upper", and -# *constrained layout* will make room for the legend. - -fig, axs = plt.subplots(1, 2, layout='constrained') - -x = np.arange(0.0, 2.0, 0.02) -y1 = np.sin(2 * np.pi * x) -y2 = np.exp(-x) -l1, = axs[0].plot(x, y1) -l2, = axs[0].plot(x, y2, marker='o') - -y3 = np.sin(4 * np.pi * x) -y4 = np.exp(-2 * x) -l3, = axs[1].plot(x, y3, color='tab:green') -l4, = axs[1].plot(x, y4, color='tab:red', marker='^') - -fig.legend((l1, l2), ('Line 1', 'Line 2'), loc='upper left') -fig.legend((l3, l4), ('Line 3', 'Line 4'), loc='outside right upper') - -plt.show() +# The outside positioning is discussed in detail here: +# https://matplotlib.org/stable/users/explain/axes/legend_guide.html#figure-legends From b4f94a4817e878629c40aab4fa5ccff6eed45490 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 26 Feb 2025 11:55:50 -0500 Subject: [PATCH 67/73] Backport PR #29680: DOC: fix the bug of examples\event_handling --- galleries/examples/event_handling/data_browser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/event_handling/data_browser.py b/galleries/examples/event_handling/data_browser.py index 6d9068940285..3d2dfeddc3a3 100644 --- a/galleries/examples/event_handling/data_browser.py +++ b/galleries/examples/event_handling/data_browser.py @@ -82,7 +82,7 @@ def update(self): transform=ax2.transAxes, va='top') ax2.set_ylim(-0.5, 1.5) self.selected.set_visible(True) - self.selected.set_data(xs[dataind], ys[dataind]) + self.selected.set_data([xs[dataind]], [ys[dataind]]) self.text.set_text('selected: %d' % dataind) fig.canvas.draw() From 294499449ec76cc04461c68bf2c63cc75ebd5198 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 26 Feb 2025 23:39:20 +0100 Subject: [PATCH 68/73] Backport PR #29670: DOC: change marginal scatter plot to subplot_mosaic --- .../lines_bars_and_markers/scatter_hist.py | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/scatter_hist.py b/galleries/examples/lines_bars_and_markers/scatter_hist.py index 0a97fef5e44c..d2b4c4eab228 100644 --- a/galleries/examples/lines_bars_and_markers/scatter_hist.py +++ b/galleries/examples/lines_bars_and_markers/scatter_hist.py @@ -3,8 +3,11 @@ Scatter plot with histograms ============================ -Show the marginal distributions of a scatter plot as histograms at the sides of -the plot. +Add histograms to the x-axes and y-axes margins of a scatter plot. + +This layout features a central scatter plot illustrating the relationship +between x and y, a histogram at the top displaying the distribution of x, and a +histogram on the right showing the distribution of y. For a nice alignment of the main Axes with the marginals, two options are shown below: @@ -15,14 +18,9 @@ While `.Axes.inset_axes` may be a bit more complex, it allows correct handling of main Axes with a fixed aspect ratio. -An alternative method to produce a similar figure using the ``axes_grid1`` -toolkit is shown in the :doc:`/gallery/axes_grid1/scatter_hist_locatable_axes` -example. Finally, it is also possible to position all Axes in absolute -coordinates using `.Figure.add_axes` (not shown here). - -Let us first define a function that takes x and y data as input, as well -as three Axes, the main Axes for the scatter, and two marginal Axes. It will -then create the scatter and histograms inside the provided Axes. +Let us first define a function that takes x and y data as input, as well as +three Axes, the main Axes for the scatter, and two marginal Axes. It will then +create the scatter and histograms inside the provided Axes. """ import matplotlib.pyplot as plt @@ -55,27 +53,22 @@ def scatter_hist(x, y, ax, ax_histx, ax_histy): # %% +# Defining the Axes positions using subplot_mosaic +# ------------------------------------------------ # -# Defining the Axes positions using a gridspec -# -------------------------------------------- -# -# We define a gridspec with unequal width- and height-ratios to achieve desired -# layout. Also see the :ref:`arranging_axes` tutorial. - -# Start with a square Figure. -fig = plt.figure(figsize=(6, 6)) -# Add a gridspec with two rows and two columns and a ratio of 1 to 4 between -# the size of the marginal Axes and the main Axes in both directions. -# Also adjust the subplot parameters for a square plot. -gs = fig.add_gridspec(2, 2, width_ratios=(4, 1), height_ratios=(1, 4), - left=0.1, right=0.9, bottom=0.1, top=0.9, - wspace=0.05, hspace=0.05) -# Create the Axes. -ax = fig.add_subplot(gs[1, 0]) -ax_histx = fig.add_subplot(gs[0, 0], sharex=ax) -ax_histy = fig.add_subplot(gs[1, 1], sharey=ax) -# Draw the scatter plot and marginals. -scatter_hist(x, y, ax, ax_histx, ax_histy) +# We use the `~.pyplot.subplot_mosaic` function to define the positions and +# names of the three axes; the empty axes is specified by ``'.'``. We manually +# specify the size of the figure, and can make the different axes have +# different sizes by specifying the *width_ratios* and *height_ratios* +# arguments. The *layout* argument is set to ``'constrained'`` to optimize the +# spacing between the axes. + +fig, axs = plt.subplot_mosaic([['histx', '.'], + ['scatter', 'histy']], + figsize=(6, 6), + width_ratios=(4, 1), height_ratios=(1, 4), + layout='constrained') +scatter_hist(x, y, axs['scatter'], axs['histx'], axs['histy']) # %% @@ -109,13 +102,27 @@ def scatter_hist(x, y, ax, ax_histx, ax_histy): # %% # +# While we recommend using one of the two methods described above, there are +# number of other ways to achieve a similar layout: +# +# - The Axes can be positioned manually in relative coordinates using +# `~matplotlib.figure.Figure.add_axes`. +# - A gridspec can be used to create the layout +# (`~matplotlib.figure.Figure.add_gridspec`) and adding only the three desired +# axes (`~matplotlib.figure.Figure.add_subplot`). +# - Four subplots can be created using `~.pyplot.subplots`, and the unused +# axes in the upper right can be removed manually. +# - The ``axes_grid1`` toolkit can be used, as shown in +# :doc:`/gallery/axes_grid1/scatter_hist_locatable_axes`. +# # .. admonition:: References # # The use of the following functions, methods, classes and modules is shown # in this example: # +# - `matplotlib.figure.Figure.subplot_mosaic` +# - `matplotlib.pyplot.subplot_mosaic` # - `matplotlib.figure.Figure.add_subplot` -# - `matplotlib.figure.Figure.add_gridspec` # - `matplotlib.axes.Axes.inset_axes` # - `matplotlib.axes.Axes.scatter` # - `matplotlib.axes.Axes.hist` From 526785e912adddaa7ef0b19d11cebc2d5e96b2de Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 27 Feb 2025 12:19:38 -0600 Subject: [PATCH 69/73] Github stats v3.10.1 --- doc/users/github_stats.rst | 702 ++++-------------- .../prev_whats_new/github_stats_3.10.0.rst | 587 +++++++++++++++ 2 files changed, 730 insertions(+), 559 deletions(-) create mode 100644 doc/users/prev_whats_new/github_stats_3.10.0.rst diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index c12a983aa6a8..de1f85004f09 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -1,590 +1,174 @@ .. _github-stats: -GitHub statistics for 3.10.0 (Dec 13, 2024) +GitHub statistics for 3.10.1 (Feb 27, 2025) =========================================== -GitHub statistics for 2024/05/15 (tag: v3.9.0) - 2024/12/13 +GitHub statistics for 2024/12/14 (tag: v3.10.0) - 2025/02/27 These lists are automatically generated, and may be incomplete or contain duplicates. -We closed 100 issues and merged 337 pull requests. -The full list can be seen `on GitHub `__ +We closed 14 issues and merged 107 pull requests. +The full list can be seen `on GitHub `__ -The following 128 authors contributed 1932 commits. +The following 28 authors contributed 241 commits. -* abhi-jha -* Adam J. Stewart -* Aditi Gautam -* Aditya Vidyadhar Kamath -* Aishling Cooke -* Alan -* Alan Sosa -* Alice -* Aman Nijjar -* Ammar Qazi -* Ancheng -* anpaulan -* Anson0028 -* Anthony Lee -* anTon +* Anselm Hahn * Antony Lee -* Ayoub Gouasmi -* Brigitta Sipőcz -* Caitlin Hathaway -* cesar -* Charlie LeWarne -* Christian Mattsson -* ClarkeAC -* Clemens Brunner -* Clement Gilli -* cmp0xff -* Costa Paraskevopoulos -* dale -* Dani Pinyol -* Daniel Weiss -* Danny -* David Bakaj -* David Lowry-Duda -* David Meyer -* David Stansby -* dbakaj +* Ben Greiner +* Chaoyi Hu +* Christine P. Chai * dependabot[bot] -* Diogo Cardoso -* Doron Behar -* Edgar Andrés Margffoy Tuay * Elliott Sales de Andrade -* Eytan Adler -* farquh -* Felipe Cybis Pereira -* Filippo Balzaretti -* FMasson -* Francisco Cardozo -* Gavin S +* G.D. McBain * Greg Lucas -* haaris * hannah -* Ian Thomas -* Illviljan -* James Addison -* James Spencer -* Jody Klymak -* john -* Jonas Eschle -* Jouni K. Seppänen -* juanis2112 -* Juanita Gomez -* Justin Hendrick -* K900 -* Kaustbh -* Kaustubh -* Kherim Willems +* hu-xiaonan +* Khushi_29 +* Khushikela29 +* KIU Shueng Chuan +* Kyle Martin * Kyle Sunden -* Kyra Cho -* Larry Bradley -* litchi -* Lorenzo -* Lucx33 * Lumberbot (aka Jack) -* MadPhysicist -* malhar2460 -* Martino Sorbaro -* Mathias Hauser -* Matthew Feickert -* Matthew Petroff -* Melissa Weber Mendonça -* Michael -* Michael Droettboom -* Michael Hinton -* MischaMegens2 -* Moritz Wolter -* muchojp -* Nabil -* nakamura yuki -* odile -* OdileVidrine +* Manthan Nagvekar +* musvaage +* Nathan G. Wiseman * Oscar Gustafsson -* Panicks28 -* Paul An -* Pedro Barão -* PedroBittarBarao -* Peter Talley -* Pierre-antoine Comby -* Pranav -* Pranav Raghu -* pre-commit-ci[bot] -* proximalf -* r3kste -* Randolf Scholz -* Refael Ackermann -* RickyP24 -* rnhmjoj +* Owl * Ruth Comer -* Ryan May -* Sai Chaitanya, Sanivada -* saranti -* scaccol +* saikarna913 * Scott Shambaugh -* Sean Smith -* Simon May -* simond07 -* smcgrawDotNet -* Takumasa N -* Takumasa N. -* Takumasa Nakamura -* thiagoluisbecker * Thomas A Caswell -* Tiago Lubiana * Tim Hoffmann -* trananso * Trygve Magnus Ræder -* Victor Liu -* vittoboa -* Xeniya Shoiko GitHub issues and pull requests: -Pull Requests (337): +Pull Requests (107): -* :ghpull:`29299`: Merge v3.9.x into v3.10.x -* :ghpull:`29296`: Backport PR #29295 on branch v3.10.x (BLD: Pin meson-python to <0.17.0) -* :ghpull:`29290`: Backport PR #29254 on branch v3.10.x (DOC: Add note to align_labels()) -* :ghpull:`29289`: Backport PR #29260 on branch v3.10.x (DOC: Better explanation of rcParams "patch.edgecolor" and "patch.force_edgecolor") -* :ghpull:`29288`: Backport PR #29285 on branch v3.10.x (Retarget PR#29175 to main) -* :ghpull:`29254`: DOC: Add note to align_labels() -* :ghpull:`29260`: DOC: Better explanation of rcParams "patch.edgecolor" and "patch.force_edgecolor" -* :ghpull:`29285`: Retarget PR#29175 to main -* :ghpull:`29286`: Backport PR #29274 on branch v3.10.x (Bump the actions group across 1 directory with 2 updates) -* :ghpull:`29274`: Bump the actions group across 1 directory with 2 updates -* :ghpull:`29283`: Backport PR #29272 on branch v3.10.x (DOC: Add section on translating between Axes and pyplot interface) -* :ghpull:`29272`: DOC: Add section on translating between Axes and pyplot interface -* :ghpull:`29279`: Backport PR #29265 on branch v3.10.x (DOC: Slightly improve the LineCollection docstring) -* :ghpull:`29276`: Backport PR #29247 on branch v3.10.x (Fix building freetype 2.6.1 on macOS clang 18) -* :ghpull:`29244`: Switch to a 3d rotation trackball implementation with path independence -* :ghpull:`29265`: DOC: Slightly improve the LineCollection docstring -* :ghpull:`29247`: Fix building freetype 2.6.1 on macOS clang 18 -* :ghpull:`29268`: Bump the actions group with 2 updates -* :ghpull:`29266`: Backport PR #29251 on branch v3.10.x (Zizmor audit) -* :ghpull:`29269`: Backport PR #29267 on branch v3.10.x (Exclude pylab from mypy checks) -* :ghpull:`29267`: Exclude pylab from mypy checks -* :ghpull:`29251`: Zizmor audit -* :ghpull:`29255`: Backport PR #29249 on branch v3.10.x ([Bug Fix] Fix reverse mapping for _translate_tick_params) -* :ghpull:`29249`: [Bug Fix] Fix reverse mapping for _translate_tick_params -* :ghpull:`29250`: Backport PR #29243 on branch v3.10.x (Add quotes around [dev] in environment.yml) -* :ghpull:`29243`: Add quotes around [dev] in environment.yml -* :ghpull:`29246`: Backport PR #29240 on branch v3.10.x (DOC: Add plt.show() to introductory pyplot example) -* :ghpull:`29240`: DOC: Add plt.show() to introductory pyplot example -* :ghpull:`29239`: Backport PR #29236 on branch v3.10.x (ANI: Reduce Pillow frames to RGB when opaque) -* :ghpull:`29238`: Backport PR #29167 on branch v3.10.x (BUGFIX: use axes unit information in ConnectionPatch ) -* :ghpull:`29236`: ANI: Reduce Pillow frames to RGB when opaque -* :ghpull:`29167`: BUGFIX: use axes unit information in ConnectionPatch -* :ghpull:`29232`: Merge branch v3.9.x into v3.10.x -* :ghpull:`29230`: Backport PR #29188 on branch v3.10.x (Bump pypa/cibuildwheel from 2.21.3 to 2.22.0 in the actions group) -* :ghpull:`29188`: Bump pypa/cibuildwheel from 2.21.3 to 2.22.0 in the actions group -* :ghpull:`29225`: Backport PR #29213 on branch v3.10.x (avoid-unnecessary-warning-in-_pcolorargs-function) -* :ghpull:`29211`: Backport PR #29133 on branch v3.10.x (Creating_parse_bar_color_args to unify color handling in plt.bar with precedence and sequence support for facecolor and edgecolor) -* :ghpull:`29177`: Backport PR #29148 on branch v3.10.x (Don't fail on equal-but-differently-named cmaps in qt figureoptions.) -* :ghpull:`29226`: Backport PR #29206 on branch v3.10.x (Skip more tests on pure-Wayland systems) -* :ghpull:`29206`: Skip more tests on pure-Wayland systems -* :ghpull:`29213`: avoid-unnecessary-warning-in-_pcolorargs-function -* :ghpull:`29210`: Backport PR #29209 on branch v3.10.x (FIX: pcolormesh with no x y args and nearest interp) -* :ghpull:`29133`: Creating_parse_bar_color_args to unify color handling in plt.bar with precedence and sequence support for facecolor and edgecolor -* :ghpull:`29209`: FIX: pcolormesh with no x y args and nearest interp -* :ghpull:`29200`: Backport PR #29182 on branch v3.10.x (Update backend_qt.py: parent not passed to __init__ on subplottool) -* :ghpull:`29207`: Backport PR #29169 on branch v3.10.x (Minor fixes to text intro explainer) -* :ghpull:`29169`: Minor fixes to text intro explainer -* :ghpull:`29159`: Pending warning for deprecated parameter 'vert' of box and violin on 3.10 -* :ghpull:`29196`: Backport PR #29191 on branch v3.10.x (ci: Simplify 3.13t test setup) -* :ghpull:`29182`: Update backend_qt.py: parent not passed to __init__ on subplottool -* :ghpull:`29189`: Backport PR #28934 on branch v3.10.x (ci: Unpin micromamba again) -* :ghpull:`29186`: Backport PR #28335 on branch v3.10.x (DOC: do not posting LLM output as your own work) -* :ghpull:`28934`: ci: Unpin micromamba again -* :ghpull:`28335`: DOC: do not posting LLM output as your own work -* :ghpull:`29178`: Backport PR #29163 on branch v3.9.x (ci: Remove outdated pkg-config package on macOS) -* :ghpull:`29170`: Backport PR #29154 on branch v3.10.x (Relax conditions for warning on updating converters) -* :ghpull:`29154`: Relax conditions for warning on updating converters -* :ghpull:`29166`: Backport PR #29153 on branch v3.10.x (Bump codecov/codecov-action from 4 to 5 in the actions group) -* :ghpull:`29164`: Backport PR #29163 on branch v3.10.x (ci: Remove outdated pkg-config package on macOS) -* :ghpull:`29168`: Backport PR #29073 on branch v3.10.x (Update secondary_axis tutorial) -* :ghpull:`29073`: Update secondary_axis tutorial -* :ghpull:`29163`: ci: Remove outdated pkg-config package on macOS -* :ghpull:`29145`: Backport PR #29144 on branch v3.10.x (Use both TCL_SETVAR and TCL_SETVAR2 for tcl 9 support) -* :ghpull:`29144`: Use both TCL_SETVAR and TCL_SETVAR2 for tcl 9 support -* :ghpull:`29140`: Backport PR #29080 on branch v3.10.x (Updates the ``galleries/tutorials/artists.py`` file in response to issue #28920) -* :ghpull:`29080`: Updates the ``galleries/tutorials/artists.py`` file in response to issue #28920 -* :ghpull:`29138`: Backport PR #29134 on branch v3.10.x (MNT: Temporarily skip failing test to unbreak CI) -* :ghpull:`29134`: MNT: Temporarily skip failing test to unbreak CI -* :ghpull:`29132`: Backport PR #29128 on branch v3.10.x (Tweak AutoMinorLocator docstring.) -* :ghpull:`29128`: Tweak AutoMinorLocator docstring. -* :ghpull:`29123`: Bump the actions group with 2 updates -* :ghpull:`29122`: Backport PR #29120 on branch v3.10.x (DOC: Switch nested pie example from cmaps to color_sequences) -* :ghpull:`29100`: Backport PR #29099 on branch v3.10.x (MNT: remove _ttconv.pyi) -* :ghpull:`29099`: MNT: remove _ttconv.pyi -* :ghpull:`29098`: Backport PR #29097 on branch v3.10.x (ENH: add back/forward buttons to osx backend move) -* :ghpull:`29097`: ENH: add back/forward buttons to osx backend move -* :ghpull:`29095`: Backport PR #29071 on branch v3.10.x (Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.11.0 in the actions group) -* :ghpull:`29096`: Backport PR #29094 on branch v3.10.x (DOC: fix link in See Also section of axes.violin) -* :ghpull:`29092`: Backport PR #29088 on branch v3.10.x (DOC: Format aliases in kwargs tables) -* :ghpull:`29094`: DOC: fix link in See Also section of axes.violin -* :ghpull:`29091`: Backport PR #29085 on branch v3.10.x (FIX: Update GTK3Agg backend export name for consistency) -* :ghpull:`29088`: DOC: Format aliases in kwargs tables -* :ghpull:`29089`: Backport PR #29065 on branch v3.10.x (DOC: Update docstring of triplot()) -* :ghpull:`29085`: FIX: Update GTK3Agg backend export name for consistency -* :ghpull:`29084`: Backport PR #29081 on branch v3.10.x (Document "none" as color value) -* :ghpull:`29065`: DOC: Update docstring of triplot() -* :ghpull:`29081`: Document "none" as color value -* :ghpull:`29061`: Backport PR #29024 on branch v3.10.x (Fix saving animations to transparent formats) -* :ghpull:`29069`: Backport PR #29068 on branch v3.10.x ([DOC] Fix indentation in sync_cmaps example) -* :ghpull:`29070`: Backport PR #29048 on branch v3.10.x (DOC: integrated pr workflow from contributing guide into install and workflow) -* :ghpull:`29048`: DOC: integrated pr workflow from contributing guide into install and workflow -* :ghpull:`29068`: [DOC] Fix indentation in sync_cmaps example -* :ghpull:`29024`: Fix saving animations to transparent formats -* :ghpull:`29059`: Cleanup converter docs and StrCategoryConverter behavior -* :ghpull:`29058`: [DOC] Update missing-references.json -* :ghpull:`29057`: DOC/TST: lock numpy<2.1 in environment.yml -* :ghpull:`29053`: Factor out common formats strings in LogFormatter, LogFormatterExponent. -* :ghpull:`28970`: Add explicit converter setting to Axis -* :ghpull:`28048`: Enables setting hatch linewidth in Patches and Collections, also fixes setting hatch linewidth by rcParams -* :ghpull:`29017`: DOC: Document preferred figure size for examples -* :ghpull:`28871`: updated contribution doc #28476 -* :ghpull:`28453`: Stop relying on dead-reckoning mouse buttons for motion_notify_event. -* :ghpull:`28495`: ticker.EngFormatter: allow offset -* :ghpull:`29039`: MNT: Add provisional get_backend(resolve=False) flag -* :ghpull:`28946`: MNT: Deprecate plt.polar() with an existing non-polar Axes -* :ghpull:`29013`: FIX: auto_fmtxdate for constrained layout -* :ghpull:`29022`: Fixes AIX internal CI build break. -* :ghpull:`28830`: Feature: Support passing DataFrames to table.table -* :ghpull:`27766`: Return filename from save_figure -* :ghpull:`27167`: ENH: add long_axis property to colorbar -* :ghpull:`29021`: Update minimum pybind11 to 2.13.2 -* :ghpull:`28863`: Improved documentation for quiver -* :ghpull:`29019`: Update requirements to add PyStemmer to doc-requirements and environment -* :ghpull:`28653`: Mnt/generalize plot varargs -* :ghpull:`28967`: Fix MSVC cast warnings -* :ghpull:`29016`: DOC: Better explain suptitle / supxlabel / supylabel naming -* :ghpull:`28842`: FT2Font extension improvements -* :ghpull:`28658`: New data → color pipeline -* :ghpull:`29012`: Bump required pybind11 to 2.13 -* :ghpull:`29007`: MNT: Deprecate changing Figure.number -* :ghpull:`28861`: Break Artist._remove_method reference cycle -* :ghpull:`28478`: bugfix for ``PathSimplifier`` -* :ghpull:`28992`: DOC: Refresh transform tree example -* :ghpull:`28890`: MNT: Add missing dependency to environment.yml -* :ghpull:`28354`: Add Quiverkey zorder option -* :ghpull:`28966`: Fix polar error bar cap orientation -* :ghpull:`28819`: Mark all extensions as free-threading safe -* :ghpull:`28986`: DOC: Add tags for 3D fill_between examples -* :ghpull:`28984`: DOC / BUG: Better example for 3D axlim_clip argument -* :ghpull:`20866`: Remove ttconv and implement Type-42 embedding using fontTools -* :ghpull:`28975`: Set guiEvent where applicable for gtk4. -* :ghpull:`28568`: added tags to mplot3d examples -* :ghpull:`28976`: Bump pypa/cibuildwheel from 2.21.2 to 2.21.3 in the actions group -* :ghpull:`28978`: CI: Resolve mypy stubtest build errors -* :ghpull:`28823`: Fix 3D rotation precession -* :ghpull:`28841`: Make mplot3d mouse rotation style adjustable -* :ghpull:`28971`: DOC: correct linestyle example and reference rcParams -* :ghpull:`28702`: [MNT]: #28701 separate the generation of polygon vertices in fill_between to enable resampling -* :ghpull:`28965`: Suggest imageio_ffmpeg to provide ffmpeg as animation writer. -* :ghpull:`28964`: FIX macos: Use the agg buffer_rgba rather than private attribute -* :ghpull:`28963`: Remove refs to outdated writers in animation.py. -* :ghpull:`28948`: Raise ValueError for RGB values outside the [0, 1] range in rgb_to_hsv function -* :ghpull:`28857`: Pybind11 cleanup -* :ghpull:`28949`: [pre-commit.ci] pre-commit autoupdate -* :ghpull:`28950`: Bump the actions group with 2 updates -* :ghpull:`28904`: Agg: Remove 16-bit limits -* :ghpull:`28856`: Convert remaining code to pybind11 -* :ghpull:`28874`: Remove remaining 3.8 deprecations -* :ghpull:`28943`: DOC: Clarify the returned line of axhline()/axvline() -* :ghpull:`28935`: DOC: Fix invalid rcParam references -* :ghpull:`28942`: In colorbar docs, add ref from 'boundaries' doc to 'spacing' doc. -* :ghpull:`28933`: Switch AxLine.set_xy{1,2} to take a single argument. -* :ghpull:`28869`: ci: Bump build image on AppVeyor to MSVC 2019 -* :ghpull:`28906`: Re-fix exception caching in dviread. -* :ghpull:`27349`: [ENH] Implement dynamic clipping to axes limits for 3D plots -* :ghpull:`28913`: DOC: Fix Axis.set_label reference -* :ghpull:`28911`: MNT: Fix double evaluation of _LazyTickList -* :ghpull:`28584`: MNT: Prevent users from erroneously using legend label API on Axis -* :ghpull:`28853`: MNT: Check the input sizes of regular X,Y in pcolorfast -* :ghpull:`28838`: TST: Fix minor issues in interactive backend test -* :ghpull:`28795`: MNT: Cleanup docstring substitution mechanisms -* :ghpull:`28897`: Fix minor issues in stubtest wrapper -* :ghpull:`28899`: Don't cache exception with traceback reference loop in dviread. -* :ghpull:`28888`: DOC: Better visualization for the default color cycle example -* :ghpull:`28896`: doc: specify non-python dependencies in dev install docs -* :ghpull:`28843`: MNT: Cleanup FontProperties __init__ API -* :ghpull:`28683`: MNT: Warn if fixed aspect overwrites explicitly set data limits -* :ghpull:`25645`: Fix issue with sketch not working on PathCollection in Agg -* :ghpull:`28886`: DOC: Cross-link Axes attributes -* :ghpull:`28880`: Remove 'in' from removal substitution for deprecation messages -* :ghpull:`28875`: DOC: Fix documentation of hist() kwarg lists -* :ghpull:`28825`: DOC: Fix non-working code object references -* :ghpull:`28862`: Improve pie chart error messages -* :ghpull:`28844`: DOC: Add illustration to Figure.subplots_adjust -* :ghpull:`28588`: Fix scaling in Tk on non-Windows systems -* :ghpull:`28849`: DOC: Mark subfigures as no longer provisional -* :ghpull:`26000`: making onselect a keyword argument on selectors -* :ghpull:`26013`: Support unhashable callbacks in CallbackRegistry -* :ghpull:`27011`: Convert Agg extension to pybind11 -* :ghpull:`28845`: In examples, prefer named locations rather than location numbers. -* :ghpull:`27218`: API: finish LocationEvent.lastevent removal -* :ghpull:`26870`: Removed the deprecated code from axis.py -* :ghpull:`27996`: Create ``InsetIndicator`` artist -* :ghpull:`28532`: TYP: Fix xycoords and friends -* :ghpull:`28785`: Convert ft2font extension to pybind11 -* :ghpull:`28815`: DOC: Document policy on colormaps and styles -* :ghpull:`28826`: MNT: Replace _docstring.dedent_interpd by its alias _docstring.interpd -* :ghpull:`27567`: DOC: batch of tags -* :ghpull:`27302`: Tags for simple_scatter.py demo -* :ghpull:`28820`: DOC: Fix missing cross-reference checks for sphinx-tags -* :ghpull:`28786`: Handle single color in ContourSet -* :ghpull:`28808`: DOC: Add a plot to margins() to visualize the effect -* :ghpull:`27938`: feat: add dunder method for math operations on Axes Size divider -* :ghpull:`28569`: Adding tags to many examples -* :ghpull:`28183`: Expire deprecations -* :ghpull:`28801`: DOC: Clarify AxLine.set_xy2 / AxLine.set_slope -* :ghpull:`28788`: TST: Skip webp tests if it isn't available -* :ghpull:`28550`: Remove internal use of ``Artist.figure`` -* :ghpull:`28767`: MNT: expire ``ContourSet`` deprecations -* :ghpull:`28755`: TYP: Add typing for internal _tri extension -* :ghpull:`28765`: Add tests for most of FT2Font, and fix some bugs -* :ghpull:`28781`: TST: Fix test_pickle_load_from_subprocess in a dirty tree -* :ghpull:`28783`: Fix places where "auto" was not listed as valid interpolation_stage. -* :ghpull:`28779`: DOC/TST: lock numpy < 2.1 -* :ghpull:`28771`: Ensure SketchParams is always fully initialized -* :ghpull:`28375`: FIX: Made AffineDeltaTransform pass-through properly -* :ghpull:`28454`: MultivarColormap and BivarColormap -* :ghpull:`27891`: Refactor some parts of ft2font extension -* :ghpull:`28752`: quick fix dev build by locking out numpy version that's breaking things -* :ghpull:`28749`: Add sphinxcontrib-video to environment.yml -* :ghpull:`27851`: Add ten-color accessible color cycle as style sheet -* :ghpull:`28501`: ConciseDateFormatter's offset string is correct on an inverted axis -* :ghpull:`28734`: Compressed layout moves suptitle -* :ghpull:`28736`: Simplify some code in dviread -* :ghpull:`28347`: Doc: added triage section to new contributor docs -* :ghpull:`28735`: ci: Avoid setuptools 72.2.0 when installing kiwi on PyPy -* :ghpull:`28728`: MNT: Deprecate reimported functions in top-level namespace -* :ghpull:`28730`: MNT: Don't rely on RcParams being a dict subclass in internal code -* :ghpull:`28714`: Simplify _api.warn_external on Python 3.12+ -* :ghpull:`28727`: MNT: Better workaround for format_cursor_data on ScalarMappables -* :ghpull:`28725`: Stop disabling FH4 Exception Handling on MSVC -* :ghpull:`28711`: Merge branch v3.9.x into main -* :ghpull:`28713`: DOC: Add a few more notes to release guide -* :ghpull:`28720`: DOC: Clarify axhline() uses axes coordinates -* :ghpull:`28718`: DOC: Update missing references for numpydoc 1.8.0 -* :ghpull:`28710`: DOC: clarify alpha handling for indicate_inset[_zoom] -* :ghpull:`28704`: Fixed arrowstyle doc interpolation in FancyPatch.set_arrow() #28698. -* :ghpull:`28709`: Bump actions/attest-build-provenance from 1.4.0 to 1.4.1 in the actions group -* :ghpull:`28707`: Avoid division-by-zero in Sketch::Sketch -* :ghpull:`28610`: CI: Add CI to test matplotlib against free-threaded Python -* :ghpull:`28262`: Fix PolygonSelector cursor to temporarily hide during active zoom/pan -* :ghpull:`28670`: API: deprecate unused helper in patch._Styles -* :ghpull:`28589`: Qt embedding example: Separate drawing and data retrieval timers -* :ghpull:`28655`: Inline annotation and PGF user demos -* :ghpull:`28654`: DOC: Remove long uninstructive examples -* :ghpull:`28652`: Fix docstring style inconsistencies in lines.py -* :ghpull:`28641`: DOC: Standardize example titles - part 2 -* :ghpull:`28642`: DOC: Simplify heatmap example -* :ghpull:`28638`: DOC: Remove hint on PRs from origin/main -* :ghpull:`28587`: Added dark-mode diverging colormaps -* :ghpull:`28546`: DOC: Clarify/simplify example of multiple images with one colorbar -* :ghpull:`28613`: Added documentation for parameters vmin and vmax inside specgram function. -* :ghpull:`28627`: DOC: Bump minimum Sphinx to 5.1.0 -* :ghpull:`28628`: DOC: Sub-structure next API changes overview -* :ghpull:`28629`: FIX: ``Axis.set_in_layout`` respected -* :ghpull:`28575`: Add branch tracking to development workflow instructions -* :ghpull:`28616`: CI: Build docs on latest Python -* :ghpull:`28617`: DOC: Enable parallel builds -* :ghpull:`28544`: DOC: Standardize example titles -* :ghpull:`28615`: DOC: hack to suppress sphinx-gallery 17.0 warning -* :ghpull:`28293`: BLD: Enable building Python 3.13 wheels for nightlies -* :ghpull:`27385`: Fix 3D lines being visible when behind camera -* :ghpull:`28609`: svg: Ensure marker-only lines get URLs -* :ghpull:`28599`: Upgrade code to Python 3.10 -* :ghpull:`28593`: Update ruff to 0.2.0 -* :ghpull:`28603`: Simplify ttconv python<->C++ conversion using std::optional. -* :ghpull:`28557`: DOC: apply toc styling to remove nesting -* :ghpull:`28542`: CI: adjust pins in mypy GHA job -* :ghpull:`28504`: Changes in SVG backend to improve compatibility with Affinity designer -* :ghpull:`28122`: Disable clipping in Agg resamplers. -* :ghpull:`28597`: Pin PyQt6 back on Ubuntu 20.04 -* :ghpull:`28073`: Add support for multiple hatches, edgecolors and linewidths in histograms -* :ghpull:`28594`: MNT: Raise on GeoAxes limits manipulation -* :ghpull:`28312`: Remove one indirection layer in ToolSetCursor. -* :ghpull:`28573`: ENH: include property name in artist AttributeError -* :ghpull:`28503`: Bump minimum Python to 3.10 -* :ghpull:`28525`: FIX: colorbar pad for ``ImageGrid`` -* :ghpull:`28558`: DOC: Change _make_image signature to numpydoc -* :ghpull:`28061`: API: add antialiased to interpolation-stage in image -* :ghpull:`28536`: [svg] Add rcParam["svg.id"] to add a top-level id attribute to -* :ghpull:`28540`: Subfigures become stale when their artists are stale -* :ghpull:`28177`: Rationalise artist get_figure methods; make figure attribute a property -* :ghpull:`28527`: DOC: improve tagging guidelines page -* :ghpull:`28530`: DOC: Simplify axhspan example -* :ghpull:`28537`: DOC: Update timeline example for newer releases -* :ghpull:`27833`: [SVG] Introduce sequential ID-generation scheme for clip-paths. -* :ghpull:`28512`: DOC: Fix version switcher for stable docs -* :ghpull:`28492`: MNT: Remove PolyQuadMesh deprecations -* :ghpull:`28509`: CI: Use micromamba on AppVeyor -* :ghpull:`28510`: Merge v3.9.1 release into main -* :ghpull:`28494`: [pre-commit.ci] pre-commit autoupdate -* :ghpull:`28497`: Add words to ignore for codespell -* :ghpull:`28455`: Expand ticklabels_rotation example to cover rotating default ticklabels. -* :ghpull:`28282`: DOC: clarify no-build-isolation & mypy ignoring new functions -* :ghpull:`28306`: Fixed PolarAxes not using fmt_xdata and added simple test (#4568) -* :ghpull:`28400`: DOC: Improve doc wording of data parameter -* :ghpull:`28225`: [ENH]: fill_between extended to 3D -* :ghpull:`28371`: Bump pypa/cibuildwheel from 2.18.1 to 2.19.0 in the actions group -* :ghpull:`28390`: Inline RendererBase._get_text_path_transform. -* :ghpull:`28381`: Take hinting rcParam into account in MathTextParser cache. -* :ghpull:`28363`: flip subfigures axes to match subplots -* :ghpull:`28340`: Fix missing font error when using MiKTeX -* :ghpull:`28379`: PathEffectsRenderer can plainly inherit RendererBase._draw_text_as_path. -* :ghpull:`28275`: Revive sanitizing default filenames extracted from UI window titles -* :ghpull:`28360`: DOC: fixed code for testing check figures equal example -* :ghpull:`28370`: Reorder Axes3D parameters semantically. -* :ghpull:`28350`: Typo in communication guide: extensiblity -> extensibility -* :ghpull:`28290`: Introduce natural 3D rotation with mouse -* :ghpull:`28186`: apply unary minus spacing directly after equals sign -* :ghpull:`28311`: Update 3D orientation indication right away -* :ghpull:`28300`: Faster title alignment -* :ghpull:`28313`: Factor out handling of missing spines in alignment calculations. -* :ghpull:`28196`: TST: add timeouts to font_manager + threading test -* :ghpull:`28279`: Doc/ipython dep -* :ghpull:`28091`: [MNT]: create build-requirements.txt and update dev-requirements.txt -* :ghpull:`27992`: Add warning for multiple pyplot.figure calls with same ID -* :ghpull:`28238`: DOC: Update release guide to match current automations -* :ghpull:`28232`: Merge v3.9.0 release into main -* :ghpull:`28228`: DOC: Fix typo in release_guide.rst -* :ghpull:`28074`: Add ``orientation`` parameter to Boxplot and deprecate ``vert`` -* :ghpull:`27998`: Add a new ``orientation`` parameter to Violinplot and deprecate ``vert`` -* :ghpull:`28217`: Better group logging of font handling by texmanager. -* :ghpull:`28130`: Clarify the role of out_mask and out_alpha in _make_image. -* :ghpull:`28201`: Deprecate ``Poly3DCollection.get_vector`` -* :ghpull:`28046`: DOC: Clarify merge policy -* :ghpull:`26893`: PGF: Consistently set LaTeX document font size -* :ghpull:`28156`: Don't set savefig.facecolor/edgecolor in dark_background/538 styles. -* :ghpull:`28030`: Fix #28016: wrong lower ylim when baseline=None on stairs -* :ghpull:`28127`: GOV: write up policy on not updating req for CVEs in dependencies -* :ghpull:`28106`: Fix: [Bug]: Setting norm by string doesn't work for hexbin #28105 -* :ghpull:`28143`: Merge branch v3.9.x into main -* :ghpull:`28133`: Make ``functions`` param to secondary_x/yaxis not keyword-only. -* :ghpull:`28083`: Convert TensorFlow to numpy for plots -* :ghpull:`28116`: FIX: Correct names of aliased cmaps -* :ghpull:`28118`: Remove redundant baseline tests in test_image. -* :ghpull:`28093`: Minor maintenance on pgf docs/backends. -* :ghpull:`27818`: Set polygon offsets for log scaled hexbin -* :ghpull:`28058`: TYP: add float to to_rgba x type -* :ghpull:`27964`: BUG: Fix NonUniformImage with nonlinear scale -* :ghpull:`28054`: DOC: Clarify that parameters to gridded data plotting functions are p… -* :ghpull:`27882`: Deleting all images that have passed tests before upload -* :ghpull:`28033`: API: warn if stairs used in way that is likely not desired -* :ghpull:`27786`: Deprecate positional use of most arguments of plotting functions -* :ghpull:`28025`: DOC: Clarify interface terminology -* :ghpull:`28043`: MNT: Add git blame ignore for docstring parameter indentation fix -* :ghpull:`28037`: DOC: Fix inconsistent spacing in some docstrings in _axes.py -* :ghpull:`28031`: Be more specific in findobj return type +* :ghpull:`29682`: Backport PR #29680 on branch v3.10.x (DOC: fix the bug of examples\event_handling) +* :ghpull:`29683`: Backport PR #29670 on branch v3.10.x (DOC: change marginal scatter plot to subplot_mosaic) +* :ghpull:`29680`: DOC: fix the bug of examples\event_handling +* :ghpull:`29676`: Backport PR #29666 on branch v3.10.x (DOC: Revising the Figure Legend Demo Example) +* :ghpull:`29675`: Backport PR #29662 on branch v3.10.x (DOC: Move Colorbar parameters to __init__) +* :ghpull:`29662`: DOC: Move Colorbar parameters to __init__ +* :ghpull:`29668`: Backport PR #29667 on branch v3.10.x (DOC: remove redundant gridspec from example) +* :ghpull:`29664`: Backport PR #29642 on branch v3.10.x (DOC: Add docstrings to get_usetex and set_usetex in ticker.py) +* :ghpull:`29663`: Backport PR #29075 on branch v3.10.x (Add xaxis and yaxis attributes to Axes docs) +* :ghpull:`29642`: DOC: Add docstrings to get_usetex and set_usetex in ticker.py +* :ghpull:`29661`: Backport PR #29652 on branch v3.10.x (Reorder kwonly kwargs in Colorbar & related docs.) +* :ghpull:`29652`: Reorder kwonly kwargs in Colorbar & related docs. +* :ghpull:`29075`: Add xaxis and yaxis attributes to Axes docs +* :ghpull:`29656`: Backport PR #28437 on branch v3.10.x (Respect array alpha with interpolation_stage='rgba' in _Imagebase::_make_image) +* :ghpull:`29448`: Backport PR #29362 on branch v3.10.0-doc (TYP: semantics of enums in stub files changed) +* :ghpull:`28437`: Respect array alpha with interpolation_stage='rgba' in _Imagebase::_make_image +* :ghpull:`29651`: Backport PR #29650 on branch v3.10.x (Copy-edit "interactive figures & async programming" guide.) +* :ghpull:`29650`: Copy-edit "interactive figures & async programming" guide. +* :ghpull:`29633`: Backport PR #29631 on branch v3.10.x (Add inline notebook to test data) +* :ghpull:`29631`: Add inline notebook to test data +* :ghpull:`29627`: Backport PR #29617 on branch v3.10.x (DOC: Add docstrings to matplotlib.cbook.GrouperView) +* :ghpull:`29617`: DOC: Add docstrings to matplotlib.cbook.GrouperView +* :ghpull:`29625`: Backport PR #29622 on branch v3.10.x (DOC: Move "Infinite lines" example from section "pyplot" to "Lines, bars and markers) +* :ghpull:`29623`: Backport PR #29621 on branch v3.10.x (DOC: Cleanup text rotation in data coordinates example) +* :ghpull:`29619`: Backport PR #29616 on branch v3.10.x (FIX: Fix unit example so that we can unpin numpy<2.1) +* :ghpull:`29616`: FIX: Fix unit example so that we can unpin numpy<2.1 +* :ghpull:`29611`: Backport PR #29608 on branch v3.10.x (Remove md5 usage to prevent issues on FIPS enabled systems (closes #29603)) +* :ghpull:`29608`: Remove md5 usage to prevent issues on FIPS enabled systems (closes #29603) +* :ghpull:`29609`: Backport PR #29607 on branch v3.10.x (Correct doc for axvline arg x which sets x not y) +* :ghpull:`29604`: Backport PR #29601 on branch v3.10.x (DOC: Duplicate categorical values are mapped to the same position) +* :ghpull:`29598`: Backport PR #29597 on branch v3.10.x (Fix typo in deprecation notes for 3.10.0) +* :ghpull:`29591`: Backport PR #29585 on branch v3.10.x (DOC: Document that tight_layout may not converge) +* :ghpull:`29585`: DOC: Document that tight_layout may not converge +* :ghpull:`29587`: Backport PR #25801 on branch v3.10.x (Remove some examples from Userdemo) +* :ghpull:`29577`: Backport PR #29576 on branch v3.10.x (Remove documentation for no-longer existent ContourSet attributes.) +* :ghpull:`29576`: Remove documentation for no-longer existent ContourSet attributes. +* :ghpull:`29530`: Bump the actions group with 5 updates +* :ghpull:`29564`: Backport PR #29563 on branch v3.10.x (DOC: add color sequences reference example) +* :ghpull:`29563`: DOC: add color sequences reference example +* :ghpull:`29557`: Backport PR #29518: TST: Increase tolerance on more arches +* :ghpull:`29555`: Backport PR #29546 on branch v3.10.x (FIX: pyplot.matshow figure handling) +* :ghpull:`29546`: FIX: pyplot.matshow figure handling +* :ghpull:`29518`: TST: Increase tolerance on more arches +* :ghpull:`29547`: Backport PR #29543 on branch v3.10.x (DOC: Minor improvement on broken_barh()) +* :ghpull:`29538`: Backport PR #29536 on branch v3.10.x (Fix typo in solarized example plot.) +* :ghpull:`29531`: Backport PR #29520 on branch v3.10.x (FIX: Correct variable name from _frame to _frames in PillowWriter class) +* :ghpull:`29520`: FIX: Correct variable name from _frame to _frames in PillowWriter class +* :ghpull:`29521`: Backport PR #29509 on branch v3.10.x (MNT: Discourage arrow()) +* :ghpull:`29509`: MNT: Discourage arrow() +* :ghpull:`29514`: Backport PR #29511 on branch v3.10.x (DOC: Document the behavior of bar() for categorical x data) +* :ghpull:`29513`: Backport PR #29471 on branch v3.10.x (Fix subplot docs) +* :ghpull:`29511`: DOC: Document the behavior of bar() for categorical x data +* :ghpull:`29471`: Fix subplot docs +* :ghpull:`29500`: Backport PR #29478 on branch v3.10.x (DOC: Added blurb for colorizer objects in what's new for 3.10) +* :ghpull:`29498`: Backport PR #29488 on branch v3.10.x (DOC: Update broken_barh example) +* :ghpull:`29490`: Backport PR #29476 on branch v3.10.x (ci: Enable native ARM builders for wheels) +* :ghpull:`29476`: ci: Enable native ARM builders for wheels +* :ghpull:`29462`: Backport PR #29404 on branch v3.10.x (DOC: scales - built in options and custom scale usefulness) +* :ghpull:`29459`: Backport PR #29456 on branch v3.10.x (DOC: Fix type descriptions in fill_between docstring) +* :ghpull:`29404`: DOC: scales - built in options and custom scale usefulness +* :ghpull:`29458`: Backport PR #29457 on branch v3.10.x (DOC: Use float instead for scalar for type descriptions in docstrings) +* :ghpull:`29456`: DOC: Fix type descriptions in fill_between docstring +* :ghpull:`29457`: DOC: Use float instead for scalar for type descriptions in docstrings +* :ghpull:`29452`: Backport PR #29411 on branch v3.10.x (fix #29410 Modifying Axes' position also alters the original Bbox object used for initialization) +* :ghpull:`29411`: fix #29410 Modifying Axes' position also alters the original Bbox object used for initialization +* :ghpull:`29451`: Backport PR #29449 on branch v3.10.x (ci: Install libnotify4 on all Ubuntu) +* :ghpull:`29449`: ci: Install libnotify4 on all Ubuntu +* :ghpull:`29444`: Backport PR #29442 on branch v3.10.x (DOC: put section headings in 3.10 what's new) +* :ghpull:`29436`: Backport PR #29407 on branch v3.10.x (DOC: Improve log scale example) +* :ghpull:`29432`: Backport PR #29431 on branch v3.10.x (ft2font: Split named instance count from style flags) +* :ghpull:`29431`: ft2font: Split named instance count from style flags +* :ghpull:`29423`: Backport PR #29130 on branch v3.10.x (Raise warning if both c and facecolors are used in scatter plot (... and related improvements in the test suite).) +* :ghpull:`29420`: Backport PR #29406 on branch v3.10.x (DOC: Update scales overview) +* :ghpull:`29417`: Backport PR #29409 on branch v3.10.x (Fixed test case(test_axes.py) failing on ppc64le) +* :ghpull:`29416`: Backport PR #29382 on branch v3.10.x (Fix title position for polar plots) +* :ghpull:`29382`: Fix title position for polar plots +* :ghpull:`29412`: Backport PR #29363 on branch v3.10.x (FIX: Add version gate to GTK4 calls when necessary) +* :ghpull:`29409`: Fixed test case(test_axes.py) failing on ppc64le +* :ghpull:`29363`: FIX: Add version gate to GTK4 calls when necessary +* :ghpull:`29408`: Backport PR #29401 on branch v3.10.x (FIX: add errorbars with ``add_container``) +* :ghpull:`29401`: FIX: add errorbars with ``add_container`` +* :ghpull:`29130`: Raise warning if both c and facecolors are used in scatter plot (... and related improvements in the test suite). +* :ghpull:`29390`: Backport PR #29389 on branch v3.10.x (DOC: Minor improvements on VPacker, HPacker, PaddedBox docs) +* :ghpull:`29389`: DOC: Minor improvements on VPacker, HPacker, PaddedBox docs +* :ghpull:`29371`: Backport PR #29353 on branch v3.10.x (DOC: Improve module docs of matplotlib.scale) +* :ghpull:`29361`: Backport PR #29355 on branch v3.10.x (Add QtCore.Slot() decorations to FigureCanvasQT) +* :ghpull:`29369`: Backport PR #29362 on branch v3.10.x (TYP: semantics of enums in stub files changed) +* :ghpull:`29353`: DOC: Improve module docs of matplotlib.scale +* :ghpull:`29362`: TYP: semantics of enums in stub files changed +* :ghpull:`29365`: Backport PR #29364 on branch v3.10.x (fix typo) +* :ghpull:`29366`: Backport PR #29347 on branch v3.10.x (DOC: Explain parameters linthresh and linscale of symlog scale) +* :ghpull:`29364`: fix typo +* :ghpull:`29355`: Add QtCore.Slot() decorations to FigureCanvasQT +* :ghpull:`29351`: Backport PR #29348 on branch v3.10.x (DOC: Cleanup scales examples) +* :ghpull:`29336`: Backport PR #29328 on branch v3.10.x (Bump github/codeql-action from 3.27.6 to 3.27.9 in the actions group) +* :ghpull:`29328`: Bump github/codeql-action from 3.27.6 to 3.27.9 in the actions group +* :ghpull:`29330`: Backport PR #29321 on branch v3.10.x (DOC: List min. Python version for Matplotlib 3.10) +* :ghpull:`29324`: Backport PR #29258 on branch v3.10.x (Adding font Size as default parameter) +* :ghpull:`29326`: Backport PR #29323 on branch v3.10.x (DOC: Don't put quotes around coordinate system names) +* :ghpull:`29323`: DOC: Don't put quotes around coordinate system names +* :ghpull:`29258`: Adding font Size as default parameter +* :ghpull:`29320`: Backport PR #29317 on branch v3.10.x (FIX: pass renderer through ``_auto_legend_data``) +* :ghpull:`29317`: FIX: pass renderer through ``_auto_legend_data`` +* :ghpull:`29315`: Backport PR #29314 on branch v3.10.x (DOC: fix footnote in choosing colormaps guide) +* :ghpull:`29309`: Backport PR #29308 on branch v3.10.x (Update cibuildwheel workflow) +* :ghpull:`29310`: Backport PR #29292 on branch v3.10.x (Update dependencies.rst) +* :ghpull:`29308`: Update cibuildwheel workflow -Issues (100): +Issues (14): -* :ghissue:`29298`: [Doc]: The link at "see also" is incorrect. (Axes.violin) -* :ghissue:`29248`: [Bug]: Figure.align_labels() confused by GridSpecFromSubplotSpec -* :ghissue:`26738`: Improve LineCollection docstring further -* :ghissue:`29263`: [Bug]: mypy failures in CI -* :ghissue:`27416`: [Bug]: get_tick_params on xaxis shows wrong keywords -* :ghissue:`29241`: [Bug]: Instructions for setting up conda dev environment in environment.yml give issues with MacOS/zsh -* :ghissue:`29227`: [Bug]: Introductory example on the pyplot API page does not show - missing plt.show() -* :ghissue:`29190`: [Bug]: inconsistent ‘animation.FuncAnimation’ between display and save -* :ghissue:`29090`: [MNT]: More consistent color parameters for bar() -* :ghissue:`29179`: [Bug]: Incorrect pcolormesh when shading='nearest' and only the mesh data C is provided. -* :ghissue:`29067`: [Bug]: ``secondary_xaxis`` produces ticks at incorrect locations -* :ghissue:`29126`: [Bug]: TkAgg backend is broken with tcl/tk 9.0 -* :ghissue:`29045`: [ENH]: implement back/forward buttons on mouse move events on macOS -* :ghissue:`27173`: [Bug]: Gifs no longer create transparent background -* :ghissue:`19229`: Add public API for setting an axis unit converter -* :ghissue:`21108`: [Bug]: Hatch linewidths cannot be modified in an rcParam context -* :ghissue:`27784`: [Bug]: Polar plot error bars don't rotate with angle for ``set_theta_direction`` and ``set_theta_offset`` -* :ghissue:`29011`: [Bug]: Figure.autofmt_xdate() not working in presence of colorbar with constrained layout -* :ghissue:`29020`: AIX internal CI build break #Matplotlib -* :ghissue:`28726`: feature request: support passing DataFrames to table.table -* :ghissue:`28570`: [MNT]: Try improving doc build speed by using PyStemmer -* :ghissue:`13388`: Typo in the figure API (fig.suptitle) -* :ghissue:`28994`: [Bug]: Figure Number Gives Type Error -* :ghissue:`28985`: [ENH]: Cannot disable coordinate display in ToolManager/Toolbar (it's doable in NavigationToolbar2) -* :ghissue:`17914`: ``PathSimplifier`` fails to ignore ``CLOSEPOLY`` vertices -* :ghissue:`28885`: [Bug]: Strange errorbar caps when polar axes have non-default theta direction or theta zero location -* :ghissue:`12418`: replace ttconv for ps/pdf -* :ghissue:`28962`: [Bug]: gtk4 backend does not set guiEvent attribute -* :ghissue:`28408`: [ENH]: mplot3d mouse rotation style -* :ghissue:`28701`: [MNT]: Separate the generation of polygon vertices from ``_fill_between_x_or_y`` -* :ghissue:`28941`: [Bug]: unexplicit error message when using ``matplotlib.colors.rgb_to_hsv()`` with wrong input -* :ghissue:`23846`: [MNT]: Pybind11 transition plan -* :ghissue:`28866`: Possible memory leak in pybind11 migration -* :ghissue:`26368`: [Bug]: Long audio files result in incomplete spectrogram visualizations -* :ghissue:`23826`: [Bug]: Overflow of 16-bit integer in Agg renderer causes PolyCollections to be drawn at incorrect locations -* :ghissue:`28927`: [Bug]: Enforce that Line data modifications are sequences -* :ghissue:`12312`: colorbar(boundaries=...) doesn't work so well with nonlinear norms -* :ghissue:`28800`: [ENH]: AxLine xy1/xy2 setters should take xy as single parameters, (possibly) not separate ones -* :ghissue:`28893`: [Bug]: Lines between points are invisible when there are more than 7 subfigures per row -* :ghissue:`28908`: [Bug]: Possible performance issue with _LazyTickList -* :ghissue:`27971`: [Bug]: ax.xaxis.set_label(...) doesn't set the x-axis label -* :ghissue:`28059`: [Bug]: pcolorfast should validate that regularly spaced X or Y inputs have the right size -* :ghissue:`28892`: [Doc]: Be more specific on dependencies that need to be installed for a "reasonable" dev environment -* :ghissue:`19693`: path.sketch doesn't apply to PolyCollection -* :ghissue:`28873`: [Bug]: hist()'s doc for edgecolors/facecolors does not match behavior (which is itself not very consistent) -* :ghissue:`23005`: [Doc]: Add figure to ``subplots_adjust`` -* :ghissue:`25947`: [Doc]: Subfigures still marked as provisional -* :ghissue:`26012`: [Bug]: "Unhashable type" when event callback is a method of a ``dict`` subclass -* :ghissue:`23425`: [Bug]: Axes.indicate_inset connectors affect constrained layout -* :ghissue:`23424`: [Bug]: Axes.indicate_inset(linewidth=...) doesn't affect connectors -* :ghissue:`19768`: Overlay created by ``Axes.indicate_inset_zoom`` does not adjust when changing inset ranges -* :ghissue:`27673`: [Doc]: Confusing page on color changes -* :ghissue:`28782`: [Bug]: String ``contour(colors)`` gives confusing error when ``extend`` used -* :ghissue:`27930`: [ENH]: Make axes_grid1.Size more math friendly. -* :ghissue:`28372`: [Bug]: AffineDeltaTransform does not appear to invalidate properly -* :ghissue:`27866`: [Bug]: Adding suptitle in compressed layout causes weird spacing -* :ghissue:`28731`: [Bug]: Plotting numpy.array of dtype float32 with pyplot.imshow and specified colors.LogNorm produces wrong colors -* :ghissue:`28715`: [Bug]: CI doc builds fail since a couple of days -* :ghissue:`28698`: [bug]: arrowstyle doc interpolation in FancyPatch.set_arrow() -* :ghissue:`28669`: [Bug]: division-by-zero error in Sketch::Sketch with Agg backend -* :ghissue:`28548`: [Doc]: matplotlib.pyplot.specgram parameters vmin and vmax are not documented -* :ghissue:`28165`: [Bug]: PolygonSelector should hide itself when zoom/pan is active -* :ghissue:`18608`: Feature proposal: "Dark mode" divergent colormaps -* :ghissue:`28623`: [Bug]: ``Axis.set_in_layout`` not respected? -* :ghissue:`6305`: Matplotlib 3D plot - parametric curve “wraparound” from certain perspectives -* :ghissue:`28595`: [Bug]: set_url without effect for instances of Line2D with linestyle 'none' -* :ghissue:`20910`: [Bug]: Exported SVG files are no longer imported Affinity Designer correctly -* :ghissue:`28600`: [TST] Upcoming dependency test failures -* :ghissue:`26718`: [Bug]: stacked histogram does not properly handle edgecolor and hatches -* :ghissue:`28590`: [ENH]: Geo Projections support for inverting axis -* :ghissue:`27954`: [ENH]: Iterables in grouped histogram labels -* :ghissue:`27878`: [ENH]: AttributeError('... got an unexpected keyword argument ...') should set the .name attribute to the keyword -* :ghissue:`28489`: [TST] Upcoming dependency test failures -* :ghissue:`28343`: [Bug]: inconsistent colorbar pad for ``ImageGrid`` with ``cbar_mode="single"`` -* :ghissue:`28535`: [ENH]: Add id attribute to top level svg tag -* :ghissue:`28170`: [Doc]: ``get_figure`` may return a ``SubFigure`` -* :ghissue:`27831`: [Bug]: Nondeterminism in SVG clipPath element id attributes -* :ghissue:`4568`: Add ``fmt_r`` and ``fmt_theta`` methods to polar axes -* :ghissue:`28105`: [Bug]: Setting norm by string doesn't work for hexbin -* :ghissue:`28142`: [ENH]: Add fill between support for 3D plots -* :ghissue:`28344`: [Bug]: subfigures are added in column major order -* :ghissue:`28212`: [Bug]: Matplotlib not work with MiKTeX. -* :ghissue:`28288`: [ENH]: Natural 3D rotation with mouse -* :ghissue:`28180`: [Bug]: mathtext should distinguish between unary and binary minus -* :ghissue:`26150`: [Bug]: Savefig slow with subplots -* :ghissue:`28310`: [Bug]: orientation indication shows up late in mplot3d, and then lingers -* :ghissue:`16263`: Apply NEP29 (time-limited support) to IPython -* :ghissue:`28192`: [MNT]: Essential build requirements not included in dev-requirements -* :ghissue:`27978`: [Bug]: strange behaviour when redefining figure size -* :ghissue:`13435`: boxplot/violinplot orientation-setting API -* :ghissue:`28199`: [MNT]: Misleading function name ``Poly3DCollection.get_vector()`` -* :ghissue:`26892`: [Bug]: PGF font size mismatch between measurement and output -* :ghissue:`28016`: [Bug]: Unexpected ylim of stairs with baseline=None -* :ghissue:`28114`: [Bug]: mpl.colormaps[ "Grays" ].name is "Greys", not "Grays" -* :ghissue:`18045`: Cannot access hexbin data when ``xscale='log'`` and ``yscale='log'`` are set. -* :ghissue:`27820`: [Bug]: Logscale Axis + NonUniformImage + GUI move tool = Distortion -* :ghissue:`28047`: [Bug]: plt.barbs is a command that cannot be passed in a c parameter by parameter name, but can be passed in the form of a positional parameter -* :ghissue:`23400`: Only upload failed images on failure -* :ghissue:`26752`: [Bug]: ``ax.stairs()`` creates inaccurate ``fill`` for the plot -* :ghissue:`21817`: [Doc/Dev]: style guide claims "object oriented" is verboten. +* :ghissue:`28382`: [Bug]: interpolation_stage="rgba" does not respect array-alpha +* :ghissue:`28780`: Doc build fails with numpy>=2.1.0 +* :ghissue:`29603`: [Bug]: Setting ``text.usetex=True`` in ``pyplot.rcParams`` Raises FIPS Compliance Errors +* :ghissue:`29575`: [Doc]: QuadContourSet does not contain a collections attribute like stated in the manual +* :ghissue:`29519`: [Bug]: 'PillowWriter' object has no attribute '_frame' shouldn't be '_frames'? +* :ghissue:`29507`: [Bug]: Duplicating the labels in the ``height``/``width`` argument in ``barh()``/``bar`` leads to undrawn bars +* :ghissue:`29447`: [Doc]: ``subplot`` behavior is not same as the doc reads in 3.10(stable) +* :ghissue:`29410`: [Bug]: Modifying Axes' position also alters the original Bbox object used for initialization +* :ghissue:`29396`: [Bug]: Style flag errors trying to save figures as PDF with font Inter +* :ghissue:`29381`: [Bug]: title position incorrect for polar plot +* :ghissue:`29350`: [Bug]: Matplotlib causes segmentation fault when hovering mouse over graph +* :ghissue:`25274`: [Bug]: .remove() on ErrorbarContainer object does not remove the corresponding item from the legend +* :ghissue:`29202`: [Bug]: ``fontsize`` in tables not working +* :ghissue:`29301`: [Bug]: Blank EPS output with legend and annotate Previous GitHub statistics diff --git a/doc/users/prev_whats_new/github_stats_3.10.0.rst b/doc/users/prev_whats_new/github_stats_3.10.0.rst new file mode 100644 index 000000000000..01b54708b7ec --- /dev/null +++ b/doc/users/prev_whats_new/github_stats_3.10.0.rst @@ -0,0 +1,587 @@ +.. _github-stats-3_10_0: + +GitHub statistics for 3.10.0 (Dec 13, 2024) +=========================================== + +GitHub statistics for 2024/05/15 (tag: v3.9.0) - 2024/12/13 + +These lists are automatically generated, and may be incomplete or contain duplicates. + +We closed 100 issues and merged 337 pull requests. +The full list can be seen `on GitHub `__ + +The following 128 authors contributed 1932 commits. + +* abhi-jha +* Adam J. Stewart +* Aditi Gautam +* Aditya Vidyadhar Kamath +* Aishling Cooke +* Alan +* Alan Sosa +* Alice +* Aman Nijjar +* Ammar Qazi +* Ancheng +* anpaulan +* Anson0028 +* Anthony Lee +* anTon +* Antony Lee +* Ayoub Gouasmi +* Brigitta Sipőcz +* Caitlin Hathaway +* cesar +* Charlie LeWarne +* Christian Mattsson +* ClarkeAC +* Clemens Brunner +* Clement Gilli +* cmp0xff +* Costa Paraskevopoulos +* dale +* Dani Pinyol +* Daniel Weiss +* Danny +* David Bakaj +* David Lowry-Duda +* David Meyer +* David Stansby +* dbakaj +* dependabot[bot] +* Diogo Cardoso +* Doron Behar +* Edgar Andrés Margffoy Tuay +* Elliott Sales de Andrade +* Eytan Adler +* farquh +* Felipe Cybis Pereira +* Filippo Balzaretti +* FMasson +* Francisco Cardozo +* Gavin S +* Greg Lucas +* haaris +* hannah +* Ian Thomas +* Illviljan +* James Addison +* James Spencer +* Jody Klymak +* john +* Jonas Eschle +* Jouni K. Seppänen +* juanis2112 +* Juanita Gomez +* Justin Hendrick +* K900 +* Kaustbh +* Kaustubh +* Kherim Willems +* Kyle Sunden +* Kyra Cho +* Larry Bradley +* litchi +* Lorenzo +* Lucx33 +* Lumberbot (aka Jack) +* MadPhysicist +* malhar2460 +* Martino Sorbaro +* Mathias Hauser +* Matthew Feickert +* Matthew Petroff +* Melissa Weber Mendonça +* Michael +* Michael Droettboom +* Michael Hinton +* MischaMegens2 +* Moritz Wolter +* muchojp +* Nabil +* nakamura yuki +* odile +* OdileVidrine +* Oscar Gustafsson +* Panicks28 +* Paul An +* Pedro Barão +* PedroBittarBarao +* Peter Talley +* Pierre-antoine Comby +* Pranav +* Pranav Raghu +* pre-commit-ci[bot] +* proximalf +* r3kste +* Randolf Scholz +* Refael Ackermann +* RickyP24 +* rnhmjoj +* Ruth Comer +* Ryan May +* Sai Chaitanya, Sanivada +* saranti +* scaccol +* Scott Shambaugh +* Sean Smith +* Simon May +* simond07 +* smcgrawDotNet +* Takumasa N +* Takumasa N. +* Takumasa Nakamura +* thiagoluisbecker +* Thomas A Caswell +* Tiago Lubiana +* Tim Hoffmann +* trananso +* Trygve Magnus Ræder +* Victor Liu +* vittoboa +* Xeniya Shoiko + +GitHub issues and pull requests: + +Pull Requests (337): + +* :ghpull:`29299`: Merge v3.9.x into v3.10.x +* :ghpull:`29296`: Backport PR #29295 on branch v3.10.x (BLD: Pin meson-python to <0.17.0) +* :ghpull:`29290`: Backport PR #29254 on branch v3.10.x (DOC: Add note to align_labels()) +* :ghpull:`29289`: Backport PR #29260 on branch v3.10.x (DOC: Better explanation of rcParams "patch.edgecolor" and "patch.force_edgecolor") +* :ghpull:`29288`: Backport PR #29285 on branch v3.10.x (Retarget PR#29175 to main) +* :ghpull:`29254`: DOC: Add note to align_labels() +* :ghpull:`29260`: DOC: Better explanation of rcParams "patch.edgecolor" and "patch.force_edgecolor" +* :ghpull:`29285`: Retarget PR#29175 to main +* :ghpull:`29286`: Backport PR #29274 on branch v3.10.x (Bump the actions group across 1 directory with 2 updates) +* :ghpull:`29274`: Bump the actions group across 1 directory with 2 updates +* :ghpull:`29283`: Backport PR #29272 on branch v3.10.x (DOC: Add section on translating between Axes and pyplot interface) +* :ghpull:`29272`: DOC: Add section on translating between Axes and pyplot interface +* :ghpull:`29279`: Backport PR #29265 on branch v3.10.x (DOC: Slightly improve the LineCollection docstring) +* :ghpull:`29276`: Backport PR #29247 on branch v3.10.x (Fix building freetype 2.6.1 on macOS clang 18) +* :ghpull:`29244`: Switch to a 3d rotation trackball implementation with path independence +* :ghpull:`29265`: DOC: Slightly improve the LineCollection docstring +* :ghpull:`29247`: Fix building freetype 2.6.1 on macOS clang 18 +* :ghpull:`29268`: Bump the actions group with 2 updates +* :ghpull:`29266`: Backport PR #29251 on branch v3.10.x (Zizmor audit) +* :ghpull:`29269`: Backport PR #29267 on branch v3.10.x (Exclude pylab from mypy checks) +* :ghpull:`29267`: Exclude pylab from mypy checks +* :ghpull:`29251`: Zizmor audit +* :ghpull:`29255`: Backport PR #29249 on branch v3.10.x ([Bug Fix] Fix reverse mapping for _translate_tick_params) +* :ghpull:`29249`: [Bug Fix] Fix reverse mapping for _translate_tick_params +* :ghpull:`29250`: Backport PR #29243 on branch v3.10.x (Add quotes around [dev] in environment.yml) +* :ghpull:`29243`: Add quotes around [dev] in environment.yml +* :ghpull:`29246`: Backport PR #29240 on branch v3.10.x (DOC: Add plt.show() to introductory pyplot example) +* :ghpull:`29240`: DOC: Add plt.show() to introductory pyplot example +* :ghpull:`29239`: Backport PR #29236 on branch v3.10.x (ANI: Reduce Pillow frames to RGB when opaque) +* :ghpull:`29238`: Backport PR #29167 on branch v3.10.x (BUGFIX: use axes unit information in ConnectionPatch ) +* :ghpull:`29236`: ANI: Reduce Pillow frames to RGB when opaque +* :ghpull:`29167`: BUGFIX: use axes unit information in ConnectionPatch +* :ghpull:`29232`: Merge branch v3.9.x into v3.10.x +* :ghpull:`29230`: Backport PR #29188 on branch v3.10.x (Bump pypa/cibuildwheel from 2.21.3 to 2.22.0 in the actions group) +* :ghpull:`29188`: Bump pypa/cibuildwheel from 2.21.3 to 2.22.0 in the actions group +* :ghpull:`29225`: Backport PR #29213 on branch v3.10.x (avoid-unnecessary-warning-in-_pcolorargs-function) +* :ghpull:`29211`: Backport PR #29133 on branch v3.10.x (Creating_parse_bar_color_args to unify color handling in plt.bar with precedence and sequence support for facecolor and edgecolor) +* :ghpull:`29177`: Backport PR #29148 on branch v3.10.x (Don't fail on equal-but-differently-named cmaps in qt figureoptions.) +* :ghpull:`29226`: Backport PR #29206 on branch v3.10.x (Skip more tests on pure-Wayland systems) +* :ghpull:`29206`: Skip more tests on pure-Wayland systems +* :ghpull:`29213`: avoid-unnecessary-warning-in-_pcolorargs-function +* :ghpull:`29210`: Backport PR #29209 on branch v3.10.x (FIX: pcolormesh with no x y args and nearest interp) +* :ghpull:`29133`: Creating_parse_bar_color_args to unify color handling in plt.bar with precedence and sequence support for facecolor and edgecolor +* :ghpull:`29209`: FIX: pcolormesh with no x y args and nearest interp +* :ghpull:`29200`: Backport PR #29182 on branch v3.10.x (Update backend_qt.py: parent not passed to __init__ on subplottool) +* :ghpull:`29207`: Backport PR #29169 on branch v3.10.x (Minor fixes to text intro explainer) +* :ghpull:`29169`: Minor fixes to text intro explainer +* :ghpull:`29159`: Pending warning for deprecated parameter 'vert' of box and violin on 3.10 +* :ghpull:`29196`: Backport PR #29191 on branch v3.10.x (ci: Simplify 3.13t test setup) +* :ghpull:`29182`: Update backend_qt.py: parent not passed to __init__ on subplottool +* :ghpull:`29189`: Backport PR #28934 on branch v3.10.x (ci: Unpin micromamba again) +* :ghpull:`29186`: Backport PR #28335 on branch v3.10.x (DOC: do not posting LLM output as your own work) +* :ghpull:`28934`: ci: Unpin micromamba again +* :ghpull:`28335`: DOC: do not posting LLM output as your own work +* :ghpull:`29178`: Backport PR #29163 on branch v3.9.x (ci: Remove outdated pkg-config package on macOS) +* :ghpull:`29170`: Backport PR #29154 on branch v3.10.x (Relax conditions for warning on updating converters) +* :ghpull:`29154`: Relax conditions for warning on updating converters +* :ghpull:`29166`: Backport PR #29153 on branch v3.10.x (Bump codecov/codecov-action from 4 to 5 in the actions group) +* :ghpull:`29164`: Backport PR #29163 on branch v3.10.x (ci: Remove outdated pkg-config package on macOS) +* :ghpull:`29168`: Backport PR #29073 on branch v3.10.x (Update secondary_axis tutorial) +* :ghpull:`29073`: Update secondary_axis tutorial +* :ghpull:`29163`: ci: Remove outdated pkg-config package on macOS +* :ghpull:`29145`: Backport PR #29144 on branch v3.10.x (Use both TCL_SETVAR and TCL_SETVAR2 for tcl 9 support) +* :ghpull:`29144`: Use both TCL_SETVAR and TCL_SETVAR2 for tcl 9 support +* :ghpull:`29140`: Backport PR #29080 on branch v3.10.x (Updates the ``galleries/tutorials/artists.py`` file in response to issue #28920) +* :ghpull:`29080`: Updates the ``galleries/tutorials/artists.py`` file in response to issue #28920 +* :ghpull:`29138`: Backport PR #29134 on branch v3.10.x (MNT: Temporarily skip failing test to unbreak CI) +* :ghpull:`29134`: MNT: Temporarily skip failing test to unbreak CI +* :ghpull:`29132`: Backport PR #29128 on branch v3.10.x (Tweak AutoMinorLocator docstring.) +* :ghpull:`29128`: Tweak AutoMinorLocator docstring. +* :ghpull:`29123`: Bump the actions group with 2 updates +* :ghpull:`29122`: Backport PR #29120 on branch v3.10.x (DOC: Switch nested pie example from cmaps to color_sequences) +* :ghpull:`29100`: Backport PR #29099 on branch v3.10.x (MNT: remove _ttconv.pyi) +* :ghpull:`29099`: MNT: remove _ttconv.pyi +* :ghpull:`29098`: Backport PR #29097 on branch v3.10.x (ENH: add back/forward buttons to osx backend move) +* :ghpull:`29097`: ENH: add back/forward buttons to osx backend move +* :ghpull:`29095`: Backport PR #29071 on branch v3.10.x (Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.11.0 in the actions group) +* :ghpull:`29096`: Backport PR #29094 on branch v3.10.x (DOC: fix link in See Also section of axes.violin) +* :ghpull:`29092`: Backport PR #29088 on branch v3.10.x (DOC: Format aliases in kwargs tables) +* :ghpull:`29094`: DOC: fix link in See Also section of axes.violin +* :ghpull:`29091`: Backport PR #29085 on branch v3.10.x (FIX: Update GTK3Agg backend export name for consistency) +* :ghpull:`29088`: DOC: Format aliases in kwargs tables +* :ghpull:`29089`: Backport PR #29065 on branch v3.10.x (DOC: Update docstring of triplot()) +* :ghpull:`29085`: FIX: Update GTK3Agg backend export name for consistency +* :ghpull:`29084`: Backport PR #29081 on branch v3.10.x (Document "none" as color value) +* :ghpull:`29065`: DOC: Update docstring of triplot() +* :ghpull:`29081`: Document "none" as color value +* :ghpull:`29061`: Backport PR #29024 on branch v3.10.x (Fix saving animations to transparent formats) +* :ghpull:`29069`: Backport PR #29068 on branch v3.10.x ([DOC] Fix indentation in sync_cmaps example) +* :ghpull:`29070`: Backport PR #29048 on branch v3.10.x (DOC: integrated pr workflow from contributing guide into install and workflow) +* :ghpull:`29048`: DOC: integrated pr workflow from contributing guide into install and workflow +* :ghpull:`29068`: [DOC] Fix indentation in sync_cmaps example +* :ghpull:`29024`: Fix saving animations to transparent formats +* :ghpull:`29059`: Cleanup converter docs and StrCategoryConverter behavior +* :ghpull:`29058`: [DOC] Update missing-references.json +* :ghpull:`29057`: DOC/TST: lock numpy<2.1 in environment.yml +* :ghpull:`29053`: Factor out common formats strings in LogFormatter, LogFormatterExponent. +* :ghpull:`28970`: Add explicit converter setting to Axis +* :ghpull:`28048`: Enables setting hatch linewidth in Patches and Collections, also fixes setting hatch linewidth by rcParams +* :ghpull:`29017`: DOC: Document preferred figure size for examples +* :ghpull:`28871`: updated contribution doc #28476 +* :ghpull:`28453`: Stop relying on dead-reckoning mouse buttons for motion_notify_event. +* :ghpull:`28495`: ticker.EngFormatter: allow offset +* :ghpull:`29039`: MNT: Add provisional get_backend(resolve=False) flag +* :ghpull:`28946`: MNT: Deprecate plt.polar() with an existing non-polar Axes +* :ghpull:`29013`: FIX: auto_fmtxdate for constrained layout +* :ghpull:`29022`: Fixes AIX internal CI build break. +* :ghpull:`28830`: Feature: Support passing DataFrames to table.table +* :ghpull:`27766`: Return filename from save_figure +* :ghpull:`27167`: ENH: add long_axis property to colorbar +* :ghpull:`29021`: Update minimum pybind11 to 2.13.2 +* :ghpull:`28863`: Improved documentation for quiver +* :ghpull:`29019`: Update requirements to add PyStemmer to doc-requirements and environment +* :ghpull:`28653`: Mnt/generalize plot varargs +* :ghpull:`28967`: Fix MSVC cast warnings +* :ghpull:`29016`: DOC: Better explain suptitle / supxlabel / supylabel naming +* :ghpull:`28842`: FT2Font extension improvements +* :ghpull:`28658`: New data → color pipeline +* :ghpull:`29012`: Bump required pybind11 to 2.13 +* :ghpull:`29007`: MNT: Deprecate changing Figure.number +* :ghpull:`28861`: Break Artist._remove_method reference cycle +* :ghpull:`28478`: bugfix for ``PathSimplifier`` +* :ghpull:`28992`: DOC: Refresh transform tree example +* :ghpull:`28890`: MNT: Add missing dependency to environment.yml +* :ghpull:`28354`: Add Quiverkey zorder option +* :ghpull:`28966`: Fix polar error bar cap orientation +* :ghpull:`28819`: Mark all extensions as free-threading safe +* :ghpull:`28986`: DOC: Add tags for 3D fill_between examples +* :ghpull:`28984`: DOC / BUG: Better example for 3D axlim_clip argument +* :ghpull:`20866`: Remove ttconv and implement Type-42 embedding using fontTools +* :ghpull:`28975`: Set guiEvent where applicable for gtk4. +* :ghpull:`28568`: added tags to mplot3d examples +* :ghpull:`28976`: Bump pypa/cibuildwheel from 2.21.2 to 2.21.3 in the actions group +* :ghpull:`28978`: CI: Resolve mypy stubtest build errors +* :ghpull:`28823`: Fix 3D rotation precession +* :ghpull:`28841`: Make mplot3d mouse rotation style adjustable +* :ghpull:`28971`: DOC: correct linestyle example and reference rcParams +* :ghpull:`28702`: [MNT]: #28701 separate the generation of polygon vertices in fill_between to enable resampling +* :ghpull:`28965`: Suggest imageio_ffmpeg to provide ffmpeg as animation writer. +* :ghpull:`28964`: FIX macos: Use the agg buffer_rgba rather than private attribute +* :ghpull:`28963`: Remove refs to outdated writers in animation.py. +* :ghpull:`28948`: Raise ValueError for RGB values outside the [0, 1] range in rgb_to_hsv function +* :ghpull:`28857`: Pybind11 cleanup +* :ghpull:`28949`: [pre-commit.ci] pre-commit autoupdate +* :ghpull:`28950`: Bump the actions group with 2 updates +* :ghpull:`28904`: Agg: Remove 16-bit limits +* :ghpull:`28856`: Convert remaining code to pybind11 +* :ghpull:`28874`: Remove remaining 3.8 deprecations +* :ghpull:`28943`: DOC: Clarify the returned line of axhline()/axvline() +* :ghpull:`28935`: DOC: Fix invalid rcParam references +* :ghpull:`28942`: In colorbar docs, add ref from 'boundaries' doc to 'spacing' doc. +* :ghpull:`28933`: Switch AxLine.set_xy{1,2} to take a single argument. +* :ghpull:`28869`: ci: Bump build image on AppVeyor to MSVC 2019 +* :ghpull:`28906`: Re-fix exception caching in dviread. +* :ghpull:`27349`: [ENH] Implement dynamic clipping to axes limits for 3D plots +* :ghpull:`28913`: DOC: Fix Axis.set_label reference +* :ghpull:`28911`: MNT: Fix double evaluation of _LazyTickList +* :ghpull:`28584`: MNT: Prevent users from erroneously using legend label API on Axis +* :ghpull:`28853`: MNT: Check the input sizes of regular X,Y in pcolorfast +* :ghpull:`28838`: TST: Fix minor issues in interactive backend test +* :ghpull:`28795`: MNT: Cleanup docstring substitution mechanisms +* :ghpull:`28897`: Fix minor issues in stubtest wrapper +* :ghpull:`28899`: Don't cache exception with traceback reference loop in dviread. +* :ghpull:`28888`: DOC: Better visualization for the default color cycle example +* :ghpull:`28896`: doc: specify non-python dependencies in dev install docs +* :ghpull:`28843`: MNT: Cleanup FontProperties __init__ API +* :ghpull:`28683`: MNT: Warn if fixed aspect overwrites explicitly set data limits +* :ghpull:`25645`: Fix issue with sketch not working on PathCollection in Agg +* :ghpull:`28886`: DOC: Cross-link Axes attributes +* :ghpull:`28880`: Remove 'in' from removal substitution for deprecation messages +* :ghpull:`28875`: DOC: Fix documentation of hist() kwarg lists +* :ghpull:`28825`: DOC: Fix non-working code object references +* :ghpull:`28862`: Improve pie chart error messages +* :ghpull:`28844`: DOC: Add illustration to Figure.subplots_adjust +* :ghpull:`28588`: Fix scaling in Tk on non-Windows systems +* :ghpull:`28849`: DOC: Mark subfigures as no longer provisional +* :ghpull:`26000`: making onselect a keyword argument on selectors +* :ghpull:`26013`: Support unhashable callbacks in CallbackRegistry +* :ghpull:`27011`: Convert Agg extension to pybind11 +* :ghpull:`28845`: In examples, prefer named locations rather than location numbers. +* :ghpull:`27218`: API: finish LocationEvent.lastevent removal +* :ghpull:`26870`: Removed the deprecated code from axis.py +* :ghpull:`27996`: Create ``InsetIndicator`` artist +* :ghpull:`28532`: TYP: Fix xycoords and friends +* :ghpull:`28785`: Convert ft2font extension to pybind11 +* :ghpull:`28815`: DOC: Document policy on colormaps and styles +* :ghpull:`28826`: MNT: Replace _docstring.dedent_interpd by its alias _docstring.interpd +* :ghpull:`27567`: DOC: batch of tags +* :ghpull:`27302`: Tags for simple_scatter.py demo +* :ghpull:`28820`: DOC: Fix missing cross-reference checks for sphinx-tags +* :ghpull:`28786`: Handle single color in ContourSet +* :ghpull:`28808`: DOC: Add a plot to margins() to visualize the effect +* :ghpull:`27938`: feat: add dunder method for math operations on Axes Size divider +* :ghpull:`28569`: Adding tags to many examples +* :ghpull:`28183`: Expire deprecations +* :ghpull:`28801`: DOC: Clarify AxLine.set_xy2 / AxLine.set_slope +* :ghpull:`28788`: TST: Skip webp tests if it isn't available +* :ghpull:`28550`: Remove internal use of ``Artist.figure`` +* :ghpull:`28767`: MNT: expire ``ContourSet`` deprecations +* :ghpull:`28755`: TYP: Add typing for internal _tri extension +* :ghpull:`28765`: Add tests for most of FT2Font, and fix some bugs +* :ghpull:`28781`: TST: Fix test_pickle_load_from_subprocess in a dirty tree +* :ghpull:`28783`: Fix places where "auto" was not listed as valid interpolation_stage. +* :ghpull:`28779`: DOC/TST: lock numpy < 2.1 +* :ghpull:`28771`: Ensure SketchParams is always fully initialized +* :ghpull:`28375`: FIX: Made AffineDeltaTransform pass-through properly +* :ghpull:`28454`: MultivarColormap and BivarColormap +* :ghpull:`27891`: Refactor some parts of ft2font extension +* :ghpull:`28752`: quick fix dev build by locking out numpy version that's breaking things +* :ghpull:`28749`: Add sphinxcontrib-video to environment.yml +* :ghpull:`27851`: Add ten-color accessible color cycle as style sheet +* :ghpull:`28501`: ConciseDateFormatter's offset string is correct on an inverted axis +* :ghpull:`28734`: Compressed layout moves suptitle +* :ghpull:`28736`: Simplify some code in dviread +* :ghpull:`28347`: Doc: added triage section to new contributor docs +* :ghpull:`28735`: ci: Avoid setuptools 72.2.0 when installing kiwi on PyPy +* :ghpull:`28728`: MNT: Deprecate reimported functions in top-level namespace +* :ghpull:`28730`: MNT: Don't rely on RcParams being a dict subclass in internal code +* :ghpull:`28714`: Simplify _api.warn_external on Python 3.12+ +* :ghpull:`28727`: MNT: Better workaround for format_cursor_data on ScalarMappables +* :ghpull:`28725`: Stop disabling FH4 Exception Handling on MSVC +* :ghpull:`28711`: Merge branch v3.9.x into main +* :ghpull:`28713`: DOC: Add a few more notes to release guide +* :ghpull:`28720`: DOC: Clarify axhline() uses axes coordinates +* :ghpull:`28718`: DOC: Update missing references for numpydoc 1.8.0 +* :ghpull:`28710`: DOC: clarify alpha handling for indicate_inset[_zoom] +* :ghpull:`28704`: Fixed arrowstyle doc interpolation in FancyPatch.set_arrow() #28698. +* :ghpull:`28709`: Bump actions/attest-build-provenance from 1.4.0 to 1.4.1 in the actions group +* :ghpull:`28707`: Avoid division-by-zero in Sketch::Sketch +* :ghpull:`28610`: CI: Add CI to test matplotlib against free-threaded Python +* :ghpull:`28262`: Fix PolygonSelector cursor to temporarily hide during active zoom/pan +* :ghpull:`28670`: API: deprecate unused helper in patch._Styles +* :ghpull:`28589`: Qt embedding example: Separate drawing and data retrieval timers +* :ghpull:`28655`: Inline annotation and PGF user demos +* :ghpull:`28654`: DOC: Remove long uninstructive examples +* :ghpull:`28652`: Fix docstring style inconsistencies in lines.py +* :ghpull:`28641`: DOC: Standardize example titles - part 2 +* :ghpull:`28642`: DOC: Simplify heatmap example +* :ghpull:`28638`: DOC: Remove hint on PRs from origin/main +* :ghpull:`28587`: Added dark-mode diverging colormaps +* :ghpull:`28546`: DOC: Clarify/simplify example of multiple images with one colorbar +* :ghpull:`28613`: Added documentation for parameters vmin and vmax inside specgram function. +* :ghpull:`28627`: DOC: Bump minimum Sphinx to 5.1.0 +* :ghpull:`28628`: DOC: Sub-structure next API changes overview +* :ghpull:`28629`: FIX: ``Axis.set_in_layout`` respected +* :ghpull:`28575`: Add branch tracking to development workflow instructions +* :ghpull:`28616`: CI: Build docs on latest Python +* :ghpull:`28617`: DOC: Enable parallel builds +* :ghpull:`28544`: DOC: Standardize example titles +* :ghpull:`28615`: DOC: hack to suppress sphinx-gallery 17.0 warning +* :ghpull:`28293`: BLD: Enable building Python 3.13 wheels for nightlies +* :ghpull:`27385`: Fix 3D lines being visible when behind camera +* :ghpull:`28609`: svg: Ensure marker-only lines get URLs +* :ghpull:`28599`: Upgrade code to Python 3.10 +* :ghpull:`28593`: Update ruff to 0.2.0 +* :ghpull:`28603`: Simplify ttconv python<->C++ conversion using std::optional. +* :ghpull:`28557`: DOC: apply toc styling to remove nesting +* :ghpull:`28542`: CI: adjust pins in mypy GHA job +* :ghpull:`28504`: Changes in SVG backend to improve compatibility with Affinity designer +* :ghpull:`28122`: Disable clipping in Agg resamplers. +* :ghpull:`28597`: Pin PyQt6 back on Ubuntu 20.04 +* :ghpull:`28073`: Add support for multiple hatches, edgecolors and linewidths in histograms +* :ghpull:`28594`: MNT: Raise on GeoAxes limits manipulation +* :ghpull:`28312`: Remove one indirection layer in ToolSetCursor. +* :ghpull:`28573`: ENH: include property name in artist AttributeError +* :ghpull:`28503`: Bump minimum Python to 3.10 +* :ghpull:`28525`: FIX: colorbar pad for ``ImageGrid`` +* :ghpull:`28558`: DOC: Change _make_image signature to numpydoc +* :ghpull:`28061`: API: add antialiased to interpolation-stage in image +* :ghpull:`28536`: [svg] Add rcParam["svg.id"] to add a top-level id attribute to +* :ghpull:`28540`: Subfigures become stale when their artists are stale +* :ghpull:`28177`: Rationalise artist get_figure methods; make figure attribute a property +* :ghpull:`28527`: DOC: improve tagging guidelines page +* :ghpull:`28530`: DOC: Simplify axhspan example +* :ghpull:`28537`: DOC: Update timeline example for newer releases +* :ghpull:`27833`: [SVG] Introduce sequential ID-generation scheme for clip-paths. +* :ghpull:`28512`: DOC: Fix version switcher for stable docs +* :ghpull:`28492`: MNT: Remove PolyQuadMesh deprecations +* :ghpull:`28509`: CI: Use micromamba on AppVeyor +* :ghpull:`28510`: Merge v3.9.1 release into main +* :ghpull:`28494`: [pre-commit.ci] pre-commit autoupdate +* :ghpull:`28497`: Add words to ignore for codespell +* :ghpull:`28455`: Expand ticklabels_rotation example to cover rotating default ticklabels. +* :ghpull:`28282`: DOC: clarify no-build-isolation & mypy ignoring new functions +* :ghpull:`28306`: Fixed PolarAxes not using fmt_xdata and added simple test (#4568) +* :ghpull:`28400`: DOC: Improve doc wording of data parameter +* :ghpull:`28225`: [ENH]: fill_between extended to 3D +* :ghpull:`28371`: Bump pypa/cibuildwheel from 2.18.1 to 2.19.0 in the actions group +* :ghpull:`28390`: Inline RendererBase._get_text_path_transform. +* :ghpull:`28381`: Take hinting rcParam into account in MathTextParser cache. +* :ghpull:`28363`: flip subfigures axes to match subplots +* :ghpull:`28340`: Fix missing font error when using MiKTeX +* :ghpull:`28379`: PathEffectsRenderer can plainly inherit RendererBase._draw_text_as_path. +* :ghpull:`28275`: Revive sanitizing default filenames extracted from UI window titles +* :ghpull:`28360`: DOC: fixed code for testing check figures equal example +* :ghpull:`28370`: Reorder Axes3D parameters semantically. +* :ghpull:`28350`: Typo in communication guide: extensiblity -> extensibility +* :ghpull:`28290`: Introduce natural 3D rotation with mouse +* :ghpull:`28186`: apply unary minus spacing directly after equals sign +* :ghpull:`28311`: Update 3D orientation indication right away +* :ghpull:`28300`: Faster title alignment +* :ghpull:`28313`: Factor out handling of missing spines in alignment calculations. +* :ghpull:`28196`: TST: add timeouts to font_manager + threading test +* :ghpull:`28279`: Doc/ipython dep +* :ghpull:`28091`: [MNT]: create build-requirements.txt and update dev-requirements.txt +* :ghpull:`27992`: Add warning for multiple pyplot.figure calls with same ID +* :ghpull:`28238`: DOC: Update release guide to match current automations +* :ghpull:`28232`: Merge v3.9.0 release into main +* :ghpull:`28228`: DOC: Fix typo in release_guide.rst +* :ghpull:`28074`: Add ``orientation`` parameter to Boxplot and deprecate ``vert`` +* :ghpull:`27998`: Add a new ``orientation`` parameter to Violinplot and deprecate ``vert`` +* :ghpull:`28217`: Better group logging of font handling by texmanager. +* :ghpull:`28130`: Clarify the role of out_mask and out_alpha in _make_image. +* :ghpull:`28201`: Deprecate ``Poly3DCollection.get_vector`` +* :ghpull:`28046`: DOC: Clarify merge policy +* :ghpull:`26893`: PGF: Consistently set LaTeX document font size +* :ghpull:`28156`: Don't set savefig.facecolor/edgecolor in dark_background/538 styles. +* :ghpull:`28030`: Fix #28016: wrong lower ylim when baseline=None on stairs +* :ghpull:`28127`: GOV: write up policy on not updating req for CVEs in dependencies +* :ghpull:`28106`: Fix: [Bug]: Setting norm by string doesn't work for hexbin #28105 +* :ghpull:`28143`: Merge branch v3.9.x into main +* :ghpull:`28133`: Make ``functions`` param to secondary_x/yaxis not keyword-only. +* :ghpull:`28083`: Convert TensorFlow to numpy for plots +* :ghpull:`28116`: FIX: Correct names of aliased cmaps +* :ghpull:`28118`: Remove redundant baseline tests in test_image. +* :ghpull:`28093`: Minor maintenance on pgf docs/backends. +* :ghpull:`27818`: Set polygon offsets for log scaled hexbin +* :ghpull:`28058`: TYP: add float to to_rgba x type +* :ghpull:`27964`: BUG: Fix NonUniformImage with nonlinear scale +* :ghpull:`28054`: DOC: Clarify that parameters to gridded data plotting functions are p… +* :ghpull:`27882`: Deleting all images that have passed tests before upload +* :ghpull:`28033`: API: warn if stairs used in way that is likely not desired +* :ghpull:`27786`: Deprecate positional use of most arguments of plotting functions +* :ghpull:`28025`: DOC: Clarify interface terminology +* :ghpull:`28043`: MNT: Add git blame ignore for docstring parameter indentation fix +* :ghpull:`28037`: DOC: Fix inconsistent spacing in some docstrings in _axes.py +* :ghpull:`28031`: Be more specific in findobj return type + +Issues (100): + +* :ghissue:`29298`: [Doc]: The link at "see also" is incorrect. (Axes.violin) +* :ghissue:`29248`: [Bug]: Figure.align_labels() confused by GridSpecFromSubplotSpec +* :ghissue:`26738`: Improve LineCollection docstring further +* :ghissue:`29263`: [Bug]: mypy failures in CI +* :ghissue:`27416`: [Bug]: get_tick_params on xaxis shows wrong keywords +* :ghissue:`29241`: [Bug]: Instructions for setting up conda dev environment in environment.yml give issues with MacOS/zsh +* :ghissue:`29227`: [Bug]: Introductory example on the pyplot API page does not show - missing plt.show() +* :ghissue:`29190`: [Bug]: inconsistent ‘animation.FuncAnimation’ between display and save +* :ghissue:`29090`: [MNT]: More consistent color parameters for bar() +* :ghissue:`29179`: [Bug]: Incorrect pcolormesh when shading='nearest' and only the mesh data C is provided. +* :ghissue:`29067`: [Bug]: ``secondary_xaxis`` produces ticks at incorrect locations +* :ghissue:`29126`: [Bug]: TkAgg backend is broken with tcl/tk 9.0 +* :ghissue:`29045`: [ENH]: implement back/forward buttons on mouse move events on macOS +* :ghissue:`27173`: [Bug]: Gifs no longer create transparent background +* :ghissue:`19229`: Add public API for setting an axis unit converter +* :ghissue:`21108`: [Bug]: Hatch linewidths cannot be modified in an rcParam context +* :ghissue:`27784`: [Bug]: Polar plot error bars don't rotate with angle for ``set_theta_direction`` and ``set_theta_offset`` +* :ghissue:`29011`: [Bug]: Figure.autofmt_xdate() not working in presence of colorbar with constrained layout +* :ghissue:`29020`: AIX internal CI build break #Matplotlib +* :ghissue:`28726`: feature request: support passing DataFrames to table.table +* :ghissue:`28570`: [MNT]: Try improving doc build speed by using PyStemmer +* :ghissue:`13388`: Typo in the figure API (fig.suptitle) +* :ghissue:`28994`: [Bug]: Figure Number Gives Type Error +* :ghissue:`28985`: [ENH]: Cannot disable coordinate display in ToolManager/Toolbar (it's doable in NavigationToolbar2) +* :ghissue:`17914`: ``PathSimplifier`` fails to ignore ``CLOSEPOLY`` vertices +* :ghissue:`28885`: [Bug]: Strange errorbar caps when polar axes have non-default theta direction or theta zero location +* :ghissue:`12418`: replace ttconv for ps/pdf +* :ghissue:`28962`: [Bug]: gtk4 backend does not set guiEvent attribute +* :ghissue:`28408`: [ENH]: mplot3d mouse rotation style +* :ghissue:`28701`: [MNT]: Separate the generation of polygon vertices from ``_fill_between_x_or_y`` +* :ghissue:`28941`: [Bug]: unexplicit error message when using ``matplotlib.colors.rgb_to_hsv()`` with wrong input +* :ghissue:`23846`: [MNT]: Pybind11 transition plan +* :ghissue:`28866`: Possible memory leak in pybind11 migration +* :ghissue:`26368`: [Bug]: Long audio files result in incomplete spectrogram visualizations +* :ghissue:`23826`: [Bug]: Overflow of 16-bit integer in Agg renderer causes PolyCollections to be drawn at incorrect locations +* :ghissue:`28927`: [Bug]: Enforce that Line data modifications are sequences +* :ghissue:`12312`: colorbar(boundaries=...) doesn't work so well with nonlinear norms +* :ghissue:`28800`: [ENH]: AxLine xy1/xy2 setters should take xy as single parameters, (possibly) not separate ones +* :ghissue:`28893`: [Bug]: Lines between points are invisible when there are more than 7 subfigures per row +* :ghissue:`28908`: [Bug]: Possible performance issue with _LazyTickList +* :ghissue:`27971`: [Bug]: ax.xaxis.set_label(...) doesn't set the x-axis label +* :ghissue:`28059`: [Bug]: pcolorfast should validate that regularly spaced X or Y inputs have the right size +* :ghissue:`28892`: [Doc]: Be more specific on dependencies that need to be installed for a "reasonable" dev environment +* :ghissue:`19693`: path.sketch doesn't apply to PolyCollection +* :ghissue:`28873`: [Bug]: hist()'s doc for edgecolors/facecolors does not match behavior (which is itself not very consistent) +* :ghissue:`23005`: [Doc]: Add figure to ``subplots_adjust`` +* :ghissue:`25947`: [Doc]: Subfigures still marked as provisional +* :ghissue:`26012`: [Bug]: "Unhashable type" when event callback is a method of a ``dict`` subclass +* :ghissue:`23425`: [Bug]: Axes.indicate_inset connectors affect constrained layout +* :ghissue:`23424`: [Bug]: Axes.indicate_inset(linewidth=...) doesn't affect connectors +* :ghissue:`19768`: Overlay created by ``Axes.indicate_inset_zoom`` does not adjust when changing inset ranges +* :ghissue:`27673`: [Doc]: Confusing page on color changes +* :ghissue:`28782`: [Bug]: String ``contour(colors)`` gives confusing error when ``extend`` used +* :ghissue:`27930`: [ENH]: Make axes_grid1.Size more math friendly. +* :ghissue:`28372`: [Bug]: AffineDeltaTransform does not appear to invalidate properly +* :ghissue:`27866`: [Bug]: Adding suptitle in compressed layout causes weird spacing +* :ghissue:`28731`: [Bug]: Plotting numpy.array of dtype float32 with pyplot.imshow and specified colors.LogNorm produces wrong colors +* :ghissue:`28715`: [Bug]: CI doc builds fail since a couple of days +* :ghissue:`28698`: [bug]: arrowstyle doc interpolation in FancyPatch.set_arrow() +* :ghissue:`28669`: [Bug]: division-by-zero error in Sketch::Sketch with Agg backend +* :ghissue:`28548`: [Doc]: matplotlib.pyplot.specgram parameters vmin and vmax are not documented +* :ghissue:`28165`: [Bug]: PolygonSelector should hide itself when zoom/pan is active +* :ghissue:`18608`: Feature proposal: "Dark mode" divergent colormaps +* :ghissue:`28623`: [Bug]: ``Axis.set_in_layout`` not respected? +* :ghissue:`6305`: Matplotlib 3D plot - parametric curve “wraparound” from certain perspectives +* :ghissue:`28595`: [Bug]: set_url without effect for instances of Line2D with linestyle 'none' +* :ghissue:`20910`: [Bug]: Exported SVG files are no longer imported Affinity Designer correctly +* :ghissue:`28600`: [TST] Upcoming dependency test failures +* :ghissue:`26718`: [Bug]: stacked histogram does not properly handle edgecolor and hatches +* :ghissue:`28590`: [ENH]: Geo Projections support for inverting axis +* :ghissue:`27954`: [ENH]: Iterables in grouped histogram labels +* :ghissue:`27878`: [ENH]: AttributeError('... got an unexpected keyword argument ...') should set the .name attribute to the keyword +* :ghissue:`28489`: [TST] Upcoming dependency test failures +* :ghissue:`28343`: [Bug]: inconsistent colorbar pad for ``ImageGrid`` with ``cbar_mode="single"`` +* :ghissue:`28535`: [ENH]: Add id attribute to top level svg tag +* :ghissue:`28170`: [Doc]: ``get_figure`` may return a ``SubFigure`` +* :ghissue:`27831`: [Bug]: Nondeterminism in SVG clipPath element id attributes +* :ghissue:`4568`: Add ``fmt_r`` and ``fmt_theta`` methods to polar axes +* :ghissue:`28105`: [Bug]: Setting norm by string doesn't work for hexbin +* :ghissue:`28142`: [ENH]: Add fill between support for 3D plots +* :ghissue:`28344`: [Bug]: subfigures are added in column major order +* :ghissue:`28212`: [Bug]: Matplotlib not work with MiKTeX. +* :ghissue:`28288`: [ENH]: Natural 3D rotation with mouse +* :ghissue:`28180`: [Bug]: mathtext should distinguish between unary and binary minus +* :ghissue:`26150`: [Bug]: Savefig slow with subplots +* :ghissue:`28310`: [Bug]: orientation indication shows up late in mplot3d, and then lingers +* :ghissue:`16263`: Apply NEP29 (time-limited support) to IPython +* :ghissue:`28192`: [MNT]: Essential build requirements not included in dev-requirements +* :ghissue:`27978`: [Bug]: strange behaviour when redefining figure size +* :ghissue:`13435`: boxplot/violinplot orientation-setting API +* :ghissue:`28199`: [MNT]: Misleading function name ``Poly3DCollection.get_vector()`` +* :ghissue:`26892`: [Bug]: PGF font size mismatch between measurement and output +* :ghissue:`28016`: [Bug]: Unexpected ylim of stairs with baseline=None +* :ghissue:`28114`: [Bug]: mpl.colormaps[ "Grays" ].name is "Greys", not "Grays" +* :ghissue:`18045`: Cannot access hexbin data when ``xscale='log'`` and ``yscale='log'`` are set. +* :ghissue:`27820`: [Bug]: Logscale Axis + NonUniformImage + GUI move tool = Distortion +* :ghissue:`28047`: [Bug]: plt.barbs is a command that cannot be passed in a c parameter by parameter name, but can be passed in the form of a positional parameter +* :ghissue:`23400`: Only upload failed images on failure +* :ghissue:`26752`: [Bug]: ``ax.stairs()`` creates inaccurate ``fill`` for the plot +* :ghissue:`21817`: [Doc/Dev]: style guide claims "object oriented" is verboten. From 2495bbc020dcf349b1cf6a431050621d012bb3f9 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 24 Jan 2025 14:13:32 -0600 Subject: [PATCH 70/73] Fix toctrees for 3.10 release notes --- doc/users/prev_whats_new/whats_new_3.10.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/users/prev_whats_new/whats_new_3.10.0.rst b/doc/users/prev_whats_new/whats_new_3.10.0.rst index 8ba7de3dda76..6172fe1953ff 100644 --- a/doc/users/prev_whats_new/whats_new_3.10.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.10.0.rst @@ -11,6 +11,7 @@ For a list of all of the issues and pull requests since the last revision, see t .. toctree:: :maxdepth: 4 + New more-accessible color cycle ------------------------------- From 33361fb3a9b67559a048c6bd3794c125faefc6ef Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 27 Feb 2025 12:21:44 -0600 Subject: [PATCH 71/73] Release notes v3.10.1 --- .../api_changes_3.10.1.rst} | 6 ++++++ doc/users/release_notes.rst | 2 ++ 2 files changed, 8 insertions(+) rename doc/api/{next_api_changes/behavior/28437-CH.rst => prev_api_changes/api_changes_3.10.1.rst} (83%) diff --git a/doc/api/next_api_changes/behavior/28437-CH.rst b/doc/api/prev_api_changes/api_changes_3.10.1.rst similarity index 83% rename from doc/api/next_api_changes/behavior/28437-CH.rst rename to doc/api/prev_api_changes/api_changes_3.10.1.rst index 6121dfec8163..26d43ddf8b17 100644 --- a/doc/api/next_api_changes/behavior/28437-CH.rst +++ b/doc/api/prev_api_changes/api_changes_3.10.1.rst @@ -1,3 +1,9 @@ +API Changes for 3.10.1 +====================== + +Behaviour +--------- + *alpha* parameter handling on images ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst index 045132e50ac8..ae06d9875988 100644 --- a/doc/users/release_notes.rst +++ b/doc/users/release_notes.rst @@ -18,8 +18,10 @@ Version 3.10 :maxdepth: 1 prev_whats_new/whats_new_3.10.0.rst + ../api/prev_api_changes/api_changes_3.10.1.rst ../api/prev_api_changes/api_changes_3.10.0.rst github_stats.rst + prev_whats_new/github_stats_3.10.0.rst Version 3.9 ^^^^^^^^^^^ From 6fc8169112a42e3f6f55793a6b56159cd8ff69d7 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 27 Feb 2025 12:41:13 -0600 Subject: [PATCH 72/73] REL 3.10.1 This is the first bugfix release of the 3.10.x series. This release contains several bug-fixes and adjustments: - Respect array alpha with interpolation_stage='rgba' in _Imagebase::_make_image - Remove md5 usage to prevent issues on FIPS enabled systems - Fix pyplot.matshow figure handling - Fix modifying Axes' position also alters the original Bbox object used for initialization - Fix title position for polar plots - Add version gate to GTK4 calls when necessary - Raise warning if both c and facecolors are used in scatter plot As well as several documentation improvements and corrections. From 14d07d657c56bac30d3f5ce467a4a315f5319373 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 27 Feb 2025 12:43:07 -0600 Subject: [PATCH 73/73] Bump from v3.10.1