simba-uw-tf-dev 4.7.4__py3-none-any.whl → 4.7.6__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.
- simba/SimBA.py +1180 -1178
- simba/assets/.recent_projects.txt +1 -0
- simba/mixins/feature_extraction_mixin.py +0 -2
- simba/mixins/geometry_mixin.py +357 -302
- simba/outlier_tools/skip_outlier_correction.py +2 -2
- simba/plotting/heat_mapper_clf_mp.py +45 -23
- simba/plotting/plot_clf_results.py +2 -1
- simba/plotting/plot_clf_results_mp.py +456 -455
- simba/sandbox/av1.py +5 -0
- simba/sandbox/denoise_hqdn3d.py +266 -0
- simba/sandbox/extract_random_frames.py +126 -0
- simba/sandbox/remove_end_of_video.py +80 -80
- simba/ui/import_pose_frame.py +13 -13
- simba/ui/pop_ups/clf_plot_pop_up.py +1 -1
- simba/ui/pop_ups/video_processing_pop_up.py +11 -10
- simba/ui/video_timelaps.py +158 -36
- simba/video_processors/video_processing.py +20 -13
- {simba_uw_tf_dev-4.7.4.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/METADATA +1 -1
- {simba_uw_tf_dev-4.7.4.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/RECORD +23 -20
- {simba_uw_tf_dev-4.7.4.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/LICENSE +0 -0
- {simba_uw_tf_dev-4.7.4.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/WHEEL +0 -0
- {simba_uw_tf_dev-4.7.4.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/entry_points.txt +0 -0
- {simba_uw_tf_dev-4.7.4.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/top_level.txt +0 -0
simba/SimBA.py
CHANGED
|
@@ -1,1178 +1,1180 @@
|
|
|
1
|
-
__author__ = "Simon Nilsson; sronilsson@gmail.com"
|
|
2
|
-
|
|
3
|
-
from simba.utils.printing import SimbaTimer,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
warnings.filterwarnings("ignore", category=
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
from tkinter
|
|
21
|
-
from tkinter.
|
|
22
|
-
from
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
from simba.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
from simba.mixins.
|
|
34
|
-
from simba.
|
|
35
|
-
from simba.model.
|
|
36
|
-
from simba.model.
|
|
37
|
-
from simba.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
from simba.third_party_label_appenders.
|
|
47
|
-
from simba.third_party_label_appenders.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
from simba.
|
|
55
|
-
from simba.ui.
|
|
56
|
-
from simba.ui.
|
|
57
|
-
from simba.ui.
|
|
58
|
-
from simba.ui.
|
|
59
|
-
from simba.ui.pop_ups.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
from simba.ui.pop_ups.
|
|
67
|
-
from simba.ui.pop_ups.
|
|
68
|
-
from simba.ui.pop_ups.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
from simba.ui.pop_ups.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
from simba.ui.pop_ups.
|
|
79
|
-
from simba.ui.pop_ups.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
from simba.ui.pop_ups.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
from simba.ui.pop_ups.
|
|
92
|
-
from simba.ui.pop_ups.
|
|
93
|
-
from simba.ui.pop_ups.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
from simba.ui.pop_ups.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
from simba.ui.pop_ups.
|
|
104
|
-
from simba.ui.pop_ups.
|
|
105
|
-
from simba.ui.pop_ups.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
from simba.ui.pop_ups.
|
|
109
|
-
from simba.ui.pop_ups.
|
|
110
|
-
from simba.ui.pop_ups.
|
|
111
|
-
from simba.ui.pop_ups.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
from simba.ui.pop_ups.
|
|
115
|
-
from simba.ui.pop_ups.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
from simba.ui.pop_ups.
|
|
119
|
-
from simba.ui.pop_ups.
|
|
120
|
-
from simba.ui.pop_ups.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
from simba.ui.pop_ups.
|
|
130
|
-
from simba.ui.pop_ups.
|
|
131
|
-
from simba.ui.pop_ups.
|
|
132
|
-
from simba.ui.pop_ups.
|
|
133
|
-
from simba.ui.pop_ups.
|
|
134
|
-
from simba.ui.pop_ups.
|
|
135
|
-
from simba.ui.pop_ups.
|
|
136
|
-
from simba.ui.pop_ups.
|
|
137
|
-
from simba.ui.pop_ups.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
from simba.ui.pop_ups.
|
|
143
|
-
from simba.ui.pop_ups.
|
|
144
|
-
from simba.ui.pop_ups.
|
|
145
|
-
from simba.ui.pop_ups.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
from simba.ui.pop_ups.
|
|
151
|
-
from simba.ui.pop_ups.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
from simba.ui.pop_ups.
|
|
163
|
-
from simba.ui.pop_ups.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
from simba.ui.pop_ups.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
from simba.ui.pop_ups.
|
|
195
|
-
from simba.ui.pop_ups.
|
|
196
|
-
from simba.ui.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
from simba.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
from simba.utils.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
from simba.utils.
|
|
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
|
-
self.main_frm
|
|
239
|
-
self.main_frm.
|
|
240
|
-
self.
|
|
241
|
-
|
|
242
|
-
self.
|
|
243
|
-
self.
|
|
244
|
-
self.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
self.load_project_frm
|
|
248
|
-
self.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
self.
|
|
255
|
-
self.
|
|
256
|
-
self.load_recent_frm.
|
|
257
|
-
self.
|
|
258
|
-
self.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
self.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
simongui
|
|
287
|
-
simongui.
|
|
288
|
-
simongui.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
project_name =
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
simongui.
|
|
297
|
-
simongui.
|
|
298
|
-
|
|
299
|
-
self.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
tab_style
|
|
307
|
-
tab_style.configure('Custom.TNotebook
|
|
308
|
-
tab_style.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
tab_parent.add(
|
|
331
|
-
tab_parent.add(
|
|
332
|
-
tab_parent.add(
|
|
333
|
-
tab_parent.add(
|
|
334
|
-
tab_parent.add(
|
|
335
|
-
tab_parent.add(
|
|
336
|
-
tab_parent.add(
|
|
337
|
-
tab_parent.add(
|
|
338
|
-
tab_parent.add(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
tab_parent.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
import_frm
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
self.
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
self.new_ROI_frm.
|
|
367
|
-
self.
|
|
368
|
-
self.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
self.roi_draw.
|
|
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
|
-
self.
|
|
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
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
self.
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
self.
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
'
|
|
500
|
-
'
|
|
501
|
-
'
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
sklearn_visualization_btn
|
|
525
|
-
|
|
526
|
-
gantt_visualization_btn
|
|
527
|
-
|
|
528
|
-
probability_visualization_btn
|
|
529
|
-
|
|
530
|
-
path_visualization_btn
|
|
531
|
-
|
|
532
|
-
distance_visualization_btn
|
|
533
|
-
|
|
534
|
-
heatmap_clf_visualization_btn
|
|
535
|
-
|
|
536
|
-
data_plot_visualization_btn = SimbaButton(parent=visualization_frm,
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
clf_validation_btn
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
plotlyCheckbox[i]
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
self.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
button_bel = SimbaButton(parent=lbl_addon, txt="
|
|
563
|
-
|
|
564
|
-
cue_light_analyser_btn = SimbaButton(parent=lbl_addon, txt="
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
self.
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
self.
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
self.
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
unsupervised_btn
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
video_info_tabler.
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
outlier_correction_skipper.
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
model_trainer
|
|
695
|
-
model_trainer.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
model_trainer
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
interactive_grapher.
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
self.
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
#
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
feature_extractor_classes = get_bp_config_code_class_pairs()
|
|
791
|
-
if self.user_defined_var.get():
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
if self.pose_setting
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
feature_extractor = feature_extractor_classes[self.pose_setting](config_path=self.config_path)
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
self.
|
|
831
|
-
|
|
832
|
-
self.root
|
|
833
|
-
self.root.
|
|
834
|
-
self.root.
|
|
835
|
-
self.root.
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
self.
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
background.image =
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
self.file_menu
|
|
858
|
-
|
|
859
|
-
self.file_menu.
|
|
860
|
-
self.
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
self.
|
|
867
|
-
|
|
868
|
-
self.file_menu.
|
|
869
|
-
|
|
870
|
-
self.file_menu.add_separator()
|
|
871
|
-
self.file_menu.add_command(label="
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
batch_process_menu
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
blob_tracking_menu
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
yolo_tracking_menu
|
|
885
|
-
yolo_tracking_menu.add_command(label="
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
fps_menu
|
|
892
|
-
fps_menu.add_command(label="
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
clip_video_menu
|
|
900
|
-
|
|
901
|
-
clip_video_menu.add_command(label="Clip
|
|
902
|
-
|
|
903
|
-
clip_video_menu.add_command(label="Clip multiple videos
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
crop_video_menu
|
|
910
|
-
crop_video_menu.add_command(label="Crop videos
|
|
911
|
-
crop_video_menu.add_command(label="
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
img_format_menu.add_command(label="Convert images to
|
|
923
|
-
img_format_menu.add_command(label="Convert images to
|
|
924
|
-
img_format_menu.add_command(label="Convert images
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
video_format_menu.add_command(label="Convert videos to
|
|
928
|
-
video_format_menu.add_command(label="Convert videos to
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
rm_clr_menu
|
|
936
|
-
rm_clr_menu.add_command(label="
|
|
937
|
-
rm_clr_menu.add_command(label="
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
concatenate_menu
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
convert_pose_file_format_menu
|
|
949
|
-
convert_pose_file_format_menu.add_command(label="
|
|
950
|
-
convert_pose_file_format_menu.add_command(label="
|
|
951
|
-
convert_pose_file_format_menu.add_command(label="DLC
|
|
952
|
-
convert_pose_file_format_menu.add_command(label="
|
|
953
|
-
convert_pose_file_format_menu.add_command(label="
|
|
954
|
-
convert_pose_file_format_menu.add_command(label="SLEAP
|
|
955
|
-
convert_pose_file_format_menu.add_command(label="
|
|
956
|
-
convert_pose_file_format_menu.add_command(label="
|
|
957
|
-
convert_pose_file_format_menu.add_command(label="
|
|
958
|
-
convert_pose_file_format_menu.add_command(label="
|
|
959
|
-
convert_pose_file_format_menu.add_command(label="Labelme
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
convert_data_menu
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
downsample_video_menu
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
extract_frames_menu
|
|
977
|
-
extract_frames_menu.add_command(label="Extract frames
|
|
978
|
-
extract_frames_menu.add_command(label="Extract frames from
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
video_process_menu.
|
|
982
|
-
|
|
983
|
-
video_process_menu.add_command(label="
|
|
984
|
-
|
|
985
|
-
video_process_menu.add_command(label="
|
|
986
|
-
video_process_menu.add_command(label="Change video
|
|
987
|
-
video_process_menu.add_command(label="
|
|
988
|
-
video_process_menu.add_command(label="
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
rotate_menu
|
|
996
|
-
rotate_menu.add_command(label="
|
|
997
|
-
rotate_menu.add_command(label="
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
superimpose_menu
|
|
1003
|
-
superimpose_menu.add_command(label="Superimpose
|
|
1004
|
-
superimpose_menu.add_command(label="Superimpose
|
|
1005
|
-
superimpose_menu.add_command(label="Superimpose
|
|
1006
|
-
superimpose_menu.add_command(label="Superimpose
|
|
1007
|
-
superimpose_menu.add_command(label="Superimpose
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
remove_bg_menu
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
temporal_join_videos
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
video_process_menu.
|
|
1021
|
-
video_process_menu.add_command(label="
|
|
1022
|
-
video_process_menu.add_command(label="
|
|
1023
|
-
video_process_menu.add_command(label="
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
download_menu
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
links_menu.
|
|
1040
|
-
links_menu.add_command(label="
|
|
1041
|
-
links_menu.add_command(label="SimBA
|
|
1042
|
-
links_menu.add_command(label="
|
|
1043
|
-
links_menu.add_command(label="SimBA
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
help_menu.
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
self.
|
|
1052
|
-
self.r_click_menu
|
|
1053
|
-
self.r_click_menu.add_command(label="
|
|
1054
|
-
self.r_click_menu.
|
|
1055
|
-
self.r_click_menu.add_command(label="
|
|
1056
|
-
|
|
1057
|
-
self.
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
self.txt.
|
|
1062
|
-
self.txt.
|
|
1063
|
-
self.txt.tag_configure(TagNames.
|
|
1064
|
-
self.txt.tag_configure(TagNames.
|
|
1065
|
-
self.txt.tag_configure(TagNames.
|
|
1066
|
-
self.txt.tag_configure(TagNames.
|
|
1067
|
-
self.txt.tag_configure("
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
self.txt.insert(INSERT, Defaults.WELCOME_MSG.value + "\n" * 2)
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
self.txt.
|
|
1075
|
-
y_sb.
|
|
1076
|
-
self.txt.
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
self.r_click_menu.
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
self.
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
self.text_space.
|
|
1161
|
-
self.text_space.
|
|
1162
|
-
self.text_space.
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
ctypes
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1
|
+
__author__ = "Simon Nilsson; sronilsson@gmail.com"
|
|
2
|
+
|
|
3
|
+
from simba.utils.printing import (SimbaTimer, stdout_information,
|
|
4
|
+
stdout_success, stdout_warning)
|
|
5
|
+
|
|
6
|
+
load_timer = SimbaTimer(start=True)
|
|
7
|
+
import os.path
|
|
8
|
+
import warnings
|
|
9
|
+
|
|
10
|
+
warnings.filterwarnings("ignore", category=FutureWarning)
|
|
11
|
+
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
|
12
|
+
import atexit
|
|
13
|
+
import platform
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
import threading
|
|
17
|
+
import tkinter.ttk as ttk
|
|
18
|
+
import urllib.request
|
|
19
|
+
import webbrowser
|
|
20
|
+
from tkinter import *
|
|
21
|
+
from tkinter.filedialog import askdirectory
|
|
22
|
+
from tkinter.messagebox import askyesno
|
|
23
|
+
from typing import Union
|
|
24
|
+
|
|
25
|
+
import PIL.Image
|
|
26
|
+
from PIL import ImageTk
|
|
27
|
+
|
|
28
|
+
from simba.bounding_box_tools.boundary_menus import BoundaryMenus
|
|
29
|
+
from simba.labelling.labelling_advanced_interface import \
|
|
30
|
+
select_labelling_video_advanced
|
|
31
|
+
from simba.labelling.targeted_annotations_clips import \
|
|
32
|
+
select_labelling_video_targeted_clips
|
|
33
|
+
from simba.mixins.config_reader import ConfigReader
|
|
34
|
+
from simba.mixins.pop_up_mixin import PopUpMixin
|
|
35
|
+
from simba.model.grid_search_rf import GridSearchRandomForestClassifier
|
|
36
|
+
from simba.model.inference_validation import InferenceValidation
|
|
37
|
+
from simba.model.train_rf import TrainRandomForestClassifier
|
|
38
|
+
from simba.outlier_tools.outlier_corrector_location import \
|
|
39
|
+
OutlierCorrecterLocation
|
|
40
|
+
from simba.outlier_tools.outlier_corrector_movement import \
|
|
41
|
+
OutlierCorrecterMovement
|
|
42
|
+
from simba.outlier_tools.skip_outlier_correction import \
|
|
43
|
+
OutlierCorrectionSkipper
|
|
44
|
+
from simba.plotting.interactive_probability_grapher import \
|
|
45
|
+
InteractiveProbabilityGrapher
|
|
46
|
+
from simba.third_party_label_appenders.BENTO_appender import BentoAppender
|
|
47
|
+
from simba.third_party_label_appenders.BORIS_appender import BorisAppender
|
|
48
|
+
from simba.third_party_label_appenders.deepethogram_importer import \
|
|
49
|
+
DeepEthogramImporter
|
|
50
|
+
from simba.third_party_label_appenders.ethovision_import import \
|
|
51
|
+
ImportEthovision
|
|
52
|
+
from simba.third_party_label_appenders.observer_importer import \
|
|
53
|
+
NoldusObserverImporter
|
|
54
|
+
from simba.third_party_label_appenders.solomon_importer import SolomonImporter
|
|
55
|
+
from simba.ui.create_project_ui import ProjectCreatorPopUp
|
|
56
|
+
from simba.ui.import_pose_frame import ImportPoseFrame
|
|
57
|
+
from simba.ui.import_videos_frame import ImportVideosFrame
|
|
58
|
+
from simba.ui.machine_model_settings_ui import MachineModelSettingsPopUp
|
|
59
|
+
from simba.ui.pop_ups.about_simba_pop_up import AboutSimBAPopUp
|
|
60
|
+
from simba.ui.pop_ups.animal_directing_other_animals_pop_up import \
|
|
61
|
+
AnimalDirectingAnimalPopUp
|
|
62
|
+
from simba.ui.pop_ups.append_roi_features_animals_pop_up import \
|
|
63
|
+
AppendROIFeaturesByAnimalPopUp
|
|
64
|
+
from simba.ui.pop_ups.append_roi_features_bodypart_pop_up import \
|
|
65
|
+
AppendROIFeaturesByBodyPartPopUp
|
|
66
|
+
from simba.ui.pop_ups.archive_files_pop_up import ArchiveProcessedFilesPopUp
|
|
67
|
+
from simba.ui.pop_ups.batch_preprocess_pop_up import BatchPreProcessPopUp
|
|
68
|
+
from simba.ui.pop_ups.blob_visualizer_pop_up import BlobVisualizerPopUp
|
|
69
|
+
from simba.ui.pop_ups.boolean_conditional_slicer_pup_up import \
|
|
70
|
+
BooleanConditionalSlicerPopUp
|
|
71
|
+
from simba.ui.pop_ups.change_speed_popup import ChangeSpeedPopup
|
|
72
|
+
from simba.ui.pop_ups.check_videos_seekable_pop_up import \
|
|
73
|
+
CheckVideoSeekablePopUp
|
|
74
|
+
from simba.ui.pop_ups.clf_add_remove_print_pop_up import (
|
|
75
|
+
AddClfPopUp, PrintModelInfoPopUp, RemoveAClassifierPopUp)
|
|
76
|
+
from simba.ui.pop_ups.clf_annotation_counts_pop_up import \
|
|
77
|
+
ClfAnnotationCountPopUp
|
|
78
|
+
from simba.ui.pop_ups.clf_by_roi_pop_up import ClfByROIPopUp
|
|
79
|
+
from simba.ui.pop_ups.clf_by_timebins_pop_up import TimeBinsClfPopUp
|
|
80
|
+
from simba.ui.pop_ups.clf_descriptive_statistics_pop_up import \
|
|
81
|
+
ClfDescriptiveStatsPopUp
|
|
82
|
+
from simba.ui.pop_ups.clf_plot_pop_up import SklearnVisualizationPopUp
|
|
83
|
+
from simba.ui.pop_ups.clf_probability_plot_pop_up import \
|
|
84
|
+
VisualizeClassificationProbabilityPopUp
|
|
85
|
+
from simba.ui.pop_ups.clf_validation_plot_pop_up import \
|
|
86
|
+
ClassifierValidationPopUp
|
|
87
|
+
from simba.ui.pop_ups.coco_keypoints_to_yolo_popup import \
|
|
88
|
+
COCOKeypoints2YOLOkeypointsPopUp
|
|
89
|
+
from simba.ui.pop_ups.csv_2_parquet_pop_up import (Csv2ParquetPopUp,
|
|
90
|
+
Parquet2CsvPopUp)
|
|
91
|
+
from simba.ui.pop_ups.cue_light_main_popup import CueLightMainPopUp
|
|
92
|
+
from simba.ui.pop_ups.data_plot_pop_up import DataPlotterPopUp
|
|
93
|
+
from simba.ui.pop_ups.delete_all_rois_pop_up import delete_all_rois_pop_up
|
|
94
|
+
from simba.ui.pop_ups.directing_animal_to_bodypart_plot_pop_up import \
|
|
95
|
+
DirectingAnimalToBodyPartVisualizerPopUp
|
|
96
|
+
from simba.ui.pop_ups.directing_other_animals_plot_pop_up import \
|
|
97
|
+
DirectingOtherAnimalsVisualizerPopUp
|
|
98
|
+
from simba.ui.pop_ups.direction_animal_to_bodypart_settings_pop_up import \
|
|
99
|
+
DirectionAnimalToBodyPartSettingsPopUp
|
|
100
|
+
from simba.ui.pop_ups.distance_plot_pop_up import DistancePlotterPopUp
|
|
101
|
+
from simba.ui.pop_ups.dlc_h5_inference_to_yolo_popup import \
|
|
102
|
+
DLCH5Inference2YoloPopUp
|
|
103
|
+
from simba.ui.pop_ups.dlc_to_labelme_popup import DLC2LabelmePopUp
|
|
104
|
+
from simba.ui.pop_ups.dlc_to_yolo_keypoints_popup import DLCYoloKeypointsPopUp
|
|
105
|
+
from simba.ui.pop_ups.egocentric_alignment_pop_up import EgocentricAlignPopUp
|
|
106
|
+
from simba.ui.pop_ups.extract_annotation_frames_pop_up import \
|
|
107
|
+
ExtractAnnotationFramesPopUp
|
|
108
|
+
from simba.ui.pop_ups.fsttc_pop_up import FSTTCPopUp
|
|
109
|
+
from simba.ui.pop_ups.gantt_pop_up import GanttPlotPopUp
|
|
110
|
+
from simba.ui.pop_ups.heatmap_clf_pop_up import HeatmapClfPopUp
|
|
111
|
+
from simba.ui.pop_ups.heatmap_location_pop_up import HeatmapLocationPopup
|
|
112
|
+
from simba.ui.pop_ups.initialize_blob_tracking_pop_up import \
|
|
113
|
+
InitializeBlobTrackerPopUp
|
|
114
|
+
from simba.ui.pop_ups.interpolate_pop_up import InterpolatePopUp
|
|
115
|
+
from simba.ui.pop_ups.kleinberg_pop_up import KleinbergPopUp
|
|
116
|
+
from simba.ui.pop_ups.labelme_bbox_to_yolo_bbox_popup import \
|
|
117
|
+
LabelmeBbox2YoloBboxPopUp
|
|
118
|
+
from simba.ui.pop_ups.labelme_to_df_popup import Labelme2DataFramePopUp
|
|
119
|
+
from simba.ui.pop_ups.labelme_to_imgs_popup import Labelme2ImgsPopUp
|
|
120
|
+
from simba.ui.pop_ups.make_path_plot_pop_up import MakePathPlotPopUp
|
|
121
|
+
from simba.ui.pop_ups.merge_coco_keypoint_files_pop_up import \
|
|
122
|
+
MergeCOCOKeypointFilesPopUp
|
|
123
|
+
from simba.ui.pop_ups.movement_analysis_pop_up import \
|
|
124
|
+
MovementAnalysisPopUp # ## LAZY
|
|
125
|
+
from simba.ui.pop_ups.movement_analysis_time_bins_pop_up import \
|
|
126
|
+
MovementAnalysisTimeBinsPopUp
|
|
127
|
+
from simba.ui.pop_ups.multiple_videos_to_frames_popup import \
|
|
128
|
+
MultipleVideos2FramesPopUp
|
|
129
|
+
from simba.ui.pop_ups.mutual_exclusivity_pop_up import MutualExclusivityPupUp
|
|
130
|
+
from simba.ui.pop_ups.outlier_settings_pop_up import OutlierSettingsPopUp
|
|
131
|
+
from simba.ui.pop_ups.path_plot_pop_up import PathPlotPopUp
|
|
132
|
+
from simba.ui.pop_ups.pose_bp_drop_pop_up import DropTrackingDataPopUp
|
|
133
|
+
from simba.ui.pop_ups.pose_reorganizer_pop_up import PoseReorganizerPopUp
|
|
134
|
+
from simba.ui.pop_ups.print_video_meta_popup import PrintVideoMetaDataPopUp
|
|
135
|
+
from simba.ui.pop_ups.pup_retrieval_pop_up import PupRetrievalPopUp
|
|
136
|
+
from simba.ui.pop_ups.quick_path_plot_pop_up import QuickLineplotPopup
|
|
137
|
+
from simba.ui.pop_ups.remove_roi_features_pop_up import RemoveROIFeaturesPopUp
|
|
138
|
+
from simba.ui.pop_ups.roi_aggregate_stats_popup import \
|
|
139
|
+
ROIAggregateDataAnalyzerPopUp
|
|
140
|
+
from simba.ui.pop_ups.roi_analysis_time_bins_pop_up import \
|
|
141
|
+
ROIAnalysisTimeBinsPopUp
|
|
142
|
+
from simba.ui.pop_ups.roi_features_plot_pop_up import VisualizeROIFeaturesPopUp
|
|
143
|
+
from simba.ui.pop_ups.roi_tracking_plot_pop_up import VisualizeROITrackingPopUp
|
|
144
|
+
from simba.ui.pop_ups.roi_video_table_pop_up import ROIVideoTable
|
|
145
|
+
from simba.ui.pop_ups.run_machine_models_popup import RunMachineModelsPopUp
|
|
146
|
+
from simba.ui.pop_ups.select_video_for_labelling_popup import \
|
|
147
|
+
SelectLabellingVideoPupUp
|
|
148
|
+
from simba.ui.pop_ups.select_video_for_pseudo_labelling_popup import \
|
|
149
|
+
SelectPseudoLabellingVideoPupUp
|
|
150
|
+
from simba.ui.pop_ups.severity_analysis_pop_up import AnalyzeSeverityPopUp
|
|
151
|
+
from simba.ui.pop_ups.simba_rois_to_yolo_pop_up import SimBAROIs2YOLOPopUp
|
|
152
|
+
from simba.ui.pop_ups.simba_to_yolo_keypoints_popup import \
|
|
153
|
+
SimBA2YoloKeypointsPopUp
|
|
154
|
+
from simba.ui.pop_ups.single_video_to_frames_popup import \
|
|
155
|
+
SingleVideo2FramesPopUp
|
|
156
|
+
from simba.ui.pop_ups.sleap_annotations_to_yolo_popup import \
|
|
157
|
+
SLEAPAnnotations2YoloPopUp
|
|
158
|
+
from simba.ui.pop_ups.sleap_csv_predictions_to_yolo_popup import \
|
|
159
|
+
SLEAPcsvInference2Yolo
|
|
160
|
+
from simba.ui.pop_ups.sleap_h5_inference_to_yolo_popup import \
|
|
161
|
+
SLEAPH5Inference2YoloPopUp
|
|
162
|
+
from simba.ui.pop_ups.smoothing_popup import SmoothingPopUp
|
|
163
|
+
from simba.ui.pop_ups.splash_popup import SplashMovie
|
|
164
|
+
from simba.ui.pop_ups.spontaneous_alternation_pop_up import \
|
|
165
|
+
SpontaneousAlternationPopUp # ## LAZY
|
|
166
|
+
from simba.ui.pop_ups.subset_feature_extractor_pop_up import \
|
|
167
|
+
FeatureSubsetExtractorPopUp
|
|
168
|
+
from simba.ui.pop_ups.third_party_annotator_appender_pop_up import \
|
|
169
|
+
ThirdPartyAnnotatorAppenderPopUp
|
|
170
|
+
from simba.ui.pop_ups.validation_plot_pop_up import ValidationVideoPopUp
|
|
171
|
+
from simba.ui.pop_ups.video_processing_pop_up import (
|
|
172
|
+
BackgroundRemoverDirectoryPopUp, BackgroundRemoverSingleVideoPopUp,
|
|
173
|
+
BoxBlurPopUp, BrightnessContrastPopUp, CalculatePixelsPerMMInVideoPopUp,
|
|
174
|
+
ChangeFpsMultipleVideosPopUp, ChangeFpsSingleVideoPopUp, CLAHEPopUp,
|
|
175
|
+
ClipSingleVideoByFrameNumbers, ClipVideoPopUp, ConcatenatingVideosPopUp,
|
|
176
|
+
ConcatenatorPopUp, Convert2AVIPopUp, Convert2BlackWhitePopUp,
|
|
177
|
+
Convert2bmpPopUp, Convert2jpegPopUp, Convert2MOVPopUp, Convert2MP4PopUp,
|
|
178
|
+
Convert2PNGPopUp, Convert2TIFFPopUp, Convert2WEBMPopUp, Convert2WEBPPopUp,
|
|
179
|
+
ConvertROIDefinitionsPopUp, CreateAverageFramePopUp, CreateGIFPopUP,
|
|
180
|
+
CropVideoCirclesPopUp, CropVideoPolygonsPopUp, CropVideoPopUp,
|
|
181
|
+
CrossfadeVideosPopUp, DownsampleMultipleVideosPopUp,
|
|
182
|
+
DownsampleSingleVideoPopUp, ExtractSEQFramesPopUp,
|
|
183
|
+
ExtractSpecificFramesPopUp, FlipVideosPopUp, GreyscaleSingleVideoPopUp,
|
|
184
|
+
ImportFrameDirectoryPopUp, InitiateClipMultipleVideosByFrameNumbersPopUp,
|
|
185
|
+
InitiateClipMultipleVideosByTimestampsPopUp, InteractiveClahePopUp,
|
|
186
|
+
ManualTemporalJoinPopUp, MergeFrames2VideoPopUp, MultiCropPopUp,
|
|
187
|
+
MultiShortenPopUp, ReverseVideoPopUp, RotateVideoSetDegreesPopUp,
|
|
188
|
+
SuperImposeFrameCountPopUp, SuperimposeProgressBarPopUp,
|
|
189
|
+
SuperimposeTextPopUp, SuperimposeTimerPopUp, SuperimposeVideoNamesPopUp,
|
|
190
|
+
SuperimposeVideoPopUp, SuperimposeWatermarkPopUp, UpsampleVideosPopUp,
|
|
191
|
+
VideoRotatorPopUp, VideoTemporalJoinPopUp)
|
|
192
|
+
from simba.ui.pop_ups.visualize_pose_in_dir_pop_up import \
|
|
193
|
+
VisualizePoseInFolderPopUp
|
|
194
|
+
from simba.ui.pop_ups.yolo_inference_popup import YOLOPoseInferencePopUP
|
|
195
|
+
from simba.ui.pop_ups.yolo_plot_results import YoloPoseVisualizerPopUp
|
|
196
|
+
from simba.ui.pop_ups.yolo_pose_train_popup import YOLOPoseTrainPopUP
|
|
197
|
+
from simba.ui.tkinter_functions import (CreateLabelFrameWithIcon, Entry_Box,
|
|
198
|
+
FileSelect, SimbaButton, SimbaCheckbox,
|
|
199
|
+
SimBADropDown, SimBALabel,
|
|
200
|
+
hxtScrollbar)
|
|
201
|
+
from simba.ui.video_info_ui import VideoInfoTable
|
|
202
|
+
from simba.utils.checks import (check_ffmpeg_available,
|
|
203
|
+
check_file_exist_and_readable, check_int)
|
|
204
|
+
from simba.utils.custom_feature_extractor import CustomFeatureExtractor
|
|
205
|
+
from simba.utils.enums import (ENV_VARS, OS, ConfigKey, Defaults, Dtypes,
|
|
206
|
+
Formats, Keys, Links, PackageNames, Paths,
|
|
207
|
+
TagNames)
|
|
208
|
+
from simba.utils.errors import InvalidInputError
|
|
209
|
+
from simba.utils.lookups import (check_for_updates,
|
|
210
|
+
get_bp_config_code_class_pairs,
|
|
211
|
+
get_current_time, get_emojis, get_icons_paths,
|
|
212
|
+
load_simba_fonts)
|
|
213
|
+
from simba.utils.read_write import (fetch_pip_data, find_core_cnt,
|
|
214
|
+
get_pkg_version, get_recent_projects_paths,
|
|
215
|
+
read_config_entry, read_config_file,
|
|
216
|
+
read_sys_env, remove_files,
|
|
217
|
+
write_to_recent_project_paths)
|
|
218
|
+
from simba.utils.warnings import (FFMpegNotFoundWarning, PythonVersionWarning,
|
|
219
|
+
VersionWarning)
|
|
220
|
+
from simba.video_processors.video_processing import \
|
|
221
|
+
extract_frames_from_all_videos_in_directory
|
|
222
|
+
|
|
223
|
+
sys.setrecursionlimit(10**6)
|
|
224
|
+
currentPlatform = platform.system()
|
|
225
|
+
ENV = read_sys_env()
|
|
226
|
+
load_timer.stop_timer()
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
import multiprocessing
|
|
230
|
+
is_worker_process = multiprocessing.current_process().name != 'MainProcess'
|
|
231
|
+
except (ImportError, AttributeError):
|
|
232
|
+
is_worker_process = False
|
|
233
|
+
if not is_worker_process:
|
|
234
|
+
print(f'SimBA environment variables: {ENV}. Load time: {load_timer.elapsed_time_str}s')
|
|
235
|
+
|
|
236
|
+
class LoadProjectPopUp(object):
|
|
237
|
+
def __init__(self):
|
|
238
|
+
self.main_frm = Toplevel()
|
|
239
|
+
self.main_frm.minsize(300, 200)
|
|
240
|
+
self.main_frm.wm_title("Load SimBA project (project_config.ini file)")
|
|
241
|
+
self.btn_icons = get_icons_paths()
|
|
242
|
+
for k in self.btn_icons.keys(): self.btn_icons[k]["img"] = ImageTk.PhotoImage(image=PIL.Image.open(os.path.join(os.path.dirname(__file__), self.btn_icons[k]["icon_path"])))
|
|
243
|
+
self.main_frm.iconphoto(False, self.btn_icons['browse']["img"])
|
|
244
|
+
self.load_project_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="LOAD SIMBA PROJECT_CONFIG.INI", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.LOAD_PROJECT.value)
|
|
245
|
+
self.selected_file = FileSelect(self.load_project_frm, "SIMBA CONFIG FILE: ", title="Select project_config.ini file", file_types=[("SimBA Project .ini", "*.ini")], lblwidth=30, lbl_icon='file_type')
|
|
246
|
+
load_project_btn = SimbaButton(parent=self.load_project_frm, txt="LOAD PROJECT PATH", txt_clr='blue', img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.launch_project, cmd_kwargs={'project_path': lambda: self.selected_file.file_path})
|
|
247
|
+
#load_project_btn = SimbaButton(parent=self.load_project_frm, txt="LOAD PROJECT PATH", txt_clr='blue', img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.launch_project, cmd_kwargs={'project_path': self.selected_file.file_path})
|
|
248
|
+
self.load_project_frm.grid(row=0, sticky=NW, pady=(0, 10))
|
|
249
|
+
self.selected_file.grid(row=0, sticky=NW)
|
|
250
|
+
load_project_btn.grid(row=1, pady=(3, 0), sticky=NW)
|
|
251
|
+
recent_project_paths = get_recent_projects_paths()
|
|
252
|
+
if len(recent_project_paths) > 0:
|
|
253
|
+
max_len = max(len(s) for s in recent_project_paths)
|
|
254
|
+
self.load_recent_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="LOAD RECENT PROJECT", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.LOAD_PROJECT.value)
|
|
255
|
+
self.recent_project_dropdown = SimBADropDown(parent=self.load_recent_frm, dropdown_options=recent_project_paths, label='RECENT CONFIG FILE PATH:', label_width=30, value=recent_project_paths[0], dropdown_width=max_len)
|
|
256
|
+
self.load_recent_project_btn = SimbaButton(parent=self.load_recent_frm, txt="LOAD RECENT PROJECT", txt_clr='darkgreen', img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.launch_project, cmd_kwargs={'project_path': lambda: self.recent_project_dropdown.get_value()})
|
|
257
|
+
self.load_recent_frm.grid(row=1, sticky=NW)
|
|
258
|
+
self.recent_project_dropdown.grid(row=0, sticky=NW)
|
|
259
|
+
self.load_recent_project_btn.grid(row=1, pady=(5, 0), sticky=NW)
|
|
260
|
+
|
|
261
|
+
def launch_project(self, project_path: str):
|
|
262
|
+
check_file_exist_and_readable(file_path=project_path)
|
|
263
|
+
_ = SimbaProjectPopUp(config_path=project_path)
|
|
264
|
+
self.load_project_frm.destroy()
|
|
265
|
+
self.main_frm.destroy()
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def wait_for_internet_connection(url):
|
|
269
|
+
while True:
|
|
270
|
+
try:
|
|
271
|
+
response = urllib.request.urlopen(url, timeout=1)
|
|
272
|
+
return
|
|
273
|
+
except:
|
|
274
|
+
pass
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class SimbaProjectPopUp(ConfigReader, PopUpMixin):
|
|
278
|
+
"""
|
|
279
|
+
Main entry to the SimBA loaded project pop-up.
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
def __init__(self, config_path: Union[str, os.PathLike]):
|
|
283
|
+
|
|
284
|
+
ConfigReader.__init__(self, config_path=config_path, read_video_info=False)
|
|
285
|
+
stdout_success(f"Loaded project {config_path}", source=self.__class__.__name__)
|
|
286
|
+
simongui = Toplevel()
|
|
287
|
+
simongui.attributes("-topmost", True)
|
|
288
|
+
simongui.after(150, lambda: simongui.attributes("-topmost", False))
|
|
289
|
+
simongui.minsize(1300, 800)
|
|
290
|
+
try:
|
|
291
|
+
config = read_config_file(config_path=config_path)
|
|
292
|
+
project_name = read_config_entry(config=config, section=ConfigKey.GENERAL_SETTINGS.value, option=ConfigKey.PROJECT_NAME.value, default_value="LOAD PROJECT", data_type=Dtypes.STR.value)
|
|
293
|
+
project_name = f'{project_name} ({config_path})'
|
|
294
|
+
except:
|
|
295
|
+
project_name = "LOAD PROJECT"
|
|
296
|
+
simongui.wm_title(project_name)
|
|
297
|
+
simongui.columnconfigure(0, weight=1)
|
|
298
|
+
simongui.rowconfigure(0, weight=1)
|
|
299
|
+
self.core_cnt = find_core_cnt()[0]
|
|
300
|
+
self.btn_icons = get_icons_paths()
|
|
301
|
+
|
|
302
|
+
for k in self.btn_icons.keys():
|
|
303
|
+
self.btn_icons[k]["img"] = ImageTk.PhotoImage(image=PIL.Image.open(os.path.join(os.path.dirname(__file__), self.btn_icons[k]["icon_path"])))
|
|
304
|
+
|
|
305
|
+
simongui.iconphoto(False, self.btn_icons['SimBA_logo_3_small']["img"])
|
|
306
|
+
tab_style = ttk.Style()
|
|
307
|
+
tab_style.configure('Custom.TNotebook', background='#f0f0f0', borderwidth=0)
|
|
308
|
+
tab_style.configure('Custom.TNotebook.Tab', font=Formats.FONT_REGULAR.value, padding=[15, 8], borderwidth=1, relief='flat', background='#f0f0f0')
|
|
309
|
+
tab_style.map('Custom.TNotebook.Tab',
|
|
310
|
+
background=[('selected', '#ffffff'), ('!selected', '#f0f0f0')],
|
|
311
|
+
foreground=[('selected', 'navy'), ('!selected', '#333333')],
|
|
312
|
+
font=[('selected', Formats.FONT_REGULAR_BOLD.value), ('!selected', Formats.FONT_REGULAR.value)],
|
|
313
|
+
bordercolor=[('selected', '#0066cc'), ('!selected', '#e0e0e0')],
|
|
314
|
+
lightcolor=[('selected', '#ffffff'), ('!selected', '#f5f5f5')],
|
|
315
|
+
darkcolor=[('selected', '#e0e0e0'), ('!selected', '#e0e0e0')])
|
|
316
|
+
|
|
317
|
+
scrollable_container = hxtScrollbar(simongui)
|
|
318
|
+
tab_parent = ttk.Notebook(scrollable_container, style='Custom.TNotebook')
|
|
319
|
+
tab2 = ttk.Frame(tab_parent)
|
|
320
|
+
tab3 = ttk.Frame(tab_parent)
|
|
321
|
+
tab4 = ttk.Frame(tab_parent)
|
|
322
|
+
tab5 = ttk.Frame(tab_parent)
|
|
323
|
+
tab6 = ttk.Frame(tab_parent)
|
|
324
|
+
tab7 = ttk.Frame(tab_parent)
|
|
325
|
+
tab8 = ttk.Frame(tab_parent)
|
|
326
|
+
tab9 = ttk.Frame(tab_parent)
|
|
327
|
+
tab10 = ttk.Frame(tab_parent)
|
|
328
|
+
tab11 = ttk.Frame(tab_parent)
|
|
329
|
+
|
|
330
|
+
tab_parent.add(tab2, text="Further imports", compound="left", image=self.btn_icons["pose"]["img"])
|
|
331
|
+
tab_parent.add(tab3, text="Video parameters", compound="left", image=self.btn_icons["calipher"]["img"])
|
|
332
|
+
tab_parent.add(tab4, text="Outlier correction", compound="left", image=self.btn_icons["outlier"]["img"])
|
|
333
|
+
tab_parent.add(tab6, text="ROI", compound="left", image=self.btn_icons["roi"]["img"])
|
|
334
|
+
tab_parent.add(tab5, text="Extract features", compound="left", image=self.btn_icons["features"]["img"])
|
|
335
|
+
tab_parent.add(tab7, text="Label behavior", compound="left", image=self.btn_icons["label"]["img"])
|
|
336
|
+
tab_parent.add(tab8, text="Train machine model", compound="left", image=self.btn_icons["clf"]["img"])
|
|
337
|
+
tab_parent.add(tab9, text="Run machine model", compound="left", image=self.btn_icons["clf_2"]["img"])
|
|
338
|
+
tab_parent.add(tab10, text="Visualizations", compound="left", image=self.btn_icons["visualize"]["img"])
|
|
339
|
+
tab_parent.add(tab11, text="Add-ons", compound="left", image=self.btn_icons["add_on"]["img"])
|
|
340
|
+
|
|
341
|
+
tab_parent.grid(row=0, sticky='ew')
|
|
342
|
+
tab_parent.enable_traversal()
|
|
343
|
+
|
|
344
|
+
import_frm = LabelFrame(tab2)
|
|
345
|
+
import_frm.grid(row=0, column=0, sticky=NW)
|
|
346
|
+
|
|
347
|
+
further_methods_frm = CreateLabelFrameWithIcon(parent=import_frm, header="FURTHER METHODS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.ADDITIONAL_IMPORTS.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
348
|
+
extract_frm_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="EXTRACT FRAMES FOR ALL VIDEOS IN SIMBA PROJECT", txt_clr='blue', compound='right', img='image', font=Formats.FONT_REGULAR.value, cmd=extract_frames_from_all_videos_in_directory, cmd_kwargs={'config_path': lambda:self.config_path, 'directory': lambda:self.video_dir})
|
|
349
|
+
import_frm_dir_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="IMPORT FRAMES DIRECTORY TO SIMBA PROJECT", txt_clr='blue', compound='right', img='import', font=Formats.FONT_REGULAR.value, cmd=ImportFrameDirectoryPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
350
|
+
add_clf_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="ADD CLASSIFIER TO SIMBA PROJECT", txt_clr='blue', compound='right', img='plus', font=Formats.FONT_REGULAR.value, cmd=AddClfPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
351
|
+
remove_clf_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="REMOVE CLASSIFIER FROM SIMBA PROJECT", txt_clr='blue', compound='right', img='trash', font=Formats.FONT_REGULAR.value, cmd=RemoveAClassifierPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
352
|
+
archive_files_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="ARCHIVE PROCESSED FILES IN SIMBA PROJECT", txt_clr='blue', compound='right', img='archive', font=Formats.FONT_REGULAR.value, cmd=ArchiveProcessedFilesPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
353
|
+
reverse_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="REVERSE TRACKING IDENTITIES IN SIMBA PROJECT", txt_clr='blue', compound='right', img='reverse_blue', font=Formats.FONT_REGULAR.value, cmd=None)
|
|
354
|
+
interpolate_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="INTERPOLATE POSE IN SIMBA PROJECT", txt_clr='blue', compound='right', img='line_chart_blue', font=Formats.FONT_REGULAR.value, cmd=InterpolatePopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
355
|
+
smooth_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="SMOOTH POSE IN SIMBA PROJECT", txt_clr='blue', compound='right', img='wand_blue', font=Formats.FONT_REGULAR.value, cmd=SmoothingPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
356
|
+
egocentric_align_btn = SimbaButton(parent=further_methods_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="EGOCENTRICALLY ALIGN POSE AND VIDEO", txt_clr='blue', compound='right', img='mouse_small', font=Formats.FONT_REGULAR.value, cmd=EgocentricAlignPopUp, cmd_kwargs={'config_path': lambda: self.config_path})
|
|
357
|
+
|
|
358
|
+
label_setscale = CreateLabelFrameWithIcon(parent=tab3, header="VIDEO PARAMETERS (FPS, RESOLUTION, PPX/MM ....)", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_PARAMETERS.value, padx=10, pady=10, relief='solid')
|
|
359
|
+
self.distance_in_mm_eb = Entry_Box(label_setscale, "KNOWN DISTANCE (MILLIMETERS): ", labelwidth=35, validation="numeric", entry_box_width=35)
|
|
360
|
+
button_setdistanceinmm = SimbaButton(parent=label_setscale, txt="AUTO-POPULATE", txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.set_distance_mm)
|
|
361
|
+
|
|
362
|
+
button_setscale = SimbaButton(parent=label_setscale, txt="CONFIGURE VIDEO PARAMETERS", txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.create_video_info_table, img='calipher')
|
|
363
|
+
self.new_ROI_frm = CreateLabelFrameWithIcon(parent=tab6, header="SIMBA ROI INTERFACE", icon_name='shapes_small', icon_link=Links.ROI.value, bg='#DCDCDC', padx=5, pady=5)
|
|
364
|
+
self.start_new_ROI = SimbaButton(parent=self.new_ROI_frm, width=Formats.BUTTON_WIDTH_L.value, txt="DEFINE ROIs", txt_clr='green', font=Formats.FONT_REGULAR.value, img='roi', cmd=ROIVideoTable, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
365
|
+
|
|
366
|
+
self.delete_all_ROIs = SimbaButton(parent=self.new_ROI_frm, width=Formats.BUTTON_WIDTH_L.value, txt="DELETE ALL ROI DEFINITIONS", txt_clr='red', font=Formats.FONT_REGULAR.value, img='trash', cmd=delete_all_rois_pop_up, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
367
|
+
self.new_ROI_frm.grid(row=0, sticky=NW, padx=10, pady=10)
|
|
368
|
+
self.start_new_ROI.grid(row=0, sticky=NW)
|
|
369
|
+
self.delete_all_ROIs.grid(row=1, column=0, sticky=NW)
|
|
370
|
+
|
|
371
|
+
self.roi_draw = CreateLabelFrameWithIcon(parent=tab6, header="ANALYZE ROI DATA", icon_name='magnifying', icon_link=Links.ROI.value, bg='#DCDCDC', padx=5, pady=5)
|
|
372
|
+
analyze_roi_btn = SimbaButton(parent=self.roi_draw, width=Formats.BUTTON_WIDTH_L.value, txt="ANALYZE ROI DATA: AGGREGATES", txt_clr='green', img='shapes_small', font=Formats.FONT_REGULAR.value, cmd=ROIAggregateDataAnalyzerPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
373
|
+
|
|
374
|
+
analyze_roi_time_bins_btn = SimbaButton(parent=self.roi_draw, width=Formats.BUTTON_WIDTH_L.value, txt="ANALYZE ROI DATA: TIME-BINS", txt_clr='blue', img='clock', font=Formats.FONT_REGULAR.value, cmd=ROIAnalysisTimeBinsPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
375
|
+
self.roi_draw.grid(row=0, column=1, sticky=N, padx=10, pady=10)
|
|
376
|
+
analyze_roi_btn.grid(row=0, sticky="NW")
|
|
377
|
+
analyze_roi_time_bins_btn.grid(row=1, sticky="NW")
|
|
378
|
+
|
|
379
|
+
self.roi_draw1 = CreateLabelFrameWithIcon(parent=tab6, header="VISUALIZE ROI DATA", icon_name='eye', icon_link=Links.ROI.value, bg='#DCDCDC', padx=5, pady=5)
|
|
380
|
+
visualizeROI = SimbaButton(parent=self.roi_draw1, width=Formats.BUTTON_WIDTH_L.value, txt="VISUALIZE ROI TRACKING", txt_clr='green', img='visualize_green', font=Formats.FONT_REGULAR.value, cmd=VisualizeROITrackingPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
381
|
+
visualizeROIfeature = SimbaButton(parent=self.roi_draw1, width=Formats.BUTTON_WIDTH_L.value, txt="VISUALIZE ROI FEATURES", txt_clr='blue', img='visualize_blue', font=Formats.FONT_REGULAR.value, cmd=VisualizeROIFeaturesPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
382
|
+
|
|
383
|
+
##organize
|
|
384
|
+
self.roi_draw1.grid(row=0, column=2, sticky=N, padx=10, pady=10)
|
|
385
|
+
visualizeROI.grid(row=0, sticky="NW")
|
|
386
|
+
visualizeROIfeature.grid(row=1, sticky="NW")
|
|
387
|
+
|
|
388
|
+
processmovementdupLabel = CreateLabelFrameWithIcon(parent=tab6, header="OTHER ANALYSES / VISUALIZATIONS", icon_name='list', icon_link=Links.ROI.value, bg='#DCDCDC', padx=5, pady=5)
|
|
389
|
+
analyze_distances_velocity_btn = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE DISTANCES / VELOCITY: AGGREGATES", img='metrics_green', txt_clr='green', font=Formats.FONT_REGULAR.value, cmd=MovementAnalysisPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
390
|
+
analyze_distances_velocity_timebins_btn = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE DISTANCES / VELOCITY: TIME-BINS", img='metrics_blue', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=MovementAnalysisTimeBinsPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
391
|
+
heatmaps_location_button = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="CREATE LOCATION HEATMAPS", txt_clr='red', img='heatmap', font=Formats.FONT_REGULAR.value, cmd=HeatmapLocationPopup, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
392
|
+
button_lineplot = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="CREATE PATH PLOTS", txt_clr='orange', img='path', font=Formats.FONT_REGULAR.value, cmd=QuickLineplotPopup, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
393
|
+
|
|
394
|
+
button_analyzeDirection = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE DIRECTIONALITY BETWEEN ANIMALS", img='direction', txt_clr='deeppink', font=Formats.FONT_REGULAR.value, cmd=AnimalDirectingAnimalPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
395
|
+
button_visualizeDirection = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE DIRECTIONALITY BETWEEN ANIMALS", img='direction', txt_clr='brown', font=Formats.FONT_REGULAR.value, cmd=DirectingOtherAnimalsVisualizerPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
396
|
+
button_analyzeDirection_bp = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE DIRECTIONALITY BETWEEN BODY PARTS", img='direction', txt_clr='purple', font=Formats.FONT_REGULAR.value, cmd=DirectionAnimalToBodyPartSettingsPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
397
|
+
button_visualizeDirection_bp = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE DIRECTIONALITY BETWEEN BODY PARTS", img='direction', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=DirectingAnimalToBodyPartVisualizerPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
398
|
+
|
|
399
|
+
btn_agg_boolean_conditional_statistics = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="AGGREGATE BOOLEAN CONDITIONAL STATISTICS", img='details', txt_clr='grey', font=Formats.FONT_REGULAR.value, cmd=BooleanConditionalSlicerPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
400
|
+
spontaneous_alternation_pop_up_btn = SimbaButton(parent=processmovementdupLabel, width=Formats.BUTTON_WIDTH_XL.value, txt="SPONTANEOUS ALTERNATION", img='t', txt_clr='navy', font=Formats.FONT_REGULAR.value, cmd=SpontaneousAlternationPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
401
|
+
|
|
402
|
+
processmovementdupLabel.grid(row=0, column=3, sticky=NW, padx=10, pady=10)
|
|
403
|
+
analyze_distances_velocity_btn.grid(row=0, sticky=NW)
|
|
404
|
+
heatmaps_location_button.grid(row=1, sticky=NW)
|
|
405
|
+
analyze_distances_velocity_timebins_btn.grid(row=2, sticky=NW)
|
|
406
|
+
button_lineplot.grid(row=3, sticky=NW)
|
|
407
|
+
button_analyzeDirection.grid(row=4, sticky=NW)
|
|
408
|
+
button_visualizeDirection.grid(row=5, sticky=NW)
|
|
409
|
+
button_analyzeDirection_bp.grid(row=6, sticky=NW)
|
|
410
|
+
button_visualizeDirection_bp.grid(row=7, sticky=NW)
|
|
411
|
+
btn_agg_boolean_conditional_statistics.grid(row=8, sticky=NW)
|
|
412
|
+
spontaneous_alternation_pop_up_btn.grid(row=9, sticky=NW)
|
|
413
|
+
|
|
414
|
+
label_outliercorrection = CreateLabelFrameWithIcon(parent=tab4, header="OUTLIER CORRECTION", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.OUTLIERS_DOC.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
415
|
+
button_settings_outlier = SimbaButton(parent=label_outliercorrection, width=Formats.BUTTON_WIDTH_L.value, txt="SETTINGS", txt_clr='blue', img='settings', font=Formats.FONT_REGULAR.value, cmd=OutlierSettingsPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
416
|
+
|
|
417
|
+
button_outliercorrection = SimbaButton(parent=label_outliercorrection, width=Formats.BUTTON_WIDTH_L.value, txt="RUN OUTLIER CORRECTION", txt_clr='green', img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.correct_outlier, thread=False)
|
|
418
|
+
button_skipOC = SimbaButton(parent=label_outliercorrection, width=Formats.BUTTON_WIDTH_L.value, txt="SKIP OUTLIER CORRECTION (CAUTION)", txt_clr='red', img='skip_2', font=Formats.FONT_REGULAR.value, cmd=self.initiate_skip_outlier_correction, thread=False)
|
|
419
|
+
|
|
420
|
+
def activate():
|
|
421
|
+
if self.user_defined_var.get(): self.scriptfile.set_state(setstatus=NORMAL)
|
|
422
|
+
else: self.scriptfile.set_state(setstatus=DISABLED)
|
|
423
|
+
|
|
424
|
+
extract_features_frm = CreateLabelFrameWithIcon(parent=tab5, header="EXTRACT FEATURES", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.EXTRACT_FEATURES.value, relief='solid')
|
|
425
|
+
userscript, self.user_defined_var = SimbaCheckbox(parent=extract_features_frm, txt="APPLY USER DEFINED FEATURE EXTRACTION SCRIPT", font=Formats.FONT_REGULAR.value, val=False, state=NORMAL, cmd= activate)
|
|
426
|
+
self.scriptfile = FileSelect(extract_features_frm, "SCRIPT PATH (.PY):", file_types=[("Python .py file", "*.py")], lblwidth=25, status=DISABLED, lbl_icon='python')
|
|
427
|
+
button_extractfeatures = SimbaButton(parent=extract_features_frm, txt="EXTRACT FEATURES", width=Formats.BUTTON_WIDTH_XL.value, txt_clr='blue', img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.run_feature_extraction, thread=False)
|
|
428
|
+
|
|
429
|
+
extract_features_frm.grid(row=0, column=0, sticky=NSEW, padx=10, pady=10)
|
|
430
|
+
userscript.grid(row=0, column=0, sticky=NW)
|
|
431
|
+
self.scriptfile.grid(row=1, column=0, sticky=NW)
|
|
432
|
+
button_extractfeatures.grid(row=2, column=0, sticky=NW)
|
|
433
|
+
|
|
434
|
+
roi_feature_frm = CreateLabelFrameWithIcon(parent=tab5, header="APPEND ROI FEATURES", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.APPEND_ROI_FEATURES.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
435
|
+
|
|
436
|
+
append_roi_features_by_animal = SimbaButton(parent=roi_feature_frm, width=Formats.BUTTON_WIDTH_XXL.value, txt="APPEND ROI DATA TO FEATURES: BY ANIMAL (CAUTION)", txt_clr='red', img='join_red', font=Formats.FONT_REGULAR.value, cmd=AppendROIFeaturesByAnimalPopUp, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
437
|
+
append_roi_features_by_body_part = SimbaButton(parent=roi_feature_frm, width=Formats.BUTTON_WIDTH_XXL.value, txt="APPEND ROI DATA TO FEATURES: BY BODY-PARTS (CAUTION)", img='join_yellow', txt_clr='orange', font=Formats.FONT_REGULAR.value, cmd=AppendROIFeaturesByBodyPartPopUp, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
438
|
+
remove_roi_features_from_feature_set = SimbaButton(parent=roi_feature_frm, width=Formats.BUTTON_WIDTH_XXL.value, txt="REMOVE ROI FEATURES FROM FEATURE SET", txt_clr='darkred', img='trash', font=Formats.FONT_REGULAR.value, cmd=RemoveROIFeaturesPopUp, cmd_kwargs={'config_path': lambda:self.config_path, 'dataset': lambda:'features_extracted'}, thread=False)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
feature_tools_frm = LabelFrame(tab5, text="FEATURE TOOLS", pady=5, font=Formats.FONT_HEADER.value, bg=Formats.LABELFRAME_GREY.value, padx=5)
|
|
442
|
+
compute_feature_subset_btn = SimbaButton(parent=feature_tools_frm, width=Formats.BUTTON_WIDTH_XXL.value, txt="CALCULATE FEATURE SUBSETS", txt_clr='blue', img='subset_blue', font=Formats.FONT_REGULAR.value, cmd=FeatureSubsetExtractorPopUp, cmd_kwargs={'config_path': lambda: self.config_path}, thread=False)
|
|
443
|
+
|
|
444
|
+
label_behavior_frm = CreateLabelFrameWithIcon(parent=tab7, header="LABEL BEHAVIOR", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.LABEL_BEHAVIOR.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
445
|
+
select_video_btn_new = SimbaButton(parent=label_behavior_frm, width=Formats.BUTTON_WIDTH_XXL.value, txt="Select video (create NEW video annotation)", img='label_blue', txt_clr='navy', cmd=SelectLabellingVideoPupUp, cmd_kwargs={'config_path': lambda :self.config_path, 'continuing': lambda: False}, thread=False)
|
|
446
|
+
select_video_btn_continue = SimbaButton(parent=label_behavior_frm, width=Formats.BUTTON_WIDTH_XXL.value, txt="Select video (CONTINUE existing video annotation)", img='label_yellow', txt_clr='darkgoldenrod', cmd=SelectLabellingVideoPupUp, cmd_kwargs={'config_path': lambda: self.config_path,'continuing': lambda: True}, thread=False)
|
|
447
|
+
|
|
448
|
+
label_thirdpartyann = CreateLabelFrameWithIcon(parent=tab7, header="IMPORT THIRD-PARTY BEHAVIOR ANNOTATIONS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.THIRD_PARTY_ANNOTATION.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
449
|
+
button_importmars = SimbaButton(parent=label_thirdpartyann, width=Formats.BUTTON_WIDTH_XS.value, txt="Import MARS Annotation (select folder with .annot files)", txt_clr="blue", cmd=self.importMARS, thread=False, font=Formats.FONT_REGULAR.value)
|
|
450
|
+
button_importboris = SimbaButton(parent=label_thirdpartyann, width=Formats.BUTTON_WIDTH_XS.value, txt="Import BORIS Annotation (select folder with .csv files)", txt_clr="green", cmd=self.importBoris, thread=False, font=Formats.FONT_REGULAR.value)
|
|
451
|
+
button_importsolomon = SimbaButton(parent=label_thirdpartyann, width=Formats.BUTTON_WIDTH_XS.value, txt="Import SOLOMON Annotation (select folder with .csv files", txt_clr="purple", cmd=self.importSolomon, thread=False, font=Formats.FONT_REGULAR.value)
|
|
452
|
+
|
|
453
|
+
button_importethovision = SimbaButton(parent=label_thirdpartyann, width=Formats.BUTTON_WIDTH_XS.value, txt="Import ETHOVISION Annotation (select folder with .xls/xlsx files)", txt_clr="blue", cmd=self.import_ethovision, thread=False, font=Formats.FONT_REGULAR.value)
|
|
454
|
+
button_importdeepethogram = SimbaButton(parent=label_thirdpartyann, width=Formats.BUTTON_WIDTH_XS.value, txt="Import DEEPETHOGRAM Annotation (select folder with .csv files)", txt_clr="green", cmd=self.import_deepethogram, thread=False, font=Formats.FONT_REGULAR.value)
|
|
455
|
+
import_observer_btn = SimbaButton(parent=label_thirdpartyann, width=Formats.BUTTON_WIDTH_XS.value, txt="Import NOLDUS OBSERVER Annotation (select folder with .xls/xlsx files)", txt_clr="purple", cmd=self.import_noldus_observer, thread=False, font=Formats.FONT_REGULAR.value)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
label_pseudo = CreateLabelFrameWithIcon(parent=tab7,header="PSEUDO-LABELLING", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.PSEUDO_LBL.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
459
|
+
pseudo_lbelling_btn = SimbaButton(parent=label_pseudo, width=Formats.BUTTON_WIDTH_XXL.value, txt="PSEUDO-LABEL VIDEO", img='label_blue', txt_clr='navy', cmd=SelectPseudoLabellingVideoPupUp, cmd_kwargs={'config_path': lambda :self.config_path}, thread=False)
|
|
460
|
+
|
|
461
|
+
label_adv_label = CreateLabelFrameWithIcon(parent=tab7, header="ADVANCED LABEL BEHAVIOR", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.ADVANCED_LBL.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
462
|
+
|
|
463
|
+
label_adv_note_1 = SimBALabel(parent=label_adv_label, txt="Note: you will have to specify the presence of *both* behavior and non-behavior on your own.", font=Formats.FONT_REGULAR.value, bg_clr=Formats.LABELFRAME_GREY.value)
|
|
464
|
+
label_adv_note_2 = SimBALabel(parent=label_adv_label, txt="Click here more information on how to use the SimBA labelling interface.", txt_clr='blue', cursor='hand2', font=Formats.FONT_REGULAR.value, link=Links.ADVANCED_LBL.value,bg_clr=Formats.LABELFRAME_GREY.value)
|
|
465
|
+
|
|
466
|
+
adv_label_btn_new = SimbaButton(parent=label_adv_label, width=Formats.BUTTON_WIDTH_XS.value, txt="Select video (create NEW video annotation)", cmd=select_labelling_video_advanced, cmd_kwargs={'config_path': lambda:self.config_path, 'continuing': lambda:False}, thread=False)
|
|
467
|
+
adv_label_btn_continue = SimbaButton(parent=label_adv_label, width=Formats.BUTTON_WIDTH_XS.value, txt="Select video (CONTINUE existing video annotation)", cmd=select_labelling_video_advanced, cmd_kwargs={'config_path': lambda:self.config_path, 'continuing': lambda:True}, thread=False)
|
|
468
|
+
|
|
469
|
+
targeted_clip_annotator_frm = CreateLabelFrameWithIcon(parent=tab7,header="TARGETED CLIP ANNOTATOR",icon_name=Keys.DOCUMENTATION.value,icon_link=Links.ADVANCED_LBL.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
470
|
+
targeted_clip_annotator_note = SimBALabel(parent=targeted_clip_annotator_frm, txt="A bout annotator that creates annotated clips from videos associated with ML results.", txt_clr='blue', cursor='hand2', font=Formats.FONT_REGULAR.value, link=Links.ADVANCED_LBL.value, bg_clr=Formats.LABELFRAME_GREY.value)
|
|
471
|
+
targeted_clip_annotator_btn = SimbaButton(parent=targeted_clip_annotator_frm, txt="Select video", cmd=select_labelling_video_targeted_clips, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
472
|
+
|
|
473
|
+
lbl_tools_frm = CreateLabelFrameWithIcon(parent=tab7, header="LABELLING TOOLS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.ADVANCED_LBL.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
474
|
+
visualize_annotation_img_btn = SimbaButton(parent=lbl_tools_frm, width=Formats.BUTTON_WIDTH_XS.value, txt="VISUALIZE ANNOTATIONS", cmd=ExtractAnnotationFramesPopUp, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
475
|
+
third_party_annotations_btn = SimbaButton(parent=lbl_tools_frm, width=Formats.BUTTON_WIDTH_XS.value, txt="APPEND THIRD-PARTY ANNOTATIONS", txt_clr='purple', cmd=ThirdPartyAnnotatorAppenderPopUp, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
476
|
+
remove_roi_features_from_annotation_set = SimbaButton(parent=lbl_tools_frm, width=Formats.BUTTON_WIDTH_XS.value, txt="REMOVE ROI FEATURES FROM LABEL SET", txt_clr='darkred', cmd=RemoveROIFeaturesPopUp, cmd_kwargs={'config_path': lambda:self.config_path, 'dataset': lambda:'targets_inserted'}, thread=False)
|
|
477
|
+
compute_annotation_statistics = SimbaButton(parent=lbl_tools_frm, width=Formats.BUTTON_WIDTH_XS.value, txt="COUNT ANNOTATIONS IN PROJECT", txt_clr='orange', cmd=ClfAnnotationCountPopUp, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
label_trainmachinemodel = CreateLabelFrameWithIcon(parent=tab8, header="TRAIN MACHINE MODELS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.TRAIN_ML_MODEL.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
button_trainmachinesettings = SimbaButton(parent=label_trainmachinemodel, width=Formats.BUTTON_WIDTH_XXL.value, txt="SETTINGS", img='settings', txt_clr='darkorange', cmd=self.trainmachinemodelsetting, thread=False)
|
|
485
|
+
button_trainmachinemodel = SimbaButton(parent=label_trainmachinemodel, width=Formats.BUTTON_WIDTH_XXL.value, txt="TRAIN SINGLE MODEL (GLOBAL ENVIRONMENT)", img='one_blue', txt_clr='blue', cmd=self.train_single_model, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
486
|
+
|
|
487
|
+
button_train_multimodel = SimbaButton(parent=label_trainmachinemodel, width=Formats.BUTTON_WIDTH_XXL.value, txt="TRAIN MULTIPLE MODELS (ONE FOR EACH SAVED SETTING)", img='multiple_green', txt_clr='green', cmd=self.train_multiple_models_from_meta, cmd_kwargs={'config_path': lambda:self.config_path}, thread=False)
|
|
488
|
+
|
|
489
|
+
label_model_validation = CreateLabelFrameWithIcon( parent=tab9, header="VALIDATE MODEL ON SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.OUT_OF_SAMPLE_VALIDATION.value, padx=5, pady=5, relief='solid')
|
|
490
|
+
self.csvfile = FileSelect(label_model_validation,fileDescription="SELECT DATA FEATURE FILE PATH", color="blue",lblwidth=40,file_types=[("SimBA CSV", "*.csv"), ("SimBA PARQUET", "*.parquet")], initialdir=os.path.join(self.project_path, Paths.FEATURES_EXTRACTED_DIR.value))
|
|
491
|
+
self.modelfile = FileSelect(label_model_validation,fileDescription="SELECT MODEL FILE PATH", color="blue", lblwidth=40, initialdir=self.project_path)
|
|
492
|
+
|
|
493
|
+
button_runvalidmodel = SimbaButton(parent=label_model_validation, width=Formats.BUTTON_WIDTH_XL.value, txt="RUN MODEL", txt_clr='blue', img='rocket', cmd=self.validate_model_first_step, thread=False)
|
|
494
|
+
button_generateplot = SimbaButton(parent=label_model_validation, width=Formats.BUTTON_WIDTH_XL.value, txt="INTERACTIVE PROBABILITY PLOT", img='interactive_blue', txt_clr='blue', cmd=self.launch_interactive_plot, thread=False)
|
|
495
|
+
|
|
496
|
+
self.dis_threshold = Entry_Box(label_model_validation, "DISCRIMINATION THRESHOLD (0.0-1.0):", labelwidth=40, entry_box_width=30)
|
|
497
|
+
self.min_behaviorbout = Entry_Box(label_model_validation,"MINIMUM BOUT LENGTH (MS):",labelwidth=40, validation="numeric", entry_box_width=30)
|
|
498
|
+
button_validate_model = SimbaButton(parent=label_model_validation, width=Formats.BUTTON_WIDTH_XL.value, txt="CREATE VALIDATION VIDEO", txt_clr='blue', img='visualize_blue', cmd=ValidationVideoPopUp, cmd_kwargs={'config_path': lambda: config_path,
|
|
499
|
+
'feature_path': lambda: self.csvfile.file_path,
|
|
500
|
+
'model_path': lambda: self.modelfile.file_path,
|
|
501
|
+
'discrimination_threshold': lambda: self.dis_threshold.entry_get,
|
|
502
|
+
'shortest_bout': lambda: self.min_behaviorbout.entry_get})
|
|
503
|
+
|
|
504
|
+
label_runmachinemodel = CreateLabelFrameWithIcon(parent=tab9,header="RUN MACHINE MODEL",icon_name=Keys.DOCUMENTATION.value,icon_link=Links.SCENARIO_2.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
505
|
+
|
|
506
|
+
button_runmachinemodel = SimbaButton(parent=label_runmachinemodel, width=Formats.BUTTON_WIDTH_XL.value, txt="RUN MODELS", txt_clr='green', img='clf', cmd=RunMachineModelsPopUp, thread=False, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
507
|
+
|
|
508
|
+
kleinberg_button = SimbaButton(parent=label_runmachinemodel, width=Formats.BUTTON_WIDTH_XL.value, txt="KLEINBERG SMOOTHING", txt_clr='green', img='feather_green', cmd=KleinbergPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
509
|
+
fsttc_button = SimbaButton(parent=label_runmachinemodel, width=Formats.BUTTON_WIDTH_XL.value, txt="FSTTC", txt_clr='green', img='tile_green', cmd=FSTTCPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
510
|
+
|
|
511
|
+
mutual_exclusivity = SimbaButton(parent=label_runmachinemodel, width=Formats.BUTTON_WIDTH_XL.value, txt="MUTUAL EXCLUSIVITY CORRECTION", img='seperate_green', txt_clr='green', cmd=MutualExclusivityPupUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
512
|
+
|
|
513
|
+
label_machineresults = CreateLabelFrameWithIcon( parent=tab9, header="ANALYZE MACHINE RESULTS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.ANALYZE_ML_RESULTS.value, bg=Formats.LABELFRAME_GREY.value, pady=5, padx=5)
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
button_process_datalog = SimbaButton(parent=label_machineresults, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE MACHINE PREDICTIONS: AGGREGATES", img='metrics_blue', txt_clr='blue', cmd=ClfDescriptiveStatsPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
517
|
+
button_process_movement = SimbaButton(parent=label_machineresults, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE DISTANCES/VELOCITY: AGGREGATES", img='metrics_blue', txt_clr='blue', cmd=MovementAnalysisPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
518
|
+
button_movebins = SimbaButton(parent=label_machineresults, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE DISTANCES/VELOCITY: TIME BINS", txt_clr='blue', img='metrics_blue', cmd=MovementAnalysisTimeBinsPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
519
|
+
button_classifierbins = SimbaButton(parent=label_machineresults, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE MACHINE PREDICTIONS: TIME-BINS", txt_clr='blue', img='metrics_blue', cmd=TimeBinsClfPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
520
|
+
button_classifier_ROI = SimbaButton(parent=label_machineresults, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE MACHINE PREDICTION: BY ROI", txt_clr='blue', img='metrics_blue', cmd=ClfByROIPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
521
|
+
button_severity = SimbaButton(parent=label_machineresults, width=Formats.BUTTON_WIDTH_XL.value, txt="ANALYZE MACHINE PREDICTION: BY SEVERITY", txt_clr='blue', img='metrics_blue', cmd=AnalyzeSeverityPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
522
|
+
|
|
523
|
+
visualization_frm = CreateLabelFrameWithIcon(parent=tab10, header="DATA VISUALIZATIONS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VISUALIZATION.value, bg=Formats.LABELFRAME_GREY.value, padx=5, pady=5)
|
|
524
|
+
sklearn_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE CLASSIFICATIONS", img='split', txt_clr='black', cmd=SklearnVisualizationPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
525
|
+
sklearn_visualization_btn.grid(row=0, column=0, sticky=NW)
|
|
526
|
+
gantt_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE GANTT", img='bar_graph_blue', txt_clr='blue', cmd=GanttPlotPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
527
|
+
gantt_visualization_btn.grid(row=1, column=0, sticky=NW)
|
|
528
|
+
probability_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE PROBABILITIES", img='dice_green', txt_clr='green', cmd=VisualizeClassificationProbabilityPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
529
|
+
probability_visualization_btn.grid(row=2, column=0, sticky=NW)
|
|
530
|
+
path_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE PATHS", img='path', txt_clr='navy', cmd=PathPlotPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
531
|
+
path_visualization_btn.grid(row=3, column=0, sticky=NW)
|
|
532
|
+
distance_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE DISTANCES", img='distance_red', txt_clr='red', cmd=DistancePlotterPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
533
|
+
distance_visualization_btn.grid(row=4, column=0, sticky=NW)
|
|
534
|
+
heatmap_clf_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE CLASSIFICATION HEATMAPS", img='heatmap', txt_clr='green', cmd=HeatmapClfPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
535
|
+
heatmap_clf_visualization_btn.grid(row=5, column=0, sticky=NW)
|
|
536
|
+
#data_plot_visualization_btn = SimbaButton(parent=visualization_frm, txt="VISUALIZE DATA PLOTS", img='metrics', txt_clr='purple', cmd=Nne, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
537
|
+
data_plot_visualization_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="VISUALIZE DATA PLOTS", img='metrics', txt_clr='purple', cmd=DataPlotterPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
data_plot_visualization_btn.grid(row=6, column=0, sticky=NW)
|
|
541
|
+
clf_validation_btn = SimbaButton(parent=visualization_frm, width=Formats.BUTTON_WIDTH_XL.value, txt="CLASSIFIER VALIDATION CLIPS", txt_clr='blue', img='check_blue', cmd=ClassifierValidationPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
542
|
+
clf_validation_btn.grid(row=7, column=0, sticky=NW)
|
|
543
|
+
merge_frm = CreateLabelFrameWithIcon(parent=tab10, header="MERGE FRAMES", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.CONCAT_VIDEOS.value)
|
|
544
|
+
merge_frm_btn = SimbaButton(parent=merge_frm, txt="MERGE FRAMES", img='merge', txt_clr='black', cmd=ConcatenatorPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
545
|
+
plotlyInterface = CreateLabelFrameWithIcon(parent=tab10, header="PLOTLY / DASH", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.PLOTLY.value)
|
|
546
|
+
plotlyInterfaceTitles = ["Sklearn results", "Time bin analyses", "Probabilities", "Severity analysis"]
|
|
547
|
+
toIncludeVar = []
|
|
548
|
+
for i in range(len(plotlyInterfaceTitles) + 1):
|
|
549
|
+
toIncludeVar.append(IntVar())
|
|
550
|
+
plotlyCheckbox = [0] * (len(plotlyInterfaceTitles) + 1)
|
|
551
|
+
for i in range(len(plotlyInterfaceTitles)):
|
|
552
|
+
plotlyCheckbox[i] = Checkbutton(plotlyInterface, text=plotlyInterfaceTitles[i], variable=toIncludeVar[i])
|
|
553
|
+
plotlyCheckbox[i].grid(row=i, sticky=W)
|
|
554
|
+
|
|
555
|
+
button_save_plotly_file = Button(plotlyInterface, text="Save SimBA / Plotly dataset", command=lambda: self.generateSimBPlotlyFile(toIncludeVar))
|
|
556
|
+
self.plotly_file = FileSelect( plotlyInterface, "SimBA Dashboard file (H5)", title="Select SimBA/Plotly dataset (h5)")
|
|
557
|
+
self.groups_file = FileSelect(plotlyInterface, "SimBA Groups file (CSV)", title="Select groups file (csv)")
|
|
558
|
+
button_open_plotly_interface = Button(plotlyInterface, text="Open SimBA / Plotly dataset", font=Formats.FONT_REGULAR.value, fg="black", command=lambda: [self.open_plotly_interface("http://127.0.0.1:8050")])
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
lbl_addon = CreateLabelFrameWithIcon(parent=tab11, header="SimBA EXPANSIONS", icon_name='plus_green_2')
|
|
562
|
+
#button_bel = SimbaButton(parent=lbl_addon, txt="Pup retrieval - Analysis Protocol 1", txt_clr='blue', cmd=None, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
563
|
+
button_bel = SimbaButton(parent=lbl_addon, txt="PUP RETRIEVAL - ANALYSIS PROTOCOL 1", txt_clr='blue', cmd=PupRetrievalPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
564
|
+
#cue_light_analyser_btn = SimbaButton(parent=lbl_addon, txt="Cue light analysis", txt_clr='red', cmd=None, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
565
|
+
cue_light_analyser_btn = SimbaButton(parent=lbl_addon, txt="CUE LIGHT ANALYSIS", txt_clr='red', img='light_bulb', cmd=CueLightMainPopUp, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
anchored_roi_analysis_btn = SimbaButton(parent=lbl_addon, txt="ANIMAL-ANCHORED ROIs", txt_clr='orange', cmd=BoundaryMenus, cmd_kwargs={'config_path': lambda:self.config_path})
|
|
570
|
+
ImportVideosFrame(parent_frm=import_frm, config_path=config_path, idx_row=0, idx_column=0)
|
|
571
|
+
ImportPoseFrame(parent_frm=import_frm, idx_row=1, idx_column=0, config_path=config_path)
|
|
572
|
+
further_methods_frm.grid(row=0, column=1, sticky=NW, pady=10, padx=10)
|
|
573
|
+
extract_frm_btn.grid(row=1, column=0, sticky=NW)
|
|
574
|
+
import_frm_dir_btn.grid(row=2, column=0, sticky=NW)
|
|
575
|
+
add_clf_btn.grid(row=3, column=0, sticky=NW)
|
|
576
|
+
remove_clf_btn.grid(row=4, column=0, sticky=NW)
|
|
577
|
+
archive_files_btn.grid(row=5, column=0, sticky=NW)
|
|
578
|
+
reverse_btn.grid(row=6, column=0, sticky=NW)
|
|
579
|
+
interpolate_btn.grid(row=7, column=0, sticky=NW)
|
|
580
|
+
smooth_btn.grid(row=8, column=0, sticky=NW)
|
|
581
|
+
egocentric_align_btn.grid(row=9, column=0, sticky=NW)
|
|
582
|
+
|
|
583
|
+
label_setscale.grid(row=0, sticky=NW, pady=20, padx=20)
|
|
584
|
+
self.distance_in_mm_eb.grid(row=0, column=0, sticky=NW)
|
|
585
|
+
button_setdistanceinmm.grid(row=0, column=1, sticky=NW)
|
|
586
|
+
button_setscale.grid(row=1, column=0, sticky=NW)
|
|
587
|
+
|
|
588
|
+
label_outliercorrection.grid(row=0, sticky=W, padx=10, pady=10)
|
|
589
|
+
button_settings_outlier.grid(row=0, sticky=W)
|
|
590
|
+
button_outliercorrection.grid(row=1, sticky=W)
|
|
591
|
+
button_skipOC.grid(row=2, sticky=W, pady=5)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
roi_feature_frm.grid(row=1, column=0, sticky=NW, padx=10, pady=10)
|
|
595
|
+
append_roi_features_by_animal.grid(row=0, column=0, sticky=NW)
|
|
596
|
+
append_roi_features_by_body_part.grid(row=1, column=0, sticky=NW)
|
|
597
|
+
remove_roi_features_from_feature_set.grid(row=2, column=0, sticky=NW)
|
|
598
|
+
|
|
599
|
+
feature_tools_frm.grid(row=2, column=0, sticky=NW, padx=10, pady=10)
|
|
600
|
+
compute_feature_subset_btn.grid(row=0, column=0, sticky=NW)
|
|
601
|
+
|
|
602
|
+
label_behavior_frm.grid(row=5, sticky=W, padx=10, pady=10)
|
|
603
|
+
select_video_btn_new.grid(row=0, sticky=W)
|
|
604
|
+
select_video_btn_continue.grid(row=1, sticky=W)
|
|
605
|
+
|
|
606
|
+
label_pseudo.grid(row=6, sticky=W, padx=10, pady=10)
|
|
607
|
+
pseudo_lbelling_btn.grid(row=0, column=0, sticky=W, pady=10)
|
|
608
|
+
|
|
609
|
+
label_adv_label.grid(row=7, column=0, sticky=NW, padx=10, pady=10)
|
|
610
|
+
label_adv_note_1.grid(row=0, column=0, sticky=NW)
|
|
611
|
+
label_adv_note_2.grid(row=1, column=0, sticky=NW)
|
|
612
|
+
adv_label_btn_new.grid(row=3, column=0, sticky=NW)
|
|
613
|
+
adv_label_btn_continue.grid(row=4, column=0, sticky=NW)
|
|
614
|
+
|
|
615
|
+
targeted_clip_annotator_frm.grid(row=8, column=0, sticky=NW, padx=10, pady=10)
|
|
616
|
+
targeted_clip_annotator_note.grid(row=0, column=0, sticky=NW)
|
|
617
|
+
targeted_clip_annotator_btn.grid(row=1, column=0, sticky=NW)
|
|
618
|
+
|
|
619
|
+
label_thirdpartyann.grid(row=9, sticky=W, padx=10, pady=10)
|
|
620
|
+
button_importmars.grid(row=0, column=0, sticky=NW)
|
|
621
|
+
button_importboris.grid(row=1, column=0, sticky=NW)
|
|
622
|
+
button_importsolomon.grid(row=2, column=0, sticky=NW)
|
|
623
|
+
button_importethovision.grid(row=0, column=1, sticky=NW)
|
|
624
|
+
button_importdeepethogram.grid(row=1, column=1, sticky=NW)
|
|
625
|
+
import_observer_btn.grid(row=2, column=1, sticky=NW)
|
|
626
|
+
|
|
627
|
+
lbl_tools_frm.grid(row=10, column=0, sticky=NW, padx=10, pady=10)
|
|
628
|
+
visualize_annotation_img_btn.grid(row=0, column=0, sticky=NW)
|
|
629
|
+
third_party_annotations_btn.grid(row=0, column=1, sticky=NW)
|
|
630
|
+
remove_roi_features_from_annotation_set.grid(row=1, column=0, sticky=NW)
|
|
631
|
+
compute_annotation_statistics.grid(row=1, column=1, sticky=NW)
|
|
632
|
+
|
|
633
|
+
label_trainmachinemodel.grid(row=6, sticky=W, padx=10, pady=10)
|
|
634
|
+
button_trainmachinesettings.grid(row=0, column=0, sticky=NW, padx=5)
|
|
635
|
+
button_trainmachinemodel.grid(row=1, column=0, sticky=NW, padx=5)
|
|
636
|
+
button_train_multimodel.grid(row=2, column=0, sticky=NW, padx=5)
|
|
637
|
+
|
|
638
|
+
label_model_validation.grid(row=7, sticky=W, pady=10, padx=10)
|
|
639
|
+
self.csvfile.grid(row=0, sticky=W)
|
|
640
|
+
self.modelfile.grid(row=1, sticky=W)
|
|
641
|
+
button_runvalidmodel.grid(row=2, sticky=W)
|
|
642
|
+
button_generateplot.grid(row=3, sticky=W)
|
|
643
|
+
self.dis_threshold.grid(row=4, sticky=W)
|
|
644
|
+
self.min_behaviorbout.grid(row=5, sticky=W)
|
|
645
|
+
button_validate_model.grid(row=6, sticky=W)
|
|
646
|
+
|
|
647
|
+
label_runmachinemodel.grid(row=8, sticky=NW, padx=10, pady=10)
|
|
648
|
+
button_runmachinemodel.grid(row=0, sticky=NW)
|
|
649
|
+
kleinberg_button.grid(row=1, sticky=NW)
|
|
650
|
+
fsttc_button.grid(row=2, sticky=NW)
|
|
651
|
+
mutual_exclusivity.grid(row=3, sticky=NW)
|
|
652
|
+
|
|
653
|
+
label_machineresults.grid(row=9, sticky=W, padx=10, pady=10)
|
|
654
|
+
button_process_datalog.grid(row=2, column=0, sticky=W, padx=3)
|
|
655
|
+
button_process_movement.grid(row=2, column=1, sticky=W, padx=3)
|
|
656
|
+
button_movebins.grid(row=3, column=1, sticky=W, padx=3)
|
|
657
|
+
button_classifierbins.grid(row=3, column=0, sticky=W, padx=3)
|
|
658
|
+
button_classifier_ROI.grid(row=4, column=0, sticky=W, padx=3)
|
|
659
|
+
button_severity.grid(row=4, column=1, sticky=W, padx=3)
|
|
660
|
+
|
|
661
|
+
visualization_frm.grid(row=11, column=0, sticky=W + N, padx=10, pady=10)
|
|
662
|
+
merge_frm.grid(row=11, column=2, sticky=W + N, padx=5)
|
|
663
|
+
merge_frm_btn.grid(row=0, sticky=NW, padx=5)
|
|
664
|
+
|
|
665
|
+
plotlyInterface.grid(row=11, column=3, sticky=W + N, padx=5)
|
|
666
|
+
button_save_plotly_file.grid(row=10, sticky=W)
|
|
667
|
+
self.plotly_file.grid(row=11, sticky=W)
|
|
668
|
+
self.groups_file.grid(row=12, sticky=W)
|
|
669
|
+
button_open_plotly_interface.grid(row=13, sticky=W)
|
|
670
|
+
|
|
671
|
+
lbl_addon.grid(row=0, sticky=W)
|
|
672
|
+
button_bel.grid(row=0, sticky=W)
|
|
673
|
+
cue_light_analyser_btn.grid(row=1, sticky=NW)
|
|
674
|
+
anchored_roi_analysis_btn.grid(row=2, sticky=NW)
|
|
675
|
+
|
|
676
|
+
if ENV[ENV_VARS.UNSUPERVISED_INTERFACE.value]:
|
|
677
|
+
from simba.unsupervised.unsupervised_main import UnsupervisedGUI
|
|
678
|
+
unsupervised_btn = Button(lbl_addon, text="Unsupervised analysis", fg="purple", font=Formats.FONT_REGULAR.value, command=lambda: UnsupervisedGUI(config_path=self.config_path))
|
|
679
|
+
unsupervised_btn.grid(row=3, sticky=NW)
|
|
680
|
+
write_to_recent_project_paths(config_path=self.config_path)
|
|
681
|
+
|
|
682
|
+
def create_video_info_table(self):
|
|
683
|
+
video_info_tabler = VideoInfoTable(config_path=self.config_path)
|
|
684
|
+
video_info_tabler.run()
|
|
685
|
+
|
|
686
|
+
def initiate_skip_outlier_correction(self):
|
|
687
|
+
outlier_correction_skipper = OutlierCorrectionSkipper(config_path=self.config_path)
|
|
688
|
+
outlier_correction_skipper.run()
|
|
689
|
+
|
|
690
|
+
def validate_model_first_step(self):
|
|
691
|
+
_ = InferenceValidation(config_path=self.config_path, input_file_path=self.csvfile.file_path, clf_path=self.modelfile.file_path)
|
|
692
|
+
|
|
693
|
+
def train_single_model(self, config_path=None):
|
|
694
|
+
model_trainer = TrainRandomForestClassifier(config_path=config_path)
|
|
695
|
+
model_trainer.run()
|
|
696
|
+
model_trainer.save()
|
|
697
|
+
|
|
698
|
+
def train_multiple_models_from_meta(self, config_path=None):
|
|
699
|
+
model_trainer = GridSearchRandomForestClassifier(config_path=config_path)
|
|
700
|
+
model_trainer.run()
|
|
701
|
+
|
|
702
|
+
def importBoris(self):
|
|
703
|
+
ann_folder = askdirectory()
|
|
704
|
+
boris_appender = BorisAppender(config_path=self.config_path, data_dir=ann_folder)
|
|
705
|
+
threading.Thread(target=boris_appender.run).start()
|
|
706
|
+
|
|
707
|
+
def importSolomon(self):
|
|
708
|
+
ann_folder = askdirectory()
|
|
709
|
+
solomon_importer = SolomonImporter(config_path=self.config_path, data_dir=ann_folder)
|
|
710
|
+
threading.Thread(target=solomon_importer.run).start()
|
|
711
|
+
|
|
712
|
+
def import_ethovision(self):
|
|
713
|
+
ann_folder = askdirectory()
|
|
714
|
+
ethovision_importer = ImportEthovision(config_path=self.config_path, data_dir=ann_folder)
|
|
715
|
+
threading.Thread(target=ethovision_importer.run).start()
|
|
716
|
+
|
|
717
|
+
def import_deepethogram(self):
|
|
718
|
+
ann_folder = askdirectory()
|
|
719
|
+
deepethogram_importer = DeepEthogramImporter(config_path=self.config_path, data_dir=ann_folder)
|
|
720
|
+
if self.core_cnt > Defaults.THREADSAFE_CORE_COUNT.value:
|
|
721
|
+
deepethogram_importer.run()
|
|
722
|
+
else:
|
|
723
|
+
threading.Thread(target=deepethogram_importer.run).start()
|
|
724
|
+
|
|
725
|
+
def import_noldus_observer(self):
|
|
726
|
+
directory = askdirectory()
|
|
727
|
+
noldus_observer_importer = NoldusObserverImporter(config_path=self.config_path, data_dir=directory)
|
|
728
|
+
threading.Thread(target=noldus_observer_importer.run).start()
|
|
729
|
+
|
|
730
|
+
def importMARS(self):
|
|
731
|
+
bento_dir = askdirectory()
|
|
732
|
+
bento_appender = BentoAppender(config_path=self.config_path, data_dir=bento_dir)
|
|
733
|
+
threading.Thread(target=bento_appender.run).start()
|
|
734
|
+
|
|
735
|
+
def launch_interactive_plot(self):
|
|
736
|
+
interactive_grapher = InteractiveProbabilityGrapher(config_path=self.config_path,file_path=self.csvfile.file_path,model_path=self.modelfile.file_path)
|
|
737
|
+
interactive_grapher.run()
|
|
738
|
+
|
|
739
|
+
def generateSimBPlotlyFile(self, var):
|
|
740
|
+
inputList = []
|
|
741
|
+
for i in var:
|
|
742
|
+
inputList.append(i.get())
|
|
743
|
+
stdout_warning(msg="SimBA plotly interface is not available.")
|
|
744
|
+
pass
|
|
745
|
+
|
|
746
|
+
def open_plotly_interface(self, url):
|
|
747
|
+
try:
|
|
748
|
+
self.p.kill()
|
|
749
|
+
self.p2.kill()
|
|
750
|
+
except:
|
|
751
|
+
print("Starting plotly")
|
|
752
|
+
# get h5 file path and csv file path
|
|
753
|
+
filePath, groupPath = self.plotly_file.file_path, self.groups_file.file_path
|
|
754
|
+
|
|
755
|
+
# print file read
|
|
756
|
+
if filePath.endswith(".h5"):
|
|
757
|
+
print("Reading in", os.path.basename(filePath))
|
|
758
|
+
elif groupPath.endswith(".csv"):
|
|
759
|
+
print("Reading in", os.path.basename(groupPath))
|
|
760
|
+
|
|
761
|
+
self.p = subprocess.Popen(
|
|
762
|
+
[
|
|
763
|
+
sys.executable,
|
|
764
|
+
os.path.join(
|
|
765
|
+
os.path.dirname(__file__), "dash_app", "SimBA_dash_app.py"
|
|
766
|
+
),
|
|
767
|
+
filePath,
|
|
768
|
+
groupPath,
|
|
769
|
+
]
|
|
770
|
+
)
|
|
771
|
+
# csvPath = os.path.join(os.path.dirname(self.config_path),'csv')
|
|
772
|
+
# p = subprocess.Popen([sys.executable, r'simba\SimBA_dash_app.py', filePath, groupPath, csvPath])
|
|
773
|
+
wait_for_internet_connection(url)
|
|
774
|
+
self.p2 = subprocess.Popen(
|
|
775
|
+
[
|
|
776
|
+
sys.executable,
|
|
777
|
+
os.path.join(
|
|
778
|
+
os.path.dirname(__file__), "dash_app", "run_dash_tkinter.py"
|
|
779
|
+
),
|
|
780
|
+
url,
|
|
781
|
+
]
|
|
782
|
+
)
|
|
783
|
+
subprocess_children = [self.p, self.p2]
|
|
784
|
+
atexit.register(terminate_children, subprocess_children)
|
|
785
|
+
|
|
786
|
+
def trainmachinemodelsetting(self):
|
|
787
|
+
_ = MachineModelSettingsPopUp(config_path=self.config_path)
|
|
788
|
+
|
|
789
|
+
def run_feature_extraction(self):
|
|
790
|
+
feature_extractor_classes = get_bp_config_code_class_pairs()
|
|
791
|
+
if self.user_defined_var.get():
|
|
792
|
+
check_file_exist_and_readable(file_path=self.scriptfile.file_path, raise_error=True)
|
|
793
|
+
stdout_information(msg=f"Running feature extraction from file {self.scriptfile.file_path}...")
|
|
794
|
+
custom_feature_extractor = CustomFeatureExtractor(extractor_file_path=self.scriptfile.file_path,config_path=self.config_path)
|
|
795
|
+
custom_feature_extractor.run()
|
|
796
|
+
stdout_success(msg="Custom feature extraction complete!",source=self.__class__.__name__)
|
|
797
|
+
else:
|
|
798
|
+
stdout_information(msg=f"Pose-estimation body part setting for feature extraction: {str(self.animal_cnt)} animals {str(self.pose_setting)} body-parts...")
|
|
799
|
+
if self.pose_setting not in feature_extractor_classes.keys():
|
|
800
|
+
raise InvalidInputError(msg=f"The project pose-configuration key is set to {self.pose_setting} which is invalid. OPTIONS: {list(feature_extractor_classes.keys())}. Check the pose-estimation setting in the project_config.ini", source=self.__class__.__name__)
|
|
801
|
+
if self.pose_setting == "8":
|
|
802
|
+
feature_extractor = feature_extractor_classes[self.pose_setting][self.animal_cnt](config_path=self.config_path)
|
|
803
|
+
else:
|
|
804
|
+
feature_extractor = feature_extractor_classes[self.pose_setting](config_path=self.config_path)
|
|
805
|
+
feature_extractor.run()
|
|
806
|
+
|
|
807
|
+
def set_distance_mm(self):
|
|
808
|
+
check_int(name="DISTANCE IN MILLIMETER",value=self.distance_in_mm_eb.entry_get,min_value=1)
|
|
809
|
+
self.config.set("Frame settings", "distance_mm", self.distance_in_mm_eb.entry_get)
|
|
810
|
+
with open(self.config_path, "w") as f:
|
|
811
|
+
self.config.write(f)
|
|
812
|
+
|
|
813
|
+
def correct_outlier(self):
|
|
814
|
+
outlier_correcter_movement = OutlierCorrecterMovement(config_path=self.config_path)
|
|
815
|
+
outlier_correcter_movement.run()
|
|
816
|
+
outlier_correcter_location = OutlierCorrecterLocation(config_path=self.config_path)
|
|
817
|
+
outlier_correcter_location.run()
|
|
818
|
+
stdout_success(msg='Outlier corrected files located in "project_folder/csv/outlier_corrected_movement_location" directory',source=self.__class__.__name__)
|
|
819
|
+
|
|
820
|
+
def callback(self, url):
|
|
821
|
+
webbrowser.open_new(url)
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
class App(object):
|
|
825
|
+
def __init__(self):
|
|
826
|
+
bg_path = os.path.join(os.path.dirname(__file__), Paths.BG_IMG_PATH.value)
|
|
827
|
+
emojis = get_emojis()
|
|
828
|
+
icon_path_windows = os.path.join(os.path.dirname(__file__), Paths.LOGO_ICON_WINDOWS_PATH.value)
|
|
829
|
+
icon_path_darwin = os.path.join(os.path.dirname(__file__), Paths.LOGO_ICON_DARWIN_PATH.value)
|
|
830
|
+
self.menu_icons = get_icons_paths()
|
|
831
|
+
recent_project_paths = get_recent_projects_paths()
|
|
832
|
+
self.root = Tk()
|
|
833
|
+
self.root.title("SimBA")
|
|
834
|
+
self.root.minsize(750, 750)
|
|
835
|
+
self.root.geometry(Formats.ROOT_WINDOW_SIZE.value)
|
|
836
|
+
self.root.rowconfigure(0, weight=1)
|
|
837
|
+
self.root.columnconfigure(0, weight=1)
|
|
838
|
+
if currentPlatform == OS.WINDOWS.value:
|
|
839
|
+
load_simba_fonts()
|
|
840
|
+
self.root.iconbitmap(icon_path_windows)
|
|
841
|
+
if currentPlatform == OS.MAC.value:
|
|
842
|
+
load_simba_fonts()
|
|
843
|
+
self.root.iconphoto(False, ImageTk.PhotoImage(PIL.Image.open(icon_path_darwin)))
|
|
844
|
+
for k in self.menu_icons.keys():
|
|
845
|
+
self.menu_icons[k]["img"] = ImageTk.PhotoImage(image=PIL.Image.open(os.path.join(os.path.dirname(__file__), self.menu_icons[k]["icon_path"])))
|
|
846
|
+
bg_img = ImageTk.PhotoImage(file=bg_path)
|
|
847
|
+
background = Label(self.root, image=bg_img, bd=0, bg="white")
|
|
848
|
+
background.pack(fill="both", expand=True)
|
|
849
|
+
background.image = bg_img
|
|
850
|
+
|
|
851
|
+
ultralytics_version = get_pkg_version(pkg=PackageNames.ULTRALYTICS.value)
|
|
852
|
+
yolo_state = DISABLED if ultralytics_version is None else NORMAL
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
menu = Menu(self.root)
|
|
856
|
+
self.root.config(menu=menu)
|
|
857
|
+
self.file_menu = Menu(menu)
|
|
858
|
+
menu.add_cascade(label="File", menu=self.file_menu)
|
|
859
|
+
self.file_menu.add_command(label="Create a new project", compound="left", image=self.menu_icons["create"]["img"], command=lambda: ProjectCreatorPopUp(), font=Formats.FONT_REGULAR.value)
|
|
860
|
+
self.file_menu.add_command(label="Load project", compound="left", image=self.menu_icons["load"]["img"], command=lambda: LoadProjectPopUp(), font=Formats.FONT_REGULAR.value)
|
|
861
|
+
self.file_menu.add_separator()
|
|
862
|
+
self.recent_projects_menu = Menu(menu)
|
|
863
|
+
|
|
864
|
+
for recent_project_path in recent_project_paths:
|
|
865
|
+
self.recent_projects_menu.add_command(label=recent_project_path,command=lambda p=recent_project_path: SimbaProjectPopUp(config_path=p), font=Formats.FONT_REGULAR.value)
|
|
866
|
+
self.recent_projects_menu.add_command(label='Clear recent projects', command=lambda: self.clear_recent_projects(), font=Formats.FONT_REGULAR_ITALICS.value)
|
|
867
|
+
recent_project_state = DISABLED if len(recent_project_paths) == 0 else NORMAL
|
|
868
|
+
self.file_menu.add_cascade(label="Open recent project...", compound="left", image=self.menu_icons["recent_files"]["img"], menu=self.recent_projects_menu, font=Formats.FONT_REGULAR.value, state=recent_project_state)
|
|
869
|
+
|
|
870
|
+
self.file_menu.add_separator()
|
|
871
|
+
self.file_menu.add_command(label="Restart", compound="left", image=self.menu_icons["restart"]["img"], command=lambda: self.restart(), font=Formats.FONT_REGULAR.value)
|
|
872
|
+
self.file_menu.add_separator()
|
|
873
|
+
self.file_menu.add_command(label="Exit", compound="left", image=self.menu_icons["exit"]["img"], command=self.root.destroy, font=Formats.FONT_REGULAR.value)
|
|
874
|
+
|
|
875
|
+
batch_process_menu = Menu(menu)
|
|
876
|
+
menu.add_cascade(label="Process Videos", menu=batch_process_menu)
|
|
877
|
+
batch_process_menu.add_command(label="Batch pre-process videos", compound="left", image=self.menu_icons["factory"]["img"], command=lambda: BatchPreProcessPopUp(), font=Formats.FONT_REGULAR.value)
|
|
878
|
+
|
|
879
|
+
blob_tracking_menu = Menu(batch_process_menu)
|
|
880
|
+
blob_tracking_menu.add_command(label="Perform blob tracking", compound="left", image=self.menu_icons["bubble_green"]["img"], command=InitializeBlobTrackerPopUp, font=Formats.FONT_REGULAR.value)
|
|
881
|
+
blob_tracking_menu.add_command(label="Visualize blob tracking", compound="left", image=self.menu_icons["bubble_pink"]["img"], command=BlobVisualizerPopUp, font=Formats.FONT_REGULAR.value)
|
|
882
|
+
batch_process_menu.add_cascade(label="Blob tracking...", compound="left", image=self.menu_icons["bubble"]["img"], menu=blob_tracking_menu, font=Formats.FONT_REGULAR.value)
|
|
883
|
+
|
|
884
|
+
yolo_tracking_menu = Menu(batch_process_menu)
|
|
885
|
+
yolo_tracking_menu.add_command(label="Train YOLO model", compound="left", image=self.menu_icons["ultralytics_2"]["img"], command=YOLOPoseTrainPopUP, font=Formats.FONT_REGULAR.value, state=yolo_state)
|
|
886
|
+
yolo_tracking_menu.add_command(label="Predict with YOLO model", compound="left", image=self.menu_icons["ultralytics_2"]["img"], command=YOLOPoseInferencePopUP, font=Formats.FONT_REGULAR.value, state=yolo_state)
|
|
887
|
+
yolo_tracking_menu.add_command(label="Visualize YOLO model results", compound="left", image=self.menu_icons["ultralytics_2"]["img"], command=YoloPoseVisualizerPopUp, font=Formats.FONT_REGULAR.value, state=yolo_state)
|
|
888
|
+
batch_process_menu.add_cascade(label="YOLO tracking...", compound="left", image=self.menu_icons["ultralytics_2"]["img"], menu=yolo_tracking_menu, font=Formats.FONT_REGULAR.value, state=yolo_state)
|
|
889
|
+
|
|
890
|
+
video_process_menu = Menu(menu)
|
|
891
|
+
fps_menu = Menu(video_process_menu)
|
|
892
|
+
fps_menu.add_command(label="Change FPS for single video", compound="left", image=self.menu_icons["single_blue"]["img"], command=ChangeFpsSingleVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
893
|
+
fps_menu.add_command(label="Change FPS for multiple videos", compound="left", image=self.menu_icons["multiple_blue"]["img"], command=ChangeFpsMultipleVideosPopUp, font=Formats.FONT_REGULAR.value)
|
|
894
|
+
fps_menu.add_command(label="Up-sample fps with interpolation", command=UpsampleVideosPopUp, font=Formats.FONT_REGULAR.value)
|
|
895
|
+
|
|
896
|
+
menu.add_cascade(label="Tools", menu=video_process_menu)
|
|
897
|
+
video_process_menu.add_cascade(label="Change FPS...", compound="left", image=self.menu_icons["fps"]["img"], menu=fps_menu, font=Formats.FONT_REGULAR.value)
|
|
898
|
+
|
|
899
|
+
clip_video_menu = Menu(menu)
|
|
900
|
+
clip_video_menu.add_command(label="Clip single video", command=ClipVideoPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["video_2"]["img"], compound="left",)
|
|
901
|
+
clip_video_menu.add_command(label="Clip multiple videos", command=InitiateClipMultipleVideosByTimestampsPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["stack"]["img"], compound="left",)
|
|
902
|
+
|
|
903
|
+
clip_video_menu.add_command(label="Clip video into multiple videos", command=MultiShortenPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["one_to_many"]["img"], compound="left",)
|
|
904
|
+
clip_video_menu.add_command(label="Clip single video by frame numbers", command=ClipSingleVideoByFrameNumbers, font=Formats.FONT_REGULAR.value, image=self.menu_icons["video_2"]["img"], compound="left",)
|
|
905
|
+
clip_video_menu.add_command(label="Clip multiple videos by frame numbers", command=InitiateClipMultipleVideosByFrameNumbersPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["stack"]["img"], compound="left",)
|
|
906
|
+
|
|
907
|
+
video_process_menu.add_cascade(label="Clip videos...", compound="left", image=self.menu_icons["clip"]["img"], menu=clip_video_menu, font=Formats.FONT_REGULAR.value)
|
|
908
|
+
|
|
909
|
+
crop_video_menu = Menu(menu)
|
|
910
|
+
crop_video_menu.add_command(label="Crop videos", compound="left", image=self.menu_icons["crop"]["img"], command=CropVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
911
|
+
crop_video_menu.add_command(label="Crop videos (circles)", compound="left", image=self.menu_icons["circle"]["img"], command=CropVideoCirclesPopUp, font=Formats.FONT_REGULAR.value)
|
|
912
|
+
crop_video_menu.add_command(label="Crop videos (polygons)", compound="left", image=self.menu_icons["polygon"]["img"], command=CropVideoPolygonsPopUp, font=Formats.FONT_REGULAR.value)
|
|
913
|
+
crop_video_menu.add_command(label="Multi-crop", compound="left", image=self.menu_icons["crop"]["img"], command=MultiCropPopUp, font=Formats.FONT_REGULAR.value)
|
|
914
|
+
video_process_menu.add_cascade(label="Crop videos...", compound="left", image=self.menu_icons["crop"]["img"], menu=crop_video_menu, font=Formats.FONT_REGULAR.value)
|
|
915
|
+
|
|
916
|
+
format_menu = Menu(video_process_menu)
|
|
917
|
+
img_format_menu = Menu(format_menu)
|
|
918
|
+
video_format_menu = Menu(format_menu)
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
img_format_menu.add_command(label="Convert images to PNG", compound="left", image=self.menu_icons["png"]["img"], command=Convert2PNGPopUp, font=Formats.FONT_REGULAR.value)
|
|
923
|
+
img_format_menu.add_command(label="Convert images to JPEG", compound="left", image=self.menu_icons["jpeg"]["img"], command=Convert2jpegPopUp, font=Formats.FONT_REGULAR.value)
|
|
924
|
+
img_format_menu.add_command(label="Convert images to BMP", compound="left", image=self.menu_icons["bmp"]["img"], command=Convert2bmpPopUp, font=Formats.FONT_REGULAR.value)
|
|
925
|
+
img_format_menu.add_command(label="Convert images to TIFF", compound="left", image=self.menu_icons["tiff"]["img"], command=Convert2TIFFPopUp, font=Formats.FONT_REGULAR.value)
|
|
926
|
+
img_format_menu.add_command(label="Convert images to WEBP", compound="left", image=self.menu_icons["webp"]["img"], command=Convert2WEBPPopUp, font=Formats.FONT_REGULAR.value)
|
|
927
|
+
video_format_menu.add_command(label="Convert videos to MP4", compound="left", image=self.menu_icons["mp4"]["img"], command=Convert2MP4PopUp, font=Formats.FONT_REGULAR.value)
|
|
928
|
+
video_format_menu.add_command(label="Convert videos to AVI", compound="left", image=self.menu_icons["avi"]["img"], command=Convert2AVIPopUp, font=Formats.FONT_REGULAR.value)
|
|
929
|
+
video_format_menu.add_command(label="Convert videos to WEBM", compound="left", image=self.menu_icons["webm"]["img"], command=Convert2WEBMPopUp, font=Formats.FONT_REGULAR.value)
|
|
930
|
+
video_format_menu.add_command(label="Convert videos to MOV", compound="left", image=self.menu_icons["mov"]["img"], command=Convert2MOVPopUp, font=Formats.FONT_REGULAR.value)
|
|
931
|
+
format_menu.add_cascade(label="Convert image file formats...", compound="left", image=self.menu_icons["image"]["img"], menu=img_format_menu, font=Formats.FONT_REGULAR.value)
|
|
932
|
+
format_menu.add_cascade(label="Change video file formats...", compound="left", image=self.menu_icons["video_2"]["img"], menu=video_format_menu, font=Formats.FONT_REGULAR.value)
|
|
933
|
+
video_process_menu.add_cascade(label="Convert file formats...", compound="left", image=self.menu_icons["convert"]["img"], menu=format_menu, font=Formats.FONT_REGULAR.value)
|
|
934
|
+
|
|
935
|
+
rm_clr_menu = Menu(video_process_menu)
|
|
936
|
+
rm_clr_menu.add_command(label="Convert to grayscale", compound="left", image=self.menu_icons["greyscale"]["img"], command=lambda: GreyscaleSingleVideoPopUp(), font=Formats.FONT_REGULAR.value)
|
|
937
|
+
rm_clr_menu.add_command(label="Convert to black and white", compound="left", image=self.menu_icons["bw"]["img"], command=Convert2BlackWhitePopUp, font=Formats.FONT_REGULAR.value)
|
|
938
|
+
rm_clr_menu.add_command(label="CLAHE enhance videos", compound="left", image=self.menu_icons["clahe"]["img"], command=CLAHEPopUp, font=Formats.FONT_REGULAR.value)
|
|
939
|
+
rm_clr_menu.add_command(label="Interactively CLAHE enhance videos", compound="left", image=self.menu_icons["clahe"]["img"], command=InteractiveClahePopUp, font=Formats.FONT_REGULAR.value)
|
|
940
|
+
video_process_menu.add_cascade(label="Remove color from videos...", compound="left", image=self.menu_icons["clahe"]["img"], menu=rm_clr_menu, font=Formats.FONT_REGULAR.value)
|
|
941
|
+
|
|
942
|
+
concatenate_menu = Menu(video_process_menu)
|
|
943
|
+
concatenate_menu.add_command(label="Concatenate two videos", compound="left", image=self.menu_icons["concat"]["img"], command=ConcatenatingVideosPopUp, font=Formats.FONT_REGULAR.value)
|
|
944
|
+
concatenate_menu.add_command(label="Concatenate multiple videos", compound="left", image=self.menu_icons["concat_videos"]["img"], command=lambda: ConcatenatorPopUp(config_path=None), font=Formats.FONT_REGULAR.value)
|
|
945
|
+
video_process_menu.add_cascade(label="Concatenate (stack) videos...", compound="left", image=self.menu_icons["concat"]["img"], menu=concatenate_menu, font=Formats.FONT_REGULAR.value)
|
|
946
|
+
video_process_menu.add_command(label="Convert ROI definitions", compound="left", image=self.menu_icons["roi"]["img"], command=lambda: ConvertROIDefinitionsPopUp(), font=Formats.FONT_REGULAR.value)
|
|
947
|
+
|
|
948
|
+
convert_pose_file_format_menu = Menu(video_process_menu)
|
|
949
|
+
convert_pose_file_format_menu.add_command(label="COCO key-points -> YOLO key-points", compound="left", image=self.menu_icons["coco_small"]["img"], command=COCOKeypoints2YOLOkeypointsPopUp, font=Formats.FONT_REGULAR.value)
|
|
950
|
+
convert_pose_file_format_menu.add_command(label="COCO key-point files (multiple) -> COCO key-point file (single)", compound="left", image=self.menu_icons["coco_small"]["img"], command=MergeCOCOKeypointFilesPopUp, font=Formats.FONT_REGULAR.value)
|
|
951
|
+
convert_pose_file_format_menu.add_command(label="DLC annotations -> Labelme key-points", compound="left", image=self.menu_icons["dlc_2"]["img"], command=DLC2LabelmePopUp, font=Formats.FONT_REGULAR.value)
|
|
952
|
+
convert_pose_file_format_menu.add_command(label="DLC annotations -> YOLO pose-estimation annotations", compound="left", image=self.menu_icons["dlc_2"]["img"], command=DLCYoloKeypointsPopUp, font=Formats.FONT_REGULAR.value)
|
|
953
|
+
convert_pose_file_format_menu.add_command(label="DLC H5 inference -> YOLO pose-estimation annotations", compound="left", image=self.menu_icons["dlc_2"]["img"], command=DLCH5Inference2YoloPopUp, font=Formats.FONT_REGULAR.value)
|
|
954
|
+
convert_pose_file_format_menu.add_command(label="SLEAP CSV inference -> YOLO pose-estimation annotations", compound="left", image=self.menu_icons["sleap_small"]["img"], command=SLEAPcsvInference2Yolo, font=Formats.FONT_REGULAR.value)
|
|
955
|
+
convert_pose_file_format_menu.add_command(label="SLEAP H5 inference -> YOLO pose-estimation annotations", compound="left", image=self.menu_icons["sleap_small"]["img"], command=SLEAPH5Inference2YoloPopUp, font=Formats.FONT_REGULAR.value)
|
|
956
|
+
convert_pose_file_format_menu.add_command(label="SLEAP SLP annotations -> YOLO pose-estimation annotations", compound="left", image=self.menu_icons["sleap_small"]["img"], command=SLEAPAnnotations2YoloPopUp, font=Formats.FONT_REGULAR.value)
|
|
957
|
+
convert_pose_file_format_menu.add_command(label="SimBA ROI -> YOLO bounding-box annotations", compound="left", image=self.menu_icons["SimBA_logo_3_small"]["img"], command=SimBAROIs2YOLOPopUp, font=Formats.FONT_REGULAR.value)
|
|
958
|
+
convert_pose_file_format_menu.add_command(label="SimBA -> YOLO pose-estimation annotations", compound="left", image=self.menu_icons["SimBA_logo_3_small"]["img"], command=SimBA2YoloKeypointsPopUp, font=Formats.FONT_REGULAR.value)
|
|
959
|
+
convert_pose_file_format_menu.add_command(label="Labelme key-points -> Images", compound="left", image=self.menu_icons["labelme"]["img"], command=Labelme2ImgsPopUp, font=Formats.FONT_REGULAR.value)
|
|
960
|
+
convert_pose_file_format_menu.add_command(label="Labelme key-points -> CSV", compound="left", image=self.menu_icons["labelme"]["img"], command=Labelme2DataFramePopUp, font=Formats.FONT_REGULAR.value)
|
|
961
|
+
convert_pose_file_format_menu.add_command(label="Labelme bounding-boxes -> YOLO bounding-box annotations", compound="left", image=self.menu_icons["labelme"]["img"], command=LabelmeBbox2YoloBboxPopUp, font=Formats.FONT_REGULAR.value)
|
|
962
|
+
|
|
963
|
+
video_process_menu.add_cascade(label="Convert tracking data formats...", compound="left", image=self.menu_icons["pose"]["img"], menu=convert_pose_file_format_menu, font=Formats.FONT_REGULAR.value)
|
|
964
|
+
|
|
965
|
+
convert_data_menu = Menu(video_process_menu)
|
|
966
|
+
convert_data_menu.add_command(label="Convert CSV to parquet", compound="left", image=self.menu_icons["parquet"]["img"], command=Csv2ParquetPopUp, font=Formats.FONT_REGULAR.value)
|
|
967
|
+
convert_data_menu.add_command(label="Convert parquet to CSV", compound="left", image=self.menu_icons["csv_grey"]["img"], command=Parquet2CsvPopUp, font=Formats.FONT_REGULAR.value)
|
|
968
|
+
video_process_menu.add_cascade(label="Convert working file type...", compound="left", image=self.menu_icons["change"]["img"], menu=convert_data_menu, font=Formats.FONT_REGULAR.value)
|
|
969
|
+
video_process_menu.add_command(label="Create path plot", compound="left", image=self.menu_icons["path"]["img"], command=MakePathPlotPopUp, font=Formats.FONT_REGULAR.value)
|
|
970
|
+
|
|
971
|
+
downsample_video_menu = Menu(video_process_menu)
|
|
972
|
+
downsample_video_menu.add_command(label="Down-sample single video", compound="left", image=self.menu_icons["single_green"]["img"], command=DownsampleSingleVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
973
|
+
downsample_video_menu.add_command(label="Down-sample multiple videos", compound="left", image=self.menu_icons["multiple_green"]["img"], command=DownsampleMultipleVideosPopUp, font=Formats.FONT_REGULAR.value)
|
|
974
|
+
video_process_menu.add_cascade(label="Down-sample video...", compound="left", image=self.menu_icons["sample"]["img"], menu=downsample_video_menu, font=Formats.FONT_REGULAR.value)
|
|
975
|
+
video_process_menu.add_cascade(label="Drop body-parts from tracking data", compound="left", image=self.menu_icons["trash"]["img"], command=DropTrackingDataPopUp, font=Formats.FONT_REGULAR.value)
|
|
976
|
+
extract_frames_menu = Menu(video_process_menu, font=Formats.FONT_REGULAR.value)
|
|
977
|
+
extract_frames_menu.add_command(label="Extract defined frames", command=ExtractSpecificFramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["frames"]["img"], compound="left")
|
|
978
|
+
extract_frames_menu.add_command(label="Extract frames from single video", command=SingleVideo2FramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["frames_2"]["img"], compound="left")
|
|
979
|
+
extract_frames_menu.add_command(label="Extract frames from multiple videos", command=MultipleVideos2FramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["stack"]["img"], compound="left")
|
|
980
|
+
extract_frames_menu.add_command(label="Extract frames from seq files", command=ExtractSEQFramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["fire"]["img"], compound="left")
|
|
981
|
+
video_process_menu.add_cascade(label="Extract frames...", compound="left", image=self.menu_icons["frames"]["img"], menu=extract_frames_menu, font=Formats.FONT_REGULAR.value)
|
|
982
|
+
|
|
983
|
+
video_process_menu.add_command(label="Create GIFs", compound="left", image=self.menu_icons["gif"]["img"], command=CreateGIFPopUP, font=Formats.FONT_REGULAR.value)
|
|
984
|
+
|
|
985
|
+
video_process_menu.add_command(label="Get metric conversion factor (pixels/millimeter)", compound="left", image=self.menu_icons["calipher"]["img"], command=CalculatePixelsPerMMInVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
986
|
+
video_process_menu.add_command(label="Change video brightness / contrast", compound="left", image=self.menu_icons["brightness"]["img"], command=BrightnessContrastPopUp, font=Formats.FONT_REGULAR.value)
|
|
987
|
+
video_process_menu.add_command(label="Merge frames to video", compound="left", image=self.menu_icons["merge"]["img"], command=MergeFrames2VideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
988
|
+
video_process_menu.add_command(label="Change video playback speed", compound="left", image=self.menu_icons["run"]["img"], command=ChangeSpeedPopup, font=Formats.FONT_REGULAR.value)
|
|
989
|
+
video_process_menu.add_command(label="Print classifier info", compound="left", image=self.menu_icons["print"]["img"], command=PrintModelInfoPopUp, font=Formats.FONT_REGULAR.value)
|
|
990
|
+
video_process_menu.add_command(label="Show video file(s) meta data", compound="left", image=self.menu_icons["print"]["img"], command=PrintVideoMetaDataPopUp, font=Formats.FONT_REGULAR.value)
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
video_process_menu.add_cascade(label="Reorganize Tracking Data", compound="left", image=self.menu_icons["reorganize"]["img"], command=PoseReorganizerPopUp, font=Formats.FONT_REGULAR.value)
|
|
994
|
+
|
|
995
|
+
rotate_menu = Menu(menu)
|
|
996
|
+
rotate_menu.add_command(label="Rotate videos", compound="left", image=self.menu_icons["flip_red"]["img"], command=RotateVideoSetDegreesPopUp, font=Formats.FONT_REGULAR.value)
|
|
997
|
+
rotate_menu.add_command(label="Interactively rotate videos", compound="left", image=self.menu_icons["flip_red"]["img"], command=VideoRotatorPopUp, font=Formats.FONT_REGULAR.value)
|
|
998
|
+
rotate_menu.add_command(label="Flip videos", compound="left", image=self.menu_icons["flip_green"]["img"], command=FlipVideosPopUp, font=Formats.FONT_REGULAR.value)
|
|
999
|
+
rotate_menu.add_command(label="Reverse videos", compound="left", image=self.menu_icons["reverse_blue"]["img"], command=ReverseVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
1000
|
+
video_process_menu.add_cascade(label="Rotate / flip / reverse videos...", compound="left", image=self.menu_icons["rotate"]["img"], menu=rotate_menu, font=Formats.FONT_REGULAR.value)
|
|
1001
|
+
|
|
1002
|
+
superimpose_menu = Menu(menu)
|
|
1003
|
+
superimpose_menu.add_command(label="Superimpose frame numbers", compound="left", image=self.menu_icons["number_black"]["img"], command=SuperImposeFrameCountPopUp, font=Formats.FONT_REGULAR.value)
|
|
1004
|
+
superimpose_menu.add_command(label="Superimpose watermark", compound="left", image=self.menu_icons["watermark_green"]["img"], command=SuperimposeWatermarkPopUp, font=Formats.FONT_REGULAR.value)
|
|
1005
|
+
superimpose_menu.add_command(label="Superimpose timer", compound="left", image=self.menu_icons["timer"]["img"], command=SuperimposeTimerPopUp, font=Formats.FONT_REGULAR.value)
|
|
1006
|
+
superimpose_menu.add_command(label="Superimpose progress-bar", compound="left", image=self.menu_icons["progressbar_black"]["img"], command=SuperimposeProgressBarPopUp, font=Formats.FONT_REGULAR.value)
|
|
1007
|
+
superimpose_menu.add_command(label="Superimpose video on video", compound="left", image=self.menu_icons["video_2"]["img"], command=SuperimposeVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
1008
|
+
superimpose_menu.add_command(label="Superimpose video names", compound="left", image=self.menu_icons["id_card"]["img"], command=SuperimposeVideoNamesPopUp, font=Formats.FONT_REGULAR.value)
|
|
1009
|
+
superimpose_menu.add_command(label="Superimpose free-text", compound="left", image=self.menu_icons["text_black"]["img"], command=SuperimposeTextPopUp, font=Formats.FONT_REGULAR.value)
|
|
1010
|
+
video_process_menu.add_cascade(label="Superimpose on videos...", compound="left", image=self.menu_icons["superimpose"]["img"], menu=superimpose_menu, font=Formats.FONT_REGULAR.value)
|
|
1011
|
+
|
|
1012
|
+
remove_bg_menu = Menu(menu)
|
|
1013
|
+
remove_bg_menu.add_command(label="Remove background from single video (mean subtraction)", compound="left", image=self.menu_icons["remove_bg"]["img"], command=BackgroundRemoverSingleVideoPopUp, font=Formats.FONT_REGULAR.value)
|
|
1014
|
+
remove_bg_menu.add_command(label="Remove background from multiple videos (mean subtraction)", compound="left", image=self.menu_icons["remove_bg"]["img"], command=BackgroundRemoverDirectoryPopUp, font=Formats.FONT_REGULAR.value)
|
|
1015
|
+
video_process_menu.add_cascade(label="Remove video backgrounds...", compound="left", image=self.menu_icons["remove_bg"]["img"], menu=remove_bg_menu, font=Formats.FONT_REGULAR.value)
|
|
1016
|
+
|
|
1017
|
+
temporal_join_videos = Menu(menu)
|
|
1018
|
+
temporal_join_videos.add_command(label="Temporal join all videos in directory", command=VideoTemporalJoinPopUp, font=Formats.FONT_REGULAR.value)
|
|
1019
|
+
temporal_join_videos.add_command(label="Temporal join selected videos", command=ManualTemporalJoinPopUp, font=Formats.FONT_REGULAR.value)
|
|
1020
|
+
video_process_menu.add_cascade(label="Temporal join videos...", compound="left", image=self.menu_icons["stopwatch"]["img"], menu=temporal_join_videos, font=Formats.FONT_REGULAR.value)
|
|
1021
|
+
video_process_menu.add_command(label="Box blur videos", compound="left", image=self.menu_icons["blur"]["img"], command=BoxBlurPopUp, font=Formats.FONT_REGULAR.value)
|
|
1022
|
+
video_process_menu.add_command(label="Cross-fade videos", compound="left", image=self.menu_icons["crossfade"]["img"], command=CrossfadeVideosPopUp, font=Formats.FONT_REGULAR.value)
|
|
1023
|
+
video_process_menu.add_command(label="Create average frames from videos", compound="left", image=self.menu_icons["average"]["img"], command=CreateAverageFramePopUp, font=Formats.FONT_REGULAR.value)
|
|
1024
|
+
video_process_menu.add_command(label="Validate video seekability", compound="left", image=self.menu_icons["search"]["img"], command=CheckVideoSeekablePopUp, font=Formats.FONT_REGULAR.value)
|
|
1025
|
+
video_process_menu.add_command(label="Visualize pose-estimation in folder...", compound="left", image=self.menu_icons["visualize"]["img"], command=VisualizePoseInFolderPopUp, font=Formats.FONT_REGULAR.value)
|
|
1026
|
+
|
|
1027
|
+
help_menu = Menu(menu)
|
|
1028
|
+
menu.add_cascade(label="Help", menu=help_menu)
|
|
1029
|
+
links_menu = Menu(help_menu)
|
|
1030
|
+
download_menu = Menu(links_menu)
|
|
1031
|
+
download_menu.add_command(label="Download weights", compound="left", image=self.menu_icons["dumbbell"]["img"], command=lambda: webbrowser.open_new(str(r"https://osf.io/sr3ck/")), font=Formats.FONT_REGULAR.value)
|
|
1032
|
+
download_menu.add_command(label="Download data/classifiers", compound="left", image=self.menu_icons["osf"]["img"], command=lambda: webbrowser.open_new(str(r"https://osf.io/kwge8/")), font=Formats.FONT_REGULAR.value)
|
|
1033
|
+
|
|
1034
|
+
yolo_links = Menu(download_menu)
|
|
1035
|
+
for mdl_name, mdl_link in Links.YOLO_11_WEIGHTS.value.items():
|
|
1036
|
+
yolo_links.add_command(label=mdl_name, compound="left", image=self.menu_icons["ultralytics_2"]["img"], command=lambda: webbrowser.open_new(str({mdl_link})), font=Formats.FONT_REGULAR.value)
|
|
1037
|
+
|
|
1038
|
+
download_menu.add_cascade(label="YOLO weights...", compound="left", image=self.menu_icons["ultralytics_2"]["img"], menu=yolo_links, font=Formats.FONT_REGULAR.value)
|
|
1039
|
+
links_menu.add_cascade(label="Download...", compound="left", image=self.menu_icons["download"]["img"], menu=download_menu, font=Formats.FONT_REGULAR.value)
|
|
1040
|
+
links_menu.add_command(label="SimBA Github", compound="left", image=self.menu_icons["github"]["img"], command=lambda: webbrowser.open_new(str(r"https://github.com/sgoldenlab/simba")), font=Formats.FONT_REGULAR.value)
|
|
1041
|
+
links_menu.add_command(label="SimBA Gitter Support Chatroom", compound="left", image=self.menu_icons["gitter"]["img"], command=lambda: webbrowser.open_new(str(r"https://gitter.im/SimBA-Resource/community")), font=Formats.FONT_REGULAR.value)
|
|
1042
|
+
links_menu.add_command(label="Install FFmpeg", compound="left", image=self.menu_icons["ffmpeg"]["img"], command=lambda: webbrowser.open_new(str(r"https://m.wikihow.com/Install-FFmpeg-on-Windows")), font=Formats.FONT_REGULAR.value)
|
|
1043
|
+
links_menu.add_command(label="SimBA API", compound="left", image=self.menu_icons["api"]["img"], command=lambda: webbrowser.open_new(str(r"https://simba-uw-tf-dev.readthedocs.io/")), font=Formats.FONT_REGULAR.value)
|
|
1044
|
+
links_menu.add_command(label="SimBA usage statistics", compound="left", image=self.menu_icons["line_chart_light_blue"]["img"], command=lambda: webbrowser.open_new(str(r"https://sronilsson.github.io/download_stats/")), font=Formats.FONT_REGULAR.value)
|
|
1045
|
+
links_menu.add_command(label="SimBA developer contact", compound="left", image=self.menu_icons["developer"]["img"], command=lambda: webbrowser.open_new(str(r"https://sronilsson.netlify.app/")), font=Formats.FONT_REGULAR.value)
|
|
1046
|
+
|
|
1047
|
+
help_menu.add_cascade(label="Links", menu=links_menu, compound="left", image=self.menu_icons["link"]["img"], font=Formats.FONT_REGULAR.value)
|
|
1048
|
+
help_menu.add_command(label="Check for updates", compound="left", image=self.menu_icons["download"]["img"], command=check_for_updates, font=Formats.FONT_REGULAR.value)
|
|
1049
|
+
help_menu.add_command(label="About", compound="left", image=self.menu_icons["about"]["img"], command=AboutSimBAPopUp, font=Formats.FONT_REGULAR.value)
|
|
1050
|
+
|
|
1051
|
+
self.frame = Frame(background, bd=2, relief=SUNKEN, width=750, height=300)
|
|
1052
|
+
self.r_click_menu = Menu(self.root, tearoff=0)
|
|
1053
|
+
self.r_click_menu.add_command(label="Copy selection", command=lambda: self.copy_selection_to_clipboard(), font=Formats.FONT_REGULAR.value)
|
|
1054
|
+
self.r_click_menu.add_command(label="Copy all", command=lambda: self.copy_all_to_clipboard(), font=Formats.FONT_REGULAR.value)
|
|
1055
|
+
self.r_click_menu.add_command(label="Paste", command=lambda: self.paste_to_txt(), font=Formats.FONT_REGULAR.value)
|
|
1056
|
+
self.r_click_menu.add_separator()
|
|
1057
|
+
self.r_click_menu.add_command(label="Clear", command=lambda: self.clean_txt(), font=Formats.FONT_REGULAR.value)
|
|
1058
|
+
y_sb = Scrollbar(self.frame, orient=VERTICAL)
|
|
1059
|
+
self.frame.pack(expand=True)
|
|
1060
|
+
self.txt = Text(self.frame, bg="white", insertborderwidth=2, height=30, width=100, yscrollcommand=y_sb)
|
|
1061
|
+
if currentPlatform == OS.WINDOWS.value: self.txt.bind("<Button-3>", self.show_right_click_pop_up)
|
|
1062
|
+
elif currentPlatform == OS.MAC.value: self.txt.bind("<Button-2>", self.show_right_click_pop_up)
|
|
1063
|
+
self.txt.tag_configure(TagNames.GREETING.value, justify="center", foreground="blue", font=Formats.FONT_LARGE_BOLD.value)
|
|
1064
|
+
self.txt.tag_configure(TagNames.ERROR.value, justify="left", foreground="red", font=Formats.FONT_REGULAR.value)
|
|
1065
|
+
self.txt.tag_configure(TagNames.STANDARD.value, justify="left", foreground="black", font=Formats.FONT_REGULAR.value)
|
|
1066
|
+
self.txt.tag_configure(TagNames.COMPLETE.value, justify="left", foreground="darkgreen", font=Formats.FONT_REGULAR_BOLD.value)
|
|
1067
|
+
self.txt.tag_configure(TagNames.WARNING.value, justify="left", foreground="darkorange", font=Formats.FONT_REGULAR.value)
|
|
1068
|
+
self.txt.tag_configure(TagNames.INFORMATION.value, justify="left", foreground="blue", font=Formats.FONT_REGULAR.value)
|
|
1069
|
+
self.txt.tag_configure("TABLE", foreground="darkorange", font=Formats.FONT_REGULAR.value, wrap="none", borderwidth=0)
|
|
1070
|
+
if ENV[ENV_VARS.PRINT_EMOJIS.value]:
|
|
1071
|
+
self.txt.insert(INSERT, Defaults.WELCOME_MSG.value + emojis["relaxed"] + "\n" * 2)
|
|
1072
|
+
else:
|
|
1073
|
+
self.txt.insert(INSERT, Defaults.WELCOME_MSG.value + "\n" * 2)
|
|
1074
|
+
self.txt.tag_add(TagNames.GREETING.value, "1.0", "3.25")
|
|
1075
|
+
y_sb.pack(side=RIGHT, fill=Y)
|
|
1076
|
+
self.txt.pack(expand=True, fill="both")
|
|
1077
|
+
y_sb.config(command=self.txt.yview)
|
|
1078
|
+
self.txt.config(state=DISABLED, font=Formats.FONT_REGULAR.value)
|
|
1079
|
+
|
|
1080
|
+
clear_txt_btn = SimbaButton(parent=self.frame, txt=" CLEAR", txt_clr='blue', img='clean', cmd=self.clean_txt, font=Formats.FONT_HEADER.value, anchor='center', hover_font=Formats.FONT_HEADER.value)
|
|
1081
|
+
clear_txt_btn.pack(side=BOTTOM, fill=X)
|
|
1082
|
+
sys.stdout = StdRedirector(self.txt)
|
|
1083
|
+
|
|
1084
|
+
if OS.PYTHON_VER.value != "3.6":
|
|
1085
|
+
self.txt['width'], self.txt['height'] = 200, 38
|
|
1086
|
+
PythonVersionWarning(msg=f"SimBA is not extensively tested beyond python 3.6. You are using python {OS.PYTHON_VER.value}. If you encounter errors in python>3.6, please report them on GitHub or Gitter (links in the help toolbar) and we will work together to fix the issues!", source=self.__class__.__name__)
|
|
1087
|
+
|
|
1088
|
+
if not check_ffmpeg_available():
|
|
1089
|
+
FFMpegNotFoundWarning(msg='SimBA could not find a FFMPEG installation on computer (as evaluated by "ffmpeg" returning None). SimBA works best with FFMPEG and it is recommended to install it on your computer', source=self.__class__.__name__)
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
simba_pip_data = fetch_pip_data(pip_url=Links.SIMBA_PIP_URL.value)
|
|
1095
|
+
if (simba_pip_data[1] is not None) and OS.SIMBA_VERSION.value is not None:
|
|
1096
|
+
if simba_pip_data[1] != OS.SIMBA_VERSION.value:
|
|
1097
|
+
msg = f"A new version of SimBA is available: {simba_pip_data[1]} (you have version {OS.SIMBA_VERSION.value}). Consider upgrading using: pip install simba-uw-tf-dev --upgrade"
|
|
1098
|
+
VersionWarning(msg=msg)
|
|
1099
|
+
|
|
1100
|
+
def clear_recent_projects(self):
|
|
1101
|
+
file_path = os.path.join(os.path.dirname(__file__), Paths.RECENT_PROJECTS_PATHS.value)
|
|
1102
|
+
remove_files(file_paths=[file_path], raise_error=False)
|
|
1103
|
+
self.recent_projects_menu.delete(0, self.recent_projects_menu.index('end') - 1)
|
|
1104
|
+
self.file_menu.entryconfig("Open recent project...", state=DISABLED)
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
def restart(self):
|
|
1109
|
+
confirm_restart = askyesno(title="RESTART", message="Are you sure that you want restart SimBA?")
|
|
1110
|
+
if confirm_restart:
|
|
1111
|
+
self.root.destroy()
|
|
1112
|
+
os.execl(sys.executable, sys.executable, *sys.argv)
|
|
1113
|
+
|
|
1114
|
+
def clean_txt(self):
|
|
1115
|
+
self.txt.config(state=NORMAL)
|
|
1116
|
+
self.txt.delete("1.0", END)
|
|
1117
|
+
|
|
1118
|
+
def show_right_click_pop_up(self, event):
|
|
1119
|
+
try:
|
|
1120
|
+
self.r_click_menu.tk_popup(event.x_root, event.y_root)
|
|
1121
|
+
finally:
|
|
1122
|
+
self.r_click_menu.grab_release()
|
|
1123
|
+
|
|
1124
|
+
def copy_selection_to_clipboard(self):
|
|
1125
|
+
self.root.clipboard_clear()
|
|
1126
|
+
text = self.txt.get("sel.first", "sel.last")
|
|
1127
|
+
text = text.encode("ascii", "ignore").decode()
|
|
1128
|
+
self.root.clipboard_append(text)
|
|
1129
|
+
|
|
1130
|
+
def copy_all_to_clipboard(self):
|
|
1131
|
+
self.root.clipboard_clear()
|
|
1132
|
+
self.root.clipboard_append(self.txt.get("1.0", "end-1c"))
|
|
1133
|
+
|
|
1134
|
+
def paste_to_txt(self):
|
|
1135
|
+
try:
|
|
1136
|
+
print(self.root.clipboard_get())
|
|
1137
|
+
except UnicodeDecodeError:
|
|
1138
|
+
raise InvalidInputError(
|
|
1139
|
+
msg="Can only paste utf-8 compatible text",
|
|
1140
|
+
source=self.__class__.__name__,
|
|
1141
|
+
)
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
class StdRedirector(object):
|
|
1145
|
+
def __init__(self, text_widget):
|
|
1146
|
+
self.text_space = text_widget
|
|
1147
|
+
self.emojis = get_emojis()
|
|
1148
|
+
|
|
1149
|
+
def write(self, s: str):
|
|
1150
|
+
tag_name = TagNames.STANDARD.value
|
|
1151
|
+
try:
|
|
1152
|
+
s, tag_name = s.split(Defaults.STR_SPLIT_DELIMITER.value, 2)
|
|
1153
|
+
except ValueError:
|
|
1154
|
+
pass
|
|
1155
|
+
if (tag_name != TagNames.STANDARD.value) and (tag_name != "TABLE"):
|
|
1156
|
+
if ENV[ENV_VARS.PRINT_EMOJIS.value]:
|
|
1157
|
+
s = s + " " + self.emojis[tag_name]
|
|
1158
|
+
else:
|
|
1159
|
+
pass
|
|
1160
|
+
self.text_space.config(state=NORMAL)
|
|
1161
|
+
self.text_space.insert("end", s, (tag_name))
|
|
1162
|
+
self.text_space.update()
|
|
1163
|
+
self.text_space.see("end")
|
|
1164
|
+
self.text_space.config(state=DISABLED)
|
|
1165
|
+
|
|
1166
|
+
def flush(self):
|
|
1167
|
+
pass
|
|
1168
|
+
|
|
1169
|
+
def terminate_children(children):
|
|
1170
|
+
for process in children:
|
|
1171
|
+
process.terminate()
|
|
1172
|
+
|
|
1173
|
+
def main():
|
|
1174
|
+
if currentPlatform == OS.WINDOWS.value:
|
|
1175
|
+
import ctypes
|
|
1176
|
+
myappid = "SimBA development wheel"
|
|
1177
|
+
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
|
|
1178
|
+
SplashMovie()
|
|
1179
|
+
app = App()
|
|
1180
|
+
app.root.mainloop()
|