123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- import warnings
- import numpy as np
- from numpy.testing import assert_array_equal
- import pytest
- from matplotlib.testing.decorators import image_comparison
- import matplotlib.pyplot as plt
- from matplotlib.offsetbox import AnchoredOffsetbox, DrawingArea
- from matplotlib.patches import Rectangle
- def example_plot(ax, fontsize=12):
- ax.plot([1, 2])
- ax.locator_params(nbins=3)
- ax.set_xlabel('x-label', fontsize=fontsize)
- ax.set_ylabel('y-label', fontsize=fontsize)
- ax.set_title('Title', fontsize=fontsize)
- @image_comparison(['tight_layout1'])
- def test_tight_layout1():
- 'Test tight_layout for a single subplot'
- fig, ax = plt.subplots()
- example_plot(ax, fontsize=24)
- plt.tight_layout()
- @image_comparison(['tight_layout2'])
- def test_tight_layout2():
- 'Test tight_layout for multiple subplots'
- fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
- example_plot(ax1)
- example_plot(ax2)
- example_plot(ax3)
- example_plot(ax4)
- plt.tight_layout()
- @image_comparison(['tight_layout3'])
- def test_tight_layout3():
- 'Test tight_layout for multiple subplots'
- ax1 = plt.subplot(221)
- ax2 = plt.subplot(223)
- ax3 = plt.subplot(122)
- example_plot(ax1)
- example_plot(ax2)
- example_plot(ax3)
- plt.tight_layout()
- @image_comparison(['tight_layout4'], freetype_version=('2.5.5', '2.6.1'))
- def test_tight_layout4():
- 'Test tight_layout for subplot2grid'
- ax1 = plt.subplot2grid((3, 3), (0, 0))
- ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
- ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
- ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
- example_plot(ax1)
- example_plot(ax2)
- example_plot(ax3)
- example_plot(ax4)
- plt.tight_layout()
- @image_comparison(['tight_layout5'])
- def test_tight_layout5():
- 'Test tight_layout for image'
- ax = plt.subplot(111)
- arr = np.arange(100).reshape((10, 10))
- ax.imshow(arr, interpolation="none")
- plt.tight_layout()
- @image_comparison(['tight_layout6'])
- def test_tight_layout6():
- 'Test tight_layout for gridspec'
- # This raises warnings since tight layout cannot
- # do this fully automatically. But the test is
- # correct since the layout is manually edited
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", UserWarning)
- fig = plt.figure()
- import matplotlib.gridspec as gridspec
- gs1 = gridspec.GridSpec(2, 1)
- ax1 = fig.add_subplot(gs1[0])
- ax2 = fig.add_subplot(gs1[1])
- example_plot(ax1)
- example_plot(ax2)
- gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
- gs2 = gridspec.GridSpec(3, 1)
- for ss in gs2:
- ax = fig.add_subplot(ss)
- example_plot(ax)
- ax.set_title("")
- ax.set_xlabel("")
- ax.set_xlabel("x-label", fontsize=12)
- gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.45)
- top = min(gs1.top, gs2.top)
- bottom = max(gs1.bottom, gs2.bottom)
- gs1.tight_layout(fig, rect=[None, 0 + (bottom-gs1.bottom),
- 0.5, 1 - (gs1.top-top)])
- gs2.tight_layout(fig, rect=[0.5, 0 + (bottom-gs2.bottom),
- None, 1 - (gs2.top-top)],
- h_pad=0.45)
- @image_comparison(['tight_layout7'])
- def test_tight_layout7():
- # tight layout with left and right titles
- fontsize = 24
- fig, ax = plt.subplots()
- ax.plot([1, 2])
- ax.locator_params(nbins=3)
- ax.set_xlabel('x-label', fontsize=fontsize)
- ax.set_ylabel('y-label', fontsize=fontsize)
- ax.set_title('Left Title', loc='left', fontsize=fontsize)
- ax.set_title('Right Title', loc='right', fontsize=fontsize)
- plt.tight_layout()
- @image_comparison(['tight_layout8'])
- def test_tight_layout8():
- 'Test automatic use of tight_layout'
- fig = plt.figure()
- fig.set_tight_layout({'pad': .1})
- ax = fig.add_subplot(111)
- example_plot(ax, fontsize=24)
- @image_comparison(['tight_layout9'])
- def test_tight_layout9():
- # Test tight_layout for non-visible subplots
- # GH 8244
- f, axarr = plt.subplots(2, 2)
- axarr[1][1].set_visible(False)
- plt.tight_layout()
- def test_outward_ticks():
- 'Test automatic use of tight_layout'
- fig = plt.figure()
- ax = fig.add_subplot(221)
- ax.xaxis.set_tick_params(tickdir='out', length=16, width=3)
- ax.yaxis.set_tick_params(tickdir='out', length=16, width=3)
- ax.xaxis.set_tick_params(
- tickdir='out', length=32, width=3, tick1On=True, which='minor')
- ax.yaxis.set_tick_params(
- tickdir='out', length=32, width=3, tick1On=True, which='minor')
- ax.xaxis.set_ticks([0], minor=True)
- ax.yaxis.set_ticks([0], minor=True)
- ax = fig.add_subplot(222)
- ax.xaxis.set_tick_params(tickdir='in', length=32, width=3)
- ax.yaxis.set_tick_params(tickdir='in', length=32, width=3)
- ax = fig.add_subplot(223)
- ax.xaxis.set_tick_params(tickdir='inout', length=32, width=3)
- ax.yaxis.set_tick_params(tickdir='inout', length=32, width=3)
- ax = fig.add_subplot(224)
- ax.xaxis.set_tick_params(tickdir='out', length=32, width=3)
- ax.yaxis.set_tick_params(tickdir='out', length=32, width=3)
- plt.tight_layout()
- # These values were obtained after visual checking that they correspond
- # to a tight layouting that did take the ticks into account.
- ans = [[[0.091, 0.607], [0.433, 0.933]],
- [[0.579, 0.607], [0.922, 0.933]],
- [[0.091, 0.140], [0.433, 0.466]],
- [[0.579, 0.140], [0.922, 0.466]]]
- for nn, ax in enumerate(fig.axes):
- assert_array_equal(np.round(ax.get_position().get_points(), 3),
- ans[nn])
- def add_offsetboxes(ax, size=10, margin=.1, color='black'):
- """
- Surround ax with OffsetBoxes
- """
- m, mp = margin, 1+margin
- anchor_points = [(-m, -m), (-m, .5), (-m, mp),
- (mp, .5), (.5, mp), (mp, mp),
- (.5, -m), (mp, -m), (.5, -m)]
- for point in anchor_points:
- da = DrawingArea(size, size)
- background = Rectangle((0, 0), width=size,
- height=size,
- facecolor=color,
- edgecolor='None',
- linewidth=0,
- antialiased=False)
- da.add_artist(background)
- anchored_box = AnchoredOffsetbox(
- loc='center',
- child=da,
- pad=0.,
- frameon=False,
- bbox_to_anchor=point,
- bbox_transform=ax.transAxes,
- borderpad=0.)
- ax.add_artist(anchored_box)
- return anchored_box
- @image_comparison(['tight_layout_offsetboxes1', 'tight_layout_offsetboxes2'])
- def test_tight_layout_offsetboxes():
- # 1.
- # - Create 4 subplots
- # - Plot a diagonal line on them
- # - Surround each plot with 7 boxes
- # - Use tight_layout
- # - See that the squares are included in the tight_layout
- # and that the squares in the middle do not overlap
- #
- # 2.
- # - Make the squares around the right side axes invisible
- # - See that the invisible squares do not affect the
- # tight_layout
- rows = cols = 2
- colors = ['red', 'blue', 'green', 'yellow']
- x = y = [0, 1]
- def _subplots():
- _, axs = plt.subplots(rows, cols)
- axs = axs.flat
- for ax, color in zip(axs, colors):
- ax.plot(x, y, color=color)
- add_offsetboxes(ax, 20, color=color)
- return axs
- # 1.
- axs = _subplots()
- plt.tight_layout()
- # 2.
- axs = _subplots()
- for ax in (axs[cols-1::rows]):
- for child in ax.get_children():
- if isinstance(child, AnchoredOffsetbox):
- child.set_visible(False)
- plt.tight_layout()
- def test_empty_layout():
- """Test that tight layout doesn't cause an error when there are no axes."""
- fig = plt.gcf()
- fig.tight_layout()
- @pytest.mark.parametrize("label", ["xlabel", "ylabel"])
- def test_verybig_decorators(label):
- """Test that warning emitted when xlabel/ylabel too big."""
- fig, ax = plt.subplots(figsize=(3, 2))
- ax.set(**{label: 'a' * 100})
- with pytest.warns(UserWarning):
- fig.tight_layout()
- def test_big_decorators_horizontal():
- "Test that warning emitted when xlabel too big"
- fig, axs = plt.subplots(1, 2, figsize=(3, 2))
- axs[0].set_xlabel('a' * 30)
- axs[1].set_xlabel('b' * 30)
- with pytest.warns(UserWarning):
- fig.tight_layout()
- def test_big_decorators_vertical():
- "Test that warning emitted when xlabel too big"
- fig, axs = plt.subplots(2, 1, figsize=(3, 2))
- axs[0].set_ylabel('a' * 20)
- axs[1].set_ylabel('b' * 20)
- with pytest.warns(UserWarning):
- fig.tight_layout()
- def test_badsubplotgrid():
- # test that we get warning for mismatched subplot grids, not than an error
- plt.subplot2grid((4, 5), (0, 0))
- # this is the bad entry:
- plt.subplot2grid((5, 5), (0, 3), colspan=3, rowspan=5)
- with pytest.warns(UserWarning):
- plt.tight_layout()
- def test_collapsed():
- # test that if a call to tight_layout will collapses the axes that
- # it does not get applied:
- fig, ax = plt.subplots(tight_layout=True)
- ax.set_xlim([0, 1])
- ax.set_ylim([0, 1])
- ax.annotate('BIG LONG STRING', xy=(1.25, 2), xytext=(10.5, 1.75),)
- p1 = ax.get_position()
- with pytest.warns(UserWarning):
- plt.tight_layout()
- p2 = ax.get_position()
- assert p1.width == p2.width
- # test that passing a rect doesn't crash...
- with pytest.warns(UserWarning):
- plt.tight_layout(rect=[0, 0, 0.8, 0.8])
|