You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			1856 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			1856 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Python
		
	
from collections import namedtuple
 | 
						|
import contextlib
 | 
						|
from functools import cache, reduce, wraps
 | 
						|
import inspect
 | 
						|
from inspect import Signature, Parameter
 | 
						|
import logging
 | 
						|
from numbers import Number, Real
 | 
						|
import operator
 | 
						|
import re
 | 
						|
import warnings
 | 
						|
 | 
						|
import numpy as np
 | 
						|
 | 
						|
import matplotlib as mpl
 | 
						|
from . import _api, cbook
 | 
						|
from .path import Path
 | 
						|
from .transforms import (BboxBase, Bbox, IdentityTransform, Transform, TransformedBbox,
 | 
						|
                         TransformedPatchPath, TransformedPath)
 | 
						|
 | 
						|
_log = logging.getLogger(__name__)
 | 
						|
 | 
						|
 | 
						|
def _prevent_rasterization(draw):
 | 
						|
    # We assume that by default artists are not allowed to rasterize (unless
 | 
						|
    # its draw method is explicitly decorated). If it is being drawn after a
 | 
						|
    # rasterized artist and it has reached a raster_depth of 0, we stop
 | 
						|
    # rasterization so that it does not affect the behavior of normal artist
 | 
						|
    # (e.g., change in dpi).
 | 
						|
 | 
						|
    @wraps(draw)
 | 
						|
    def draw_wrapper(artist, renderer, *args, **kwargs):
 | 
						|
        if renderer._raster_depth == 0 and renderer._rasterizing:
 | 
						|
            # Only stop when we are not in a rasterized parent
 | 
						|
            # and something has been rasterized since last stop.
 | 
						|
            renderer.stop_rasterizing()
 | 
						|
            renderer._rasterizing = False
 | 
						|
 | 
						|
        return draw(artist, renderer, *args, **kwargs)
 | 
						|
 | 
						|
    draw_wrapper._supports_rasterization = False
 | 
						|
    return draw_wrapper
 | 
						|
 | 
						|
 | 
						|
def allow_rasterization(draw):
 | 
						|
    """
 | 
						|
    Decorator for Artist.draw method. Provides routines
 | 
						|
    that run before and after the draw call. The before and after functions
 | 
						|
    are useful for changing artist-dependent renderer attributes or making
 | 
						|
    other setup function calls, such as starting and flushing a mixed-mode
 | 
						|
    renderer.
 | 
						|
    """
 | 
						|
 | 
						|
    @wraps(draw)
 | 
						|
    def draw_wrapper(artist, renderer):
 | 
						|
        try:
 | 
						|
            if artist.get_rasterized():
 | 
						|
                if renderer._raster_depth == 0 and not renderer._rasterizing:
 | 
						|
                    renderer.start_rasterizing()
 | 
						|
                    renderer._rasterizing = True
 | 
						|
                renderer._raster_depth += 1
 | 
						|
            else:
 | 
						|
                if renderer._raster_depth == 0 and renderer._rasterizing:
 | 
						|
                    # Only stop when we are not in a rasterized parent
 | 
						|
                    # and something has be rasterized since last stop
 | 
						|
                    renderer.stop_rasterizing()
 | 
						|
                    renderer._rasterizing = False
 | 
						|
 | 
						|
            if artist.get_agg_filter() is not None:
 | 
						|
                renderer.start_filter()
 | 
						|
 | 
						|
            return draw(artist, renderer)
 | 
						|
        finally:
 | 
						|
            if artist.get_agg_filter() is not None:
 | 
						|
                renderer.stop_filter(artist.get_agg_filter())
 | 
						|
            if artist.get_rasterized():
 | 
						|
                renderer._raster_depth -= 1
 | 
						|
            if (renderer._rasterizing and (fig := artist.get_figure(root=True)) and
 | 
						|
                    fig.suppressComposite):
 | 
						|
                # restart rasterizing to prevent merging
 | 
						|
                renderer.stop_rasterizing()
 | 
						|
                renderer.start_rasterizing()
 | 
						|
 | 
						|
    draw_wrapper._supports_rasterization = True
 | 
						|
    return draw_wrapper
 | 
						|
 | 
						|
 | 
						|
def _finalize_rasterization(draw):
 | 
						|
    """
 | 
						|
    Decorator for Artist.draw method. Needed on the outermost artist, i.e.
 | 
						|
    Figure, to finish up if the render is still in rasterized mode.
 | 
						|
    """
 | 
						|
    @wraps(draw)
 | 
						|
    def draw_wrapper(artist, renderer, *args, **kwargs):
 | 
						|
        result = draw(artist, renderer, *args, **kwargs)
 | 
						|
        if renderer._rasterizing:
 | 
						|
            renderer.stop_rasterizing()
 | 
						|
            renderer._rasterizing = False
 | 
						|
        return result
 | 
						|
    return draw_wrapper
 | 
						|
 | 
						|
 | 
						|
def _stale_axes_callback(self, val):
 | 
						|
    if self.axes:
 | 
						|
        self.axes.stale = val
 | 
						|
 | 
						|
 | 
						|
_XYPair = namedtuple("_XYPair", "x y")
 | 
						|
 | 
						|
 | 
						|
class _Unset:
 | 
						|
    def __repr__(self):
 | 
						|
        return "<UNSET>"
 | 
						|
_UNSET = _Unset()
 | 
						|
 | 
						|
 | 
						|
