Skip to content

Commit 0821495

Browse files
story645timhoffm
andcommitted
breakup annotationbbox demo and add annotationbbox to annotation guide
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
1 parent 9957c39 commit 0821495

2 files changed

Lines changed: 133 additions & 52 deletions

File tree

Lines changed: 89 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,74 @@
11
"""
2-
===================
3-
AnnotationBbox demo
4-
===================
5-
6-
`.AnnotationBbox` creates an annotation using an `.OffsetBox`, and
7-
provides more fine-grained control than `.Axes.annotate`. This example
8-
demonstrates the use of AnnotationBbox together with three different
9-
OffsetBoxes: `.TextArea`, `.DrawingArea`, and `.OffsetImage`.
2+
======================
3+
Artists as annotations
4+
======================
5+
6+
`.AnnotationBbox` facilitates annotating parts of the figure or axes using arbitrary
7+
artists, such as texts, images, and `matplotlib.patches`. `.AnnotationBbox` supports
8+
these artists via inputs that are subclasses of `.OffsetBox`, which is a class of
9+
container artists for positioning an artist relative to a parent artist.
1010
"""
1111

1212
import matplotlib.pyplot as plt
1313
import numpy as np
1414

1515
from matplotlib.cbook import get_sample_data
16-
from matplotlib.offsetbox import AnnotationBbox, DrawingArea, OffsetImage, TextArea
17-
from matplotlib.patches import Circle
16+
from matplotlib.offsetbox import (AnnotationBbox, DrawingArea, OffsetImage,
17+
TextArea)
18+
from matplotlib.patches import Annulus, Circle, ConnectionPatch
1819

19-
fig, ax = plt.subplots()
20+
# %%%%
21+
# Text
22+
# ====
23+
#
24+
# `.AnnotationBbox` supports positioning annotations relative to data, Artists, and
25+
# callables, as described in :ref:`annotations`. The `.TextArea` is used to create a
26+
# textbox that is not explicitly attached to an axes, which allows it to be used for
27+
# annotating figure objects. The `.annotate` method should be used when annotating an
28+
# axes element (such as a plot) with text.
29+
#
30+
fig, axd = plt.subplot_mosaic([['t1', '.', 't2']], layout='compressed')
2031

2132
# Define a 1st position to annotate (display it with a marker)
22-
xy = (0.5, 0.7)
23-
ax.plot(xy[0], xy[1], ".r")
24-
25-
# Annotate the 1st position with a text box ('Test 1')
33+
xy1 = (.25, .75)
34+
xy2 = (.75, .25)
35+
axd['t1'].plot(*xy1, ".r")
36+
axd['t2'].plot(*xy2, ".r")
37+
axd['t1'].set(xlim=(0, 1), ylim=(0, 1), aspect='equal')
38+
axd['t2'].set(xlim=(0, 1), ylim=(0, 1), aspect='equal')
39+
# Draw an arrow between the points
40+
41+
c = ConnectionPatch(xyA=xy1, xyB=xy2,
42+
coordsA=axd['t1'].transData, coordsB=axd['t2'].transData,
43+
arrowstyle='->')
44+
fig.add_artist(c)
45+
46+
# Annotate the ConnectionPatch position ('Test 1')
2647
offsetbox = TextArea("Test 1")
2748

28-
ab = AnnotationBbox(offsetbox, xy,
29-
xybox=(-20, 40),
30-
xycoords='data',
31-
boxcoords="offset points",
32-
arrowprops=dict(arrowstyle="->"),
33-
bboxprops=dict(boxstyle="sawtooth"))
34-
ax.add_artist(ab)
49+
ab1 = AnnotationBbox(offsetbox, (.5, .5),
50+
xybox=(0, 0),
51+
xycoords=c,
52+
boxcoords="offset points",
53+
arrowprops=dict(arrowstyle="->"),
54+
bboxprops=dict(boxstyle="sawtooth"))
55+
fig.add_artist(ab1)
3556

36-
# Annotate the 1st position with another text box ('Test')
37-
offsetbox = TextArea("Test")
57+
# %%%%
58+
# Images
59+
# ======
60+
# The `.OffsetImage` container supports plotting images. `.OffsetImage` accepts many of
61+
# the same parameters as other image plotting methods, such as *cmap*, *norm*, and
62+
# *interpolation*.
3863

39-
ab = AnnotationBbox(offsetbox, xy,
40-
xybox=(1.02, xy[1]),
41-
xycoords='data',
42-
boxcoords=("axes fraction", "data"),
43-
box_alignment=(0., 0.5),
44-
arrowprops=dict(arrowstyle="->"))
45-
ax.add_artist(ab)
4664

47-
# Define a 2nd position to annotate (don't display with a marker this time)
65+
fig, ax = plt.subplots()
66+
# Define a position to annotate (don't display with a marker)
4867
xy = [0.3, 0.55]
4968

