diff options
author | robot-piglet <[email protected]> | 2025-08-01 21:30:33 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2025-08-01 21:44:33 +0300 |
commit | 5e971f676b02569e1f054c14ab46fc88d64646ca (patch) | |
tree | e91e46b98393b6ff7e7c581cc7f3b728fc67783c /contrib/python/matplotlib | |
parent | d26972227453799b411b840c959784b73d6d99db (diff) |
Intermediate changes
commit_hash:2593e29b01982d14fc576c3f4c4ddf2e4febb604
Diffstat (limited to 'contrib/python/matplotlib')
30 files changed, 266 insertions, 149 deletions
diff --git a/contrib/python/matplotlib/py3/.dist-info/METADATA b/contrib/python/matplotlib/py3/.dist-info/METADATA index cdd2df573fc..c269e1e5c7d 100644 --- a/contrib/python/matplotlib/py3/.dist-info/METADATA +++ b/contrib/python/matplotlib/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: matplotlib -Version: 3.8.2 +Version: 3.8.4 Summary: Python plotting package Home-page: https://matplotlib.org Download-URL: https://matplotlib.org/stable/users/installing/index.html @@ -43,7 +43,7 @@ Requires-Dist: contourpy >=1.0.1 Requires-Dist: cycler >=0.10 Requires-Dist: fonttools >=4.22.0 Requires-Dist: kiwisolver >=1.3.1 -Requires-Dist: numpy <2,>=1.21 +Requires-Dist: numpy >=1.21 Requires-Dist: packaging >=20.0 Requires-Dist: pillow >=8 Requires-Dist: pyparsing >=2.3.1 diff --git a/contrib/python/matplotlib/py3/LICENSE_STIX b/contrib/python/matplotlib/py3/LICENSE_STIX index 2f7aeea331c..6034d947481 100644 --- a/contrib/python/matplotlib/py3/LICENSE_STIX +++ b/contrib/python/matplotlib/py3/LICENSE_STIX @@ -1,71 +1,124 @@ -TERMS AND CONDITIONS - - 1. Permission is hereby granted, free of charge, to any person -obtaining a copy of the STIX Fonts-TM set accompanying this license -(collectively, the "Fonts") and the associated documentation files -(collectively with the Fonts, the "Font Software"), to reproduce and -distribute the Font Software, including the rights to use, copy, merge -and publish copies of the Font Software, and to permit persons to whom -the Font Software is furnished to do so same, subject to the following -terms and conditions (the "License"). - - 2. The following copyright and trademark notice and these Terms and -Conditions shall be included in all copies of one or more of the Font -typefaces and any derivative work created as permitted under this -License: - - Copyright (c) 2001-2005 by the STI Pub Companies, consisting of -the American Institute of Physics, the American Chemical Society, the -American Mathematical Society, the American Physical Society, Elsevier, -Inc., and The Institute of Electrical and Electronic Engineers, Inc. -Portions copyright (c) 1998-2003 by MicroPress, Inc. Portions copyright -(c) 1990 by Elsevier, Inc. All rights reserved. STIX Fonts-TM is a -trademark of The Institute of Electrical and Electronics Engineers, Inc. - - 3. You may (a) convert the Fonts from one format to another (e.g., -from TrueType to PostScript), in which case the normal and reasonable -distortion that occurs during such conversion shall be permitted and (b) -embed or include a subset of the Fonts in a document for the purposes of -allowing users to read text in the document that utilizes the Fonts. In -each case, you may use the STIX Fonts-TM mark to designate the resulting -Fonts or subset of the Fonts. - - 4. You may also (a) add glyphs or characters to the Fonts, or modify -the shape of existing glyphs, so long as the base set of glyphs is not -removed and (b) delete glyphs or characters from the Fonts, provided -that the resulting font set is distributed with the following -disclaimer: "This [name] font does not include all the Unicode points -covered in the STIX Fonts-TM set but may include others." In each case, -the name used to denote the resulting font set shall not include the -term "STIX" or any similar term. - - 5. You may charge a fee in connection with the distribution of the -Font Software, provided that no copy of one or more of the individual -Font typefaces that form the STIX Fonts-TM set may be sold by itself. - - 6. THE FONT SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY -KIND, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK OR OTHER RIGHT. IN NO EVENT SHALL -MICROPRESS OR ANY OF THE STI PUB COMPANIES BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, INCLUDING, BUT NOT LIMITED TO, ANY GENERAL, -SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM OR OUT OF THE USE OR -INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT -SOFTWARE. - - 7. Except as contained in the notice set forth in Section 2, the -names MicroPress Inc. and STI Pub Companies, as well as the names of the -companies/organizations that compose the STI Pub Companies, shall not be -used in advertising or otherwise to promote the sale, use or other -dealings in the Font Software without the prior written consent of the -respective company or organization. - - 8. This License shall become null and void in the event of any -material breach of the Terms and Conditions herein by licensee. - - 9. A substantial portion of the STIX Fonts set was developed by -MicroPress Inc. for the STI Pub Companies. To obtain additional -mathematical fonts, please contact MicroPress, Inc., 68-30 Harrow -Street, Forest Hills, NY 11375, USA - Phone: (718) 575-1816. +The STIX fonts distributed with matplotlib have been modified from +their canonical form. They have been converted from OTF to TTF format +using Fontforge and this script: + #!/usr/bin/env fontforge + i=1 + while ( i<$argc ) + Open($argv[i]) + Generate($argv[i]:r + ".ttf") + i = i+1 + endloop + +The original STIX Font License begins below. + +----------------------------------------------------------- + +STIX Font License + +24 May 2010 + +Copyright (c) 2001-2010 by the STI Pub Companies, consisting of the American +Institute of Physics, the American Chemical Society, the American Mathematical +Society, the American Physical Society, Elsevier, Inc., and The Institute of +Electrical and Electronic Engineers, Inc. (www.stixfonts.org), with Reserved +Font Name STIX Fonts, STIX Fonts (TM) is a trademark of The Institute of +Electrical and Electronics Engineers, Inc. + +Portions copyright (c) 1998-2003 by MicroPress, Inc. (www.micropress-inc.com), +with Reserved Font Name TM Math. To obtain additional mathematical fonts, please +contact MicroPress, Inc., 68-30 Harrow Street, Forest Hills, NY 11375, USA, +Phone: (718) 575-1816. + +Portions copyright (c) 1990 by Elsevier, Inc. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/contrib/python/matplotlib/py3/matplotlib/_version.py b/contrib/python/matplotlib/py3/matplotlib/_version.py index f14d882a3d9..29a8837f730 100644 --- a/contrib/python/matplotlib/py3/matplotlib/_version.py +++ b/contrib/python/matplotlib/py3/matplotlib/_version.py @@ -12,5 +12,5 @@ __version__: str __version_tuple__: VERSION_TUPLE version_tuple: VERSION_TUPLE -__version__ = version = '3.8.2' -__version_tuple__ = version_tuple = (3, 8, 2) +__version__ = version = '3.8.4' +__version_tuple__ = version_tuple = (3, 8, 4) diff --git a/contrib/python/matplotlib/py3/matplotlib/axes/_axes.py b/contrib/python/matplotlib/py3/matplotlib/axes/_axes.py index b4a41099bed..0285ec6bdae 100644 --- a/contrib/python/matplotlib/py3/matplotlib/axes/_axes.py +++ b/contrib/python/matplotlib/py3/matplotlib/axes/_axes.py @@ -280,7 +280,7 @@ class Axes(_AxesBase): Parameters ---------- - handles : sequence of (`.Artist` or tuple of `.Artist`), optional + handles : list of (`.Artist` or tuple of `.Artist`), optional A list of Artists (lines, patches) to be added to the legend. Use this together with *labels*, if you need full control on what is shown in the legend and the automatic mechanism described above @@ -632,7 +632,10 @@ class Axes(_AxesBase): """ Add text to the Axes. - Add the text *s* to the Axes at location *x*, *y* in data coordinates. + Add the text *s* to the Axes at location *x*, *y* in data coordinates, + with a default ``horizontalalignment`` on the ``left`` and + ``verticalalignment`` at the ``baseline``. See + :doc:`/gallery/text_labels_and_annotations/text_alignment`. Parameters ---------- @@ -893,7 +896,7 @@ class Axes(_AxesBase): Returns ------- - `.Line2D` + `.AxLine` Other Parameters ---------------- @@ -2391,7 +2394,8 @@ class Axes(_AxesBase): # checking and processing will be left to the errorbar method. xerr = kwargs.pop('xerr', None) yerr = kwargs.pop('yerr', None) - error_kw = kwargs.pop('error_kw', {}) + error_kw = kwargs.pop('error_kw', None) + error_kw = {} if error_kw is None else error_kw.copy() ezorder = error_kw.pop('zorder', None) if ezorder is None: ezorder = kwargs.get('zorder', None) @@ -2547,9 +2551,8 @@ class Axes(_AxesBase): error_kw.setdefault("label", '_nolegend_') - errorbar = self.errorbar(ex, ey, - yerr=yerr, xerr=xerr, - fmt='none', **error_kw) + errorbar = self.errorbar(ex, ey, yerr=yerr, xerr=xerr, fmt='none', + **error_kw) else: errorbar = None @@ -5084,10 +5087,10 @@ default: :rc:`scatter.edgecolors` ) # Set normalizer if bins is 'log' - if bins == 'log': + if cbook._str_equal(bins, 'log'): if norm is not None: _api.warn_external("Only one of 'bins' and 'norm' arguments " - f"can be supplied, ignoring bins={bins}") + f"can be supplied, ignoring {bins=}") else: norm = mcolors.LogNorm(vmin=vmin, vmax=vmax) vmin = vmax = None @@ -5849,7 +5852,7 @@ default: :rc:`scatter.edgecolors` def _interp_grid(X): # helper for below if np.shape(X)[1] > 1: - dX = np.diff(X, axis=1)/2. + dX = np.diff(X, axis=1) * 0.5 if not (np.all(dX >= 0) or np.all(dX <= 0)): _api.warn_external( f"The input coordinates to {funcname} are " diff --git a/contrib/python/matplotlib/py3/matplotlib/axes/_axes.pyi b/contrib/python/matplotlib/py3/matplotlib/axes/_axes.pyi index 9602db3b950..0a70e575dfc 100644 --- a/contrib/python/matplotlib/py3/matplotlib/axes/_axes.pyi +++ b/contrib/python/matplotlib/py3/matplotlib/axes/_axes.pyi @@ -18,7 +18,7 @@ from matplotlib.contour import ContourSet, QuadContourSet from matplotlib.image import AxesImage, PcolorImage from matplotlib.legend import Legend from matplotlib.legend_handler import HandlerBase -from matplotlib.lines import Line2D +from matplotlib.lines import Line2D, AxLine from matplotlib.mlab import GaussianKDE from matplotlib.patches import Rectangle, FancyArrow, Polygon, StepPatch, Wedge from matplotlib.quiver import Quiver, QuiverKey, Barbs @@ -31,7 +31,7 @@ import matplotlib.streamplot as mstream import datetime import PIL.Image -from collections.abc import Callable, Sequence +from collections.abc import Callable, Iterable, Sequence from typing import Any, Literal, overload import numpy as np from numpy.typing import ArrayLike @@ -57,11 +57,11 @@ class Axes(_AxesBase): @overload def legend(self) -> Legend: ... @overload - def legend(self, handles: Sequence[Artist | tuple[Artist, ...]], labels: Sequence[str], **kwargs) -> Legend: ... + def legend(self, handles: Iterable[Artist | tuple[Artist, ...]], labels: Iterable[str], **kwargs) -> Legend: ... @overload - def legend(self, *, handles: Sequence[Artist | tuple[Artist, ...]], **kwargs) -> Legend: ... + def legend(self, *, handles: Iterable[Artist | tuple[Artist, ...]], **kwargs) -> Legend: ... @overload - def legend(self, labels: Sequence[str], **kwargs) -> Legend: ... + def legend(self, labels: Iterable[str], **kwargs) -> Legend: ... @overload def legend(self, **kwargs) -> Legend: ... @@ -151,7 +151,7 @@ class Axes(_AxesBase): *, slope: float | None = ..., **kwargs - ) -> Line2D: ... + ) -> AxLine: ... def axhspan( self, ymin: float, ymax: float, xmin: float = ..., xmax: float = ..., **kwargs ) -> Polygon: ... diff --git a/contrib/python/matplotlib/py3/matplotlib/backend_bases.py b/contrib/python/matplotlib/py3/matplotlib/backend_bases.py index 958b6e0e1c2..fd5e70433fa 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backend_bases.py +++ b/contrib/python/matplotlib/py3/matplotlib/backend_bases.py @@ -2584,9 +2584,13 @@ class FigureManagerBase: backend-independent way. It's an adapter for the real (GUI) framework that represents the visual figure on screen. - GUI backends define from this class to translate common operations such + The figure manager is connected to a specific canvas instance, which in turn + is connected to a specific figure instance. To access a figure manager for + a given figure in user code, you typically use ``fig.canvas.manager``. + + GUI backends derive from this class to translate common operations such as *show* or *resize* to the GUI-specific code. Non-GUI backends do not - support these operations an can just use the base class. + support these operations and can just use the base class. This following basic operations are accessible: @@ -2771,6 +2775,11 @@ class FigureManagerBase: Set the title text of the window containing the figure. This has no effect for non-GUI (e.g., PS) backends. + + Examples + -------- + >>> fig = plt.figure() + >>> fig.canvas.manager.set_window_title('My figure') """ diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3agg.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3agg.py index a006a4c6f12..90b38ffa4ec 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3agg.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3agg.py @@ -2,7 +2,7 @@ import numpy as np from .. import cbook, transforms from . import backend_agg, backend_gtk3 -from .backend_gtk3 import Gtk, _BackendGTK3 +from .backend_gtk3 import GLib, Gtk, _BackendGTK3 import cairo # Presence of cairo is already checked by _backend_gtk. @@ -14,6 +14,11 @@ class FigureCanvasGTK3Agg(backend_agg.FigureCanvasAgg, self._bbox_queue = [] def on_draw_event(self, widget, ctx): + if self._idle_draw_id: + GLib.source_remove(self._idle_draw_id) + self._idle_draw_id = 0 + self.draw() + scale = self.device_pixel_ratio allocation = self.get_allocation() w = allocation.width * scale diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3cairo.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3cairo.py index 1da8419e538..24a26111f06 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3cairo.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk3cairo.py @@ -1,11 +1,16 @@ from contextlib import nullcontext from .backend_cairo import FigureCanvasCairo -from .backend_gtk3 import Gtk, FigureCanvasGTK3, _BackendGTK3 +from .backend_gtk3 import GLib, Gtk, FigureCanvasGTK3, _BackendGTK3 class FigureCanvasGTK3Cairo(FigureCanvasCairo, FigureCanvasGTK3): def on_draw_event(self, widget, ctx): + if self._idle_draw_id: + GLib.source_remove(self._idle_draw_id) + self._idle_draw_id = 0 + self.draw() + with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar else nullcontext()): self._renderer.set_context(ctx) diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4.py index cb4006048d5..7e73a486321 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4.py @@ -361,7 +361,7 @@ class NavigationToolbar2GTK4(_NavigationToolbar2GTK, Gtk.Box): formats = [formats[default_format], *formats[:default_format], *formats[default_format+1:]] dialog.add_choice('format', 'File format', formats, formats) - dialog.set_choice('format', formats[default_format]) + dialog.set_choice('format', formats[0]) dialog.set_current_folder(Gio.File.new_for_path( os.path.expanduser(mpl.rcParams['savefig.directory']))) diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4agg.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4agg.py index efddfec5607..0af07850a30 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4agg.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4agg.py @@ -2,7 +2,7 @@ import numpy as np from .. import cbook from . import backend_agg, backend_gtk4 -from .backend_gtk4 import Gtk, _BackendGTK4 +from .backend_gtk4 import GLib, Gtk, _BackendGTK4 import cairo # Presence of cairo is already checked by _backend_gtk. @@ -11,6 +11,11 @@ class FigureCanvasGTK4Agg(backend_agg.FigureCanvasAgg, backend_gtk4.FigureCanvasGTK4): def on_draw_event(self, widget, ctx): + if self._idle_draw_id: + GLib.source_remove(self._idle_draw_id) + self._idle_draw_id = 0 + self.draw() + scale = self.device_pixel_ratio allocation = self.get_allocation() diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4cairo.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4cairo.py index d57f53fb28d..b1d54370435 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4cairo.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_gtk4cairo.py @@ -1,13 +1,18 @@ from contextlib import nullcontext from .backend_cairo import FigureCanvasCairo -from .backend_gtk4 import Gtk, FigureCanvasGTK4, _BackendGTK4 +from .backend_gtk4 import GLib, Gtk, FigureCanvasGTK4, _BackendGTK4 class FigureCanvasGTK4Cairo(FigureCanvasCairo, FigureCanvasGTK4): _context_is_scaled = True def on_draw_event(self, widget, ctx): + if self._idle_draw_id: + GLib.source_remove(self._idle_draw_id) + self._idle_draw_id = 0 + self.draw() + with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar else nullcontext()): self._renderer.set_context(ctx) diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_macosx.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_macosx.py index a39f5b5b149..66bc9bfc99d 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_macosx.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_macosx.py @@ -64,13 +64,9 @@ class FigureCanvasMac(FigureCanvasAgg, _macosx.FigureCanvas, FigureCanvasBase): def _single_shot_timer(self, callback): """Add a single shot timer with the given callback""" - # We need to explicitly stop and remove the timer after - # firing, otherwise segfaults will occur when trying to deallocate - # the singleshot timers. def callback_func(callback, timer): callback() self._timers.remove(timer) - timer.stop() timer = self.new_timer(interval=0) timer.single_shot = True timer.add_callback(callback_func, callback, timer) @@ -183,6 +179,8 @@ class FigureManagerMac(_macosx.FigureManager, FigureManagerBase): _macosx.show() def show(self): + if self.canvas.figure.stale: + self.canvas.draw_idle() if not self._shown: self._show() self._shown = True diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_pdf.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_pdf.py index aa4883135d9..facb8efec81 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_pdf.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_pdf.py @@ -2732,7 +2732,7 @@ class PdfPages: _api.warn_deprecated("3.8", message=( "Keeping empty pdf files is deprecated since %(since)s and support " "will be removed %(removal)s.")) - PdfFile(self._filename, metadata=self._metadata) # touch the file. + PdfFile(self._filename, metadata=self._metadata).close() # touch the file. def infodict(self): """ diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_pgf.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_pgf.py index ccf4b800a61..46fd6635750 100644 --- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_pgf.py +++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_pgf.py @@ -257,7 +257,8 @@ class LatexManager: # Open LaTeX process for real work; register it for deletion. On # Windows, we must ensure that the subprocess has quit before being # able to delete the tmpdir in which it runs; in order to do so, we - # must first `kill()` it, and then `communicate()` with it. + # must first `kill()` it, and then `communicate()` with or `wait()` on + # it. try: self.latex = subprocess.Popen( [mpl.rcParams["pgf.texsystem"], "-halt-on-error"], @@ -274,7 +275,10 @@ class LatexManager: def finalize_latex(latex): latex.kill() - latex.communicate() + try: + latex.communicate() + except RuntimeError: + latex.wait() self._finalize_latex = weakref.finalize( self, finalize_latex, self.latex) diff --git a/contrib/python/matplotlib/py3/matplotlib/bezier.py b/contrib/python/matplotlib/py3/matplotlib/bezier.py index f310f287e2c..069e20d0591 100644 --- a/contrib/python/matplotlib/py3/matplotlib/bezier.py +++ b/contrib/python/matplotlib/py3/matplotlib/bezier.py @@ -171,9 +171,17 @@ def find_bezier_t_intersecting_with_closedpath( if start_inside ^ middle_inside: t1 = middle_t + if end == middle: + # Edge case where infinite loop is possible + # Caused by large numbers relative to tolerance + return t0, t1 end = middle else: t0 = middle_t + if start == middle: + # Edge case where infinite loop is possible + # Caused by large numbers relative to tolerance + return t0, t1 start = middle start_inside = middle_inside diff --git a/contrib/python/matplotlib/py3/matplotlib/collections.py b/contrib/python/matplotlib/py3/matplotlib/collections.py index 81db24d0c02..81cd13567bc 100644 --- a/contrib/python/matplotlib/py3/matplotlib/collections.py +++ b/contrib/python/matplotlib/py3/matplotlib/collections.py @@ -1038,12 +1038,12 @@ class PathCollection(_CollectionWithSizes): Create legend handles and labels for a PathCollection. Each legend handle is a `.Line2D` representing the Path that was drawn, - and each label is a string what each Path represents. + and each label is a string that represents the Path. This is useful for obtaining a legend for a `~.Axes.scatter` plot; e.g.:: - scatter = plt.scatter([1, 2, 3], [4, 5, 6], c=[7, 2, 3]) + scatter = plt.scatter([1, 2, 3], [4, 5, 6], c=[7, 2, 3], num=None) plt.legend(*scatter.legend_elements()) creates three legend elements, one for each color with the numerical diff --git a/contrib/python/matplotlib/py3/matplotlib/colors.py b/contrib/python/matplotlib/py3/matplotlib/colors.py index bd89e70049c..81db1611550 100644 --- a/contrib/python/matplotlib/py3/matplotlib/colors.py +++ b/contrib/python/matplotlib/py3/matplotlib/colors.py @@ -127,8 +127,8 @@ class ColorSequenceRegistry(Mapping): 'Accent': _cm._Accent_data, 'Dark2': _cm._Dark2_data, 'Set1': _cm._Set1_data, - 'Set2': _cm._Set1_data, - 'Set3': _cm._Set1_data, + 'Set2': _cm._Set2_data, + 'Set3': _cm._Set3_data, } def __init__(self): diff --git a/contrib/python/matplotlib/py3/matplotlib/lines.py b/contrib/python/matplotlib/py3/matplotlib/lines.py index 92d55a3fe6a..9bc058f9213 100644 --- a/contrib/python/matplotlib/py3/matplotlib/lines.py +++ b/contrib/python/matplotlib/py3/matplotlib/lines.py @@ -1478,9 +1478,10 @@ class AxLine(Line2D): The first set of (x, y) coordinates for the line to pass through. xy2 : (float, float) or None The second set of (x, y) coordinates for the line to pass through. - Either *xy2* or *slope* has to be given. + Both *xy2* and *slope* must be passed, but one of them must be None. slope : float or None - The slope of the line. Either *xy2* or *slope* has to be given. + The slope of the line. Both *xy2* and *slope* must be passed, but one of + them must be None. """ super().__init__([0, 1], [0, 1], **kwargs) diff --git a/contrib/python/matplotlib/py3/matplotlib/mpl-data/images/hand.svg b/contrib/python/matplotlib/py3/matplotlib/mpl-data/images/hand.svg index f246f51e57d..28b96a2a9c4 100644 --- a/contrib/python/matplotlib/py3/matplotlib/mpl-data/images/hand.svg +++ b/contrib/python/matplotlib/py3/matplotlib/mpl-data/images/hand.svg @@ -5,7 +5,7 @@ <!ATTLIST svg xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"> ]> -<!-- Created with Sodipodi ("http://www.sodipodi.com/") --> +<!-- Created with Sodipodi ("https://sourceforge.net/projects/sodipodi/") --> <svg xml:space="preserve" width="128pt" diff --git a/contrib/python/matplotlib/py3/matplotlib/patches.py b/contrib/python/matplotlib/py3/matplotlib/patches.py index f80df92c62f..ce012b0faf9 100644 --- a/contrib/python/matplotlib/py3/matplotlib/patches.py +++ b/contrib/python/matplotlib/py3/matplotlib/patches.py @@ -190,10 +190,10 @@ class Patch(artist.Artist): transform them first: >>> center = 0, 0 - >>> c = Circle(center, radius=1) + >>> c = Circle(center, radius=3) >>> plt.gca().add_patch(c) - >>> transformed_center = c.get_transform().transform(center) - >>> c.contains_point(transformed_center) + >>> transformed_interior_point = c.get_data_transform().transform((0, 2)) + >>> c.contains_point(transformed_interior_point) True """ diff --git a/contrib/python/matplotlib/py3/matplotlib/projections/polar.py b/contrib/python/matplotlib/py3/matplotlib/projections/polar.py index 0bff320e572..33063674c41 100644 --- a/contrib/python/matplotlib/py3/matplotlib/projections/polar.py +++ b/contrib/python/matplotlib/py3/matplotlib/projections/polar.py @@ -298,7 +298,7 @@ class ThetaLocator(mticker.Locator): def __call__(self): lim = self.axis.get_view_interval() if _is_full_circle_deg(lim[0], lim[1]): - return np.arange(8) * 2 * np.pi / 8 + return np.deg2rad(min(lim)) + np.arange(8) * 2 * np.pi / 8 else: return np.deg2rad(self.base()) diff --git a/contrib/python/matplotlib/py3/matplotlib/pylab.py b/contrib/python/matplotlib/py3/matplotlib/pylab.py index 77eb6506d87..a50779cf6d2 100644 --- a/contrib/python/matplotlib/py3/matplotlib/pylab.py +++ b/contrib/python/matplotlib/py3/matplotlib/pylab.py @@ -60,6 +60,8 @@ import datetime bytes = __import__("builtins").bytes # We also don't want the numpy version of these functions abs = __import__("builtins").abs +bool = __import__("builtins").bool max = __import__("builtins").max min = __import__("builtins").min +pow = __import__("builtins").pow round = __import__("builtins").round diff --git a/contrib/python/matplotlib/py3/matplotlib/pyplot.py b/contrib/python/matplotlib/py3/matplotlib/pyplot.py index 62f7eba74ee..fb925f1df62 100644 --- a/contrib/python/matplotlib/py3/matplotlib/pyplot.py +++ b/contrib/python/matplotlib/py3/matplotlib/pyplot.py @@ -130,7 +130,7 @@ if TYPE_CHECKING: # We may not need the following imports here: from matplotlib.colors import Normalize -from matplotlib.lines import Line2D +from matplotlib.lines import Line2D, AxLine from matplotlib.text import Text, Annotation from matplotlib.patches import Polygon, Rectangle, Circle, Arrow from matplotlib.widgets import Button, Slider, Widget @@ -1000,9 +1000,24 @@ def gcf() -> Figure: return figure() -def fignum_exists(num: int) -> bool: - """Return whether the figure with the given id exists.""" - return _pylab_helpers.Gcf.has_fignum(num) or num in get_figlabels() +def fignum_exists(num: int | str) -> bool: + """Return whether the figure with the given id exists. + + Parameters + ---------- + num : int or str + A figure identifier. + + Returns + ------- + bool + Whether or not a figure with id *num* exists. + """ + return ( + _pylab_helpers.Gcf.has_fignum(num) + if isinstance(num, int) + else num in get_figlabels() + ) def get_fignums() -> list[int]: @@ -2706,7 +2721,7 @@ def axline( *, slope: float | None = None, **kwargs, -) -> Line2D: +) -> AxLine: return gca().axline(xy1, xy2=xy2, slope=slope, **kwargs) diff --git a/contrib/python/matplotlib/py3/matplotlib/quiver.py b/contrib/python/matplotlib/py3/matplotlib/quiver.py index c8f8ba56610..5dbf7970f93 100644 --- a/contrib/python/matplotlib/py3/matplotlib/quiver.py +++ b/contrib/python/matplotlib/py3/matplotlib/quiver.py @@ -263,7 +263,7 @@ class QuiverKey(martist.Artist): The key label (e.g., length and units of the key). angle : float, default: 0 The angle of the key arrow, in degrees anti-clockwise from the - x-axis. + horizontal axis. coordinates : {'axes', 'figure', 'data', 'inches'}, default: 'axes' Coordinate system and units for *X*, *Y*: 'axes' and 'figure' are normalized coordinate systems with (0, 0) in the lower left and @@ -327,10 +327,8 @@ class QuiverKey(martist.Artist): Umask=ma.nomask): u = self.U * np.cos(np.radians(self.angle)) v = self.U * np.sin(np.radians(self.angle)) - angle = (self.Q.angles if isinstance(self.Q.angles, str) - else 'uv') - self.verts = self.Q._make_verts( - np.array([u]), np.array([v]), angle) + self.verts = self.Q._make_verts([[0., 0.]], + np.array([u]), np.array([v]), 'uv') kwargs = self.Q.polykw kwargs.update(self.kw) self.vector = mcollections.PolyCollection( @@ -521,7 +519,7 @@ class Quiver(mcollections.PolyCollection): # _make_verts sets self.scale if not already specified if (self._dpi_at_last_init != self.axes.figure.dpi and self.scale is None): - self._make_verts(self.U, self.V, self.angles) + self._make_verts(self.XY, self.U, self.V, self.angles) self._dpi_at_last_init = self.axes.figure.dpi @@ -537,7 +535,7 @@ class Quiver(mcollections.PolyCollection): @martist.allow_rasterization def draw(self, renderer): self._init() - verts = self._make_verts(self.U, self.V, self.angles) + verts = self._make_verts(self.XY, self.U, self.V, self.angles) self.set_verts(verts, closed=False) super().draw(renderer) self.stale = False @@ -594,33 +592,38 @@ class Quiver(mcollections.PolyCollection): self.set_transform(trans) return trans - def _angles_lengths(self, U, V, eps=1): - xy = self.axes.transData.transform(self.XY) + # Calculate angles and lengths for segment between (x, y), (x+u, y+v) + def _angles_lengths(self, XY, U, V, eps=1): + xy = self.axes.transData.transform(XY) uv = np.column_stack((U, V)) - xyp = self.axes.transData.transform(self.XY + eps * uv) + xyp = self.axes.transData.transform(XY + eps * uv) dxy = xyp - xy angles = np.arctan2(dxy[:, 1], dxy[:, 0]) lengths = np.hypot(*dxy.T) / eps return angles, lengths - def _make_verts(self, U, V, angles): + # XY is stacked [X, Y]. + # See quiver() doc for meaning of X, Y, U, V, angles. + def _make_verts(self, XY, U, V, angles): uv = (U + V * 1j) str_angles = angles if isinstance(angles, str) else '' if str_angles == 'xy' and self.scale_units == 'xy': # Here eps is 1 so that if we get U, V by diffing # the X, Y arrays, the vectors will connect the # points, regardless of the axis scaling (including log). - angles, lengths = self._angles_lengths(U, V, eps=1) + angles, lengths = self._angles_lengths(XY, U, V, eps=1) elif str_angles == 'xy' or self.scale_units == 'xy': # Calculate eps based on the extents of the plot # so that we don't end up with roundoff error from # adding a small number to a large. eps = np.abs(self.axes.dataLim.extents).max() * 0.001 - angles, lengths = self._angles_lengths(U, V, eps=eps) + angles, lengths = self._angles_lengths(XY, U, V, eps=eps) + if str_angles and self.scale_units == 'xy': a = lengths else: a = np.abs(uv) + if self.scale is None: sn = max(10, math.sqrt(self.N)) if self.Umask is not ma.nomask: @@ -630,6 +633,7 @@ class Quiver(mcollections.PolyCollection): # crude auto-scaling # scale is typical arrow length as a multiple of the arrow width scale = 1.8 * amean * sn / self.span + if self.scale_units is None: if self.scale is None: self.scale = scale diff --git a/contrib/python/matplotlib/py3/matplotlib/text.py b/contrib/python/matplotlib/py3/matplotlib/text.py index 7a58ce71720..7e7b84a3f9c 100644 --- a/contrib/python/matplotlib/py3/matplotlib/text.py +++ b/contrib/python/matplotlib/py3/matplotlib/text.py @@ -123,7 +123,7 @@ class Text(Artist): The text is aligned relative to the anchor point (*x*, *y*) according to ``horizontalalignment`` (default: 'left') and ``verticalalignment`` - (default: 'bottom'). See also + (default: 'baseline'). See also :doc:`/gallery/text_labels_and_annotations/text_alignment`. While Text accepts the 'label' keyword argument, by default it is not @@ -1251,7 +1251,7 @@ class Text(Artist): Parameters ---------- - align : {'bottom', 'baseline', 'center', 'center_baseline', 'top'} + align : {'baseline', 'bottom', 'center', 'center_baseline', 'top'} """ _api.check_in_list( ['top', 'bottom', 'center', 'baseline', 'center_baseline'], diff --git a/contrib/python/matplotlib/py3/matplotlib/ticker.py b/contrib/python/matplotlib/py3/matplotlib/ticker.py index 5b1b7e11408..47a06f3eec3 100644 --- a/contrib/python/matplotlib/py3/matplotlib/ticker.py +++ b/contrib/python/matplotlib/py3/matplotlib/ticker.py @@ -2895,7 +2895,7 @@ class AutoMinorLocator(Locator): 'logarithmic scale') return [] - majorlocs = self.axis.get_majorticklocs() + majorlocs = np.unique(self.axis.get_majorticklocs()) try: majorstep = majorlocs[1] - majorlocs[0] except IndexError: diff --git a/contrib/python/matplotlib/py3/matplotlib/widgets.py b/contrib/python/matplotlib/py3/matplotlib/widgets.py index 0a31a9dd252..3c6208e7102 100644 --- a/contrib/python/matplotlib/py3/matplotlib/widgets.py +++ b/contrib/python/matplotlib/py3/matplotlib/widgets.py @@ -2915,7 +2915,12 @@ class SpanSelector(_SelectorWidget): @property def extents(self): - """Return extents of the span selector.""" + """ + (float, float) + The values, in data coordinates, for the start and end points of the current + selection. If there is no selection then the start and end values will be + the same. + """ if self.direction == 'horizontal': vmin = self._selection_artist.get_x() vmax = vmin + self._selection_artist.get_width() diff --git a/contrib/python/matplotlib/py3/mpl_toolkits/mplot3d/axes3d.py b/contrib/python/matplotlib/py3/mpl_toolkits/mplot3d/axes3d.py index a74c11f54e6..6bcd7a6b65a 100644 --- a/contrib/python/matplotlib/py3/mpl_toolkits/mplot3d/axes3d.py +++ b/contrib/python/matplotlib/py3/mpl_toolkits/mplot3d/axes3d.py @@ -2727,15 +2727,10 @@ class Axes3D(Axes): UVW = np.column_stack(input_args[3:]).astype(float) # Normalize rows of UVW - norm = np.linalg.norm(UVW, axis=1) - - # If any row of UVW is all zeros, don't make a quiver for it - mask = norm > 0 - XYZ = XYZ[mask] if normalize: - UVW = UVW[mask] / norm[mask].reshape((-1, 1)) - else: - UVW = UVW[mask] + norm = np.linalg.norm(UVW, axis=1) + norm[norm == 0] = 1 + UVW = UVW / norm.reshape((-1, 1)) if len(XYZ) > 0: # compute the shaft lines all at once with an outer product @@ -2749,7 +2744,7 @@ class Axes3D(Axes): # transpose to get a list of lines heads = heads.swapaxes(0, 1) - lines = [*shafts, *heads] + lines = [*shafts, *heads[::2], *heads[1::2]] else: lines = [] diff --git a/contrib/python/matplotlib/py3/src/_path_wrapper.cpp b/contrib/python/matplotlib/py3/src/_path_wrapper.cpp index 369d9e03088..15a30e298df 100644 --- a/contrib/python/matplotlib/py3/src/_path_wrapper.cpp +++ b/contrib/python/matplotlib/py3/src/_path_wrapper.cpp @@ -699,8 +699,8 @@ static PyObject *Py_is_sorted_and_has_non_nan(PyObject *self, PyObject *obj) { bool result; - PyArrayObject *array = (PyArrayObject *)PyArray_FromAny( - obj, NULL, 1, 1, 0, NULL); + PyArrayObject *array = (PyArrayObject *)PyArray_CheckFromAny( + obj, NULL, 1, 1, NPY_ARRAY_NOTSWAPPED, NULL); if (array == NULL) { return NULL; diff --git a/contrib/python/matplotlib/py3/ya.make b/contrib/python/matplotlib/py3/ya.make index 51056316730..21496e14c7a 100644 --- a/contrib/python/matplotlib/py3/ya.make +++ b/contrib/python/matplotlib/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(3.8.2) +VERSION(3.8.4) LICENSE(PSF-2.0) |