test_quiver.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import warnings
  2. import numpy as np
  3. import pytest
  4. import sys
  5. from matplotlib import pyplot as plt
  6. from matplotlib.testing.decorators import image_comparison
  7. def draw_quiver(ax, **kw):
  8. X, Y = np.meshgrid(np.arange(0, 2 * np.pi, 1),
  9. np.arange(0, 2 * np.pi, 1))
  10. U = np.cos(X)
  11. V = np.sin(Y)
  12. Q = ax.quiver(U, V, **kw)
  13. return Q
  14. def test_quiver_memory_leak():
  15. fig, ax = plt.subplots()
  16. Q = draw_quiver(ax)
  17. ttX = Q.X
  18. Q.remove()
  19. del Q
  20. assert sys.getrefcount(ttX) == 2
  21. def test_quiver_key_memory_leak():
  22. fig, ax = plt.subplots()
  23. Q = draw_quiver(ax)
  24. qk = ax.quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$',
  25. labelpos='W',
  26. fontproperties={'weight': 'bold'})
  27. assert sys.getrefcount(qk) == 3
  28. qk.remove()
  29. assert sys.getrefcount(qk) == 2
  30. def test_quiver_number_of_args():
  31. X = [1, 2]
  32. with pytest.raises(TypeError,
  33. match='takes 2-5 positional arguments but 1 were given'):
  34. plt.quiver(X)
  35. with pytest.raises(TypeError,
  36. match='takes 2-5 positional arguments but 6 were given'):
  37. plt.quiver(X, X, X, X, X, X)
  38. def test_quiver_arg_sizes():
  39. X2 = [1, 2]
  40. X3 = [1, 2, 3]
  41. with pytest.raises(ValueError,
  42. match=('X and Y must be the same size, but '
  43. 'X.size is 2 and Y.size is 3.')):
  44. plt.quiver(X2, X3, X2, X2)
  45. with pytest.raises(ValueError,
  46. match=('Argument U has a size 3 which does not match 2,'
  47. ' the number of arrow positions')):
  48. plt.quiver(X2, X2, X3, X2)
  49. with pytest.raises(ValueError,
  50. match=('Argument V has a size 3 which does not match 2,'
  51. ' the number of arrow positions')):
  52. plt.quiver(X2, X2, X2, X3)
  53. with pytest.raises(ValueError,
  54. match=('Argument C has a size 3 which does not match 2,'
  55. ' the number of arrow positions')):
  56. plt.quiver(X2, X2, X2, X2, X3)
  57. def test_no_warnings():
  58. fig, ax = plt.subplots()
  59. X, Y = np.meshgrid(np.arange(15), np.arange(10))
  60. U = V = np.ones_like(X)
  61. phi = (np.random.rand(15, 10) - .5) * 150
  62. with warnings.catch_warnings(record=True) as w:
  63. ax.quiver(X, Y, U, V, angles=phi)
  64. fig.canvas.draw()
  65. assert len(w) == 0
  66. def test_zero_headlength():
  67. # Based on report by Doug McNeil:
  68. # http://matplotlib.1069221.n5.nabble.com/quiver-warnings-td28107.html
  69. fig, ax = plt.subplots()
  70. X, Y = np.meshgrid(np.arange(10), np.arange(10))
  71. U, V = np.cos(X), np.sin(Y)
  72. with warnings.catch_warnings(record=True) as w:
  73. ax.quiver(U, V, headlength=0, headaxislength=0)
  74. fig.canvas.draw()
  75. assert len(w) == 0
  76. @image_comparison(['quiver_animated_test_image.png'])
  77. def test_quiver_animate():
  78. # Tests fix for #2616
  79. fig, ax = plt.subplots()
  80. Q = draw_quiver(ax, animated=True)
  81. ax.quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$',
  82. labelpos='W', fontproperties={'weight': 'bold'})
  83. @image_comparison(['quiver_with_key_test_image.png'])
  84. def test_quiver_with_key():
  85. fig, ax = plt.subplots()
  86. ax.margins(0.1)
  87. Q = draw_quiver(ax)
  88. ax.quiverkey(Q, 0.5, 0.95, 2,
  89. r'$2\, \mathrm{m}\, \mathrm{s}^{-1}$',
  90. angle=-10,
  91. coordinates='figure',
  92. labelpos='W',
  93. fontproperties={'weight': 'bold', 'size': 'large'})
  94. @image_comparison(['quiver_single_test_image.png'], remove_text=True)
  95. def test_quiver_single():
  96. fig, ax = plt.subplots()
  97. ax.margins(0.1)
  98. ax.quiver([1], [1], [2], [2])
  99. def test_quiver_copy():
  100. fig, ax = plt.subplots()
  101. uv = dict(u=np.array([1.1]), v=np.array([2.0]))
  102. q0 = ax.quiver([1], [1], uv['u'], uv['v'])
  103. uv['v'][0] = 0
  104. assert q0.V[0] == 2.0
  105. @image_comparison(['quiver_key_pivot.png'], remove_text=True)
  106. def test_quiver_key_pivot():
  107. fig, ax = plt.subplots()
  108. u, v = np.mgrid[0:2*np.pi:10j, 0:2*np.pi:10j]
  109. q = ax.quiver(np.sin(u), np.cos(v))
  110. ax.set_xlim(-2, 11)
  111. ax.set_ylim(-2, 11)
  112. ax.quiverkey(q, 0.5, 1, 1, 'N', labelpos='N')
  113. ax.quiverkey(q, 1, 0.5, 1, 'E', labelpos='E')
  114. ax.quiverkey(q, 0.5, 0, 1, 'S', labelpos='S')
  115. ax.quiverkey(q, 0, 0.5, 1, 'W', labelpos='W')
  116. @image_comparison(['quiver_key_xy.png'], remove_text=True)
  117. def test_quiver_key_xy():
  118. # With scale_units='xy', ensure quiverkey still matches its quiver.
  119. # Note that the quiver and quiverkey lengths depend on the axes aspect
  120. # ratio, and that with angles='xy' their angles also depend on the axes
  121. # aspect ratio.
  122. X = np.arange(8)
  123. Y = np.zeros(8)
  124. angles = X * (np.pi / 4)
  125. uv = np.exp(1j * angles)
  126. U = uv.real
  127. V = uv.imag
  128. fig, axs = plt.subplots(2)
  129. for ax, angle_str in zip(axs, ('uv', 'xy')):
  130. ax.set_xlim(-1, 8)
  131. ax.set_ylim(-0.2, 0.2)
  132. q = ax.quiver(X, Y, U, V, pivot='middle',
  133. units='xy', width=0.05,
  134. scale=2, scale_units='xy',
  135. angles=angle_str)
  136. for x, angle in zip((0.2, 0.5, 0.8), (0, 45, 90)):
  137. ax.quiverkey(q, X=x, Y=0.8, U=1, angle=angle, label='', color='b')
  138. @image_comparison(['barbs_test_image.png'], remove_text=True)
  139. def test_barbs():
  140. x = np.linspace(-5, 5, 5)
  141. X, Y = np.meshgrid(x, x)
  142. U, V = 12*X, 12*Y
  143. fig, ax = plt.subplots()
  144. ax.barbs(X, Y, U, V, np.hypot(U, V), fill_empty=True, rounding=False,
  145. sizes=dict(emptybarb=0.25, spacing=0.2, height=0.3),
  146. cmap='viridis')
  147. @image_comparison(['barbs_pivot_test_image.png'], remove_text=True)
  148. def test_barbs_pivot():
  149. x = np.linspace(-5, 5, 5)
  150. X, Y = np.meshgrid(x, x)
  151. U, V = 12*X, 12*Y
  152. fig, ax = plt.subplots()
  153. ax.barbs(X, Y, U, V, fill_empty=True, rounding=False, pivot=1.7,
  154. sizes=dict(emptybarb=0.25, spacing=0.2, height=0.3))
  155. ax.scatter(X, Y, s=49, c='black')
  156. @image_comparison(['barbs_test_flip.png'], remove_text=True)
  157. def test_barbs_flip():
  158. """Test barbs with an array for flip_barb."""
  159. x = np.linspace(-5, 5, 5)
  160. X, Y = np.meshgrid(x, x)
  161. U, V = 12*X, 12*Y
  162. fig, ax = plt.subplots()
  163. ax.barbs(X, Y, U, V, fill_empty=True, rounding=False, pivot=1.7,
  164. sizes=dict(emptybarb=0.25, spacing=0.2, height=0.3),
  165. flip_barb=Y < 0)
  166. def test_bad_masked_sizes():
  167. 'Test error handling when given differing sized masked arrays'
  168. x = np.arange(3)
  169. y = np.arange(3)
  170. u = np.ma.array(15. * np.ones((4,)))
  171. v = np.ma.array(15. * np.ones_like(u))
  172. u[1] = np.ma.masked
  173. v[1] = np.ma.masked
  174. fig, ax = plt.subplots()
  175. with pytest.raises(ValueError):
  176. ax.barbs(x, y, u, v)
  177. def test_angles_and_scale():
  178. # angles array + scale_units kwarg
  179. fig, ax = plt.subplots()
  180. X, Y = np.meshgrid(np.arange(15), np.arange(10))
  181. U = V = np.ones_like(X)
  182. phi = (np.random.rand(15, 10) - .5) * 150
  183. ax.quiver(X, Y, U, V, angles=phi, scale_units='xy')
  184. @image_comparison(['quiver_xy.png'], remove_text=True)
  185. def test_quiver_xy():
  186. # simple arrow pointing from SW to NE
  187. fig, ax = plt.subplots(subplot_kw=dict(aspect='equal'))
  188. ax.quiver(0, 0, 1, 1, angles='xy', scale_units='xy', scale=1)
  189. ax.set_xlim(0, 1.1)
  190. ax.set_ylim(0, 1.1)
  191. ax.grid()
  192. def test_quiverkey_angles():
  193. # Check that only a single arrow is plotted for a quiverkey when an array
  194. # of angles is given to the original quiver plot
  195. fig, ax = plt.subplots()
  196. X, Y = np.meshgrid(np.arange(2), np.arange(2))
  197. U = V = angles = np.ones_like(X)
  198. q = ax.quiver(X, Y, U, V, angles=angles)
  199. qk = ax.quiverkey(q, 1, 1, 2, 'Label')
  200. # The arrows are only created when the key is drawn
  201. fig.canvas.draw()
  202. assert len(qk.verts) == 1
  203. def test_quiver_setuvc_numbers():
  204. """Check that it is possible to set all arrow UVC to the same numbers"""
  205. fig, ax = plt.subplots()
  206. X, Y = np.meshgrid(np.arange(2), np.arange(2))
  207. U = V = np.ones_like(X)
  208. q = ax.quiver(X, Y, U, V)
  209. q.set_UVC(0, 1)