Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
niwatorrri opened this issue Jun 28, 2018 · 7 comments · Fixed by #28054
Closed

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

niwatorrri opened this issue Jun 28, 2018 · 7 comments · Fixed by #28054

Comments

@niwatorrri
Copy link

niwatorrri commented Jun 28, 2018

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
@tacaswell tacaswell added this to the v3.1 milestone Jun 28, 2018
@tacaswell tacaswell added API: consistency Good first issue Open a pull request against these issues if there are no active ones! labels Jun 28, 2018
@tacaswell
Copy link
Member

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

@anntzer
Copy link
Contributor

anntzer commented Aug 27, 2018

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)...

@anntzer anntzer removed the Good first issue Open a pull request against these issues if there are no active ones! label Aug 27, 2018
@tacaswell
Copy link
Member

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

@anntzer
Copy link
Contributor

anntzer commented Aug 29, 2018

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

@timhoffm
Copy link
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.

@tacaswell
Copy link
Member

fair enough.

@tacaswell
Copy link
Member

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

@QuLogic QuLogic removed this from the v3.1 milestone Aug 29, 2018
timhoffm added a commit to timhoffm/matplotlib that referenced this issue Apr 10, 2024
…ositional-only

Closes matplotlib#28047 and the already closed matplotlib#11526.

This introduces the positional-only marker `/` into the call
signatures (`pcolorfast` already had it). While IIRC I originally
opted against adding it for simplicity, the above issues show that
this is not clear enough. It's helpful for experienced people and
I believe it does not distract people who don't know what it is too
much because it's here always at the end before **kwargs.

Additionally, it does not hurt to spell it out in text as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants