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 into LineString objects
  • _lines_from_kml – Parses <coordinates> strings from <LineString> elements, handling the lon,lat[,alt] format
  • read_track – Public entry point that accepts a single path, list, or tuple and returns a unified MultiLineString

# 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 geometry
  • track_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_center becomes the new query (a (lat, lon) tuple)
  • track_radius determines 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 gpx to overlay tracks on any map query
  • Use a track file as query for automatic centering and zoom
  • Multiple files are supported via list or tuple input
  • Style customization merges with GPX_STYLE through the gpx_style argument
  • 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →