| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Thanks for keeping at this, does #28104 need to be merged first? |
Sorry, something went wrong.
|
Yes, preferably, so that the changes for Patches can be accurately replicated for Collections |
Sorry, something went wrong.
|
There is currently one test which is failing and might need a rewrite: lib/matplotlib/tests/test_axes.py::test_contour_hatching Previous BehaviorIn collections, hatchcolor is set along with edgecolor. In the cases where edgecolors is explicitly specified by the user, hatchcolor is set to the first color in edgecolors and it also uses the alpha value specified by the user. However, if edgecolors is not specified, hatchcolor uses mpl.rcParams['hatch.color'] for the color, but it doesn't use the alpha value specified by the user. New BehaviorThe new implementation in this PR has hatchcolor separated from edgecolor and it uses the alpha value specified by the user, regardless of whether edgecolors is specified or not. Reason for New Behavioralpha works on hatchcolor when edgecolors is specified. Therefore, I believe that it should also work when edgecolors is not specified. In the above test, alpha is set to 0.5. Ideally, the hatch should have an alpha value of 0.5, but it has the default alpha value of 1.0. |
Sorry, something went wrong.
|
pinging @story645 for review |
Sorry, something went wrong.
|
The PDF test for test_axes.py::test_contour_hatching isn't failing, so the baseline PDF is left untouched. I suspect that this is because alpha on hatches on PDF backend isn't completely implemented and it looks like #17049 aims to fix this. |
Sorry, something went wrong.
There was a problem hiding this comment.
It's somewhat unfortunate that we have to put the parameter at the end of each function signature and make it optional on all lower-level functions. But I suppose that is the price we have to pay to keep API backward compatibility. I would have to check how public all this is and whether we could eventually migrate to a cleaner API.
Sorry, something went wrong.
I think that we can't avoid this change, because the default behavior is somewhat inconsistent, as explained in this comment.
I think it might be better to update the images, because it looks like the test was previously testing the incorrect behavior. I think that it is better to have the test images reflect the correct behavior, as this test covers the behavior of hatchcolors with alpha values more comprehensively than if we change the test to explicitly set the hatch color to black with alpha = 1.0. When explicitly setting hatchcolor, I wasn't able to force alpha as 1.0 for hatchcolor without using _hatchcolors attribute. diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index 38857e846c..5764d3fff6 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -2651,6 +2651,9 @@ def test_contour_hatching():
cmap=mpl.colormaps['gray'],
extend='both', alpha=0.5)
+ for c in ax.collections:
+ c._hatchcolors = mpl.colors.to_rgba_array('black', 1.0)
+
@image_comparison(
['contour_colorbar'], style='mpl20',Here is why I think that the test was previously testing the incorrect behavior:
|
Sorry, something went wrong.
|
I think that if we want to move this PR forward, the realistic short-term approach is to do API support sniffing via the empty call (and not even warn on third-parties for now, at least until we can agree on the long-term plan and likely also add support for multiple hatches). |
Sorry, something went wrong.
… suggested changes.
|
Thanks @Impaler343 for adding the API sniffing. Unfortunately this is not enough, because you choose to just not pass hatchcolors at all if they are unsupported. While the idea of just drawing single-color hatches on 3rd-party backends may be reasonable (I'm fine with that), it means that these backends will try to consult rcParams["hatch.color"] to select a color; and since #28104 they can see the new unnormalized value "edge", for which there was no support before, and they will crash there. At least this value should be normalized (e.g. to the first edgecolor, I guess); ideally if hatchcolors is not supported, the draw_path_collection call should be expanded as in ContourSet.draw to draw one path at a time. |
Sorry, something went wrong.
|
This works now on mplcairo. Thanks for going through all the work! |
Sorry, something went wrong.
|
@anntzer Are there any other changes expected? Or is this ready to be merged? |
Sorry, something went wrong.
There was a problem hiding this comment.
Just one last suggestion to improve on the future extensibility (approval is conditional on at least discussing it).
I still don't really like the API but it's also unrealistic to hope for a full rewrite here, so let's go with it.
Sorry, something went wrong.
I agree that this API will need to be changed in the future. @timhoffm any suggestions? |
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks for this PR - it looks great overall, and the examples were super nice to understand the new feature.
There's a few minor points I think can be improved, and some questions I had - I've left my comments inline in the code.
Sorry, something went wrong.
| "screen", hatchcolors=self.get_hatchcolor() | ||
| ) | ||
| except TypeError: | ||
| hatchcolors_arg_supported = False |
There was a problem hiding this comment.
codecov is saying that these lines aren't covered (and several other lines in this file). Could you add some tests for these lines? They don't have to be figure tests, they can just test that the code works without erroring.
Sorry, something went wrong.
There was a problem hiding this comment.
These lines are run only in the case of a third-party backend. However, I am not sure how to test this within the current testing framework of matplotlib, without a third-party backend.
Sorry, something went wrong.
There was a problem hiding this comment.
You can make a mock third party backend to call the function - there are some examples of other mocks in the tests
Sorry, something went wrong.
| # The current new API of draw_path_collection() is provisional | ||
| # and will be changed in a future PR. | ||
|
|
||
| # Find whether renderer.draw_path_collection() takes hatchcolor parameter |
There was a problem hiding this comment.
| # Find whether renderer.draw_path_collection() takes hatchcolor parameter | |
| # Find whether renderer.draw_path_collection() takes hatchcolor parameter. | |
| # Since third-party implementations of draw_path_collection() may not be | |
| # introspectable, e.g. with inspect.signature, the only way is to try and | |
| # call this with the hatchcolors parameter. |
Sorry, something went wrong.
| "screen") | ||
| "screen", hatchcolors=self.get_hatchcolor() | ||
| ) | ||
| except TypeError: |
There was a problem hiding this comment.
It's worth explicitly documenting this in the comment, see suggestion above.
Sorry, something went wrong.
| def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, | ||
| coordinates, offsets, offsetTrans, facecolors, | ||
| antialiased, edgecolors): | ||
| antialiased, edgecolors, hatchcolors=None): |
There was a problem hiding this comment.
Is this a red herring? From what I understand from #29044 (comment), making hatchcolors optional (or even kw-only) does not buy us anything in terms of better API compatibility: This is reimplemented by backends. Some may have implemented a hatchcolors parameter, others may not. It is only called from our matplotlib code, so we anyway have to deal with it being available or not (and if it's available, we always want to pass hatchcolors). There shouldn't be any third-party/user code needing to call this function.
If that's correct, an additional positional parameter would have the same effect. And then I'd prefer that because it keeps the whole function consistent.
ping @anntzer Am I correct here?
Edit: There seem to be very few "real" usages of draw_path_collection (I've tried to filter outforks or copies of our files):
https://github.com/search?q=%2F%5C.draw_path_collection%5C%28%2F+language%3APython+NOT+is%3Afork+NOT+repo%3Amatplotlib%2Fmatplotlib+NOT+path%3A**%2Fbackend_bases.py+NOT+path%3A**%2Fcollections.py++NOT+path%3A**%2Fpatheffects.py+NOT+path%3A**%2Fbackend_agg.py+NOT+path%3A**%2Fbackend_svg.py+NOT+path%3A**%2Fbackend_pdf.py++NOT+path%3A**%2Fbackend_ps.py+NOT+path%3A**%2Fbackend_macosx.py++NOT+path%3A**%2Fleft.py+NOT+path%3A**%2Fright.py++NOT+path%3A**%2Fmerge.py++NOT+path%3A**%2Fbase.py+NOT+path%3A**%2Fsite-packages%2F**&type=code
I think making this optional is meaningful for a start because it will support some very rare use cases. But in terms of API consistency, I'd like to move this to a regular parameter in the future, i.e.
Sorry, something went wrong.
|
re: making hatchcolors optional and API compatibility: |
Sorry, something went wrong.
|
Thanks. I agree optional is set to begin with for compatibility. Questions are:
|
Sorry, something went wrong.
It makes it easier to later include parameters before it, e.g. hatches is something that's clearly missing and would be expected to come first.
Let's not for now. As argued above I think the API introduced in this PR is actually not so great (but still the best that can be done without an in-depth reworking of draw_path_collection), so e.g. I'd rather not implement support for it at all in mplcairo (and instead rely on Matplotlib's fallback implementation) until a better API comes. Likewise I don't think we should encourage any third parties to implement it. |
Sorry, something went wrong.
| path_ids = renderer._iter_collection_raw_paths( | ||
| transform.frozen(), ipaths, self.get_transforms()) | ||
| for xo, yo, path_id, gc0, rgbFace in renderer._iter_collection( | ||
| gc, list(path_ids), *args, hatchcolors=self.get_hatchcolor(), | ||
| ): | ||
| path, transform = path_id | ||
| if xo != 0 or yo != 0: | ||
| transform = transform.frozen() | ||
| transform.translate(xo, yo) | ||
| renderer.draw_path(gc0, path, transform, rgbFace) |
There was a problem hiding this comment.
For better backward-compatibility/performance, would it be reasonable to split the "backend does not support hatchcolors" into
if no_hatches_needed:
renderer_draw_path_collection(...) # no hatch colors passed
else:
# unroll the collection to draw paths in a loop
I'm unclear how performance-critical this is and whether we can unversally force the collection unrolling on backends that do not support hatchcolors.
ping @anntzer
Sorry, something went wrong.
There was a problem hiding this comment.
Good catch. I agree that only going through the unrolled version when hatchcolors are actually passed would likely be much better performance-wise.
Sorry, something went wrong.
|
Thanks @r3kste for going through all the nitty gritty details with us! |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
PR summary
Follow on PR to #28104 helping to fix issues #26074 and #7059
Added hatchcolor parameter for Collections, to be able to separately control edgecolors and hatchcolors.
The fallback logic for hatchcolor is identical to the previous PR, where it follows this precedence order:
hatchcolor parameter -> hatch.color rcParam -> inherit from edgecolors if hatch.color is edge -> default to patch.edgecolor rcParam if edgecolors is not specified.
PR checklist