645 lines
22 KiB
Python
645 lines
22 KiB
Python
|
import collections
|
||
|
import platform
|
||
|
from unittest import mock
|
||
|
|
||
|
import numpy as np
|
||
|
import pytest
|
||
|
|
||
|
from matplotlib.testing.decorators import image_comparison
|
||
|
import matplotlib.pyplot as plt
|
||
|
import matplotlib as mpl
|
||
|
import matplotlib.transforms as mtransforms
|
||
|
import matplotlib.collections as mcollections
|
||
|
from matplotlib.legend_handler import HandlerTuple
|
||
|
import matplotlib.legend as mlegend
|
||
|
from matplotlib import rc_context
|
||
|
|
||
|
|
||
|
def test_legend_ordereddict():
|
||
|
# smoketest that ordereddict inputs work...
|
||
|
|
||
|
X = np.random.randn(10)
|
||
|
Y = np.random.randn(10)
|
||
|
labels = ['a'] * 5 + ['b'] * 5
|
||
|
colors = ['r'] * 5 + ['g'] * 5
|
||
|
|
||
|
fig, ax = plt.subplots()
|
||
|
for x, y, label, color in zip(X, Y, labels, colors):
|
||
|
ax.scatter(x, y, label=label, c=color)
|
||
|
|
||
|
handles, labels = ax.get_legend_handles_labels()
|
||
|
legend = collections.OrderedDict(zip(labels, handles))
|
||
|
ax.legend(legend.values(), legend.keys(),
|
||
|
loc='center left', bbox_to_anchor=(1, .5))
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_auto1'], remove_text=True)
|
||
|
def test_legend_auto1():
|
||
|
"""Test automatic legend placement"""
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(111)
|
||
|
x = np.arange(100)
|
||
|
ax.plot(x, 50 - x, 'o', label='y=1')
|
||
|
ax.plot(x, x - 50, 'o', label='y=-1')
|
||
|
ax.legend(loc='best')
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_auto2'], remove_text=True)
|
||
|
def test_legend_auto2():
|
||
|
"""Test automatic legend placement"""
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(111)
|
||
|
x = np.arange(100)
|
||
|
b1 = ax.bar(x, x, align='edge', color='m')
|
||
|
b2 = ax.bar(x, x[::-1], align='edge', color='g')
|
||
|
ax.legend([b1[0], b2[0]], ['up', 'down'], loc='best')
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_auto3'])
|
||
|
def test_legend_auto3():
|
||
|
"""Test automatic legend placement"""
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(111)
|
||
|
x = [0.9, 0.1, 0.1, 0.9, 0.9, 0.5]
|
||
|
y = [0.95, 0.95, 0.05, 0.05, 0.5, 0.5]
|
||
|
ax.plot(x, y, 'o-', label='line')
|
||
|
ax.set_xlim(0.0, 1.0)
|
||
|
ax.set_ylim(0.0, 1.0)
|
||
|
ax.legend(loc='best')
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_various_labels'], remove_text=True)
|
||
|
def test_various_labels():
|
||
|
# tests all sorts of label types
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(121)
|
||
|
ax.plot(np.arange(4), 'o', label=1)
|
||
|
ax.plot(np.linspace(4, 4.1), 'o', label='Développés')
|
||
|
ax.plot(np.arange(4, 1, -1), 'o', label='__nolegend__')
|
||
|
ax.legend(numpoints=1, loc='best')
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_labels_first.png'], remove_text=True)
|
||
|
def test_labels_first():
|
||
|
# test labels to left of markers
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(111)
|
||
|
ax.plot(np.arange(10), '-o', label=1)
|
||
|
ax.plot(np.ones(10)*5, ':x', label="x")
|
||
|
ax.plot(np.arange(20, 10, -1), 'd', label="diamond")
|
||
|
ax.legend(loc='best', markerfirst=False)
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_multiple_keys.png'], remove_text=True)
|
||
|
def test_multiple_keys():
|
||
|
# test legend entries with multiple keys
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(111)
|
||
|
p1, = ax.plot([1, 2, 3], '-o')
|
||
|
p2, = ax.plot([2, 3, 4], '-x')
|
||
|
p3, = ax.plot([3, 4, 5], '-d')
|
||
|
ax.legend([(p1, p2), (p2, p1), p3], ['two keys', 'pad=0', 'one key'],
|
||
|
numpoints=1,
|
||
|
handler_map={(p1, p2): HandlerTuple(ndivide=None),
|
||
|
(p2, p1): HandlerTuple(ndivide=None, pad=0)})
|
||
|
|
||
|
|
||
|
@image_comparison(['rgba_alpha.png'], remove_text=True,
|
||
|
tol=0 if platform.machine() == 'x86_64' else 0.01)
|
||
|
def test_alpha_rgba():
|
||
|
fig, ax = plt.subplots(1, 1)
|
||
|
ax.plot(range(10), lw=5)
|
||
|
leg = plt.legend(['Longlabel that will go away'], loc='center')
|
||
|
leg.legendPatch.set_facecolor([1, 0, 0, 0.5])
|
||
|
|
||
|
|
||
|
@image_comparison(['rcparam_alpha.png'], remove_text=True,
|
||
|
tol=0 if platform.machine() == 'x86_64' else 0.01)
|
||
|
def test_alpha_rcparam():
|
||
|
fig, ax = plt.subplots(1, 1)
|
||
|
ax.plot(range(10), lw=5)
|
||
|
with mpl.rc_context(rc={'legend.framealpha': .75}):
|
||
|
leg = plt.legend(['Longlabel that will go away'], loc='center')
|
||
|
# this alpha is going to be over-ridden by the rcparam with
|
||
|
# sets the alpha of the patch to be non-None which causes the alpha
|
||
|
# value of the face color to be discarded. This behavior may not be
|
||
|
# ideal, but it is what it is and we should keep track of it changing
|
||
|
leg.legendPatch.set_facecolor([1, 0, 0, 0.5])
|
||
|
|
||
|
|
||
|
@image_comparison(['fancy'], remove_text=True)
|
||
|
def test_fancy():
|
||
|
# using subplot triggers some offsetbox functionality untested elsewhere
|
||
|
plt.subplot(121)
|
||
|
plt.scatter(np.arange(10), np.arange(10, 0, -1), label='XX\nXX')
|
||
|
plt.plot([5] * 10, 'o--', label='XX')
|
||
|
plt.errorbar(np.arange(10), np.arange(10), xerr=0.5,
|
||
|
yerr=0.5, label='XX')
|
||
|
plt.legend(loc="center left", bbox_to_anchor=[1.0, 0.5],
|
||
|
ncol=2, shadow=True, title="My legend", numpoints=1)
|
||
|
|
||
|
|
||
|
@image_comparison(['framealpha'], remove_text=True,
|
||
|
tol=0 if platform.machine() == 'x86_64' else 0.02)
|
||
|
def test_framealpha():
|
||
|
x = np.linspace(1, 100, 100)
|
||
|
y = x
|
||
|
plt.plot(x, y, label='mylabel', lw=10)
|
||
|
plt.legend(framealpha=0.5)
|
||
|
|
||
|
|
||
|
@image_comparison(['scatter_rc3', 'scatter_rc1'], remove_text=True)
|
||
|
def test_rc():
|
||
|
# using subplot triggers some offsetbox functionality untested elsewhere
|
||
|
plt.figure()
|
||
|
ax = plt.subplot(121)
|
||
|
ax.scatter(np.arange(10), np.arange(10, 0, -1), label='three')
|
||
|
ax.legend(loc="center left", bbox_to_anchor=[1.0, 0.5],
|
||
|
title="My legend")
|
||
|
|
||
|
mpl.rcParams['legend.scatterpoints'] = 1
|
||
|
plt.figure()
|
||
|
ax = plt.subplot(121)
|
||
|
ax.scatter(np.arange(10), np.arange(10, 0, -1), label='one')
|
||
|
ax.legend(loc="center left", bbox_to_anchor=[1.0, 0.5],
|
||
|
title="My legend")
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_expand'], remove_text=True)
|
||
|
def test_legend_expand():
|
||
|
"""Test expand mode"""
|
||
|
legend_modes = [None, "expand"]
|
||
|
fig, axes_list = plt.subplots(len(legend_modes), 1)
|
||
|
x = np.arange(100)
|
||
|
for ax, mode in zip(axes_list, legend_modes):
|
||
|
ax.plot(x, 50 - x, 'o', label='y=1')
|
||
|
l1 = ax.legend(loc='upper left', mode=mode)
|
||
|
ax.add_artist(l1)
|
||
|
ax.plot(x, x - 50, 'o', label='y=-1')
|
||
|
l2 = ax.legend(loc='right', mode=mode)
|
||
|
ax.add_artist(l2)
|
||
|
ax.legend(loc='lower left', mode=mode, ncol=2)
|
||
|
|
||
|
|
||
|
@image_comparison(['hatching'], remove_text=True, style='default')
|
||
|
def test_hatching():
|
||
|
# Remove this line when this test image is regenerated.
|
||
|
plt.rcParams['text.kerning_factor'] = 6
|
||
|
|
||
|
fig, ax = plt.subplots()
|
||
|
|
||
|
# Patches
|
||
|
patch = plt.Rectangle((0, 0), 0.3, 0.3, hatch='xx',
|
||
|
label='Patch\ndefault color\nfilled')
|
||
|
ax.add_patch(patch)
|
||
|
patch = plt.Rectangle((0.33, 0), 0.3, 0.3, hatch='||', edgecolor='C1',
|
||
|
label='Patch\nexplicit color\nfilled')
|
||
|
ax.add_patch(patch)
|
||
|
patch = plt.Rectangle((0, 0.4), 0.3, 0.3, hatch='xx', fill=False,
|
||
|
label='Patch\ndefault color\nunfilled')
|
||
|
ax.add_patch(patch)
|
||
|
patch = plt.Rectangle((0.33, 0.4), 0.3, 0.3, hatch='||', fill=False,
|
||
|
edgecolor='C1',
|
||
|
label='Patch\nexplicit color\nunfilled')
|
||
|
ax.add_patch(patch)
|
||
|
|
||
|
# Paths
|
||
|
ax.fill_between([0, .15, .3], [.8, .8, .8], [.9, 1.0, .9],
|
||
|
hatch='+', label='Path\ndefault color')
|
||
|
ax.fill_between([.33, .48, .63], [.8, .8, .8], [.9, 1.0, .9],
|
||
|
hatch='+', edgecolor='C2', label='Path\nexplicit color')
|
||
|
|
||
|
ax.set_xlim(-0.01, 1.1)
|
||
|
ax.set_ylim(-0.01, 1.1)
|
||
|
ax.legend(handlelength=4, handleheight=4)
|
||
|
|
||
|
|
||
|
def test_legend_remove():
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(1, 1, 1)
|
||
|
lines = ax.plot(range(10))
|
||
|
leg = fig.legend(lines, "test")
|
||
|
leg.remove()
|
||
|
assert fig.legends == []
|
||
|
leg = ax.legend("test")
|
||
|
leg.remove()
|
||
|
assert ax.get_legend() is None
|
||
|
|
||
|
|
||
|
class TestLegendFunction:
|
||
|
# Tests the legend function on the Axes and pyplot.
|
||
|
def test_legend_handle_label(self):
|
||
|
lines = plt.plot(range(10))
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
plt.legend(lines, ['hello world'])
|
||
|
Legend.assert_called_with(plt.gca(), lines, ['hello world'])
|
||
|
|
||
|
def test_legend_handles_only(self):
|
||
|
lines = plt.plot(range(10))
|
||
|
with pytest.raises(TypeError, match='but found an Artist'):
|
||
|
# a single arg is interpreted as labels
|
||
|
# it's a common error to just pass handles
|
||
|
plt.legend(lines)
|
||
|
|
||
|
def test_legend_no_args(self):
|
||
|
lines = plt.plot(range(10), label='hello world')
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
plt.legend()
|
||
|
Legend.assert_called_with(plt.gca(), lines, ['hello world'])
|
||
|
|
||
|
def test_legend_label_args(self):
|
||
|
lines = plt.plot(range(10), label='hello world')
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
plt.legend(['foobar'])
|
||
|
Legend.assert_called_with(plt.gca(), lines, ['foobar'])
|
||
|
|
||
|
def test_legend_three_args(self):
|
||
|
lines = plt.plot(range(10), label='hello world')
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
plt.legend(lines, ['foobar'], loc='right')
|
||
|
Legend.assert_called_with(plt.gca(), lines, ['foobar'], loc='right')
|
||
|
|
||
|
def test_legend_handler_map(self):
|
||
|
lines = plt.plot(range(10), label='hello world')
|
||
|
with mock.patch('matplotlib.legend.'
|
||
|
'_get_legend_handles_labels') as handles_labels:
|
||
|
handles_labels.return_value = lines, ['hello world']
|
||
|
plt.legend(handler_map={'1': 2})
|
||
|
handles_labels.assert_called_with([plt.gca()], {'1': 2})
|
||
|
|
||
|
def test_kwargs(self):
|
||
|
fig, ax = plt.subplots(1, 1)
|
||
|
th = np.linspace(0, 2*np.pi, 1024)
|
||
|
lns, = ax.plot(th, np.sin(th), label='sin', lw=5)
|
||
|
lnc, = ax.plot(th, np.cos(th), label='cos', lw=5)
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
ax.legend(labels=('a', 'b'), handles=(lnc, lns))
|
||
|
Legend.assert_called_with(ax, (lnc, lns), ('a', 'b'))
|
||
|
|
||
|
def test_warn_args_kwargs(self):
|
||
|
fig, ax = plt.subplots(1, 1)
|
||
|
th = np.linspace(0, 2*np.pi, 1024)
|
||
|
lns, = ax.plot(th, np.sin(th), label='sin', lw=5)
|
||
|
lnc, = ax.plot(th, np.cos(th), label='cos', lw=5)
|
||
|
with pytest.warns(UserWarning) as record:
|
||
|
ax.legend((lnc, lns), labels=('a', 'b'))
|
||
|
assert len(record) == 1
|
||
|
assert str(record[0].message) == (
|
||
|
"You have mixed positional and keyword arguments, some input may "
|
||
|
"be discarded.")
|
||
|
|
||
|
def test_parasite(self):
|
||
|
from mpl_toolkits.axes_grid1 import host_subplot
|
||
|
|
||
|
host = host_subplot(111)
|
||
|
par = host.twinx()
|
||
|
|
||
|
p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
|
||
|
p2, = par.plot([0, 1, 2], [0, 3, 2], label="Temperature")
|
||
|
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
plt.legend()
|
||
|
Legend.assert_called_with(host, [p1, p2], ['Density', 'Temperature'])
|
||
|
|
||
|
|
||
|
class TestLegendFigureFunction:
|
||
|
# Tests the legend function for figure
|
||
|
def test_legend_handle_label(self):
|
||
|
fig, ax = plt.subplots()
|
||
|
lines = ax.plot(range(10))
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
fig.legend(lines, ['hello world'])
|
||
|
Legend.assert_called_with(fig, lines, ['hello world'],
|
||
|
bbox_transform=fig.transFigure)
|
||
|
|
||
|
def test_legend_no_args(self):
|
||
|
fig, ax = plt.subplots()
|
||
|
lines = ax.plot(range(10), label='hello world')
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
fig.legend()
|
||
|
Legend.assert_called_with(fig, lines, ['hello world'],
|
||
|
bbox_transform=fig.transFigure)
|
||
|
|
||
|
def test_legend_label_arg(self):
|
||
|
fig, ax = plt.subplots()
|
||
|
lines = ax.plot(range(10))
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
fig.legend(['foobar'])
|
||
|
Legend.assert_called_with(fig, lines, ['foobar'],
|
||
|
bbox_transform=fig.transFigure)
|
||
|
|
||
|
def test_legend_label_three_args(self):
|
||
|
fig, ax = plt.subplots()
|
||
|
lines = ax.plot(range(10))
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
fig.legend(lines, ['foobar'], 'right')
|
||
|
Legend.assert_called_with(fig, lines, ['foobar'], 'right',
|
||
|
bbox_transform=fig.transFigure)
|
||
|
|
||
|
def test_legend_label_three_args_pluskw(self):
|
||
|
# test that third argument and loc= called together give
|
||
|
# Exception
|
||
|
fig, ax = plt.subplots()
|
||
|
lines = ax.plot(range(10))
|
||
|
with pytest.raises(Exception):
|
||
|
fig.legend(lines, ['foobar'], 'right', loc='left')
|
||
|
|
||
|
def test_legend_kw_args(self):
|
||
|
fig, axs = plt.subplots(1, 2)
|
||
|
lines = axs[0].plot(range(10))
|
||
|
lines2 = axs[1].plot(np.arange(10) * 2.)
|
||
|
with mock.patch('matplotlib.legend.Legend') as Legend:
|
||
|
fig.legend(loc='right', labels=('a', 'b'), handles=(lines, lines2))
|
||
|
Legend.assert_called_with(
|
||
|
fig, (lines, lines2), ('a', 'b'), loc='right',
|
||
|
bbox_transform=fig.transFigure)
|
||
|
|
||
|
def test_warn_args_kwargs(self):
|
||
|
fig, axs = plt.subplots(1, 2)
|
||
|
lines = axs[0].plot(range(10))
|
||
|
lines2 = axs[1].plot(np.arange(10) * 2.)
|
||
|
with pytest.warns(UserWarning) as record:
|
||
|
fig.legend((lines, lines2), labels=('a', 'b'))
|
||
|
assert len(record) == 1
|
||
|
assert str(record[0].message) == (
|
||
|
"You have mixed positional and keyword arguments, some input may "
|
||
|
"be discarded.")
|
||
|
|
||
|
|
||
|
@image_comparison(['legend_stackplot.png'])
|
||
|
def test_legend_stackplot():
|
||
|
"""Test legend for PolyCollection using stackplot."""
|
||
|
# related to #1341, #1943, and PR #3303
|
||
|
fig = plt.figure()
|
||
|
ax = fig.add_subplot(111)
|
||
|
x = np.linspace(0, 10, 10)
|
||
|
y1 = 1.0 * x
|
||
|
y2 = 2.0 * x + 1
|
||
|
y3 = 3.0 * x + 2
|
||
|
ax.stackplot(x, y1, y2, y3, labels=['y1', 'y2', 'y3'])
|
||
|
ax.set_xlim((0, 10))
|
||
|
ax.set_ylim((0, 70))
|
||
|
ax.legend(loc='best')
|
||
|
|
||
|
|
||
|
def test_cross_figure_patch_legend():
|
||
|
fig, ax = plt.subplots()
|
||
|
fig2, ax2 = plt.subplots()
|
||
|
|
||
|
brs = ax.bar(range(3), range(3))
|
||
|
fig2.legend(brs, 'foo')
|
||
|
|
||
|
|
||
|
def test_nanscatter():
|
||
|
fig, ax = plt.subplots()
|
||
|
|
||
|
h = ax.scatter([np.nan], [np.nan], marker="o",
|
||
|
facecolor="r", edgecolor="r", s=3)
|
||
|
|
||
|
ax.legend([h], ["scatter"])
|
||
|
|
||
|
fig, ax = plt.subplots()
|
||
|
for color in ['red', 'green', 'blue']:
|
||
|
n = 750
|
||
|
x, y = np.random.rand(2, n)
|
||
|
scale = 200.0 * np.random.rand(n)
|
||
|
ax.scatter(x, y, c=color, s=scale, label=color,
|
||
|
alpha=0.3, edgecolors='none')
|
||
|
|
||
|
ax.legend()
|
||
|
ax.grid(True)
|
||
|
|
||
|
|
||
|
def test_legend_repeatcheckok():
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.scatter(0.0, 1.0, color='k', marker='o', label='test')
|
||
|
ax.scatter(0.5, 0.0, color='r', marker='v', label='test')
|
||
|
ax.legend()
|
||
|
hand, lab = mlegend._get_legend_handles_labels([ax])
|
||
|
assert len(lab) == 2
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.scatter(0.0, 1.0, color='k', marker='o', label='test')
|
||
|
ax.scatter(0.5, 0.0, color='k', marker='v', label='test')
|
||
|
ax.legend()
|
||
|
hand, lab = mlegend._get_legend_handles_labels([ax])
|
||
|
assert len(lab) == 2
|
||
|
|
||
|
|
||
|
@image_comparison(['not_covering_scatter.png'])
|
||
|
def test_not_covering_scatter():
|
||
|
colors = ['b', 'g', 'r']
|
||
|
|
||
|
for n in range(3):
|
||
|
plt.scatter([n], [n], color=colors[n])
|
||
|
|
||
|
plt.legend(['foo', 'foo', 'foo'], loc='best')
|
||
|
plt.gca().set_xlim(-0.5, 2.2)
|
||
|
plt.gca().set_ylim(-0.5, 2.2)
|
||
|
|
||
|
|
||
|
@image_comparison(['not_covering_scatter_transform.png'])
|
||
|
def test_not_covering_scatter_transform():
|
||
|
# Offsets point to top left, the default auto position
|
||
|
offset = mtransforms.Affine2D().translate(-20, 20)
|
||
|
x = np.linspace(0, 30, 1000)
|
||
|
plt.plot(x, x)
|
||
|
|
||
|
plt.scatter([20], [10], transform=offset + plt.gca().transData)
|
||
|
|
||
|
plt.legend(['foo', 'bar'], loc='best')
|
||
|
|
||
|
|
||
|
def test_linecollection_scaled_dashes():
|
||
|
lines1 = [[(0, .5), (.5, 1)], [(.3, .6), (.2, .2)]]
|
||
|
lines2 = [[[0.7, .2], [.8, .4]], [[.5, .7], [.6, .1]]]
|
||
|
lines3 = [[[0.6, .2], [.8, .4]], [[.5, .7], [.1, .1]]]
|
||
|
lc1 = mcollections.LineCollection(lines1, linestyles="--", lw=3)
|
||
|
lc2 = mcollections.LineCollection(lines2, linestyles="-.")
|
||
|
lc3 = mcollections.LineCollection(lines3, linestyles=":", lw=.5)
|
||
|
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.add_collection(lc1)
|
||
|
ax.add_collection(lc2)
|
||
|
ax.add_collection(lc3)
|
||
|
|
||
|
leg = ax.legend([lc1, lc2, lc3], ["line1", "line2", 'line 3'])
|
||
|
h1, h2, h3 = leg.legendHandles
|
||
|
|
||
|
for oh, lh in zip((lc1, lc2, lc3), (h1, h2, h3)):
|
||
|
assert oh.get_linestyles()[0][1] == lh._dashSeq
|
||
|
assert oh.get_linestyles()[0][0] == lh._dashOffset
|
||
|
|
||
|
|
||
|
def test_handler_numpoints():
|
||
|
"""Test legend handler with numpoints <= 1."""
|
||
|
# related to #6921 and PR #8478
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(range(5), label='test')
|
||
|
ax.legend(numpoints=0.5)
|
||
|
|
||
|
|
||
|
def test_empty_bar_chart_with_legend():
|
||
|
"""Test legend when bar chart is empty with a label."""
|
||
|
# related to issue #13003. Calling plt.legend() should not
|
||
|
# raise an IndexError.
|
||
|
plt.bar([], [], label='test')
|
||
|
plt.legend()
|
||
|
|
||
|
|
||
|
def test_shadow_framealpha():
|
||
|
# Test if framealpha is activated when shadow is True
|
||
|
# and framealpha is not explicitly passed'''
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(range(100), label="test")
|
||
|
leg = ax.legend(shadow=True, facecolor='w')
|
||
|
assert leg.get_frame().get_alpha() == 1
|
||
|
|
||
|
|
||
|
def test_legend_title_empty():
|
||
|
# test that if we don't set the legend title, that
|
||
|
# it comes back as an empty string, and that it is not
|
||
|
# visible:
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(range(10))
|
||
|
leg = ax.legend()
|
||
|
assert leg.get_title().get_text() == ""
|
||
|
assert not leg.get_title().get_visible()
|
||
|
|
||
|
|
||
|
def test_legend_proper_window_extent():
|
||
|
# test that legend returns the expected extent under various dpi...
|
||
|
fig, ax = plt.subplots(dpi=100)
|
||
|
ax.plot(range(10), label='Aardvark')
|
||
|
leg = ax.legend()
|
||
|
x01 = leg.get_window_extent(fig.canvas.get_renderer()).x0
|
||
|
|
||
|
fig, ax = plt.subplots(dpi=200)
|
||
|
ax.plot(range(10), label='Aardvark')
|
||
|
leg = ax.legend()
|
||
|
x02 = leg.get_window_extent(fig.canvas.get_renderer()).x0
|
||
|
assert pytest.approx(x01*2, 0.1) == x02
|
||
|
|
||
|
|
||
|
def test_window_extent_cached_renderer():
|
||
|
fig, ax = plt.subplots(dpi=100)
|
||
|
ax.plot(range(10), label='Aardvark')
|
||
|
leg = ax.legend()
|
||
|
leg2 = fig.legend()
|
||
|
fig.canvas.draw()
|
||
|
# check that get_window_extent will use the cached renderer
|
||
|
leg.get_window_extent()
|
||
|
leg2.get_window_extent()
|
||
|
|
||
|
|
||
|
def test_legend_title_fontsize():
|
||
|
# test the title_fontsize kwarg
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(range(10))
|
||
|
leg = ax.legend(title='Aardvark', title_fontsize=22)
|
||
|
assert leg.get_title().get_fontsize() == 22
|
||
|
|
||
|
|
||
|
def test_legend_labelcolor_single():
|
||
|
# test labelcolor for a single color
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(np.arange(10), np.arange(10)*1, label='#1')
|
||
|
ax.plot(np.arange(10), np.arange(10)*2, label='#2')
|
||
|
ax.plot(np.arange(10), np.arange(10)*3, label='#3')
|
||
|
|
||
|
leg = ax.legend(labelcolor='red')
|
||
|
for text in leg.get_texts():
|
||
|
assert mpl.colors.same_color(text.get_color(), 'red')
|
||
|
|
||
|
|
||
|
def test_legend_labelcolor_list():
|
||
|
# test labelcolor for a list of colors
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(np.arange(10), np.arange(10)*1, label='#1')
|
||
|
ax.plot(np.arange(10), np.arange(10)*2, label='#2')
|
||
|
ax.plot(np.arange(10), np.arange(10)*3, label='#3')
|
||
|
|
||
|
leg = ax.legend(labelcolor=['r', 'g', 'b'])
|
||
|
for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
|
||
|
assert mpl.colors.same_color(text.get_color(), color)
|
||
|
|
||
|
|
||
|
def test_legend_labelcolor_linecolor():
|
||
|
# test the labelcolor for labelcolor='linecolor'
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(np.arange(10), np.arange(10)*1, label='#1', color='r')
|
||
|
ax.plot(np.arange(10), np.arange(10)*2, label='#2', color='g')
|
||
|
ax.plot(np.arange(10), np.arange(10)*3, label='#3', color='b')
|
||
|
|
||
|
leg = ax.legend(labelcolor='linecolor')
|
||
|
for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
|
||
|
assert mpl.colors.same_color(text.get_color(), color)
|
||
|
|
||
|
|
||
|
def test_legend_labelcolor_markeredgecolor():
|
||
|
# test the labelcolor for labelcolor='markeredgecolor'
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(np.arange(10), np.arange(10)*1, label='#1', markeredgecolor='r')
|
||
|
ax.plot(np.arange(10), np.arange(10)*2, label='#2', markeredgecolor='g')
|
||
|
ax.plot(np.arange(10), np.arange(10)*3, label='#3', markeredgecolor='b')
|
||
|
|
||
|
leg = ax.legend(labelcolor='markeredgecolor')
|
||
|
for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
|
||
|
assert mpl.colors.same_color(text.get_color(), color)
|
||
|
|
||
|
|
||
|
def test_legend_labelcolor_markerfacecolor():
|
||
|
# test the labelcolor for labelcolor='markerfacecolor'
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(np.arange(10), np.arange(10)*1, label='#1', markerfacecolor='r')
|
||
|
ax.plot(np.arange(10), np.arange(10)*2, label='#2', markerfacecolor='g')
|
||
|
ax.plot(np.arange(10), np.arange(10)*3, label='#3', markerfacecolor='b')
|
||
|
|
||
|
leg = ax.legend(labelcolor='markerfacecolor')
|
||
|
for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
|
||
|
assert mpl.colors.same_color(text.get_color(), color)
|
||
|
|
||
|
|
||
|
def test_get_set_draggable():
|
||
|
legend = plt.legend()
|
||
|
assert not legend.get_draggable()
|
||
|
legend.set_draggable(True)
|
||
|
assert legend.get_draggable()
|
||
|
legend.set_draggable(False)
|
||
|
assert not legend.get_draggable()
|
||
|
|
||
|
|
||
|
def test_alpha_handles():
|
||
|
x, n, hh = plt.hist([1, 2, 3], alpha=0.25, label='data', color='red')
|
||
|
legend = plt.legend()
|
||
|
for lh in legend.legendHandles:
|
||
|
lh.set_alpha(1.0)
|
||
|
assert lh.get_facecolor()[:-1] == hh[1].get_facecolor()[:-1]
|
||
|
assert lh.get_edgecolor()[:-1] == hh[1].get_edgecolor()[:-1]
|
||
|
|
||
|
|
||
|
def test_warn_big_data_best_loc():
|
||
|
fig, ax = plt.subplots()
|
||
|
fig.canvas.draw() # So that we can call draw_artist later.
|
||
|
for idx in range(1000):
|
||
|
ax.plot(np.arange(5000), label=idx)
|
||
|
with rc_context({'legend.loc': 'best'}):
|
||
|
legend = ax.legend()
|
||
|
with pytest.warns(UserWarning) as records:
|
||
|
fig.draw_artist(legend) # Don't bother drawing the lines -- it's slow.
|
||
|
# The _find_best_position method of Legend is called twice, duplicating
|
||
|
# the warning message.
|
||
|
assert len(records) == 2
|
||
|
for record in records:
|
||
|
assert str(record.message) == (
|
||
|
'Creating legend with loc="best" can be slow with large '
|
||
|
'amounts of data.')
|
||
|
|
||
|
|
||
|
def test_no_warn_big_data_when_loc_specified():
|
||
|
fig, ax = plt.subplots()
|
||
|
fig.canvas.draw()
|
||
|
for idx in range(1000):
|
||
|
ax.plot(np.arange(5000), label=idx)
|
||
|
legend = ax.legend('best')
|
||
|
fig.draw_artist(legend) # Check that no warning is emitted.
|