matplotlibgraphics

How to center an annotation horizontally over a point?


I'd like to take something like this code for scatter plot annotations...

import matplotlib; matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
    
labels = ["Abra", "Kadabra", "Alazkazam", "Mew"]
x_values = [0.3, 0.6, 0.2, 0.4]
y_values = [0.2, 0.2, 0.4, 0.9]

fig = plt.figure(figsize=(5, 5))
plt.axis('off')

renderer = fig.canvas.get_renderer()

for i, label in enumerate(labels):
    plt.scatter(x_values[i], y_values[i])
    text_object = plt.annotate(label, xy=(x_values[i], y_values[i]))

plt.savefig("horizontally_centered_text_annotations.png")

...which produces this plot: annotations without centering

...and make it produce something like this plot: annotations with centering

I've tried getting the window extent around the text boxes, grabbing the x coordinate and width, and shifting over for each annotation like so:

for i, label in enumerate(labels):
    plt.scatter(x_values[i], y_values[i])
    text_object = plt.annotate(label, xy=(x_values[i], y_values[i]))
    text_window_extent = text_object.get_window_extent(renderer)
    new_x_position = x_values[i] - text_window_extent.width / 2
    text_object.set_position((new_x_position, y_values[i]))
    print "x_value: {}, window_extent_width: {}, new_x_position: {}".format(x_values[i], text_window_extent.width, new_x_position)

But as you can see here from print statements the widths are too big:

x_value: 0.3, window_extent_width: 31.5, new_x_position: -15.45
x_value: 0.6, window_extent_width: 56.0, new_x_position: -27.4
x_value: 0.2, window_extent_width: 72.875, new_x_position: -36.2375
x_value: 0.4, window_extent_width: 30.75, new_x_position: -14.975

Not sure how if this has to do with coordinate systems...


Solution

  • Use the horizontalalignment (which can be shortened as ha) option to the annotate call:

    text_object = plt.annotate(label, xy=(x_values[i], y_values[i]), ha='center')