Source code for ezgpx.parsers.fit_parser

"""
This module contains the FitParser class.
"""

from pathlib import Path
from typing import IO

from fitparse import FitFile

from ..complex_types import Trk, Trkseg, Wpt
from ..constants.precisions import DEFAULT_PRECISION
from .parser import Parser


[docs] class FitParser(Parser): """ Fit file parser. """ _semicircles_to_deg_const = 180 / 2**31 def __init__(self, source: str | Path | IO[str] | IO[bytes] | bytes) -> None: """ Initialise FitParser instance. Args: source (str | Path | IO[str] | IO[bytes] | bytes): Path to a file or a file-like object to parse. """ super().__init__(source) def _semicircles_to_deg(self, semicircle_coord: list) -> list: """ Convert semicircle data from FIT file to dms data. Args: semicircle_coord (list): list of semicircle values. Returns: list: list of dms values. """ return [FitParser._semicircles_to_deg_const * x for x in semicircle_coord] def _parse(self): """ Parse FIT file and store data in a Gpx element. """ lat_data = [] lon_data = [] alt_data = [] time_data = [] units = {"alt": "", "lat": "", "lon": ""} fit_file = FitFile(self.source) for record in fit_file.get_messages("record"): for record_data in record: if record_data.name == "position_lat": lat_data.append(record_data.value) if units["lat"] == "": units["lat"] = record_data.units # Temporary (may change if units["lat"] == "semicircles") self.precisions["lat_lon"] = self._find_precision( record_data.value ) if record_data.name == "position_long": lon_data.append(record_data.value) if units["lon"] == "": units["lon"] = record_data.units if record_data.name == "altitude": alt_data.append(record_data.value) if units["alt"] == "": units["alt"] = record_data.units self.precisions["elevation"] = self._find_precision( record_data.value ) if record_data.name == "timestamp": time_data.append(record_data.value) self._find_time_format(record_data.value) # Convert semicircles data to radians ?? if units["lat"] == "semicircles": self.precisions["lat_lon"] = DEFAULT_PRECISION lat_data = self._semicircles_to_deg(lat_data) if units["lon"] == "semicircles": lon_data = self._semicircles_to_deg(lon_data) # Store FIT data in Gpx element trkpt = [ Wpt("trkpt", lat, lon, alt, time) for lat, lon, alt, time in zip(lat_data, lon_data, alt_data, time_data) ] trkseg = Trkseg(trkpt=trkpt) trk = Trk(trkseg=[trkseg]) self.gpx.trk = [trk] def _add_properties(self): self.gpx.creator = "ezGPX" self.gpx.xmlns = "http://www.topografix.com/GPX/1/1" self.gpx.version = "1.1" self.gpx.xmlns_xsi = "http://www.w3.org/2001/XMLSchema-instance" self.gpx.xsi_schema_location = [ "http://www.topografix.com/GPX/1/1", "http://www.topografix.com/GPX/1/1/gpx.xsd", ]
[docs] def parse(self) -> dict: """ Parse Fit file. dict: Gpx, precisions and time_format. Example: >>> # TODO """ # Parse FIT file self._parse() # Add properties self._add_properties() return { "gpx": self.gpx, "precisions": self.precisions, "time_format": self.time_format, }