-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrestructure_data.py
221 lines (177 loc) · 7.49 KB
/
restructure_data.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import json
# Please note: "conf_id" represents the "conf_key" in the output dictionary from the API
def create_children(node_id, nodes, edges_from):
"""
Creates children of nodes
:param node_id:
:param nodes:
:param edges_from:
:return:
"""
target_node = nodes[node_id]
if node_id in edges_from:
for child_id in edges_from[node_id]:
if 'children' not in target_node:
target_node['children'] = dict()
target_node['children'][child_id] = nodes[child_id]
create_children(child_id, nodes, edges_from)
def tree_structure(data_path):
"""
Converts the data from list structure to tree structure
:param data_path: relative path of where the data organized as list structure is located
:return:
"""
with open(data_path, 'r', encoding='utf-8') as f:
data = json.load(f)
for conf, conf_data in data.items():
nodes = dict()
edges_from = dict() # key = from node, list of nodes to
bld_node = None
model = conf_data['output']['model']
for node in model:
assert node['id'] not in nodes
nodes[node['id']] = node
if node['node_type'] == 'Building':
bld_node = node
edge_from = node['parent']
edge_to = node['id']
if edge_from is not None:
if edge_from not in edges_from:
edges_from[edge_from] = list()
edges_from[edge_from].append(edge_to)
assert bld_node is not None
create_children(bld_node['id'], nodes, edges_from)
return data
def find_building(data, conf_id):
for node in data[conf_id]['output']['model']:
if node['node_type'] == 'Building':
return node
raise Exception('No building found')
def find_node_from_node_instance_id(data, conf_id, node_id): # fra instans id
"""
USAGE: Hotspots_tree_2plots.py script, to allow for the user to select a node to investigate further.
:param data: The restructured data.
:param conf_id: Configuration id, example: conf_000000.json (the first keys in the dictionary containing all output from the API.)
:param node_id: Id if the node 'ElementInstance' in the output file from the API. For other types of instances model_id should be used.
# TODO: Add list of all types of instances that used node_id
:return:
"""
for node in data[conf_id]['output']['model']:
if node['id'] == node_id:
return node
raise Exception(f'No node for the given node id is found {node_id}')
def find_node_from_node_model_id(data, conf_id, node_model_id): # fra model id
"""
USAGE: Hotspots_tree_2plots.py script, to allow for the user to select a node to investigate further..
:param data: The restructured data.
:param conf_id: Configuration id, example: conf_000000.json (the first keys in the dictionary containing all output from the API.)
:param node_model_id: Used for the other types of instances model_id.
# TODO: Add list of all types of instances that used node_model_id
:return:
"""
for node in data[conf_id]['output']['model']:
if node['model_id'] == node_model_id:
return node
raise Exception(f'No node for the given node model id is found {node_model_id}')
def find_children_of_type(parent_node, child_type):
children_nodes = []
for child_id, child in parent_node['children'].items():
if child['node_type'] == child_type:
children_nodes.append(child)
return children_nodes
def find_one_child_of_type(parent_node, child_type):
only_child = find_children_of_type(parent_node, child_type)
assert len(only_child) == 1
return only_child[0]
def find_children_in_list(parent_node_list, child_type):
"""
Find children in a list.
:param parent_node_list:
:param child_type: = white_list
:return:
"""
children_nodes = []
for parent_node in parent_node_list:
children_list = find_children_of_type(parent_node, child_type)
children_nodes.extend(children_list)
return children_nodes
def find_all_children_of_type(target_node, child_type, save_data, allowed_cat):
"""
Recursive function
:param target_node:
:param child_type:
:param save_data:
:param allowed_cat: filter by white-list
:return:
"""
if target_node['node_type'] == child_type:
save_data.append(target_node)
if target_node['node_type'] == 'ElementCategoryInstance' and target_node['model_id'] not in allowed_cat:
return
if 'children' in target_node:
for _, child in target_node['children'].items():
find_all_children_of_type(child, child_type, save_data, allowed_cat)
def find_all_children_of_type_with_children(target_node, child_type, save_data):
"""
About: Recursive function that filters the target_nodes from which do not have children
allowed category is built into "and 'children' in target_node"
Usage: For one configuration
:param target_node: Starting point
:param child_type: Where you specify which type of node you want out (filter)
:param save_data: Input, output is used as the output list you dump to. The list must be empty when you call it the first time. This is the selected data you want to save
:return:
"""
if target_node['node_type'] == child_type and 'children' in target_node:
save_data.append(target_node)
# Runs through all children of a given target node
if 'children' in target_node:
for _, child in target_node['children'].items():
# Jumps down on a child and takes its new starting point in it
find_all_children_of_type_with_children(child, child_type, save_data)
# Hereafter is target_node = 'children'
def find_ancestor_of_type(target_id, conf_data, ancestor_target_node_type):
"""
Recursive function to find ancestor of type, not efficient function
:param target_id:
:param conf_data:
:param ancestor_target_node_type:
:return:
"""
target_node = None # svarer til ikke fundet nogen
for node in conf_data['output']['model']:
if node['id'] == target_id:
target_node = node
break
assert target_node is not None
if target_node['node_type'] == ancestor_target_node_type:
return target_node
else:
# target_node['parent'] # arget node when we call ourselves again
# if not found, it jumped a steps backwards into the tree data structure
return find_ancestor_of_type(target_node['parent'], conf_data, ancestor_target_node_type)
# TODO: Go backwards an find all ancestors? See def below
'''
def find_ancestor_backwards_tree(target_id, conf_data, ancestor_target_node_type):
"""
Recursive function to find the hierarchy of ancestor of type,
Work in progress - not efficient operation
:param target_id:
:param conf_data:
:param ancestor_target_node_type:
:return:
"""
target_node = None
for node in conf_data['output']['model']:
if node['id'] == target_id:
target_node = node
break
assert target_node is not None
if target_node['node_type'] == ancestor_target_node_type:
return target_node
else:
# Target node when we call ourselves again
# target_node['parent']
# If not found, it jumped a notch backwards into the tree
# return find_ancestor_of_type(target_node['parent'], conf_data, ancestor_target_node_type)
# save_data
'''