Hi all, Is there a way to get the size of a text object? I
> can't seem to find a method that does that. The
> functionality must be in there somewhere, or having
> different reference points wouldn't work.
The size of a text object is tricky. Do you mean the width and height
in points? Or in data coords? The x,y location of text is in one
coordinate system (axes, figure or data), but the width and height are
not. To convert between coordinate systems (eg points or display
versus data) the way mpl does it is to one transform coord system to
display and use the other coordinate system to inverse transform.
This would enable you to get, for example, a text bounding box in data
coords, but could be screwed up by a figure resize.
If you tell me more precisely what you are trying to achieve, I might
be able to help you or think about design changes to accommodate it.
FYI, this is an issue that crops up a lot and is vexing. What one
would like to be able to do is use a layout engine and say, place
object one above and to the right of object 2 with a pad of 2 points.
The text instance can give you its bounding box in display if you pass
it the backend renderer -- this is required because the width and
height can be backend dependent. I suppose you are using OO agg based
on your previous posts. One problem with the current design that is
that the agg canvas doesn't generate it's renderer until draw time
(with caching), but you need access to the renderer before draw time
for layout that depends on text. If we move this logic to a
get_renderer method, you can use it at draw time. I'll attach a
replacement backend_agg.FigureCanvasAgg class to support this below
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
fig = Figure()
canvas = FigureCanvasAgg(fig)
renderer = canvas.get_renderer()
ax = fig.add_subplot(111)
ax.plot([1,2,3])
t = ax.text(1,2,'hi mom')
bbox = t.get_window_extent(renderer)
print 'display', bbox.get_bounds() #l,b,w,h
# get the axes data coords bbox of this display bounding box
from matplotlib.transforms import inverse_transform_bbox
axbox = inverse_transform_bbox(ax.transData, bbox)
print 'data coords', axbox.get_bounds()
fig.savefig('test')
In backend_agg.py FigureCanvasAgg, replace the draw method with the following 2
methods
def draw(self):
"""
Draw the figure using the renderer
"""
if __debug__: verbose.report('FigureCanvasAgg.draw', 'debug-annoying')
renderer = self.get_renderer()
self.figure.draw(renderer)
def get_renderer(self):
l,b,w,h = self.figure.bbox.get_bounds()
key = w, h, self.figure.dpi.get()
try: self._lastKey, self.renderer
except AttributeError: need_new_renderer = True
else: need_new_renderer = (self._lastKey != key)
if need_new_renderer:
self.renderer = RendererAgg(w, h, self.figure.dpi)
self._lastKey = key
return self.renderer
Hope this gets you started -- if you provide more details we maybe
able to improve from here.
JDG