Skip to content

SubFigure legend not included in figure bounding box #20736

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
tomneep opened this issue Jul 24, 2021 · 6 comments
Closed

SubFigure legend not included in figure bounding box #20736

tomneep opened this issue Jul 24, 2021 · 6 comments
Milestone

Comments

@tomneep
Copy link
Contributor

tomneep commented Jul 24, 2021

Bug report

Bug summary

This relies on #20723 being addressed.

As reported in a comment on that issue, a legend added to a SubFigure is not included when calculating the bbox of the parent figure and so the subfigure legend is cut off the plot when saving a figure with bbox_inches="tight".

Code for reproduction

import matplotlib.pyplot as plt
fig = plt.figure()
subfig = fig.subfigures()
ax = subfig.subplots()
ax.plot([0, 1, 2], [0, 1, 2], label="test")
subfig.legend()
print(fig.get_default_bbox_extra_artists())
plt.savefig("test.png", bbox_inches="tight")

Actual outcome

test

[<matplotlib.figure.SubFigure at 0x7fc17864e700>,
 <matplotlib.lines.Line2D at 0x7fc17874aa90>,
 <matplotlib.spines.Spine at 0x7fc178612700>,
 <matplotlib.spines.Spine at 0x7fc178612910>,
 <matplotlib.spines.Spine at 0x7fc178612c70>,
 <matplotlib.spines.Spine at 0x7fc17864e5e0>,
 <matplotlib.axis.XAxis at 0x7fc178612c10>,
 <matplotlib.axis.YAxis at 0x7fc17864ed60>,
 <matplotlib.patches.Rectangle at 0x7fc178738730>]

Expected outcome

The subfigure legend should be included in the bbox.

test

Matplotlib version

  • Operating system: Mac OS 11.4
  • Matplotlib version (import matplotlib; print(matplotlib.__version__)): 3.4.2
  • Matplotlib backend (print(matplotlib.get_backend())): TkAgg
  • Python version: 3.8.3
@jklymak
Copy link
Member

jklymak commented Jul 24, 2021

I think the Figure's extra artists should only be the SubFigures, and anything added at the Figure level. I don't think things at the SubFigure level should bubble up to the Figure level.

OTOH there are issues here that will require some thought. Folks enjoy adding legends outside the figure, and then letting bbox_inches='tight' expand the figure to match. Its hard to know how that will be compatible with SubFigure.

@jklymak jklymak added this to the v3.5.0 milestone Jul 24, 2021
@tomneep
Copy link
Contributor Author

tomneep commented Jul 24, 2021

Folks enjoy adding legends outside the figure, and then letting bbox_inches='tight' expand the figure to match. Its hard to know how that will be compatible with SubFigure.

Yes in fact this is exactly how I ran into this problem. I wanted to add a legend outside the axes of the subfigure.

I've removed my suggestion from the issue, because there are problems with that too (what if there was a figure legend or other figure artists not associated with subfigures for example)

@jklymak
Copy link
Member

jklymak commented Jul 24, 2021

Yeah, that is my main point - Figure and SubFigure should be different from one another (probably).

@tomneep
Copy link
Contributor Author

tomneep commented Jul 24, 2021

I had a quick investigation and ignoring the fact that fig.get_default_bbox_extra_artists() includes stuff it perhaps shouldn't, I think the problem seems to be that FigureBase.get_tightbbox() returns the bounding box in figure inches. I think this is probably wrong for a SubFigure. As a quick test, I just added a return in FigureBase.get_tightbbox() here

_bbox = Bbox.union(bb)
bbox_inches = TransformedBbox(_bbox, Affine2D().scale(1 / self.dpi))
return bbox_inches

such that _bbox is returned (instead of bbox_inches) if self is a SubFigure. This at least keeps the legend in the figure but breaks test_subfigure_tightbbox so some more investigation is needed. I'm not proposing this as the solution but hopefully this give some hint as to why even though the SubFigure is in the list from fig.get_default_bbox_extra_artists() we don't seem to get the right bbox.

@QuLogic QuLogic modified the milestones: v3.5.0, v3.5.1 Nov 15, 2021
@QuLogic QuLogic modified the milestones: v3.5.1, v3.5.2 Dec 10, 2021
@oscargus
Copy link
Member

Executing the code on current main branch leads to:

[<matplotlib.figure.SubFigure object at 0x00000185331DE340>,
<matplotlib.spines.Spine object at 0x00000185331DEA60>,
<matplotlib.spines.Spine object at 0x00000185331DEB50>,
<matplotlib.spines.Spine object at 0x00000185331DEC40>,
<matplotlib.spines.Spine object at 0x00000185331DED30>,
<matplotlib.patches.Rectangle object at 0x000001853321F5E0>]

so the line is no longer there. On the other hand, the resulting image looks like:
test

@tomneep
Copy link
Contributor Author

tomneep commented Feb 20, 2022

Thanks @oscargus. It looks to me like this was fixed by #21845 and can be closed.

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

No branches or pull requests

4 participants