Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 87d05ae

Browse files
alanlau28alextanned
authored andcommitted
Fix legend auto-placement in the presence of text or PolyCollections
Co-authored-by: alextanned <[email protected]>
1 parent 09eab5b commit 87d05ae

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
``loc='best'`` for ``legend`` now considers ``Text`` and ``PolyCollections``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
The location selection ``legend`` now considers the existence of ``Text``
5+
and ``PolyCollections`` in the ``badness`` calculation.
6+
7+
Note: The ``best`` option can already be quite slow for plots with large
8+
amounts of data. For ``PolyCollections``, it only considers the ``Path``
9+
of ``PolyCollections`` and not the enclosed area when checking for overlap
10+
to reduce additional latency. However, it can still be quite slow when
11+
there are large amounts of ``PolyCollections`` in the plot to check for.

lib/matplotlib/legend.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,10 +978,15 @@ def _auto_legend_data(self):
978978
elif isinstance(artist, Patch):
979979
lines.append(
980980
artist.get_transform().transform_path(artist.get_path()))
981+
elif isinstance(artist, PolyCollection):
982+
lines.extend(artist.get_transform().transform_path(path)
983+
for path in artist.get_paths())
981984
elif isinstance(artist, Collection):
982985
transform, transOffset, hoffsets, _ = artist._prepare_points()
983986
if len(hoffsets):
984987
offsets.extend(transOffset.transform(hoffsets))
988+
elif isinstance(artist, Text):
989+
bboxes.append(artist.get_window_extent())
985990

986991
return bboxes, lines, offsets
987992

lib/matplotlib/tests/test_legend.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,3 +1391,39 @@ def test_legend_nolabels_draw():
13911391
plt.plot([1, 2, 3])
13921392
plt.legend()
13931393
assert plt.gca().get_legend() is not None
1394+
1395+
1396+
def test_legend_loc_polycollection():
1397+
# Test that the legend is placed in the correct
1398+
# position for 'best' for polycollection
1399+
x = [3, 4, 5]
1400+
y1 = [1, 1, 1]
1401+
y2 = [5, 5, 5]
1402+
leg_bboxes = []
1403+
fig, axs = plt.subplots(ncols=2, figsize=(10, 5))
1404+
for ax, loc in zip(axs.flat, ('best', 'lower left')):
1405+
ax.fill_between(x, y1, y2, color='gray', alpha=0.5, label='Shaded Area')
1406+
ax.set_xlim(0, 6)
1407+
ax.set_ylim(-1, 5)
1408+
leg = ax.legend(loc=loc)
1409+
fig.canvas.draw()
1410+
leg_bboxes.append(
1411+
leg.get_window_extent().transformed(ax.transAxes.inverted()))
1412+
assert_allclose(leg_bboxes[1].bounds, leg_bboxes[0].bounds)
1413+
1414+
1415+
def test_legend_text():
1416+
# Test that legend is place in the correct
1417+
# position for 'best' when there is text in figure
1418+
fig, axs = plt.subplots(ncols=2, figsize=(10, 5))
1419+
leg_bboxes = []
1420+
for ax, loc in zip(axs.flat, ('best', 'lower left')):
1421+
x = [1, 2]
1422+
y = [2, 1]
1423+
ax.plot(x, y, label='plot name')
1424+
ax.text(1.5, 2, 'some text blahblah', verticalalignment='top')
1425+
leg = ax.legend(loc=loc)
1426+
fig.canvas.draw()
1427+
leg_bboxes.append(
1428+
leg.get_window_extent().transformed(ax.transAxes.inverted()))
1429+
assert_allclose(leg_bboxes[1].bounds, leg_bboxes[0].bounds)

0 commit comments

Comments
 (0)