I have a graph where I would like to annotate a specific location on the x axis with arrow and label:
- The location of the arrowhead must be precisely indicated in the data coordinates.
- The arrow must be vertical, so the x-coordinate of the blunt end of the arrow (and text label) must also be exactly indicated in the data coordinates.
- However, I would ideally want to indicate the y-position of the blunt end of the arrow relative to the bounding box of the axis, not the data.
My current working solution includes indicating the locations of both the arrowhead and the label in the data coordinates:
import numpy as np from matplotlib import pyplot as plt from matplotlib.transforms import blended_transform_factory x = np.random.randn(10000) r = 3 label = 'foo' arrowprops = dict(fc='r', ec='k') def make_example_plot(): fig, ax = plt.subplots(1, 1) ax.hold(True) counts, edges, patches = ax.hist(x) return fig, ax fig, ax = make_example_plot() lo, hi = ax.get_ylim() ax.annotate(label, xy=(r, 0), xycoords='data', xytext=(r, hi * 1.1), textcoords='data', fontsize='xx-large', ha='center', va='center', color='r', arrowprops=arrowprops) ax.set_ylim(0, hi * 1.3)

I would prefer the label to remain constant at y, regardless of how I scale or pan the y axis. I can achieve the desired effect for a simple text label by passing a mixed conversion of xy to ax.text :
fig, ax = make_example_plot() tform = blended_transform_factory(ax.transData, ax.transAxes) ax.text(r, 0.9, label, fontsize='xx-large', color='r', transform=tform)

If you reproduce this digit, then pan or zoom it, you will see that the text moves in x relative to the bounding box of the axis, but remains in a fixed position along y. Of course, this still does not give me an arrow. I was hoping that using ax.annotate you can use the same approach, but this does not work:
fig, ax = make_example_plot() tform = blended_transform_factory(ax.transData, ax.transAxes) ax.annotate(label, xy=(r, 0), xycoords='data', transform=tform, xytext=(r, 0.9), textcoords='data', fontsize='xx-large', ha='center', va='center', color='r', arrowprops=arrowprops)
The label and arrow are placed at y = 0.9 in the data coordinates, and not 90% of the total y-axis height:

Is there a way to separately specify link frames for x- and y-transforms applied to matplotlib.text.Annotation ?