Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions examples/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

import linkbikenet as lbn

lbn.settings.import_path = '/Users/mszell/Tresorit/bikenetkitshare/'
city_id = "aachen_de"

edges_ordered = lbn.linkbikenet(
"Budapest",
connection_strategy='closest_components'
"Aachen",
connection_strategy='closest_components',
import_files={
'city_boundary': 'boundaries/'+city_id+'.geojson',
'street_network': 'streetbike_networks/'+city_id+'.gpkg',
},
)
2 changes: 1 addition & 1 deletion linkbikenet/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
"""

TOP_CLOSEST_COMPONENTS = 5
_PROGRESS_BAR_DESC_LENGTH = 21
_PROGRESS_BAR_DESC_LENGTH = 23
_PROGRESS_BAR_LENGTH = 23
55 changes: 41 additions & 14 deletions linkbikenet/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ def pair_between_largest_components(G, wcc):
the following info: 'lcc_nodeid', 'comp_nodeid', 'distance_eucl',
'lcc', 'comp'
"""
closest_pairs = pd.DataFrame(columns=['lcc_nodeid','comp_nodeid','distance_eucl','lcc','comp'])
G1 = wcc[0]
G2 = wcc[1]
best_topn_distance = np.inf
Expand All @@ -274,7 +275,6 @@ def pair_between_largest_components(G, wcc):
# Build KD-tree
tree = cKDTree(coords2)

closest_pairs = pd.DataFrame(columns=['lcc_nodeid','comp_nodeid','distance_eucl','lcc','comp'])
# Query the nearest node in G2 for every node in G1
for n1, data in G1.nodes(data=True):
coord = np.array([data["x"], data["y"]])
Expand All @@ -294,6 +294,8 @@ def pair_between_largest_components(G, wcc):
closest_pairs = pd.concat([closest_pairs, new_row]).reset_index(drop=True)
closest_pairs = closest_pairs.nsmallest(constants.TOP_CLOSEST_COMPONENTS, 'distance_eucl')
best_topn_distance = closest_pairs['distance_eucl'].iloc[-1]
if closest_pairs.empty:
return None
return closest_pairs.nsmallest(constants.TOP_CLOSEST_COMPONENTS,'distance_eucl')

