test_table.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import numpy as np
  2. import pytest
  3. import matplotlib.pyplot as plt
  4. import matplotlib as mpl
  5. from matplotlib.path import Path
  6. from matplotlib.table import CustomCell, Table
  7. from matplotlib.testing.decorators import image_comparison, check_figures_equal
  8. from matplotlib.transforms import Bbox
  9. def test_non_square():
  10. # Check that creating a non-square table works
  11. cellcolors = ['b', 'r']
  12. plt.table(cellColours=cellcolors)
  13. @image_comparison(['table_zorder.png'], remove_text=True)
  14. def test_zorder():
  15. data = [[66386, 174296],
  16. [58230, 381139]]
  17. colLabels = ('Freeze', 'Wind')
  18. rowLabels = ['%d year' % x for x in (100, 50)]
  19. cellText = []
  20. yoff = np.zeros(len(colLabels))
  21. for row in reversed(data):
  22. yoff += row
  23. cellText.append(['%1.1f' % (x/1000.0) for x in yoff])
  24. t = np.linspace(0, 2*np.pi, 100)
  25. plt.plot(t, np.cos(t), lw=4, zorder=2)
  26. plt.table(cellText=cellText,
  27. rowLabels=rowLabels,
  28. colLabels=colLabels,
  29. loc='center',
  30. zorder=-2,
  31. )
  32. plt.table(cellText=cellText,
  33. rowLabels=rowLabels,
  34. colLabels=colLabels,
  35. loc='upper center',
  36. zorder=4,
  37. )
  38. plt.yticks([])
  39. @image_comparison(['table_labels.png'])
  40. def test_label_colours():
  41. dim = 3
  42. c = np.linspace(0, 1, dim)
  43. colours = plt.cm.RdYlGn(c)
  44. cellText = [['1'] * dim] * dim
  45. fig = plt.figure()
  46. ax1 = fig.add_subplot(4, 1, 1)
  47. ax1.axis('off')
  48. ax1.table(cellText=cellText,
  49. rowColours=colours,
  50. loc='best')
  51. ax2 = fig.add_subplot(4, 1, 2)
  52. ax2.axis('off')
  53. ax2.table(cellText=cellText,
  54. rowColours=colours,
  55. rowLabels=['Header'] * dim,
  56. loc='best')
  57. ax3 = fig.add_subplot(4, 1, 3)
  58. ax3.axis('off')
  59. ax3.table(cellText=cellText,
  60. colColours=colours,
  61. loc='best')
  62. ax4 = fig.add_subplot(4, 1, 4)
  63. ax4.axis('off')
  64. ax4.table(cellText=cellText,
  65. colColours=colours,
  66. colLabels=['Header'] * dim,
  67. loc='best')
  68. @image_comparison(['table_cell_manipulation.png'], remove_text=True)
  69. def test_diff_cell_table():
  70. cells = ('horizontal', 'vertical', 'open', 'closed', 'T', 'R', 'B', 'L')
  71. cellText = [['1'] * len(cells)] * 2
  72. colWidths = [0.1] * len(cells)
  73. _, axs = plt.subplots(nrows=len(cells), figsize=(4, len(cells)+1))
  74. for ax, cell in zip(axs, cells):
  75. ax.table(
  76. colWidths=colWidths,
  77. cellText=cellText,
  78. loc='center',
  79. edges=cell,
  80. )
  81. ax.axis('off')
  82. plt.tight_layout()
  83. def test_customcell():
  84. types = ('horizontal', 'vertical', 'open', 'closed', 'T', 'R', 'B', 'L')
  85. codes = (
  86. (Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO, Path.MOVETO),
  87. (Path.MOVETO, Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO),
  88. (Path.MOVETO, Path.MOVETO, Path.MOVETO, Path.MOVETO, Path.MOVETO),
  89. (Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY),
  90. (Path.MOVETO, Path.MOVETO, Path.MOVETO, Path.LINETO, Path.MOVETO),
  91. (Path.MOVETO, Path.MOVETO, Path.LINETO, Path.MOVETO, Path.MOVETO),
  92. (Path.MOVETO, Path.LINETO, Path.MOVETO, Path.MOVETO, Path.MOVETO),
  93. (Path.MOVETO, Path.MOVETO, Path.MOVETO, Path.MOVETO, Path.LINETO),
  94. )
  95. for t, c in zip(types, codes):
  96. cell = CustomCell((0, 0), visible_edges=t, width=1, height=1)
  97. code = tuple(s for _, s in cell.get_path().iter_segments())
  98. assert c == code
  99. @image_comparison(['table_auto_column.png'])
  100. def test_auto_column():
  101. fig = plt.figure()
  102. # iterable list input
  103. ax1 = fig.add_subplot(4, 1, 1)
  104. ax1.axis('off')
  105. tb1 = ax1.table(
  106. cellText=[['Fit Text', 2],
  107. ['very long long text, Longer text than default', 1]],
  108. rowLabels=["A", "B"],
  109. colLabels=["Col1", "Col2"],
  110. loc="center")
  111. tb1.auto_set_font_size(False)
  112. tb1.set_fontsize(12)
  113. tb1.auto_set_column_width([-1, 0, 1])
  114. # iterable tuple input
  115. ax2 = fig.add_subplot(4, 1, 2)
  116. ax2.axis('off')
  117. tb2 = ax2.table(
  118. cellText=[['Fit Text', 2],
  119. ['very long long text, Longer text than default', 1]],
  120. rowLabels=["A", "B"],
  121. colLabels=["Col1", "Col2"],
  122. loc="center")
  123. tb2.auto_set_font_size(False)
  124. tb2.set_fontsize(12)
  125. tb2.auto_set_column_width((-1, 0, 1))
  126. # 3 single inputs
  127. ax3 = fig.add_subplot(4, 1, 3)
  128. ax3.axis('off')
  129. tb3 = ax3.table(
  130. cellText=[['Fit Text', 2],
  131. ['very long long text, Longer text than default', 1]],
  132. rowLabels=["A", "B"],
  133. colLabels=["Col1", "Col2"],
  134. loc="center")
  135. tb3.auto_set_font_size(False)
  136. tb3.set_fontsize(12)
  137. tb3.auto_set_column_width(-1)
  138. tb3.auto_set_column_width(0)
  139. tb3.auto_set_column_width(1)
  140. # 4 non integer iterable input
  141. ax4 = fig.add_subplot(4, 1, 4)
  142. ax4.axis('off')
  143. tb4 = ax4.table(
  144. cellText=[['Fit Text', 2],
  145. ['very long long text, Longer text than default', 1]],
  146. rowLabels=["A", "B"],
  147. colLabels=["Col1", "Col2"],
  148. loc="center")
  149. tb4.auto_set_font_size(False)
  150. tb4.set_fontsize(12)
  151. with pytest.warns(mpl.MatplotlibDeprecationWarning,
  152. match="'col' must be an int or sequence of ints"):
  153. tb4.auto_set_column_width("-101") # type: ignore [arg-type]
  154. with pytest.warns(mpl.MatplotlibDeprecationWarning,
  155. match="'col' must be an int or sequence of ints"):
  156. tb4.auto_set_column_width(["-101"]) # type: ignore [list-item]
  157. def test_table_cells():
  158. fig, ax = plt.subplots()
  159. table = Table(ax)
  160. cell = table.add_cell(1, 2, 1, 1)
  161. assert isinstance(cell, CustomCell)
  162. assert cell is table[1, 2]
  163. cell2 = CustomCell((0, 0), 1, 2, visible_edges=None)
  164. table[2, 1] = cell2
  165. assert table[2, 1] is cell2
  166. # make sure getitem support has not broken
  167. # properties and setp
  168. table.properties()
  169. plt.setp(table)
  170. @check_figures_equal(extensions=["png"])
  171. def test_table_bbox(fig_test, fig_ref):
  172. data = [[2, 3],
  173. [4, 5]]
  174. col_labels = ('Foo', 'Bar')
  175. row_labels = ('Ada', 'Bob')
  176. cell_text = [[f"{x}" for x in row] for row in data]
  177. ax_list = fig_test.subplots()
  178. ax_list.table(cellText=cell_text,
  179. rowLabels=row_labels,
  180. colLabels=col_labels,
  181. loc='center',
  182. bbox=[0.1, 0.2, 0.8, 0.6]
  183. )
  184. ax_bbox = fig_ref.subplots()
  185. ax_bbox.table(cellText=cell_text,
  186. rowLabels=row_labels,
  187. colLabels=col_labels,
  188. loc='center',
  189. bbox=Bbox.from_extents(0.1, 0.2, 0.9, 0.8)
  190. )