iury simoes-sousa
iury simoes-sousa

Reputation: 1600

Change FaceColor and EdgeColor of Matplotlib Streamplot Arrows

I have some data in grid and I plot the streamlines with streamplot with color and width related to the speed. How can I change the color of the arrows, or just the edgecolors? My goal is to emphasis the stream direction. If someone have another way to do it..

I tried to do it using c.arrows, editing c.arrows.set_edgecolor,c.arrows.set_edgecolors,c.arrows.set_facecolor and c.arrows.set_facecolors and nothing happened, even when I run plt.draw()

Figure: The Result of the code

Code:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-10,-1, 50)
y = np.linspace(-30, -28, 50)

xi, yi = np.meshgrid(x,y)

u =  3*np.cos(xi)*((-3)*np.sin(yi))**3
v = 2*np.sin(xi)*3*np.cos(yi)
speed = np.sqrt((u**2)+(v**2))

lw = 4*speed/speed.max()

plt.ion()
plt.figure()
plt.plot(xi,yi,'-k',alpha=0.1)
plt.plot(xi.T,yi.T,'-k',alpha=0.1)
c = plt.streamplot(xi,yi,u,v,linewidth=lw,color=speed)

Upvotes: 2

Views: 3266

Answers (1)

DrV
DrV

Reputation: 23530

(Beware, the analysis below may not be completely correct, I only took a cursory look into the source.)

It seems that streamplot does two things when it creates the arrows:

  • adds arrow patches (type FancyArrowPatch) to the axes
  • adds the same arrow patches to the PatchCollection (c.arrows)

For some reason (I guess getting the correct scaling is behind this) the collection does not seem to be used and is not added to the axes. So, if you change the color map or color of the collection, it has no effect on the drawing.

There might be more beautiful ways of doing this, but if you want, e.g., black arrows into your plot, you may do this:

import matplotlib.patches

# get the axes (note that you should actually capture this when creating the subplot)
ax = plt.gca()

# iterate through the children of ax
for art in ax.get_children():
    # we are only interested in FancyArrowPatches
    if not isinstance(art, matplotlib.patches.FancyArrowPatch):
        continue
    # remove the edge, fill with black
    art.set_edgecolor([0, 0, 0, 0])
    art.set_facecolor([0, 0, 0, 1])
    # make it bigger
    art.set_mutation_scale(30)
    # move the arrow head to the front
    art.set_zorder(10)

This creates:

enter image description here

And then the usual warnings: This is ugly and fragile.

Upvotes: 4

Related Questions