class Artist:
 | 
						|
    """
 | 
						|
    Abstract base class for objects that render into a FigureCanvas.
 | 
						|
 | 
						|
    Typically, all visible elements in a figure are subclasses of Artist.
 | 
						|
    """
 | 
						|
 | 
						|
    zorder = 0
 | 
						|
 | 
						|
    def __init_subclass__(cls):
 | 
						|
 | 
						|
        # Decorate draw() method so that all artists are able to stop
 | 
						|
        # rastrization when necessary. If the artist's draw method is already
 | 
						|
        # decorated (has a `_supports_rasterization` attribute), it won't be
 | 
						|
        # decorated.
 | 
						|
 | 
						|
        if not hasattr(cls.draw, "_supports_rasterization"):
 | 
						|
            cls.draw = _prevent_rasterization(cls.draw)
 | 
						|
 | 
						|
        # Inject custom set() methods into the subclass with signature and
 | 
						|
        # docstring based on the subclasses' properties.
 | 
						|
 | 
						|
        if not hasattr(cls.set, '_autogenerated_signature'):
 | 
						|
            # Don't overwrite cls.set if the subclass or one of its parents
 | 
						|
            # has defined a set method set itself.
 | 
						|
            # If there was no explicit definition, cls.set is inherited from
 | 
						|
            # the hierarchy of auto-generated set methods, which hold the
 | 
						|
            # flag _autogenerated_signature.
 | 
						|
            return
 | 
						|
 | 
						|
        cls.set = lambda self, **kwargs: Artist.set(self, **kwargs)
 | 
						|
        cls.set.__name__ = "set"
 | 
						|
        cls.set.__qualname__ = f"{cls.__qualname__}.set"
 | 
						|
        cls._update_set_signature_and_docstring()
 | 
						|
 | 
						|
    _PROPERTIES_EXCLUDED_FROM_SET = [
 | 
						|
        'navigate_mode',  # not a user-facing function
 | 
						|
        'figure',         # changing the figure is such a profound operation
 | 
						|
                          # that we don't want this in set()
 | 
						|
        '3d_properties',  # cannot be used as a keyword due to leading digit
 | 
						|
    ]
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _update_set_signature_and_docstring(cls):
 | 
						|
        """
 | 
						|
        Update the signature of the set function to list all properties
 | 
						|
        as keyword arguments.
 | 
						|
 | 
						|
        Property aliases are not listed in the signature for brevity, but
 | 
						|
        are still accepted as keyword arguments.
 | 
						|
        """
 | 
						|
        cls.set.__signature__ = Signature(
 | 
						|
            [Parameter("self", Parameter.POSITIONAL_OR_KEYWORD),
 | 
						|
             *[Parameter(prop, Parameter.KEYWORD_ONLY, default=_UNSET)
 | 
						|
               for prop in ArtistInspector(cls).get_setters()
 | 
						|
               if prop not in Artist._PROPERTIES_EXCLUDED_FROM_SET]])
 | 
						|
        cls.set._autogenerated_signature = True
 | 
						|
 | 
						|
        cls.set.__doc__ = (
 | 
						|
            "Set multiple properties at once.\n\n"
 | 
						|
            "Supported properties are\n\n"
 | 
						|
            + kwdoc(cls))
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        self._stale = True
 | 
						|
        self.stale_callback = None
 | 
						|
        self._axes = None
 | 
						|
        self._parent_figure = None
 | 
						|
 | 
						|
        self._transform = None
 | 
						|
        self._transformSet = False
 | 
						|
        self._visible = True
 | 
						|
        self._animated = False
 | 
						|
        self._alpha = None
 | 
						|
        self.clipbox = None
 | 
						|
        self._clippath = None
 | 
						|
        self._clipon = True
 | 
						|
        self._label = ''
 | 
						|
        self._picker = None
 | 
						|
        self._rasterized = False
 | 
						|
        self._agg_filter = None
 | 
						|
        # Normally, artist classes need to be queried for mouseover info if and
 | 
						|
        # only if they override get_cursor_data.
 | 
						|
        self._mouseover = type(self).get_cursor_data != Artist.get_cursor_data
 | 
						|
        self._callbacks = cbook.CallbackRegistry(signals=["pchanged"])
 | 
						|
        try:
 | 
						|
            self.axes = None
 | 
						|
        except AttributeError:
 | 
						|
            # Handle self.axes as a read-only property, as in Figure.
 | 
						|
            pass
 | 
						|
        self._remove_method = None
 | 
						|
        self._url = None
 | 
						|
        self._gid = None
 | 
						|
        self._snap = None
 | 
						|
        self._sketch = mpl.rcParams['path.sketch']
 | 
						|
        self._path_effects = mpl.rcParams['path.effects']
 | 
						|
        self._sticky_edges = _XYPair([], [])
 | 
						|
        self._in_layout = True
 | 
						|
 | 
						|
    def __getstate__(self):
 | 
						|
        d = self.__dict__.copy()
 | 
						|
        d['stale_callback'] = None
 | 
						|
        return d
 | 
						|
 | 
						|
    def remove(self):
 | 
						|
        """
 | 
						|
        Remove the artist from the figure if possible.
 | 
						|
 | 
						|
        The effect will not be visible until the figure is redrawn, e.g.,
 | 
						|
        with `.FigureCanvasBase.draw_idle`.  Call `~.axes.Axes.relim` to
 | 
						|
        update the Axes limits if desired.
 | 
						|
 | 
						|
        Note: `~.axes.Axes.relim` will not see collections even if the
 | 
						|
        collection was added to the Axes with *autolim* = True.
 | 
						|
 | 
						|
        Note: there is no support for removing the artist's legend entry.
 | 
						|
        """
 | 
						|
 | 
						|
        # There is no method to set the callback.  Instead, the parent should
 | 
						|
        # set the _remove_method attribute directly.  This would be a
 | 
						|
        # protected attribute if Python supported that sort of thing.  The
 | 
						|
        # callback has one parameter, which is the child to be removed.
 | 
						|
        if self._remove_method is not None:
 | 
						|
            self._remove_method(self)
 | 
						|
            # clear stale callback
 | 
						|
            self.stale_callback = None
 | 
						|
            _ax_flag = False
 | 
						|
            if hasattr(self, 'axes') and self.axes:
 | 
						|
                # remove from the mouse hit list
 | 
						|
                self.axes._mouseover_set.discard(self)
 | 
						|
                self.axes.stale = True
 | 
						|
                self.axes = None  # decouple the artist from the Axes
 | 
						|
                _ax_flag = True
 | 
						|
 | 
						|
            if (fig := self.get_figure(root=False)) is not None:
 | 
						|
                if not _ax_flag:
 | 
						|
                    fig.stale = True
 | 
						|
                self._parent_figure = None
 | 
						|
 | 
						|
        else:
 | 
						|
            raise NotImplementedError('cannot remove artist')
 | 
						|
        # TODO: the fix for the collections relim problem is to move the
 | 
						|
        # limits calculation into the artist itself, including the property of
 | 
						|
        # whether or not the artist should affect the limits.  Then there will
 | 
						|
        # be no distinction between axes.add_line, axes.add_patch, etc.
 | 
						|
        # TODO: add legend support
 | 
						|
 | 
						|
    def have_units(self):
 | 
						|
        """Return whether units are set on any axis."""
 | 
						|
        ax = self.axes
 | 
						|
        return ax and any(axis.have_units() for axis in ax._axis_map.values())
 | 
						|
 | 
						|
    def convert_xunits(self, x):
 | 
						|
        """
 | 
						|
        Convert *x* using the unit type of the xaxis.
 | 
						|
 | 
						|
        If the artist is not contained in an Axes or if the xaxis does not
 | 
						|
        have units, *x* itself is returned.
 | 
						|
        """
 | 
						|
        ax = getattr(self, 'axes', None)
 | 
						|
        if ax is None or ax.xaxis is None:
 | 
						|
            return x
 | 
						|
        return ax.xaxis.convert_units(x)
 | 
						|
 | 
						|
    def convert_yunits(self, y):
 | 
						|
        """
 | 
						|
        Convert *y* using the unit type of the yaxis.
 | 
						|
 | 
						|
        If the artist is not contained in an Axes or if the yaxis does not
 | 
						|
        have units, *y* itself is returned.
 | 
						|
        """
 | 
						|
        ax = getattr(self, 'axes', None)
 | 
						|
        if ax is None or ax.yaxis is None:
 | 
						|
            return y
 | 
						|
        return ax.yaxis.convert_units(y)
 | 
						|
 | 
						|
    @property
 | 
						|
    def axes(self):
 | 
						|
        """The `~.axes.Axes` instance the artist resides in, or *None*."""
 | 
						|
        return self._axes
 | 
						|
 | 
						|
    @axes.setter
 | 
						|
    def axes(self, new_axes):
 | 
						|
        if (new_axes is not None and self._axes is not None
 | 
						|
                and new_axes != self._axes):
 | 
						|
            raise ValueError("Can not reset the Axes. You are probably trying to reuse "
 | 
						|
                             "an artist in more than one Axes which is not supported")
 | 
						|
        self._axes = new_axes
 | 
						|
        if new_axes is not None and new_axes is not self:
 | 
						|
            self.stale_callback = _stale_axes_callback
 | 
						|
 | 
						|
    @property
 | 
						|
    def stale(self):
 | 
						|
        """
 | 
						|
        Whether the artist is 'stale' and needs to be re-drawn for the output
 | 
						|
        to match the internal state of the artist.
 | 
						|
        """
 | 
						|
        return self._stale
 | 
						|
 | 
						|
    @stale.setter
 | 
						|
    def stale(self, val):
 | 
						|
        self._stale = val
 | 
						|
 | 
						|
        # if the artist is animated it does not take normal part in the
 | 
						|
        # draw stack and is not expected to be drawn as part of the normal
 | 
						|
        # draw loop (when not saving) so do not propagate this change
 | 
						|
        if self._animated:
 | 
						|
            return
 | 
						|
 | 
						|
        if val and self.stale_callback is not None:
 | 
						|
            self.stale_callback(self, val)
 | 
						|
 | 
						|
    def get_window_extent(self, renderer=None):
 | 
						|
        """
 | 
						|
        Get the artist's bounding box in display space.
 | 
						|
 | 
						|
        The bounding box' width and height are nonnegative.
 | 
						|
 | 
						|
        Subclasses should override for inclusion in the bounding box
 | 
						|
        "tight" calculation. Default is to return an empty bounding
 | 
						|
        box at 0, 0.
 | 
						|
 | 
						|
        Be careful when using this function, the results will not update
 | 
						|
        if the artist window extent of the artist changes.  The extent
 | 
						|
        can change due to any changes in the transform stack, such as
 | 
						|
        changing the Axes limits, the figure size, or the canvas used
 | 
						|
        (as is done when saving a figure).  This can lead to unexpected
 | 
						|
        behavior where interactive figures will look fine on the screen,
 | 
						|
        but will save incorrectly.
 | 
						|
        """
 | 
						|
        return Bbox([[0, 0], [0, 0]])
 | 
						|
 | 
						|
    def get_tightbbox(self, renderer=None):
 | 
						|
        """
 | 
						|
        Like `.Artist.get_window_extent`, but includes any clipping.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        renderer : `~matplotlib.backend_bases.RendererBase` subclass, optional
 | 
						|
            renderer that will be used to draw the figures (i.e.
 | 
						|
            ``fig.canvas.get_renderer()``)
 | 
						|
 | 
						|
        Returns
 | 
						|
        -------
 | 
						|
        `.Bbox` or None
 | 
						|
            The enclosing bounding box (in figure pixel coordinates).
 | 
						|
            Returns None if clipping results in no intersection.
 | 
						|
        """
 | 
						|
        bbox = self.get_window_extent(renderer)
 | 
						|
        if self.get_clip_on():
 | 
						|
            clip_box = self.get_clip_box()
 | 
						|
            if clip_box is not None:
 | 
						|
                bbox = Bbox.intersection(bbox, clip_box)
 | 
						|
            clip_path = self.get_clip_path()
 | 
						|
            if clip_path is not None and bbox is not None:
 | 
						|
                clip_path = clip_path.get_fully_transformed_path()
 | 
						|
                bbox = Bbox.intersection(bbox, clip_path.get_extents())
 | 
						|
        return bbox
 | 
						|
 | 
						|
    def add_callback(self, func):
 | 
						|
        """
 | 
						|
        Add a callback function that will be called whenever one of the
 | 
						|
        `.Artist`'s properties changes.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        func : callable
 | 
						|
            The callback function. It must have the signature::
 | 
						|
 | 
						|
                def func(artist: Artist) -> Any
 | 
						|
 | 
						|
            where *artist* is the calling `.Artist`. Return values may exist
 | 
						|
            but are ignored.
 | 
						|
 | 
						|
        Returns
 | 
						|
        -------
 | 
						|
        int
 | 
						|
            The observer id associated with the callback. This id can be
 | 
						|
            used for removing the callback with `.remove_callback` later.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        remove_callback
 | 
						|
        """
 | 
						|
        # Wrapping func in a lambda ensures it can be connected multiple times
 | 
						|
        # and never gets weakref-gc'ed.
 | 
						|
        return self._callbacks.connect("pchanged", lambda: func(self))
 | 
						|
 | 
						|
    def remove_callback(self, oid):
 | 
						|
        """
 | 
						|
        Remove a callback based on its observer id.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        add_callback
 | 
						|
        """
 | 
						|
        self._callbacks.disconnect(oid)
 | 
						|
 | 
						|
    def pchanged(self):
 | 
						|
        """
 | 
						|
        Call all of the registered callbacks.
 | 
						|
 | 
						|
        This function is triggered internally when a property is changed.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        add_callback
 | 
						|
        remove_callback
 | 
						|
        """
 | 
						|
        self._callbacks.process("pchanged")
 | 
						|
 | 
						|
    def is_transform_set(self):
 | 
						|
        """
 | 
						|
        Return whether the Artist has an explicitly set transform.
 | 
						|
 | 
						|
        This is *True* after `.set_transform` has been called.
 | 
						|
        """
 | 
						|
        return self._transformSet
 | 
						|
 | 
						|
    def set_transform(self, t):
 | 
						|
        """
 | 
						|
        Set the artist transform.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        t : `~matplotlib.transforms.Transform`
 | 
						|
        """
 | 
						|
        self._transform = t
 | 
						|
        self._transformSet = True
 | 
						|
        self.pchanged()
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def get_transform(self):
 | 
						|
        """Return the `.Transform` instance used by this artist."""
 | 
						|
        if self._transform is None:
 | 
						|
            self._transform = IdentityTransform()
 | 
						|
        elif (not isinstance(self._transform, Transform)
 | 
						|
              and hasattr(self._transform, '_as_mpl_transform')):
 | 
						|
            self._transform = self._transform._as_mpl_transform(self.axes)
 | 
						|
        return self._transform
 | 
						|
 | 
						|
    def get_children(self):
 | 
						|
        r"""Return a list of the child `.Artist`\s of this `.Artist`."""
 | 
						|
        return []
 | 
						|
 | 
						|
    def _different_canvas(self, event):
 | 
						|
        """
 | 
						|
        Check whether an *event* occurred on a canvas other that this artist's canvas.
 | 
						|
 | 
						|
        If this method returns True, the event definitely occurred on a different
 | 
						|
        canvas; if it returns False, either it occurred on the same canvas, or we may
 | 
						|
        not have enough information to know.
 | 
						|
 | 
						|
        Subclasses should start their definition of `contains` as follows::
 | 
						|
 | 
						|
            if self._different_canvas(mouseevent):
 | 
						|
                return False, {}
 | 
						|
            # subclass-specific implementation follows
 | 
						|
        """
 | 
						|
        return (getattr(event, "canvas", None) is not None
 | 
						|
                and (fig := self.get_figure(root=True)) is not None
 | 
						|
                and event.canvas is not fig.canvas)
 | 
						|
 | 
						|
    def contains(self, mouseevent):
 | 
						|
        """
 | 
						|
        Test whether the artist contains the mouse event.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        mouseevent : `~matplotlib.backend_bases.MouseEvent`
 | 
						|
 | 
						|
        Returns
 | 
						|
        -------
 | 
						|
        contains : bool
 | 
						|
            Whether any values are within the radius.
 | 
						|
        details : dict
 | 
						|
            An artist-specific dictionary of details of the event context,
 | 
						|
            such as which points are contained in the pick radius. See the
 | 
						|
            individual Artist subclasses for details.
 | 
						|
        """
 | 
						|
        _log.warning("%r needs 'contains' method", self.__class__.__name__)
 | 
						|
        return False, {}
 | 
						|
 | 
						|
    def pickable(self):
 | 
						|
        """
 | 
						|
        Return whether the artist is pickable.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        .Artist.set_picker, .Artist.get_picker, .Artist.pick
 | 
						|
        """
 | 
						|
        return self.get_figure(root=False) is not None and self._picker is not None
 | 
						|
 | 
						|
    def pick(self, mouseevent):
 | 
						|
        """
 | 
						|
        Process a pick event.
 | 
						|
 | 
						|
        Each child artist will fire a pick event if *mouseevent* is over
 | 
						|
        the artist and the artist has picker set.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        .Artist.set_picker, .Artist.get_picker, .Artist.pickable
 | 
						|
        """
 | 
						|
        from .backend_bases import PickEvent  # Circular import.
 | 
						|
        # Pick self
 | 
						|
        if self.pickable():
 | 
						|
            picker = self.get_picker()
 | 
						|
            if callable(picker):
 | 
						|
                inside, prop = picker(self, mouseevent)
 | 
						|
            else:
 | 
						|
                inside, prop = self.contains(mouseevent)
 | 
						|
            if inside:
 | 
						|
                PickEvent("pick_event", self.get_figure(root=True).canvas,
 | 
						|
                          mouseevent, self, **prop)._process()
 | 
						|
 | 
						|
        # Pick children
 | 
						|
        for a in self.get_children():
 | 
						|
            # make sure the event happened in the same Axes
 | 
						|
            ax = getattr(a, 'axes', None)
 | 
						|
            if (isinstance(a, mpl.figure.SubFigure)
 | 
						|
                    or mouseevent.inaxes is None or ax is None
 | 
						|
                    or mouseevent.inaxes == ax):
 | 
						|
                # we need to check if mouseevent.inaxes is None
 | 
						|
                # because some objects associated with an Axes (e.g., a
 | 
						|
                # tick label) can be outside the bounding box of the
 | 
						|
                # Axes and inaxes will be None
 | 
						|
                # also check that ax is None so that it traverse objects
 | 
						|
                # which do not have an axes property but children might
 | 
						|
                a.pick(mouseevent)
 | 
						|
 | 
						|
    def set_picker(self, picker):
 | 
						|
        """
 | 
						|
        Define the picking behavior of the artist.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        picker : None or bool or float or callable
 | 
						|
            This can be one of the following:
 | 
						|
 | 
						|
            - *None*: Picking is disabled for this artist (default).
 | 
						|
 | 
						|
            - A boolean: If *True* then picking will be enabled and the
 | 
						|
              artist will fire a pick event if the mouse event is over
 | 
						|
              the artist.
 | 
						|
 | 
						|
            - A float: If picker is a number it is interpreted as an
 | 
						|
              epsilon tolerance in points and the artist will fire
 | 
						|
              off an event if its data is within epsilon of the mouse
 | 
						|
              event.  For some artists like lines and patch collections,
 | 
						|
              the artist may provide additional data to the pick event
 | 
						|
              that is generated, e.g., the indices of the data within
 | 
						|
              epsilon of the pick event
 | 
						|
 | 
						|
            - A function: If picker is callable, it is a user supplied
 | 
						|
              function which determines whether the artist is hit by the
 | 
						|
              mouse event::
 | 
						|
 | 
						|
                hit, props = picker(artist, mouseevent)
 | 
						|
 | 
						|
              to determine the hit test.  if the mouse event is over the
 | 
						|
              artist, return *hit=True* and props is a dictionary of
 | 
						|
              properties you want added to the PickEvent attributes.
 | 
						|
        """
 | 
						|
        self._picker = picker
 | 
						|
 | 
						|
    def get_picker(self):
 | 
						|
        """
 | 
						|
        Return the picking behavior of the artist.
 | 
						|
 | 
						|
        The possible values are described in `.Artist.set_picker`.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        .Artist.set_picker, .Artist.pickable, .Artist.pick
 | 
						|
        """
 | 
						|
        return self._picker
 | 
						|
 | 
						|
    def get_url(self):
 | 
						|
        """Return the url."""
 | 
						|
        return self._url
 | 
						|
 | 
						|
    def set_url(self, url):
 | 
						|
        """
 | 
						|
        Set the url for the artist.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        url : str
 | 
						|
        """
 | 
						|
        self._url = url
 | 
						|
 | 
						|
    def get_gid(self):
 | 
						|
        """Return the group id."""
 | 
						|
        return self._gid
 | 
						|
 | 
						|
    def set_gid(self, gid):
 | 
						|
        """
 | 
						|
        Set the (group) id for the artist.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        gid : str
 | 
						|
        """
 | 
						|
        self._gid = gid
 | 
						|
 | 
						|
    def get_snap(self):
 | 
						|
        """
 | 
						|
        Return the snap setting.
 | 
						|
 | 
						|
        See `.set_snap` for details.
 | 
						|
        """
 | 
						|
        if mpl.rcParams['path.snap']:
 | 
						|
            return self._snap
 | 
						|
        else:
 | 
						|
            return False
 | 
						|
 | 
						|
    def set_snap(self, snap):
 | 
						|
        """
 | 
						|
        Set the snapping behavior.
 | 
						|
 | 
						|
        Snapping aligns positions with the pixel grid, which results in
 | 
						|
        clearer images. For example, if a black line of 1px width was
 | 
						|
        defined at a position in between two pixels, the resulting image
 | 
						|
        would contain the interpolated value of that line in the pixel grid,
 | 
						|
        which would be a grey value on both adjacent pixel positions. In
 | 
						|
        contrast, snapping will move the line to the nearest integer pixel
 | 
						|
        value, so that the resulting image will really contain a 1px wide
 | 
						|
        black line.
 | 
						|
 | 
						|
        Snapping is currently only supported by the Agg and MacOSX backends.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        snap : bool or None
 | 
						|
            Possible values:
 | 
						|
 | 
						|
            - *True*: Snap vertices to the nearest pixel center.
 | 
						|
            - *False*: Do not modify vertex positions.
 | 
						|
            - *None*: (auto) If the path contains only rectilinear line
 | 
						|
              segments, round to the nearest pixel center.
 | 
						|
        """
 | 
						|
        self._snap = snap
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def get_sketch_params(self):
 | 
						|
        """
 | 
						|
        Return the sketch parameters for the artist.
 | 
						|
 | 
						|
        Returns
 | 
						|
        -------
 | 
						|
        tuple or None
 | 
						|
 | 
						|
            A 3-tuple with the following elements:
 | 
						|
 | 
						|
            - *scale*: The amplitude of the wiggle perpendicular to the
 | 
						|
              source line.
 | 
						|
            - *length*: The length of the wiggle along the line.
 | 
						|
            - *randomness*: The scale factor by which the length is
 | 
						|
              shrunken or expanded.
 | 
						|
 | 
						|
            Returns *None* if no sketch parameters were set.
 | 
						|
        """
 | 
						|
        return self._sketch
 | 
						|
 | 
						|
    def set_sketch_params(self, scale=None, length=None, randomness=None):
 | 
						|
        """
 | 
						|
        Set the sketch parameters.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        scale : float, optional
 | 
						|
            The amplitude of the wiggle perpendicular to the source
 | 
						|
            line, in pixels.  If scale is `None`, or not provided, no
 | 
						|
            sketch filter will be provided.
 | 
						|
        length : float, optional
 | 
						|
             The length of the wiggle along the line, in pixels
 | 
						|
             (default 128.0)
 | 
						|
        randomness : float, optional
 | 
						|
            The scale factor by which the length is shrunken or
 | 
						|
            expanded (default 16.0)
 | 
						|
 | 
						|
            The PGF backend uses this argument as an RNG seed and not as
 | 
						|
            described above. Using the same seed yields the same random shape.
 | 
						|
 | 
						|
            .. ACCEPTS: (scale: float, length: float, randomness: float)
 | 
						|
        """
 | 
						|
        if scale is None:
 | 
						|
            self._sketch = None
 | 
						|
        else:
 | 
						|
            self._sketch = (scale, length or 128.0, randomness or 16.0)
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def set_path_effects(self, path_effects):
 | 
						|
        """
 | 
						|
        Set the path effects.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        path_effects : list of `.AbstractPathEffect`
 | 
						|
        """
 | 
						|
        self._path_effects = path_effects
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def get_path_effects(self):
 | 
						|
        return self._path_effects
 | 
						|
 | 
						|
    def get_figure(self, root=False):
 | 
						|
        """
 | 
						|
        Return the `.Figure` or `.SubFigure` instance the artist belongs to.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        root : bool, default=False
 | 
						|
            If False, return the (Sub)Figure this artist is on.  If True,
 | 
						|
            return the root Figure for a nested tree of SubFigures.
 | 
						|
        """
 | 
						|
        if root and self._parent_figure is not None:
 | 
						|
            return self._parent_figure.get_figure(root=True)
 | 
						|
 | 
						|
        return self._parent_figure
 | 
						|
 | 
						|
    def set_figure(self, fig):
 | 
						|
        """
 | 
						|
        Set the `.Figure` or `.SubFigure` instance the artist belongs to.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        fig : `~matplotlib.figure.Figure` or `~matplotlib.figure.SubFigure`
 | 
						|
        """
 | 
						|
        # if this is a no-op just return
 | 
						|
        if self._parent_figure is fig:
 | 
						|
            return
 | 
						|
        # if we currently have a figure (the case of both `self.figure`
 | 
						|
        # and *fig* being none is taken care of above) we then user is
 | 
						|
        # trying to change the figure an artist is associated with which
 | 
						|
        # is not allowed for the same reason as adding the same instance
 | 
						|
        # to more than one Axes
 | 
						|
        if self._parent_figure is not None:
 | 
						|
            raise RuntimeError("Can not put single artist in "
 | 
						|
                               "more than one figure")
 | 
						|
        self._parent_figure = fig
 | 
						|
        if self._parent_figure and self._parent_figure is not self:
 | 
						|
            self.pchanged()
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    figure = property(get_figure, set_figure,
 | 
						|
                      doc=("The (Sub)Figure that the artist is on.  For more "
 | 
						|
                           "control, use the `get_figure` method."))
 | 
						|
 | 
						|
    def set_clip_box(self, clipbox):
 | 
						|
        """
 | 
						|
        Set the artist's clip `.Bbox`.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        clipbox : `~matplotlib.transforms.BboxBase` or None
 | 
						|
            Will typically be created from a `.TransformedBbox`. For instance,
 | 
						|
            ``TransformedBbox(Bbox([[0, 0], [1, 1]]), ax.transAxes)`` is the default
 | 
						|
            clipping for an artist added to an Axes.
 | 
						|
 | 
						|
        """
 | 
						|
        _api.check_isinstance((BboxBase, None), clipbox=clipbox)
 | 
						|
        if clipbox != self.clipbox:
 | 
						|
            self.clipbox = clipbox
 | 
						|
            self.pchanged()
 | 
						|
            self.stale = True
 | 
						|
 | 
						|
    def set_clip_path(self, path, transform=None):
 | 
						|
        """
 | 
						|
        Set the artist's clip path.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        path : `~matplotlib.patches.Patch` or `.Path` or `.TransformedPath` or None
 | 
						|
            The clip path. If given a `.Path`, *transform* must be provided as
 | 
						|
            well. If *None*, a previously set clip path is removed.
 | 
						|
        transform : `~matplotlib.transforms.Transform`, optional
 | 
						|
            Only used if *path* is a `.Path`, in which case the given `.Path`
 | 
						|
            is converted to a `.TransformedPath` using *transform*.
 | 
						|
 | 
						|
        Notes
 | 
						|
        -----
 | 
						|
        For efficiency, if *path* is a `.Rectangle` this method will set the
 | 
						|
        clipping box to the corresponding rectangle and set the clipping path
 | 
						|
        to ``None``.
 | 
						|
 | 
						|
        For technical reasons (support of `~.Artist.set`), a tuple
 | 
						|
        (*path*, *transform*) is also accepted as a single positional
 | 
						|
        parameter.
 | 
						|
 | 
						|
        .. ACCEPTS: Patch or (Path, Transform) or None
 | 
						|
        """
 | 
						|
        from matplotlib.patches import Patch, Rectangle
 | 
						|
 | 
						|
        success = False
 | 
						|
        if transform is None:
 | 
						|
            if isinstance(path, Rectangle):
 | 
						|
                self.clipbox = TransformedBbox(Bbox.unit(),
 | 
						|
                                               path.get_transform())
 | 
						|
                self._clippath = None
 | 
						|
                success = True
 | 
						|
            elif isinstance(path, Patch):
 | 
						|
                self._clippath = TransformedPatchPath(path)
 | 
						|
                success = True
 | 
						|
            elif isinstance(path, tuple):
 | 
						|
                path, transform = path
 | 
						|
 | 
						|
        if path is None:
 | 
						|
            self._clippath = None
 | 
						|
            success = True
 | 
						|
        elif isinstance(path, Path):
 | 
						|
            self._clippath = TransformedPath(path, transform)
 | 
						|
            success = True
 | 
						|
        elif isinstance(path, TransformedPatchPath):
 | 
						|
            self._clippath = path
 | 
						|
            success = True
 | 
						|
        elif isinstance(path, TransformedPath):
 | 
						|
            self._clippath = path
 | 
						|
            success = True
 | 
						|
 | 
						|
        if not success:
 | 
						|
            raise TypeError(
 | 
						|
                "Invalid arguments to set_clip_path, of type "
 | 
						|
                f"{type(path).__name__} and {type(transform).__name__}")
 | 
						|
        # This may result in the callbacks being hit twice, but guarantees they
 | 
						|
        # will be hit at least once.
 | 
						|
        self.pchanged()
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def get_alpha(self):
 | 
						|
        """
 | 
						|
        Return the alpha value used for blending - not supported on all
 | 
						|
        backends.
 | 
						|
        """
 | 
						|
        return self._alpha
 | 
						|
 | 
						|
    def get_visible(self):
 | 
						|
        """Return the visibility."""
 | 
						|
        return self._visible
 | 
						|
 | 
						|
    def get_animated(self):
 | 
						|
        """Return whether the artist is animated."""
 | 
						|
        return self._animated
 | 
						|
 | 
						|
    def get_in_layout(self):
 | 
						|
        """
 | 
						|
        Return boolean flag, ``True`` if artist is included in layout
 | 
						|
        calculations.
 | 
						|
 | 
						|
        E.g. :ref:`constrainedlayout_guide`,
 | 
						|
        `.Figure.tight_layout()`, and
 | 
						|
        ``fig.savefig(fname, bbox_inches='tight')``.
 | 
						|
        """
 | 
						|
        return self._in_layout
 | 
						|
 | 
						|
    def _fully_clipped_to_axes(self):
 | 
						|
        """
 | 
						|
        Return a boolean flag, ``True`` if the artist is clipped to the Axes
 | 
						|
        and can thus be skipped in layout calculations. Requires `get_clip_on`
 | 
						|
        is True, one of `clip_box` or `clip_path` is set, ``clip_box.extents``
 | 
						|
        is equivalent to ``ax.bbox.extents`` (if set), and ``clip_path._patch``
 | 
						|
        is equivalent to ``ax.patch`` (if set).
 | 
						|
        """
 | 
						|
        # Note that ``clip_path.get_fully_transformed_path().get_extents()``
 | 
						|
        # cannot be directly compared to ``axes.bbox.extents`` because the
 | 
						|
        # extents may be undefined (i.e. equivalent to ``Bbox.null()``)
 | 
						|
        # before the associated artist is drawn, and this method is meant
 | 
						|
        # to determine whether ``axes.get_tightbbox()`` may bypass drawing
 | 
						|
        clip_box = self.get_clip_box()
 | 
						|
        clip_path = self.get_clip_path()
 | 
						|
        return (self.axes is not None
 | 
						|
                and self.get_clip_on()
 | 
						|
                and (clip_box is not None or clip_path is not None)
 | 
						|
                and (clip_box is None
 | 
						|
                     or np.all(clip_box.extents == self.axes.bbox.extents))
 | 
						|
                and (clip_path is None
 | 
						|
                     or isinstance(clip_path, TransformedPatchPath)
 | 
						|
                     and clip_path._patch is self.axes.patch))
 | 
						|
 | 
						|
    def get_clip_on(self):
 | 
						|
        """Return whether the artist uses clipping."""
 | 
						|
        return self._clipon
 | 
						|
 | 
						|
    def get_clip_box(self):
 | 
						|
        """Return the clipbox."""
 | 
						|
        return self.clipbox
 | 
						|
 | 
						|
    def get_clip_path(self):
 | 
						|
        """Return the clip path."""
 | 
						|
        return self._clippath
 | 
						|
 | 
						|
    def get_transformed_clip_path_and_affine(self):
 | 
						|
        """
 | 
						|
        Return the clip path with the non-affine part of its
 | 
						|
        transformation applied, and the remaining affine part of its
 | 
						|
        transformation.
 | 
						|
        """
 | 
						|
        if self._clippath is not None:
 | 
						|
            return self._clippath.get_transformed_path_and_affine()
 | 
						|
        return None, None
 | 
						|
 | 
						|
    def set_clip_on(self, b):
 | 
						|
        """
 | 
						|
        Set whether the artist uses clipping.
 | 
						|
 | 
						|
        When False, artists will be visible outside the Axes which
 | 
						|
        can lead to unexpected results.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        b : bool
 | 
						|
        """
 | 
						|
        self._clipon = b
 | 
						|
        # This may result in the callbacks being hit twice, but ensures they
 | 
						|
        # are hit at least once
 | 
						|
        self.pchanged()
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def _set_gc_clip(self, gc):
 | 
						|
        """Set the clip properly for the gc."""
 | 
						|
        if self._clipon:
 | 
						|
            if self.clipbox is not None:
 | 
						|
                gc.set_clip_rectangle(self.clipbox)
 | 
						|
            gc.set_clip_path(self._clippath)
 | 
						|
        else:
 | 
						|
            gc.set_clip_rectangle(None)
 | 
						|
            gc.set_clip_path(None)
 | 
						|
 | 
						|
    def get_rasterized(self):
 | 
						|
        """Return whether the artist is to be rasterized."""
 | 
						|
        return self._rasterized
 | 
						|
 | 
						|
    def set_rasterized(self, rasterized):
 | 
						|
        """
 | 
						|
        Force rasterized (bitmap) drawing for vector graphics output.
 | 
						|
 | 
						|
        Rasterized drawing is not supported by all artists. If you try to
 | 
						|
        enable this on an artist that does not support it, the command has no
 | 
						|
        effect and a warning will be issued.
 | 
						|
 | 
						|
        This setting is ignored for pixel-based output.
 | 
						|
 | 
						|
        See also :doc:`/gallery/misc/rasterization_demo`.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        rasterized : bool
 | 
						|
        """
 | 
						|
        supports_rasterization = getattr(self.draw,
 | 
						|
                                         "_supports_rasterization", False)
 | 
						|
        if rasterized and not supports_rasterization:
 | 
						|
            _api.warn_external(f"Rasterization of '{self}' will be ignored")
 | 
						|
 | 
						|
        self._rasterized = rasterized
 | 
						|
 | 
						|
    def get_agg_filter(self):
 | 
						|
        """Return filter function to be used for agg filter."""
 | 
						|
        return self._agg_filter
 | 
						|
 | 
						|
    def set_agg_filter(self, filter_func):
 | 
						|
        """
 | 
						|
        Set the agg filter.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        filter_func : callable
 | 
						|
            A filter function, which takes a (m, n, depth) float array
 | 
						|
            and a dpi value, and returns a (m, n, depth) array and two
 | 
						|
            offsets from the bottom left corner of the image
 | 
						|
 | 
						|
            .. ACCEPTS: a filter function, which takes a (m, n, 3) float array
 | 
						|
                and a dpi value, and returns a (m, n, 3) array and two offsets
 | 
						|
                from the bottom left corner of the image
 | 
						|
        """
 | 
						|
        self._agg_filter = filter_func
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def draw(self, renderer):
 | 
						|
        """
 | 
						|
        Draw the Artist (and its children) using the given renderer.
 | 
						|
 | 
						|
        This has no effect if the artist is not visible (`.Artist.get_visible`
 | 
						|
        returns False).
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        renderer : `~matplotlib.backend_bases.RendererBase` subclass.
 | 
						|
 | 
						|
        Notes
 | 
						|
        -----
 | 
						|
        This method is overridden in the Artist subclasses.
 | 
						|
        """
 | 
						|
        if not self.get_visible():
 | 
						|
            return
 | 
						|
        self.stale = False
 | 
						|
 | 
						|
    def set_alpha(self, alpha):
 | 
						|
        """
 | 
						|
        Set the alpha value used for blending - not supported on all backends.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        alpha : float or None
 | 
						|
            *alpha* must be within the 0-1 range, inclusive.
 | 
						|
        """
 | 
						|
        if alpha is not None and not isinstance(alpha, Real):
 | 
						|
            raise TypeError(
 | 
						|
                f'alpha must be numeric or None, not {type(alpha)}')
 | 
						|
        if alpha is not None and not (0 <= alpha <= 1):
 | 
						|
            raise ValueError(f'alpha ({alpha}) is outside 0-1 range')
 | 
						|
        if alpha != self._alpha:
 | 
						|
            self._alpha = alpha
 | 
						|
            self.pchanged()
 | 
						|
            self.stale = True
 | 
						|
 | 
						|
    def _set_alpha_for_array(self, alpha):
 | 
						|
        """
 | 
						|
        Set the alpha value used for blending - not supported on all backends.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        alpha : array-like or float or None
 | 
						|
            All values must be within the 0-1 range, inclusive.
 | 
						|
            Masked values and nans are not supported.
 | 
						|
        """
 | 
						|
        if isinstance(alpha, str):
 | 
						|
            raise TypeError("alpha must be numeric or None, not a string")
 | 
						|
        if not np.iterable(alpha):
 | 
						|
            Artist.set_alpha(self, alpha)
 | 
						|
            return
 | 
						|
        alpha = np.asarray(alpha)
 | 
						|
        if not (0 <= alpha.min() and alpha.max() <= 1):
 | 
						|
            raise ValueError('alpha must be between 0 and 1, inclusive, '
 | 
						|
                             f'but min is {alpha.min()}, max is {alpha.max()}')
 | 
						|
        self._alpha = alpha
 | 
						|
        self.pchanged()
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def set_visible(self, b):
 | 
						|
        """
 | 
						|
        Set the artist's visibility.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        b : bool
 | 
						|
        """
 | 
						|
        if b != self._visible:
 | 
						|
            self._visible = b
 | 
						|
            self.pchanged()
 | 
						|
            self.stale = True
 | 
						|
 | 
						|
    def set_animated(self, b):
 | 
						|
        """
 | 
						|
        Set whether the artist is intended to be used in an animation.
 | 
						|
 | 
						|
        If True, the artist is excluded from regular drawing of the figure.
 | 
						|
        You have to call `.Figure.draw_artist` / `.Axes.draw_artist`
 | 
						|
        explicitly on the artist. This approach is used to speed up animations
 | 
						|
        using blitting.
 | 
						|
 | 
						|
        See also `matplotlib.animation` and
 | 
						|
        :ref:`blitting`.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        b : bool
 | 
						|
        """
 | 
						|
        if self._animated != b:
 | 
						|
            self._animated = b
 | 
						|
            self.pchanged()
 | 
						|
 | 
						|
    def set_in_layout(self, in_layout):
 | 
						|
        """
 | 
						|
        Set if artist is to be included in layout calculations,
 | 
						|
        E.g. :ref:`constrainedlayout_guide`,
 | 
						|
        `.Figure.tight_layout()`, and
 | 
						|
        ``fig.savefig(fname, bbox_inches='tight')``.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        in_layout : bool
 | 
						|
        """
 | 
						|
        self._in_layout = in_layout
 | 
						|
 | 
						|
    def get_label(self):
 | 
						|
        """Return the label used for this artist in the legend."""
 | 
						|
        return self._label
 | 
						|
 | 
						|
    def set_label(self, s):
 | 
						|
        """
 | 
						|
        Set a label that will be displayed in the legend.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        s : object
 | 
						|
            *s* will be converted to a string by calling `str`.
 | 
						|
        """
 | 
						|
        label = str(s) if s is not None else None
 | 
						|
        if label != self._label:
 | 
						|
            self._label = label
 | 
						|
            self.pchanged()
 | 
						|
            self.stale = True
 | 
						|
 | 
						|
    def get_zorder(self):
 | 
						|
        """Return the artist's zorder."""
 | 
						|
        return self.zorder
 | 
						|
 | 
						|
    def set_zorder(self, level):
 | 
						|
        """
 | 
						|
        Set the zorder for the artist.  Artists with lower zorder
 | 
						|
        values are drawn first.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        level : float
 | 
						|
        """
 | 
						|
        if level is None:
 | 
						|
            level = self.__class__.zorder
 | 
						|
        if level != self.zorder:
 | 
						|
            self.zorder = level
 | 
						|
            self.pchanged()
 | 
						|
            self.stale = True
 | 
						|
 | 
						|
    @property
 | 
						|
    def sticky_edges(self):
 | 
						|
        """
 | 
						|
        ``x`` and ``y`` sticky edge lists for autoscaling.
 | 
						|
 | 
						|
        When performing autoscaling, if a data limit coincides with a value in
 | 
						|
        the corresponding sticky_edges list, then no margin will be added--the
 | 
						|
        view limit "sticks" to the edge. A typical use case is histograms,
 | 
						|
        where one usually expects no margin on the bottom edge (0) of the
 | 
						|
        histogram.
 | 
						|
 | 
						|
        Moreover, margin expansion "bumps" against sticky edges and cannot
 | 
						|
        cross them.  For example, if the upper data limit is 1.0, the upper
 | 
						|
        view limit computed by simple margin application is 1.2, but there is a
 | 
						|
        sticky edge at 1.1, then the actual upper view limit will be 1.1.
 | 
						|
 | 
						|
        This attribute cannot be assigned to; however, the ``x`` and ``y``
 | 
						|
        lists can be modified in place as needed.
 | 
						|
 | 
						|
        Examples
 | 
						|
        --------
 | 
						|
        >>> artist.sticky_edges.x[:] = (xmin, xmax)
 | 
						|
        >>> artist.sticky_edges.y[:] = (ymin, ymax)
 | 
						|
 | 
						|
        """
 | 
						|
        return self._sticky_edges
 | 
						|
 | 
						|
    def update_from(self, other):
 | 
						|
        """Copy properties from *other* to *self*."""
 | 
						|
        self._transform = other._transform
 | 
						|
        self._transformSet = other._transformSet
 | 
						|
        self._visible = other._visible
 | 
						|
        self._alpha = other._alpha
 | 
						|
        self.clipbox = other.clipbox
 | 
						|
        self._clipon = other._clipon
 | 
						|
        self._clippath = other._clippath
 | 
						|
        self._label = other._label
 | 
						|
        self._sketch = other._sketch
 | 
						|
        self._path_effects = other._path_effects
 | 
						|
        self.sticky_edges.x[:] = other.sticky_edges.x.copy()
 | 
						|
        self.sticky_edges.y[:] = other.sticky_edges.y.copy()
 | 
						|
        self.pchanged()
 | 
						|
        self.stale = True
 | 
						|
 | 
						|
    def properties(self):
 | 
						|
        """Return a dictionary of all the properties of the artist."""
 | 
						|
        return ArtistInspector(self).properties()
 | 
						|
 | 
						|
    def _update_props(self, props, errfmt):
 | 
						|
        """
 | 
						|
        Helper for `.Artist.set` and `.Artist.update`.
 | 
						|
 | 
						|
        *errfmt* is used to generate error messages for invalid property
 | 
						|
        names; it gets formatted with ``type(self)`` for "{cls}" and the
 | 
						|
        property name for "{prop_name}".
 | 
						|
        """
 | 
						|
        ret = []
 | 
						|
        with cbook._setattr_cm(self, eventson=False):
 | 
						|
            for k, v in props.items():
 | 
						|
                # Allow attributes we want to be able to update through
 | 
						|
                # art.update, art.set, setp.
 | 
						|
                if k == "axes":
 | 
						|
                    ret.append(setattr(self, k, v))
 | 
						|
                else:
 | 
						|
                    func = getattr(self, f"set_{k}", None)
 | 
						|
                    if not callable(func):
 | 
						|
                        raise AttributeError(
 | 
						|
                            errfmt.format(cls=type(self), prop_name=k),
 | 
						|
                            name=k)
 | 
						|
                    ret.append(func(v))
 | 
						|
        if ret:
 | 
						|
            self.pchanged()
 | 
						|
            self.stale = True
 | 
						|
        return ret
 | 
						|
 | 
						|
    def update(self, props):
 | 
						|
        """
 | 
						|
        Update this artist's properties from the dict *props*.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        props : dict
 | 
						|
        """
 | 
						|
        return self._update_props(
 | 
						|
            props, "{cls.__name__!r} object has no property {prop_name!r}")
 | 
						|
 | 
						|
    def _internal_update(self, kwargs):
 | 
						|
        """
 | 
						|
        Update artist properties without prenormalizing them, but generating
 | 
						|
        errors as if calling `set`.
 | 
						|
 | 
						|
        The lack of prenormalization is to maintain backcompatibility.
 | 
						|
        """
 | 
						|
        return self._update_props(
 | 
						|
            kwargs, "{cls.__name__}.set() got an unexpected keyword argument "
 | 
						|
            "{prop_name!r}")
 | 
						|
 | 
						|
    def set(self, **kwargs):
 | 
						|
        # docstring and signature are auto-generated via
 | 
						|
        # Artist._update_set_signature_and_docstring() at the end of the
 | 
						|
        # module.
 | 
						|
        return self._internal_update(cbook.normalize_kwargs(kwargs, self))
 | 
						|
 | 
						|
    @contextlib.contextmanager
 | 
						|
    def _cm_set(self, **kwargs):
 | 
						|
        """
 | 
						|
        `.Artist.set` context-manager that restores original values at exit.
 | 
						|
        """
 | 
						|
        orig_vals = {k: getattr(self, f"get_{k}")() for k in kwargs}
 | 
						|
        try:
 | 
						|
            self.set(**kwargs)
 | 
						|
            yield
 | 
						|
        finally:
 | 
						|
            self.set(**orig_vals)
 | 
						|
 | 
						|
    def findobj(self, match=None, include_self=True):
 | 
						|
        """
 | 
						|
        Find artist objects.
 | 
						|
 | 
						|
        Recursively find all `.Artist` instances contained in the artist.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        match
 | 
						|
            A filter criterion for the matches. This can be
 | 
						|
 | 
						|
            - *None*: Return all objects contained in artist.
 | 
						|
            - A function with signature ``def match(artist: Artist) -> bool``.
 | 
						|
              The result will only contain artists for which the function
 | 
						|
              returns *True*.
 | 
						|
            - A class instance: e.g., `.Line2D`. The result will only contain
 | 
						|
              artists of this class or its subclasses (``isinstance`` check).
 | 
						|
 | 
						|
        include_self : bool
 | 
						|
            Include *self* in the list to be checked for a match.
 | 
						|
 | 
						|
        Returns
 | 
						|
        -------
 | 
						|
        list of `.Artist`
 | 
						|
 | 
						|
        """
 | 
						|
        if match is None:  # always return True
 | 
						|
            def matchfunc(x):
 | 
						|
                return True
 | 
						|
        elif isinstance(match, type) and issubclass(match, Artist):
 | 
						|
            def matchfunc(x):
 | 
						|
                return isinstance(x, match)
 | 
						|
        elif callable(match):
 | 
						|
            matchfunc = match
 | 
						|
        else:
 | 
						|
            raise ValueError('match must be None, a matplotlib.artist.Artist '
 | 
						|
                             'subclass, or a callable')
 | 
						|
 | 
						|
        artists = reduce(operator.iadd,
 | 
						|
                         [c.findobj(matchfunc) for c in self.get_children()], [])
 | 
						|
        if include_self and matchfunc(self):
 | 
						|
            artists.append(self)
 | 
						|
        return artists
 | 
						|
 | 
						|
    def get_cursor_data(self, event):
 | 
						|
        """
 | 
						|
        Return the cursor data for a given event.
 | 
						|
 | 
						|
        .. note::
 | 
						|
            This method is intended to be overridden by artist subclasses.
 | 
						|
            As an end-user of Matplotlib you will most likely not call this
 | 
						|
            method yourself.
 | 
						|
 | 
						|
        Cursor data can be used by Artists to provide additional context
 | 
						|
        information for a given event. The default implementation just returns
 | 
						|
        *None*.
 | 
						|
 | 
						|
        Subclasses can override the method and return arbitrary data. However,
 | 
						|
        when doing so, they must ensure that `.format_cursor_data` can convert
 | 
						|
        the data to a string representation.
 | 
						|
 | 
						|
        The only current use case is displaying the z-value of an `.AxesImage`
 | 
						|
        in the status bar of a plot window, while moving the mouse.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        event : `~matplotlib.backend_bases.MouseEvent`
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        format_cursor_data
 | 
						|
 | 
						|
        """
 | 
						|
        return None
 | 
						|
 | 
						|
    def format_cursor_data(self, data):
 | 
						|
        """
 | 
						|
        Return a string representation of *data*.
 | 
						|
 | 
						|
        .. note::
 | 
						|
            This method is intended to be overridden by artist subclasses.
 | 
						|
            As an end-user of Matplotlib you will most likely not call this
 | 
						|
            method yourself.
 | 
						|
 | 
						|
        The default implementation converts ints and floats and arrays of ints
 | 
						|
        and floats into a comma-separated string enclosed in square brackets,
 | 
						|
        unless the artist has an associated colorbar, in which case scalar
 | 
						|
        values are formatted using the colorbar's formatter.
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        get_cursor_data
 | 
						|
        """
 | 
						|
        if np.ndim(data) == 0 and hasattr(self, "_format_cursor_data_override"):
 | 
						|
            # workaround for ScalarMappable to be able to define its own
 | 
						|
            # format_cursor_data(). See ScalarMappable._format_cursor_data_override
 | 
						|
            # for details.
 | 
						|
            return self._format_cursor_data_override(data)
 | 
						|
        else:
 | 
						|
            try:
 | 
						|
                data[0]
 | 
						|
            except (TypeError, IndexError):
 | 
						|
                data = [data]
 | 
						|
            data_str = ', '.join(f'{item:0.3g}' for item in data
 | 
						|
                                 if isinstance(item, Number))
 | 
						|
            return "[" + data_str + "]"
 | 
						|
 | 
						|
    def get_mouseover(self):
 | 
						|
        """
 | 
						|
        Return whether this artist is queried for custom context information
 | 
						|
        when the mouse cursor moves over it.
 | 
						|
        """
 | 
						|
        return self._mouseover
 | 
						|
 | 
						|
    def set_mouseover(self, mouseover):
 | 
						|
        """
 | 
						|
        Set whether this artist is queried for custom context information when
 | 
						|
        the mouse cursor moves over it.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        mouseover : bool
 | 
						|
 | 
						|
        See Also
 | 
						|
        --------
 | 
						|
        get_cursor_data
 | 
						|
        .ToolCursorPosition
 | 
						|
        .NavigationToolbar2
 | 
						|
        """
 | 
						|
        self._mouseover = bool(mouseover)
 | 
						|
        ax = self.axes
 | 
						|
        if ax:
 | 
						|
            if self._mouseover:
 | 
						|
                ax._mouseover_set.add(self)
 | 
						|
            else:
 | 
						|
                ax._mouseover_set.discard(self)
 | 
						|
 | 
						|
    mouseover = property(get_mouseover, set_mouseover)  # backcompat.
 | 
						|
 | 
						|
 | 
						|
