Normalised HRV added to /fitness page

HRV:HR which is HRV normalised by resting HR is now available on the /fitness page.

HRV:HR = rMSSD * resting HR / 600

The first version just divided rMSSD by resting HR. Tx to @Jules_Cusson-Fradet and @MedTechCD for the discussion that led to the update.

NB: Resting HR and rMSSD must come from the same source for this metric to have any validity!

Read all about it here:

7 Likes

Very interesting! However, I believe the correct and exact formula that matches the values shown in HRV4Training (based on the graph in the article) is: rMSSD divided by AVNN, then multiplied by 100.
Alternatively, if AVNN is unavailable, a good shortcut would be: rMSSD multiplied by heart rate, divided by 60, then divided by 10, or simply rMSSD times HR divided by 600.

This method is more accurate than just using rMSSD divided by HR, because it considers the inverse relationship between heart rate and RR intervals. It provides a more physiologically meaningful normalization, especially when heart rate varies.

Let’s compare 2 days:

Day rMSSD (ms) HR (bpm) AVNN (ms) = 60000 / HR rMSSD / HR rMSSD / AVNN × 100 rMSSD × HR / 600
A 60 60 1000 1.00 6.0 6.0
B 60 40 1500 1.50 ↑ 4.0 ↓ 4.0 ↓

Interpretation:

  • rMSSD is the same both days (so actual HRV is unchanged).
  • HR is lower on day B (better parasympathetic activity).
  • AVNN is higher on day B (as expected when HR is lower).

:white_check_mark: rMSSD / AVNN × 100 and rMSSD × HR / 600 drop on day B → This correctly shows that despite more room for variability (lower HR), rMSSD didn’t increase, so relative HRV actually dropped.

:cross_mark: rMSSD / HR increases → It gives a false signal that HRV improved, just because HR dropped.

just tried out of curiosity. nothing shown. I only have SDNN from Apple Health. Is that why?

It only uses the RMSSD field.

1 Like

You are 100% correct!
Normalized HRV should be rMSSD divided by ‘mean RR’ during measurement. Be it a with or without a scaling factor, or maybe a natural log of the result as HRV4T uses for its HRV parameter.
HRV4T displays rMSSD only in the pro version (AFAIK). In the standard version, you get HRV only (and you can’t see rMSSD - correct me if that changed over the last couple of years).
In fact, HRV4T plots HRV as 20*Ln(rMSSD). The natural log compacts the range. If you are not paying attention to CV (Coefficient of variation), it doesn’t really matter because the trend is the same. But when CV is talked about in the literature, they always use a natural log converted value. CV lower then 12% (good stable situation), for the raw rMSSD is totally different compared to the one for the Ln(rMSSD).

Putting this all together, I would think that normalized HRV should be either based on

  • rMSSD / (mean RR in seconds)
  • Ln(rMSSD / mean RR) which would result in a compacted range

Given the lower numbers in the screenshot from HRV4T, there probably is a multiplier applied, but that is of minor importance. As long as the plot shows the same trend, the absolute value from a multiple or not, is not important.

If someone owns HRV4T PRO, he could verify the above.

I saw @david 's post earlier this week, but haven’t got the time to look at it in more detail until now. If Intervals uses rMSSD/HRrest, then it is as you say, not correct. Will have a play with it later today.

1 Like

On the phone app we have access to raw rMSSD !

I am happy to change this. But should I do:

Or one of @MedTechCD versions? I am leaning towards @Jules_Cusson-Fradet if that will match what is in Marco’s software.

Also is it ok to do the same for SDNN?

1 Like

If the user knows what he’s doing, rMSSD * HR / 600 is no problem. But if he takes resting HR, from ‘somewhere’ nothing to do with the rMSSD measurement, this will only show BS.
To be meaningful, the HRrest during the HRV measurement must be used. For those using overnight HRV, I would strongly discourage using this.
I can’t be 100% sure but i would think that the same can apply to SDNN.

I already implemented my own preferred way to calculate and implement this. Since I use an external tool to daily get the info from the API and send back some calculated stuff in Custom Wellness fields, I just added the normalized HRV to it.
I use HRV and mean RR from Kubios app and take the natural log from the division.

Differences are subtle, but they do exist!

3 Likes

Ok I have changed it. The current measure has the same issues with “where did the resting HR come from”.

2 Likes

Thanks for the change @david !

It might be helpful to add a disclaimer emphasizing good practice—namely, that rMSSD and heart rate values should come from the same measurement to ensure accurate calculations.

1 Like

Great change, but a clarrification:

Which rMSSD is it based on , ithe standard one that would typically come from Garmin wellness stats, or the rMSSD field populated from Marko’s app?

I think there is only one resting HR, the Garmin one, but I could be wrong on that?

100% agree, otherwise Intervals.icu slowly loses its credibility as a reliable analytical tool.

I have added a note to the first post in this thread about that:

NB: Resting HR and rMSSD must come from the same source for this metric to have any validity!

It uses the standard Intervals.icu fields. How these are filled in depends on which device(s) and so on you have connected. If you have connected Marco’s app via Dropbox then those will be the values used.

Even though is coming for Garmin’s overnight?

Tks

Already gave my opinion on that. It will be unusable.

Marco Altini’s advice to measure HRV in the morning is in a sitting position because of the influence of the baroreflex. Hence HR of that measurement is higher than the usual resting HR in a lying position.
What measurement for HR should therefore be used for the normalized HRV?

Aside from that I might be doing something wrong but the norm (green dots) scale doesn’t seem right.

Guys, come on. The instructions are perfectly clear.
You use avg HR from the EXACT same time frame as you used for HRV.
And thus only from a morning measurement.
Everything else will flaw the results.
I’m not going to go further in this regarding responses.

3 Likes

You have the HRV axis starting at zero. You need to do the same to the axis for HRV:HR:

1 Like