Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ENH: rely on non-rectangular patch paths rather than bboxes for legend auto-placing (fix #9580) #9598

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

Merged
merged 3 commits into from
Dec 15, 2022

Conversation

afvincent
Copy link
Contributor

@afvincent afvincent commented Oct 28, 2017

PR Summary

This PR addresses issue #9580.

Rationale

Currently, when using the legend auto-placing (NB: default since 2.0), one can get significantly surprising results as
orig_test
where things are OK with the two upper subplots but the two lower ones are not.

As @anntzer explained in #9580, this is because "step*" histogram types return a single Polygon patch while non-"step*" types return a list of Rectangle patches. As the legend auto-placing algorithm relies on the bbox of the patches, it can significantly overestimates the actual patch area (e.g. as in the case displayed above). This PR simply suggests to use the path that defines non-rectangular patches instead of their bbox in the legend auto-placing algorithm. By doing this the algorithm should handle these patches as well (or bad) as any Line2D instances.

At least, it fixes the previous example...
with_cleverer_auto_legend

Remaining concerns

NB: the followings points are kind of related actually.

Is it not kind of a nuke to treat every non-rectangular patches as a path?

A less radical change may be to keep the current bbox-based approach for some other patches like Ellipse, Circle, etc. where the issue stated above is less “severe” and the bbox provide a quite good approximation of the area that is covered by the patch.

What about speed?

A very crude and genuine benchmark with a ~ 1000 bin-histogram is given in #9580 and suggest than this change is not likely to be the performance bottleneck of legend. If I am correct, at least for histograms, the new approach should not be really more computationally expensive than the cost of the non-step* histogram types, where the legend bbox is tested against every Rectangle patch the histogram is made of, isn't it? However, it may be worth to check that performance does not become a issue for plot with very high amounts of “complex” patches.

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • [?] Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

This breaks the previously “incorrect” behavior, and there will be no way to recover it. @tacaswell Should I add a proper entry in api_changes.rst about it?

@afvincent afvincent added this to the v2.2 milestone Oct 28, 2017
@afvincent
Copy link
Contributor Author

afvincent commented Oct 28, 2017

Tests are coming! here. I tried to use non image ones, but to do so, I did not find anything more straightforward than relying on assertions about the Bboxes of the legends... If there was something way more clever to do, I am interested.

In both tests, the leftmost subplot is designed to be used as the reference case. FYI, here are the pictures (not used to perform the tests) that I used for the two tests:
test_legend_auto4
test_legend_auto5
while formerly the results would have been:
old_behavior_test_legend_auto4
old_behavior_test_legend_auto5

@afvincent afvincent changed the title [WiP] ENH: rely on non-rectangular patch paths rather than bboxes for legend auto-placing (fix #9580) ENH: rely on non-rectangular patch paths rather than bboxes for legend auto-placing (fix #9580) Oct 28, 2017
@afvincent afvincent force-pushed the enh_cleverer_auto_legend branch from e97e93c to 414d4f8 Compare October 28, 2017 05:23
@afvincent
Copy link
Contributor Author

Sorry, I let an F-string from former iterations in the previous commit (3.6+ ❤️)... I fixed it and rebased to squash the one character-commit.

Copy link
Contributor

@anntzer anntzer left a comment

Choose a reason for hiding this comment

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

I think it would be good to add a "the auto-legend locator algorithm has been tweaked" note in the API changes, without necessarily going into the details (so if we change it again before the next release it would be OK to leave it as it is), mostly to leave a breadcrumb if anyone is confused by the change in behavior.

I honestly wouldn't worry about the loss of a clearly less optimal behavior.

@Kojoley
Copy link
Member

Kojoley commented Oct 28, 2017

So with this change it could place a legend inside a non-solid bar (if the bar is big enough)?

@anntzer
Copy link
Contributor

anntzer commented Oct 28, 2017

good point... (but I think being fully in a solid polygon is less annoying that crossing some boundaries)

@jklymak
Copy link
Member

jklymak commented Oct 28, 2017

You could check if the legend was inside any polygons as well though your second test would fail. But I don’t think most of the time you want the legend inside a drawn polygon.

@tacaswell
Copy link
Member

How much computation time does this add? With the 'auto' behavior now the default this is a bit of a hot-path for people updating plots.

@afvincent
Copy link
Contributor Author

afvincent commented Oct 30, 2017

@anntzer: I added an entry in api_changes, quite minimalistic as you suggested ;).

@tacaswell: I tried to write a benchmark script here. It seems to me that the performance impact is barely noticeable (between +0.9% and +1.3% of execution time in the examples of the benchmark). However TBH I know very little about profiling (and monkey-patching with mock too...), so I may have misunderstand the profiler (pprofile) output. Any advice or suggestion are welcome if there were better ways to do this kind of study 🐑.

The plots used for benchmarking look like:

  • current (former?) algorithm
    benchmark_of_former_method_000

  • suggested (new?) algorithm
    benchmark_of_new_method_000

and they are more intended to give hard time to the legend locator than to be representative of real-life plots. (Well, I am not used to plot histograms with ~ 5000 bins or plots with 500 Polygon patches with ~ 10 edges each.)

One can see that the behavior with the patch collection is still quite surprising (not to say wrong...), and there is something weird with the plot coordinates. (I guess that I missed some transform trick.)

@Kojoley and @jklymak: I am still looking into the consequences of this PR in the kind of situations that you suggested!

Edit: Added some values from the benchmark results.

@afvincent
Copy link
Contributor Author

Putting back the [WiP] mark, as some legitimate questions about the consequences of this PR have been made and still need to be evaluated.

@jklymak
Copy link
Member

jklymak commented Oct 30, 2017

Personally, I think putting a legend inside an artist is an OK fallback, but only if it can't be put outside an artist. I wonder if a "better" way to go would be doing the old bounding box check first and then, only if that fails for all possible locations, do the intersecting-vertex check. I think that gets better behaviour but still preserves the spirit of this PR.

@jklymak
Copy link
Member

jklymak commented Oct 30, 2017

Also, looking at the above, I wonder if the check order needs to be changed. I'd far prefer the legend top center than bottom center in the first test.

@afvincent
Copy link
Contributor Author

@jklymak About the check order: I was having the same thought (but usually @tacaswell is a bit reluctant with API changes just for “aesthetic” reasons 😈 :P). Anyway, other things are broken/weird with the check order, for example "(centered) right" seems to be evaluated twice but not even in successive positions...

For your other idea, that is an interesting idea, I'll try to give it a shot when I have more time (likely not today...).

@jklymak
Copy link
Member

jklymak commented Dec 12, 2017

ping @afvincent I still think this is a great enhancement....

@afvincent
Copy link
Contributor Author

@jklymak I did not forget it ;). It is simply that day-job and other more natural events (Thomas Fire, I am speaking of you 😈) have required a significant share of my attention during the past few weeks... Hopefully I will have more time to take care of this (and the other PRs I opened recently) during the second half of December. If something is really urgent, I do not mind friendly take overs. But I guess that the next “deadline” was pushed to 2.2, which gives a bit of time, does it not?

