Code Monkey home page Code Monkey logo

od2net's Introduction

od2net

Logo

WARNING: This repo is not ready for general use. The API and input/output formats will keep changing. There are big limitations not yet documented.

od2net helps you turn origin/destination data about where people travel into a cycling network plan. You can use this to decide what streets to prioritize for safety improvements.

  1. You specify origins and destinations of trips that cyclists take today or of short trips taken by car
  2. You specify how cyclists would like to choose routes. Are fast/direct routes important, or sticking to quiet streets? Do you want to route near greenspace and shops?)
  3. od2net calculates routes very quickly, counting how many routes cross every street
  4. You use the web viewer to look at the most popular streets, filtering for streets that don't have good cycling infrastructure today

How to use it

You can quickly try out od2net without installing anything:

Once you're ready to run in a large area with your own origin/destination data, then start with the tutorial and see all documentation. Again note this project status is still pre-alpha; docs are not all written yet.

Contributing

We'd love contributions of all sorts -- developers, designers, data scientists, and applying it somewhere new! Check out GitHub Issues, file a new one, or email [email protected] to get started.

This project follows the Rust code of conduct and is Apache 2.0 licensed. See all credits.

od2net's People

Contributors

andrewphilipsmith avatar dabreegster avatar kdkasonde avatar robinlovelace avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

od2net's Issues

Represent network edits

Ungap the Map, v2! Glue to the scheme sketcher, let people apply a proposed scheme, and see how it affects od2net output

More input to edge costs and LTS

For all of these, I think we could first just detect this situation about the edge (and surface that info in the UI clearly). Then we can write edge cost and LTS functions that take these things into account, using TBD weightings.

And a further idea: local knowledge (or routing preference) is always going to be helpful. If we have a way in the UI to just annotate a road and edit the LTS / edge cost manually, then that could be super helpful.

Edge bundling

For visualization and/or analysis purposes, bundle parallel edes

pmtiles defaults lead to bitty network when zoomed out

There are ways to fix this by changing the arguments sent to tippecanoe, sure others have noticed it but cannot see an issue open on it.

Related issue is #37, I think fixing this one would yield a bigger benefit, especially for use cases where strategic planning is the aim.

image

Source: following instructions in #2

Basic docs

I know this is work in progress but thought I'd give it a spin. Things I've tried so far based on looking at https://github.com/dabreegster/od2net/blob/main/examples/run_all.sh

I've tried:

cd examples/liverpool/
python setup.py 
Traceback (most recent call last):
  File "/home/robin/github/people/dabreegster/od2net/examples/liverpool/setup.py", line 109, in <module>
    run(["mkdir", "-p", "input"])
NameError: name 'run' is not defined

Idea: generate README.md from README.qmd for reproducibility

The

```bash

code in there can run with quarto render README.qmd improving reproducibility.

Could set

#| eval: false

for the computationally intensive chunks or could just run the whole thing on any suitably resourced computer.

I plan to give this a bash over the next couple of weeks in any case, impressive speed-ups compared with routing used by PCT from what I can tell.

Docs

Probably make a multi-page book, possibly integrated with the Svelte app or not

  • Contribution guide
  • Credits (including Rust and other tech dependencies)
  • Describe different ways of using/interpreting -- what people can access something safely right now, vs if we could modify any road
  • Explain why turn restrictions (and relations) are ignored
  • Define scope (and notable omissions like PT and accessibility/connectivity)
  • Explain use cases with walkthroughs/examples (comparing to current counts, looking for what could be done safely right now, looking for potential demand, understanding detours)
  • How to interpret overall potential demand vs making just a few upgraded edges?
  • Flow chart for how to use it
  • Pipeline diagram of how it works
  • Perf table
  • Intro it as betweenness centrality in different worlds (existing or perfect)
  • Validation against real counts, possibly ignoring absolute and even relative amounts; just checking ordering
  • Explain why one country-wide run is more useful than a bunch of runs in smaller regions
  • Expandable detail sections, explaining how it works, like with the OSM node model (and how node pairs work)
  • Explain why a full traffic assignment model isn't useful
  • Include all references (especially https://npct.github.io/pct-shiny/regions_www/www/static/03a_manual/pct-bike-eng-user-manual-c1.pdf)

Replace key hardcoded parameters with config files

Currently settings such as the tags associated with paths on which cycling is forbidden are hard coded in .rs files:

if tags.is_any("highway", vec!["footway", "path"])
&& tags.is("footway", "sidewalk")
&& !tags.is("bicycle", "yes")
{
msgs.push(format!(
"Cycling not permitted on highway={}, when footway=sidewalk and bicycle=yes is missing",
tags.get("highway").unwrap()
));

Would it be possible to replace such settings with config files in json for easier editing and less Rust code reading? Aligns with the aim set out in #28 to make this more accessible (and in this case configurable) for others.

Use case: places like Norway and I believe Japan where cycling on footpaths is allowed, or for uses where we want to route cycling on a wider part of the network to inform investment decisions.

Finish BikeOttawa LTS port

  • Finish porting TS to Rust logic
  • Split into a new crate, and add a WASM API
  • Remove old code from the frontend, and use the WASM API for messages/rationale
  • Start unit tests
  • Ping BikeOttawa folks (and ask about highway=construction and maxspeed bugs)

Full tests for all examples

A way to run all examples locally, recording time / memory / space / etc requirements and formatting nicely for docs.

Web app to form examples/config

  • Specify OD pattern interactively, drawing zones / points and assigning weights
  • Pick route profile and other things
  • Output config.json
  • Integrate with popgetter?

Example instructions for Leeds hospital

From every building to https://www.openstreetmap.org/way/23196317:

AREA=leeds
URL=https://download.geofabrik.de/europe/great-britain/england/west-yorkshire-latest.osm.pbf

mkdir $AREA
curl $URL -o $AREA/input.osm.pbf
ogr2ogr -f GeoJSON -dialect sqlite -sql 'SELECT ST_Centroid(geometry) FROM multipolygons WHERE building IS NOT NULL' $AREA/origins.geojson $AREA/input.osm.pbf
# For destinations, just one hospital: https://www.openstreetmap.org/way/23196317
echo '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"coordinates":[-1.5521021406315,53.80241788159283],"type":"Point"}}]}' > $AREA/destinations.geojson

# Generate the "fast" network
cargo run --release -- '{"directory":"'"$AREA"'","requests":{"Generate":{"pattern":"FromEveryOriginToOneDestination"}},"routing":{"FastPaths":{"cost":"Distance"}}}'
mv $AREA/output.geojson $AREA/fast_output.geojson

# Now a rough approximation of a "quiet" network, penalizing main roads heavily
rm -f $AREA/ch.bin
cargo run --release -- '{"directory":"'"$AREA"'","requests":{"Generate":{"pattern":"FromEveryOriginToOneDestination"}},"routing":{"FastPaths":{"cost":"AvoidMainRoads"}}}'
mv $AREA/output.geojson $AREA/quiet_output.geojson

Manually load the two leeds/{fast,quiet}_output.geojson files in the viewer

Branding

Decide a name. I have many ideas offline, but none quite fit yet

Integrate with OSRM

This project started by making HTTP requests to OSRM, but the performance of that is terrible. I'm going to remove that integration for now to simplify and trim dependencies. Later on, revisit this:

  • Can we link against the native API and get better performance?
  • Can we use a prepared OSRM CH and just do the calculation ourselves?
  • Can we use an input graph from OSRM, effectively copying/reusing its profile?

Same questions for other routing engines

Nicer timer output

  • Preserve the hierarchy of blocks
  • Print the final summary more nicely (flamegraph / proportional)
  • Work on the API style
  • Get feedback from r/rust and console-rs

Example in Lisbon

Next: Create an example for Lisbon! @partavogen already forked this repo and is trying to make that, but also facing some issues.

Originally posted by @temospena in #2 (comment)

Hi all,

We are exploring od2net in Lisbon, and facing some problems.
Regarding #18 , how can we add this as the gradient value? Is it a matter to put the geotiff in a folder and point to it, or we need to pre-process with the data?
Here is a nice geotiff of Lisbon area: https://github.com/U-Shift/Declives-RedeViaria/blob/main/raster/LisboaIST_clip_r1.tif (10m res)
https://github.com/U-Shift/Declives-RedeViaria/blob/main/raster/LisboaCOPERNICUS_clip.tif (25m res)

Thanks!

More example input

  • wf02eq, UK output area to workplace zone, about 16 million rows
  • wu03ew, UK MSOA to MSOA, about 2 million rows
  • Soundcast, completely disaggregated individuals (about 4 million people?)

e2e tests

Run one of the Python examples end-to-end in GH actions and check something about the output. Pick a small one and possibly stash fixed input files somewhere.

Comparison mode in web app

If you have two different count outputs, visualize the diff

Example diffs could represent a network modification (if some edge becomes nicer, how does traffic redirect) or be used to parameter tune (if we change LTS definition, what overall effect does it have?)

Cleanup directory structure

  • Document it
  • Get rid of default filenames for input.osm.pbf, origins.geojson, etc?
  • Name ch.bin more carefully, based on params
  • Name the output more carefully

LTS level 1 on busy road with light segregation (Roseville Road, Leeds)

Just documenting findings as I look at this with Joey:

image

That's from running it in browser for Leeds. Not an issue with this codebase but with the LTS scoring or OSM tags or combination. There is a light seggregated cycleway on and off the road but is defo not suitable for children, this is quite a scary place to be on a bike:

image

Source: https://www.google.com/maps/@53.8067038,-1.5294913,3a,60y,90t/data=!3m6!1e1!3m4!1sVjDNXOnf-deeLq26tVSLWg!2e0!7i16384!8i8192?entry=ttu

Travel to hospital use case

A particularly useful first example to flesh out more.

  • For visualization, we actually only care about one destination (hospital) at a time
  • We can use 2011 OA-to-OA flows, noting the hospital is the main thing in its OA
  • Be careful about LTS / edge scoring -- the obvious path by the hospital isn't lit, so it's not a good option
  • actdev UI for inspiration
  • Questions
    • Assuming existing infra, what percentage of the staff can safely reach the hospital today?
    • If we could improve infrastructure everywhere, what's the potential network look like?

Possibly this could be a generally useful mode of the web app... instead of loading a prebuilt network representing some OD pattern, let people manually pick a destination, use preconfigured OD data, and show the network to that one place. Depending on the size of the inputs, could/should we...

  • run this totally in-browser with WASM
  • have a simple API to calculate on-the-fly
  • precalculate and store files for some fixed destinations

Improve web app visualization

  • Plumb along and display zones for origins/destinations too?
  • Scale O/D circles based on count, and include histograms for them too?
  • Try rank/ordering for line width (1st most important edge, 2nd...)

Handle direction

  • Output counts forwards and backwards
  • Be much more careful in the routing input graph and edge cost function with one-ways (depending on the policy question, we may care about existing one-ways or not)

Observations on reproducing outputs

Just a heads-up after reproducing some of the code in the README, managed to get this map which I'm happy with ๐ŸŽ‰

image

FYI anyone running this on Ubuntu, you may need to update your node version. This is what worked for me after reading this.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc
nvm list-remote
nvm install v18.12.0
nvm use v18.12.0

Feature request: option to keep summary information about origins and destinations associated with each link

Use case: you want to know the main areas that will benefit from investment in a particular bridge. Illustration for Waterloo Bridge:

image

This suggests that many of the users are coming from the south of the river to access destinations just north of the river.

I recall conversations at FOSS4G last year in Florence about ways to do this on-the-fly, that was impressive. In this case it's just returning all the routes that intersect with the view area after zooming in and clicking 'Free lines'. Not the most intuitive interface or efficient implementation, but works to illustrate the concept.

Source: https://www.pct.bike/m/?r=london

Cleanup OD patterns

Today:

  • from every origin to one destination
  • from every origin to nearest destination
  • from zone to zone
  • from zone to point

Can we re-express this with less repetition?

Also, another pattern is commuting distance from an origin, without knowing direction

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.