Reporting
This tutorial will cover using vspyx.Reporting.Module
to easily create reports in Vehicle Spy X.
Setup
This tutorial will build on the work of Getting signal values. If you have not completed that tutorial, a finished example is availble at its bottom.
We will use numpy and matplotlib for numerical processing generating plots. These packages can be installed with pip.
pip3 install matplotlib numpy
Creating an empty report
A new report is created by calling vspyx.Reporting.Module.NewReport()
.
report = app.Reporting.NewReport()
report.Title = "My Report"
Adding content
For the report to be useful, we need to add some content to it.
Referring back to Getting signal values, we will add a new section to the report for every signal that was individually requested.
We will then append to a list all values for the signal, giving us the ability to process these after the entire buffer is finished.
Every report has a vspyx.Reporting.Report.RootSection
.
New subsections can be added by calling vspyx.Reporting.Section.NewSection()
.
# at global scope
import matplotlib
matplotlib.use("agg")
import matplotlib.pyplot as pyplot
pyplot.ioff()
import numpy
signal_points = {}
# in on_trace_point
if point.Traceable not in signal_points:
signal_points[point.Traceable] = [point]
else:
signal_points[point.Traceable].append(point)
# before looping over all signals
sections = {}
# after trace.OnPoint.Add(on_trace_point)
sections[signal] = report.RootSection.NewSection()
sections[signal].Name = signal_id
We now have a report section defined for each signal, as well as all of the signal points.
Here, we will calculate some statistics on the each signal with numpy
and use matplotlib
to generate a plot.
# after app.VehicleSpy.Stop()
for signal, points in signal_points.items():
timestamps = [(x.Timestamp - points[0].Timestamp).total_seconds() for x in points]
values = [x.PhysicalValue for x in points]
min = numpy.min(values)
max = numpy.max(values)
std_dev = numpy.std(values)
average = numpy.average(values)
stats = sections[signal].NewTable()
stats.SetHeader(["Statistic", "Value"])
stats.AddRow(["min", str(min)])
stats.AddRow(["max", str(max)])
stats.AddRow(["average", str(average)])
stats.AddRow(["std dev", str(std_dev)])
pyplot.clf()
_, axis = pyplot.subplots()
axis.plot(timestamps, values, label=signal.ID)
axis.set_ylabel(signal.ID)
axis.set_xlabel("Time (s)")
pyplot.savefig(f"{signal.ID}.png", format='png')
sections[signal].NewImage(f"{signal.ID}.png")
Generating the report
vspyx.Reporting.Report
has two functions for generating the actual report: vspyx.Reporting.Report.BuildHTML()
and vspyx.Reporting.Report.BuildPDF()
.
Since generating the report may take some time, these functions immediately return a vspyx.Core.Task_bool_t
.
This task can either by synchronously executed, or ran in the background.
report.BuildHTML("report.html").Execute()
report.BuildPDF("report.pdf").Execute()