Districts (with OSM data)#

District should be derived using a car-based street network and for an area that is larger than the case study area (see below, e.g. for the city centre of London one should use Greater London)

[3]:
import osmnx as ox, networkx as nx, matplotlib.cm as cm, pandas as pd, numpy as np
import geopandas as gpd
from shapely.geometry import Point, mapping
%matplotlib inline

import warnings
warnings.simplefilter(action="ignore")
pd.options.display.float_format = '{:20.2f}'.format
pd.options.mode.chained_assignment = None

import cityImage as ci

Acquiring the Street Network#

[4]:
city_name = 'Muenster'
epsg = 25832
crs = 'EPSG:'+str(epsg)

Download from OSM thedrive** network**

Choose between the following methods:

  • OSMplace, provide an OSM place name (e.g. City).

  • polygon, provide an WGS polygon of the case-study area.

  • distance_from_address, provide a precise address and define parameter distance (which is otherwise not necessary)

[5]:
place = 'Muenster, Germany'
download_method = 'OSMplace'
distance = None

nodes_graph, edges_graph = ci.get_network_fromOSM(place, download_method, 'drive', epsg, distance = distance)
nodes_graph, edges_graph = ci.clean_network(nodes_graph, edges_graph, dead_ends = True, remove_islands = True,
                            self_loops = True, same_vertexes_edges = True)

# Creating and saving the dual geodataframes
nodesDual_graph, edgesDual_graph = ci.dual_gdf(nodes_graph, edges_graph, epsg)

Visualisation

[5]:
fig = ci.plot_gdf(edges_graph, black_background = False, figsize = (10,10), title = city_name+': Street Network - drive')
../_images/notebooks_Districts_fromOSM_7_0.png

District identification#

[6]:
# creating the dual_graph
dual_graph = ci.dual_graph_fromGDF(nodesDual_graph, edgesDual_graph)

Different weights can be used to extract the partitions. None indicates that no weights will be used (only topological relationships will matter). The function returns a GeoDataFrame with partitions assigned to edges, with column named as p_name_weight (e.g. p_length).

[7]:
weights = ['length', 'rad', None]
districts = edges_graph.copy()
for weight in weights:
    districts = ci.identify_regions(dual_graph, districts, weight = weight)

Visualisation

[8]:
columns = ['p_length','p_rad', 'p_topo']
titles = ['Partition - Distance', 'Partition - Angles', 'Partition - Topological']

nlabels = max([len(districts[column].unique()) for column in columns])
cmap = ci.rand_cmap(nlabels = nlabels, type_color='bright')
fig = ci.plot_grid_gdf_columns(districts, columns = columns, titles = titles, geometry_size = 1.5, cmap = cmap, black_background = True,
                  legend = False, figsize = (15, 10), ncols = 3, nrows = 1)
../_images/notebooks_Districts_fromOSM_13_0.png
[9]:
for n, column in enumerate(columns):
    cmap = ci.rand_cmap(nlabels = len(districts[column].unique()), type_color='bright')
    partitions = ci.polygonise_partitions(districts, column, convex_hull = False)
    ci.plot_gdf(partitions, column = column, cmap = cmap, title =  titles[n], black_background = True,  figsize = (7, 5),
               base_map_gdf = districts, base_map_color = 'grey', base_map_zorder = 1)
../_images/notebooks_Districts_fromOSM_14_0.png
../_images/notebooks_Districts_fromOSM_14_1.png
../_images/notebooks_Districts_fromOSM_14_2.png

Exporting

[30]:
# provide path
output_path = '../output/'+city_name
ci.remove_lists_columns(districts).to_file(output_path+"_edges_districts.gpkg",  driver="GPKG")

Assigning regions to the Pedestrian Street Network#

Case-study area (pedestrian walkable network)

This set of functions assigns regions to a walkable network for further modelling in Pedestrian Simulation, for example. The simply identification of regions (districts) from the urban configuration ends above.

