Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 88a84eb

Browse filesBrowse files
authored
Merge pull request #27697 from meeseeksmachine/auto-backport-of-pr-27044-on-v3.8.x
Backport PR #27044 on branch v3.8.x (Fix quiver key plot when angles='xy' and/or scale_units='xy')
2 parents 889e0a5 + b0e7df3 commit 88a84eb
Copy full SHA for 88a84eb

File tree

Expand file treeCollapse file tree

3 files changed

+73
-13
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+73
-13
lines changed

‎lib/matplotlib/quiver.py

Copy file name to clipboardExpand all lines: lib/matplotlib/quiver.py
+17-13Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def __init__(self, Q, X, Y, U, label,
263263
The key label (e.g., length and units of the key).
264264
angle : float, default: 0
265265
The angle of the key arrow, in degrees anti-clockwise from the
266-
x-axis.
266+
horizontal axis.
267267
coordinates : {'axes', 'figure', 'data', 'inches'}, default: 'axes'
268268
Coordinate system and units for *X*, *Y*: 'axes' and 'figure' are
269269
normalized coordinate systems with (0, 0) in the lower left and
@@ -327,10 +327,8 @@ def _init(self):
327327
Umask=ma.nomask):
328328
u = self.U * np.cos(np.radians(self.angle))
329329
v = self.U * np.sin(np.radians(self.angle))
330-
angle = (self.Q.angles if isinstance(self.Q.angles, str)
331-
else 'uv')
332-
self.verts = self.Q._make_verts(
333-
np.array([u]), np.array([v]), angle)
330+
self.verts = self.Q._make_verts([[0., 0.]],
331+
np.array([u]), np.array([v]), 'uv')
334332
kwargs = self.Q.polykw
335333
kwargs.update(self.kw)
336334
self.vector = mcollections.PolyCollection(
@@ -521,7 +519,7 @@ def _init(self):
521519
# _make_verts sets self.scale if not already specified
522520
if (self._dpi_at_last_init != self.axes.figure.dpi
523521
and self.scale is None):
524-
self._make_verts(self.U, self.V, self.angles)
522+
self._make_verts(self.XY, self.U, self.V, self.angles)
525523

526524
self._dpi_at_last_init = self.axes.figure.dpi
527525

@@ -537,7 +535,7 @@ def get_datalim(self, transData):
537535
@martist.allow_rasterization
538536
def draw(self, renderer):
539537
self._init()
540-
verts = self._make_verts(self.U, self.V, self.angles)
538+
verts = self._make_verts(self.XY, self.U, self.V, self.angles)
541539
self.set_verts(verts, closed=False)
542540
super().draw(renderer)
543541
self.stale = False
@@ -594,33 +592,38 @@ def _set_transform(self):
594592
self.set_transform(trans)
595593
return trans
596594

597-
def _angles_lengths(self, U, V, eps=1):
598-
xy = self.axes.transData.transform(self.XY)
595+
# Calculate angles and lengths for segment between (x, y), (x+u, y+v)
596+
def _angles_lengths(self, XY, U, V, eps=1):
597+
xy = self.axes.transData.transform(XY)
599598
uv = np.column_stack((U, V))
600-
xyp = self.axes.transData.transform(self.XY + eps * uv)
599+
xyp = self.axes.transData.transform(XY + eps * uv)
601600
dxy = xyp - xy
602601
angles = np.arctan2(dxy[:, 1], dxy[:, 0])
603602
lengths = np.hypot(*dxy.T) / eps
604603
return angles, lengths
605604

606-
def _make_verts(self, U, V, angles):
605+
# XY is stacked [X, Y].
606+
# See quiver() doc for meaning of X, Y, U, V, angles.
607+
def _make_verts(self, XY, U, V, angles):
607608
uv = (U + V * 1j)
608609
str_angles = angles if isinstance(angles, str) else ''
609610
if str_angles == 'xy' and self.scale_units == 'xy':
610611
# Here eps is 1 so that if we get U, V by diffing
611612
# the X, Y arrays, the vectors will connect the
612613
# points, regardless of the axis scaling (including log).
613-
angles, lengths = self._angles_lengths(U, V, eps=1)
614+
angles, lengths = self._angles_lengths(XY, U, V, eps=1)
614615
elif str_angles == 'xy' or self.scale_units == 'xy':
615616
# Calculate eps based on the extents of the plot
616617
# so that we don't end up with roundoff error from
617618
# adding a small number to a large.
618619
eps = np.abs(self.axes.dataLim.extents).max() * 0.001
619-
angles, lengths = self._angles_lengths(U, V, eps=eps)
620+
angles, lengths = self._angles_lengths(XY, U, V, eps=eps)
621+
620622
if str_angles and self.scale_units == 'xy':
621623
a = lengths
622624
else:
623625
a = np.abs(uv)
626+
624627
if self.scale is None:
625628
sn = max(10, math.sqrt(self.N))
626629
if self.Umask is not ma.nomask:
@@ -630,6 +633,7 @@ def _make_verts(self, U, V, angles):
630633
# crude auto-scaling
631634
# scale is typical arrow length as a multiple of the arrow width
632635
scale = 1.8 * amean * sn / self.span
636+
633637
if self.scale_units is None:
634638
if self.scale is None:
635639
self.scale = scale
Loading

‎lib/matplotlib/tests/test_quiver.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_quiver.py
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,62 @@ def test_quiverkey_angles():
267267
assert len(qk.verts) == 1
268268

269269

270+
def test_quiverkey_angles_xy_aitoff():
271+
# GH 26316 and GH 26748
272+
# Test that only one arrow will be plotted with non-cartesian
273+
# when angles='xy' and/or scale_units='xy'
274+
275+
# only for test purpose
276+
# scale_units='xy' may not be a valid use case for non-cartesian
277+
kwargs_list = [
278+
{'angles': 'xy'},
279+
{'angles': 'xy', 'scale_units': 'xy'},
280+
{'scale_units': 'xy'}
281+
]
282+
283+
for kwargs_dict in kwargs_list:
284+
285+
x = np.linspace(-np.pi, np.pi, 11)
286+
y = np.ones_like(x) * np.pi / 6
287+
vx = np.zeros_like(x)
288+
vy = np.ones_like(x)
289+
290+
fig = plt.figure()
291+
ax = fig.add_subplot(projection='aitoff')
292+
q = ax.quiver(x, y, vx, vy, **kwargs_dict)
293+
qk = ax.quiverkey(q, 0, 0, 1, '1 units')
294+
295+
fig.canvas.draw()
296+
assert len(qk.verts) == 1
297+
298+
299+
def test_quiverkey_angles_scale_units_cartesian():
300+
# GH 26316
301+
# Test that only one arrow will be plotted with normal cartesian
302+
# when angles='xy' and/or scale_units='xy'
303+
304+
kwargs_list = [
305+
{'angles': 'xy'},
306+
{'angles': 'xy', 'scale_units': 'xy'},
307+
{'scale_units': 'xy'}
308+
]
309+
310+
for kwargs_dict in kwargs_list:
311+
X = [0, -1, 0]
312+
Y = [0, -1, 0]
313+
U = [1, -1, 1]
314+
V = [1, -1, 0]
315+
316+
fig, ax = plt.subplots()
317+
q = ax.quiver(X, Y, U, V, **kwargs_dict)
318+
ax.quiverkey(q, X=0.3, Y=1.1, U=1,
319+
label='Quiver key, length = 1', labelpos='E')
320+
qk = ax.quiverkey(q, 0, 0, 1, '1 units')
321+
322+
fig.canvas.draw()
323+
assert len(qk.verts) == 1
324+
325+
270326
def test_quiver_setuvc_numbers():
271327
"""Check that it is possible to set all arrow UVC to the same numbers"""
272328

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.