Initial commit
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# Check that the test directories exist
|
||||
if not (Path(__file__).parent / "baseline_images").exists():
|
||||
raise OSError(
|
||||
'The baseline image directory does not exist. '
|
||||
'This is most likely because the test data is not installed. '
|
||||
'You may need to install matplotlib from source to get the '
|
||||
'test data.')
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
from matplotlib.testing.conftest import (mpl_test_settings, # noqa
|
||||
pytest_configure, pytest_unconfigure)
|
||||
@@ -0,0 +1,782 @@
|
||||
from itertools import product
|
||||
import io
|
||||
import platform
|
||||
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.ticker as mticker
|
||||
from matplotlib import cbook
|
||||
from matplotlib.backend_bases import MouseEvent
|
||||
from matplotlib.colors import LogNorm
|
||||
from matplotlib.patches import Circle, Ellipse
|
||||
from matplotlib.transforms import Bbox, TransformedBbox
|
||||
from matplotlib.testing.decorators import (
|
||||
check_figures_equal, image_comparison, remove_ticks_and_titles)
|
||||
|
||||
from mpl_toolkits.axes_grid1 import (
|
||||
axes_size as Size,
|
||||
host_subplot, make_axes_locatable,
|
||||
Grid, AxesGrid, ImageGrid)
|
||||
from mpl_toolkits.axes_grid1.anchored_artists import (
|
||||
AnchoredAuxTransformBox, AnchoredDrawingArea,
|
||||
AnchoredDirectionArrows, AnchoredSizeBar)
|
||||
from mpl_toolkits.axes_grid1.axes_divider import (
|
||||
Divider, HBoxDivider, make_axes_area_auto_adjustable, SubplotDivider,
|
||||
VBoxDivider)
|
||||
from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
|
||||
from mpl_toolkits.axes_grid1.inset_locator import (
|
||||
zoomed_inset_axes, mark_inset, inset_axes, BboxConnectorPatch)
|
||||
import mpl_toolkits.axes_grid1.mpl_axes
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal, assert_array_almost_equal
|
||||
|
||||
|
||||
def test_divider_append_axes():
|
||||
fig, ax = plt.subplots()
|
||||
divider = make_axes_locatable(ax)
|
||||
axs = {
|
||||
"main": ax,
|
||||
"top": divider.append_axes("top", 1.2, pad=0.1, sharex=ax),
|
||||
"bottom": divider.append_axes("bottom", 1.2, pad=0.1, sharex=ax),
|
||||
"left": divider.append_axes("left", 1.2, pad=0.1, sharey=ax),
|
||||
"right": divider.append_axes("right", 1.2, pad=0.1, sharey=ax),
|
||||
}
|
||||
fig.canvas.draw()
|
||||
bboxes = {k: axs[k].get_window_extent() for k in axs}
|
||||
dpi = fig.dpi
|
||||
assert bboxes["top"].height == pytest.approx(1.2 * dpi)
|
||||
assert bboxes["bottom"].height == pytest.approx(1.2 * dpi)
|
||||
assert bboxes["left"].width == pytest.approx(1.2 * dpi)
|
||||
assert bboxes["right"].width == pytest.approx(1.2 * dpi)
|
||||
assert bboxes["top"].y0 - bboxes["main"].y1 == pytest.approx(0.1 * dpi)
|
||||
assert bboxes["main"].y0 - bboxes["bottom"].y1 == pytest.approx(0.1 * dpi)
|
||||
assert bboxes["main"].x0 - bboxes["left"].x1 == pytest.approx(0.1 * dpi)
|
||||
assert bboxes["right"].x0 - bboxes["main"].x1 == pytest.approx(0.1 * dpi)
|
||||
assert bboxes["left"].y0 == bboxes["main"].y0 == bboxes["right"].y0
|
||||
assert bboxes["left"].y1 == bboxes["main"].y1 == bboxes["right"].y1
|
||||
assert bboxes["top"].x0 == bboxes["main"].x0 == bboxes["bottom"].x0
|
||||
assert bboxes["top"].x1 == bboxes["main"].x1 == bboxes["bottom"].x1
|
||||
|
||||
|
||||
# Update style when regenerating the test image
|
||||
@image_comparison(['twin_axes_empty_and_removed'], extensions=["png"], tol=1,
|
||||
style=('classic', '_classic_test_patch'))
|
||||
def test_twin_axes_empty_and_removed():
|
||||
# Purely cosmetic font changes (avoid overlap)
|
||||
mpl.rcParams.update(
|
||||
{"font.size": 8, "xtick.labelsize": 8, "ytick.labelsize": 8})
|
||||
generators = ["twinx", "twiny", "twin"]
|
||||
modifiers = ["", "host invisible", "twin removed", "twin invisible",
|
||||
"twin removed\nhost invisible"]
|
||||
# Unmodified host subplot at the beginning for reference
|
||||
h = host_subplot(len(modifiers)+1, len(generators), 2)
|
||||
h.text(0.5, 0.5, "host_subplot",
|
||||
horizontalalignment="center", verticalalignment="center")
|
||||
# Host subplots with various modifications (twin*, visibility) applied
|
||||
for i, (mod, gen) in enumerate(product(modifiers, generators),
|
||||
len(generators) + 1):
|
||||
h = host_subplot(len(modifiers)+1, len(generators), i)
|
||||
t = getattr(h, gen)()
|
||||
if "twin invisible" in mod:
|
||||
t.axis[:].set_visible(False)
|
||||
if "twin removed" in mod:
|
||||
t.remove()
|
||||
if "host invisible" in mod:
|
||||
h.axis[:].set_visible(False)
|
||||
h.text(0.5, 0.5, gen + ("\n" + mod if mod else ""),
|
||||
horizontalalignment="center", verticalalignment="center")
|
||||
plt.subplots_adjust(wspace=0.5, hspace=1)
|
||||
|
||||
|
||||
def test_twin_axes_both_with_units():
|
||||
host = host_subplot(111)
|
||||
with pytest.warns(mpl.MatplotlibDeprecationWarning):
|
||||
host.plot_date([0, 1, 2], [0, 1, 2], xdate=False, ydate=True)
|
||||
twin = host.twinx()
|
||||
twin.plot(["a", "b", "c"])
|
||||
assert host.get_yticklabels()[0].get_text() == "00:00:00"
|
||||
assert twin.get_yticklabels()[0].get_text() == "a"
|
||||
|
||||
|
||||
def test_axesgrid_colorbar_log_smoketest():
|
||||
fig = plt.figure()
|
||||
grid = AxesGrid(fig, 111, # modified to be only subplot
|
||||
nrows_ncols=(1, 1),
|
||||
ngrids=1,
|
||||
label_mode="L",
|
||||
cbar_location="top",
|
||||
cbar_mode="single",
|
||||
)
|
||||
|
||||
Z = 10000 * np.random.rand(10, 10)
|
||||
im = grid[0].imshow(Z, interpolation="nearest", norm=LogNorm())
|
||||
|
||||
grid.cbar_axes[0].colorbar(im)
|
||||
|
||||
|
||||
def test_inset_colorbar_tight_layout_smoketest():
|
||||
fig, ax = plt.subplots(1, 1)
|
||||
pts = ax.scatter([0, 1], [0, 1], c=[1, 5])
|
||||
|
||||
cax = inset_axes(ax, width="3%", height="70%")
|
||||
plt.colorbar(pts, cax=cax)
|
||||
|
||||
with pytest.warns(UserWarning, match="This figure includes Axes"):
|
||||
# Will warn, but not raise an error
|
||||
plt.tight_layout()
|
||||
|
||||
|
||||
@image_comparison(['inset_locator.png'], style='default', remove_text=True)
|
||||
def test_inset_locator():
|
||||
fig, ax = plt.subplots(figsize=[5, 4])
|
||||
|
||||
# prepare the demo image
|
||||
# Z is a 15x15 array
|
||||
Z = cbook.get_sample_data("axes_grid/bivariate_normal.npy")
|
||||
extent = (-3, 4, -4, 3)
|
||||
Z2 = np.zeros((150, 150))
|
||||
ny, nx = Z.shape
|
||||
Z2[30:30+ny, 30:30+nx] = Z
|
||||
|
||||
ax.imshow(Z2, extent=extent, interpolation="nearest",
|
||||
origin="lower")
|
||||
|
||||
axins = zoomed_inset_axes(ax, zoom=6, loc='upper right')
|
||||
axins.imshow(Z2, extent=extent, interpolation="nearest",
|
||||
origin="lower")
|
||||
axins.yaxis.get_major_locator().set_params(nbins=7)
|
||||
axins.xaxis.get_major_locator().set_params(nbins=7)
|
||||
# sub region of the original image
|
||||
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
|
||||
axins.set_xlim(x1, x2)
|
||||
axins.set_ylim(y1, y2)
|
||||
|
||||
plt.xticks(visible=False)
|
||||
plt.yticks(visible=False)
|
||||
|
||||
# draw a bbox of the region of the inset axes in the parent axes and
|
||||
# connecting lines between the bbox and the inset axes area
|
||||
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")
|
||||
|
||||
asb = AnchoredSizeBar(ax.transData,
|
||||
0.5,
|
||||
'0.5',
|
||||
loc='lower center',
|
||||
pad=0.1, borderpad=0.5, sep=5,
|
||||
frameon=False)
|
||||
ax.add_artist(asb)
|
||||
|
||||
|
||||
@image_comparison(['inset_axes.png'], style='default', remove_text=True)
|
||||
def test_inset_axes():
|
||||
fig, ax = plt.subplots(figsize=[5, 4])
|
||||
|
||||
# prepare the demo image
|
||||
# Z is a 15x15 array
|
||||
Z = cbook.get_sample_data("axes_grid/bivariate_normal.npy")
|
||||
extent = (-3, 4, -4, 3)
|
||||
Z2 = np.zeros((150, 150))
|
||||
ny, nx = Z.shape
|
||||
Z2[30:30+ny, 30:30+nx] = Z
|
||||
|
||||
ax.imshow(Z2, extent=extent, interpolation="nearest",
|
||||
origin="lower")
|
||||
|
||||
# creating our inset axes with a bbox_transform parameter
|
||||
axins = inset_axes(ax, width=1., height=1., bbox_to_anchor=(1, 1),
|
||||
bbox_transform=ax.transAxes)
|
||||
|
||||
axins.imshow(Z2, extent=extent, interpolation="nearest",
|
||||
origin="lower")
|
||||
axins.yaxis.get_major_locator().set_params(nbins=7)
|
||||
axins.xaxis.get_major_locator().set_params(nbins=7)
|
||||
# sub region of the original image
|
||||
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
|
||||
axins.set_xlim(x1, x2)
|
||||
axins.set_ylim(y1, y2)
|
||||
|
||||
plt.xticks(visible=False)
|
||||
plt.yticks(visible=False)
|
||||
|
||||
# draw a bbox of the region of the inset axes in the parent axes and
|
||||
# connecting lines between the bbox and the inset axes area
|
||||
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")
|
||||
|
||||
asb = AnchoredSizeBar(ax.transData,
|
||||
0.5,
|
||||
'0.5',
|
||||
loc='lower center',
|
||||
pad=0.1, borderpad=0.5, sep=5,
|
||||
frameon=False)
|
||||
ax.add_artist(asb)
|
||||
|
||||
|
||||
def test_inset_axes_complete():
|
||||
dpi = 100
|
||||
figsize = (6, 5)
|
||||
fig, ax = plt.subplots(figsize=figsize, dpi=dpi)
|
||||
fig.subplots_adjust(.1, .1, .9, .9)
|
||||
|
||||
ins = inset_axes(ax, width=2., height=2., borderpad=0)
|
||||
fig.canvas.draw()
|
||||
assert_array_almost_equal(
|
||||
ins.get_position().extents,
|
||||
[(0.9*figsize[0]-2.)/figsize[0], (0.9*figsize[1]-2.)/figsize[1],
|
||||
0.9, 0.9])
|
||||
|
||||
ins = inset_axes(ax, width="40%", height="30%", borderpad=0)
|
||||
fig.canvas.draw()
|
||||
assert_array_almost_equal(
|
||||
ins.get_position().extents, [.9-.8*.4, .9-.8*.3, 0.9, 0.9])
|
||||
|
||||
ins = inset_axes(ax, width=1., height=1.2, bbox_to_anchor=(200, 100),
|
||||
loc=3, borderpad=0)
|
||||
fig.canvas.draw()
|
||||
assert_array_almost_equal(
|
||||
ins.get_position().extents,
|
||||
[200/dpi/figsize[0], 100/dpi/figsize[1],
|
||||
(200/dpi+1)/figsize[0], (100/dpi+1.2)/figsize[1]])
|
||||
|
||||
ins1 = inset_axes(ax, width="35%", height="60%", loc=3, borderpad=1)
|
||||
ins2 = inset_axes(ax, width="100%", height="100%",
|
||||
bbox_to_anchor=(0, 0, .35, .60),
|
||||
bbox_transform=ax.transAxes, loc=3, borderpad=1)
|
||||
fig.canvas.draw()
|
||||
assert_array_equal(ins1.get_position().extents,
|
||||
ins2.get_position().extents)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
ins = inset_axes(ax, width="40%", height="30%",
|
||||
bbox_to_anchor=(0.4, 0.5))
|
||||
|
||||
with pytest.warns(UserWarning):
|
||||
ins = inset_axes(ax, width="40%", height="30%",
|
||||
bbox_transform=ax.transAxes)
|
||||
|
||||
|
||||
def test_inset_axes_tight():
|
||||
# gh-26287 found that inset_axes raised with bbox_inches=tight
|
||||
fig, ax = plt.subplots()
|
||||
inset_axes(ax, width=1.3, height=0.9)
|
||||
|
||||
f = io.BytesIO()
|
||||
fig.savefig(f, bbox_inches="tight")
|
||||
|
||||
|
||||
@image_comparison(['fill_facecolor.png'], remove_text=True, style='mpl20')
|
||||
def test_fill_facecolor():
|
||||
fig, ax = plt.subplots(1, 5)
|
||||
fig.set_size_inches(5, 5)
|
||||
for i in range(1, 4):
|
||||
ax[i].yaxis.set_visible(False)
|
||||
ax[4].yaxis.tick_right()
|
||||
bbox = Bbox.from_extents(0, 0.4, 1, 0.6)
|
||||
|
||||
# fill with blue by setting 'fc' field
|
||||
bbox1 = TransformedBbox(bbox, ax[0].transData)
|
||||
bbox2 = TransformedBbox(bbox, ax[1].transData)
|
||||
# set color to BboxConnectorPatch
|
||||
p = BboxConnectorPatch(
|
||||
bbox1, bbox2, loc1a=1, loc2a=2, loc1b=4, loc2b=3,
|
||||
ec="r", fc="b")
|
||||
p.set_clip_on(False)
|
||||
ax[0].add_patch(p)
|
||||
# set color to marked area
|
||||
axins = zoomed_inset_axes(ax[0], 1, loc='upper right')
|
||||
axins.set_xlim(0, 0.2)
|
||||
axins.set_ylim(0, 0.2)
|
||||
plt.gca().axes.xaxis.set_ticks([])
|
||||
plt.gca().axes.yaxis.set_ticks([])
|
||||
mark_inset(ax[0], axins, loc1=2, loc2=4, fc="b", ec="0.5")
|
||||
|
||||
# fill with yellow by setting 'facecolor' field
|
||||
bbox3 = TransformedBbox(bbox, ax[1].transData)
|
||||
bbox4 = TransformedBbox(bbox, ax[2].transData)
|
||||
# set color to BboxConnectorPatch
|
||||
p = BboxConnectorPatch(
|
||||
bbox3, bbox4, loc1a=1, loc2a=2, loc1b=4, loc2b=3,
|
||||
ec="r", facecolor="y")
|
||||
p.set_clip_on(False)
|
||||
ax[1].add_patch(p)
|
||||
# set color to marked area
|
||||
axins = zoomed_inset_axes(ax[1], 1, loc='upper right')
|
||||
axins.set_xlim(0, 0.2)
|
||||
axins.set_ylim(0, 0.2)
|
||||
plt.gca().axes.xaxis.set_ticks([])
|
||||
plt.gca().axes.yaxis.set_ticks([])
|
||||
mark_inset(ax[1], axins, loc1=2, loc2=4, facecolor="y", ec="0.5")
|
||||
|
||||
# fill with green by setting 'color' field
|
||||
bbox5 = TransformedBbox(bbox, ax[2].transData)
|
||||
bbox6 = TransformedBbox(bbox, ax[3].transData)
|
||||
# set color to BboxConnectorPatch
|
||||
p = BboxConnectorPatch(
|
||||
bbox5, bbox6, loc1a=1, loc2a=2, loc1b=4, loc2b=3,
|
||||
ec="r", color="g")
|
||||
p.set_clip_on(False)
|
||||
ax[2].add_patch(p)
|
||||
# set color to marked area
|
||||
axins = zoomed_inset_axes(ax[2], 1, loc='upper right')
|
||||
axins.set_xlim(0, 0.2)
|
||||
axins.set_ylim(0, 0.2)
|
||||
plt.gca().axes.xaxis.set_ticks([])
|
||||
plt.gca().axes.yaxis.set_ticks([])
|
||||
mark_inset(ax[2], axins, loc1=2, loc2=4, color="g", ec="0.5")
|
||||
|
||||
# fill with green but color won't show if set fill to False
|
||||
bbox7 = TransformedBbox(bbox, ax[3].transData)
|
||||
bbox8 = TransformedBbox(bbox, ax[4].transData)
|
||||
# BboxConnectorPatch won't show green
|
||||
p = BboxConnectorPatch(
|
||||
bbox7, bbox8, loc1a=1, loc2a=2, loc1b=4, loc2b=3,
|
||||
ec="r", fc="g", fill=False)
|
||||
p.set_clip_on(False)
|
||||
ax[3].add_patch(p)
|
||||
# marked area won't show green
|
||||
axins = zoomed_inset_axes(ax[3], 1, loc='upper right')
|
||||
axins.set_xlim(0, 0.2)
|
||||
axins.set_ylim(0, 0.2)
|
||||
axins.xaxis.set_ticks([])
|
||||
axins.yaxis.set_ticks([])
|
||||
mark_inset(ax[3], axins, loc1=2, loc2=4, fc="g", ec="0.5", fill=False)
|
||||
|
||||
|
||||
# Update style when regenerating the test image
|
||||
@image_comparison(['zoomed_axes.png', 'inverted_zoomed_axes.png'],
|
||||
style=('classic', '_classic_test_patch'),
|
||||
tol=0 if platform.machine() == 'x86_64' else 0.02)
|
||||
def test_zooming_with_inverted_axes():
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot([1, 2, 3], [1, 2, 3])
|
||||
ax.axis([1, 3, 1, 3])
|
||||
inset_ax = zoomed_inset_axes(ax, zoom=2.5, loc='lower right')
|
||||
inset_ax.axis([1.1, 1.4, 1.1, 1.4])
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot([1, 2, 3], [1, 2, 3])
|
||||
ax.axis([3, 1, 3, 1])
|
||||
inset_ax = zoomed_inset_axes(ax, zoom=2.5, loc='lower right')
|
||||
inset_ax.axis([1.4, 1.1, 1.4, 1.1])
|
||||
|
||||
|
||||
# Update style when regenerating the test image
|
||||
@image_comparison(['anchored_direction_arrows.png'],
|
||||
tol=0 if platform.machine() == 'x86_64' else 0.01,
|
||||
style=('classic', '_classic_test_patch'))
|
||||
def test_anchored_direction_arrows():
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(np.zeros((10, 10)), interpolation='nearest')
|
||||
|
||||
simple_arrow = AnchoredDirectionArrows(ax.transAxes, 'X', 'Y')
|
||||
ax.add_artist(simple_arrow)
|
||||
|
||||
|
||||
# Update style when regenerating the test image
|
||||
@image_comparison(['anchored_direction_arrows_many_args.png'],
|
||||
style=('classic', '_classic_test_patch'))
|
||||
def test_anchored_direction_arrows_many_args():
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(np.ones((10, 10)))
|
||||
|
||||
direction_arrows = AnchoredDirectionArrows(
|
||||
ax.transAxes, 'A', 'B', loc='upper right', color='red',
|
||||
aspect_ratio=-0.5, pad=0.6, borderpad=2, frameon=True, alpha=0.7,
|
||||
sep_x=-0.06, sep_y=-0.08, back_length=0.1, head_width=9,
|
||||
head_length=10, tail_width=5)
|
||||
ax.add_artist(direction_arrows)
|
||||
|
||||
|
||||
def test_axes_locatable_position():
|
||||
fig, ax = plt.subplots()
|
||||
divider = make_axes_locatable(ax)
|
||||
with mpl.rc_context({"figure.subplot.wspace": 0.02}):
|
||||
cax = divider.append_axes('right', size='5%')
|
||||
fig.canvas.draw()
|
||||
assert np.isclose(cax.get_position(original=False).width,
|
||||
0.03621495327102808)
|
||||
|
||||
|
||||
@image_comparison(['image_grid_each_left_label_mode_all.png'], style='mpl20',
|
||||
savefig_kwarg={'bbox_inches': 'tight'})
|
||||
def test_image_grid_each_left_label_mode_all():
|
||||
imdata = np.arange(100).reshape((10, 10))
|
||||
|
||||
fig = plt.figure(1, (3, 3))
|
||||
grid = ImageGrid(fig, (1, 1, 1), nrows_ncols=(3, 2), axes_pad=(0.5, 0.3),
|
||||
cbar_mode="each", cbar_location="left", cbar_size="15%",
|
||||
label_mode="all")
|
||||
# 3-tuple rect => SubplotDivider
|
||||
assert isinstance(grid.get_divider(), SubplotDivider)
|
||||
assert grid.get_axes_pad() == (0.5, 0.3)
|
||||
assert grid.get_aspect() # True by default for ImageGrid
|
||||
for ax, cax in zip(grid, grid.cbar_axes):
|
||||
im = ax.imshow(imdata, interpolation='none')
|
||||
cax.colorbar(im)
|
||||
|
||||
|
||||
@image_comparison(['image_grid_single_bottom_label_mode_1.png'], style='mpl20',
|
||||
savefig_kwarg={'bbox_inches': 'tight'})
|
||||
def test_image_grid_single_bottom():
|
||||
imdata = np.arange(100).reshape((10, 10))
|
||||
|
||||
fig = plt.figure(1, (2.5, 1.5))
|
||||
grid = ImageGrid(fig, (0, 0, 1, 1), nrows_ncols=(1, 3),
|
||||
axes_pad=(0.2, 0.15), cbar_mode="single", cbar_pad=0.3,
|
||||
cbar_location="bottom", cbar_size="10%", label_mode="1")
|
||||
# 4-tuple rect => Divider, isinstance will give True for SubplotDivider
|
||||
assert type(grid.get_divider()) is Divider
|
||||
for i in range(3):
|
||||
im = grid[i].imshow(imdata, interpolation='none')
|
||||
grid.cbar_axes[0].colorbar(im)
|
||||
|
||||
|
||||
def test_image_grid_label_mode_invalid():
|
||||
fig = plt.figure()
|
||||
with pytest.raises(ValueError, match="'foo' is not a valid value for mode"):
|
||||
ImageGrid(fig, (0, 0, 1, 1), (2, 1), label_mode="foo")
|
||||
|
||||
|
||||
@image_comparison(['image_grid.png'],
|
||||
remove_text=True, style='mpl20',
|
||||
savefig_kwarg={'bbox_inches': 'tight'})
|
||||
def test_image_grid():
|
||||
# test that image grid works with bbox_inches=tight.
|
||||
im = np.arange(100).reshape((10, 10))
|
||||
|
||||
fig = plt.figure(1, (4, 4))
|
||||
grid = ImageGrid(fig, 111, nrows_ncols=(2, 2), axes_pad=0.1)
|
||||
assert grid.get_axes_pad() == (0.1, 0.1)
|
||||
for i in range(4):
|
||||
grid[i].imshow(im, interpolation='nearest')
|
||||
|
||||
|
||||
def test_gettightbbox():
|
||||
fig, ax = plt.subplots(figsize=(8, 6))
|
||||
|
||||
l, = ax.plot([1, 2, 3], [0, 1, 0])
|
||||
|
||||
ax_zoom = zoomed_inset_axes(ax, 4)
|
||||
ax_zoom.plot([1, 2, 3], [0, 1, 0])
|
||||
|
||||
mark_inset(ax, ax_zoom, loc1=1, loc2=3, fc="none", ec='0.3')
|
||||
|
||||
remove_ticks_and_titles(fig)
|
||||
bbox = fig.get_tightbbox(fig.canvas.get_renderer())
|
||||
np.testing.assert_array_almost_equal(bbox.extents,
|
||||
[-17.7, -13.9, 7.2, 5.4])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("click_on", ["big", "small"])
|
||||
@pytest.mark.parametrize("big_on_axes,small_on_axes", [
|
||||
("gca", "gca"),
|
||||
("host", "host"),
|
||||
("host", "parasite"),
|
||||
("parasite", "host"),
|
||||
("parasite", "parasite")
|
||||
])
|
||||
def test_picking_callbacks_overlap(big_on_axes, small_on_axes, click_on):
|
||||
"""Test pick events on normal, host or parasite axes."""
|
||||
# Two rectangles are drawn and "clicked on", a small one and a big one
|
||||
# enclosing the small one. The axis on which they are drawn as well as the
|
||||
# rectangle that is clicked on are varied.
|
||||
# In each case we expect that both rectangles are picked if we click on the
|
||||
# small one and only the big one is picked if we click on the big one.
|
||||
# Also tests picking on normal axes ("gca") as a control.
|
||||
big = plt.Rectangle((0.25, 0.25), 0.5, 0.5, picker=5)
|
||||
small = plt.Rectangle((0.4, 0.4), 0.2, 0.2, facecolor="r", picker=5)
|
||||
# Machinery for "receiving" events
|
||||
received_events = []
|
||||
def on_pick(event):
|
||||
received_events.append(event)
|
||||
plt.gcf().canvas.mpl_connect('pick_event', on_pick)
|
||||
# Shortcut
|
||||
rectangles_on_axes = (big_on_axes, small_on_axes)
|
||||
# Axes setup
|
||||
axes = {"gca": None, "host": None, "parasite": None}
|
||||
if "gca" in rectangles_on_axes:
|
||||
axes["gca"] = plt.gca()
|
||||
if "host" in rectangles_on_axes or "parasite" in rectangles_on_axes:
|
||||
axes["host"] = host_subplot(111)
|
||||
axes["parasite"] = axes["host"].twin()
|
||||
# Add rectangles to axes
|
||||
axes[big_on_axes].add_patch(big)
|
||||
axes[small_on_axes].add_patch(small)
|
||||
# Simulate picking with click mouse event
|
||||
if click_on == "big":
|
||||
click_axes = axes[big_on_axes]
|
||||
axes_coords = (0.3, 0.3)
|
||||
else:
|
||||
click_axes = axes[small_on_axes]
|
||||
axes_coords = (0.5, 0.5)
|
||||
# In reality mouse events never happen on parasite axes, only host axes
|
||||
if click_axes is axes["parasite"]:
|
||||
click_axes = axes["host"]
|
||||
(x, y) = click_axes.transAxes.transform(axes_coords)
|
||||
m = MouseEvent("button_press_event", click_axes.get_figure(root=True).canvas, x, y,
|
||||
button=1)
|
||||
click_axes.pick(m)
|
||||
# Checks
|
||||
expected_n_events = 2 if click_on == "small" else 1
|
||||
assert len(received_events) == expected_n_events
|
||||
event_rects = [event.artist for event in received_events]
|
||||
assert big in event_rects
|
||||
if click_on == "small":
|
||||
assert small in event_rects
|
||||
|
||||
|
||||
@image_comparison(['anchored_artists.png'], remove_text=True, style='mpl20')
|
||||
def test_anchored_artists():
|
||||
fig, ax = plt.subplots(figsize=(3, 3))
|
||||
ada = AnchoredDrawingArea(40, 20, 0, 0, loc='upper right', pad=0.,
|
||||
frameon=False)
|
||||
p1 = Circle((10, 10), 10)
|
||||
ada.drawing_area.add_artist(p1)
|
||||
p2 = Circle((30, 10), 5, fc="r")
|
||||
ada.drawing_area.add_artist(p2)
|
||||
ax.add_artist(ada)
|
||||
|
||||
box = AnchoredAuxTransformBox(ax.transData, loc='upper left')
|
||||
el = Ellipse((0, 0), width=0.1, height=0.4, angle=30, color='cyan')
|
||||
box.drawing_area.add_artist(el)
|
||||
ax.add_artist(box)
|
||||
|
||||
# This block used to test the AnchoredEllipse class, but that was removed. The block
|
||||
# remains, though it duplicates the above ellipse, so that the test image doesn't
|
||||
# need to be regenerated.
|
||||
box = AnchoredAuxTransformBox(ax.transData, loc='lower left', frameon=True,
|
||||
pad=0.5, borderpad=0.4)
|
||||
el = Ellipse((0, 0), width=0.1, height=0.25, angle=-60)
|
||||
box.drawing_area.add_artist(el)
|
||||
ax.add_artist(box)
|
||||
|
||||
asb = AnchoredSizeBar(ax.transData, 0.2, r"0.2 units", loc='lower right',
|
||||
pad=0.3, borderpad=0.4, sep=4, fill_bar=True,
|
||||
frameon=False, label_top=True, prop={'size': 20},
|
||||
size_vertical=0.05, color='green')
|
||||
ax.add_artist(asb)
|
||||
|
||||
|
||||
def test_hbox_divider():
|
||||
arr1 = np.arange(20).reshape((4, 5))
|
||||
arr2 = np.arange(20).reshape((5, 4))
|
||||
|
||||
fig, (ax1, ax2) = plt.subplots(1, 2)
|
||||
ax1.imshow(arr1)
|
||||
ax2.imshow(arr2)
|
||||
|
||||
pad = 0.5 # inches.
|
||||
divider = HBoxDivider(
|
||||
fig, 111, # Position of combined axes.
|
||||
horizontal=[Size.AxesX(ax1), Size.Fixed(pad), Size.AxesX(ax2)],
|
||||
vertical=[Size.AxesY(ax1), Size.Scaled(1), Size.AxesY(ax2)])
|
||||
ax1.set_axes_locator(divider.new_locator(0))
|
||||
ax2.set_axes_locator(divider.new_locator(2))
|
||||
|
||||
fig.canvas.draw()
|
||||
p1 = ax1.get_position()
|
||||
p2 = ax2.get_position()
|
||||
assert p1.height == p2.height
|
||||
assert p2.width / p1.width == pytest.approx((4 / 5) ** 2)
|
||||
|
||||
|
||||
def test_vbox_divider():
|
||||
arr1 = np.arange(20).reshape((4, 5))
|
||||
arr2 = np.arange(20).reshape((5, 4))
|
||||
|
||||
fig, (ax1, ax2) = plt.subplots(1, 2)
|
||||
ax1.imshow(arr1)
|
||||
ax2.imshow(arr2)
|
||||
|
||||
pad = 0.5 # inches.
|
||||
divider = VBoxDivider(
|
||||
fig, 111, # Position of combined axes.
|
||||
horizontal=[Size.AxesX(ax1), Size.Scaled(1), Size.AxesX(ax2)],
|
||||
vertical=[Size.AxesY(ax1), Size.Fixed(pad), Size.AxesY(ax2)])
|
||||
ax1.set_axes_locator(divider.new_locator(0))
|
||||
ax2.set_axes_locator(divider.new_locator(2))
|
||||
|
||||
fig.canvas.draw()
|
||||
p1 = ax1.get_position()
|
||||
p2 = ax2.get_position()
|
||||
assert p1.width == p2.width
|
||||
assert p1.height / p2.height == pytest.approx((4 / 5) ** 2)
|
||||
|
||||
|
||||
def test_axes_class_tuple():
|
||||
fig = plt.figure()
|
||||
axes_class = (mpl_toolkits.axes_grid1.mpl_axes.Axes, {})
|
||||
gr = AxesGrid(fig, 111, nrows_ncols=(1, 1), axes_class=axes_class)
|
||||
|
||||
|
||||
def test_grid_axes_lists():
|
||||
"""Test Grid axes_all, axes_row and axes_column relationship."""
|
||||
fig = plt.figure()
|
||||
grid = Grid(fig, 111, (2, 3), direction="row")
|
||||
assert_array_equal(grid, grid.axes_all)
|
||||
assert_array_equal(grid.axes_row, np.transpose(grid.axes_column))
|
||||
assert_array_equal(grid, np.ravel(grid.axes_row), "row")
|
||||
assert grid.get_geometry() == (2, 3)
|
||||
grid = Grid(fig, 111, (2, 3), direction="column")
|
||||
assert_array_equal(grid, np.ravel(grid.axes_column), "column")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('direction', ('row', 'column'))
|
||||
def test_grid_axes_position(direction):
|
||||
"""Test positioning of the axes in Grid."""
|
||||
fig = plt.figure()
|
||||
grid = Grid(fig, 111, (2, 2), direction=direction)
|
||||
loc = [ax.get_axes_locator() for ax in np.ravel(grid.axes_row)]
|
||||
# Test nx.
|
||||
assert loc[1].args[0] > loc[0].args[0]
|
||||
assert loc[0].args[0] == loc[2].args[0]
|
||||
assert loc[3].args[0] == loc[1].args[0]
|
||||
# Test ny.
|
||||
assert loc[2].args[1] < loc[0].args[1]
|
||||
assert loc[0].args[1] == loc[1].args[1]
|
||||
assert loc[3].args[1] == loc[2].args[1]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('rect, ngrids, error, message', (
|
||||
((1, 1), None, TypeError, "Incorrect rect format"),
|
||||
(111, -1, ValueError, "ngrids must be positive"),
|
||||
(111, 7, ValueError, "ngrids must be positive"),
|
||||
))
|
||||
def test_grid_errors(rect, ngrids, error, message):
|
||||
fig = plt.figure()
|
||||
with pytest.raises(error, match=message):
|
||||
Grid(fig, rect, (2, 3), ngrids=ngrids)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('anchor, error, message', (
|
||||
(None, TypeError, "anchor must be str"),
|
||||
("CC", ValueError, "'CC' is not a valid value for anchor"),
|
||||
((1, 1, 1), TypeError, "anchor must be str"),
|
||||
))
|
||||
def test_divider_errors(anchor, error, message):
|
||||
fig = plt.figure()
|
||||
with pytest.raises(error, match=message):
|
||||
Divider(fig, [0, 0, 1, 1], [Size.Fixed(1)], [Size.Fixed(1)],
|
||||
anchor=anchor)
|
||||
|
||||
|
||||
@check_figures_equal(extensions=["png"])
|
||||
def test_mark_inset_unstales_viewlim(fig_test, fig_ref):
|
||||
inset, full = fig_test.subplots(1, 2)
|
||||
full.plot([0, 5], [0, 5])
|
||||
inset.set(xlim=(1, 2), ylim=(1, 2))
|
||||
# Check that mark_inset unstales full's viewLim before drawing the marks.
|
||||
mark_inset(full, inset, 1, 4)
|
||||
|
||||
inset, full = fig_ref.subplots(1, 2)
|
||||
full.plot([0, 5], [0, 5])
|
||||
inset.set(xlim=(1, 2), ylim=(1, 2))
|
||||
mark_inset(full, inset, 1, 4)
|
||||
# Manually unstale the full's viewLim.
|
||||
fig_ref.canvas.draw()
|
||||
|
||||
|
||||
def test_auto_adjustable():
|
||||
fig = plt.figure()
|
||||
ax = fig.add_axes([0, 0, 1, 1])
|
||||
pad = 0.1
|
||||
make_axes_area_auto_adjustable(ax, pad=pad)
|
||||
fig.canvas.draw()
|
||||
tbb = ax.get_tightbbox()
|
||||
assert tbb.x0 == pytest.approx(pad * fig.dpi)
|
||||
assert tbb.x1 == pytest.approx(fig.bbox.width - pad * fig.dpi)
|
||||
assert tbb.y0 == pytest.approx(pad * fig.dpi)
|
||||
assert tbb.y1 == pytest.approx(fig.bbox.height - pad * fig.dpi)
|
||||
|
||||
|
||||
# Update style when regenerating the test image
|
||||
@image_comparison(['rgb_axes.png'], remove_text=True,
|
||||
style=('classic', '_classic_test_patch'))
|
||||
def test_rgb_axes():
|
||||
fig = plt.figure()
|
||||
ax = RGBAxes(fig, (0.1, 0.1, 0.8, 0.8), pad=0.1)
|
||||
rng = np.random.default_rng(19680801)
|
||||
r = rng.random((5, 5))
|
||||
g = rng.random((5, 5))
|
||||
b = rng.random((5, 5))
|
||||
ax.imshow_rgb(r, g, b, interpolation='none')
|
||||
|
||||
|
||||
# The original version of this test relied on mpl_toolkits's slightly different
|
||||
# colorbar implementation; moving to matplotlib's own colorbar implementation
|
||||
# caused the small image comparison error.
|
||||
@image_comparison(['imagegrid_cbar_mode.png'],
|
||||
remove_text=True, style='mpl20', tol=0.3)
|
||||
def test_imagegrid_cbar_mode_edge():
|
||||
arr = np.arange(16).reshape((4, 4))
|
||||
|
||||
fig = plt.figure(figsize=(18, 9))
|
||||
|
||||
positions = (241, 242, 243, 244, 245, 246, 247, 248)
|
||||
directions = ['row']*4 + ['column']*4
|
||||
cbar_locations = ['left', 'right', 'top', 'bottom']*2
|
||||
|
||||
for position, direction, location in zip(
|
||||
positions, directions, cbar_locations):
|
||||
grid = ImageGrid(fig, position,
|
||||
nrows_ncols=(2, 2),
|
||||
direction=direction,
|
||||
cbar_location=location,
|
||||
cbar_size='20%',
|
||||
cbar_mode='edge')
|
||||
ax1, ax2, ax3, ax4 = grid
|
||||
|
||||
ax1.imshow(arr, cmap='nipy_spectral')
|
||||
ax2.imshow(arr.T, cmap='hot')
|
||||
ax3.imshow(np.hypot(arr, arr.T), cmap='jet')
|
||||
ax4.imshow(np.arctan2(arr, arr.T), cmap='hsv')
|
||||
|
||||
# In each row/column, the "first" colorbars must be overwritten by the
|
||||
# "second" ones. To achieve this, clear out the axes first.
|
||||
for ax in grid:
|
||||
ax.cax.cla()
|
||||
cb = ax.cax.colorbar(ax.images[0])
|
||||
|
||||
|
||||
def test_imagegrid():
|
||||
fig = plt.figure()
|
||||
grid = ImageGrid(fig, 111, nrows_ncols=(1, 1))
|
||||
ax = grid[0]
|
||||
im = ax.imshow([[1, 2]], norm=mpl.colors.LogNorm())
|
||||
cb = ax.cax.colorbar(im)
|
||||
assert isinstance(cb.locator, mticker.LogLocator)
|
||||
|
||||
|
||||
def test_removal():
|
||||
import matplotlib.pyplot as plt
|
||||
import mpl_toolkits.axisartist as AA
|
||||
fig = plt.figure()
|
||||
ax = host_subplot(111, axes_class=AA.Axes, figure=fig)
|
||||
col = ax.fill_between(range(5), 0, range(5))
|
||||
fig.canvas.draw()
|
||||
col.remove()
|
||||
fig.canvas.draw()
|
||||
|
||||
|
||||
@image_comparison(['anchored_locator_base_call.png'], style="mpl20")
|
||||
def test_anchored_locator_base_call():
|
||||
fig = plt.figure(figsize=(3, 3))
|
||||
fig1, fig2 = fig.subfigures(nrows=2, ncols=1)
|
||||
|
||||
ax = fig1.subplots()
|
||||
ax.set(aspect=1, xlim=(-15, 15), ylim=(-20, 5))
|
||||
ax.set(xticks=[], yticks=[])
|
||||
|
||||
Z = cbook.get_sample_data("axes_grid/bivariate_normal.npy")
|
||||
extent = (-3, 4, -4, 3)
|
||||
|
||||
axins = zoomed_inset_axes(ax, zoom=2, loc="upper left")
|
||||
axins.set(xticks=[], yticks=[])
|
||||
|
||||
axins.imshow(Z, extent=extent, origin="lower")
|
||||
|
||||
|
||||
def test_grid_with_axes_class_not_overriding_axis():
|
||||
Grid(plt.figure(), 111, (2, 2), axes_class=mpl.axes.Axes)
|
||||
RGBAxes(plt.figure(), 111, axes_class=mpl.axes.Axes)
|
||||
Reference in New Issue
Block a user