Data Field: AppBuilder

By user request, this app lets you define your own data field, based on a simple math formula like cadence / 2.

If you want to get fancy, there's conditional expressions (like IF in Excel), functions for data analysis (like MIN and AVG), and the data field can also display the text of your choice. The resulting data can be (optionally) written to the activity FIT file.

With AppBuilder, you can implement almost any field that involves math, such as: calculating normalized power and saving the data to the FIT activity file, showing the average pace for even-numbered laps, or recording the amount of time you sprinted.

Full documentation and examples here:
http://ciq-appbuilder.blogspot.com/

AppBuilder 5:
Now with new features! AppBuilder 5 is a completely new app, so please check it out in the store if you are interested in any of the new features.
https://apps.garmin.com/en-US/apps/fd690281-9c22-4fee-a81e-3b7f39aa67c5

- Store up to four formulas per app. Switch between formulas directly on the watch, without using a phone or PC. With four clone apps, you can store up to 16 formulas total
- User variables. Allows for powerful formulas where information can be stored at one point, like the start of a lap, and used later. e.g. Lap elevation change
- Improved timeavg() options. Allows for simpler, more flexible normalized power function
- More functions and variables

4 clones of AppBuilder are available in the store, so you can have 2 formulas in the same activity
  • somebizzare sorry, no.

    The main issue with older (Connect IQ 1) devices is the lack of memory available to apps (half as much as newer devices), not the SDK version itself. Almost all of the AppBuilder functionality which is exclusive to newer devices is that way because of lack of memory in older devices, not because of CIQ2 per se.
  • Former Member
    Former Member over 7 years ago
    In the introduction post there was a mention of multiple values for one field, fore example Stride length | avg stride length on same field. Is this currently possible, or is it still future development?

    On 4 field layout the top / bottom fields are usually larger and there are data fields that already take advantage of it. Thinking further if one used 3 field layout on a round screen the wide middle field could possibly fit even 3 metrics...

    I'm thinking something like fitting power & hr on same field to free up other fields for new metrics. :)
  • Former Member
    Former Member over 7 years ago
    I did a quick test and 10000*HR+Power for example seems to offer workaround. Of course it's a bit difficult to read when it looks something like 1550235.

    So all we need is a way to separate the calculations / answers. For starters simply by space would do. Once the answer gets longer the font gets smaller so it would be up to the user what they try to fit.

    Am I the only one interested in this? :)
  • Former Member
    Former Member over 7 years ago
    I want to display the Intensity Factor for lap just completed in the lap alert screen. Is there for this to do it? It would be Lap Normalized Power / FTP, but I can't see either of those fields in the documentation. Any suggestions?

    Thanks
    Gerrard

  • Former Member
    Former Member over 7 years ago
    For higher end watches this is already available in cycling mode (F5 / FR 935).

    I agree it would be very useful with Stryd for example if one could show this in run mode as running power is not yet natively supported. Especially when Training Peaks already supports running power so you can plan / build workouts and training load based on IF / TSS.

    Anyway it requires normalized power to be able to calculate it, but looking back at older posts this is apparently not available in CIQ as variable. IF is basically your NP / FTP. Based on this knowledge it would be also possible to calculate TSS.

    There is a formula on page 10 to calculate NP and I tried it but seems it doesn't give the same result as the one used by my F5 (I compared in cycling mode). For example it starts to update right away when it should only start calculating the result after gathering 30 secs worth of data. I tried playing with prevt, but couldn't get it to work so probably not currently possible...?

    I believe the actual formula used by the watch is trademark of Peaksware LLC so they don't share it although Dr Coggan has shared the original idea previously on forums like slowtwitch. Might still be they made some adjustments to it to react better to short intervals etc.

    Anyway if someone found a solution to this I would also be interested to try it as I also use Stryd.

    PS. I wonder if the app is still being developed? No answers to my previous questions either...

    EDIT: stand myself corrected, IF is not available for laps, so would have a valid use for cycling as well...
  • JTH9 having multiple values in the same field would be nice, but as with any feature that I add to AppBuilder, it would take up valuable memory that is currently being used to calculate formulas. This would especially be a problem on older watches. In the past when I've added new features, I've saved memory by optimizing existing code, but this can only work so many times.

    So the problem is that if anyone is using a super-complicated formula that pushes memory usage to the limit, if I add that one feature that somebody wants, it will break the app for them.

    I assume you're talking about this formula for normalized power:
    TIMEAVG(Power ^ 4, 30) ^ 0.25

    I derived that based on sources such as this:
    https://www.mathworks.com/matlabcent...rmalized-power
    • Calculate a 30-second rolling average of the power data
    • Raise these values to the fourth power
    • Average the resulting values
    • Take the fourth root of the result


    If anyone knows of a better formula (that could be implemented in AppBuilder), I'd love to hear it.

    As far as the result for NP appearing immediately, instead of 30 seconds in, that's how I implemented TIMEAVG(x,t) and TIMEAVG0(): you see averaged results immediately (for 1, 2, ..29 seconds), instead of only at t seconds in. After t seconds, it'll always be a t-second average. Unfortunately, it's hard to know what people really want from these functions before the fact.

    To answer your other question, there are some features I'd like to implement in a perfect world, such as the "multiple values in the same field" feature, but again, memory constraints are a huge issue. I also get requests via email to add variables such as temperature, but that also comes at the cost of memory. Every the code get bigger, there's always a chance it breaks someone's existing formula.

    The other thing to remember is that I created this app for fun, in my own spare time. Same goes with ongoing support, the countless features I've added, examples created, emails answered, etc. Hope you'll keep that in mind if I don't answer forum q's instantly.
  • Former Member
    Former Member over 7 years ago
    Of course it would be up to the user to understand the possible limitations. If one would just use simple base values without complex calculations like combine HR and power in same field, then it could be a justified use case? I do understand the complexity this would add to the app though, so probably better just to accept the limitation.

    As for normalized power, not exactly sure why it doesn't work, but might have an idea. From a googled forum post by Coggan himself stated one would have to collect 30s worth data before doing the calculations. So again not sure, but if I understood correctly then 30s rolling average produces already smoothed data while correct function would need collecting 30s chunks of raw 1s values, raise them to 4th, average and take 4th root. I didn't have time to figure out further how to implement it or if even possible with your app, because the examples didn't support this use case and it's quite time consuming inputting formulas on mobile app then try it out.

    Also sorry if my post seemed unjustified. I do understand the limitations and that it's a free app. There is no obligation for you to implement any of this of course.
  • Of course it would be up to the user to understand the possible limitations. If one would just use simple base values without complex calculations like combine HR and power in same field, then it could be a justified use case? I do understand the complexity this would add to the app though, so probably better just to accept the limitation.


    Well, the problem is that there are only 2 version of AppBuilder (disregarded the 3 extra clones): CIQ1 and CIQ2

    The CIQ1 version has less features so it fits on older watches. CIQ2 has more features. So if I add a new features to one or both, it decreases available memory for formulas for all users of that respective version. More code/features = less memory for everybody's formulas.

    That's why I was always careful to trim existing fat every time I added new features in the past. Unfortunately I may have already reached the point where it isn't possible to trim any more fat.

    As for normalized power, not exactly sure why it doesn't work, but might have an idea. From a googled forum post by Coggan himself stated one would have to collect 30s worth data before doing the calculations. So again not sure, but if I understood correctly then 30s rolling average produces already smoothed data while correct function would need collecting 30s chunks of raw 1s values, raise them to 4th, average and take 4th root. I didn't have time to figure out further how to implement it or if even possible with your app, because the examples didn't support this use case and it's quite time consuming inputting formulas on mobile app then try it out.


    Hmm, but my formula already does what I boldedabove. I think the problem is that I interpreted Normalized Power as some kind of instantaneous measure, or a rolling average, when it's actually meant to be an average for your entire activity. (I'm a runner, not a cyclist. ¯\_(?)_/¯)

    https://medium.com/critical-powers/formulas-from-training-and-racing-with-a-power-meter-2a295c661b46
    rolling_average = 30 second rolling average rolling_avg_powered = rolling_average^4 avg_powered_values = average of rolling_avg_powered NP = avg_powered_values^0.25

    This actually matches my quote above (and the following thread) more closely. http://forum.slowtwitch.com/Slowtwitch_Forums_C1/Triathlon_Forum_F1/Normalized_Power_Formula_or_Calculator..._P3097774/)

    The problem is for step 2 and 3 when it said "raise these values" and "average these values", I didn't take it literally.

    In that case, try this:
    AVG0(TIMEAVG0(Power, 30) ^ 4) ^ 0.25
    or
    IF (Timer > 30, AVG0(TIMEAVG0(Power, 30) ^ 4) ^ 0.25, null)

    If that works for you, I'll update the formula in the examples.

    (The flaw with the second formula (and the timeavg functions) is that the rolling average data is cleared when you pause the watch (not just at the start of the activity), and it's not simple to ignore the samples for the first 29 seconds in that case, without changing AppBuilder.

    I'll think about changing TIMEAVG and TIMEAVG0 to return null (no data) if the required interval hasn't passed yet. Only problem is that would change existing behaviour. I could also make new versions of those functions, but then again that will take up valuable memory. I originally implemented TIMEAVG that way on purpose. I was thinking that if someone picked a really large interval like 60 or 300 seconds, they would still want to see data before that interval had passed, especially if they paused and unpaused the activity. But maybe I was wrong about that.)

    Also sorry if my post seemed unjustified. I do understand the limitations and that it's a free app. There is no obligation for you to implement any of this of course.


    No worries. I'm glad that people are finding it useful, actually. TBH I wish there were easy ways for me to add the new features that everyone (including myself) would like to see. I'd love to make it more useful, but I don't want to break anything for existing users.
  • Let me try to summarize and clarify. Sorry I can't edit the previous post, the forum is back to its old tricks.

    Proper Normalized Power formula -- hopefully:
    AVG0(TIMEAVG0(Power, 30) ^ 4) ^ 0.25

  • "If (timer gte 30)":

    Don't use this workaround I suggested for ignoring the first 29 seconds of data returned by TIMEAVG(x, 30) [sorry], it won't work when you unpause your watch.


    I'll think about changing TIMEAVG and TIMEAVG0 to return null [no data] if the required interval hasn't passed yet. Only problem is that would change existing behaviour. I could also make new versions of those functions, but then again that will take up valuable memory. I originally implemented TIMEAVG that way on purpose. I was thinking that if someone picked a really large interval like 60 or 300 seconds, they would still want to see data before that interval had passed, especially if they paused and unpaused the activity. But maybe I was wrong about that.


    To be clear, if I make the suggested change, then TIMEAVG[X, 30] would work as follows:
    - For the first 29 seconds of the activity, the value would be NULL (blank data). Previously I would just show the rolling average for 1 to 29 seconds.
    - For the first 29 seconds after unpausing an activity, the value would be NULL. Previously I would just show the rolling average for 1 to 29 seconds.

    To be honest, the existing behaviour seems wrong to me, but at the time I thought it might be more user-friendly.

    (If anyone at Garmin is reading this, I had to edit this post 50 times to get it to submit.
    The following text, including quotes, but without the space, prevented the message from posting:
    "- -"
    )

    EDIT: I looked at various "moving/rolling average" code samples on github, and it seems that many people chose to still return an average when the number of samples is less than the window size, as appbuilder does. I did find one project which stated that, technically, the moving average is undefined when you have less samples than the window size. I tend to agree with the latter implementation, but again, it all depends on what people expect.