camo
camo

Reputation: 551

matplotlib rotated text has an offset

I'm trying to draw some text within the boundaries of some lines. The lines can be rotated and therefore the text also needs to be rotated.

When I add the text without rotation, it seems to have the correct placement and size. After rotation though, it does not (best explained when you take a look at the picture).

Here is what I tried:

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(1)
fig.set_dpi( 100 )
fig.set_size_inches( 1, 1 )

# Plot diagonal line (45 degrees)
ax.plot((0, 0),(0, 10))
ax.plot((10, 10), (0, 10))
ax.plot((0, 10), (10, 10))
ax.plot((0, 10), (0, 0))
ax.plot((0,10),(1.3,1.3)) # font size 10 has 13 pixels, hence 1.3
ax.plot((3,10),(3,10))

# compute the offset of the line that is exactly 1.3 above the diagonal
d = np.array([-1,1])
d = d / np.sqrt(sum(d**2)) * 1.3
u = np.array([3,3]) + d
ax.plot( (u[0], 10+u[0]-u[1]), (u[1], 10 ))

# set limits so that it no longer looks on screen to be 45 degrees
ax.set_xlim([0, 10])
ax.set_ylim([0, 10])

# Plot text
ax.text(0,0, 'In', fontsize=10 )
ax.text(4,0, 'Bbox', fontsize=10, bbox={"pad":0} )
ax.text(3,3, 'Out', fontsize=10, rotation=45, verticalalignment="bottom", \
    horizontalalignment="left", rotation_mode="anchor" )
ax.text(6,6, 'Bbox', fontsize=10, rotation=45, verticalalignment="bottom", \
    horizontalalignment="left", rotation_mode="anchor",bbox={"pad":0} )
plt.axis("off")
plt.savefig( "test.pdf", bbox_inches="tight" )

This gives me the following output. Plot with rotated but offset text:

Plot with rotated but offset text

Note that the "Out" does not exactly fit within its two adjacent lines, as intended. Anybody an idea on how to adjust/fix this?

Upvotes: 1

Views: 693

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339340

For the "In" text, you use verticalalignment="baseline" (implicitely, because it's the default). For the "Out" text you use verticalalignment="bottom" instead.

You may change this to verticalalignment="baseline" as well, or just leave it out completely.

ax.text(0,0, 'In', fontsize=10 )
ax.text(4,0, 'Bbox', fontsize=10, bbox={"pad":0} )
ax.text(3,3, 'Out', fontsize=10, rotation=45, 
        horizontalalignment="left", rotation_mode="anchor" )
ax.text(6,6, 'Bbox', fontsize=10, rotation=45, 
        horizontalalignment="left", rotation_mode="anchor",bbox={"pad":0} )

enter image description here

There is a nice example, Demo text rotation mode, on the matplotlib website, that explains this behaviour.

Upvotes: 1

Related Questions