Source code for ezgpx.plotters.plotly_plotter

import os
import warnings
from typing import Optional

import numpy as np
import plotly.graph_objects as go

from .plotter import Plotter


[docs] class PlotlyPlotter(Plotter): """ GPX plotter based on Plotly. """
[docs] def plot( self, tiles: str = "open-street-map", # "open-street-map" mode: str = "lines", # "lines", "markers+lines" color: str = "#FFA800", start_point_color: Optional[str] = None, stop_point_color: Optional[str] = None, waypoints_color: Optional[str] = None, title: Optional[str] = None, zoom: Optional[float] = None, file_path: Optional[str] = None, ): """ Plot (animation) GPX using Plotly. Args: tiles (str, optional): Map tiles to use. Defaults to "open-street-map". start_point_color (Optional[str], optional): Color of the first point. Defaults to None. stop_point_color (Optional[str], optional): Color of the last point. Defaults to None. waypoints_color (Optional[str], optional): Color of the way points. Defaults to None. title (Optional[str], optional): Title of the plot. Defaults to None. zoom (float, optional): Zoom. Defaults to 12.0. file_path (Optional[str], optional): Path to save the plot. Defaults to None. Returns: _type_: _description_ """ self._df = self._gpx.to_polars() center_lat, center_lon = self._gpx.center() min_lat, min_lon, max_lat, max_lon = self._gpx.bounds() if zoom is None: # Determine zoom level based on bounds lat_range = max_lat - min_lat lon_range = max_lon - min_lon max_range = max(lat_range, lon_range) zoom = 8 - np.log2(max_range + 1e-6) # Create map and scatter fig = go.Figure( go.Scattermap( mode=mode, lon=self._df["lon"], lat=self._df["lat"], marker={"size": 5, "color": color}, ) ) # Scatter start and stop points with different color if start_point_color: fig.add_trace( go.Scattermap( mode="markers", lon=[self._df["lon"].iloc[0]], lat=[self._df["lat"].iloc[0]], marker={"size": 5, "color": start_point_color}, ) ) if stop_point_color: fig.add_trace( go.Scattermap( mode="markers", lon=[self._df["lon"].iloc[-1]], lat=[self._df["lat"].iloc[-1]], marker={"size": 5, "color": stop_point_color}, ) ) # Scatter way points with different color if waypoints_color: for waypoint in self._gpx.gpx.wpt: fig.add_trace( go.Scattermap( mode="markers", lon=waypoint.lon, lat=waypoint.lat, marker={"size": 5, "color": waypoints_color}, ) ) # Update layout for nice display fig.update_layout( margin={"l": 0, "t": 0, "b": 0, "r": 0}, map={ "center": {"lon": center_lon, "lat": center_lat}, "style": tiles, "zoom": zoom, }, title={"text": title}, ) # Save plot if file_path is not None: # Check if provided path exists directory_path = os.path.dirname(os.path.realpath(file_path)) if not os.path.exists(directory_path): warnings.warn("Provided path does not exist") return if file_path.endswith(".html"): fig.write_html(file_path) elif file_path.endswith(".json"): fig.write_json(file_path) else: fig.write_image(file_path) return fig