NetAnalyzer 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- NetAnalyzer/__init__.py +11 -0
- NetAnalyzer/adv_mat_calc.py +106 -0
- NetAnalyzer/cli_manager.py +331 -0
- NetAnalyzer/graph2sim.py +106 -0
- NetAnalyzer/integration.py +165 -0
- NetAnalyzer/main_modules.py +610 -0
- NetAnalyzer/net_parser.py +78 -0
- NetAnalyzer/net_plotter.py +200 -0
- NetAnalyzer/netanalyzer.py +1257 -0
- NetAnalyzer/performancer.py +83 -0
- NetAnalyzer/ranker.py +353 -0
- NetAnalyzer/seed_parser.py +27 -0
- NetAnalyzer/templates/net_explorer.txt +83 -0
- NetAnalyzer/templates/network.txt +1 -0
- NetAnalyzer-1.0.0.dist-info/LICENSE.txt +21 -0
- NetAnalyzer-1.0.0.dist-info/METADATA +86 -0
- NetAnalyzer-1.0.0.dist-info/RECORD +20 -0
- NetAnalyzer-1.0.0.dist-info/WHEEL +5 -0
- NetAnalyzer-1.0.0.dist-info/entry_points.txt +8 -0
- NetAnalyzer-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import glob
|
|
4
|
+
import numpy as np
|
|
5
|
+
import concurrent.futures
|
|
6
|
+
import itertools
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
class Kernels:
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.kernels_raw = [] # [Mat1, Mat2, Mat3,...]
|
|
13
|
+
self.local_indexes = [] # [{Node1 => idx1, Node2=> idx2},{Node1 => idx4, Node2 => idx2}]
|
|
14
|
+
self.general_nodes = [] # list of all nodes
|
|
15
|
+
self.kernels_position_index = {} # { Node1 => [idx1, idx2, None], Node2 => ...}
|
|
16
|
+
self.integrated_kernel = [] # [integrated_matrix, list_of_nodes]
|
|
17
|
+
|
|
18
|
+
def move2zero_reference(self):
|
|
19
|
+
moved_kernels = []
|
|
20
|
+
for idx, kernel in enumerate(self.kernels_raw):
|
|
21
|
+
min_kernel = np.min(kernel)
|
|
22
|
+
if min_kernel < 0:
|
|
23
|
+
logging.warning(f"Fixing negative values on matrix {idx}")
|
|
24
|
+
kernel -= min_kernel
|
|
25
|
+
moved_kernels.append(kernel)
|
|
26
|
+
self.kernels_raw = moved_kernels
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def load_kernels_by_bin_matrixes(self, input_matrix, input_nodes, kernels_names):
|
|
30
|
+
for pos, kernel_name in enumerate(kernels_names):
|
|
31
|
+
self.kernels_raw.append(np.load(input_matrix[pos]))
|
|
32
|
+
self.local_indexes.append(self.build_matrix_index(self.lst2arr(input_nodes[pos])))
|
|
33
|
+
|
|
34
|
+
def create_general_index(self):
|
|
35
|
+
self.general_nodes = []
|
|
36
|
+
for index in self.local_indexes:
|
|
37
|
+
self.general_nodes += index.keys()
|
|
38
|
+
self.general_nodes = sorted(list(set(self.general_nodes))) # Uniq elements and sorted to remove permutated matrixes.
|
|
39
|
+
|
|
40
|
+
for node in self.general_nodes:
|
|
41
|
+
self.kernels_position_index[node] = [ind.get(node) for ind in self.local_indexes]
|
|
42
|
+
self.local_indexes = [] # Removing not needed local indexes
|
|
43
|
+
|
|
44
|
+
def integrate(self, method, n_workers = 8, symmetry = True, n_partition_axis = None):
|
|
45
|
+
general_nodes = self.general_nodes.copy()
|
|
46
|
+
nodes_dimension = len(general_nodes)
|
|
47
|
+
general_kernel = np.zeros((nodes_dimension,nodes_dimension))
|
|
48
|
+
n_kernel = len(self.kernels_raw)
|
|
49
|
+
if n_partition_axis == None: n_partition_axis = int(np.trunc(np.sqrt(n_workers))) # Default value to use the corect number of blocks for n_workers
|
|
50
|
+
|
|
51
|
+
# Filling the argument section
|
|
52
|
+
splitted_general_nodes = list(self.split(general_nodes, n_partition_axis))
|
|
53
|
+
if symmetry:
|
|
54
|
+
pair_nodes = list(itertools.combinations_with_replacement(splitted_general_nodes, 2))
|
|
55
|
+
else:
|
|
56
|
+
pair_nodes = list(itertools.product(splitted_general_nodes, repeat = 2))
|
|
57
|
+
process_number = len(pair_nodes)
|
|
58
|
+
|
|
59
|
+
# Calling the multiprocessing
|
|
60
|
+
with concurrent.futures.ProcessPoolExecutor(max_workers=n_workers) as executor:
|
|
61
|
+
|
|
62
|
+
results = [executor.submit(self.build_matrix_block, pair_nodes[i][0],
|
|
63
|
+
pair_nodes[i][1], method, n_kernel, general_nodes, splitted_general_nodes, symmetry) for i in range(process_number)]
|
|
64
|
+
|
|
65
|
+
for f in concurrent.futures.as_completed(results):
|
|
66
|
+
row_start, row_end, col_start, col_end, block_matrix = f.result()
|
|
67
|
+
general_kernel[row_start:row_end, col_start:col_end] = block_matrix
|
|
68
|
+
if row_start != col_start and symmetry:
|
|
69
|
+
general_kernel[col_start:col_end, row_start:row_end] = block_matrix.transpose()
|
|
70
|
+
|
|
71
|
+
self.integrated_kernel = [general_kernel, self.general_nodes]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def build_matrix_block(self, row_nodes, col_nodes, method, n_kernel, general_nodes, splitted_general_nodes, symmetry):
|
|
75
|
+
general_block_matrix = np.zeros((len(row_nodes),len(col_nodes))) # TODO: Add option to considerar matrixes (maybe the min.
|
|
76
|
+
|
|
77
|
+
row_start = general_nodes.index(row_nodes[0])
|
|
78
|
+
row_end = row_start + len(row_nodes)
|
|
79
|
+
col_start = general_nodes.index(col_nodes[0])
|
|
80
|
+
col_end = col_start + len(col_nodes)
|
|
81
|
+
|
|
82
|
+
if symmetry and row_start == col_start:
|
|
83
|
+
# Filling main diagonal blocks with upper triang.
|
|
84
|
+
nodes_dimension = len(row_nodes)
|
|
85
|
+
i = 0
|
|
86
|
+
while len(row_nodes) > 0:
|
|
87
|
+
node_A = row_nodes[-1]
|
|
88
|
+
ind = len(row_nodes) - 1
|
|
89
|
+
for node_B in reversed(row_nodes):
|
|
90
|
+
j = ind
|
|
91
|
+
values = self.get_values(node_A, node_B)
|
|
92
|
+
if values:
|
|
93
|
+
reversed_i = nodes_dimension -1 - i
|
|
94
|
+
general_block_matrix[reversed_i, j] = method(values, n_kernel)
|
|
95
|
+
general_block_matrix[j, reversed_i] = general_block_matrix[reversed_i, j]
|
|
96
|
+
ind -= 1
|
|
97
|
+
row_nodes.pop()
|
|
98
|
+
i += 1
|
|
99
|
+
else:
|
|
100
|
+
# Filling all vs all
|
|
101
|
+
for i, node_A in enumerate(row_nodes):
|
|
102
|
+
for j, node_B in enumerate(col_nodes):
|
|
103
|
+
values = self.get_values(node_A, node_B)
|
|
104
|
+
if values:
|
|
105
|
+
general_block_matrix[i, j] = method(values, n_kernel)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
return row_start, row_end, col_start, col_end, general_block_matrix
|
|
109
|
+
|
|
110
|
+
def get_values(self, node_A, node_B):
|
|
111
|
+
rows = self.kernels_position_index[node_A]
|
|
112
|
+
cols = self.kernels_position_index[node_B]
|
|
113
|
+
values = []
|
|
114
|
+
for i, r_ind in enumerate(rows): #Load just the pairs in both sides of the kernel matrix
|
|
115
|
+
if r_ind is not None:
|
|
116
|
+
c_ind = cols[i] # Maybe a get is needed watch out!!!
|
|
117
|
+
if c_ind is not None:
|
|
118
|
+
values.append(self.kernels_raw[i][r_ind, c_ind])
|
|
119
|
+
return values
|
|
120
|
+
|
|
121
|
+
def mean(self, values, n_kernel):
|
|
122
|
+
return sum(values)/n_kernel
|
|
123
|
+
|
|
124
|
+
def mean_by_presence(self, values, n_kernel):
|
|
125
|
+
return sum(values)/len(values)
|
|
126
|
+
|
|
127
|
+
def median(self, values, n_kernel):
|
|
128
|
+
return np.median(values)
|
|
129
|
+
|
|
130
|
+
def max(self, values, n_kernel):
|
|
131
|
+
return max(values)
|
|
132
|
+
|
|
133
|
+
def geometric_mean(self, values, n_kernel):
|
|
134
|
+
# TODO: Talk about the possibility of improving execution time with a non-log formula.
|
|
135
|
+
# log to avoid overflows
|
|
136
|
+
return np.exp(np.log(values).mean())
|
|
137
|
+
|
|
138
|
+
def integrate_matrix(self, method, n_workers = 8, symmetry = True):
|
|
139
|
+
if method == "mean":
|
|
140
|
+
self.integrate(method = self.mean, n_workers = n_workers, symmetry = symmetry)
|
|
141
|
+
elif method == "integration_mean_by_presence":
|
|
142
|
+
self.integrate(method = self.mean_by_presence, n_workers = n_workers, symmetry = symmetry)
|
|
143
|
+
elif method == "median":
|
|
144
|
+
self.integrate(method = self.median, n_workers = n_workers, symmetry = symmetry)
|
|
145
|
+
elif method == "max":
|
|
146
|
+
self.integrate(method = self.max, n_workers = n_workers, symmetry = symmetry)
|
|
147
|
+
elif method == "geometric_mean":
|
|
148
|
+
self.integrate(method = self.geometric_mean, n_workers = n_workers, symmetry = symmetry)
|
|
149
|
+
|
|
150
|
+
## AUXILIAR METHODS
|
|
151
|
+
##############################
|
|
152
|
+
|
|
153
|
+
def split(self, a, n): # https://stackoverflow.com/questions/2130016/splitting-a-list-into-n-parts-of-approximately-equal-length
|
|
154
|
+
k, m = divmod(len(a), n)
|
|
155
|
+
return (a[i*k+min(i, m):(i+1)*k+min(i+1, m)] for i in range(n))
|
|
156
|
+
|
|
157
|
+
def lst2arr(self,lst_file):
|
|
158
|
+
nodes = []
|
|
159
|
+
with open(lst_file, "r") as file:
|
|
160
|
+
for line in file:
|
|
161
|
+
nodes.append(line.rstrip())
|
|
162
|
+
return nodes
|
|
163
|
+
|
|
164
|
+
def build_matrix_index(self, node_list):
|
|
165
|
+
return {node: i for i, node in enumerate(node_list)}
|