Movable Legend

View: New views
4 Messages — Rating Filter:   Alert me  

Movable Legend

by Andrea Gavana :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi All,

    a while ago, Che posted a nice example on how to drag a legend
with the mouse. I have upgraded to matplotlib 0.99.1 and it looks like
the nice example is not working anymore: for the life of me I can't
figure out what's wrong. I attach the runnable sample submitted
originally.

Any suggestion regarding what's wrong with the code?

Thank you in advance.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
http://thedoomedcity.blogspot.com/

#Boa:Frame:Frame1

import wx

import matplotlib
matplotlib.interactive(True)
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure

def create(parent):
    return Frame1(parent)

[wxID_FRAME1, wxID_FRAME1NOTEBOOK1, wxID_FRAME1PANEL1,
] = [wx.NewId() for _init_ctrls in range(3)]

class PlotPanel(wx.Panel):    
    def __init__(self, parent,id = -1, color = None,\
        dpi = None, style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
        self.gotLegend = 0  #to begin, legend is not picked.
       
        self.parent = parent
        self.line_collections_list = []

        wx.Panel.__init__(self, parent, **kwargs)
       
        self.figure = Figure(None, dpi)
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )

        #Connect all the mpl events
        self.canvas.mpl_connect('motion_notify_event', self.on_motion)
        self.canvas.mpl_connect('pick_event', self.on_pick)
        self.canvas.mpl_connect('button_release_event', self.on_release)

        self._SetInitialSize()
       
        self.Bind(wx.EVT_SIZE, self._onSize)

        self.draw()

    #a few sizing issues, not relevant to this draggable legend point.
    def _onSize(self, event):
        self._SetSize()
        event.Skip()
       
    def _SetSize( self ):
        pixels = tuple( self.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )
   
    def _SetInitialSize(self,):
        pixels = self.parent.GetClientSize()
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches( (pixels[0])/self.figure.get_dpi(),
         (pixels[1])/self.figure.get_dpi(), forward=True )
       
    def draw(self):
        self.subplot = self.figure.add_subplot(111)
        line, = self.subplot.plot([1],[6],'o',picker=5)
        if self.gotLegend == 0:  #need to prevent it from keep appending each time if it is just moving legend.
            self.line_collections_list.append(line)    
       
        #Legend.
        self.legend = self.subplot.legend(self.line_collections_list, ['1'], numpoints=1)
        self.legend.set_picker(self.my_legend_picker)
       
    #pick up the legend patch
    def my_legend_picker(self, legend, event):
        return self.legend.legendPatch.contains(event)  
   
    #pick the legend
    def on_pick(self, event):    
        legend = self.legend
        if event.artist == legend:
            bbox = self.legend.get_window_extent()  #gets the box of the legend.
            self.mouse_x = event.mouseevent.x  #get mouse coordinates at time of pick.
            self.mouse_y = event.mouseevent.y
            print 'mouse x position at pick time', self.mouse_x
            print 'mouse y position at pick time', self.mouse_y
            self.legend_x = bbox.xmin          #get legend coordinates at time of pick.
            self.legend_y = bbox.ymin
            print 'Legend x position @ pick time = ', self.legend_x
            print 'Legend y position @ pick time= ', self.legend_y
            self.gotLegend = 1  #indicates we picked up the legend.

    #drag the legend
    def on_motion(self, event):  
        if self.gotLegend == 1:
            x = mouse_diff_x = self.mouse_x - event.x  #how much the mouse moved.
            y = mouse_diff_y = self.mouse_y - event.y
           
            print 'motion_event.x =', event.x
            print 'motion_event.y =', event.y
            print 'mouse moved x = ', mouse_diff_x
            print 'mouse moved y = ', mouse_diff_y
           
            #move the legend from its previous location by that same amount
            loc_in_canvas = self.legend_x - mouse_diff_x, self.legend_y - mouse_diff_y
            #transform into legend coordinate system
            loc_in_norm_axes = self.legend.parent.transAxes.inverted().transform_point(loc_in_canvas)
            self.legend._loc = tuple(loc_in_norm_axes)
           
            self.canvas.draw()
       
    #release the legend    
    def on_release(self, event):
        if self.gotLegend == 1:
            self.gotLegend = 0
            print 'legend released'
           
class Frame1(wx.Frame):
    def _init_coll_boxSizer1_Items(self, parent):
        # generated method, don't edit

        parent.AddWindow(self.notebook1, 1, border=0, flag=wx.EXPAND)

    def _init_sizers(self):
        # generated method, don't edit
        self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)

        self._init_coll_boxSizer1_Items(self.boxSizer1)

        self.panel1.SetSizer(self.boxSizer1)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(333, 202), size=wx.Size(592, 474),
              style=wx.DEFAULT_FRAME_STYLE,
              title='moving the legend accurately')
        self.SetClientSize(wx.Size(584, 440))

        self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(584, 440),
              style=wx.TAB_TRAVERSAL)

        self.notebook1 = wx.Notebook(id=wxID_FRAME1NOTEBOOK1, name='notebook1',
              parent=self.panel1, pos=wx.Point(0, 0), size=wx.Size(584, 440),
              style=0)

        self._init_sizers()

    def __init__(self, parent):
        self._init_ctrls(parent)
        graph = PlotPanel(self.notebook1)    
        self.notebook1.AddPage(graph,'graph')

if __name__ == '__main__':
    app = wx.PySimpleApp(0)  #set to wx.PySimpleApp() for no stdout window.
    frame = create(None)
    frame.Show()

    app.MainLoop()

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Re: Movable Legend

by Jae-Joon Lee :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This is a known bug. While this is fixed in the svn, this did go into
the maint. branch.
As a workaround, add the following line after line 70.

        self.legend.set_axes(self.subplot)

Regards,

-JJ


On Mon, Oct 26, 2009 at 9:44 AM, Andrea Gavana <andrea.gavana@...> wrote:

> Hi All,
>
>    a while ago, Che posted a nice example on how to drag a legend
> with the mouse. I have upgraded to matplotlib 0.99.1 and it looks like
> the nice example is not working anymore: for the life of me I can't
> figure out what's wrong. I attach the runnable sample submitted
> originally.
>
> Any suggestion regarding what's wrong with the code?
>
> Thank you in advance.
>
> Andrea.
>
> "Imagination Is The Only Weapon In The War Against Reality."
> http://xoomer.alice.it/infinity77/
> http://thedoomedcity.blogspot.com/
>
> ------------------------------------------------------------------------------
> Come build with us! The BlackBerry(R) Developer Conference in SF, CA
> is the only developer event you need to attend this year. Jumpstart your
> developing skills, take BlackBerry mobile applications to market and stay
> ahead of the curve. Join us from November 9 - 12, 2009. Register now!
> http://p.sf.net/sfu/devconference
> _______________________________________________
> Matplotlib-users mailing list
> Matplotlib-users@...
> https://lists.sourceforge.net/lists/listinfo/matplotlib-users
>
>

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Re: Movable Legend

by Andrea Gavana :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Jae-Joon,

2009/10/26 Jae-Joon Lee:
> This is a known bug. While this is fixed in the svn, this did go into
> the maint. branch.
> As a workaround, add the following line after line 70.
>
>        self.legend.set_axes(self.subplot)

Thank you for your help, it works perfectly.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
http://thedoomedcity.blogspot.com/

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Re: Movable Legend

by Gökhan SEVER-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This movable legend is a good idea on plots, especially if there are many elements on one figure. However a few notes that I would like to add:

1-) So many lines of code. Makes it hard to read when I share the code with someone else. Would be so much better to have a functionality like:
plt.legend(movable=True). I might add this into the feature request page, if one hasn't submitted yet.

2-) When I move the legend out of a canvas area, I can't bring back into the canvas, nor move it any longer.

3-) The rest of the toolbox items are gone. How to zoom or pan when I have a moving legend?

Regards,

On Tue, Oct 27, 2009 at 10:21 AM, Andrea Gavana <andrea.gavana@...> wrote:
Hi Jae-Joon,

2009/10/26 Jae-Joon Lee:
> This is a known bug. While this is fixed in the svn, this did go into
> the maint. branch.
> As a workaround, add the following line after line 70.
>
>        self.legend.set_axes(self.subplot)

Thank you for your help, it works perfectly.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
http://thedoomedcity.blogspot.com/

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users



--
Gökhan

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@...
https://lists.sourceforge.net/lists/listinfo/matplotlib-users