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)
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.
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.
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.
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.
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'
)
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. :^)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With