Skip to content

DOC: nudges legend position in tutorial to be within graph area #12377

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

Conversation

deniederhut
Copy link

PR Summary

The tutorial on constrained layout has an example showing the (recommended) approach of placing a legend on the figure object to avoid shrinking a bunch of other stuff. However, the legend runs off the edge of the plot figure, which seems a bit undesirable. This commit bumps the anchor point a bit so everything fits.

Before

screenshot 2018-10-03 02 35 27

After

screenshot 2018-10-03 02 41 19

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@anntzer anntzer requested a review from jklymak October 3, 2018 08:07
@timhoffm
Copy link
Member

timhoffm commented Oct 3, 2018

I think, at least the first part is intended to demonstrate that cropping may happen:

Of course this can mean the legend ends up cropped,

However, I don't follow the overall argument of that section.

@jklymak Why would I want to take the legend out of the layout? Clipping is always undesirable. If I want the legend not to steal space from the subplot layout, I should place it in a way that it's within the subplot grid. IMO that's what should be demonstrated here (e.g. something like legend(loc='center right', bbox_to_anchor=(1, 0.15))).

@ImportanceOfBeingErnest
Copy link
Member

ImportanceOfBeingErnest commented Oct 3, 2018

This section is intended to show how to opt out of the contrained-layout mechanism for a legend. This is desireable in any case where you don't want your grid layout be affected by the legend. One reason for that is given in the text,

but can be useful if the plot is subsequently called with fig.savefig('outname.png', bbox_inches='tight')

The two options described here are (1) use set_in_layout(False) (2) use fig.legend instead of ax.legend. It makes sense that both options show the same figure.

The confusion may be due to the second example not having the fig.savefig line in it? So it might make sense to add it to the second case as well.

If you put the legend into the axes as proposed here, there would not be any need to opt out of constrained-layout at all.

@jklymak
Copy link
Member

jklymak commented Oct 3, 2018

Thanks for the PR @deniederhut

However, as noted above, the point of the example is that the legend is off the edge of the plot and cropped. If the pre-amble is not clear on this point, please let us know!

@jklymak jklymak closed this Oct 3, 2018
@timhoffm
Copy link
Member

timhoffm commented Oct 3, 2018

Can we add a positive example of when/why to exclude the legend from the layout? So far we're only explaining that there is some danger in doing so because it can clip the legend.

@ImportanceOfBeingErnest
Copy link
Member

No, there is no danger, or at least there shouldn't be any. The problem is, just looking at the pictures the wrong expectation is created. The picture that is shown is the desired and expected. Reading the text, I find this pretty understandable. The point would be crystal clear if the figure saved by fig.savefig('outname.png', bbox_inches='tight') was shown next to the existing plot.

But... The code does not seem to be runnable and does not give a sensible result. I used this code

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flatten()[:-1]:
    ax.plot(np.arange(10))
axs[1, 1].plot(np.arange(10), label='This is a plot')
leg = axs[1, 1].legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
leg.set_in_layout(False)
wanttoprint = True
if wanttoprint:
    leg.set_in_layout(True)
    fig.do_constrained_layout(False)
    fig.savefig('outname.png', bbox_inches='tight')
plt.show()

i.e. the code from the matplotlib 3.0 documentation with wanttoprint = True but it gives an error AttributeError: 'Figure' object has no attribute 'do_constrained_layout'.

Assuming that what is meant here is set_constrained_layout, the problem is that the figure shown deviates from the one obtained via wanttoprint = False. So it seems it's not possible to show the figure after saving it?

Using the second code (the one with fig.legend()) everything works as expected.

In my eyes there are the following things to do:

  1. Correct the first code to be runnable and produce the expected outcome for both settings of wanttoprint on screen and as saved image.
  2. Explain the reasoning behind turning the legend in layout option first off then on etc.
  3. Add a savefig line to the second example to make is clear that this is to be understood parallel to the previous example.

@jklymak
Copy link
Member

jklymak commented Oct 3, 2018

Agreed, opened new issue...

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

Successfully merging this pull request may close these issues.

5 participants