diff --git a/doc/users/prev_whats_new/whats_new_3.1.0.rst b/doc/users/prev_whats_new/whats_new_3.1.0.rst index 8821f8e59257..c64e6d64291a 100644 --- a/doc/users/prev_whats_new/whats_new_3.1.0.rst +++ b/doc/users/prev_whats_new/whats_new_3.1.0.rst @@ -179,9 +179,8 @@ changed. Alternatively to strings like ``"data"`` or ``"axes fraction"``, `.ConnectionPatch` now accepts any `~matplotlib.transforms.Transform` as input for the *coordsA* and *coordsB* arguments. This allows to draw lines between -points defined in different user defined coordinate systems. Also see the -:doc:`Connect Simple01 example `. - +points defined in different user defined coordinate systems. Also see +:ref:`using_connectionpatch`. mplot3d Line3D now allows {set,get}_data_3d ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/galleries/examples/userdemo/annotate_simple_coord02.py b/galleries/examples/userdemo/annotate_simple_coord02.py deleted file mode 100644 index 18eca0ad88a4..000000000000 --- a/galleries/examples/userdemo/annotate_simple_coord02.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -======================= -Annotate Simple Coord02 -======================= - -""" - -import matplotlib.pyplot as plt - -fig, ax = plt.subplots(figsize=(3, 2)) -an1 = ax.annotate("Test 1", xy=(0.5, 0.5), xycoords="data", - va="center", ha="center", - bbox=dict(boxstyle="round", fc="w")) - -an2 = ax.annotate("Test 2", xy=(0.5, 1.), xycoords=an1, - xytext=(0.5, 1.1), textcoords=(an1, "axes fraction"), - va="bottom", ha="center", - bbox=dict(boxstyle="round", fc="w"), - arrowprops=dict(arrowstyle="->")) - -fig.subplots_adjust(top=0.83) -plt.show() diff --git a/galleries/examples/userdemo/connect_simple01.py b/galleries/examples/userdemo/connect_simple01.py deleted file mode 100644 index ab0e036713c0..000000000000 --- a/galleries/examples/userdemo/connect_simple01.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -================ -Connect Simple01 -================ - -A `.ConnectionPatch` can be used to draw a line (possibly with arrow head) -between points defined in different coordinate systems and/or axes. -""" - -import matplotlib.pyplot as plt - -from matplotlib.patches import ConnectionPatch - -fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6, 3)) - -# Draw a simple arrow between two points in axes coordinates -# within a single axes. -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) - -# Draw an arrow between the same point in data coordinates, -# but in different axes. -xy = (0.3, 0.2) -con = ConnectionPatch( - xyA=xy, coordsA=ax2.transData, - xyB=xy, coordsB=ax1.transData, - arrowstyle="->", shrinkB=5) -fig.add_artist(con) - -# Draw a line between the different points, defined in different coordinate -# systems. -con = ConnectionPatch( - # in axes coordinates - xyA=(0.6, 1.0), coordsA=ax2.transAxes, - # x in axes coordinates, y in data coordinates - xyB=(0.0, 0.2), coordsB=ax2.get_yaxis_transform(), - arrowstyle="-") -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.show() diff --git a/galleries/users_explain/text/annotations.py b/galleries/users_explain/text/annotations.py index 24991d6e0556..c9bfd08cc7e5 100644 --- a/galleries/users_explain/text/annotations.py +++ b/galleries/users_explain/text/annotations.py @@ -5,7 +5,9 @@ .. redirect-from:: /gallery/userdemo/annotate_simple04 .. redirect-from:: /gallery/userdemo/anchored_box04 .. redirect-from:: /gallery/userdemo/annotate_simple_coord01 +.. redirect-from:: /gallery/userdemo/annotate_simple_coord02 .. redirect-from:: /gallery/userdemo/annotate_simple_coord03 +.. redirect-from:: /gallery/userdemo/connect_simple01 .. redirect-from:: /tutorials/text/annotations .. _annotations: @@ -85,7 +87,7 @@ # .. _annotation-data: # # Annotating data -# ~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^ # # This example places the text coordinates in fractional axes coordinates: @@ -104,7 +106,7 @@ # %% # # Annotating an Artist -# ~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^ # # Annotations can be positioned relative to an `.Artist` instance by passing # that Artist in as *xycoords*. Then *xy* is interpreted as a fraction of the @@ -131,7 +133,7 @@ # .. _annotation-with-arrow: # # Annotating with arrows -# ~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^ # # You can enable drawing of an arrow from the text to the annotated point # by giving a dictionary of arrow properties in the optional keyword @@ -181,7 +183,7 @@ # .. _annotations-offset-text: # # Placing text annotations relative to data -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # Annotations can be positioned at a relative offset to the *xy* input to # annotation by setting the *textcoords* keyword argument to ``'offset points'`` @@ -210,7 +212,7 @@ # and :func:`~matplotlib.pyplot.annotate` before reading this section. # # Annotating with boxed text -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^^^^^ # # `~.Axes.text` takes a *bbox* keyword argument, which draws a box around the # text: @@ -261,7 +263,7 @@ # # # Defining custom box styles -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^^^^^ # # You can use a custom box style. The value for the ``boxstyle`` can be a # callable object in the following forms: @@ -307,7 +309,7 @@ def custom_box_style(x0, y0, width, height, mutation_size): # .. _annotation_with_custom_arrow: # # Customizing annotation arrows -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # An arrow connecting *xy* to *xytext* can be optionally drawn by # specifying the *arrowprops* argument. To draw only an arrow, use @@ -446,7 +448,7 @@ def custom_box_style(x0, y0, width, height, mutation_size): # %% # Placing Artist at anchored Axes locations -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # There are classes of artists that can be placed at an anchored # location in the Axes. A common example is the legend. This type @@ -562,11 +564,15 @@ def custom_box_style(x0, y0, width, height, mutation_size): # examples in :ref:`annotations-tutorial` used the ``data`` coordinate system; # Some others more advanced options are: # -# 1. A `.Transform` instance. For more information on transforms, see the -# :ref:`transforms_tutorial` For example, the -# ``Axes.transAxes`` transform positions the annotation relative to the Axes -# coordinates and using it is therefore identical to setting the -# coordinate system to "axes fraction": +# `.Transform` instance +# ^^^^^^^^^^^^^^^^^^^^^ +# +# Transforms map coordinates into different coordinate systems, usually the +# display coordinate system. See :ref:`transforms_tutorial` for a detailed +# explanation. Here Transform objects are used to identify the coordinate +# system of the corresponding points. For example, the ``Axes.transAxes`` +# transform positions the annotation relative to the Axes coordinates; therefore +# using it is identical to setting the coordinate system to "axes fraction": fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(6, 3)) ax1.annotate("Test", xy=(0.2, 0.2), xycoords=ax1.transAxes) @@ -592,8 +598,11 @@ def custom_box_style(x0, y0, width, height, mutation_size): # %% # .. _artist_annotation_coord: # -# 2. An `.Artist` instance. The *xy* value (or *xytext*) is interpreted as a -# fractional coordinate of the bounding box (bbox) of the artist: +# `.Artist` instance +# ^^^^^^^^^^^^^^^^^^ +# +# The *xy* value (or *xytext*) is interpreted as a fractional coordinate of the +# bounding box (bbox) of the artist: fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(3, 3)) an1 = ax.annotate("Test 1", @@ -614,7 +623,10 @@ def custom_box_style(x0, y0, width, height, mutation_size): # that *an2* needs to be drawn after *an1*. The base class for all bounding # boxes is `.BboxBase` # -# 3. A callable object that takes the renderer instance as single argument, and +# Callable that returns `.Transform` of `.BboxBase` +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# A callable object that takes the renderer instance as single argument, and # returns either a `.Transform` or a `.BboxBase`. For example, the return # value of `.Artist.get_window_extent` is a bbox, so this method is identical # to (2) passing in the artist: @@ -642,7 +654,10 @@ def custom_box_style(x0, y0, width, height, mutation_size): an2 = ax2.annotate("Test 2", xy=(0.5, 0.5), xycoords=ax2.get_window_extent) # %% -# 4. A blended pair of coordinate specifications -- the first for the +# Blended coordinate specification +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# A blended pair of coordinate specifications -- the first for the # x-coordinate, and the second is for the y-coordinate. For example, x=0.5 is # in data coordinates, and y=1 is in normalized axes coordinates: @@ -652,7 +667,22 @@ def custom_box_style(x0, y0, width, height, mutation_size): ax.set(xlim=(0, 2), ylim=(1, 2)) # %% -# 5. Sometimes, you want your annotation with some "offset points", not from the +# Any of the supported coordinate systems can be used in a blended +# specification. For example, the text "Anchored to 1 & 2" is positioned +# relative to the two `.Text` Artists: + +fig, ax = plt.subplots(figsize=(3, 3)) + +t1 = ax.text(0.05, .05, "Text 1", va='bottom', ha='left') +t2 = ax.text(0.90, .90, "Text 2", ha='right') +t3 = ax.annotate("Anchored to 1 & 2", xy=(0, 0), xycoords=(t1, t2), + va='bottom', color='tab:orange',) + +# %% +# `.text.OffsetFrom` +# ^^^^^^^^^^^^^^^^^^ +# +# Sometimes, you want your annotation with some "offset points", not from the # annotated point but from some other point or artist. `.text.OffsetFrom` is # a helper for such cases. @@ -672,8 +702,13 @@ def custom_box_style(x0, y0, width, height, mutation_size): arrowprops=dict(arrowstyle="->")) # %% +# Non-text annotations +# -------------------- +# +# .. _using_connectionpatch: +# # Using ConnectionPatch -# ~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^ # # `.ConnectionPatch` is like an annotation without text. While `~.Axes.annotate` # is sufficient in most situations, `.ConnectionPatch` is useful when you want @@ -698,7 +733,7 @@ def custom_box_style(x0, y0, width, height, mutation_size): # for positioning the axes. # # Zoom effect between Axes -# ~~~~~~~~~~~~~~~~~~~~~~~~ +# ^^^^^^^^^^^^^^^^^^^^^^^^ # # `mpl_toolkits.axes_grid1.inset_locator` defines some patch classes useful for # interconnecting two axes.