Hello all,

I have written a small patch which extends the functionality of
Figure.legend and pyplot.figlegend to match that of Axes.legend.

This patch allows figlegend to automatically build a legend for lines with the "label" property set when figlegend is called without a list of strings or object handles.

Also, the "loc" argument is made optional, and defaults to the upper right, same as Axes.legend.

I hope the attached patch is suitable for inclusion. I have also attached a test script showing each of the call signatures.

Thanks,
Ray Speth

 lib/matplotlib/figure.py |  119 +++++++++++++++++++++++++++++++++++-----------
 lib/matplotlib/pyplot.py |   13 ++++-
 2 files changed, 102 insertions(+), 30 deletions(-)

diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py
index 36fe423..8204ddd 100644
--- a/lib/matplotlib/figure.py
+++ b/lib/matplotlib/figure.py
@@ -818,33 +818,43 @@ class Figure(Artist):
     def get_axes(self):
         return self.axes
 
-    def legend(self, handles, labels, *args, **kwargs):
-        """
-        Place a legend in the figure.  Labels are a sequence of
-        strings, handles is a sequence of
-        :class:`~matplotlib.lines.Line2D` or
-        :class:`~matplotlib.patches.Patch` instances, and loc can be a
-        string or an integer specifying the legend location
-
-        USAGE::
-
-          legend( (line1, line2, line3),
-                  ('label1', 'label2', 'label3'),
-                  'upper right')
-
-        The *loc* location codes are::
-
-          'best' : 0,          (currently not supported for figure legends)
-          'upper right'  : 1,
-          'upper left'   : 2,
-          'lower left'   : 3,
-          'lower right'  : 4,
-          'right'        : 5,
-          'center left'  : 6,
-          'center right' : 7,
-          'lower center' : 8,
-          'upper center' : 9,
-          'center'       : 10,
+    def legend(self, *args, **kwargs):
+        """
+        call signatures::
+
+          legend()
+          legend(labels)
+          legend(loc)
+          legend(labels, loc)
+          legend(handles, labels)
+          legend(handles, labels, loc)
+
+        Place a legend in the figure. *labels* is a sequence of
+        strings. *handles* is a sequence of
+        :class:`~matplotlib.lines.Line2D`,
+        :class:`~matplotlib.patches.Patch`, or
+        :class:`~matplotlib.collections.RegularPolyCollection`
+        instances. If neither *labels* nor *handles* is specified,
+        legend entries will be created for those line, patch, and
+        collection instances with a *label* property.
+
+        *loc* can be a string or an integer specifying the legend
+        location. The *loc* location codes are::
+
+          ===============   =============
+          Location String   Location Code
+          ===============   =============
+          'upper right'     1
+          'upper left'      2
+          'lower left'      3
+          'lower right'     4
+          'right'           5
+          'center left'     6
+          'center right'    7
+          'lower center'    8
+          'upper center'    9
+          'center'          10
+          ===============   =============
 
         *loc* can also be an (x,y) tuple in figure coords, which
         specifies the lower left of the legend box.  figure coords are
@@ -907,8 +917,61 @@ class Figure(Artist):
 
         .. plot:: mpl_examples/pylab_examples/figlegend_demo.py
         """
+        if len(args)==0:
+            handles = []
+            labels = []
+            for ax in self.get_axes():
+                axhandles, axlabels = ax.get_legend_handles_labels()
+                handles.extend(axhandles)
+                labels.extend(axlabels)
+
+            if len(handles) == 0:
+                warnings.warn("No labeled objects found. "
+                              "Use label='...' kwarg on individual plots.")
+                return None
+
+        elif len(args)==1:
+            if is_string_like(args[0]) or isinstance(args[0], int):
+                # LOC
+                kwargs['loc'] = args[0]
+                handles = []
+                labels = []
+                for ax in self.get_axes():
+                    axhandles, axlabels = ax.get_legend_handles_labels()
+                    handles.extend(axhandles)
+                    labels.extend(axlabels)
+
+            else:
+                # LABELS
+                labels = args[0]
+                handles = []
+                for ax in self.get_axes():
+                    handles.extend(ax._get_legend_handles())
+                handles = handles[:len(labels)]
+
+        elif len(args)==2:
+            if is_string_like(args[1]) or isinstance(args[1], int):
+                # LABELS, LOC
+                labels, loc = args
+                handles = []
+                for ax in self.get_axes():
+                    handles.extend(ax._get_legend_handles())
+                handles = handles[:len(labels)]
+                kwargs['loc'] = loc
+            else:
+                # LINES, LABELS
+                handles, labels = args
+
+        elif len(args)==3:
+            # LINES, LABELS, LOC
+            handles, labels, loc = args
+            kwargs['loc'] = loc
+
+        else:
+            raise TypeError('Invalid arguments to legend')
+
         handles = flatten(handles)
-        l = Legend(self, handles, labels, *args, **kwargs)
+        l = Legend(self, handles, labels, **kwargs)
         self.legends.append(l)
         return l
 
diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index e53df1a..9134514 100644
--- a/lib/matplotlib/pyplot.py
+++ b/lib/matplotlib/pyplot.py
@@ -404,8 +404,17 @@ def figimage(*args, **kwargs):
     #sci(ret)  # JDH figimage should not set current image -- it is not mappable, etc
     return ret
 
-def figlegend(handles, labels, loc, **kwargs):
+def figlegend(*args, **kwargs):
     """
+    call signatures::
+
+      figlegend()
+      figlegend(labels)
+      figlegend(loc)
+      figlegend(labels, loc)
+      figlegend(handles, labels)
+      figlegend(handles, labels, loc)
+
     Place a legend in the figure.
 
     *labels*
@@ -432,7 +441,7 @@ def figlegend(handles, labels, loc, **kwargs):
        :func:`~matplotlib.pyplot.legend`
 
     """
-    l = gcf().legend(handles, labels, loc, **kwargs)
+    l = gcf().legend(*args, **kwargs)
     draw_if_interactive()
     return l
 
-- 
1.6.0.4

#!/usr/bin/python
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

def makefig():
    f = plt.figure()
    s1 = plt.subplot(2,1,1)
    s2 = plt.subplot(2,1,2)
    h1 = s1.plot(x, x**2, 'ro-',label='square')
    h2 = s2.plot(x, x**0.5, 'g--', label='sqrt')
    return h1,h2

# none (loc->upper right)
makefig()
plt.figlegend()

# loc
makefig()
plt.figlegend('center')

# labels
makefig()
plt.figlegend(['thing1','thing2'])

# labels, loc
makefig()
plt.figlegend(['foo','bar'],'center left')

# lines, labels
h1,h2 = makefig()
plt.figlegend([h1,h2],['foo','bar'])

# lines, labels, loc
h1,h2 = makefig()
plt.figlegend([h2,h1],['bar','foo'],'upper left')

plt.show()
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to