Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix bugs in legend positioning with loc='best' #1640

Merged
merged 10 commits into from

4 participants

@maxalbert

This PR fixes a couple of bugs which caused the legend positioning algorithm to ignore vertices when figuring out the best location of the legend box.

@NelleV
Collaborator

Hi @maxalbert,

Thanks for this patch. I ran the tests on your branch, and unfortunately they don't pass. Here is the traceback:

Traceback (most recent call last):
File "/home/nelle/.work/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(self.arg)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/testing/decorators.py", line 39, in failer
result = f(
args, *kwargs)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/testing/decorators.py", line 145, in do_test
figure.savefig(actual_fname, *
self._savefig_kwarg)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/figure.py", line 1363, in savefig
self.canvas.print_figure(args, *kwargs)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 2127, in print_figure
*kwargs)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 491, in print_png
FigureCanvasAgg.draw(self)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 439, in draw
self.figure.draw(self.renderer)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/artist.py", line 54, in draw_wrapper
draw(artist, renderer, *args, *
kwargs)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/figure.py", line 999, in draw
func(args)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/artist.py", line 54, in draw_wrapper
draw(artist, renderer, *args, *
kwargs)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/axes.py", line 2093, in draw
a.draw(renderer)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/artist.py", line 54, in draw_wrapper
draw(artist, renderer, args, *kwargs)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/legend.py", line 465, in draw
bbox = self._legend_box.get_window_extent(renderer)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/offsetbox.py", line 244, in get_window_extent
px, py = self.get_offset(w, h, xd, yd, renderer)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/offsetbox.py", line 197, in get_offset
return self._offset(width, height, xdescent, ydescent, renderer)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/legend.py", line 428, in _findoffset_best
ox, oy = self._find_best_position(width, height, renderer)
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/legend.py", line 916, in _find_best_position
verts, bboxes, lines = self._auto_legend_data()
File "/home/nelle/.work/local/lib/python2.7/site-packages/matplotlib/legend.py", line 752, in _auto_legend_data
vertices = np.concatenate([l.vertices for l in lines])
ValueError: concatenation of zero-length sequences is impossible

Can you have a look at this?

Cheers,
N

@NelleV NelleV commented on the diff
lib/matplotlib/legend.py
@@ -108,7 +108,7 @@ class Legend(Artist):
'upper center' : 9,
'center' : 10,
- loc can be a tuple of the noramilzed coordinate values with
+ loc can be a tuple of the normalized coordinate values with
@NelleV Collaborator
NelleV added a note

Good catch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@maxalbert

Hi @NelleV,

