Skip to content

[Bug]: ax.quiver does not accept "normalize" argument when quiver plot is 2D #24814

@RelativisticMechanic

Description

@RelativisticMechanic

Bug summary

The 3-dimensional quiver accepts the argument 'normalize' and 'length'.

%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = plt.axes(projection='3d')

X, Y = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10))
Z = X**2 + Y**2

# Gradient Vector Components U and V
U, V = (2*X, 2*Y)

ax.plot_surface(X, Y, Z, cmap='YlGnBu')
ax.quiver(X, Y, 0, U, V, 0, length=1, normalize=True)

This gives the desired output:
image

However, when using a 2D quiver plot, I get an error. It seems inconsistent to me.

Code for reproduction

%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = plt.axes()

X, Y = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10))
Z = X**2 + Y**2

U, V = (2*X, 2*Y)

ax.contourf(X, Y, Z, cmap='plasma')
ax.quiver(X, Y, U, V, normalize=True, length=1)

Actual outcome

AttributeError                            Traceback (most recent call last)
Cell In[70], line 14
     12 U, V = (2*X, 2*Y)
     13 ax.contourf(X, Y, Z, cmap='plasma')
---> 14 ax.quiver(X, Y, U, V, normalize=True, length=1)

File C:\Python\310\lib\site-packages\matplotlib\__init__.py:1423, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
   1420 @functools.wraps(func)
   1421 def inner(ax, *args, data=None, **kwargs):
   1422     if data is None:
-> 1423         return func(ax, *map(sanitize_sequence, args), **kwargs)
   1425     bound = new_sig.bind(ax, *args, **kwargs)
   1426     auto_label = (bound.arguments.get(label_namer)
   1427                   or bound.kwargs.get(label_namer))

File C:\Python\310\lib\site-packages\matplotlib\axes\_axes.py:5103, in Axes.quiver(self, *args, **kwargs)
   5101 # Make sure units are handled for x and y values
   5102 args = self._quiver_units(args, kwargs)
-> 5103 q = mquiver.Quiver(self, *args, **kwargs)
   5104 self.add_collection(q, autolim=True)
   5105 self._request_autoscale_view()

File C:\Python\310\lib\site-packages\matplotlib\quiver.py:514, in Quiver.__init__(self, ax, scale, headwidth, headlength, headaxislength, minshaft, minlength, units, scale_units, angles, width, color, pivot, *args, **kwargs)
    512 kwargs.setdefault('facecolors', color)
    513 kwargs.setdefault('linewidths', (0,))
--> 514 super().__init__([], offsets=self.XY, offset_transform=self.transform,
    515                  closed=False, **kwargs)
    516 self.polykw = kwargs
    517 self.set_UVC(U, V, C)

File C:\Python\310\lib\site-packages\matplotlib\_api\deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
    448 if len(args) > name_idx:
    449     warn_deprecated(
    450         since, message="Passing the %(name)s %(obj_type)s "
    451         "positionally is deprecated since Matplotlib %(since)s; the "
    452         "parameter will become keyword-only %(removal)s.",
    453         name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)

File C:\Python\310\lib\site-packages\matplotlib\collections.py:1174, in PolyCollection.__init__(self, verts, sizes, closed, **kwargs)
   1153 @_api.make_keyword_only("3.6", name="closed")
   1154 def __init__(self, verts, sizes=None, closed=True, **kwargs):
   1155     """
   1156     Parameters
   1157     ----------
   (...)
   1172         Forwarded to `.Collection`.
   1173     """
-> 1174     super().__init__(**kwargs)
   1175     self.set_sizes(sizes)
   1176     self.set_verts(verts, closed)

File C:\Python\310\lib\site-packages\matplotlib\_api\deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
    448 if len(args) > name_idx:
    449     warn_deprecated(
    450         since, message="Passing the %(name)s %(obj_type)s "
    451         "positionally is deprecated since Matplotlib %(since)s; the "
    452         "parameter will become keyword-only %(removal)s.",
    453         name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)

File C:\Python\310\lib\site-packages\matplotlib\collections.py:202, in Collection.__init__(self, edgecolors, facecolors, linewidths, linestyles, capstyle, joinstyle, antialiaseds, offsets, offset_transform, norm, cmap, pickradius, hatch, urls, zorder, **kwargs)
    199 self._offset_transform = offset_transform
    201 self._path_effects = None
--> 202 self._internal_update(kwargs)
    203 self._paths = None

File C:\Python\310\lib\site-packages\matplotlib\artist.py:1186, in Artist._internal_update(self, kwargs)
   1179 def _internal_update(self, kwargs):
   1180     """
   1181     Update artist properties without prenormalizing them, but generating
   1182     errors as if calling `set`.
   1183 
   1184     The lack of prenormalization is to maintain backcompatibility.
   1185     """
-> 1186     return self._update_props(
   1187         kwargs, "{cls.__name__}.set() got an unexpected keyword argument "
   1188         "{prop_name!r}")

File C:\Python\310\lib\site-packages\matplotlib\artist.py:1160, in Artist._update_props(self, props, errfmt)
   1158             func = getattr(self, f"set_{k}", None)
   1159             if not callable(func):
-> 1160                 raise AttributeError(
   1161                     errfmt.format(cls=type(self), prop_name=k))
   1162             ret.append(func(v))
   1163 if ret:

AttributeError: Quiver.set() got an unexpected keyword argument 'normalize'

Expected outcome

Without the arguments, I get the plot as expected, however I want the vectors to be normalized to a certain length.

image

Additional information

No response

Operating system

Windows

Matplotlib Version

3.6.2

Matplotlib Backend

nbagg

Python version

3.10.8

Jupyter version

6.5.2

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy