Skip to content

Testing the 'od2net' approach with data from Edinburgh

License

Notifications You must be signed in to change notification settings

nptscot/od2net-tests

Repository files navigation

Demo of od2net

The in this repo is intended to demonstrate how to use od2net to generate route networks and to compare the workflow, and results, with the R-based approach currently used in the NPT project.

od2net minimum example

The following is based on od2net’s docs and the code in the examples/edinburgh folder.

Setup the files in the input folder as follows:

source("R/setup.R")
main()

Run the tool with Docker as follows:

# Time it:
docker run -v $(pwd):/app ghcr.io/urban-analytics-technology-platform/od2net:main /app/config.json
# Summary:
#   - Load network took 100.799767ms
#     - Loading origins took 175.604547ms
#     - Loading destinations took 174.229604ms
#     - Loading zones from /app/input/zones.geojson took 714.082µs
#     - Matching points to zones took 54.914894ms
#     - Generating requests from /app/input/od.csv took 659.614µs
#   - Loading or generating requests took 406.16771ms
#     - Building RTree for matching request points to OSM nodes took 16.235263ms
#   - Routing took 56.808164ms
#   - Writing output CSV took 18.805512ms
#   - Writing output GJ took 125.66129ms
#   - Converting to pmtiles for rendering took 7.733441909s
# - everything took 8.441747553s

After that you should see the following in the output folder:

fs::dir_tree("output")
output
├── counts.csv
├── output-r.geojson
├── output.geojson
└── rnet.pmtiles

R minimum example

library(tidyverse)
od = readr::read_csv("input/od.csv")
zones = sf::read_sf("input/zones.geojson")
desire_lines = od::od_to_sf(od, zones)
# Requires API key:
system.time({
  routes = cyclestreets::batch(desire_lines, username = "robinlovelace", wait = TRUE)
})
# 133 seconds
rnet = stplanr::overline(routes, attrib = "count")
sf::write_sf(rnet, "output/output-r.geojson")

Comparison

output_od2net = sf::read_sf("output/output.geojson")
output_r = sf::read_sf("output/output-r.geojson")
sum(sf::st_length(output_od2net))
2432481 [m]
sum(sf::st_length(output_r))
1192642 [m]
names(output_od2net)
 [1] "backward_cost"     "count"             "destination_count"
 [4] "forward_cost"      "length"            "lts"              
 [7] "nearby_amenities"  "node1"             "node2"            
[10] "origin_count"      "osm_tags"          "slope"            
[13] "way"               "geometry"         
names(output_r)
[1] "count"    "geometry"
summary(output_od2net$way)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max.      NA's 
1.370e+02 5.368e+06 7.098e+07 2.546e+08 3.613e+08 1.313e+09     13596 
sum(output_od2net$count * sf::st_length(output_od2net), na.rm = TRUE) |>
  units::set_units("km")
34685.34 [km]
sum(output_r$count * sf::st_length(output_r), na.rm = TRUE) |>
  units::set_units("km")
83155.09 [km]
# Vs flow implied from desire lines (expectation: ~1.3 x this amount):
sum(desire_lines$count * sf::st_length(desire_lines), na.rm = TRUE) |>
  units::set_units("km")
30394.87 [km]
output_combined = bind_rows(
  output_od2net |>
    filter(!is.na(way)) |>
    # Only large counts:
    filter(count > 5) |>
    mutate(source = "od2net"),
  output_r |>
    mutate(source = "R") |>
    filter(count > 5)
)
central_edinburgh = zonebuilder::zb_zone("Edinburgh", n_circles = 2)
output_combined = output_combined |>
  sf::st_intersection(central_edinburgh)
output_combined |>
  ggplot() +
  geom_sf(aes(colour = count)) +
  scale_colour_viridis_c() +
  facet_wrap(~source) +
  theme_void()

Setup

Run the code on a computer with Ubuntu 22.04 after running the setup outlined in the link above.

gh repo clone Urban-Analytics-Technology-Platform/od2net
# Copy the example to this folder:
cp -r od2net/examples/edinburgh/* .
cp -r od2net/
# Setup quarto-publish:

About

Testing the 'od2net' approach with data from Edinburgh

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published