title: Combine key and mouse button events in wxpython panel using matplotlib
body: <p>In a <code>wxPython</code> panel I want to use <code>matplotlib's</code> <a href="http://matplotlib.org/api/widgets_api.html?highlight=lasso#matplotlib.widgets.Lasso" rel="nofollow">Lasso</a> widget. In my implementation <code>Lasso</code> is used in three different functionalities. Nevertheless, in order to accomplish these functionalities I must combine key events with mouse button events. </p>
  
  <p>By default, the initial <code>Lasso</code> function can be used by pressing the left mouse button. So, for my first functionality I press the left mouse button, select a region of interest and do something with the points included. For the second functionality, I would like to select another region of interest and do something else with these points.I am trying to do that by pressing <code>shift</code>+<code>LMB</code>. Finally, in my third functionality I would like to do something else with the selected points by pressing <code>Ctrl</code>+<code>LMB</code>. </p>
  
  <p>Schematically, I would like to do the following:</p>
  
  <pre><code> if left mouse button is pressed:
      use Lasso and with the included points do the 1st functionality
  
   if shift is press and left mouse button is pressed:
  
     use Lasso and with the included points do the 2nd functionality
  
   if ctrl is press and lmb is also pressed :
      call Lasso and with the included points do the 3rd functionality
  </code></pre>
  
  <p>Unfortunately, I can not achieve my goal and I get the following error: <code>if self.shift_is_held == True:
  AttributeError: object has no attribute 'shift_is_held'</code>. It seems that it can not recognize the button events, while in other cases the <code>widgetlock</code> command seems not to make the axes available.</p>
  
  <p>Here are parts of my code: </p>
  
  <pre><code>def scatter(self,data):
  #create scatter plot
      fig = self._view_frame.figure
      fig.clf()
  
      Data = []
      self.lmans = []
      self.points_colors = []
  
      Data2 = []
      self.lmans_2 = []
  
      Data3 = []
      self.lmans_2 = []
  
  
      ax = fig.add_subplot('111')
  
      datum = []
      datum_2 = []
      datum_3 = []
  
      for x,y in zip(self.data[:,0],self.data[:,1]):
          datum.append(Datum(x,y))
          datum_2.append(Datum2(x,y))
          datum_3.append(Datum3(x,y))
  
  
      ax.scatter(self.data[:, 0], self.data[:, 1], s=150, marker='d')
      ax.set_xlim((min(self.data[:,0]), max(self.data[:,0])))
      ax.set_ylim((min(self.data[:,1]), max(self.data[:,1])))
      ax.set_aspect('auto')
  
      Data.append(datum)
      Data2.append(datum_2)
      Data3.append(datum_3)
      lman = self.LassoManager(ax, datum, Data)
      lman_2 = self.LassoManager2(ax, datum_2, Data2)
      lman_3 = self.LassoManager3(ax, datum_3, Data3)
      fig.canvas.draw()
      self.lmans.append(lman)
      self.lmans_2.append(lman_2)
      self.lmans_3.append(lman_3)
      fig.canvas.mpl_connect('axes_enter_event', self.enter_axes)
  
  
  class Lasso(AxesWidget):
  
  
  """Selection curve of an arbitrary shape.
  
  The selected path can be used in conjunction with
  :func:`~matplotlib.path.Path.contains_point` to select data points
  from an image.
  
  Unlike :class:`LassoSelector`, this must be initialized with a starting
  point `xy`, and the `Lasso` events are destroyed upon release.
  
  Parameters:
  
  *ax* : :class:`~matplotlib.axes.Axes`
      The parent axes for the widget.
  *xy* : array
      Coordinates of the start of the lasso.
  *callback* : function
      Whenever the lasso is released, the `callback` function is called and
      passed the vertices of the selected path.
  
  """
  
  def __init__(self, ax, xy, callback=None, useblit=True):
      AxesWidget.__init__(self, ax)
  
      self.useblit = useblit and self.canvas.supports_blit
      if self.useblit:
          self.background = self.canvas.copy_from_bbox(self.ax.bbox)
  
      x, y = xy
      self.verts = [(x, y)]
      self.line = Line2D([x], [y], linestyle='-', color='black', lw=2)
      self.ax.add_line(self.line)
      self.callback = callback
      self.connect_event('button_release_event', self.onrelease)
      self.connect_event('motion_notify_event', self.onmove)
  
  def onrelease(self, event):
      if self.ignore(event):
          return
      if self.verts is not None:
          self.verts.append((event.xdata, event.ydata))
          if len(self.verts) &gt; 2:
              self.callback(self.verts)
          self.ax.lines.remove(self.line)
      self.verts = None
      self.disconnect_events()
  
  def onmove(self, event):
      if self.ignore(event):
          return
      if self.verts is None:
          return
      if event.inaxes != self.ax:
          return
      if event.button != 1:
          return
      self.verts.append((event.xdata, event.ydata))
  
      self.line.set_data(list(zip(*self.verts)))
  
      if self.useblit:
          self.canvas.restore_region(self.background)
          self.ax.draw_artist(self.line)
          self.canvas.blit(self.ax.bbox)
      else:
          self.canvas.draw_idle()
  
  def enter_axes(self, event):
      self.idfig = event.inaxes.colNum
      self._view_frame.figure.canvas.mpl_connect('button_press_event', self.onpress_2)
      self._view_frame.figure.canvas.mpl_connect('key_press_event', self.onkey_press_2)
      self._view_frame.figure.canvas.mpl_connect('key_release_event', self.onkey_release_2)
      self._view_frame.figure.canvas.mpl_connect('button_press_event', self.onpress_3)
      self._view_frame.figure.canvas.mpl_connect('key_press_event', self.onkey_press_3)
      self._view_frame.figure.canvas.mpl_connect('key_release_event', self.onkey_release_3)
  
  def LassoManager(self, ax, data, Data):
      self.axes = ax
      self.canvas = ax.figure.canvas
      self.data = data
      self.Data = Data
      self.Nxy = len(data)
  
      # self.facecolors = [d.color for d in data]
      self.xys = [(d.x, d.y) for d in data]
      fig = ax.figure
      #self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
  
  
  
  def callback(self, verts):
      #facecolors = self.facecolors#collection.get_facecolors()
      #colorin = colorConverter.to_rgba('red')
      #colorout = colorConverter.to_rgba('blue')
      p = path.Path(verts)
      self.ind = p.contains_points([(d.x, d.y) for d in self.Data[self.where.colNum]])
      self._view_frame.figure.canvas.mpl_connect('button_press_event', self.onpress)
  
      #Functionality 1
  
      self.canvas.draw_idle()
      self.canvas.widgetlock.release(self.lasso)
      del self.lasso
  
  def onpress(self,event):
       if self.canvas.widgetlock.locked(): return
          if event.inaxes is None: return
          self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)
          self.where = event.inaxes
          # acquire a lock on the widget drawing
          self.canvas.widgetlock(self.lasso)
  
     def onkey_press_2(self,event):
      if event.key =='shift':
          self.merge_is_held = True
  
  
  def onkey_press_3(self,event):
      if event.key == 'control':
          self.split_is_held = True
  
  def onkey_release_2(self, event):
         if event.key == 'shift':
             self.merge_is_held = False
  
  
  def onkey_release_3(self, event):
     if event.key == 'control':
          self.split_is_held = False
  
  def LassoManagerMerge(self, ax, data2, Data2):
      self.axes = ax
      self.canvas = ax.figure.canvas
      self.data2 = data2
      self.Data2 = Data2
      self.Nxy = len(dataMerge)
  
      self.facecolors_2 = [d.color for d in data2]
      # print "facecolors",self.facecolors
      self.xys = [(d.x, d.y) for d in data2]
      # print "xys",self.xys
      fig = ax.figure
      self.collection_2 = RegularPolyCollection(
          fig.dpi, 6, sizes=(0,),
          facecolors=self.facecolors_2,
          offsets = self.xys,
          transOffset = ax.transData)
  
      ax.add_collection(self.collection_2)
  
  
  
  
  
  def callback_2(self, verts):
  
      self.facecolors_2 = self.collection_2.get_facecolors()
      #colorin = colorConverter.to_rgba('red')
      #colorout = colorConverter.to_rgba('blue')
      p = path.Path(verts)
      self.ind = p.contains_points([(d.x, d.y) for d in self.Data2[self.where.colNum]])   
      #Functionality 2             
  
      self.canvas.draw_idle()
      self.canvas.widgetlock.release(self.lasso_2)
  
      del self.lasso_2
  
   def onpress_2(self, event):
  
  
              if self.canvas.widgetlock.locked():  return
              if event.inaxes is None: return
              if event.button == 1:
                 if self.shift_is_held == True:
                      print "Shift pressed"
                      self.lasso_2 = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback_2)
                      print "Shift pressed"
                      self.where = event.inaxes
                      self.canvas.widgetlock(self.lasso_2)
  
                def LassoManager3(self, ax, data3, Data3):
      self.axes = ax
      self.canvas = ax.figure.canvas
      self.data3 = data3
      self.Data3 = Data3
      self.Nxy = len(data3)
  
      self.facecolors_3= [d.color for d in data3]
      # print "facecolors",self.facecolors
      self.xys = [(d.x, d.y) for d in data3]
  
      # print "xys",self.xys
      fig = ax.figure
      self.collection_3 = RegularPolyCollection(
          fig.dpi, 6, sizes=(0,),
          facecolors=self.facecolors_3,
          offsets = self.xys,
          transOffset = ax.transData)
  
      ax.add_collection(self.collection_3)
  
  
  
  def callback_3(self, verts):
      self.facecolors_3 = self.collection_3.get_facecolors()
      #colorin = colorConverter.to_rgba('red')
      #colorout = colorConverter.to_rgba('blue')
      p = path.Path(verts)
      self.ind = p.contains_points([(d.x, d.y) for d in self.Data3[self.where.colNum]])
  
      #Functionality 3
      self.canvas.draw_idle()
      self.canvas.widgetlock.release(self.lasso_3)
  
      del self.lasso_3
  
  def onpress_3(self, event):
  
              if self.canvas.widgetlock.locked(): return
              if event.inaxes is None: return
              if event.button == 1:
                  if self.split_is_held == True:
                      print " Split pressed"
                      self.lasso_3 = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback_3)
                      print "Split pressed"
                      self.where = event.inaxes
                      # acquire a lock on the widget drawing
                      self.canvas.widgetlock(self.lasso_3)
  </code></pre>
  
  <p>Any suggestions?</p>