The Performance Management Chart

Now that I can analyze and plot my workouts in detail, and I can estimate the Training Stress Score (TSS) of each ride, it is time to make use of all the statistics. It is nice to have numbers quantifying my trainings one-by-one, but how nice would it be to track my form and fitness during the season based on the volume and intensity of my rides. This is the concept behind creating the Performance Management Chart. I will write down (partly quote, or just rephrase) here the most basic things, but again, everything is based on the following two articles (take time to read them, they are very interesting):

What is the Performance Management Chart in TrainingPeaks WKO+?, by Hunter Allen
The scientific inspiration for the Performance Manager, by Andrew R. Coggan, Ph.D.

Andrew R. Coggan defines form as a combination of fitness and freshness (Form = Fitness + Freshness). You will have a really good day in the saddle when your fitness level is high, and when your fatigue level is low. Fitness is a response to training stress (or training load); the more you train the better you will be. Freshness is simply a result of rest. As TSS quantifies training load, knowing TSS values of workouts from the past enables us to determine the rider’s fitness in the present, and see how much training is needed in the future to raise this level higher.

The Performance Management Chart is based on Banister’s impulse-response model (see 2nd article for details), and we define the following components:

1) Chronic training load (CTL) provides a measure of how much an athlete has been training historically (chronically). It is calculated as an exponentially-weighted moving average of daily TSS values, with the default time constant set to 42 days. CTL can be viewed as analogous to the positive effect of training on performance in the impulse-response model. It is a relative indicator of changes in performance ability due to changes in fitness.

2) Acute training load (ATL) provides a measure of how much an athlete has been training recently (acutely). It is calculated as an exponentially-weighted moving average of daily TSS values, with the default time constant set to 7 days. ATL can be viewed as analogous to the negative effect of training on performance in the impulse-response model. It is a relative indicator of changes in performance ability due to fatigue.

3) Training stress balance (TSB) is the difference between CTL and ATL, i.e., TSB = CTL – ATL. TSB provides a measure of how much an athlete has been training recently, compared to how much they have been training historically. It can be viewed as an indicator of how fully-adapted an individual is to their recent training load, i.e., how “fresh” they are likely to be.

In the Performance Manager concept, an individual’s CTL determines their performance potential, but their TSB influences their ability to fully express that potential. Their actual performance at any point in time will therefore depend on both their CTL and their TSB, but determining how much emphasis to accord to each is now a matter of trial-and-error/experience, not science. (Really go and see more details in the original article.)

Some other interesting quotes before I tell you about my progress in the topic:

“The following approximate guidelines may prove useful when analyzing prior data: a TSB of less than ‑10 would usually not be accompanied by the feeling of very fresh legs, while a TSB of greater than +10 usually would be. A TSB of -10 to +10, then, might be considered neutral, i.e., the individual is unlikely to feel either particularly fatigued or particularly rested. The precise values, however, will depend not only on the individual but also the time constants used to calculate CTL and ATL, and therefore should not be applied too literally.”

“The optimal training load seems to lie at a CTL somewhere between 100 and 150 TSS/d. That is, individuals whose CTL is less than 100 TSS/d usually feel that they are undertraining, i.e., they recognize that they could tolerate a heavier training load, if only they had more time available to train and/or if other stresses in life (e.g., job, family) were minimized. (…) On the other hand, few, if any, athletes seem to be able to sustain a long-term average of >150 TSS/d.”

“In addition to the absolute magnitude of CTL, considerable insight into an individual’s training (and/or mistakes in training) can often be obtained by examining the pattern of change in CTL over time. Specifically, a long (e.g., 4-6 week) plateau in CTL during a time when a) the focus of training has not changed, and b) the athlete’s performance is constant is generally evidence of what might be termed training stagnation – that is, the individual may feel that they are training well, by being very consistent and repeatedly performing the same workouts, but in fact they are not training at all, but simply maintaining, because the overload principle is not being applied. On the other hand, attempting to increase CTL too rapidly, i.e., at a rate of >5-7 TSS/d/week for four or more weeks, is often a recipe for disaster, in that it appears to frequently lead to illness and/or other symptoms of overreaching/overtraining. Of course, since changes in CTL are driven by changes in ATL, this means that any sudden increase in the training load (e.g., training camp, stage race) must be followed by an appropriate period of reduced training/recovery, so as to avoid too great of an overload.”

So now that I have all my rides processed with my python script (even the indoor ones, so really all cycling workouts), I only had to write a script which grabs the TSS values from every statistics file (then calculates daily values if there were more rides on a given day), calculates the ATL, CTL and TSB values for every day in the given period, and plots them (plus saves the data as a table). This was not too hard ;) There is even an option to change the default time constants in the parameter file (the same parameter file which is used by the workout analyzer and plotter script), and to define a start date and end date for the plotting in the command line. Then after giving the

`>python plotgarmintcx_makePMC.py 20101201 20110920`

command (where the dates are optional and only affect the plotting limits, while the calculations are always done using all the data), you have your Performance Management Chart plotted and all the data saved in an ASCII file too. Let’s see how the result (with some additional comments photoshopped over in red) looks like (click and it will be bigger)!

As a conclusion, I think it is a very nice visualization and an extremely useful tool for a cyclist!

Estimating cycling power and training load

Updated 1: I modified the script slightly to perfectly match the estimation method of Joe Friel (see below), and as this had a small but clearly positive effect on the results, I have also updated the last plot and the paragraphs describing it at the end.

Updated 2: I have also tested the power estimate on very low intensity efforts with known average wattages (check out the bottom of the post).

You might remember that I have written a python script earlier this year, to analyze my cycling workouts and besides the calculation of detailed statistics, also create all kinds of fancy (multidimensional) plots. If you do not remember, or you would like to refresh your memories, please click here before reading this post further.

The most important thing missing from my script was the ability to directly compare different workouts. Of course you can tell that a 150 km ride with 5000 meters of elevation gain is more difficult than an easy 50 km Sunday afternoon ride, but how much more difficult? And what about an easy 75 kilometer training and a short but hard interval session? How do these compare? How tired am I going to feel myself after these? I really wanted to create or find a metric which tells me how much I did on a training. Of course this is only a problem when you don’t have a power meter installed on the bike, because that would directly tell you the amount of work in SI units for every workout. But power meters are expensive, and most importantly I don’t have one. This situation might change in the future, but till then let’s see what can we do.

I kinda forgot about the problem (and I did not even start dealing with it earlier, I just simply made a note on my To Do list), but some days ago Strava (a similar site to Garmin Connect, but with competitive – social media based – extras, unluckily with basically no users in Europe, so it is not an alternative for me) introduced a so called suffer score on their website, basically giving a rating to every ride based on its intensity (estimated from heart rate – HR – data) and duration. I knew that the algorithm behind this will be quickly decoded on one of the blogs I frequently read, and indeed it did happen very quickly, go and have a look there. First I wanted to implement this into my script, but then I got some extra motivation from the post and the comments there, so I looked a bit into the literature, and thus I got to know about the Training Stress Score, or simply TSS (among others, but this is the most important thing for us right now). To save some space here, check out the following three sites, so I can skip retyping things which are already on the Internet.

Though TSS and all these metrics are used in and based on power measurements, you can see that it is possible to give a good estimate (as good as estimating the realtive power on climbs from the slope gradient and VAM, which my script already did before) of it from time spent in HR zones using the scaling values from Joe Friel. We have seen that by definition a TSS of 100 equals to a one hour ride at FTP (so as hard as you can go for one hour). This means that rides shorter than one hour can have a TSS/hour higher than 100, but longer rides will have a lover value. So the TSS value tells you how big the training load of a given ride was (and it is related to the amount of post-ride fatigue), and the TSS/hour value gives you the intensity of your workout. The way it’s calcualted, TSS varies by the square of intensity. That means if you’re only going at 90% for an hour then you’re only accumulating 81 TSS per hour (90% = 0.9, which squared is 0.81, then you multiply by 100 to get TSS). So from the TSS/hour you can calculate an intensity factor, which gives you your average power output in units of your FTP power for the whole workout. Given that you know your FTP power, you can have a good estimate of the average power of any of your training rides! Now that is pretty cool. So that is what I have built into my script, this way now the TSS, TSS/h, average power and total work estimate values are also given in the summary file. And I also performed some test calculations and comparisons – because you should never forget, these are estimates! You need to know your FTP, and your HR at FTP, and then you might even get a reasonable value…