Get the pedestrian network from OSM:

Choose between the following methods:

  • OSMplace, provide an OSM place name (e.g. City).

  • polygon, provide an WGS polygon of the case-study area.

  • distance_from_address, provide a precise address and define parameter distance (which is otherwise not necessary)

[31]:
place = 'Domplatz, Muenster, Germany' ## must be different from the area used for the drive network
download_method = 'distance_from_address'
distance = 2500

nodes_graph_ped, edges_graph_ped = ci.get_network_fromOSM(place, download_method, 'walk', epsg, distance = distance)
nodes_graph_ped, edges_graph_ped = ci.clean_network(nodes_graph_ped, edges_graph_ped, dead_ends = True,
                                remove_islands = True, self_loops = True, same_vertexes_edges = True)

Visualisation

[32]:
fig = ci.plot_gdf(edges_graph_ped, black_background = False, figsize = (10,10), title = city_name+': Street Network - walk',
                  color = 'red', geometry_size = 0.3)
../_images/notebooks_Districts_fromOSM_20_0.png
[33]:
fig = ci.plot_gdf(edges_graph_ped, scheme = None,  black_background = False, figsize = (10,10), title =
              city_name+': Entire Street Network vs Case-study area', color = 'red', geometry_size = 0.2,
             base_map_gdf = edges_graph, base_map_color = 'black', base_map_alpha = 0.3)
../_images/notebooks_Districts_fromOSM_21_0.png

Assigning nodes and edges in the pedestrian network to the Partitions#

[34]:
# choosing the type of partition to be used
column = 'p_length'
min_size_district = 10
[35]:
dc = dict(districts[column].value_counts())

## ignore small portions
to_ignore = {k: v for k, v in dc.items() if v <= min_size_district}
tmp = districts[~((districts[column].isin(to_ignore))| (districts[column] == 999999))].copy()

partitions = ci.polygonise_partitions(tmp, column)
nodes_graph_ped = ci.district_to_nodes_from_polygons(nodes_graph_ped, partitions, column)
nodes_graph_ped[column] = nodes_graph_ped[column].astype(int)

Visualisation

[37]:
cmap = ci.rand_cmap(nlabels = len(nodes_graph_ped[column].unique()), type_color='bright')
fig = ci.plot_gdf(nodes_graph_ped, column = column, title = 'Districts assigned to pedestrian SN', cmap = cmap,
                  geometry_size = 3.5, base_map_gdf = edges_graph_ped, base_map_color = 'white', base_map_alpha = 0.35,
                black_background = True, legend = False, figsize = (10,10))
../_images/notebooks_Districts_fromOSM_26_0.png

Fixing disconnected districts and assigning nodes to existing connected districts#

[38]:
nodes_graph_ped = ci.amend_nodes_membership(nodes_graph_ped, edges_graph_ped, column, min_size_district)

# assigning gateways
nodes_graph_ped = ci.find_gateways(nodes_graph_ped, edges_graph_ped, column)

Final Sub-division in Districts/Regions#

[39]:
cmap = ci.rand_cmap(nlabels = len(nodes_graph_ped[column].unique()), type_color='bright')
fig = ci.plot_gdf(nodes_graph_ped, column = column, title = 'Districts assigned to pedestrian SN - after correction',
               cmap = cmap, geometry_size = 3.5, base_map_gdf = edges_graph_ped, base_map_color = 'white',
                  base_map_alpha = 0.35, black_background = True, legend = False, figsize = (10,10))
../_images/notebooks_Districts_fromOSM_30_0.png

Exporting

[46]:
nodes_graph_ped['district'] = nodes_graph_ped[column].astype(int)
nodes_graph_ped.to_file(output_path+"_nodes_ped.gpkg", driver="GPKG")
edges_graph_ped.to_file(output_path+"_edges_ped.gpkg", driver="GPKG")