fill color between arrowheads in a quiver plot

Viewed 100

I'm plotting a few arrows in a quiver plot, and I wonder if there is a way to fill the shape traced between the arrowheads with color. The quiver plots look like this:

import numpy as np
import matplotlib.pyplot as plt

theta = np.linspace( 0 , 2 * np.pi , 40 ) 
R = 5.0
x = R * np.cos( theta ) 
y = R * np.sin( theta ) 
m2_x = 9.0
m2_y = 9.0
u = -(x - m2_x)/((m2_x - x)**2 + (m2_y - y)**2)**2 
v = -(y - m2_y)/((m2_x - x)**2 + (m2_y - y)**2)**2 

fig, ax = plt.subplots(figsize=(7,7))
ax.quiver(x,y,u,v, headwidth=2, headlength=5, width=0.005)
ax.set_xlim((-20,20))
ax.set_ylim((-20,20))

I want to fill the circle-ish shape traced by the arrow heads with color, or at least connect the arrowheads with a line. Seems like it should be simple but I couldn't find how yet.

1 Answers

quiver returns a specialized PolyCollection for arrows. The tip of the arrow head is vertice #3 of each arrow. From this collection we get the coordinates of the arrowheads and create a PathPatch to add to the Axes:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.path as mpath
import matplotlib.patches as mpatches

theta = np.linspace( 0 , 2 * np.pi , 40 ) 
R = 5.0
x = R * np.cos( theta ) 
y = R * np.sin( theta ) 
m2_x = 9.0
m2_y = 9.0
u = -(x - m2_x)/((m2_x - x)**2 + (m2_y - y)**2)**2 
v = -(y - m2_y)/((m2_x - x)**2 + (m2_y - y)**2)**2 

fig, ax = plt.subplots(figsize=(7,7))
q = ax.quiver(x,y,u,v, headwidth=2, headlength=5, width=0.005)
ax.set_xlim((-20,20))
ax.set_ylim((-20,20))

# draw the quiver to get the coordinates of the arrows
fig.draw_without_rendering()

# get x,y in display coords (pixels)
xy_disp = q.transform.transform(q.properties()['offsets'])

# get arrow heads in display coords, relative to x,y
heads_rel = np.vstack([p.vertices[3] for p in q.properties()['paths']])
heads_rel_disp = q.properties()['transform'].transform(heads_rel)

# get arrow heads in absolute data coordinates
heads = q.transform.inverted().transform(xy_disp + heads_rel_disp)

# draw patch
ax.add_patch(mpatches.PathPatch(mpath.Path(heads), fc='r', alpha=0.5))

enter image description here

Related