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

Skip to content

Commit fa3aea9

Browse files
authored
Merge pull request #26483 from QuLogic/loc-best-warning
Improve legend(loc='best') warning and test
2 parents 5bdf0e0 + 3cc6610 commit fa3aea9

File tree

2 files changed

+35
-27
lines changed

2 files changed

+35
-27
lines changed

lib/matplotlib/legend.py

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,30 +1158,22 @@ def _get_anchored_bbox(self, loc, bbox, parentbbox, renderer):
11581158
loc, bbox, parentbbox,
11591159
self.borderaxespad * renderer.points_to_pixels(self._fontsize))
11601160

1161-
def _find_best_position(self, width, height, renderer, consider=None):
1162-
"""
1163-
Determine the best location to place the legend.
1164-
1165-
*consider* is a list of ``(x, y)`` pairs to consider as a potential
1166-
lower-left corner of the legend. All are display coords.
1167-
"""
1161+
def _find_best_position(self, width, height, renderer):
1162+
"""Determine the best location to place the legend."""
11681163
assert self.isaxes # always holds, as this is only called internally
11691164

11701165
start_time = time.perf_counter()
11711166

11721167
bboxes, lines, offsets = self._auto_legend_data()
11731168

11741169
bbox = Bbox.from_bounds(0, 0, width, height)
1175-
if consider is None:
1176-
consider = [self._get_anchored_bbox(x, bbox,
1177-
self.get_bbox_to_anchor(),
1178-
renderer)
1179-
for x in range(1, len(self.codes))]
11801170

11811171
candidates = []
1182-
for idx, (l, b) in enumerate(consider):
1172+
for idx in range(1, len(self.codes)):
1173+
l, b = self._get_anchored_bbox(idx, bbox,
1174+
self.get_bbox_to_anchor(),
1175+
renderer)
11831176
legendBox = Bbox.from_bounds(l, b, width, height)
1184-
badness = 0
11851177
# XXX TODO: If markers are present, it would be good to take them
11861178
# into account when checking vertex overlaps in the next line.
11871179
badness = (sum(legendBox.count_contains(line.vertices)
@@ -1190,10 +1182,10 @@ def _find_best_position(self, width, height, renderer, consider=None):
11901182
+ legendBox.count_overlaps(bboxes)
11911183
+ sum(line.intersects_bbox(legendBox, filled=False)
11921184
for line in lines))
1193-
if badness == 0:
1194-
return l, b
11951185
# Include the index to favor lower codes in case of a tie.
11961186
candidates.append((badness, idx, (l, b)))
1187+
if badness == 0:
1188+
break
11971189

11981190
_, _, (l, b) = min(candidates)
11991191

lib/matplotlib/tests/test_legend.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import collections
2+
import itertools
23
import platform
4+
import time
35
from unittest import mock
46
import warnings
57

@@ -1109,29 +1111,43 @@ def test_usetex_no_warn(caplog):
11091111
assert "Font family ['serif'] not found." not in caplog.text
11101112

11111113

1112-
def test_warn_big_data_best_loc():
1114+
def test_warn_big_data_best_loc(monkeypatch):
1115+
# Force _find_best_position to think it took a long time.
1116+
counter = itertools.count(0, step=1.5)
1117+
monkeypatch.setattr(time, 'perf_counter', lambda: next(counter))
1118+
11131119
fig, ax = plt.subplots()
11141120
fig.canvas.draw() # So that we can call draw_artist later.
1115-
for idx in range(1000):
1116-
ax.plot(np.arange(5000), label=idx)
1121+
1122+
# Place line across all possible legend locations.
1123+
x = [0.9, 0.1, 0.1, 0.9, 0.9, 0.5]
1124+
y = [0.95, 0.95, 0.05, 0.05, 0.5, 0.5]
1125+
ax.plot(x, y, 'o-', label='line')
1126+
11171127
with rc_context({'legend.loc': 'best'}):
11181128
legend = ax.legend()
1119-
with pytest.warns(UserWarning) as records:
1129+
with pytest.warns(UserWarning,
1130+
match='Creating legend with loc="best" can be slow with large '
1131+
'amounts of data.') as records:
11201132
fig.draw_artist(legend) # Don't bother drawing the lines -- it's slow.
11211133
# The _find_best_position method of Legend is called twice, duplicating
11221134
# the warning message.
11231135
assert len(records) == 2
1124-
for record in records:
1125-
assert str(record.message) == (
1126-
'Creating legend with loc="best" can be slow with large '
1127-
'amounts of data.')
11281136

11291137

1130-
def test_no_warn_big_data_when_loc_specified():
1138+
def test_no_warn_big_data_when_loc_specified(monkeypatch):
1139+
# Force _find_best_position to think it took a long time.
1140+
counter = itertools.count(0, step=1.5)
1141+
monkeypatch.setattr(time, 'perf_counter', lambda: next(counter))
1142+
11311143
fig, ax = plt.subplots()
11321144
fig.canvas.draw()
1133-
for idx in range(1000):
1134-
ax.plot(np.arange(5000), label=idx)
1145+
1146+
# Place line across all possible legend locations.
1147+
x = [0.9, 0.1, 0.1, 0.9, 0.9, 0.5]
1148+
y = [0.95, 0.95, 0.05, 0.05, 0.5, 0.5]
1149+
ax.plot(x, y, 'o-', label='line')
1150+
11351151
legend = ax.legend('best')
11361152
fig.draw_artist(legend) # Check that no warning is emitted.
11371153

0 commit comments

Comments
 (0)