Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Made it so that PatchCollection uses the hatch of the patch in the co…
…llection.

PatchCollection will currently ignore hatches of the provided patches, only allowing a hatch passed as a keyword into the constructor. If match_original is true, we now keep the hatch of the first patch provided in the collection. Additionally, the hatchcolor is determined by the edge color, so we will only pass the edgecolors of the patches to the Collection if the edgecolor is not blank - its default color of [0, 0, 0, 0]. This ensures that the hatch will use its default of black in the case where no edgecolor of the patches was ever set.
  • Loading branch information
hhalwan committed Apr 9, 2022
commit 43f16a010b550bbd6fcb53776e25c66430a63512
19 changes: 14 additions & 5 deletions lib/matplotlib/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -1808,9 +1808,10 @@ def __init__(self, patches, match_original=False, **kwargs):

*match_original*
If True, use the colors and linewidths of the original
patches. If False, new colors may be assigned by
providing the standard collection arguments, facecolor,
edgecolor, linewidths, norm or cmap.
patches. Also use the hatch of the first patch provided.
If False, new colors may be assigned by providing the
standard collection arguments, facecolor, edgecolor,
linewidths, norm or cmap.

If any of *edgecolors*, *facecolors*, *linewidths*, *antialiaseds* are
None, they default to their `.rcParams` patch setting, in sequence
Expand All @@ -1827,12 +1828,20 @@ def determine_facecolor(patch):
if patch.get_fill():
return patch.get_facecolor()
return [0, 0, 0, 0]

def is_default(c):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This in only the default default (that is, there is a set of rcparams which will cause this to be miss. Looking at

def _set_edgecolor(self, color):
set_hatch_color = True
if color is None:
if (mpl.rcParams['patch.force_edgecolor'] or
not self._fill or self._edge_default):
color = mpl.rcParams['patch.edgecolor']
else:
color = 'none'
set_hatch_color = False
self._edgecolor = colors.to_rgba(color, self._alpha)
if set_hatch_color:
self._hatch_color = self._edgecolor
self.stale = True
def set_edgecolor(self, color):
"""
Set the patch edge color.
Parameters
----------
color : color or None
"""
self._original_edgecolor = color
self._set_edgecolor(color)
we have some private state (which we are allowed to use inside of Matplotlib) to check this. In this case, I think it is better to check p._original_edgecolor and if None either re-implement the default logic or pass in None here (if we can) and let the next layer down deal with resolving the default behavior.

return mcolors.same_color([0, 0, 0, 0], c)
kwargs['facecolors'] = [determine_facecolor(p) for p in patches]
kwargs['edgecolors'] = [p.get_edgecolor() for p in patches]
edgecolors = [p.get_edgecolor() for p in patches]
# Since the hatch color is updated when the edge color
# is updated, we will ignore the edge color if it is blank (the
# default of [0, 0, 0, 0]).
if not all(is_default(c) for c in edgecolors):
kwargs['edgecolors'] = edgecolors
kwargs['linewidths'] = [p.get_linewidth() for p in patches]
kwargs['linestyles'] = [p.get_linestyle() for p in patches]
kwargs['antialiaseds'] = [p.get_antialiased() for p in patches]
if patches:
kwargs['hatch'] = patches[0].get_hatch()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to only pick of the hatch from the first patch, then we should warn or raise if we are going to ignore the rest of the hatches.

@hhalwan hhalwan Apr 12, 2022 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? If that's true, it would be impossible to make a collection of multiple patches w/ hatches without getting a warning.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I was not clear. The check should be "are all of the hatches the same? if so carry on, if not fail!" As implemented if the user passes in

[
        mpatches.Rectangle((0, 0), 0.2, .2, hatch="/"),
        mpatches.Rectangle((0.4, 0.4), 0.2, .2, hatch="\\")
]

then the first hatch will be used for both and we will silently drop the "\\" on the second one!


super().__init__(**kwargs)

Expand Down