test_cycles.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import platform
  2. from matplotlib.testing.decorators import image_comparison
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. import pytest
  6. from cycler import cycler
  7. @image_comparison(['color_cycle_basic.png'], remove_text=True,
  8. tol={'aarch64': 0.02}.get(platform.machine(), 0.0))
  9. def test_colorcycle_basic():
  10. fig, ax = plt.subplots()
  11. ax.set_prop_cycle(cycler('color', ['r', 'g', 'y']))
  12. xs = np.arange(10)
  13. ys = 0.25 * xs + 2
  14. ax.plot(xs, ys, label='red', lw=4)
  15. ys = 0.45 * xs + 3
  16. ax.plot(xs, ys, label='green', lw=4)
  17. ys = 0.65 * xs + 4
  18. ax.plot(xs, ys, label='yellow', lw=4)
  19. ys = 0.85 * xs + 5
  20. ax.plot(xs, ys, label='red2', lw=4)
  21. ax.legend(loc='upper left')
  22. @image_comparison(['marker_cycle.png', 'marker_cycle.png'], remove_text=True,
  23. tol={'aarch64': 0.02}.get(platform.machine(), 0.0))
  24. def test_marker_cycle():
  25. fig, ax = plt.subplots()
  26. ax.set_prop_cycle(cycler('c', ['r', 'g', 'y']) +
  27. cycler('marker', ['.', '*', 'x']))
  28. xs = np.arange(10)
  29. ys = 0.25 * xs + 2
  30. ax.plot(xs, ys, label='red dot', lw=4, ms=16)
  31. ys = 0.45 * xs + 3
  32. ax.plot(xs, ys, label='green star', lw=4, ms=16)
  33. ys = 0.65 * xs + 4
  34. ax.plot(xs, ys, label='yellow x', lw=4, ms=16)
  35. ys = 0.85 * xs + 5
  36. ax.plot(xs, ys, label='red2 dot', lw=4, ms=16)
  37. ax.legend(loc='upper left')
  38. fig, ax = plt.subplots()
  39. # Test keyword arguments, numpy arrays, and generic iterators
  40. ax.set_prop_cycle(c=np.array(['r', 'g', 'y']),
  41. marker=iter(['.', '*', 'x']))
  42. xs = np.arange(10)
  43. ys = 0.25 * xs + 2
  44. ax.plot(xs, ys, label='red dot', lw=4, ms=16)
  45. ys = 0.45 * xs + 3
  46. ax.plot(xs, ys, label='green star', lw=4, ms=16)
  47. ys = 0.65 * xs + 4
  48. ax.plot(xs, ys, label='yellow x', lw=4, ms=16)
  49. ys = 0.85 * xs + 5
  50. ax.plot(xs, ys, label='red2 dot', lw=4, ms=16)
  51. ax.legend(loc='upper left')
  52. @image_comparison(['lineprop_cycle_basic.png'], remove_text=True,
  53. tol={'aarch64': 0.02}.get(platform.machine(), 0.0))
  54. def test_linestylecycle_basic():
  55. fig, ax = plt.subplots()
  56. ax.set_prop_cycle(cycler('ls', ['-', '--', ':']))
  57. xs = np.arange(10)
  58. ys = 0.25 * xs + 2
  59. ax.plot(xs, ys, label='solid', lw=4, color='k')
  60. ys = 0.45 * xs + 3
  61. ax.plot(xs, ys, label='dashed', lw=4, color='k')
  62. ys = 0.65 * xs + 4
  63. ax.plot(xs, ys, label='dotted', lw=4, color='k')
  64. ys = 0.85 * xs + 5
  65. ax.plot(xs, ys, label='solid2', lw=4, color='k')
  66. ax.legend(loc='upper left')
  67. @image_comparison(['fill_cycle_basic.png'], remove_text=True)
  68. def test_fillcycle_basic():
  69. fig, ax = plt.subplots()
  70. ax.set_prop_cycle(cycler('c', ['r', 'g', 'y']) +
  71. cycler('hatch', ['xx', 'O', '|-']) +
  72. cycler('linestyle', ['-', '--', ':']))
  73. xs = np.arange(10)
  74. ys = 0.25 * xs**.5 + 2
  75. ax.fill(xs, ys, label='red, xx', linewidth=3)
  76. ys = 0.45 * xs**.5 + 3
  77. ax.fill(xs, ys, label='green, circle', linewidth=3)
  78. ys = 0.65 * xs**.5 + 4
  79. ax.fill(xs, ys, label='yellow, cross', linewidth=3)
  80. ys = 0.85 * xs**.5 + 5
  81. ax.fill(xs, ys, label='red2, xx', linewidth=3)
  82. ax.legend(loc='upper left')
  83. @image_comparison(['fill_cycle_ignore.png'], remove_text=True)
  84. def test_fillcycle_ignore():
  85. fig, ax = plt.subplots()
  86. ax.set_prop_cycle(cycler('color', ['r', 'g', 'y']) +
  87. cycler('hatch', ['xx', 'O', '|-']) +
  88. cycler('marker', ['.', '*', 'D']))
  89. xs = np.arange(10)
  90. ys = 0.25 * xs**.5 + 2
  91. # Should not advance the cycler, even though there is an
  92. # unspecified property in the cycler "marker".
  93. # "marker" is not a Polygon property, and should be ignored.
  94. ax.fill(xs, ys, 'r', hatch='xx', label='red, xx')
  95. ys = 0.45 * xs**.5 + 3
  96. # Allow the cycler to advance, but specify some properties
  97. ax.fill(xs, ys, hatch='O', label='red, circle')
  98. ys = 0.65 * xs**.5 + 4
  99. ax.fill(xs, ys, label='green, circle')
  100. ys = 0.85 * xs**.5 + 5
  101. ax.fill(xs, ys, label='yellow, cross')
  102. ax.legend(loc='upper left')
  103. @image_comparison(['property_collision_plot.png'], remove_text=True)
  104. def test_property_collision_plot():
  105. fig, ax = plt.subplots()
  106. ax.set_prop_cycle('linewidth', [2, 4])
  107. for c in range(1, 4):
  108. ax.plot(np.arange(10), c * np.arange(10), lw=0.1, color='k')
  109. ax.plot(np.arange(10), 4 * np.arange(10), color='k')
  110. ax.plot(np.arange(10), 5 * np.arange(10), color='k')
  111. @image_comparison(['property_collision_fill.png'], remove_text=True)
  112. def test_property_collision_fill():
  113. fig, ax = plt.subplots()
  114. xs = np.arange(10)
  115. ys = 0.25 * xs**.5 + 2
  116. ax.set_prop_cycle(linewidth=[2, 3, 4, 5, 6], facecolor='bgcmy')
  117. for c in range(1, 4):
  118. ax.fill(xs, c * ys, lw=0.1)
  119. ax.fill(xs, 4 * ys)
  120. ax.fill(xs, 5 * ys)
  121. def test_valid_input_forms():
  122. fig, ax = plt.subplots()
  123. # These should not raise an error.
  124. ax.set_prop_cycle(None)
  125. ax.set_prop_cycle(cycler('linewidth', [1, 2]))
  126. ax.set_prop_cycle('color', 'rgywkbcm')
  127. ax.set_prop_cycle('lw', (1, 2))
  128. ax.set_prop_cycle('linewidth', [1, 2])
  129. ax.set_prop_cycle('linewidth', iter([1, 2]))
  130. ax.set_prop_cycle('linewidth', np.array([1, 2]))
  131. ax.set_prop_cycle('color', np.array([[1, 0, 0],
  132. [0, 1, 0],
  133. [0, 0, 1]]))
  134. ax.set_prop_cycle('dashes', [[], [13, 2], [8, 3, 1, 3], [None, None]])
  135. ax.set_prop_cycle(lw=[1, 2], color=['k', 'w'], ls=['-', '--'])
  136. ax.set_prop_cycle(lw=np.array([1, 2]),
  137. color=np.array(['k', 'w']),
  138. ls=np.array(['-', '--']))
  139. def test_cycle_reset():
  140. fig, ax = plt.subplots()
  141. # Can't really test a reset because only a cycle object is stored
  142. # but we can test the first item of the cycle.
  143. prop = next(ax._get_lines.prop_cycler)
  144. ax.set_prop_cycle(linewidth=[10, 9, 4])
  145. assert prop != next(ax._get_lines.prop_cycler)
  146. ax.set_prop_cycle(None)
  147. got = next(ax._get_lines.prop_cycler)
  148. assert prop == got
  149. def test_invalid_input_forms():
  150. fig, ax = plt.subplots()
  151. with pytest.raises((TypeError, ValueError)):
  152. ax.set_prop_cycle(1)
  153. with pytest.raises((TypeError, ValueError)):
  154. ax.set_prop_cycle([1, 2])
  155. with pytest.raises((TypeError, ValueError)):
  156. ax.set_prop_cycle('color', 'fish')
  157. with pytest.raises((TypeError, ValueError)):
  158. ax.set_prop_cycle('linewidth', 1)
  159. with pytest.raises((TypeError, ValueError)):
  160. ax.set_prop_cycle('linewidth', {'1': 1, '2': 2})
  161. with pytest.raises((TypeError, ValueError)):
  162. ax.set_prop_cycle(linewidth=1, color='r')
  163. with pytest.raises((TypeError, ValueError)):
  164. ax.set_prop_cycle('foobar', [1, 2])
  165. with pytest.raises((TypeError, ValueError)):
  166. ax.set_prop_cycle(foobar=[1, 2])
  167. with pytest.raises((TypeError, ValueError)):
  168. ax.set_prop_cycle(cycler(foobar=[1, 2]))
  169. with pytest.raises(ValueError):
  170. ax.set_prop_cycle(cycler(color='rgb', c='cmy'))