Stream plots are used to visualize flow in vector fields. Examples from science and nature include fields of magnetic and gravitational forces or movement of liquid materials.
Vector field can be visualized in such a way, where we assign a line and one or more arrows to every point. The intensity can be represented by the line length, and direction by arrow pointing in particular direction.
Usually, the intensity of the force is visualized with the length of a particular streamline, but density can also be used for the same purpose.
To visualize vector fields, we will use matplotlib
's matplotlib.pyplot.streamplot
function. This function creates plots from streamlines of a flow uniformly filling the domain. The velocities field is interpolated and streamlines are integrated. The original source for this function is to visualize wind patterns or liquid flow, hence we don't need strict vector lines but uniform representation of the vector field.
Most important arguments for this function are x
, y
evenly spaced grid of one-dimensional NumPy array, and u
, v
matching two-dimensional NumPy arrays of x
, y
velocities. Matrices u
and v
must be of such dimensions that the number of rows must be of equal length of y
, and the number of columns must match the length of x
.
Line width of stream plot can be controlled per line, if the linewidth
argument is given a two-dimensional array matching the shape of u
and v
velocities, or it, simply can be just one integer value that all lines will accept.
Color, can not only be just one value for all stream line, but also a matrix shaped like the linewidth
argument.
Arrows (the FancyArrowPatch
class) are used to indicate vector direction, and we can control them using two params: arrowsize
—size of the arrow, and arrowstyle
—format of the arrow (for example, "simple"
, "->"
).
We will start with a simple example, just to get the sense of what's going on here. Perform the following steps:
import matplotlib.pyplot as plt import numpy as np Y, X = np.mgrid[0:5:100j, 0:5:100j] U = X V = Y from pprint import pprint print "X" pprint(X) print "Y" pprint(Y) plt.streamplot(X, Y, U, V) plt.show()
This will give the following textual output:
X array([[ 0. , 0.05050505, 0.1010101 , ..., 4.8989899 , 4.94949495, 5. ], [ 0. , 0.05050505, 0.1010101 , ..., 4.8989899 , 4.94949495, 5. ], [ 0. , 0.05050505, 0.1010101 , ..., 4.8989899 , 4.94949495, 5. ], ..., [ 0. , 0.05050505, 0.1010101 , ..., 4.8989899 , 4.94949495, 5. ], [ 0. , 0.05050505, 0.1010101 , ..., 4.8989899 , 4.94949495, 5. ], [ 0. , 0.05050505, 0.1010101 , ..., 4.8989899 , 4.94949495, 5. ]]) Y array([[ 0. , 0. , 0. , ..., 0. , 0. , 0. ], [ 0.05050505, 0.05050505, 0.05050505, ..., 0.05050505, 0.05050505, 0.05050505], [ 0.1010101 , 0.1010101 , 0.1010101 , ..., 0.1010101 , 0.1010101 , 0.1010101 ], ..., [ 4.8989899 , 4.8989899 , 4.8989899 , ..., 4.8989899 , 4.8989899 , 4.8989899 ], [ 4.94949495, 4.94949495, 4.94949495, ..., 4.94949495, 4.94949495, 4.94949495], [ 5. , 5. , 5. , ..., 5. , 5. , 5. ]])
We create a vector field of X
and Y
by indexing the two-dimensional mesh grid, using NumPy's mgrid
instance. We specify the range of the grid, as start and stop (-2 and 2, respectively). The third index represents a step length. The step length is the number of points to include between start and stop. If you want to include the stop value, use complex numbers for step length, where magnitude is used for the number of points required between start and stop, stop being inclusive.
Mesh grid, fleshed out like this, is then used to compute vector velocities. Here, for the sake of example, we just use the same meshgrid
as vector velocities.
This generates a plot that clearly shows plain linear dependency and flow of represented vector field.
Play with the values of U
and V
to get a sense of how values of U
and V
influence stream plot. For example, make U = np.sin(X)
or V = np.sin(Y)
. Following that, try to change the start and stop values. The following figure shows U = np.sin(X)
:
Bare in mind that the plot we plotted is generated by a set of lines and arrow patches; hence, there is no way (currently, at least) to update the existing figure. Lines and arrows know nothing about vectors and fields. Future implementations might bring about this change, but at the moment, this is a known limitation in the current version of matplotlib.
Of course this example gives you an opportunity to get to know and understand matplotlib's stream plot features and capabilities.
Real power comes when you have the real data at hand to play with. After understanding this recipe, you will be able to recognize the tools you have. So when you are given the data and you know the domain of it, you will be able to pick the best tool for the job.