title: Live data plotting lags after a while
body: <p>I've been writing a program for a workstation automation in a laboratory. One of the instruments I communicate is called beam profiler, it basically reads light inputs from two ortogonal directions (x,y). Once the input is read, I need to convert it to a 2D image, for that I use the numpy <code>meshgrid</code> and I'm able to obtain my desired output. 
  For better clarity, see image bellow. The two Gaussian lines in the x and y axis are my raw input and the colored figure is after processed with meshgrid.
  <a href="https://i.stack.imgur.com/D3Exq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/D3Exq.png" alt="enter image description here"></a></p>
  
  <p>I divide my software in two parts for this. First I create another QT thread that initializes my device and runs in a loop getting the data and processing it. Then this thread sends a signal to the main thread with the values.</p>
  
  <p>In the main thread I get the values, plot the graph and update the gui screen.</p>
  
  <p>It is already working, the problem is that when I start the beam profiler readings the software starts getting slower as time passes. At first I thought it was because of the data processing but it doesn't make sense because it is running in the second thread and when I start the device there is no lag.
  It seems like if it were "saving" the data in memory and getting slower, which is weird since I'm using the <code>set_data</code> and <code>draw</code> methods for plotting.</p>
  
  <p>Note: if I close the device readings inside my software the lags stops and if I start it again, it starts good but then lags as time passes.</p>
  
  <p>Any incoming help is much appreciated!</p>
  
  <p>Data acquisition thread code:</p>
  
  <pre><code>class ThreadGraph(QtCore.QThread):
      _signalValues = QtCore.pyqtSignal(float, float, float, float, float, float, float, float)
      _signalGraph = QtCore.pyqtSignal(np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray)
      _signalError = QtCore.pyqtSignal(str)
      BEAMstatus = QtCore.pyqtSignal(str)
  
      def __init__(self, parent=None):
          super(ThreadGraph, self).__init__(parent)
          self.slit = 0
          self.state = False
  
      #Thread starts
      def run(self):
          self.init() #Device initialization (Not relevant, therefore omitted)
          time.sleep(0.1)
          while self.state == True: #Thread loop (data acquisition)
              self.emitValues() #Fun to get the data and emit
              time.sleep(0.016)
              self.emitGraph() #Process data into 2D and emit
          try: #When while is over, terminate the thread
              self.beam.close(self.session)
          except RuntimeError as err:
              print err 
          self.quit()
  
      def emitGraph(self): #Use the data acquired to to generate 2D image and emit
          xx, yy = np.meshgrid(self.slit_data_int[self.slit][0::10], self.slit_data_int[self.slit+1][0::10])
          zz = xx * yy
  
          self._signalGraph.emit(
              self.slit_data_pos[self.slit][0::10],
              self.slit_data_int[self.slit][0::10],
              self.slit_data_pos[self.slit + 1][0::10],
              self.slit_data_int[self.slit + 1][0::10],
              zz
              )
  
  
      def emitValues(self):
          try: #Try to get data from device (data is stored in calculation_result)
              self.slit_data_pos, self.slit_data_int, self.calculation_result, self.power, self.power_saturation, self.power_intensities = self.beam.get_slit_scan_data(self.session)
          except RuntimeError as err:
              self._signalError.emit(str(err))
              return
          else: #emit data to gui main thread
              self._signalValues.emit(
                  self.calculation_result[self.slit].peakPosition, 
                  self.calculation_result[self.slit + 1].peakPosition,
                  self.calculation_result[self.slit].peakIntensity, 
                  self.calculation_result[self.slit + 1].peakIntensity,
                  self.calculation_result[self.slit].centroidPosition, 
                  self.calculation_result[self.slit + 1].centroidPosition,
                  self.calculation_result[self.slit].gaussianFitDiameter, 
                  self.calculation_result[self.slit + 1].gaussianFitDiameter
                  )
  </code></pre>
  
  <p>Main Gui code:</p>
  
  <pre><code>class BP209_class(QtGui.QWidget):
  
      def __init__(self, vbox, slit25, slit5, peakposx, peakposy, peakintx, peakinty, centroidposx, centroidposy, mfdx, mfdy):
          QtGui.QWidget.__init__(self)
          #Initialize a bunch of gui variables
          self.matplotlibWidget = MatplotlibWidget('2d')
          self.vboxBeam = vbox
          self.vboxBeam.addWidget(self.matplotlibWidget)
          self.vboxBeam.addWidget(self.matplotlibWidget.canvastoolbar)
          #Create the thread and connects
          self.thread = ThreadGraph(self)
          self.thread._signalError.connect(self.Error_Handling)
          self.thread._signalValues.connect(self.values_update)
          self.thread._signalGraph.connect(self.graph_update)
          self.thread.BEAMstatus.connect(self.Status)
  
  
          #Initialize variables for plots
          self.zz = zeros([750, 750])
          self.im = self.matplotlibWidget.axis.imshow(self.zz, cmap=cm.jet,  origin='upper', vmin=0, vmax=1, aspect='auto', extent=[-5000,5000,-5000,5000])
          self.pv,  = self.matplotlibWidget.axis.plot(np.zeros(750) , np.zeros(750) , color="white" , alpha=0.6, lw=2)
          self.ph,  = self.matplotlibWidget.axis.plot(np.zeros(750) , np.zeros(750), color="white" , alpha=0.6, lw=2)
          self.matplotlibWidget.figure.subplots_adjust(left=0.00, bottom=0.01, right=0.99, top=1, wspace=None, hspace=None)
          self.matplotlibWidget.axis.set_xlim([-5000, 5000])
          self.matplotlibWidget.axis.set_ylim([-5000,5000])
  
      def __del__(self): #stop thread  
          self.thread.state = False
          self.thread.wait()
  
      def start(self): #start thread
          if self.thread.state == False:
              self.thread.state = True
              self.thread.start()
          else:
              self.thread.state = False
              self.thread.wait()
  
      #Slot that receives data from device and plots it
      def graph_update(self, slit_samples_positionsX, slit_samples_intensitiesX, slit_samples_positionsY, slit_samples_intensitiesY, zz):
          self.pv.set_data(np.divide(slit_samples_intensitiesX, 15)-5000, slit_samples_positionsX)
          self.ph.set_data(slit_samples_positionsY, np.divide(slit_samples_intensitiesY, 15)-5000)
          self.im.set_data(zz)
          self.im.autoscale()
          self.matplotlibWidget.canvas.draw()
  </code></pre>
  
  <p>Edit: I also have a camera attached to my system and I display it also in the gui using opencv. I noticed that if I start the cam the beam profiler's fps reduce to almost a half. So, maybe a QT paint optimization would be the way to go?</p>