Hi everyone, I know I am late to the party, but I wanted to share my experience using both pyqtgraph and matplotlib embedded in a PyQt application and the use of QtThreads for various tasks. It is actually four different applications, each one is a status screen with live updating images and plots based on telemetry inputs from instrumentation, but the same approach is used in each status screen.
First of all, I used PyQt5 as it was a much easier environment in which to work than Qt, which is C++ :-). I used Qt Creator and Designer to develop the overall application display windows. For real-time image display, I used two different approaches: 1) I created a generic image display widget using pyqtgraph's GraphicsLayoutWidget, subclassing it to add methods to update the image data and add an overlay grid. 2) I created a generic surface plot widget using pyqtgraph's GLViewWidget, subclassing it to add methods for updating the display data and for changing the amplitude scale of the surface plot. The generic image display widget was used to display images of varying sizes, all the way up to a 2k x 2k image updating at 10 Hz. On a couple of the images I also used pyqtgraph's HistogramLUTWidget to allow for real-time adjustment of the display to maximize contrast based on the current image conditions (autoscaling is not always your friend in this regard). I used matplotlib for graphs and plots, as they all had fairly slow update requirements and matplotlib was fast enough to handle the load. If matplotlib had not been fast enough I would have used pyqtgraph for the plots. I developed a few simple QtWidgets with matplotlib plots embedded in them. All of the image display and plotting was done by the main Qt application's event loop, as that way Qt handles all of the multiple graphics tasks that were happening simultaneously. I used QThreads to handle the receipt of the telemetry data, which came from several socket subscriptions to the various data sources on other servers. The nice thing about the QThreads was that it allowed me to separate the receipt of new data from the display application. Moreover, QThreads support the Qt infrastructure, so I was able to use signals and slots to communicate the new data and values directly to the Qt widgets that displayed them. Basically I had one QThread per data source, with the run method subscribing to the data source, then repeatedly calling a data acquisition method until a shutdown command occurs, and finally, unsubscribing from the data source. The data acquisition method performs blocking reads on the data queue associated with that thread, performs minimal preprocessing to unpack the data and then calls the Qt signal methods to pass the data to the respective widgets. This design works surprisingly well and is able to support a high volume of image data and simultaneous plots updating in real time. Hope this is helpful. Regards, Erik On Thu, Oct 13, 2022 at 11:38 AM Ognyan Moore <[email protected]> wrote: > I just want to add that the real advantage of QThreads (when talking about > pyqtgraph) is that you can do CPU-heavy processing in a non-GUI thread, so > the GUI doesn't (temporarily) freeze/lag as number crunching is happening. > I use a QThread to do some log-based calculations here, and I use the > Signal/Slot mechanism to relay the information I want pyqtgraph to plot: > > > https://github.com/j9ac9k/barney/blob/main/src/barney/controllers/SubPlotControllers/SpectrogramController.py > > The calculation is based on an interactive element in the GUI, so when I > first had this setup, when the user would adjust a linear region item, the > GUI would temporarily freeze while I was doing a log calculation on a > ~500x2000 numpy array. Moving to a QThread meant the resulting plot was a > little late to update vs. the others, but the GUI didn't lag or freeze. > > Adding QThreads does add complexity, and I hope to roll an example in the > pyqtgraph example library on how to do this; but the general advice is > don't go down that route unless you have an actual need. > > On Thu, Oct 13, 2022 at 5:27 AM Edmondo Giovannozzi < > [email protected]> wrote: > >> Personally I want speed in a GUI application. So I always use pyqtgraph, >> even sometime modifying the pyqtgraph source in order to have what I need. >> It is well written, so modifying it is easy. >> If a calculation is slowing me down I can transform it in a Fortran or C >> code and use ctypes to link it to Python. >> >> Il Mer 12 Ott 2022, 23:36 Martin Chase <[email protected]> ha >> scritto: >> >>> Heya, >>> >>> There isn't any performance difference between QThreads and python >>> Threads; that's mostly a difference of how you want to integrate with Qt >>> (QThreads fit into the rest of the Qt lifecycle better). Otherwise, the >>> question that I ask to determine thread v. multiprocess is: will my worker >>> mostly be sitting around waiting? If that's the case (e.g. waiting on i/o), >>> then using a thread is great. Otherwise, if the worker needs to do a bunch >>> of heavy work before the data is ready to display (e.g. it's the output of >>> a difficult analysis), put that work on a different core. >>> >>> Only matplotlib is as good at plotting as matplotlib; it's the best >>> python plotting library. If that's your minimum bar, I agree that you'll be >>> writing everything yourself from scratch. PyQtGraph is built for >>> performance, though, so you're going to need the best of both libraries if >>> that's your use-case. >>> >>> Good luck, >>> - Martin >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "pyqtgraph" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/pyqtgraph/CAD_p8v3668bj82zYmWi%2Bns_DfHK4JHAbwvb8oSmitU-RkArFpA%40mail.gmail.com >>> <https://groups.google.com/d/msgid/pyqtgraph/CAD_p8v3668bj82zYmWi%2Bns_DfHK4JHAbwvb8oSmitU-RkArFpA%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "pyqtgraph" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/pyqtgraph/CACwj3kUb7toyty5sAE4vP6mV3YsRxQ%2BjGMxRh-hecLFvy9w2DA%40mail.gmail.com >> <https://groups.google.com/d/msgid/pyqtgraph/CACwj3kUb7toyty5sAE4vP6mV3YsRxQ%2BjGMxRh-hecLFvy9w2DA%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > -- > You received this message because you are subscribed to the Google Groups > "pyqtgraph" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/pyqtgraph/CA%2BnduTFi5wBSuqB9_g43HC_yYhwVSunEf7qz4Km4fjUMLnLbXw%40mail.gmail.com > <https://groups.google.com/d/msgid/pyqtgraph/CA%2BnduTFi5wBSuqB9_g43HC_yYhwVSunEf7qz4Km4fjUMLnLbXw%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "pyqtgraph" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/CAMZ%2BuanqZVBv18-Ow7cAH%3DdaKc7BbzYTWZOw_cMwGcbfV5U2TQ%40mail.gmail.com.
