-
Notifications
You must be signed in to change notification settings - Fork 1
/
node_connectivity.py
126 lines (105 loc) · 4.84 KB
/
node_connectivity.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import numpy as np
import pandas as pd
import json
import matplotlib.pylab as plt
import networkx as nx
import os
import ntpath
import copy
import time
import util_defs
# EDA Plots
def plot_nodes_vs_ways(utild, cf):
"""
Plot frequency distribution of #Nodes in each way
TO DO : CHECK IF NODES SHOULD MEAN ALL THE NODES OR JUST NODES FROM WAYS
"""
coord_freq_dict = dict()
for elem in utild.ways_list:
if len(elem) not in coord_freq_dict.keys():
coord_freq_dict[len(elem)] = 1
else:
coord_freq_dict[len(elem)] += 1
lists = sorted(coord_freq_dict.items())
x, y = zip(*lists)
plt.xlim((0, 10))
plt.bar(x, y)
plt.title("Node distribution (limited to 10 nodes)")
plt.xlabel("Number of Nodes")
plt.ylabel("Number of Ways")
# plt.show(block=False)
save_path = os.path.join(cf.writePath,
(ntpath.basename(utild.ways_file).split('.')[0] + "_NodesVsWays.PNG"))
plt.savefig(save_path, format="PNG")
plt.clf()
def subgraph_eda(utild, cf):
"""
Calculates the number of subgraphs from the given ways_list
Plots a subraph and it's edges
"""
print("Number of ways in the file : ", len(utild.ways_list))
connected_df = utild.ways_df
connected_FG = nx.from_pandas_edgelist(connected_df, source='origin', target='dest')
print("Number of Subgraphs/islands : ",nx.number_connected_components(connected_FG))
print("Number of ways not connected to any other way: ", len(utild.disconnected_ways['features']))
print("Number of ways that are connected to atleast one other way: ", len(utild.connected_ways['features']))
subgraphs = [connected_FG.subgraph(c).copy() for c in nx.connected_components(connected_FG)]
for i in range(len(subgraphs)):
print("Number of ways in subgraph " + str(i) + ": " + str(len(subgraphs[i].nodes)))
ways_set = get_way_from_subgraph(subgraphs[i], connected_df)
write_geojson(utild, cf, ways_set, i)
def write_geojson(utild, cf, ways_set, sg_ind):
ways_json = copy.deepcopy(utild.ways_json)
ways_json['features'] = []
for id in sorted(ways_set):
ways_json['features'].append(utild.ways_json['features'][id])
ways_save_path = os.path.join(cf.writePath, (ntpath.basename(utild.ways_file).split('.')[0] + '_subgraph_' + str(sg_ind) + '.geojson'))
#print(ways_save_path)
util_defs.save_file(ways_save_path, ways_json)
def get_way_from_subgraph(sgraph, df):
"""
Networkx gives subgraphs. This function is to infer the 'way id' from the given subgraph.
Args : subgraph and df
Returns : set of ways that belong to subgraph
"""
ways_set = set()
for ind, edge in enumerate(sgraph.edges):
# Coordinates can be interchanged between origin and dest. Hence checking both ways
# either s1 or s2 gets a value which is index of the way from df, the given edge belongs to
s1 = pd.Series((df['origin'] == edge[-1]) & (df['dest'] == edge[0]))
s2 = pd.Series((df['origin'] == edge[0]) & (df['dest'] == edge[-1]))
s = s1[s1].index.tolist() + s2[s2].index.tolist()
ways_set.update(s)
return list(ways_set)
def save_file(path, json_file):
with open(path, 'w') as fp:
json.dump(json_file, fp, indent=4)
# Validations
def get_invalidNodes(utild, cf):
"""
From nodes_dict(N) and ways_dict(W), we obtain the set of Points
1. N - W : gives nodes that are stand alone and not part of any ways.
These nodes are invalid if they don't have at least one property
2. W - N : gives Ways that contain points that are not listed in the nodes file
"""
error_nodes_dict = dict()
error_ways_dict = dict()
# Nodes - Ways : The remaining nodes should have properties
diff_nodes = set(utild.nodes_coord_dict.keys()) - set(utild.ways_coord_dict.keys())
for node in diff_nodes:
node_id = utild.nodes_coord_dict[node]
if 'properties' not in utild.nodes_json['features'][node_id].keys() or not len(utild.nodes_json['features'][node_id]['properties']):
if node_id not in error_nodes_dict.keys():
error_nodes_dict[node_id] = [
"Point properties cannot be empty unless it is part of a way"]
# Ways - Nodes : Ways containing the remaining nodes are invalid. The nodes should be present in nodes file
diff_ways = set(utild.ways_coord_dict.keys()) - set(utild.nodes_coord_dict.keys())
for node in diff_ways:
for way_id in utild.ways_coord_dict[node]:
if way_id not in error_ways_dict.keys():
error_ways_dict[way_id] = [
str("Point " + node + " is not present in Nodes file")]
else:
error_ways_dict[way_id].append(
str("Point " + node + " is not present in Nodes file"))
return error_nodes_dict, error_ways_dict