Matplotlib PatchCollection to Legend
<p>Currently, I am trying to make my own custom legend handler by creating a proxy artist (?) patch using PatchCollections and then following <a href="http://matplotlib.org/users/legend_guide.html" rel="nofollow">http://matplotlib.org/users/legend_guide.html</a> to make a custom handler.</p>

<p>However I am running into a roadblock in trying to implement this into the legend. The arguments for legend takes in patches, but not patchcollections.</p>

<pre><code>import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import matplotlib.patches as mpatches
from matplotlib.path import Path
from matplotlib.collections import PatchCollection

fig = plt.figure()
ax = fig.add_subplot(111)

verts1 = [(0.,0.),(0.,1.),(1.,1.),(0.51,0.51),(0.,0.),(0.,0.),]
codes1 = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.MOVETO,Path.CLOSEPOLY,]
path1 = Path(verts1,codes1)
patch1 = mpatches.PathPatch(path1,ls='dashed',ec='red',facecolor="none")


verts2 = [(0.49,0.49),(0.,0.),(1.,0.),(1.,1.),(0.5,0.5),(0.,0.),]
codes2 = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.MOVETO,Path.CLOSEPOLY,]
path2 = Path(verts2,codes2)
patch2 = mpatches.PathPatch(path2,ls='solid',edgecolor='red', facecolor="none")

patch = PatchCollection([patch1,patch2],match_original=True)

ax.set_xlim(-2,2)
ax.set_ylim(-2,2)

ax.add_collection(patch)
</code></pre>

<p><a href="http://i.stack.imgur.com/dZdd0.png" rel="nofollow"><img src="http://i.stack.imgur.com/dZdd0.png" alt="Visual"></a></p>

<p>The above is the code to visualise the handler. Basically a rectangle with the upper triangle as dashed lines and the lower as solid</p>

<p>Using,</p>

<pre><code>plt.legend([patch],["hellocello"],loc='upper right')
</code></pre>

<p>Recreates the error. Is there a workaround?</p>

<p>From the example in this <a href="http://matplotlib.org/users/legend_guide.html#implementing-a-custom-legend-handler" rel="nofollow">section</a>, it looks like you need to define an object and express all coordinates in terms of the handlebox size,</p>

<pre><code>import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import matplotlib.patches as mpatches
from matplotlib.path import Path
from matplotlib.collections import PatchCollection

class AnyObject(object):
    pass

class AnyObjectHandler(object):
    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        width, height = handlebox.width, handlebox.height
        hw = 0.5*width; hh = 0.5*height
        verts1 = [(x0,y0),(x0,y0+height),(x0+width,y0+height),((x0+hw)*1.01,(y0+hh)*1.01),(x0,y0),(x0,y0),]
        codes1 = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.MOVETO,Path.CLOSEPOLY,]
        path1 = Path(verts1,codes1)
        patch1 = mpatches.PathPatch(path1,ls='dashed',ec='red',facecolor="none")

        verts2 = [((x0+hw)*0.99,(y0+hh)*0.99),(x0,y0),(x0+width,y0),(x0+width,y0+height),(x0+hw,y0+hh),(x0,y0),]
        codes2 = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.MOVETO,Path.CLOSEPOLY,]
        path2 = Path(verts2,codes2)
        patch2 = mpatches.PathPatch(path2,ls='solid',edgecolor='red', facecolor="none")

        patch = PatchCollection([patch1,patch2],match_original=True)

        handlebox.add_artist(patch)
        return patch


fig = plt.figure()
ax = fig.add_subplot(111)

ax.set_xlim(-2,2)
ax.set_ylim(-2,2)

plt.legend([AnyObject()], ['hellocello'],
           handler_map={AnyObject: AnyObjectHandler()})

plt.show()
</code></pre>

<p>This seems to work okay with <code>PatchCollection</code>, at least for me on <code>matplotlib</code> version 1.4.3. The result looks like,</p>

<p><a href="http://i.stack.imgur.com/duO0S.png" rel="nofollow"><img src="http://i.stack.imgur.com/duO0S.png" alt="enter image description here"></a></p>

python matplotlib