Question: I have a chart that I'm annotating some text and would like to draw an arrow to a point, however I cannot get the arrow to center align with the text. It always aligns to the left of the text. I came across this article which shows an arrow tail center aligned with the text and points to the area of concern. This is what I'd like on my chart. import matplotlib.pyplot as plt import numpy as np plt.rcParams['figure.figsize']=(10,6) x= np.arange(0,2*np.pi,0.01) y= np.sin(x) plt.axhline(y=0, color='k',linewidth=1) # Simple arrow plt.annotate('Maximum value of sin(x)',xy=(1.55,0.98),xytext=(1,-0.25), arrowprops={"width":6,"headwidth":20,'headlength':20}, horizontalalignment='center',fontsize=15) plt.plot(x,y,label='sine curve',color='r') plt.legend() plt.grid() plt.show()  The result is this:  Where the arrow tail is center aligned with the text. However, when I try to use this snippet of code, mine is aligned to the left of the text. See below. import matplotlib.pyplot as plt import numpy as np x = np.arange(0, 200.25, 0.25) x2 = x * 1.852 y1 = (np.sqrt(x2**2 + 72227335.111 + (2*x2)*(8498.66667)*(np.sin(0.5*0.0174533))) - 8498.66667) * 3280.84 y15 = (np.sqrt(x2**2 + 72227335.111 + (2*x2)*(8498.66667)*(np.sin(0.025*0.0174533))) - 8498.66667) * 3280.84 y29 = (np.sqrt(x2**2 + 72227335.111 + (2*x2)*(8498.66667)*(np.sin(0.975*0.0174533))) - 8498.66667) * 3280.84 fig, ax = plt.subplots(figsize = (14,9)) ax.plot(x,y1,lw = 2, color = 'b') ax.plot(x,y15, lw = 0.5, color = 'b', alpha = 0.0) ax.plot(x,y29, lw = 0.5, color = 'b', alpha = 0.0) ax.set_ylim(ymin = 0) ax.set_ylim(ymax = 60000) ax.set_xlim(xmin = 0) ax.set_xlim(xmax = 200) ax.fill_between(x, y15,y29,color='b',alpha=.2) ax.grid(which='major', linestyle='-', linewidth='0.5', color='gray') ax.grid(which='minor', linestyle=':', linewidth='0.5', color='gray') ax.tick_params(axis = 'both', which = 'both', top = False, bottom = False, left = False, right = False, labelsize = 12) plt.annotate('5045 feet', xy = (50, 1500), xytext = (41.8, 7800), fontsize = 12, fontweight = 'bold', arrowprops = dict(arrowstyle = '<->', color = 'red', lw = 2)) plt.annotate('10085 feet', xy = (100, 6500), xytext = (90.5, 18000), fontsize = 12, fontweight = 'bold', arrowprops = dict(arrowstyle = '<->', color = 'red', lw = 2)) plt.annotate('15110 feet', xy = (150, 15000), xytext = (140.5, 31000), fontsize = 12, fontweight = 'bold', arrowprops = dict(arrowstyle = '<->', color = 'red', lw = 2)) plt.annotate(' 20200 feet', xy = (200, 26500), xytext = (190, 48000), fontsize = 12, fontweight = 'bold', arrowprops = dict(arrowstyle = '<->', color = 'red', lw = 2)) plt.annotate('Test Text Goes Here',xy=(21,3000),xytext=(33,20000), arrowprops={"width":6,"headwidth":20,'headlength':20}, horizontalalignment='center',fontsize=15) plt.scatter(20, 1300, s = 200, marker = '*', color = 'purple', zorder = 10) plt.scatter(98, 11600, s = 200, marker = '*', color = 'purple', zorder = 10) plt.show()  Resulting in something like this:  Is there a way to get this arrow center-aligned like in the top image?

Answer: Set xycoords='data' and xytext=(0, y)* and both the horizontal & vertical alignment parameters to "center" for always text-centered [arrow] annotations  *Where y corresponds to the apparent height¹ of the arrow.  ¹ (In this example, measured in units of "offset points" - which will be dependent on the set DPI. [default: 72]) E.g., the following modification: labels = [ "Labels", "Composed Of", "[Test Text Goes Here]", "Varying Lengths Increasingly", "Getting Longer With Each Subsequent Label", ][::-1] # Center-aligned text-arrow annotations for x, y in zip(range(21, 21 * 11, 21 * 2), range(3000, 3000 * 20, 3000 * 3)): plt.annotate( labels.pop(), xy=(x, y), xycoords="data", xytext=(0, 140), textcoords="offset points", arrowprops={"width": 6, "headwidth": 20, "headlength": 20}, horizontalalignment="center", verticalalignment="center", fontsize=15, ) plt.scatter(x, y, s=200, marker="*", color="purple", zorder=10)  produces: