12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343 |
- import collections
- import platform
- from unittest import mock
- import warnings
- import numpy as np
- from numpy.testing import assert_allclose
- import pytest
- from matplotlib.testing.decorators import check_figures_equal, image_comparison
- from matplotlib.testing._markers import needs_usetex
- import matplotlib.pyplot as plt
- import matplotlib as mpl
- import matplotlib.patches as mpatches
- import matplotlib.transforms as mtransforms
- import matplotlib.collections as mcollections
- import matplotlib.lines as mlines
- from matplotlib.legend_handler import HandlerTuple
- import matplotlib.legend as mlegend
- from matplotlib import _api, rc_context
- from matplotlib.font_manager import FontProperties
- 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, ax = plt.subplots()
- 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, ax = plt.subplots()
- 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, ax = plt.subplots()
- 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')
- def test_legend_auto4():
- """
- Check that the legend location with automatic placement is the same,
- whatever the histogram type is. Related to issue #9580.
- """
- # NB: barstacked is pointless with a single dataset.
- fig, axs = plt.subplots(ncols=3, figsize=(6.4, 2.4))
- leg_bboxes = []
- for ax, ht in zip(axs.flat, ('bar', 'step', 'stepfilled')):
- ax.set_title(ht)
- # A high bar on the left but an even higher one on the right.
- ax.hist([0] + 5*[9], bins=range(10), label="Legend", histtype=ht)
- leg = ax.legend(loc="best")
- fig.canvas.draw()
- leg_bboxes.append(
- leg.get_window_extent().transformed(ax.transAxes.inverted()))
- # The histogram type "bar" is assumed to be the correct reference.
- assert_allclose(leg_bboxes[1].bounds, leg_bboxes[0].bounds)
- assert_allclose(leg_bboxes[2].bounds, leg_bboxes[0].bounds)
- def test_legend_auto5():
- """
- Check that the automatic placement handle a rather complex
- case with non rectangular patch. Related to issue #9580.
- """
- fig, axs = plt.subplots(ncols=2, figsize=(9.6, 4.8))
- leg_bboxes = []
- for ax, loc in zip(axs.flat, ("center", "best")):
- # An Ellipse patch at the top, a U-shaped Polygon patch at the
- # bottom and a ring-like Wedge patch: the correct placement of
- # the legend should be in the center.
- for _patch in [
- mpatches.Ellipse(
- xy=(0.5, 0.9), width=0.8, height=0.2, fc="C1"),
- mpatches.Polygon(np.array([
- [0, 1], [0, 0], [1, 0], [1, 1], [0.9, 1.0], [0.9, 0.1],
- [0.1, 0.1], [0.1, 1.0], [0.1, 1.0]]), fc="C1"),
- mpatches.Wedge((0.5, 0.5), 0.5, 0, 360, width=0.05, fc="C0")
- ]:
- ax.add_patch(_patch)
- ax.plot([0.1, 0.9], [0.9, 0.9], label="A segment") # sthg to label
- leg = ax.legend(loc=loc)
- fig.canvas.draw()
- leg_bboxes.append(
- leg.get_window_extent().transformed(ax.transAxes.inverted()))
- assert_allclose(leg_bboxes[1].bounds, leg_bboxes[0].bounds)
- @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')
- def test_legend_label_with_leading_underscore():
- """
- Test that artists with labels starting with an underscore are not added to
- the legend, and that a warning is issued if one tries to add them
- explicitly.
- """
- fig, ax = plt.subplots()
- line, = ax.plot([0, 1], label='_foo')
- with pytest.warns(_api.MatplotlibDeprecationWarning, match="with an underscore"):
- legend = ax.legend(handles=[line])
- assert len(legend.legend_handles) == 0
- @image_comparison(['legend_labels_first.png'], remove_text=True)
- def test_labels_first():
- # test labels to left of markers
- fig, ax = plt.subplots()
- 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, ax = plt.subplots()
- 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()
- 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()
- 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, tol=0.05)
- def test_fancy():
- # Tolerance caused by changing default shadow "shade" from 0.3 to 1 - 0.7 =
- # 0.30000000000000004
- # using subplot triggers some offsetbox functionality untested elsewhere
- plt.subplot(121)
- plt.plot([5] * 10, 'o--', label='XX')
- plt.scatter(np.arange(10), np.arange(10, 0, -1), label='XX\nXX')
- 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],
- ncols=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, axs = plt.subplots(len(legend_modes), 1)
- x = np.arange(100)
- for ax, mode in zip(axs, 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, ncols=2)
- @image_comparison(['hatching'], remove_text=True, style='default')
- def test_hatching():
- # Remove legend texts when this image is regenerated.
- # 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, ax = plt.subplots()
- 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
- def test_reverse_legend_handles_and_labels():
- """Check that the legend handles and labels are reversed."""
- fig, ax = plt.subplots()
- x = 1
- y = 1
- labels = ["First label", "Second label", "Third label"]
- markers = ['.', ',', 'o']
- ax.plot(x, y, markers[0], label=labels[0])
- ax.plot(x, y, markers[1], label=labels[1])
- ax.plot(x, y, markers[2], label=labels[2])
- leg = ax.legend(reverse=True)
- actual_labels = [t.get_text() for t in leg.get_texts()]
- actual_markers = [h.get_marker() for h in leg.legend_handles]
- assert actual_labels == list(reversed(labels))
- assert actual_markers == list(reversed(markers))
- @check_figures_equal(extensions=["png"])
- def test_reverse_legend_display(fig_test, fig_ref):
- """Check that the rendered legend entries are reversed"""
- ax = fig_test.subplots()
- ax.plot([1], 'ro', label="first")
- ax.plot([2], 'bx', label="second")
- ax.legend(reverse=True)
- ax = fig_ref.subplots()
- ax.plot([2], 'bx', label="second")
- ax.plot([1], 'ro', label="first")
- ax.legend()
- class TestLegendFunction:
- # Tests the legend function on the Axes and pyplot.
- 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_positional_handles_labels(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_positional_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_positional_labels_only(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_legend_kwargs_handles_only(self):
- fig, ax = plt.subplots()
- x = np.linspace(0, 1, 11)
- ln1, = ax.plot(x, x, label='x')
- ln2, = ax.plot(x, 2*x, label='2x')
- ln3, = ax.plot(x, 3*x, label='3x')
- with mock.patch('matplotlib.legend.Legend') as Legend:
- ax.legend(handles=[ln3, ln2]) # reversed and not ln1
- Legend.assert_called_with(ax, [ln3, ln2], ['3x', '2x'])
- def test_legend_kwargs_labels_only(self):
- fig, ax = plt.subplots()
- x = np.linspace(0, 1, 11)
- ln1, = ax.plot(x, x)
- ln2, = ax.plot(x, 2*x)
- with mock.patch('matplotlib.legend.Legend') as Legend:
- ax.legend(labels=['x', '2x'])
- Legend.assert_called_with(ax, [ln1, ln2], ['x', '2x'])
- def test_legend_kwargs_handles_labels(self):
- fig, ax = plt.subplots()
- th = np.linspace(0, 2*np.pi, 1024)
- lns, = ax.plot(th, np.sin(th), label='sin')
- lnc, = ax.plot(th, np.cos(th), label='cos')
- with mock.patch('matplotlib.legend.Legend') as Legend:
- # labels of lns, lnc are overwritten with explicit ('a', 'b')
- ax.legend(labels=('a', 'b'), handles=(lnc, lns))
- Legend.assert_called_with(ax, (lnc, lns), ('a', 'b'))
- def test_warn_mixed_args_and_kwargs(self):
- fig, ax = plt.subplots()
- th = np.linspace(0, 2*np.pi, 1024)
- lns, = ax.plot(th, np.sin(th), label='sin')
- lnc, = ax.plot(th, np.cos(th), label='cos')
- 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 # type: ignore
- 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 pytest.raises(TypeError, match="0-2"):
- fig.legend(lines, ['foobar'], 'right')
- with pytest.raises(TypeError, match="0-2"):
- 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.")
- def test_figure_legend_outside():
- todos = ['upper ' + pos for pos in ['left', 'center', 'right']]
- todos += ['lower ' + pos for pos in ['left', 'center', 'right']]
- todos += ['left ' + pos for pos in ['lower', 'center', 'upper']]
- todos += ['right ' + pos for pos in ['lower', 'center', 'upper']]
- upperext = [20.347556, 27.722556, 790.583, 545.499]
- lowerext = [20.347556, 71.056556, 790.583, 588.833]
- leftext = [151.681556, 27.722556, 790.583, 588.833]
- rightext = [20.347556, 27.722556, 659.249, 588.833]
- axbb = [upperext, upperext, upperext,
- lowerext, lowerext, lowerext,
- leftext, leftext, leftext,
- rightext, rightext, rightext]
- legbb = [[10., 555., 133., 590.], # upper left
- [338.5, 555., 461.5, 590.], # upper center
- [667, 555., 790., 590.], # upper right
- [10., 10., 133., 45.], # lower left
- [338.5, 10., 461.5, 45.], # lower center
- [667., 10., 790., 45.], # lower right
- [10., 10., 133., 45.], # left lower
- [10., 282.5, 133., 317.5], # left center
- [10., 555., 133., 590.], # left upper
- [667, 10., 790., 45.], # right lower
- [667., 282.5, 790., 317.5], # right center
- [667., 555., 790., 590.]] # right upper
- for nn, todo in enumerate(todos):
- print(todo)
- fig, axs = plt.subplots(constrained_layout=True, dpi=100)
- axs.plot(range(10), label='Boo1')
- leg = fig.legend(loc='outside ' + todo)
- fig.draw_without_rendering()
- assert_allclose(axs.get_window_extent().extents,
- axbb[nn])
- assert_allclose(leg.get_window_extent().extents,
- legbb[nn])
- @image_comparison(['legend_stackplot.png'])
- def test_legend_stackplot():
- """Test legend for PolyCollection using stackplot."""
- # related to #1341, #1943, and PR #3303
- fig, ax = plt.subplots()
- 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.legend_handles
- for oh, lh in zip((lc1, lc2, lc3), (h1, h2, h3)):
- assert oh.get_linestyles()[0] == lh._dash_pattern
- 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_text_nohandler_warning():
- """Test that Text artists with labels raise a warning"""
- fig, ax = plt.subplots()
- ax.text(x=0, y=0, s="text", label="label")
- with pytest.warns(UserWarning) as record:
- ax.legend()
- assert len(record) == 1
- # this should _not_ warn:
- f, ax = plt.subplots()
- ax.pcolormesh(np.random.uniform(0, 1, (10, 10)))
- with warnings.catch_warnings():
- warnings.simplefilter("error")
- ax.get_legend_handles_labels()
- 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()
- @image_comparison(['shadow_argument_types.png'], remove_text=True,
- style='mpl20')
- def test_shadow_argument_types():
- # Test that different arguments for shadow work as expected
- fig, ax = plt.subplots()
- ax.plot([1, 2, 3], label='test')
- # Test various shadow configurations
- # as well as different ways of specifying colors
- legs = (ax.legend(loc='upper left', shadow=True), # True
- ax.legend(loc='upper right', shadow=False), # False
- ax.legend(loc='center left', # string
- shadow={'color': 'red', 'alpha': 0.1}),
- ax.legend(loc='center right', # tuple
- shadow={'color': (0.1, 0.2, 0.5), 'oy': -5}),
- ax.legend(loc='lower left', # tab
- shadow={'color': 'tab:cyan', 'ox': 10})
- )
- for l in legs:
- ax.add_artist(l)
- ax.legend(loc='lower right') # default
- def test_shadow_invalid_argument():
- # Test if invalid argument to legend shadow
- # (i.e. not [color|bool]) raises ValueError
- fig, ax = plt.subplots()
- ax.plot([1, 2, 3], label='test')
- with pytest.raises(ValueError, match="dict or bool"):
- ax.legend(loc="upper left", shadow="aardvark") # Bad argument
- 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_fontprop_fontsize():
- # test the title_fontsize kwarg
- plt.plot(range(10))
- with pytest.raises(ValueError):
- plt.legend(title='Aardvark', title_fontsize=22,
- title_fontproperties={'family': 'serif', 'size': 22})
- leg = plt.legend(title='Aardvark', title_fontproperties=FontProperties(
- family='serif', size=22))
- assert leg.get_title().get_size() == 22
- fig, axes = plt.subplots(2, 3, figsize=(10, 6))
- axes = axes.flat
- axes[0].plot(range(10))
- leg0 = axes[0].legend(title='Aardvark', title_fontsize=22)
- assert leg0.get_title().get_fontsize() == 22
- axes[1].plot(range(10))
- leg1 = axes[1].legend(title='Aardvark',
- title_fontproperties={'family': 'serif', 'size': 22})
- assert leg1.get_title().get_fontsize() == 22
- axes[2].plot(range(10))
- mpl.rcParams['legend.title_fontsize'] = None
- leg2 = axes[2].legend(title='Aardvark',
- title_fontproperties={'family': 'serif'})
- assert leg2.get_title().get_fontsize() == mpl.rcParams['font.size']
- axes[3].plot(range(10))
- leg3 = axes[3].legend(title='Aardvark')
- assert leg3.get_title().get_fontsize() == mpl.rcParams['font.size']
- axes[4].plot(range(10))
- mpl.rcParams['legend.title_fontsize'] = 20
- leg4 = axes[4].legend(title='Aardvark',
- title_fontproperties={'family': 'serif'})
- assert leg4.get_title().get_fontsize() == 20
- axes[5].plot(range(10))
- leg5 = axes[5].legend(title='Aardvark')
- assert leg5.get_title().get_fontsize() == 20
- @pytest.mark.parametrize('alignment', ('center', 'left', 'right'))
- def test_legend_alignment(alignment):
- fig, ax = plt.subplots()
- ax.plot(range(10), label='test')
- leg = ax.legend(title="Aardvark", alignment=alignment)
- assert leg.get_children()[0].align == alignment
- assert leg.get_alignment() == alignment
- @pytest.mark.parametrize('loc', ('center', 'best',))
- def test_ax_legend_set_loc(loc):
- fig, ax = plt.subplots()
- ax.plot(range(10), label='test')
- leg = ax.legend()
- leg.set_loc(loc)
- assert leg._get_loc() == mlegend.Legend.codes[loc]
- @pytest.mark.parametrize('loc', ('outside right', 'right',))
- def test_fig_legend_set_loc(loc):
- fig, ax = plt.subplots()
- ax.plot(range(10), label='test')
- leg = fig.legend()
- leg.set_loc(loc)
- loc = loc.split()[1] if loc.startswith("outside") else loc
- assert leg._get_loc() == mlegend.Legend.codes[loc]
- @pytest.mark.parametrize('alignment', ('center', 'left', 'right'))
- def test_legend_set_alignment(alignment):
- fig, ax = plt.subplots()
- ax.plot(range(10), label='test')
- leg = ax.legend()
- leg.set_alignment(alignment)
- assert leg.get_children()[0].align == alignment
- assert leg.get_alignment() == alignment
- @pytest.mark.parametrize('color', ('red', 'none', (.5, .5, .5)))
- def test_legend_labelcolor_single(color):
- # 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=color)
- for text in leg.get_texts():
- assert mpl.colors.same_color(text.get_color(), color)
- 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_pathcollection_labelcolor_linecolor():
- # test the labelcolor for labelcolor='linecolor' on PathCollection
- fig, ax = plt.subplots()
- ax.scatter(np.arange(10), np.arange(10)*1, label='#1', c='r')
- ax.scatter(np.arange(10), np.arange(10)*2, label='#2', c='g')
- ax.scatter(np.arange(10), np.arange(10)*3, label='#3', c='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_pathcollection_labelcolor_linecolor_iterable():
- # test the labelcolor for labelcolor='linecolor' on PathCollection
- # with iterable colors
- fig, ax = plt.subplots()
- colors = np.random.default_rng().choice(['r', 'g', 'b'], 10)
- ax.scatter(np.arange(10), np.arange(10)*1, label='#1', c=colors)
- leg = ax.legend(labelcolor='linecolor')
- text, = leg.get_texts()
- assert mpl.colors.same_color(text.get_color(), 'black')
- def test_legend_pathcollection_labelcolor_linecolor_cmap():
- # test the labelcolor for labelcolor='linecolor' on PathCollection
- # with a colormap
- fig, ax = plt.subplots()
- ax.scatter(np.arange(10), np.arange(10), c=np.arange(10), label='#1')
- leg = ax.legend(labelcolor='linecolor')
- text, = leg.get_texts()
- assert mpl.colors.same_color(text.get_color(), 'black')
- 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_pathcollection_labelcolor_markeredgecolor():
- # test the labelcolor for labelcolor='markeredgecolor' on PathCollection
- fig, ax = plt.subplots()
- ax.scatter(np.arange(10), np.arange(10)*1, label='#1', edgecolor='r')
- ax.scatter(np.arange(10), np.arange(10)*2, label='#2', edgecolor='g')
- ax.scatter(np.arange(10), np.arange(10)*3, label='#3', edgecolor='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_pathcollection_labelcolor_markeredgecolor_iterable():
- # test the labelcolor for labelcolor='markeredgecolor' on PathCollection
- # with iterable colors
- fig, ax = plt.subplots()
- colors = np.random.default_rng().choice(['r', 'g', 'b'], 10)
- ax.scatter(np.arange(10), np.arange(10)*1, label='#1', edgecolor=colors)
- leg = ax.legend(labelcolor='markeredgecolor')
- for text, color in zip(leg.get_texts(), ['k']):
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_pathcollection_labelcolor_markeredgecolor_cmap():
- # test the labelcolor for labelcolor='markeredgecolor' on PathCollection
- # with a colormap
- fig, ax = plt.subplots()
- edgecolors = mpl.cm.viridis(np.random.rand(10))
- ax.scatter(
- np.arange(10),
- np.arange(10),
- label='#1',
- c=np.arange(10),
- edgecolor=edgecolors,
- cmap="Reds"
- )
- leg = ax.legend(labelcolor='markeredgecolor')
- for text, color in zip(leg.get_texts(), ['k']):
- 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_legend_pathcollection_labelcolor_markerfacecolor():
- # test the labelcolor for labelcolor='markerfacecolor' on PathCollection
- fig, ax = plt.subplots()
- ax.scatter(np.arange(10), np.arange(10)*1, label='#1', facecolor='r')
- ax.scatter(np.arange(10), np.arange(10)*2, label='#2', facecolor='g')
- ax.scatter(np.arange(10), np.arange(10)*3, label='#3', facecolor='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_legend_pathcollection_labelcolor_markerfacecolor_iterable():
- # test the labelcolor for labelcolor='markerfacecolor' on PathCollection
- # with iterable colors
- fig, ax = plt.subplots()
- colors = np.random.default_rng().choice(['r', 'g', 'b'], 10)
- ax.scatter(np.arange(10), np.arange(10)*1, label='#1', facecolor=colors)
- leg = ax.legend(labelcolor='markerfacecolor')
- for text, color in zip(leg.get_texts(), ['k']):
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_pathcollection_labelcolor_markfacecolor_cmap():
- # test the labelcolor for labelcolor='markerfacecolor' on PathCollection
- # with colormaps
- fig, ax = plt.subplots()
- facecolors = mpl.cm.viridis(np.random.rand(10))
- ax.scatter(
- np.arange(10),
- np.arange(10),
- label='#1',
- c=np.arange(10),
- facecolor=facecolors
- )
- leg = ax.legend(labelcolor='markerfacecolor')
- for text, color in zip(leg.get_texts(), ['k']):
- assert mpl.colors.same_color(text.get_color(), color)
- @pytest.mark.parametrize('color', ('red', 'none', (.5, .5, .5)))
- def test_legend_labelcolor_rcparam_single(color):
- # test the rcParams legend.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')
- mpl.rcParams['legend.labelcolor'] = color
- leg = ax.legend()
- for text in leg.get_texts():
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_labelcolor_rcparam_linecolor():
- # test the rcParams legend.labelcolor for a 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')
- mpl.rcParams['legend.labelcolor'] = 'linecolor'
- leg = ax.legend()
- for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_labelcolor_rcparam_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')
- mpl.rcParams['legend.labelcolor'] = 'markeredgecolor'
- leg = ax.legend()
- for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_labelcolor_rcparam_markeredgecolor_short():
- # 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')
- mpl.rcParams['legend.labelcolor'] = 'mec'
- leg = ax.legend()
- for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_labelcolor_rcparam_markerfacecolor():
- # test the labelcolor for labelcolor='markeredgecolor'
- 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')
- mpl.rcParams['legend.labelcolor'] = 'markerfacecolor'
- leg = ax.legend()
- for text, color in zip(leg.get_texts(), ['r', 'g', 'b']):
- assert mpl.colors.same_color(text.get_color(), color)
- def test_legend_labelcolor_rcparam_markerfacecolor_short():
- # test the labelcolor for labelcolor='markeredgecolor'
- 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')
- mpl.rcParams['legend.labelcolor'] = 'mfc'
- leg = ax.legend()
- 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()
- @pytest.mark.parametrize('draggable', (True, False))
- def test_legend_draggable(draggable):
- fig, ax = plt.subplots()
- ax.plot(range(10), label='shabnams')
- leg = ax.legend(draggable=draggable)
- assert leg.get_draggable() is 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.legend_handles:
- 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]
- @needs_usetex
- def test_usetex_no_warn(caplog):
- mpl.rcParams['font.family'] = 'serif'
- mpl.rcParams['font.serif'] = 'Computer Modern'
- mpl.rcParams['text.usetex'] = True
- fig, ax = plt.subplots()
- ax.plot(0, 0, label='input')
- ax.legend(title="My legend")
- fig.canvas.draw()
- assert "Font family ['serif'] not found." not in caplog.text
- 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.
- @pytest.mark.parametrize('label_array', [['low', 'high'],
- ('low', 'high'),
- np.array(['low', 'high'])])
- def test_plot_multiple_input_multiple_label(label_array):
- # test ax.plot() with multidimensional input
- # and multiple labels
- x = [1, 2, 3]
- y = [[1, 2],
- [2, 5],
- [4, 9]]
- fig, ax = plt.subplots()
- ax.plot(x, y, label=label_array)
- leg = ax.legend()
- legend_texts = [entry.get_text() for entry in leg.get_texts()]
- assert legend_texts == ['low', 'high']
- @pytest.mark.parametrize('label', ['one', 1, int])
- def test_plot_multiple_input_single_label(label):
- # test ax.plot() with multidimensional input
- # and single label
- x = [1, 2, 3]
- y = [[1, 2],
- [2, 5],
- [4, 9]]
- fig, ax = plt.subplots()
- ax.plot(x, y, label=label)
- leg = ax.legend()
- legend_texts = [entry.get_text() for entry in leg.get_texts()]
- assert legend_texts == [str(label)] * 2
- @pytest.mark.parametrize('label_array', [['low', 'high'],
- ('low', 'high'),
- np.array(['low', 'high'])])
- def test_plot_single_input_multiple_label(label_array):
- # test ax.plot() with 1D array like input
- # and iterable label
- x = [1, 2, 3]
- y = [2, 5, 6]
- fig, ax = plt.subplots()
- ax.plot(x, y, label=label_array)
- leg = ax.legend()
- assert len(leg.get_texts()) == 1
- assert leg.get_texts()[0].get_text() == str(label_array)
- def test_plot_multiple_label_incorrect_length_exception():
- # check that exception is raised if multiple labels
- # are given, but number of on labels != number of lines
- with pytest.raises(ValueError):
- x = [1, 2, 3]
- y = [[1, 2],
- [2, 5],
- [4, 9]]
- label = ['high', 'low', 'medium']
- fig, ax = plt.subplots()
- ax.plot(x, y, label=label)
- def test_legend_face_edgecolor():
- # Smoke test for PolyCollection legend handler with 'face' edgecolor.
- fig, ax = plt.subplots()
- ax.fill_between([0, 1, 2], [1, 2, 3], [2, 3, 4],
- facecolor='r', edgecolor='face', label='Fill')
- ax.legend()
- def test_legend_text_axes():
- fig, ax = plt.subplots()
- ax.plot([1, 2], [3, 4], label='line')
- leg = ax.legend()
- assert leg.axes is ax
- assert leg.get_texts()[0].axes is ax
- def test_handlerline2d():
- # Test marker consistency for monolithic Line2D legend handler (#11357).
- fig, ax = plt.subplots()
- ax.scatter([0, 1], [0, 1], marker="v")
- handles = [mlines.Line2D([0], [0], marker="v")]
- leg = ax.legend(handles, ["Aardvark"], numpoints=1)
- assert handles[0].get_marker() == leg.legend_handles[0].get_marker()
- def test_subfigure_legend():
- # Test that legend can be added to subfigure (#20723)
- subfig = plt.figure().subfigures()
- ax = subfig.subplots()
- ax.plot([0, 1], [0, 1], label="line")
- leg = subfig.legend()
- assert leg.figure is subfig
- def test_setting_alpha_keeps_polycollection_color():
- pc = plt.fill_between([0, 1], [2, 3], color='#123456', label='label')
- patch = plt.legend().get_patches()[0]
- patch.set_alpha(0.5)
- assert patch.get_facecolor()[:3] == tuple(pc.get_facecolor()[0][:3])
- assert patch.get_edgecolor()[:3] == tuple(pc.get_edgecolor()[0][:3])
- def test_legend_markers_from_line2d():
- # Test that markers can be copied for legend lines (#17960)
- _markers = ['.', '*', 'v']
- fig, ax = plt.subplots()
- lines = [mlines.Line2D([0], [0], ls='None', marker=mark)
- for mark in _markers]
- labels = ["foo", "bar", "xyzzy"]
- markers = [line.get_marker() for line in lines]
- legend = ax.legend(lines, labels)
- new_markers = [line.get_marker() for line in legend.get_lines()]
- new_labels = [text.get_text() for text in legend.get_texts()]
- assert markers == new_markers == _markers
- assert labels == new_labels
- @check_figures_equal()
- def test_ncol_ncols(fig_test, fig_ref):
- # Test that both ncol and ncols work
- strings = ["a", "b", "c", "d", "e", "f"]
- ncols = 3
- fig_test.legend(strings, ncol=ncols)
- fig_ref.legend(strings, ncols=ncols)
- def test_loc_invalid_tuple_exception():
- # check that exception is raised if the loc arg
- # of legend is not a 2-tuple of numbers
- fig, ax = plt.subplots()
- with pytest.raises(ValueError, match=('loc must be string, coordinate '
- 'tuple, or an integer 0-10, not \\(1.1,\\)')):
- ax.legend(loc=(1.1, ))
- with pytest.raises(ValueError, match=('loc must be string, coordinate '
- 'tuple, or an integer 0-10, not \\(0.481, 0.4227, 0.4523\\)')):
- ax.legend(loc=(0.481, 0.4227, 0.4523))
- with pytest.raises(ValueError, match=('loc must be string, coordinate '
- 'tuple, or an integer 0-10, not \\(0.481, \'go blue\'\\)')):
- ax.legend(loc=(0.481, "go blue"))
- def test_loc_valid_tuple():
- fig, ax = plt.subplots()
- ax.legend(loc=(0.481, 0.442))
- ax.legend(loc=(1, 2))
- def test_loc_valid_list():
- fig, ax = plt.subplots()
- ax.legend(loc=[0.481, 0.442])
- ax.legend(loc=[1, 2])
- def test_loc_invalid_list_exception():
- fig, ax = plt.subplots()
- with pytest.raises(ValueError, match=('loc must be string, coordinate '
- 'tuple, or an integer 0-10, not \\[1.1, 2.2, 3.3\\]')):
- ax.legend(loc=[1.1, 2.2, 3.3])
- def test_loc_invalid_type():
- fig, ax = plt.subplots()
- with pytest.raises(ValueError, match=("loc must be string, coordinate "
- "tuple, or an integer 0-10, not {'not': True}")):
- ax.legend(loc={'not': True})
- def test_loc_validation_numeric_value():
- fig, ax = plt.subplots()
- ax.legend(loc=0)
- ax.legend(loc=1)
- ax.legend(loc=5)
- ax.legend(loc=10)
- with pytest.raises(ValueError, match=('loc must be string, coordinate '
- 'tuple, or an integer 0-10, not 11')):
- ax.legend(loc=11)
- with pytest.raises(ValueError, match=('loc must be string, coordinate '
- 'tuple, or an integer 0-10, not -1')):
- ax.legend(loc=-1)
- def test_loc_validation_string_value():
- fig, ax = plt.subplots()
- ax.legend(loc='best')
- ax.legend(loc='upper right')
- ax.legend(loc='best')
- ax.legend(loc='upper right')
- ax.legend(loc='upper left')
- ax.legend(loc='lower left')
- ax.legend(loc='lower right')
- ax.legend(loc='right')
- ax.legend(loc='center left')
- ax.legend(loc='center right')
- ax.legend(loc='lower center')
- ax.legend(loc='upper center')
- with pytest.raises(ValueError, match="'wrong' is not a valid value for"):
- ax.legend(loc='wrong')
|