pythonpyqtgraph

pyqtgraph plot with x-Axis in date units


I try to plot a chart with dates in the x-axis. But the units displayed are in hours and minutes.

import sys
import datetime
import pyqtgraph as pg
from PySide6.QtWidgets import QApplication, QMainWindow


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.plotWidget = pg.PlotWidget()
        self.setCentralWidget(self.plotWidget)

        self.scatter = pg.ScatterPlotItem()
        self.plotWidget.addItem(self.scatter)
        self.plotWidget.setBackground('w')
        dateAxis = pg.DateAxisItem()
        self.plotWidget.setAxisItems({'bottom': dateAxis})

        self.add_points()

    def add_points(self):
        x_values = [datetime.date(2024, 1, 1), datetime.date(
            2024, 3, 1), datetime.date(2024, 4, 21)]
        points = [
            {'pos': (x_values[0].toordinal(), 1)},
            {'pos': (x_values[1].toordinal(), 2)},
            {'pos': (x_values[2].toordinal(), 3)}]
        self.scatter.addPoints(points)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

enter image description here

How can I force the x-Axis unit with dates? eg 01.01.2024

Thanks for hints

Vik


Solution

  • This is the best I could get it:

    import sys
    import datetime
    import pyqtgraph as pg
    from PySide6.QtWidgets import QApplication, QMainWindow
    import time
    from collections import OrderedDict
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
    
            self.plotWidget = pg.PlotWidget()
            self.setCentralWidget(self.plotWidget)
    
            self.scatter = pg.ScatterPlotItem()
            self.plotWidget.addItem(self.scatter)
            self.plotWidget.setBackground('w')
            dateAxis = pg.DateAxisItem()
            new_zoom_levels = OrderedDict()
            for index, (key, item) in enumerate(dateAxis.zoomLevels.items()):
                if index == 1:
                    new_zoom_levels[key*2] = item
                else:
                    new_zoom_levels[key] = item
    
            dateAxis.zoomLevels = new_zoom_levels
            self.plotWidget.setAxisItems({'bottom': dateAxis})
    
            self.add_points()
    
        def add_points(self):
            x_values = [datetime.datetime(2024, 1, 1), datetime.datetime(
                2024, 3, 1), datetime.datetime(2024, 4, 21)]
            points = [
                {'pos': (x_values[0].timestamp(), 1)},
                {'pos': (x_values[1].timestamp(), 2)},
                {'pos': (x_values[2].timestamp(), 3)}]
            print(points)
            print(time.time())
            self.scatter.addPoints(points)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec())
        
    

    The biggest problem in your code is that pyqtgraph expects a unix timestamp, while in your code, an ordinal representation of a date is given (number of days since 1 January 1 AD). This is fixed by changing the datetime.date, to datetime.datetime objects, and then getting the unix timestamp by using .timestamp().

    A problem that I ran into, when I did this is that the days where not visible, only the months. I ran into issues with the proper way (using dateAxis.setZoomLevelForDensity()), so I used a bit of a workaround, by adjusting dateAxis.ZoomLevels. If anyone can get the proper way working that would be nice.