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%20Weighted%20Flows%20vs%20Uniform%20Betweenness%0A%0A%20%20%20%20Standard%20betweenness%20assumes%20uniform%20demand%3A%20every%20origin-destination%20pair%20counts%20equally.%20Demand-weighted%20flows%20replace%20that%20assumption%20with%20where%20people%20actually%20are%20and%20where%20they%20are%20going.%20This%20recipe%20runs%20both%20on%20the%20**same%20network%20and%20threshold**%20so%20the%20difference%20is%20only%20the%20demand%20model%2C%20then%20maps%20them%20side%20by%20side.%20See%20the%20%5BOrigin-Destination%20Flows%20guide%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fguide%2Fflows)%20for%20the%20background.%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%20geopandas%20as%20gpd%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20from%20cityseer.network%20import%20CityNetwork%0A%0A%20%20%20%20return%20CityNetwork%2C%20gpd%2C%20plt%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%20Network%20and%20demand%20data%0A%0A%20%20%20%20A%20central-Madrid%20network%2C%20with%20Eurostat%20census%20population%20as%20**origins**%20and%20hospitality%20premises%20as%20**destinations**.%20%60CityNetwork%60%20builds%20the%20dual%20graph%20internally%2C%20so%20both%20measures%20share%20one%20basis.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(CityNetwork%2C%20gpd%2C%20mo)%3A%0A%20%20%20%20data_dir%20%3D%20(mo.notebook_dir()%20%2F%20%22..%22%20%2F%20%22..%22%20%2F%20%22data%22).resolve()%0A%20%20%20%20streets_gpd%20%3D%20gpd.read_file(data_dir%20%2F%20%22madrid_streets%22%20%2F%20%22street_network.gpkg%22)%0A%20%20%20%20streets_gpd%20%3D%20streets_gpd.explode(ignore_index%3DTrue).drop_duplicates(subset%3D%22geometry%22)%0A%20%20%20%20centre%20%3D%20gpd.GeoSeries.from_xy(%5B440300%5D%2C%20%5B4474300%5D%2C%20crs%3Dstreets_gpd.crs)%0A%20%20%20%20study_poly%20%3D%20centre.buffer(3000).iloc%5B0%5D%0A%20%20%20%20buffered_poly%20%3D%20centre.buffer(3800).iloc%5B0%5D%20%20%23%20network%20buffered%20past%20the%20800%20m%20threshold%0A%20%20%20%20cn%20%3D%20CityNetwork.from_geopandas(streets_gpd%5Bstreets_gpd.intersects(buffered_poly)%5D%2C%20boundary%3Dstudy_poly)%0A%0A%20%20%20%20census%20%3D%20gpd.read_file(data_dir%20%2F%20%22madrid_census%22%20%2F%20%22eu_stat_clipped.gpkg%22).to_crs(streets_gpd.crs)%0A%20%20%20%20origins%20%3D%20census%5B%5B%22T%22%2C%20%22geometry%22%5D%5D.copy()%0A%20%20%20%20origins%5B%22geometry%22%5D%20%3D%20origins.geometry.centroid%0A%20%20%20%20origins%20%3D%20origins%5Borigins.within(buffered_poly)%5D%0A%20%20%20%20premises%20%3D%20gpd.read_file(data_dir%20%2F%20%22madrid_premises%22%20%2F%20%22madrid_premises.gpkg%22)%0A%20%20%20%20dests%20%3D%20premises%5Bpremises%5B%22section_id%22%5D%20%3D%3D%20%22I%22%5D.copy()%0A%20%20%20%20dests%20%3D%20dests%5Bdests.within(buffered_poly)%5D%0A%20%20%20%20dests%5B%22weight%22%5D%20%3D%201.0%0A%20%20%20%20return%20cn%2C%20dests%2C%20origins%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%20Compute%20both%20measures%0A%0A%20%20%20%20Uniform%20betweenness%20needs%20only%20the%20network.%20Demand-weighted%20flow%20additionally%20takes%20the%20weighted%20origins%20and%20destinations%20and%20a%20distance-decay%20deterrence%20function.%20Both%20write%20to%20%60nodes_gdf%60%2C%20and%20%60to_geopandas%60%20projects%20them%20onto%20the%20street%20segments%20for%20mapping.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cn%2C%20dests%2C%20origins)%3A%0A%20%20%20%20cn.centrality_shortest(distances%3D%5B800%5D)%20%20%23%20uniform%20betweenness%20-%3E%20cc_betweenness_800%0A%20%20%20%20cn.betweenness_demand(%20%20%23%20population%20-%3E%20hospitality%2C%20gravity-style%20decay%20-%3E%20cc_demand_800%0A%20%20%20%20%20%20%20%20origins_gdf%3Dorigins%2C%0A%20%20%20%20%20%20%20%20destinations_gdf%3Ddests%2C%0A%20%20%20%20%20%20%20%20origin_weight_col%3D%22T%22%2C%0A%20%20%20%20%20%20%20%20destination_weight_col%3D%22weight%22%2C%0A%20%20%20%20%20%20%20%20distances%3D%5B800%5D%2C%0A%20%20%20%20%20%20%20%20decay_fn%3D%22exp(-0.002%20*%20c)%22%2C%0A%20%20%20%20)%0A%20%20%20%20streets%20%3D%20cn.to_geopandas()%20%20%23%20both%20metrics%20projected%20onto%20the%20street%20segments%0A%20%20%20%20return%20(streets%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%23%20Map%20them%20side%20by%20side%0A%0A%20%20%20%20Both%20use%20the%20same%20styling%20(line%20width%20and%20orange-red%20colour%20scaled%20by%20a%20percentile%20rank%20of%20the%20value)%2C%20so%20the%20patterns%20are%20directly%20comparable.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20streets)%3A%0A%20%20%20%20fig%2C%20axes%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(13%2C%206.5))%0A%20%20%20%20live%20%3D%20streets%5Bstreets.live%5D%0A%20%20%20%20for%20ax%2C%20col%2C%20title%20in%20%5B%0A%20%20%20%20%20%20%20%20(axes%5B0%5D%2C%20%22cc_betweenness_800%22%2C%20%22Uniform%20betweenness%22)%2C%0A%20%20%20%20%20%20%20%20(axes%5B1%5D%2C%20%22cc_demand_800%22%2C%20%22Demand-weighted%20flow%22)%2C%0A%20%20%20%20%5D%3A%0A%20%20%20%20%20%20%20%20g%20%3D%20live.copy()%0A%20%20%20%20%20%20%20%20g%5B%22rank%22%5D%20%3D%20g%5Bcol%5D.rank(pct%3DTrue)%0A%20%20%20%20%20%20%20%20g%20%3D%20g.sort_values(%22rank%22)%20%20%23%20strongest%20drawn%20last%0A%20%20%20%20%20%20%20%20g.plot(ax%3Dax%2C%20color%3Dplt.get_cmap(%22OrRd%22)(g%5B%22rank%22%5D)%2C%20linewidth%3D0.15%20%2B%202.25%20*%20g%5B%22rank%22%5D)%0A%20%20%20%20%20%20%20%20ax.set_title(title%2C%20loc%3D%22left%22)%0A%20%20%20%20%20%20%20%20ax.set_axis_off()%0A%20%20%20%20%20%20%20%20ax.set_aspect(%22equal%22)%0A%20%20%20%20fig.tight_layout()%0A%20%20%20%20fig%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%20Interpretation%0A%0A%20%20%20%20Uniform%20betweenness%20marks%20the%20network's%20structural%20through-routes%3A%20the%20streets%20most%20likely%20to%20lie%20on%20a%20shortest%20path%20between%20any%20two%20points.%20Demand-weighted%20flow%20shifts%20emphasis%20towards%20streets%20that%20connect%20where%20people%20live%20to%20where%20they%20go%2C%20so%20residential-to-amenity%20corridors%20strengthen%20and%20structurally%20central%20but%20lightly-used%20streets%20recede.%20Neither%20is%20more%20correct.%20Uniform%20betweenness%20reflects%20structural%20position%20and%20needs%20only%20the%20network%3B%20demand-weighted%20flow%20estimates%20use%20but%20depends%20on%20the%20quality%20of%20the%20origin%20and%20destination%20weights.%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
67ee67a529f3f10db5752b619d26d2ba