User Formulas in V3.3

7,075 views
Skip to first unread message

Mark Liversedge

unread,
Aug 23, 2015, 5:38:17 AM8/23/15
to golden-cheetah-users
We will release 3.3 at Christmas, it will contain user formulas and a metric scatter plot, and maybe a few other little fixes. We will also release 4.0 sometime around next years TdF that will contain planning and impulse-response modelling.

I said, for those that are playing along with the master repo (3.3 development) that I would document the User Formula stuff, so here is a very brief and to the point summary of what formulas can do. As ever, it is likely to change rapidly over the next few weeks, but these are the current features.

[FWIW, I am entirely conflicted about allowing vector operations by default; on the one hand they are elegant but in the other they aren't exactly user friendly ! Also, the Eigen matrix lib is likely to become a dependency for some new work on impulse response that needs matrix functions so we may also extend to allow that. But then, this "simple" idea is turning into a clone of R and I think that is wrong...]


GOLDENCHEETAH FORMULAS

1. EXTENDING DATA FILTERS

We have extended the datafilter functionality that allowed you to write logical expressions to filter rides to return values that can be used when charting.

For example, in the past you could write;

NP > Average_Power

To find NP busters in your ride collection. We have now updated this to allow the result to be a value, that you could then chart, in this case how much of an NP buster is it:

NP - Average_Power



2. WORKING WITH RIDES

At present, the formulas are being used to generate values to plot on long term metric charts. They are applied for each ride and the result is then plotted. There are drawbacks to this approach, but for now, they allow us to get started and we can then consider using them in more complex ways.

Certainly in the future I would like to use them to compute new metrics from ride data, dervice data series from ride data and compute impulse-response models or even power duration models. But for now they are applied to rides when plotting LTM charts.



3. GETTING STARTED

If we create a new LTM chart and add a curve we can choose a 'Formula'. This formula can be entered into the formula editor. The editor has autocomplete, syntax highlighting and brace matching. The autocomplete will offer completions for all the named metrics (things like Average_Power, TSS, IF) as well as metadata (things like Sport and Workout_Code) as well as all the built-in functions (things like min(), max(), sum()).

The very simplest formula would be:

1

This will plot the value 1 for every ride. We can extend this a little and change that to a ride metric:

TSS

This will plot the TSS value for every ride. And of course we can then extend this with some arithmetic:

TSS/2

Will plot half of TSS for every ride. But you will quickly want to use the metrics in more interesting computations. For example you might want to calculate how many calories were burned in a workout, for bike rides that is really easy (its essentially the 'Work' metric), but for runs we will need to calculate it, e.g. as weight * distance in imperial;

(Athlete_Weight * 2.2) * (Distance * 1.609)

To help out a little, we also have access to the athlete configurations, via a function called config(), for example to use the athlete weight (on the date of the ride) we can rewrite the formula as;

(config(weight) * 2.2) * (Distance * 1.609)

The config function will return values for; cp, cv, scv, w', pmax, height, weight, units, lthr, maxhr, rhr. All of which are returned in metric units. So you will need to convert if you prefer imperial units, the config(units) will be non-zero if imperial units are preferred.

There is also a const() function that will return high precision mathematical constants for e and pi that can be used in more advanced formulas. As you might expect we also have math functions to use to; cos/tan/sin and acos/acosh friends, exp, log/log10, fabs, ceil, floor, round as well as isinf/isnan. They all call standard math functions (see C++ math.h).



4. MAKING DECISIONS

In our example of calories burned we use two different formulas depending on if the activity is a bike ride or a run. So we need to decide which one to use in our formula. There is a conditional statement that will be familiar to C and Java developers:

isRun>0 ? (config(weight) * 2.2) * (Distance * 1.609) : Work

Unpicking this, the '?' operator and ':' operators are the key piece. The '?' after 'isRun>0' tells us it is a conditional statement. If isRun>0 then evaluate the expression to the left of the colon, otherwise the one to the right. They can be nested so you can get quite funky.



5. BESTS, TIME IN ZONE AND ESTIMATES

As well as all the pre-computed metrics available to use, we can also work with the mean maximal data for the ride as well. We use the best() function for this:

best(power, 3600)

Will return the best 1hr power within this ride. The duration is always in seconds, and we can choose from power, hr, apower, cadence, speed, torque, vam, xpower, np and wpk. There are lots of formulas in the literature that use power for a duration to derive other markers. Naturally we may also want to plug in an estimated value from the power duration models too. So to access an estimate that applied on the date of the ride use:

estimate(2p, 3600)

As you would imagine this will return the estimated 1hr power using the 2 parameter critical power model. You can use other models; 2p, 3p, ext, velo and ws are classic CP, morton 3 parameter, GC extended model, veloclinic and ward-smith respectively. You can also get the parameters that applied;

estimate(2p, cp)

Will return the estimated value for CP from the 2 parameter model. Where we supplied a duration in the previous example as the second parameter we can also request the parameters by name; cp, w', ftp, pmax can all be extracted.

We also provide functions for extracting time spent in zone, currently it is just for the configured power and hr zones;

tiz(power, 4)

Will return the time spent in seconds at power zone 4. 



6. WORKING WITH DATES

When filtering it is quite useful to filter rides based upon when they occurred. The date of the current ride is 'date', the current date is 'today' and we can create a specific date via the string format "yyyy/mm/dd". This string format was chosen to be independent of regional conventions and (hopefully) easy to remember.

The filter below will select activities where the date is greater than 90 days ago.

date > today-90

Also, to get access to the currently selected daterange (when on trend or diary view there is always a date range selected to chart for) we can use the daterange function; daterange(from) is the first date of the currently selected range, and daterange(to) is the last date.




6. WORKING WITH LOTS OF ACTIVITIES (VECTORS)

So far all we have done is compute a result on the basis of details regarding the current ride, but there are situations where we need to know a little more. For example, I want to know when I have done more than one workout in a day.

So to support these kinds of things we can create a list of rides and apply a formula to them:

Activities["2015/01/01" : "2015/12/31"]

This will evaluate the expression Activities (which is always 1 for a single ride) for all rides in the year 2015. When working with ranges we basically apply an expression to the range selected:

(expression) [ from : to ]

For every activity in the range from/to the expression is applied and stored away. This results in a list of values rather than a single result. This list is referred to as a vector. If you use a vector in another operation e.g.

Activities["2015/01/02" : "2015/12/32"] > 10

Then the list is evaluated as a sum of all entries. So the example above will evaluate to true if there are more than 10 rides in 2015. So back to our example, where we wanted to find 2-a-days;

Activities[date:date] > 1

Will count all activities on the same date as the one being evaluated and if there is more than one it returns true. But we often want to do a little more than sum, we might want to find the average TSS. So there are functions we can use to work with each of the vector elements;

mean(TSS["2015/01/01":"2015/12/31])

Will find the average TSS in 2015. But it will be skewed by activities that have a zero TSS (maybe they are runs or swims), so we can also filter vectors;

which(x>0, TSS["2015/01/02" : "2015/12/31"])

Will create a vector of all rides. The expression 'x>0' is applied to every element replacing x with the value of the element.

Other functions that we can use to work with vectors include;

sum() - to calculate the sum of the elements
count() - to provide a count of elements
max() - to return the largest
min() - to return the lowest

Lastly, these functions can be passed a list of parameters and will work on those as well as vectors;

max(BikeScore, SwimScore, GOVSS) 

for example will return whichever is the highest value, a sneaky way of getting stress across multple sports without having to check if its a run, swim or ride.



7. WORKING WITH PMC

Lastly, we have functions for calculating PMC stress metrics; sts, lts, sb and rr will calculate short-term, long-term, stress balance and ramp rate for the supplied formula.

So if you like to use TSS then its straight forward;

sts(TSS)

will return the CTL for the day of the ride. But you can provide a formula too, so a triscore type pmc might have an expression like

sts(max(BikeScore,SwimScore,GOVSS))

to cascade between the three as an input. There is no limit to the expression you provide as an input, so you could use

sts(mean(TSS[date:date-30]))

To calculate stress based upon a rolling 30d average TSS.
 
Cheers
Mark

Mark Liversedge

unread,
Aug 23, 2015, 5:40:21 AM8/23/15
to golden-cheetah-users
Oops, typo, an NP buster is

Average_Power > NP

Mark

Mark Liversedge

unread,
Aug 23, 2015, 6:42:27 AM8/23/15
to golden-cheetah-users
Also;

Activities[date:date] > 1

is a parser error bug (Ale,  lexpr not supported in cexpr) 

So instead;

sum(Activities[date:date]) > 1

Mark

Ryan Switala

unread,
Aug 23, 2015, 10:07:18 AM8/23/15
to golden-cheetah-users
Looks really cool Mark. Will probably need a few tutorials on these!

Ruud Goorden

unread,
Aug 23, 2015, 1:35:30 PM8/23/15
to golden-cheetah-users
I thought WKO4+ went to the moon, but you guys are already seem to aim at Pluto

Andrea Sabba

unread,
Nov 20, 2015, 4:39:10 PM11/20/15
to golden-cheetah-users
Hi Mark,he user 
where can I find the user formula editor?
Could you post some screenshots?

Thank you
Andrea

Mark Liversedge

unread,
Nov 20, 2015, 4:42:15 PM11/20/15
to golden-cheetah-users
On Friday, 20 November 2015 21:39:10 UTC, Andrea Sabba wrote:
Hi Mark,he user 
where can I find the user formula editor?
Could you post some screenshots?

Watch the 'What's new in V3.3 video' jump to 8:55 https://vimeo.com/145425005

Mark 

Ale Martinez

unread,
Nov 28, 2015, 9:32:55 AM11/28/15
to golden-cheetah-users
There are some test charts using formulas at https://github.com/GoldenCheetah/GoldenCheetah/tree/master/test/charts

For example to compute sTSS and to compare with SwimScore:


To estimate rTSS and to compare with GOVSS:


And several others

Andrea Sabba

unread,
Nov 29, 2015, 3:24:59 PM11/29/15
to golden-cheetah-users
Hi,
I'm looking for a way to create a chart to plot the average powers of a specific interval called "Hill #1" (the same interval is many different rides).
The purpose of this chart is to compare my improvement in this interval in a speficia range of time.
Could the "User Formula" be useful?
Any other idea?

Thanks to everyone.

Andrea

Il giorno domenica 23 agosto 2015 11:38:17 UTC+2, Mark Liversedge ha scritto:

Ale Martinez

unread,
Nov 30, 2015, 10:15:25 AM11/30/15
to golden-cheetah-users
El domingo, 29 de noviembre de 2015, 17:24:59 (UTC-3), Andrea Sabba escribió:
Hi,
I'm looking for a way to create a chart to plot the average powers of a specific interval called "Hill #1" (the same interval is many different rides).
The purpose of this chart is to compare my improvement in this interval in a speficia range of time.
Could the "User Formula" be useful?
Any other idea?
I don't think you can to exactly that with current formulas, you could use the new API (https://github.com/GoldenCheetah/GoldenCheetah/blob/master/doc/user/rest-api.txt) if you know how to program in R/Python/Matlab or similar tool.

A simpler alternative not involving programming would be to track average power for a lower bound of the minimum duration for that interval, let's say it takes you 26'-29' to climb that hill depending on fitness and conditions then you can track Maximum Average Power for 25' and, eventually, filter the chart to consider only rides having that interval using the search facility.

Ale

unread,
Nov 30, 2015, 3:22:29 PM11/30/15
to golden-cheetah-users
Which formula could I use if I would track the time I spent between CP and Vo2max higher limit? For example If my CP is 300 and my Vo2max il between 320 and 360, I would like to track the time spent between 300 and 360 watt. Thanks

Ale Martinez

unread,
Nov 30, 2015, 7:05:33 PM11/30/15
to golden-cheetah-users
El lunes, 30 de noviembre de 2015, 17:22:29 (UTC-3), Ale escribió:
Which formula could I use if I would track the time I spent between CP and Vo2max higher limit? For example If my CP is 300 and my Vo2max il between 320 and 360, I would like to track the time spent between 300 and 360 watt. Thanks

The formula for metric "L5 Time in Zone" is tiz(Power, 5), to use those limits you should change the boundary between L4-L5 to CP and L5-L6 to VO2max power in Power Zones config.

Ale

unread,
Dec 1, 2015, 6:28:03 AM12/1/15
to golden-cheetah-users
I thought the same but I hoped for a less destructive way

Mark Liversedge

unread,
Dec 1, 2015, 6:52:08 AM12/1/15
to golden-cheetah-users
On Tuesday, 1 December 2015 11:28:03 UTC, Ale wrote:
I thought the same but I hoped for a less destructive way

Whilst we have added user formulas for working with ride metrics on trends view and ride samples on the ride view there is more to come.

1. register a new metric to plot in trends, but based upon ride data i.e. custom metrics
2. extend the user formulas to make them available on the summary and scatter plot in analysis and trend view
3. toying with the idea of having an 'R' chart (embedding R within GC, not 100% sure about this)

Cheers
Mark

Serban Mestecaneanu

unread,
Jan 17, 2016, 5:57:52 AM1/17/16
to golden-cheetah-users
Mark,

The level of what we can do with GC is amazing! Thanks for hard working on this,

I have been sent here to check on the formulas for for to edit multiple workouts, but I have to say that I am not sure how to do it. For example I want to edit the Sport or Workout Code on multiple activities.

I tried to select multiple activities, with my mouse, but I think I have to use the Search function for this.

Thanks,
Serban

Richard Staley

unread,
Jan 19, 2016, 1:37:26 PM1/19/16
to golden-cheetah-users
Hi,
Firstly can I say what a great tool this is especially with the ability to add user formulas.  I’ve got two questions as I am attempting to implement Tanda Marathon Predictor Formula: Ref: https://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cad=rja&uact=8&ved=0ahUKEwiRxfeU85TKAhWBiRoKHUuwBrMQFggyMAM&url=http%3A%2F%2Fwww.jhse.ua.es%2Fjhse%2Farticle%2Fdownload%2F190%2F385&usg=AFQjCNFpaKHqyfjvWsOHNAlGxpoeALLZbA&sig2=KRPh0ldHn5xZa-QY6oWIZw&bvm=bv.110151844,d.d2s

To do this I need to add up all my Running mileage over the previous 8 weeks & all my running time over the last 8 weeks. Using the conditional statement I think I am getting both Bike and Run data put just plotted on days where isRun>0.  Do you have any thoughts on how I may be able to just add my total running time and total moving times over the last 8 weeks? As I have written it:
#Tanda Pm
# Pm(sec/km)=17.1+140e[-0.0053k(km/week)]+0.55P(sec/km)
isRun>0 ?
     17.1+(140*exp(-0.0053*(sum(Distance[Date-56:Date])/8)))+(0.55*(sum(Time_Moving[Date-56:Date])/sum(Distance[Date-56:Date])))
:0

In addition, is there any other reference apart from this post for user formulas? I am currently progressing with trial and error,

Kind Regards

Richard

Ale Martinez

unread,
Jan 19, 2016, 5:52:16 PM1/19/16
to golden-cheetah-users
El martes, 19 de enero de 2016, 13:37:26 (UTC-5), Richard Staley escribió:
To do this I need to add up all my Running mileage over the previous 8 weeks & all my running time over the last 8 weeks. Using the conditional statement I think I am getting both Bike and Run data put just plotted on days where isRun>0.  Do you have any thoughts on how I may be able to just add my total running time and total moving times over the last 8 weeks?
Look at the top of the form where you enter the formula, there there is a box to input a filter specific for that curve where you can put isRun<>0 to consider only running activities 

Richard Staley

unread,
Jan 20, 2016, 2:47:15 PM1/20/16
to golden-cheetah-users
Thanks for your reply Ale, I have done this too and I must have some anomalies in my data that I will need to inspect, I appreciate your response. 

Roberto Duca

unread,
Jan 22, 2016, 4:02:55 PM1/22/16
to golden-cheetah-users
hi all

i would like to implement a formula that calculates cumulative sum of the distance over the activity days. 
i know that just by typing distance and specifying "runnign total" the chart is correct but takes the current dates of the chart itself.

 i would like to over-plot on the same graph the distance over a selected period of time, lets say 2014, 2015 and 2016, so i can compare.

to be more clear something that veloviewer does, for all the years of activities i have on strava.

can somebody help me in making this formula to plot the cumulative distance over a certain designated period of time?

thanks
R

Mark Liversedge

unread,
Jan 22, 2016, 4:06:24 PM1/22/16
to golden-cheetah-users
Use compare mode to do that. When you have a cumulative chart shown drag and drop the date ranges from the sidebar over the chart and the compare pane will show.

Mark

Roberto Duca

unread,
Jan 23, 2016, 3:42:27 PM1/23/16
to golden-cheetah-users
thanks Mark. works indeed. appreciated.

R

Ale

unread,
Feb 6, 2016, 9:56:17 AM2/6/16
to golden-cheetah-users
How can I set a chart if I would like to track the percentage of time spent each ride in polarised zone? I'm only able to get a simple chart where I can see the percentage in polarized zone during all season.

Thanks

Roberto Duca

unread,
Feb 25, 2016, 10:05:07 AM2/25/16
to golden-cheetah-users
i want to plot power profile (critical power chart) for different period of time, on the same chart, to see the evolution of th epower profile during the season. e.g. jan-feb, and then mar-apr, on the same chart.
is there a way to do so with the formula?
thanks
R


Il giorno domenica 23 agosto 2015 11:38:17 UTC+2, Mark Liversedge ha scritto:

Mark Liversedge

unread,
Feb 25, 2016, 10:24:06 AM2/25/16
to golden-cheetah-users
On Thursday, 25 February 2016 15:05:07 UTC, Roberto Duca wrote:
i want to plot power profile (critical power chart) for different period of time, on the same chart, to see the evolution of th epower profile during the season. e.g. jan-feb, and then mar-apr, on the same chart.
is there a way to do so with the formula?
thanks
R

You can do this with compare mode.

Create the date ranges you are interested in Trends view.
Drag and drop the date ranges into the compare pane (it will open automatically when you drag a date range onto the trend chart)
Choose CP in Trends view.
Turn compare on in the compare pane

Mark 

Roberto Duca

unread,
Feb 25, 2016, 10:38:07 AM2/25/16
to golden-cheetah-users
thanks Mark.
looking at the previous tip you gave, i should have though about this method, indeed :)

Ale Martinez

unread,
Mar 28, 2016, 3:54:33 PM3/28/16
to golden-cheetah-users
El martes, 19 de enero de 2016, 15:37:26 (UTC-3), Richard Staley escribió:
Hi,
Firstly can I say what a great tool this is especially with the ability to add user formulas.  I’ve got two questions as I am attempting to implement Tanda Marathon Predictor Formula: Ref: https://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cad=rja&uact=8&ved=0ahUKEwiRxfeU85TKAhWBiRoKHUuwBrMQFggyMAM&url=http%3A%2F%2Fwww.jhse.ua.es%2Fjhse%2Farticle%2Fdownload%2F190%2F385&usg=AFQjCNFpaKHqyfjvWsOHNAlGxpoeALLZbA&sig2=KRPh0ldHn5xZa-QY6oWIZw&bvm=bv.110151844,d.d2s

To do this I need to add up all my Running mileage over the previous 8 weeks & all my running time over the last 8 weeks. Using the conditional statement I think I am getting both Bike and Run data put just plotted on days where isRun>0.  Do you have any thoughts on how I may be able to just add my total running time and total moving times over the last 8 weeks? As I have written it:
#Tanda Pm
# Pm(sec/km)=17.1+140e[-0.0053k(km/week)]+0.55P(sec/km)
isRun>0 ?
     17.1+(140*exp(-0.0053*(sum(Distance[Date-56:Date])/8)))+(0.55*(sum(Time_Moving[Date-56:Date])/sum(Distance[Date-56:Date])))
:0
I've tried this myself, the problem is the expression inside sum must skip non-running activities, this works for me:

17 + 140*exp(-0.0053*(sum((isRun ? Distance : 0)[Date-56:Date])/8)) + 0.55*sum((isRun ? Time_Moving : 0)[Date-56:Date])/sum((isRun ? Distance : 0)[Date-56:Date])

Sorry for the late response and hope it helps 

Jean Div

unread,
Apr 5, 2016, 6:46:42 AM4/5/16
to golden-cheetah-users
Hi All

I'm looking to use the custom user formulas to create a few more common metrics, and I'm a little stuck. These are what I'm trying to build:

SWOLF
'Swim Golf' - a measure of efficiency. Basically time per length in S normalised to 25m pool + number of 1-arm strokes to get there (http://thetriguy.com/play-swim-golf-swolf/). Easy to do in excel.. not sure how to do this in GC because I cant seem to get a length time in S from the variables available.

Distance Per Stroke (M)
A measure of efficiency - bigger is better. This should be something like 'Lap (Pool) Distance'/(lap CADENCE*2). Measured from double-arm so thats why cadence *2.

Actual Swim Cadence
This is one that I did get right (because it was so simple), and I thought I'd share.

So GC records single arm cadence, and we usually refer to strokes in double-arm terms (different to cycling and running). Also the fact that you push off a wall and glide (without strokes) on either length means that even if you double it to get 2 arms, the number will be a bit slower than what your actual instantaneous turnover rate is. This number will also probably vary a bit between different lengths of pools because the percentage time gliding off a wall is higher as a % of the length as the pool gets shorter. I was filmed during a 1500m TT in a 50m pool, and compared my actual observed stroke rate vs. Garmin data that was recorded. Garmin was definitely slower and so the following formula works for me to get to a better adjusted value:

SWIM CADENCE = CADENCE*1.17*2

The Garmin recorded a steady cadence around 29 (58), while my actual timed cadence was a steady 68.

That 1.17 adjustment factor is probably higher in a shortcourse pool, and I'd have to do something similar with filming and comparing to see what the actual number is. This number may also be quite different for different swimmers, as their push off and glide may be shorter or longer, and may also change with tumbleturns vs. touchturns. To get this to work really well, the formula would be able to recognise and adjust for pool length, but I don't think pool length variables are available to us? Anyways, just a thought.

Ta,
Jean

Ale Martinez

unread,
Apr 5, 2016, 12:10:12 PM4/5/16
to golden-cheetah-users
El martes, 5 de abril de 2016, 7:46:42 (UTC-3), Jean Div escribió:
SWOLF
... not sure how to do this in GC because I cant seem to get a length time in S from the variables available.

For 50m lengths It could be estimated as: Time_Moving*50/Distance_Swim

c c

unread,
May 11, 2016, 4:06:37 PM5/11/16
to golden-cheetah-users
for the attached file i used the formula Elevation_Gain["2015/11/01" : date], but since mid april it don't add meters, which is the problem? thx
elevation.gif

Mark Liversedge

unread,
May 11, 2016, 5:36:34 PM5/11/16
to golden-cheetah-users
On Wednesday, 11 May 2016 21:06:37 UTC+1, c c wrote:
for the attached file i used the formula Elevation_Gain["2015/11/01" : date], but since mid april it don't add meters, which is the problem? thx

Do the rides contain altitude since Mid April ?

Mark 

Jean Div

unread,
May 14, 2016, 12:38:57 PM5/14/16
to golden-cheetah-users
Hey Ale

It just shows a constant 21.8 if I enter the formula. Also, would we have to rewrite this every time for different pool length? Is there anyway to get the pool length from the data?

Ta,
Jean

Ale Martinez

unread,
May 14, 2016, 6:24:46 PM5/14/16
to golden-cheetah-users
El sábado, 14 de mayo de 2016, 13:38:57 (UTC-3), Jean Div escribió:
Hey Ale

It just shows a constant 21.8 if I enter the formula.

Where did you entered the formula? Time_Moving and Distance_Swim are metrics computed for the involved time span
 

Is there anyway to get the pool length from the data?

Not now, but I will add a Tag to import pool length in meters 

Jean Div

unread,
May 18, 2016, 8:37:39 AM5/18/16
to golden-cheetah-users
Thanks Ale!

I had put the formula into the chart data. Can post screens tonight, if you like?

Jean Div

unread,
May 18, 2016, 8:43:01 AM5/18/16
to golden-cheetah-users
Forgot to ask.. If you are able to isolate the pool length, could you also use this to make sure that pool swim distances are rounded off to the nearest length..?

My pool swim lengths are a bit fuzzy.. 23m, 54m, etc.

Ale Martinez

unread,
May 18, 2016, 10:27:33 AM5/18/16
to golden-cheetah-users
El miércoles, 18 de mayo de 2016, 9:37:39 (UTC-3), Jean Div escribió:

I had put the formula into the chart data. Can post screens tonight, if you like?

In a chart (both User Data in Ride chart and formula Metrics Trends) will give a fixed number, Time_Moving and Distance_Swim are spanning the whole workout.

OTOH if you use them to build a user defined metric it can be used at interval level to show averages for each interval.

If you want a curve in Ride chart you would need to use sample data SPEED, CADENCE and DISTANCE to compute DPS or SWOLF

BTW, pool length is available for newly imported FIT and SML files as Pool_Length, units are meters


Simon Cirnski

unread,
Jun 24, 2016, 8:23:01 AM6/24/16
to golden-cheetah-users
Hi. Got one question. Is it possible to get avgerages form computed values in intervals?? Example: I am get torque form Power and cadence and when i highlight lets say one climb i would like to get average on the left side in Interval box. Is that possible?.

Thanks
Simon

Jason Mahoney

unread,
Oct 3, 2016, 5:22:45 PM10/3/16
to golden-cheetah-users
Is it possible to isolate the data from only a portion of a ride file with these custom formulas, for example the first 30 or 60 minutes?

Mark Liversedge

unread,
Oct 4, 2016, 7:09:35 AM10/4/16
to golden-cheetah-users
On Monday, 3 October 2016 22:22:45 UTC+1, Jason Mahoney wrote:
Is it possible to isolate the data from only a portion of a ride file with these custom formulas, for example the first 30 or 60 minutes?

If you are looking to only plot the first 30 or 60 mins in an activity plot using user data then sure, you could just return a value when  SECS < 1800 or 3600.

If you are looking to create metrics then use the user defined metrics feature coming in 3.4 to only compute metrics using the first 30 or 60 minutes.

Hope this helps *.

Mark

* When 3.4 is released I will be recording some tutorials on analytics using xdata, user data, metrics and R


Jason Mahoney

unread,
Oct 4, 2016, 5:30:27 PM10/4/16
to golden-cheetah-users
Thanks Mark,

So, looking at the 3.4 release candidate

Is the idea that I create a sample of data using the SECS < 3600 and then apply a formula to the data from that sample either by analysing second by second data or averages for that sample?

That would be the beez knees!

Very much looking forward to the tutorials for this.

Cheers

J

Mark Liversedge

unread,
Oct 5, 2016, 1:06:57 AM10/5/16
to golden-cheetah-users
On Tuesday, 4 October 2016 22:30:27 UTC+1, Jason Mahoney wrote:
Thanks Mark,

So, looking at the 3.4 release candidate

Is the idea that I create a sample of data using the SECS < 3600 and then apply a formula to the data from that sample either by analysing second by second data or averages for that sample?

That would be the beez knees!

Just ignore samples after 3600 seconds in the calculation of a metric, something like this for the example you get when creating a new metric (I haven't checked it, but looks about right):

sample() {
    if (SECS < 3600) {
        total <- total + (POWER * RECINTSECS)
    }

Mark

Argonaut

unread,
Oct 5, 2016, 3:14:43 PM10/5/16
to golden-cheetah-users
Got it.  Thanks Mark.

Ps: Still love GC after all these years using it.  Thanks so much for a great product.

J
Message has been deleted

Jason Mahoney

unread,
Oct 9, 2016, 6:03:59 PM10/9/16
to golden-cheetah-users
One last question - is there anyway to get the power zone information for use in the custom metrics formula?

For example, the standard metrics have time in zone and this requires knowing the upper and lower boundaries of each zone.  I cant seem to find any options in the autocomplete fields or online that let me access these details.  

Thanks

Jason

PS: Got the first 30 and 60 minute formulas working nicely.  Cheers. J

de...@mountainridgept.com

unread,
Dec 12, 2016, 9:59:17 AM12/12/16
to golden-cheetah-users
Hi Ale, 

I'm not doing well at building formulas. I'm trying to create a formula to calculate acute to chronic workload ratio from mileage. I want the most recent week's mileage divided by the average weekly mileage over the past four weeks. It doesn't return any information if I enter: 

((sum(Distance[Date-7:Date]) / (sum(Distance[Date-28:Date]))))


Where am I going wrong? Thank you. 

Ale Martinez

unread,
Dec 12, 2016, 11:49:29 AM12/12/16
to golden-cheetah-users
El lunes, 12 de diciembre de 2016, 11:59:17 (UTC-3), de...@mountainridgept.com escribió:
Hi Ale, 

I'm not doing well at building formulas. I'm trying to create a formula to calculate acute to chronic workload ratio from mileage. I want the most recent week's mileage divided by the average weekly mileage over the past four weeks. It doesn't return any information if I enter: 

((sum(Distance[Date-7:Date]) / (sum(Distance[Date-28:Date]))))


Where am I going wrong? Thank you. 

I don't know, vector formulas on Metric Trends chart are not working for me either...

To create an acute to chronic workload ratio from mileage I use this formula: sts(Distance)/lts(Distance) 

de...@mountainridgept.com

unread,
Dec 12, 2016, 1:41:04 PM12/12/16
to golden-cheetah-users
Wow. Great. That does work. The ratio does appear to be giving expected values. Not an issue to have expanded to the 6 week lts time frame from where I was trying to get 4 weeks. Thanks!

Mark Liversedge

unread,
Dec 12, 2016, 1:53:51 PM12/12/16
to golden-cheetah-users
On Monday, 12 December 2016 16:49:29 UTC, Ale Martinez wrote:

I don't know, vector formulas on Metric Trends chart are not working for me either...

I broke them when I added array subscripts !

Will see if I can fix this for 3.4.1

Mark 

DaxPlusPlus

unread,
Dec 17, 2016, 6:16:29 PM12/17/16
to golden-cheetah-users
Did you get anywhere with this?

I'm looking to solve the same (or very similar) requirement - show percentages of time spent in particular groups of zones for rides.

I've gotten as far as getting it to work but only if I choose to group by day - if I try to group by any other period the (100/sum(Activities[date:date])) part of the formula doesn't work correctly.

(100/sum(Activities[date:date])) * (tiz(power, 1) + tiz(power, 2))/(tiz(power, 1) + tiz(power,2) + tiz(power, 3) + tiz(power, 4) + tiz(power, 5) + tiz(power, 6) + tiz(power, 7))
and
(100/sum(Activities[date:date])) * (tiz(power, 3) + tiz(power, 4))/(tiz(power, 1) + tiz(power,2) + tiz(power, 3) + tiz(power, 4) + tiz(power, 5) + tiz(power, 6) + tiz(power, 7))
and
(100/sum(Activities[date:date])) * (tiz(power, 5) + tiz(power, 6) + tiz(power, 7))/(tiz(power, 1) + tiz(power,2) + tiz(power, 3) + tiz(power, 4) + tiz(power, 5) + tiz(power, 6) + tiz(power, 7))

which I view view a data table or histogram



On Saturday, 6 February 2016 14:56:17 UTC, Ale wrote:
How can I set a chart if I would like to track the percentage of time spent each ride in polarised zone? I'm only able to get a simple chart where I can see the percentage in polarized zone during all season.

Thanks

Michael Freiberg

unread,
Jan 2, 2017, 8:48:21 AM1/2/17
to golden-cheetah-users
Is is possible to create a chart to accumulate heart beats within a single ride?
I am looking to overlay this with a chart that accumulates KJ within a single ride - much like the charts show here http://markliversedge.blogspot.com.au/2015/05/finding-tte-and-sustained-efforts-in.html
Cheers, 
Michael.

Mark Liversedge

unread,
Jan 2, 2017, 9:09:32 AM1/2/17
to golden-cheetah-users
Here you go:

Accumulate.gchart

Michael Freiberg

unread,
Jan 2, 2017, 7:58:11 PM1/2/17
to golden-cheetah-users
Thanks!

Bob McRae

unread,
Jan 22, 2017, 2:46:56 PM1/22/17
to golden-cheetah-users
Mark/All,

Sorry if I missed it somewhere, but I am not seeing a afew built-in functions, like:
1. Standard deviation or variance.  Essentially, I'd like to calculate a moving standard deviation or variance on the HEARTRATE signal to make calculations when stable for a period of time
2.  A Histogram function.  I'd like to use this to determine the range of values for a given signal, like HEARTRATE.  Then, from that histogram, I'd like to get the associated SPEED (runs) or POWER (bikes).

Ultimately, I'd like to get the slope & intercept of HEARTRATE vs SPEED|POWER when HEARTRATE is stable for 90-seconds.

Thanks in advance.

Mark Liversedge

unread,
Jan 22, 2017, 3:05:31 PM1/22/17
to golden-cheetah-users
As the metric is calculated by iterating over the samples you can implement both yourself.
If you are looking to chart this rather than create a metric, you could use functions offered from R packages.

Alternatively, try and describe how you'd like the function to work, maybe we could add it. 

Mark

Bob McRae

unread,
Jan 25, 2017, 9:34:13 AM1/25/17
to golden-cheetah-users
Mark,

Thanks SOOOO much for point me down the "path of R".  Within a very short time I have been able to create the chart of interest.  I'll paste the code below if others are interested.  Now, this code is applied (now) to Activities, but what I want to do next is to apply it to all running activities so I can see trends, understand my current running fitness, and -- come race season -- be able to predict my potential run split.  (Using this approach last year, I was able to convince myself of untapped running potential, set a running PR [at age 47], and came within 1-minute of my predicted time @ IM-Boulder.)

Mark, I think a wrapper to communicate with R should be a future feature; it would be a killer app in GC.  You could also perhaps save yourself & others a huge amount of work re-creating functions already implemented in R.  I would LOVE to have the ability to create a User Metric in R and "insert" it into CG (e.g., GC.metrics() <- myNewMetric).

library('caTools')


data <- GC.activity()




n <- length(data$speed)-90


lagSpeed <- c(tail(data$speed,n),rep(NA,90))


data$lagSpeed <- lagSpeed




range <- runmax(data$heart.rate,90) - runmin(data$heart.rate,90)


data$range <- range


stable_data = subset(data, range<=4 & heart.rate > 110 & lagSpeed > 10, select =c(heart.rate, lagSpeed))




fit <- lm(stable_data$lagSpeed~stable_data$heart.rate)


cf <- round(coef(fit), 3)


intercept <- cf[1]


slope <- cf[2]


plot(stable_data$heart.rate, stable_data$lagSpeed)


abline(fit, col="red")


#eq <- paste0("speed = ", intercept, " + ", slope, "*HR")


#mtext(eq, 3, line=-1, col="green")


him <- (1.61*60)/(intercept + slope*155)


him_min <- floor(him)


him_sec <- round(60*(him - him_min),0)


mtext(paste0("HIM Pace [min/mile] = ", him_min, ":", him_sec), 3, line=-1, col="red")





Mark Liversedge

unread,
Jan 25, 2017, 1:11:07 PM1/25/17
to golden-cheetah-users
On Wednesday, 25 January 2017 14:34:13 UTC, Bob McRae wrote:
I would LOVE to have the ability to create a User Metric in R and "insert" it into CG (e.g., GC.metrics() <- myNewMetric).

Yes, maybe in the future.  

BrentK

unread,
Apr 20, 2017, 3:55:09 AM4/20/17
to golden-cheetah-users
Hi Mark,

Is this still an outstanding issue? I have been looking at one of the trend charts which is supposed to give Tanda Marathon Prediction but it doesn't plot anything. I'm not quite across the array formula syntax, but also tried a simplified formula of 
sum(Distance[Date-56:Date])
in a Trend chart, and this also gives no output. Have tried this in the latest 3.5-DEV1704 with no luck.

Thanks,

Brent

Ale Martinez

unread,
Apr 25, 2017, 8:36:26 PM4/25/17
to golden-cheetah-users
El jueves, 20 de abril de 2017, 4:55:09 (UTC-3), BrentK escribió:
Hi Mark,

Is this still an outstanding issue? I have been looking at one of the trend charts which is supposed to give Tanda Marathon Prediction but it doesn't plot anything. I'm not quite across the array formula syntax, but also tried a simplified formula of 
sum(Distance[Date-56:Date])
in a Trend chart, and this also gives no output. Have tried this in the latest 3.5-DEV1704 with no luck.
Yes, it is on that version, for the next development build vector formulas are re-enabled with a modified syntax to avoid conflicts with array indexing, the one above needs to be re-written as sum(Distance[[Date-56:Date]]).
Attached is a version of that chart using the new notation plus an Acute/Chronic Workload Ration based on this paper which also uses vector formulas, but -unless you are building from source- you need to wait for the may dev build.
Run PMC (km).gchart

Ward Muylaert

unread,
May 4, 2017, 12:03:24 PM5/4/17
to golden-cheetah-users

Is either of those two notations supposed to work in the current stable build (3.4)?

Ale Martinez

unread,
May 4, 2017, 2:38:25 PM5/4/17
to golden-cheetah-users
 No, the original one works on v3.3 and the last one on v3.5dev1705.

Edouard Lavergne

unread,
May 16, 2017, 6:44:23 PM5/16/17
to golden-cheetah-users

To help out a little, we also have access to the athlete configurations, via a function called config(), for example to use the athlete weight (on the date of the ride) we can rewrite the formula as;

(config(weight) * 2.2) * (Distance * 1.609)

The config function will return values for; cp, cv, scv, w', pmax, height, weight, units, lthr, maxhr, rhr. All of which are returned in metric units. So you will need to convert if you prefer imperial units, the config(units) will be non-zero if imperial units are preferred.

Dear Mark, dear all
Thanks for all your contribution to Golden Cheetah
I am new to GC working group and to Golden Cheetah. I have a small experience with R and programming but the user formula syntax is for me sometime difficult, mainly because there are very few examples that could let me understand how each function works and no feed back or error message that indicates where errors in the code are located, we can only test the results values. Not a complain against GC which is a very nice piece of software but a remark on my limited programming skills.
Anyway, I tried to use config(scv) in the formula, even by itself as value{ config(scv); } it sometime returns the good results when clicking on "test" but sometime GCv3.4 crashes (I also try with 3.5dev). I tried with all my swim workout individually and for any of them it crashes or give results randomly. The crash becomes permanent when I close the custom formula and save the option pop up windows. Then I cannot reopen GC which crashes directly on opening. I need to create a new athlete without workout to be able to modify the formula and reopen my athlete session. I also notice that this issue appear wit all config() functions e.g cp, cv, scv, w', pmax, height, weight, units, lthr, maxhr, rhr, cranklength etc...

I tried on 3 different PC under win7, win 8 and win10

Here is the formula
{

    # only calculate for swim workouts

    relevant { isSwim=1; }


    # calculate metric value at end

    value { config(scv) ; }

}


I would be grateful if you could help me solve the issue, or confirm if this is a know issue in GC.
Thank you
Ed

Ale Martinez

unread,
May 17, 2017, 9:43:37 AM5/17/17
to golden-cheetah-users
The formula looks Ok, I can't reproduce the problem using 3.5 Dev 1705 on Linux, it works as intended.

Edouard Lavergne

unread,
May 19, 2017, 4:31:32 AM5/19/17
to golden-cheetah-users
Dear Ale

Thanks for trying. I am wondering if it is not just one of my workout that messes everything up. When I save the formula the calculation loading bar starts but in the middle it crashes.
I will try again to fins the issue.
Thank again for your quick respond
All the best
Ed

Edouard Lavergne

unread,
May 20, 2017, 3:17:12 AM5/20/17
to golden-cheetah-users
Dear Ale

I tried again with a new athlete and just couple of my workouts. What I noticed is that whenever I set up more than one SCV (I try to update it every 3 months) in the swim pace zone parameter tab, the crash occurs systematically. However when I deleted all of them but keep only one SCV value (I tried with many different fake pace values) GC remains stable and calculate everything I ask, using config(scv). I did this procedure again on three different pc, three different win OS and all crash when multiple SCV values are included but not with a single SCV value.
I would be grateful if you could try reproducing this crash by including more than 2 or 3 SCV historical values in the swim pace zone parameter tab.

Thanks a lot
Best regards

Ed

On Wednesday, May 17, 2017 at 10:43:37 PM UTC+9, Ale Martinez wrote:

Ale Martinez

unread,
May 20, 2017, 10:53:37 AM5/20/17
to golden-cheetah-users
Thanks Edouard, but my Test athlete already has multiple SCVs and each swim shows the right SCV according to date using your custom metric, I can't reproduce the error.

alessandropr...@gmail.com

unread,
May 25, 2017, 2:56:38 AM5/25/17
to golden-cheetah-users

Hi Guys,
i will like to make a formula for have availaible the metric  Np/Kg
i created some others formula with success but this one that sound "simple" i'm not able to do
can you help me?
thx
Ale

Ale Martinez

unread,
May 25, 2017, 10:06:25 AM5/25/17
to golden-cheetah-users
Try this one:

{


    relevant { Data contains "P"; }


    value { NP / Athlete_Weight; }


    count { Duration; }


}



alessandropr...@gmail.com

unread,
May 26, 2017, 2:33:07 AM5/26/17
to golden-cheetah-users
Thx a lot Ale, work perfectly;)

wooliethai

unread,
May 28, 2017, 11:25:52 AM5/28/17
to golden-cheetah-users

When using a date vector in a formula ie sum(Distance[[Date-365:Date]] date ranges of 133 days or greater cause the chart to flatline


Screen Shot 2017-05-28 at 8.22.42 AM.png

Mikael Mose

unread,
Jun 16, 2017, 11:05:53 AM6/16/17
to golden-cheetah-users
Hi.

I want to create a formula of 20min peak power for each ride, and want to the Efficency factor of that 20 min. to see a trend in my training. 

Ale Martinez

unread,
Jun 16, 2017, 12:35:03 PM6/16/17
to golden-cheetah-users
El viernes, 16 de junio de 2017, 12:05:53 (UTC-3), Mikael Mose escribió:
Hi.

I want to create a formula of 20min peak power for each ride, and want to the Efficency factor of that 20 min. to see a trend in my training. 
You can use the formula 20_min_Peak_Power/20_min_Peak_Power_HR in a Metric Trends chart, for an alternative approach see https://groups.google.com/forum/#!topic/golden-cheetah-users/58MwPZbrFKE

alessandropr...@gmail.com

unread,
Jun 28, 2017, 12:37:16 PM6/28/17
to golden-cheetah-users
Hi Guys,
I will like to make a formula for calculate the MMP Percentage of selected intervals not in base of full history of mean max power
but calculated only a selected period (example last year or last 3 months or last month or last weeks)
I find this potencially very usefull.
If someone can help me will be appriciate;)

Thx
Ale

Ale Martinez

unread,
Jun 28, 2017, 3:09:53 PM6/28/17
to golden-cheetah-users
El miércoles, 28 de junio de 2017, 13:37:16 (UTC-3), alessandropr...@gmail.com escribió:
Hi Guys,
I will like to make a formula for calculate the MMP Percentage of selected intervals not in base of full history of mean max power
but calculated only a selected period (example last year or last 3 months or last month or last weeks)
 I think this can't be done with formulas but it can be observed in Activities>CP Chart using the desired period as Date Range for the chart.

Ben Hammond

unread,
Jun 29, 2017, 2:24:34 AM6/29/17
to golden-cheetah-users

Hi guys, 

My programming ability is sub-par (non-existant) but just trying to get started with a few metrics I've been experimenting with. Basically I just want to get a basic idea of how to do this stuff then experiment as I add values to the larger metrics I'm experimenting with. I'm stuck at step 1 though....any help appreciated. 

I simply want to view: 

Elevation Gain / Distance * 100

Ale Martinez

unread,
Jun 29, 2017, 7:48:40 PM6/29/17
to golden-cheetah-users
See above in this thread for an example similar to this one: https://groups.google.com/d/msg/golden-cheetah-users/WmUGbNHviJE/8KZpeltJBwAJ

Ben Hammond

unread,
Jul 5, 2017, 8:20:19 PM7/5/17
to golden-cheetah-users
Thanks for that. A bit of fiddling and I got it working. 

I have managed to get the metric (an alternate view of run pace) into a decimal format (i.e 4.87min/km)

I'm stumped at how I'm able to get that into a Time format? 

Any help would be much appreciated. 

Ale Martinez

unread,
Jul 6, 2017, 9:10:44 AM7/6/17
to golden-cheetah-users
There is a "Time" checkbox in the custom metric dialog for time format, the value needs to be in seconds, so you also need to multiply your previous formula by 60

mark...@gmail.com

unread,
Aug 3, 2017, 6:06:28 AM8/3/17
to golden-cheetah-users
Wow, this is really fantastic. I am trying to create a couple of charts which I want to use for my performance planing on the bike. 

- 28 Day rolling average for TSS to be calculated for each day from cycling activities only

I've been using the 'Running Total' option from the aggregate drop down list and can get the TSS running total using just TSS, however when I try to filter for a date range I don't seem to be able to get any results. 

sum(TSS[date-28:date]) or sum(TSS[[date-28:date]])

There's a comment earlier in the thread saying that vectors aren't working in 3.4, would this cause problems with what I'm trying to do?

Thanks, 

Mark 






Also, how do I use a gchart file in GC? I downloaded an example from this thread but couldn't work out how to add it to GC. 

Are there any blog articles or videos which talk through how to use the formula capability as I will want to get other information using it? 

Ale Martinez

unread,
Aug 3, 2017, 9:09:56 AM8/3/17
to golden-cheetah-users
El jueves, 3 de agosto de 2017, 7:06:28 (UTC-3), mark...@gmail.com escribió:
Wow, this is really fantastic. I am trying to create a couple of charts which I want to use for my performance planing on the bike. 

- 28 Day rolling average for TSS to be calculated for each day from cycling activities only

I've been using the 'Running Total' option from the aggregate drop down list and can get the TSS running total using just TSS, however when I try to filter for a date range I don't seem to be able to get any results. 

sum(TSS[date-28:date]) or sum(TSS[[date-28:date]])

There's a comment earlier in the thread saying that vectors aren't working in 3.4, would this cause problems with what I'm trying to do?
Yes, this formula doesn't work on v3.4, you need v3.5dev to use the second form.

Also, how do I use a gchart file in GC? I downloaded an example from this thread but couldn't work out how to add it to GC. 
Just drag&drop the gchart file onto GC 

mark...@gmail.com

unread,
Aug 11, 2017, 5:20:34 AM8/11/17
to golden-cheetah-users
Thanks for the info, much appreciated. Would the formula above give the result I was after when in the working version?

Ale Martinez

unread,
Aug 11, 2017, 9:40:56 AM8/11/17
to golden-cheetah-users
El viernes, 11 de agosto de 2017, 6:20:34 (UTC-3), mark...@gmail.com escribió:
Thanks for the info, much appreciated. Would the formula above give the result I was after when in the working version?

I works, but it is a rolling sum, if you need to divide by 28 for a rolling average 

mark...@gmail.com

unread,
Aug 12, 2017, 6:59:18 PM8/12/17
to golden-cheetah-users
That's what I am looking to calculate. 

Thanks, 

Mark 

Salvatore Taibi

unread,
Aug 23, 2017, 3:02:47 PM8/23/17
to golden-cheetah-users
Is it possible to create a P-D curve that doesn't use logarithmic scaling? IIRC, many moons ago we used to be able to do this in GC. I'd like to create such a chart, with the duration portion being variable or even simply out to 10 or 20 minutes. Thanks!

On Saturday, August 22, 2015 at 11:38:17 PM UTC-10, Mark Liversedge wrote:
We will release 3.3 at Christmas, it will contain user formulas and a metric scatter plot, and maybe a few other little fixes. We will also release 4.0 sometime around next years TdF that will contain planning and impulse-response modelling.

I said, for those that are playing along with the master repo (3.3 development) that I would document the User Formula stuff, so here is a very brief and to the point summary of what formulas can do. As ever, it is likely to change rapidly over the next few weeks, but these are the current features.

[FWIW, I am entirely conflicted about allowing vector operations by default; on the one hand they are elegant but in the other they aren't exactly user friendly ! Also, the Eigen matrix lib is likely to become a dependency for some new work on impulse response that needs matrix functions so we may also extend to allow that. But then, this "simple" idea is turning into a clone of R and I think that is wrong...]


GOLDENCHEETAH FORMULAS

1. EXTENDING DATA FILTERS

We have extended the datafilter functionality that allowed you to write logical expressions to filter rides to return values that can be used when charting.

For example, in the past you could write;

NP > Average_Power

To find NP busters in your ride collection. We have now updated this to allow the result to be a value, that you could then chart, in this case how much of an NP buster is it:

NP - Average_Power



2. WORKING WITH RIDES

At present, the formulas are being used to generate values to plot on long term metric charts. They are applied for each ride and the result is then plotted. There are drawbacks to this approach, but for now, they allow us to get started and we can then consider using them in more complex ways.

Certainly in the future I would like to use them to compute new metrics from ride data, dervice data series from ride data and compute impulse-response models or even power duration models. But for now they are applied to rides when plotting LTM charts.



3. GETTING STARTED

If we create a new LTM chart and add a curve we can choose a 'Formula'. This formula can be entered into the formula editor. The editor has autocomplete, syntax highlighting and brace matching. The autocomplete will offer completions for all the named metrics (things like Average_Power, TSS, IF) as well as metadata (things like Sport and Workout_Code) as well as all the built-in functions (things like min(), max(), sum()).

The very simplest formula would be:

1

This will plot the value 1 for every ride. We can extend this a little and change that to a ride metric:

TSS

This will plot the TSS value for every ride. And of course we can then extend this with some arithmetic:

TSS/2

Will plot half of TSS for every ride. But you will quickly want to use the metrics in more interesting computations. For example you might want to calculate how many calories were burned in a workout, for bike rides that is really easy (its essentially the 'Work' metric), but for runs we will need to calculate it, e.g. as weight * distance in imperial;

(Athlete_Weight * 2.2) * (Distance * 1.609)

To help out a little, we also have access to the athlete configurations, via a function called config(), for example to use the athlete weight (on the date of the ride) we can rewrite the formula as;

(config(weight) * 2.2) * (Distance * 1.609)

The config function will return values for; cp, cv, scv, w', pmax, height, weight, units, lthr, maxhr, rhr. All of which are returned in metric units. So you will need to convert if you prefer imperial units, the config(units) will be non-zero if imperial units are preferred.

There is also a const() function that will return high precision mathematical constants for e and pi that can be used in more advanced formulas. As you might expect we also have math functions to use to; cos/tan/sin and acos/acosh friends, exp, log/log10, fabs, ceil, floor, round as well as isinf/isnan. They all call standard math functions (see C++ math.h).



4. MAKING DECISIONS

In our example of calories burned we use two different formulas depending on if the activity is a bike ride or a run. So we need to decide which one to use in our formula. There is a conditional statement that will be familiar to C and Java developers:

isRun>0 ? (config(weight) * 2.2) * (Distance * 1.609) : Work

Unpicking this, the '?' operator and ':' operators are the key piece. The '?' after 'isRun>0' tells us it is a conditional statement. If isRun>0 then evaluate the expression to the left of the colon, otherwise the one to the right. They can be nested so you can get quite funky.



5. BESTS, TIME IN ZONE AND ESTIMATES

As well as all the pre-computed metrics available to use, we can also work with the mean maximal data for the ride as well. We use the best() function for this:

best(power, 3600)

Will return the best 1hr power within this ride. The duration is always in seconds, and we can choose from power, hr, apower, cadence, speed, torque, vam, xpower, np and wpk. There are lots of formulas in the literature that use power for a duration to derive other markers. Naturally we may also want to plug in an estimated value from the power duration models too. So to access an estimate that applied on the date of the ride use:

estimate(2p, 3600)

As you would imagine this will return the estimated 1hr power using the 2 parameter critical power model. You can use other models; 2p, 3p, ext, velo and ws are classic CP, morton 3 parameter, GC extended model, veloclinic and ward-smith respectively. You can also get the parameters that applied;

estimate(2p, cp)

Will return the estimated value for CP from the 2 parameter model. Where we supplied a duration in the previous example as the second parameter we can also request the parameters by name; cp, w', ftp, pmax can all be extracted.

We also provide functions for extracting time spent in zone, currently it is just for the configured power and hr zones;

tiz(power, 4)

Will return the time spent in seconds at power zone 4. 



6. WORKING WITH DATES

When filtering it is quite useful to filter rides based upon when they occurred. The date of the current ride is 'date', the current date is 'today' and we can create a specific date via the string format "yyyy/mm/dd". This string format was chosen to be independent of regional conventions and (hopefully) easy to remember.

The filter below will select activities where the date is greater than 90 days ago.

date > today-90

Also, to get access to the currently selected daterange (when on trend or diary view there is always a date range selected to chart for) we can use the daterange function; daterange(from) is the first date of the currently selected range, and daterange(to) is the last date.




6. WORKING WITH LOTS OF ACTIVITIES (VECTORS)

So far all we have done is compute a result on the basis of details regarding the current ride, but there are situations where we need to know a little more. For example, I want to know when I have done more than one workout in a day.

So to support these kinds of things we can create a list of rides and apply a formula to them:

Activities["2015/01/01" : "2015/12/31"]

This will evaluate the expression Activities (which is always 1 for a single ride) for all rides in the year 2015. When working with ranges we basically apply an expression to the range selected:

(expression) [ from : to ]

For every activity in the range from/to the expression is applied and stored away. This results in a list of values rather than a single result. This list is referred to as a vector. If you use a vector in another operation e.g.

Activities["2015/01/02" : "2015/12/32"] > 10

Then the list is evaluated as a sum of all entries. So the example above will evaluate to true if there are more than 10 rides in 2015. So back to our example, where we wanted to find 2-a-days;

Activities[date:date] > 1

Will count all activities on the same date as the one being evaluated and if there is more than one it returns true. But we often want to do a little more than sum, we might want to find the average TSS. So there are functions we can use to work with each of the vector elements;

mean(TSS["2015/01/01":"2015/12/31])

Will find the average TSS in 2015. But it will be skewed by activities that have a zero TSS (maybe they are runs or swims), so we can also filter vectors;

which(x>0, TSS["2015/01/02" : "2015/12/31"])

Will create a vector of all rides. The expression 'x>0' is applied to every element replacing x with the value of the element.

Other functions that we can use to work with vectors include;

sum() - to calculate the sum of the elements
count() - to provide a count of elements
max() - to return the largest
min() - to return the lowest

Lastly, these functions can be passed a list of parameters and will work on those as well as vectors;

max(BikeScore, SwimScore, GOVSS) 

for example will return whichever is the highest value, a sneaky way of getting stress across multple sports without having to check if its a run, swim or ride.



7. WORKING WITH PMC

Lastly, we have functions for calculating PMC stress metrics; sts, lts, sb and rr will calculate short-term, long-term, stress balance and ramp rate for the supplied formula.

So if you like to use TSS then its straight forward;

sts(TSS)

will return the CTL for the day of the ride. But you can provide a formula too, so a triscore type pmc might have an expression like

sts(max(BikeScore,SwimScore,GOVSS))

to cascade between the three as an input. There is no limit to the expression you provide as an input, so you could use

sts(mean(TSS[date:date-30]))

To calculate stress based upon a rolling 30d average TSS.
 
Cheers
Mark

John Cunningham

unread,
Mar 26, 2018, 2:28:29 PM3/26/18
to golden-cheetah-users
I hope a question of this type hasn't been answered already (if it has, I apologize, but I couldn't find it).

I am trying to calculate average power by HR zone and I am having trouble with the formula.  In short hand it should be something like:

SUM of Power where HR Zone = 3 / SUM of Seconds where HR Zone = 3

Any direction would be greatly appreciated.

Thanks in advance.

-John
Reply all
Reply to author
Forward
0 new messages