def get_underway_connections(H, pairinfo, components_sorted):
Expand Down Expand Up @@ -340,7 +342,9 @@ def pair_between_largest_and_closest_components(wcc):
the following info: 'lcc_nodeid', 'comp_nodeid', 'distance_eucl',
'lcc', 'comp'
"""
closest_pairs = pd.DataFrame(columns=['lcc_nodeid','comp_nodeid','distance_eucl','lcc','comp'])
lcc = wcc[0]
best_topn_distance = np.inf

# Build KD-tree for the largest component
lcc_nodes = list(lcc.nodes())
Expand All @@ -350,7 +354,6 @@ def pair_between_largest_and_closest_components(wcc):
])
tree = cKDTree(lcc_xy)

closest_pairs = pd.DataFrame(columns=['lcc_nodeid','comp_nodeid','distance_eucl','lcc','comp'])
# Compare every remaining component to the lcc
for comp in wcc[1:]:
comp_nodes = list(comp.nodes())
Expand All @@ -359,8 +362,29 @@ def pair_between_largest_and_closest_components(wcc):
for n in comp_nodes
])
distances, indices = tree.query(comp_xy)
i = np.argmin(distances)
closest_pairs.loc[len(closest_pairs)] = [lcc_nodes[indices[i]], comp_nodes[i], distances[i], lcc, comp] # To do: Optimize. Never grow a dataframe. Could use code from pair_between_closest_components()
k = np.argmin(distances)
# if type(distances[k]) is not float: # If all are disconnected, abort
# print(distances[k], type(distances[k]))
# sys.exit()
# continue
if len(closest_pairs) < constants.TOP_CLOSEST_COMPONENTS: # Start filling up
closest_pairs.loc[len(closest_pairs)] = [lcc_nodes[indices[k]], comp_nodes[k], float(distances[k]), lcc, comp]
closest_pairs.sort_values(by=['distance_eucl'], inplace=True)
best_topn_distance = closest_pairs['distance_eucl'].iloc[-1]
elif distances[k] < best_topn_distance: # Append only if better than top N
new_row = pd.DataFrame({
'lcc_nodeid': [lcc_nodes[indices[k]]],
'comp_nodeid': [comp_nodes[k]],
'distance_eucl': [float(distances[k])],
'lcc': [lcc],
'comp': [comp],
})
closest_pairs = pd.concat([closest_pairs, new_row]).reset_index(drop=True)
closest_pairs = closest_pairs.nsmallest(constants.TOP_CLOSEST_COMPONENTS, 'distance_eucl')
best_topn_distance = closest_pairs['distance_eucl'].iloc[-1]

if closest_pairs.empty:
return None
return closest_pairs.nsmallest(constants.TOP_CLOSEST_COMPONENTS,'distance_eucl')

def pair_between_closest_components(wcc):
Expand All @@ -382,41 +406,44 @@ def pair_between_closest_components(wcc):
closest_pairs = pd.DataFrame(columns=['lcc_nodeid','comp_nodeid','distance_eucl','lcc','comp'])
best_topn_distance = np.inf


for i in range(len(wcc) - 1):
G1 = wcc[i]
nodes1 = list(G1.nodes())
lcc = wcc[i]
nodes1 = list(lcc.nodes())
coords1 = np.array([
(G1.nodes[n]["x"], G1.nodes[n]["y"])
(lcc.nodes[n]["x"], lcc.nodes[n]["y"])
for n in nodes1
])
tree = cKDTree(coords1)

# By construction, G1 is larger than G2
# By construction, lcc is larger than comp
for j in range(i + 1, len(wcc)):
G2 = wcc[j]
nodes2 = list(G2.nodes())
comp = wcc[j]
nodes2 = list(comp.nodes())
coords2 = np.array([
(G2.nodes[n]["x"], G2.nodes[n]["y"])
(comp.nodes[n]["x"], comp.nodes[n]["y"])
for n in nodes2
])

distances, indices = tree.query(coords2)
k = np.argmin(distances)
if len(closest_pairs) < constants.TOP_CLOSEST_COMPONENTS: # Start filling up
closest_pairs.loc[len(closest_pairs)] = [nodes1[indices[k]], nodes2[k], distances[k], G1, G2]
closest_pairs.loc[len(closest_pairs)] = [nodes1[indices[k]], nodes2[k], distances[k], lcc, comp]
closest_pairs.sort_values(by=['distance_eucl'], inplace=True)
best_topn_distance = closest_pairs['distance_eucl'].iloc[-1]
elif distances[k] < best_topn_distance: # Append only if better than top N
new_row = pd.DataFrame({
'lcc_nodeid': [nodes1[indices[k]]],
'comp_nodeid': [nodes2[k]],
'distance_eucl': [distances[k]],
'lcc': [G1],
'comp': [G2],
'lcc': [lcc],
'comp': [comp],
})
closest_pairs = pd.concat([closest_pairs, new_row]).reset_index(drop=True)
closest_pairs = closest_pairs.nsmallest(constants.TOP_CLOSEST_COMPONENTS, 'distance_eucl')
best_topn_distance = closest_pairs['distance_eucl'].iloc[-1]
if closest_pairs.empty:
return None
return closest_pairs


Expand Down
16 changes: 8 additions & 8 deletions linkbikenet/linkbikenet.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,15 @@ def linkbikenet(
city_boundary = ox.geocoder.geocode_to_gdf(city_query)

if import_files['bike_network'] is not None:
progress_bar = initialize_progress_bar("Importing bike network data", 1, "network")
progress_bar = initialize_progress_bar("Importing network data", 1, "network")
h = import_bike_network(import_files['bike_network'])
nodes_h = ox.graph_to_gdfs(h, nodes=True, edges=False, node_geometry=True)
proj_crs = resolve_crs_calculations(nodes_h, settings.crs_projected)
h = ox.project_graph(h, to_crs=proj_crs)
h = nx.Graph(h)

if import_files['street_network'] is not None:
progress_bar = initialize_progress_bar("Importing bike network data", 1, "network")
progress_bar = initialize_progress_bar("Importing network data", 1, "network")
g = import_network(import_files['street_network'])

else:
Expand Down Expand Up @@ -251,11 +251,11 @@ def linkbikenet(
components_sorted = [H.subgraph(c).copy() for c in sorted(nx.connected_components(H), key=lambda c: sum(
[l[-1] for l in H.subgraph(c).copy().edges.data('length')]), reverse=True)]
pair_candidates = pair_between_largest_and_closest_components(components_sorted)
if pair_candidates.isnull().values.all(): # Completely disconnected - ignore it
continue
if pair_candidates is None: # Completely disconnected - ignore it
continue # To do: remove component
pairinfo = shortest_path_components_from_candidates(G, pair_candidates)
if pairinfo['path'] is None: # Completely disconnected - ignore it
continue
continue # To do: remove component
pathedges = path_to_edges(pairinfo['path'])
paths_all.append(pairinfo['path'])
G_path = G.subgraph(pairinfo['path']).copy()
Expand All @@ -279,11 +279,11 @@ def linkbikenet(
components_sorted = [H.subgraph(c).copy() for c in sorted(nx.connected_components(H), key=lambda c: sum(
[l[-1] for l in H.subgraph(c).copy().edges.data('length')]), reverse=True)]
pair_candidates = pair_between_closest_components(components_sorted)
if pair_candidates.isnull().values.all(): # Completely disconnected - ignore it
continue
if pair_candidates is None: # Completely disconnected - ignore it
continue # To do: remove component
pairinfo = shortest_path_components_from_candidates(G, pair_candidates)
if pairinfo['path'] is None: # Completely disconnected - ignore it
continue
continue # To do: remove component
pathedges = path_to_edges(pairinfo['path'])
paths_all.append(pairinfo['path'])
G_path = G.subgraph(pairinfo['path']).copy()
Expand Down
Loading