In matplotlib, is there a way to specify arrow head sizes in figure units rather than in data units?
The use case is: I am making a multi-panel figure in which each panel has a different axis size (e.g., one goes from 0 to 1 on the X-axis, and the next goes from 0 to 10). I'd like the arrows to appear the same in each panel. I'd also like the arrows to appear the same independent of direction.
For axes with an aspect ratio not equal to 1, the width of the tail (and therefore the size of the head) varies with direction.
The closest I've come is, after drawing on the canvas:
dx = ax.get_xlim()[1] - ax.get_xlim()[0]
for arrow in ax.patches:
arrow.set_data(width=dx/50)
but this does not work; it results in images like this:
Just use ax.annotate()
instead of ax.arrow()
:
import matplotlib.pyplot as plt
import numpy as np
xlim, ylim = (-.3, .8), (0, 5.8)
arrow_start, arrow_end = np.asarray([.1, 3]), np.asarray([.5, 5])
fig = plt.figure(figsize=(3, 2))
ax = plt.gca()
ax.set_title('using ax.arrow()')
ax.set_xlim(xlim)
ax.set_ylim(ylim)
ax.arrow(*arrow_start, *(arrow_end - arrow_start), width=1/50)
fig = plt.figure(figsize=(3, 2))
ax = plt.gca()
ax.set_title('using ax.annotate()')
ax.set_xlim(xlim)
ax.set_ylim(ylim)
ax.annotate('', arrow_end, arrow_start, arrowprops=dict(width=5, headwidth=10, headlength=5))