Reputation: 641
I'm trying to understand how the quiver function in the Matplotlib module works. Supposedly it allows to visualize graphically the values of two arrays, for example horizontal and vertical velocities. I have the following very simple example, but I show it just to see if you can help me to find out what I'm not doing well:
x = np.linspace(0,1,11)
y = np.linspace(1,0,11)
u = v = np.zeros((11,11))
u[5,5] = 0.2
plt.quiver(x, y, u, v)
The code produces the following figure:
As you can see, the arrow is not an arrow, but a line and it is longer than 0.2. My intention is to get an arrow of length 0.2 and I thought I could do it using quiver
. Is it possible? Or should I better use another command?
Upvotes: 22
Views: 48078
Reputation: 131550
The quiver function visualizes a vector field, like this:
(from the examples page). In this type of plot, the vector at a point represents the magnitude of the field vector at that point. For example, if you're visualizing velocity of a fluid, the length of the arrow represents the speed of the fluid.
You can think of a vector field as a function mapping input (position) to output (the vector, e.g. velocity). The output values have no relation to the input positions; in particular, they may not even be measured in the same units! So a quiver plot can only show the relative magnitude of the field at different points - only the relative lengths of the arrows are meaningful, not their absolute lengths.
In other words, you shouldn't expect a field value of 0.2 to be represented by an arrow of length 0.2 in data units.
However, matplotlib provides an option you can specify to do that: the scale_units
option to quiver
. According to the documentation, you can give scale_units = 'xy'
and it will render the arrow lengths using the same units as the axes.
Upvotes: 2
Reputation: 421
Not related to your problem, but interesting to mention: Funny thing is that by writing u[5, 5] = 0.2
you are implyingv[5, 5] = 0.2
as well (as shown in your diagonal arrow), since before you wrote u = v = np.zeros((11, 11))
. You could avoid that by writing
u = np.zeros((11, 11))
v = np.zeros((11, 11))
to make u
and v
independent from each other.
Upvotes: 6
Reputation: 85442
matplotlib quiver does auto scaling. Set the scale to 1
to get your 0.2 units in x an y:
x = np.linspace(0,1,11)
y = np.linspace(1,0,11)
u = v = np.zeros((11,11))
u[5,5] = 0.2
plt.quiver(x, y, u, v, scale=1)
If you don't set scale
, matplotlib uses an auto scaling algorithm based on the average vector length and the number of vectors. Since you only have one vector with a length greater zero, it becomes really big. Adding more vectors makes the arrows successively smaller.
To have equal x and y extensions of your arrow a few more adjustments are needed:
x = np.linspace(0,1,11)
y = np.linspace(1,0,11)
u = v = np.zeros((11,11))
u[5,5] = 0.2
plt.axis('equal')
plt.quiver(x, y, u, v, scale=1, units='xy')
Both axes need to be equal and the units need to be set to xy
.
Upvotes: 25