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

[Bug]: Adding suptitle in compressed layout causes weird spacing #27866

Open
pavlin-policar opened this issue Mar 5, 2024 · 10 comments
Open
Labels
topic: geometry manager LayoutEngine, Constrained layout, Tight layout

Comments

@pavlin-policar
Copy link

pavlin-policar commented Mar 5, 2024

Bug summary

If I create a "compressed" layout with two rows with both subplots having fixed aspect ratios, adding a suptitle will insert the space between the suptitle and the plots. I would expect the excess space to be put in below the subplots.

Code for reproduction

fig, (ax0, ax1) = plt.subplots(
    nrows=2, figsize=(4, 10), layout="compressed",
    gridspec_kw={"height_ratios": (1 / 4, 3 / 4), "hspace": 0}
)

ax0.axis("equal")
ax0.set_box_aspect(1/3)

ax1.axis("equal")
ax1.set_box_aspect(1)

# Adding suptitle causes weird spacing
fig.suptitle("Title")

Actual outcome

With suptitle:

image

Without suptitle:

image

Notably, this also happens without defining the gridspec kwargs.

Expected outcome

I would expect the extra spacing to be added at the bottom, not be inserted between the suptitle and the plots.

Additional information

No response

Operating system

OSX

Matplotlib Version

3.8.0

Matplotlib Backend

module://matplotlib_inline.backend_inline

I am running this inside jupyter lab, but this persists even if I save the figure to a file.

Python version

No response

Jupyter version

No response

Installation

pip

@timhoffm timhoffm added the topic: geometry manager LayoutEngine, Constrained layout, Tight layout label Mar 5, 2024
@MohitHire
Copy link

MohitHire commented Mar 5, 2024

Hi as I want to working on it, please let me known this is your expected output
Screenshot 2024-03-06 at 1 04 10 AM
please tell me in which file I need to make pull request for this issue

@MohitHire
Copy link

MohitHire commented Mar 5, 2024

How can I make pull request for this issue by making new file in this repo or by editing in any other folder????

@pavlin-policar
Copy link
Author

It seems like your fix involves adding the following code:

plt.subplots_adjust(top=0.9)

However, this seems to produce the following error:

UserWarning: This figure was using a layout engine that is incompatible with subplots_adjust and/or tight_layout; not calling subplots_adjust.

This seems to indicate that this particular line of code isn't doing anything. And really, I don't see any difference in the figure.

@rcomer
Copy link
Member

rcomer commented Mar 5, 2024

I would not say that this is a bug: suptitle is adding the title to the top of the figure, as expected. Compressed layout removes space from between the subplots by moving them together, as expected. The inline backend automatically removes excess space from around the figure, but that is not the default in Matplotlib generally.

It could be a feature request to have compressed layout move suptitle, supxlabel and supylabel close to the axes. I have no idea how easy that would be to implement. I would want such a feature to be optional as I have use-cases where I want the axes central but a main title at the top, and I keep the original figure size.

@pavlin-policar
Copy link
Author

Ah, I see, so the inline layout is removing the space from the bottom. So, in reality, the two plots are vertically centered, it's just not showing up in jupyter lab. Am I getting this right?

What I really want to achieve is have the plots stack from the top-down. And I know what aspect ratio I want the subplots to have. I don't really care how tall the final plot is, I just want to be able to set its width, and then have the height expand as needed. From my understanding, matplotlib doesn't really support this easily? Do you have any idea how I might go about doing this?

@jklymak
Copy link
Member

jklymak commented Mar 5, 2024

@pavlin-policar you will definitely have to work around this issue. But how depends on why are you choosing to use suptitle in this situation versus a title on the top axes.

@rcomer
Copy link
Member

rcomer commented Mar 5, 2024

So, in reality, the two plots are vertically centered, it's just not showing up in jupyter lab. Am I getting this right?

Yes, that’s right.

@timhoffm
Copy link
Member

timhoffm commented Mar 5, 2024

Yes, you are right.

Do you have any idea how I might go about doing this?

A cheap workaround would be to use ax0.set_title() to set the title above the top axes. This is not really the same as the suptitle is centered over the figure but the Axes title is centered over the Axes box, but might be sufficient.

If you really want a suptitle, you'll have to tune the vertical position:

  • either completely manual: fig.suptitle("Title", y=0.78)
  • or by calculating the position:
    fig.draw_without_rendering()  # to calculate the Axes positions in the layout
    pad = 0.01  # in fractions of the figure height
    fig.suptitle("Title", y=ax0.get_position().y1 + pad, verticalalignment="bottom")
    

@pavlin-policar
Copy link
Author

pavlin-policar commented Mar 5, 2024

Thank you all for the wonderful suggestions!

In my actual use case, I have a 2 by 2 grid of subplots, so setting the axis title for the the top-left axis wouldn't work, since the title wouldn't be centered on the overall plot. I only posted a minimal example to reproduce my problem.

@timhoffm The second solution worked well for me. When saving to a file, it's important then to add bbox_inches="tight", which clips off the extra whitespace from the top and bottom of the plot. Otherwise, the excess whitespace gets saved as well.

Judging by all your (very helpful) comments, I suppose this isn't really a bug, but expected behavior, so I'll close the issue. The solution does feel a bit hacky though and I do wish there was like a layout="stack_vertical_and_ignore_height" option that would do what I wanted, but I'm sure it's a fairly uncommon use-case.

@jklymak
Copy link
Member

jklymak commented Mar 5, 2024

I think this could stay open if someone wanted to fix it. I think it would just take a bit of logic in compressed layout to check for suptitle

@jklymak jklymak reopened this Mar 5, 2024
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

No branches or pull requests

5 participants