50-
# Annotate the 2nd position with a circle patch
51-
da = DrawingArea(20, 20, 0, 0)
52-
p = Circle((10, 10), 10)
53-
da.add_artist(p)
54-
55-
ab = AnnotationBbox(da, xy,
56-
xybox=(1., xy[1]),
57-
xycoords='data',
58-
boxcoords=("axes fraction", "data"),
59-
box_alignment=(0.2, 0.5),
60-
arrowprops=dict(arrowstyle="->"),
61-
bboxprops=dict(alpha=0.5))
62-
63-
ax.add_artist(ab)
64-
65-
# Annotate the 2nd position with an image (a generated array of pixels)
69+
# Annotate a position with an image generated from an array of pixels
6670
arr = np.arange(100).reshape((10, 10))
67-
im = OffsetImage(arr, zoom=2)
71+
im = OffsetImage(arr, zoom=2, cmap='viridis')
6872
im.image.axes = ax
6973

7074
ab = AnnotationBbox(im, xy,
@@ -73,10 +77,9 @@
7377
boxcoords="offset points",
7478
pad=0.3,
7579
arrowprops=dict(arrowstyle="->"))
76-
7780
ax.add_artist(ab)
7881

79-
# Annotate the 2nd position with another image (a Grace Hopper portrait)
82+
# Annotate the position with another image (a Grace Hopper portrait)
8083
with get_sample_data("grace_hopper.jpg") as file:
8184
arr_img = plt.imread(file)
8285

@@ -101,6 +104,38 @@
101104

102105
plt.show()
103106

107+
# %%%%
108+
# Arbitrary Artists
109+
# ================
110+
#
111+
# Multiple and arbitrary artists can be placed inside a `.DrawingArea`.
112+
113+
114+
fig, ax = plt.subplots()
115+
# Define a position to annotate (don't display with a marker)
116+
xy = [0.3, 0.55]
117+
118+
# Annotate the position with a circle and annulus
119+
da = DrawingArea(30, 30, 0, 0)
120+
p = Circle((10, 10), 10, color='C0')
121+
da.add_artist(p)
122+
q = Annulus((20, 20), 10, 5, color='C1')
123+
da.add_artist(q)
124+
125+
126+
# Use the drawing area as an annotation
127+
ab = AnnotationBbox(da, xy,
128+
xybox=(.75, xy[1]),
129+
xycoords='data',
130+
boxcoords=("axes fraction", "data"),
131+
box_alignment=(0.2, 0.5),
132+
arrowprops=dict(arrowstyle="->"),
133+
bboxprops=dict(alpha=0.5))
134+
135+
ax.add_artist(ab)
136+
plt.show()
137+
#
138+
104139
# %%
105140
#
106141
# .. admonition:: References
@@ -116,3 +151,6 @@
116151
# - `matplotlib.cbook.get_sample_data`
117152
# - `matplotlib.pyplot.subplots`
118153
# - `matplotlib.pyplot.imread`
154+
#
155+
# .. tags::
156+
# component: annotation, styling: position

galleries/users_explain/text/annotations.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,11 +692,54 @@ def __call__(self, x0, y0, width, height, mutation_size):
692692

693693
ax.add_artist(anchored_box)
694694
fig.subplots_adjust(top=0.8)
695-
696695
# %%
697696
# Note that, unlike in `.Legend`, the ``bbox_transform`` is set to
698697
# `.IdentityTransform` by default
699698
#
699+
# .. _annotations-bbox:
700+
#
701+
# Using an Artist as an annotation
702+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
703+
# `.AnnotationBbox` uses `.OffsetBox` artists as the annotations and supports
704+
# positioning these annotations in the same was the other annotation methods.
705+
# For more examples, see
706+
# :doc:`/gallery/text_labels_and_annotations/demo_annotation_box`
707+
708+
from matplotlib.offsetbox import AnnotationBbox, DrawingArea, OffsetImage
709+
from matplotlib.patches import Annulus
710+
711+
fig, ax = plt.subplots()
712+
713+
text = ax.text(.2, .8, "Green!", color='green')
714+
715+
da = DrawingArea(20, 20, 0, 0)
716+
annulus = Annulus((10, 10), 10, 5, color='tab:green')
717+
da.add_artist(annulus)
718+
719+
# position annulus relative to text
720+
ab1 = AnnotationBbox(da, (.5, 0),
721+
xybox=(.5, .25),
722+
xycoords=text,
723+
boxcoords=(text, "data"),
724+
arrowprops=dict(arrowstyle="->"),
725+
bboxprops=dict(alpha=0.5))
726+
ax.add_artist(ab1)
727+
728+
N = 25
729+
arr = np.repeat(np.linspace(0, 1, N), N).reshape(N, N)
730+
im = OffsetImage(arr, cmap='Greens')
731+
im.image.axes = ax
732+
733+
# position gradient relative to text and annulus
734+
ab2 = AnnotationBbox(im, xy=(.5, 0),
735+
xybox=(.75, 0),
736+
xycoords=text,
737+
boxcoords=('data', annulus),
738+
arrowprops=dict(arrowstyle="->"),
739+
bboxprops=dict(alpha=0.5))
740+
ax.add_artist(ab2)
741+
742+
# %%%%
700743
# .. _annotating_coordinate_systems:
701744
#
702745
# Coordinate systems for annotations

0 commit comments

Comments
 (0)