| Name | fastmm JSON |
| Version |
0.1.2
JSON |
| download |
| home_page | None |
| Summary | Fast Map Matching - High-performance map matching library |
| upload_time | 2025-10-24 00:38:42 |
| maintainer | None |
| docs_url | None |
| author | kodonnell |
| requires_python | >=3.8 |
| license | None |
| keywords |
map-matching
gps
trajectory
routing
gis
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# fastmm
fastmm is a fast (C++) map-matching library for python with no dependencies, and the ability to interpolate time on the match, not just position.
It's based on a desire to map match a lot of vehicle trace data quickly, without the infrastructure to spin up OSRM / Valhalla. (And this is probably faster as there's no IPC ... ?)
It is based on <https://github.com/cyang-kth/fmm> but updated to:
- Remove GDAL/OGR dependencies - networks are created programmatically from Python
- Include Python helper classes for automatic trajectory splitting and time interpolation
- Be buildable on Windows/Linux/Mac with modern tooling
- Focus on Python packaging with distributable wheels
- Remove STMatch - we'll focus on FMM for now
**Status:**
- [ ] Tested ... = )
- [ ] MapMatcher helper class with auto-splitting and time interpolation
- [x] FASTMM algorithm working
- [x] Python API for network creation and matching
- [x] Windows, linux, and macOS wheel builds
## Installation
```bash
pip install fastmm
```
## TODO
- Bring in extra python code.
- Get test working in python.
- If not found in UBODT, instead of bailing, do a normal djikstra lookup.
- Need to check reverse tolerance - on our edges, they're all directed, so we probably shouldn't allow reversing. This causes errors when we're parsing - if you reverse on the same edge, the geometry gets flipped (I think - line = ALGORITHM::cutoffseg_unique(e0.geom, start_offset, end_offset); goes backward?), which then messes with our python post-processing of associating time as the segment start/stop are now the edge stop/start, not the other way round. We could add a reversed flag to the edge? That would help. For now, just don't have a reverse tolerance.
- Could move the journey splitting (e.g. when unmatched candidate or points too far apart) into the C++ code here. Would be more optimal as a) C++, and b) don't need to repeat candidate lookup etc.
- Improve serialization of UBODT to be cross-platform.
- Specify versions for build libs (e.g. cibuildwheel).
### Custom costs
To implement, just update the NetworkGraph construction, and set g[e].length = edge.cost (where you read edge in from the read_ogr_file etc.). The change transition probability to
```
// double tp = TransitionGraph::calculate_transition_probability(shortest_path_distance, euclidean_distance);
double tp = exp(-0.01 * shortest_path_distance); //
```
Seems to work:
- set cost to 1 and it minimizes the number of edges
- set cost to edge length, and gives similar result (as both the methods minimise distance - only differences is the previous method is using euclidean distance between candidates maybe, not matched points? would only matter with dense points).
- can prevent some edges being used by manually bumping up their cost (tested on one road by cost *= 100 for those edges - worked, it avoided those edges).
- Untested:
- time based: if we have speed on all edges, set cost = distance / speed.
- use road hierachy or similar - prioritise main highways. More useful for addinsight.
Raw data
{
"_id": null,
"home_page": null,
"name": "fastmm",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "map-matching, gps, trajectory, routing, GIS",
"author": "kodonnell",
"author_email": null,
"download_url": null,
"platform": null,
"description": "# fastmm\n\nfastmm is a fast (C++) map-matching library for python with no dependencies, and the ability to interpolate time on the match, not just position.\n\nIt's based on a desire to map match a lot of vehicle trace data quickly, without the infrastructure to spin up OSRM / Valhalla. (And this is probably faster as there's no IPC ... ?)\n\nIt is based on <https://github.com/cyang-kth/fmm> but updated to:\n\n- Remove GDAL/OGR dependencies - networks are created programmatically from Python\n- Include Python helper classes for automatic trajectory splitting and time interpolation\n- Be buildable on Windows/Linux/Mac with modern tooling\n- Focus on Python packaging with distributable wheels\n- Remove STMatch - we'll focus on FMM for now\n\n**Status:**\n\n- [ ] Tested ... = )\n- [ ] MapMatcher helper class with auto-splitting and time interpolation\n- [x] FASTMM algorithm working\n- [x] Python API for network creation and matching\n- [x] Windows, linux, and macOS wheel builds\n\n\n## Installation\n\n```bash\npip install fastmm\n```\n\n## TODO\n\n- Bring in extra python code.\n- Get test working in python.\n- If not found in UBODT, instead of bailing, do a normal djikstra lookup.\n- Need to check reverse tolerance - on our edges, they're all directed, so we probably shouldn't allow reversing. This causes errors when we're parsing - if you reverse on the same edge, the geometry gets flipped (I think - line = ALGORITHM::cutoffseg_unique(e0.geom, start_offset, end_offset); goes backward?), which then messes with our python post-processing of associating time as the segment start/stop are now the edge stop/start, not the other way round. We could add a reversed flag to the edge? That would help. For now, just don't have a reverse tolerance.\n- Could move the journey splitting (e.g. when unmatched candidate or points too far apart) into the C++ code here. Would be more optimal as a) C++, and b) don't need to repeat candidate lookup etc.\n- Improve serialization of UBODT to be cross-platform.\n- Specify versions for build libs (e.g. cibuildwheel).\n\n### Custom costs\n\nTo implement, just update the NetworkGraph construction, and set g[e].length = edge.cost (where you read edge in from the read_ogr_file etc.). The change transition probability to\n\n```\n// double tp = TransitionGraph::calculate_transition_probability(shortest_path_distance, euclidean_distance);\ndouble tp = exp(-0.01 * shortest_path_distance); //\n```\n\n Seems to work:\n\n- set cost to 1 and it minimizes the number of edges\n- set cost to edge length, and gives similar result (as both the methods minimise distance - only differences is the previous method is using euclidean distance between candidates maybe, not matched points? would only matter with dense points).\n- can prevent some edges being used by manually bumping up their cost (tested on one road by cost *= 100 for those edges - worked, it avoided those edges).\n- Untested:\n - time based: if we have speed on all edges, set cost = distance / speed.\n - use road hierachy or similar - prioritise main highways. More useful for addinsight.\n",
"bugtrack_url": null,
"license": null,
"summary": "Fast Map Matching - High-performance map matching library",
"version": "0.1.2",
"project_urls": {
"Documentation": "https://github.com/kodonnell/fastmm",
"Homepage": "https://github.com/kodonnell/fastmm",
"Repository": "https://github.com/kodonnell/fastmm"
},
"split_keywords": [
"map-matching",
" gps",
" trajectory",
" routing",
" gis"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "47e66abe7ab66adfd31d6cd5c3a64a09ec81f007284c2503e99b0e63ce5744a1",
"md5": "d0280219e4bb4629ea8ec93baef5e7e2",
"sha256": "63948bbbc35136d8154dca44b56472ea126869dd27a817e8ff7a5444a82aa44b"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp310-cp310-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "d0280219e4bb4629ea8ec93baef5e7e2",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 655970,
"upload_time": "2025-10-24T00:38:42",
"upload_time_iso_8601": "2025-10-24T00:38:42.931558Z",
"url": "https://files.pythonhosted.org/packages/47/e6/6abe7ab66adfd31d6cd5c3a64a09ec81f007284c2503e99b0e63ce5744a1/fastmm-0.1.2-cp310-cp310-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4af226402b6a4c6f8248ebd4de842f07f8eb85b7dd3874e04d3d3d8e57f3a84c",
"md5": "79ee500940e084567e15e0af3ef47ba2",
"sha256": "09c21a7625fe3233cecd4bd600e2fffd09f4d91c5f1aa044cf0c59e7e7d04d87"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp310-cp310-manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "79ee500940e084567e15e0af3ef47ba2",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 652894,
"upload_time": "2025-10-24T00:38:44",
"upload_time_iso_8601": "2025-10-24T00:38:44.789144Z",
"url": "https://files.pythonhosted.org/packages/4a/f2/26402b6a4c6f8248ebd4de842f07f8eb85b7dd3874e04d3d3d8e57f3a84c/fastmm-0.1.2-cp310-cp310-manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "9eba950419db2908aafb89c0c90c20f7fdafe8a7b1fd5012591ba1f18a9d6f13",
"md5": "240a7dc67c6b70f7b05a0927720e85c0",
"sha256": "5add7de78bb97b6e2f7f4727f39d9a4d62c515a5eee17724a390bd76056b4df6"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp310-cp310-win_amd64.whl",
"has_sig": false,
"md5_digest": "240a7dc67c6b70f7b05a0927720e85c0",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 707803,
"upload_time": "2025-10-24T00:38:46",
"upload_time_iso_8601": "2025-10-24T00:38:46.436205Z",
"url": "https://files.pythonhosted.org/packages/9e/ba/950419db2908aafb89c0c90c20f7fdafe8a7b1fd5012591ba1f18a9d6f13/fastmm-0.1.2-cp310-cp310-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "172642ffbaf4f6f16102f299505aec304ac9c364825efd2666d05bea427762a1",
"md5": "e65b4c1514e47f7a2886a63f6c44f4f6",
"sha256": "7fba64e35d0fbb43b59f2878afeff627526ec9c873b988d11917da1c373cb7de"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp311-cp311-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "e65b4c1514e47f7a2886a63f6c44f4f6",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.8",
"size": 657348,
"upload_time": "2025-10-24T00:38:47",
"upload_time_iso_8601": "2025-10-24T00:38:47.952763Z",
"url": "https://files.pythonhosted.org/packages/17/26/42ffbaf4f6f16102f299505aec304ac9c364825efd2666d05bea427762a1/fastmm-0.1.2-cp311-cp311-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e72e1fc16973b62026b03667687b48deca5209c9de238a06d4b1500e36d13365",
"md5": "b40569abdf2161b451cdeb879dba7c16",
"sha256": "b0e3c9d5a55ca70a2b115ea924cdc81d11bad086beffbc707522b44950e0e099"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp311-cp311-manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "b40569abdf2161b451cdeb879dba7c16",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.8",
"size": 654556,
"upload_time": "2025-10-24T00:38:49",
"upload_time_iso_8601": "2025-10-24T00:38:49.387252Z",
"url": "https://files.pythonhosted.org/packages/e7/2e/1fc16973b62026b03667687b48deca5209c9de238a06d4b1500e36d13365/fastmm-0.1.2-cp311-cp311-manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "2a9d571fbcf776c1ee277dca16babc99bb726ee5a2bd627df45cd1ab564929c0",
"md5": "f4a418dc0e1952878633e74a555b6d4e",
"sha256": "790d565e92d5c283d8869963f34ffba6cb8d17329fbbe52e1698291988e1ae35"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp311-cp311-win_amd64.whl",
"has_sig": false,
"md5_digest": "f4a418dc0e1952878633e74a555b6d4e",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.8",
"size": 708532,
"upload_time": "2025-10-24T00:38:51",
"upload_time_iso_8601": "2025-10-24T00:38:51.616551Z",
"url": "https://files.pythonhosted.org/packages/2a/9d/571fbcf776c1ee277dca16babc99bb726ee5a2bd627df45cd1ab564929c0/fastmm-0.1.2-cp311-cp311-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "a4d017c0b7cfc6e387ff57835c11968b45c9346f70cc15b9c77b62fab604b409",
"md5": "b2e5080a308595d840cbc004bd1b9cde",
"sha256": "5a2da55214b8cd677949bc7c716b077456995828ec3a5644079be44740919dd6"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp312-cp312-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "b2e5080a308595d840cbc004bd1b9cde",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.8",
"size": 657002,
"upload_time": "2025-10-24T00:38:53",
"upload_time_iso_8601": "2025-10-24T00:38:53.388357Z",
"url": "https://files.pythonhosted.org/packages/a4/d0/17c0b7cfc6e387ff57835c11968b45c9346f70cc15b9c77b62fab604b409/fastmm-0.1.2-cp312-cp312-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c56796fc8475cfbba260cc9c4ee829f072d5d0b28cca8ed8b7f63b13b5a46c96",
"md5": "3a82ae5c929138071cd49eca85e708a2",
"sha256": "3d13ab9e7a4d9ee3973cd8195570283de0a366c83540cb201ed3ce48d2edaaaa"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp312-cp312-manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "3a82ae5c929138071cd49eca85e708a2",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.8",
"size": 653671,
"upload_time": "2025-10-24T00:38:54",
"upload_time_iso_8601": "2025-10-24T00:38:54.875539Z",
"url": "https://files.pythonhosted.org/packages/c5/67/96fc8475cfbba260cc9c4ee829f072d5d0b28cca8ed8b7f63b13b5a46c96/fastmm-0.1.2-cp312-cp312-manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "efdc2cb79b6c420a0cfc29f555adabf98fd105842d4636ec6ba30fbd93e54409",
"md5": "c2756af7d33e24afb5b966deb0cd0c94",
"sha256": "3eeec820d4ba2ca8d9dcc99b464d1f7b09b04e2b1d6311d59634ccdd1b802843"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp312-cp312-win_amd64.whl",
"has_sig": false,
"md5_digest": "c2756af7d33e24afb5b966deb0cd0c94",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.8",
"size": 709220,
"upload_time": "2025-10-24T00:38:56",
"upload_time_iso_8601": "2025-10-24T00:38:56.226951Z",
"url": "https://files.pythonhosted.org/packages/ef/dc/2cb79b6c420a0cfc29f555adabf98fd105842d4636ec6ba30fbd93e54409/fastmm-0.1.2-cp312-cp312-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "3fe05524707103e09ecbc925c1ffb3d78e5ea44672683f9186f7ecca5c488a69",
"md5": "ece162f8e1a5f05f7095e1e3b64b99ee",
"sha256": "e2585f3bebc46326da87512b3c2e1a69fb6c57efed93a8d0e87f8baaa18bc6a0"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp38-cp38-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "ece162f8e1a5f05f7095e1e3b64b99ee",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 655879,
"upload_time": "2025-10-24T00:38:57",
"upload_time_iso_8601": "2025-10-24T00:38:57.507511Z",
"url": "https://files.pythonhosted.org/packages/3f/e0/5524707103e09ecbc925c1ffb3d78e5ea44672683f9186f7ecca5c488a69/fastmm-0.1.2-cp38-cp38-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "71bb129fbbee0b9448c5ae9a1b82cd699efe3a3dc84ded1ba654579cdd2db29e",
"md5": "bd8947186a73ef518f0567b72ea261b2",
"sha256": "001c75d9eace362dabea50f48a18706b73cb0213d6337b6d1530a9368b59bb84"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp38-cp38-manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "bd8947186a73ef518f0567b72ea261b2",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 653838,
"upload_time": "2025-10-24T00:38:58",
"upload_time_iso_8601": "2025-10-24T00:38:58.855024Z",
"url": "https://files.pythonhosted.org/packages/71/bb/129fbbee0b9448c5ae9a1b82cd699efe3a3dc84ded1ba654579cdd2db29e/fastmm-0.1.2-cp38-cp38-manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "0278ce87c34c97991ef42f2f90c3d98cd1b9db92acc8208f36a5b75010c39b66",
"md5": "b034513d767bc6479fcf1817333f5d74",
"sha256": "e189a91f19912e59b5c70eede0e10e4776e29b3d335012577216043c73c16d27"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp38-cp38-win_amd64.whl",
"has_sig": false,
"md5_digest": "b034513d767bc6479fcf1817333f5d74",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 718056,
"upload_time": "2025-10-24T00:39:00",
"upload_time_iso_8601": "2025-10-24T00:39:00.377386Z",
"url": "https://files.pythonhosted.org/packages/02/78/ce87c34c97991ef42f2f90c3d98cd1b9db92acc8208f36a5b75010c39b66/fastmm-0.1.2-cp38-cp38-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "b7e71da6f3be8b1f25b0b104b39d5491a88f367d218168ef9763161c16b38f63",
"md5": "fa839bc086ca6845cdb7a3ce7ded43f6",
"sha256": "5a9fe3a579fd43421f8084c8a3156f52705b89577aa490edd07991420e9999c3"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp39-cp39-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "fa839bc086ca6845cdb7a3ce7ded43f6",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.8",
"size": 656062,
"upload_time": "2025-10-24T00:39:02",
"upload_time_iso_8601": "2025-10-24T00:39:02.127413Z",
"url": "https://files.pythonhosted.org/packages/b7/e7/1da6f3be8b1f25b0b104b39d5491a88f367d218168ef9763161c16b38f63/fastmm-0.1.2-cp39-cp39-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "0104b286434ad6adea3f5f5b8636aff0ea458ea68e0034e0e506f992b2495a70",
"md5": "961acfabb2ef4cc44546e63c7c863b17",
"sha256": "0ea801abfdf4cf0c0896c0f835288321651ec48791f4ad9a3470e12e37fc03af"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp39-cp39-manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "961acfabb2ef4cc44546e63c7c863b17",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.8",
"size": 654257,
"upload_time": "2025-10-24T00:39:03",
"upload_time_iso_8601": "2025-10-24T00:39:03.797752Z",
"url": "https://files.pythonhosted.org/packages/01/04/b286434ad6adea3f5f5b8636aff0ea458ea68e0034e0e506f992b2495a70/fastmm-0.1.2-cp39-cp39-manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "50efdf4dafca166f1f358f503f0e7bfba4b0833af173a73f91ee7735454166e1",
"md5": "4e24c39d686c836509934d1b1d555ee4",
"sha256": "001760fe0314ae174e89ce0d85c7baad4a045386a14be5a3043a8ee2eb63c768"
},
"downloads": -1,
"filename": "fastmm-0.1.2-cp39-cp39-win_amd64.whl",
"has_sig": false,
"md5_digest": "4e24c39d686c836509934d1b1d555ee4",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.8",
"size": 708126,
"upload_time": "2025-10-24T00:39:05",
"upload_time_iso_8601": "2025-10-24T00:39:05.130312Z",
"url": "https://files.pythonhosted.org/packages/50/ef/df4dafca166f1f358f503f0e7bfba4b0833af173a73f91ee7735454166e1/fastmm-0.1.2-cp39-cp39-win_amd64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-24 00:38:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "kodonnell",
"github_project": "fastmm",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "fastmm"
}