Legend Marker Color Bug

List,

Consider the following script:

import pylab
pylab.plot(pylab.linspace(0,1,100),label='Test',marker='o',ls='')
pylab.plot(pylab.linspace(0,1,100),label='Test2',marker='o',ls='-')
leg=pylab.legend(loc='best')
line=leg.get_lines()
line[0].set_color('black')
line[1].set_color('black')
pylab.draw()

I am attaching the results I see with the TkAgg baackend. I am using version 1.1.0.

I would expect the markers to change colors also. However, I can't seem to find the markers recorded in the legend object to be able to change them. Is this a bug or a feature (resetting the color could lead to inconsistencies between legend and plot)?

Thanks,
Sterling

legend_error.tiff (27.7 KB)

2012/8/28 Sterling Smith <smithsp@...3304...>:

List,

Consider the following script:

import pylab
pylab.plot(pylab.linspace(0,1,100),label='Test',marker='o',ls='')
pylab.plot(pylab.linspace(0,1,100),label='Test2',marker='o',ls='-')
leg=pylab.legend(loc='best')
line=leg.get_lines()
line[0].set_color('black')
line[1].set_color('black')
pylab.draw()

I am attaching the results I see with the TkAgg baackend. I am using version 1.1.0.

I would expect the markers to change colors also. However, I can't seem to find the markers recorded in the legend object to be able to change them. Is this a bug or a feature (resetting the color could lead to inconsistencies between legend and plot)?

I think it's a design issue, there's no connection kept between plot
lines and the legend. You can change colors in the plot an then call
legend again instead.

Cheers

Goyo

That is correct. The lines that one obtains from the get_lines() method of legend are completely new line objects. It is only upon the creation of those lines (at legend creation) that the lines inherit the plot’s line properties.

Now, in the future, it would be nice for artist objects to have shareable “styles”, in which case an edit to a style in one place effects all artists with the same style object. But that might be something reserved for version 2+.

Cheers!
Ben Root

···

On Thu, Aug 30, 2012 at 3:26 PM, Goyo <goyodiaz@…287…> wrote:

2012/8/28 Sterling Smith <smithsp@…3304…>:

List,

Consider the following script:

import pylab

pylab.plot(pylab.linspace(0,1,100),label=‘Test’,marker=‘o’,ls=‘’)

pylab.plot(pylab.linspace(0,1,100),label=‘Test2’,marker=‘o’,ls=‘-’)

leg=pylab.legend(loc=‘best’)

line=leg.get_lines()

line[0].set_color(‘black’)

line[1].set_color(‘black’)

pylab.draw()

I am attaching the results I see with the TkAgg baackend. I am using version 1.1.0.

I would expect the markers to change colors also. However, I can’t seem to find the markers recorded in the legend object to be able to change them. Is this a bug or a feature (resetting the color could lead to inconsistencies between legend and plot)?

I think it’s a design issue, there’s no connection kept between plot

lines and the legend. You can change colors in the plot an then call

legend again instead.

Cheers

Goyo

Ben, Goyo,

Thank you for taking the time to consider my question. I'm sorry that I didn't pose my question correctly. I should have said: 'Consider the _results_ of the following script:' I originally tried to attach the results I obtained, which showed no change in color for the markers in the legend, while the line connecting the markers in the legend did change color.

I understand that the lines in the legend are new objects; this is desirable in my case because I have the same symbol with different colors, where the color means one thing (plasma condition), but the symbol means something else (simulated vs measured). So it makes sense for the markers in the legend describing the meaning of the symbols to be black, as opposed to any of the colors of the markers. However, setting the legend's new line2d object color properties does not change the appearance of the marker in the legend, only the appearance of the line. I suspect that this is because the legend marker is drawn separately from the legend line to accommodate the numpoints argument of the legend functions. Then the question is how to access these markers if they are separate from the line2d objects in the legend. I didn't even see them in the children of the legend [legend.get_children()].

Thank you for your attention,
Sterling

···

On Aug 30, 2012, at 12:35PM, Benjamin Root wrote:

On Thu, Aug 30, 2012 at 3:26 PM, Goyo <goyodiaz@...287...> wrote:
2012/8/28 Sterling Smith <smithsp@...3304...>:
> List,
>
> Consider the following script:
>
> import pylab
> pylab.plot(pylab.linspace(0,1,100),label='Test',marker='o',ls='')
> pylab.plot(pylab.linspace(0,1,100),label='Test2',marker='o',ls='-')
> leg=pylab.legend(loc='best')
> line=leg.get_lines()
> line[0].set_color('black')
> line[1].set_color('black')
> pylab.draw()
>
> I am attaching the results I see with the TkAgg baackend. I am using version 1.1.0.
>
> I would expect the markers to change colors also. However, I can't seem to find the markers recorded in the legend object to be able to change them. Is this a bug or a feature (resetting the color could lead to inconsistencies between legend and plot)?

I think it's a design issue, there's no connection kept between plot
lines and the legend. You can change colors in the plot an then call
legend again instead.

Cheers

Goyo

That is correct. The lines that one obtains from the get_lines() method of legend are completely new line objects. It is only upon the creation of those lines (at legend creation) that the lines inherit the plot's line properties.

Now, in the future, it would be nice for artist objects to have shareable "styles", in which case an edit to a style in one place effects all artists with the same style object. But that might be something reserved for version 2+.

Cheers!
Ben Root

2012/8/30 Sterling Smith <smithsp@...3304...>:

Thank you for taking the time to consider my question. I'm sorry that I didn't pose my question correctly. I should have said: 'Consider the _results_ of the following script:' I originally tried to attach the results I obtained, which showed no change in color for the markers in the legend, while the line connecting the markers in the legend did change color.

Actualy your question is correctly posted but I misread it. Calling
set_color changes only the line color, not the markers. This is
expected and documented behavoir. There are separate methods for the
markers:

line[0].set_markerfacecolor
line[0].set_markeredgecolor

See http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.lines.Line2D

Regards

Goyo

2012/8/30 Sterling Smith <smithsp@...3304...>:

Thank you for taking the time to consider my question. I'm sorry that I didn't pose my question correctly. I should have said: 'Consider the _results_ of the following script:' I originally tried to attach the results I obtained, which showed no change in color for the markers in the legend, while the line connecting the markers in the legend did change color.

Actualy your question is correctly posted but I misread it. Calling
set_color changes only the line color, not the markers. This is
expected and documented behavoir. There are separate methods for the
markers:

line[0].set_markerfacecolor
line[0].set_markeredgecolor

See http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.lines.Line2D

Regards

Goyo

Goyo,

Again I thank you for taking time to look into this. You are correct that there are separate functions for setting the marker properties vs the line properties. However, I have tried your solution, and it does not work. Given the following code:

import pylab
pylab.plot(pylab.linspace(0,1,100),label='Test',marker='o',ls='')
pylab.plot(pylab.linspace(0,1,100),label='Test2',marker='o',ls='-')
leg=pylab.legend(loc='best')
line=leg.get_lines()
line[0].set_markerfacecolor('black')
line[1].set_markerfacecolor('black')
pylab.draw()

I still do not get black markers. Furthermore, if you try to make a new legend with the result of leg.get_lines(), you will get lines without markers, which leads me to the conclusion I stated in my previous email (which you did not copy)

I suspect that this is because the legend marker is drawn separately from the legend line to accommodate the numpoints argument of the legend functions. Then the question is how to access these markers if they are separate from the line2d objects in the legend. I didn't even see them in the children of the legend [legend.get_children()].

Thanks,
Sterling

···

On Aug 31, 2012, at 11:29AM, Goyo wrote:

This is correct. To support legend handle like --o-- (i.e., no markers
at the ends), lines and markers are drawn as a separate artist. You
may use something like,

line[0]._legmarker.set_markerfacecolor('black')
line[1]._legmarker.set_markerfacecolor('black')

I, personally, recommend you to use a proxy artist.

http://matplotlib.sourceforge.net/users/legend_guide.html#using-proxy-artist

For example,

You may do something like

import pylab
pylab.plot(pylab.linspace(0,1,100),marker='o',ls='')
pylab.plot(pylab.linspace(0,1,100),marker='o',ls='-')

# creates artists for legend purpose only
l1, = pylab.plot(pylab.linspace(0,1,100), 'ko-')
l2, = pylab.plot(pylab.linspace(0,1,100), 'ko')
# remove them from the axes.
l1.remove()
l2.remove()

leg=pylab.legend([l1, l2], ["Test 1", "Test 2"], loc='best')

Regards,

-JJ

···

On Wed, Sep 5, 2012 at 6:05 AM, Sterling Smith <smithsp@...3304...> wrote:

I still do not get black markers. Furthermore, if you try to make a new legend with the result of leg.get_lines(), you will get lines without markers, which leads me to the conclusion I stated in my previous email (which you did not copy)

I suspect that this is because the legend marker is drawn separately from the legend line to accommodate the numpoints argument of the legend functions. Then the question is how to access these markers if they are separate from the line2d objects in the legend. I didn't even see them in the children of the legend [legend.get_children()].

JJ,

Thank you for responding. I was looking for the _legmarker method, which works great.

Thanks,
Sterling

···

On Sep 4, 2012, at 5:33PM, Jae-Joon Lee wrote:

On Wed, Sep 5, 2012 at 6:05 AM, Sterling Smith <smithsp@...3304...> wrote:

I still do not get black markers. Furthermore, if you try to make a new legend with the result of leg.get_lines(), you will get lines without markers, which leads me to the conclusion I stated in my previous email (which you did not copy)

I suspect that this is because the legend marker is drawn separately from the legend line to accommodate the numpoints argument of the legend functions. Then the question is how to access these markers if they are separate from the line2d objects in the legend. I didn't even see them in the children of the legend [legend.get_children()].

This is correct. To support legend handle like --o-- (i.e., no markers
at the ends), lines and markers are drawn as a separate artist. You
may use something like,

line[0]._legmarker.set_markerfacecolor('black')
line[1]._legmarker.set_markerfacecolor('black')

I, personally, recommend you to use a proxy artist.

http://matplotlib.sourceforge.net/users/legend_guide.html#using-proxy-artist

For example,

You may do something like

import pylab
pylab.plot(pylab.linspace(0,1,100),marker='o',ls='')
pylab.plot(pylab.linspace(0,1,100),marker='o',ls='-')

# creates artists for legend purpose only
l1, = pylab.plot(pylab.linspace(0,1,100), 'ko-')
l2, = pylab.plot(pylab.linspace(0,1,100), 'ko')
# remove them from the axes.
l1.remove()
l2.remove()

leg=pylab.legend([l1, l2], ["Test 1", "Test 2"], loc='best')

Regards,

-JJ