Created
February 12, 2026 14:24
-
-
Save Luca-Pozzi/889b0ba890b328cb81be4b8650a8536e to your computer and use it in GitHub Desktop.
Utility file to extract data from Garmin FIT files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os | |
| import csv | |
| import tkinter.filedialog | |
| import garmin_fit_sdk | |
| import matplotlib.pyplot as plt | |
| # Import one .fit file from filedialog | |
| fpath = tkinter.filedialog.askopenfile( | |
| mode='r', | |
| filetypes=[('Garmin FIT files', '*.fit;*.FIT')] | |
| ).name | |
| # Read data from .fit file | |
| stream = garmin_fit_sdk.Stream.from_file(fpath) | |
| decoder = garmin_fit_sdk.Decoder(stream) | |
| messages, errors = decoder.read( | |
| apply_scale_and_offset=True, | |
| convert_datetimes_to_dates=True, | |
| convert_types_to_strings=True, | |
| enable_crc_check=True, | |
| expand_sub_fields=True, | |
| expand_components=True, | |
| merge_heart_rates=True, | |
| mesg_listener=None | |
| ) | |
| # Extract HR and timestamp data | |
| hr_list = [] | |
| t_list = [] | |
| for msg in messages['record_mesgs']: | |
| if not 'heart_rate' in msg: | |
| continue | |
| hr_list.append(msg['heart_rate']) | |
| t_list.append(msg['timestamp'].timestamp()) | |
| # Extract laps | |
| lap_list = [] | |
| for msg in messages['lap_mesgs']: | |
| lap_list.append(msg['start_time'].timestamp()) | |
| # Plot the data | |
| plt.plot() | |
| plt.plot(t_list, hr_list) | |
| # Draw vertical lines corresponding to laps | |
| y_min, y_max = plt.gca().get_ylim() # get current Y-axis limits | |
| plt.vlines(lap_list, y_min, y_max, colors='r', linestyles='dashed') | |
| # Set the axis labels | |
| plt.xlabel("Time [s]") | |
| plt.ylabel("HR [bpm]") | |
| plt.title("Heart rate") | |
| plt.show() | |
| # Save HR data and laps to (separate) CSV files | |
| fdir = os.path.dirname(fpath) # get name of directory where files are | |
| fname = os.path.basename(fpath).split('.')[0] # get fname w/o extension | |
| with open(os.path.join(fdir, f"{fname}_hr.csv"), 'w', newline='') as f: | |
| csv_writer = csv.writer(f) | |
| csv_writer.writerow(['HR [bpm]', 't [s]']) | |
| csv_writer.writerows([[hr, t] for hr, t in zip(hr_list, t_list)]) | |
| with open(os.path.join(fdir, f"{fname}_lap.csv"), 'w', newline='') as f: | |
| csv_writer = csv.writer(f) | |
| csv_writer.writerow(['t [s]']) | |
| csv_writer.writerows([[t] for t in lap_list]) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
fit_reader.pyExtract data from Garmin FIT file, and save to CSV file.
In the current implementation, the script:
Tip
All data included in the FIT file can be extracted by tweaking the parsing stage (i.e., lines 27-39). Some knowledge about the structure of the FIT file format can be found in the Garmin FIT SDK documentation.
Requirements
Before running the script, install the required dependencies with
Note
The
matplotlibdependency can be omitted if the plotting stage is commented out from the code.