From 97e5042d35cd5c4651c6d53773409d60662560e2 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 20 Sep 2021 18:31:14 +0200 Subject: [PATCH] Fix DATA_PARAMETER_PLACEHOLDER interpolation for quiver&contour{,f}. The docstring must be set (which we do using docstring.dedent_interpd) before the decoration with _preprocess_data(). While we're at it, replace kw by kwargs in quiver/barbs. --- lib/matplotlib/axes/_axes.py | 58 ++--- lib/matplotlib/contour.py | 411 ++++++++++++++++++----------------- lib/matplotlib/pyplot.py | 14 +- lib/matplotlib/quiver.py | 2 + 4 files changed, 245 insertions(+), 240 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index cef0f8c3c88d..1e9e2fb12c6c 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4966,43 +4966,39 @@ def arrow(self, x, y, dx, dy, **kwargs): return a @docstring.copy(mquiver.QuiverKey.__init__) - def quiverkey(self, Q, X, Y, U, label, **kw): - qk = mquiver.QuiverKey(Q, X, Y, U, label, **kw) + def quiverkey(self, Q, X, Y, U, label, **kwargs): + qk = mquiver.QuiverKey(Q, X, Y, U, label, **kwargs) self.add_artist(qk) return qk # Handle units for x and y, if they've been passed - def _quiver_units(self, args, kw): + def _quiver_units(self, args, kwargs): if len(args) > 3: x, y = args[0:2] - x, y = self._process_unit_info([("x", x), ("y", y)], kw) + x, y = self._process_unit_info([("x", x), ("y", y)], kwargs) return (x, y) + args[2:] return args # args can by a combination if X, Y, U, V, C and all should be replaced @_preprocess_data() - def quiver(self, *args, **kw): + @docstring.dedent_interpd + def quiver(self, *args, **kwargs): + """%(quiver_doc)s""" # Make sure units are handled for x and y values - args = self._quiver_units(args, kw) - - q = mquiver.Quiver(self, *args, **kw) - + args = self._quiver_units(args, kwargs) + q = mquiver.Quiver(self, *args, **kwargs) self.add_collection(q, autolim=True) self._request_autoscale_view() return q - quiver.__doc__ = mquiver.Quiver.quiver_doc # args can be some combination of X, Y, U, V, C and all should be replaced @_preprocess_data() @docstring.dedent_interpd - def barbs(self, *args, **kw): - """ - %(barbs_doc)s - """ + def barbs(self, *args, **kwargs): + """%(barbs_doc)s""" # Make sure units are handled for x and y values - args = self._quiver_units(args, kw) - - b = mquiver.Barbs(self, *args, **kw) + args = self._quiver_units(args, kwargs) + b = mquiver.Barbs(self, *args, **kwargs) self.add_collection(b, autolim=True) self._request_autoscale_view() return b @@ -6308,32 +6304,36 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None, return ret @_preprocess_data() + @docstring.dedent_interpd def contour(self, *args, **kwargs): - kwargs['filled'] = False - contours = mcontour.QuadContourSet(self, *args, **kwargs) - self._request_autoscale_view() - return contours - contour.__doc__ = """ + """ Plot contour lines. Call signature:: contour([X, Y,] Z, [levels], **kwargs) - """ + mcontour.QuadContourSet._contour_doc - - @_preprocess_data() - def contourf(self, *args, **kwargs): - kwargs['filled'] = True + %(contour_doc)s + """ + kwargs['filled'] = False contours = mcontour.QuadContourSet(self, *args, **kwargs) self._request_autoscale_view() return contours - contourf.__doc__ = """ + + @_preprocess_data() + @docstring.dedent_interpd + def contourf(self, *args, **kwargs): + """ Plot filled contours. Call signature:: contourf([X, Y,] Z, [levels], **kwargs) - """ + mcontour.QuadContourSet._contour_doc + %(contour_doc)s + """ + kwargs['filled'] = True + contours = mcontour.QuadContourSet(self, *args, **kwargs) + self._request_autoscale_view() + return contours def clabel(self, CS, levels=None, **kwargs): """ diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 4d124ce8c57c..15f44aa91692 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1574,215 +1574,216 @@ def _initialize_x_y(self, z): y = y[::-1] return np.meshgrid(x, y) - _contour_doc = """ - `.contour` and `.contourf` draw contour lines and filled contours, - respectively. Except as noted, function signatures and return values - are the same for both versions. - Parameters - ---------- - X, Y : array-like, optional - The coordinates of the values in *Z*. - - *X* and *Y* must both be 2D with the same shape as *Z* (e.g. - created via `numpy.meshgrid`), or they must both be 1-D such - that ``len(X) == N`` is the number of columns in *Z* and - ``len(Y) == M`` is the number of rows in *Z*. - - If not given, they are assumed to be integer indices, i.e. - ``X = range(N)``, ``Y = range(M)``. - - Z : (M, N) array-like - The height values over which the contour is drawn. - - levels : int or array-like, optional - Determines the number and positions of the contour lines / regions. - - If an int *n*, use `~matplotlib.ticker.MaxNLocator`, which tries - to automatically choose no more than *n+1* "nice" contour levels - between *vmin* and *vmax*. +docstring.interpd.update(contour_doc=""" +`.contour` and `.contourf` draw contour lines and filled contours, +respectively. Except as noted, function signatures and return values +are the same for both versions. - If array-like, draw contour lines at the specified levels. - The values must be in increasing order. - - Returns - ------- - `~.contour.QuadContourSet` - - Other Parameters - ---------------- - corner_mask : bool, default: :rc:`contour.corner_mask` - Enable/disable corner masking, which only has an effect if *Z* is - a masked array. If ``False``, any quad touching a masked point is - masked out. If ``True``, only the triangular corners of quads - nearest those points are always masked out, other triangular - corners comprising three unmasked points are contoured as usual. - - colors : color string or sequence of colors, optional - The colors of the levels, i.e. the lines for `.contour` and the - areas for `.contourf`. - - The sequence is cycled for the levels in ascending order. If the - sequence is shorter than the number of levels, it's repeated. - - As a shortcut, single color strings may be used in place of - one-element lists, i.e. ``'red'`` instead of ``['red']`` to color - all levels with the same color. This shortcut does only work for - color strings, not for other ways of specifying colors. - - By default (value *None*), the colormap specified by *cmap* - will be used. - - alpha : float, default: 1 - The alpha blending value, between 0 (transparent) and 1 (opaque). - - cmap : str or `.Colormap`, default: :rc:`image.cmap` - A `.Colormap` instance or registered colormap name. The colormap - maps the level values to colors. - - If both *colors* and *cmap* are given, an error is raised. - - norm : `~matplotlib.colors.Normalize`, optional - If a colormap is used, the `.Normalize` instance scales the level - values to the canonical colormap range [0, 1] for mapping to - colors. If not given, the default linear scaling is used. - - vmin, vmax : float, optional - If not *None*, either or both of these values will be supplied to - the `.Normalize` instance, overriding the default color scaling - based on *levels*. - - origin : {*None*, 'upper', 'lower', 'image'}, default: None - Determines the orientation and exact position of *Z* by specifying - the position of ``Z[0, 0]``. This is only relevant, if *X*, *Y* - are not given. - - - *None*: ``Z[0, 0]`` is at X=0, Y=0 in the lower left corner. - - 'lower': ``Z[0, 0]`` is at X=0.5, Y=0.5 in the lower left corner. - - 'upper': ``Z[0, 0]`` is at X=N+0.5, Y=0.5 in the upper left - corner. - - 'image': Use the value from :rc:`image.origin`. - - extent : (x0, x1, y0, y1), optional - If *origin* is not *None*, then *extent* is interpreted as in - `.imshow`: it gives the outer pixel boundaries. In this case, the - position of Z[0, 0] is the center of the pixel, not a corner. If - *origin* is *None*, then (*x0*, *y0*) is the position of Z[0, 0], - and (*x1*, *y1*) is the position of Z[-1, -1]. - - This argument is ignored if *X* and *Y* are specified in the call - to contour. - - locator : ticker.Locator subclass, optional - The locator is used to determine the contour levels if they - are not given explicitly via *levels*. - Defaults to `~.ticker.MaxNLocator`. - - extend : {'neither', 'both', 'min', 'max'}, default: 'neither' - Determines the ``contourf``-coloring of values that are outside the - *levels* range. - - If 'neither', values outside the *levels* range are not colored. - If 'min', 'max' or 'both', color the values below, above or below - and above the *levels* range. - - Values below ``min(levels)`` and above ``max(levels)`` are mapped - to the under/over values of the `.Colormap`. Note that most - colormaps do not have dedicated colors for these by default, so - that the over and under values are the edge values of the colormap. - You may want to set these values explicitly using - `.Colormap.set_under` and `.Colormap.set_over`. - - .. note:: - - An existing `.QuadContourSet` does not get notified if - properties of its colormap are changed. Therefore, an explicit - call `.QuadContourSet.changed()` is needed after modifying the - colormap. The explicit call can be left out, if a colorbar is - assigned to the `.QuadContourSet` because it internally calls - `.QuadContourSet.changed()`. - - Example:: - - x = np.arange(1, 10) - y = x.reshape(-1, 1) - h = x * y - - cs = plt.contourf(h, levels=[10, 30, 50], - colors=['#808080', '#A0A0A0', '#C0C0C0'], extend='both') - cs.cmap.set_over('red') - cs.cmap.set_under('blue') - cs.changed() - - xunits, yunits : registered units, optional - Override axis units by specifying an instance of a - :class:`matplotlib.units.ConversionInterface`. - - antialiased : bool, optional - Enable antialiasing, overriding the defaults. For - filled contours, the default is *True*. For line contours, - it is taken from :rc:`lines.antialiased`. - - nchunk : int >= 0, optional - If 0, no subdivision of the domain. Specify a positive integer to - divide the domain into subdomains of *nchunk* by *nchunk* quads. - Chunking reduces the maximum length of polygons generated by the - contouring algorithm which reduces the rendering workload passed - on to the backend and also requires slightly less RAM. It can - however introduce rendering artifacts at chunk boundaries depending - on the backend, the *antialiased* flag and value of *alpha*. - - linewidths : float or array-like, default: :rc:`contour.linewidth` - *Only applies to* `.contour`. - - The line width of the contour lines. - - If a number, all levels will be plotted with this linewidth. - - If a sequence, the levels in ascending order will be plotted with - the linewidths in the order specified. - - If None, this falls back to :rc:`lines.linewidth`. - - linestyles : {*None*, 'solid', 'dashed', 'dashdot', 'dotted'}, optional - *Only applies to* `.contour`. - - If *linestyles* is *None*, the default is 'solid' unless the lines - are monochrome. In that case, negative contours will take their - linestyle from :rc:`contour.negative_linestyle` setting. - - *linestyles* can also be an iterable of the above strings - specifying a set of linestyles to be used. If this - iterable is shorter than the number of contour levels - it will be repeated as necessary. - - hatches : list[str], optional - *Only applies to* `.contourf`. - - A list of cross hatch patterns to use on the filled areas. - If None, no hatching will be added to the contour. - Hatching is supported in the PostScript, PDF, SVG and Agg - backends only. - - data : indexable object, optional - DATA_PARAMETER_PLACEHOLDER +Parameters +---------- +X, Y : array-like, optional + The coordinates of the values in *Z*. + + *X* and *Y* must both be 2D with the same shape as *Z* (e.g. + created via `numpy.meshgrid`), or they must both be 1-D such + that ``len(X) == N`` is the number of columns in *Z* and + ``len(Y) == M`` is the number of rows in *Z*. + + If not given, they are assumed to be integer indices, i.e. + ``X = range(N)``, ``Y = range(M)``. + +Z : (M, N) array-like + The height values over which the contour is drawn. + +levels : int or array-like, optional + Determines the number and positions of the contour lines / regions. + + If an int *n*, use `~matplotlib.ticker.MaxNLocator`, which tries + to automatically choose no more than *n+1* "nice" contour levels + between *vmin* and *vmax*. + + If array-like, draw contour lines at the specified levels. + The values must be in increasing order. + +Returns +------- +`~.contour.QuadContourSet` + +Other Parameters +---------------- +corner_mask : bool, default: :rc:`contour.corner_mask` + Enable/disable corner masking, which only has an effect if *Z* is + a masked array. If ``False``, any quad touching a masked point is + masked out. If ``True``, only the triangular corners of quads + nearest those points are always masked out, other triangular + corners comprising three unmasked points are contoured as usual. + +colors : color string or sequence of colors, optional + The colors of the levels, i.e. the lines for `.contour` and the + areas for `.contourf`. + + The sequence is cycled for the levels in ascending order. If the + sequence is shorter than the number of levels, it's repeated. + + As a shortcut, single color strings may be used in place of + one-element lists, i.e. ``'red'`` instead of ``['red']`` to color + all levels with the same color. This shortcut does only work for + color strings, not for other ways of specifying colors. + + By default (value *None*), the colormap specified by *cmap* + will be used. + +alpha : float, default: 1 + The alpha blending value, between 0 (transparent) and 1 (opaque). + +cmap : str or `.Colormap`, default: :rc:`image.cmap` + A `.Colormap` instance or registered colormap name. The colormap + maps the level values to colors. + + If both *colors* and *cmap* are given, an error is raised. + +norm : `~matplotlib.colors.Normalize`, optional + If a colormap is used, the `.Normalize` instance scales the level + values to the canonical colormap range [0, 1] for mapping to + colors. If not given, the default linear scaling is used. + +vmin, vmax : float, optional + If not *None*, either or both of these values will be supplied to + the `.Normalize` instance, overriding the default color scaling + based on *levels*. + +origin : {*None*, 'upper', 'lower', 'image'}, default: None + Determines the orientation and exact position of *Z* by specifying + the position of ``Z[0, 0]``. This is only relevant, if *X*, *Y* + are not given. + + - *None*: ``Z[0, 0]`` is at X=0, Y=0 in the lower left corner. + - 'lower': ``Z[0, 0]`` is at X=0.5, Y=0.5 in the lower left corner. + - 'upper': ``Z[0, 0]`` is at X=N+0.5, Y=0.5 in the upper left + corner. + - 'image': Use the value from :rc:`image.origin`. + +extent : (x0, x1, y0, y1), optional + If *origin* is not *None*, then *extent* is interpreted as in + `.imshow`: it gives the outer pixel boundaries. In this case, the + position of Z[0, 0] is the center of the pixel, not a corner. If + *origin* is *None*, then (*x0*, *y0*) is the position of Z[0, 0], + and (*x1*, *y1*) is the position of Z[-1, -1]. + + This argument is ignored if *X* and *Y* are specified in the call + to contour. + +locator : ticker.Locator subclass, optional + The locator is used to determine the contour levels if they + are not given explicitly via *levels*. + Defaults to `~.ticker.MaxNLocator`. + +extend : {'neither', 'both', 'min', 'max'}, default: 'neither' + Determines the ``contourf``-coloring of values that are outside the + *levels* range. + + If 'neither', values outside the *levels* range are not colored. + If 'min', 'max' or 'both', color the values below, above or below + and above the *levels* range. + + Values below ``min(levels)`` and above ``max(levels)`` are mapped + to the under/over values of the `.Colormap`. Note that most + colormaps do not have dedicated colors for these by default, so + that the over and under values are the edge values of the colormap. + You may want to set these values explicitly using + `.Colormap.set_under` and `.Colormap.set_over`. + + .. note:: + + An existing `.QuadContourSet` does not get notified if + properties of its colormap are changed. Therefore, an explicit + call `.QuadContourSet.changed()` is needed after modifying the + colormap. The explicit call can be left out, if a colorbar is + assigned to the `.QuadContourSet` because it internally calls + `.QuadContourSet.changed()`. + + Example:: + + x = np.arange(1, 10) + y = x.reshape(-1, 1) + h = x * y + + cs = plt.contourf(h, levels=[10, 30, 50], + colors=['#808080', '#A0A0A0', '#C0C0C0'], extend='both') + cs.cmap.set_over('red') + cs.cmap.set_under('blue') + cs.changed() + +xunits, yunits : registered units, optional + Override axis units by specifying an instance of a + :class:`matplotlib.units.ConversionInterface`. + +antialiased : bool, optional + Enable antialiasing, overriding the defaults. For + filled contours, the default is *True*. For line contours, + it is taken from :rc:`lines.antialiased`. + +nchunk : int >= 0, optional + If 0, no subdivision of the domain. Specify a positive integer to + divide the domain into subdomains of *nchunk* by *nchunk* quads. + Chunking reduces the maximum length of polygons generated by the + contouring algorithm which reduces the rendering workload passed + on to the backend and also requires slightly less RAM. It can + however introduce rendering artifacts at chunk boundaries depending + on the backend, the *antialiased* flag and value of *alpha*. + +linewidths : float or array-like, default: :rc:`contour.linewidth` + *Only applies to* `.contour`. + + The line width of the contour lines. + + If a number, all levels will be plotted with this linewidth. + + If a sequence, the levels in ascending order will be plotted with + the linewidths in the order specified. + + If None, this falls back to :rc:`lines.linewidth`. + +linestyles : {*None*, 'solid', 'dashed', 'dashdot', 'dotted'}, optional + *Only applies to* `.contour`. + + If *linestyles* is *None*, the default is 'solid' unless the lines + are monochrome. In that case, negative contours will take their + linestyle from :rc:`contour.negative_linestyle` setting. + + *linestyles* can also be an iterable of the above strings + specifying a set of linestyles to be used. If this + iterable is shorter than the number of contour levels + it will be repeated as necessary. + +hatches : list[str], optional + *Only applies to* `.contourf`. + + A list of cross hatch patterns to use on the filled areas. + If None, no hatching will be added to the contour. + Hatching is supported in the PostScript, PDF, SVG and Agg + backends only. + +data : indexable object, optional + DATA_PARAMETER_PLACEHOLDER - Notes - ----- - 1. `.contourf` differs from the MATLAB version in that it does not draw - the polygon edges. To draw edges, add line contours with calls to - `.contour`. +Notes +----- +1. `.contourf` differs from the MATLAB version in that it does not draw + the polygon edges. To draw edges, add line contours with calls to + `.contour`. - 2. `.contourf` fills intervals that are closed at the top; that is, for - boundaries *z1* and *z2*, the filled region is:: +2. `.contourf` fills intervals that are closed at the top; that is, for + boundaries *z1* and *z2*, the filled region is:: - z1 < Z <= z2 + z1 < Z <= z2 - except for the lowest interval, which is closed on both sides (i.e. - it includes the lowest value). + except for the lowest interval, which is closed on both sides (i.e. + it includes the lowest value). - 3. `.contour` and `.contourf` use a `marching squares - `_ algorithm to - compute contour locations. More information can be found in - the source ``src/_contour.h``. - """ +3. `.contour` and `.contourf` use a `marching squares + `_ algorithm to + compute contour locations. More information can be found in + the source ``src/_contour.h``. +""") diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index a203984aacec..a7deb9a5e78b 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -2387,9 +2387,10 @@ def bar( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.barbs) -def barbs(*args, data=None, **kw): +def barbs(*args, data=None, **kwargs): return gca().barbs( - *args, **({"data": data} if data is not None else {}), **kw) + *args, **({"data": data} if data is not None else {}), + **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @@ -2779,17 +2780,18 @@ def psd( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.quiver) -def quiver(*args, data=None, **kw): +def quiver(*args, data=None, **kwargs): __ret = gca().quiver( - *args, **({"data": data} if data is not None else {}), **kw) + *args, **({"data": data} if data is not None else {}), + **kwargs) sci(__ret) return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.quiverkey) -def quiverkey(Q, X, Y, U, label, **kw): - return gca().quiverkey(Q, X, Y, U, label, **kw) +def quiverkey(Q, X, Y, U, label, **kwargs): + return gca().quiverkey(Q, X, Y, U, label, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. diff --git a/lib/matplotlib/quiver.py b/lib/matplotlib/quiver.py index 112f93dc3de7..c7e665086ca9 100644 --- a/lib/matplotlib/quiver.py +++ b/lib/matplotlib/quiver.py @@ -203,6 +203,8 @@ .Axes.quiverkey : Add a key to a quiver plot. """ % docstring.interpd.params +docstring.interpd.update(quiver_doc=_quiver_doc) + class QuiverKey(martist.Artist): """Labelled arrow for use as a quiver plot scale key."""