fractional (decimal) heart rate zone calculation

What's the "best" algorithm to calculate fractional HR zones (i.e: zone: 3.45)?

Splitting from: forums.garmin.com/.../how-edge-calculate-current-heart-zone-decimal-value

  • And to be clear, in my previous comments about my test results:

    - when I said "touching algorithm", I meant my latest implementation of my algorithm

    - when I said "non-touching algorithm", I meant your implementation of your algorithm

  • And now back to the real question. Forget the math stuff above. As a Garmin user, when your HR zones are set to (this is what UserProfile.getHeartRateZones returns):

    minZ1:128, maxZ1:153, maxZ2:162, maxZ3:180, maxZ4:185, maxZ5:190
    what would you expect to see your HR zone is when your HR is 152, 153, 154?
    Because the real difference between my original computeHrZoneFlocsy and your computeHrZoneFlowState is that:
    HR: 152, HR zone: flocsy: 1.920000, FlowState: 1.960000
    HR: 153, HR zone: flocsy: 1.960000, FlowState: 2.000000
    HR: 154, HR zone: flocsy: 2.000000, FlowState: 2.111111
    so when my HR is maxZ1 (153) then am I in zone 1.x or 2.x?
    My interpretation was that if my max HR for zone 1 is 153 and my HR is 153 then I must be in zone 1.x

    I'd like to reply to this but the forum won't let me

  • Right so now we're back to the original topic: comparing each of our two algorithms.

    To answer your question, I already explained what I expect to see in the other topic, but I'll try again:

    - viewing the zones as "touching" (some would say "overlapping", speaking colloquially) - just as they are configured - 153 is both the max of zone 1 and the min of zone 2
    - from my pov - another way of looking at "max of zone 1" is "100% of zone 1", which is equivalent to zone "1 + 1.0" = 2.0
    - from my pov - another way of looking at "min of zone 2" is "0% of zone 2", which is equivalent to zone "2 + 0.0" = 2.0

    So again, whether you view 153 (the value on the shared border between zone 1 and zone 2) as being in zone 1 or zone 2, logically / mathematically the answer is 2.0.

    And indeed, my algorithm would calculate 2.0 given the specified hr zones and an input of 153.

    I think the real question is what Garmin would display in this case. Ofc we can try to test this irl, but there's the little problem of the fact that Garmin will also round the the decimal zone to 1 place.

    So we would have to choose zones carefully so we could try to guess whether Garmin's behaviour is closer to your algorithm or my algorithm, for a given zone border, given a certain assumption of how Garmin is rounding. But how do we know if Garmin rounds or truncates? You'll recall that in the past we didn't even agree on how rounding is supposed to work in "math" (as if there's only one way) or in programming (well in most languages, including Monkey C, the standard rounding function works a certain way, but you understood Monkey C rounding to work a different way than it actually does).

    So none of this stuff is necessarily intuitive or straightforward for the end user. Even if they could guess how the algorithm works, they might not guess how rounding is supposed to work. Or vice versa.

    It's very unlikely that anyone would even care.

    But again I will point out that my algorithm is simpler - there's fewer (arbitrary) implementation *choices* that had to be made.

    Your implementation had to make at least one additional (and arbitrary) implementation choice: the choice on how to make the zones "non-touching" (and again, you chose the opposite way that Garmin did, at least when they implemented time in zones.)

    But again it doesn't matter. If we made a data field which randomly cycled between the following approaches, nobody would notice or care:

    - my algorithm
    - your algorithm
    - your algorithm, but the "zone adjustment" algorithm works the opposite way (same as what garmin does for time in zones)

  • The real question is why do you think it's important for the zones to be "non-touching" (in the context of decimal hr zone calculation)?

    Clearly if HR values could be real numbers, the zones would have to be "touching". (Again it doesn't matter whether adjacent intervals are considered to be closed/open, open/closed, or closed/closed, as long as the algorithm calculates the same answer for a value at any of the interval "borders")

    Is it because you think it doesn't make sense for adjacent zones to share a value at the border? That's true for time in zones. But it's not necessarily true for the decimal zone calculation.

    As a not-so-great analogy, suppose it's currently Monday 23:00 (11:00 PM). In one hour, it will be midnight. But will it be midnight Monday or midnight Tuesday?

    Attacking the problem from the other direction, if I say "meet me at midnight on Friday", does that mean the start of Friday or end of Friday?

    Obviously the answer to either of those questions is ambiguous.

    That's why "00:00:00" refers to the start of day and "24:00:00" refers to the end of day.

    And it's why in US (which uses a 12-hour clock), people who write contracts try to avoid saying "midnight" (or even 12 AM), and prefer to write 11:59 PM or 12:01 AM, which is unambiguous.

    And that's why 24:00:00 Monday is the same as 00:00:00 Tuesday (just like how 153 in the previous example is both zone 1 max and zone 2 min).

    So in the same way that zone 1 and zone 2 "touch" and both share a value at the border (153), the days "touch" and share the moment at the end of one day / start of the next day.

    Note that when doing date/time calculations, nobody ever adds or subtracts a second from the beginning or end of day to account for the fact that the days "touch".

    Similarly, I don't feel the need to add 1 beat to an hr zone min or subtract 1 beat from an hr zone max to account for the fact that the zones touch, at least for the purposes of doing a fractional hr zone calculation.

    (Yeah, it's not the best analogy)

    To continue the analogy, yes if you are calculating "time in HR zones", then you have to decide how to adjust the zones so they don't touch. (Garmin chose one way, and you chose another)

    And yes, if you were doing a calculation involving "how much time dId so-and-so work on Monday, Tuesday, etc", then you would have to decide whether 24:00:00 Monday / 00:00:00 Tuesday actually "belongs" to Monday or Tuesday, so you don't double count that one precious second.

  • I think I explained it. And no, it is not important for me to be non-touching. On the contrary, what seems to be the issue is that for you it's important for them to be touching :) 

    So again: when my Z2max is 153 and my HR is 153 then I expect to see that I'm in zone 2 or 2.x and not zone 3. That's my requirement. If you have a way to achieve that or to tell me why that expectation is problematic, then you're welcome.