Matlab's compass is a very handy function to plot arrows emanating from an origin. As far as I know matplotlib does not have an equivalent function. However, matplotlib is so versatile that we can build a compass like function very quickly.
We will need a function to convert from Cartesian coordinates to Polar coordinates.
In [2]:
import numpy as np
def cart2pol(x, y):
"""Convert from Cartesian to polar coordinates.
Example
-------
>>> theta, radius = pol2cart(x, y)
"""
radius = np.hypot(x, y)
theta = np.arctan2(y, x)
return theta, radius
Now we need a way to plot the arrows from the origin in the Polar coordinates. My first guess was to use arrow, but then I found this and realized it is not a good idea to use arrows. Then I thought about quiver... But before I even tried quiver I found this and I realized that arrow annotations was the way to go for simple, good looking graphs.
From the docs:
An arrow connecting two point (xy & xytext) can be optionally
drawn by specifying the arrowprops argument. To draw only an
arrow, use empty string as the first argument.
In [3]:
import matplotlib.pyplot as plt
def compass(u, v, arrowprops=None):
"""
Compass draws a graph that displays the vectors with
components `u` and `v` as arrows from the origin.
Examples
--------
>>> import numpy as np
>>> u = [+0, +0.5, -0.50, -0.90]
>>> v = [+1, +0.5, -0.45, +0.85]
>>> compass(u, v)
"""
angles, radii = cart2pol(u, v)
fig, ax = plt.subplots(subplot_kw=dict(polar=True))
kw = dict(arrowstyle="->", color='k')
if arrowprops:
kw.update(arrowprops)
[ax.annotate("", xy=(angle, radius), xytext=(0, 0),
arrowprops=kw) for
angle, radius in zip(angles, radii)]
ax.set_ylim(0, np.max(radii))
return fig, ax
Now let's plot it,
In [4]:
u = [+0, -0.5, -0.50, +0.90]
v = [+1, +0.5, -0.45, -0.85]
fig, ax = compass(u, v)
and customize the arrows:
In [5]:
arrowprops = dict(color='darkorange', linewidth=2)
fig, ax = compass(u, v, arrowprops=arrowprops)
In [6]:
HTML(html)
Out[6]: