diff --git a/doc/api/artist_api.rst b/doc/api/artist_api.rst index a6f39d39f6b0..99b467d8cb6d 100644 --- a/doc/api/artist_api.rst +++ b/doc/api/artist_api.rst @@ -30,18 +30,18 @@ Interactive :nosignatures: Artist.add_callback - Artist.format_cursor_data - Artist.get_contains + Artist.remove_callback + Artist.pchanged Artist.get_cursor_data - Artist.get_picker + Artist.format_cursor_data Artist.mouseover - Artist.pchanged + Artist.contains + Artist.set_contains + Artist.get_contains Artist.pick Artist.pickable - Artist.remove_callback - Artist.set_contains Artist.set_picker - Artist.contains + Artist.get_picker Margins and Autoscaling ----------------------- @@ -59,12 +59,12 @@ Clipping :toctree: _as_gen :nosignatures: - Artist.get_clip_box + Artist.set_clip_on Artist.get_clip_on - Artist.get_clip_path Artist.set_clip_box - Artist.set_clip_on + Artist.get_clip_box Artist.set_clip_path + Artist.get_clip_path Bulk Properties --------------- @@ -86,29 +86,29 @@ Drawing :nosignatures: Artist.draw - Artist.get_animated Artist.set_animated + Artist.get_animated - Artist.get_agg_filter - + Artist.set_alpha Artist.get_alpha + Artist.set_snap Artist.get_snap + Artist.set_visible Artist.get_visible + Artist.zorder + Artist.set_zorder Artist.get_zorder Artist.set_agg_filter - Artist.set_alpha Artist.set_sketch_params - Artist.set_snap - Artist.get_rasterized Artist.get_sketch_params - Artist.set_path_effects Artist.set_rasterized - Artist.zorder - Artist.set_visible - Artist.set_zorder - Artist.get_window_extent + Artist.get_rasterized + Artist.set_path_effects Artist.get_path_effects + + Artist.get_agg_filter + Artist.get_window_extent Artist.get_transformed_clip_path_and_affine Figure and Axes @@ -164,12 +164,12 @@ Metadata :toctree: _as_gen :nosignatures: - Artist.get_gid - Artist.get_label Artist.set_gid + Artist.get_gid Artist.set_label - Artist.get_url + Artist.get_label Artist.set_url + Artist.get_url Artist.aname Stale diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index 86d653137841..184253791b3c 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -68,8 +68,9 @@ def _stale_axes_callback(self, val): class Artist(object): """ - Abstract base class for someone who renders into a - :class:`FigureCanvas`. + Abstract base class for objects that render into a FigureCanvas. + + Typically, all visible elements in a figure are subclasses of Artist. """ @property @cbook.deprecated("3.1") @@ -128,15 +129,14 @@ def __getstate__(self): 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 - :meth:`matplotlib.axes.Axes.draw_idle`. Call - :meth:`matplotlib.axes.Axes.relim` to update the axes limits - if desired. + 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: :meth:`~matplotlib.axes.Axes.relim` will not see - collections even if the collection was added to axes with - *autolim* = True. + 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. """ @@ -173,15 +173,18 @@ def remove(self): # TODO: add legend support def have_units(self): - 'Return *True* if units are set on the *x* or *y* axes' + """Return *True* if units are set on the *x* or *y* axes.""" ax = self.axes if ax is None or ax.xaxis is None: return False return ax.xaxis.have_units() or ax.yaxis.have_units() def convert_xunits(self, x): - """For artists in an axes, if the xaxis has units support, - convert *x* using xaxis unit type + """ + Convert *x* using the unit type of the xaxis. + + If the artist is not in 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: @@ -189,8 +192,11 @@ def convert_xunits(self, x): return ax.xaxis.convert_units(x) def convert_yunits(self, y): - """For artists in an axes, if the yaxis has units support, - convert *y* using yaxis unit type + """ + Convert *y* using the unit type of the yaxis. + + If the artist is not in 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: @@ -199,10 +205,7 @@ def convert_yunits(self, y): @property def axes(self): - """ - The :class:`~matplotlib.axes.Axes` instance the artist - resides in, or *None*. - """ + """The `~.axes.Axes` instance the artist resides in, or *None*.""" return self._axes @axes.setter @@ -220,8 +223,8 @@ def axes(self, new_axes): @property def stale(self): """ - If the artist is 'stale' and needs to be re-drawn for the output to - match the internal state of the artist. + 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 @@ -267,10 +270,9 @@ def get_tightbbox(self, renderer): Returns ------- - bbox : `.BboxBase` - containing the bounding box (in figure pixel co-ordinates). + bbox : `.BBox` + The enclosing bounding box (in figure pixel co-ordinates). """ - bbox = self.get_window_extent(renderer) if self.get_clip_on(): clip_box = self.get_clip_box() @@ -284,11 +286,28 @@ def get_tightbbox(self, renderer): def add_callback(self, func): """ - Adds a callback function that will be called whenever one of - the :class:`Artist`'s properties changes. + Add a callback function that will be called whenever one of the + `.Artist`'s properties changes. - Returns an *id* that is useful for removing the callback with - :meth:`remove_callback` later. + 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 + ------- + oid : 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 """ oid = self._oid self._propobservers[oid] = func @@ -297,13 +316,11 @@ def add_callback(self, func): def remove_callback(self, oid): """ - Remove a callback based on its *id*. - - .. seealso:: - - :meth:`add_callback` - For adding callbacks + Remove a callback based on its observer id. + See Also + -------- + add_callback """ try: del self._propobservers[oid] @@ -312,16 +329,23 @@ def remove_callback(self, oid): def pchanged(self): """ - Fire an event when property changed, calling all of the - registered callbacks. + Call all of the registered callbacks. + + This function is triggered internally when a property is changed. + + See Also + -------- + add_callback + remove_callback """ for oid, func in self._propobservers.items(): func(self) def is_transform_set(self): """ - Returns *True* if :class:`Artist` has a transform explicitly - set. + Return whether the Artist has an explicitly set transform. + + This is *True* after `.set_transform` has been called. """ return self._transformSet @@ -339,10 +363,7 @@ def set_transform(self, t): self.stale = True def get_transform(self): - """ - Return the :class:`~matplotlib.transforms.Transform` - instance used by this artist. - """ + """Return the `.Transform` instance used by this artist.""" if self._transform is None: self._transform = IdentityTransform() elif (not isinstance(self._transform, Transform) @@ -370,18 +391,28 @@ def hitlist(self, event): return L def get_children(self): - """ - Return a list of the child :class:`Artist`s this - :class:`Artist` contains. - """ + r"""Return a list of the child `.Artist`\s this `.Artist` contains.""" return [] def contains(self, mouseevent): """Test whether the artist contains the mouse event. - Returns the truth value and a dictionary of artist specific details of - selection, such as which points are contained in the pick radius. See - individual artists for details. + 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. + + See Also + -------- + set_contains, get_contains """ if callable(self._contains): return self._contains(self, mouseevent) @@ -390,40 +421,61 @@ def contains(self, mouseevent): def set_contains(self, picker): """ - Replace the contains test used by this artist. The new picker - should be a callable function which determines whether the - artist is hit by the mouse event:: + Define a custom contains test for the artist. - hit, props = picker(artist, mouseevent) - - If the mouse event is over the artist, return *hit* = *True* - and *props* is a dictionary of properties you want returned - with the contains test. + The provided callable replaces the default `.contains` method + of the artist. Parameters ---------- picker : callable + A custom picker function to evaluate if an event is within the + artist. The function must have the signature:: + + def contains(artist: Artist, event: MouseEvent) -> bool, dict + + that returns: + + - a bool indicating if the event is within the artist + - a dict of additional information. The dict should at least + return the same information as the default ``contains()`` + implementation of the respective artist, but may provide + additional information. """ self._contains = picker def get_contains(self): """ - Return the _contains test used by the artist, or *None* for default. + Return the custom contains function of the artist if set, or *None*. + + See Also + -------- + set_contains """ return self._contains def pickable(self): - 'Return *True* if :class:`Artist` is pickable.' + """ + Return whether the artist is pickable. + + See Also + -------- + set_picker, get_picker, pick + """ return (self.figure is not None and self.figure.canvas is not None and self._picker is not None) def pick(self, mouseevent): """ - Process pick event + Process a pick event. + + Each child artist will fire a pick event if *mouseevent* is over + the artist and the artist has picker set. - each child artist will fire a pick event if *mouseevent* is over - the artist and the artist has picker set + See Also + -------- + set_picker, get_picker, pickable """ # Pick self if self.pickable(): @@ -451,42 +503,50 @@ def pick(self, mouseevent): def set_picker(self, picker): """ - Set the epsilon for picking used by this artist + Define the picking behavior of the artist. - *picker* can be one of the following: + Parameters + ---------- + picker : None or bool or float or callable + This can be one of the following: - * *None*: picking is disabled for this artist (default) + - *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 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 it's 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 float: If picker is a number it is interpreted as an + epsilon tolerance in points and the artist will fire + off an event if it's 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:: + - 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) + 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. + 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. - Parameters - ---------- - picker : None or bool or float or callable """ self._picker = picker def get_picker(self): - """Return the picker object used by this artist.""" + """ + Return the picking behavior of the artist. + + The possible values are described in `.set_picker`. + + See Also + -------- + set_picker, pickable, pick + """ return self._picker @cbook.deprecated("2.2", "artist.figure is not None") @@ -495,12 +555,12 @@ def is_figure_set(self): return self.figure is not None def get_url(self): - """Returns the url.""" + """Return the url.""" return self._url def set_url(self, url): """ - Sets the url for the artist. + Set the url for the artist. Parameters ---------- @@ -509,12 +569,12 @@ def set_url(self, url): self._url = url def get_gid(self): - """Returns the group id.""" + """Return the group id.""" return self._gid def set_gid(self, gid): """ - Sets the (group) id for the artist. + Set the (group) id for the artist. Parameters ---------- @@ -524,16 +584,9 @@ def set_gid(self, gid): def get_snap(self): """ - Returns the snap setting which may be: - - * True: snap vertices to the nearest pixel center - - * False: leave vertices as-is + Returns the snap setting. - * None: (auto) If the path contains only rectilinear line - segments, round to the nearest pixel center - - Only supported by the Agg and MacOSX backends. + See `.set_snap` for details. """ if rcParams['path.snap']: return self._snap @@ -542,20 +595,28 @@ def get_snap(self): def set_snap(self, snap): """ - Sets the snap setting which may be: - - * True: snap vertices to the nearest pixel center + Set the snapping behavior. - * False: leave vertices as-is + 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. - * None: (auto) If the path contains only rectilinear line - segments, round to the nearest pixel center - - Only supported by the Agg and MacOSX backends. + 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 @@ -566,19 +627,17 @@ def get_sketch_params(self): Returns ------- - sketch_params : tuple or `None` + sketch_params : tuple or None A 3-tuple with the following elements: - * `scale`: The amplitude of the wiggle perpendicular to the - source line. + - *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. - * `length`: The length of the wiggle along the line. - - * `randomness`: The scale factor by which the length is - shrunken or expanded. - - May return `None` if no sketch parameters were set. + Returns *None* if no sketch parameters were set. """ return self._sketch @@ -725,11 +784,11 @@ def get_alpha(self): return self._alpha def get_visible(self): - "Return the artist's visiblity" + """Return the visiblity.""" return self._visible def get_animated(self): - "Return the artist's animated state" + """Return the animated state.""" return self._animated def get_in_layout(self): @@ -744,15 +803,15 @@ def get_in_layout(self): return self._in_layout def get_clip_on(self): - 'Return whether artist uses clipping' + """Return whether the artist uses clipping.""" return self._clipon def get_clip_box(self): - 'Return artist clipbox' + """Return the clipbox.""" return self.clipbox def get_clip_path(self): - 'Return artist clip path' + """Return the clip path.""" return self._clippath def get_transformed_clip_path_and_affine(self): @@ -767,7 +826,7 @@ def get_transformed_clip_path_and_affine(self): def set_clip_on(self, b): """ - Set whether artist uses clipping. + Set whether the artist uses clipping. When False artists will be visible out side of the axes which can lead to unexpected results. @@ -897,7 +956,7 @@ def set_in_layout(self, in_layout): def update(self, props): """ - Update this artist's properties from the dictionary *prop*. + Update this artist's properties from the dictionary *props*. """ def _update_property(self, k, v): """Sorting out how to update property (setter or setattr). @@ -934,12 +993,12 @@ def _update_property(self, k, v): return ret def get_label(self): - """Get the label used for this artist in the legend.""" + """Return the label used for this artist in the legend.""" return self._label def set_label(self, s): """ - Set the label to *s* for auto legend. + Set a label that will be displayed in the legend. Parameters ---------- @@ -1013,9 +1072,7 @@ def update_from(self, other): self.stale = True def properties(self): - """ - return a dictionary mapping property name -> value for all Artist props - """ + """Return a dictionary of all the properties of the artist.""" return ArtistInspector(self).properties() def set(self, **kwargs): @@ -1031,20 +1088,26 @@ def findobj(self, match=None, include_self=True): """ Find artist objects. - Recursively find all :class:`~matplotlib.artist.Artist` instances - contained in self. - - *match* can be + Recursively find all `.Artist` instances contained in the artist. - - None: return all objects contained in artist. + Parameters + ---------- + match + A filter criterion for the matches. This can be - - function with signature ``boolean = match(artist)`` - used to filter matches + - *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). - - class instance: e.g., Line2D. Only return artists of class type. + include_self : bool + Include *self* in the list to be checked for a match. - If *include_self* is True (default), include self in the list to be - checked for a match. + Returns + ------- + artists : list of `.Artist` """ if match is None: # always return True diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index 55368cdd4559..4e4aedb21944 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -438,14 +438,16 @@ def contains(self, mouseevent): Parameters ---------- - mouseevent : `matplotlib.backend_bases.MouseEvent`. + mouseevent : `matplotlib.backend_bases.MouseEvent` Returns ------- contains : bool Whether any values are within the radius. - ``{'ind': pointlist}`` - Where *pointlist* is the set of points within the radius. + details : dict + A dictionary ``{'ind': pointlist}``, where *pointlist* is a + list of points of the line that are within the pickradius around + the event position. TODO: sort returned indices by distance """