Aluode/PerceptionLabPortable
0
1from itertools import product2import io3import platform4 5import matplotlib as mpl6import matplotlib.pyplot as plt7import matplotlib.ticker as mticker8from matplotlib import cbook9from matplotlib.backend_bases import MouseEvent10from matplotlib.colors import LogNorm11from matplotlib.patches import Circle, Ellipse12from matplotlib.transforms import Bbox, TransformedBbox13from matplotlib.testing.decorators import (14 check_figures_equal, image_comparison, remove_ticks_and_titles)15 16from mpl_toolkits.axes_grid1 import (17 axes_size as Size,18 host_subplot, make_axes_locatable,19 Grid, AxesGrid, ImageGrid)20from mpl_toolkits.axes_grid1.anchored_artists import (21 AnchoredAuxTransformBox, AnchoredDrawingArea,22 AnchoredDirectionArrows, AnchoredSizeBar)23from mpl_toolkits.axes_grid1.axes_divider import (24 Divider, HBoxDivider, make_axes_area_auto_adjustable, SubplotDivider,25 VBoxDivider)26from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes27from mpl_toolkits.axes_grid1.inset_locator import (28 zoomed_inset_axes, mark_inset, inset_axes, BboxConnectorPatch)29import mpl_toolkits.axes_grid1.mpl_axes30import pytest31 32import numpy as np33from numpy.testing import assert_array_equal, assert_array_almost_equal34 35 36def test_divider_append_axes():37 fig, ax = plt.subplots()38 divider = make_axes_locatable(ax)39 axs = {40 "main": ax,41 "top": divider.append_axes("top", 1.2, pad=0.1, sharex=ax),42 "bottom": divider.append_axes("bottom", 1.2, pad=0.1, sharex=ax),43 "left": divider.append_axes("left", 1.2, pad=0.1, sharey=ax),44 "right": divider.append_axes("right", 1.2, pad=0.1, sharey=ax),45 }46 fig.canvas.draw()47 bboxes = {k: axs[k].get_window_extent() for k in axs}48 dpi = fig.dpi49 assert bboxes["top"].height == pytest.approx(1.2 * dpi)50 assert bboxes["bottom"].height == pytest.approx(1.2 * dpi)51 assert bboxes["left"].width == pytest.approx(1.2 * dpi)52 assert bboxes["right"].width == pytest.approx(1.2 * dpi)53 assert bboxes["top"].y0 - bboxes["main"].y1 == pytest.approx(0.1 * dpi)54 assert bboxes["main"].y0 - bboxes["bottom"].y1 == pytest.approx(0.1 * dpi)55 assert bboxes["main"].x0 - bboxes["left"].x1 == pytest.approx(0.1 * dpi)56 assert bboxes["right"].x0 - bboxes["main"].x1 == pytest.approx(0.1 * dpi)57 assert bboxes["left"].y0 == bboxes["main"].y0 == bboxes["right"].y058 assert bboxes["left"].y1 == bboxes["main"].y1 == bboxes["right"].y159 assert bboxes["top"].x0 == bboxes["main"].x0 == bboxes["bottom"].x060 assert bboxes["top"].x1 == bboxes["main"].x1 == bboxes["bottom"].x161 62 63# Update style when regenerating the test image64@image_comparison(['twin_axes_empty_and_removed'], extensions=["png"], tol=1,65 style=('classic', '_classic_test_patch'))66def test_twin_axes_empty_and_removed():67 # Purely cosmetic font changes (avoid overlap)68 mpl.rcParams.update(69 {"font.size": 8, "xtick.labelsize": 8, "ytick.labelsize": 8})70 generators = ["twinx", "twiny", "twin"]71 modifiers = ["", "host invisible", "twin removed", "twin invisible",72 "twin removed\nhost invisible"]73 # Unmodified host subplot at the beginning for reference74 h = host_subplot(len(modifiers)+1, len(generators), 2)75 h.text(0.5, 0.5, "host_subplot",76 horizontalalignment="center", verticalalignment="center")77 # Host subplots with various modifications (twin*, visibility) applied78 for i, (mod, gen) in enumerate(product(modifiers, generators),79 len(generators) + 1):80 h = host_subplot(len(modifiers)+1, len(generators), i)81 t = getattr(h, gen)()82 if "twin invisible" in mod:83 t.axis[:].set_visible(False)84 if "twin removed" in mod:85 t.remove()86 if "host invisible" in mod:87 h.axis[:].set_visible(False)88 h.text(0.5, 0.5, gen + ("\n" + mod if mod else ""),89 horizontalalignment="center", verticalalignment="center")90 plt.subplots_adjust(wspace=0.5, hspace=1)91 92 93def test_twin_axes_both_with_units():94 host = host_subplot(111)95 with pytest.warns(mpl.MatplotlibDeprecationWarning):96 host.plot_date([0, 1, 2], [0, 1, 2], xdate=False, ydate=True)97 twin = host.twinx()98 twin.plot(["a", "b", "c"])99 assert host.get_yticklabels()[0].get_text() == "00:00:00"100 assert twin.get_yticklabels()[0].get_text() == "a"101 102 103def test_axesgrid_colorbar_log_smoketest():104 fig = plt.figure()105 grid = AxesGrid(fig, 111, # modified to be only subplot106 nrows_ncols=(1, 1),107 ngrids=1,108 label_mode="L",109 cbar_location="top",110 cbar_mode="single",111 )112 113 Z = 10000 * np.random.rand(10, 10)114 im = grid[0].imshow(Z, interpolation="nearest", norm=LogNorm())115 116 grid.cbar_axes[0].colorbar(im)117 118 119def test_inset_colorbar_tight_layout_smoketest():120 fig, ax = plt.subplots(1, 1)121 pts = ax.scatter([0, 1], [0, 1], c=[1, 5])122 123 cax = inset_axes(ax, width="3%", height="70%")124 plt.colorbar(pts, cax=cax)125 126 with pytest.warns(UserWarning, match="This figure includes Axes"):127 # Will warn, but not raise an error128 plt.tight_layout()129 130 131@image_comparison(['inset_locator.png'], style='default', remove_text=True)132def test_inset_locator():133 fig, ax = plt.subplots(figsize=[5, 4])134 135 # prepare the demo image136 # Z is a 15x15 array137 Z = cbook.get_sample_data("axes_grid/bivariate_normal.npy")138 extent = (-3, 4, -4, 3)139 Z2 = np.zeros((150, 150))140 ny, nx = Z.shape141 Z2[30:30+ny, 30:30+nx] = Z142 143 ax.imshow(Z2, extent=extent, interpolation="nearest",144 origin="lower")145 146 axins = zoomed_inset_axes(ax, zoom=6, loc='upper right')147 axins.imshow(Z2, extent=extent, interpolation="nearest",148 origin="lower")149 axins.yaxis.get_major_locator().set_params(nbins=7)150 axins.xaxis.get_major_locator().set_params(nbins=7)151 # sub region of the original image152 x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9153 axins.set_xlim(x1, x2)154 axins.set_ylim(y1, y2)155 156 plt.xticks(visible=False)157 plt.yticks(visible=False)158 159 # draw a bbox of the region of the inset axes in the parent axes and160 # connecting lines between the bbox and the inset axes area161 mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")162 163 asb = AnchoredSizeBar(ax.transData,164 0.5,165 '0.5',166 loc='lower center',167 pad=0.1, borderpad=0.5, sep=5,168 frameon=False)169 ax.add_artist(asb)170 171 172@image_comparison(['inset_axes.png'], style='default', remove_text=True)173def test_inset_axes():174 fig, ax = plt.subplots(figsize=[5, 4])175 176 # prepare the demo image177 # Z is a 15x15 array178 Z = cbook.get_sample_data("axes_grid/bivariate_normal.npy")179 extent = (-3, 4, -4, 3)180 Z2 = np.zeros((150, 150))181 ny, nx = Z.shape182 Z2[30:30+ny, 30:30+nx] = Z183 184 ax.imshow(Z2, extent=extent, interpolation="nearest",185 origin="lower")186 187 # creating our inset axes with a bbox_transform parameter188 axins = inset_axes(ax, width=1., height=1., bbox_to_anchor=(1, 1),189 bbox_transform=ax.transAxes)190 191 axins.imshow(Z2, extent=extent, interpolation="nearest",192 origin="lower")193 axins.yaxis.get_major_locator().set_params(nbins=7)194 axins.xaxis.get_major_locator().set_params(nbins=7)195 # sub region of the original image196 x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9197 axins.set_xlim(x1, x2)198 axins.set_ylim(y1, y2)199 200 plt.xticks(visible=False)201 plt.yticks(visible=False)202 203 # draw a bbox of the region of the inset axes in the parent axes and204 # connecting lines between the bbox and the inset axes area205 mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")206 207 asb = AnchoredSizeBar(ax.transData,208 0.5,209 '0.5',210 loc='lower center',211 pad=0.1, borderpad=0.5, sep=5,212 frameon=False)213 ax.add_artist(asb)214 215 216def test_inset_axes_complete():217 dpi = 100218 figsize = (6, 5)219 fig, ax = plt.subplots(figsize=figsize, dpi=dpi)220 fig.subplots_adjust(.1, .1, .9, .9)221 222 ins = inset_axes(ax, width=2., height=2., borderpad=0)223 fig.canvas.draw()224 assert_array_almost_equal(225 ins.get_position().extents,226 [(0.9*figsize[0]-2.)/figsize[0], (0.9*figsize[1]-2.)/figsize[1],227 0.9, 0.9])228 229 ins = inset_axes(ax, width="40%", height="30%", borderpad=0)230 fig.canvas.draw()231 assert_array_almost_equal(232 ins.get_position().extents, [.9-.8*.4, .9-.8*.3, 0.9, 0.9])233 234 ins = inset_axes(ax, width=1., height=1.2, bbox_to_anchor=(200, 100),235 loc=3, borderpad=0)236 fig.canvas.draw()237 assert_array_almost_equal(238 ins.get_position().extents,239 [200/dpi/figsize[0], 100/dpi/figsize[1],240 (200/dpi+1)/figsize[0], (100/dpi+1.2)/figsize[1]])241 242 ins1 = inset_axes(ax, width="35%", height="60%", loc=3, borderpad=1)243 ins2 = inset_axes(ax, width="100%", height="100%",244 bbox_to_anchor=(0, 0, .35, .60),245 bbox_transform=ax.transAxes, loc=3, borderpad=1)246 fig.canvas.draw()247 assert_array_equal(ins1.get_position().extents,248 ins2.get_position().extents)249 250 with pytest.raises(ValueError):251 ins = inset_axes(ax, width="40%", height="30%",252 bbox_to_anchor=(0.4, 0.5))253 254 with pytest.warns(UserWarning):255 ins = inset_axes(ax, width="40%", height="30%",256 bbox_transform=ax.transAxes)257 258 259def test_inset_axes_tight():260 # gh-26287 found that inset_axes raised with bbox_inches=tight261 fig, ax = plt.subplots()262 inset_axes(ax, width=1.3, height=0.9)263 264 f = io.BytesIO()265 fig.savefig(f, bbox_inches="tight")266 267 268@image_comparison(['fill_facecolor.png'], remove_text=True, style='mpl20')269def test_fill_facecolor():270 fig, ax = plt.subplots(1, 5)271 fig.set_size_inches(5, 5)272 for i in range(1, 4):273 ax[i].yaxis.set_visible(False)274 ax[4].yaxis.tick_right()275 bbox = Bbox.from_extents(0, 0.4, 1, 0.6)276 277 # fill with blue by setting 'fc' field278 bbox1 = TransformedBbox(bbox, ax[0].transData)279 bbox2 = TransformedBbox(bbox, ax[1].transData)280 # set color to BboxConnectorPatch281 p = BboxConnectorPatch(282 bbox1, bbox2, loc1a=1, loc2a=2, loc1b=4, loc2b=3,283 ec="r", fc="b")284 p.set_clip_on(False)285 ax[0].add_patch(p)286 # set color to marked area287 axins = zoomed_inset_axes(ax[0], 1, loc='upper right')288 axins.set_xlim(0, 0.2)289 axins.set_ylim(0, 0.2)290 plt.gca().axes.xaxis.set_ticks([])291 plt.gca().axes.yaxis.set_ticks([])292 mark_inset(ax[0], axins, loc1=2, loc2=4, fc="b", ec="0.5")293 294 # fill with yellow by setting 'facecolor' field295 bbox3 = TransformedBbox(bbox, ax[1].transData)296 bbox4 = TransformedBbox(bbox, ax[2].transData)297 # set color to BboxConnectorPatch298 p = BboxConnectorPatch(299 bbox3, bbox4, loc1a=1, loc2a=2, loc1b=4, loc2b=3,300 ec="r", facecolor="y")301 p.set_clip_on(False)302 ax[1].add_patch(p)303 # set color to marked area304 axins = zoomed_inset_axes(ax[1], 1, loc='upper right')305 axins.set_xlim(0, 0.2)306 axins.set_ylim(0, 0.2)307 plt.gca().axes.xaxis.set_ticks([])308 plt.gca().axes.yaxis.set_ticks([])309 mark_inset(ax[1], axins, loc1=2, loc2=4, facecolor="y", ec="0.5")310 311 # fill with green by setting 'color' field312 bbox5 = TransformedBbox(bbox, ax[2].transData)313 bbox6 = TransformedBbox(bbox, ax[3].transData)314 # set color to BboxConnectorPatch315 p = BboxConnectorPatch(316 bbox5, bbox6, loc1a=1, loc2a=2, loc1b=4, loc2b=3,317 ec="r", color="g")318 p.set_clip_on(False)319 ax[2].add_patch(p)320 # set color to marked area321 axins = zoomed_inset_axes(ax[2], 1, loc='upper right')322 axins.set_xlim(0, 0.2)323 axins.set_ylim(0, 0.2)324 plt.gca().axes.xaxis.set_ticks([])325 plt.gca().axes.yaxis.set_ticks([])326 mark_inset(ax[2], axins, loc1=2, loc2=4, color="g", ec="0.5")327 328 # fill with green but color won't show if set fill to False329 bbox7 = TransformedBbox(bbox, ax[3].transData)330 bbox8 = TransformedBbox(bbox, ax[4].transData)331 # BboxConnectorPatch won't show green332 p = BboxConnectorPatch(333 bbox7, bbox8, loc1a=1, loc2a=2, loc1b=4, loc2b=3,334 ec="r", fc="g", fill=False)335 p.set_clip_on(False)336 ax[3].add_patch(p)337 # marked area won't show green338 axins = zoomed_inset_axes(ax[3], 1, loc='upper right')339 axins.set_xlim(0, 0.2)340 axins.set_ylim(0, 0.2)341 axins.xaxis.set_ticks([])342 axins.yaxis.set_ticks([])343 mark_inset(ax[3], axins, loc1=2, loc2=4, fc="g", ec="0.5", fill=False)344 345 346# Update style when regenerating the test image347@image_comparison(['zoomed_axes.png', 'inverted_zoomed_axes.png'],348 style=('classic', '_classic_test_patch'),349 tol=0 if platform.machine() == 'x86_64' else 0.02)350def test_zooming_with_inverted_axes():351 fig, ax = plt.subplots()352 ax.plot([1, 2, 3], [1, 2, 3])353 ax.axis([1, 3, 1, 3])354 inset_ax = zoomed_inset_axes(ax, zoom=2.5, loc='lower right')355 inset_ax.axis([1.1, 1.4, 1.1, 1.4])356 357 fig, ax = plt.subplots()358 ax.plot([1, 2, 3], [1, 2, 3])359 ax.axis([3, 1, 3, 1])360 inset_ax = zoomed_inset_axes(ax, zoom=2.5, loc='lower right')361 inset_ax.axis([1.4, 1.1, 1.4, 1.1])362 363 364# Update style when regenerating the test image365@image_comparison(['anchored_direction_arrows.png'],366 tol=0 if platform.machine() == 'x86_64' else 0.01,367 style=('classic', '_classic_test_patch'))368def test_anchored_direction_arrows():369 fig, ax = plt.subplots()370 ax.imshow(np.zeros((10, 10)), interpolation='nearest')371 372 simple_arrow = AnchoredDirectionArrows(ax.transAxes, 'X', 'Y')373 ax.add_artist(simple_arrow)374 375 376# Update style when regenerating the test image377@image_comparison(['anchored_direction_arrows_many_args.png'],378 style=('classic', '_classic_test_patch'))379def test_anchored_direction_arrows_many_args():380 fig, ax = plt.subplots()381 ax.imshow(np.ones((10, 10)))382 383 direction_arrows = AnchoredDirectionArrows(384 ax.transAxes, 'A', 'B', loc='upper right', color='red',385 aspect_ratio=-0.5, pad=0.6, borderpad=2, frameon=True, alpha=0.7,386 sep_x=-0.06, sep_y=-0.08, back_length=0.1, head_width=9,387 head_length=10, tail_width=5)388 ax.add_artist(direction_arrows)389 390 391def test_axes_locatable_position():392 fig, ax = plt.subplots()393 divider = make_axes_locatable(ax)394 with mpl.rc_context({"figure.subplot.wspace": 0.02}):395 cax = divider.append_axes('right', size='5%')396 fig.canvas.draw()397 assert np.isclose(cax.get_position(original=False).width,398 0.03621495327102808)399 400 401@image_comparison(['image_grid_each_left_label_mode_all.png'], style='mpl20',402 savefig_kwarg={'bbox_inches': 'tight'})403def test_image_grid_each_left_label_mode_all():404 imdata = np.arange(100).reshape((10, 10))405 406 fig = plt.figure(1, (3, 3))407 grid = ImageGrid(fig, (1, 1, 1), nrows_ncols=(3, 2), axes_pad=(0.5, 0.3),408 cbar_mode="each", cbar_location="left", cbar_size="15%",409 label_mode="all")410 # 3-tuple rect => SubplotDivider411 assert isinstance(grid.get_divider(), SubplotDivider)412 assert grid.get_axes_pad() == (0.5, 0.3)413 assert grid.get_aspect() # True by default for ImageGrid414 for ax, cax in zip(grid, grid.cbar_axes):415 im = ax.imshow(imdata, interpolation='none')416 cax.colorbar(im)417 418 419@image_comparison(['image_grid_single_bottom_label_mode_1.png'], style='mpl20',420 savefig_kwarg={'bbox_inches': 'tight'})421def test_image_grid_single_bottom():422 imdata = np.arange(100).reshape((10, 10))423 424 fig = plt.figure(1, (2.5, 1.5))425 grid = ImageGrid(fig, (0, 0, 1, 1), nrows_ncols=(1, 3),426 axes_pad=(0.2, 0.15), cbar_mode="single", cbar_pad=0.3,427 cbar_location="bottom", cbar_size="10%", label_mode="1")428 # 4-tuple rect => Divider, isinstance will give True for SubplotDivider429 assert type(grid.get_divider()) is Divider430 for i in range(3):431 im = grid[i].imshow(imdata, interpolation='none')432 grid.cbar_axes[0].colorbar(im)433 434 435def test_image_grid_label_mode_invalid():436 fig = plt.figure()437 with pytest.raises(ValueError, match="'foo' is not a valid value for mode"):438 ImageGrid(fig, (0, 0, 1, 1), (2, 1), label_mode="foo")439 440 441@image_comparison(['image_grid.png'],442 remove_text=True, style='mpl20',443 savefig_kwarg={'bbox_inches': 'tight'})444def test_image_grid():445 # test that image grid works with bbox_inches=tight.446 im = np.arange(100).reshape((10, 10))447 448 fig = plt.figure(1, (4, 4))449 grid = ImageGrid(fig, 111, nrows_ncols=(2, 2), axes_pad=0.1)450 assert grid.get_axes_pad() == (0.1, 0.1)451 for i in range(4):452 grid[i].imshow(im, interpolation='nearest')453 454 455def test_gettightbbox():456 fig, ax = plt.subplots(figsize=(8, 6))457 458 l, = ax.plot([1, 2, 3], [0, 1, 0])459 460 ax_zoom = zoomed_inset_axes(ax, 4)461 ax_zoom.plot([1, 2, 3], [0, 1, 0])462 463 mark_inset(ax, ax_zoom, loc1=1, loc2=3, fc="none", ec='0.3')464 465 remove_ticks_and_titles(fig)466 bbox = fig.get_tightbbox(fig.canvas.get_renderer())467 np.testing.assert_array_almost_equal(bbox.extents,468 [-17.7, -13.9, 7.2, 5.4])469 470 471@pytest.mark.parametrize("click_on", ["big", "small"])472@pytest.mark.parametrize("big_on_axes,small_on_axes", [473 ("gca", "gca"),474 ("host", "host"),475 ("host", "parasite"),476 ("parasite", "host"),477 ("parasite", "parasite")478])479def test_picking_callbacks_overlap(big_on_axes, small_on_axes, click_on):480 """Test pick events on normal, host or parasite axes."""481 # Two rectangles are drawn and "clicked on", a small one and a big one482 # enclosing the small one. The axis on which they are drawn as well as the483 # rectangle that is clicked on are varied.484 # In each case we expect that both rectangles are picked if we click on the485 # small one and only the big one is picked if we click on the big one.486 # Also tests picking on normal axes ("gca") as a control.487 big = plt.Rectangle((0.25, 0.25), 0.5, 0.5, picker=5)488 small = plt.Rectangle((0.4, 0.4), 0.2, 0.2, facecolor="r", picker=5)489 # Machinery for "receiving" events490 received_events = []491 def on_pick(event):492 received_events.append(event)493 plt.gcf().canvas.mpl_connect('pick_event', on_pick)494 # Shortcut495 rectangles_on_axes = (big_on_axes, small_on_axes)496 # Axes setup497 axes = {"gca": None, "host": None, "parasite": None}498 if "gca" in rectangles_on_axes:499 axes["gca"] = plt.gca()500 if "host" in rectangles_on_axes or "parasite" in rectangles_on_axes:501 axes["host"] = host_subplot(111)502 axes["parasite"] = axes["host"].twin()503 # Add rectangles to axes504 axes[big_on_axes].add_patch(big)505 axes[small_on_axes].add_patch(small)506 # Simulate picking with click mouse event507 if click_on == "big":508 click_axes = axes[big_on_axes]509 axes_coords = (0.3, 0.3)510 else:511 click_axes = axes[small_on_axes]512 axes_coords = (0.5, 0.5)513 # In reality mouse events never happen on parasite axes, only host axes514 if click_axes is axes["parasite"]:515 click_axes = axes["host"]516 (x, y) = click_axes.transAxes.transform(axes_coords)517 m = MouseEvent("button_press_event", click_axes.get_figure(root=True).canvas, x, y,518 button=1)519 click_axes.pick(m)520 # Checks521 expected_n_events = 2 if click_on == "small" else 1522 assert len(received_events) == expected_n_events523 event_rects = [event.artist for event in received_events]524 assert big in event_rects525 if click_on == "small":526 assert small in event_rects527 528 529@image_comparison(['anchored_artists.png'], remove_text=True, style='mpl20')530def test_anchored_artists():531 fig, ax = plt.subplots(figsize=(3, 3))532 ada = AnchoredDrawingArea(40, 20, 0, 0, loc='upper right', pad=0.,533 frameon=False)534 p1 = Circle((10, 10), 10)535 ada.drawing_area.add_artist(p1)536 p2 = Circle((30, 10), 5, fc="r")537 ada.drawing_area.add_artist(p2)538 ax.add_artist(ada)539 540 box = AnchoredAuxTransformBox(ax.transData, loc='upper left')541 el = Ellipse((0, 0), width=0.1, height=0.4, angle=30, color='cyan')542 box.drawing_area.add_artist(el)543 ax.add_artist(box)544 545 # This block used to test the AnchoredEllipse class, but that was removed. The block546 # remains, though it duplicates the above ellipse, so that the test image doesn't547 # need to be regenerated.548 box = AnchoredAuxTransformBox(ax.transData, loc='lower left', frameon=True,549 pad=0.5, borderpad=0.4)550 el = Ellipse((0, 0), width=0.1, height=0.25, angle=-60)551 box.drawing_area.add_artist(el)552 ax.add_artist(box)553 554 asb = AnchoredSizeBar(ax.transData, 0.2, r"0.2 units", loc='lower right',555 pad=0.3, borderpad=0.4, sep=4, fill_bar=True,556 frameon=False, label_top=True, prop={'size': 20},557 size_vertical=0.05, color='green')558 ax.add_artist(asb)559 560 561def test_hbox_divider():562 arr1 = np.arange(20).reshape((4, 5))563 arr2 = np.arange(20).reshape((5, 4))564 565 fig, (ax1, ax2) = plt.subplots(1, 2)566 ax1.imshow(arr1)567 ax2.imshow(arr2)568 569 pad = 0.5 # inches.570 divider = HBoxDivider(571 fig, 111, # Position of combined axes.572 horizontal=[Size.AxesX(ax1), Size.Fixed(pad), Size.AxesX(ax2)],573 vertical=[Size.AxesY(ax1), Size.Scaled(1), Size.AxesY(ax2)])574 ax1.set_axes_locator(divider.new_locator(0))575 ax2.set_axes_locator(divider.new_locator(2))576 577 fig.canvas.draw()578 p1 = ax1.get_position()579 p2 = ax2.get_position()580 assert p1.height == p2.height581 assert p2.width / p1.width == pytest.approx((4 / 5) ** 2)582 583 584def test_vbox_divider():585 arr1 = np.arange(20).reshape((4, 5))586 arr2 = np.arange(20).reshape((5, 4))587 588 fig, (ax1, ax2) = plt.subplots(1, 2)589 ax1.imshow(arr1)590 ax2.imshow(arr2)591 592 pad = 0.5 # inches.593 divider = VBoxDivider(594 fig, 111, # Position of combined axes.595 horizontal=[Size.AxesX(ax1), Size.Scaled(1), Size.AxesX(ax2)],596 vertical=[Size.AxesY(ax1), Size.Fixed(pad), Size.AxesY(ax2)])597 ax1.set_axes_locator(divider.new_locator(0))598 ax2.set_axes_locator(divider.new_locator(2))599 600 fig.canvas.draw()601 p1 = ax1.get_position()602 p2 = ax2.get_position()603 assert p1.width == p2.width604 assert p1.height / p2.height == pytest.approx((4 / 5) ** 2)605 606 607def test_axes_class_tuple():608 fig = plt.figure()609 axes_class = (mpl_toolkits.axes_grid1.mpl_axes.Axes, {})610 gr = AxesGrid(fig, 111, nrows_ncols=(1, 1), axes_class=axes_class)611 612 613def test_grid_axes_lists():614 """Test Grid axes_all, axes_row and axes_column relationship."""615 fig = plt.figure()616 grid = Grid(fig, 111, (2, 3), direction="row")617 assert_array_equal(grid, grid.axes_all)618 assert_array_equal(grid.axes_row, np.transpose(grid.axes_column))619 assert_array_equal(grid, np.ravel(grid.axes_row), "row")620 assert grid.get_geometry() == (2, 3)621 grid = Grid(fig, 111, (2, 3), direction="column")622 assert_array_equal(grid, np.ravel(grid.axes_column), "column")623 624 625@pytest.mark.parametrize('direction', ('row', 'column'))626def test_grid_axes_position(direction):627 """Test positioning of the axes in Grid."""628 fig = plt.figure()629 grid = Grid(fig, 111, (2, 2), direction=direction)630 loc = [ax.get_axes_locator() for ax in np.ravel(grid.axes_row)]631 # Test nx.632 assert loc[1].args[0] > loc[0].args[0]633 assert loc[0].args[0] == loc[2].args[0]634 assert loc[3].args[0] == loc[1].args[0]635 # Test ny.636 assert loc[2].args[1] < loc[0].args[1]637 assert loc[0].args[1] == loc[1].args[1]638 assert loc[3].args[1] == loc[2].args[1]639 640 641@pytest.mark.parametrize('rect, ngrids, error, message', (642 ((1, 1), None, TypeError, "Incorrect rect format"),643 (111, -1, ValueError, "ngrids must be positive"),644 (111, 7, ValueError, "ngrids must be positive"),645))646def test_grid_errors(rect, ngrids, error, message):647 fig = plt.figure()648 with pytest.raises(error, match=message):649 Grid(fig, rect, (2, 3), ngrids=ngrids)650 651 652@pytest.mark.parametrize('anchor, error, message', (653 (None, TypeError, "anchor must be str"),654 ("CC", ValueError, "'CC' is not a valid value for anchor"),655 ((1, 1, 1), TypeError, "anchor must be str"),656))657def test_divider_errors(anchor, error, message):658 fig = plt.figure()659 with pytest.raises(error, match=message):660 Divider(fig, [0, 0, 1, 1], [Size.Fixed(1)], [Size.Fixed(1)],661 anchor=anchor)662 663 664@check_figures_equal(extensions=["png"])665def test_mark_inset_unstales_viewlim(fig_test, fig_ref):666 inset, full = fig_test.subplots(1, 2)667 full.plot([0, 5], [0, 5])668 inset.set(xlim=(1, 2), ylim=(1, 2))669 # Check that mark_inset unstales full's viewLim before drawing the marks.670 mark_inset(full, inset, 1, 4)671 672 inset, full = fig_ref.subplots(1, 2)673 full.plot([0, 5], [0, 5])674 inset.set(xlim=(1, 2), ylim=(1, 2))675 mark_inset(full, inset, 1, 4)676 # Manually unstale the full's viewLim.677 fig_ref.canvas.draw()678 679 680def test_auto_adjustable():681 fig = plt.figure()682 ax = fig.add_axes([0, 0, 1, 1])683 pad = 0.1684 make_axes_area_auto_adjustable(ax, pad=pad)685 fig.canvas.draw()686 tbb = ax.get_tightbbox()687 assert tbb.x0 == pytest.approx(pad * fig.dpi)688 assert tbb.x1 == pytest.approx(fig.bbox.width - pad * fig.dpi)689 assert tbb.y0 == pytest.approx(pad * fig.dpi)690 assert tbb.y1 == pytest.approx(fig.bbox.height - pad * fig.dpi)691 692 693# Update style when regenerating the test image694@image_comparison(['rgb_axes.png'], remove_text=True,695 style=('classic', '_classic_test_patch'))696def test_rgb_axes():697 fig = plt.figure()698 ax = RGBAxes(fig, (0.1, 0.1, 0.8, 0.8), pad=0.1)699 rng = np.random.default_rng(19680801)700 r = rng.random((5, 5))701 g = rng.random((5, 5))702 b = rng.random((5, 5))703 ax.imshow_rgb(r, g, b, interpolation='none')704 705 706# The original version of this test relied on mpl_toolkits's slightly different707# colorbar implementation; moving to matplotlib's own colorbar implementation708# caused the small image comparison error.709@image_comparison(['imagegrid_cbar_mode.png'],710 remove_text=True, style='mpl20', tol=0.3)711def test_imagegrid_cbar_mode_edge():712 arr = np.arange(16).reshape((4, 4))713 714 fig = plt.figure(figsize=(18, 9))715 716 positions = (241, 242, 243, 244, 245, 246, 247, 248)717 directions = ['row']*4 + ['column']*4718 cbar_locations = ['left', 'right', 'top', 'bottom']*2719 720 for position, direction, location in zip(721 positions, directions, cbar_locations):722 grid = ImageGrid(fig, position,723 nrows_ncols=(2, 2),724 direction=direction,725 cbar_location=location,726 cbar_size='20%',727 cbar_mode='edge')728 ax1, ax2, ax3, ax4 = grid729 730 ax1.imshow(arr, cmap='nipy_spectral')731 ax2.imshow(arr.T, cmap='hot')732 ax3.imshow(np.hypot(arr, arr.T), cmap='jet')733 ax4.imshow(np.arctan2(arr, arr.T), cmap='hsv')734 735 # In each row/column, the "first" colorbars must be overwritten by the736 # "second" ones. To achieve this, clear out the axes first.737 for ax in grid:738 ax.cax.cla()739 cb = ax.cax.colorbar(ax.images[0])740 741 742def test_imagegrid():743 fig = plt.figure()744 grid = ImageGrid(fig, 111, nrows_ncols=(1, 1))745 ax = grid[0]746 im = ax.imshow([[1, 2]], norm=mpl.colors.LogNorm())747 cb = ax.cax.colorbar(im)748 assert isinstance(cb.locator, mticker.LogLocator)749 750 751def test_removal():752 import matplotlib.pyplot as plt753 import mpl_toolkits.axisartist as AA754 fig = plt.figure()755 ax = host_subplot(111, axes_class=AA.Axes, figure=fig)756 col = ax.fill_between(range(5), 0, range(5))757 fig.canvas.draw()758 col.remove()759 fig.canvas.draw()760 761 762@image_comparison(['anchored_locator_base_call.png'], style="mpl20")763def test_anchored_locator_base_call():764 fig = plt.figure(figsize=(3, 3))765 fig1, fig2 = fig.subfigures(nrows=2, ncols=1)766 767 ax = fig1.subplots()768 ax.set(aspect=1, xlim=(-15, 15), ylim=(-20, 5))769 ax.set(xticks=[], yticks=[])770 771 Z = cbook.get_sample_data("axes_grid/bivariate_normal.npy")772 extent = (-3, 4, -4, 3)773 774 axins = zoomed_inset_axes(ax, zoom=2, loc="upper left")775 axins.set(xticks=[], yticks=[])776 777 axins.imshow(Z, extent=extent, origin="lower")778 779 780def test_grid_with_axes_class_not_overriding_axis():781 Grid(plt.figure(), 111, (2, 2), axes_class=mpl.axes.Axes)782 RGBAxes(plt.figure(), 111, axes_class=mpl.axes.Axes)783 