Skip to content

FIX: use cached renderer on Legend.get_window_extent #11971

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 1 commit into from
Sep 7, 2018

Conversation

tacaswell
Copy link
Member

@tacaswell tacaswell commented Aug 29, 2018

Closes #11970

PR Summary

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@tacaswell tacaswell added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Aug 29, 2018
@tacaswell tacaswell added this to the v3.0 milestone Aug 29, 2018
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.

Ooops, sorry about that. Hard to tell what artists require a renderer argument if we use generic *args, **kwargs.

Here, the only suggestion would be that renderer=None be explained.

fig.canvas.draw()

leg.get_window_extent()
leg2.get_window_extent()
Copy link
Member

Choose a reason for hiding this comment

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

There is no assert in here. What exactly should this test? Just that get_window_extent() can be called without renderer?

The comment does tell differently. It says something about the "expected extent" and "various dpi". Both of which I don't see in the test code.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was lazy and did not remove the comment.

Yes, the test is just that this does not raise.

@tacaswell tacaswell force-pushed the fix_legend_get_window_extent branch from e1e4307 to 873ae23 Compare August 29, 2018 18:36
'Return extent of the legend.'
return self._legend_box.get_window_extent(*args, **kwargs)
if renderer is None:
renderer = self.figure._cachedRenderer
Copy link
Member

Choose a reason for hiding this comment

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

So, we have lots of get_window_extent(renderer=...) in the code base. Is it all necessary or could a lot of it be safely replaced by this? I guess I can understand for objects that don't have a reference to their figure, but in general, I think most objects know how to get back to their containing figure...

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think we want to always fall back to the cached renderer. There are some use-cases (such as the mixed-mode vector/raster cases where we need to be able to specify which renderer we want to be using with out having to propgate that state globally.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the mixed mode renderer is the only case where this could be a problem, right?
But in fact even for the mixed mode renderer we're not doing this correctly right now, because artist.draw(renderer) will store the instance of MixedModeRenderer as the _renderer attribute, so e.g. even if the artist was drawn rasterized, by the end of the draw the MixedModeRenderer will have reset itself to vectorized and later calls to get_window_extent() will use the cached MixedModeRenderer in the vectorized state.

@@ -976,9 +976,11 @@ def get_title(self):
'Return the `.Text` instance for the legend title.'
return self._legend_title_box._text

def get_window_extent(self, *args, **kwargs):
def get_window_extent(self, renderer=None):
Copy link
Member

Choose a reason for hiding this comment

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

That's technically a backward incompatible change (although, as I've mentioned in a previous PR doing something similar, I think this is a change that is worth making.)

@NelleV NelleV merged commit aae3af0 into matplotlib:master Sep 7, 2018
@NelleV
Copy link
Member

NelleV commented Sep 7, 2018

Thanks @tacaswell

meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Sep 7, 2018
@tacaswell tacaswell deleted the fix_legend_get_window_extent branch September 7, 2018 19:42
@tacaswell
Copy link
Member Author

I still get a kick when my PRs get merged 😄

anntzer added a commit that referenced this pull request Sep 7, 2018
…971-on-v3.0.x

Backport PR #11971 on branch v3.0.x (FIX: use cached renderer on Legend.get_window_extent)
@Dannyad84
Copy link

I have the same issue using seaborn.

@tacaswell
Copy link
Member Author

@Dannyad84 with what version of matplotlib?

@Dannyad84
Copy link

n/m had the wrong version. Updated and it worked. Thanks for the quick response!! ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Legend.get_window_extent now requires a renderer
6 participants