def _get_tightbbox_for_layout_only(obj, *args, **kwargs):
 | 
						|
    """
 | 
						|
    Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
 | 
						|
    *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
 | 
						|
    when encountering third-party subclasses that do not support it.
 | 
						|
    """
 | 
						|
    try:
 | 
						|
        return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
 | 
						|
    except TypeError:
 | 
						|
        return obj.get_tightbbox(*args, **kwargs)
 | 
						|
 | 
						|
 | 
						|
class ArtistInspector:
 | 
						|
    """
 | 
						|
    A helper class to inspect an `~matplotlib.artist.Artist` and return
 | 
						|
    information about its settable properties and their current values.
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, o):
 | 
						|
        r"""
 | 
						|
        Initialize the artist inspector with an `Artist` or an iterable of
 | 
						|
        `Artist`\s.  If an iterable is used, we assume it is a homogeneous
 | 
						|
        sequence (all `Artist`\s are of the same type) and it is your
 | 
						|
        responsibility to make sure this is so.
 | 
						|
        """
 | 
						|
        if not isinstance(o, Artist):
 | 
						|
            if np.iterable(o):
 | 
						|
                o = list(o)
 | 
						|
                if len(o):
 | 
						|
                    o = o[0]
 | 
						|
 | 
						|
        self.oorig = o
 | 
						|
        if not isinstance(o, type):
 | 
						|
            o = type(o)
 | 
						|
        self.o = o
 | 
						|
 | 
						|
        self.aliasd = self.get_aliases()
 | 
						|
 | 
						|
    def get_aliases(self):
 | 
						|
        """
 | 
						|
        Get a dict mapping property fullnames to sets of aliases for each alias
 | 
						|
        in the :class:`~matplotlib.artist.ArtistInspector`.
 | 
						|
 | 
						|
        e.g., for lines::
 | 
						|
 | 
						|
          {'markerfacecolor': {'mfc'},
 | 
						|
           'linewidth'      : {'lw'},
 | 
						|
          }
 | 
						|
        """
 | 
						|
        names = [name for name in dir(self.o)
 | 
						|
                 if name.startswith(('set_', 'get_'))
 | 
						|
                    and callable(getattr(self.o, name))]
 | 
						|
        aliases = {}
 | 
						|
        for name in names:
 | 
						|
            func = getattr(self.o, name)
 | 
						|
            if not self.is_alias(func):
 | 
						|
                continue
 | 
						|
            propname = re.search(f"`({name[:4]}.*)`",  # get_.*/set_.*
 | 
						|
                                 inspect.getdoc(func)).group(1)
 | 
						|
            aliases.setdefault(propname[4:], set()).add(name[4:])
 | 
						|
        return aliases
 | 
						|
 | 
						|
    _get_valid_values_regex = re.compile(
 | 
						|
        r"\n\s*(?:\.\.\s+)?ACCEPTS:\s*((?:.|\n)*?)(?:$|(?:\n\n))"
 | 
						|
    )
 | 
						|
 | 
						|
    def get_valid_values(self, attr):
 | 
						|
        """
 | 
						|
        Get the legal arguments for the setter associated with *attr*.
 | 
						|
 | 
						|
        This is done by querying the docstring of the setter for a line that
 | 
						|
        begins with "ACCEPTS:" or ".. ACCEPTS:", and then by looking for a
 | 
						|
        numpydoc-style documentation for the setter's first argument.
 | 
						|
        """
 | 
						|
 | 
						|
        name = 'set_%s' % attr
 | 
						|
        if not hasattr(self.o, name):
 | 
						|
            raise AttributeError(f'{self.o} has no function {name}')
 | 
						|
        func = getattr(self.o, name)
 | 
						|
 | 
						|
        if hasattr(func, '_kwarg_doc'):
 | 
						|
            return func._kwarg_doc
 | 
						|
 | 
						|
        docstring = inspect.getdoc(func)
 | 
						|
        if docstring is None:
 | 
						|
            return 'unknown'
 | 
						|
 | 
						|
        if docstring.startswith('Alias for '):
 | 
						|
            return None
 | 
						|
 | 
						|
        match = self._get_valid_values_regex.search(docstring)
 | 
						|
        if match is not None:
 | 
						|
            return re.sub("\n *", " ", match.group(1))
 | 
						|
 | 
						|
        # Much faster than list(inspect.signature(func).parameters)[1],
 | 
						|
        # although barely relevant wrt. matplotlib's total import time.
 | 
						|
        param_name = func.__code__.co_varnames[1]
 | 
						|
        # We could set the presence * based on whether the parameter is a
 | 
						|
        # varargs (it can't be a varkwargs) but it's not really worth it.
 | 
						|
        match = re.search(fr"(?m)^ *\*?{param_name} : (.+)", docstring)
 | 
						|
        if match:
 | 
						|
            return match.group(1)
 | 
						|
 | 
						|
        return 'unknown'
 | 
						|
 | 
						|
    def _replace_path(self, source_class):
 | 
						|
        """
 | 
						|
        Changes the full path to the public API path that is used
 | 
						|
        in sphinx. This is needed for links to work.
 | 
						|
        """
 | 
						|
        replace_dict = {'_base._AxesBase': 'Axes',
 | 
						|
                        '_axes.Axes': 'Axes'}
 | 
						|
        for key, value in replace_dict.items():
 | 
						|
            source_class = source_class.replace(key, value)
 | 
						|
        return source_class
 | 
						|
 | 
						|
    def get_setters(self):
 | 
						|
        """
 | 
						|
        Get the attribute strings with setters for object.
 | 
						|
 | 
						|
        For example, for a line, return ``['markerfacecolor', 'linewidth',
 | 
						|
        ....]``.
 | 
						|
        """
 | 
						|
        setters = []
 | 
						|
        for name in dir(self.o):
 | 
						|
            if not name.startswith('set_'):
 | 
						|
                continue
 | 
						|
            func = getattr(self.o, name)
 | 
						|
            if (not callable(func)
 | 
						|
                    or self.number_of_parameters(func) < 2
 | 
						|
                    or self.is_alias(func)):
 | 
						|
                continue
 | 
						|
            setters.append(name[4:])
 | 
						|
        return setters
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    @cache
 | 
						|
    def number_of_parameters(func):
 | 
						|
        """Return number of parameters of the callable *func*."""
 | 
						|
        return len(inspect.signature(func).parameters)
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    @cache
 | 
						|
    def is_alias(method):
 | 
						|
        """
 | 
						|
        Return whether the object *method* is an alias for another method.
 | 
						|
        """
 | 
						|
 | 
						|
        ds = inspect.getdoc(method)
 | 
						|
        if ds is None:
 | 
						|
            return False
 | 
						|
 | 
						|
        return ds.startswith('Alias for ')
 | 
						|
 | 
						|
    def aliased_name(self, s):
 | 
						|
        """
 | 
						|
        Return 'PROPNAME or alias' if *s* has an alias, else return 'PROPNAME'.
 | 
						|
 | 
						|
        For example, for the line markerfacecolor property, which has an
 | 
						|
        alias, return 'markerfacecolor or mfc' and for the transform
 | 
						|
        property, which does not, return 'transform'.
 | 
						|
        """
 | 
						|
        aliases = ''.join(' or %s' % x for x in sorted(self.aliasd.get(s, [])))
 | 
						|
        return s + aliases
 | 
						|
 | 
						|
    _NOT_LINKABLE = {
 | 
						|
        # A set of property setter methods that are not available in our
 | 
						|
        # current docs. This is a workaround used to prevent trying to link
 | 
						|
        # these setters which would lead to "target reference not found"
 | 
						|
        # warnings during doc build.
 | 
						|
        'matplotlib.image._ImageBase.set_alpha',
 | 
						|
        'matplotlib.image._ImageBase.set_array',
 | 
						|
        'matplotlib.image._ImageBase.set_data',
 | 
						|
        'matplotlib.image._ImageBase.set_filternorm',
 | 
						|
        'matplotlib.image._ImageBase.set_filterrad',
 | 
						|
        'matplotlib.image._ImageBase.set_interpolation',
 | 
						|
        'matplotlib.image._ImageBase.set_interpolation_stage',
 | 
						|
        'matplotlib.image._ImageBase.set_resample',
 | 
						|
        'matplotlib.text._AnnotationBase.set_annotation_clip',
 | 
						|
    }
 | 
						|
 | 
						|
    def aliased_name_rest(self, s, target):
 | 
						|
        """
 | 
						|
        Return 'PROPNAME or alias' if *s* has an alias, else return 'PROPNAME',
 | 
						|
        formatted for reST.
 | 
						|
 | 
						|
        For example, for the line markerfacecolor property, which has an
 | 
						|
        alias, return 'markerfacecolor or mfc' and for the transform
 | 
						|
        property, which does not, return 'transform'.
 | 
						|
        """
 | 
						|
        # workaround to prevent "reference target not found"
 | 
						|
        if target in self._NOT_LINKABLE:
 | 
						|
            return f'``{s}``'
 | 
						|
 | 
						|
        aliases = ''.join(
 | 
						|
            f' or :meth:`{a} <{target}>`' for a in sorted(self.aliasd.get(s, [])))
 | 
						|
        return f':meth:`{s} <{target}>`{aliases}'
 | 
						|
 | 
						|
    def pprint_setters(self, prop=None, leadingspace=2):
 | 
						|
        """
 | 
						|
        If *prop* is *None*, return a list of strings of all settable
 | 
						|
        properties and their valid values.
 | 
						|
 | 
						|
        If *prop* is not *None*, it is a valid property name and that
 | 
						|
        property will be returned as a string of property : valid
 | 
						|
        values.
 | 
						|
        """
 | 
						|
        if leadingspace:
 | 
						|
            pad = ' ' * leadingspace
 | 
						|
        else:
 | 
						|
            pad = ''
 | 
						|
        if prop is not None:
 | 
						|
            accepts = self.get_valid_values(prop)
 | 
						|
            return f'{pad}{prop}: {accepts}'
 | 
						|
 | 
						|
        lines = []
 | 
						|
        for prop in sorted(self.get_setters()):
 | 
						|
            accepts = self.get_valid_values(prop)
 | 
						|
            name = self.aliased_name(prop)
 | 
						|
            lines.append(f'{pad}{name}: {accepts}')
 | 
						|
        return lines
 | 
						|
 | 
						|
    def pprint_setters_rest(self, prop=None, leadingspace=4):
 | 
						|
        """
 | 
						|
        If *prop* is *None*, return a list of reST-formatted strings of all
 | 
						|
        settable properties and their valid values.
 | 
						|
 | 
						|
        If *prop* is not *None*, it is a valid property name and that
 | 
						|
        property will be returned as a string of "property : valid"
 | 
						|
        values.
 | 
						|
        """
 | 
						|
        if leadingspace:
 | 
						|
            pad = ' ' * leadingspace
 | 
						|
        else:
 | 
						|
            pad = ''
 | 
						|
        if prop is not None:
 | 
						|
            accepts = self.get_valid_values(prop)
 | 
						|
            return f'{pad}{prop}: {accepts}'
 | 
						|
 | 
						|
        prop_and_qualnames = []
 | 
						|
        for prop in sorted(self.get_setters()):
 | 
						|
            # Find the parent method which actually provides the docstring.
 | 
						|
            for cls in self.o.__mro__:
 | 
						|
                method = getattr(cls, f"set_{prop}", None)
 | 
						|
                if method and method.__doc__ is not None:
 | 
						|
                    break
 | 
						|
            else:  # No docstring available.
 | 
						|
                method = getattr(self.o, f"set_{prop}")
 | 
						|
            prop_and_qualnames.append(
 | 
						|
                (prop, f"{method.__module__}.{method.__qualname__}"))
 | 
						|
 | 
						|
        names = [self.aliased_name_rest(prop, target)
 | 
						|
                 .replace('_base._AxesBase', 'Axes')
 | 
						|
                 .replace('_axes.Axes', 'Axes')
 | 
						|
                 for prop, target in prop_and_qualnames]
 | 
						|
        accepts = [self.get_valid_values(prop)
 | 
						|
                   for prop, _ in prop_and_qualnames]
 | 
						|
 | 
						|
        col0_len = max(len(n) for n in names)
 | 
						|
        col1_len = max(len(a) for a in accepts)
 | 
						|
        table_formatstr = pad + '   ' + '=' * col0_len + '   ' + '=' * col1_len
 | 
						|
 | 
						|
        return [
 | 
						|
            '',
 | 
						|
            pad + '.. table::',
 | 
						|
            pad + '   :class: property-table',
 | 
						|
            '',
 | 
						|
            table_formatstr,
 | 
						|
            pad + '   ' + 'Property'.ljust(col0_len)
 | 
						|
            + '   ' + 'Description'.ljust(col1_len),
 | 
						|
            table_formatstr,
 | 
						|
            *[pad + '   ' + n.ljust(col0_len) + '   ' + a.ljust(col1_len)
 | 
						|
              for n, a in zip(names, accepts)],
 | 
						|
            table_formatstr,
 | 
						|
            '',
 | 
						|
        ]
 | 
						|
 | 
						|
    def properties(self):
 | 
						|
        """Return a dictionary mapping property name -> value."""
 | 
						|
        o = self.oorig
 | 
						|
        getters = [name for name in dir(o)
 | 
						|
                   if name.startswith('get_') and callable(getattr(o, name))]
 | 
						|
        getters.sort()
 | 
						|
        d = {}
 | 
						|
        for name in getters:
 | 
						|
            func = getattr(o, name)
 | 
						|
            if self.is_alias(func):
 | 
						|
                continue
 | 
						|
            try:
 | 
						|
                with warnings.catch_warnings():
 | 
						|
                    warnings.simplefilter('ignore')
 | 
						|
                    val = func()
 | 
						|
            except Exception:
 | 
						|
                continue
 | 
						|
            else:
 | 
						|
                d[name[4:]] = val
 | 
						|
        return d
 | 
						|
 | 
						|
    def pprint_getters(self):
 | 
						|
        """Return the getters and actual values as list of strings."""
 | 
						|
        lines = []
 | 
						|
        for name, val in sorted(self.properties().items()):
 | 
						|
            if getattr(val, 'shape', ()) != () and len(val) > 6:
 | 
						|
                s = str(val[:6]) + '...'
 | 
						|
            else:
 | 
						|
                s = str(val)
 | 
						|
            s = s.replace('\n', ' ')
 | 
						|
            if len(s) > 50:
 | 
						|
                s = s[:50] + '...'
 | 
						|
            name = self.aliased_name(name)
 | 
						|
            lines.append(f'    {name} = {s}')
 | 
						|
        return lines
 | 
						|
 | 
						|
 | 
						|
def getp(obj, property=None):
 | 
						|
    """
 | 
						|
    Return the value of an `.Artist`'s *property*, or print all of them.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    obj : `~matplotlib.artist.Artist`
 | 
						|
        The queried artist; e.g., a `.Line2D`, a `.Text`, or an `~.axes.Axes`.
 | 
						|
 | 
						|
    property : str or None, default: None
 | 
						|
        If *property* is 'somename', this function returns
 | 
						|
        ``obj.get_somename()``.
 | 
						|
 | 
						|
        If it's None (or unset), it *prints* all gettable properties from
 | 
						|
        *obj*.  Many properties have aliases for shorter typing, e.g. 'lw' is
 | 
						|
        an alias for 'linewidth'.  In the output, aliases and full property
 | 
						|
        names will be listed as:
 | 
						|
 | 
						|
          property or alias = value
 | 
						|
 | 
						|
        e.g.:
 | 
						|
 | 
						|
          linewidth or lw = 2
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    setp
 | 
						|
    """
 | 
						|
    if property is None:
 | 
						|
        insp = ArtistInspector(obj)
 | 
						|
        ret = insp.pprint_getters()
 | 
						|
        print('\n'.join(ret))
 | 
						|
        return
 | 
						|
    return getattr(obj, 'get_' + property)()
 | 
						|
 | 
						|
# alias
 | 
						|
get = getp
 | 
						|
 | 
						|
 | 
						|
def setp(obj, *args, file=None, **kwargs):
 | 
						|
    """
 | 
						|
    Set one or more properties on an `.Artist`, or list allowed values.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    obj : `~matplotlib.artist.Artist` or list of `.Artist`
 | 
						|
        The artist(s) whose properties are being set or queried.  When setting
 | 
						|
        properties, all artists are affected; when querying the allowed values,
 | 
						|
        only the first instance in the sequence is queried.
 | 
						|
 | 
						|
        For example, two lines can be made thicker and red with a single call:
 | 
						|
 | 
						|
        >>> x = arange(0, 1, 0.01)
 | 
						|
        >>> lines = plot(x, sin(2*pi*x), x, sin(4*pi*x))
 | 
						|
        >>> setp(lines, linewidth=2, color='r')
 | 
						|
 | 
						|
    file : file-like, default: `sys.stdout`
 | 
						|
        Where `setp` writes its output when asked to list allowed values.
 | 
						|
 | 
						|
        >>> with open('output.log') as file:
 | 
						|
        ...     setp(line, file=file)
 | 
						|
 | 
						|
        The default, ``None``, means `sys.stdout`.
 | 
						|
 | 
						|
    *args, **kwargs
 | 
						|
        The properties to set.  The following combinations are supported:
 | 
						|
 | 
						|
        - Set the linestyle of a line to be dashed:
 | 
						|
 | 
						|
          >>> line, = plot([1, 2, 3])
 | 
						|
          >>> setp(line, linestyle='--')
 | 
						|
 | 
						|
        - Set multiple properties at once:
 | 
						|
 | 
						|
          >>> setp(line, linewidth=2, color='r')
 | 
						|
 | 
						|
        - List allowed values for a line's linestyle:
 | 
						|
 | 
						|
          >>> setp(line, 'linestyle')
 | 
						|
          linestyle: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
 | 
						|
 | 
						|
        - List all properties that can be set, and their allowed values:
 | 
						|
 | 
						|
          >>> setp(line)
 | 
						|
          agg_filter: a filter function, ...
 | 
						|
          [long output listing omitted]
 | 
						|
 | 
						|
        `setp` also supports MATLAB style string/value pairs.  For example, the
 | 
						|
        following are equivalent:
 | 
						|
 | 
						|
        >>> setp(lines, 'linewidth', 2, 'color', 'r')  # MATLAB style
 | 
						|
        >>> setp(lines, linewidth=2, color='r')        # Python style
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    getp
 | 
						|
    """
 | 
						|
 | 
						|
    if isinstance(obj, Artist):
 | 
						|
        objs = [obj]
 | 
						|
    else:
 | 
						|
        objs = list(cbook.flatten(obj))
 | 
						|
 | 
						|
    if not objs:
 | 
						|
        return
 | 
						|
 | 
						|
    insp = ArtistInspector(objs[0])
 | 
						|
 | 
						|
    if not kwargs and len(args) < 2:
 | 
						|
        if args:
 | 
						|
            print(insp.pprint_setters(prop=args[0]), file=file)
 | 
						|
        else:
 | 
						|
            print('\n'.join(insp.pprint_setters()), file=file)
 | 
						|
        return
 | 
						|
 | 
						|
    if len(args) % 2:
 | 
						|
        raise ValueError('The set args must be string, value pairs')
 | 
						|
 | 
						|
    funcvals = dict(zip(args[::2], args[1::2]))
 | 
						|
    ret = [o.update(funcvals) for o in objs] + [o.set(**kwargs) for o in objs]
 | 
						|
    return list(cbook.flatten(ret))
 | 
						|
 | 
						|
 | 
						|
def kwdoc(artist):
 | 
						|
    r"""
 | 
						|
    Inspect an `~matplotlib.artist.Artist` class (using `.ArtistInspector`) and
 | 
						|
    return information about its settable properties and their current values.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    artist : `~matplotlib.artist.Artist` or an iterable of `Artist`\s
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    str
 | 
						|
        The settable properties of *artist*, as plain text if
 | 
						|
        :rc:`docstring.hardcopy` is False and as a rst table (intended for
 | 
						|
        use in Sphinx) if it is True.
 | 
						|
    """
 | 
						|
    ai = ArtistInspector(artist)
 | 
						|
    return ('\n'.join(ai.pprint_setters_rest(leadingspace=4))
 | 
						|
            if mpl.rcParams['docstring.hardcopy'] else
 | 
						|
            'Properties:\n' + '\n'.join(ai.pprint_setters(leadingspace=4)))
 | 
						|
 | 
						|
# We defer this to the end of them module, because it needs ArtistInspector
 | 
						|
# to be defined.
 | 
						|
Artist._update_set_signature_and_docstring()
 |