Metadata-Version: 2.4
Name: mapmatcher4gmns
Version: 0.2.1
Summary: A high-performance map matching tool for GMNS networks
Author: Yajun Liu, Xuesong (Simon) Zhou
Author-email: yajunliu@asu.edu, xzhou74@asu.edu
License-Expression: MIT
Project-URL: GitHub, https://github.com/yajunliu99/mapmatcher4gmns
Keywords: map-matching,GMNS,GPS,transportation,GIS
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20.0
Requires-Dist: pandas>=1.3.0
Requires-Dist: shapely>=2.0.0
Requires-Dist: geopandas>=0.10.0
Requires-Dist: networkx>=2.6.0
Requires-Dist: tqdm>=4.60.0
Dynamic: license-file

# MapMatcher4GMNS

A high-performance map matching tool for GPS trajectories on GMNS (General Modeling Network Specification) networks.

## Features

- **High-Performance Map Matching**: Efficient Hidden Markov Model (HMM) based map matching algorithm
- **GMNS Network Support**: Native support for GMNS network format (node.csv, link.csv)
- **Multi-Core Processing**: Built-in parallel processing support for large-scale GPS data
- **Flexible Configuration**: Comprehensive parameters for fine-tuning matching quality
- **Route Generation**: Automatic generation of complete routes between matched points
- **GMNS Identifier Preservation**: Supports numeric, alphanumeric, and zero-padded `link_id` values
- **Robust Time Parsing**: Supports offset-aware text timestamps and numeric Unix epochs across pandas versions

## Installation

### From PyPI

```bash
pip install mapmatcher4gmns
```

## Quick Start

```python
import mapmatcher4gmns as m4g

def main():
    # Load network from GMNS format
    net = m4g.LoadNetFromCSV(
        folder='path/to/network',
        node_file='node.csv',
        link_file='link.csv'
    )

    # Create matcher
    matcher = m4g.MapMatcher(
        network=net,
        time_field='timestamp',
        time_format='%Y-%m-%dT%H:%M:%S.%fZ',
        out_dir='output',
        result_file='matched_result.csv',
        route_file='matched_route.csv',
    )

    # Perform map matching (pass CSV path)
    matcher.match('gps_data.csv')

    # Note: match(...) accepts CSV path string input.

if __name__ == '__main__':
    main()
```


## Input Data Requirements

### Network Files (GMNS Format)

**node.csv** (required fields):
- `node_id`: Unique node identifier
- `x_coord`: Longitude (if coordinate_type='lonlat') or X coordinate
- `y_coord`: Latitude (if coordinate_type='lonlat') or Y coordinate

**link.csv** (required fields):
- `link_id`: Unique integer or string identifier. Values such as `193912AB` and
  zero-padded IDs such as `0007` are preserved.
- `from_node_id`: Starting node ID
- `to_node_id`: Ending node ID
- `lanes`: Number of lanes
- `geometry`: LineString geometry in WKT format

### GPS Data

**Required fields**:
- `journey_id` (or custom agent_field): Unique identifier for each GPS trajectory
- `longitude`: GPS longitude
- `latitude`: GPS latitude

**Optional but recommended**:
- `time` (or custom time_field): Timestamp for temporal ordering
- `speed`: Speed
- `heading`: Heading direction in degrees

### Timestamp Handling

Set `time_format` when the input uses a known text format. If `time_format` is
omitted, text timestamps are parsed automatically and normalized to UTC
internally. Numeric values, including numeric strings, are treated as Unix
epochs; the package infers seconds, milliseconds, microseconds, or nanoseconds
from their magnitude. This prevents Unix seconds from being silently treated as
nanoseconds.

## Configuration Parameters

### Core Matching Parameters

- `search_radius` (default: 15.0): Search radius in meters for candidate links
- `noise_sigma` (default: 8.0): GPS noise standard deviation in meters
- `trans_weight` (default: 12.0): Weight for transition probability
- `max_candidates` (default: 10): Maximum number of candidate links per GPS point

### Movement Consistency

- `turn_sigma` (default: 45.0): Turn angle standard deviation in degrees
- `heading_sigma` (default: 30.0): Heading difference standard deviation
- `use_heading` (default: True): Whether to use heading information

### Filtering

- `filter_dwell` (default: False): Filter out stationary points
- `dwell_dist` (default: 5.0): Distance threshold for dwell detection in meters
- `dwell_count` (default: 2): Minimum consecutive points to be considered dwelling
- `max_gap_seconds` (default: 45.0): Maximum time gap allowed between consecutive points
- `fused_point`: If this input column exists, rows with `fused_point=True` are automatically excluded from matching

### Performance

- `core_num`: Number of CPU cores to use (default: 1). If set above
  `os.cpu_count()`, it is capped to available CPU cores. Each process builds its
  own network graph and spatial index, so start with one worker for large
  networks and increase only after measuring memory and runtime.
- `max_agents` (default: None): Maximum number of trajectories to process (useful for testing/debugging). If set, only the first N trajectories will be matched

## Output

The tool generates two main output files:

### 1. Matched Results (`matched_result.csv`)

Contains the matched GPS points with:
- `journey_id`: Trajectory identifier
- `seq`: Sequence number
- `time`: Timestamp
- `link_id`: Matched link ID
- `from_node_id`, `to_node_id`: Link endpoints
- `longitude`, `latitude`: Original GPS coordinates
- `speed_mph`: Speed (if provided)
- `match_heading`: Heading of matched link
- `route_dis`: Cumulative route distance

### 2. Route File (`matched_route.csv`)

Contains the complete route for each journey:
- `journey_id`: Trajectory identifier
- `link_ids`: Comma-separated list of link IDs forming the complete route

### 3. Run Summary (`summary.txt`)

Contains run-level summary statistics:
- Input/kept/dropped/matched journeys
- Input/matched data points and match rate
- Total elapsed time

## Advanced Usage

**Note:** When using multiprocessing features, wrap your code in `if __name__ == '__main__':` to avoid issues, especially on Windows.

### Multi-Core Processing

```python
matcher = m4g.MapMatcher(
    network=net,
    core_num=2,  # Use 2 CPU cores
    # ... other parameters
)
```

Multiprocessing is most useful when the network is modest relative to available
memory. For very large GMNS networks, worker-local copies of the NetworkX graph
and spatial index can make several workers slower than one.

### Large CSV (Memory-Safe Streaming)

For very large GPS files (for example, 100M+ rows), avoid loading all rows
into memory at once. Pass CSV path directly to `match(...)`.

In streaming mode, the matcher internally hashes `journey_id` into temporary
partitions first, then processes partition files. This keeps the same
`journey_id` in one partition without requiring a global CSV sort.

```python
matcher = m4g.MapMatcher(
    network=net,
    time_field='local_time',
    time_format='%Y-%m-%dT%H:%M:%S%z',
    out_dir='output',
    result_file='matched_result.csv',
    route_file='matched_route.csv',
    core_num=1,
)

matcher.match('data.csv')
```

### Custom Field Names

```python
matcher = m4g.MapMatcher(
    network=net,
    agent_field='vehicle_id',  # Custom trajectory ID field
    lng_field='lon',           # Custom longitude field
    lat_field='lat',            # Custom latitude field
    time_field='timestamp',     # Custom time field
    # ... other parameters
)
```

### Extra Fields

Keep additional fields from input GPS data in the output:

```python
matcher = m4g.MapMatcher(
    network=net,
    extra_fields=['vehicle_type', 'driver_id', 'trip_purpose'],
    # ... other parameters
)
```

## Requirements

- Python >= 3.8
- numpy >= 1.20.0
- pandas >= 1.3.0
- shapely >= 2.0.0
- geopandas >= 0.10.0
- networkx >= 2.6.0
- tqdm >= 4.60.0

## Citation

If you use this tool in your research, please cite this tool.

**Suggested citation:**

> Liu, Y., & Zhou, X. (2026). *MapMatcher4GMNS: A high-performance map
> matching tool for GMNS networks* (Version 0.2.1) [Computer software].
> https://github.com/yajunliu99/mapmatcher4gmns

**BibTeX:**

```bibtex
@software{liu_zhou_mapmatcher4gmns_2026,
  author  = {Liu, Yajun and Zhou, Xuesong (Simon)},
  title   = {MapMatcher4GMNS: A High-Performance Map Matching Tool for GMNS Networks},
  year    = {2026},
  version = {0.2.1},
  url     = {https://github.com/yajunliu99/mapmatcher4gmns},
  note    = {Python software package}
}
```

## Authors

- Yajun Liu (`yajunliu@asu.edu`)
- Xuesong (Simon) Zhou (`xzhou74@asu.edu`)

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Acknowledgments

This package was inspired by and references the excellent work of the [TrackIt (GoTrackIt)](https://github.com/zdsjjtTLG/TrackIt) project. We are grateful for their contributions to the open-source map matching community and their innovative approach to HMM-based map matching algorithms.

### References

- **TrackIt/GoTrackIt**: A comprehensive map matching Python package based on Hidden Markov Model (HMM)
  - GitHub: https://github.com/zdsjjtTLG/TrackIt
  - Documentation: https://gotrackit.readthedocs.io/
  - Developed by: TangKai and contributors at Hangzhou Zecheng Data Technology Co., Ltd.

This tool is designed to work with the General Modeling Network Specification (GMNS) format, supporting transportation network analysis and GPS trajectory processing.

## Support

For questions, issues, or feature requests, please use the
[GitHub repository](https://github.com/yajunliu99/mapmatcher4gmns) or contact
Yajun Liu (`yajunliu@asu.edu`) and Xuesong (Simon) Zhou (`xzhou74@asu.edu`).
