-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnormalized_power.js
73 lines (65 loc) · 2.29 KB
/
normalized_power.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Normalized Power
//
// Vance, Jim. "Run with Power", page 46
//
// https://www.mathworks.com/matlabcentral/cody/problems/3064-cycling-normalized-power
//
// In cycling, a power meter is an indispensable tool to record power output
// (in Watts) and measure fitness gains and performance metrics. When analyzing
// the data though, many different workouts can yield approximately the same
// average power, despite major differences between workouts (e.g., a long
// steady effort vs. sprints or intervals). Normalized power (NP) is a method
// to measure the effect of more intense efforts on the overall workout. NP is
// calculated by the following four steps (from Training and Racing with
// a Power Meter by Allen and Coggan):
//
// 1. Calculate a 30-second rolling average of the power data
// 2. Raise these values to the fourth power
// 3. Average the resulting values
// 4. Take the fourth root of the result
function NP(data) {
// check if data series is available
if (!data.hasOwnProperty('seriesSampled') ||
!data.seriesSampled.data.hasOwnProperty('power')) {
return null;
}
// extract relevant data
const {
duration,
seriesSampled: {
data: {
power
}
}
} = data;
// window length in seconds
const window_length = 30;
// extrapolate data
var extrapolated_power = [];
const seconds_per_sample = (duration / power.length).toFixed();
var write_idx;
var read_idx = -1;
for (write_idx = 0; write_idx < duration; write_idx++) {
read_idx += write_idx % seconds_per_sample === 0 ? 1 : 0;
extrapolated_power.push(power[read_idx]);
}
// initial window
var window_sum = 0;
var add_idx = 0;
while (add_idx < window_length) {
window_sum += extrapolated_power[add_idx++];
}
// slide the window and calculate the rolling average
var remove_idx = 0;
var average_counter = 2;
var average_of_windows = window_sum;
while (add_idx < duration) {
window_sum += extrapolated_power[add_idx++];
window_sum -= extrapolated_power[remove_idx++];
var window_average = window_sum / window_length;
average_of_windows += (Math.pow(window_average, 4) - average_of_windows) / average_counter++;
}
return (Math.pow(average_of_windows, 1/4)).toFixed(1);
}
// Additional code when added to tredict:
//APPEND return NP(this);