1
votes

i am new to python's matplotlib and have to plot something, show images and add text underneath. What i have done so far is that (simplified example):

from matplotlib import pyplot as plt
from matplotlib import image as img

fig = plt.figure()
pic = img.imread("image path")

ax1 = fig.add_subplot(121)
ax1.plot()
ax1.set_yticks([0, 1, 2, 3, 4, 5])
ax1.set_xticks([0, 1, 2, 3, 4, 5])

ax1.annotate("Text", xy=(0, -0.12), xycoords="axes fraction")
ax1.annotate("More text", xy=(0, -0.17), xycoords="axes fraction")
ax1.annotate("Even more text", xy=(0, -0.22), xycoords="axes fraction")
ax1.annotate("1", xy=(1, -0.12), xycoords="axes fraction", ha="right")
ax1.annotate("2", xy=(1, -0.17), xycoords="axes fraction", ha="right")
ax1.annotate("3", xy=(1, -0.22), xycoords="axes fraction", ha="right")

ax2 = fig.add_subplot(122)
ax2.imshow(pic)
ax2.axis("off")

ax2.annotate("Text", xy=(0, -0.1), xycoords="axes fraction")
ax2.annotate("More text", xy=(0, -0.2), xycoords="axes fraction")
ax2.annotate("Even more text", xy=(0, -0.3), xycoords="axes fraction")
ax2.annotate("1", xy=(1, -0.1), xycoords="axes fraction", ha="right")
ax2.annotate("2", xy=(1, -0.2), xycoords="axes fraction", ha="right")
ax2.annotate("3", xy=(1, -0.3), xycoords="axes fraction", ha="right")

plt.subplots_adjust(bottom=0.18)
plt.show()

Problem: I would like to have both subplots vertically aligned, so that the text underneath both subplots is also vertically aligned. But images appear always "in the middle" (red pic in the middle of left plot and not same x axis). Is there a possibility to put the image on the x-axis of the plot or does anyone know a better way to add text underneath the two subplots (without annotate)?

What I tried:

  • vary figsize: close but still not aligned (the plot is only squeezed)
  • ax2.imshow(pic, aspect="auto"): this distorts my image
1

1 Answers

0
votes

Blended transformations Ref is used in my code to get the annotation items on the two axes aligned as you need.

from matplotlib import pyplot as plt
from matplotlib import image as img
import matplotlib.transforms as transforms

fig = plt.figure()
pic = img.imread("testimg1.png")  #use your image

ax1 = fig.add_subplot(121)
ax1.plot((1,5,3,2,1,4))           #sample data that fit xy-ticks below
ax1.set_yticks([0, 1, 2, 3, 4, 5])
ax1.set_xticks([0, 1, 2, 3, 4, 5])

# Blended transformation for handling annotation coordinates on `ax1`
trans1 = transforms.blended_transform_factory(ax1.transData, ax1.transAxes)
topy1 = -0.20
dy1 = - 0.07
lx1 = 0
rx1 = 5.0   # max value of x

ax1.annotate("Text1", xy=(lx1, topy1), xycoords=trans1)
ax1.annotate("More text1", xy=(lx1, topy1+dy1), xycoords=trans1)
ax1.annotate("Even more text1", xy=(lx1, topy1+dy1*2), xycoords=trans1)
ax1.annotate("11", xy=(rx1, topy1), xycoords=trans1, ha="right")
ax1.annotate("21", xy=(rx1, topy1+dy1), xycoords=trans1, ha="right")
ax1.annotate("31", xy=(rx1, topy1+dy1*2), xycoords=trans1, ha="right")

ax2 = fig.add_subplot(122)
ax2.axis("off")
ax2.imshow(pic)

# Blended transformation for handling annotation coordinates on `ax2`, ...
#  note that it uses y-axis of `ax1`, thus, make it easy to align items in
#  both axes (vertically)
trans2 = transforms.blended_transform_factory(ax2.transData, ax1.transAxes)
topy2 = topy1   # possible with `trans2`
dy2 = dy1
lx2 = 0
rx2 = pic.shape[1]  #width of `pic` image

ax2.annotate("Text2", xy=(lx2, topy2), xycoords=trans2)
ax2.annotate("More text2", xy=(lx2, topy2+dy2), xycoords=trans2)
ax2.annotate("Even more text2", xy=(lx2, topy2+dy2*2), xycoords=trans2)
ax2.annotate("12", xy=(rx2, topy2), xycoords=trans2, ha="right")
ax2.annotate("22", xy=(rx2, topy2+dy2), xycoords=trans2, ha="right")
ax2.annotate("32", xy=(rx2, topy2+dy2*2), xycoords=trans2, ha="right")

plt.subplots_adjust(bottom=0.18)
plt.show()

The output plot:

output-plot