From cc76e51747674f611db118d06ccbdd8881e2237d Mon Sep 17 00:00:00 2001 From: hannah Date: Sun, 22 Dec 2024 18:39:29 -0500 Subject: [PATCH] breakup annotationbbox demo and add annotationbbox to annotation guide Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- .../demo_annotation_box.py | 137 +++++++++++------- galleries/users_explain/text/annotations.py | 45 +++++- 2 files changed, 131 insertions(+), 51 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/demo_annotation_box.py b/galleries/examples/text_labels_and_annotations/demo_annotation_box.py index ad28c4abd96c..84030593bbfa 100644 --- a/galleries/examples/text_labels_and_annotations/demo_annotation_box.py +++ b/galleries/examples/text_labels_and_annotations/demo_annotation_box.py @@ -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` facilitates annotating parts of the figure or axes using arbitrary +artists, such as texts, images, and `matplotlib.patches`. `.AnnotationBbox` supports +these artists via inputs that are subclasses of `.OffsetBox`, which is a class of +container artists for positioning an artist relative to a parent artist. """ import matplotlib.pyplot as plt @@ -15,57 +15,60 @@ 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, ConnectionPatch -fig, ax = plt.subplots() +# %%%% +# 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, which allows it to be used for +# annotating figure objects. The `.annotate` method should be used when annotating an +# axes element (such as a plot) with text. +# +fig, axd = plt.subplot_mosaic([['t1', '.', 't2']], layout='compressed') # Define a 1st position to annotate (display it with a marker) -xy = (0.5, 0.7) -ax.plot(xy[0], xy[1], ".r") - -# Annotate the 1st position with a text box ('Test 1') +xy1 = (.25, .75) +xy2 = (.75, .25) +axd['t1'].plot(*xy1, ".r") +axd['t2'].plot(*xy2, ".r") +axd['t1'].set(xlim=(0, 1), ylim=(0, 1), aspect='equal') +axd['t2'].set(xlim=(0, 1), ylim=(0, 1), aspect='equal') +# Draw an arrow between the points + +c = ConnectionPatch(xyA=xy1, xyB=xy2, + coordsA=axd['t1'].transData, coordsB=axd['t2'].transData, + arrowstyle='->') +fig.add_artist(c) + +# Annotate the ConnectionPatch position ('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, (.5, .5), + xybox=(0, 0), + xycoords=c, + boxcoords="offset points", + arrowprops=dict(arrowstyle="->"), + bboxprops=dict(boxstyle="sawtooth")) +fig.add_artist(ab1) -# Annotate the 1st position with another text box ('Test') -offsetbox = TextArea("Test") +# %%%% +# Images +# ====== +# The `.OffsetImage` container supports plotting images. `.OffsetImage` accepts many of +# the same parameters as other image plotting methods, such as *cmap*, *norm*, and +# *interpolation*. -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) -# Define a 2nd position to annotate (don't display with a marker this time) +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 a circle patch -da = DrawingArea(20, 20, 0, 0) -p = Circle((10, 10), 10) -da.add_artist(p) - -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) - -# 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, @@ -74,10 +77,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) @@ -102,6 +104,38 @@ plt.show() +# %%%% +# Arbitrary Artists +# ================ +# +# Multiple and arbitrary artists can be placed inside a `.DrawingArea`. + + +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 @@ -117,3 +151,6 @@ # - `matplotlib.cbook.get_sample_data` # - `matplotlib.pyplot.subplots` # - `matplotlib.pyplot.imread` +# +# .. tags:: +# component: annotation, styling: position diff --git a/galleries/users_explain/text/annotations.py b/galleries/users_explain/text/annotations.py index 5cfb16c12715..d0ae0d0070f6 100644 --- a/galleries/users_explain/text/annotations.py +++ b/galleries/users_explain/text/annotations.py @@ -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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy