def load_gpx(self, file_name: str, timezone_adjuster: typing.Optional[TimezoneAdjuster]) -> None: """Load the GPX file into self. Args: file_name: GPX file to be loaded . Raises: TrackLoadError: An error occurred while parsing the GPX file (empty or bad format). PermissionError: An error occurred while opening the GPX file. """ try: self.file_names = [os.path.basename(file_name)] # Handle empty gpx files # (for example, treadmill runs pulled via garmin-connect-export) if os.path.getsize(file_name) == 0: raise TrackLoadError("Empty GPX file") with open(file_name, "r") as file: self._load_gpx_data(gpxpy.parse(file), timezone_adjuster) except TrackLoadError as e: raise e except gpxpy.gpx.GPXXMLSyntaxException as e: raise TrackLoadError("Failed to parse GPX.") from e except PermissionError as e: raise TrackLoadError("Cannot load GPX (bad permissions)") from e except Exception as e: raise TrackLoadError( "Something went wrong when loading GPX.") from e
def load_cache(self, cache_file_name: str) -> None: """Load the track from a previously cached track Args: cache_file_name: Filename of the cached track to be loaded. Raises: TrackLoadError: An error occurred while loading the track data from the cache file. """ try: with open(cache_file_name) as data_file: data = json.load(data_file) self.start_time = datetime.datetime.strptime( data["start"], "%Y-%m-%d %H:%M:%S") self.end_time = datetime.datetime.strptime( data["end"], "%Y-%m-%d %H:%M:%S") self._length_meters = float(data["length"]) self.polylines = [] for data_line in data["segments"]: self.polylines.append([ s2sphere.LatLng.from_degrees(float(d["lat"]), float(d["lng"])) for d in data_line ]) except Exception as e: raise TrackLoadError( "Failed to load track data from cache.") from e
def _load_gpx_data(self, gpx: "mod_gpxpy.gpx.GPX"): self.start_time, self.end_time = gpx.get_time_bounds() if self.start_time is None: raise TrackLoadError("Track has no start time.") if self.end_time is None: raise TrackLoadError("Track has no end time.") self.length = gpx.length_2d() if self.length == 0: raise TrackLoadError("Track is empty.") gpx.simplify() for t in gpx.tracks: for s in t.segments: line = [ s2.LatLng.from_degrees(p.latitude, p.longitude) for p in s.points ] self.polylines.append(line)
def _get_cache_file_name(self, file_name: str) -> str: assert self.cache_dir if file_name in self._cache_file_names: return self._cache_file_names[file_name] try: checksum = hashlib.sha256(open(file_name, "rb").read()).hexdigest() except PermissionError as e: raise TrackLoadError("Failed to compute checksum (bad permissions).") from e except Exception as e: raise TrackLoadError("Failed to compute checksum.") from e cache_file_name = os.path.join(self.cache_dir, f"{checksum}.json") self._cache_file_names[file_name] = cache_file_name return cache_file_name
def _load_gpx_data(self, gpx: gpxpy.gpx.GPX, timezone_adjuster: typing.Optional[TimezoneAdjuster]) -> None: self._start_time, self._end_time = gpx.get_time_bounds() if not self.has_time(): raise TrackLoadError("Track has no start or end time.") if timezone_adjuster: lat, _, lng, _ = list(gpx.get_bounds()) latlng = s2sphere.LatLng.from_degrees(lat, lng) self.set_start_time(timezone_adjuster.adjust(self.start_time(), latlng)) self.set_end_time(timezone_adjuster.adjust(self.end_time(), latlng)) self._length_meters = gpx.length_2d() if self._length_meters <= 0: raise TrackLoadError("Track is empty.") gpx.simplify() for t in gpx.tracks: for s in t.segments: line = [s2sphere.LatLng.from_degrees(p.latitude, p.longitude) for p in s.points] self.polylines.append(line)
def load_cached_track_file(cache_file_name: str, file_name: str) -> Track: """Load an individual track from cache files""" try: t = Track() t.load_cache(cache_file_name) t.file_names = [os.path.basename(file_name)] log.info(f"Loaded track {file_name} from cache file {cache_file_name}") return t except Exception as e: raise TrackLoadError("Failed to load track from cache.") from e