Skip to content

[Bug]: _constrained_layout takes several iterations to converge to expected result #30300

Open
@fontanj

Description

@fontanj

Bug summary

When legend is placed outside of the axes bounds (using bbox_to_anchor), particularly by a relatively wide margin, and layout is set to "constrained", one would expect the axes to be scaled such that both the axes and legend fit inside the figure size, as shown below:

Image

However, the initially generated plot does not scale the axes enough to include the legend within the figure, as shown below:

Image

However, when the _constrained_layout function is iterated upon (by repeated plt.savefig(), the figure converges to the expected result. The attached example illustrates this convergence. For the purposes of generated the attached output images, the example script was executed with the internal number of _constrained_layout set to 1 (instead of 2), on this line of the _constrained_layout function:

This was done to show what happens with each iteration of _constrained_layout. An animated GIF of the sequence of images produced is shown below:

Image

Code for reproduction

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 500)
y1 = np.sin(x)

fig, ax = plt.subplots(figsize=(10, 6), layout="constrained")
ax.plot(x, y1, label='sin(x) long title')

ax.set_xlabel('x')
ax.set_ylabel('y')

ax.legend( loc="upper right", bbox_to_anchor=(1.5, -0.8))

for i in range(21): 
    fig.savefig(f'constrained_test_{i}.png')

Actual outcome

Image

Expected outcome

Image

Additional information

No response

Operating system

No response

Matplotlib Version

3.11.0.dev52743+g30f4ece.d20250712 (Current main, with above noted modification)

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

git checkout

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions