0

I want to plot a path (circle) in a vector field and calculate the work done on the path by the field (line integral). To visualise this, it is important to see which direction the circle path is going in. So I was wondering if there's a way to have arrows on the circle (at every 20 points for example) to show this?

The code follows:

import matplotlib.pyplot as plt
import numpy as np

t= np.linspace(0, 2*np.pi, 100)
x= np.cos(t)
y= np.sin(t)

X= Y = np.arange(-2,2,0.2)
X, Y = np.meshgrid(X,Y)
I = Y
J = -X

plt.figure()
plt.plot(x,y)
plt.quiver(X, Y, I, J)
plt.xlabel('x')
plt.ylabel('y')
plt.show()

I saw this picture on another question but the answer didn't work for me (and my reputation isn't high enough to comment or get help there)
enter image description here

link for the question: Arrow on a line plot with matplotlib

PS.
Python 3.6 and using the latest versions.

Reblochon Masque
  • 35,405
  • 10
  • 55
  • 80
Shervin Rad
  • 460
  • 9
  • 21

2 Answers2

2

The following approach samples values on the curve, calculates a direction for the tangent, and overlays a short arrow on the plotted curve:

import matplotlib.pyplot as plt
import numpy as np


t = np.linspace(0, 2*np.pi, 100)
x = np.cos(t)
y = np.sin(t)

# sample at 0, 1/3rd, and 2/3rd of curve 
adx0, adx1 = 0, len(t) // 3
adx2 = adx1 * 2

arrow0 = x[adx0+1], y[adx0+1], x[adx0+1]-x[adx0], y[adx0+1]-y[adx0]
arrow1 = x[adx1+1], y[adx1+1], x[adx1+1]-x[adx1], y[adx1+1]-y[adx1]
arrow2 = x[adx2+1], y[adx2+1], x[adx2+1]-x[adx2], y[adx2+1]-y[adx2]

X = Y = np.arange(-2, 2, 0.2)
X, Y = np.meshgrid(X, Y)
I = -Y
J = X

plt.figure()
plt.plot(x, y)
plt.arrow(*arrow0, shape='full', lw=0, length_includes_head=True, head_width=0.12) 
plt.arrow(*arrow1, shape='full', lw=0, length_includes_head=True, head_width=0.12)  
plt.arrow(*arrow2, shape='full', lw=0, length_includes_head=True, head_width=0.12)

plt.quiver(X, Y, I, J)

plt.xlabel('x')
plt.ylabel('y')
plt.show()

The result looks like this:

enter image description here

Reblochon Masque
  • 35,405
  • 10
  • 55
  • 80
  • Thanks so much! Exactly what I was looking for – Shervin Rad Aug 05 '18 at 13:06
  • The arrows are reversed in this solution because you are subtracting the initial values from the final ones. You are doing `x[adx0] - x[adx0+1]` instead of the correct `x[adx0+1] - x[adx0]`. You can also see the arrows are reversed in the graph because the unit circle `(cos(t), sin(t), 0 <= t <= 2pi` always goes counter clockwise, but this graph shows it going clockwise. – Ani Aggarwal Jan 31 '21 at 15:42
  • Thank you for bringing this to my attention @AniAggarwal; your edit omitted reversing the underlying vector field; I have corrected it, and updated the plot image. – Reblochon Masque Jan 31 '21 at 22:55
2

Further to @Reblochon Masque's answer, I wrote his code in a loop just to make it look nicer and you can sample as many arrows as you like (for anyone who wants to use it):

arrows = 6   # Number of arrows we want
p = []

# Coordinates for arrow 
xs_  = []
ys_  = []
dxs_ = []
dys_ = []

for i in range(arrows):
    p.append(int(i/arrows*len(t))) # Equally spaced intervals
    ys_.append(y[p[i]+1])
    xs_.append(x[p[i]+1])
    dys_.append(y[p[i]]-y[p[i]+1])
    dxs_.append(x[p[i]]-x[p[i]+1])
    plt.arrow(xs_[i],ys_[i],dxs_[i],dys_[i],shape='full', lw=0, length_includes_head=True, head_width=0.12)
Community
  • 1
  • 1
Shervin Rad
  • 460
  • 9
  • 21