Skip to content

Commit

Permalink
Merge pull request #24470 from story645/pie
Browse files Browse the repository at this point in the history
[ENH] hatch keyword for pie + some pie documentation
  • Loading branch information
jklymak committed Jan 11, 2023
2 parents bff0f32 + d0e1236 commit a483e85
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 24 deletions.
18 changes: 18 additions & 0 deletions doc/users/next_whats_new/pie_hatch.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
``hatch`` parameter for pie
-------------------------------------------

`~matplotlib.axes.Axes.pie` now accepts a *hatch* keyword that takes as input
a hatch or list of hatches:

.. plot::
:include-source: true
:alt: Two pie charts, identified as ax1 and ax2, both have a small blue slice, a medium orange slice, and a large green slice. ax1 has a dot hatching on the small slice, a small open circle hatching on the medium slice, and a large open circle hatching on the large slice. ax2 has the same large open circle with a dot hatch on every slice.

fig, (ax1, ax2) = plt.subplots(ncols=2)
x = [10, 30, 60]

ax1.pie(x, hatch=['.', 'o', 'O'])
ax2.pie(x, hatch='.O')

ax1.set_title("hatch=['.', 'o', 'O']")
ax2.set_title("hatch='.O'")
57 changes: 35 additions & 22 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3075,7 +3075,7 @@ def pie(self, x, explode=None, labels=None, colors=None,
autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
startangle=0, radius=1, counterclock=True,
wedgeprops=None, textprops=None, center=(0, 0),
frame=False, rotatelabels=False, *, normalize=True):
frame=False, rotatelabels=False, *, normalize=True, hatch=None):
"""
Plot a pie chart.
Expand All @@ -3101,29 +3101,34 @@ def pie(self, x, explode=None, labels=None, colors=None,
A sequence of colors through which the pie chart will cycle. If
*None*, will use the colors in the currently active cycle.
hatch : str or list, default: None
Hatching pattern applied to all pie wedges or sequence of patterns
through which the chart will cycle. For a list of valid patterns,
see :doc:`/gallery/shapes_and_collections/hatch_style_reference`.
.. versionadded:: 3.7
autopct : None or str or callable, default: None
If not *None*, is a string or function used to label the wedges
with their numeric value. The label will be placed inside the
wedge. If it is a format string, the label will be ``fmt % pct``.
If it is a function, it will be called.
If not *None*, *autopct* is a string or function used to label the
wedges with their numeric value. The label will be placed inside
the wedge. If *autopct* is a format string, the label will be
``fmt % pct``. If *autopct* is a function, then it will be called.
pctdistance : float, default: 0.6
The ratio between the center of each pie slice and the start of
the text generated by *autopct*. Ignored if *autopct* is *None*.
The relative distance along the radius at which the the text
generated by *autopct* is drawn. To draw the text outside the pie,
set *pctdistance* > 1. This parameter is ignored if *autopct* is
``None``.
labeldistance : float or None, default: 1.1
The relative distance along the radius at which the labels are
drawn. To draw the labels inside the pie, set *labeldistance* < 1.
If set to ``None``, labels are not drawn but are still stored for
use in `.legend`.
shadow : bool, default: False
Draw a shadow beneath the pie.
normalize : bool, default: True
When *True*, always make a full pie by normalizing x so that
``sum(x) == 1``. *False* makes a partial pie if ``sum(x) <= 1``
and raises a `ValueError` for ``sum(x) > 1``.
labeldistance : float or None, default: 1.1
The radial distance at which the pie labels are drawn.
If set to ``None``, label are not drawn, but are stored for use in
``legend()``
startangle : float, default: 0 degrees
The angle by which the start of the pie is rotated,
counterclockwise from the x-axis.
Expand All @@ -3135,11 +3140,11 @@ def pie(self, x, explode=None, labels=None, colors=None,
Specify fractions direction, clockwise or counterclockwise.
wedgeprops : dict, default: None
Dict of arguments passed to the wedge objects making the pie.
For example, you can pass in ``wedgeprops = {'linewidth': 3}``
to set the width of the wedge border lines equal to 3.
For more details, look at the doc/arguments of the wedge object.
By default, ``clip_on=False``.
Dict of arguments passed to each `.patches.Wedge` of the pie.
For example, ``wedgeprops = {'linewidth': 3}`` sets the width of
the wedge border lines equal to 3. By default, ``clip_on=False``.
When there is a conflict between these properties and other
keywords, properties passed to *wedgeprops* take precedence.
textprops : dict, default: None
Dict of arguments to pass to the text objects.
Expand All @@ -3153,6 +3158,11 @@ def pie(self, x, explode=None, labels=None, colors=None,
rotatelabels : bool, default: False
Rotate each label to the angle of the corresponding slice if true.
normalize : bool, default: True
When *True*, always make a full pie by normalizing x so that
``sum(x) == 1``. *False* makes a partial pie if ``sum(x) <= 1``
and raises a `ValueError` for ``sum(x) > 1``.
data : indexable object, optional
DATA_PARAMETER_PLACEHOLDER
Expand Down Expand Up @@ -3207,6 +3217,8 @@ def pie(self, x, explode=None, labels=None, colors=None,
def get_next_color():
return next(color_cycle)

hatch_cycle = itertools.cycle(np.atleast_1d(hatch))

_api.check_isinstance(Number, radius=radius, startangle=startangle)
if radius <= 0:
raise ValueError(f'radius must be a positive number, not {radius}')
Expand All @@ -3233,6 +3245,7 @@ def get_next_color():
w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2),
360. * max(theta1, theta2),
facecolor=get_next_color(),
hatch=next(hatch_cycle),
clip_on=False,
label=label)
w.set(**wedgeprops)
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/pyplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2779,15 +2779,15 @@ def pie(
pctdistance=0.6, shadow=False, labeldistance=1.1,
startangle=0, radius=1, counterclock=True, wedgeprops=None,
textprops=None, center=(0, 0), frame=False,
rotatelabels=False, *, normalize=True, data=None):
rotatelabels=False, *, normalize=True, hatch=None, data=None):
return gca().pie(
x, explode=explode, labels=labels, colors=colors,
autopct=autopct, pctdistance=pctdistance, shadow=shadow,
labeldistance=labeldistance, startangle=startangle,
radius=radius, counterclock=counterclock,
wedgeprops=wedgeprops, textprops=textprops, center=center,
frame=frame, rotatelabels=rotatelabels, normalize=normalize,
**({"data": data} if data is not None else {}))
hatch=hatch, **({"data": data} if data is not None else {}))


# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
Expand Down
18 changes: 18 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5744,6 +5744,24 @@ def test_normalize_kwarg_pie():
assert abs(t2[0][-1].theta2 - 360.) > 1e-3


@check_figures_equal()
def test_pie_hatch_single(fig_test, fig_ref):
x = [0.3, 0.3, 0.1]
hatch = '+'
fig_test.subplots().pie(x, hatch=hatch)
wedges, _ = fig_ref.subplots().pie(x)
[w.set_hatch(hatch) for w in wedges]


@check_figures_equal()
def test_pie_hatch_multi(fig_test, fig_ref):
x = [0.3, 0.3, 0.1]
hatch = ['/', '+', '.']
fig_test.subplots().pie(x, hatch=hatch)
wedges, _ = fig_ref.subplots().pie(x)
[w.set_hatch(hp) for w, hp in zip(wedges, hatch)]


@image_comparison(['set_get_ticklabels.png'])
def test_set_get_ticklabels():
# test issue 2246
Expand Down

0 comments on commit a483e85

Please sign in to comment.