Skip to content

Removed normalization of arrows in 3D quiver #5458

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

Merged
merged 10 commits into from
Nov 16, 2015
16 changes: 16 additions & 0 deletions doc/api/api_changes/2015-11-12-DDH.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
New defaults for 3D quiver function in mpl_toolkits.mplot3d.axes3d.py
```````````````````````````
Matplotlib has both a 2D and a 3D ``quiver`` function. These changes affect only the 3D function and make the default behavior of the 3D function match 2D version. There are two changes:

1) The 3D quiver function previously normalized the arrows to be the same length, which makes it unusable for situations where the arrows should be different lengths and does not match the behavior of the 2D function. This normalization behavior is now controlled with the ``normalize`` keyword, which defaults to False.

2) The ``pivot`` keyword now defaults to ``tail`` instead of ``tip``. This was done in order to match the default behavior of the 2D quiver function.

To obtain the previous behavior with the 3D quiver function, one can call the function with ::

ax.quiver(x, y, z, u, v, w, normalize=True, pivot='tip')

where "ax" is a axes3d object created with something like ::

import mpl_toolkits.mplot3d.axes3d
ax = plt.sublot(111, projection='3d')
2 changes: 1 addition & 1 deletion examples/mplot3d/quiver3d_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))

ax.quiver(x, y, z, u, v, w, length=0.1)
ax.quiver(x, y, z, u, v, w, length=0.1, normalize=True)

plt.show()
20 changes: 16 additions & 4 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -2477,7 +2477,7 @@ def quiver(self, *args, **kwargs):

*X*, *Y*, *Z*:
The x, y and z coordinates of the arrow locations (default is
tip of arrow; see *pivot* kwarg)
tail of arrow; see *pivot* kwarg)

*U*, *V*, *W*:
The x, y and z components of the arrow vectors
Expand All @@ -2499,7 +2499,13 @@ def quiver(self, *args, **kwargs):

*pivot*: [ 'tail' | 'middle' | 'tip' ]
The part of the arrow that is at the grid point; the arrow
rotates about this point, hence the name *pivot*.
rotates about this point, hence the name *pivot*.
Default is 'tail'

*normalize*: [False | True]
When True, all of the arrows will be the same length. This
defaults to False, where the arrows will be different lengths
depending on the values of u,v,w.

Any additional keyword arguments are delegated to
:class:`~matplotlib.collections.LineCollection`
Expand All @@ -2508,6 +2514,7 @@ def quiver(self, *args, **kwargs):
def calc_arrow(uvw, angle=15):
"""
To calculate the arrow head. uvw should be a unit vector.
We normalize it here:
"""
# get unit direction vector perpendicular to (u,v,w)
norm = np.linalg.norm(uvw[:2])
Expand Down Expand Up @@ -2540,7 +2547,9 @@ def calc_arrow(uvw, angle=15):
# arrow length ratio to the shaft length
arrow_length_ratio = kwargs.pop('arrow_length_ratio', 0.3)
# pivot point
pivot = kwargs.pop('pivot', 'tip')
pivot = kwargs.pop('pivot', 'tail')
# normalize
normalize = kwargs.pop('normalize', False)

# handle args
argi = 6
Expand Down Expand Up @@ -2601,7 +2610,10 @@ def calc_arrow(uvw, angle=15):
# If any row of UVW is all zeros, don't make a quiver for it
mask = norm > 1e-10
XYZ = XYZ[mask]
UVW = UVW[mask] / norm[mask].reshape((-1, 1))
if normalize:
UVW = UVW[mask] / norm[mask].reshape((-1, 1))
else:
UVW = UVW[mask]

if len(XYZ) > 0:
# compute the shaft lines all at once with an outer product
Expand Down
10 changes: 5 additions & 5 deletions lib/mpl_toolkits/tests/test_mplot3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def test_quiver3d():
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))

ax.quiver(x, y, z, u, v, w, length=0.1)
ax.quiver(x, y, z, u, v, w, length=0.1, pivot='tip', normalize=True)

@image_comparison(baseline_images=['quiver3d_empty'], remove_text=True)
def test_quiver3d_empty():
Expand All @@ -229,7 +229,7 @@ def test_quiver3d_empty():
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))

ax.quiver(x, y, z, u, v, w, length=0.1)
ax.quiver(x, y, z, u, v, w, length=0.1, pivot='tip', normalize=True)

@image_comparison(baseline_images=['quiver3d_masked'], remove_text=True)
def test_quiver3d_masked():
Expand All @@ -247,7 +247,7 @@ def test_quiver3d_masked():
u = np.ma.masked_where((-0.4 < x) & (x < 0.1), u, copy=False)
v = np.ma.masked_where((0.1 < y) & (y < 0.7), v, copy=False)

ax.quiver(x, y, z, u, v, w, length=0.1)
ax.quiver(x, y, z, u, v, w, length=0.1, pivot='tip', normalize=True)

@image_comparison(baseline_images=['quiver3d_pivot_middle'], remove_text=True,
extensions=['png'])
Expand All @@ -262,7 +262,7 @@ def test_quiver3d_pivot_middle():
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))

ax.quiver(x, y, z, u, v, w, length=0.1, pivot='middle')
ax.quiver(x, y, z, u, v, w, length=0.1, pivot='middle', normalize=True)

@image_comparison(baseline_images=['quiver3d_pivot_tail'], remove_text=True,
extensions=['png'])
Expand All @@ -277,7 +277,7 @@ def test_quiver3d_pivot_tail():
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))

ax.quiver(x, y, z, u, v, w, length=0.1, pivot='tail')
ax.quiver(x, y, z, u, v, w, length=0.1, pivot='tail', normalize=True)


@image_comparison(baseline_images=['axes3d_labelpad'], extensions=['png'])
Expand Down
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