Help getting started with custom field

I’m wanting to calculate a regression line for each activities power/HR, and then return the slope of that line as a custom field.

In WKO the expression is “slrm((ewma(power,30),heartrate))”

In this post I found a function to calculate linear regression of x & y:

I’ve modified the function name and have it return just the slope in the code below.

So far so good.

Now I need some code to use the function. Strong background in algorithms and have been programming in C and shell scripts for 40 years, but not a programmer.

Poking around the forum, I’ve got some (ugly) skeleton code:

{
  let activity = icu.activity

  let Power = icu.streams.fixed_power;
  let ewma30Power = [];
  let HR = icu.streams.fixed_heartrate;

/// calculate EWMA power
???

let trend = linRegSlope(ewma30Power, HR);

return[trend];
}

function linRegSlope(x, y) {
	let SXi2 = 0;
	let SXi = 0;
	let SXiYi = 0;
	let SYi = 0;
	let n = x.length;
	for (let i = 0; i < n; i++) {
		SXi = SXi + x[i];
		SXi2 = SXi2 + x[i] * x[i];
		SYi = SYi + y[i];
		SXiYi = SXiYi + x[i] * y[i];
	}
	let det_A = SXi2 * n - SXi * SXi;
	let m = 0;
//	let b = y[0];
	if (det_A != 0) {
		m = (SXiYi * n - SXi * SYi) / det_A;
//		b = (SXi2 * SYi - SXiYi * SXi) / det_A;
	}
	return [m];
}

Appreciate any pointers and nudges in the right direction.

You could adapt this one for your purposes:


{
// Samples
const values1 = [200, 200, 200, 200, 200];
const values2 = [120, 121, 122, 123, 124];

// Division 
const dividedValues = values1.map((value, index) => value / values2[index]);
console.log(dividedValues);

// Function 
function linearRegression(x, y) {
    const n = x.length;
    const sumX = x.reduce((a, b) => a + b, 0);
    const sumY = y.reduce((a, b) => a + b, 0);
    const sumXY = x.reduce((sum, xi, i) => sum + xi * y[i], 0);
    const sumX2 = x.reduce((sum, xi) => sum + xi * xi, 0);

    const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
    const intercept = (sumY - slope * sumX) / n;

    return { slope, intercept };
}

// Index of values
const xValues = dividedValues.map((_, index) => index);
console.log(xValues);

// Calculate linear regression
const result = linearRegression(xValues, dividedValues);

console.log(`Slope: ${result.slope}`);
console.log(`Intercept: ${result.intercept}`);
}

1 Like

Thanks, far easier to get started in a new programming language with examples. I’ve got a recursive and iterative formula for ewma and need to reverse engineer alpha from WKO (first guess - its 0.0645 = 2/30+1 where 30 comes from the number of seconds).

I think it should be the 30s moving average power.
You can calculate it like this:

Edit:
I looked at it again, and I think EWMA is exponentially weighted, so not sure if there is a server side function for this. Then you‘re right, you have to iterate through the power stream.

For Alpha you should be right, it is 2/(N+1), where N is the number of seconds (30 in this case)

not if I’m trying to match WKO5:

Step one is to match WKO. Step two is to experiment with substituting other moving averages. Off the top of my head, reaching back to my old signal processing background, they are slightly different low-pass filters and I’m not sure how much that impacts the slope of the regression line (I’m looking for specific workouts above a certain slope).