many thanks for the lightning-speed reply! :) (And apologies in advance if my responses come a bit slower, I'm on a rather intermittent/flaky internet connection for at least another week or so.)

I tried to take a look at this, but (un?)-fortunately can't reproduce the error as the test suite passes for me. Maybe I'm doing something wrong in running the tests? I'm calling python tests.py from the toplevel directory, is there something else I need to do?

Thanks,
Max

P.S.: It just occurred to me that I have multiple versions of matplotlib lying around but ran the test suite in a fresh checkout of my branch which I didn't install first. I'll check if this could be the cause of the missing error. Do you know if the test suite picks up the version of matplotlib from the repository that it is being run in, or does it use the system-wide installation?

@maxalbert

Update: looks like the latter is true, so it was indeed a case of one installation interfering with another. I now get the same error and will take a look. Btw, would it be worth to make the test suite automatically pick up the matplotlib version from the repository that it is being run in, or am I missing any hidden pitfalls that this might lead to?

@NelleV
Collaborator

I think it is possible, if the code is build inplace. That's something I'd like to have a look at, as soon as I'm finished with all my open branches (or someone else could have a look at it). I think it may require some code refactoring.

@maxalbert

Hi @NelleV,

the test failure was trivial to fix (as expected from the error message), but it took me a while to upload it because I wanted to add at least one test case. Could you try again and see if it works for you now, too?

Originally I had planned to add a few more tests, but unfortunately in preparing them I realised that the code is still not optimal (see the FIXME comment in commit 49ee4e8). Alas, a proper fix might result in increased running times in case there are a lot of vertices in a plot, although this may not be an issue. I do not have time to look into this at the moment or to do some profiling, but wanted to at least mention it.

Thanks again for your time, any further comments/suggestions are appreciated.

Cheers,
Max

@mdboom mdboom commented on the diff
lib/matplotlib/transforms.py
@@ -645,7 +645,7 @@ def count_contains(self, vertices):
dy0 = np.sign(vertices[:, 1] - y0)
dx1 = np.sign(vertices[:, 0] - x1)
dy1 = np.sign(vertices[:, 1] - y1)
- inside = (abs(dx0 + dx1) + abs(dy0 + dy1)) <= 2
+ inside = ((abs(dx0 + dx1) + abs(dy0 + dy1)) == 0)
@mdboom Owner
mdboom added a note

Good catch! I'm not sure what my original thinking was here, but it doesn't make much sense to me now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@efiring efiring merged commit d179f4b into matplotlib:master

1 check failed

Details default The Travis build failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 7, 2013
  1. @maxalbert

    Typo in docstring.

    maxalbert authored
  2. @maxalbert
  3. @maxalbert
  4. @maxalbert

    Fix bug in helper function which prevented the legend from avoiding v…

    maxalbert authored
    …ertices.
    
    This bug was not triggered before because count_contains() was never
    called due to the empty vertex list in Legend._find_best_position().
  5. @maxalbert
Commits on Jan 9, 2013
  1. @maxalbert

    Typo in docs.

    maxalbert authored
  2. @maxalbert
  3. @maxalbert

    Add new test for automatic legend placement to check that vertices ar…

    maxalbert authored
    …e indeed taken into account.
  4. @maxalbert

    Add FIXME comment.

    maxalbert authored
  5. @maxalbert
This page is out of date. Refresh to see the latest.
View
2  doc/devel/testing.rst
@@ -73,7 +73,7 @@ example, here is a test from :mod:`matplotlib.tests.test_basic`::
Nose determines which functions are tests by searching for functions
beginning with "test" in their name.
-If the test as side effects that need to be cleaned up, such as
+If the test has side effects that need to be cleaned up, such as
creating figures using the pyplot interface, use the ``@cleanup``
decorator::
View
27 lib/matplotlib/legend.py
@@ -108,7 +108,7 @@ class Legend(Artist):
'upper center' : 9,
'center' : 10,
- loc can be a tuple of the noramilzed coordinate values with
+ loc can be a tuple of the normalized coordinate values with
@NelleV Collaborator
NelleV added a note

Good catch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
respect its parent.
"""
@@ -729,7 +729,6 @@ def _auto_legend_data(self):
assert self.isaxes
ax = self.parent
- vertices = []
bboxes = []
lines = []
@@ -750,6 +749,11 @@ def _auto_legend_data(self):
transform = handle.get_transform()
bboxes.append(handle.get_path().get_extents(transform))
+ try:
+ vertices = np.concatenate([l.vertices for l in lines])
+ except ValueError:
+ vertices = np.array([])
+
return [vertices, bboxes, lines]
def draw_frame(self, b):
@@ -915,10 +919,11 @@ def _find_best_position(self, width, height, renderer, consider=None):
verts, bboxes, lines = self._auto_legend_data()
bbox = Bbox.from_bounds(0, 0, width, height)
- consider = [self._get_anchored_bbox(x, bbox, self.get_bbox_to_anchor(),
- renderer)
- for x
- in range(1, len(self.codes))]
+ if consider is None:
+ consider = [self._get_anchored_bbox(x, bbox,
+ self.get_bbox_to_anchor(),
+ renderer)
+ for x in range(1, len(self.codes))]
#tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y()
@@ -926,9 +931,19 @@ def _find_best_position(self, width, height, renderer, consider=None):
for l, b in consider:
legendBox = Bbox.from_bounds(l, b, width, height)
badness = 0
+ # XXX TODO: If markers are present, it would be good to
+ # take their into account when checking vertex overlaps in
+ # the next line.
badness = legendBox.count_contains(verts)
badness += legendBox.count_overlaps(bboxes)
for line in lines:
+ # FIXME: the following line is ill-suited for lines
+ # that 'spiral' around the center, because the bbox
+ # may intersect with the legend even if the line
+ # itself doesn't. One solution would be to break up
+ # the line into its straight-segment components, but
+ # this may (or may not) result in a significant
+ # slowdown if lines with many vertices are present.
if line.intersects_bbox(legendBox):
badness += 1
View
BIN  lib/matplotlib/tests/baseline_images/test_legend/legend_auto3.pdf
Binary file not shown
View
BIN  lib/matplotlib/tests/baseline_images/test_legend/legend_auto3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
607 lib/matplotlib/tests/baseline_images/test_legend/legend_auto3.svg
@@ -0,0 +1,607 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Created with matplotlib (http://matplotlib.org/) -->
+<svg height="432pt" version="1.1" viewBox="0 0 576 432" width="576pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <style type="text/css">
+*{stroke-linecap:square;stroke-linejoin:round;}
+ </style>
+ </defs>
+ <g id="figure_1">
+ <g id="patch_1">
+ <path d="
+M0 432
+L576 432
+L576 0
+L0 0
+z
+" style="fill:#ffffff;"/>
+ </g>
+ <g id="axes_1">
+ <g id="patch_2">
+ <path d="
+M72 388.8
+L518.4 388.8
+L518.4 43.2
+L72 43.2
+z
+" style="fill:#ffffff;"/>
+ </g>
+ <g id="line2d_1">
+ <path clip-path="url(#p7ff5b81e1d)" d="
+M473.76 60.48
+L116.64 60.48
+L116.64 371.52
+L473.76 371.52
+L473.76 216
+L295.2 216" style="fill:none;stroke:#0000ff;"/>
+ <defs>
+ <path d="
+M0 3
+C0.795609 3 1.55874 2.6839 2.12132 2.12132
+C2.6839 1.55874 3 0.795609 3 0
+C3 -0.795609 2.6839 -1.55874 2.12132 -2.12132
+C1.55874 -2.6839 0.795609 -3 0 -3
+C-0.795609 -3 -1.55874 -2.6839 -2.12132 -2.12132
+C-2.6839 -1.55874 -3 -0.795609 -3 0
+C-3 0.795609 -2.6839 1.55874 -2.12132 2.12132
+C-1.55874 2.6839 -0.795609 3 0 3
+z
+" id="m0f54036a79" style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;"/>
+ </defs>
+ <g clip-path="url(#p7ff5b81e1d)">
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="473.76" xlink:href="#m0f54036a79" y="60.48"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="116.64" xlink:href="#m0f54036a79" y="60.48"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="116.64" xlink:href="#m0f54036a79" y="371.52"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="473.76" xlink:href="#m0f54036a79" y="371.52"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="473.76" xlink:href="#m0f54036a79" y="216.0"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="295.2" xlink:href="#m0f54036a79" y="216.0"/>
+ </g>
+ </g>
+ <g id="matplotlib.axis_1">
+ <g id="xtick_1">
+ <g id="line2d_2">
+ <defs>
+ <path d="
+M0 0
+L0 -4" id="mcb557df647" style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;"/>
+ </defs>
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mcb557df647" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_3">
+ <defs>
+ <path d="
+M0 0
+L0 4" id="mdad270ee8e" style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;"/>
+ </defs>
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mdad270ee8e" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_1">
+ <!-- 0.0 -->
+ <defs>
+ <path d="
+M31.7812 66.4062
+Q24.1719 66.4062 20.3281 58.9062
+Q16.5 51.4219 16.5 36.375
+Q16.5 21.3906 20.3281 13.8906
+Q24.1719 6.39062 31.7812 6.39062
+Q39.4531 6.39062 43.2812 13.8906
+Q47.125 21.3906 47.125 36.375
+Q47.125 51.4219 43.2812 58.9062
+Q39.4531 66.4062 31.7812 66.4062
+M31.7812 74.2188
+Q44.0469 74.2188 50.5156 64.5156
+Q56.9844 54.8281 56.9844 36.375
+Q56.9844 17.9688 50.5156 8.26562
+Q44.0469 -1.42188 31.7812 -1.42188
+Q19.5312 -1.42188 13.0625 8.26562
+Q6.59375 17.9688 6.59375 36.375
+Q6.59375 54.8281 13.0625 64.5156
+Q19.5312 74.2188 31.7812 74.2188" id="BitstreamVeraSans-Roman-30"/>
+ <path d="
+M10.6875 12.4062
+L21 12.4062
+L21 0
+L10.6875 0
+z
+" id="BitstreamVeraSans-Roman-2e"/>
+ </defs>
+ <g transform="translate(63.2521875 401.70625)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-30"/>
+ </g>
+ </g>
+ </g>
+ <g id="xtick_2">
+ <g id="line2d_4">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="161.28" xlink:href="#mcb557df647" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_5">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="161.28" xlink:href="#mdad270ee8e" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_2">
+ <!-- 0.2 -->
+ <defs>
+ <path d="
+M19.1875 8.29688
+L53.6094 8.29688
+L53.6094 0
+L7.32812 0
+L7.32812 8.29688
+Q12.9375 14.1094 22.625 23.8906
+Q32.3281 33.6875 34.8125 36.5312
+Q39.5469 41.8438 41.4219 45.5312
+Q43.3125 49.2188 43.3125 52.7812
+Q43.3125 58.5938 39.2344 62.25
+Q35.1562 65.9219 28.6094 65.9219
+Q23.9688 65.9219 18.8125 64.3125
+Q13.6719 62.7031 7.8125 59.4219
+L7.8125 69.3906
+Q13.7656 71.7812 18.9375 73
+Q24.125 74.2188 28.4219 74.2188
+Q39.75 74.2188 46.4844 68.5469
+Q53.2188 62.8906 53.2188 53.4219
+Q53.2188 48.9219 51.5312 44.8906
+Q49.8594 40.875 45.4062 35.4062
+Q44.1875 33.9844 37.6406 27.2188
+Q31.1094 20.4531 19.1875 8.29688" id="BitstreamVeraSans-Roman-32"/>
+ </defs>
+ <g transform="translate(152.7346875 401.70625)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-32"/>
+ </g>
+ </g>
+ </g>
+ <g id="xtick_3">
+ <g id="line2d_6">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="250.56" xlink:href="#mcb557df647" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_7">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="250.56" xlink:href="#mdad270ee8e" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_3">
+ <!-- 0.4 -->
+ <defs>
+ <path d="
+M37.7969 64.3125
+L12.8906 25.3906
+L37.7969 25.3906
+z
+
+M35.2031 72.9062
+L47.6094 72.9062
+L47.6094 25.3906
+L58.0156 25.3906
+L58.0156 17.1875
+L47.6094 17.1875
+L47.6094 0
+L37.7969 0
+L37.7969 17.1875
+L4.89062 17.1875
+L4.89062 26.7031
+z
+" id="BitstreamVeraSans-Roman-34"/>
+ </defs>
+ <g transform="translate(241.7503125 401.70625)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-34"/>
+ </g>
+ </g>
+ </g>
+ <g id="xtick_4">
+ <g id="line2d_8">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="339.84" xlink:href="#mcb557df647" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_9">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="339.84" xlink:href="#mdad270ee8e" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_4">
+ <!-- 0.6 -->
+ <defs>
+ <path d="
+M33.0156 40.375
+Q26.375 40.375 22.4844 35.8281
+Q18.6094 31.2969 18.6094 23.3906
+Q18.6094 15.5312 22.4844 10.9531
+Q26.375 6.39062 33.0156 6.39062
+Q39.6562 6.39062 43.5312 10.9531
+Q47.4062 15.5312 47.4062 23.3906
+Q47.4062 31.2969 43.5312 35.8281
+Q39.6562 40.375 33.0156 40.375
+M52.5938 71.2969
+L52.5938 62.3125
+Q48.875 64.0625 45.0938 64.9844
+Q41.3125 65.9219 37.5938 65.9219
+Q27.8281 65.9219 22.6719 59.3281
+Q17.5312 52.7344 16.7969 39.4062
+Q19.6719 43.6562 24.0156 45.9219
+Q28.375 48.1875 33.5938 48.1875
+Q44.5781 48.1875 50.9531 41.5156
+Q57.3281 34.8594 57.3281 23.3906
+Q57.3281 12.1562 50.6875 5.35938
+Q44.0469 -1.42188 33.0156 -1.42188
+Q20.3594 -1.42188 13.6719 8.26562
+Q6.98438 17.9688 6.98438 36.375
+Q6.98438 53.6562 15.1875 63.9375
+Q23.3906 74.2188 37.2031 74.2188
+Q40.9219 74.2188 44.7031 73.4844
+Q48.4844 72.75 52.5938 71.2969" id="BitstreamVeraSans-Roman-36"/>
+ </defs>
+ <g transform="translate(331.0715625 401.70625)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-36"/>
+ </g>
+ </g>
+ </g>
+ <g id="xtick_5">
+ <g id="line2d_10">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="429.12" xlink:href="#mcb557df647" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_11">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="429.12" xlink:href="#mdad270ee8e" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_5">
+ <!-- 0.8 -->
+ <defs>
+ <path d="
+M31.7812 34.625
+Q24.75 34.625 20.7188 30.8594
+Q16.7031 27.0938 16.7031 20.5156
+Q16.7031 13.9219 20.7188 10.1562
+Q24.75 6.39062 31.7812 6.39062
+Q38.8125 6.39062 42.8594 10.1719
+Q46.9219 13.9688 46.9219 20.5156
+Q46.9219 27.0938 42.8906 30.8594
+Q38.875 34.625 31.7812 34.625
+M21.9219 38.8125
+Q15.5781 40.375 12.0312 44.7188
+Q8.5 49.0781 8.5 55.3281
+Q8.5 64.0625 14.7188 69.1406
+Q20.9531 74.2188 31.7812 74.2188
+Q42.6719 74.2188 48.875 69.1406
+Q55.0781 64.0625 55.0781 55.3281
+Q55.0781 49.0781 51.5312 44.7188
+Q48 40.375 41.7031 38.8125
+Q48.8281 37.1562 52.7969 32.3125
+Q56.7812 27.4844 56.7812 20.5156
+Q56.7812 9.90625 50.3125 4.23438
+Q43.8438 -1.42188 31.7812 -1.42188
+Q19.7344 -1.42188 13.25 4.23438
+Q6.78125 9.90625 6.78125 20.5156
+Q6.78125 27.4844 10.7812 32.3125
+Q14.7969 37.1562 21.9219 38.8125
+M18.3125 54.3906
+Q18.3125 48.7344 21.8438 45.5625
+Q25.3906 42.3906 31.7812 42.3906
+Q38.1406 42.3906 41.7188 45.5625
+Q45.3125 48.7344 45.3125 54.3906
+Q45.3125 60.0625 41.7188 63.2344
+Q38.1406 66.4062 31.7812 66.4062
+Q25.3906 66.4062 21.8438 63.2344
+Q18.3125 60.0625 18.3125 54.3906" id="BitstreamVeraSans-Roman-38"/>
+ </defs>
+ <g transform="translate(420.384375 401.70625)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-38"/>
+ </g>
+ </g>
+ </g>
+ <g id="xtick_6">
+ <g id="line2d_12">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#mcb557df647" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_13">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#mdad270ee8e" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_6">
+ <!-- 1.0 -->
+ <defs>
+ <path d="
+M12.4062 8.29688
+L28.5156 8.29688
+L28.5156 63.9219
+L10.9844 60.4062
+L10.9844 69.3906
+L28.4219 72.9062
+L38.2812 72.9062
+L38.2812 8.29688
+L54.3906 8.29688
+L54.3906 0
+L12.4062 0
+z
+" id="BitstreamVeraSans-Roman-31"/>
+ </defs>
+ <g transform="translate(509.915625 401.70625)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-31"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-30"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="matplotlib.axis_2">
+ <g id="ytick_1">
+ <g id="line2d_14">
+ <defs>
+ <path d="
+M0 0
+L4 0" id="mc8fcea1516" style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;"/>
+ </defs>
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mc8fcea1516" y="388.8"/>
+ </g>
+ </g>
+ <g id="line2d_15">
+ <defs>
+ <path d="
+M0 0
+L-4 0" id="m0d5b0a6425" style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;"/>
+ </defs>
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#m0d5b0a6425" y="388.8"/>
+ </g>
+ </g>
+ <g id="text_7">
+ <!-- 0.0 -->
+ <g transform="translate(50.504375 393.1678125)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-30"/>
+ </g>
+ </g>
+ </g>
+ <g id="ytick_2">
+ <g id="line2d_16">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mc8fcea1516" y="319.68"/>
+ </g>
+ </g>
+ <g id="line2d_17">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#m0d5b0a6425" y="319.68"/>
+ </g>
+ </g>
+ <g id="text_8">
+ <!-- 0.2 -->
+ <g transform="translate(50.909375 324.0478125)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-32"/>
+ </g>
+ </g>
+ </g>
+ <g id="ytick_3">
+ <g id="line2d_18">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mc8fcea1516" y="250.56"/>
+ </g>
+ </g>
+ <g id="line2d_19">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#m0d5b0a6425" y="250.56"/>
+ </g>
+ </g>
+ <g id="text_9">
+ <!-- 0.4 -->
+ <g transform="translate(50.380625 254.9278125)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-34"/>
+ </g>
+ </g>
+ </g>
+ <g id="ytick_4">
+ <g id="line2d_20">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mc8fcea1516" y="181.44"/>
+ </g>
+ </g>
+ <g id="line2d_21">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#m0d5b0a6425" y="181.44"/>
+ </g>
+ </g>
+ <g id="text_10">
+ <!-- 0.6 -->
+ <g transform="translate(50.463125 185.8078125)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-36"/>
+ </g>
+ </g>
+ </g>
+ <g id="ytick_5">
+ <g id="line2d_22">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mc8fcea1516" y="112.32"/>
+ </g>
+ </g>
+ <g id="line2d_23">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#m0d5b0a6425" y="112.32"/>
+ </g>
+ </g>
+ <g id="text_11">
+ <!-- 0.8 -->
+ <g transform="translate(50.52875 116.6878125)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-30"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-38"/>
+ </g>
+ </g>
+ </g>
+ <g id="ytick_6">
+ <g id="line2d_24">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="72.0" xlink:href="#mc8fcea1516" y="43.2"/>
+ </g>
+ </g>
+ <g id="line2d_25">
+ <g>
+ <use style="stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="518.4" xlink:href="#m0d5b0a6425" y="43.2"/>
+ </g>
+ </g>
+ <g id="text_12">
+ <!-- 1.0 -->
+ <g transform="translate(51.03125 47.5678125)scale(0.12 -0.12)">
+ <use xlink:href="#BitstreamVeraSans-Roman-31"/>
+ <use x="63.623046875" xlink:href="#BitstreamVeraSans-Roman-2e"/>
+ <use x="95.41015625" xlink:href="#BitstreamVeraSans-Roman-30"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="patch_3">
+ <path d="
+M72 43.2
+L518.4 43.2" style="fill:none;stroke:#000000;"/>
+ </g>
+ <g id="patch_4">
+ <path d="
+M518.4 388.8
+L518.4 43.2" style="fill:none;stroke:#000000;"/>
+ </g>
+ <g id="patch_5">
+ <path d="
+M72 388.8
+L518.4 388.8" style="fill:none;stroke:#000000;"/>
+ </g>
+ <g id="patch_6">
+ <path d="
+M72 388.8
+L72 43.2" style="fill:none;stroke:#000000;"/>
+ </g>
+ <g id="legend_1">
+ <g id="patch_7">
+ <path d="
+M79.2 227.333
+L154.868 227.333
+L154.868 204.667
+L79.2 204.667
+L79.2 227.333
+z
+" style="fill:#ffffff;stroke:#000000;"/>
+ </g>
+ <g id="line2d_26">
+ <path d="
+M89.28 216.328
+L109.44 216.328" style="fill:none;stroke:#0000ff;"/>
+ </g>
+ <g id="line2d_27">
+ <g>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="89.28" xlink:href="#m0f54036a79" y="216.3285"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="109.44" xlink:href="#m0f54036a79" y="216.3285"/>
+ </g>
+ </g>
+ <g id="text_13">
+ <!-- line -->
+ <defs>
+ <path d="
+M54.8906 33.0156
+L54.8906 0
+L45.9062 0
+L45.9062 32.7188
+Q45.9062 40.4844 42.875 44.3281
+Q39.8438 48.1875 33.7969 48.1875
+Q26.5156 48.1875 22.3125 43.5469
+Q18.1094 38.9219 18.1094 30.9062
+L18.1094 0
+L9.07812 0
+L9.07812 54.6875
+L18.1094 54.6875
+L18.1094 46.1875
+Q21.3438 51.125 25.7031 53.5625
+Q30.0781 56 35.7969 56
+Q45.2188 56 50.0469 50.1719
+Q54.8906 44.3438 54.8906 33.0156" id="BitstreamVeraSans-Roman-6e"/>
+ <path d="
+M56.2031 29.5938
+L56.2031 25.2031
+L14.8906 25.2031
+Q15.4844 15.9219 20.4844 11.0625
+Q25.4844 6.20312 34.4219 6.20312
+Q39.5938 6.20312 44.4531 7.46875
+Q49.3125 8.73438 54.1094 11.2812
+L54.1094 2.78125
+Q49.2656 0.734375 44.1875 -0.34375
+Q39.1094 -1.42188 33.8906 -1.42188
+Q20.7969 -1.42188 13.1562 6.1875
+Q5.51562 13.8125 5.51562 26.8125
+Q5.51562 40.2344 12.7656 48.1094
+Q20.0156 56 32.3281 56
+Q43.3594 56 49.7812 48.8906
+Q56.2031 41.7969 56.2031 29.5938
+M47.2188 32.2344
+Q47.125 39.5938 43.0938 43.9844
+Q39.0625 48.3906 32.4219 48.3906
+Q24.9062 48.3906 20.3906 44.1406
+Q15.875 39.8906 15.1875 32.1719
+z
+" id="BitstreamVeraSans-Roman-65"/>
+ <path d="
+M9.42188 54.6875
+L18.4062 54.6875
+L18.4062 0
+L9.42188 0
+z
+
+M9.42188 75.9844
+L18.4062 75.9844
+L18.4062 64.5938
+L9.42188 64.5938
+z
+" id="BitstreamVeraSans-Roman-69"/>
+ <path d="
+M9.42188 75.9844
+L18.4062 75.9844
+L18.4062 0
+L9.42188 0
+z
+" id="BitstreamVeraSans-Roman-6c"/>
+ </defs>
+ <g transform="translate(125.28 221.3685)scale(0.144 -0.144)">
+ <use xlink:href="#BitstreamVeraSans-Roman-6c"/>
+ <use x="27.783203125" xlink:href="#BitstreamVeraSans-Roman-69"/>
+ <use x="55.56640625" xlink:href="#BitstreamVeraSans-Roman-6e"/>
+ <use x="118.9453125" xlink:href="#BitstreamVeraSans-Roman-65"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <defs>
+ <clipPath id="p7ff5b81e1d">
+ <rect height="345.6" width="446.4" x="72.0" y="43.2"/>
+ </clipPath>
+ </defs>
+</svg>
View
BIN  lib/matplotlib/tests/baseline_images/test_legend/legend_various_labels.pdf
Binary file not shown
View
BIN  lib/matplotlib/tests/baseline_images/test_legend/legend_various_labels.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
20 lib/matplotlib/tests/baseline_images/test_legend/legend_various_labels.svg
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Created with matplotlib (http://matplotlib.sourceforge.net/) -->
+<!-- Created with matplotlib (http://matplotlib.org/) -->
<svg height="432pt" version="1.1" viewBox="0 0 576 432" width="576pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
@@ -378,18 +378,18 @@ L72 43.2" style="fill:none;stroke:#000000;"/>
<g id="legend_1">
<g id="patch_7">
<path d="
-M133.338 97.1659
-L267.709 97.1659
-L267.709 50.4
-L133.338 50.4
-L133.338 97.1659
+M79.2 381.6
+L213.571 381.6
+L213.571 334.834
+L79.2 334.834
+L79.2 381.6
z
" style="fill:#ffffff;stroke:#000000;"/>
</g>
<g id="line2d_36"/>
<g id="line2d_37">
<g>
- <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="153.497840909" xlink:href="#m0f54036a79" y="62.06175"/>
+ <use style="fill:#0000ff;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="99.36" xlink:href="#m0f54036a79" y="346.495875"/>
</g>
</g>
<g id="text_1">
@@ -410,14 +410,14 @@ L12.4062 0
z
" id="BitstreamVeraSans-Roman-31"/>
</defs>
- <g transform="translate(179.417840909 67.10175)scale(0.144 -0.144)">
+ <g transform="translate(125.28 351.535875)scale(0.144 -0.144)">
<use xlink:href="#BitstreamVeraSans-Roman-31"/>
</g>
</g>
<g id="line2d_38"/>
<g id="line2d_39">
<g>
- <use style="fill:#008000;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="153.497840909" xlink:href="#m365dd9364a" y="83.371125"/>
+ <use style="fill:#008000;stroke:#000000;stroke-linecap:butt;stroke-width:0.5;" x="99.36" xlink:href="#m365dd9364a" y="367.80525"/>
</g>
</g>
<g id="text_2">
@@ -587,7 +587,7 @@ Q26.2656 6.10938 33.4062 6.10938
Q40.5312 6.10938 44.6094 11.75
Q48.6875 17.3906 48.6875 27.2969" id="BitstreamVeraSans-Roman-70"/>
</defs>
- <g transform="translate(179.417840909 88.411125)scale(0.144 -0.144)">
+ <g transform="translate(125.28 372.84525)scale(0.144 -0.144)">
<use xlink:href="#BitstreamVeraSans-Roman-44"/>
<use x="77.001953125" xlink:href="#BitstreamVeraSans-Roman-e9"/>
<use x="138.525390625" xlink:href="#BitstreamVeraSans-Roman-76"/>
View
15 lib/matplotlib/tests/test_legend.py
@@ -26,6 +26,19 @@ def test_legend_auto2():
ax.legend([b1[0], b2[0]], ['up', 'down'], loc=0)
+@image_comparison(baseline_images=['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=0)
+
+
@image_comparison(baseline_images=['legend_various_labels'], remove_text=True)
def test_various_labels():
# tests all sorts of label types
@@ -34,7 +47,7 @@ def test_various_labels():
ax.plot(range(4), 'o', label=1)
ax.plot(np.linspace(4, 4.1), 'o', label=u'D\xe9velopp\xe9s')
ax.plot(range(4, 1, -1), 'o', label='__nolegend__')
- ax.legend(numpoints=1)
+ ax.legend(numpoints=1, loc=0)
@image_comparison(baseline_images=['fancy'], remove_text=True)
View
2  lib/matplotlib/transforms.py
@@ -645,7 +645,7 @@ def count_contains(self, vertices):
dy0 = np.sign(vertices[:, 1] - y0)
dx1 = np.sign(vertices[:, 0] - x1)
dy1 = np.sign(vertices[:, 1] - y1)
- inside = (abs(dx0 + dx1) + abs(dy0 + dy1)) <= 2
+ inside = ((abs(dx0 + dx1) + abs(dy0 + dy1)) == 0)
@mdboom Owner
mdboom added a note

Good catch! I'm not sure what my original thinking was here, but it doesn't make much sense to me now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
return np.sum(inside)
def count_overlaps(self, bboxes):
Something went wrong with that request. Please try again.