-
-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Consolidate style parameter handling for plotting methods that call other plotting methods #30808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
lib/matplotlib/stackplot.py
Outdated
| if colors is None: | ||
| colors = [axes._get_lines.get_next_color() for _ in y] | ||
|
|
||
| kwargs['hatch'] = hatch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsure whether to do this or to remove hatch from the named parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really important, but I'm inclined to remove the explicit hatch parameter. The code is simpler without and there's no reason to name this explicitly, but not other style parameters.
cf5016c to
db8bfba
Compare
478264e to
ab39326
Compare
| ax.stackplot(x, y1, y2, | ||
| facecolor=['tab:red', 'tab:blue'], | ||
| edgecolor=['black', 'gray'], | ||
| linestyle=[':', '--'], | ||
| linewidth=[2, 3], | ||
| hatch=['.', '*']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it is structurally reasonable to also iterate edge-related parameters, I don't see a practical use case because the horizontal edges overlap, so that you get no clear picture / artifacts if they are different.
I would only do an example if we can come up with an example that may be actually used in practice.
We also don't have to showcase every aspect of the feature, e.g. different line widths should be extermely rare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played around a bit, but didn't produce a plot I actually liked, so just removed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rcomer FYI: There may be arcane use cases for line styling in stackplots, e.g. one could add small finite linewidths in #22393 to compensate antialiasing artifacts of adjacent polygon edges with the same color. So it is good to have these options. But this use case is too special to be mentioned as an example.
timhoffm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Comments are small suggestions.
| 'edgecolor': next(edgecolors), | ||
| 'facecolor': next(facecolors), | ||
| }) | ||
| kwargs.update(next(style_gen)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the correct translation keeping existing behavior.
Semi-OT: I'm wondering whether the behavior is logically correct: If patches is empty, we do not advance the style. This means depending on data contents the assignment of styles to datasets may vary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried removing the if not patch loop, and the only test that failed was this one
matplotlib/lib/matplotlib/tests/test_axes.py
Lines 5116 to 5122 in 89aa371
| def test_hist_unused_labels(): | |
| # When a list with one dataset and N elements is provided and N labels, ensure | |
| # that the first label is used for the dataset and all other labels are ignored | |
| fig, ax = plt.subplots() | |
| ax.hist([[1, 2, 3]], label=["values", "unused", "also unused"]) | |
| _, labels = ax.get_legend_handles_labels() | |
| assert labels == ["values"] |
So I think we are not checking for an empty patch sequence, but rather a None that was created by zip_longest if there are more labels than datasets. I also tried creating histograms where the data is outside the bin range for 'bar', 'step' and 'stepfilled' types, and they all gave my an artist back, so I think there is always a patch for a dataset.
This could all be a bit more obvious though, and I wondering why we don't just enforce that the number of labels is the same as the number of datasets (or perhaps n_labels <= n_datasets).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bar() and grouped_bar() require the same length:
matplotlib/lib/matplotlib/axes/_axes.py
Lines 2601 to 2603 in 4aeb773
| if len(patch_labels) != len(x): | |
| raise ValueError(f'number of labels ({len(patch_labels)}) ' | |
| f'does not match number of bars ({len(x)}).') |
matplotlib/lib/matplotlib/axes/_axes.py
Line 3331 in 89aa371
| assert len(labels) == num_datasets |
We should do the same for stackplot. If people do not want to label selected elements they should mark this explicitly in the list of labels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do the labels check and possible logic changes in patches as a follow-up.
27dd4d3 to
e2adeed
Compare
…ther plotting methods Co-authored-by: Ilakkuvaselvi Manoharan <ilakkmanoharan@gmail.com>
This reverts commit ab39326.
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
9b1838e to
11f44ee
Compare
PR summary
hist,stackplotandgrouped_barall loop through datasets and call another plotting method repeatedly. This means they have a common requirement to support sequences for parameters such as facecolor and hatch.histalready has handling for this, which I have factored out into a new helper function. I wasn't sure where to put the helper, so for now it is in its own new private module. I tried putting it in_axes,_apiandcbookbut all those options gave me circular import problems. The tests from #29719 are now reimagined as cheaper tests on the helper.Using the helper in
stackplotcloses #30804.Using the helper in
grouped_barcloses #30673, so this would supersede #30726. I copied thegrouped_bartest from there so added @ilakkmanoharan as a co-author. Note that, contrary to agreement in #30726, this does support a single hatch string forgrouped_bar. I still don't think a single hatch makes sense for any of these methods, but it is already supported for bothhistandstackplotand I do not feel strongly enough to deprecate the existing support or to throw a special case exception ingrouped_bar.grouped_barexample usage:Note the helper does not handle color because the methods already have bespoke handling for colors. E.g.
stackplotmaps colors to facecolor,histwith "step" type maps colors to edgecolor. What should happen if color is in**kwargsprobably needs individual consideration for each method.PR checklist