Reputation: 13
I run into what seems to be a bug in matplotlib (version 1.4.3
)/pyplot when attempting to draw a line between subplots: after setting set_aspect("equal")
, it appears the relevant coordinate transformation functions (transData
) don't update. Execute the code below with ax.set_aspect("equal")
uncommented to see the difference.
import matplotlib.pyplot as plt
import matplotlib as mpl
f, (ax1, ax2) = plt.subplots(1, 2, sharey='all', sharex='all')
for ax in (ax1, ax2):
# ax.set_aspect("equal")
ax.set_ylim([-.2, 1.2])
ax.set_xlim([-.2, 1.2])
# From http://stackoverflow.com/questions/17543359/drawing-lines-between-two-plots-in-matplotlib
transFigure = f.transFigure.inverted()
coord1 = transFigure.transform(ax1.transData.transform([0,0]))
coord2 = transFigure.transform(ax2.transData.transform([1,0]))
line = mpl.lines.Line2D((coord1[0],coord2[0]),(coord1[1],coord2[1]),
transform=f.transFigure)
f.lines.append(line)
plt.show()
The relevant images are here (1) and here (2).
Upvotes: 1
Views: 665
Reputation: 30210
cge is right with his assessment of why, but for me, his code produced:
The x-limits are getting confused because they're supposed to match the y-limits and be equal.
To fix this, you can adjust your figure size to something more appropriate with the figsize
keyword argument to subplots. In the following code, I chose 10in x 5in.
import matplotlib.pyplot as plt
import matplotlib as mpl
f, (ax1, ax2) = plt.subplots(1, 2, sharey='all', sharex='all', figsize=(10,5))
for ax in (ax1, ax2):
ax.set_aspect("equal")
ax.set_ylim([-.2, 1.2])
ax.set_xlim([-.2, 1.2])
plt.draw()
# From http://stackoverflow.com/questions/17543359/drawing-lines-between-two-plots-in-matplotlib
transFigure = f.transFigure.inverted()
coord1 = transFigure.transform(ax1.transData.transform([0,0]))
coord2 = transFigure.transform(ax2.transData.transform([1,0]))
line = mpl.lines.Line2D(
(coord1[0],coord2[0]),
(coord1[1],coord2[1]),
transform=f.transFigure)
f.lines.append(line)
plt.show()
This produces:
Upvotes: 0
Reputation: 9890
The problem you're having is that set_aspect
isn't applied until after a draw operation. Thus when you're making the line, the limits haven't been changed. Notice the different x limits in your second image, while the line is in the same place: the line is drawn as though the x limits didn't change, because they hadn't been changed yet, and wouldn't be changed until plt.show()
. The solution to this is to add a plt.draw()
after you do set_aspect
, but before you start working on the transforms. The following code does this, with print statements that make clear the issue with the limits and transforms at different times:
import matplotlib.pyplot as plt
import matplotlib as mpl
f, (ax1, ax2) = plt.subplots(1, 2, sharey='all', sharex='all')
for ax in (ax1, ax2):
ax.set_ylim([-.2, 1.2])
ax.set_xlim([-0.2, 1.2])
transFigure = f.transFigure.inverted()
print ax1.get_xlim(), ax1.transData.transform([0,0])
for ax in (ax1, ax2):
ax.set_aspect('equal')
print ax1.get_xlim(), ax1.transData.transform([0,0])
plt.draw()
print ax1.get_xlim(), ax1.transData.transform([0,0])
coord1 = transFigure.transform(ax1.transData.transform([0,0]))
coord2 = transFigure.transform(ax2.transData.transform([1,0]))
line = mpl.lines.Line2D((coord1[0],coord2[0]),(coord1[1],coord2[1]),
transform=f.transFigure)
f.lines.append(line)
plt.show()
This point should really be added to the docstring for set_aspect, and I'll see if I can do that. It's not a bug: the aspect can't really be determined until after the plot is ready to be drawn.
Upvotes: 1