CP MMP Filter improvement

.. use powerIndex to select points when t > 120s. This has resulted
   in a much higher hit rate at finding performance tests in MMP
   data (almost 99% of the time).
This commit is contained in:
Mark Liversedge
2019-01-04 13:27:28 +00:00
parent 46abc66484
commit efb1a648f6
3 changed files with 30 additions and 17 deletions

View File

@@ -25,6 +25,7 @@
#include "CPPlot.h"
#include "PowerProfile.h"
#include "RideCache.h"
#include "Banister.h"
#include <QDebug>
#include <qwt_series_data.h>
@@ -1384,7 +1385,7 @@ CPPlot::plotBests(RideItem *rideItem)
// away from a linear regression
// the best we found is stored in here
struct { int i; double p, t, d; } keep;
struct { int i; double p, t, d, pix; } keep;
for(int i=0; i<t.count(); i++) {
@@ -1399,6 +1400,7 @@ CPPlot::plotBests(RideItem *rideItem)
keep.i=i;
keep.p=p[i];
keep.t=t[i];
keep.pix=powerIndex(keep.p, keep.t);
// but clear since we iterate beyond
if (i>0) { // always keep pmax point
@@ -1413,8 +1415,10 @@ CPPlot::plotBests(RideItem *rideItem)
// if its beloe the line multiply distance by -1
double d = (p[x] * t[x] * 60.0f) - ((slope * t[x] * 60.00f) + intercept);
double pix = powerIndex(p[x],t[x]);
if (keep.d < d) {
// use the regression for shorter durations and 3p for longer
if ((keep.t < 120 && keep.d < d) || (keep.t >= 120 && keep.pix < pix)) {
keep.d = d;
keep.i = x;
keep.p = p[x];

View File

@@ -48,6 +48,23 @@ const double typical_CP = 261,
// and also useful to normalise TTEs for use in the Banister model as a
// performance measurement.
//
double powerIndex(double averagepower, double duration)
{
// so now lets work out what the 3p model says the
// typical athlete would do for the same duration
//
// P(t) = W' / (t - (W'/(CP-Pmax))) + CP
double typicalpower = (typical_WPrime / (duration - (typical_WPrime/(typical_CP-typical_Pmax)))) + typical_CP;
// make sure we got a sensible value
if (typicalpower < 0 || typicalpower > 2500) return 0;
// we could convert to linear work time model before
// indexing, but they cancel out so no value in doing so
return(100.0 * averagepower/typicalpower);
}
class PowerIndex : public RideMetric {
Q_DECLARE_TR_FUNCTIONS(PowerIndex)
public:
@@ -100,24 +117,13 @@ class PowerIndex : public RideMetric {
return;
}
// so now lets work out what the 3p model says the
// typical athlete would do for the same duration
//
// P(t) = W' / (t - (W'/(CP-Pmax))) + CP
//
double typicalpower = (typical_WPrime / (duration - (typical_WPrime/(typical_CP-typical_Pmax)))) + typical_CP;
// make sure we got a sensible value
if (typicalpower < 0 || typicalpower > 2500) {
setValue(RideFile::NIL);
setCount(0);
return;
}
// calculate power index, 0=out of bounds
double pix = powerIndex(averagepower, duration);
// we could convert to linear work time model before
// indexing, but they cancel out so no value in doing so
setValue(100.0 * averagepower/typicalpower);
setCount(1);
setValue(pix);
setCount(pix > 0 ? 1 : 0);
}
MetricClass classification() const { return Undefined; }

View File

@@ -23,4 +23,7 @@
// using floats because they are typically used in calculations
// that require float precision (the actual values are integers)
extern const double typical_CP, typical_WPrime, typical_Pmax;
// calculate power index, used to model in cp plot too
extern double powerIndex(double averagepower, double duration);
#endif