fill_between, legends, and "label" parameter

Hi,

I have a piece of code that creates a plot without warning when using just fill(), but gives a warning when using fill_between() because that function doesn't seem to actually do register values passed to it by the "label" parameter.

The warning happens when I try to make a legend after using fill_between():
      /cms/sw/python/2.5/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-x86_64.egg/matplotlib/axes.py:4014: UserWarning: No labeled objects found. Use label='...' kwarg on individual plots.
   warnings.warn("No labeled objects found. "

In essence this code works fine when I use fill() rather than fill_between():

···

--------------------
for column in sorted(yValues):
  ax.fill_between(xValues, yValues[column], label=column)

legend = plt.legend(bbox_to_anchor=(1.3, 1), shadow=True, fancybox=True)
--------------------

That is, the legend finds the labels when I use fill(), but not when I use fill_between().

Why is that?
Mike

Why is that?

"fill" creates Patches
(http://matplotlib.sourceforge.net/api/artist_api.html?highlight=patch#matplotlib.patches.Patch)
but fill_between creates PolyCollection
(http://matplotlib.sourceforge.net/api/collections_api.html?highlight=polycollection#matplotlib.collections.PolyCollection).
And, unfortunately, PolyCollection is currently not supported with
legend (it would be better if the error message is more meaningful
though).

If you want to have a legend for PolyCollection, you may use a proxy artist.

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

Regards,

-JJ

If you want to have a legend for PolyCollection, you may use a proxy artist.

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

Thanks for the link! Although, it seems that legend does not support PolyCollection at all:

   "Remember that some pyplot commands return artist not supported by legend, e.g., fill_between() returns PolyCollection that is not supported."

so that even trying to use a proxy artist results in an error (shown at bottom), with the code here:

···

------------------------------
listOfThingsPlotted =
listOfLegendLabels =
for column in sorted(yValues):
     temp = ax.fill_between(xValues, yValues[column], label=column)
     listOfThingsPlotted.append(temp)
     listOfLegendLabels.append(column)

     legend = plt.legend(listOfThingsPlotted,listOfLegendLabels,bbox_to_anchor=(1.25, 1), shadow=True, fancybox=True)
------------------------------

Error:
------------------------------
Traceback (most recent call last):
   File "/cms/cmsprod/bin/prodJobMonitorPlots_matplotlib.py", line 117, in <module>
     plotStackedJobsVsTime(inputFile, outputFile, outputTitle)
   File "/cms/cmsprod/bin/prodJobMonitorPlots_matplotlib.py", line 93, in plotStackedJobsVsTime
     legend = plt.legend(listOfThingsPlotted,listOfLegendLabels,bbox_to_anchor=(1.25, 1), shadow=True, fancybox=True) # Make legend
   File "/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/pyplot.py", line 2437, in legend
     ret = gca().legend(*args, **kwargs)
   File "/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/axes.py", line 4044, in legend
     self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
   File "/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/legend.py", line 304, in __init__
     self._init_legend_box(handles, labels)
   File "/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/legend.py", line 582, in _init_legend_box
     handlebox.add_artist(handle)
   File "/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/offsetbox.py", line 475, in add_artist
     a.set_transform(self.get_transform())
AttributeError: 'NoneType' object has no attribute 'set_transform'

I think you misunderstood what I meant by proxy artist (I'm not sure
if this is a right choice of the word, as a matter of fact).

Again, PolyCollection instance that is returned by fill_between is not
supported by legend.
Therefore, you have to use other kind of artist (which I call proxy
artist) that is supported.
The example I linked just show how to use Rectangle as a proxy.

-JJ

···

On Thu, Oct 22, 2009 at 4:18 PM, Mike Anderson <mbanderson@...150...> wrote:

If you want to have a legend for PolyCollection, you may use a proxy
artist.

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

Thanks for the link! Although, it seems that legend does not support
PolyCollection at all:

"Remember that some pyplot commands return artist not supported by legend,
e.g., fill_between() returns PolyCollection that is not supported."

so that even trying to use a proxy artist results in an error (shown at
bottom), with the code here:
------------------------------
listOfThingsPlotted =
listOfLegendLabels =
for column in sorted(yValues):
temp = ax.fill_between(xValues, yValues[column], label=column)
listOfThingsPlotted.append(temp)
listOfLegendLabels.append(column)

legend =
plt.legend(listOfThingsPlotted,listOfLegendLabels,bbox_to_anchor=(1.25, 1),
shadow=True, fancybox=True)
------------------------------

Error:
------------------------------
Traceback (most recent call last):
File "/cms/cmsprod/bin/prodJobMonitorPlots_matplotlib.py", line 117, in
<module>
plotStackedJobsVsTime(inputFile, outputFile, outputTitle)
File "/cms/cmsprod/bin/prodJobMonitorPlots_matplotlib.py", line 93, in
plotStackedJobsVsTime
legend =
plt.legend(listOfThingsPlotted,listOfLegendLabels,bbox_to_anchor=(1.25, 1),
shadow=True, fancybox=True) # Make legend
File
"/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/pyplot.py",
line 2437, in legend
ret = gca().legend(*args, **kwargs)
File
"/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/axes.py",
line 4044, in legend
self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
File
"/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/legend.py",
line 304, in __init__
self._init_legend_box(handles, labels)
File
"/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/legend.py",
line 582, in _init_legend_box
handlebox.add_artist(handle)
File
"/afs/hep.wisc.edu/cms/sw/python/x86/2.5.4/lib/python2.5/site-packages/matplotlib-0.99.1.1_r0-py2.5-linux-i686.egg/matplotlib/offsetbox.py",
line 475, in add_artist
a.set_transform(self.get_transform())
AttributeError: 'NoneType' object has no attribute 'set_transform'