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%20Urban%20Analytics%0A%0A%20%20%20%20This%20lesson%20introduces%20two%20packages%20from%20the%20wider%20Python%20geospatial%20ecosystem%3A%20%60osmnx%60%2C%20for%20downloading%20data%20from%20OpenStreetMap%2C%20and%20%60momepy%60%2C%20for%20analysing%20urban%20form.%0A%0A%20%20%20%20Both%20packages%20are%20included%20in%20this%20repository's%20%60examples%60%20dependency%20group%2C%20so%20they%20are%20available%20automatically%20when%20you%20open%20the%20notebook%20with%20%60uv%20run%20marimo%20edit%60.%20If%20you%20are%20working%20in%20your%20own%20environment%2C%20install%20them%20first%20(e.g.%20%60pip%20install%20osmnx%20momepy%60).%0A%0A%20%20%20%20%23%23%23%20Importing%20Libraries%0A%0A%20%20%20%20Let's%20import%20the%20necessary%20packages%3A%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%20%23%20use%20an%20alias%20for%20convenience%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20momepy%0A%20%20%20%20import%20osmnx%20as%20ox%0A%0A%20%20%20%20return%20momepy%2C%20ox%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%20osmnx%0A%0A%20%20%20%20%5B%60osmnx%60%5D(https%3A%2F%2Fosmnx.readthedocs.io%2F)%20is%20a%20Python%20package%20that%20simplifies%20downloading%20and%20working%20with%20geospatial%20data%20from%20OpenStreetMap%20(OSM)%2C%20such%20as%20building%20footprints%20or%20points%20of%20interest.%0A%0A%20%20%20%20This%20example%20demonstrates%20how%20to%20download%20building%20footprints%20within%20a%201km%20radius%20of%20a%20specified%20location%20in%20Nicosia%2C%20Cyprus%2C%20defined%20by%20its%20coordinates.%20%60osmnx%60%20provides%20several%20methods%20for%20downloading%20data%3B%20here%2C%20we%20will%20use%20%5B%60features_from_point%60%5D(https%3A%2F%2Fosmnx.readthedocs.io%2Fen%2Fstable%2Fuser-reference.html%23osmnx.features.features_from_point).%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%20%23%20Define%20the%20point%20of%20interest%20(latitude%2C%20longitude)%20and%20distance%0A%20%20%20%20center_point%20%3D%20(35.17526%2C%2033.36402)%0A%20%20%20%20distance_m%20%3D%201000%0A%0A%20%20%20%20%23%20Download%20building%20footprints%0A%20%20%20%20gdf_buildings%20%3D%20ox.features_from_point(center_point%2C%20tags%3D%7B%22building%22%3A%20True%7D%2C%20dist%3Ddistance_m)%0A%20%20%20%20return%20distance_m%2C%20gdf_buildings%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%60osmnx%60%20returns%20GeoDataFrames%20which%2C%20as%20shown%20in%20the%20previous%20lesson%2C%20are%20ideal%20for%20spatial%20analysis%20in%20Python.%20Note%20the%20%60tags%3D%7B%22building%22%3A%20True%7D%60%20argument%2C%20which%20instructs%20%60osmnx%60%20to%20fetch%20all%20features%20tagged%20as%20buildings%20in%20OSM.%20By%20changing%20these%20tags%2C%20you%20can%20also%20download%20other%20types%20of%20features%2C%20such%20as%20roads%20or%20parks.%0A%0A%20%20%20%20It%20is%20good%20practice%20to%20inspect%20the%20data%20you%20have%20downloaded.%20The%20%60head()%60%20function%20displays%20the%20first%20few%20rows%20of%20the%20GeoDataFrame%2C%20allowing%20you%20to%20quickly%20check%20the%20data%20structure%20and%20attributes.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings)%3A%0A%20%20%20%20%23%20Display%20the%20first%20few%20rows%20of%20the%20buildings%20GeoDataFrame%0A%20%20%20%20gdf_buildings.head()%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%20You%20can%20also%20plot%20the%20downloaded%20data%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(distance_m%2C%20gdf_buildings%2C%20plt)%3A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(10%2C%2010)%2C%20dpi%3D150)%0A%20%20%20%20gdf_buildings.plot(ax%3D_ax)%0A%20%20%20%20_ax.set_title(f%22Buildings%20within%20%7Bdistance_m%7D%20m%20of%20the%20study%20point%22)%0A%20%20%20%20_ax.set_axis_off()%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%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%20For%20more%20detailed%20information%20on%20different%20ways%20to%20query%20OSM%20features%20data%2C%20refer%20to%20the%20%60osmnx%60%20%5Bfeatures%20documentation%5D(https%3A%2F%2Fosmnx.readthedocs.io%2Fen%2Fstable%2Fuser-reference.html%23module-osmnx.features).%0A%0A%20%20%20%20%23%23%20Data%20Preparation%0A%0A%20%20%20%20To%20streamline%20the%20subsequent%20analysis%2C%20it%20is%20advisable%20to%20first%20filter%20for%20the%20types%20of%20geometry%20you%20intend%20to%20work%20with.%20In%20this%20instance%2C%20we%20are%20interested%20in%20polygon%20or%20multi-polygon%20geometries%20and%20will%20discard%20other%20types%2C%20such%20as%20points%20or%20linestrings.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings)%3A%0A%20%20%20%20%23%20Filter%20out%20non-polygon%20geometries%0A%20%20%20%20gdf_buildings_1%20%3D%20gdf_buildings%5Bgdf_buildings.geometry.geom_type.isin(%5B%22Polygon%22%2C%20%22MultiPolygon%22%5D)%5D%0A%20%20%20%20gdf_buildings_1.head()%0A%20%20%20%20return%20(gdf_buildings_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%20Secondly%2C%20we%20will%20reset%20the%20index%20so%20that%20all%20features%20are%20neatly%20indexed%20from%20zero%20upwards%2C%20without%20duplicates.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings_1)%3A%0A%20%20%20%20%23%20Reset%20the%20index%0A%20%20%20%20gdf_buildings_2%20%3D%20gdf_buildings_1.reset_index(drop%3DTrue)%0A%20%20%20%20gdf_buildings_2.head()%0A%20%20%20%20return%20(gdf_buildings_2%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%20Thirdly%2C%20we%20will%20drop%20any%20columns%20not%20relevant%20to%20our%20analysis.%20In%20this%20case%2C%20we%20will%20retain%20the%20geometry%20column%20and%20the%20%60building%60%20column.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings_2)%3A%0A%20%20%20%20gdf_buildings_3%20%3D%20gdf_buildings_2%5B%5B%22geometry%22%2C%20%22building%22%5D%5D%0A%20%20%20%20gdf_buildings_3.head()%0A%20%20%20%20return%20(gdf_buildings_3%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%20Before%20performing%20morphological%20analysis%2C%20it%20is%20necessary%20to%20ensure%20your%20data%20is%20in%20a%20**projected%20Coordinate%20Reference%20System%20(CRS)**.%20Morphological%20metrics%20often%20involve%20measurements%20of%20distance%20and%20area%2C%20which%20are%20only%20accurate%20in%20a%20projected%20CRS.%20For%20Nicosia%2C%20we%20will%20use%20EPSG%3A3035%20(ETRS89%20%2F%20LAEA%20Europe)%2C%20a%20European%20projection.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings_3)%3A%0A%20%20%20%20%23%20Set%20the%20target%20CRS%0A%20%20%20%20gdf_buildings_proj%20%3D%20gdf_buildings_3.to_crs(3035)%0A%20%20%20%20return%20(gdf_buildings_proj%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%20Let's%20replot%20the%20building%20data%20to%20ensure%20everything%20is%20in%20order.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(distance_m%2C%20gdf_buildings_proj%2C%20plt)%3A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(10%2C%2010)%2C%20dpi%3D150)%0A%20%20%20%20gdf_buildings_proj.plot(ax%3D_ax)%0A%20%20%20%20_ax.set_title(f%22Buildings%20within%20%7Bdistance_m%7D%20m%20of%20the%20study%20point%2C%20projected%20to%20EPSG%3A3035%22)%0A%20%20%20%20_ax.set_axis_off()%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%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%20momepy%0A%0A%20%20%20%20%5B%60momepy%60%5D(https%3A%2F%2Fmomepy.readthedocs.io%2F)%20is%20a%20library%20for%20the%20quantitative%20analysis%20of%20urban%20form%2C%20also%20known%20as%20urban%20morphology.%20It%20operates%20primarily%20on%20GeoDataFrames%20and%20provides%20a%20range%20of%20functions%20for%20calculating%20various%20morphological%20metrics.%0A%0A%20%20%20%20By%20way%20of%20example%2C%20we%20will%20explore%20two%20of%20these%20functions.%0A%0A%20%20%20%20%23%23%23%20Building%20Orientations%0A%0A%20%20%20%20%60momepy%60%20can%20calculate%20the%20orientation%20of%20building%20footprints%20using%20the%20%5B%60orientation%60%5D(https%3A%2F%2Fdocs.momepy.org%2Fen%2Fstable%2Fapi%2Fmomepy.orientation.html)%20function.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings_proj%2C%20momepy%2C%20plt)%3A%0A%20%20%20%20gdf_buildings_proj%5B%22orientation%22%5D%20%3D%20momepy.orientation(gdf_buildings_proj)%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(10%2C%2010)%2C%20dpi%3D150)%0A%20%20%20%20gdf_buildings_proj.plot(%0A%20%20%20%20%20%20%20%20ax%3D_ax%2C%0A%20%20%20%20%20%20%20%20column%3D%22orientation%22%2C%0A%20%20%20%20%20%20%20%20cmap%3D%22viridis%22%2C%0A%20%20%20%20%20%20%20%20legend%3DTrue%2C%0A%20%20%20%20%20%20%20%20legend_kwds%3D%7B%22label%22%3A%20%22Orientation%20(degrees%20from%20cardinal)%22%2C%20%22shrink%22%3A%200.6%7D%2C%0A%20%20%20%20)%0A%20%20%20%20_ax.set_title(%22Building%20orientations%22)%0A%20%20%20%20_ax.set_axis_off()%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%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%23%20Shared%20Walls%0A%0A%20%20%20%20%60momepy%60%20can%20calculate%20shared%20wall%20lengths%20between%20buildings%20using%20the%20%5B%60shared_walls%60%5D(https%3A%2F%2Fdocs.momepy.org%2Fen%2Fstable%2Fapi%2Fmomepy.shared_walls.html)%20function.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings_proj%2C%20momepy%2C%20plt)%3A%0A%20%20%20%20gdf_buildings_proj%5B%22shared_wall_length%22%5D%20%3D%20momepy.shared_walls(gdf_buildings_proj)%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(10%2C%2010)%2C%20dpi%3D150)%0A%20%20%20%20gdf_buildings_proj.plot(%0A%20%20%20%20%20%20%20%20ax%3D_ax%2C%0A%20%20%20%20%20%20%20%20column%3D%22shared_wall_length%22%2C%0A%20%20%20%20%20%20%20%20cmap%3D%22magma%22%2C%0A%20%20%20%20%20%20%20%20legend%3DTrue%2C%0A%20%20%20%20%20%20%20%20legend_kwds%3D%7B%22label%22%3A%20%22Shared%20wall%20length%20(m)%22%2C%20%22shrink%22%3A%200.6%7D%2C%0A%20%20%20%20)%0A%20%20%20%20_ax.set_title(%22Building%20shared%20wall%20lengths%22)%0A%20%20%20%20_ax.set_axis_off()%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%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%20Many%20other%20functions%20are%20available%20in%20%60momepy%60%20for%20calculating%20various%20morphological%20metrics.%20For%20a%20comprehensive%20list%2C%20please%20refer%20to%20the%20%5Bmomepy%20documentation%5D(https%3A%2F%2Fdocs.momepy.org%2Fen%2Fstable%2Fapi.html).%0A%0A%20%20%20%20%23%23%23%20Exercises%0A%0A%20%20%20%20-%20Use%20%60osmnx%60%20to%20download%20a%20different%20feature%20type%20(e.g.%2C%20parks%20with%20%60tags%3D%7B%22leisure%22%3A%20%22park%22%7D%60)%20for%20the%20same%20area.%20Plot%20the%20result.%0A%20%20%20%20-%20Explore%20the%20%60momepy%60%20documentation%20and%20calculate%20a%20different%20morphological%20metric%20(e.g.%2C%20%60momepy.elongation%60%20or%20%60momepy.circular_compactness%60)%20on%20the%20building%20footprints.%20What%20do%20the%20values%20tell%20you%20about%20building%20shapes%3F%0A%20%20%20%20-%20Download%20building%20footprints%20for%20a%20location%20of%20your%20choice%20(a%20different%20city%20or%20neighbourhood).%20Compare%20building%20orientations%20between%20the%20two%20areas.%0A%0A%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20This%20has%20been%20a%20brief%20exploration%20of%20the%20broader%20Python%20geospatial%20ecosystem%2C%20focusing%20on%20%60osmnx%60%20for%20downloading%20urban%20data%20from%20OpenStreetMap%20and%20%60momepy%60%20for%20conducting%20urban%20morphology%20analysis.%20This%20is%20just%20a%20small%20sample%20of%20what%20these%20and%20other%20tools%20can%20achieve.%0A%0A%20%20%20%20Remember%20that%20with%20GeoPandas%2C%20you%20can%20export%20your%20data.%20So%2C%20after%20downloading%20data%20and%20running%20any%20variety%20of%20metrics%20using%20available%20Python%20packages%2C%20you%20can%20then%20export%20the%20file%2C%20which%20can%20be%20further%20visualised%20or%20manipulated%20with%20packages%20such%20as%20QGIS.%20For%20example%2C%20you%20can%20export%20your%20data%20to%20a%20GeoPackage%20file%20using%20the%20%60to_file%60%20method%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(gdf_buildings_proj)%3A%0A%20%20%20%20gdf_buildings_proj.to_file(%22nicosia_buildings_metrics.gpkg%22%2C%20driver%3D%22GPKG%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%20Next%3A%20%5BData%20Science%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fstart%2F6-data-science)%20introduces%20dimensionality%20reduction%20and%20prediction%20with%20%60scikit-learn%60.%20The%20%60osmnx%60%20skills%20from%20this%20chapter%20are%20used%20in%20many%20of%20the%20%5BCityseer%20Recipes%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fexamples)%2C%20particularly%20the%20%5BNetwork%20Preparation%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fexamples%2Fnetworks)%20examples.%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
0ca7e0829e4d2d5f03881448e7b9aeb0