This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Recovery Heart Rate stored?

I currently have a 230, but I'm really tempted to get the 945, mostly because of training load focus, though the ability to have podcasts and maps (and perhaps even Garmin Pay) are pretty cool/exciting.

I'm curious if this watch will save my recovery hear rate? On the 230 it shows up 2 minutes after my run, but it's not save in such a way to be displayed anywhere. I'm comfortable digging through files if this info is stored in some file, but I don't know what directory/file to look for this. That way I could extract this info and plot it myself.

I'm sort of surprised this info isn't displayed as it's considered an indicator of fitness, even if it requires the user to wait 2 minutes. If he/she does, why not allow it to be tracked/displayed?
  • If you allow it to generate a HR recovery number before saving the value gets saved in the FIT file for the activity. Unfortunately nobody, not Garmin or Strava or Training Peaks, does anything with it. Which has never made any sense to me.
  • If you allow it to generate a HR recovery number before saving the value gets saved in the FIT file for the activity. Unfortunately nobody, not Garmin or Strava or Training Peaks, does anything with it. Which has never made any sense to me.


    Thanks .. I agree, it seems just one more indicator that could be helpful to assess fitness. I look at it 90% of the time (unless I accidentally click past it, and then it's gone), but it would be nice to have a record over time.

    just checking, that's the .fit file in the Activity folder right? Can you recommend a tool for converting the .fit file to .csv or excel
  • You can export to CSV straight from the Connect web interface. Just click on the gear symbol in the upper right when viewing the activity.
  • You can export to CSV straight from the Connect web interface. Just click on the gear symbol in the upper right when viewing the activity.


    I appreciate the pointer and I had seen that, but that only exports your splits essentially, not some of the other info that might be useful/I'm looking for like the recover hear rate

    [TABLE="border: 0, cellpadding: 0, cellspacing: 0"]
    [TR]
    [TD="width: 65"]Split[/TD]
    [TD="width: 50"]Time[/TD]
    [TD="width: 87"]Moving Time[/TD]
    [TD="width: 60"]Distance[/TD]
    [TD="width: 97"]Elevation Gain[/TD]
    [TD="width: 62"]Elev Loss[/TD]
    [TD="width: 62"]Avg Pace[/TD]
    [TD="width: 118"]Avg Moving Paces[/TD]
    [TD="width: 66"]Best Pace[/TD]
    [TD="width: 114"]Avg Run Cadence[/TD]
    [TD="width: 117"]Max Run Cadence[/TD]
    [TD="width: 116"]Avg Stride Length[/TD]
    [TD="width: 50"]Avg HR[/TD]
    [TD="width: 53"]Max HR[/TD]
    [TD="width: 115"]Avg Temperature[/TD]
    [TD="width: 57"]Calories[/TD]
    [/TR]
    [/TABLE]

  • The RHR is stored in the tail of the FIT file. Runalyze expose it.
  • The RHR is stored in the tail of the FIT file. Runalyze expose it.


    Cool .. also, I had never heard of Runalyze but just signed up, looks interesting - thanks for the info.
  • The RHR is stored in the tail of the FIT file. Runalyze expose it.


    Where does Runalyze expose it ? I went through the whole list in /Configuration/Dataset and can't seem to find it ?
  • I don't think it does. It shows the recovery time in hours, and other useful things like the current VO2max to a couple of decimal places, but not recovery HR.

    After reading the coursepoints thread, I banged together some python code using fitparse to pull the recovery HR values out of the FIT files in a folder and save them into a .csv file. A work of art it is not, but you may find it useful.

    # recoveryhr.py
    # mcbadger, May 2019
    import fitparse
    import glob

    fnames = glob.glob('*.fit')

    def parsefile( fname):
    fitfile = fitparse.FitFile(fname)

    # Is this a run?
    try:
    for sport in fitfile.get_messages('sport'):
    continue # so if it's a standard tri, it identifies as running
    if sport.get('sport').value == 'running':
    print '{}: is running ({}), scanning for recovery HR'.format(fname, sport.get('name').value)
    else:
    print '{}: is {}, skipping'.format(fname, sport.get('sport').value)
    return None
    except Exception as e:
    print '{} Exception {} looking for sport'.format(fname,e)
    return None

    # Get all data messages that are of type event
    # and search for recovery_hr. Don't break when found, if you pause for more than two minutes there will be a recovery_hr event for that.
    recovery_hr = -1
    final_hr = -1
    for event in fitfile.get_messages('event'):
    if event.get('event').value == 'recovery_hr':
    recovery_hr = event.get('data').value

    if recovery_hr < 0:
    print '\n{}: Recovery heart rate not found'.format(fname)
    return None

    # found, so worth looking for the final activity hr
    for record in fitfile.get_messages('record'):
    try:
    final_hr = record.get('heart_rate').value
    except:
    pass
    if final_hr > 0:
    print '\n{}: Final heart rate {} recovery heart rate {} delta {}'.format(fname, final_hr, recovery_hr, final_hr - recovery_hr)
    else:
    print '{}: Final heart rate not found, recovery heart rate {}'.format(fname, recovery_hr)
    for session in fitfile.get_messages('session'):
    print '{}: Total time {} minutes {} seconds, total distance {:.2f} km'.format(fname, int(session.get('total_timer_time').value/60.), int(round(session.get('total_timer_time').value%60)), session.get('total_distance').value/1000.0)
    return([fname,sport.get('name').value, session.get('start_time').value, final_hr, recovery_hr, session.get('total_timer_time').value, session.get('total_distance').value])



    with open('output.csv','w') as f:
    f.write('Filename,Sport,Start date and time, Final HR, Recovery HR, Decrease, Total time/sec, Total distance/km, Pace/(min/km)\n')
    for fname in fnames:
    retval = parsefile(fname)
    if retval:
    # seconds/km, printed as min/km below
    pace = int(round((1000.)*retval[5]/retval[6]))
    f.write('{},{},{},{},{},{},{},{},{}:{}\n'.format(retval[0],retval[1],retval[2],retval[3],retval[4],retval[3]-retval[4],retval[5], retval[6]/1000, int(pace/60),pace%60))
  • I don't think it does. It shows the recovery time in hours, and other useful things like the current VO2max to a couple of decimal places, but not recovery HR.

    After reading the coursepoints thread, I banged together some python code using fitparse to pull the recovery HR values out of the FIT files in a folder and save them into a .csv file. A work of art it is not, but you may find it useful.



    Super -- thanks for sharing this, I'll definitely will try this out (Python 2 I see :) ). Much appreciated, I had just downloaded the fitparse library and ran the sample program, but wasn't quite sure what I was looking for yet - this will definitely help.
  • Thanks for the script. So I installed Pythin 3.7 and created an rhr.py file, put a .fit in the same folder and ran it and get :

    "C:\Python>rhr.py
    File "C:\Python\rhr.py", line 16
    print '{}: is running ({}), scanning for recovery HR'.format(fname, sport.get('name').value)
    ^
    SyntaxError: invalid syntax"

    Am I doing something wrong ? Thanks !