import%20marimo%0A%0A__generated_with%20%3D%20%220.23.13%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20OSM%20Network%20from%20a%20Relation%20ID%0A%0A%20%20%20%20Use%20an%20OSM%20relation%20id%20to%20create%20a%20%60networkx%60%20graph%20from%20OSM.%0A%0A%20%20%20%20Use%20OpenStreetMap%20to%20identify%20a%20boundary%20relations%20id.%20Then%2C%20use%20%60osmnx%60%20to%20retrieve%20the%20relation%20id%20as%20a%20%60GeoDataFrame%60.%0A%0A%20%20%20%20Network%20data%20%C2%A9%20%5BOpenStreetMap%5D(https%3A%2F%2Fwww.openstreetmap.org%2Fcopyright)%20contributors%2C%20available%20under%20the%20Open%20Database%20Licence.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20osmnx%20as%20ox%0A%20%20%20%20from%20cityseer.tools%20import%20io%2C%20plot%0A%0A%20%20%20%20return%20io%2C%20ox%2C%20plot%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20In%20this%20case%2C%20we'll%20retrieve%20the%20London%20%5BSoho%5D(https%3A%2F%2Fwww.openstreetmap.org%2Frelation%2F17710512)%20boundary%20relation%20%6017710512%60.%20For%20this%2C%20we%20can%20use%20the%20%60osmnx%60%20%5B%60geocode_to_gdf%60%5D(https%3A%2F%2Fosmnx.readthedocs.io%2Fen%2Fstable%2Fuser-reference.html%23osmnx.geocoder.geocode_to_gdf)%20function%20with%20the%20%60by_osmid%60%20parameter%20set%20to%20%60True%60.%20Note%20the%20preceding%20%60R%60%20prepended%20to%20the%20id%20as%20per%20the%20API%20documentation.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ox)%3A%0A%20%20%20%20bounds_gdf%20%3D%20ox.geocode_to_gdf(%0A%20%20%20%20%20%20%20%20%22R17710512%22%2C%20%20%23%20OSM%20relation%20ID%0A%20%20%20%20%20%20%20%20by_osmid%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20bounds_gdf%0A%20%20%20%20return%20(bounds_gdf%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Convert%20the%20%60GeoDataFrame%60%20into%20a%20unified%20Polygon%20using%20the%20%60geopandas%60%20%60union_all%60%20method.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(bounds_gdf)%3A%0A%20%20%20%20%23%20returns%20a%20geoDataFrame%20-%20union%20for%20the%20geom%0A%20%20%20%20bounds_geom%20%3D%20bounds_gdf.union_all()%0A%20%20%20%20bounds_geom%0A%20%20%20%20return%20(bounds_geom%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20If%20the%20geometry%20is%20complex%2C%20then%20the%20subsequent%20OSM%20API%20request%20(which%20happens%20behind%20the%20scenes)%20can%20fail%20due%20to%20a%20long%20URL%20request.%20In%20this%20case%2C%20you%20can%20take%20the%20geometrically%20simpler%20%60convex_hull%60%20instead.%20Alternatively%2C%20you%20can%20simplify%20the%20geometry%2C%20but%20remember%20to%20use%20spatial%20units%20matching%20the%20CRS%20of%20the%20geometry.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(bounds_geom)%3A%0A%20%20%20%20bounds_geom_1%20%3D%20bounds_geom.convex_hull%0A%20%20%20%20bounds_geom_1%0A%20%20%20%20return%20(bounds_geom_1%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20%60shapely%60%20geometry%20can%20then%20be%20passed%20to%20the%20%60cityseer%60%20%5Bosm_graph_from_poly%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Ftools%2Fio%23osm-graph-from-poly)%20function%2C%20as%20per%20other%20examples.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(bounds_geom_1%2C%20io)%3A%0A%20%20%20%20G%20%3D%20io.osm_graph_from_poly(bounds_geom_1)%0A%20%20%20%20print(G)%0A%20%20%20%20return%20(G%2C)%0A%0A%0A%40app.cell%0Adef%20_(G%2C%20plot)%3A%0A%20%20%20%20plot.plot_nx(G%2C%20plot_geoms%3DTrue)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Conclusion%0A%0A%20%20%20%20This%20notebook%20demonstrated%20how%20to%20retrieve%20an%20administrative%20or%20neighbourhood%20boundary%20from%20OpenStreetMap%20using%20an%20OSM%20relation%20ID%20via%20%60osmnx%60%2C%20and%20then%20use%20that%20boundary%20to%20create%20a%20%60cityseer%60-compatible%20street%20network%20graph.%20This%20approach%20is%20convenient%20when%20a%20well-defined%20boundary%20already%20exists%20in%20OSM%2C%20avoiding%20the%20need%20to%20supply%20a%20custom%20boundary%20file.%0A%0A%20%20%20%20To%20continue%20into%20analysis%2C%20hand%20the%20prepared%20graph%20to%20the%20high-level%20API%20with%20%5B%60CityNetwork.from_nx%60%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fapi%2Fnetwork%23from_nx)%2C%20which%20builds%20the%20dual%20network%20and%20exposes%20the%20centrality%20and%20land-use%20methods.%0A%0A%20%20%20%20**Next%20steps%3A**%20To%20create%20a%20network%20from%20a%20custom%20streets%20dataset%2C%20see%20%5BStreets%20Dataset%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fexamples%2Fnetworks%2Fnetwork-from-streets).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
22fa66c5aad57852ddea16a3ac8bd112