Reputation: 3182
I'm looking for a way of exactly aligning (overlaying) the corner edge of my image with corner and edge of a text box edge (bbox or other)
The code in question is:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1)
ax.imshow(np.random.random((256,256)), cmap=plt.get_cmap("viridis"))
ax.axis("off")
ax.annotate(
s = 'image title',
xy=(0, 0),
xytext=(0, 0),
va='top',
ha='left',
fontsize = 15,
bbox=dict(facecolor='white', alpha=1),
)
plt.show()
As you can see, the edges of the text box is outside the image. For the life of me, I cannot find a consistent way of aligning the corner of the text box with the corner of the image. Ideally, I'd like the alignment to be independent of font size and image pixel size, but that might be asking a bit too much.
Finally, I'd like to achieve this with a grid of images, like the second example, below.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 8))
images = 4*[np.random.random((256,256))]
gs = gridspec.GridSpec(
nrows=2,
ncols=2,
top=1.,
bottom=0.,
right=1.,
left=0.,
hspace=0.,
wspace=0.,
)
for g, i in zip(gs, range(len(images))):
ax = plt.subplot(g)
im = ax.imshow(
images[i],
cmap=plt.get_cmap("viridis")
)
ax.set_xticks([])
ax.set_yticks([])
ax.annotate(
s = 'image title',
xy=(0, 0),
xytext=(0, 0),
va='top',
ha='left',
fontsize = 15,
bbox=dict(facecolor='white', alpha=1),
)
Upvotes: 5
Views: 1698
Reputation: 3182
Thanks to P-robot for the solution. The key part of the solution is that the annotation text edge is offset x and y by one pixel from the xy
coordinate. Any extra padding used increases the necessary amount to compensate for this offset. The second grouping of arguments given to ax.annotate
, below, are the relevant ones.
fig, ax = plt.subplots(1)
ax.imshow(np.random.random((256,256)), cmap=plt.get_cmap("viridis"))
ax.axis("off")
padding = 5
ax.annotate(
s = 'image title',
fontsize = 12,
xy=(0, 0),
xytext=(padding-1, -(padding-1)),
textcoords = 'offset pixels',
bbox=dict(facecolor='white', alpha=1, pad=padding),
va='top',
ha='left',
)
plt.show()
Oddly, for the grid of four images, the offset in the x-direction did not require the subtraction of one pixel, which changes xytext
to xytext=(padding, -(padding-1))
.
Upvotes: 5
Reputation: 4904
The issue is caused from the padding of the bounding box. You can change the padding by passing the pad
argument to the bounding box dictionary (for instance pad = 0
will keep the box inside the axes). I'm assuming you want some padding so it's probably best to set a padding argument and remove this from the position of the annotation (in units of pixels).
Upvotes: 3