thomaschampagne / elevate

A sport app to "Elevate" your training experience and goals! Track your fitness and progressions over time. Analyse deeper your activities. And more...
https://thomaschampagne.github.io/elevate-docs/
Mozilla Public License 2.0
1.27k stars 174 forks source link

Running Index issue for near maximale performance... #871

Open tsourbier opened 5 years ago

tsourbier commented 5 years ago

Polar provides a performance chart to correlate actual performance to the Running Index : https://www.polar.com/en/smart_coaching/features/running_index/chart (we notice how it seems linked to a Cooper test result...).

While it seems to work for practice runs, I noticed the Running Index of actual races and tests was off compared to the chart. It is easy to check for yourself checking any road race or Cooper test you've done.

Running a 40:35 10k at a 170 bpm average (max HR 178) gives me 59 Running Index while the chart marks it at 64...

Digging in the code and discussion linked to this feature it seems to come from this line of code :

const runIntensity: number = Math.round((averageHeartRate / userMaxHr * 1.45 - 0.3) * 100) / 100; // Calculate the run intensity; this is rounded to 2 decimal points

A runIntensity shall not be allowed to be over 1 (it was mentioned by Chrisx68) https://github.com/thomaschampagne/elevate/issues/704

As I understand it, the runIntensity is used to "normalize" any "easy" run to a maximal effort, not give up to 15% penalty to "hard" runs. This may lead one to believe (s)he did poorly at a race/test while in fact the best was given.

Oddly it seems the same issue may be found on the v800 (and possibly all Polar models) - I don't use it anymore but looking back on Polar flow I can see the "bug". This may be why it passed the quality checks... One may argue it could be a "feature" to be as good and as bad as Polar Running Index ;)

T.

jonaganoj commented 5 years ago

The breaking point is approx at 90% of max HR that for well trained is approx the lactate threshold. Does this mean that the index is not valid for race durations less than an hour? (for example 10K and less)

tsourbier commented 5 years ago

Correct, any effort where the average HR is abobe 89,65% will receive an undesired "penalty". As you point out this will typically be for any maximal effort test or race <= 10k or even longer for some (I averaged near 90% max HR on my marathons without being a top athlete).

Chrisx68 commented 4 years ago

Sorry for my late answer. I agree that the somehow artificial truncation is penalizing short races with duration below approx. one hour. I looked back in my database an found about 20 out of 131 runs where the factor (HR/HRmax x 1.45 - 0.3) was above 1. From these 20 runs, 12 runs where indeed less than an hour (average 40 minutes). Actually I don't know if such a truncation is done by Polar's algorithm. But after closer look, I think the upper truncation should be removed from the code. This change would anyway affect only very few activities where the effort is near maximal and the duration is short.

Chrisx68 commented 4 years ago

I just looked in the code and found no truncation in the above mentioned line of code:

const runIntensity: number = Math.round((averageHeartRate / userMaxHr 1.45 - 0.3) 100) / 100; // Calculate the run intensity; this is rounded to 2 decimal points

As such, no undesired "penalty" should be happen...

tsourbier commented 4 years ago

The problem is not truncation, it is that RunIntensity can be > 1.

The fix should be should be const runIntensity: number = Min(1,Math.round((averageHeartRate / userMaxHr 1.45 - 0.3) 100) / 100);

I averaged 94% HR on a marathon well over 3h, so depending on your training and physiology, it may not only be for "short" effort :D

tsourbier commented 4 years ago

to be clear from the original post on Running Index : Running Index = RI0 / x RI0 = 213.9 / t (d/1000)^1.06 + 3.5 x = HR/HRmax 1.45 - 0.30 (x should be truncated to 0..1)

by truncated the author meant within the range 0..1.

The purpose of the Running Index is to be able to compare runs at different intensities. The runIntensity, being usualy < 1, is used to bumped up the Running Index. All efforts > +-90% should be considered "all-out" and do not need normalization (runIntensity = 1).

jonaganoj commented 4 years ago

Yeah, the formula (probably) assumes that 90% HR is the anaerobic threshold and that all efforts above this HR is as the last writer called "all-out". HR could in competition situations or due to cardiac drift be higher than normal and then the RI would be lower. But what is the value of an index for an "all-out" effort where one can measure the actual results instead. One could of course improve the formula with using HR at anaerobic threshold instead of % of max HR, but again, the HR in competitions could still be higher than normal and still producing too low indexes.

Chrisx68 commented 4 years ago

ok understood.

I averaged 94% HR on a marathon well over 3h, so depending on your training and physiology, it may not only be for "short" effort :D

I would be interested whether your average marathon HR is always above 90%. If yes, maybe increasing the max HR would be an option to avoid training intensities >1? This of course would change (i.e. increase) also the RI of all other sub-maximal activities.

My observation is that finding the max HR is very crucial. I assume that the max HR measured normally under non-race conditions is lower than the value under race conditions as adrenaline pushes up HR (and also maxHR) during a competition. At least this is what I observe: The running index should normally independent on the running speed, but in my case it decreases with increasing speed. I explain this with a disproportionate increase of my HR with increasing speed(=stress=adrenaline). I can easily reach high HR in a race which I hardly reach under non-race conditions.

tsourbier commented 4 years ago

I've only been providing my personnal data as an example ;) I don't think it is interesting to discuss them here, but we should rather focus on the Running Index, what it means, how to use it, and why it should be fixed :)

The RI is based on the facts that :

Hence

If i determine that correlation then by knowing your max HR I could determine your max aerobic speed and guestimate from there your performance on races.

The RI tries to provide a "quik-and-dirty-one-size-fits-all" correlation, avoiding any complex calculations. It takes roughly into account that longer runs are harder by powering up the distance by 1.06 and "normalize" the HR to be at least 90% (the current behavior normalize the HR to be exactly 90%)

note : My use of the word "normalize" is not enterely correct, understand it the formula estimates the performance you would have reach should you have run at a 90% HR...

I know all this sounds a bit too simplistic as of course so many more things come into play:

(I didn't mention the grade as it is taken into account currently with added/substracted distance base of the total ascent and total descent)

RI should therefore be look at more as a trend than an absolute value. If my RI tends to improve then that probably means I'm getting fitter -- If I'm only running 5ks to train for a marathon, that does not mean I'll not face problems on raceday... but I'll certainly be faster to reach them :D

This is a quick and dirty way to compare the "quality" of 2 runs of different intensities et distances provided the conditions are more or less the same. It makes no sens to compare the RI of a trail run and a track session...

You can use the polar chart to ballpark the RI necessary to acheive a given performance (https://www.polar.com/en/smart_coaching/features/running_index/chart). If you are training to race a 45' / 10k, you know that you must reach RIs close to 58 for example.

Correctly used, this make even the "slow" jogging session fun. During those you'll get "rewarded" for your low average HR as the speed is not really supposed to be challenging. Your running economy gets measured.

In the original post (see #704) the idea is that all efforts beyond 90% HR are considered "all out" 100% intensity, the RI will therefore not need any "low-intensity correction", to acheive a better RI just run faster! Applying a "penalty" because the HR was high makes little sens... One cannot go over 100% intensity or that means we need to rethink what is "100% intensity" :D

Of course like the rest, this 90% (or 89,65%) is arbitrary but should roughly cover most people for most of the distances. If you can race above 90% then your RI will be underestimated, if you currently race under 90% of your HR, you probably have some room for improvement through training. Your RI will be at bit over-estimated.

We may not know precisely what our 100% HR is, it takes quite a bit of will and freshness to achieve it, it evolves with age, it depends on the sport (all-out biking, all-out running, all-out rowing may give you different max HR), ...

The RI is far from perfect but once you inderstand its limitations is a pretty cool way to track progress thru short/long/slow/fast runs with very little calculation. The simple figure it provides can be correlated to a level of racing performance (provided your training is adequate for that distance).

In the file activity-computer.ts the fix would read something like: const runIntensity: number = Math.max(1, Math.round((averageHeartRate / userMaxHr 1.45 - 0.3) 100) / 100 ); // Calculate the run intensity; this is rounded to 2 decimal points

T.

tsourbier commented 4 years ago

to answer previous comments :

Yeah, the formula (probably) assumes that 90% HR is the anaerobic threshold and that all efforts above this HR is as the last writer called "all-out". HR could in competition situations or due to cardiac drift be higher than normal and then the RI would be lower.

A max effort is a max effort. HR shall not be considered then.

If you know yourself well and have a lot of racing data, your average HR could provide you an indication if you have or not given your very best.

You could argue that if you race a 45 min / 10k @ 90% max HR average and another @ 95% max HR average. The first performance might look "better" than the 2nde one, but in fact in a "max effort" context they are the same. You are "worth" 45min on 10k (or a 58 RI).

But what is the value of an index for an "all-out" effort where one can measure the actual results instead.

Comparing RI accross races of différent distances can be interesting. Should you work on your speed or on your endurance? If your RI lowers with the distance that means you are lacking endurance, if it increases you are lacking speed.

One could of course improve the formula with using HR at anaerobic threshold instead of % of max HR, but again, the HR in competitions could still be higher than normal and still producing too low indexes.

It is a bit more complex than that... the runIntensity tries to evaluate the % of your HR reserve. It estimates that your resting HR is at 20% of your max HR and AT is at 90% of your max HR.

To accuratly capture the value of a sub-max run you would need to individualize that range, as well your personal endurance factor and speed/HR relationship.

I've been toying with my data to determine all that. But playing with thousands of HR/Speed datas points is far from simple in terms of calculation especialy when you consider that the data is never all that accurate...

First Beat published a white paper on the subject : https://assets.firstbeat.com/firstbeat/uploads/2015/10/white_paper_VO2max_11-11-20142.pdf

RI is certainly not perfect but given its simplicity to calculate and the fairly good indications it gives, provides an excellent bang for the buck I think.

tsourbier commented 4 years ago

My observation is that finding the max HR is very crucial. I assume that the max HR measured normally under non-race conditions is lower than the value under race conditions as adrenaline pushes up HR (and also maxHR) during a competition. At least this is what I observe: The running index should normally independent on the running speed, but in my case it decreases with increasing speed. I explain this with a disproportionate increase of my HR with increasing speed(=stress=adrenaline). I can easily reach high HR in a race which I hardly reach under non-race conditions.

The fact that your RI decreases with increased speed may be simply due to the bug I pointed out ;) Currently if you go above 90% max HR average, your RI decreases... Providing you a wrong clue you've been inefficient.

If you currently observe that phenomena while keeping your HR below 90%, that means you are more geared toward endurance and would probably gain doing speed work.

Reaching high HR indeed requires some motivation :D Top athletes are able to "red zone" in training when necessary when most are just afraid to push that hard because it is freaking painful.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

tsourbier commented 3 years ago

as I received the stale notification, let me point out the file & change to be made elevate-develop/plugin/core/scripts/processors/activity-computer.ts

line 452

const runIntensity: number = Math.round((averageHeartRate / userMaxHr * 1.45 - 0.3) * 100) / 100; // Calculate the run intensity; this is rounded to 2 decimal points

should be updated as:

const runIntensity: number = Math.min(Math.round((averageHeartRate / userMaxHr * 1.45 - 0.3) * 100) / 100,1); // Calculate the run intensity; this is rounded to 2 decimal points

as an intensity cannot go over 100% (only the coach can go 110% of his capacity LOL) this is consistent with the description of the feature made here : https://github.com/thomaschampagne/elevate/issues/704

where the original formula by @Chrisx68 mentioned :

Running Index = RI0 / x
RI0 = 213.9 / t * (d/1000)^1.06 + 3.5
x = HR/HRmax * 1.45 - 0.30 **(x should be truncated to 0..1)**

x being the Running Intensity, the **should be truncated to 0..1** was dropped out in the implementation.

T.

Chrisx68 commented 3 years ago

I would like to support this change in the code, as it reflects my original post #704. Can this be done in an upcoming revision?

thomaschampagne commented 3 years ago

Ok i postpone this to be done once the v7 is released (which will include the new desktop app)

tsourbier commented 3 years ago

thanks you for jumping in @Chrisx68 and @thomaschampagne (I'm taking the opportunity to "dire merci pour cette superbe extension Thomas")

byroncheung commented 3 years ago

interesting stuff. i got to this page by looking up running index forumla. i have been using running index for my running, massively useful in keeping track of training progress and predicting race performance.

i wonder if there exists a similar measurement for biking. looking at the formula posted about:

Running Index = RI0 / x RI0 = 213.9 / t (d/1000)^1.06 + 3.5 x = HR/HRmax 1.45 - 0.30 (x should be truncated to 0..1)

is the "RI0" basically a representation of power? so for biking can i just take the power output and divided by x would that be a reasonable version of a "biking index"?

tsourbier commented 3 years ago

@byroncheung interesting idea.

The RI0 formula was reverse engineered from Polar and doesn't directly translate to the actual power. The ^1.06 accounts for the fact we are expected to run a bit slower as distance increases.

I'm also not too sure if the avg power of a ride is always meaningful as a biker may recover better during the downhills than a runner.

byroncheung commented 3 years ago

@tsourbier i hear you...

i'm mostly a spinner (well I'm mostly a runner but now is cross-training on peloton because of injury) and would like to see how I improve my "biking" performance. I'm kinda hoping the power output from the peloton will be more accurate than a real ride and maybe power/HR will provide a decent measure of biking fitness/efficiency...

tsourbier commented 3 years ago

@byroncheung if we are talking about an indoor bike that's even trickier as the watts are not really measured but just estimated from the RPM & Gear (same can be said about running power to be fair).

Being indoor offers much less cool than going through the wind making it harder to maintain high wattage.

That said it may not hurt to try to find some relationship :

That may allow you to derive your own formula for non maximum efforts (more than % of HR Max, try to take the % of HR Reserve which is HR Max - HR Rest.)

Have fun!

jonaganoj commented 3 years ago

I have used the running index and tried to make my own version. Regardless it is hard to accurately use it to compare to others, and even comparing your own runs with different paces. I have most success with comparing workouts with quite the same intensity and the same interval and rest periods. Continuous runs are easier to compare than interval sessions. The heart rate varies slightly day to day, but over weeks it seems possible to compare the mean values. The index and your heart rate is based on your max and max could change slightly over years so comparing over to long time gaps can be less accurate. Since it is hard to compare across different paces accurately one can live with a very simple index like pace/HR or power/HR and compare equal workouts. Then you can track the development / improvement of such a simple index for each type of workout.

Chrisx68 commented 3 years ago

I all agree what was said before. In principle you are right. I am currently working on a "biking index". For that I am collecting power and HR data of c<cling activities and try to find a suitable correlation between Power and HR. But I am less confident that it works. Compared to running, riding is much more irregular with lots of ups and downs in the heart rate....

tsourbier commented 3 years ago

@Chrisx68 if you want to dwelve into the complexity of biking you might want to checkout the work done by bestbikesplit.com... super interesting. Afaik they are trying to convert watts into speed, more than hr into watts so this wouldn't directly relate to us, but still that gives a nice illustration on how running & biking are different beasts.

thomaschampagne commented 2 years ago

@tsourbier Could we speak together on "phone/discord/google meet" to make sur I properly understood everything so I can handle the ticket for version 7. Email me at: th.champagne[at]gmail.com. Thanks :)

tsourbier commented 2 years ago

@thomaschampagne email sent :)

thomaschampagne commented 2 years ago

I all agree what was said before. In principle you are right. I am currently working on a "biking index". For that I am collecting power and HR data of c<cling activities and try to find a suitable correlation between Power and HR. But I am less confident that it works. Compared to running, riding is much more irregular with lots of ups and downs in the heart rate....

I can provide you 3M anonymized rows (.csv) coming from Strava. The header:

sportType, movingTime, distance, elevation, avgSpeed, avgHr, avgCad, avgWatts, isTrainer, geoBaryCenter
jonaganoj commented 2 years ago

Interesting and may I chip in?

I both run and cycle. I think power is optimal to show effort and is quite reliable for cycling. My HR does not vary much or more in running or cycling. If the cyclist have a reliable FTP, which ties HR at higher intensity to power, one could almost skip HR for cycling index. Alternatively one could read the HR and power correlation from a power curve at least for the mid or lower part where duration is above 4-5 min.

Power for running is too inaccurate and noisy at least on my garmin.

Br

Jon Arne Glomsrud Get Outlook for Android

Chrisx68 commented 2 years ago

I all agree what was said before. In principle you are right. I am currently working on a "biking index". For that I am collecting power and HR data of c<cling activities and try to find a suitable correlation between Power and HR. But I am less confident that it works. Compared to running, riding is much more irregular with lots of ups and downs in the heart rate....

I can provide you 3M anonymized rows (.csv) coming from Strava. The header:

sportType, movingTime, distance, elevation, avgSpeed, avgHr, avgCad, avgWatts, isTrainer, geoBaryCenter

Does it also contain maxHR? Without the maximum HR, the avgHr is not menaingful.

Chrisx68 commented 2 years ago

Interesting and may I chip in? I both run and cycle. I think power is optimal to show effort and is quite reliable for cycling. My HR does not vary much or more in running or cycling. If the cyclist have a reliable FTP, which ties HR at higher intensity to power, one could almost skip HR for cycling index. Alternatively one could read the HR and power correlation from a power curve at least for the mid or lower part where duration is above 4-5 min. Power for running is too inaccurate and noisy at least on my garmin. Br Jon Arne Glomsrud Get Outlook for Android

I fully agree. Doing an FTP test is the best way to monitor your fitness. If during such a test (e.g. a 20 min all-out test), the average HR is called HR@FTP, then the goal would be to find a relationship to extrapolate the power at subHR excercises to FTP: FTP = function (power@SubHr, avgSubHr, HR@FTP ) Having such a function, it would be theoretically possible to determine the FTP for any bicylcle ride.

tsourbier commented 2 years ago

@Chrisx68 the max HR is supposed to be a known constant in the user's profile. You are -hopefully- not requested to reach it at each ride/run 😂

thomaschampagne commented 2 years ago

I all agree what was said before. In principle you are right. I am currently working on a "biking index". For that I am collecting power and HR data of c<cling activities and try to find a suitable correlation between Power and HR. But I am less confident that it works. Compared to running, riding is much more irregular with lots of ups and downs in the heart rate....

I can provide you 3M anonymized rows (.csv) coming from Strava. The header:

sportType, movingTime, distance, elevation, avgSpeed, avgHr, avgCad, avgWatts, isTrainer, geoBaryCenter

Does it also contain maxHR? Without the maximum HR, the avgHr is not menaingful.

Unfortunatly no :/ But that's possible to retrieve it. but we should wait 1 or 2 months to gather sufficient data.

jonaganoj commented 2 years ago

Over time, I have experienced for me that sub Vo2max even easy running, 1 bpm is 1% faster/slower pace. I also use 1 bpm is 3W around easy cycling. Get Outlook for Android

thomaschampagne commented 2 years ago

Does someone here has a polar watch with official polar running index history?

thomasturrell commented 2 years ago

One may argue it could be a "feature"

I’m firmly in this camp.

I have noticed that my running index for races is significantly lower than I usually get on a training run. Whilst at first I used to believe it was a bug I now believe that it is correct.

On race day my body is full of adrenaline and I’m not as relaxed as I would be for a training run. I might hit my predicted time but my heart rate is far higher than it should be.

Maybe the answer is a simple as not giving races a running index.

However I do not believe that a single running index is useful, I only look at my rolling average over a year. (Even over a year it needs careful interpretation because of wind, snow, rain, temperature, etc)

tsourbier commented 2 years ago

@thomasturrell the bug was affecting all runs with an average > 89,65% FC Max... that explains the sub-par Running Index :)

It could indeed be a feature as we are now departing a bit from Polar's Running Index (I believe we mostly differ on the data filtering to account for "bad data" and we are a bit more precise to account for uphills/downhills...). Still a work in progress as, as we discovered going deeper with Thomas, there was much more of a fix that initially thought 😂

T.

thomasturrell commented 2 years ago

@tsourbier I find that bad data gets hidden in my average rolling running index so I'm not too concerned about uphills and down hills, although I can see that without taking it into account it makes it impossible to compare two different runners.

As it stands I think that someone that was doing a mix of road running and trail running would have to be very careful about drawing too many conclusions from their running index.

I see my running index as a personal measure. I am very careful not to look at it run by run and I do not compare it with anyone else. If I want a running index that I can compare with another run, I run the same route at the same time.

The biggest issue that I see in my running index is that is seasonal, your can literally see the seasons in my rolling average, not because of changes in my training but due to the temperature. My performance is very temperature dependent.

I believe that Elevate could find similar runs and compare the running indexes but I personally I think that accounting for all the variables would be very hard.

Many things would effect a running index such as, terrain (sand, mud, snow, ice) elevation gain or loss, altitude, humidity, temperature, shade, wind direction, etc.

Anyway, I'm in danger of simply thinking aloud and getting off topic ;-) Nice to chat to like minded people.

avcodecs commented 1 year ago

Hello, everyone. Thank you for sharing the formula of RI @tsourbier. RI0 indicates the exercise intensity of different distances, which has a strong correlation with VO2max (Jack Daniels' formula) of the corresponding distance in Table 4 given by firstbeat. For example, in 1km running, the residual between the predicted VO2max and the VO2max given by firstbeat is only less than 5%. But there is no correlation between races at different distances. If the parameters obtained by nonlinear regression are used to fit RI0 and VO2max, the error between them will reach 30% or even higher.

tsourbier commented 1 year ago

Running Index does not intend to be correlated exactly with VO2 max (as Firstbeat tries to do). This is why Polar refers to it as an "index". It is just a simple tool to easily compare runs at different intensities and different duration.

T.