'Calculating Matplotlib Text Rotation [duplicate]
I'm trying to figure out how to rotate text in matplotlib to align to a curve in a plot, but I haven't figured what transformations give the proper coordinate system for rotating text to match a specific slope in data coordinates. Here's a minimal example of drawing a line and trying to align some text along it:
# Make some really non-square figure
plt.figure(figsize=(2,5))
# Draw some line between two points
pB=np.array((0,0))
pA=np.array((1,2))
pC=(pA+pB)/2
plt.plot(*zip(pA,pB))
# All the transforms at our disposal
tD=plt.gca().transData
tA=plt.gca().transAxes
tF=plt.gcf().transFigure
# Transform the endpoints of the line two some coordinate system
pA,pB=[
##### What goes here???
p # <- trivial no transform
#tD.transform(p)
#tA.inverted().transform(tD.transform(p))
#tF.inverted().transform(tD.transform(p))
for p in (pA,pB)]
# Then calculate the angle of the line
rise,run=pA-pB
rot=(180/np.pi)*np.arctan(rise/run)
# Draw some text at that angle
plt.text(pC[0],pC[1],'hi there',rotation=rot,
horizontalalignment='center',verticalalignment='bottom');
No matter what I try, the text is still misoriented:
[this image is for the no-transform case above, rendered by the %matplotlib inline
option in a Jupyter notebook.]
Solution 1:[1]
As suggested in the comments, you may want to include the proportional relationship between the abstract representation (axis size) and the actual figure (figure size). The rotation angle of the text is an absolute measure when the angle of the curve depends on the axis' scales
# define the figure size
fig_x, fig_y = 4, 8
plt.figure(figsize=(fig_x, fig_y))
# Draw some line between two points
pB = np.array((0, 0))
pA = np.array((1, 2))
pC = (pA+pB)/2
plt.plot(*zip(pA, pB))
# Calculate the angle of the line
dx, dy = pA-pB
# --- retrieve the 'abstract' size
x_min, x_max = plt.xlim()
y_min, y_max = plt.ylim()
# --- apply the proportional conversion
Dx = dx * fig_x / (x_max - x_min)
Dy = dy * fig_y / (y_max - y_min)
# --- convert gaps into an angle
angle = (180/np.pi)*np.arctan( Dy / Dx)
# Draw text at that angle
plt.text(pC[0], pC[1], 'it worked', rotation=angle,
horizontalalignment='center', verticalalignment='bottom')
plt.show()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Trenton McKinney |