Revision: 7440
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7440&view=rev
Author: leejjoon
Date: 2009-08-09 19:38:48 +0000 (Sun, 09 Aug 2009)
Log Message:
-----------
AnnotationBbox implemented.
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/lib/matplotlib/offsetbox.py
trunk/matplotlib/lib/matplotlib/text.py
trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py
Added Paths:
-----------
trunk/matplotlib/examples/pylab_examples/demo_annotation_box.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-08-09 19:25:49 UTC (rev 7439)
+++ trunk/matplotlib/CHANGELOG 2009-08-09 19:38:48 UTC (rev 7440)
@@ -1,3 +1,7 @@
+2009-08-09 AnnotationBbox added. Similar to Annotation, but works with
+ OffsetBox instead of Text. See the example
+ demo_annotation_box.py. -JJL
+
2009-08-07 BboxImage implemented. Two examples, demo_bboximage.py and
demo_ribbon_box.py added. - JJL
Added: trunk/matplotlib/examples/pylab_examples/demo_annotation_box.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/demo_annotation_box.py
(rev 0)
+++ trunk/matplotlib/examples/pylab_examples/demo_annotation_box.py
2009-08-09 19:38:48 UTC (rev 7440)
@@ -0,0 +1,94 @@
+import matplotlib.pyplot as plt
+from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, \
+ AnnotationBbox
+from matplotlib.cbook import get_sample_data
+
+import numpy as np
+
+if 1:
+ fig = plt.gcf()
+ fig.clf()
+ ax = plt.subplot(111)
+
+ offsetbox = TextArea("Test 1", minimumdescent=False)
+
+ xy = (0.5, 0.7)
+
+ ax.plot(xy[0], xy[1], ".r")
+
+ ab = AnnotationBbox(offsetbox, xy,
+ xybox=(-20, 40),
+ xycoords='data',
+ boxcoords="offset points",
+ arrowprops=dict(arrowstyle="->"))
+ ax.add_artist(ab)
+
+ offsetbox = TextArea("Test", minimumdescent=False)
+
+ ab = AnnotationBbox(offsetbox, xy,
+ xybox=(1.02, xy[1]),
+ xycoords='data',
+ boxcoords=("axes fraction", "data"),
+ box_alignment=(0.,0.5),
+ arrowprops=dict(arrowstyle="->"))
+ ax.add_artist(ab)
+
+
+ from matplotlib.patches import Circle
+ da = DrawingArea(20, 20, 0, 0)
+ p = Circle((10, 10), 10)
+ da.add_artist(p)
+
+ xy = [0.3, 0.55]
+ ab = AnnotationBbox(da, xy,
+ xybox=(1.02, xy[1]),
+ xycoords='data',
+ boxcoords=("axes fraction", "data"),
+ box_alignment=(0.,0.5),
+ arrowprops=dict(arrowstyle="->"))
+ #arrowprops=None)
+
+ ax.add_artist(ab)
+
+
+ arr = np.arange(100).reshape((10,10))
+ im = OffsetImage(arr, zoom=2)
+
+ ab = AnnotationBbox(im, xy,
+ xybox=(-50., 50.),
+ xycoords='data',
+ boxcoords="offset points",
+ pad=0.3,
+ arrowprops=dict(arrowstyle="->"))
+ #arrowprops=None)
+
+ ax.add_artist(ab)
+
+
+ # another image
+
+
+ from matplotlib._png import read_png
+ fn = get_sample_data("lena.png", asfileobj=False)
+ arr_lena = read_png(fn)
+
+ imagebox = OffsetImage(arr_lena, zoom=0.2)
+
+ ab = AnnotationBbox(imagebox, xy,
+ xybox=(120., -80.),
+ xycoords='data',
+ boxcoords="offset points",
+ pad=0.5,
+ arrowprops=dict(arrowstyle="->",
+
connectionstyle="angle,angleA=0,angleB=90,rad=3")
+ )
+
+
+ ax.add_artist(ab)
+
+ ax.set_xlim(0, 1)
+ ax.set_ylim(0, 1)
+
+
+ plt.draw()
+ plt.show()
Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-08-09 19:25:49 UTC
(rev 7439)
+++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-08-09 19:38:48 UTC
(rev 7440)
@@ -19,13 +19,21 @@
import matplotlib.artist as martist
import matplotlib.text as mtext
import numpy as np
-from matplotlib.transforms import Bbox, BboxBase, TransformedBbox,
BboxTransformTo
+from matplotlib.transforms import Bbox, BboxBase, TransformedBbox, \
+ IdentityTransform
from matplotlib.font_manager import FontProperties
-from matplotlib.patches import FancyBboxPatch
+from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
from matplotlib import rcParams
+import matplotlib.cbook as cbook
+
+#from bboximage import BboxImage
+from matplotlib.image import BboxImage
+
from matplotlib.patches import bbox_artist as mbbox_artist
+
+
DEBUG=False
# for debuging use
def bbox_artist(*args, **kwargs):
@@ -744,7 +752,7 @@
def get_extent(self, renderer):
# clear the offset transforms
- _off = self.ref_offset_transform.to_values() # to be restored later
+ _off = self.offset_transform.to_values() # to be restored later
self.ref_offset_transform.clear()
self.offset_transform.clear()
@@ -755,8 +763,10 @@
# adjust ref_offset_tansform
self.ref_offset_transform.translate(-ub.x0, -ub.y0)
+
# restor offset transform
- self.offset_transform.matrix_from_values(*_off)
+ mtx = self.offset_transform.matrix_from_values(*_off)
+ self.offset_transform.set_matrix(mtx)
return ub.width, ub.height, 0., 0.
@@ -890,10 +900,10 @@
else:
return TransformedBbox(self._bbox_to_anchor,
transform)
-
+
def set_bbox_to_anchor(self, bbox, transform=None):
"""
set the bbox that the child will be anchored.
@@ -901,7 +911,7 @@
*bbox* can be a Bbox instance, a list of [left, bottom, width,
height], or a list of [left, bottom] where the width and
height will be assumed to be zero. The bbox will be
- transformed to display coordinate by the given transform.
+ transformed to display coordinate by the given transform.
"""
if bbox is None or isinstance(bbox, BboxBase):
self._bbox_to_anchor = bbox
@@ -951,6 +961,13 @@
self.set_offset(_offset)
+ def update_frame(self, bbox, fontsize=None):
+ self.patch.set_bounds(bbox.x0, bbox.y0,
+ bbox.width, bbox.height)
+
+ if fontsize:
+ self.patch.set_mutation_scale(fontsize)
+
def draw(self, renderer):
"draw the artist"
@@ -962,11 +979,7 @@
if self._drawFrame:
# update the location and size of the legend
bbox = self.get_window_extent(renderer)
- self.patch.set_bounds(bbox.x0, bbox.y0,
- bbox.width, bbox.height)
-
- self.patch.set_mutation_scale(fontsize)
-
+ self.update_frame(bbox, fontsize)
self.patch.draw(renderer)
@@ -1004,3 +1017,399 @@
container = parentbbox.padded(-borderpad)
anchored_box = bbox.anchored(c, container=container)
return anchored_box.x0, anchored_box.y0
+
+
+class AnchoredText(AnchoredOffsetbox):
+ """
+ AnchoredOffsetbox with Text
+ """
+
+ def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, **kwargs):
+ """
+ *s* : string
+ *loc* : location code
+ *prop* : font property
+ *pad* : pad between the text and the frame as fraction of the font
size.
+ *borderpad* : pad between the frame and the axes (or bbox_to_anchor).
+
+ other keyword parameters of AnchoredOffsetbox are also allowed.
+ """
+
+ self.txt = TextArea(s, textprops=prop,
+ minimumdescent=False)
+ fp = self.txt._text.get_fontproperties()
+
+ super(AnchoredText, self).__init__(loc, pad=pad, borderpad=borderpad,
+ child=self.txt,
+ prop=fp,
+ **kwargs)
+
+
+
+class OffsetImage(OffsetBox):
+ def __init__(self, arr,
+ zoom=1,
+ cmap = None,
+ norm = None,
+ interpolation=None,
+ origin=None,
+ filternorm=1,
+ filterrad=4.0,
+ resample = False,
+ dpi_cor=True,
+ **kwargs
+ ):
+
+ self._dpi_cor = dpi_cor
+
+ self.image = BboxImage(bbox=self.get_window_extent,
+ cmap = cmap,
+ norm = norm,
+ interpolation=interpolation,
+ origin=origin,
+ filternorm=filternorm,
+ filterrad=filterrad,
+ resample = resample,
+ **kwargs
+ )
+
+ self._children = [self.image]
+
+ self.set_zoom(zoom)
+ self.set_data(arr)
+
+ OffsetBox.__init__(self)
+
+
+ def set_data(self, arr):
+ self._data = np.asarray(arr)
+ self.image.set_data(self._data)
+
+ def get_data(self):
+ return self._data
+
+ def set_zoom(self, zoom):
+ self._zoom = zoom
+
+ def get_zoom(self):
+ return self._zoom
+
+# def set_axes(self, axes):
+# self.image.set_axes(axes)
+# martist.Artist.set_axes(self, axes)
+
+# def set_offset(self, xy):
+# """
+# set offset of the container.
+
+# Accept : tuple of x,y cooridnate in disokay units.
+# """
+# self._offset = xy
+
+# self.offset_transform.clear()
+# self.offset_transform.translate(xy[0], xy[1])
+
+
+ def get_offset(self):
+ """
+ return offset of the container.
+ """
+ return self._offset
+
+
+ def get_window_extent(self, renderer):
+ '''
+ get the bounding box in display space.
+ '''
+ w, h, xd, yd = self.get_extent(renderer)
+ ox, oy = self.get_offset()
+ return mtransforms.Bbox.from_bounds(ox-xd, oy-yd, w, h)
+
+
+ def get_extent(self, renderer):
+
+ if self._dpi_cor: # True, do correction
+ dpi_cor = renderer.points_to_pixels(1.)
+ else:
+ dpi_cor = 1.
+
+ zoom = self.get_zoom()
+ data = self.get_data()
+ ny, nx = data.shape[:2]
+ w, h = nx*zoom, ny*zoom
+
+ return w, h, 0, 0
+
+
+
+ def draw(self, renderer):
+ """
+ Draw the children
+ """
+
+ self.image.draw(renderer)
+
+ #bbox_artist(self, renderer, fill=False, props=dict(pad=0.))
+
+
+
+from matplotlib.text import _AnnotationBase
+
+class AnnotationBbox(martist.Artist, _AnnotationBase):
+ """
+ Annotation-like class, but with offsetbox instead of Text.
+ """
+
+ zorder = 3
+
+ def __str__(self):
+ return "AnnotationBbox(%g,%g)"%(self.xy[0],self.xy[1])
+ def __init__(self, offsetbox, xy,
+ xybox=None,
+ xycoords='data',
+ boxcoords=None,
+ frameon=True, pad=0.4, # BboxPatch
+ annotation_clip=None,
+ box_alignment=(0.5, 0.5),
+ bboxprops=None,
+ arrowprops=None,
+ fontsize=None,
+ **kwargs):
+ """
+ *offsetbox* : OffsetBox instance
+
+ *xycoords* : same as Annotation but can be a tuple of two
+ strings which are interpreted as x and y coordinates.
+
+ *boxcoords* : similar to textcoords as Annotation but can be a
+ tuple of two strings which are interpreted as x and y
+ coordinates.
+
+ *box_alignment* : a tuple of two floats for a vertical and
+ horizontal alignment of the offset box w.r.t. the *boxcoords*.
+ The lower-left corner is (0.0) and upper-right corner is (1.1).
+
+ other parameters are identical to that of Annotation.
+ """
+ self.offsetbox = offsetbox
+
+ self.arrowprops = arrowprops
+
+ self.set_fontsize(fontsize)
+
+
+ if arrowprops is not None:
+ self._arrow_relpos = self.arrowprops.pop("relpos", (0.5, 0.5))
+ self.arrow_patch = FancyArrowPatch((0, 0), (1,1),
+ **self.arrowprops)
+ else:
+ self._arrow_relpos = None
+ self.arrow_patch = None
+
+ _AnnotationBase.__init__(self,
+ xy, xytext=xybox,
+ xycoords=xycoords, textcoords=boxcoords,
+ annotation_clip=annotation_clip)
+
+ martist.Artist.__init__(self, **kwargs)
+
+ #self._fw, self._fh = 0., 0. # for alignment
+ self._box_alignment = box_alignment
+
+ # frame
+ self.patch = FancyBboxPatch(
+ xy=(0.0, 0.0), width=1., height=1.,
+ facecolor='w', edgecolor='k',
+ mutation_scale=self.prop.get_size_in_points(),
+ snap=True
+ )
+ self.patch.set_boxstyle("square",pad=pad)
+ if bboxprops:
+ self.patch.set(**bboxprops)
+ self._drawFrame = frameon
+
+
+ __init__.__doc__ = cbook.dedent(__init__.__doc__) % martist.kwdocd
+
+ def contains(self,event):
+ t,tinfo = self.offsetbox.contains(event)
+ if self.arrow is not None:
+ a,ainfo=self.arrow.contains(event)
+ t = t or a
+
+ # self.arrow_patch is currently not checked as this can be a line - JJ
+
+ return t,tinfo
+
+
+ def get_children(self):
+ children = [self.offsetbox, self.patch]
+ if self.arrow_patch:
+ children.append(self.arrow_patch)
+ return children
+
+ def set_figure(self, fig):
+
+ if self.arrow_patch is not None:
+ self.arrow_patch.set_figure(fig)
+ self.offsetbox.set_figure(fig)
+ martist.Artist.set_figure(self, fig)
+
+ def set_fontsize(self, s=None):
+ """
+ set fontsize in points
+ """
+ if s is None:
+ s = rcParams["legend.fontsize"]
+
+ self.prop=FontProperties(size=s)
+
+ def get_fontsize(self, s=None):
+ """
+ return fontsize in points
+ """
+ return self.prop.get_size_in_points()
+
+ def update_positions(self, renderer):
+ "Update the pixel positions of the annotated point and the text."
+ xy_pixel = self._get_position_xy(renderer)
+ self._update_position_xybox(renderer, xy_pixel)
+
+ mutation_scale = renderer.points_to_pixels(self.get_fontsize())
+ self.patch.set_mutation_scale(mutation_scale)
+
+ if self.arrow_patch:
+ self.arrow_patch.set_mutation_scale(mutation_scale)
+
+
+ def _update_position_xybox(self, renderer, xy_pixel):
+ "Update the pixel positions of the annotation text and the arrow
patch."
+
+ x, y = self.xytext
+ if isinstance(self.textcoords, tuple):
+ xcoord, ycoord = self.textcoords
+ x1, y1 = self._get_xy(x, y, xcoord)
+ x2, y2 = self._get_xy(x, y, ycoord)
+ ox0, oy0 = x1, y2
+ else:
+ ox0, oy0 = self._get_xy(x, y, self.textcoords)
+
+ #self.offsetbox.set_bbox_to_anchor((ox0, oy0))
+ w, h, xd, yd = self.offsetbox.get_extent(renderer)
+
+ _fw, _fh = self._box_alignment
+ self.offsetbox.set_offset((ox0-_fw*w, oy0-_fh*h))
+
+ # update patch position
+ bbox = self.offsetbox.get_window_extent(renderer)
+ #self.offsetbox.set_offset((ox0-_fw*w, oy0-_fh*h))
+ self.patch.set_bounds(bbox.x0, bbox.y0,
+ bbox.width, bbox.height)
+
+ x, y = xy_pixel
+
+ ox1, oy1 = x, y
+
+ if self.arrowprops:
+ x0, y0 = x, y
+
+ d = self.arrowprops.copy()
+
+ # Use FancyArrowPatch if self.arrowprops has "arrowstyle" key.
+
+ # adjust the starting point of the arrow relative to
+ # the textbox.
+ # TODO : Rotation needs to be accounted.
+ relpos = self._arrow_relpos
+
+ ox0 = bbox.x0 + bbox.width * relpos[0]
+ oy0 = bbox.y0 + bbox.height * relpos[1]
+
+ # The arrow will be drawn from (ox0, oy0) to (ox1,
+ # oy1). It will be first clipped by patchA and patchB.
+ # Then it will be shrinked by shirnkA and shrinkB
+ # (in points). If patch A is not set, self.bbox_patch
+ # is used.
+
+ self.arrow_patch.set_positions((ox0, oy0), (ox1,oy1))
+ fs = self.prop.get_size_in_points()
+ mutation_scale = d.pop("mutation_scale", fs)
+ mutation_scale = renderer.points_to_pixels(mutation_scale)
+ self.arrow_patch.set_mutation_scale(mutation_scale)
+
+ patchA = d.pop("patchA", self.patch)
+ self.arrow_patch.set_patchA(patchA)
+
+
+
+ def draw(self, renderer):
+ """
+ Draw the :class:`Annotation` object to the given *renderer*.
+ """
+
+ if renderer is not None:
+ self._renderer = renderer
+ if not self.get_visible(): return
+
+ xy_pixel = self._get_position_xy(renderer)
+
+ if not self._check_xy(renderer, xy_pixel):
+ return
+
+ self.update_positions(renderer)
+
+ if self.arrow_patch is not None:
+ if self.arrow_patch.figure is None and self.figure is not None:
+ self.arrow_patch.figure = self.figure
+ self.arrow_patch.draw(renderer)
+
+ if self._drawFrame:
+ self.patch.draw(renderer)
+
+ self.offsetbox.draw(renderer)
+
+
+
+
+if __name__ == "__main__":
+
+ fig = plt.figure(1)
+ fig.clf()
+ ax = plt.subplot(121)
+
+ #txt = ax.text(0.5, 0.5, "Test", size=30, ha="center", color="w")
+ kwargs = dict()
+
+ a = np.arange(256).reshape(16,16)/256.
+ myimage = OffsetImage(a,
+ zoom=2,
+ norm = None,
+ origin=None,
+ **kwargs
+ )
+ ax.add_artist(myimage)
+
+ myimage.set_offset((100, 100))
+
+
+ myimage2 = OffsetImage(a,
+ zoom=2,
+ norm = None,
+ origin=None,
+ **kwargs
+ )
+ ann = AnnotationBbox(myimage2, (0.5, 0.5),
+ xybox=(30, 30),
+ xycoords='data',
+ boxcoords="offset points",
+ frameon=True, pad=0.4, # BboxPatch
+ bboxprops=dict(boxstyle="round", fc="y"),
+ fontsize=None,
+ arrowprops=dict(arrowstyle="->"),
+ )
+
+ ax.add_artist(ann)
+
+ plt.draw()
+ plt.show()
+
Modified: trunk/matplotlib/lib/matplotlib/text.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/text.py 2009-08-09 19:25:49 UTC (rev
7439)
+++ trunk/matplotlib/lib/matplotlib/text.py 2009-08-09 19:38:48 UTC (rev
7440)
@@ -1340,7 +1340,158 @@
artist.kwdocd['TextWithDash'] = artist.kwdoc(TextWithDash)
-class Annotation(Text):
+class _AnnotationBase(object):
+ def __init__(self,
+ xy, xytext=None,
+ xycoords='data', textcoords=None,
+ annotation_clip=None):
+ if xytext is None:
+ xytext = xy
+ if textcoords is None:
+ textcoords = xycoords
+ # we'll draw ourself after the artist we annotate by default
+ x,y = self.xytext = xytext
+
+ self.xy = xy
+ self.xycoords = xycoords
+ self.textcoords = textcoords
+ self.set_annotation_clip(annotation_clip)
+
+ def _get_xy(self, x, y, s):
+ if s=='data':
+ trans = self.axes.transData
+ x = float(self.convert_xunits(x))
+ y = float(self.convert_yunits(y))
+ return trans.transform_point((x, y))
+ elif s=='offset points':
+ # convert the data point
+ dx, dy = self.xy
+
+ # prevent recursion
+ if self.xycoords == 'offset points':
+ return self._get_xy(dx, dy, 'data')
+
+ dx, dy = self._get_xy(dx, dy, self.xycoords)
+
+ # convert the offset
+ dpi = self.figure.get_dpi()
+ x *= dpi/72.
+ y *= dpi/72.
+
+ # add the offset to the data point
+ x += dx
+ y += dy
+
+ return x, y
+ elif s=='polar':
+ theta, r = x, y
+ x = r*np.cos(theta)
+ y = r*np.sin(theta)
+ trans = self.axes.transData
+ return trans.transform_point((x,y))
+ elif s=='figure points':
+ #points from the lower left corner of the figure
+ dpi = self.figure.dpi
+ l,b,w,h = self.figure.bbox.bounds
+ r = l+w
+ t = b+h
+
+ x *= dpi/72.
+ y *= dpi/72.
+ if x<0:
+ x = r + x
+ if y<0:
+ y = t + y
+ return x,y
+ elif s=='figure pixels':
+ #pixels from the lower left corner of the figure
+ l,b,w,h = self.figure.bbox.bounds
+ r = l+w
+ t = b+h
+ if x<0:
+ x = r + x
+ if y<0:
+ y = t + y
+ return x, y
+ elif s=='figure fraction':
+ #(0,0) is lower left, (1,1) is upper right of figure
+ trans = self.figure.transFigure
+ return trans.transform_point((x,y))
+ elif s=='axes points':
+ #points from the lower left corner of the axes
+ dpi = self.figure.dpi
+ l,b,w,h = self.axes.bbox.bounds
+ r = l+w
+ t = b+h
+ if x<0:
+ x = r + x*dpi/72.
+ else:
+ x = l + x*dpi/72.
+ if y<0:
+ y = t + y*dpi/72.
+ else:
+ y = b + y*dpi/72.
+ return x, y
+ elif s=='axes pixels':
+ #pixels from the lower left corner of the axes
+
+ l,b,w,h = self.axes.bbox.bounds
+ r = l+w
+ t = b+h
+ if x<0:
+ x = r + x
+ else:
+ x = l + x
+ if y<0:
+ y = t + y
+ else:
+ y = b + y
+ return x, y
+ elif s=='axes fraction':
+ #(0,0) is lower left, (1,1) is upper right of axes
+ trans = self.axes.transAxes
+ return trans.transform_point((x, y))
+
+ def set_annotation_clip(self, b):
+ """
+ set *annotation_clip* attribute.
+
+ * True : the annotation will only be drawn when self.xy is inside
the axes.
+ * False : the annotation will always be drawn regardless of its
position.
+ * None : the self.xy will be checked only if *xycoords* is "data"
+ """
+ self._annotation_clip = b
+
+ def get_annotation_clip(self):
+ """
+ Return *annotation_clip* attribute.
+ See :meth:`set_annotation_clip` for the meaning of return values.
+ """
+ return self._annotation_clip
+
+ def _get_position_xy(self, renderer):
+ "Return the pixel position of the the annotated point."
+ x, y = self.xy
+ return self._get_xy(x, y, self.xycoords)
+
+ def _check_xy(self, renderer, xy_pixel):
+ """
+ given the xy pixel coordinate, check if the annotation need to
+ be drawn.
+ """
+
+ b = self.get_annotation_clip()
+ if b or (b is None and self.xycoords == "data"):
+ # check if self.xy is inside the axes.
+ if not self.axes.contains_point(xy_pixel):
+ return False
+
+ return True
+
+
+
+
+class Annotation(Text, _AnnotationBase):
"""
A :class:`~matplotlib.text.Text` class to make annotating things
in the figure, such as :class:`~matplotlib.figure.Figure`,
@@ -1354,6 +1505,7 @@
xycoords='data',
textcoords=None,
arrowprops=None,
+ annotation_clip=None,
**kwargs):
"""
Annotate the *x*, *y* point *xy* with text *s* at *x*, *y*
@@ -1442,16 +1594,14 @@
%(Text)s
"""
- if xytext is None:
- xytext = xy
- if textcoords is None:
- textcoords = xycoords
- # we'll draw ourself after the artist we annotate by default
- x,y = self.xytext = xytext
+
+ _AnnotationBase.__init__(self,
+ xy, xytext=xytext,
+ xycoords=xycoords, textcoords=textcoords,
+ annotation_clip=annotation_clip)
+
+ x,y = self.xytext
Text.__init__(self, x, y, s, **kwargs)
- self.xy = xy
- self.xycoords = xycoords
- self.textcoords = textcoords
self.arrowprops = arrowprops
@@ -1465,9 +1615,6 @@
else:
self.arrow_patch = None
- # if True, draw annotation only if self.xy is inside the axes
- self._annotation_clip = None
-
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
def contains(self,event):
@@ -1489,131 +1636,13 @@
self.arrow_patch.set_figure(fig)
Artist.set_figure(self, fig)
- def _get_xy(self, x, y, s):
- if s=='data':
- trans = self.axes.transData
- x = float(self.convert_xunits(x))
- y = float(self.convert_yunits(y))
- return trans.transform_point((x, y))
- elif s=='offset points':
- # convert the data point
- dx, dy = self.xy
- # prevent recursion
- if self.xycoords == 'offset points':
- return self._get_xy(dx, dy, 'data')
-
- dx, dy = self._get_xy(dx, dy, self.xycoords)
-
- # convert the offset
- dpi = self.figure.get_dpi()
- x *= dpi/72.
- y *= dpi/72.
-
- # add the offset to the data point
- x += dx
- y += dy
-
- return x, y
- elif s=='polar':
- theta, r = x, y
- x = r*np.cos(theta)
- y = r*np.sin(theta)
- trans = self.axes.transData
- return trans.transform_point((x,y))
- elif s=='figure points':
- #points from the lower left corner of the figure
- dpi = self.figure.dpi
- l,b,w,h = self.figure.bbox.bounds
- r = l+w
- t = b+h
-
- x *= dpi/72.
- y *= dpi/72.
- if x<0:
- x = r + x
- if y<0:
- y = t + y
- return x,y
- elif s=='figure pixels':
- #pixels from the lower left corner of the figure
- l,b,w,h = self.figure.bbox.bounds
- r = l+w
- t = b+h
- if x<0:
- x = r + x
- if y<0:
- y = t + y
- return x, y
- elif s=='figure fraction':
- #(0,0) is lower left, (1,1) is upper right of figure
- trans = self.figure.transFigure
- return trans.transform_point((x,y))
- elif s=='axes points':
- #points from the lower left corner of the axes
- dpi = self.figure.dpi
- l,b,w,h = self.axes.bbox.bounds
- r = l+w
- t = b+h
- if x<0:
- x = r + x*dpi/72.
- else:
- x = l + x*dpi/72.
- if y<0:
- y = t + y*dpi/72.
- else:
- y = b + y*dpi/72.
- return x, y
- elif s=='axes pixels':
- #pixels from the lower left corner of the axes
-
- l,b,w,h = self.axes.bbox.bounds
- r = l+w
- t = b+h
- if x<0:
- x = r + x
- else:
- x = l + x
- if y<0:
- y = t + y
- else:
- y = b + y
- return x, y
- elif s=='axes fraction':
- #(0,0) is lower left, (1,1) is upper right of axes
- trans = self.axes.transAxes
- return trans.transform_point((x, y))
-
- def set_annotation_clip(self, b):
- """
- set *annotation_clip* attribute.
-
- * True : the annotation will only be drawn when self.xy is inside
the axes.
- * False : the annotation will always be drawn regardless of its
position.
- * None : the self.xy will be checked only if *xycoords* is "data"
- """
- self._annotation_clip = b
-
- def get_annotation_clip(self):
- """
- Return *annotation_clip* attribute.
- See :meth:`set_annotation_clip` for the meaning of return values.
- """
- return self._annotation_clip
-
-
def update_positions(self, renderer):
"Update the pixel positions of the annotated point and the text."
xy_pixel = self._get_position_xy(renderer)
self._update_position_xytext(renderer, xy_pixel)
- def _get_position_xy(self, renderer):
- "Return the pixel position of the the annotated point."
- x, y = self.xy
- return self._get_xy(x, y, self.xycoords)
-
-
def _update_position_xytext(self, renderer, xy_pixel):
"Update the pixel positions of the annotation text and the arrow
patch."
@@ -1698,21 +1727,6 @@
self.arrow.set_clip_box(self.get_clip_box())
- def _check_xy(self, renderer, xy_pixel):
- """
- given the xy pixel coordinate, check if the annotation need to
- be drawn.
- """
-
- b = self.get_annotation_clip()
- if b or (b is None and self.xycoords == "data"):
- # check if self.xy is inside the axes.
- if not self.axes.contains_point(xy_pixel):
- return False
-
- return True
-
-
def draw(self, renderer):
"""
Draw the :class:`Annotation` object to the given *renderer*.
Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py
2009-08-09 19:25:49 UTC (rev 7439)
+++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py
2009-08-09 19:38:48 UTC (rev 7440)
@@ -1,41 +1,35 @@
-
-from matplotlib.font_manager import FontProperties
-from matplotlib import rcParams
from matplotlib.patches import Rectangle, Ellipse
+import numpy as np
+
from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\
- TextArea, DrawingArea
+ TextArea, AnchoredText, DrawingArea, AnnotationBbox
-class AnchoredText(AnchoredOffsetbox):
- def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, **kwargs):
+class AnchoredDrawingArea(AnchoredOffsetbox):
+ """
+ AnchoredOffsetbox with DrawingArea
+ """
- self.txt = TextArea(s, textprops=prop,
- minimumdescent=False)
- fp = self.txt._text.get_fontproperties()
-
- super(AnchoredText, self).__init__(loc, pad=pad, borderpad=borderpad,
- child=self.txt,
- prop=fp,
- **kwargs)
-
-
-
-class AnchoredDrawingArea(AnchoredOffsetbox):
def __init__(self, width, height, xdescent, ydescent,
loc, pad=0.4, borderpad=0.5, prop=None, frameon=True,
**kwargs):
+ """
+ *width*, *height*, *xdescent*, *ydescent* : the dimensions of the
DrawingArea.
+ *prop* : font property. this is only used for scaling the paddings.
+ """
self.da = DrawingArea(width, height, xdescent, ydescent, clip=True)
self.drawing_area = self.da
-
+
super(AnchoredDrawingArea, self).__init__(loc, pad=pad,
borderpad=borderpad,
child=self.da,
prop=None,
frameon=frameon,
**kwargs)
+
class AnchoredAuxTransformBox(AnchoredOffsetbox):
def __init__(self, transform, loc,
pad=0.4, borderpad=0.5, prop=None, frameon=True, **kwargs):
@@ -49,6 +43,7 @@
**kwargs)
+
class AnchoredEllipse(AnchoredOffsetbox):
def __init__(self, transform, width, height, angle, loc,
pad=0.1, borderpad=0.1, prop=None, frameon=True, **kwargs):
@@ -93,3 +88,73 @@
prop=prop,
frameon=frameon, **kwargs)
+
+if __name__ == "__main__":
+
+ import matplotlib.pyplot as plt
+
+ fig = plt.gcf()
+ fig.clf()
+ ax = plt.subplot(111)
+
+ offsetbox = AnchoredText("Test", loc=6, pad=0.3,
+ borderpad=0.3, prop=None)
+ xy = (0.5, 0.5)
+ ax.plot([0.5], [0.5], "xk")
+ ab = AnnotationBbox(offsetbox, xy,
+ xybox=(1., .5),
+ xycoords='data',
+ boxcoords=("axes fraction", "data"),
+ arrowprops=dict(arrowstyle="->"))
+ #arrowprops=None)
+
+ ax.add_artist(ab)
+
+
+ from matplotlib.patches import Circle
+ ada = AnchoredDrawingArea(20, 20, 0, 0,
+ loc=6, pad=0.1, borderpad=0.3, frameon=True)
+ p = Circle((10, 10), 10)
+ ada.da.add_artist(p)
+
+ ab = AnnotationBbox(ada, (0.3, 0.4),
+ xybox=(1., 0.4),
+ xycoords='data',
+ boxcoords=("axes fraction", "data"),
+ arrowprops=dict(arrowstyle="->"))
+ #arrowprops=None)
+
+ ax.add_artist(ab)
+
+
+ arr = np.arange(100).reshape((10,10))
+ im = AnchoredImage(arr,
+ loc=4,
+ pad=0.5, borderpad=0.2, prop=None, frameon=True,
+ zoom=1,
+ cmap = None,
+ norm = None,
+ interpolation=None,
+ origin=None,
+ extent=None,
+ filternorm=1,
+ filterrad=4.0,
+ resample = False,
+ )
+
+ ab = AnnotationBbox(im, (0.5, 0.5),
+ xybox=(-10., 10.),
+ xycoords='data',
+ boxcoords="offset points",
+ arrowprops=dict(arrowstyle="->"))
+ #arrowprops=None)
+
+ ax.add_artist(ab)
+
+ ax.set_xlim(0, 1)
+ ax.set_ylim(0, 1)
+
+
+ plt.draw()
+ plt.show()
+
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins