Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

converting text size into data coordinates

In matplotlib, what is a way of converting the text box size into data coordinates? For example, in this toy script I'm fine-tuning the coordinates of the text box so that it's next to a data point.

#!/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()

Is there a way of doing something like this pseudocode instead?

x = xx[1] - text_height
y = yy[1] - text_width/2
ax.text(x,y,text)
like image 660
ev-br Avatar asked Jun 06 '11 11:06

ev-br


People also ask

How can I convert a text address to geographic coordinates?

The process of converting a real text address to geographic coordinates, for example ("Plaza de Bolívar de Bogotá") into geographic coordinates (like latitude 4.5981206 and longitude -74.0760435), is called Geocoding, you may store this information in your database to place markers on Google maps or any other thing you may imagine.

How do I work with text coordinates and font metrics?

If you need to work with text coordinates and font metrics using the new drawing engine in Graphics Mill, read the Fonts and Measuring Text article. To draw text accurately to pixel level, you need to know the details that describe a font numerically. This information is called font metrics.

How does the coordinate converter work?

The coordinate converter supports different formats of gps coordinates such as decimal degrees (DD) and degrees, minutes and seconds (DMS). When you enter an address, the lat long converter will quickly convert your address to the corresponding gps coordinates.

How to convert latitude and longitude to GPS coordinates?

Type an address or latitude and longitude to start using our gps coordinate converter. Simply type the lat and long coordinate values and press Get Address or the Get GPS Coordinates button above. Reverse geocoded address will also show up on the map coordinates along with latlong.


2 Answers

Generally speaking, you can't get the size of the text until after it's drawn (thus the hacks in @DSM's answer).

For what you're wanting to do, you'd be far better off using annotate.

E.g. ax.annotate('Your text string', xy=(x, y), xytext=(x-0.1, y-0.4))

Note that you can specify the offset in points as well, and thus offset the text by it's height (just specify textcoords='offset points')

If you're wanting to adjust vertical alignment, horizontal alignment, etc, just add those as arguments to annotate (e.g. horizontalalignment='right' or equivalently ha='right')

like image 172
Joe Kington Avatar answered Nov 06 '22 18:11

Joe Kington


I'm not happy with it at all, but the following works; I was getting frustrated until I found this code for a similar problem, which suggested a way to get at the renderer.

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, while this might get the text box out of the actual data point, it doesn't necessarily get the box out of the way of the marker, or the error bar. So I don't know how useful it'll be in practice, but I guess it wouldn't be that hard to loop over all the drawn objects and move the text until it's out of the way. I think the linked code tries something similar.

Edit: Please note that this was clearly a courtesy accept; I would use Joe Kington's solution if I actually wanted to do this, and so should everyone else. :^)

like image 40
DSM Avatar answered Nov 06 '22 16:11

DSM