fancy arrow

It would be great though if the docstring was more help:

This is a typical problem we encounter in documenting pylab functions.
As you know, pylab is basically a pass-though interface to the
underlying matplotlib objects. In this case pylab.arrow calls
matplotlib.axes.Axes.arrow which creates a
matplotlib.patches.FancyArrow instance. If we're not careful (and in
this case we were not) it is easy to leave an un- or under-documented
pylab function docstring. I copied the relevant documentation from
the FancyArrow class into the Axes.arrow docstring, which pylab.arrow
reuses. It now reads:

        ARROW(x, y, dx, dy, **kwargs)
        Draws arrow on specified axis from (x,y) to (x+dx,y+dy).

        keyword arguments **kwargs:

          * length_includes_head: True if head is counted in
            calculating the length.
        
          * shape: ['full', 'left', 'right']
        
          * overhang: distance that the arrow is swept back (0
            overhang means triangular shape).

          * head_starts_at_zero: if True, the head starts being drawn
            at coordinate 0 instead of ending at coordinate 0.

Sometimes with matplotlib it's not RTFM, but RTFSC (read the *&$%&U
source code). I don't mean this glibly, since we want the user
experience to "just work"(TM) but I do mention it because it is one of
the benefits of using open-source software. If you are using a pylab
function like pylab.arrow and do not understand how to use it, you
have the option of grokking the source code for pylab.arrow. Here it
is:

# This function was autogenerated by boilerplate.py. Do not edit as
# changes will be lost
def arrow(*args, **kwargs):
    # allow callers to override the hold state by passing hold=True|False
    b = ishold()
    h = popd(kwargs, 'hold', None)
    if h is not None:
        hold(h)
    try:
        ret = gca().arrow(*args, **kwargs)
        draw_if_interactive()
    except:
        hold(b)
        raise

    hold(b)
    return ret
if Axes.arrow.__doc__ is not None:
    arrow.__doc__ = _shift_string(Axes.arrow.__doc__) + """
Addition kwargs: hold = [True|False] overrides default hold state"""

As the comment above indicates, most of this is boilerplate and is in
fact auto-generated. The crucial part is

    try:
        ret = gca().arrow(*args, **kwargs)
        draw_if_interactive()

[note we are using pass-through arguments and keyword arguments which
is why our docstrings sometimes suck]. If you know just enough
matplotlib internals, you'll know that gca ("get current axes")
returns the current matplotlib.axes.Axes object, and thus the relevant
method is Axes.arrow. Opening up axes.py, and searching for 'def
arrow' you'll find

    def arrow(self, x, y, dx, dy, **kwargs):
        'docstring snipped'
        a = FancyArrow(x, y, dx, dy, **kwargs)
        self.add_artist(a)
        return a

So all Axes.arrow does is create a FancyArrow, add it to the Axes, and
returns it. If you go to the top of the file axes.py, you'll find an
import line indicating where FancyArrow comes from

  from patches import Patch, Rectangle, ..., FancyArrow, ...

so FancyArrow is coming from matplotlib.patches. We're almost there.
Open up patches.py, search for 'class FancyArrow', and you arrive at
the real player:

class FancyArrow(Polygon):
    """Like Arrow, but lets you set head width and head height
    independently."""
    def __init__(self, x, y, dx, dy, width=0.001,
                 length_includes_head=False,
                 head_width=None, head_length=None, shape='full',
                 overhang=0,
                 head_starts_at_zero=False,**kwargs):
        """Returns a new Arrow.

        length_includes_head: True if head is counted in calculating
        the length.
        
        shape: ['full', 'left', 'right']
        
        overhang: distance that the arrow is swept back (0 overhang means
        triangular shape).

        head_starts_at_zero: if True, the head starts being drawn at
        coordinate 0 instead of ending at coordinate 0. """ if
        head_width is None: head_width = 3 * width

That's what I did to answer your question (not knowing anything much
about how Rob Knight worked his fancy arrow magic). I don't mention
this to discourage you from asking these kinds of questions: quite the
opposite since your question helps us fix the doc strings and user
interface. But I wanted to describe the approach that matplotlib
developers, none of whom have an intimate understanding of all of the
parts of this code, take when trying to understand how things (should)
work.

JDH