Skip to content

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

Merged
merged 1 commit into from
Aug 11, 2021

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented May 14, 2021

PR Summary

This PR moves all of the state for constrained_layout out of figure and gridspec except for the kwargs in figure. There are a few clear advantages.

  1. No extra state to worry about if the figure is serialized (kiwi solver objects don't serialize).
  2. constrained_layout can respond to changing gridspec specs (like width ratios) because all the state is decided at draw time.
  3. More parallel to tight_layout which does all its work at draw time as well.

This may have a minor speed hit because all the layout boxes are made each draw, but I doubt its very significant

  • performance benchmarks.
    • seems to be no discernible difference using the mpl-bench constrained_layout benchmarks...

PR Checklist

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (run flake8 on changed files to check).
  • New features are documented, with examples if plot related.
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • Conforms to Matplotlib style conventions (install flake8-docstrings and run flake8 --docstring-convention=all).
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).

@jklymak jklymak force-pushed the enh-cl-drawtime branch from dc3c027 to 600dd6f Compare May 14, 2021 05:49
@jklymak jklymak changed the title ENH: Just do constrained layout at draw... ENH: Only do constrained layout at draw... May 14, 2021
@jklymak jklymak force-pushed the enh-cl-drawtime branch from 600dd6f to bd2cb36 Compare May 14, 2021 14:24
@jklymak jklymak added the topic: geometry manager LayoutEngine, Constrained layout, Tight layout label May 14, 2021
@jklymak
Copy link
Member Author

jklymak commented May 14, 2021

Benchmarks

https://github.com/matplotlib/mpl-bench

% asv dev --bench constrained

master:

asv dev --bench constrained
· Discovering benchmarks
· Running 2 total benchmarks (1 commits * 1 environments * 2 benchmarks)
[  0.00%] ·· Benchmarking existing-py_Users_jklymak_anaconda3_envs_matplotlibdev_bin_python
[ 25.00%] ··· constrained_layout.time_subplots                                                                                                                  ok
[ 25.00%] ··· === ==========
               n
              --- ----------
               1   55.3±0ms
               2   184±0ms
               5   833±0ms
              === ==========

[ 50.00%] ··· constrained_layout.time_subplots_colorbar                                                                                                         ok
[ 50.00%] ··· === =========
               n
              --- ---------
               1   134±0ms
               2   448±0ms
               4   1.34±0s
              === =========

This PR:

[ 25.00%] ··· constrained_layout.time_subplots                                                                                                                  ok
[ 25.00%] ··· === ==========
               n
              --- ----------
               1   85.5±0ms
               2   208±0ms
               5   836±0ms
              === ==========

[ 50.00%] ··· constrained_layout.time_subplots_colorbar                                                                                                         ok
[ 50.00%] ··· === =========
               n
              --- ---------
               1   120±0ms
               2   452±0ms
               4   1.35±0s
              === =========

@jklymak jklymak force-pushed the enh-cl-drawtime branch from dac4f5a to 949cb33 Compare May 14, 2021 16:54
@jklymak
Copy link
Member Author

jklymak commented May 14, 2021

This is inspired by #19892 where we will probably move towards making layout managers more modular....

@jklymak
Copy link
Member Author

jklymak commented May 15, 2021

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.

@jklymak jklymak added this to the v3.5.0 milestone May 15, 2021
@jklymak jklymak marked this pull request as ready for review May 15, 2021 15:18
@jklymak jklymak marked this pull request as draft May 16, 2021 19:26
@jklymak jklymak mentioned this pull request Jun 13, 2021
7 tasks
@jklymak jklymak marked this pull request as ready for review June 13, 2021 16:37
@jklymak
Copy link
Member Author

jklymak commented Jun 13, 2021

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,
Copy link
Member Author

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):
Copy link
Member Author

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):
Copy link
Member Author

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):
Copy link
Member Author

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...

Copy link
Contributor

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?

Copy link
Member Author

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?

Copy link
Member

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:
Copy link
Member Author

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()),
Copy link
Contributor

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)

Copy link
Member Author

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.

@jklymak
Copy link
Member Author

jklymak commented Jun 17, 2021

Benchmark with 30 draws per benchmark:

master:

$ asv dev --bench constrained
· Discovering benchmarks
· Running 2 total benchmarks (1 commits * 1 environments * 2 benchmarks)
[  0.00%] ·· Benchmarking existing-py_Users_jklymak_anaconda3_envs_matplotlibdev_bin_python
[ 25.00%] ··· constrained_layout.time_subplots                                ok
[ 25.00%] ··· === =========
               n           
              --- ---------
               1   868±0ms 
               2   3.27±0s 
               5   17.4±0s 
              === =========

[ 50.00%] ··· constrained_layout.time_subplots_colorbar                       ok
[ 50.00%] ··· === =========
               n           
              --- ---------
               1   2.22±0s 
               2   8.48±0s 
               4   28.9±0s 
              === =========

This PR:

$ asv dev --bench constrained
· Discovering benchmarks
· Running 2 total benchmarks (1 commits * 1 environments * 2 benchmarks)
[  0.00%] ·· Benchmarking existing-py_Users_jklymak_anaconda3_envs_matplotlibdev_bin_python
[ 25.00%] ··· constrained_layout.time_subplots                                ok
[ 25.00%] ··· === =========
               n           
              --- ---------
               1   928±0ms 
               2   3.31±0s 
               5   16.5±0s 
              === =========

[ 50.00%] ··· constrained_layout.time_subplots_colorbar                       ok
[ 50.00%] ··· === =========
               n           
              --- ---------
               1   2.27±0s 
               2   8.98±0s 
               4   28.1±0s 
              === =========

Same benchmark, but constrained_layout=False

asv dev --bench constrained
· Discovering benchmarks
· Running 2 total benchmarks (1 commits * 1 environments * 2 benchmarks)
[  0.00%] ·· Benchmarking existing-py_Users_jklymak_anaconda3_envs_matplotlibdev_bin_python
[ 25.00%] ··· constrained_layout.time_subplots                                ok
[ 25.00%] ··· === =========
               n           
              --- ---------
               1   404±0ms 
               2   1.57±0s 
               5   6.59±0s 
              === =========

[ 50.00%] ··· constrained_layout.time_subplots_colorbar                       ok
[ 50.00%] ··· === =========
               n           
              --- ---------
               1   925±0ms 
               2   2.95±0s 
               4   9.16±0s 
              === =========

@jklymak
Copy link
Member Author

jklymak commented Jul 28, 2021

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):
Copy link
Member

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?

Copy link
Member Author

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....

@jklymak jklymak force-pushed the enh-cl-drawtime branch 2 times, most recently from 5eec6c5 to e61bf9f Compare August 10, 2021 17:56
@QuLogic
Copy link
Member

QuLogic commented Aug 10, 2021

I think you missed a couple of the alignment comments, but otherwise LGTM.

@jklymak
Copy link
Member Author

jklymak commented Aug 10, 2021

I think you missed a couple of the alignment comments, but otherwise LGTM.

fixed now, thanks...

@QuLogic QuLogic merged commit a0d2e39 into matplotlib:master Aug 11, 2021
@jklymak jklymak deleted the enh-cl-drawtime branch August 11, 2021 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: geometry manager LayoutEngine, Constrained layout, Tight layout
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants