-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
savefig
messes up coordinate transformation of annotate
#4375
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
Comments
Strangely enough, when commenting out the |
@PiQuer are you saying that explicitly calling I'm running in to this exact issue, I think, see my griping here. |
BTW different weirdness happens whether I save as PDF or PNG |
attn: @mdboom. From the looks of it, it seems like the transform stack of On Wed, Jul 29, 2015 at 8:29 AM, Adrian Price-Whelan <
|
I wonder if this is fixed by #4843 |
no 😞 not fixed that branch. |
Maybe (?) related to #2831 (comment) |
@adrn That sort of griping is not the most effective at making devs want to help you. Without seeing your code I suspect you are using display-space units at some point which you should not be doing. Please open a new issue or send a note to the mailing list. @PiQuer Does this work reliably on any version of mpl? Trying to sort out if this is a regression or a long standing bug. I suspect this issues is related to the use of the inset axes which has some non-trivial logic in how it's transforms get managed. The inset axes has it's transforms defined in terms of the transforms of the parent axes. Currently the details of those transforms get set up (somehow, have not traced the code path yet) as part of the draw process off the inset axes. When it is initialized it's transforms have some default value. The annotation in the above code is a child of the inset axes. The way the draw tree is worked is that the parent axes, then all it's children, then the inset axes, then all of it's children are drawn. The source of the error here is that the annotation is drawn before the inset axes is drawn, and hence before it's transforms have been updated to reflect that it is an inset axes. The simplest work around is to just make the annotation belong to the inset axes so it is always drawn after the transfroms have been properly updated: import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
x=np.linspace(0,10,200)
y=np.exp(-x)*np.sin(x)
fig,ax = plt.subplots(figsize=(3.39,3))
ax.plot(x,y)
axins=inset_axes(ax, width=0.6, height=0.6, bbox_to_anchor=(6, 0.2),bbox_transform=ax.transData)
axins.axes.get_xaxis().set_visible(False)
axins.axes.get_yaxis().set_visible(False)
axins.annotate("",xy=(x[150],y[150]), xycoords=ax.transData,
xytext=(1, 0), textcoords=axins.transAxes,
arrowprops=dict(arrowstyle="->"), clip_on=False)
fig.savefig('example.pdf')
plt.show() (the Removing this from the next point release milestone because:
cc @leejjoon |
I will try to test in a couple of days, at the moment unfortunately I have no time to do it. |
I know this is rather old, but I will make a quick comment as this is still open. Maybe, we'd better create a new general issue for the discussion (and assemble all the related issues under it)? |
FWIW: import matplotlib.pyplot as plt
import numpy as np
x=np.linspace(0,10,200)
y=np.exp(-x)*np.sin(x)
fig,ax = plt.subplots(figsize=(3.39,3))
ax.plot(x,y)
axins = ax.inset_axes([0.4, 0.5, 0.3, 0.3])
axins.axes.get_xaxis().set_visible(False)
axins.axes.get_yaxis().set_visible(False)
ax.annotate("",xy=(x[150],y[150]), xycoords=ax.transData,
xytext=(1, 0), textcoords=axins.transAxes,
arrowprops=dict(arrowstyle="->"))
fig.savefig('example.pdf')
plt.show() Works fine on master. |
I guess this works because the inset location is given in normalized axes coordinate, so its location is unchanged during its draw process. If you put 'axins.set_aspect(1.)', you will see that the location of the arrow becomes incorrect. |
Yes, agreed - had the same problem w/ inset axes locators. Lets start a new issue with as simple as possible a failing case and maybe we can work out a fix. But I think you are correct that the issue is the draw process sometimes needs to iterate, or at least be done twice before complicated layouts will work. Calling A dangerous idea is for when the figure gets drawn call import matplotlib.pyplot as plt
import numpy as np
x=np.linspace(0,10,200)
y=np.exp(-x)*np.sin(x)
fig,ax = plt.subplots(figsize=(3.39,3))
ax.plot(x,y)
axins = ax.inset_axes([0.4, 0.5, 0.3, 0.3])
axins.xaxis.set_visible(False)
axins.yaxis.set_visible(False)
axins.set_aspect(0.2)
ax.annotate("",xy=(x[150],y[150]), xycoords=ax.transData,
xytext=(1, 0), textcoords=axins.transAxes,
arrowprops=dict(arrowstyle="->"))
axins.apply_aspect()
fig.savefig('example.pdf')
plt.show() |
Closing because this seems to be fixed by #11753. At least the pdf and screen output are now the same. |
I want to annotate a data point with an inset axis (matplotlib-1.4.3, Linux):
This is the correct plot shown on screen:


This is what
savefig
produces:Apparently
savefig
changes the coordinates(1,0)
from the inset axes to the parent axes for some reason.The text was updated successfully, but these errors were encountered: