Repository navigation
Description
Bug summary
Since matplotlib 3.5.0, I see a slightly different result when using tight_layout() or set_tight_layout(True) with the macOS backend. These differences do not appear with matplotlib 3.4.3, or in a Debian container.
Code for reproduction
import matplotlib.pyplot as plt
from matplotlib.testing.compare import compare_images
fig1, ax1 = plt.subplots()
fig1.set_tight_layout(True)
fig1.savefig("1.png")
fig2, ax2 = plt.subplots()
fig2.tight_layout()
fig2.savefig("2.png")
assert compare_images("1.png", "2.png", 0) is NoneActual outcome
The comparison fails, and the figures slightly differ on macOS:
Traceback (most recent call last):
File "test.py", line 13, in <module>
assert compare_images("1.png", "2.png", 0) is None
AssertionErrorThe difference is rather small: the rightmost x-axis tick label slightly moves.
On Debian the assertion succeeds, and when downgrading to matplotlib 3.4.3 it also succeeds on macOS.
Expected outcome
According to the tight layout guide:
Note that
matplotlib.pyplot.tight_layout()will only adjust the subplot params when it is called. In order to perform this adjustment each time the figure is redrawn, you can callfig.set_tight_layout(True), or, equivalently, setrcParams["figure.autolayout"](default:False) toTrue.
I expect both figures to be equivalent, as there is nothing else happening after the tight_layout() / set_tight_layout(True) call and before saving.
Additional information
I can only reproduce the behavior on macOS with matplotlib 3.5.0. Earlier versions produce consistent figures, and a Debian container with python:3.9-slim also produces consistent figures with matplotlib 3.4.3.
I came across this while trying to understand differences in figure layout observed between CI running Ubuntu and a local macOS setup, which appeared with matplotlib 3.5.0 when using tight_layout(). These differences disappear with set_tight_layout(True), and I also see consistent behavior with constrained_layout.
While the observed difference in the example above is very small, the differences become slightly larger with more complex setups. This gist shows another figure comparison where the differences are a bit more noticeable (though still small, and hard to see unless flipping back and forth between the images).
When switching the backend to TkAgg (matplotlib.use("TkAgg")), the discrepancy also disappears.
Operating system
macOS 11.5.2
Matplotlib Version
3.5.0
Matplotlib Backend
MacOSX
Python version
Python 3.8.10
Jupyter version
6.4.0
Installation
pip
Activity
timhoffm commentedon Nov 18, 2021
Does your Mac have a HiDPI screen? This might be related to HiDPI adaptions such as #18274 or #21365 (not necessarily a full list).
greglucas commentedon Nov 18, 2021
Both of the examples work on my mac. I am unable to reproduce either of the failures (the included one, or the gist). I'm on Catalina with an intel chip, so another possibility is if you're running on the new M1 chip?
alexander-held commentedon Nov 18, 2021
I am seeing this with Big Sur on an Intel MacBook Pro, and yes with HiDPI display.
greglucas commentedon Nov 19, 2021
I think the macosx is a red herring here and only produces it because you start out with a higher dpi. I can reproduce with Agg in a similar test where we set the figure dpi to 200 right away and then save it with a lower dpi later.
Bisects to: #19126
ping @QuLogic
QuLogic commentedon Nov 19, 2021
#19126 just makes things properly consistent in how DPI is handled; it was wrong in macosx before. This issue doesn't have to do with that specifically, and is a peril of using tight layout, which is rather fragile to DPI, especially with text.
If you call
tight_layout(), then the figure is adjusted using 200 DPI, and saved at 100 DPI using the positions that were calculated that one time. If you callset_tight_layout(True), then it's always on and when saving at 100 DPI, it will re-adjust itself which probably comes out different.I think we can fix this by making
tight_layoutalways work with the original DPI, ignore the saving DPI. That also fixes the problem you whittled it down to as well, with mixed display/saving DPI.github-actions commentedon Nov 10, 2025
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!