Skip to content

Commit

Permalink
breakup annotationbbox demo and add annotationbbox to annotation guide
Browse files Browse the repository at this point in the history
  • Loading branch information
story645 committed Dec 23, 2024
1 parent c01eb01 commit 91d2558
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 45 deletions.
119 changes: 75 additions & 44 deletions galleries/examples/text_labels_and_annotations/demo_annotation_box.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""
===================
AnnotationBbox demo
===================
`.AnnotationBbox` creates an annotation using an `.OffsetBox`, and
provides more fine-grained control than `.Axes.annotate`. This example
demonstrates the use of AnnotationBbox together with three different
OffsetBoxes: `.TextArea`, `.DrawingArea`, and `.OffsetImage`.
======================
Artists as annotations
======================
`.AnnotationBbox` creates an annotation using an `.OffsetBox` object, which is a class
of container artists for positioning an artist relative to a parent artist. This allows
for annotations that are texts, images, and arbitrary artists. `.AnnotationBbox` also
provides more fine-grained control than `.Axes.annotate`.
"""

import matplotlib.pyplot as plt
Expand All @@ -15,8 +15,16 @@
from matplotlib.cbook import get_sample_data
from matplotlib.offsetbox import (AnnotationBbox, DrawingArea, OffsetImage,
TextArea)
from matplotlib.patches import Circle
from matplotlib.patches import Annulus, Circle

# %%%%
# Text
# ====
#
# `.AnnotationBbox` supports positioning annotations relative to data, Artists, and
# callables, as described in :ref:`annotations`. The `.TextArea` is used to create a
# textbox that is not explicitly attached to an axes.
#
fig, ax = plt.subplots()

# Define a 1st position to annotate (display it with a marker)
Expand All @@ -26,46 +34,37 @@
# Annotate the 1st position with a text box ('Test 1')
offsetbox = TextArea("Test 1")

ab = AnnotationBbox(offsetbox, xy,
xybox=(-20, 40),
xycoords='data',
boxcoords="offset points",
arrowprops=dict(arrowstyle="->"),
bboxprops=dict(boxstyle="sawtooth"))
ax.add_artist(ab)
ab1 = AnnotationBbox(offsetbox, xy,
xybox=(-20, 40),
xycoords='data',
boxcoords="offset points",
arrowprops=dict(arrowstyle="->"),
bboxprops=dict(boxstyle="sawtooth"))
ax.add_artist(ab1)

# Annotate the 1st position with another text box ('Test')
offsetbox = TextArea("Test")

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)
offsetbox = TextArea("Test 2")

# Define a 2nd position to annotate (don't display with a marker this time)
xy = [0.3, 0.55]
ab2 = AnnotationBbox(offsetbox, (1, .85),
xybox=(.75, xy[1]),
xycoords=ab1,
boxcoords=("axes fraction", "data"),
box_alignment=(0., 0.5),
arrowprops=dict(arrowstyle="->"))
ax.add_artist(ab2)

# Annotate the 2nd position with a circle patch
da = DrawingArea(20, 20, 0, 0)
p = Circle((10, 10), 10)
da.add_artist(p)
# %%%%
# Images
# ======
# The `.OffsetImage` container supports plotting images using `.BboxImage`

ab = AnnotationBbox(da, xy,
xybox=(1., xy[1]),
xycoords='data',
boxcoords=("axes fraction", "data"),
box_alignment=(0.2, 0.5),
arrowprops=dict(arrowstyle="->"),
bboxprops=dict(alpha=0.5))

ax.add_artist(ab)
fig, ax = plt.subplots()
# Define a position to annotate (don't display with a marker)
xy = [0.3, 0.55]

# Annotate the 2nd position with an image (a generated array of pixels)
# Annotate a position with an image generated from an array of pixels
arr = np.arange(100).reshape((10, 10))
im = OffsetImage(arr, zoom=2)
im = OffsetImage(arr, zoom=2, cmap='viridis')
im.image.axes = ax

ab = AnnotationBbox(im, xy,
Expand All @@ -74,10 +73,9 @@
boxcoords="offset points",
pad=0.3,
arrowprops=dict(arrowstyle="->"))

ax.add_artist(ab)

# Annotate the 2nd position with another image (a Grace Hopper portrait)
# Annotate the position with another image (a Grace Hopper portrait)
with get_sample_data("grace_hopper.jpg") as file:
arr_img = plt.imread(file)

Expand All @@ -102,6 +100,36 @@

plt.show()

# %%%%
# Arbitrary Artists
# ================
# `.DrawingArea` artists position arbitrary artists relative to their parent artists.

fig, ax = plt.subplots()
# Define a position to annotate (don't display with a marker)
xy = [0.3, 0.55]

# Annotate the position with a circle and annulus
da = DrawingArea(30, 30, 0, 0)
p = Circle((10, 10), 10, color='C0')
da.add_artist(p)
q = Annulus((20, 20), 10, 5, color='C1')
da.add_artist(q)


# Use the drawing area as an annotation
ab = AnnotationBbox(da, xy,
xybox=(.75, xy[1]),
xycoords='data',
boxcoords=("axes fraction", "data"),
box_alignment=(0.2, 0.5),
arrowprops=dict(arrowstyle="->"),
bboxprops=dict(alpha=0.5))

ax.add_artist(ab)
plt.show()
#

# %%
#
# .. admonition:: References
Expand All @@ -117,3 +145,6 @@
# - `matplotlib.cbook.get_sample_data`
# - `matplotlib.pyplot.subplots`
# - `matplotlib.pyplot.imread`
#
# .. tags::
# component: annotation, styling: position
45 changes: 44 additions & 1 deletion galleries/users_explain/text/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,54 @@ def __call__(self, x0, y0, width, height, mutation_size):

ax.add_artist(anchored_box)
fig.subplots_adjust(top=0.8)

# %%
# Note that, unlike in `.Legend`, the ``bbox_transform`` is set to
# `.IdentityTransform` by default
#
# .. _annotations-bbox:
#
# Using an Artist as an annotation
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# `.AnnotationBbox` uses `.OffsetBox` artists as the annotations and supports
# positioning these annotations in the same was the other annotation methods.
# For more examples, see
# :doc:`/gallery/text_labels_and_annotations/demo_annotation_box`

from matplotlib.offsetbox import AnnotationBbox, DrawingArea, OffsetImage
from matplotlib.patches import Annulus

fig, ax = plt.subplots()

text = ax.text(.2, .8, "Green!", color='green')

da = DrawingArea(20, 20, 0, 0)
annulus = Annulus((10, 10), 10, 5, color='tab:green')
da.add_artist(annulus)

# position annulus relative to text
ab1 = AnnotationBbox(da, (.5, 0),
xybox=(.5, .25),
xycoords=text,
boxcoords=(text, "data"),
arrowprops=dict(arrowstyle="->"),
bboxprops=dict(alpha=0.5))
ax.add_artist(ab1)

N = 25
arr = np.repeat(np.linspace(0, 1, N), N).reshape(N, N)
im = OffsetImage(arr, cmap='Greens')
im.image.axes = ax

# position gradient relative to text and annulus
ab2 = AnnotationBbox(im, xy=(.5, 0),
xybox=(.75, 0),
xycoords=text,
boxcoords=('data', annulus),
arrowprops=dict(arrowstyle="->"),
bboxprops=dict(alpha=0.5))
ax.add_artist(ab2)

# %%%%
# .. _annotating_coordinate_systems:
#
# Coordinate systems for annotations
Expand Down

0 comments on commit 91d2558

Please sign in to comment.