How to access labelled interval properties in custom activity fields?

Hi,

I’m trying to create custom activity fields that automatically read data from a labelled interval within an activity.

For example, I have an interval in the activity timeline labelled:

tramo_control_z2

The interval is correctly displayed in the activity and contains valid data, such as:

  • Elapsed time: 19:20
  • Average power: 233 W
  • Average heart rate, etc.

My goal is for a custom activity field to find that interval by its label and retrieve values such as elapsed time, average power, EF, RPP, etc.

I tried the following code:

{
    let duration
    for (let iv of activity.icu_intervals) {
        if (iv.label === "tramo_control_z2") {
            duration = iv.elapsed_time
            break
        }
    }
    duration
}

However, it always returns nothing.

On the other hand, if I access the interval by its position, it works correctly:

{
    activity.icu_intervals && activity.icu_intervals[1]
        ? activity.icu_intervals[1].elapsed_time
        : null
}

This returns the expected value (19:20).

So it seems that:

  • activity.icu_intervals exists.
  • The correct interval is inside activity.icu_intervals.
  • elapsed_time works correctly.
  • But I can’t identify the interval using iv.label.

I’ve also re-analysed the activity several times while keeping the intervals.

My questions are:

  1. Is iv.label the correct property to access the visible interval label?
  2. Should iv.label work inside a custom activity field?
  3. Is there a way to inspect or print all the properties of an interval (for example, activity.icu_intervals[1])?
  4. Is there any documentation listing all the available properties for activity, activity.icu_intervals, and the interval objects?

Thank you very much!

So code seems correct, but if you label intervals afterwards (after processing / importing), then you have always to reanalyse the activity, so that custom fields are filled.

You can use this to show all interval fields:

{
let data = ''
sl=activity.icu_intervals[0];
for (const property in sl) {
  console.log(`${property}: ${sl[property]}`);
}
data;

}
2 Likes

Thanks for reminding me about reanalysing the activity after editing the interval labels.

I was already doing that and I had it in mind, but you are right that it is an important step: if labels are added or changed after the activity has been imported/processed, the activity has to be reanalysed while keeping the existing intervals, so that the custom fields are recalculated.

In my case, the final problem was not the code or the reanalysis, but something much harder to see: one of the interval labels had an invisible trailing space at the end.

Visually it looked correct:

tramo_control_z2

but Intervals was actually reading something like:

tramo_control_z2

That is why the exact comparison in the script was not finding the interval.

The solution was to clean the label before comparing it, using .trim():

{
let tramo
for (let iv of activity.icu_intervals) {
let label = (iv.label || “”).trim()
if (label === “tramo_control_z2” || label === “tramo_control_z3”) {
tramo = iv
break
}
}

tramo ? tramo.average_watts : null
}

With this, even if there is an accidental space before or after the interval label, the script still works correctly.

Your snippet to inspect activity.icu_intervals was also very useful, because it allowed me to see what Intervals was actually reading and to confirm the available properties inside each interval.

So, in case anyone else runs into the same issue, my checklist would be:

  1. Label the interval correctly.
  2. Reanalyse the activity while keeping the existing intervals.
  3. Use .trim() in the script to avoid problems with invisible spaces.
  4. If it still fails, inspect activity.icu_intervals to see what Intervals is actually reading.

Thanks again for the help.

1 Like