First of all, I wanted to see what is the intensity factor of my personal best ride to Mechelen and back. It was an approximately 1 hour 20 min all out effort, and the script gave an intensity factor of 1.00, meaning that I was riding on FTP. Though the ride was a bit longer than one hour (when it should not be possible to ride on FTP anymore), but I had a small 10 min break between the two legs in Mechelen, so it might still be a valid approximation, but for sure it should be extremely close to reality. Also, though it was a very tough ride, because it was short, the TSS value is ‘only’ 135.0, meaning that in 24 hours I might have probably almost fully recovered. In comparison, a normal ride (in my terms, so an average of 32 km/h instead of the record 35.7 km/h) on the same route gives a TSS around 110, while a recovery ride is probably below 100, and my epic ride (147 km and a bit more than 5000 meters of elevation gain) climbing twice up from sea level to the highest point of La Palma had a TSS of 483.7, which – as you have already guessed it probably – is in the epic category. Just as comparison, the last short  (46 km and 400 meters of ascent) and recovery paced ride from France had a TSS of 69.5 (which is approximately half the TSS of my personal best ride which was done on an almost equally long, but completely flat route, so this really shows how easy this French ride was). So as I got an IF (intensity factor) of 1.00 on a ride which is very close to the definition of FTP I was already quite happy with the result. (If for such a ride you get something like 1.05 or even higher as IF, then that is a sign that your threshold heart rate is now higher, so you should change it accordingly in the parameter file.)

As a second test I wanted to see how does this power estimate compare to the power estimate from VAM and average gradient, which is a widely accepted and used relation for climbing sections. If the power values from the two methods match, then it is OK to use the power estimate from the hourly TSS value on rides even with no climbing at all. So first I took my recent ride up to the Mont Ventoux, where I did 1 hour and 40 minutes of all out riding, so I expect to get an IF around 0.95 and of course I am very interested to see how the two different power estimates will differ from each other (if they will differ at all). So here is the statistics file (recent additions marked with a grey background):

So from the IF of 0.96 you can see that indeed I did all I could in this time frame. Now we can estimate the average power from my FTP, which is somewhere around 300 W (or maybe a bit more, but I have to admit I don’t have a recent measurement, so I can only guess this from my workouts on the trainer back in the first months of the year). The result from this is 288 W. What about the value from the other method? I was ~70.5 kg and my bike + drink and food + clothes is an extra ~11.5 kg, then with a total weight of 82 kg and the relative power estimate from the VAM and gradient you get an average power of 287 W. These values are surprisingly almost perfectly identical! This means that I can most probably trust the TSS based method, and use it for complete rides, while the VAM and gradient based method only works on climb sections. This is quite nice! Of course one measurement is not a measurement, so I wanted to check this on other climbs as well. Unluckily I don’t have to many climbs (as Flanders is pretty flat), but I still managed to put together a sample of 18 climbs from this year, mostly from my rides on La Palma in may, and some others from later (so there is a chance that my FTP was not the same at the time of the different rides, but I still calculated with the same value, while for my total weight – with equipment included – I could make small changes based on me having a backpack with 2 extra liters of water or not). The sample has climbs from short explosive hills to the long ascents of La Palma, steep climbs and not so steep climbs, climbs where I was really fit and well recovered, and also climbs where I was tired, to see what is the effect of these on the relation. So all these climbs are displayed on the plot below (the size of the circles is related to the length of the climb, while the colour resembles the steepness).

With a perfect 1:1 relation between the two different power estimates we expect the climbs to fall on the x=y linear (which is the grey dashed line here). The correlation is well visible, with of corse some noise, but the trend seems to be pretty clear. The biggest outlier is the Smeysberg on the top right, which is a very short (430 meter) but very steep (an average of 9.8%) climb, and the reason why it is an outlier is that it was a sprint effort well above threshold, but starting with a very low heart rate, so it took some time till my HR got up into the regime which really corresponds to the level of my power output, and this time was in the order of the full length of the effort, so of course the TSS based metric is lower. For such sprint efforts the heart rate based estimated TSS will be always lower than the power based, because 1) the already mentioned lag of HR behind the sudden raise of power output, 2) that much above FTP the HR will not get higher, it does not matter if you maintain 400 W or 600 W for 30 seconds, your HR will be probably stuck at you maximum HR value. But these problems only arise when you do very short above threshold sprints. This is also why one of the small blue dots is also a clear outlier. Still, in the region where most of my training rides are (~220 W to 300 W) the match is almost perfect. Fitting a linear [y = f(x) = mx + b] to all the climbs (solid grey line) or only climbs which were longer than 3 km (a.k.a. efforts where there was a significant heart rate lag were dropped, thick black line) gives the following equations: