diff --git a/galleries/examples/event_handling/resample.py b/galleries/examples/event_handling/resample.py index a573552e800e..25661eb239b7 100644 --- a/galleries/examples/event_handling/resample.py +++ b/galleries/examples/event_handling/resample.py @@ -32,7 +32,8 @@ def __init__(self, xdata, y1data, y2data): def plot(self, ax): x, y1, y2 = self._downsample(self.origXData.min(), self.origXData.max()) (self.line,) = ax.plot(x, y1, 'o-') - self.poly_collection = ax.fill_between(x, y1, y2, step="pre", color="r") + self.poly_collection = ax.fill_between(x, y1, y2, + drawstyle="steps-pre", color="r") def _downsample(self, xstart, xend): # get the points in the view range diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 75dcb4653c52..769da11975a8 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -6074,7 +6074,7 @@ def fill(self, *args, data=None, **kwargs): def _fill_between_x_or_y( self, ind_dir, ind, dep1, dep2=0, *, - where=None, interpolate=False, step=None, **kwargs): + where=None, interpolate=False, drawstyle=None, step=None, **kwargs): # Common implementation between fill_between (*ind_dir*="x") and # fill_betweenx (*ind_dir*="y"). *ind* is the independent variable, # *dep* the dependent variable. The docstring below is interpolated @@ -6126,18 +6126,26 @@ def _fill_between_x_or_y( Setting *interpolate* to *True* will calculate the actual intersection point and extend the filled region up to this point. - step : {{'pre', 'post', 'mid'}}, optional - Define *step* if the filling should be a step function, - i.e. constant in between *{ind}*. The value determines where the + drawstyle : {{'steps', 'steps-pre', 'steps-post', 'steps-mid'}}, optional + Define *drawstyle* if the filling should be a step function, + i.e. constant in between *t*. The value determines where the step will occur: - - 'pre': The {dep} value is continued constantly to the left from - every *{ind}* position, i.e. the interval ``({ind}[i-1], {ind}[i]]`` - has the value ``{dep}[i]``. - - 'post': The y value is continued constantly to the right from - every *{ind}* position, i.e. the interval ``[{ind}[i], {ind}[i+1])`` - has the value ``{dep}[i]``. - - 'mid': Steps occur half-way between the *{ind}* positions. + - 'steps-pre' or 'steps': The f value is continued constantly to the left + from every *t* position, i.e. the interval ``(t[i-1], t[i]]`` has the + value ``f[i]``. + - 'steps-post': The y value is continued constantly to the right from + every *x* position, i.e. the interval ``[t[i], t[i+1])`` has the + value ``f[i]``. + - 'steps-mid': Steps occur half-way between the *t* positions. + + step : {{'pre', 'post', 'mid'}}, optional + + .. admonition:: Discouraged + + This parameter is discouraged in favor of *drawstyle*. The effect is the + same as the corresponding *drawstyle* value; e.g. ``step='pre'`` is the + same as ``drawstyle='steps-pre'``. Returns ------- @@ -6172,7 +6180,8 @@ def _fill_between_x_or_y( collection = mcoll.FillBetweenPolyCollection( ind_dir, ind, dep1, dep2, - where=where, interpolate=interpolate, step=step, **kwargs) + where=where, interpolate=interpolate, + drawstyle=drawstyle, step=step, **kwargs) self.add_collection(collection) return collection @@ -6183,10 +6192,11 @@ def _fill_between_process_units(self, ind_dir, dep_dir, ind, dep1, dep2, **kwarg [(ind_dir, ind), (dep_dir, dep1), (dep_dir, dep2)], kwargs)) def fill_between(self, x, y1, y2=0, where=None, interpolate=False, - step=None, **kwargs): + drawstyle=None, step=None, **kwargs): return self._fill_between_x_or_y( "x", x, y1, y2, - where=where, interpolate=interpolate, step=step, **kwargs) + where=where, interpolate=interpolate, drawstyle=drawstyle, step=step, + **kwargs) if _fill_between_x_or_y.__doc__: fill_between.__doc__ = _fill_between_x_or_y.__doc__.format( @@ -6197,10 +6207,11 @@ def fill_between(self, x, y1, y2=0, where=None, interpolate=False, replace_names=["x", "y1", "y2", "where"]) def fill_betweenx(self, y, x1, x2=0, where=None, - step=None, interpolate=False, **kwargs): + drawstyle=None, step=None, interpolate=False, **kwargs): return self._fill_between_x_or_y( "y", y, x1, x2, - where=where, interpolate=interpolate, step=step, **kwargs) + where=where, interpolate=interpolate, drawstyle=drawstyle, step=step, + **kwargs) if _fill_between_x_or_y.__doc__: fill_betweenx.__doc__ = _fill_between_x_or_y.__doc__.format( diff --git a/lib/matplotlib/axes/_axes.pyi b/lib/matplotlib/axes/_axes.pyi index b0871167dd75..a08b337b160a 100644 --- a/lib/matplotlib/axes/_axes.pyi +++ b/lib/matplotlib/axes/_axes.pyi @@ -26,7 +26,7 @@ from matplotlib.patches import Rectangle, FancyArrow, Polygon, StepPatch from matplotlib.quiver import Quiver, QuiverKey, Barbs from matplotlib.text import Annotation, Text from matplotlib.transforms import Transform -from matplotlib.typing import CoordsType +from matplotlib.typing import CoordsType, DrawStyleType import matplotlib.tri as mtri import matplotlib.table as mtable import matplotlib.stackplot as mstack @@ -483,6 +483,7 @@ class Axes(_AxesBase): y2: ArrayLike | float = ..., where: Sequence[bool] | None = ..., interpolate: bool = ..., + drawstyle: DrawStyleType | None = ..., step: Literal["pre", "post", "mid"] | None = ..., *, data=..., @@ -494,6 +495,7 @@ class Axes(_AxesBase): x1: ArrayLike | float, x2: ArrayLike | float = ..., where: Sequence[bool] | None = ..., + drawstyle: DrawStyleType | None = ..., step: Literal["pre", "post", "mid"] | None = ..., interpolate: bool = ..., *, diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index c9e04a70b356..5c25dfc49cc9 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -1384,7 +1384,7 @@ class FillBetweenPolyCollection(PolyCollection): """ def __init__( self, t_direction, t, f1, f2, *, - where=None, interpolate=False, step=None, **kwargs): + where=None, interpolate=False, drawstyle=None, step=None, **kwargs): """ Parameters ---------- @@ -1426,18 +1426,26 @@ def __init__( Setting *interpolate* to *True* will calculate the actual intersection point and extend the filled region up to this point. - step : {{'pre', 'post', 'mid'}}, optional - Define *step* if the filling should be a step function, + drawstyle : {'steps', 'steps-pre', 'steps-post', 'steps-mid'}, optional + Define *drawstyle* if the filling should be a step function, i.e. constant in between *t*. The value determines where the step will occur: - - 'pre': The f value is continued constantly to the left from - every *t* position, i.e. the interval ``(t[i-1], t[i]]`` has the + - 'steps-pre' or 'steps': The f value is continued constantly to the left + from every *t* position, i.e. the interval ``(t[i-1], t[i]]`` has the value ``f[i]``. - - 'post': The y value is continued constantly to the right from + - 'steps-post': The y value is continued constantly to the right from every *x* position, i.e. the interval ``[t[i], t[i+1])`` has the value ``f[i]``. - - 'mid': Steps occur half-way between the *t* positions. + - 'steps-mid': Steps occur half-way between the *t* positions. + + step : {{'pre', 'post', 'mid'}}, optional + + .. admonition:: Discouraged + + This parameter is discouraged in favor of *drawstyle*. The effect is the + same as the corresponding *drawstyle* value; e.g. ``step='pre'`` is the + same as ``drawstyle='steps-pre'``. **kwargs Forwarded to `.PolyCollection`. @@ -1448,7 +1456,14 @@ def __init__( """ self.t_direction = t_direction self._interpolate = interpolate - self._step = step + if drawstyle is not None and step is not None: + raise ValueError( + "Using drawstyle and step simultaneously is not supported as they " + "specify the same behavior. It is recommended the more modern " + "parameter drawstype for new code.") + self._drawstyle = drawstyle + if step is not None: + self._drawstyle = f"steps-{step}" verts = self._make_verts(t, f1, f2, where) super().__init__(verts, **kwargs) @@ -1572,8 +1587,8 @@ def _make_verts_for_region(self, t, f1, f2, idx0, idx1): t_slice = t[idx0:idx1] f1_slice = f1[idx0:idx1] f2_slice = f2[idx0:idx1] - if self._step is not None: - step_func = cbook.STEP_LOOKUP_MAP["steps-" + self._step] + if self._drawstyle is not None: + step_func = cbook.STEP_LOOKUP_MAP[self._drawstyle] t_slice, f1_slice, f2_slice = step_func(t_slice, f1_slice, f2_slice) if self._interpolate: diff --git a/lib/matplotlib/collections.pyi b/lib/matplotlib/collections.pyi index ecd969cfacc6..8eddd1584135 100644 --- a/lib/matplotlib/collections.pyi +++ b/lib/matplotlib/collections.pyi @@ -13,7 +13,7 @@ from .path import Path from .patches import Patch from .ticker import Locator, Formatter from .tri import Triangulation -from .typing import ColorType, LineStyleType, CapStyleType, JoinStyleType +from .typing import ColorType, DrawStyleType, LineStyleType, CapStyleType, JoinStyleType class Collection(colorizer.ColorizingArtist): def __init__( @@ -124,6 +124,7 @@ class FillBetweenPolyCollection(PolyCollection): *, where: Sequence[bool] | None = ..., interpolate: bool = ..., + drawstyle: DrawStyleType | None = ..., step: Literal["pre", "post", "mid"] | None = ..., **kwargs, ) -> None: ... diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 209593aee15e..fd578012c01e 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2709,15 +2709,15 @@ def test_stairs_fill(fig_test, fig_ref): # # Ref ref_axes = fig_ref.subplots(2, 2).flatten() - ref_axes[0].fill_between(bins, np.append(h, h[-1]), step='post', lw=0) + ref_axes[0].fill_between(bins, np.append(h, h[-1]), drawstyle='steps-post', lw=0) ref_axes[0].set_ylim(0, None) - ref_axes[1].fill_betweenx(bins, np.append(h, h[-1]), step='post', lw=0) + ref_axes[1].fill_betweenx(bins, np.append(h, h[-1]), drawstyle='steps-post', lw=0) ref_axes[1].set_xlim(0, None) ref_axes[2].fill_between(bins, np.append(h, h[-1]), - np.ones(len(h)+1)*bs, step='post', lw=0) + np.ones(len(h)+1)*bs, drawstyle='steps-post', lw=0) ref_axes[2].set_ylim(bs, None) ref_axes[3].fill_betweenx(bins, np.append(h, h[-1]), - np.ones(len(h)+1)*bs, step='post', lw=0) + np.ones(len(h)+1)*bs, drawstyle='steps-post', lw=0) ref_axes[3].set_xlim(bs, None)