@jklymak
Copy link
Member

jklymak commented Dec 12, 2017

Yeah, but 2.2 has over 900 issues, so we will be busy ;-)

@jklymak
Copy link
Member

jklymak commented Mar 21, 2018

ping @afvincent real-life bah! I still think this should go in, maybe after some mods...

@jklymak jklymak modified the milestones: needs sorting, v3.0 Mar 21, 2018
@afvincent
Copy link
Contributor Author

@jklymak Hearing you loud and clear, and this PR is still in my on-going work list ;).

I am still trying to find a useful way to benchmark that change (IIRC @tacaswell was a bit worry about that change). Besides, there was also a comment in the thread about the fact that the default order used to explore the possible position might not be the most “intuitive” one (whatever this means :P), but I guess that we might re-evaluate it for 3.0 if that is relevant.

@jklymak
Copy link
Member

jklymak commented Mar 21, 2018

As someone who is slowing down drawing as fast as others are speeding it up, I disagree that perfomance is a huge issue (within reason). If a user needs performance, they shouldn't use automatic convenience functions, i.e in this case, they can specify the location kwarg. But thats just my vote; I appreciate that its also the default, so it has the potential to slow people down by default is an issue.

My only problem w/ this PR is that I think its possible to theoretically put the legend inside the data curve, and that doesn't appeal.

At the very least, this could get its own value for the location kwarg. "superauto"?

@anntzer
Copy link
Contributor

anntzer commented Mar 21, 2018

Would rather not introduce a new location keyword, keep things lean, yada yada. If it's just a 1% slowdown I wouldn't worry to much about it...

@jklymak jklymak modified the milestones: v3.0, v3.1 Jul 9, 2018
@jklymak jklymak removed this from the v3.1.0 milestone Feb 9, 2019
@jklymak jklymak added this to the unassigned milestone Feb 9, 2019
@jklymak
Copy link
Member

jklymak commented Jul 16, 2019

ping @afvincent - I think this one was quite close if you have time...

@jklymak jklymak removed the stale label Jul 16, 2019
@jklymak jklymak marked this pull request as draft July 23, 2020 16:42
@jklymak
Copy link
Member

jklymak commented Jul 23, 2020

Annual ping @afvincent...

@story645 story645 modified the milestones: unassigned, needs sorting Oct 6, 2022
@tacaswell
Copy link
Member

I took the liberty of rebasing this and think it is ready for re-review.

@tacaswell tacaswell marked this pull request as ready for review December 5, 2022 22:06
@tacaswell tacaswell force-pushed the enh_cleverer_auto_legend branch from 5f5c798 to 694e2f4 Compare December 9, 2022 20:23
@tacaswell
Copy link
Member

@jklymak Can you please make the call if this should go in or be pushed to 3.8?

Copy link
Member

@jklymak jklymak left a comment

Choose a reason for hiding this comment

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

This seems like it should work and not be too much of a speed drain (beyond what best already does). Thanks for rebasing @tacaswell.

@jklymak jklymak merged commit d8bb1a5 into matplotlib:main Dec 15, 2022
@jklymak
Copy link
Member

jklymak commented Dec 15, 2022

I took the liberty of doing a squash merge

raphaelquast pushed a commit to raphaelquast/matplotlib that referenced this pull request Mar 16, 2023
…d auto-placing (fix matplotlib#9580) (matplotlib#9598)

* use path rather than bbox for non rectangular patches

* Add tests

* Add a short breadcrumb note in api_changes
@zhondori
Copy link

zhondori commented Apr 4, 2024

It took 5 years to merge this PR 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants