title: Implementing pyqtgraph multiprocessing into a pyqt widget
body: <p>I am trying to plot images on a GUI that I am designing in Python. The full program will be collecting image data from a camera and then displaying the images on the GUI. I have explored using matplotlib, but it was too slow for my application. I need the plot to update rather quickly (preferably as fast as I can acquisition from the camera, once ever half second or second). This is challenging with pyqt because it seems that even when using a QThread, the plot can only update on the main thread, which causes my program to stop and the GUI to be inaccessible to the user. </p>
  
  <p>I read that pyqtgraph is suppose to be a much faster plotting library than matplotlib. So I gave it a try and like it, but it seems to have the same problem as matplotlib when displaying an image. It stops the entire GUI. I did some research and came across this question: <a href="https://stackoverflow.com/questions/15706187/painting-without-paintevent">Painting without paintEvent</a> and one of the answers proposed the use of QtProcess(). Therefore, my question is whether it is possible (and if so, can you provide some example code) to implement QtProcess() into a GUI, i.e. how can I make a plot on a GUI run in a separate process? (Also, if there is a way to do this with matplotlib, that would be extremely helpful.)</p>
  
  <p>Here is the simple example I designed to test out my problem. I took an example script from pyqtgraph's examples and imported a pyqtgraph plot into a pyqt widget. Then when the pushButton is pressed, the plot it displayed. If you run the script, you will notice that the first plot will take a long time to load (6 or 7 seconds). Press the button again and it seems to load much faster. I am doing all of the data generation in a QThread(), but the plotting seems to require the main thread to work even though it is done in the QThread. I want to do exactly the same thing as in this example, except use QtProcess() to handle the plotting.</p>
  
  <p>Any other suggestions about plotting or possible alternatives are welcome. Thanks</p>
  
  <p><strong>GUI script:</strong></p>
  
  <pre><code># -*- coding: utf-8 -*-
  
  # Form implementation generated from reading ui file 'GUI.ui'
  #
  # Created: Fri Jun 28 14:40:22 2013
  #      by: PyQt4 UI code generator 4.9.5
  #
  # WARNING! All changes made in this file will be lost!
  
  from PyQt4 import QtCore, QtGui
  
  try:
      _fromUtf8 = QtCore.QString.fromUtf8
  except AttributeError:
      _fromUtf8 = lambda s: s
  
  class Ui_MainWindow(object):
      def setupUi(self, MainWindow):
          MainWindow.setObjectName(_fromUtf8("MainWindow"))
          MainWindow.resize(800, 534)
          self.centralwidget = QtGui.QWidget(MainWindow)
          self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
          self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget)
          self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
          self.gridLayout = QtGui.QGridLayout()
          self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
          self.scrollArea = QtGui.QScrollArea(self.centralwidget)
          self.scrollArea.setFrameShape(QtGui.QFrame.NoFrame)
          self.scrollArea.setFrameShadow(QtGui.QFrame.Plain)
          self.scrollArea.setWidgetResizable(True)
          self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
          self.scrollAreaWidgetContents = QtGui.QWidget()
          self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 780, 514))
          self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
          self.widgetPlot = QtGui.QWidget(self.scrollAreaWidgetContents)
          self.widgetPlot.setGeometry(QtCore.QRect(20, 10, 741, 451))
          self.widgetPlot.setObjectName(_fromUtf8("widgetPlot"))
          self.pushButtonPlot = QtGui.QPushButton(self.scrollAreaWidgetContents)
          self.pushButtonPlot.setGeometry(QtCore.QRect(340, 480, 75, 23))
          self.pushButtonPlot.setObjectName(_fromUtf8("pushButtonPlot"))
          self.scrollArea.setWidget(self.scrollAreaWidgetContents)
          self.gridLayout.addWidget(self.scrollArea, 1, 0, 1, 1)
          self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
          MainWindow.setCentralWidget(self.centralwidget)
  
          self.retranslateUi(MainWindow)
          QtCore.QMetaObject.connectSlotsByName(MainWindow)
  
      def retranslateUi(self, MainWindow):
          MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
          self.pushButtonPlot.setText(QtGui.QApplication.translate("MainWindow", "Plot", None, QtGui.QApplication.UnicodeUTF8))
  </code></pre>
  
  <p><strong>The wrapper:</strong></p>
  
  <pre><code>import numpy as np
  import scipy
  
  from pyqtgraph.Qt import QtCore, QtGui
  import pyqtgraph as pg
  
  import sys
  
  from PyQt4.QtCore import * 
  from PyQt4.QtGui import *
  
  from GUI import Ui_MainWindow
  
  
  class MyForm(QMainWindow):
      def __init__(self, parent=None):
          QWidget.__init__(self, parent)
          self.ui = Ui_MainWindow()
          self.ui.setupUi(self)
  
          self.imv = pg.ImageView()
  
          vbox = QVBoxLayout()
          vbox.addWidget(self.imv)
          self.ui.widgetPlot.setLayout(vbox)
  
          self.plot_thread = plotData()
  
          self.connect(self.ui.pushButtonPlot, SIGNAL("clicked()"), lambda : self.plot_thread.input(self.imv))
  
      def threadPlot(self):
          self.plot_thread.input(self.imv)
  
  
      def plot(self):
          ## Create random 3D data set with noisy signals
          self.img = scipy.ndimage.gaussian_filter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
          self.img = self.img[np.newaxis,:,:]
          decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
          data = np.random.normal(size=(100, 200, 200))
          data += self.img * decay
          data += 2
  
          ## Add time-varying signal
          sig = np.zeros(data.shape[0])
          sig[30:] += np.exp(-np.linspace(1,10, 70))
          sig[40:] += np.exp(-np.linspace(1,10, 60))
          sig[70:] += np.exp(-np.linspace(1,10, 30))
  
          sig = sig[:,np.newaxis,np.newaxis] * 3
          data[:,50:60,50:60] += sig
  
          self.imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
  
  
  class plotData(QThread):
      def __init__(self,parent=None):
          QThread.__init__(self,parent)
          self.exiting = False
      def input(self, imv):
          self.imv = imv
          self.start()
  
      def collectImage(self):
          ## Create random 3D data set with noisy signals
          self.img = scipy.ndimage.gaussian_filter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
          self.img = self.img[np.newaxis,:,:]
          decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
          data = np.random.normal(size=(100, 200, 200))
          data += self.img * decay
          data += 2
  
          ## Add time-varying signal
          sig = np.zeros(data.shape[0])
          sig[30:] += np.exp(-np.linspace(1,10, 70))
          sig[40:] += np.exp(-np.linspace(1,10, 60))
          sig[70:] += np.exp(-np.linspace(1,10, 30))
  
          sig = sig[:,np.newaxis,np.newaxis] * 3
          data[:,50:60,50:60] += sig
  
          self.imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
  
      def run(self):
  
          self.collectImage()
          self.emit(SIGNAL("Done"))
  
  
  app = QApplication(sys.argv)
  myapp = MyForm()
  
  myapp.show()
  sys.exit(app.exec_())
  </code></pre>
  
  <p><strong>My attempt at trying to use QtProcess()</strong> (unsuccessful, I do not know how to import a QtProcess() widget into a Qt GUI):</p>
  
  <pre><code>import numpy as np
  import scipy
  
  from pyqtgraph.Qt import QtCore, QtGui
  import pyqtgraph as pg
  
  import sys
  
  from PyQt4.QtCore import * 
  from PyQt4.QtGui import *
  
  from GUI import Ui_MainWindow
  
  
  class MyForm(QMainWindow):
      def __init__(self, parent=None):
          QWidget.__init__(self, parent)
          self.ui = Ui_MainWindow()
          self.ui.setupUi(self)
  
          self.proc = mp.QtProcess()
  
          self.remotepg = self.proc._import('pyqtgraph')
          self.win = self.remotepg.plot()
  
          self.imv = self.win.plot([1,4,2,3], [4,6,3,4], pen=None, symbol='o')
  
          vbox = QVBoxLayout()
          vbox.addWidget(self.imv)
          self.ui.widgetPlot.setLayout(vbox)
  
  app = QApplication(sys.argv)
  myapp = MyForm()
  
  myapp.show()
  sys.exit(app.exec_())
  </code></pre>