Skip to content
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

Adding subplots dynamically with constrained_layout #19730

Closed
juliospain opened this issue Mar 18, 2021 · 8 comments
Closed

Adding subplots dynamically with constrained_layout #19730

juliospain opened this issue Mar 18, 2021 · 8 comments
Labels
New feature status: needs clarification Issues that need more information to resolve.

Comments

@juliospain
Copy link

For an interactive interface where the user can add more plots, it seems impossible to use constrained_layout.
The whole adding a new axes is unnecesarily complex but it can be done. A new gridspec is set-up and the current axes are repositioned into their new "slots". This is working.

However the constrained_layout solver fails (error that height or width is 0).

Proposed Solution

It seems that some work has already been performed as part of setting a colorbar. It seems to me that with some effort it would be possible to extend that solution to be more generic.

Otherwise the whole layout boxes set-up could be exposed to the external API, such that the users can use it in a similar fashion.

(Ideally the matploplib API could make simpler adapating the gridspec after it has been created)

Additional context and prior art

None

@jklymak
Copy link
Member

jklymak commented Mar 18, 2021

Can you give us some more explanation of what doesn't work, preferably with some code? If you mean you keep tearing gridspecs down and adding new ones, and reassigning axes to the new one, that could indeed be problematic. OTOH, did you try this on matplotlib master? constrained_layout has had a rewrite that makes the layout properties less dependent on the axes and more so on the gridspec. But I wouldn't expect miracles - it is written assuming a known gridspec and isn't meant to be changed dynamically on the fly.

@jklymak jklymak added the status: needs clarification Issues that need more information to resolve. label Mar 18, 2021
@jklymak
Copy link
Member

jklymak commented Mar 18, 2021

Otherwise the whole layout boxes set-up could be exposed to the external API, such that the users can use it in a similar fashion.

BTW, users are always welcome to use the internal API, they just can't complain if it changes ;-)

@juliospain
Copy link
Author

Can you give us some more explanation of what doesn't work, preferably with some code? If you mean you keep tearing gridspecs down and adding new ones, and reassigning axes to the new one, that could indeed be problematic. OTOH, did you try this on matplotlib master? constrained_layout has had a rewrite that makes the layout properties less dependent on the axes and more so on the gridspec. But I wouldn't expect miracles - it is written assuming a known gridspec and isn't meant to be changed dynamically on the fly.

Thanks for the quick reply. I will try the master and report back.

However, yes, I do change gridspecs a lot! Isn't there a simple way to "restart" the layout solver with a complete new gridspec?

@jklymak
Copy link
Member

jklymak commented Mar 18, 2021

Isn't there a simple way to "restart" the layout solver with a complete new gridspec?

Yes - clear the figure.

If I need to change the number of subplots I just restructure my script to do so and rerun it. I don't think that it is more efficient to move things around, rather than just start over.

@juliospain
Copy link
Author

Isn't there a simple way to "restart" the layout solver with a complete new gridspec?

Yes - clear the figure.

If I need to change the number of subplots I just restructure my script to do so and rerun it. I don't think that it is more efficient to move things around, rather than just start over.

This is a little bit inconvenient. I can understand you do not support arbitrary changes of gridspec, but the complete gridspec of the figure and full reset of constrained layout would be nice.

The approach you suggest works for generating static figures (for publications for instance). But adding a little bit of interaction like in my case where I just want to add another stacked axes, reformatting and reading all the existing lines and artists that are already there it is painful and inefficient.

Unfortunately, I was not able to run directly the master branch, some unexpected error. I will keep trying...

@jklymak
Copy link
Member

jklymak commented Mar 20, 2021

Again, it would be nice if you gave us a sequence of what you are doing, as runnable code, so we can see what the problem is.

@juliospain
Copy link
Author

Ok, let me see:

import matplotlib as mpl
import matplotlib.pyplot as plt

for constrained_layout in (False, True):
    fig = plt.figure(constrained_layout=constrained_layout)
    
    # Initial plots
    nb_plots = 2
    gs = fig.add_gridspec(nb_plots, 1)
    
    axes = []
    for i in range(nb_plots):
        ax = fig.add_subplot(gs[i])
        ax.plot(range(5), range(5))
        axes.append(ax)

    if not constrained_layout:
        fig.tight_layout()
        
    fig.show()
    
    # Now to add another plot
    # First reposition the existing axes
    gs = fig.add_gridspec(nb_plots + 1, 1)
    
    for i in range(nb_plots):
        axes[i].set_position(gs[i].get_position(fig))
        axes[i].set_subplotspec(gs[i])
    
    # And add the new one...
    ax = fig.add_subplot(gs[-1])
    ax.plot(range(5), range(5))
    axes.append(ax)
    
    # Tight layout if not constrained (works)
    if not constrained_layout:
        fig.tight_layout()
        
    fig.show()
    

For the initial plots, tight_layout and constrained_layout offer the same results. When adding a new one, tight_layout is working:

image

However constrained_layout does not with the previous axes. I just put the example to show you my intention. I know this is exepcted given the current design (set_position put the axes out of the constrained_layout solver):
image

Strangely, I get different results with this MRE. In my previous tries the new plot was not correctly displayed saying that either height or width collapsed to 0 or something similar.

Of course I could go for tight_layout, but constrained_layout seems logically better and from my perspective this "adding axes" should not be that complicated (maybe if I understand the layout boxes better...)

@jklymak
Copy link
Member

jklymak commented Mar 21, 2021

Thanks for the reproducible example. I didn't even know we had set_subplotspec. But, fortuitously, this works fine on master and 3.4 release candidate. CL got a major rewrite a few months ago. Closed by #17494 and will be in the 3.4 release.

@jklymak jklymak closed this as completed Mar 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New feature status: needs clarification Issues that need more information to resolve.
Projects
None yet
Development

No branches or pull requests

2 participants