Z mojego doświadczenia to działa najlepiej za pomocą annotate. W ten sposób unikasz dziwnego wypaczenia, które dostajesz z ax.arrow
, co jest trudne do kontrolowania.
EDIT: Zawinęłam go w małą funkcję.
from matplotlib import pyplot as plt
import numpy as np
def add_arrow(line, position=None, direction='right', size=15, color=None):
"""
add an arrow to a line.
line: Line2D object
position: x-position of the arrow. If None, mean of xdata is taken
direction: 'left' or 'right'
size: size of the arrow in fontsize points
color: if None, line color is taken.
"""
if color is None:
color = line.get_color()
xdata = line.get_xdata()
ydata = line.get_ydata()
if position is None:
position = xdata.mean()
# find closest index
start_ind = np.argmin(np.absolute(xdata - position))
if direction == 'right':
end_ind = start_ind + 1
else:
end_ind = start_ind - 1
line.axes.annotate('',
xytext=(xdata[start_ind], ydata[start_ind]),
xy=(xdata[end_ind], ydata[end_ind]),
arrowprops=dict(arrowstyle="->", color=color),
size=size
)
t = np.linspace(-2, 2, 100)
y = np.sin(t)
# return the handle of the line
line = plt.plot(t, y)[0]
add_arrow(line)
plt.show()
To nie jest bardzo intuicyjne, ale działa. Następnie możesz grać ze słownikiem arrowprops
, dopóki nie będzie wyglądać dobrze.
Niezły pomysł. Dzięki (+1). Nie ma sposobu na owijanie tego wszystkiego wewnątrz "fabuły"? – cjorssen
Nie, chyba że napiszesz własną funkcję "fabuły" :). Zaletą tego jest to, że rzeczy takie jak adnotacje i tekst są traktowane inaczej przez matplotlib niż rzeczy, które rysujesz, tzn. Zawsze zachowują one swój rozmiar i proporcje, itp., Gdy przeskalujesz lub powiększysz. – thomas
Ok. Ma sens. – cjorssen