-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
ENH: Only do constrained layout at draw... #20229
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
Conversation
Benchmarkshttps://github.com/matplotlib/mpl-bench
master:
This PR:
|
This is inspired by #19892 where we will probably move towards making layout managers more modular.... |
One note - for constrained_layout, at least, the figure does need to know that it is being used before any colorbars are added so that it can use the non-gridspec colorbars. So, in general, its not possible to strip all layout manager state to draw time. However, this PR is still useful because it allows more layout manager state to be determined at draw time. |
I'd like to get this in so #20426 can get in for 3.5. Note this is a relatively straightforward change, despite its apparent length. The logic for creating the layout boxes that comprise constrained_layout are created at draw-time instead of when the figure and gridspecs are created. |
@@ -188,7 +283,7 @@ def _get_margin_from_padding(obj, *, w_pad=0, h_pad=0, | |||
return margin | |||
|
|||
|
|||
def _make_layout_margins(fig, renderer, *, w_pad=0, h_pad=0, | |||
def _make_layout_margins(_layoutgrids, fig, renderer, *, w_pad=0, h_pad=0, |
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.
Changes from here and below are just adding the _layoutgrids
structure to all the methods....
return _layoutgrids | ||
|
||
|
||
def _make_layoutgrids(fig, _layoutgrids): |
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 logic was all in figure.py
.
|
||
def _make_layoutgrids_gs(_layoutgrids, gs): |
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 logic was all in gridspecs.py
@@ -2065,21 +2058,6 @@ def get_constrained_layout_pads(self, relative=False): | |||
""" | |||
return self._parent.get_constrained_layout_pads(relative=relative) | |||
|
|||
def init_layoutgrid(self): |
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 was moved to _constrained_layout
Not how there are no _layoutgrids
attached to the figure any longer...
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.
Do you want to add a changelog note?
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.
Do we need one for private attributes?
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.
Nope.
@@ -387,25 +385,8 @@ def __init__(self, nrows, ncols, figure=None, | |||
width_ratios=width_ratios, | |||
height_ratios=height_ratios) | |||
|
|||
# set up layoutgrid for constrained_layout: |
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.
All moved to _constrained_layout.py
and happens at draw time...
_layoutgrids[fig] = layoutgrid.LayoutGrid( | ||
parent=parentlb, | ||
name=(parentlb.name + '.' + 'panellb' + | ||
layoutgrid.seq_id()), |
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.
Perhaps you can have a seq_id(<prefix>)
function to avoid all these string manipulations everywhere.
(possibly in a separate PR)
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.
Sure, I just moved it into LayoutGrid. The names were just for debug purposes to keep track of what each grid was supposed to be containing.
Benchmark with 30 draws per benchmark:master:
This PR:
Same benchmark, but
|
I'll pop this to "merge with single review". There are no API changes, and its operating on something we still nominally consider experimental. |
|
||
def make_layoutgrids(fig, layoutgrids): |
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.
All the others take layoutgrids
first; should this not do the same also?
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 (usually) called first, so the layoutgrids
is only if we are doing the call recursively....
5eec6c5
to
e61bf9f
Compare
I think you missed a couple of the alignment comments, but otherwise LGTM. |
e61bf9f
to
eacda99
Compare
fixed now, thanks... |
PR Summary
This PR moves all of the state for constrained_layout out of
figure
andgridspec
except for the kwargs in figure. There are a few clear advantages.This may have a minor speed hit because all the layout boxes are made each draw, but I doubt its very significant
PR Checklist
pytest
passes).flake8
on changed files to check).flake8-docstrings
and runflake8 --docstring-convention=all
).doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).