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

Skip to content

Replace "panels" with EdgeStack, permit working directly with add_subplot/GridSpec #110

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

Closed
wants to merge 9 commits into from

Conversation

lukelbd
Copy link
Collaborator

@lukelbd lukelbd commented Jan 20, 2020

This PR replaces #50 in order to clean up its history.

Subplots

This will allow Figure.add_subplot to be used by ProPlot users. Basic idea will be that, because we want one single gridspec for the whole axes, the user can generate a naked figure with fig = plot.figure(), then the first call to fig.add_subplot will set the geometry, and subsequent calls have to match that geometry. This workflow may be more readable when users want (1) complex combinations of projections, or (2) prefer to make highly complex grids with the add_subplot(121) notation or GridSpec objects rather than passing arrays to plot.subplots. I think it also makes more sense to implement projection handling in add_subplot rather than subplots.

This was implemented by 51967ce for v0.8.0.

User-accessible GridSpec

If users can now use plot.Figure.add_subplot, they should be able to use plot.GridSpec too. This means GridSpec must accept left, right, wspace, etc. in physical units rather than making subplots do the work. This can be done simply by overriding GridSpec.get_grid_positions(), which carries out 100% of the math used to calculate subplot positions.

This was implemented in 2050234 for v0.8.0.

GeometrySolver class

The above changes mean we have to let users pass gridspec spacing values before the gridspec is necessarily created. Matplotlib specifies default subplot spacing on the figure (Figure.subplots_adjust and matplotlib.figure.SubplotParams) then applies Figure spacing values to the unset GridSpec values whenver the gridspec is updated. I can mimick this approach with a GeometrySolver class that acts as the interface between the Figure and the GridSpec. This class will parse subplots / figure spacing arguments, carry out the tight layout algorithm, and perform figure-resizing and gridspec-updating tasks. This has the added benefit of cleaning up the internals and removing a bunch of hidden methods from Figure.

This was not implemented; instead, the functionality was added directly to GridSpec 2050234 for v0.8.0.

EdgeStack class

Currently, when colorbars, legends, and axes panels are created, they secretly "insert a new column or row" by destroying the existing gridspec and create a new one. This means if users keep using the GridSpec object after adding a figure panel or something, its geometry is different from the figure GridSpec, and weird stuff will happen. I considered two approaches to fixing this:

  1. Incorporate "panel" rows and columns into the definition of GridSpec itself. But then we regress back to having GridSpec.__getitem__ obfuscate underlying gridspec dimensions and things generally get messy.
  2. Stop drawing panels inside the GridSpec. Instead manage arbitrary artists along the "edge" of individual subplots (or contiguous subplots) with a special EdgeStack class. This requires redesigning the "tight layout" algorithm to work with artists in the EdgeStack, figuring out how to lock them to the main axes (probably similar to how "inset" axes are locked), and figuring out how to lock their physical widths.

In the end I decided to pursue # 2. It's sad that that I spent so much time working with "panels" instead of doing this overhaul... but I think it's the right move, given the following benefits:

  • Panels in the same row or column no longer have to be the same width, which can be a problem when you have legends + colorbars alongisde each other.
  • It allows drawing legends + colorbars along the sides of arbitrary contiguous subplots rather than just along the figure edge.
  • Legends no longer have to belong to an empty, dummy axes -- we can just lock the legend position.
  • Colorbars no longer have to belong to empty, dummy axes to extend them along <100% of the axes -- we just adjust the parent-relative long axis coordinates.
  • It will remove all references to GridSpecFromSubplotSpec, which proplot's GridSpec tries to render obsolete.
  • We can implement rowlabels and collabels with the same API, allow "stacking" arbitrary outer text objects just like legends, colorbars, and panels.

Also, for permitting colorbars, legends, and text along arbitrary contiguous axes, I can write a helper function that accepts lists of subplots and makes sure their right/left/top/bottom edges are in alignment. When you call e.g. axes_grid([...]).colorbar(...), it will pass the axes in the container to a helper function. When you call e.g. Figure.colorbar(...), it will select the subplots lying along the figure edge and pass them to the helper function.

I decided to use approach # 1 after all, adding the "panel" obfuscation directly onto the GridSpec object in 2050234. I use _total and _panel attributes to improve this obfuscation. See below notes for details.

@lukelbd
Copy link
Collaborator Author

lukelbd commented Jul 30, 2021

I'm going to delete this due to too many conflicts, but will open another empty PR later that copies these partial changes. This refactor will take a while... will try to work on it very incrementally and shoot for completion only by the end of the year.

@lukelbd lukelbd closed this Jul 30, 2021
@lukelbd lukelbd deleted the permit-add-subplot branch July 30, 2021 20:24
@lukelbd
Copy link
Collaborator Author

lukelbd commented Mar 29, 2023

I ended up adding the features listed above in a couple separate commits during some major summertime refactoring. Similar to the fate of the refactor changes described in #264.

However I have not yet added the "multi-axes colorbar" support mentioned above. See #329 for updates.

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

Successfully merging this pull request may close these issues.

1 participant