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%20Adding%20GTFS%20Transport%20Data%20to%20Accessibility%0A%0A%20%20%20%20This%20notebook%20demonstrates%20how%20GTFS%20(General%20Transit%20Feed%20Specification)%20public%20transport%20data%20can%20be%20integrated%20into%20the%20street%20network%20before%20computing%20landuse%20accessibility%20metrics.%20By%20adding%20metro%20stops%20and%20segment%20travel%20times%2C%20the%20accessibility%20calculations%20can%20account%20for%20the%20extended%20reach%20provided%20by%20public%20transport.%0A%0A%20%20%20%20Accessibility%20to%20retail%20premises%20is%20computed%20twice%3A%20once%20on%20the%20street%20network%20alone%2C%20and%20again%20after%20adding%20the%20metro%20network.%20The%20difference%20reveals%20how%20the%20metro%20network%20extends%20the%20catchment%20area%20for%20retail%20access.%0A%0A%20%20%20%20The%20analysis%20uses%20a%204km%20study%20area%20around%20the%20city%20centre%20rather%20than%20the%20whole%20city%3A%20this%20is%20large%20enough%20to%20span%20multiple%20metro%20lines%20and%20interchanges%2C%20and%20since%20accessibility%20is%20computed%20per%20node%20from%20local%20catchments%2C%20the%20district%20reproduces%20the%20city-wide%20values%20at%20far%20lower%20cost.%20The%20network%20is%20buffered%20by%20the%20maximum%20analysis%20distance%20so%20nodes%20near%20the%20study%20edge%20keep%20their%20full%20catchments.%0A%0A%20%20%20%20This%20recipe%20uses%20the%20high-level%20%5B%60CityNetwork%60%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fapi%2Fnetwork)%20class%2C%20integrating%20the%20transit%20data%20through%20its%20%60add_gtfs%60%20method.%20Two%20instances%20are%20built%20from%20the%20same%20clipped%20streets%3A%20one%20street-only%20baseline%20and%20one%20with%20the%20metro%20added.%0A%0A%20%20%20%20The%20bundled%20datasets%20and%20their%20source%20attributions%20are%20documented%20on%20the%20%5Bdatasets%20page%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fexamples%2Fdatasets).%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%20import%20pandas%20as%20pd%0A%20%20%20%20from%20cityseer.network%20import%20CityNetwork%0A%0A%20%20%20%20return%20CityNetwork%2C%20gpd%2C%20pd%2C%20plt%0A%0A%0A%40app.cell%0Adef%20_(CityNetwork%2C%20gpd)%3A%0A%20%20%20%20streets_gpd%20%3D%20gpd.read_file(%22..%2F..%2Fdata%2Fmadrid_streets%2Fstreet_network.gpkg%22)%0A%20%20%20%20streets_gpd%20%3D%20streets_gpd.explode(ignore_index%3DTrue)%0A%20%20%20%20%23%20the%20source%20data%20contains%20a%20small%20number%20of%20exact%20duplicate%20geometries%0A%20%20%20%20streets_gpd%20%3D%20streets_gpd.drop_duplicates(subset%3D%22geometry%22)%0A%20%20%20%20%23%204km%20study%20area%20around%20the%20city%20centre%2C%20with%20the%20network%20buffered%20a%20further%201600m%0A%20%20%20%20%23%20(the%20maximum%20analysis%20distance)%20to%20prevent%20edge%20rolloff%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(4000).iloc%5B0%5D%0A%20%20%20%20buffered_poly%20%3D%20centre.buffer(5600).iloc%5B0%5D%0A%20%20%20%20streets_clip%20%3D%20streets_gpd%5Bstreets_gpd.intersects(buffered_poly)%5D%0A%20%20%20%20cn_base%20%3D%20CityNetwork.from_geopandas(streets_clip%2C%20boundary%3Dstudy_poly)%0A%20%20%20%20return%20buffered_poly%2C%20cn_base%2C%20streets_clip%2C%20study_poly%0A%0A%0A%40app.cell%0Adef%20_(buffered_poly%2C%20gpd)%3A%0A%20%20%20%20prems_gpd%20%3D%20gpd.read_file(%22..%2F..%2Fdata%2Fmadrid_premises%2Fmadrid_premises.gpkg%22)%0A%20%20%20%20prems_gpd%20%3D%20prems_gpd%5Bprems_gpd.within(buffered_poly)%5D%0A%20%20%20%20prems_gpd.head()%0A%20%20%20%20return%20(prems_gpd%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%20Compute%20baseline%20retail%20accessibility%20(without%20GTFS%20data)%20and%20snapshot%20the%20results%20with%20%60to_geopandas%60%20for%20later%20comparison.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cn_base%2C%20prems_gpd)%3A%0A%20%20%20%20%23%20compute%20baseline%20accessibility%0A%20%20%20%20distances%20%3D%20%5B800%2C%201600%5D%0A%20%20%20%20_cn%2C%20prems_gpd_1%20%3D%20cn_base.compute_accessibilities(%0A%20%20%20%20%20%20%20%20prems_gpd%2C%0A%20%20%20%20%20%20%20%20landuse_column_label%3D%22division_desc%22%2C%0A%20%20%20%20%20%20%20%20accessibility_keys%3D%5B%22retail%22%5D%2C%0A%20%20%20%20%20%20%20%20distances%3Ddistances%2C%0A%20%20%20%20)%0A%20%20%20%20base_gdf%20%3D%20cn_base.to_geopandas()%0A%20%20%20%20return%20base_gdf%2C%20distances%2C%20prems_gpd_1%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%20Build%20a%20second%20network%20from%20the%20same%20clipped%20streets%20and%20load%20the%20bundled%20metro%20GTFS%20data%20with%20%5B%60add_gtfs%60%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fapi%2Fnetwork%23add_gtfs).%20This%20adds%20metro%20stops%20as%20nodes%20and%20segment%20travel%20times%20as%20edges.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(CityNetwork%2C%20streets_clip%2C%20study_poly)%3A%0A%20%20%20%20cn_metro%20%3D%20CityNetwork.from_geopandas(streets_clip%2C%20boundary%3Dstudy_poly)%0A%20%20%20%20cn_metro.add_gtfs(%22..%2F..%2Fdata%2Fmadrid_gtfs%2Fmadrid_metro%22)%0A%20%20%20%20return%20(cn_metro%2C)%0A%0A%0A%40app.cell%0Adef%20_(cn_metro%2C%20gpd%2C%20pd)%3A%0A%20%20%20%20%23%20read%20the%20GTFS%20stop%20locations%20for%20plotting%0A%20%20%20%20stops%20%3D%20pd.read_csv(%22..%2F..%2Fdata%2Fmadrid_gtfs%2Fmadrid_metro%2Fstops.txt%22)%0A%20%20%20%20stops_gdf%20%3D%20gpd.GeoDataFrame(%0A%20%20%20%20%20%20%20%20stops%2C%0A%20%20%20%20%20%20%20%20geometry%3Dgpd.points_from_xy(stops%5B%22stop_lon%22%5D%2C%20stops%5B%22stop_lat%22%5D)%2C%0A%20%20%20%20%20%20%20%20crs%3D4326%2C%20%20%23%20GTFS%20stop%20coordinates%20are%20WGS84%0A%20%20%20%20)%0A%20%20%20%20stops_gdf%20%3D%20stops_gdf.to_crs(cn_metro.crs)%0A%20%20%20%20stops_gdf%0A%20%20%20%20return%20(stops_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%20Compute%20retail%20accessibility%20on%20the%20metro-integrated%20network.%20The%20shortest-path%20algorithms%20can%20now%20route%20through%20metro%20segments%2C%20extending%20the%20effective%20catchment%20area.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cn_metro%2C%20distances%2C%20prems_gpd_1)%3A%0A%20%20%20%20_cn%2C%20prems_gpd_2%20%3D%20cn_metro.compute_accessibilities(%0A%20%20%20%20%20%20%20%20prems_gpd_1%2C%0A%20%20%20%20%20%20%20%20landuse_column_label%3D%22division_desc%22%2C%0A%20%20%20%20%20%20%20%20accessibility_keys%3D%5B%22retail%22%5D%2C%0A%20%20%20%20%20%20%20%20distances%3Ddistances%2C%0A%20%20%20%20)%0A%20%20%20%20metro_gdf%20%3D%20cn_metro.to_geopandas()%0A%20%20%20%20return%20metro_gdf%2C%20prems_gpd_2%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%20Compare%20results%0A%20%20%20%20%22%22%22)%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%20Compute%20the%20difference%20between%20the%20metro-integrated%20and%20baseline%20retail%20accessibility.%20The%20three-panel%20plot%20below%20shows%20retail%20accessibility%20within%20800m%20without%20the%20metro%2C%20with%20the%20metro%2C%20and%20the%20difference.%20Retail%20premises%20are%20shown%20in%20white%20and%20metro%20stops%20in%20red.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(metro_gdf)%3A%0A%20%20%20%20metro_gdf.columns%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(base_gdf%2C%20metro_gdf)%3A%0A%20%20%20%20metro_gdf%5B%22cc_retail_800_diff%22%5D%20%3D%20metro_gdf%5B%22cc_retail_800%22%5D%20-%20base_gdf%5B%22cc_retail_800%22%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(base_gdf%2C%20metro_gdf%2C%20plt%2C%20prems_gpd_2%2C%20stops_gdf)%3A%0A%20%20%20%20import%20matplotlib.colors%20as%20mcolors%0A%0A%20%20%20%20fig%2C%20axes%20%3D%20plt.subplots(3%2C%201%2C%20figsize%3D(8%2C%2020)%2C%20dpi%3D150)%0A%20%20%20%20%23%20baseline%20and%20with-metro%20retail%20accessibility%3A%20OrRd%20rank%20style%2C%20width%20and%20colour%20by%20percentile%0A%20%20%20%20for%20_ax%2C%20_gdf%2C%20_title%20in%20%5B%0A%20%20%20%20%20%20%20%20(axes%5B0%5D%2C%20base_gdf%2C%20%22Retail%20accessibility%20without%20metro%2C%20800%20m%22)%2C%0A%20%20%20%20%20%20%20%20(axes%5B1%5D%2C%20metro_gdf%2C%20%22Retail%20accessibility%20with%20metro%2C%20800%20m%22)%2C%0A%20%20%20%20%5D%3A%0A%20%20%20%20%20%20%20%20_g%20%3D%20_gdf%5B_gdf.live%5D.copy()%0A%20%20%20%20%20%20%20%20_g%5B%22_r%22%5D%20%3D%20_g%5B%22cc_retail_800%22%5D.rank(pct%3DTrue)%0A%20%20%20%20%20%20%20%20_g%20%3D%20_g.sort_values(%22_r%22)%0A%20%20%20%20%20%20%20%20_g.plot(ax%3D_ax%2C%20color%3Dplt.get_cmap(%22OrRd%22)(_g%5B%22_r%22%5D)%2C%20linewidth%3D0.15%20%2B%202.25%20*%20_g%5B%22_r%22%5D)%0A%20%20%20%20%20%20%20%20_ax.set_title(_title%2C%20loc%3D%22left%22)%0A%20%20%20%20%23%20difference%20map%3A%20signed%20values%2C%20so%20keep%20a%20diverging%20scheme%20centred%20on%20zero%0A%20%20%20%20_gd%20%3D%20metro_gdf%5Bmetro_gdf.live%5D.copy()%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20_norm%20%3D%20mcolors.TwoSlopeNorm(vcenter%3D0)%0A%20%20%20%20%20%20%20%20_gd.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20column%3D%22cc_retail_800_diff%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cmap%3D%22coolwarm%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20norm%3D_norm%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20legend%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20legend_kwds%3D%7B%22label%22%3A%20%22Difference%20in%20retail%20accessibility%2C%20800%20m%22%2C%20%22shrink%22%3A%200.6%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ax%3Daxes%5B2%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20except%20ValueError%3A%0A%20%20%20%20%20%20%20%20_gd.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20column%3D%22cc_retail_800_diff%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cmap%3D%22coolwarm%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20legend%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20legend_kwds%3D%7B%22label%22%3A%20%22Difference%20in%20retail%20accessibility%2C%20800%20m%22%2C%20%22shrink%22%3A%200.6%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ax%3Daxes%5B2%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20axes%5B2%5D.set_title(%22Difference%20due%20to%20metro%2C%20800%20m%22%2C%20loc%3D%22left%22)%0A%20%20%20%20for%20ax%20in%20axes%3A%0A%20%20%20%20%20%20%20%20%23%20context%20overlays%20on%20top%3A%20retail%20premises%20and%20metro%20stops%20in%20neutral%20dark%0A%20%20%20%20%20%20%20%20prems_gpd_2%5Bprems_gpd_2%5B%22division_desc%22%5D%20%3D%3D%20%22retail%22%5D.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20markersize%3D1%2C%20edgecolor%3DNone%2C%20color%3D%22%23333333%22%2C%20legend%3DFalse%2C%20ax%3Dax%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20stops_gdf.plot(ax%3Dax%2C%20color%3D%22%23333333%22%2C%20markersize%3D1)%0A%20%20%20%20%20%20%20%20ax.set_xlim(438500%2C%20438500%20%2B%203500)%0A%20%20%20%20%20%20%20%20ax.set_ylim(4472500%2C%204472500%20%2B%203500)%0A%20%20%20%20%20%20%20%20ax.set_axis_off()%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%20Conclusion%0A%0A%20%20%20%20This%20notebook%20integrated%20GTFS%20public%20transport%20data%20(the%20bundled%20metro%20feed)%20into%20the%20street%20network%20via%20%60CityNetwork.add_gtfs%60%20and%20compared%20retail%20accessibility%20with%20and%20without%20transit%20connectivity.%20The%20before-and-after%20comparison%20reveals%20how%20the%20metro%20extends%20the%20effective%20catchment%20area%20for%20retail%20access%2C%20particularly%20around%20metro%20stop%20locations.%0A%0A%20%20%20%20**Next%20steps%3A**%20For%20centrality%20with%20GTFS%20data%2C%20see%20%5BGTFS%20Centrality%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fexamples%2Fcentrality%2Fcentrality-metro).%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
c1e7016840de0c3b35f6d9199c2aca85