boris-behav-obs 9.4.1__py2.py3-none-any.whl → 9.5.2__py2.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.
- boris/analysis_plugins/_latency.py +1 -1
- boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
- boris/config.py +10 -0
- boris/connections.py +2 -1
- boris/core.py +2 -0
- boris/core_ui.py +6 -2
- boris/export_observation.py +2 -6
- boris/external_processes.py +98 -73
- boris/import_observations.py +28 -19
- boris/observation_operations.py +45 -26
- boris/plot_events.py +1 -1
- boris/plot_events_rt.py +1 -1
- boris/plot_spectrogram_rt.py +62 -13
- boris/plot_waveform_rt.py +1 -1
- boris/plugins.py +136 -25
- boris/preferences.py +182 -108
- boris/preferences_ui.py +216 -32
- boris/project_functions.py +1 -3
- boris/utilities.py +21 -14
- boris/version.py +2 -2
- {boris_behav_obs-9.4.1.dist-info → boris_behav_obs-9.5.2.dist-info}/METADATA +4 -1
- {boris_behav_obs-9.4.1.dist-info → boris_behav_obs-9.5.2.dist-info}/RECORD +26 -25
- {boris_behav_obs-9.4.1.dist-info → boris_behav_obs-9.5.2.dist-info}/WHEEL +0 -0
- {boris_behav_obs-9.4.1.dist-info → boris_behav_obs-9.5.2.dist-info}/entry_points.txt +0 -0
- {boris_behav_obs-9.4.1.dist-info → boris_behav_obs-9.5.2.dist-info}/licenses/LICENSE.TXT +0 -0
- {boris_behav_obs-9.4.1.dist-info → boris_behav_obs-9.5.2.dist-info}/top_level.txt +0 -0
boris/preferences_ui.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
################################################################################
|
|
4
4
|
## Form generated from reading UI file 'preferences.ui'
|
|
5
5
|
##
|
|
6
|
-
## Created by: Qt User Interface Compiler version 6.
|
|
6
|
+
## Created by: Qt User Interface Compiler version 6.9.0
|
|
7
7
|
##
|
|
8
8
|
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
|
9
9
|
################################################################################
|
|
@@ -16,10 +16,11 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
|
|
16
16
|
QImage, QKeySequence, QLinearGradient, QPainter,
|
|
17
17
|
QPalette, QPixmap, QRadialGradient, QTransform)
|
|
18
18
|
from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QDialog,
|
|
19
|
-
QDoubleSpinBox, QFormLayout,
|
|
19
|
+
QDoubleSpinBox, QFormLayout, QGroupBox, QHBoxLayout,
|
|
20
20
|
QLabel, QLineEdit, QListWidget, QListWidgetItem,
|
|
21
21
|
QPlainTextEdit, QPushButton, QSizePolicy, QSpacerItem,
|
|
22
|
-
QSpinBox, QTabWidget, QVBoxLayout,
|
|
22
|
+
QSpinBox, QSplitter, QTabWidget, QVBoxLayout,
|
|
23
|
+
QWidget)
|
|
23
24
|
|
|
24
25
|
class Ui_prefDialog(object):
|
|
25
26
|
def setupUi(self, prefDialog):
|
|
@@ -27,8 +28,8 @@ class Ui_prefDialog(object):
|
|
|
27
28
|
prefDialog.setObjectName(u"prefDialog")
|
|
28
29
|
prefDialog.setWindowModality(Qt.WindowModality.WindowModal)
|
|
29
30
|
prefDialog.resize(904, 554)
|
|
30
|
-
self.
|
|
31
|
-
self.
|
|
31
|
+
self.horizontalLayout_17 = QHBoxLayout(prefDialog)
|
|
32
|
+
self.horizontalLayout_17.setObjectName(u"horizontalLayout_17")
|
|
32
33
|
self.verticalLayout_2 = QVBoxLayout()
|
|
33
34
|
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
|
34
35
|
self.tabWidget = QTabWidget(prefDialog)
|
|
@@ -250,34 +251,40 @@ class Ui_prefDialog(object):
|
|
|
250
251
|
self.tabWidget.addTab(self.tab_observations, "")
|
|
251
252
|
self.tab_analysis_plugins = QWidget()
|
|
252
253
|
self.tab_analysis_plugins.setObjectName(u"tab_analysis_plugins")
|
|
253
|
-
self.
|
|
254
|
-
self.
|
|
255
|
-
self.
|
|
254
|
+
self.verticalLayout_15 = QVBoxLayout(self.tab_analysis_plugins)
|
|
255
|
+
self.verticalLayout_15.setObjectName(u"verticalLayout_15")
|
|
256
|
+
self.splitter_2 = QSplitter(self.tab_analysis_plugins)
|
|
257
|
+
self.splitter_2.setObjectName(u"splitter_2")
|
|
258
|
+
self.splitter_2.setOrientation(Qt.Orientation.Horizontal)
|
|
259
|
+
self.widget = QWidget(self.splitter_2)
|
|
260
|
+
self.widget.setObjectName(u"widget")
|
|
261
|
+
self.verticalLayout_11 = QVBoxLayout(self.widget)
|
|
256
262
|
self.verticalLayout_11.setObjectName(u"verticalLayout_11")
|
|
257
|
-
self.
|
|
263
|
+
self.verticalLayout_11.setContentsMargins(0, 0, 0, 0)
|
|
264
|
+
self.label_13 = QLabel(self.widget)
|
|
258
265
|
self.label_13.setObjectName(u"label_13")
|
|
259
266
|
|
|
260
267
|
self.verticalLayout_11.addWidget(self.label_13)
|
|
261
268
|
|
|
262
|
-
self.lv_all_plugins = QListWidget(self.
|
|
269
|
+
self.lv_all_plugins = QListWidget(self.widget)
|
|
263
270
|
self.lv_all_plugins.setObjectName(u"lv_all_plugins")
|
|
264
271
|
|
|
265
272
|
self.verticalLayout_11.addWidget(self.lv_all_plugins)
|
|
266
273
|
|
|
267
|
-
self.label_15 = QLabel(self.
|
|
274
|
+
self.label_15 = QLabel(self.widget)
|
|
268
275
|
self.label_15.setObjectName(u"label_15")
|
|
269
276
|
|
|
270
277
|
self.verticalLayout_11.addWidget(self.label_15)
|
|
271
278
|
|
|
272
279
|
self.horizontalLayout_16 = QHBoxLayout()
|
|
273
280
|
self.horizontalLayout_16.setObjectName(u"horizontalLayout_16")
|
|
274
|
-
self.le_personal_plugins_dir = QLineEdit(self.
|
|
281
|
+
self.le_personal_plugins_dir = QLineEdit(self.widget)
|
|
275
282
|
self.le_personal_plugins_dir.setObjectName(u"le_personal_plugins_dir")
|
|
276
283
|
self.le_personal_plugins_dir.setReadOnly(True)
|
|
277
284
|
|
|
278
285
|
self.horizontalLayout_16.addWidget(self.le_personal_plugins_dir)
|
|
279
286
|
|
|
280
|
-
self.pb_browse_plugins_dir = QPushButton(self.
|
|
287
|
+
self.pb_browse_plugins_dir = QPushButton(self.widget)
|
|
281
288
|
self.pb_browse_plugins_dir.setObjectName(u"pb_browse_plugins_dir")
|
|
282
289
|
|
|
283
290
|
self.horizontalLayout_16.addWidget(self.pb_browse_plugins_dir)
|
|
@@ -285,29 +292,52 @@ class Ui_prefDialog(object):
|
|
|
285
292
|
|
|
286
293
|
self.verticalLayout_11.addLayout(self.horizontalLayout_16)
|
|
287
294
|
|
|
288
|
-
self.lw_personal_plugins = QListWidget(self.
|
|
295
|
+
self.lw_personal_plugins = QListWidget(self.widget)
|
|
289
296
|
self.lw_personal_plugins.setObjectName(u"lw_personal_plugins")
|
|
290
297
|
|
|
291
298
|
self.verticalLayout_11.addWidget(self.lw_personal_plugins)
|
|
292
299
|
|
|
293
|
-
|
|
294
|
-
self.
|
|
295
|
-
|
|
296
|
-
self.
|
|
300
|
+
self.splitter_2.addWidget(self.widget)
|
|
301
|
+
self.splitter = QSplitter(self.splitter_2)
|
|
302
|
+
self.splitter.setObjectName(u"splitter")
|
|
303
|
+
self.splitter.setOrientation(Qt.Orientation.Vertical)
|
|
304
|
+
self.widget1 = QWidget(self.splitter)
|
|
305
|
+
self.widget1.setObjectName(u"widget1")
|
|
306
|
+
self.verticalLayout_12 = QVBoxLayout(self.widget1)
|
|
297
307
|
self.verticalLayout_12.setObjectName(u"verticalLayout_12")
|
|
298
|
-
self.
|
|
308
|
+
self.verticalLayout_12.setContentsMargins(0, 0, 0, 0)
|
|
309
|
+
self.label_14 = QLabel(self.widget1)
|
|
299
310
|
self.label_14.setObjectName(u"label_14")
|
|
300
311
|
|
|
301
312
|
self.verticalLayout_12.addWidget(self.label_14)
|
|
302
313
|
|
|
303
|
-
self.pte_plugin_description = QPlainTextEdit(self.
|
|
314
|
+
self.pte_plugin_description = QPlainTextEdit(self.widget1)
|
|
304
315
|
self.pte_plugin_description.setObjectName(u"pte_plugin_description")
|
|
305
316
|
self.pte_plugin_description.setReadOnly(True)
|
|
306
317
|
|
|
307
318
|
self.verticalLayout_12.addWidget(self.pte_plugin_description)
|
|
308
319
|
|
|
320
|
+
self.splitter.addWidget(self.widget1)
|
|
321
|
+
self.widget2 = QWidget(self.splitter)
|
|
322
|
+
self.widget2.setObjectName(u"widget2")
|
|
323
|
+
self.verticalLayout_14 = QVBoxLayout(self.widget2)
|
|
324
|
+
self.verticalLayout_14.setObjectName(u"verticalLayout_14")
|
|
325
|
+
self.verticalLayout_14.setContentsMargins(0, 0, 0, 0)
|
|
326
|
+
self.label_23 = QLabel(self.widget2)
|
|
327
|
+
self.label_23.setObjectName(u"label_23")
|
|
328
|
+
|
|
329
|
+
self.verticalLayout_14.addWidget(self.label_23)
|
|
330
|
+
|
|
331
|
+
self.pte_plugin_code = QPlainTextEdit(self.widget2)
|
|
332
|
+
self.pte_plugin_code.setObjectName(u"pte_plugin_code")
|
|
333
|
+
self.pte_plugin_code.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
|
|
334
|
+
|
|
335
|
+
self.verticalLayout_14.addWidget(self.pte_plugin_code)
|
|
336
|
+
|
|
337
|
+
self.splitter.addWidget(self.widget2)
|
|
338
|
+
self.splitter_2.addWidget(self.splitter)
|
|
309
339
|
|
|
310
|
-
self.
|
|
340
|
+
self.verticalLayout_15.addWidget(self.splitter_2)
|
|
311
341
|
|
|
312
342
|
self.tabWidget.addTab(self.tab_analysis_plugins, "")
|
|
313
343
|
self.tab_ffmpeg = QWidget()
|
|
@@ -358,31 +388,39 @@ class Ui_prefDialog(object):
|
|
|
358
388
|
self.tabWidget.addTab(self.tab_ffmpeg, "")
|
|
359
389
|
self.tab_spectro = QWidget()
|
|
360
390
|
self.tab_spectro.setObjectName(u"tab_spectro")
|
|
361
|
-
self.
|
|
391
|
+
self.verticalLayout_13 = QVBoxLayout(self.tab_spectro)
|
|
392
|
+
self.verticalLayout_13.setObjectName(u"verticalLayout_13")
|
|
393
|
+
self.groupBox = QGroupBox(self.tab_spectro)
|
|
394
|
+
self.groupBox.setObjectName(u"groupBox")
|
|
395
|
+
self.verticalLayout_8 = QVBoxLayout(self.groupBox)
|
|
362
396
|
self.verticalLayout_8.setObjectName(u"verticalLayout_8")
|
|
363
397
|
self.horizontalLayout_7 = QHBoxLayout()
|
|
364
398
|
self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
|
|
365
|
-
self.label_7 = QLabel(self.
|
|
399
|
+
self.label_7 = QLabel(self.groupBox)
|
|
366
400
|
self.label_7.setObjectName(u"label_7")
|
|
367
401
|
|
|
368
402
|
self.horizontalLayout_7.addWidget(self.label_7)
|
|
369
403
|
|
|
370
|
-
self.cbSpectrogramColorMap = QComboBox(self.
|
|
404
|
+
self.cbSpectrogramColorMap = QComboBox(self.groupBox)
|
|
371
405
|
self.cbSpectrogramColorMap.setObjectName(u"cbSpectrogramColorMap")
|
|
372
406
|
|
|
373
407
|
self.horizontalLayout_7.addWidget(self.cbSpectrogramColorMap)
|
|
374
408
|
|
|
409
|
+
self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
410
|
+
|
|
411
|
+
self.horizontalLayout_7.addItem(self.horizontalSpacer_2)
|
|
412
|
+
|
|
375
413
|
|
|
376
414
|
self.verticalLayout_8.addLayout(self.horizontalLayout_7)
|
|
377
415
|
|
|
378
416
|
self.horizontalLayout_10 = QHBoxLayout()
|
|
379
417
|
self.horizontalLayout_10.setObjectName(u"horizontalLayout_10")
|
|
380
|
-
self.label_12 = QLabel(self.
|
|
418
|
+
self.label_12 = QLabel(self.groupBox)
|
|
381
419
|
self.label_12.setObjectName(u"label_12")
|
|
382
420
|
|
|
383
421
|
self.horizontalLayout_10.addWidget(self.label_12)
|
|
384
422
|
|
|
385
|
-
self.sb_time_interval = QSpinBox(self.
|
|
423
|
+
self.sb_time_interval = QSpinBox(self.groupBox)
|
|
386
424
|
self.sb_time_interval.setObjectName(u"sb_time_interval")
|
|
387
425
|
self.sb_time_interval.setMinimum(2)
|
|
388
426
|
self.sb_time_interval.setMaximum(360)
|
|
@@ -390,12 +428,140 @@ class Ui_prefDialog(object):
|
|
|
390
428
|
|
|
391
429
|
self.horizontalLayout_10.addWidget(self.sb_time_interval)
|
|
392
430
|
|
|
431
|
+
self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
432
|
+
|
|
433
|
+
self.horizontalLayout_10.addItem(self.horizontalSpacer_3)
|
|
434
|
+
|
|
393
435
|
|
|
394
436
|
self.verticalLayout_8.addLayout(self.horizontalLayout_10)
|
|
395
437
|
|
|
438
|
+
self.horizontalLayout_18 = QHBoxLayout()
|
|
439
|
+
self.horizontalLayout_18.setObjectName(u"horizontalLayout_18")
|
|
440
|
+
self.label_16 = QLabel(self.groupBox)
|
|
441
|
+
self.label_16.setObjectName(u"label_16")
|
|
442
|
+
|
|
443
|
+
self.horizontalLayout_18.addWidget(self.label_16)
|
|
444
|
+
|
|
445
|
+
self.cb_window_type = QComboBox(self.groupBox)
|
|
446
|
+
self.cb_window_type.addItem("")
|
|
447
|
+
self.cb_window_type.addItem("")
|
|
448
|
+
self.cb_window_type.addItem("")
|
|
449
|
+
self.cb_window_type.setObjectName(u"cb_window_type")
|
|
450
|
+
|
|
451
|
+
self.horizontalLayout_18.addWidget(self.cb_window_type)
|
|
452
|
+
|
|
453
|
+
self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
454
|
+
|
|
455
|
+
self.horizontalLayout_18.addItem(self.horizontalSpacer_4)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
self.verticalLayout_8.addLayout(self.horizontalLayout_18)
|
|
459
|
+
|
|
460
|
+
self.horizontalLayout_19 = QHBoxLayout()
|
|
461
|
+
self.horizontalLayout_19.setObjectName(u"horizontalLayout_19")
|
|
462
|
+
self.label_17 = QLabel(self.groupBox)
|
|
463
|
+
self.label_17.setObjectName(u"label_17")
|
|
464
|
+
|
|
465
|
+
self.horizontalLayout_19.addWidget(self.label_17)
|
|
466
|
+
|
|
467
|
+
self.cb_NFFT = QComboBox(self.groupBox)
|
|
468
|
+
self.cb_NFFT.addItem("")
|
|
469
|
+
self.cb_NFFT.addItem("")
|
|
470
|
+
self.cb_NFFT.addItem("")
|
|
471
|
+
self.cb_NFFT.addItem("")
|
|
472
|
+
self.cb_NFFT.setObjectName(u"cb_NFFT")
|
|
473
|
+
|
|
474
|
+
self.horizontalLayout_19.addWidget(self.cb_NFFT)
|
|
475
|
+
|
|
476
|
+
self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
477
|
+
|
|
478
|
+
self.horizontalLayout_19.addItem(self.horizontalSpacer_5)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
self.verticalLayout_8.addLayout(self.horizontalLayout_19)
|
|
482
|
+
|
|
483
|
+
self.horizontalLayout_20 = QHBoxLayout()
|
|
484
|
+
self.horizontalLayout_20.setObjectName(u"horizontalLayout_20")
|
|
485
|
+
self.label_18 = QLabel(self.groupBox)
|
|
486
|
+
self.label_18.setObjectName(u"label_18")
|
|
487
|
+
|
|
488
|
+
self.horizontalLayout_20.addWidget(self.label_18)
|
|
489
|
+
|
|
490
|
+
self.sb_noverlap = QSpinBox(self.groupBox)
|
|
491
|
+
self.sb_noverlap.setObjectName(u"sb_noverlap")
|
|
492
|
+
self.sb_noverlap.setMaximum(900)
|
|
493
|
+
self.sb_noverlap.setSingleStep(10)
|
|
494
|
+
self.sb_noverlap.setValue(128)
|
|
495
|
+
|
|
496
|
+
self.horizontalLayout_20.addWidget(self.sb_noverlap)
|
|
497
|
+
|
|
498
|
+
self.horizontalSpacer_6 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
499
|
+
|
|
500
|
+
self.horizontalLayout_20.addItem(self.horizontalSpacer_6)
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
self.verticalLayout_8.addLayout(self.horizontalLayout_20)
|
|
504
|
+
|
|
505
|
+
self.horizontalLayout_21 = QHBoxLayout()
|
|
506
|
+
self.horizontalLayout_21.setObjectName(u"horizontalLayout_21")
|
|
507
|
+
self.label_19 = QLabel(self.groupBox)
|
|
508
|
+
self.label_19.setObjectName(u"label_19")
|
|
509
|
+
|
|
510
|
+
self.horizontalLayout_21.addWidget(self.label_19)
|
|
511
|
+
|
|
512
|
+
self.sb_vmin = QSpinBox(self.groupBox)
|
|
513
|
+
self.sb_vmin.setObjectName(u"sb_vmin")
|
|
514
|
+
self.sb_vmin.setMinimum(-200)
|
|
515
|
+
self.sb_vmin.setMaximum(0)
|
|
516
|
+
self.sb_vmin.setValue(-100)
|
|
517
|
+
|
|
518
|
+
self.horizontalLayout_21.addWidget(self.sb_vmin)
|
|
519
|
+
|
|
520
|
+
self.label_21 = QLabel(self.groupBox)
|
|
521
|
+
self.label_21.setObjectName(u"label_21")
|
|
522
|
+
|
|
523
|
+
self.horizontalLayout_21.addWidget(self.label_21)
|
|
524
|
+
|
|
525
|
+
self.horizontalSpacer_7 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
526
|
+
|
|
527
|
+
self.horizontalLayout_21.addItem(self.horizontalSpacer_7)
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
self.verticalLayout_8.addLayout(self.horizontalLayout_21)
|
|
531
|
+
|
|
532
|
+
self.horizontalLayout_22 = QHBoxLayout()
|
|
533
|
+
self.horizontalLayout_22.setObjectName(u"horizontalLayout_22")
|
|
534
|
+
self.label_20 = QLabel(self.groupBox)
|
|
535
|
+
self.label_20.setObjectName(u"label_20")
|
|
536
|
+
|
|
537
|
+
self.horizontalLayout_22.addWidget(self.label_20)
|
|
538
|
+
|
|
539
|
+
self.sb_vmax = QSpinBox(self.groupBox)
|
|
540
|
+
self.sb_vmax.setObjectName(u"sb_vmax")
|
|
541
|
+
self.sb_vmax.setMinimum(-40)
|
|
542
|
+
self.sb_vmax.setMaximum(0)
|
|
543
|
+
self.sb_vmax.setValue(-20)
|
|
544
|
+
|
|
545
|
+
self.horizontalLayout_22.addWidget(self.sb_vmax)
|
|
546
|
+
|
|
547
|
+
self.label_22 = QLabel(self.groupBox)
|
|
548
|
+
self.label_22.setObjectName(u"label_22")
|
|
549
|
+
|
|
550
|
+
self.horizontalLayout_22.addWidget(self.label_22)
|
|
551
|
+
|
|
552
|
+
self.horizontalSpacer_8 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
|
553
|
+
|
|
554
|
+
self.horizontalLayout_22.addItem(self.horizontalSpacer_8)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
self.verticalLayout_8.addLayout(self.horizontalLayout_22)
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
self.verticalLayout_13.addWidget(self.groupBox)
|
|
561
|
+
|
|
396
562
|
self.verticalSpacer_3 = QSpacerItem(20, 319, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
|
397
563
|
|
|
398
|
-
self.
|
|
564
|
+
self.verticalLayout_13.addItem(self.verticalSpacer_3)
|
|
399
565
|
|
|
400
566
|
self.tabWidget.addTab(self.tab_spectro, "")
|
|
401
567
|
self.tab_colors = QWidget()
|
|
@@ -459,7 +625,7 @@ class Ui_prefDialog(object):
|
|
|
459
625
|
self.label_9 = QLabel(self.tab_interface)
|
|
460
626
|
self.label_9.setObjectName(u"label_9")
|
|
461
627
|
|
|
462
|
-
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label_9)
|
|
628
|
+
self.formLayout.setWidget(0, QFormLayout.ItemRole.LabelRole, self.label_9)
|
|
463
629
|
|
|
464
630
|
self.sb_toolbar_icon_size = QSpinBox(self.tab_interface)
|
|
465
631
|
self.sb_toolbar_icon_size.setObjectName(u"sb_toolbar_icon_size")
|
|
@@ -467,7 +633,7 @@ class Ui_prefDialog(object):
|
|
|
467
633
|
self.sb_toolbar_icon_size.setMaximum(128)
|
|
468
634
|
self.sb_toolbar_icon_size.setValue(24)
|
|
469
635
|
|
|
470
|
-
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.sb_toolbar_icon_size)
|
|
636
|
+
self.formLayout.setWidget(0, QFormLayout.ItemRole.FieldRole, self.sb_toolbar_icon_size)
|
|
471
637
|
|
|
472
638
|
|
|
473
639
|
self.verticalLayout_7.addLayout(self.formLayout)
|
|
@@ -505,12 +671,12 @@ class Ui_prefDialog(object):
|
|
|
505
671
|
self.verticalLayout_2.addLayout(self.horizontalLayout_2)
|
|
506
672
|
|
|
507
673
|
|
|
508
|
-
self.
|
|
674
|
+
self.horizontalLayout_17.addLayout(self.verticalLayout_2)
|
|
509
675
|
|
|
510
676
|
|
|
511
677
|
self.retranslateUi(prefDialog)
|
|
512
678
|
|
|
513
|
-
self.tabWidget.setCurrentIndex(
|
|
679
|
+
self.tabWidget.setCurrentIndex(2)
|
|
514
680
|
|
|
515
681
|
|
|
516
682
|
QMetaObject.connectSlotsByName(prefDialog)
|
|
@@ -546,13 +712,31 @@ class Ui_prefDialog(object):
|
|
|
546
712
|
self.label_15.setText(QCoreApplication.translate("prefDialog", u"Personal plugins", None))
|
|
547
713
|
self.pb_browse_plugins_dir.setText(QCoreApplication.translate("prefDialog", u"Browse", None))
|
|
548
714
|
self.label_14.setText(QCoreApplication.translate("prefDialog", u"Plugin info", None))
|
|
715
|
+
self.label_23.setText(QCoreApplication.translate("prefDialog", u"Plugin code", None))
|
|
549
716
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_analysis_plugins), QCoreApplication.translate("prefDialog", u"Analysis plugins", None))
|
|
550
717
|
self.lbFFmpegPath.setText(QCoreApplication.translate("prefDialog", u"FFmpeg path:", None))
|
|
551
718
|
self.lbFFmpegCacheDir.setText(QCoreApplication.translate("prefDialog", u"FFmpeg cache directory", None))
|
|
552
719
|
self.pbBrowseFFmpegCacheDir.setText(QCoreApplication.translate("prefDialog", u"...", None))
|
|
553
720
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_ffmpeg), QCoreApplication.translate("prefDialog", u"FFmpeg framework", None))
|
|
554
|
-
self.
|
|
721
|
+
self.groupBox.setTitle(QCoreApplication.translate("prefDialog", u"Spectrogram", None))
|
|
722
|
+
self.label_7.setText(QCoreApplication.translate("prefDialog", u"Color map", None))
|
|
555
723
|
self.label_12.setText(QCoreApplication.translate("prefDialog", u"Default time interval (s)", None))
|
|
724
|
+
self.label_16.setText(QCoreApplication.translate("prefDialog", u"Window type", None))
|
|
725
|
+
self.cb_window_type.setItemText(0, QCoreApplication.translate("prefDialog", u"hanning", None))
|
|
726
|
+
self.cb_window_type.setItemText(1, QCoreApplication.translate("prefDialog", u"hamming", None))
|
|
727
|
+
self.cb_window_type.setItemText(2, QCoreApplication.translate("prefDialog", u"blackmanharris", None))
|
|
728
|
+
|
|
729
|
+
self.label_17.setText(QCoreApplication.translate("prefDialog", u"NFFT", None))
|
|
730
|
+
self.cb_NFFT.setItemText(0, QCoreApplication.translate("prefDialog", u"256", None))
|
|
731
|
+
self.cb_NFFT.setItemText(1, QCoreApplication.translate("prefDialog", u"512", None))
|
|
732
|
+
self.cb_NFFT.setItemText(2, QCoreApplication.translate("prefDialog", u"1024", None))
|
|
733
|
+
self.cb_NFFT.setItemText(3, QCoreApplication.translate("prefDialog", u"2048", None))
|
|
734
|
+
|
|
735
|
+
self.label_18.setText(QCoreApplication.translate("prefDialog", u"noverlap", None))
|
|
736
|
+
self.label_19.setText(QCoreApplication.translate("prefDialog", u"vmin", None))
|
|
737
|
+
self.label_21.setText(QCoreApplication.translate("prefDialog", u"dBFS", None))
|
|
738
|
+
self.label_20.setText(QCoreApplication.translate("prefDialog", u"vmax", None))
|
|
739
|
+
self.label_22.setText(QCoreApplication.translate("prefDialog", u"dBFS", None))
|
|
556
740
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_spectro), QCoreApplication.translate("prefDialog", u"Spectrogram/Wave form", None))
|
|
557
741
|
self.label_10.setText(QCoreApplication.translate("prefDialog", u"<html><head/><body><p>List of colors for behaviors. See <a href=\"https://matplotlib.org/api/colors_api.html\"><span style=\" text-decoration: underline; color:#0000ff;\">matplotlib colors</span></a></p></body></html>", None))
|
|
558
742
|
self.pb_reset_behav_colors.setText(QCoreApplication.translate("prefDialog", u"Reset colors to default", None))
|
boris/project_functions.py
CHANGED
|
@@ -565,7 +565,7 @@ def check_project_integrity(
|
|
|
565
565
|
for player in pj[cfg.OBSERVATIONS][obs_id][cfg.FILE]:
|
|
566
566
|
for media_file in pj[cfg.OBSERVATIONS][obs_id][cfg.FILE][player]:
|
|
567
567
|
for info in (cfg.LENGTH, cfg.FPS, cfg.HAS_AUDIO, cfg.HAS_VIDEO):
|
|
568
|
-
if media_file not in pj[cfg.OBSERVATIONS][obs_id][cfg.MEDIA_INFO]
|
|
568
|
+
if media_file not in pj[cfg.OBSERVATIONS][obs_id][cfg.MEDIA_INFO].get(info, {}):
|
|
569
569
|
tmp_out += f"Observation <b>{obs_id}</b>:<br>"
|
|
570
570
|
tmp_out += f"The media file {media_file} has no <b>{info}</b> info.<br>"
|
|
571
571
|
if tmp_out:
|
|
@@ -1984,6 +1984,4 @@ def project2dataframe(pj: dict, observations_list: list = []) -> pd.DataFrame:
|
|
|
1984
1984
|
|
|
1985
1985
|
pd.DataFrame(data).info()
|
|
1986
1986
|
|
|
1987
|
-
# print(pd.DataFrame(data))
|
|
1988
|
-
|
|
1989
1987
|
return pd.DataFrame(data)
|
boris/utilities.py
CHANGED
|
@@ -23,7 +23,7 @@ from decimal import Decimal as dec
|
|
|
23
23
|
from decimal import getcontext, ROUND_DOWN
|
|
24
24
|
from hachoir.metadata import extractMetadata
|
|
25
25
|
from hachoir.parser import createParser
|
|
26
|
-
from shutil import copyfile
|
|
26
|
+
from shutil import copyfile, which
|
|
27
27
|
from typing import Union, Tuple
|
|
28
28
|
import csv
|
|
29
29
|
import datetime
|
|
@@ -34,7 +34,7 @@ import logging
|
|
|
34
34
|
import math
|
|
35
35
|
import numpy as np
|
|
36
36
|
import os
|
|
37
|
-
|
|
37
|
+
from pathlib import Path
|
|
38
38
|
from PIL.ImageQt import Image
|
|
39
39
|
import platform
|
|
40
40
|
import re
|
|
@@ -71,7 +71,7 @@ except Exception:
|
|
|
71
71
|
external_files_dir = ""
|
|
72
72
|
# search where to download libmpv-2.dll
|
|
73
73
|
|
|
74
|
-
external_files_dir =
|
|
74
|
+
external_files_dir = Path(__file__).parent / "misc"
|
|
75
75
|
if not external_files_dir.is_dir():
|
|
76
76
|
logger.info(f"Creating {external_files_dir} directory")
|
|
77
77
|
external_files_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -143,10 +143,10 @@ def extract_exif_DateTimeOriginal(file_path: str) -> int:
|
|
|
143
143
|
else:
|
|
144
144
|
try:
|
|
145
145
|
# read from file name (YYYY-MM-DD_HHMMSS)
|
|
146
|
-
return int(datetime.datetime.strptime(
|
|
146
|
+
return int(datetime.datetime.strptime(Path(file_path).stem, "%Y-%m-%d_%H%M%S").timestamp())
|
|
147
147
|
except Exception:
|
|
148
148
|
# read from file name (YYYY-MM-DD_HH:MM:SS)
|
|
149
|
-
return int(datetime.datetime.strptime(
|
|
149
|
+
return int(datetime.datetime.strptime(Path(file_path).stem, "%Y-%m-%d_%H:%M:%S").timestamp())
|
|
150
150
|
|
|
151
151
|
except Exception:
|
|
152
152
|
return -1
|
|
@@ -159,7 +159,7 @@ def extract_video_creation_date(file_path: str) -> int | None:
|
|
|
159
159
|
|
|
160
160
|
logger.debug(f"extract_video_creation_date for {file_path}")
|
|
161
161
|
|
|
162
|
-
if not
|
|
162
|
+
if not Path(file_path).is_file():
|
|
163
163
|
logger.debug(f"{file_path} not found")
|
|
164
164
|
return None
|
|
165
165
|
try:
|
|
@@ -839,7 +839,7 @@ def extract_wav(ffmpeg_bin: str, media_file_path: str, tmp_dir: str) -> str:
|
|
|
839
839
|
str: wav file path or "" if error
|
|
840
840
|
"""
|
|
841
841
|
|
|
842
|
-
wav_file_path =
|
|
842
|
+
wav_file_path = Path(tmp_dir) / Path(media_file_path + ".wav").name
|
|
843
843
|
|
|
844
844
|
# check if media file is a wav file
|
|
845
845
|
try:
|
|
@@ -1272,11 +1272,11 @@ def check_ffmpeg_path() -> Tuple[bool, str]:
|
|
|
1272
1272
|
|
|
1273
1273
|
# search embedded ffmpeg
|
|
1274
1274
|
if sys.platform.startswith("linux") or sys.platform.startswith("darwin"):
|
|
1275
|
-
ffmpeg_executable =
|
|
1275
|
+
ffmpeg_executable = Path("ffmpeg")
|
|
1276
1276
|
elif sys.platform.startswith("win"):
|
|
1277
|
-
ffmpeg_executable =
|
|
1277
|
+
ffmpeg_executable = Path("ffmpeg.exe")
|
|
1278
1278
|
|
|
1279
|
-
ffmpeg_path =
|
|
1279
|
+
ffmpeg_path = Path(__file__).parent / "misc" / ffmpeg_executable
|
|
1280
1280
|
|
|
1281
1281
|
if not ffmpeg_path.is_file():
|
|
1282
1282
|
# search global ffmpeg
|
|
@@ -1387,15 +1387,20 @@ def ffprobe_media_analysis(ffmpeg_bin: str, file_name: str) -> dict:
|
|
|
1387
1387
|
Returns:
|
|
1388
1388
|
dict
|
|
1389
1389
|
"""
|
|
1390
|
-
|
|
1390
|
+
|
|
1391
|
+
# check ffprobe executable in same place than ffmpeg
|
|
1391
1392
|
ffprobe_bin = ffmpeg_bin.replace("ffmpeg", "ffprobe")
|
|
1393
|
+
if not Path(ffprobe_bin).is_file():
|
|
1394
|
+
if which(ffprobe_bin) is None:
|
|
1395
|
+
return {"error": "ffprobe not found"}
|
|
1392
1396
|
|
|
1393
1397
|
command = f'"{ffprobe_bin}" -hide_banner -v error -print_format json -show_format -show_streams "{file_name}"'
|
|
1394
1398
|
|
|
1395
1399
|
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
1396
1400
|
out, error = p.communicate()
|
|
1397
1401
|
if error:
|
|
1398
|
-
|
|
1402
|
+
if b"invalid data" in error:
|
|
1403
|
+
return {"error": f"{error}"}
|
|
1399
1404
|
|
|
1400
1405
|
try:
|
|
1401
1406
|
hasVideo = False
|
|
@@ -1404,7 +1409,7 @@ def ffprobe_media_analysis(ffmpeg_bin: str, file_name: str) -> dict:
|
|
|
1404
1409
|
video_bitrate = None
|
|
1405
1410
|
audio_bitrate = []
|
|
1406
1411
|
resolution = None
|
|
1407
|
-
fps = 0
|
|
1412
|
+
fps: float = 0
|
|
1408
1413
|
sample_rate = None
|
|
1409
1414
|
duration = None
|
|
1410
1415
|
audio_duration = cfg.NA
|
|
@@ -1447,6 +1452,8 @@ def ffprobe_media_analysis(ffmpeg_bin: str, file_name: str) -> dict:
|
|
|
1447
1452
|
except Exception:
|
|
1448
1453
|
pass
|
|
1449
1454
|
|
|
1455
|
+
fps = round(fps, 3)
|
|
1456
|
+
|
|
1450
1457
|
if "duration" in stream:
|
|
1451
1458
|
duration = float(stream["duration"])
|
|
1452
1459
|
if "duration_ts" in stream:
|
|
@@ -1698,7 +1705,7 @@ def dir_images_number(dir_path_str: str) -> dict:
|
|
|
1698
1705
|
return number of images in dir_path (see cfg.IMAGE_EXTENSIONS)
|
|
1699
1706
|
"""
|
|
1700
1707
|
|
|
1701
|
-
dir_path =
|
|
1708
|
+
dir_path = Path(dir_path_str)
|
|
1702
1709
|
if not dir_path.is_dir():
|
|
1703
1710
|
return {"error": f"The directory {dir_path_str} does not exists"}
|
|
1704
1711
|
img_count = 0
|
boris/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boris-behav-obs
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.5.2
|
|
4
4
|
Summary: BORIS - Behavioral Observation Research Interactive Software
|
|
5
5
|
Author-email: Olivier Friard <olivier.friard@unito.it>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -26,10 +26,13 @@ Requires-Dist: tablib[cli,html,ods,pandas,xls,xlsx]>=3
|
|
|
26
26
|
Requires-Dist: pyreadr
|
|
27
27
|
Requires-Dist: pyside6==6.9
|
|
28
28
|
Requires-Dist: hachoir>=3.3.0
|
|
29
|
+
Requires-Dist: scipy>=1.15.3
|
|
29
30
|
Provides-Extra: dev
|
|
30
31
|
Requires-Dist: ruff; extra == "dev"
|
|
31
32
|
Requires-Dist: pytest; extra == "dev"
|
|
32
33
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
34
|
+
Provides-Extra: r
|
|
35
|
+
Requires-Dist: rpy2>=3.6.1; extra == "r"
|
|
33
36
|
Dynamic: license-file
|
|
34
37
|
|
|
35
38
|
BORIS (Behavioral Observation Research Interactive Software)
|