|
| 1 | +""" |
| 2 | +=========== |
| 3 | +Arrow guide |
| 4 | +=========== |
| 5 | +
|
| 6 | +Adding arrow patches to plots. |
| 7 | +
|
| 8 | +Arrows are often used to annotate plots. This tutorial shows how to plot arrows |
| 9 | +that behave differently when the data limits on a plot are changed. In general, |
| 10 | +points on a plot can either be fixed in "data space" or "display space". |
| 11 | +Something plotted in data space moves when the data limits are altered - an |
| 12 | +example would the points in a scatter plot. Something plotted in display space |
| 13 | +stays static when data limits are altered - an example would be a figure title |
| 14 | +or the axis labels. |
| 15 | +
|
| 16 | +Arrows consist of a head (and possibly a tail) and a stem drawn between a |
| 17 | +start point and and end point, called 'anchor points' from now on. |
| 18 | +Here we show three use cases for plotting arrows, depending on whether the |
| 19 | +head or anchor points need to be fixed in data or display space: |
| 20 | +
|
| 21 | + 1. Head shape fixed in display space, anchor points fixed in data space |
| 22 | + 2. Head shape and anchor points fixed in display space |
| 23 | + 3. Entire patch fixed in data space |
| 24 | +
|
| 25 | +Below each use case is presented in turn. |
| 26 | +""" |
| 27 | +import matplotlib.patches as mpatches |
| 28 | +import matplotlib.pyplot as plt |
| 29 | +x_tail = 0.1 |
| 30 | +y_tail = 0.1 |
| 31 | +x_head = 0.9 |
| 32 | +y_head = 0.9 |
| 33 | +dx = x_head - x_tail |
| 34 | +dy = y_head - y_tail |
| 35 | + |
| 36 | + |
| 37 | +############################################################################### |
| 38 | +# Head shape fixed in display space and anchor points fixed in data space |
| 39 | +# ----------------------------------------------------------------------- |
| 40 | +# |
| 41 | +# This is useful if you are annotating a plot, and don't want the arrow to |
| 42 | +# to change shape or position if you pan or scale the plot. Note that when |
| 43 | +# the axis limits change |
| 44 | +# |
| 45 | +# In this case we use `.patches.FancyArrowPatch` |
| 46 | +# |
| 47 | +# Note that when the axis limits are changed, the arrow shape stays the same, |
| 48 | +# but the anchor points move. |
| 49 | + |
| 50 | +fig, axs = plt.subplots(nrows=2) |
| 51 | +arrow = mpatches.FancyArrowPatch((x_tail, y_tail), (dx, dy), |
| 52 | + mutation_scale=100) |
| 53 | +axs[0].add_patch(arrow) |
| 54 | + |
| 55 | +arrow = mpatches.FancyArrowPatch((x_tail, y_tail), (dx, dy), |
| 56 | + mutation_scale=100) |
| 57 | +axs[1].add_patch(arrow) |
| 58 | +axs[1].set_xlim(0, 2) |
| 59 | +axs[1].set_ylim(0, 2) |
| 60 | + |
| 61 | +############################################################################### |
| 62 | +# Head shape and anchor points fixed in display space |
| 63 | +# --------------------------------------------------- |
| 64 | +# |
| 65 | +# This is useful if you are annotating a plot, and don't want the arrow to |
| 66 | +# to change shape or position if you pan or scale the plot. |
| 67 | +# |
| 68 | +# In this case we use `.patches.FancyArrowPatch`, and pass the keyword argument |
| 69 | +# ``transform=ax.transAxes`` where ``ax`` is the axes we are adding the patch |
| 70 | +# to. |
| 71 | +# |
| 72 | +# Note that when the axis limits are changed, the arrow shape and location |
| 73 | +# stays the same. |
| 74 | + |
| 75 | +fig, axs = plt.subplots(nrows=2) |
| 76 | +arrow = mpatches.FancyArrowPatch((x_tail, y_tail), (dx, dy), |
| 77 | + mutation_scale=100, |
| 78 | + transform=axs[0].transAxes) |
| 79 | +axs[0].add_patch(arrow) |
| 80 | + |
| 81 | +arrow = mpatches.FancyArrowPatch((x_tail, y_tail), (dx, dy), |
| 82 | + mutation_scale=100, |
| 83 | + transform=axs[1].transAxes) |
| 84 | +axs[1].add_patch(arrow) |
| 85 | +axs[1].set_xlim(0, 2) |
| 86 | +axs[1].set_ylim(0, 2) |
| 87 | + |
| 88 | + |
| 89 | +############################################################################### |
| 90 | +# Head shape and anchor points fixed in data space |
| 91 | +# ------------------------------------------------ |
| 92 | +# |
| 93 | +# In this case we use `.patches.Arrow` |
| 94 | +# |
| 95 | +# Note that when the axis limits are changed, the arrow shape and location |
| 96 | +# changes. |
| 97 | + |
| 98 | +fig, axs = plt.subplots(nrows=2) |
| 99 | + |
| 100 | +arrow = mpatches.Arrow(x_tail, y_tail, dx, dy) |
| 101 | +axs[0].add_patch(arrow) |
| 102 | + |
| 103 | +arrow = mpatches.Arrow(x_tail, y_tail, dx, dy) |
| 104 | +axs[1].add_patch(arrow) |
| 105 | +axs[1].set_xlim(0, 2) |
| 106 | +axs[1].set_ylim(0, 2) |
| 107 | + |
| 108 | +############################################################################### |
| 109 | + |
| 110 | +plt.show() |
0 commit comments