Thanks, these aren’t actual interviews they are sudo intervals created in the script to break it down by every x mins.
Theres an athlete settings table with zones in so could get them there (presumably, not actually looked yet) but worried how to code it if some people have 4 zones and some have 6 say.
Might just go for the sub 80% of FTP and over FTP for now.
Very nice, @Mike_Schaefer! However, your plot requires crank_length field that my activity lacked. I had to go through the code an put various vars in the plot title to debug.
@david it seems we can’t just console.log with these plots? How can we debug them and maybe declare requirements/show errors?
@Andrii_Magalich I threw this script up on github if you (or anyone else) want to enhance. I made the chart public so i can take enhancements and update source.
Latest update added default crank length of 172.5 if no crank length is in activity, and it adds percentage of data points in each quadrant.
I have added the power, pace and hr curves to the icu object. These are also available to custom activity field scripts.
powerCurve (power duration curve)
powerCurveFatigued0 (power curve after some KJ of work done)
powerCurveFatigued1 (power curve after more KJ of work done)
hrCurve (heart rate duration curve)
paceCurve (distance vs time curve)
gapCurve (distance vs time using gradient adjusted pace)
PDC chart:
{
let pc = icu.powerCurve
let trace1 = {
x: pc.secs,
y: pc.watts,
type: 'scatter'
}
let data = [trace1]
let layout = {
title: {
text: "Power curve"
},
xaxis: {
type: 'log',
autorange: true
}
}
chart = {data, layout}
}
Data model:
JsHRCurve
A heart rate duration curve.
secs int[] ~ Time points. Note that not all seconds are included. The curve gets sparse as time goes out.
bpm int[] ~ HR for corresponding entry in secs.
start_index int[] ~ Where corresponding point starts in the activity
end_index int[] ~ Where corresponding point ends in the activity (exclusive)
indexOf(int seconds) int ~ What is the index of the point on the curve that has a duration of at least seconds? Returns -1 if the curve
is not that long.
getBpm(int seconds) Integer
JsPaceCurve
A pace duration curve.
isGap boolean ~ Is this gradient adjusted pace?
distance float[] ~ Distance points. Note that not all distances are included. The curve gets sparse as time goes out.
secs int[] ~ Time to cover the matching distance.
start_index int[] ~ Where corresponding point starts in the activity
end_index int[] ~ Where corresponding point ends in the activity (exclusive)
indexOf(float distance) int ~ What is the index of the point on the curve that has a distance of at least distance? Returns -1 if the curve
is not that long.
getSpeed(float distance) Float ~ Returns speed in meters/second or null if curve not that long. Note that the distance might be more than the
distance parameter.
JsPowerCurve
A power duration curve.
secs int[] ~ Time points. Note that not all seconds are included. The curve gets sparse as time goes out.
watts int[] ~ Power for corresponding entry in secs.
watts_per_kg float[] ~ Power/weight for corresponding entry in secs.
start_index int[] ~ Where corresponding point starts in the activity
end_index int[] ~ Where corresponding point ends in the activity (exclusive)
after_kj int ~ If the curve is fatigued then this is the amount of work done before the curve.
indexOf(int seconds) int ~ What is the index of the point on the curve that has a duration of at least seconds? Returns -1 if the curve
is not that long.
Some types of charts only make sense for certain types of activities (e.g. run activities, activities with power, activities with at least one interval, activities with certain custom streams etc.).
Perhaps there should be a way to signal “don’t draw this chart for this activity”. Either simply not setting a value for chart or setting a value containing a reason - or error message.
(posted in the wrong thread first, so now I have to put some more text so they’re not similar)
Thats a good idea. If the script does not return a value or returns null then the chart is hidden completely when displayed on an activity. Unfortunately you can’t use “return” in these scripts without defining a function and invoking it:
function chart() {
if (true) return // not the right type of activity or whatever
// your chart code
return { data: [], layout: { title: { "Hello" } } }
}
chart()
If you are editing the chart script then you will see “Script did not return a value object” instead of just blank.
I’ve been using labeled blocks to get around that, and around excessive nesting - see break in labeled blocks.
I think the function approach is a bit less exotic but this seems to work too. I’m not sure how you’ve implemented the sandbox so not sure if there’s any advantages to any approach.
This also creates unexpected behaviour as Plotly disregards Text values in the x-array when numbers are present. If some work intervals do not have a label, only those will be plotted and the intervals with a text label will not be shown.
I haven’t found a way yet to tell Plotly that it needs to interpret the whole x-array as text values, so I came up with this intermediate solution:
x.push("°" + (iv.label ? c + "-" + iv.label : c))
The ° sign as first character, makes sure that all values in the x-array are considered as text values.
Anyone able to assist, please, with the syntax required to create a chart with the x-axis in hours (activity duration) and then the y-axis using any of the metrics, eg. kJ?
I can work out what the various sections of the code means, but I’m not sure of the correct syntax used, so I created a Google Sheets document to allow a line-by-line explanation of the coding. I’m sure this will help other people besides myself.
so the quoted code is running through each of the intervals in the activity and picking out the label and average watts for the work intervals and saving them in their own array. (it then moves on to the plotting bits)
the options for what metrics you can pick are here
it sounds like you don’t want to look at the metrics aggregated into their intervals though and instead want the time series, in which case have a look at the activity stream models
best bet is probably to explore some charts already shared that look a bit like what you want and adapt them
chart certain metrics per hour to compare for each hour.
The custom stream has kJ/hour, but looks to be total kJ/duration, which is an average. It doesn’t say if the first hour was more or less than the second, third, and so on. I can view the summary by highlighting each hour, but would be easier to view across all activities and athletes.