3

I want to visualize data in a LinePlot using reportlab. The data has x-axis values (timestamps) with the form YYYYMMDDHHMMSS. I know that a reportlab x-axis class NormalDateXValueAxis exists but it only takes dates (YYYYMMDD) and does not allow to use time.

One question is does reportlab already support this with any class that I have not found yet?

A different approach I am trying is to simply use the timestamp string as x-axis values and define a formatter for these values. An example is:

from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin
from datetime import datetime


def formatter(val):
    dtstr = str(int(val))
    print(dtstr)
    dt = (datetime.strptime(str(int(val)), "%Y%m%d%H%M%S")).strftime("%d.%m.%Y %H:%M:%S")
    return dt

class Test(_DrawingEditorMixin, Drawing):

    def __init__(self,width=258,height=150,*args,**kw):
        Drawing.__init__(self,width,height,*args,**kw)
        # font
        fontSize = 7
        # chart
        self._add(self,LinePlot(),name='chart',validate=None,desc=None)
        self.chart.y                = 16
        self.chart.x                = 32
        self.chart.width            = 212
        self.chart.height           = 90
        # x axis
        self.chart.xValueAxis.labels.fontSize       = fontSize-1
        self.chart.xValueAxis.labelTextFormat       = formatter
        # y axis
        self.chart.yValueAxis.labels.fontSize       = fontSize -1
        # sample data
        self.chart.data = [
            [
                (20200225130120, 100),
                (20200225130125, 0),
                (20200225130130, 300),
                (20200225130135, 0),
                (20200225130140, 500),
                (20200225130145, 0),
                (20200225130150, 700),
                (20200225130155, 0),
                (20200225130315, 900)
            ]
        ]

if __name__=="__main__": #NORUNTESTS
    Test().save(formats=['pdf'],outDir='.',fnRoot=None)

But I have two problems with this aproach.

  1. The values given to the formatter are unpredictable (at least for me). Reportlab seems to modify the ticks in a way it deems to be best. The result is sometimes there are values that are not valid timestamps and can't be parsed by datetime. I sometimes got the exception that seconds must be between 0 and 59. Reportlab created a tick with value 20200225136000.

  2. Since the x axis does not know that that these values are timestamps it still leaves room for 20200225135961, 20200225135965, etc. The result is a gap in the graph.

enter image description here

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
ap0
  • 1,083
  • 1
  • 12
  • 37

2 Answers2

0

One question is does reportlab already support this with any class that I have not found yet?

Not that I know of, but I think what you want can be achieved from ValueAxis. If you can change the library, I suggest you to do with matplotlib as I've seen previous working examples. You can also try to see if PYX (which is also a good alternative to ReportLab) deals with such scenarios, but I didn't find any.

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
  • 1
    I would rather not use an additional library for these graphs at the current time. Although this may be a solution for the future. My problem with different libraries is that I create whole documents intwo which I embed these line graphs. I would have to find out if other libraries are usable in combination with reportlab. – ap0 Mar 09 '20 at 08:16
0

Inside the documentation it has a function inside the lineplots.py file called SimpleTimeSeriesPlot(LinePlot)

By looking at it when you specify .xValueAxis It will read your data as a date (how much flexibility this has I am not sure as I haven't tested it but it's worth testing that out)

Instead of calling LinePlot() you would call SimpleTimeSeriesPlot() and push through that same line of code and just add the .xValueAxis to your code. You can also specify min and max dates to parse by doing .xValueAxis.valueMin or Max