Visualizing a vector field with Matplotlib


Matplotlib provides a function, streamplot, to create a plot of streamlines representing a vector field. The following program displays a representation of the electric field vector resulting from a multipole arrangement of charges. The multipole is selected as a power of 2 on the command line (1=dipole, 2=quadrupole, etc.)

It requires Matplotlib 1.5+ because of the choice of colormap ( this can be replaced with another (for example if using an older version of Matplotlib.

import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle

def E(q, r0, x, y):
    """Return the electric field vector E=(Ex,Ey) due to charge q at r0."""
    den = np.hypot(x-r0[0], y-r0[1])**3
    return q * (x - r0[0]) / den, q * (y - r0[1]) / den

# Grid of x, y points
nx, ny = 64, 64
x = np.linspace(-2, 2, nx)
y = np.linspace(-2, 2, ny)
X, Y = np.meshgrid(x, y)

# Create a multipole with nq charges of alternating sign, equally spaced
# on the unit circle.
nq = 2**int(sys.argv[1])
charges = []
for i in range(nq):
    q = i%2 * 2 - 1
    charges.append((q, (np.cos(2*np.pi*i/nq), np.sin(2*np.pi*i/nq))))

# Electric field vector, E=(Ex, Ey), as separate components
Ex, Ey = np.zeros((ny, nx)), np.zeros((ny, nx))
for charge in charges:
    ex, ey = E(*charge, x=X, y=Y)
    Ex += ex
    Ey += ey

fig = plt.figure()
ax = fig.add_subplot(111)

# Plot the streamlines with an appropriate colormap and arrow style
color = 2 * np.log(np.hypot(Ex, Ey))
ax.streamplot(x, y, Ex, Ey, color=color, linewidth=1,,
              density=2, arrowstyle='->', arrowsize=1.5)

# Add filled circles for the charges themselves
charge_colors = {True: '#aa0000', False: '#0000aa'}
for q, pos in charges:
    ax.add_artist(Circle(pos, 0.05, color=charge_colors[q>0]))


The electric field of a dipole: $ python 1 Electric field of a dipole

The electric field of an octopole: $ python 3 Electric field of an octopole

Current rating: 4.5


Stafford 2 years ago

What clever program, Loved it. I had to change the 'inferno' to 'hot' as we were warned in the opening comments. Didn't
realise I was using an outdated version of matplotlib.

Link | Reply
Current rating: 5

christian 2 years ago

Thanks, Stafford – the issue of colormaps is one that exercises some people a great deal: for a good article about how awful the default colormap, jet, is, take a look here:

Link | Reply
Current rating: 3

Steven Armour 1 year, 3 months ago

Would you be opposed to me publishing a reproduction of this example that I made with the python yt lib ( to the yt repository examples archive? (they need non-astro examples like nothing else) I have already made a prototype of what I am purposing for my E&M class last fall and would also like you to review the photo notebook as well as the final notebook to make sure there are no errors in trying to visualize the vector field volumetrically.

Steven Armour

Link | Reply
Currently unrated

christian 1 year, 3 months ago

Not at all – you're welcome to the example and any code here you find useful. I'd be happy to take a look at the Notebook you are preparing for your EM class.
Best wishes,

Link | Reply
Currently unrated

Youcef 1 year, 1 month ago

i have some trouble running this program, it gives me this error if you can help me figure out what's the problem:

nq = 2**int(sys.argv[1])
IndexError: list index out of range

Thanks for your time

Link | Reply
Current rating: 5

christian 1 year, 1 month ago

Hi Youcef,
The program expects the user to provide the order of the multipole on the command line (e.g. 1 for dipole, 2 for quadrupole etc.), so you should run the code with e.g.

python 3

to plot a figure for an octopole.

Link | Reply
Current rating: 5

Youcef 1 year, 1 month ago

Hello again Christian,

I did what you told me and it worked, so thanks a lot for the help and the quick response !

good day

Link | Reply
Currently unrated

Joaquín 1 month, 4 weeks ago

Hello Christian,

I am a beginner in python, what do you exactly would write in the code for a dipole ?

I know you already answered the question but i need you to be more specific please.

Link | Reply
Currently unrated

christian 1 month, 4 weeks ago

Dear Joaquín,
You need to save the code somewhere and open a command prompt (Terminal, whatever). If you navigate to the directory in which you've saved the code (on a Mac or *nix system, use the cd command; on windows I think it's chdir), you can just type:
python 1
to run the code for a dipole (2 for a quadrupole, 3 for a hexapole, etc), assuming you saved the code as and your python installation has the correct libraries installed. You might find it useful to install Anaconda ( to manage your python installation.
I hope that helps,

Link | Reply
Currently unrated

Lina 11 months, 4 weeks ago

Is it possible to get the coordinates of the different streamlines ?
Also how can I interpolate between the streamlines ?

Link | Reply
Currently unrated

christian 11 months, 4 weeks ago

Hi Lina,
The call to streamplot returns a container object, stream_container, from which you can obtain the lines making up the plot as stream_container.lines, and get their coordinates from there.

If you want the lines to be closer together, you can set the density argument to streamplot when you call it, as described in the documentation: []

Link | Reply
Currently unrated

Mark 11 months, 2 weeks ago

Perfect for creating custom field plots to add into my teaching notes.

Link | Reply
Currently unrated

christian 11 months, 2 weeks ago

I'm glad you find it useful – thanks for dropping by.

Link | Reply
Currently unrated

Keith 11 months, 1 week ago

In a couple of places hypot(x,y) should be used instead of sqrt(x**2+y**2).

Link | Reply
Currently unrated

christian 11 months, 1 week ago

That's a good idea – I've made the changes.
Thanks, Christian

Link | Reply
Currently unrated

Xinyuan Wei 9 months, 2 weeks ago

I wonder In line 8: den = np.hypot(x-r0[0], y-r0[1])**1.5
if the exponent 1.5 should be replaced by 3?

Link | Reply
Current rating: 4

christian 9 months, 2 weeks ago

Thanks for that catch, Xinyaun – you're absolutely right. I changed the previous code to use np.hypot without thinking it through. I've fixed it now.

Link | Reply
Currently unrated

New Comment


required (not published)