Legend and proxy artists

Adam,

Your example is not complete. I don't understand the value variable that you are iterating over, or how it affects the different plots you are making.

I would guess that the problem is that you have a list of tuples of handles for value_plot, instead of a list of handles. Note that each of the plot_date commands returns a length=1 tuple of lines. So you should pick out the first item of each tuple, and you probably only need the 1st item of the value_plot list, since you only give 3 labels.

-Sterling

PS Sorry if somebody already responded; I get my list mail in digests.

···

From: Adam Mercer <ramercer@...287...>
Date: October 27, 2011 6:12:50 AM PDT
To: matplotlib-users@lists.sourceforge.net
Subject: [Matplotlib-users] Legend and proxy artists

Hi

I have recently updated to Matplotlib-1.1.0 and now one of my scripts
displays the following warning:

UserWarning: Legend does not support [[<matplotlib.lines.Line2D object
at 0x1026296d0>]]
Use proxy artist instead.

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

The link it refers to doesn't seem to be much help, and I can't see
what I need to do in order to correctly display the legend. Below is
the appropriate plotting section of my script, could anyone offer
suggestions as to how to correctly display the legend?

# plot size, scale by golden ratio
fig = pyplot.figure()
fig.set_size_inches(10, 10 / ((1 + math.sqrt(5)) / 2))
date_axes = fig.add_subplot(111)

# setup secondary axes
value_axes = date_axes.twinx()

# set plot labels
date_axes.set_xlabel("Date")
date_axes.set_ylabel("Time")
value_axes.set_ylabel("Value")

# produce plot
morning_plot = date_axes.plot_date(morning[:,0], morning[:,1], 'bo-', ms=4)
evening_plot = date_axes.plot_date(evening[:,0], evening[:,1], 'go-', ms=4)
value_plot =
for v in value:
value_plot.append(value_axes.plot_date(w[:,0], w[:,1], 'ro-', ms=4))

# legend
date_axes.legend(([morning_plot], [evening_plot], [value_plot]),
   ("Morning", "Evening", "Value"),
   numpoints=1, loc=0, borderpad=1, shadow=True, fancybox=True)

# save plot
fig.savefig(plot_file)

Cheers

Adam

Your example is not complete. I don't understand the value variable that you are iterating over, or how it affects the different plots you are making.

value is simply a list of different datasets to plot, read in using:

value =
for v_file in glob.glob(value_glob):
  value.append(numpy.atleast_2d(numpy.loadtxt(v_file, converters={0:
dates.datestr2num})))

where value_glob specifies a glob pattern of files to read in.

I would guess that the problem is that you have a list of tuples of handles for value_plot, instead of a list of handles. Note that each of the plot_date commands returns a length=1 tuple of lines. So you should pick out the first item of each tuple, and you probably only need the 1st item of the value_plot list, since you only give 3 labels.

I'm not really following you, do you mean something like the following:

# legend
date_axes.legend(([morning_plot], [evening_plot], [value_plot[0]]),
   ("Morning", "Evening", "Value"),
   numpoints=1, loc=0, borderpad=1, shadow=True, fancybox=True)

as that results in the same errors?

Cheers

Adam

···

On Thu, Oct 27, 2011 at 12:05, Sterling Smith <smithsp@...3304...> wrote:

Adam,

I'm sorry that I wasn't clear before.

Here is a working example:

from pylab import figure, arange
fig = figure(1)
fig.clear()
ax = fig.add_subplot(111)
x = arange(0,1,.25)
y1 = x
y2 = x**2
y3 = x**3
l1 = ax.plot(x,y1,'bo-')
l2 = ax.plot(x,y2,'go-')
l3 =
for xi,x1 in enumerate(x):
  l3.append(ax.plot(x1,y3[xi],'ro-'))
print l1,l2,l3
leg = ax.legend((l1[0],l2[0],l3[0][0]),('x','x^2','x^3'),
  numpoints=1, loc=0, borderpad=1, shadow=True, fancybox=True)

Note that when l1 and l2 are printed that they are 1-element lists, and l3 is a list of 1-element lists, all of which are not the type of handles that legend is looking for. Furthermore, in your code, you are trying to embed these lists in yet another layer of list.

If your code worked as it was with previous versions of matplotlib, then maybe someone with more knowledge could explain what changed to not allow your code to work now (it may be related to Make Figure.legend not to flatten the input handle list by leejjoon · Pull Request #534 · matplotlib/matplotlib · GitHub).

-Sterling

···

On Oct 27, 2011, at 8:32PM, Adam Mercer wrote:

On Thu, Oct 27, 2011 at 12:05, Sterling Smith <smithsp@...3304...> wrote:

Your example is not complete. I don't understand the value variable that you are iterating over, or how it affects the different plots you are making.

value is simply a list of different datasets to plot, read in using:

value =
for v_file in glob.glob(value_glob):
value.append(numpy.atleast_2d(numpy.loadtxt(v_file, converters={0:
dates.datestr2num})))

where value_glob specifies a glob pattern of files to read in.

I would guess that the problem is that you have a list of tuples of handles for value_plot, instead of a list of handles. Note that each of the plot_date commands returns a length=1 tuple of lines. So you should pick out the first item of each tuple, and you probably only need the 1st item of the value_plot list, since you only give 3 labels.

I'm not really following you, do you mean something like the following:

# legend
date_axes.legend(([morning_plot], [evening_plot], [value_plot[0]]),
  ("Morning", "Evening", "Value"),
  numpoints=1, loc=0, borderpad=1, shadow=True, fancybox=True)

as that results in the same errors?

Cheers

Adam

Here is a working example:

from pylab import figure, arange
fig = figure(1)
fig.clear()
ax = fig.add_subplot(111)
x = arange(0,1,.25)
y1 = x
y2 = x**2
y3 = x**3
l1 = ax.plot(x,y1,'bo-')
l2 = ax.plot(x,y2,'go-')
l3 =
for xi,x1 in enumerate(x):
l3.append(ax.plot(x1,y3[xi],'ro-'))
print l1,l2,l3
leg = ax.legend((l1[0],l2[0],l3[0][0]),('x','x^2','x^3'),
numpoints=1, loc=0, borderpad=1, shadow=True, fancybox=True)

OK, you're example works but trying to modify my code is resulting in
the same errors. But it's late so that's a job for tomorrow...

Note that when l1 and l2 are printed that they are 1-element lists, and l3 is a list of 1-element lists, all of which are not the type of handles that legend is looking for. Furthermore, in your code, you are trying to embed these lists in yet another layer of list.

Thanks, this is starting to make sense...

If your code worked as it was with previous versions of matplotlib, then maybe someone with more knowledge could explain what changed to not allow your code to work now (it may be related to Make Figure.legend not to flatten the input handle list by leejjoon · Pull Request #534 · matplotlib/matplotlib · GitHub).

It worked without issue with matplotlib-1.0.1.

Cheers

Adam

···

On Fri, Oct 28, 2011 at 00:56, Sterling Smith <smithsp@...3304...> wrote: