Skip to content

Matplotlib.pyplot.quiver does not accept X, Y, U, V and C as keyword arguments #11526

Closed

Description

@niwatorrri

Bug report

Bug summary

Bug: matplotlib.pyplot.quiver cannot accept X, Y, U, V and C as keyword arguments, such operation leads to an IndexError: pop from empty list (if all of them are keyword arguments) or an AttributeError: Unknown property * (if part of them are keyword arguments). This error arises because line 444 in quiver.py, inside the constructor of Quiver class, only uses *args but excludes **kw for parsing of arguments X, Y, U, V and C, and thus nothing can be parsed from *args in the function _parse_args on line 385 if these arguments are given by keywords.

Code for reproduction

import matplotlib.pyplot as plt

x, y, u, v = 0, 0, .01, .02

plt.quiver(X=x, Y=y, U=u, V=v, units='xy', scale=1)
plt.show()

Actual outcome

Traceback (most recent call last):
  File "untitled.py", line 5, in <module>
    plt.quiver(X=x, Y=y, U=u, V=v, units='xy', scale=1)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/pyplot.py", line 3425, in quiver
    ret = ax.quiver(*args, **kw)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/__init__.py", line 1855, in inner
    return func(ax, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/axes/_axes.py", line 4872, in quiver
    q = mquiver.Quiver(self, *args, **kw)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/quiver.py", line 444, in __init__
    X, Y, U, V, C = _parse_args(*args)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/quiver.py", line 393, in _parse_args
    V = np.atleast_1d(args.pop(-1))
IndexError: pop from empty list

And the error disappears if we write the code as plt.quiver(x, y, u, v, units='xy', scale=1).

Matplotlib version

  • Operating system: Mac OS High Sierra
  • Matplotlib version: 2.2.2 (installed from pip3)
  • Matplotlib backend: MacOSX
  • Python version: 3.6.5

Activity

  1. added this to the v3.1 milestone on Jun 28, 2018
  2. added
    API: consistencyConsistency of the matplotlib API, including naming, behavior, defaults, …
    🌱 Good first issueOpen a pull request against these issues if there are no active ones!
    on Jun 28, 2018
  3. tacaswell commented on Jun 28, 2018

    @tacaswell
    Member

    That does seem like a mistake, want to take a crack at fixing it @niwatori1217 ?

  4. anntzer commented on Aug 27, 2018

    @anntzer
    Contributor

    Looking at this again I am tempted to say that we should just declare that these arguments are positional-only. The problem is that adding keyword support is only going to make a confusing API even more worse: for example, do we expect that in

    quiver(arg1, arg2, U=u, V=v)
    

    arg1 and arg2 are considered as X and Y, but in

    quiver(arg1, arg2, X=x, Y=y)
    

    arg1 and arg2 are considered as U and V?
    (Of course you can imaging even more funky cases involving passing e.g. X positionally and Y as keyword, but they are a bit artificial, whereas I don't think the above is.)

    I think there's some similarly, the builtin range takes no keyword arguments. Again, it would be pretty terrible if range(3, stop=5) meant range(3, 5) but range(3, step=5) meant range(0, 3, 5)...

  5. removed
    🌱 Good first issueOpen a pull request against these issues if there are no active ones!
    on Aug 27, 2018
  6. tacaswell commented on Aug 29, 2018

    @tacaswell
    Member

    I agree that the mix is very confusing, but would allowing all kwarg or all arg make sense?

  7. anntzer commented on Aug 29, 2018

    @anntzer
    Contributor

    Honestly I don't really see the point... Documenting xyuvc as positional only seems simpler than "positional only, or all keyword".

  8. timhoffm commented on Aug 29, 2018

    @timhoffm
    Member

    Up to five positional arguments are not that nice, in particular since the meaning of the arguments depends on the number of arguments used.

    quiver(U, V, **kw)
    quiver(U, V, C, **kw)
    quiver(X, Y, U, V, **kw)
    quiver(X, Y, U, V, C, **kw)
    

    However, adding more options does not simplify the present signature of quiver(*args, data=None, **kw). We cannot add explicit kwargs for XYUVC if we want to maintain compatibility with the above positional variants. The signature itself must be unchanged. The only thing would be to allow different calls.

    I would in principle be fine with all-kwarg signatures:

    quiver(U=u, V=v, **kw)
    quiver(U=u, V=v, C=c, **kw)
    quiver(X=x, Y=y, U=u, V=v, **kw)
    quiver(X=x, Y=y, U=u, V=v, C=v, **kw)
    

    That could in principle catch errors of using the wrong arguments or positions. Say, you want to use X, Y, U, V and you miss V, you would accidentially end up with U, V, C semantics. On the downside, I don't think that the all-kwarg variants add to readability. And internally this would add to the complexity of argument parsing.

    Note also, that other similar functions like contour, pcolor and tripcolor variants are currently all positional only. To be consistent, we should change them all if we change one.

    Overall, I'm -0.5 on supporting all-kwarg as well here.

  9. tacaswell commented on Aug 29, 2018

    @tacaswell
    Member

    fair enough.

  10. tacaswell commented on Aug 29, 2018

    @tacaswell
    Member

    @niwatori1217 Thanks for the suggestion, however we are probably not going to implement this 😞 . Hopefully we will hear from you again!

  11. removed this from the v3.1 milestone on Aug 29, 2018
  12. added a commit that references this issue on Apr 10, 2024
    9fe39a7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    API: consistencyConsistency of the matplotlib API, including naming, behavior, defaults, …

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions