From: <lee...@us...> - 2009-07-14 21:24:12
|
Revision: 7262 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7262&view=rev Author: leejjoon Date: 2009-07-14 21:24:07 +0000 (Tue, 14 Jul 2009) Log Message: ----------- initial submission of the annotation guide. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/users/plotting.rst Added Paths: ----------- trunk/matplotlib/doc/users/plotting/annotation.rst trunk/matplotlib/doc/users/plotting/examples/anchored_box01.py trunk/matplotlib/doc/users/plotting/examples/anchored_box02.py trunk/matplotlib/doc/users/plotting/examples/anchored_box03.py trunk/matplotlib/doc/users/plotting/examples/anchored_box04.py trunk/matplotlib/doc/users/plotting/examples/annotate_explain.py trunk/matplotlib/doc/users/plotting/examples/annotate_simple01.py trunk/matplotlib/doc/users/plotting/examples/annotate_simple02.py trunk/matplotlib/doc/users/plotting/examples/annotate_simple03.py trunk/matplotlib/doc/users/plotting/examples/annotate_simple04.py trunk/matplotlib/doc/users/plotting/examples/annotate_text_arrow.py trunk/matplotlib/doc/users/plotting/examples/axes_zoom_effect.py trunk/matplotlib/doc/users/plotting/examples/connect_simple01.py trunk/matplotlib/doc/users/plotting/examples/connectionstyle_demo.py trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle01.py trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle02.py trunk/matplotlib/doc/users/plotting/examples/simple_annotate01.py trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-07-14 21:18:58 UTC (rev 7261) +++ trunk/matplotlib/CHANGELOG 2009-07-14 21:24:07 UTC (rev 7262) @@ -1,3 +1,5 @@ +2009-07-14 initial submission of the annotation guide. -JJL + 2009-07-14 axes_grid : minor improvements in anchored_artists and inset_locator. -JJL Added: trunk/matplotlib/doc/users/plotting/annotation.rst =================================================================== --- trunk/matplotlib/doc/users/plotting/annotation.rst (rev 0) +++ trunk/matplotlib/doc/users/plotting/annotation.rst 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,332 @@ +.. _plotting-guide-annotation: + +**************** +Annotating Axes +**************** + +Do not proceed unless you already have read +:func:`~matplotlib.pyplot.text` and :func:`~matplotlib.pyplot.annotate`! + + +Annotating with Text with Box +============================= + +Let's start with a simple example. + +.. plot:: users/plotting/examples/annotate_text_arrow.py + + +The :func:`~matplotlib.pyplot.text` function in the pyplot module (or +text method of the Axes class) takes bbox keyword argument, and when +given, a box around the text is drawn. :: + + bbox_props = dict(boxstyle="rarrow,pad=0.3", fc="cyan", ec="b", lw=2) + t = ax.text(0, 0, "Direction", ha="center", va="center", rotation=45, + size=15, + bbox=bbox_props) + + +The patch object associated with the text can be accessed by:: + + bb = t.get_bbox_patch() + +The return value is an instance of FancyBboxPatch and the patch +properties like facecolor, edgewidth, etc. can be accessed and +modified as usual. To change the shape of the box, use *set_boxstyle* +method. :: + + bb.set_boxstyle("rarrow", pad=0.6) + +The arguments are the name of the box style with its attributes as +keyword arguments. Currently, followign box styles are implemented. + + ========== ============== ========================== + Class Name Attrs + ========== ============== ========================== + LArrow ``larrow`` pad=0.3 + RArrow ``rarrow`` pad=0.3 + Round ``round`` pad=0.3,rounding_size=None + Round4 ``round4`` pad=0.3,rounding_size=None + Roundtooth ``roundtooth`` pad=0.3,tooth_size=None + Sawtooth ``sawtooth`` pad=0.3,tooth_size=None + Square ``square`` pad=0.3 + ========== ============== ========================== + +.. plot:: mpl_examples/pylab_examples/fancybox_demo2.py + + +Note that the attrubutes arguments can be specified within the style +name with separating comma (this form can be used as "boxstyle" value +of bbox argument when initializing the text instance) :: + + bb.set_boxstyle("rarrow,pad=0.6") + + + + +Annotating with Arrow +===================== + +The :func:`~matplotlib.pyplot.annotate` function in the pyplot module +(or annotate method of the Axes class) is used to draw an arrow +connecting two points on the plot. :: + + ax.annotate("Annotation", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='offset points', + ) + +This annotates a point at ``xy`` in the given coordinate (``xycoords``) +with the text at ``xytext`` given in ``textcoords``. Often, the +annotated point is specified in the *data* coordinate and the annotating +text in *offset points*. +See :func:`~matplotlib.pyplot.annotate` for available coordinate systems. + +An arrow connecting two point (xy & xytext) can be optionally drawn by +specifying the ``arrowprops`` argument. To draw only an arrow, use +empty string as the first argument. :: + + ax.annotate("", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3"), + ) + +.. plot:: users/plotting/examples/annotate_simple01.py + +The arrow drawing takes a few steps. + +1. a connecting path between two points are created. This is + controlled by ``connectionstyle`` key value. + +2. If patch object is given (*patchA* & *patchB*), the path is clipped to + avoid the patch. + +3. The path is further shrinked by given amount of pixels (*shirnkA* + & *shrinkB*) + +4. The path is transmuted to arrow patch, which is controlled by the + ``arrowstyle`` key value. + + +.. plot:: users/plotting/examples/annotate_explain.py + + +The creation of the connecting path between two points is controlled by +``connectionstyle`` key and follwing styles are available. + + ========== ============================================= + Name Attrs + ========== ============================================= + ``angle`` angleA=90,angleB=0,rad=0.0 + ``angle3`` angleA=90,angleB=0 + ``arc`` angleA=0,angleB=0,armA=None,armB=None,rad=0.0 + ``arc3`` rad=0.0 + ``bar`` armA=0.0,armB=0.0,fraction=0.3,angle=None + ========== ============================================= + +Note that "3" in ``angle3`` and ``arc3`` is meant to indicate that the +resulting path is a quadratic spline segment (three control +points). As will be discussed below, some arrow style option only can +be used when the connecting path is a quadratic spline. + +The behavior of each connection style is (limitedly) demonstrated in the +example below. (Warning : The behavior of the ``bar`` style is currently not +well defined, it may be changed in the future). + +.. plot:: users/plotting/examples/connectionstyle_demo.py + + +The connecting path (after clipping and shrinking) is then mutated to +an arrow patch, according to the given ``arrowstyle``. + + ========== ============================================= + Name Attrs + ========== ============================================= + ``-`` None + ``->`` head_length=0.4,head_width=0.2 + ``-[`` widthB=1.0,lengthB=0.2,angleB=None + ``-|>`` head_length=0.4,head_width=0.2 + ``<-`` head_length=0.4,head_width=0.2 + ``<->`` head_length=0.4,head_width=0.2 + ``<|-`` head_length=0.4,head_width=0.2 + ``<|-|>`` head_length=0.4,head_width=0.2 + ``fancy`` head_length=0.4,head_width=0.4,tail_width=0.4 + ``simple`` head_length=0.5,head_width=0.5,tail_width=0.2 + ``wedge`` tail_width=0.3,shrink_factor=0.5 + ========== ============================================= + +.. plot:: mpl_examples/pylab_examples/fancyarrow_demo.py + +Some arrowstyles only work with connection style that generates a +quadratic-spline segment. They are ``fancy``, ``simple``, and ``wedge``. +For these arrow styles, you must use "angle3" or "arc3" connection +style. + +If the annotation string is given, the patchA is set to the bbox patch +of the text by default. + +.. plot:: users/plotting/examples/annotate_simple02.py + +As in the text command, a box around the text can be drawn using +the ``bbox`` argument. + +.. plot:: users/plotting/examples/annotate_simple03.py + +By default, the starting point is set to the center of the text +extent. This can be adjusted with ``relpos`` key value. The values +are normalized to the extent of the text. For example, (0,0) means +lower-left corner and (1,1) means top-right. + +.. plot:: users/plotting/examples/annotate_simple04.py + + +Using ConnectorPatch +==================== + +The ConnectorPatch is like an annotation without a text. While the +annotate function is recommended in most of situation, the +ConnectorPatch is useful when you want to connect points in different +axes. :: + + from matplotlib.patches import ConnectionPatch + xy = (0.2, 0.2) + con = ConnectionPatch(xyA=xy, xyB=xy, coordsA="data", coordsB="data", + axesA=ax1, axesB=ax2) + ax2.add_artist(con) + +The above code connects point xy in data coordinate of ``ax1`` to +point xy int data coordiante of ``ax2``. Here is a simple example. + +.. plot:: users/plotting/examples/connect_simple01.py + + +While the ConnectorPatch instance can be added to any axes, but you +may want it to be added to the axes in the latter (?) of the axes +drawing order to prevent overlap (?) by other axes. + + +Placing Artist at the anchored location of the Axes +=================================================== + +There are class of artist that can be placed at the anchored location +of the Axes. A common example is the legend. This type of artists can +be created by using the OffsetBox class. A few predefined classes are +available in ``mpl_toolkits.axes_grid.anchored_artists``. :: + + from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + at = AnchoredText("Figure 1a", + prop=dict(size=8), frameon=True, + loc=2, + ) + at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") + ax.add_artist(at) + + +.. plot:: users/plotting/examples/anchored_box01.py + + +The *loc* keyword has same meaning as in the legend command. + +A simple application is when the size of the artist (or collection of +artists) is knwon in pixel size during the time of creation. For +example, If you want to draw a circle with fixed size of 20 pixel x 20 +pixel (radius = 10 pixel), you can utilize +``AnchoredDrawingArea``. The instance is created with a size of the +drawing area (in pixel). And user can add arbitrary artist to the +drawing area. Note that the extents of the artists that are added to +the drawing area has nothing to do with the placement of the drawing +area itself. The initial size only matters. :: + + from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea + + ada = AnchoredDrawingArea(20, 20, 0, 0, + loc=1, pad=0., frameon=False) + p1 = Circle((10, 10), 10) + ada.drawing_area.add_artist(p1) + p2 = Circle((30, 10), 5, fc="r") + ada.drawing_area.add_artist(p2) + +The artists that are added to the drawing area should not have +transform set (they will be overridden) and the dimension of those +artists are interpreted as a pixel coordinate, i.e., the radius of the +circles in above example are 10 pixel and 5 pixel, respectively. + +.. plot:: users/plotting/examples/anchored_box02.py + +Sometimes, you want to your artists scale with data coordinate (or +other coordinate than canvas pixel). You can use +``AnchoredAuxTransformBox`` class. This is similar to +``AnchoredDrawingArea`` except that the extent of the artist is +determined during the drawing time respecting the specified transform. :: + + from mpl_toolkits.axes_grid.anchored_artists import AnchoredAuxTransformBox + + box = AnchoredAuxTransformBox(ax.transData, loc=2) + el = Ellipse((0,0), width=0.1, height=0.4, angle=30) # in data coordinates! + box.drawing_area.add_artist(el) + +The ellipse in the above example will have width and height +corresponds to 0.1 and 0.4 in data coordinate and will be +automatically scaled when the view limits of the axes change. + +.. plot:: users/plotting/examples/anchored_box03.py + +As in the legend, the bbox_to_anchor argument can be set. Using the +HPacker and VPacker, you can have an arrangement(?) of artist as in the +legend (as a matter of fact, this is how the legend is created). + +.. plot:: users/plotting/examples/anchored_box04.py + +Note that unlike the legend, the ``bbox_transform`` is set +to IdentityTransform by default. + +Advanced Topics +*************** + +Zoom effect between Axes +======================== + +mpl_toolkits.axes_grid.inset_locator defines some patch classs useful +for interconnect two axes. Understanding the code requires some +knowledge of how mpl's transform works. But, utilizing it will be +straight forward. + + +.. plot:: mpl_examples/pylab_examples/axes_zoom_effect.py + + +Define Custom BoxStyle +====================== + +You can use a custom box style. The value for the ``boxstyle`` can be a +callable object in following forms.:: + + def __call__(self, x0, y0, width, height, mutation_size, + aspect_ratio=1.): + """ + Given the location and size of the box, return the path of + the box around it. + + - *x0*, *y0*, *width*, *height* : location and size of the box + - *mutation_size* : a reference scale for the mutation. + - *aspect_ratio* : aspect-ration for the mutation. + """ + path = ... + return path + +Here is a complete example. + +.. plot:: users/plotting/examples/custom_boxstyle01.py + +However, it is recommended that you derive from the +matplotlib.patches.BoxStyle._Base as demonstrated below. + +.. plot:: users/plotting/examples/custom_boxstyle02.py + :include-source: + + +Similarly, you can define custom ConnectionStyle and Custome ArrowStyle. +See the source code of ``lib/matplotlib/patches.py`` and check +how each style class is defined. Added: trunk/matplotlib/doc/users/plotting/examples/anchored_box01.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/anchored_box01.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/anchored_box01.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,14 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + +fig=plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +at = AnchoredText("Figure 1a", + prop=dict(size=15), frameon=True, + loc=2, + ) +at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") +ax.add_artist(at) + +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/anchored_box02.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/anchored_box02.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/anchored_box02.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,18 @@ +from matplotlib.patches import Circle +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea + +fig=plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + + +ada = AnchoredDrawingArea(40, 20, 0, 0, + loc=1, pad=0., frameon=False) +p1 = Circle((10, 10), 10) +ada.drawing_area.add_artist(p1) +p2 = Circle((30, 10), 5, fc="r") +ada.drawing_area.add_artist(p2) + +ax.add_artist(ada) + +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/anchored_box03.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/anchored_box03.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/anchored_box03.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,14 @@ +from matplotlib.patches import Ellipse +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.anchored_artists import AnchoredAuxTransformBox + +fig=plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +box = AnchoredAuxTransformBox(ax.transData, loc=2) +el = Ellipse((0,0), width=0.1, height=0.4, angle=30) # in data coordinates! +box.drawing_area.add_artist(el) + +ax.add_artist(box) + +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/anchored_box04.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/anchored_box04.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/anchored_box04.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,35 @@ +from matplotlib.patches import Ellipse +import matplotlib.pyplot as plt +from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, DrawingArea, HPacker + +fig=plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +box1 = TextArea(" Test : ", textprops=dict(color="k")) + +box2 = DrawingArea(60, 20, 0, 0) +el1 = Ellipse((10, 10), width=16, height=5, angle=30, fc="r") +el2 = Ellipse((30, 10), width=16, height=5, angle=170, fc="g") +el3 = Ellipse((50, 10), width=16, height=5, angle=230, fc="b") +box2.add_artist(el1) +box2.add_artist(el2) +box2.add_artist(el3) + + +box = HPacker(children=[box1, box2], + align="center", + pad=0, sep=5) + +anchored_box = AnchoredOffsetbox(loc=3, + child=box, pad=0., + frameon=True, + bbox_to_anchor=(0., 1.02), + bbox_transform=ax.transAxes, + borderpad=0., + ) + + +ax.add_artist(anchored_box) + +fig.subplots_adjust(top=0.8) +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/annotate_explain.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/annotate_explain.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/annotate_explain.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,103 @@ + +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches + +x1, y1 = 0.3, 0.3 +x2, y2 = 0.7, 0.7 + +fig = plt.figure(1, figsize=(8,3)) +fig.clf() +from mpl_toolkits.axes_grid.axes_grid import AxesGrid +from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + +#from matplotlib.font_manager import FontProperties + +def add_at(ax, t, loc=2): + fp = dict(size=10) + _at = AnchoredText(t, loc=loc, prop=fp) + ax.add_artist(_at) + return _at + + +grid = AxesGrid(fig, 111, (1, 4), label_mode="1", share_all=True) + +grid[0].set_autoscale_on(False) + +ax = grid[0] +ax.plot([x1, x2], [y1, y2], ".") +el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2) +ax.add_artist(el) +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="-", #linestyle="dashed", + color="0.5", + patchB=None, + shrinkB=0, + connectionstyle="arc3,rad=0.3", + ), + ) + +add_at(ax, "connect", loc=2) + +ax = grid[1] +ax.plot([x1, x2], [y1, y2], ".") +el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2) +ax.add_artist(el) +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="-", #linestyle="dashed", + color="0.5", + patchB=el, + shrinkB=0, + connectionstyle="arc3,rad=0.3", + ), + ) + +add_at(ax, "clip", loc=2) + + +ax = grid[2] +ax.plot([x1, x2], [y1, y2], ".") +el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2) +ax.add_artist(el) +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="-", #linestyle="dashed", + color="0.5", + patchB=el, + shrinkB=5, + connectionstyle="arc3,rad=0.3", + ), + ) + +add_at(ax, "shrink", loc=2) + + +ax = grid[3] +ax.plot([x1, x2], [y1, y2], ".") +el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2) +ax.add_artist(el) +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="fancy", #linestyle="dashed", + color="0.5", + patchB=el, + shrinkB=5, + connectionstyle="arc3,rad=0.3", + ), + ) + +add_at(ax, "mutate", loc=2) + +grid[0].set_xlim(0, 1) +grid[0].set_ylim(0, 1) +grid[0].axis["bottom"].toggle(ticklabels=False) +grid[0].axis["left"].toggle(ticklabels=False) +fig.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95) + +plt.draw() +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/annotate_simple01.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/annotate_simple01.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/annotate_simple01.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,14 @@ +import matplotlib.pyplot as plt + +plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +ax.annotate("", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3"), + ) + +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/annotate_simple02.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/annotate_simple02.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/annotate_simple02.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,15 @@ +import matplotlib.pyplot as plt + +plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +ax.annotate("Test", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + size=20, va="center", ha="center", + arrowprops=dict(arrowstyle="simple", + connectionstyle="arc3,rad=-0.2"), + ) + +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/annotate_simple03.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/annotate_simple03.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/annotate_simple03.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,17 @@ +import matplotlib.pyplot as plt + +plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +ann = ax.annotate("Test", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + size=20, va="center", ha="center", + bbox=dict(boxstyle="round4", fc="w"), + arrowprops=dict(arrowstyle="-|>", + connectionstyle="arc3,rad=-0.2", + fc="w"), + ) + +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/annotate_simple04.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/annotate_simple04.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/annotate_simple04.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,29 @@ +import matplotlib.pyplot as plt + +plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) + +ann = ax.annotate("Test", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + size=20, va="center", ha="center", + bbox=dict(boxstyle="round4", fc="w"), + arrowprops=dict(arrowstyle="-|>", + connectionstyle="arc3,rad=0.2", + relpos=(0., 0.), + fc="w"), + ) + +ann = ax.annotate("Test", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + size=20, va="center", ha="center", + bbox=dict(boxstyle="round4", fc="w"), + arrowprops=dict(arrowstyle="-|>", + connectionstyle="arc3,rad=-0.2", + relpos=(1., 0.), + fc="w"), + ) + +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/annotate_text_arrow.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/annotate_text_arrow.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/annotate_text_arrow.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,38 @@ + +import numpy.random +import matplotlib.pyplot as plt + +fig = plt.figure(1, figsize=(5,5)) +fig.clf() + +ax = fig.add_subplot(111) +ax.set_aspect(1) + +x1 = -1 + numpy.random.randn(100) +y1 = -1 + numpy.random.randn(100) +x2 = 1. + numpy.random.randn(100) +y2 = 1. + numpy.random.randn(100) + +ax.scatter(x1, y1, color="r") +ax.scatter(x2, y2, color="g") + +bbox_props = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9) +ax.text(-2, -2, "Sample A", ha="center", va="center", size=20, + bbox=bbox_props) +ax.text(2, 2, "Sample B", ha="center", va="center", size=20, + bbox=bbox_props) + + +bbox_props = dict(boxstyle="rarrow", fc=(0.8,0.9,0.9), ec="b", lw=2) +t = ax.text(0, 0, "Direction", ha="center", va="center", rotation=45, + size=15, + bbox=bbox_props) + +bb = t.get_bbox_patch() +bb.set_boxstyle("rarrow", pad=0.6) + +ax.set_xlim(-4, 4) +ax.set_ylim(-4, 4) + +plt.draw() +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/axes_zoom_effect.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/axes_zoom_effect.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/axes_zoom_effect.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1 @@ +../../../../examples/pylab_examples/axes_zoom_effect.py \ No newline at end of file Added: trunk/matplotlib/doc/users/plotting/examples/connect_simple01.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/connect_simple01.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/connect_simple01.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,31 @@ +from matplotlib.patches import ConnectionPatch +import matplotlib.pyplot as plt + +fig = plt.figure(1, figsize=(6,3)) +ax1 = plt.subplot(121) +xyA=(0.2, 0.2) +xyB=(0.8, 0.8) +coordsA="data" +coordsB="data" +con = ConnectionPatch(xyA, xyB, coordsA, coordsB, + arrowstyle="-|>", shrinkA=5, shrinkB=5, + mutation_scale=20, fc="w") +ax1.plot([xyA[0], xyB[0]], [xyA[1], xyB[1]], "o") +ax1.add_artist(con) + +ax2 = plt.subplot(122) +#xyA=(0.7, 0.7) +xy=(0.3, 0.2) +coordsA="data" +coordsB="data" +con = ConnectionPatch(xyA=xy, xyB=xy, coordsA=coordsA, coordsB=coordsB, + axesA=ax2, axesB=ax1, + arrowstyle="->", shrinkB=5) +ax2.add_artist(con) + +ax1.set_xlim(0, 1) +ax1.set_ylim(0, 1) +ax2.set_xlim(0, .5) +ax2.set_ylim(0, .5) +plt.draw() +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/connectionstyle_demo.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/connectionstyle_demo.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/connectionstyle_demo.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,109 @@ + +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches + +fig = plt.figure(1, figsize=(8,5)) +fig.clf() +from mpl_toolkits.axes_grid.axes_grid import AxesGrid +from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + +#from matplotlib.font_manager import FontProperties + +def add_at(ax, t, loc=2): + fp = dict(size=8) + _at = AnchoredText(t, loc=loc, prop=fp) + ax.add_artist(_at) + return _at + + +grid = AxesGrid(fig, 111, (3, 5), label_mode="1", share_all=True) + +grid[0].set_autoscale_on(False) + + +x1, y1 = 0.3, 0.3 +x2, y2 = 0.7, 0.7 + + +def demo_con_style(ax, connectionstyle, label=None): + + if label is None: + label = connectionstyle + + x1, y1 = 0.3, 0.2 + x2, y2 = 0.8, 0.6 + + ax.plot([x1, x2], [y1, y2], ".") + ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="->", #linestyle="dashed", + color="0.5", + shrinkA=5, shrinkB=5, + patchA=None, + patchB=None, + connectionstyle=connectionstyle, + ), + ) + + add_at(ax, label, loc=2) + +column = grid.axes_column[0] + +demo_con_style(column[0], "angle3,angleA=90,angleB=0", + label="angle3,\nangleA=90,\nangleB=0") +demo_con_style(column[1], "angle3,angleA=0,angleB=90", + label="angle3,\nangleA=0,\nangleB=90") + + + +column = grid.axes_column[1] + +demo_con_style(column[0], "arc3,rad=0.") +demo_con_style(column[1], "arc3,rad=0.3") +demo_con_style(column[2], "arc3,rad=-0.3") + + + +column = grid.axes_column[2] + +demo_con_style(column[0], "angle,angleA=-90,angleB=180,rad=0", + label="angle,\nangleA=-90,\nangleB=180,\nrad=0") +demo_con_style(column[1], "angle,angleA=-90,angleB=180,rad=5", + label="angle,\nangleA=-90,\nangleB=180,\nrad=5") +demo_con_style(column[2], "angle,angleA=-90,angleB=10,rad=5", + label="angle,\nangleA=-90,\nangleB=10,\nrad=0") + + +column = grid.axes_column[3] + +demo_con_style(column[0], "arc,angleA=-90,angleB=0,armA=30,armB=30,rad=0", + label="arc,\nangleA=-90,\nangleB=0,\narmA=30,\narmB=30,\nrad=0") +demo_con_style(column[1], "arc,angleA=-90,angleB=0,armA=30,armB=30,rad=5", + label="arc,\nangleA=-90,\nangleB=0,\narmA=30,\narmB=30,\nrad=5") +demo_con_style(column[2], "arc,angleA=-90,angleB=0,armA=0,armB=40,rad=0", + label="arc,\nangleA=-90,\nangleB=0,\narmA=0,\narmB=40,\nrad=0") + + +column = grid.axes_column[4] + +demo_con_style(column[0], "bar,fraction=0.3", + label="bar,\nfraction=0.3") +demo_con_style(column[1], "bar,fraction=-0.3", + label="bar,\nfraction=-0.3") +demo_con_style(column[2], "bar,angle=180,fraction=-0.2", + label="bar,\nangle=180,\nfraction=-0.2") + + +#demo_con_style(column[1], "arc3,rad=0.3") +#demo_con_style(column[2], "arc3,rad=-0.3") + + +grid[0].set_xlim(0, 1) +grid[0].set_ylim(0, 1) +grid.axes_llc.axis["bottom"].toggle(ticklabels=False) +grid.axes_llc.axis["left"].toggle(ticklabels=False) +fig.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95) + +plt.draw() +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle01.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle01.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle01.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,47 @@ +from matplotlib.path import Path + +def custom_box_style(x0, y0, width, height, mutation_size, mutation_aspect=1): + """ + Given the location and size of the box, return the path of + the box around it. + + - *x0*, *y0*, *width*, *height* : location and size of the box + - *mutation_size* : a reference scale for the mutation. + - *aspect_ratio* : aspect-ration for the mutation. + """ + + # note that we are ignoring mutation_aspect. This is okay in general. + + # padding + mypad = 0.3 + pad = mutation_size * mypad + + # width and height with padding added. + width, height = width + 2.*pad, \ + height + 2.*pad, + + # boundary of the padded box + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height + + cp = [(x0, y0), + (x1, y0), (x1, y1), (x0, y1), + (x0-pad, (y0+y1)/2.), (x0, y0), + (x0, y0)] + + com = [Path.MOVETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, + Path.CLOSEPOLY] + + path = Path(cp, com) + + return path + + +import matplotlib.pyplot as plt + +plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) +ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center", + bbox=dict(boxstyle=custom_box_style, alpha=0.2)) Added: trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle02.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle02.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/custom_boxstyle02.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,74 @@ +from matplotlib.path import Path +from matplotlib.patches import BoxStyle +import matplotlib.pyplot as plt + +# we may derive from matplotlib.patches.BoxStyle._Base class. +# You need to overide transmute method in this case. + +class MyStyle(BoxStyle._Base): + """ + A simple box. + """ + + def __init__(self, pad=0.3): + """ + The arguments need to be floating numbers and need to have + default values. + + *pad* + amount of padding + """ + + self.pad = pad + super(MyStyle, self).__init__() + + def transmute(self, x0, y0, width, height, mutation_size): + """ + Given the location and size of the box, return the path of + the box around it. + + - *x0*, *y0*, *width*, *height* : location and size of the box + - *mutation_size* : a reference scale for the mutation. + + Often, the *mutation_size* is the font size of the text. + You don't need to worry about the rotation as it is + automatically taken care of. + """ + + # padding + pad = mutation_size * self.pad + + # width and height with padding added. + width, height = width + 2.*pad, \ + height + 2.*pad, + + # boundary of the padded box + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height + + cp = [(x0, y0), + (x1, y0), (x1, y1), (x0, y1), + (x0-pad, (y0+y1)/2.), (x0, y0), + (x0, y0)] + + com = [Path.MOVETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, + Path.CLOSEPOLY] + + path = Path(cp, com) + + return path + + +# register the custom style +BoxStyle._style_list["angled"] = MyStyle + +plt.figure(1, figsize=(3,3)) +ax = plt.subplot(111) +ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center", rotation=30, + bbox=dict(boxstyle="angled,pad=0.5", alpha=0.2)) + +del BoxStyle._style_list["angled"] + +plt.show() Added: trunk/matplotlib/doc/users/plotting/examples/simple_annotate01.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/simple_annotate01.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/simple_annotate01.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,131 @@ + +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches + +x1, y1 = 0.3, 0.3 +x2, y2 = 0.7, 0.7 + +fig = plt.figure(1) +fig.clf() +from mpl_toolkits.axes_grid.axes_grid import Grid +from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + +from matplotlib.font_manager import FontProperties + +def add_at(ax, t, loc=2): + fp = dict(size=10) + _at = AnchoredText(t, loc=loc, prop=fp) + ax.add_artist(_at) + return _at + + +grid = Grid(fig, 111, (4, 4), label_mode="1", share_all=True) + +grid[0].set_autoscale_on(False) + +ax = grid[0] +ax.plot([x1, x2], [y1, y2], "o") +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="->")) + +add_at(ax, "A $->$ B", loc=2) + +ax = grid[1] +ax.plot([x1, x2], [y1, y2], "o") +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3,rad=0.3")) + +add_at(ax, "connectionstyle=arc3", loc=2) + + +ax = grid[2] +ax.plot([x1, x2], [y1, y2], "o") +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3,rad=0.3", + shrinkB=5, + ) + ) + +add_at(ax, "shrinkB=5", loc=2) + + +ax = grid[3] +ax.plot([x1, x2], [y1, y2], "o") +el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.5) +ax.add_artist(el) +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3,rad=0.2", + ) + ) + + +ax = grid[4] +ax.plot([x1, x2], [y1, y2], "o") +el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.5) +ax.add_artist(el) +ax.annotate("", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3,rad=0.2", + patchB=el, + ) + ) + + +add_at(ax, "patchB", loc=2) + + + +ax = grid[5] +ax.plot([x1], [y1], "o") +ax.annotate("Test", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + ha="center", va="center", + bbox=dict(boxstyle="round", + fc="w", + ), + arrowprops=dict(arrowstyle="->", + #connectionstyle="arc3,rad=0.2", + ) + ) + + +add_at(ax, "annotate", loc=2) + + +ax = grid[6] +ax.plot([x1], [y1], "o") +ax.annotate("Test", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='data', + ha="center", va="center", + bbox=dict(boxstyle="round", + fc="w", + ), + arrowprops=dict(arrowstyle="->", + #connectionstyle="arc3,rad=0.2", + relpos=(0., 0.) + ) + ) + + +add_at(ax, "relpos=(0,0)", loc=2) + + + +#ax.set_xlim(0, 1) +#ax.set_ylim(0, 1) +plt.draw() Modified: trunk/matplotlib/doc/users/plotting.rst =================================================================== --- trunk/matplotlib/doc/users/plotting.rst 2009-07-14 21:18:58 UTC (rev 7261) +++ trunk/matplotlib/doc/users/plotting.rst 2009-07-14 21:24:07 UTC (rev 7262) @@ -146,5 +146,11 @@ :ref:`plotting-guide-legend` +Annotating plot +=============== +:func:`~matplotlib.pyplot.text` and :func:`~matplotlib.pyplot.annotate` + +:ref:`plotting-guide-annotation` + TODO; see :ref:`how-to-contribute-docs`. Added: trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py 2009-07-14 21:24:07 UTC (rev 7262) @@ -0,0 +1,120 @@ +from matplotlib.transforms import Bbox, TransformedBbox, \ + blended_transform_factory + +from mpl_toolkits.axes_grid.inset_locator import BboxPatch, BboxConnector,\ + BboxConnectorPatch + + +def connect_bbox(bbox1, bbox2, + loc1a, loc2a, loc1b, loc2b, + prop_lines, prop_patches=None): + if prop_patches is None: + prop_patches = prop_lines.copy() + prop_patches["alpha"] = prop_patches.get("alpha", 1)*0.2 + + c1 = BboxConnector(bbox1, bbox2, loc1=loc1a, loc2=loc2a, **prop_lines) + c1.set_clip_on(False) + c2 = BboxConnector(bbox1, bbox2, loc1=loc1b, loc2=loc2b, **prop_lines) + c2.set_clip_on(False) + + bbox_patch1 = BboxPatch(bbox1, **prop_patches) + bbox_patch2 = BboxPatch(bbox2, **prop_patches) + + p = BboxConnectorPatch(bbox1, bbox2, + #loc1a=3, loc2a=2, loc1b=4, loc2b=1, + loc1a=loc1a, loc2a=loc2a, loc1b=loc1b, loc2b=loc2b, + **prop_patches) + p.set_clip_on(False) + + return c1, c2, bbox_patch1, bbox_patch2, p + + +def zoom_effect01(ax1, ax2, xmin, xmax, **kwargs): + u""" + ax1 : the main axes + ax1 : the zoomed axes + (xmin,xmax) : the limits of the colored area in both plot axes. + + connect ax1 & ax2. The x-range of (xmin, xmax) in both axes will + be marked. The keywords parameters will be used ti create + patches. + + """ + + trans1 = blended_transform_factory(ax1.transData, ax1.transAxes) + trans2 = blended_transform_factory(ax2.transData, ax2.transAxes) + + bbox = Bbox.from_extents(xmin, 0, xmax, 1) + + mybbox1 = TransformedBbox(bbox, trans1) + mybbox2 = TransformedBbox(bbox, trans2) + + prop_patches=kwargs.copy() + prop_patches["ec"]="none" + prop_patches["alpha"]="0.2" + + c1, c2, bbox_patch1, bbox_patch2, p = \ + connect_bbox(mybbox1, mybbox2, + loc1a=3, loc2a=2, loc1b=4, loc2b=1, + prop_lines=kwargs, prop_patches=prop_patches) + + ax1.add_patch(bbox_patch1) + ax2.add_patch(bbox_patch2) + ax2.add_patch(c1) + ax2.add_patch(c2) + ax2.add_patch(p) + + return c1, c2, bbox_patch1, bbox_patch2, p + + +def zoom_effect02(ax1, ax2, **kwargs): + u""" + ax1 : the main axes + ax1 : the zoomed axes + + Similar to zoom_effect01. The xmin & xmax will be taken from the + ax1.viewLim. + """ + + tt = ax1.transScale + (ax1.transLimits + ax2.transAxes) + trans = blended_transform_factory(ax2.transData, tt) + + mybbox1 = ax1.bbox + mybbox2 = TransformedBbox(ax1.viewLim, trans) + + prop_patches=kwargs.copy() + prop_patches["ec"]="none" + prop_patches["alpha"]="0.2" + + c1, c2, bbox_patch1, bbox_patch2, p = \ + connect_bbox(mybbox1, mybbox2, + loc1a=3, loc2a=2, loc1b=4, loc2b=1, + prop_lines=kwargs, prop_patches=prop_patches) + + ax1.add_patch(bbox_patch1) + ax2.add_patch(bbox_patch2) + ax2.add_patch(c1) + ax2.add_patch(c2) + ax2.add_patch(p) + + return c1, c2, bbox_patch1, bbox_patch2, p + + +if __name__ == "__main__": + import matplotlib.pyplot as plt + + plt.figure(1, figsize=(5,5)) + ax1 = plt.subplot(221) + ax2 = plt.subplot(212) + ax2.set_xlim(0, 1) + ax2.set_xlim(0, 5) + zoom_effect01(ax1, ax2, 0.2, 0.8) + + + ax1 = plt.subplot(222) + ax1.set_xlim(2, 3) + ax2.set_xlim(0, 5) + zoom_effect02(ax1, ax2) + + plt.show() + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |