Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing the legend fontsize "hides" dotted lines in the legend #3171

Closed
dawehner opened this issue Jun 30, 2014 · 15 comments
Closed

Changing the legend fontsize "hides" dotted lines in the legend #3171

dawehner opened this issue Jun 30, 2014 · 15 comments

Comments

@dawehner
Copy link

When you change the fontsize of legends using matplotlib.rcParams['legend.fontsize'] you get some kind of crippled result bag. The line in the legend is not shown 100%

http://nbviewer.ipython.org/76ad2a8053ef0b01a7bd

It seems to be that the font properties are somehow applied to the line itself.

@dawehner
Copy link
Author

You can fix it by using numpoints=1 as part of the legend call but this should not happen in the first place if you ask me.

@tacaswell
Copy link
Member

I don't see what is wrong.

Please post code + images directly on github, the link to your notebook will rot making this report useless.

@dawehner
Copy link
Author

Well, the URL encodes the unique ID of the gist, so this notebook with rot much like github could do.

The plotting code:

x = np.linspace(0.0, 2*np.pi, 200)
y = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y, '--', label='Sin')
plt.plot(x, y2, '-.', label='Sin')

plt.legend()

One time with

matplotlib.rcParams['legend.fontsize'] = 'large' # the default value

and once with

matplotlib.rcParams['legend.fontsize'] = 9

Here are the pictures from the notebook.

size-large
size-9

@dawehner
Copy link
Author

The difference is in the legend itself. The second example does somehow not show the full line, so "--" is kind of crippled towards "-."

@tacaswell tacaswell added this to the v1.4.x milestone Jun 30, 2014
@tacaswell
Copy link
Member

The way that the legend is drawn is it adds another Line2D artist (called the handle) with the same linestyle as the line you want to add to the legend. I suspect what is going on is that the length of the artist in the legend scales with the font size so as you make the mark get shorter. At some point it gets too short to capture a full dash cycle.

The length of the handle is controlled by the rcparam legend.handlelength (or the handlelength kwargs to legend()) . The length is specified as a multiple of the font size (hency why it scales) and the default value is tuned to look good with the default font. If you want to use a smaller font just make handlelength longer:

x = np.linspace(0.0, 2*np.pi, 200)
y = np.sin(x)
y2 = np.cos(x)
fig, ax = plt.subplots()
ax.plot(x, y, '--', label='Sin')
ax.plot(x, y2, '-.', label='cos')

ax.legend(fontsize=9, handlelength=3)

@tacaswell tacaswell removed this from the v1.4.x milestone Jun 30, 2014
@dawehner
Copy link
Author

As written before, there are workarounds, though the question is whether matplotlib could do anything to prevent this from happening.

@tacaswell
Copy link
Member

I disagree that what I suggested is a 'workaround', in all cases the library is doing exactly what you are (implicitly through rcparams) telling it to do. That is, all of the code in behaving as-advertised so there is no bug.

Currently the legend code does not make any attempt introspect the artists being used as handles to guess at what 'good' value are.

@dawehner
Copy link
Author

Good point. Thank you for the detailed explanation.

On Mon, Jun 30, 2014 at 3:00 PM, Thomas A Caswell notifications@github.com
wrote:

I disagree that what I suggested is a 'workaround', in all cases the
library is doing exactly what you are (implicitly through rcparams)
telling it to do. That is, all of the code in behaving as-advertised so
there is no bug.

Currently the legend code does not make any attempt introspect the artists
being used as handles to guess at what 'good' value are.


Reply to this email directly or view it on GitHub
#3171 (comment)
.

@WeatherGod
Copy link
Member

I would like to note that even I have never notice the handlelength feature
before. I am of the belief that most "bugs" are really due to the lack of
good documentation. The rest of them are usually from bad design choices
(he mutters to himself while still wrestling with refactoring color
cycling...)

And no, just simply presenting the attributes in a table isn't
necessarially good documentation...

On Mon, Jun 30, 2014 at 9:18 AM, Daniel Wehner notifications@github.com
wrote:

Good point. Thank you for the detailed explanation.

On Mon, Jun 30, 2014 at 3:00 PM, Thomas A Caswell <
notifications@github.com>
wrote:

I disagree that what I suggested is a 'workaround', in all cases the
library is doing exactly what you are (implicitly through rcparams)
telling it to do. That is, all of the code in behaving as-advertised so
there is no bug.

Currently the legend code does not make any attempt introspect the
artists
being used as handles to guess at what 'good' value are.


Reply to this email directly or view it on GitHub
<
https://github.com/matplotlib/matplotlib/issues/3171#issuecomment-47528184>

.


Reply to this email directly or view it on GitHub
#3171 (comment)
.

@dawehner
Copy link
Author

dawehner commented Jul 1, 2014

Well yeah as a user of matplotlib I love how simple things can be done really easy but it is kind of sad how many details you have to know to get done slightly more complex things.

@pmreyes2
Copy link

I wanted to point out, that when using LineCollection, there is a mismatch of the size of the lines in the plot and the lines of the handle in the legend. Since the lines of the handle are larger than those from the plot, handlelength needs to be used, but the problem is that the lines in the legend are still larger. See this example:

lines1 = [[(0, .5), (.5, 1)], [(.3, .6), (.2, .2)]]
lines2 = [[[0.7, .2], [.8, .4]], [[.5, .7], [.6, .1]]]
lc1 = matplotlib.collections.LineCollection(lines1, linestyles="--")
lc2 = matplotlib.collections.LineCollection(lines2, linestyles="-.")
fig, ax = plt.subplots()
ax.add_collection(lc1)
ax.add_collection(lc2)
ax.legend([lc1,lc2],["line1","line2"],handlelength=3)

fig1

@dopplershift
Copy link
Contributor

@pmreyes2 Are you talking about the thickness of the lines? If so, does the following (running against matplotlib 2.0rc2) look better?

test-handle

@pmreyes2
Copy link

pmreyes2 commented Jan 12, 2017

@dopplershift In your plot I still see different size of lines (in thickness and in dash spacing) I would prefer if the lines in the legend match the lines in the plot as it does when using Line2D . I did my previous plot using version 2.0.0b4. I just tried same code (only handlelength=3 was not needed ) in a previous version: 1.5.3 and lines sizes/styles match. So something got changed with the newer versions of matplotlib.

oqygqaaaabjru5erkjggg

@tacaswell
Copy link
Member

this is probably fall out from making the dash pattern scale with line width and the LineCollection legend handler pulling linestyle instead of dash pattern.

@pmreyes2 You are definitely hitting a different issue that the OP, can you please open a new issue?

@pmreyes2
Copy link

@tacaswell I've just created a new issue: #7814

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants