-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMethods.py
More file actions
473 lines (388 loc) · 16.1 KB
/
Copy pathMethods.py
File metadata and controls
473 lines (388 loc) · 16.1 KB
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
from utilities import Modules
from utilities import DataPoints
'''
__Initialize__ Returns "dataPoints", this is a Points object that contains all the points from the dataset.
vars:
M: Data in matrix form
nPoints: Number of points we want to look at
returns:
dataPoints: input data represented as Points object
'''
'''
params:
M: data matrix
n: nbr of points in total from data
timeOverlap: % overlap between frames in time
nFrames: number of frames
eps, min_samples: params for clustering algorithm
variable: what variable is used for coloring
returns:
frameClusters: array with nFrames elements, each element is a Groups object, containing the clusters
found in the corresponding frame.
intervalse: array with start and stop for frame intervals
'''
def __GetClustersFromFrames__(M, n, timeOverlap, nFrames, eps, min_samples, variableValues):
intervals = Modules.np.zeros([nFrames, 2])
covlen = int(n/(nFrames-(nFrames-1)*timeOverlap))
frameClusters = []
OUTLIERS = DataPoints.Points()
for i in range(0, len(M[0, :]), 1):
M[:,i] = M[:,i]/Modules.np.std(M[:,i])
#M[:, i] = (M[:, i]-Modules.np.multiply(Modules.np.ones(len(M[:,i])), Modules.np.mean(M[:,i]))) / Modules.np.std(M[:, i])
for i in range(0, nFrames, 1):
frm2 = int(-covlen * i + timeOverlap*covlen * i)
to2 = frm2 - covlen
intervals[i,0] = to2
intervals[i,1] = frm2
dataPoints = DataPoints.Points()
dataPoints.__dataToPoints__(M, to2, frm2) #Frm2 is closest in time
variableValuesTMP = variableValues[len(variableValues) + to2:len(variableValues) + frm2]
for j in range(0, len(dataPoints.pList), 1):
dataPoints.pList[j].value = variableValuesTMP[len(variableValuesTMP)- j - 1]
clusters, labelArray, ntot, outliers = __ClusterDBSCAN__(points=dataPoints, eps=eps, min_samples=min_samples)
'''IF NO CLUSTERS ARE FOUND WE HAVE TO BE CAREFUL! FIX THIS TMRW!!! '''
for j in range(0, len(outliers.pList), 1):
OUTLIERS.__add__(outliers.pList[j])
if ntot != 0:
temp = clusters.__getKernelsList__()
clusters.kernels = temp
'''for j in range(0, len(clusters.groupArray), 1): #values are set here, move this pls
clusters.groupArray[j].val = i+1'''
frameClusters.append(clusters)
'''print("FRAME " + str(nFrames - (i)) + ": INTERVAL: " + str(to2) + " TO " + str(frm2) +
", HAS " + " P:" + str(len(labelArray[0]))
+ " O: " + str(len(outliers.pList)) + " C: " + str(len(clusters.groupArray)))'''
print("FRAME " + str(nFrames - (i)) + ": " + " P: " + str(len(labelArray[0]))
+ " O: " + str(len(outliers.pList)) + " C: " + str(len(clusters.groupArray)))
else:
frameClusters.append([])
print("FRAME " + str(nFrames-(i+1)) + ": INTERVAL " + str(to2) + " TO " + str(frm2) + " HAS NO CLUSTERS")
frameClusters = frameClusters[::-1]
return frameClusters, intervals, OUTLIERS
'''
params:
points: pts to be clustered
eps: radius for "checking adjacent points"
min_samples: min nr of pts in a cluster
returns:
clusters: groups object with point groups that are seen as clusters
labelsArray: array with information about which points belong to which cluster
ntot: nbr of clusters
outliers: outlier points in points object
'''
def __ClusterDBSCAN__(points, eps, min_samples):
clusters = DataPoints.Groups()
outliers = DataPoints.Points()
labelsArray = []
ntot = 0
if isinstance(points.__getPosMat__(), Modules.numbers.Number) == False:
X = []
posMat = points.__getPosMat__()
X = Modules.StandardScaler().fit_transform(posMat)
#dist = Modules.DistanceMetric.get_metric('euclidean')
#db = Modules.DBSCAN(eps=eps, min_samples=min_samples, metric=dist).fit(X)
db = Modules.DBSCAN(eps=eps, min_samples=min_samples).fit(X)
core_samples_mask = Modules.np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_
labelsArray.append(labels)
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
ntot = ntot + n_clusters_
for i in range(-1, n_clusters_, 1):
pointsTmp = DataPoints.Points()
for j in range(0, len(labels) - 1, 1):
if labels[j] == i:
pointsTmp.__add__((points.pList[j]))
if i != -1:
clusters.__add__(pointsTmp)
else:
for k in range(0, len(pointsTmp.pList), 1):
outliers.__add__(pointsTmp.pList[k])
return clusters, labelsArray, ntot, outliers
'''
params:
frameClusters: Frames and their corresponding clusters
returns:
EVOLUTION: Array with len(frameclusters)-1 elements, each element is an mxn matrix, where each element in the matrix
tells us the distance between kernel i in the frame with index in the array EVO + 1, and kernel j in the
previous frame.
'''
def __CompareKernels__(frameClusters):
EVOLUTION = []
for i in range(1, len(frameClusters), 1):
EVTMP = Modules.np.zeros([len(frameClusters[i].kernels),len(frameClusters[i-1].kernels)])
for j in range(0, len(frameClusters[i].kernels), 1):
for k in range(0, len(frameClusters[i-1].kernels), 1):
tmp = Modules.np.linalg.norm(Modules.np.subtract(frameClusters[i].kernels[j]
, frameClusters[i-1].kernels[k]))
EVTMP[j, k] = tmp
EVOLUTION.append(EVTMP)
return EVOLUTION
def __CompareKernelsFIX__(frameClusters):
EVOLUTION = []
Modules.pdb.set_trace()
run = False
if frameClusters[0] != []:
run = True
for i in range(1, len(frameClusters), 1):
if frameClusters[i] != [] and run == True:
Modules.pdb.set_trace()
EVTMP = Modules.np.zeros([len(frameClusters[i].kernels),len(frameClusters[i-1].kernels)])
for j in range(0, len(frameClusters[i].kernels), 1):
for k in range(0, len(frameClusters[i-1].kernels), 1):
tmp = Modules.np.linalg.norm(Modules.np.subtract(frameClusters[i].kernels[j]
, frameClusters[i-1].kernels[k]))
EVTMP[j, k] = tmp
else:
run = False
if frameClusters[i] != []:
run = True
EVTMP = []
EVOLUTION.append(EVTMP)
return EVOLUTION
'''
params:
intervals: frame intervals
returns:
fromTo: array containing information about what frames are included in each window
'''
def __ConnectedFrames__(intervals):
fromTo = []
for i in range(0, len(intervals), 1):
LOWER = Modules.np.abs(intervals[i][0])
set = False
for j in range(0, len(intervals), 1):
CURRENT = Modules.np.abs(intervals[j][1])
if CURRENT > LOWER and set == False:
fromTo.append([j-1, i])
set = True
if set == False:
fromTo.append([len(intervals)-1, i])
fromTo = fromTo[::-1]
for i in range(0, len(fromTo), 1):
fromTo[i][0] = Modules.np.abs(fromTo[i][0]-len(fromTo)+1)
fromTo[i][1] = Modules.np.abs(fromTo[i][1]-len(fromTo)+1)
return fromTo
'''
params:
EVOLUTION: Contains information about distances between kernels from different frames
tolerance: radius within which kernels are connected
returns:
CONNECTIONS: Array with len(frameclusters)-1 elements, each element is an mxn matrix, where each element in the matrix
tells wether kernel i in the frame with index in the array EVO + 1, and kernel j in the
previous frame are to be connected with an edge with respect to the given tolerance.
'''
def __Connections__(EVOLUTION, tolerance):
CONNECTIONS = []
for i in range(0, len(EVOLUTION), 1):
tmp = Modules.np.zeros([len(EVOLUTION[i][:,0]), len(EVOLUTION[i][0,:])])
for j in range(0, len(EVOLUTION[i][:,0]), 1):
for k in range(0, len(EVOLUTION[i][0,:]), 1):
if EVOLUTION[i][j, k] <= tolerance:
tmp[j, k] = 1
else:
tmp[j, k] = 0
CONNECTIONS.append(tmp)
return CONNECTIONS
'''
params:
evo: evolution array, check __CompareKernels__ method for more detailed explanation
con: conn array, check __Connections__ method foro more detailed explanation
indx: ... check Connectedframes ...
frameClusters: ... check GetClustersFromFrame ...
returns:
NODES: All nodes, eg. 1, 2, ... , n
WINDOWNODES: All nodes that are contained in each window.
WINDOWEDGES: All edges that are contained within each window
SIZES: Nbr of pts in the clusters corresponding to each node
VALUES: values for clusters corresponding to nodes
FRAMENODES: Nodes within each frame
'''
def __MakeFrameGraphs__(evo, con, indx, frameClusters):
NODES = []
FRAMENODES = []
FRAMEEDGES = []
WINDOWEDGES = []
SIZES = []
VALUES = []
FRAMEWIDTH = []
WINDOWWIDTH = []
#Creates values and sizes
for i in range(0, len(frameClusters), 1):
for j in range(0, len(frameClusters[i].groupArray)):
SIZES.append(len(frameClusters[i].groupArray[j].pList))
VALUES.append(frameClusters[i].groupArray[j].__getValue__())
#Creates nodes
for i in range(0, len(evo), 1):
if i == 0:
tmp = Modules.np.zeros(len(evo[0][0]))
for j in range(1, len(tmp)+1, 1):
NODES.append(j)
tmp[j-1] = j
FRAMENODES.append(tmp)
tmp2 = Modules.np.zeros(len(evo[i]))
tmp3 = NODES[len(NODES)-1]
for j in range(1, len(tmp2) + 1, 1):
tmp2[j-1] = tmp3 + j
NODES.append(NODES[len(NODES)-1]+1)
FRAMENODES.append(tmp2)
#Finds edges in frames
for i in range(0, len(con), 1):
tmp = []
tmp2 = []
for j in range(0, len(con[i][0]), 1):
for k in range(0, len(con[i]), 1):
if con[i][k][j] == 1:
tmp2.append(evo[i][k][j])
tmp.append([int(FRAMENODES[i][j]), int(FRAMENODES[i+1][k])])
FRAMEWIDTH.append(tmp2)
FRAMEEDGES.append(tmp)
# Finds edges in windows
WINDOWNODES = []
out = indx[len(indx)-1][1]
for i in range(0, len(indx), 1):
tmp = []
tmp2 = []
for j in range(indx[i][0], indx[i][1], 1):
for k in range(0, len(FRAMEEDGES[j]), 1):
tmp2.append(FRAMEWIDTH[j][k])
tmp.append(FRAMEEDGES[j][k])
WINDOWEDGES.append(tmp)
WINDOWWIDTH.append(tmp2)
WINDOWNODES = []
#Finds nodes in windows
for i in range(0, len(indx), 1):
tmp = []
for j in range(indx[i][0], indx[i][1]+1, 1):
for k in range(0, len(FRAMENODES[j]), 1):
tmp.append(int(FRAMENODES[j][k]))
WINDOWNODES.append(tmp)
return NODES, WINDOWNODES, WINDOWEDGES, WINDOWWIDTH, SIZES, VALUES, FRAMENODES
'''
params:
nodes: Nodes..
values: values for the nodes
returns:
colors_sorted: colors for the nodes based on their values
'''
def __graphColorAssignment__(nodes, values):
'''Because the "Colours" module works so poorly with networkx getting colors to allign with values for the
clusters is abit of a hassle. It includes adding together multiple lists of colors, removing colors from the list
that are not compatible with the networkx draw fcn and lastly actually assigning colors to the clusters//nodes based
on which percentile of the value we look at it is in.'''
intervals = 99
intThird = 33
breaks = Modules.np.zeros(intervals)
for i in range(0, intervals, 1):
breaks[i] = Modules.np.percentile(values, int(100 / intervals * i))
from1 = Modules.Color("#a100ff")
to1 = Modules.Color("#00a9ff")
to2 = Modules.Color("#50ff00")
to3 = Modules.Color("#ff0000")
colors = list(from1.range_to(to1, intThird))
colors.extend(list(to1.range_to(to2, intThird)))
colors.extend(list(to2.range_to(to3, intThird)))
colors_tmp = []
for i in range(0, len(colors), 1):
colors_tmp.append(str(colors[i]))
for i in range(0, len(colors_tmp), 1):
if len(colors_tmp[i]) < 5:
colors_tmp[i] = colors_tmp[Modules.np.abs(i - 1)]
colors_sorted = []
for i in range(0, len(nodes), 1):
set = 0
for j in range(0, intervals, 1):
lower = Modules.np.percentile(values, round(100 / intervals * j))
upper = Modules.np.percentile(values, round(100 / intervals * (j + 1)))
valTmp = values[i]
if lower <= valTmp <= upper and set == 0:
colors_sorted.append(colors_tmp[j])
set = 1
if set == 0:
colors_sorted.append(str(Modules.Color("black")))
return colors_sorted
'''
params:
wndtmp: nodes in windows
szstmp: sizes for all nodes
clrstmp: colors for allnodes
returns:
szs: sizes for nodes in certian window
clrs: colors for nodes in certian window
'''
def __GraphProperties__(wndtmp, szstmp, clrstmp):
szs = []
clrs = []
for i in range(0, len(wndtmp), 1):
tmp1 = []
tmp2 = []
for j in range(int(wndtmp[i][0]-1), int(wndtmp[i][len(wndtmp[i])-1]), 1):
tmp1.append(szstmp[j])
tmp2.append(clrstmp[j])
szs.append(tmp1)
clrs.append(tmp2)
return szs, clrs
'''
params:
edg: edges
wnd: nodes in windows
wdth: edge widths
szs: node sizes
clrs: node colors
lbls: labels? true/false
returns:
none, but plots graphs
'''
def __MakeGraphs__(edg, wnd, wdth, szs, clrs, lbls):
for i in range(len(wnd)-1, -1, -1):
Modules.mp.figure()
G = Modules.nx.Graph()
G.add_nodes_from(wnd[i])
G.add_edges_from(edg[i])
pos = Modules.nx.spring_layout(G, dim=2, iterations=90)
sizes = Modules.np.add(Modules.np.multiply(szs[i], .4), Modules.np.ones(len(szs[i])) * 50) # resizers
width = 1/(Modules.np.multiply(0.3, wdth[i])+Modules.np.multiply(.1, Modules.np.ones(len(wdth[i]))))
Modules.nx.draw(G, with_labels=lbls, node_size=sizes, pos=pos, alpha=0.6, node_color=clrs[i], width=width)
Modules.mp.savefig(r'C:\Users\arvid\Desktop\TDA\PlotSaves\100fig shows split\Plot{}.png'.format(i))
'''
params:
node: the node you want the kernel for
frameClusters: clusters in frames
frameNodes: nodes in frames
returns:
kernel: the kernel corresponding to the node which was specified in the input
'''
def __getClusterFromNode__(frameClusters, frameNodes, node):
frame = 0
frameIndx = 0
for i in range(0, node, 1):
if frameIndx == len(frameClusters[frame].groupArray):
frameIndx = 0
frame = frame + 1
if frameNodes[frame][frameIndx] == node:
return frameClusters[frame].groupArray[frameIndx]
frameIndx = frameIndx + 1
return "Node not found"
def __windowIntervals__(indx, intervals):
print()
for i in range(0, len(indx), 1):
frm = intervals[len(intervals)-1-indx[i][0]][0]
to = intervals[len(intervals)-1-indx[i][1]][1]
print("WINDOW " + str(i+1) + " COVERS THE INTERVAL: " + str(frm) + " TO " + str(to))
def __PlotCovers__(intervals, A):
Modules.mp.figure()
Modules.mp.plot(A[:, 0])
Modules.mp.plot(A[:, 1])
Modules.mp.plot(A[:, 2])
Modules.mp.plot(A[:, 3])
Modules.mp.plot(A[:, 4])
Modules.mp.plot(A[:, 5])
Modules.mp.plot(A[:, 6])
Modules.mp.plot(A[:, 7])
Modules.mp.plot(A[:, 8])
Modules.mp.plot(A[:, 9])
for i in range(0, len(intervals), 1):
Modules.mp.plot([-intervals[i][0], -intervals[i][1]],
[Modules.np.mean(A[:, 0]) - 10 + i * 2, Modules.np.mean(A[:, 0]) - 10 + i * 2], 'ro-')
Modules.mp.show()
Modules.mp.figure()