-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheval_functions.py
150 lines (105 loc) · 5.68 KB
/
eval_functions.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
import statistics
import networkx as nx
import numpy as np
class Evaluation:
#node-level topological properties
def in_degree_distribution(self, network) -> list[float]:
networkx_obj = network.getNetworkxObject()
num_nodes = network.numNodes
degree_sequence = list(d for _, d in networkx_obj.in_degree())
freq = [0]*(num_nodes+1)
for d in degree_sequence:
freq[d] += 1
return [x/num_nodes for x in freq]
def out_degree_distribution(self, network) -> list[float]:
networkx_obj = network.getNetworkxObject()
num_nodes = network.numNodes
degree_sequence = list(d for _, d in networkx_obj.out_degree())
freq = [0]*(num_nodes+1)
for d in degree_sequence:
freq[d] += 1
return [x/num_nodes for x in freq]
def avg_shortest_path_length_distribution(self, network) -> list[float]:
weight = 1/network.numNodes**2
shortest_path = dict(nx.shortest_path_length(network.getNetworkxObject()))
avg_shortest = sorted([weight*np.mean(list(shortest_path[i].values())) for i in range(len(shortest_path))], reverse=True)
return avg_shortest
def betweenness_distribution(self, network) -> list[float]:
networkx_obj = network.getNetworkxObject()
return sorted(list(nx.betweenness_centrality(networkx_obj).values()), reverse=True)
#topological properties
def connectance(self, network) -> float:
return network.numInteractions / network.numNodes**2
def clustering_coefficient(self, network) -> float:
return round(nx.average_clustering(network.getNetworkxObject()), 3)
def transitivity(self, network) -> float:
return round(nx.transitivity(network.getNetworkxObject()), 3)
def proportion_of_self_loops(self, network) -> float:
return sum([1 for i in range(network.numNodes) if network.adjacencyMatrix[i][i] != 0]) / network.numNodes
def diameter(self, network) -> int:
shortest_path = dict(nx.shortest_path_length(network.getNetworkxObject()))
return max([max(shortest_path[i].values()) for i in range(len(shortest_path))])
def number_of_modules(self, network) -> int:
if network.numInteractions > 0:
return len(nx.community.greedy_modularity_communities(network.getNetworkxObject()))
else:
return 0
#interaction strength properties
def positive_interactions_proportion(self, network) -> float:
num_interactions = network.numInteractions
return network.numPositive / num_interactions if num_interactions > 0 else 0
def average_positive_interactions_strength(self, network) -> float:
sum_pos = sum([sum([y for y in x if y > 0]) for x in network.adjacencyMatrix])
num_pos = network.numPositive
return round(sum_pos/num_pos, 3) if num_pos > 0 else 0
def average_negative_interactions_strength(self, network) -> float:
sum_neg = sum([sum([y for y in x if y < 0]) for x in network.adjacencyMatrix])
num_neg = network.numNegative
return round(sum_neg/num_neg, 3) if num_neg > 0 else 0
def variance_positive_interactions_strength(self, network) -> float:
flat = [x for y in network.adjacencyMatrix for x in y if x > 0]
if len(flat) < 2:
return 0
var_pos = statistics.variance(flat)
return round(var_pos, 3)
def variance_negative_interactions_strength(self, network) -> float:
flat = [x for y in network.adjacencyMatrix for x in y if x < 0]
if len(flat) < 2:
return 0
var_neg = statistics.variance(flat)
return round(var_neg, 3)
def proportion_of_self_loops_positive(self, network) -> float:
return sum([1 for i in range(network.numNodes) if network.adjacencyMatrix[i][i] > 0]) / network.numNodes
#motifs
def proportion_of_mutualistic_pairs(self, network) -> float:
adj = network.adjacencyMatrix
nn = network.numNodes
count_pairs = sum([sum([1 for j in range(i+1, nn) if adj[i][j] > 0 and adj[j][i] > 0]) for i in range(nn)])
possible_pairs = ((nn)*(nn-1))/2
return count_pairs / possible_pairs
def proportion_of_competition_pairs(self, network) -> float:
adj = network.adjacencyMatrix
nn = network.numNodes
count_pairs = sum([sum([1 for j in range(i+1, nn) if adj[i][j] < 0 and adj[j][i] < 0]) for i in range(nn)])
possible_pairs = ((nn)*(nn-1))/2
return count_pairs / possible_pairs
def proportion_of_parasitism_pairs(self, network) -> float:
adj = network.adjacencyMatrix
nn = network.numNodes
count_pairs = sum([sum([1 for j in range(i+1, nn) if (adj[i][j] < 0 and adj[j][i] > 0) or (adj[i][j] > 0 and adj[j][i] < 0)]) for i in range(nn)])
possible_pairs = ((nn)*(nn-1))/2
return count_pairs / possible_pairs
#all callable evaluation functions
functions = {funcName:getattr(Evaluation, funcName) for funcName in dir(Evaluation)
if callable(getattr(Evaluation, funcName)) and not funcName.startswith("__")}
#non-distribution callables
properties = {funcName:getattr(Evaluation, funcName) for funcName in dir(Evaluation)
if callable(getattr(Evaluation, funcName)) and not funcName.startswith("__") and
not funcName.endswith("_distribution")}
#distribution callables
distributions = {funcName:getattr(Evaluation, funcName) for funcName in dir(Evaluation)
if callable(getattr(Evaluation, funcName)) and not funcName.startswith("__") and
funcName.endswith("_distribution")}
if __name__ == "__main__":
e = Evaluation()
print(e.functions)