Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
362 commits
Select commit Hold shift + click to select a range
566f735
Add inheritance for the pipe ramming edges
JelmarVersleijen Aug 28, 2025
278282b
Add crossings to the graph, add some template tests
JelmarVersleijen Aug 28, 2025
20950f1
Move crossing settings back to the class
JelmarVersleijen Aug 28, 2025
7b36007
Structure it so we have a distinction between segments/junction cross…
JelmarVersleijen Aug 28, 2025
7840f98
Unittest for testing the edge generator
djessedirckx Sep 4, 2025
5e8cb96
Introduce factory fixture for single criterion vectors
djessedirckx Sep 4, 2025
98ecd23
Make sure all values are within bounds of grid
djessedirckx Sep 4, 2025
45bcf1f
Test for creating full graph and asserting suitability values on samp…
djessedirckx Sep 4, 2025
f52efed
Merge branch 'feature/pipe_ramming_model' of https://github.com/allia…
djessedirckx Sep 4, 2025
97b384b
Test for asserting suitability values for the single criterion graph
djessedirckx Sep 11, 2025
50caa06
Create fixture for multiple criteria vectors
djessedirckx Sep 11, 2025
d863757
Send only the raster groups to the hexagonbuilder instead of the comp…
djessedirckx Sep 11, 2025
b150255
Change max and min node values to values that are more in line with s…
djessedirckx Sep 11, 2025
06503e3
Integration test for hexagon with multi criteria vectors
djessedirckx Sep 11, 2025
80c4786
Restructured integration test for hexagon grids
djessedirckx Sep 11, 2025
0ee257a
Add logic for getting crossings for long segments. Add thoughts prior…
JelmarVersleijen Sep 11, 2025
e21b640
Merge remote-tracking branch 'origin/feature/pipe_ramming_model' into…
JelmarVersleijen Sep 11, 2025
7b0e360
Add function for extending linestrings in both directions
JelmarVersleijen Sep 18, 2025
9d96790
Start reusing logic from the junctions splitting for street segment c…
JelmarVersleijen Sep 18, 2025
215c515
Add polygon splitter
JelmarVersleijen Sep 23, 2025
2d5ec17
Add enums for ramming origin
JelmarVersleijen Sep 23, 2025
bb39f70
major refactor, re-use functions for junctions/segment rammings
JelmarVersleijen Sep 23, 2025
953cb46
Fix bug in splitting street segments which did not result in enough s…
JelmarVersleijen Sep 24, 2025
5872486
Add some tests for all the new geo utils
JelmarVersleijen Sep 25, 2025
a9473a1
Remove confusing unused option
JelmarVersleijen Sep 25, 2025
aca9658
Add option to clip graph to polygon, useful for the pickled graph
JelmarVersleijen Sep 25, 2025
976f4d2
Fix mcda bug when there are only 1 type of obstacles as input gdfs
JelmarVersleijen Sep 25, 2025
3ca378f
Make the tests use smaller project areas
JelmarVersleijen Sep 25, 2025
bf78f30
Return empty gdf on empty graph
JelmarVersleijen Sep 26, 2025
38fbb8f
Add skip marker for OSM downloader
JelmarVersleijen Sep 26, 2025
093bb9b
Add the benchmark routes as separate dataclass for reusability
JelmarVersleijen Sep 26, 2025
f5ae3f3
Mypy stuff
JelmarVersleijen Sep 26, 2025
db9be58
Initial setup multilayer routing
JelmarVersleijen Sep 26, 2025
107034a
Start adding some "clean" examples
JelmarVersleijen Sep 26, 2025
ca65dcd
Add multilayer config to settings
JelmarVersleijen Oct 2, 2025
33cd06b
Add clean example of pipe ramming for a street segment
JelmarVersleijen Oct 2, 2025
37c8b3d
Correct angle calculator to allow for 0 degree angles
JelmarVersleijen Oct 2, 2025
f15c05a
Add clean examples for pipe ramming, share some generic asserts
JelmarVersleijen Oct 2, 2025
f92cc85
Disable test until fix
JelmarVersleijen Oct 16, 2025
2216d23
mask cost surface nodes in junction area correctly
JelmarVersleijen Oct 16, 2025
092c97c
add theory examples for junction degree 3/4
JelmarVersleijen Oct 16, 2025
d6850ab
match vanilla mcda settings for multilayer hex
JelmarVersleijen Oct 16, 2025
cf56950
add simple degree 4
JelmarVersleijen Oct 16, 2025
4fd0085
Add initial version for complex street segment
JelmarVersleijen Oct 24, 2025
02c3355
Fix linestrings with > 2 points. Fix selection of nearest crossing point
JelmarVersleijen Oct 24, 2025
5ed0d37
Remove valid input
JelmarVersleijen Oct 30, 2025
dc4262d
Ensure pairs are actually pairs when creating linestrings between sel…
JelmarVersleijen Oct 30, 2025
c9425fe
Add test for the pair validation
JelmarVersleijen Oct 30, 2025
72847c4
Enable broken test again
JelmarVersleijen Oct 30, 2025
3fa1e76
Start adding support for differences in elevation
JelmarVersleijen Nov 6, 2025
91a95c8
Make it a bit more robust
JelmarVersleijen Nov 6, 2025
e41ced0
Save height levels with a default
JelmarVersleijen Nov 6, 2025
5353850
Skip benchmark tests by default
JelmarVersleijen Nov 13, 2025
16d53b8
Some doodles before actual implementation
JelmarVersleijen Nov 13, 2025
9c02fdf
Add temp dataclass during testing
JelmarVersleijen Nov 13, 2025
1a26b2c
Move stuff to the graph merger
JelmarVersleijen Nov 13, 2025
65c1a3f
Automatically init the length property of edges
JelmarVersleijen Nov 20, 2025
edc6516
Plot the edges as well
JelmarVersleijen Nov 27, 2025
51478f4
Continue here for solving the node edge bug
JelmarVersleijen Nov 27, 2025
55a386d
Set default height as input
JelmarVersleijen Dec 4, 2025
0f696fb
Add some more validators and tests
JelmarVersleijen Dec 4, 2025
1179817
Add inspiration for smoothing
JelmarVersleijen Dec 24, 2025
4941bc2
Fix order of coordinates on numpy init
djessedirckx Jan 8, 2026
f0704cc
Use correct min values
djessedirckx Jan 8, 2026
3be9246
Fixed spacing tests after flipping hexagon matrix
djessedirckx Jan 8, 2026
5ffd3de
Merge branch 'feature/pipe_ramming_model' of https://github.com/allia…
djessedirckx Jan 8, 2026
2268303
Update packages
djessedirckx Jan 8, 2026
182662d
Updated and ran pre-commit dependencies
djessedirckx Jan 8, 2026
708bfc8
Use new ruff check id
djessedirckx Jan 8, 2026
286ccce
Started implementing boxes for hexagon generator
djessedirckx Jan 8, 2026
14b0ec1
Generate matrix blocks
djessedirckx Jan 15, 2026
bdbbe70
Convert each matrix to a geodataframe as part of the iterator
djessedirckx Jan 15, 2026
ba70a87
Handle case where the block size is >= the bounding box
djessedirckx Jan 15, 2026
1a355c8
Add nodes to the graph in blocks
djessedirckx Jan 15, 2026
022acc0
Generate edges in batches as well
djessedirckx Jan 15, 2026
3b296da
Fix deprecation of concatenating empty dataframes
djessedirckx Jan 22, 2026
0e5c6f7
Add timers for debugging
djessedirckx Jan 22, 2026
94b893a
Add polars
djessedirckx Jan 22, 2026
8a76f2c
Apply group and suitability value aggregation in polars
djessedirckx Jan 22, 2026
010f654
Perform suitability value aggregation using Polars
djessedirckx Jan 22, 2026
1d8645d
Update grid constructor suitability value tests
djessedirckx Jan 22, 2026
2b170c4
Clipping in suitability values
djessedirckx Jan 22, 2026
fe8f4c6
Compute left/rigth q and r values using polars
djessedirckx Jan 29, 2026
899dbae
Compute edge weights using polars
djessedirckx Jan 29, 2026
c33d36e
Generate edge line strings using polars
djessedirckx Jan 29, 2026
21b377f
Strip geometry and axial coordinates from nodes to reduce memory usage
djessedirckx Jan 29, 2026
2c85a61
Only create graph structure
djessedirckx Feb 5, 2026
f0ac9c7
Keep track of previous and current row to reduce memory of lookup table
djessedirckx Feb 5, 2026
7d94f4b
Calculate suitability values for edges (not so fast yet)
djessedirckx Feb 5, 2026
8e639fb
First implementation of HexagonGraph
djessedirckx Feb 12, 2026
d13fb1d
Yield final column is True in case there is only one block
djessedirckx Feb 19, 2026
d678c34
Only store block edges to save memory
djessedirckx Feb 19, 2026
ca8ee55
Compute edges using pandas instead of dicts (still quite slow)
djessedirckx Feb 19, 2026
96d6626
Mark all edges that are near an osm edge
djessedirckx Feb 19, 2026
43492bc
Remove custom graph, as it is not used
djessedirckx Feb 26, 2026
7130314
Remove osm edge marking from hexagon builder
djessedirckx Feb 26, 2026
9b52791
Construct gdf of all nodes in the hexagon
djessedirckx Feb 26, 2026
45c042c
Remove redundant copy in edge generation
djessedirckx Feb 26, 2026
7ec10df
Remove concatenation of neighbour candidates
djessedirckx Feb 26, 2026
1b09a91
Use list comprehension instead of itertuples for faster edge generation
djessedirckx Feb 26, 2026
dae2fbd
Remove old dataclass for node information
djessedirckx Feb 26, 2026
7efef03
Read hexagon nodes directly from the dataframe
djessedirckx Feb 26, 2026
7a516d0
Update piperamming tests with new interface
djessedirckx Feb 26, 2026
3837450
Decrease number of blocks to check
djessedirckx Feb 26, 2026
5c24c15
Weight does not exist on the node anymore
djessedirckx Feb 26, 2026
ab73a57
Extract filtering of coordinates to separate functions
djessedirckx Feb 26, 2026
14d5a05
Add a few inline comments
djessedirckx Feb 26, 2026
2a77091
Simplified project area fixture
djessedirckx Mar 5, 2026
9104ddc
Merge branch 'main' into feature/pipe_ramming_model
JelmarVersleijen Mar 5, 2026
7742722
Pass block_size parameter to hexagon graph builder in piperamming
djessedirckx Mar 5, 2026
b0933ad
Merge remote-tracking branch 'origin/feature/pipe_ramming_model' into…
JelmarVersleijen Mar 5, 2026
f85fa0b
Use dataclass again to simplify weights in dijkstra downstream
djessedirckx Mar 5, 2026
98d2844
reset debug level
JelmarVersleijen Mar 5, 2026
90239a4
Fix argument orders after merge
JelmarVersleijen Mar 5, 2026
84615a8
Small improvements / type hints. Use geopandas instead of fiona
JelmarVersleijen Mar 5, 2026
193c33d
Add pyarrow
JelmarVersleijen Mar 5, 2026
3459a35
Fix edge finding of block coordinates
djessedirckx Mar 5, 2026
7b33ce6
Only concatenate preprocessed vectors once
djessedirckx Mar 5, 2026
5189fd5
Add costs and length
JelmarVersleijen Mar 5, 2026
cdb5eee
Expand tests with expected crossings and cost
JelmarVersleijen Mar 5, 2026
85178ae
Make it a bit more flexible for gathering stats
JelmarVersleijen Mar 5, 2026
849b4c1
Use dataframe instead of dict with dataclasses for edge classification
djessedirckx Mar 12, 2026
aba1f1d
Remove comments
JelmarVersleijen Mar 12, 2026
7cbf20b
Add skip markers for the integration tests
JelmarVersleijen Mar 12, 2026
4258a0d
Use polars in grid builder instead of numpy to prevent copying and co…
djessedirckx Mar 12, 2026
20eb09d
Avoid unnecessary reset geopackages
JelmarVersleijen Mar 12, 2026
2ef6608
Use polars for edge generation
djessedirckx Mar 12, 2026
37ed7d3
Use polars for edge coordinate extraction
djessedirckx Mar 12, 2026
79f7fe6
Stop using dataclass in the hexagon edges
djessedirckx Mar 12, 2026
68694ed
Fix bug with missing edges cross-blocks in the hexagon
djessedirckx Mar 12, 2026
cb9ad63
Added temporary linestring debugger
djessedirckx Mar 12, 2026
8f554da
Merge branch 'feature/pipe_ramming_model' into feature/hexagon_perfor…
djessedirckx Mar 18, 2026
6983f04
Add function to determine the edge weight of an Hexagon based on havi…
djessedirckx Mar 18, 2026
0b37651
Get weighted edge sum and edge length from path
djessedirckx Mar 19, 2026
84dafe1
Cast coordinates to float32 as float64 is not required here
djessedirckx Mar 19, 2026
28c4322
Update TestConstructHexagonalGridForBoundingBox & TestAssignSuitabili…
djessedirckx Mar 19, 2026
00352e9
Updated axial conversion test
djessedirckx Mar 19, 2026
49d788d
Add centerline function, refactor merge graph setup
JelmarVersleijen Mar 19, 2026
0472945
Determine edge nodes based on coordinates instead of axial values
djessedirckx Mar 19, 2026
97302b4
Add function for creating perpendicular lines
JelmarVersleijen Mar 19, 2026
a17b39c
Remove assert for warning
JelmarVersleijen Mar 19, 2026
2c2262c
Add logic for filtering points to connect the height levels on
JelmarVersleijen Mar 19, 2026
2c85ba2
Correct coordinate order
djessedirckx Mar 20, 2026
d12121a
Combine edge validation and weight computation into a single query to…
djessedirckx Mar 23, 2026
b518f99
Remove redundant edge markings for debugging
djessedirckx Mar 23, 2026
d182d72
Generate edges at once to prevent loop
djessedirckx Mar 23, 2026
94952c1
Compute potential edges at once + added documentation
djessedirckx Mar 23, 2026
a01d4b4
Helper function to convert all hexagon edges to a geodataframe
djessedirckx Mar 24, 2026
7d94547
Use new hexagon converter method
djessedirckx Mar 24, 2026
e7e6268
Removed accidentally added offset and include piperamming in edge info
djessedirckx Mar 24, 2026
b97bde5
Update expected route length
djessedirckx Mar 24, 2026
9e7b7bd
Merge branch 'feature/pipe_ramming_model' into feature/hexagon_perfor…
djessedirckx Mar 24, 2026
7af8040
Get cost surface nodes in piperamming test
djessedirckx Mar 24, 2026
85d2352
Fix incorrect osm_id in dataclass + update remaining piperamming tests
djessedirckx Mar 24, 2026
1466ef0
Clean up graph datastructures
djessedirckx Mar 24, 2026
85267ee
Add more properties to the path
djessedirckx Mar 24, 2026
39a71b6
Move multilayer main to root of the repo
djessedirckx Mar 24, 2026
735d31e
Make sure the current row edge coordinates are emptied when going to …
djessedirckx Mar 24, 2026
aefa781
Only check relevant top coordinates, store data as a tuple on the nod…
djessedirckx Mar 25, 2026
436358b
Set edge weights as the sum of ints instead of division of floats
djessedirckx Mar 26, 2026
3be6a26
Store node information in numpy structured array
djessedirckx Mar 26, 2026
7270604
Convert numpy structured array to geodataframe for all present nodes
djessedirckx Mar 26, 2026
e46584f
Adjust edge weights in graph composer to new setup
djessedirckx Mar 26, 2026
0c4c21d
Remove state from hexagon construction classes and add some docstrings
djessedirckx Mar 26, 2026
a60caa9
Use round to compute crossing weight
djessedirckx Mar 26, 2026
8d039e6
Adjust multilayer route weight computation to new edge weights and up…
djessedirckx Mar 26, 2026
7c41334
Add multiline parser for preparing entrypoints
JelmarVersleijen Mar 26, 2026
142c5cb
Refine entrypoint filtering, add tests
JelmarVersleijen Mar 26, 2026
9f0c0bd
Correct typing of edge generator
djessedirckx Apr 2, 2026
b8352e8
Test edge generator without previous blocks
djessedirckx Apr 2, 2026
7c14e76
Added test when working with previous edges
djessedirckx Apr 2, 2026
7ab44fa
Add debug writing to tests again
djessedirckx Apr 2, 2026
6d26675
Previous block only and previous row only unittests for edge generation
djessedirckx Apr 2, 2026
8cb68ae
Add edges as tuples
djessedirckx Apr 2, 2026
ae993de
Fix bug in axial conversion that causes problems when using hexagon s…
djessedirckx Apr 2, 2026
cb41801
Update integration tests for HexagonGraphBuilder
djessedirckx Apr 2, 2026
1da27b4
Add hexagon size to self, make Dijkstra work with distance to line
JelmarVersleijen Apr 2, 2026
4057e73
Remove old hexagon graph converter method
djessedirckx Apr 2, 2026
4d38d20
First attempt to use new hexagon structure in graph composer and rout…
djessedirckx Apr 2, 2026
6f323be
Concat height level graphs
djessedirckx Apr 2, 2026
3405b00
Use hexagon size as input
JelmarVersleijen Apr 2, 2026
e9cc868
Set gpkg out only once
JelmarVersleijen Apr 3, 2026
c76e038
WIP smooth linestring constructor
JelmarVersleijen Apr 3, 2026
b826982
Merge branch 'main' into feature/pipe_ramming_model
JelmarVersleijen Apr 3, 2026
f0a4096
Update for security
JelmarVersleijen Apr 3, 2026
c3142ea
Fix connecting height level graphs on node ids
djessedirckx Apr 9, 2026
9a4630c
Reset index after concatenation and update get_weight function to ret…
djessedirckx Apr 9, 2026
fda5ebe
Temp fix for getting height level connection
djessedirckx Apr 9, 2026
9239226
Graph composer build tests working again, except connect height level…
djessedirckx Apr 9, 2026
c653455
Remove raster grid from grid constructor test
djessedirckx Apr 9, 2026
5e6c7f0
Set edge id on the graph again
djessedirckx Apr 9, 2026
f751938
Set edge id as tuple on the graph
djessedirckx Apr 9, 2026
85e3c33
Update get edge weight function
djessedirckx Apr 9, 2026
4f2b824
Update edge id using utils function
djessedirckx Apr 9, 2026
42573aa
Use same raster size for all tests
djessedirckx Apr 9, 2026
e28f193
Use hexagon size from grid builder instead of allowing a different size
djessedirckx Apr 9, 2026
230ed87
Use named tuples instead of regular tuples for better accessibility o…
djessedirckx Apr 9, 2026
b5e795e
Use new hexagon interface in multilayer main
djessedirckx Apr 9, 2026
d358f7c
Update conversion functions and set performance test as local test
djessedirckx Apr 9, 2026
60f192a
Remove custom weight function, as it is not required anymore
djessedirckx Apr 9, 2026
72dc517
Re-enable length zero connection heights test
djessedirckx Apr 9, 2026
d1f8a73
Merge branch 'feature/pipe_ramming_model' into feature/hexagon_perfor…
djessedirckx Apr 9, 2026
05903af
Add first version of multilayer routing
JelmarVersleijen Apr 9, 2026
1bd5caf
Remove old test stump
JelmarVersleijen Apr 9, 2026
50782a9
Add new version which looks further
JelmarVersleijen Apr 16, 2026
a486a2e
Handle pipe rammings in node skipping
JelmarVersleijen Apr 17, 2026
166adb8
Merge branch 'feature/pipe_ramming_model' into feature/hexagon_perfor…
djessedirckx Apr 23, 2026
39d5f7a
typo typehint
JelmarVersleijen Apr 23, 2026
cfadc09
Update edge retrieval
djessedirckx Apr 23, 2026
2ac01c3
Set node_id on node data again
djessedirckx Apr 23, 2026
5247f7e
Add missing reference to preprocessed vectors
djessedirckx Apr 23, 2026
65f17a3
Correct edge weights
djessedirckx Apr 23, 2026
96ee024
Add skip marker to performance test
djessedirckx Apr 23, 2026
b7ffb1b
Make astar work with node_df
djessedirckx Apr 23, 2026
19e9c70
Add helper function for getting the hexagon node geometry
djessedirckx Apr 23, 2026
6350e4b
Removed old todo
djessedirckx Apr 23, 2026
e846b0c
Replace process logger with tqdm
djessedirckx Apr 23, 2026
1378aad
Small refactoring of graph builder for better readability
djessedirckx Apr 23, 2026
67005f7
Add some more comments
djessedirckx Apr 23, 2026
a3ec2a1
Set node id property when adding height level nodes
djessedirckx Apr 23, 2026
d2fcf8c
Add minimum bending radius
JelmarVersleijen Apr 23, 2026
c031120
Patch straighten linestring process, add bezier curves and helpers
JelmarVersleijen Apr 23, 2026
6bb254b
Small improvements suggested by copilot PR agent
djessedirckx Apr 23, 2026
be57166
Use node id as index on node_gdf
djessedirckx Apr 23, 2026
c9f9a3e
Merge branch 'feature/pipe_ramming_model' into feature/hexagon_perfor…
djessedirckx Apr 23, 2026
16b22cb
Merge branch 'feature/pipe_ramming_model' into feature/hexagon_perfor…
djessedirckx Apr 23, 2026
208d303
Fix typo
djessedirckx Apr 23, 2026
75af4ce
Multiply node weights
djessedirckx Apr 23, 2026
229cf65
Patch shortcut cost function
JelmarVersleijen Apr 23, 2026
1e5af68
Remove unused param
JelmarVersleijen Apr 23, 2026
8fabe29
Update tqdm description
djessedirckx Apr 30, 2026
efda5e0
Added typer interface for running the multilayer engine
djessedirckx Apr 30, 2026
f709a5b
Readd performance_visuals.py
djessedirckx Apr 30, 2026
6ca78a9
Merge pull request #30 from alliander-opensource/feature/hexagon_perf…
djessedirckx Apr 30, 2026
78175e0
Add getter to benchmark route collection for easier access in typer i…
djessedirckx Apr 30, 2026
07d9116
Add function for running benchmark cases using multilayer main
djessedirckx Apr 30, 2026
f321e8f
Add first version of GHA workflow that runs on PR
djessedirckx Apr 30, 2026
cfcbf7d
Add some logger statements
JelmarVersleijen Apr 30, 2026
66f8adb
Merge remote-tracking branch 'origin/feature/pipe_ramming_model' into…
JelmarVersleijen Apr 30, 2026
1b08769
Run unit and integration tests
djessedirckx Apr 30, 2026
e99f0bf
Temp add workflow dispatch for testing
djessedirckx Apr 30, 2026
35a2cac
Install poetry using pipx instead of outdated dependency
djessedirckx Apr 30, 2026
fb988fa
Fix project case reference
djessedirckx Apr 30, 2026
3c1793b
Update pre-commit
djessedirckx Apr 30, 2026
6088657
Pre-commit fixes + rename of job
djessedirckx Apr 30, 2026
e9c85c8
Update project dependencies
djessedirckx Apr 30, 2026
1fd8adc
Merge pull request #32 from alliander-opensource/feature/add_gha_support
JelmarVersleijen Apr 30, 2026
b45eb47
Add height levels to node gdf
JelmarVersleijen Apr 30, 2026
e3ab66c
Add skip marker
JelmarVersleijen Apr 30, 2026
21a2741
Merge remote-tracking branch 'origin/feature/pipe_ramming_model' into…
JelmarVersleijen Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: Contributors to the utility-route-project and Alliander N.V.
#
# SPDX-License-Identifier: Apache-2.0

name: Quality checks
on:
pull_request:
types: [opened, reopened, synchronize, closed]
jobs:
quality_checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: 3.12
- name: Install Poetry
shell: bash
run: pipx install poetry~=2.0
- name: Install project
shell: bash
run: poetry install
- name: Run pre-commit
shell: bash
run: poetry run pre-commit run --all-files
- name: Run unit and integration tests
shell: bash
run: poetry run pytest tests
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,6 @@ dmypy.json
# Pycharm
.idea
_viminfo

# VS Code
.vscode
12 changes: 6 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Expand All @@ -22,17 +22,17 @@ repos:
args: ['--unsafe']
- id: name-tests-test
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.6
rev: v0.15.12
hooks:
- id: ruff
args: ["--fix"]
- id: ruff-check
args: [ --fix ]
- id: ruff-format
- repo: https://github.com/fsfe/reuse-tool
rev: v5.0.2
rev: v6.2.0
hooks:
- id: reuse-lint-file
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.15.0
rev: v1.20.2
hooks:
- id: mypy
args: [--ignore-missing-imports]
Expand Down
2 changes: 1 addition & 1 deletion PROJECT_GOVERNANCE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 'Copyright Contributors to the Utility-route-planner project'
SPDX-FileCopyrightText: 'Copyright Contributors to the Utility-route-planner project'

SPDX-License-Identifier: Apache-2.0
-->
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ requests to us.
# License
This project is licensed under the Apache-2.0 - see [LICENSE](https://github.com/alliander-opensource/utility-route-planner/blob/main/LICENSE) for details.

## Licenses data
## Licenses data
This project is largely dependent on data. Data is incorporated in the example folder and is licensed under their own respective Open-Source licenses:

- BGT: [CC PDM 1.0](https://creativecommons.org/publicdomain/mark/1.0/deed.en) downloaded from [PDOK](https://www.nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search#/metadata/e01e63cd-6b3d-4c58-b34e-8d343a3c264b)
Expand Down
Binary file modified data/examples/pytest_example_suitability_raster.tif
Binary file not shown.
Binary file added data/examples/pytest_osm_graph.pkl
Binary file not shown.
3 changes: 3 additions & 0 deletions data/examples/pytest_osm_graph.pkl.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: Contributors to the utility-route-project and Alliander N.V.

SPDX-License-Identifier: Apache-2.0
85 changes: 29 additions & 56 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# SPDX-FileCopyrightText: Contributors to the utility-route-project and Alliander N.V.
#
# SPDX-License-Identifier: Apache-2.0

import pathlib
import time

import shapely
import structlog

from utility_route_planner.models.benchmark_routes import BenchmarkRouteCollection
from utility_route_planner.models.lcpa.lcpa_engine import LcpaUtilityRouteEngine
from settings import Config
from utility_route_planner.models.mcda.mcda_engine import McdaCostSurfaceEngine
Expand All @@ -27,6 +27,7 @@ def run_mcda_lcpa(
human_designed_route: shapely.LineString,
raster_name_prefix: str,
compute_rasters_in_parallel: bool,
compute_metrics: bool = True,
):
reset_geopackage(Config.PATH_GEOPACKAGE_MCDA_OUTPUT, truncate=False)

Expand All @@ -49,71 +50,43 @@ def run_mcda_lcpa(
)

logger.info(f"Route CPU time: {(time.process_time_ns() - start_cpu_time) / 1e9:.2f} seconds.")
route_evaluation_metrics = RouteEvaluationMetrics(
lcpa_engine.lcpa_result,
path_suitability_raster,
human_designed_route,
project_area_geometry,
mcda_engine.processed_vector_metrics,
)
route_evaluation_metrics.get_route_evaluation_metrics()
if compute_metrics:
route_evaluation_metrics = RouteEvaluationMetrics(
lcpa_engine.lcpa_result,
path_suitability_raster,
human_designed_route,
project_area_geometry,
mcda_engine.processed_vector_metrics,
)
route_evaluation_metrics.get_route_evaluation_metrics()


if __name__ == "__main__":
cases = [
(
Config.PATH_GEOPACKAGE_CASE_01,
Config.LAYER_NAME_PROJECT_AREA_CASE_01,
Config.LAYER_NAME_HUMAN_DESIGNED_ROUTE_CASE_01,
"route_1_",
[],
),
(
Config.PATH_GEOPACKAGE_CASE_02,
Config.LAYER_NAME_PROJECT_AREA_CASE_02,
Config.LAYER_NAME_HUMAN_DESIGNED_ROUTE_CASE_02,
"route_2_",
[],
),
(
Config.PATH_GEOPACKAGE_CASE_03,
Config.LAYER_NAME_PROJECT_AREA_CASE_03,
Config.LAYER_NAME_HUMAN_DESIGNED_ROUTE_CASE_03,
"route_3_",
[],
),
(
Config.PATH_GEOPACKAGE_CASE_04,
Config.LAYER_NAME_PROJECT_AREA_CASE_04,
Config.LAYER_NAME_HUMAN_DESIGNED_ROUTE_CASE_04,
"route_4_",
[],
),
(
Config.PATH_GEOPACKAGE_CASE_05,
Config.LAYER_NAME_PROJECT_AREA_CASE_05,
Config.LAYER_NAME_HUMAN_DESIGNED_ROUTE_CASE_05,
"route_5_",
[[121462.8, 487153.4]],
),
]

reset_geopackage(Config.PATH_GEOPACKAGE_LCPA_OUTPUT, truncate=True)
route_collection = BenchmarkRouteCollection()

cases_to_run = [0, 1, 2, 3, 4] # 0/1/2/3/4
for case in cases_to_run:
geopackage, layer_project_area, human_designed_route_name, raster_name_prefix, stops = cases[case]
human_designed_route = gpd.read_file(geopackage, layer=human_designed_route_name).iloc[0].geometry
cases_to_run = [1, 2, 3, 4, 5]
for case_id in cases_to_run:
benchmark_route = route_collection.get_case(case_id)
human_designed_route = (
gpd.read_file(benchmark_route.path_geopackage, layer=benchmark_route.layer_name_human_designed_route)
.iloc[0]
.geometry
)
route_stops = get_first_last_point_from_linestring(human_designed_route)
if stops:
route_stops = list(route_stops)[:1] + [shapely.Point(i) for i in stops] + list(route_stops)[1:] # type: ignore
if benchmark_route.stops:
route_stops = (
list(route_stops)[:1] + [shapely.Point(i) for i in benchmark_route.stops] + list(route_stops)[1:] # type: ignore
)

run_mcda_lcpa(
"preset_benchmark_raw",
geopackage,
gpd.read_file(geopackage, layer=layer_project_area).iloc[0].geometry,
benchmark_route.path_geopackage,
gpd.read_file(benchmark_route.path_geopackage, layer=benchmark_route.layer_name_project_area)
.iloc[0]
.geometry,
route_stops,
human_designed_route,
raster_name_prefix,
benchmark_route.raster_name_prefix,
compute_rasters_in_parallel=True,
)
109 changes: 109 additions & 0 deletions multilayer_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# SPDX-FileCopyrightText: Contributors to the utility-route-project and Alliander N.V.
#
# SPDX-License-Identifier: Apache-2.0
import pathlib

import shapely
import geopandas as gpd
import time

import structlog
import typer
from structlog.contextvars import bound_contextvars

from settings import Config
from utility_route_planner.models.benchmark_routes import BenchmarkRouteCollection
from utility_route_planner.models.mcda.mcda_engine import McdaCostSurfaceEngine
from utility_route_planner.models.multilayer_network.hexagon_graph.hexagon_edge_generator import HexagonEdgeGenerator
from utility_route_planner.models.multilayer_network.hexagon_graph.hexagon_graph_builder import HexagonGraphBuilder
from utility_route_planner.models.multilayer_network.hexagon_graph.hexagon_grid_builder import HexagonGridBuilder
from utility_route_planner.models.multilayer_network.multilayer_route_planner import MultilayerRouteEngine
from utility_route_planner.models.multilayer_network.osm_graph_downloader import OSMGraphDownloader
from utility_route_planner.models.multilayer_network.osm_graph_preprocessing import OSMGraphPreprocessor
from utility_route_planner.models.multilayer_network.pipe_ramming import GetPotentialPipeRammingCrossings
from utility_route_planner.util.write import reset_geopackage

logger = structlog.get_logger(__name__)
app = typer.Typer(pretty_exceptions_enable=False)


def run_multilayer_network(
preset: str,
path_geopackage_mcda_input: pathlib.Path,
start_mid_end_points: shapely.LineString,
project_area_geometry: shapely.Polygon,
write_output: bool,
):
reset_geopackage(Config.PATH_GEOPACKAGE_MULTILAYER_NETWORK_OUTPUT, truncate=False)
reset_geopackage(Config.PATH_GEOPACKAGE_MCDA_OUTPUT, truncate=False)

start_cpu_time = time.process_time_ns()

raw_graph = OSMGraphDownloader(project_area_geometry).download_graph()
osm_graph_preprocessed = OSMGraphPreprocessor(raw_graph).preprocess_graph()

mcda_engine = McdaCostSurfaceEngine(preset, path_geopackage_mcda_input, project_area_geometry)
mcda_engine.preprocess_vectors()

raster_groups = {
criteria_key: criteria.group for criteria_key, criteria in mcda_engine.raster_preset.criteria.items()
}
grid_constructor = HexagonGridBuilder(hexagon_size=Config.HEXAGON_SIZE, block_size=Config.HEXAGON_BLOCK_SIZE)
hexagon_edge_generator = HexagonEdgeGenerator()
hexagon_graph_builder = HexagonGraphBuilder(grid_builder=grid_constructor, edge_generator=hexagon_edge_generator)
cost_surface_graph, cost_surface_nodes = hexagon_graph_builder.build_graph(
mcda_engine.project_area_geometry,
raster_groups,
mcda_engine.processed_vectors,
)
pipe_ramming = GetPotentialPipeRammingCrossings(osm_graph_preprocessed, cost_surface_graph, cost_surface_nodes)
pipe_ramming.get_crossings()

multi_layer_route_engine = MultilayerRouteEngine(
pipe_ramming.cost_surface_graph,
pipe_ramming.osm_graph,
pipe_ramming.cost_surface_nodes,
Config.HEXAGON_SIZE,
prefix="testing_",
write_output=write_output,
)
multi_layer_route_engine.find_route(start_mid_end_points)

logger.info(f"Multilayer route CPU time: {(time.process_time_ns() - start_cpu_time) / 1e9:.2f} seconds.")


@app.command()
def run_debug_case(write_routing_output: bool = False):
with bound_contextvars(project_area="Componistenbuurt"):
logger.info("Running multilayer routing engine for debug project area")
run_multilayer_network(
Config.RASTER_PRESET_NAME_BENCHMARK,
Config.PYTEST_PATH_GEOPACKAGE_MCDA,
shapely.LineString([(174847.18, 451178.43), (175746.347, 450435.534)]),
gpd.read_file(Config.PYTEST_PATH_GEOPACKAGE_MCDA, layer=Config.PYTEST_LAYER_NAME_PROJECT_AREA)
.iloc[0]
.geometry,
write_routing_output,
)


@app.command()
def run_benchmark_case(benchmark_case_id: int, write_routing_output: bool = False):
benchmark_routes = BenchmarkRouteCollection()
with bound_contextvars(benchmark_id=benchmark_case_id):
benchmark_route = benchmark_routes.get_case(benchmark_case_id)
run_multilayer_network(
Config.RASTER_PRESET_NAME_BENCHMARK,
benchmark_route.path_geopackage,
gpd.read_file(benchmark_route.path_geopackage, layer=benchmark_route.layer_name_human_designed_route)
.iloc[0]
.geometry,
gpd.read_file(benchmark_route.path_geopackage, layer=benchmark_route.layer_name_project_area)
.iloc[0]
.geometry,
write_routing_output,
)


if __name__ == "__main__":
app()
Loading