test_spines.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import numpy as np
  2. import pytest
  3. import matplotlib.pyplot as plt
  4. from matplotlib.spines import Spines
  5. from matplotlib.testing.decorators import check_figures_equal, image_comparison
  6. def test_spine_class():
  7. """Test Spines and SpinesProxy in isolation."""
  8. class SpineMock:
  9. def __init__(self):
  10. self.val = None
  11. def set(self, **kwargs):
  12. vars(self).update(kwargs)
  13. def set_val(self, val):
  14. self.val = val
  15. spines_dict = {
  16. 'left': SpineMock(),
  17. 'right': SpineMock(),
  18. 'top': SpineMock(),
  19. 'bottom': SpineMock(),
  20. }
  21. spines = Spines(**spines_dict)
  22. assert spines['left'] is spines_dict['left']
  23. assert spines.left is spines_dict['left']
  24. spines[['left', 'right']].set_val('x')
  25. assert spines.left.val == 'x'
  26. assert spines.right.val == 'x'
  27. assert spines.top.val is None
  28. assert spines.bottom.val is None
  29. spines[:].set_val('y')
  30. assert all(spine.val == 'y' for spine in spines.values())
  31. spines[:].set(foo='bar')
  32. assert all(spine.foo == 'bar' for spine in spines.values())
  33. with pytest.raises(AttributeError, match='foo'):
  34. spines.foo
  35. with pytest.raises(KeyError, match='foo'):
  36. spines['foo']
  37. with pytest.raises(KeyError, match='foo, bar'):
  38. spines[['left', 'foo', 'right', 'bar']]
  39. with pytest.raises(ValueError, match='single list'):
  40. spines['left', 'right']
  41. with pytest.raises(ValueError, match='Spines does not support slicing'):
  42. spines['left':'right']
  43. with pytest.raises(ValueError, match='Spines does not support slicing'):
  44. spines['top':]
  45. @image_comparison(['spines_axes_positions'])
  46. def test_spines_axes_positions():
  47. # SF bug 2852168
  48. fig = plt.figure()
  49. x = np.linspace(0, 2*np.pi, 100)
  50. y = 2*np.sin(x)
  51. ax = fig.add_subplot(1, 1, 1)
  52. ax.set_title('centered spines')
  53. ax.plot(x, y)
  54. ax.spines.right.set_position(('axes', 0.1))
  55. ax.yaxis.set_ticks_position('right')
  56. ax.spines.top.set_position(('axes', 0.25))
  57. ax.xaxis.set_ticks_position('top')
  58. ax.spines.left.set_color('none')
  59. ax.spines.bottom.set_color('none')
  60. @image_comparison(['spines_data_positions'])
  61. def test_spines_data_positions():
  62. fig, ax = plt.subplots()
  63. ax.spines.left.set_position(('data', -1.5))
  64. ax.spines.top.set_position(('data', 0.5))
  65. ax.spines.right.set_position(('data', -0.5))
  66. ax.spines.bottom.set_position('zero')
  67. ax.set_xlim([-2, 2])
  68. ax.set_ylim([-2, 2])
  69. @check_figures_equal(extensions=["png"])
  70. def test_spine_nonlinear_data_positions(fig_test, fig_ref):
  71. plt.style.use("default")
  72. ax = fig_test.add_subplot()
  73. ax.set(xscale="log", xlim=(.1, 1))
  74. # Use position="data" to visually swap the left and right spines, using
  75. # linewidth to distinguish them. The calls to tick_params removes labels
  76. # (for image comparison purposes) and harmonizes tick positions with the
  77. # reference).
  78. ax.spines.left.set_position(("data", 1))
  79. ax.spines.left.set_linewidth(2)
  80. ax.spines.right.set_position(("data", .1))
  81. ax.tick_params(axis="y", labelleft=False, direction="in")
  82. ax = fig_ref.add_subplot()
  83. ax.set(xscale="log", xlim=(.1, 1))
  84. ax.spines.right.set_linewidth(2)
  85. ax.tick_params(axis="y", labelleft=False, left=False, right=True)
  86. @image_comparison(['spines_capstyle'])
  87. def test_spines_capstyle():
  88. # issue 2542
  89. plt.rc('axes', linewidth=20)
  90. fig, ax = plt.subplots()
  91. ax.set_xticks([])
  92. ax.set_yticks([])
  93. def test_label_without_ticks():
  94. fig, ax = plt.subplots()
  95. plt.subplots_adjust(left=0.3, bottom=0.3)
  96. ax.plot(np.arange(10))
  97. ax.yaxis.set_ticks_position('left')
  98. ax.spines.left.set_position(('outward', 30))
  99. ax.spines.right.set_visible(False)
  100. ax.set_ylabel('y label')
  101. ax.xaxis.set_ticks_position('bottom')
  102. ax.spines.bottom.set_position(('outward', 30))
  103. ax.spines.top.set_visible(False)
  104. ax.set_xlabel('x label')
  105. ax.xaxis.set_ticks([])
  106. ax.yaxis.set_ticks([])
  107. plt.draw()
  108. spine = ax.spines.left
  109. spinebbox = spine.get_transform().transform_path(
  110. spine.get_path()).get_extents()
  111. assert ax.yaxis.label.get_position()[0] < spinebbox.xmin, \
  112. "Y-Axis label not left of the spine"
  113. spine = ax.spines.bottom
  114. spinebbox = spine.get_transform().transform_path(
  115. spine.get_path()).get_extents()
  116. assert ax.xaxis.label.get_position()[1] < spinebbox.ymin, \
  117. "X-Axis label not below the spine"
  118. @image_comparison(['black_axes'])
  119. def test_spines_black_axes():
  120. # GitHub #18804
  121. plt.rcParams["savefig.pad_inches"] = 0
  122. plt.rcParams["savefig.bbox"] = 'tight'
  123. fig = plt.figure(0, figsize=(4, 4))
  124. ax = fig.add_axes((0, 0, 1, 1))
  125. ax.set_xticklabels([])
  126. ax.set_yticklabels([])
  127. ax.set_xticks([])
  128. ax.set_yticks([])
  129. ax.set_facecolor((0, 0, 0))