diff --git a/doc/mpl_toolkits/axes_grid/api/anchored_artists_api.rst b/doc/mpl_toolkits/axes_grid/api/anchored_artists_api.rst new file mode 100644 index 000000000000..4aeba4e3aaf6 --- /dev/null +++ b/doc/mpl_toolkits/axes_grid/api/anchored_artists_api.rst @@ -0,0 +1,7 @@ +:mod:`mpl_toolkits.axes_grid1.anchored_artists` +=============================================== + +.. automodule:: mpl_toolkits.axes_grid1.anchored_artists + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/mpl_toolkits/axes_grid/api/index.rst b/doc/mpl_toolkits/axes_grid/api/index.rst index 0e5975592c4b..672336ee2dbf 100644 --- a/doc/mpl_toolkits/axes_grid/api/index.rst +++ b/doc/mpl_toolkits/axes_grid/api/index.rst @@ -24,4 +24,5 @@ .. toctree:: + anchored_artists_api.rst inset_locator_api.rst diff --git a/examples/axes_grid/simple_anchored_artists.py b/examples/axes_grid/simple_anchored_artists.py index 466f1a1730cb..26ef0f6a26a8 100644 --- a/examples/axes_grid/simple_anchored_artists.py +++ b/examples/axes_grid/simple_anchored_artists.py @@ -2,7 +2,7 @@ def draw_text(ax): - from mpl_toolkits.axes_grid1.anchored_artists import AnchoredText + from matplotlib.offsetbox import AnchoredText at = AnchoredText("Figure 1a", loc=2, prop=dict(size=8), frameon=True, ) diff --git a/lib/mpl_toolkits/axes_grid1/anchored_artists.py b/lib/mpl_toolkits/axes_grid1/anchored_artists.py index 5cc7c07a2e3c..3d0650f0f8d0 100644 --- a/lib/mpl_toolkits/axes_grid1/anchored_artists.py +++ b/lib/mpl_toolkits/axes_grid1/anchored_artists.py @@ -1,43 +1,156 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +from matplotlib import docstring from matplotlib.externals import six - +from matplotlib.offsetbox import (AnchoredOffsetbox, AuxTransformBox, + DrawingArea, TextArea, VPacker) from matplotlib.patches import Rectangle, Ellipse -import numpy as np - -from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\ - TextArea, AnchoredText, DrawingArea, AnnotationBbox +__all__ = ['AnchoredDrawingArea', 'AnchoredAuxTransformBox', + 'AnchoredEllipse', 'AnchoredSizeBar'] class AnchoredDrawingArea(AnchoredOffsetbox): - """ - AnchoredOffsetbox with DrawingArea - """ - + @docstring.dedent 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. - """ + An anchored container with a fixed size and fillable DrawingArea. + + Artists added to the *drawing_area* will have their coordinates + interpreted as pixels. Any transformations set on the artists will be + overridden. + + Parameters + ---------- + width, height : int or float + width and height of the container, in pixels. + + xdescent, ydescent : int or float + descent of the container in the x- and y- direction, in pixels. + + loc : int + Location of this artist. Valid location codes are:: + + 'upper right' : 1, + 'upper left' : 2, + 'lower left' : 3, + 'lower right' : 4, + 'right' : 5, + 'center left' : 6, + 'center right' : 7, + 'lower center' : 8, + 'upper center' : 9, + 'center' : 10 + + pad : int or float, optional + Padding around the child objects, in fraction of the font + size. Defaults to 0.4. + borderpad : int or float, optional + Border padding, in fraction of the font size. + Defaults to 0.5. + + prop : `matplotlib.font_manager.FontProperties`, optional + Font property used as a reference for paddings. + + frameon : bool, optional + If True, draw a box around this artists. Defaults to True. + + **kwargs : + Keyworded arguments to pass to + :class:`matplotlib.offsetbox.AnchoredOffsetbox`. + + Attributes + ---------- + drawing_area : `matplotlib.offsetbox.DrawingArea` + A container for artists to display. + + Examples + -------- + To display blue and red circles of different sizes in the upper right + of an axes *ax*: + + >>> ada = AnchoredDrawingArea(20, 20, 0, 0, loc=1, frameon=False) + >>> ada.drawing_area.add_artist(Circle((10, 10), 10, fc="b")) + >>> ada.drawing_area.add_artist(Circle((30, 10), 5, fc="r")) + >>> ax.add_artist(ada) + """ self.da = DrawingArea(width, height, xdescent, ydescent) self.drawing_area = self.da - super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, - child=self.da, - prop=None, - frameon=frameon, - **kwargs) + super(AnchoredDrawingArea, self).__init__( + loc, pad=pad, borderpad=borderpad, child=self.da, prop=None, + frameon=frameon, **kwargs + ) class AnchoredAuxTransformBox(AnchoredOffsetbox): + @docstring.dedent def __init__(self, transform, loc, pad=0.4, borderpad=0.5, prop=None, frameon=True, **kwargs): + """ + An anchored container with transformed coordinates. + Artists added to the *drawing_area* are scaled according to the + coordinates of the transformation used. The dimensions of this artist + will scale to contain the artists added. + + Parameters + ---------- + transform : `matplotlib.transforms.Transform` + The transformation object for the coordinate system in use, i.e., + :attr:`matplotlib.axes.Axes.transData`. + + loc : int + Location of this artist. Valid location codes are:: + + 'upper right' : 1, + 'upper left' : 2, + 'lower left' : 3, + 'lower right' : 4, + 'right' : 5, + 'center left' : 6, + 'center right' : 7, + 'lower center' : 8, + 'upper center' : 9, + 'center' : 10 + + pad : int or float, optional + Padding around the child objects, in fraction of the font + size. Defaults to 0.4. + + borderpad : int or float, optional + Border padding, in fraction of the font size. + Defaults to 0.5. + + prop : `matplotlib.font_manager.FontProperties`, optional + Font property used as a reference for paddings. + + frameon : bool, optional + If True, draw a box around this artists. Defaults to True. + + **kwargs : + Keyworded arguments to pass to + :class:`matplotlib.offsetbox.AnchoredOffsetbox`. + + Attributes + ---------- + drawing_area : `matplotlib.offsetbox.AuxTransformBox` + A container for artists to display. + + Examples + -------- + To display an ellipse in the upper left, with a width of 0.1 and + height of 0.4 in data coordinates: + + >>> box = AnchoredAuxTransformBox(ax.transData, loc=2) + >>> el = Ellipse((0,0), width=0.1, height=0.4, angle=30) + >>> box.drawing_area.add_artist(el) + >>> ax.add_artist(box) + """ self.drawing_area = AuxTransformBox(transform) AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, @@ -47,17 +160,64 @@ def __init__(self, transform, loc, **kwargs) - class AnchoredEllipse(AnchoredOffsetbox): + @docstring.dedent def __init__(self, transform, width, height, angle, loc, pad=0.1, borderpad=0.1, prop=None, frameon=True, **kwargs): """ - Draw an ellipse the size in data coordinate of the give axes. + Draw an anchored ellipse of a given size. + + Parameters + ---------- + transform : `matplotlib.transforms.Transform` + The transformation object for the coordinate system in use, i.e., + :attr:`matplotlib.axes.Axes.transData`. + + width, height : int or float + Width and height of the ellipse, given in coordinates of + *transform*. + + angle : int or float + Rotation of the ellipse, in degrees, anti-clockwise. + + loc : int + Location of this size bar. Valid location codes are:: + + 'upper right' : 1, + 'upper left' : 2, + 'lower left' : 3, + 'lower right' : 4, + 'right' : 5, + 'center left' : 6, + 'center right' : 7, + 'lower center' : 8, + 'upper center' : 9, + 'center' : 10 + + pad : int or float, optional + Padding around the ellipse, in fraction of the font size. Defaults + to 0.1. - pad, borderpad in fraction of the legend font size (or prop) + borderpad : int or float, optional + Border padding, in fraction of the font size. Defaults to 0.1. + + frameon : bool, optional + If True, draw a box around the ellipse. Defaults to True. + + prop : `matplotlib.font_manager.FontProperties`, optional + Font property used as a reference for paddings. + + **kwargs : + Keyworded arguments to pass to + :class:`matplotlib.offsetbox.AnchoredOffsetbox`. + + Attributes + ---------- + ellipse : `matplotlib.patches.Ellipse` + Ellipse patch drawn. """ self._box = AuxTransformBox(transform) - self.ellipse = Ellipse((0,0), width, height, angle) + self.ellipse = Ellipse((0, 0), width, height, angle) self._box.add_artist(self.ellipse) AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, @@ -67,51 +227,100 @@ def __init__(self, transform, width, height, angle, loc, class AnchoredSizeBar(AnchoredOffsetbox): + @docstring.dedent def __init__(self, transform, size, label, loc, pad=0.1, borderpad=0.1, sep=2, frameon=True, size_vertical=0, color='black', label_top=False, fontproperties=None, **kwargs): """ - Draw a horizontal bar with the size in data coordinate of the given axes. - A label will be drawn underneath (center-aligned). + Draw a horizontal scale bar with a center-aligned label underneath. + + Parameters + ---------- + transform : `matplotlib.transforms.Transform` + The transformation object for the coordinate system in use, i.e., + :attr:`matplotlib.axes.Axes.transData`. - Parameters: - ----------- - transform : matplotlib transformation object size : int or float - horizontal length of the size bar, given in data coordinates + Horizontal length of the size bar, given in coordinates of + *transform*. + label : str + Label to display. + loc : int + Location of this size bar. Valid location codes are:: + + 'upper right' : 1, + 'upper left' : 2, + 'lower left' : 3, + 'lower right' : 4, + 'right' : 5, + 'center left' : 6, + 'center right' : 7, + 'lower center' : 8, + 'upper center' : 9, + 'center' : 10 + pad : int or float, optional - in fraction of the legend font size (or prop) + Padding around the label and size bar, in fraction of the font + size. Defaults to 0.1. + borderpad : int or float, optional - in fraction of the legend font size (or prop) + Border padding, in fraction of the font size. + Defaults to 0.1. + sep : int or float, optional - in points + Seperation between the label and the size bar, in points. + Defaults to 2. + frameon : bool, optional - if True, will draw a box around the horizontal bar and label + If True, draw a box around the horizontal bar and label. + Defaults to True. + size_vertical : int or float, optional - vertical length of the size bar, given in data coordinates + Vertical length of the size bar, given in coordinates of + *transform*. Defaults to 0. + color : str, optional - color for the size bar and label + Color for the size bar and label. + Defaults to black. + label_top : bool, optional - if True, the label will be over the rectangle - fontproperties: a matplotlib.font_manager.FontProperties instance, optional - sets the font properties for the label text + If True, the label will be over the size bar. + Defaults to False. - Returns: - -------- - AnchoredSizeBar object + fontproperties : `matplotlib.font_manager.FontProperties`, optional + Font properties for the label text. + + **kwargs : + Keyworded arguments to pass to + :class:`matplotlib.offsetbox.AnchoredOffsetbox`. + + Attributes + ---------- + size_bar : `matplotlib.offsetbox.AuxTransformBox` + Container for the size bar. - Example: + txt_label : `matplotlib.offsetbox.TextArea` + Container for the label of the size bar. + + Notes + ----- + If *prop* is passed as a keyworded argument, but *fontproperties* is + not, then *prop* is be assumed to be the intended *fontproperties*. + Using both *prop* and *fontproperties* is not supported. + + Examples -------- >>> import matplotlib.pyplot as plt >>> import numpy as np - >>> from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar + >>> from mpl_toolkits.axes_grid1.anchored_artists import \ +AnchoredSizeBar >>> fig, ax = plt.subplots() >>> ax.imshow(np.random.random((10,10))) - >>> bar = AnchoredSizeBar(ax.transData, 3, '3 units', 4) + >>> bar = AnchoredSizeBar(ax.transData, 3, '3 data units', 4) >>> ax.add_artist(bar) >>> fig.show() @@ -119,18 +328,16 @@ def __init__(self, transform, size, label, loc, >>> import matplotlib.font_manager as fm >>> fontprops = fm.FontProperties(size=14, family='monospace') - >>> bar = AnchoredSizeBar(ax.transData, 3, '3 units', 4, pad=0.5, sep=5, borderpad=0.5, frameon=False, size_vertical=0.5, color='white', fontproperties=fontprops) - + >>> bar = AnchoredSizeBar(ax.transData, 3, '3 units', 4, pad=0.5, \ +sep=5, borderpad=0.5, frameon=False, \ +size_vertical=0.5, color='white', \ +fontproperties=fontprops) """ - self.size_bar = AuxTransformBox(transform) self.size_bar.add_artist(Rectangle((0, 0), size, size_vertical, fill=True, facecolor=color, edgecolor=color)) - # if fontproperties is None, but `prop` is not, assume that - # prop should be used to set the font properties. This is - # questionable behavior if fontproperties is None and 'prop' in kwargs: fontproperties = kwargs.pop('prop') @@ -157,73 +364,3 @@ def __init__(self, transform, size, label, loc, child=self._box, prop=fontproperties, 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()