Feature request: TSS on screen



It is a bug, I reported it months ago. First time was on July 1 and it dropped 8 points right after I +5 min extended the workout. It happened other times too, but I never captured a screenshot. On Aug 29th I finally captured screenshots - entered the cool down of Mount Field and TSS was approximately 60, then it dropped to 23 (yes, it dropped 37 points) and I captured screenshots. A few minutes later the workout ended with a TSS of 64.

Only seen it happen when I’ve added +5 min to a cooldown - either because that triggers it, or its the only time I pay close attention to TSS during the workout.


I can’t say for certain whether or not my experience was during an added cool down or not, but it definitely only dropped a point or two. I wouldn’t say mine was a bug based on that, but your experience does sound… interesting.


I’ve also seen it drop a point or two.

But this one is pretty obvious:

Mount Field has a 60 minute TSS of 62. And here is post workout:

p.s. I think TSS is monotonically increasing function, but to be honest I haven’t seen the formula


I’ll work this out more fully later but the equations are as follows;

TSS = (s x NP x IF / 3600 x FTP) x 100



TSS = (s x NP^2 / 3600 FTP^2) x 100

Where s is the duration of the workout in seconds.



My theory as to why TSS can decrease is because the NP is squared while time (in seconds is not). Some algebra will also show that the time factor of the equation is a linear ratio to one hour, meaning at t = 1h, then s = 3600s which then is equal to 1. So it follows that TSS scales from 0 to 1 as the time increases from 0s to 3600s (1hr). Where fluctuations in NP are squared, so even small changes are magnified exponentially. So as long as NP changes faster than the time ratio changes it can decrease. I believe in order to prove this mathematically I may need a better understanding of NP as a mathematical function.


Playing around with some numbers today makes me think that the required reduction in NP to even keep TSS at the same value, let alone decrease, is impossible even when you are producing no power.

I’ll post some numbers later if I get time.



breaking it down…

  1. It starts with a 30 second moving average on the sampled power data, which is a finite impulse response filter. The difference equation is:
    Power30secAvg (n) = 1/30 * [ power(n) + power (n-1) + power (n-2) + … + power (n-29 ]

  2. Then raise each 30 second average in the series above to the fourth power:
    Power30secAvg-to-FourthPower (n) = Power30secAverage(n) ^ 4

  3. Calculate the average ‘fourth power of 30 sec moving averages’ of the entire workout (entire time series):
    AverageFourthPower = 1/elapsedTime * [ Power30secAvg-to-FourthPower(0) + Power30secAvg-to-FourthPower(1) + … + Power30secAvg-to-FourthPower(elapsedTime) ]
    (where elapsedTime is in seconds)

  4. Calculate Normalized Power as fourth root of step 3.
    NP = AverageFourthPower ^ 0.25

edit: cleaned up for readability and fix my rookie mistake of using “cubed” instead of “fourth power”


Raising to the fourth power is not cubing (that’s to the third power) but your notation is correct. I also think it should be averaged over s - 30.



Thanks, I fixed the cubing error in the written description. As you said the formulas are correct. Teach me to not review a contract and try to do college math at the same time LOL

A 30 second average over 1 second sampled data is calculated over these timestamps:
n = 0 to 29
n = 1 to 30
n = 2 to 31
n = 3 to 32

so the notation power(n) … power (n-29) should be correct.


Sorry, my mistake.


Nice algorithm on lines 53 - 103 of the GoldenCheetah code: https://github.com/GoldenCheetah/GoldenCheetah/blob/master/src/Metrics/Coggan.cpp


OK, so here’s my whisky fuelled proof (of sorts):

(All of this assumes an even effort which then drops to zero hence the 30 second average assumes (NP(s) x 29)/30

TSS is recalculated on a second by second basis as is Normalised Power, therefor for TSS to go down it must do so on a second to second basis.

TSS(s) is equal to = (s x NP(s)^2 / 3600 x FTP^2) x 100

NP(s+1) must be equal to ((TSS(s) x 3600 x FTP^2) /(s + 1))^0.5 / 100 to keep TSS at the same value as at ‘s’.


NP(s+1) is equal to (((NP(s) x (29/30))^4 + (NP(s)^4 x (s-29)) / (s - 28))^(1/4).

When you plot the difference between the two the line is asymptotic to zero, meaning the condition for TSS to go down can never be met.

I’ll check this tomorrow and plot the graph and some better looking equations.



TSS(n) = n x NP(n)^2 x “a constant” [which is “1 / (36 x FTP^2)”]

all you need to show is that n x NP(n)^2 cannot decrease from n to n+1, for every 0 < n < elapsedTime

I’ll try and take a look later, I see what you did – its like the GC algorithm, from n to n+1 you drop the old power(n-29) and pick up power(n+1).


@danejackson Just for clarification on the wording of your description of the NP calculation: from the MatLabs work by Cody, it is the 4th root of the sum of the weighted average power of each segment raised to the 4th power. Perhaps your wording was just simplified and is the same? Here is where I obtained the formula:


Proof by induction. You just have to prove that it’s true for n+1 if it’s true for n, and prove that it’s true for n = 0.


Thanks, I used to do stuff like that in my sleep. But 25 years in technical mktg and sales is like having liposuction performed on your grey matter lol


:joy: not done one in anger in many years


Still no TSS on the screen though is there :wink:


I bet you wish you’d never asked.



but you got a two for one deal on the answer!!!

  • live TSS is on iOS/Android
  • a chapter 7 “Training and Racing with a Power Meter” math lesson on TSS

TrainerRoad is working on upgrading desktop apps (Windows and Mac) to have same features as mobile apps.