trouble with Arrow

I just want to draw a few vectors of different colors.
In Mathematica I would use Arrow:
http://reference.wolfram.com/mathematica/ref/Arrow.html

In Matplotlib I cannot find an easy way. Here's the best
I came up with so far.

import matplotlib.pyplot as plt
from matplotlib.patches import Arrow
fig, ax = plt.subplots(1,1)
ax.set_aspect('equal')
ax.add_artist( Arrow(0,0,1,1, width=0.1, facecolor='red',edgecolor=None) )
ax.add_artist( Arrow(0,1,1,-1, width=0.01, facecolor='k',edgecolor=None) )

Things that seem wrong with the interface:
- takes 4 numbers instead of a list of points
- head length and width is not determined by the line width
- edge drawing cannot (?) be turned off

The head drawing issue is particularly serious.

So, have I overlooked an easy way to do what I want?

One other question: am I supposed to use `add_patch` or
`add_artist`, and why?

Thanks,
Alan Isaac

A follow-on question: the `arrow` method of an axes
has `length_includes_head` default to False. Why?
This seems very unfriendly behavior for an "arrow".
It also conflicts with the behavior of an `Arrow`.

Thanks,
Alan Isaac

One more follow-on question:
the documented behavior of head_width and head_length is:
http://matplotlib.org/api/axes_api.html

head_width: float or None (default: 3*width) total width of the full arrow head
head_length: float or None (default: 1.5 * head_width) length of arrow head

But I believe that does not match the behavior I am seeing. E.g., the following
produces two completely different arrow heads.

fig, ax = plt.subplots(1,1)
ax.set_aspect('equal')
w=0.01
ax.arrow(0,0,1,1, width=w,head_width=3*w,head_length=1.5*3*w, facecolor='red',edgecolor=None,length_includes_head=True)
ax.arrow(0,1,1,-1, width=w, facecolor='k',edgecolor='red',length_includes_head=True)

Am I missing something?

Also, despite setting `edgecolor=None`, the edge is still stroked.

Alan Isaac

···

On 2/2/2014 11:13 PM, Alan G Isaac wrote:

A follow-on question: the `arrow` method of an axes
has `length_includes_head` default to False. Why?
This seems very unfriendly behavior for an "arrow".
It also conflicts with the behavior of an `Arrow`.

Last question about this for now ...

Yet another issue with `arrow`: the
docs say a dashed linestyle is supported
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.arrow
but really it is not: the *edge* is dashed rather than the tail!

Maybe I'm missing the intended usage here. But
I'm starting to think Matplotlib could use a "SimpleArrow".
The tail would just be a line.
The head would just be a filled triangle.
The default would be length_includes_head=True.

Alan Isaac

I suspect you need edgecolor='none'. In general, specifying a color as the string 'none' means "don't draw it".

···

On 2014/02/02 6:52 PM, Alan G Isaac wrote:

Also, despite setting `edgecolor=None`, the edge is still stroked.

Alan,

I think you are raising good points. (The default of not including the head in the length is puzzling, to say the least.) Actually making a *good* simple arrow is not as simple as it might seem, but it can be done. The main difficulty is the need to use a mix of coordinates and transforms to handle varying axes sizes and aspect ratios. In any case, I think you have pointed to one of many areas where mpl's present design and user interface could be improved. It's all a matter of volunteer labor to make such improvements--with the added difficulty of needing to maintain backward compatibility over fairly long periods.

For your immediate needs, might quiver work better? It's interface is also rather complex because of the use cases it covers.

If you are using the arrows for annotation rather than as representations of vectors, then of course the annotate() function is appropriate.

Eric

···

On 2014/02/02 7:45 PM, Alan G Isaac wrote:

Last question about this for now ...

Yet another issue with `arrow`: the
docs say a dashed linestyle is supported
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.arrow
but really it is not: the *edge* is dashed rather than the tail!

Maybe I'm missing the intended usage here. But
I'm starting to think Matplotlib could use a "SimpleArrow".
The tail would just be a line.
The head would just be a filled triangle.
The default would be length_includes_head=True.

Alan Isaac

And again, it does not match the behavior of Arrow.
So perhaps the current behavior could be changed?
(E.g., after a period of requiring `length_includes_head`,
which I'll bet practically all users are already
setting, because of the puzzling default.)

Also, am I wrong that the default head_width and head_length
are buggy (i.e., not set in proportion to the `width`,
as the documentation requires)?

Thanks,
Alan

PS Thanks for 'none'; I'd forgotten. Also, quiver is somewhat
useful (good arrows), but lacks easy control over individual
arrow properties.

···

On 2/3/2014 1:36 AM, Eric Firing wrote:

The default of not including the
head in the length is puzzling, to say the least.