You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When retrieving handles used in legend, marker property is not kept.
Code for reproduction
importmatplotlib.pyplotaspltpoint=plt.Line2D([1],[1], marker='o')
legend=plt.gcf().legend(handles=[point], labels=['point'])
# First wayhandles=legend.legendHandleshandles[0].get_marker()
# Second waylines=legend.get_lines()
lines[0].get_marker()
Actual outcome
Out[1]: ''
Expected outcome
When plotting an Axes legend, get_legend_handles_labels() can be used, which does return the right marker. There isn't such a method in Figure, so when using Legend methods or properties such as legend.get_lines() or legend.legendHandles, line2D marker isn't kept.
Is there a better way of retrieving handles from a legend?
Am I doing something wrong?
First, there is no difference between the axes and figure hadnling of the legend artists. ax.get_legend_handles_labels() is called beforelegend() to gather the needed artists from the axes. You could loop through all your axes as figure.legend does:
The solution to your mystery, however, is contained in legend_handler.py, where it was decided that text and lines must correspond one-to-one. So if you want the handle to the marker, you can do:
for h in leg.get_lines():
print(h._legmarker.get_marker())
This is pretty hacky, and the undrscore means it could go away.
Its a little strange to want the marker after the legend has been created. Why don't you just make the legend refer to something you've already drawn and keep track of what you've drawn? The legend doesn't seem like a good place to store the state of your plotting.
Thank you for your answers. @jklymak I understand now the way get_legend_handles_labels() works.
Why don't you just make the legend refer to something you've already drawn and keep track of what you've drawn? The legend doesn't seem like a good place to store the state of your plotting.
You are right, we shouldn't rely on the legend to store our plotting state.
Activity
jklymak commentedon Sep 5, 2017
Not sure what the issue is with figure legends, but you can achieve the same effect with an axes legend using something like:
(note
center topin this case sets the vertical and horizontal justification; the actual location is inbbox_to_anchor.)Maybe that is an acceptable workaround.
I am working on a way to make this automatically resize the parent axis but that'll be 2.2 or later (see #9082).
astrojuanlu commentedon Sep 5, 2017
@jklymak thank you for your suggestion - however it is a limited workaround, since axes only support one legend whereas figures support more of them.
Above all, we are interested in finding out whether this is a bug or a feature :)
jklymak commentedon Sep 5, 2017
@Juanlu001 @anhiga
First, there is no difference between the
axesandfigurehadnling of the legend artists.ax.get_legend_handles_labels()is called beforelegend()to gather the needed artists from the axes. You could loop through all your axes asfigure.legenddoes:The solution to your mystery, however, is contained in
legend_handler.py, where it was decided that text and lines must correspond one-to-one. So if you want the handle to the marker, you can do:This is pretty hacky, and the undrscore means it could go away.
Its a little strange to want the marker after the legend has been created. Why don't you just make the legend refer to something you've already drawn and keep track of what you've drawn? The legend doesn't seem like a good place to store the state of your plotting.
anhiga commentedon Sep 6, 2017
Thank you for your answers.
@jklymak I understand now the way
get_legend_handles_labels()works.You are right, we shouldn't rely on the legend to store our plotting state.
I'm closing this.