title: PyQt4 Scatterplot with Clickable and Selectable Points
body: <p>I'm trying to create a scatterplot with about 1000 data points in a way so that each data point can be selected by clicking on them using a mouse, which will result in bringing up a context menu which will allow the user to remove or change the color of the data point.  I've been following the tutorials for matplotlib, and looking at the Draggable Rectangle Exercise but I'm having a difficult time.  I'm using the matplotlib.patches.Circle class to represent each data point, but I cannot get the 'contains' method to work correctly with the 'button_press_event'.  Mainly, there seems to be no 'canvas' object associate with each Circle object.  I get the following error at line 16:</p>
  
  <pre><code>AttributeError: 'NoneType' object has no attribute 'canvas'
  </code></pre>
  
  <p>Here's the code:</p>
  
  <pre><code>#!/usr/bin/python -tt
  
  import sys
  import numpy
  #import matplotlib.pyplot
  from PyQt4 import QtGui, QtCore
  from matplotlib.figure import Figure
  from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
  from matplotlib.patches import Circle
  
  class SelectablePoint:
      def __init__(self, xy, label):
          self.point = Circle( (xy[0], xy[0]), .005 )
          self.label = label
          self.point.figure
          self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.onClick)
  
      def onClick(self, e):
  
          print e.xdata, e.ydata
          #print(dir(self.point))
          print self.point.center
          print self.point.contains(e)[0]
          #if self.point.contains(e)[0]:
          #    print self.label
  
  
  class ScatterPlot(FigureCanvas):
      '''
      classdocs
      '''
  
      def __init__(self, parent=None):
          '''
          Constructor
          '''
  
          self.fig = Figure()
          FigureCanvas.__init__(self, self.fig)
  
          self.axes = self.fig.add_subplot(111)
          #x = numpy.arange(0.0, 3.0, 0.1)
          #y = numpy.cos(2*numpy.pi*x)
          x = [.5]
          y = [.5]
  
          #scatterplot = self.axes.scatter(x,y)
  
          for i in range(len(x)):
              c = Circle( (x[i], y[i]), .05 )
              self.axes.add_patch(c)
              #SelectablePoint( (x[i],y[i]), 'label for: ' + str(i), self.figure.canvas )
              SelectablePoint( (x[i],y[i]), 'label for: ' + str(i) )
              #self.axes.add_artist(c)
  
  class MainContainer(QtGui.QMainWindow):
  
      def __init__(self):
          QtGui.QMainWindow.__init__(self)
          self.resize(900,600)
          self.setWindowTitle('Scatter Plot')
  
          sp = ScatterPlot(self)
          self.setCentralWidget(sp)
  
          self.center()
  
      def center(self):
          # Get the resolution of the screen
          screen = QtGui.QDesktopWidget().screenGeometry()
  
          # Get the size of widget
          size = self.geometry()
          self.move( (screen.width() - size.width())/2, (screen.height() - size.height())/2 )
  
  if __name__ == '__main__':
      app = QtGui.QApplication(sys.argv)
      b = MainContainer()
      b.show()
      sys.exit(app.exec_())
  </code></pre>
  
  <p>I'm not sure if I'm approaching this the right way, or if I should be looking at another graphing module, but I've looked at gnuplot and chaco, and I felt that matplotlib was more fit for my problem.  Are there any other recommendations?  Thank you very much.</p>
  
  <p>** My Solution **</p>
  
  <p>Here's what I have working so far.  It simply outputs the label of each data point to standard output when the points in the scatter plot are clicked on.</p>
  
  <pre><code>#!/usr/bin/python -tt
  
  import sys
  import numpy
  from PyQt4 import QtGui, QtCore
  from matplotlib.figure import Figure
  from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
  from matplotlib.patches import Circle
  
  class SelectablePoint:
      def __init__(self, xy, label, fig):
          self.point = Circle( (xy[0], xy[1]), .25, figure=fig)
          self.label = label
          self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.onClick)
  
      def onClick(self, e):
          if self.point.contains(e)[0]:
              print self.label
  
  
  class ScatterPlot(FigureCanvas):
      '''
      classdocs
      '''
  
      def __init__(self, parent=None):
          '''
          Constructor
          '''
  
          self.fig = Figure()
          FigureCanvas.__init__(self, self.fig)
  
          self.axes = self.fig.add_subplot(111)
          xlim = [0,7]
          ylim = [0,7]
          self.axes.set_xlim(xlim)
          self.axes.set_ylim(ylim)
          self.axes.set_aspect( 1 )
  
          x = [1, 1.2, 3, 4, 5, 6]
          y = [1, 1.2, 3, 4, 5, 6]
          labels = ['1', '2', '3', '4', '5', '6']
  
          for i in range(len(x)):
              sp = SelectablePoint( (x[i],y[i]), labels[i], self.fig)
              self.axes.add_artist(sp.point)
  
  class MainContainer(QtGui.QMainWindow):
  
      def __init__(self):
          QtGui.QMainWindow.__init__(self)
          self.resize(900,600)
          self.setWindowTitle('Scatter Plot')
  
          sp = ScatterPlot(self)
          self.setCentralWidget(sp)
  
          self.center()
  
      def center(self):
          # Get the resolution of the screen
          screen = QtGui.QDesktopWidget().screenGeometry()
  
          # Get the size of widget
          size = self.geometry()
          self.move( (screen.width() - size.width())/2, (screen.height() - size.height())/2 )
  
  if __name__ == '__main__':
      app = QtGui.QApplication(sys.argv)
      b = MainContainer()
      b.show()
      sys.exit(app.exec_())
  </code></pre>