Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Updating line plots in pyqtgraph plotwidget
Forum Updated to NodeBB v4.3 + New Features

Updating line plots in pyqtgraph plotwidget

Scheduled Pinned Locked Moved Unsolved Qt for Python
3 Posts 2 Posters 3.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kgenbio
    wrote on last edited by
    #1

    I am trying to create 3 graphs (temperature, pitch, roll) for each of my devices. Right now I have 3 devices, so i would want a separate line for each graph.

    I am trying to update the data when new data comes in from a SSE, which does get called and gets to the update function. For some reason, setData is not working for me, keep getting errors involving not being finite or nan, even though the data is clean.

    Also, I am not sure how to update only one line at a time on each graph, if that is possible with setData.

    I tried to get the code below to only have relevant parts. you can assume the server side event is working, getting the data, and calling update graphs inside a pyqtSlot (i.e. on the same thread as the GUI). Here is my code:

    from PyQt5 import QtWidgets, QtCore, uic
    from pyqtgraph import PlotWidget, plot
    import pyqtgraph as pg
    from sseclient import SSEClient
    import requests
    import json
    import threading
    import queue
    import time
    import multiprocessing as mp
    
    graph_colors = ['white', 'green', 'red', 'blue', 'orange', 'purple']
    
    class UI(QtWidgets.QMainWindow):
    
        add_row_s = QtCore.pyqtSignal(str, str, str)
        create_devices_ui_s = QtCore.pyqtSignal(list)
    
        def __init__(self):
            super(UI, self).__init__()
            uic.loadUi('ui/uhmss_ui.ui', self)
            self._run_flag = True
            self.device_data = {}
    
            self.create_devices_ui_s.connect(self.create_devices_ui)
    
            # plot data: x, y values
            self.graphlayout = self.findChild(QtWidgets.QVBoxLayout, 'graphlayout')
    
            self.temperaturegraph = pg.PlotWidget()
            self.temperaturegraph.addLegend()
            self.temperaturegraph.setTitle("Temperature")
            self.temperaturegraph.setLabel("left", "Temperature (ºC)")
            self.temperaturegraph.setYRange(-20, 80)
            self.temperaturegraph.setXRange(0, 10)
    
            self.pitchgraph = pg.PlotWidget()
            self.pitchgraph.setTitle("Pitch")
            self.pitchgraph.addLegend()
            self.pitchgraph.setLabel("left", "Degrees")
            self.pitchgraph.setYRange(-90, 90)
    
            self.rollgraph = pg.PlotWidget()
            self.rollgraph.setTitle("Roll")
            self.rollgraph.addLegend()
            self.rollgraph.setLabel("left", "Degrees")
            self.rollgraph.setYRange(-180, 180)
    
            self.graphlayout.addWidget(self.temperaturegraph)
            self.graphlayout.addWidget(self.pitchgraph)
            self.graphlayout.addWidget(self.rollgraph)
    
        def device_query(self):
            #gets device data, can assume this works
            self.create_devices_us_s.emit(devices)
    
        @QtCore.pyqtSlot(list)
        def create_devices_ui(self, devices):
            self.device_data = {}
            for i in range(0, len(devices)):
                device = devices[i]
                id = device["id"]
                name = device["name"]
                self.device_data[id] = {}
                self.device_data[id]["name"] = name
                self.device_data[id]["color"] = graph_colors[i]
                self.device_data[id]['temperatureplot'] = self.temperaturegraph.getPlotItem().plot()
                self.device_data[id]['pitchplot'] = self.pitchgraph.getPlotItem().plot()
                self.device_data[id]['rollplot'] = self.rollgraph.getPlotItem().plot()
                self.device_data[id]["Temperature"] = []
                self.device_data[id]["Pitch"] = []
                self.device_data[id]["Roll"] = []
    
        # update graphs, called from inside GUI thread, using signal/slot
        @QtCore.pyqtSlot(str, str, str)
        def update_graphs(self, id, event, data):
            device = self.device_data[id]
            match(event):
                case "Temperature":
                    tempdata = device["Temperature"]    
                    tempdata.append(data)
                    plot = device["temperatureplot"]
                    plot.setData(range(len(tempdata)), tempdata)
                case "Roll":
                    tempdata = device["Roll"]
                    tempdata.append(data)
                    plot = device["rollplot"]
                    plot.setData(range(len(tempdata)), tempdata)
                case "Pitch":
                    tempdata = device["Pitch"]
                    tempdata.append(data)
                    plot = device["pitchplot"]
                    plot.setData(range(len(tempdata)), tempdata)
    
    JonBJ 1 Reply Last reply
    0
    • K kgenbio

      I am trying to create 3 graphs (temperature, pitch, roll) for each of my devices. Right now I have 3 devices, so i would want a separate line for each graph.

      I am trying to update the data when new data comes in from a SSE, which does get called and gets to the update function. For some reason, setData is not working for me, keep getting errors involving not being finite or nan, even though the data is clean.

      Also, I am not sure how to update only one line at a time on each graph, if that is possible with setData.

      I tried to get the code below to only have relevant parts. you can assume the server side event is working, getting the data, and calling update graphs inside a pyqtSlot (i.e. on the same thread as the GUI). Here is my code:

      from PyQt5 import QtWidgets, QtCore, uic
      from pyqtgraph import PlotWidget, plot
      import pyqtgraph as pg
      from sseclient import SSEClient
      import requests
      import json
      import threading
      import queue
      import time
      import multiprocessing as mp
      
      graph_colors = ['white', 'green', 'red', 'blue', 'orange', 'purple']
      
      class UI(QtWidgets.QMainWindow):
      
          add_row_s = QtCore.pyqtSignal(str, str, str)
          create_devices_ui_s = QtCore.pyqtSignal(list)
      
          def __init__(self):
              super(UI, self).__init__()
              uic.loadUi('ui/uhmss_ui.ui', self)
              self._run_flag = True
              self.device_data = {}
      
              self.create_devices_ui_s.connect(self.create_devices_ui)
      
              # plot data: x, y values
              self.graphlayout = self.findChild(QtWidgets.QVBoxLayout, 'graphlayout')
      
              self.temperaturegraph = pg.PlotWidget()
              self.temperaturegraph.addLegend()
              self.temperaturegraph.setTitle("Temperature")
              self.temperaturegraph.setLabel("left", "Temperature (ºC)")
              self.temperaturegraph.setYRange(-20, 80)
              self.temperaturegraph.setXRange(0, 10)
      
              self.pitchgraph = pg.PlotWidget()
              self.pitchgraph.setTitle("Pitch")
              self.pitchgraph.addLegend()
              self.pitchgraph.setLabel("left", "Degrees")
              self.pitchgraph.setYRange(-90, 90)
      
              self.rollgraph = pg.PlotWidget()
              self.rollgraph.setTitle("Roll")
              self.rollgraph.addLegend()
              self.rollgraph.setLabel("left", "Degrees")
              self.rollgraph.setYRange(-180, 180)
      
              self.graphlayout.addWidget(self.temperaturegraph)
              self.graphlayout.addWidget(self.pitchgraph)
              self.graphlayout.addWidget(self.rollgraph)
      
          def device_query(self):
              #gets device data, can assume this works
              self.create_devices_us_s.emit(devices)
      
          @QtCore.pyqtSlot(list)
          def create_devices_ui(self, devices):
              self.device_data = {}
              for i in range(0, len(devices)):
                  device = devices[i]
                  id = device["id"]
                  name = device["name"]
                  self.device_data[id] = {}
                  self.device_data[id]["name"] = name
                  self.device_data[id]["color"] = graph_colors[i]
                  self.device_data[id]['temperatureplot'] = self.temperaturegraph.getPlotItem().plot()
                  self.device_data[id]['pitchplot'] = self.pitchgraph.getPlotItem().plot()
                  self.device_data[id]['rollplot'] = self.rollgraph.getPlotItem().plot()
                  self.device_data[id]["Temperature"] = []
                  self.device_data[id]["Pitch"] = []
                  self.device_data[id]["Roll"] = []
      
          # update graphs, called from inside GUI thread, using signal/slot
          @QtCore.pyqtSlot(str, str, str)
          def update_graphs(self, id, event, data):
              device = self.device_data[id]
              match(event):
                  case "Temperature":
                      tempdata = device["Temperature"]    
                      tempdata.append(data)
                      plot = device["temperatureplot"]
                      plot.setData(range(len(tempdata)), tempdata)
                  case "Roll":
                      tempdata = device["Roll"]
                      tempdata.append(data)
                      plot = device["rollplot"]
                      plot.setData(range(len(tempdata)), tempdata)
                  case "Pitch":
                      tempdata = device["Pitch"]
                      tempdata.append(data)
                      plot = device["pitchplot"]
                      plot.setData(range(len(tempdata)), tempdata)
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @kgenbio said in Updating line plots in pyqtgraph plotwidget:

      For some reason, setData is not working for me, keep getting errors involving not being finite or nan, even though the data is clean.

      Why don't you print(tempdata) immediately above each plot.setData(range(len(tempdata)), tempdata)?

      K 1 Reply Last reply
      0
      • JonBJ JonB

        @kgenbio said in Updating line plots in pyqtgraph plotwidget:

        For some reason, setData is not working for me, keep getting errors involving not being finite or nan, even though the data is clean.

        Why don't you print(tempdata) immediately above each plot.setData(range(len(tempdata)), tempdata)?

        K Offline
        K Offline
        kgenbio
        wrote on last edited by
        #3

        @JonB

        Hello Jon, I did do just what you said and thought the data looked fine. while getting you an example together... I see it.

        All of the values are strings instead of numbers because i am parsing them from a web request where they come over as string values.

        welp silly mistake on my end.

        But to my second question, what is the best way to dynamically add more devices to the list as a new line, update that line specifically with new data, and have the legend update.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved