# natlabrockies/mappymatch architecture

> Architecture diagram of the GitHub repository natlabrockies/mappymatch, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/natlabrockies/mappymatch
- Repository: https://github.com/natlabrockies/mappymatch

## Overview

1. **What the package is**
   - `mappymatch` is a pure-Python map-matching library whose core job is to take a GPS trace and align it to a road network.
   - The architecture is centered on a small domain model, pluggable map backends, and multiple matcher implementations.

2. **Core domain layer**
   - The `constructs` package defines the shared data model used by all matchers and maps: `Coordinate`, `Trace`, `Geofence`, `Road`, and `Match`.
   - These objects are the main boundary between raw inputs, map data, and matcher outputs.

3. **Trace ingestion and preprocessing**
   - Trace data is typically loaded from CSV or geospatial files into `Trace` objects.
   - `utils/process_trace.py` and related helpers handle trace normalization and preparation steps such as coordinate handling, stationary-point logic, and geometric utilities.
   - This layer is where raw GPS points become matcher-ready input.

4. **Map abstraction layer**
   - `maps/map_interface.py` defines the common map contract.
   - There are concrete map adapters for:
     - `maps/nx/NxMap` for NetworkX-based road graphs
     - `maps/igraph/IGraphMap` for igraph-based graphs
   - This abstraction lets matchers work against a common map API instead of binding to one graph library.

5. **OpenStreetMap acquisition**
   - `maps/nx/readers/osm_readers.py` is the OSM ingestion path for the NetworkX backend.
   - The typical flow is: build a `Geofence` around a trace, query OSM data within that boundary, and construct an in-memory road network.
   - In practice, the repository’s primary map source is OpenStreetMap.

6. **Matcher subsystem**
   - `matchers/matcher_interface.py` defines the matcher boundary.
   - The repo contains three matcher families:
     - `LCSSMatcher` in `matchers/lcss/`
     - `OsrmMatcher`
     - `ValhallaMatcher`
   - This is the main strategy layer: each matcher consumes the same trace/map abstractions but produces matches through a different algorithm or service.

7. **LCSS matcher internals**
   - The `lcss` package is the most substantial in-repo algorithm implementation.
   - It contains the algorithm, helper operations, and internal constructs used for segmentation/sequence alignment.
   - This matcher is local and offline: it runs entirely in Python against the in-memory road graph, making it the repo’s most self-contained matching path.

8. **External service-based matchers**
   - `OsrmMatcher` and `ValhallaMatcher` are thin clients over external routing/map-matching engines.
   - They introduce a network boundary: trace data is serialized, sent to a running OSRM or Valhalla service, and the returned match result is converted back into the package’s internal `Match` representation.
   - These matchers depend on service availability and remote API compatibility, unlike LCSS.

9. **Match results**
   - `matchers/match_result.py` is the common output container for all matchers.
   - It acts as the integration point for downstream analysis, including conversion to tabular form via pandas-like dataframe workflows.
   - This keeps result consumption separate from algorithm execution.

10. **Geometry, CRS, and geo utilities**
   - `utils/crs.py`, `utils/geo.py`, and `utils/url.py` support coordinate system handling, geometric calculations, and request construction.
   - These utilities are shared infrastructure used by trace processing, geofence creation, map loading, and service-backed matchers.

11. **Plotting and visualization**
   - `utils/plot/` contains visualization helpers for maps, traces, geofences, paths, trajectory segments, and matches.
   - This is a presentation layer, not part of the core matching pipeline, but it is important for debugging and explaining results.

12. **Data and example assets**
   - `resources/traces/` provides sample trace CSVs used in examples and tests.
   - `tests/test_assets/` includes OSM graph and geospatial fixtures, showing the intended offline testing path for map and trace behavior.
   - These assets indicate the library is designed to be exercised both with real OSM-derived graphs and small reproducible fixtures.

13. **Typical end-to-end flow**
   - The canonical architecture path is:
     - load a `Trace`
     - derive a `Geofence`
     - build or load a map backend (`NxMap` or `IGraphMap`)
     - run a matcher (`LCSSMatcher`, OSRM, or Valhalla)
     - consume a `MatchResult`
   - This is the key pipeline to show in an architecture diagram.

14. **Repository boundary and delivery**
   - The project ships as a Python package with docs and automated testing.
   - Documentation lives under `docs/`, and the test suite covers trace handling, geo logic, OSM integration, matchers, and result behavior.
   - The package is therefore a library architecture, not a server or application architecture.

Main entry points: [`mappymatch/matchers/lcss/lcss.py`](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/lcss.py) (LCSSMatcher), [`mappymatch/utils/process_trace.py`](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/process_trace.py) (Trace prep), [`mappymatch/matchers/match_result.py`](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/match_result.py) (MatchResult), [`mappymatch/constructs/trace.py`](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/trace.py) (Trace)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_core["Core domain"]
  node_coordinate(("Coordinate<br/>domain model<br/>[coordinate.py]"))
  node_trace["Trace<br/>domain model<br/>[trace.py]"]
  node_geofence{{"Geofence<br/>spatial boundary<br/>[geofence.py]"}}
  node_road["Road<br/>[road.py]"]
  node_match["Match<br/>domain model<br/>[match.py]"]
end

subgraph group_maps["Map backends"]
  node_map_interface["Map API<br/>abstract map<br/>[map_interface.py]"]
  node_nx_map[("NxMap<br/>networkx backend<br/>[nx_map.py]")]
  node_osm_readers["OSM reader<br/>osm ingestion<br/>[osm_readers.py]"]
  node_igraph_map[("IGraphMap<br/>igraph backend<br/>[igraph_map.py]")]
end

subgraph group_matchers["Matchers"]
  node_matcher_interface["Matcher API<br/>abstract matcher"]
  node_lcss_matcher{{"LCSSMatcher<br/>local matcher<br/>[lcss.py]"}}
  node_lcss_ops["LCSS ops<br/>algorithm helpers<br/>[ops.py]"]
  node_lcss_constructs["LCSS constructs<br/>algorithm state<br/>[constructs.py]"]
  node_osrm_matcher{{"OsrmMatcher<br/>service matcher<br/>[osrm.py]"}}
  node_valhalla_matcher{{"ValhallaMatcher<br/>service matcher<br/>[valhalla.py]"}}
  node_match_result["MatchResult<br/>result container<br/>[match_result.py]"]
end

subgraph group_support["Support"]
  node_process_trace["Trace prep<br/>preprocessing<br/>[process_trace.py]"]
  node_geo_utils["Geo utils<br/>geometry helpers<br/>[geo.py]"]
  node_crs_utils["CRS utils<br/>projection helpers<br/>[crs.py]"]
  node_url_utils["URL utils<br/>request helpers<br/>[url.py]"]
  node_plotting["Plotting<br/>visualization<br/>[map.py]"]
  node_sample_traces["Sample traces<br/>data assets<br/>[sample_trace_1.csv]"]
  node_test_assets["Test assets<br/>fixtures"]
end

node_trace -->|"prepared by"| node_process_trace
node_process_trace -->|"emits"| node_coordinate
node_process_trace -->|"derives"| node_geofence
node_geofence -->|"bounds query"| node_osm_readers
node_osm_readers -->|"builds"| node_nx_map
node_map_interface -->|"implements"| node_nx_map
node_map_interface -->|"implements"| node_igraph_map
node_nx_map -->|"contains"| node_road
node_igraph_map -->|"contains"| node_road
node_matcher_interface -->|"implements"| node_lcss_matcher
node_matcher_interface -->|"implements"| node_osrm_matcher
node_matcher_interface -->|"implements"| node_valhalla_matcher
node_lcss_matcher -->|"uses"| node_lcss_ops
node_lcss_matcher -->|"uses"| node_lcss_constructs
node_lcss_matcher -->|"consumes"| node_map_interface
node_osrm_matcher -->|"serializes"| node_url_utils
node_valhalla_matcher -->|"serializes"| node_url_utils
node_osrm_matcher -->|"returns"| node_match_result
node_valhalla_matcher -->|"returns"| node_match_result
node_lcss_matcher -->|"returns"| node_match_result
node_match_result -->|"wraps"| node_match
node_geo_utils -->|"uses"| node_crs_utils
node_process_trace -->|"uses"| node_geo_utils
node_process_trace -->|"uses"| node_crs_utils
node_plotting -->|"renders"| node_trace
node_plotting -->|"renders"| node_geofence
node_plotting -->|"renders"| node_match_result
node_sample_traces -->|"example input"| node_trace
node_test_assets -->|"fixture input"| node_nx_map
node_test_assets -->|"fixture input"| node_trace

click node_coordinate "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/coordinate.py"
click node_trace "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/trace.py"
click node_geofence "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/geofence.py"
click node_road "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/road.py"
click node_match "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/match.py"
click node_map_interface "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/map_interface.py"
click node_nx_map "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/nx/nx_map.py"
click node_osm_readers "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/nx/readers/osm_readers.py"
click node_igraph_map "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/igraph/igraph_map.py"
click node_matcher_interface "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/matcher_interface.py"
click node_lcss_matcher "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/lcss.py"
click node_lcss_ops "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/ops.py"
click node_lcss_constructs "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/constructs.py"
click node_osrm_matcher "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/osrm.py"
click node_valhalla_matcher "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/valhalla.py"
click node_match_result "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/match_result.py"
click node_process_trace "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/process_trace.py"
click node_geo_utils "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/geo.py"
click node_crs_utils "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/crs.py"
click node_url_utils "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/url.py"
click node_plotting "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/plot/map.py"
click node_sample_traces "https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/resources/traces/sample_trace_1.csv"
click node_test_assets "https://github.com/natlabrockies/mappymatch/blob/main/tests/test_assets/osmnx_drive_graph.graphml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_coordinate,node_trace,node_geofence,node_road,node_match toneBlue
class node_map_interface,node_nx_map,node_osm_readers,node_igraph_map toneAmber
class node_matcher_interface,node_lcss_matcher,node_lcss_ops,node_lcss_constructs,node_osrm_matcher,node_valhalla_matcher,node_match_result toneMint
class node_process_trace,node_geo_utils,node_crs_utils,node_url_utils,node_plotting,node_sample_traces,node_test_assets toneRose
```

## Components

### Core domain

Shared trace, road, geofence, and match objects used across the library

- [Coordinate](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/coordinate.py): domain model · Single GPS or projected point used throughout the package · `mappymatch/constructs/coordinate.py`
- [Trace](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/trace.py): domain model · Ordered GPS trajectory input for matching · `mappymatch/constructs/trace.py`
- [Geofence](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/geofence.py): spatial boundary · Area of interest derived from a trace or used to constrain map loading · `mappymatch/constructs/geofence.py`
- [Road](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/road.py): road segment · Road-network element shared by map adapters and matchers · `mappymatch/constructs/road.py`
- [Match](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/constructs/match.py): domain model · Matched trace output emitted by matching algorithms · `mappymatch/constructs/match.py`

### Map backends

Abstract map contract plus concrete graph-based adapters and OSM ingestion

- [Map API](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/map_interface.py): abstract map · Common contract implemented by all map backends · `mappymatch/maps/map_interface.py`
- [NxMap](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/nx/nx_map.py): networkx backend · In-memory road graph backend built on NetworkX · `mappymatch/maps/nx/nx_map.py`
- [OSM reader](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/nx/readers/osm_readers.py): osm ingestion · Builds NetworkX road graphs from OpenStreetMap data inside a geofence · `mappymatch/maps/nx/readers/osm_readers.py`
- [IGraphMap](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/maps/igraph/igraph_map.py): igraph backend · In-memory road graph backend built on igraph · `mappymatch/maps/igraph/igraph_map.py`

### Matchers

Local and service-backed matching strategies

- [Matcher API](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/matcher_interface.py): abstract matcher · Common interface implemented by all matcher strategies · `mappymatch/matchers/matcher_interface.py`
- [LCSSMatcher](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/lcss.py): local matcher · Offline Python matcher using LCSS-style sequence alignment over a map graph · `mappymatch/matchers/lcss/lcss.py`
- [LCSS ops](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/ops.py): algorithm helpers · Internal alignment and merge operations for the LCSS matcher · `mappymatch/matchers/lcss/ops.py`
- [LCSS constructs](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/lcss/constructs.py): algorithm state · Internal constructs and segmentation state used by LCSS · `mappymatch/matchers/lcss/constructs.py`
- [OsrmMatcher](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/osrm.py): service matcher · Client wrapper for external OSRM map-matching service · `mappymatch/matchers/osrm.py`
- [ValhallaMatcher](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/valhalla.py): service matcher · Client wrapper for external Valhalla map-matching service · `mappymatch/matchers/valhalla.py`
- [MatchResult](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/matchers/match_result.py): result container · Common output object returned by matchers and consumed downstream · `mappymatch/matchers/match_result.py`

### Support

Trace processing, geo utilities, plotting, and packaged assets

- [Trace prep](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/process_trace.py): preprocessing · Normalizes trace input and handles stationary-point and geometry preparation · `mappymatch/utils/process_trace.py`
- [Geo utils](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/geo.py): geometry helpers · Coordinate system, geometry, and spatial helper functions · `mappymatch/utils/geo.py`
- [CRS utils](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/crs.py): projection helpers · Coordinate reference system conversion and handling · `mappymatch/utils/crs.py`
- [URL utils](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/url.py): request helpers · Builds service request URLs for external matchers · `mappymatch/utils/url.py`
- [Plotting](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/utils/plot/map.py): visualization · Helpers for drawing traces, maps, geofences, paths, and matches · `mappymatch/utils/plot/map.py`
- [Sample traces](https://github.com/natlabrockies/mappymatch/blob/main/mappymatch/resources/traces/sample_trace_1.csv): data assets · Packaged trace CSV examples used in docs and examples · `mappymatch/resources/traces/sample_trace_1.csv`
- [Test assets](https://github.com/natlabrockies/mappymatch/blob/main/tests/test_assets/osmnx_drive_graph.graphml): fixtures · GeoJSON, GPX, and graph fixtures for offline validation · `tests/test_assets/osmnx_drive_graph.graphml`

## Connections

- Trace → Trace prep: prepared by · Raw trace input is normalized before matching
- Trace prep → Coordinate: emits · Trace preprocessing operates on coordinate objects
- Trace prep → Geofence: derives · A geofence is commonly built around the trace extent
- Geofence → OSM reader: bounds query · OpenStreetMap acquisition is constrained to the geofence
- OSM reader → NxMap: builds · OSM data is converted into an in-memory NetworkX map
- Map API → NxMap: implements · NetworkX backend satisfies the shared map contract
- Map API → IGraphMap: implements · igraph backend satisfies the shared map contract
- NxMap → Road: contains · Road segments are represented inside the graph backend
- IGraphMap → Road: contains · Road segments are represented inside the graph backend
- Matcher API → LCSSMatcher: implements · LCSS is a concrete matcher strategy
- Matcher API → OsrmMatcher: implements · OSRM is a concrete matcher strategy
- Matcher API → ValhallaMatcher: implements · Valhalla is a concrete matcher strategy
- LCSSMatcher → LCSS ops: uses · Core algorithm delegates to internal operations
- LCSSMatcher → LCSS constructs: uses · Alignment state and segmentation constructs support the matcher
- LCSSMatcher → Map API: consumes · Local matching runs against the common map API
- OsrmMatcher → URL utils: serializes · Request construction supports the external service call
- ValhallaMatcher → URL utils: serializes · Request construction supports the external service call
- OsrmMatcher → MatchResult: returns · Service response is converted into the shared result object
- ValhallaMatcher → MatchResult: returns · Service response is converted into the shared result object
- LCSSMatcher → MatchResult: returns · Offline matcher emits the shared result object
- MatchResult → Match: wraps · MatchResult packages the domain match output
- Geo utils → CRS utils: uses · Spatial helpers depend on CRS handling
- Trace prep → Geo utils: uses · Trace preprocessing relies on shared geometry helpers
- Trace prep → CRS utils: uses · Trace preprocessing relies on projection utilities
- Plotting → Trace: renders · Visualization helpers draw traces and trajectories
- Plotting → Geofence: renders · Visualization helpers draw map boundaries
- Plotting → MatchResult: renders · Visualization helpers display matches
- Sample traces → Trace: example input · Packaged CSV traces demonstrate the expected trace format
- Test assets → NxMap: fixture input · Graph fixtures exercise the map backend
- Test assets → Trace: fixture input · Trace fixtures exercise ingestion and preprocessing
