Description
quiver's docs currently read
Call signatures::
quiver(U, V, **kw)
quiver(U, V, C, **kw)
quiver(X, Y, U, V, **kw)
quiver(X, Y, U, V, C, **kw)
*U* and *V* are the arrow data, *X* and *Y* set the location of the
arrows, and *C* sets the color of the arrows. These arguments may be 1-D or
2-D arrays or sequences.
...
Parameters
----------
X : 1D or 2D array, sequence, optional
The x coordinates of the arrow locations
Y : 1D or 2D array, sequence, optional
The y coordinates of the arrow locations
U : 1D or 2D array or masked array, sequence
The x components of the arrow vectors
V : 1D or 2D array or masked array, sequence
The y components of the arrow vectors
C : 1D or 2D array, sequence, optional
The arrow colors
OK, let's try to draw 4 arrows, each with u=v=1, in red (1, 0, 0), green (0, 1, 0), blue (0, 0, 1), and gray (.5, .5, .5)
quiver([1, 1, 1, 1], [1, 1, 1, 1], ["r", "g", "b", "gray"])
...
TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Oops. Let's try to pass in RGB color tuples instead? (in the same format as scatter
would take them)
quiver([1, 1, 1, 1], [1, 1, 1, 1], [[1, 0, 0], [0, 1, 0], [0, 0, 1], [.5, .5, .5]])
??
To cut a long story short: this took the first 4 values in the flattened color array (1, 0, 0, 0) and colormapped them using the default colormap.
Actually, the correct solution to set the colors is to read all the way to the end of the docstring and notice
color : [ color | color sequence ], optional
This is a synonym for the
:class:`~matplotlib.collections.PolyCollection` facecolor kwarg.
If *C* has been set, *color* has no effect.
Indeed
quiver([1, 1, 1, 1], [1, 1, 1, 1], color=["r", "g", "b", "gray"])
or
quiver([1, 1, 1, 1], [1, 1, 1, 1], color=[[1, 0, 0], [0, 1, 0], [0, 0, 1], [.5, .5, .5]])
I think this API is clearly... not optimal.
I propose to instead make C check its shape; if its shape is (*X.shape, 3)
or (*X.shape, 4)
, then treat it as RGB; if its shape is X.shape
, treat it as colormapped values; otherwise, error out (and for consistency, check that the shapes of X, Y, U, V all match (instead of flattening them all)).
I'm not sure the behavior change needs a deprecation period (it would only affect people purposefully passing three or four times to many values as the C array as the rest would currently be ignored); obviously there would be a deprecation during which non-matching X, Y, U, V would warn instead of error out.
The color arg could also be deprecated, as it is now a complete synonym for C. Alternatively, we could instead deprecate C in favor of color, which would have the benefit of making the signatures a bit nicer (now it's just quiver(U, V, **kwargs)
and quiver(X, Y, U, V, **kwargs)
) but is perhaps mildly more disruptive.
Thoughts?
This is as of mpl 3.0.x.