Reputation: 438
I'm trying to get the legend location in matplotlib. It seems like Legend.get_window_extent() should provide this, but it returns the same value regardless of where the legend is located. Here is an example:
from matplotlib import pyplot as plt
def get_legend_pos(loc):
plt.figure()
plt.plot([0,1],label='Plot')
legend=plt.legend(loc=loc)
plt.draw()
return legend.get_window_extent()
if __name__=='__main__':
# Returns a bbox that goes from (0,0) to (1,1)
print get_legend_pos('upper left')
# Returns the same bbox, even though legend is in a different location!
print get_legend_pos('upper right')
What is the correct way to get the legend location?
Upvotes: 3
Views: 2752
Reputation: 339092
You would need to replace plt.draw()
by
plt.gcf().canvas.draw()
or, if you have a figure handle, fig.canvas.draw()
. This is needed because the legend position is only determined when the canvas is drawn, beforehands it just sits in the same place.
Using plt.draw()
is not sufficient, because the drawing the legend requires a valid renderer from the backend in use.
Upvotes: 3
Reputation: 3767
TL DR; Try this:
def get_legend_pos(loc):
plt.figure()
plt.plot([0,1],label='Plot')
legend=plt.legend(loc=loc)
plt.draw()
plt.pause(0.0001)
return legend.get_window_extent()
Here is why
So I tried your code in Jupyter and I can reproduce the behavior with option
%matplotlib notebook
However for
%matplotlib inline
I am getting correct response
Bbox(x0=60.0, y0=230.6, x1=125.69999999999999, y1=253.2)
Bbox(x0=317.1, y0=230.6, x1=382.8, y1=253.2)
It looks like in the first case the legend position is not evaluated until the execution finishes. Here is an example that proves it, in the first cell I execute
fig = plt.figure()
plt.plot([0,1],label='Plot')
legend=plt.legend(loc='upper left')
plt.draw()
print(legend.get_window_extent())
Outputs Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0)
.
In the next cell re-evaluate the last expression
print(legend.get_window_extent())
Outputs Bbox(x0=88.0, y0=396.2, x1=175.725, y1=424.0)
You probably just need to add plt.pause()
to enforce the evaluation.
Upvotes: 2