Skip to content

Commit

Permalink
Time Series User Chart plotting "Optimisation"
Browse files Browse the repository at this point in the history
.. default to 5s smoothing for plotting time series (second by
   second samples).

.. if smoothing is applied we sample the smoothed data every
   3 seconds.

.. this reduces the number of points to plot to a 3rd and has
   a significant impact on plot/paint performance.

.. for those users that care about resolution they can set
   the smoothing to none, for those that don't they will
   get faster performance.
  • Loading branch information
liversedge committed Aug 22, 2021
1 parent 81d59d4 commit 33018aa
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
23 changes: 16 additions & 7 deletions src/Charts/UserChart.cpp
Expand Up @@ -204,9 +204,15 @@ UserChart::setRide(const RideItem *item)
if (ax != -1 && axisinfo[ax].smooth != 0 && axisinfo[ax].type == GenericAxisInfo::TIME) ysmooth=axisinfo[ax].smooth;
if (ay != -1 && axisinfo[ay].smooth != 0 && axisinfo[ay].type == GenericAxisInfo::TIME) xsmooth=axisinfo[ay].smooth;

// lets pre-process the data
if (xsmooth >= 2) series.xseries = Utils::smooth_sma(series.xseries, GC_SMOOTH_CENTERED, xsmooth);
if (ysmooth >= 2) series.yseries = Utils::smooth_sma(series.yseries, GC_SMOOTH_CENTERED, ysmooth);
// lets pre-process the data- and might as well use sampling if losing resolution- some performance benefits here
if (xsmooth >= 2) {
series.xseries = Utils::smooth_sma(series.xseries, GC_SMOOTH_CENTERED, xsmooth, 3);
series.yseries = Utils::sample(series.yseries, 3);
}
if (ysmooth >= 2) {
series.yseries = Utils::smooth_sma(series.yseries, GC_SMOOTH_CENTERED, ysmooth, 3);
series.xseries = Utils::sample(series.xseries, 3);
}

// DATE groupby (applies to date axis)
int xgroupby=0, ygroupby=0;
Expand Down Expand Up @@ -1736,11 +1742,15 @@ EditUserAxisDialog::EditUserAxisDialog(Context *context, GenericAxisInfo &info)
setMinimumHeight(250 *dpiXFactor);

// update gui items from Axis info
axisname->setText(original.name);
log->setChecked(original.log);
int index=axistype->findData(original.type);
if (index >=0) axistype->setCurrentIndex(index);
else axistype->setCurrentIndex(0);

// show / hide widgets on current config, setting defaults
setWidgets();

axisname->setText(original.name);
log->setChecked(original.log);
fixed->setChecked(original.fixed);
min->setValue(original.min());
max->setValue(original.max());
Expand All @@ -1754,8 +1764,6 @@ EditUserAxisDialog::EditUserAxisDialog(Context *context, GenericAxisInfo &info)
connect(okButton, SIGNAL(clicked()), this, SLOT(okClicked()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancelClicked()));

// show / hide widgets on current config
setWidgets();
}

void
Expand All @@ -1774,6 +1782,7 @@ EditUserAxisDialog::setWidgets()
break;

case GenericAxisInfo::TIME:
smooth->setValue(5); // default to 5 seconds smoothing user can override
smooth->show();
smoothlabel->show();
groupby->setCurrentIndex(0);
Expand Down
21 changes: 17 additions & 4 deletions src/Core/Utils.cpp
Expand Up @@ -488,8 +488,11 @@ static double mean(QVector<double>&data, int start, int end)
return sum/count;
}

// return vector of smoothed values using mean average of window n samples
// samples is usually 1 to return every sample, but can be higher in which
// case sampling is performed before returning results (aka every nth sample)
QVector<double>
smooth_sma(QVector<double>&data, int pos, int window)
smooth_sma(QVector<double>&data, int pos, int window, int samples)
{
QVector<double> returning;

Expand All @@ -516,17 +519,27 @@ smooth_sma(QVector<double>&data, int pos, int window)

while (index < data.count()) {

returning << mean(data, window_start, window_end);

if (samples == 1 || index%samples == 0) // sampling
returning << mean(data, window_start, window_end);
index ++;
window_start++;
window_end++;
}

return returning;

}

// nth sampling to match sma above (usually for sampling x where sma has smoothed y
QVector<double>
sample(QVector<double>&data, int samples)
{
QVector<double>returning;
for (int index=0; index< data.count(); index++)
if (samples == 1 || index%samples==0)
returning << data.at(index);
return returning;
}

QVector<double>
smooth_ewma(QVector<double>&data, double alpha)
{
Expand Down
3 changes: 2 additions & 1 deletion src/Core/Utils.h
Expand Up @@ -53,7 +53,8 @@ namespace Utils
QVector<int> argsort(QVector<QString>&v, bool ascending=false);
QVector<int> arguniq(QVector<double> &v);
QVector<int> arguniq(QVector<QString> &v);
QVector<double> smooth_sma(QVector<double>&, int pos, int window);
QVector<double> smooth_sma(QVector<double>&, int pos, int window, int sample=1);
QVector<double> sample(QVector<double>&, int sample); // plain sampling nth sample
QVector<double> smooth_ewma(QVector<double>&, double alpha);

// used std::sort, std::lower_bound et al
Expand Down

0 comments on commit 33018aa

Please sign in to comment.