1

I am trying to generate a custom legend handler in matplotlib via looping over data. This handler includes a picture and a line, as kindly explained here (see: Replace Matplotlib legend's labels with image). I understood that handler_map always updates the previous handler, therefore I generate it after plotting my lines. My problem is that the legend does not stay in the legend box but parts of it are outside the box. With the class described in the link above this piece of code reproduces the error:

class HandlerLineImage(HandlerBase):
 def __init__(self,path,space=15,offset=10):
  self.space=space
  self.offset=offset
  self.image_data = plt.imread(path)
  super(HandlerLineImage, self).__init__()

 def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans):
  l = matplotlib.lines.Line2D([xdescent+self.offset,xdescent+(width-self.space)/3.+self.offset],[ydescent+height/2., ydescent+height/2.])
  l.update_from(orig_handle)
  l.set_clip_on(False)
  l.set_transform(trans)
  bb = Bbox.from_bounds(xdescent +(width+self.space)/3.+self.offset,ydescent,height*self.image_data.shape[1]/self.image_data.shape[0],height)
  tbb = TransformedBbox(bb, trans)
  image = BboxImage(tbb)
  image.set_data(self.image_data)
  self.update_prop(image, orig_handle, legend)
  return [l,image]

def plotting(x_axis, y_axis, fig, color, lineliste, handler_map, legendliste):
 picturepath = path
 ax = fig.add_subplot(111)
 line, =  plt.plot(x_axis,y_axis, c=color)
 lineliste.append(line)
 handler_map[line] = HandlerLineImage(picturepath)
 legendliste.append('')
 return fig, lineliste, handler_map, legendliste


def main():
 fig = plt.figure()
 list_plotting=[[0,1,3,5], [0,0.1,0.2,0.3], [1,5,9,12], [0,1,1,3], [5,5,4,3], [8,7,6,5,]]
 lineliste = []
 legendliste = []
 handler_map = dict()
 plt.xlabel('values')
 colors = iter(cm.nipy_spectral(np.linspace(0, 1, len(list_plotting))))
 cnt_style = 0
 cnt_element = 0
 for element in list_plotting:
  x_values=range(len(element))
  y_values=element
  fig, lineliste, handler_map, legendliste = plotting(x_values, y_values, fig, next(colors), lineliste, handler_map, legendliste)
 plt.legend(handles = lineliste, labels = legendliste, handler_map = handler_map, handlelength=4, labelspacing=0.0, fontsize=36, borderpad=0.1, handletextpad=0.2, borderaxespad=0.1, handleheight=2, loc='upper center', frameon = True, bbox_to_anchor=(1.35,1.1))
 fig.savefig("output.pdf", format='pdf', bbox_inches='tight')
 plt.close(fig)

if __name__=='__main__':
 main()

I had the idea that anchored_bbox could lead into the right direction, but I was unable to figure it out. Same with AnnotationBbox or the idea that I somehow have to define a BBoxBase, which I also could not figure out. As I am rather new to python/matplotlib and this seems like an unusual/complicated error, I would be really glad if anyone could help!

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
Mary
  • 23
  • 5

0 Answers0