Chapter 6 - Plot the data in the GraphsViewΒΆ

The last step of this tutorial is to plot the CSV data inside our GraphsView. For this, you need to go over our data and include the data on a QLineSeries.

After adding the data to the series, you can modify the axis to properly display the QDateTime on the X-axis, and the magnitude values on the Y-axis.

Here is the updated main_widget.py that includes an additional function to plot data using a QLineSeries:

  1from math import floor, ceil
  2
  3from PySide6.QtCore import QDateTime, QTime, QTimeZone
  4from PySide6.QtWidgets import (QWidget, QHeaderView, QHBoxLayout, QTableView,
  5                               QSizePolicy)
  6from PySide6.QtQuickWidgets import QQuickWidget
  7from PySide6.QtGraphs import QLineSeries, QDateTimeAxis, QValueAxis, QGraphsTheme
  8
  9from table_model import CustomTableModel
 10
 11
 12class Widget(QWidget):
 13    def __init__(self, data):
 14        super().__init__()
 15
 16        # Getting the Model
 17        self.model = CustomTableModel(data)
 18
 19        # Creating a QTableView
 20        self.table_view = QTableView()
 21        self.table_view.setModel(self.model)
 22
 23        # QTableView Headers
 24        resize = QHeaderView.ResizeMode.ResizeToContents
 25        self.horizontal_header = self.table_view.horizontalHeader()
 26        self.vertical_header = self.table_view.verticalHeader()
 27        self.horizontal_header.setSectionResizeMode(resize)
 28        self.vertical_header.setSectionResizeMode(resize)
 29        self.horizontal_header.setStretchLastSection(True)
 30
 31        # Create QGraphView via QML
 32        self.populate_series()
 33        self.quick_widget = QQuickWidget(self)
 34        self.quick_widget.setResizeMode(QQuickWidget.ResizeMode.SizeRootObjectToView)
 35        self.theme = QGraphsTheme()
 36        self.theme.setTheme(QGraphsTheme.Theme.BlueSeries)
 37        initial_properties = {"theme": self.theme,
 38                              "axisX": self.axis_x,
 39                              "axisY": self.axis_y,
 40                              "seriesList": self.series}
 41        self.quick_widget.setInitialProperties(initial_properties)
 42        self.quick_widget.loadFromModule("QtGraphs", "GraphsView")
 43
 44        # QWidget Layout
 45        self.main_layout = QHBoxLayout(self)
 46        size = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred)
 47
 48        # Left layout
 49        size.setHorizontalStretch(1)
 50        self.table_view.setSizePolicy(size)
 51        self.main_layout.addWidget(self.table_view)
 52
 53        # Right Layout
 54        size.setHorizontalStretch(4)
 55        self.quick_widget.setSizePolicy(size)
 56        self.main_layout.addWidget(self.quick_widget)
 57
 58    def populate_series(self):
 59        def seconds(qtime: QTime):
 60            return qtime.minute() * 60 + qtime.second()
 61
 62        self.series = QLineSeries()
 63        self.series.setName("Magnitude (Column 1)")
 64
 65        # Filling QLineSeries
 66        time_min = QDateTime(2100, 1, 1, 0, 0, 0)
 67        time_max = QDateTime(1970, 1, 1, 0, 0, 0)
 68        time_zone = QTimeZone(QTimeZone.Initialization.UTC)
 69        y_min = 1e37
 70        y_max = -1e37
 71        date_fmt = "yyyy-MM-dd HH:mm:ss.zzz"
 72        for i in range(self.model.rowCount()):
 73            t = self.model.index(i, 0).data()
 74            time = QDateTime.fromString(t, date_fmt)
 75            time.setTimeZone(time_zone)
 76            y = float(self.model.index(i, 1).data())
 77            if time.isValid() and y > 0:
 78                if time > time_max:
 79                    time_max = time
 80                if time < time_min:
 81                    time_min = time
 82                if y > y_max:
 83                    y_max = y
 84                if y < y_min:
 85                    y_min = y
 86                self.series.append(time.toMSecsSinceEpoch(), y)
 87
 88        # Setting X-axis
 89        self.axis_x = QDateTimeAxis()
 90        self.axis_x.setLabelFormat("dd.MM (h:mm)")
 91        self.axis_x.setTitleText("Date")
 92        self.axis_x.setMin(time_min.addSecs(-seconds(time_min.time())))
 93        self.axis_x.setMax(time_max.addSecs(3600 - seconds(time_max.time())))
 94        self.series.setAxisX(self.axis_x)
 95
 96        # Setting Y-axis
 97        self.axis_y = QValueAxis()
 98        self.axis_y.setLabelFormat("%.2f")
 99        self.axis_y.setTitleText("Magnitude")
100        self.axis_y.setMin(floor(y_min))
101        self.axis_y.setMax(ceil(y_max))
102        self.series.setAxisY(self.axis_y)

Now, run the application to visualize the earthquake magnitudes data at different times.

Data Visualization Screenshot

Try modifying the sources to get different output. For example, you could try to plot more data from the CSV.