How to Integrate GPX/KML Tracks with prettymaps Using the `gpx` Argument
You can overlay GPX or KML tracks on prettymaps visualizations by passing a file path or list of paths to the gpx argument, or use a track file as the map query itself for automatic framing.
The marceloprates/prettymaps library provides native support for integrating GPS track data into aesthetic OSM-based maps. This feature, implemented across prettymaps/gpx.py and prettymaps/draw.py, lets you visualize running routes, cycling tracks, or hiking paths alongside other map layers without preprocessing external tools.
How prettymaps Parses GPX and KML Files
The parsing pipeline in prettymaps/gpx.py handles both GPX (1.0/1.1) and KML formats through XML namespace-agnostic parsing.
Core Parsing Functions
The private helper _localname strips XML namespaces, enabling robust parsing regardless of schema version. Three main functions extract geometries:
_lines_from_gpx– Walks<trkseg>and<rte>elements, extracting(lon, lat)coordinate pairs intoLineStringobjects_lines_from_kml– Parses<coordinates>strings from<LineString>elements, handling thelon,lat[,alt]formatread_track– Public entry point that accepts a single path, list, or tuple and returns a unifiedMultiLineString
# Simplified flow from prettymaps/gpx.py
if isinstance(source, (list, tuple)):
# Recursively read each file and concatenate geometries
else:
root = ET.parse(source).getroot()
if _localname(root.tag) == "kml":
lines = _lines_from_kml(root)
elif _localname(root.tag) == "gpx":
lines = _lines_from_gpx(root)
else:
lines = _lines_from_gpx(root) or _lines_from_kml(root)
Geographic Utilities
Two helper functions prepare tracks for map integration:
track_center– Computes the geographic centroid of the track geometrytrack_radius– Calculates a suitable map radius from the bounding box (minimum 250 meters)
These enable auto-framing: when you pass a GPX/KML file as the main query, prettymaps automatically centers and zooms to fit the track.
How the gpx Argument Works in plot()
The integration logic resides in prettymaps/draw.py. When you call prettymaps.plot(), the function processes GPX tracks through five steps:
1. Detect the GPX/KML Source
gpx_source = gpx if gpx is not None else (query if is_track_file(query) else None)
The gpx argument takes precedence. If omitted but query is a recognizable track file (.gpx, .kml, .kmz), that becomes the source.
2. Read and Validate
track_geom = read_track(gpx_source)
Returns None if parsing fails, otherwise a MultiLineString.
3. Auto-Frame When Query Is a Track
If query is a track file and radius is not explicitly set:
track_centerbecomes the new query (a(lat, lon)tuple)track_radiusdetermines the zoom level
4. Inject as a Map Layer
if track_geom is not None:
gdfs["gpx"] = gp.GeoDataFrame(geometry=[track_geom], crs="EPSG:4326")
layers.setdefault("gpx", {})
style.setdefault("gpx", {**GPX_STYLE, **(gpx_style or {})})
The track enters the same pipeline as OSM-data layers—subject to translation, scaling, and rotation.
5. Render with draw_layers
The default style (GPX_STYLE) applies unless overridden.
Customizing GPX/KML Track Appearance
The default visual style is defined in prettymaps/draw.py:
GPX_STYLE = {"ec": "#EB4034", "lw": 3, "zorder": 6}
| Property | Value | Meaning |
|---|---|---|
ec |
"#EB4034" |
Edge color (red) |
lw |
3 |
Line width in points |
zorder |
6 |
Draw on top of most layers |
Override with the gpx_style argument. Keys merge with GPX_STYLE, so unspecified values keep defaults:
prettymaps.plot(
query="Porto Alegre",
gpx="samples/track.gpx",
gpx_style={"ec": "#00AAFF", "lw": 4} # Blue, thicker line
)
Practical Code Examples for Integrating GPX/KML Tracks
Use a Track File as the Query (Auto-Framing)
import prettymaps
# prettymaps auto-detects the format, centers the map, and sets radius
prettymaps.plot("samples/track.gpx")
Overlay a Track on a Named Location
prettymaps.plot(
query="Porto Alegre",
gpx="samples/track.gpx",
gpx_style={"ec": "#00AAFF", "lw": 4},
show=False,
save_as="porto_map.png"
)
Multiple Track Files
prettymaps.plot(
query="Berlin",
gpx=["track1.gpx", "track2.kml"], # Mixed formats supported
show=True
)
Access Track Geometry for Post-Processing
result = prettymaps.plot("track.gpx", show=False)
gpx_geom = result.geodataframes["gpx"].geometry.iloc[0] # Shapely MultiLineString
Source File Reference
| File | Purpose | Key Exports |
|---|---|---|
prettymaps/gpx.py |
Track parsing and geometry utilities | read_track, track_center, track_radius |
prettymaps/draw.py |
Plot orchestration and styling | plot, GPX_STYLE |
tests/test_gpx.py |
Validation suite | Examples of auto-framing and overlay behavior |
Summary
- Pass a GPX/KML path to
gpxto overlay tracks on any map query - Use a track file as
queryfor automatic centering and zoom - Multiple files are supported via list or tuple input
- Style customization merges with
GPX_STYLEthrough thegpx_styleargument - Track geometry is available in the returned result's
geodataframes["gpx"]for further analysis
Frequently Asked Questions
Can prettymaps handle KML files the same way as GPX?
Yes. The read_track function in prettymaps/gpx.py auto-detects format by checking the root XML tag. KML files with <LineString> elements parse correctly, and you can mix GPX and KML files in the same gpx list argument.
What happens if my track file has no valid geometry?
read_track returns None, and prettymaps.plot() skips GPX layer injection without raising an error. The map renders normally with other layers. Check result.geodataframes for the presence of a "gpx" key to confirm successful parsing.
How do I make the track line thicker or change its color?
Pass a dictionary to gpx_style with Matplotlib-compatible properties. The default {"ec": "#EB4034", "lw": 3} uses edge color and line width; any keys you provide override these defaults while preserving unspecified values.
Can I use a GPX track to define the map boundaries without showing the line?
Not directly through the public API. The track layer always renders if successfully parsed. To hide it, you would need to set lw: 0 and fc: "none" in gpx_style, or modify the gdfs["gpx"] entry after calling plot() with show=False.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →