преобразование размера текста в координаты данных

#python #matplotlib

#python #matplotlib

Вопрос:

Каков способ преобразования размера текстового поля в координаты данных в matplotlib? Например, в этом игрушечном скрипте я точно настраиваю координаты текстового поля так, чтобы оно находилось рядом с точкой данных.

 #!/usr/bin/python 
import matplotlib.pyplot as plt

xx=[1,2,3]
yy=[2,3,4]
dy=[0.1,0.2,0.05]

fig=plt.figure()
ax=fig.add_subplot(111)

ax.errorbar(xx,yy,dy,fmt='ro-',ms=6,elinewidth=4)

# HERE: can one get the text bbox size?
txt=ax.text(xx[1]-0.1,yy[1]-0.4,r'$S=0$',fontsize=16)

ax.set_xlim([0.,3.4])
ax.set_ylim([0.,4.4])

plt.show()
  

Есть ли способ сделать что-то вроде этого псевдокода вместо этого?

 x = xx[1] - text_height
y = yy[1] - text_width/2
ax.text(x,y,text)
  

Ответ №1:

Вообще говоря, вы не можете получить размер текста до тех пор, пока он не будет отрисован (отсюда и хаки в ответе @DSM).

Для того, что вы хотите сделать, вам было бы намного лучше использовать annotate .

Например. ax.annotate('Your text string', xy=(x, y), xytext=(x-0.1, y-0.4))

Обратите внимание, что вы также можете указать смещение в точках и, таким образом, сместить текст на его высоту (просто укажите textcoords='offset points' )

Если вы хотите настроить выравнивание по вертикали, горизонтали и т.д., Просто добавьте их в качестве аргументов в annotate (например, horizontalalignment='right' или эквивалентно ha='right' )

Ответ №2:

Я совсем не доволен этим, но следующее работает; я был разочарован, пока не нашел этот код для аналогичной проблемы, который подсказал способ добраться до средства визуализации.

 import matplotlib.pyplot as plt

xx=[1,2,3]
yy=[2,3,4]
dy=[0.1,0.2,0.05]

fig=plt.figure()
figname = "out.png"
ax=fig.add_subplot(111)

ax.errorbar(xx,yy,dy,fmt='ro-',ms=6,elinewidth=4)

# start of hack to get renderer
fig.savefig(figname)
renderer = plt.gca().get_renderer_cache()
# end of hack

txt = ax.text(xx[1], yy[1],r'$S=0$',fontsize=16)
tbox = txt.get_window_extent(renderer)
dbox = tbox.transformed(ax.transData.inverted())
text_width = dbox.x1-dbox.x0
text_height = dbox.y1-dbox.y0
x = xx[1] - text_height
y = yy[1] - text_width/2
txt.set_position((x,y))

ax.set_xlim([0.,3.4])
ax.set_ylim([0.,4.4])

fig.savefig(figname)
  

OTOH, хотя это может вывести текстовое поле из точки фактических данных, это не обязательно уберет поле с пути маркера или строки ошибок. Так что я не знаю, насколько это будет полезно на практике, но я думаю, что было бы не так сложно перебирать все нарисованные объекты и перемещать текст, пока он не исчезнет с дороги. Я думаю, что связанный код пытается сделать что-то подобное.

Редактировать: Пожалуйста, обратите внимание, что это было явно принято из вежливости; я бы использовал решение Джо Кингтона, если бы я действительно хотел это сделать, и так должны все остальные. : ^)

Комментарии:

1. Вау, это круто! В моем конкретном случае annotate () выполняет свою работу, как указал Джо, но ваш трюк просто такой классный. Огромное спасибо!