Search code examples
pythonpyqtreal-timeqt-designerpyqtgraph

Problem with Qt Designer - pglive integration for real-time plotting


I followed the tutorial on the pglive docs and I was able to have a real-time sine plot on my computer. Then I used an arduino to stream some random number through the serial port and I was able to read and plot the data using pglive.

Now I want to integrate a custom gui made with Qt Designer.

This is the code I'm trying to run:

import sys
from math import sin
from threading import Thread
from time import sleep
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtWidgets, QtCore, uic
from pglive.sources.data_connector import DataConnector
from pglive.sources.live_plot import LiveLinePlot
from pglive.sources.live_plot_widget import LivePlotWidget
import serial

arduino = serial.Serial(port='COM17', baudrate=9600, timeout=.1) 

app = QApplication(sys.argv)
running = True

ui = uic.loadUi('test.ui')

plot_widget = ui.plot1 # LivePlotWidget(title="Line Plot @ 100Hz")
# plot_curve = LiveLinePlot()
# plot_widget.addItem(plot_curve)
# DataConnector holding 600 points and plots @ 100Hz
data_connector = DataConnector(ui.plot1, max_points=600, update_rate=100)
# data_connector = DataConnector(plot_curve, max_points=600, update_rate=100)

def sin_wave_generator(connector):
    """Sine wave generator"""
    x = 0
    while running:
        x += 1
        data = arduino.readline().decode("utf-8") # retrieve serial data from feather
        values = data.split(",") # split at commas
        data_point = float(values[0])
        # Callback to plot new data point
        connector.cb_append_data_point(data_point, x)
        sleep(0.01)

plot_widget.show()
Thread(target=sin_wave_generator, args=(data_connector,)).start()
app.exec()
running = False

Basically, I commented the plot_curve and plot_widget lines, and loaded the ui onto the plot_widget variable.

The gui is just a widget (named plot1) that I promoted to LivePlotWidget and set header file to pglive.sources.live_plot_widget as explained again by pglive guys in their docs.

However, what I obtain is the following:

Traceback (most recent call last):
  File "C:\Users\New Wyss User\AppData\Roaming\Python\Python311\site-packages\pglive\sources\live_plot.py", line 134, in <lambda>
    plot.slot_roll_tick = lambda data_connector, tick: plot.plot_widget.slot_roll_tick(data_connector, tick)
                                                       ^^^^^^^^^^^^^^^^
  File "C:\Users\New Wyss User\AppData\Roaming\Python\Python311\site-packages\pyqtgraph\widgets\PlotWidget.py", line 82, in __getattr__
    raise AttributeError(attr)
AttributeError: plot_widget
Traceback (most recent call last):
  File "C:\Users\New Wyss User\AppData\Roaming\Python\Python311\site-packages\pglive\sources\live_plot.py", line 121, in <lambda>
    plot.slot_new_data = lambda y, x, kwargs: plot.setData(x, y, **kwargs)
                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: setData(self, key: int, value: Any): argument 1 has unexpected type 'numpy.ndarray'

Any suggestion? Thanks!


Solution

  • Bingo. I found the issue. This works:

    import sys
    from math import sin
    from threading import Thread
    from time import sleep
    
    from PyQt5.QtWidgets import QApplication
    from PyQt5 import QtWidgets, QtCore, uic
    
    from pglive.sources.data_connector import DataConnector
    from pglive.sources.live_plot import LiveLinePlot
    from pglive.sources.live_plot_widget import LivePlotWidget
    
    
    import serial
    
    arduino = serial.Serial(port='COM17', baudrate=9600, timeout=.1) 
    
    app = QApplication(sys.argv)
    running = True
    
    ui = uic.loadUi('test.ui')
    
    #plot_widget = ui.plot1 # LivePlotWidget(title="Line Plot @ 100Hz")
    plot_curve = LiveLinePlot()
    ui.plot1.addItem(plot_curve)
    # DataConnector holding 600 points and plots @ 100Hz
    data_connector = DataConnector(plot_curve, max_points=600, update_rate=100)
    # data_connector = DataConnector(plot_curve, max_points=600, update_rate=100)
    
    
    def sin_wave_generator(connector):
        """Sine wave generator"""
        x = 0
        while running:
            x += 1
            data = arduino.readline().decode("utf-8") # retrieve serial data from feather
            values = data.split(",") # split at commas
            data_point = float(values[0])
            # Callback to plot new data point
            connector.cb_append_data_point(data_point, x)
    
            sleep(0.01)
    
    
    ui.show()
    Thread(target=sin_wave_generator, args=(data_connector,)).start()
    app.exec()
    running = False
    

    Hope this will help others with the same doubts!