Add additional timing information and a histogram of intervals
This commit is contained in:
+79
-1
@@ -3,11 +3,14 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "helpwindow.h"
|
#include "helpwindow.h"
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
const QColor FrameInfoWindow::byteGraphColors[8] = {Qt::blue, Qt::green, Qt::black, Qt::red, //0 1 2 3
|
const QColor FrameInfoWindow::byteGraphColors[8] = {Qt::blue, Qt::green, Qt::black, Qt::red, //0 1 2 3
|
||||||
Qt::gray, Qt::yellow, Qt::cyan, Qt::darkMagenta}; //4 5 6 7
|
Qt::gray, Qt::yellow, Qt::cyan, Qt::darkMagenta}; //4 5 6 7
|
||||||
QPen FrameInfoWindow::bytePens[8];
|
QPen FrameInfoWindow::bytePens[8];
|
||||||
|
|
||||||
|
const int numIntervalHistBars = 20;
|
||||||
|
|
||||||
FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::FrameInfoWindow)
|
ui(new Ui::FrameInfoWindow)
|
||||||
@@ -48,12 +51,26 @@ FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *paren
|
|||||||
|
|
||||||
ui->graphBytes->legend->setVisible(false);
|
ui->graphBytes->legend->setVisible(false);
|
||||||
|
|
||||||
|
ui->timeHistogram->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
|
||||||
|
QCP::iSelectLegend | QCP::iSelectPlottables);
|
||||||
|
|
||||||
|
ui->timeHistogram->xAxis->setRange(0, numIntervalHistBars);
|
||||||
|
ui->timeHistogram->yAxis->setRange(0, 100);
|
||||||
|
ui->timeHistogram->axisRect()->setupFullAxesBox();
|
||||||
|
|
||||||
|
ui->timeHistogram->xAxis->setLabel("Interval");
|
||||||
|
ui->timeHistogram->yAxis->setLabel("Occurrences");
|
||||||
|
|
||||||
|
ui->timeHistogram->legend->setVisible(false);
|
||||||
|
|
||||||
if (useOpenGL)
|
if (useOpenGL)
|
||||||
{
|
{
|
||||||
ui->graphHistogram->setAntialiasedElements(QCP::aeAll);
|
ui->graphHistogram->setAntialiasedElements(QCP::aeAll);
|
||||||
ui->graphHistogram->setOpenGl(true);
|
ui->graphHistogram->setOpenGl(true);
|
||||||
ui->graphBytes->setAntialiasedElements(QCP::aeAll);
|
ui->graphBytes->setAntialiasedElements(QCP::aeAll);
|
||||||
ui->graphBytes->setOpenGl(true);
|
ui->graphBytes->setOpenGl(true);
|
||||||
|
ui->timeHistogram->setAntialiasedElements(QCP::aeAll);
|
||||||
|
ui->timeHistogram->setOpenGl(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -61,6 +78,8 @@ FrameInfoWindow::FrameInfoWindow(const QVector<CANFrame> *frames, QWidget *paren
|
|||||||
ui->graphHistogram->setAntialiasedElements(QCP::aeNone);
|
ui->graphHistogram->setAntialiasedElements(QCP::aeNone);
|
||||||
ui->graphBytes->setOpenGl(false);
|
ui->graphBytes->setOpenGl(false);
|
||||||
ui->graphBytes->setAntialiasedElements(QCP::aeNone);
|
ui->graphBytes->setAntialiasedElements(QCP::aeNone);
|
||||||
|
ui->timeHistogram->setOpenGl(false);
|
||||||
|
ui->timeHistogram->setAntialiasedElements(QCP::aeNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
@@ -215,6 +234,7 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
int bitfieldHistogram[64];
|
int bitfieldHistogram[64];
|
||||||
QVector<double> histGraphX, histGraphY;
|
QVector<double> histGraphX, histGraphY;
|
||||||
QVector<double> byteGraphX, byteGraphY[8];
|
QVector<double> byteGraphX, byteGraphY[8];
|
||||||
|
QVector<double> timeGraphX, timeGraphY;
|
||||||
double maxY = -1000.0;
|
double maxY = -1000.0;
|
||||||
uint8_t changedBits[8];
|
uint8_t changedBits[8];
|
||||||
uint8_t referenceBits[8];
|
uint8_t referenceBits[8];
|
||||||
@@ -310,6 +330,9 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
qDebug() << referenceBits[c];
|
qDebug() << referenceBits[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> sortedIntervals;
|
||||||
|
uint64_t intervalSum = 0;
|
||||||
|
|
||||||
//then find all data points
|
//then find all data points
|
||||||
for (int j = 0; j < frameCache.count(); j++)
|
for (int j = 0; j < frameCache.count(); j++)
|
||||||
{
|
{
|
||||||
@@ -322,6 +345,8 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
if (j != 0)
|
if (j != 0)
|
||||||
{
|
{
|
||||||
thisInterval = (frameCache[j].timestamp - frameCache[j-1].timestamp);
|
thisInterval = (frameCache[j].timestamp - frameCache[j-1].timestamp);
|
||||||
|
sortedIntervals.push_back(thisInterval);
|
||||||
|
intervalSum += thisInterval;
|
||||||
if (thisInterval > maxInterval) maxInterval = thisInterval;
|
if (thisInterval > maxInterval) maxInterval = thisInterval;
|
||||||
if (thisInterval < minInterval) minInterval = thisInterval;
|
if (thisInterval < minInterval) minInterval = thisInterval;
|
||||||
avgInterval += thisInterval;
|
avgInterval += thisInterval;
|
||||||
@@ -347,6 +372,41 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::sort(sortedIntervals.begin(), sortedIntervals.end());
|
||||||
|
uint64_t intervalStdDiv, intervalPctl5, intervalPctl95, intervalMean, intervalVariance = 0;
|
||||||
|
|
||||||
|
intervalMean = intervalSum / sortedIntervals.size();
|
||||||
|
|
||||||
|
for(int l = 0; l < sortedIntervals.size(); l++) {
|
||||||
|
intervalVariance += ((sortedIntervals[l] - intervalMean) * (sortedIntervals[l] - intervalMean));
|
||||||
|
}
|
||||||
|
|
||||||
|
intervalVariance /= sortedIntervals.size();
|
||||||
|
intervalStdDiv = sqrt(intervalVariance);
|
||||||
|
|
||||||
|
intervalPctl5 = sortedIntervals[floor(0.05 * sortedIntervals.size())];
|
||||||
|
intervalPctl95 = sortedIntervals[floor(0.95 * sortedIntervals.size())];
|
||||||
|
|
||||||
|
uint64_t step = ceil((maxInterval - minInterval) / numIntervalHistBars);
|
||||||
|
int index = 0;
|
||||||
|
int counter = 0;
|
||||||
|
int maxTimeCounter = -1;
|
||||||
|
for(int l = 0; l <= numIntervalHistBars; l++) {
|
||||||
|
uint64_t currentMax = maxInterval - ((numIntervalHistBars - l) * step); // avoid missing the biggest value due to rounding errors
|
||||||
|
while(index < sortedIntervals.size()) {
|
||||||
|
if(sortedIntervals[index] <= currentMax) {
|
||||||
|
counter++;
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeGraphX.append(l);
|
||||||
|
timeGraphY.append(counter);
|
||||||
|
if(counter > maxTimeCounter) maxTimeCounter = counter;
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (frameCache.count() > 1)
|
if (frameCache.count() > 1)
|
||||||
avgInterval = avgInterval / (frameCache.count() - 1);
|
avgInterval = avgInterval / (frameCache.count() - 1);
|
||||||
else avgInterval = 0;
|
else avgInterval = 0;
|
||||||
@@ -372,7 +432,12 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
tempItem = new QTreeWidgetItem();
|
tempItem = new QTreeWidgetItem();
|
||||||
tempItem->setText(0, tr("Inter-frame interval variation: ") + QString::number((maxInterval - minInterval) / 1000.0f) + "ms");
|
tempItem->setText(0, tr("Inter-frame interval variation: ") + QString::number((maxInterval - minInterval) / 1000.0f) + "ms");
|
||||||
baseNode->addChild(tempItem);
|
baseNode->addChild(tempItem);
|
||||||
|
tempItem = new QTreeWidgetItem();
|
||||||
|
tempItem->setText(0, tr("Interval standard deviation: ") + QString::number(intervalStdDiv / 1000.0f) + "ms");
|
||||||
|
baseNode->addChild(tempItem);
|
||||||
|
tempItem = new QTreeWidgetItem();
|
||||||
|
tempItem->setText(0, tr("Minimum range to fit 90% of inter-frame intervals: ") + QString::number((intervalPctl95 - intervalPctl5) / 1000.0f) + "ms");
|
||||||
|
baseNode->addChild(tempItem);
|
||||||
for (int c = 0; c < maxLen; c++)
|
for (int c = 0; c < maxLen; c++)
|
||||||
{
|
{
|
||||||
dataBase = new QTreeWidgetItem();
|
dataBase = new QTreeWidgetItem();
|
||||||
@@ -443,6 +508,19 @@ void FrameInfoWindow::updateDetailsWindow(QString newID)
|
|||||||
}
|
}
|
||||||
ui->graphBytes->xAxis->setRange(0, byteGraphX.count());
|
ui->graphBytes->xAxis->setRange(0, byteGraphX.count());
|
||||||
ui->graphBytes->replot();
|
ui->graphBytes->replot();
|
||||||
|
|
||||||
|
ui->timeHistogram->clearGraphs();
|
||||||
|
ui->timeHistogram->addGraph();
|
||||||
|
ui->timeHistogram->graph()->setData(timeGraphX, timeGraphY);
|
||||||
|
ui->timeHistogram->graph()->setLineStyle(QCPGraph::lsStepLeft); //connect points with lines
|
||||||
|
//QBrush graphBrush;
|
||||||
|
graphBrush.setColor(Qt::red);
|
||||||
|
graphBrush.setStyle(Qt::SolidPattern);
|
||||||
|
ui->timeHistogram->graph()->setPen(Qt::NoPen);
|
||||||
|
ui->timeHistogram->graph()->setBrush(graphBrush);
|
||||||
|
ui->timeHistogram->yAxis->setRange(0, maxTimeCounter * 1.1);
|
||||||
|
ui->timeHistogram->axisRect()->setupFullAxesBox();
|
||||||
|
ui->timeHistogram->replot();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,6 +70,32 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_time">
|
||||||
|
<property name="text">
|
||||||
|
<string>Interval Histogram</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCustomPlot" name="timeHistogram" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
Reference in New Issue
Block a user