boris-behav-obs 8.16.5__py3-none-any.whl → 9.7.1__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.
Files changed (125) hide show
  1. boris/__init__.py +1 -1
  2. boris/__main__.py +1 -1
  3. boris/about.py +24 -36
  4. boris/add_modifier.py +88 -80
  5. boris/add_modifier_ui.py +235 -131
  6. boris/advanced_event_filtering.py +23 -29
  7. boris/analysis_plugins/__init__.py +0 -0
  8. boris/analysis_plugins/_latency.py +59 -0
  9. boris/analysis_plugins/irr_cohen_kappa.py +109 -0
  10. boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
  11. boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
  12. boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
  13. boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
  14. boris/analysis_plugins/number_of_occurences.py +22 -0
  15. boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
  16. boris/analysis_plugins/time_budget.py +61 -0
  17. boris/behav_coding_map_creator.py +228 -229
  18. boris/behavior_binary_table.py +33 -50
  19. boris/behaviors_coding_map.py +17 -18
  20. boris/boris_cli.py +6 -25
  21. boris/cmd_arguments.py +12 -1
  22. boris/coding_pad.py +16 -34
  23. boris/config.py +102 -50
  24. boris/config_file.py +55 -64
  25. boris/connections.py +105 -58
  26. boris/converters.py +13 -37
  27. boris/converters_ui.py +187 -110
  28. boris/cooccurence.py +250 -0
  29. boris/core.py +2108 -1275
  30. boris/core_qrc.py +15892 -10829
  31. boris/core_ui.py +941 -806
  32. boris/db_functions.py +17 -42
  33. boris/dev.py +27 -7
  34. boris/dialog.py +461 -242
  35. boris/duration_widget.py +9 -14
  36. boris/edit_event.py +61 -31
  37. boris/edit_event_ui.py +208 -97
  38. boris/event_operations.py +405 -281
  39. boris/events_cursor.py +25 -17
  40. boris/events_snapshots.py +36 -82
  41. boris/exclusion_matrix.py +4 -9
  42. boris/export_events.py +180 -203
  43. boris/export_observation.py +60 -73
  44. boris/external_processes.py +123 -98
  45. boris/geometric_measurement.py +427 -218
  46. boris/gui_utilities.py +91 -14
  47. boris/image_overlay.py +4 -4
  48. boris/import_observations.py +190 -98
  49. boris/ipc_mpv.py +304 -0
  50. boris/irr.py +20 -57
  51. boris/latency.py +31 -24
  52. boris/measurement_widget.py +14 -18
  53. boris/media_file.py +17 -19
  54. boris/menu_options.py +16 -6
  55. boris/modifier_coding_map_creator.py +1013 -0
  56. boris/modifiers_coding_map.py +7 -9
  57. boris/mpv2.py +128 -35
  58. boris/observation.py +493 -210
  59. boris/observation_operations.py +1010 -391
  60. boris/observation_ui.py +573 -363
  61. boris/observations_list.py +51 -58
  62. boris/otx_parser.py +74 -68
  63. boris/param_panel.py +45 -59
  64. boris/param_panel_ui.py +254 -138
  65. boris/player_dock_widget.py +91 -56
  66. boris/plot_data_module.py +18 -53
  67. boris/plot_events.py +56 -153
  68. boris/plot_events_rt.py +16 -30
  69. boris/plot_spectrogram_rt.py +80 -56
  70. boris/plot_waveform_rt.py +23 -48
  71. boris/plugins.py +431 -0
  72. boris/portion/__init__.py +18 -8
  73. boris/portion/const.py +35 -18
  74. boris/portion/dict.py +5 -5
  75. boris/portion/func.py +2 -2
  76. boris/portion/interval.py +21 -41
  77. boris/portion/io.py +41 -32
  78. boris/preferences.py +298 -123
  79. boris/preferences_ui.py +664 -225
  80. boris/project.py +293 -270
  81. boris/project_functions.py +610 -537
  82. boris/project_import_export.py +204 -213
  83. boris/project_ui.py +673 -441
  84. boris/qrc_boris.py +6 -3
  85. boris/qrc_boris5.py +6 -3
  86. boris/select_modifiers.py +62 -90
  87. boris/select_observations.py +19 -197
  88. boris/select_subj_behav.py +67 -39
  89. boris/state_events.py +51 -33
  90. boris/subjects_pad.py +6 -8
  91. boris/synthetic_time_budget.py +42 -26
  92. boris/time_budget_functions.py +169 -169
  93. boris/time_budget_widget.py +77 -89
  94. boris/transitions.py +41 -41
  95. boris/utilities.py +562 -222
  96. boris/version.py +3 -3
  97. boris/video_equalizer.py +16 -14
  98. boris/video_equalizer_ui.py +199 -130
  99. boris/video_operations.py +78 -28
  100. boris/view_df.py +104 -0
  101. boris/view_df_ui.py +75 -0
  102. boris/write_event.py +240 -136
  103. boris_behav_obs-9.7.1.dist-info/METADATA +140 -0
  104. boris_behav_obs-9.7.1.dist-info/RECORD +109 -0
  105. {boris_behav_obs-8.16.5.dist-info → boris_behav_obs-9.7.1.dist-info}/WHEEL +1 -1
  106. boris_behav_obs-9.7.1.dist-info/entry_points.txt +2 -0
  107. boris/README.TXT +0 -22
  108. boris/add_modifier.ui +0 -323
  109. boris/converters.ui +0 -289
  110. boris/core.qrc +0 -37
  111. boris/core.ui +0 -1571
  112. boris/edit_event.ui +0 -233
  113. boris/icons/logo_eye.ico +0 -0
  114. boris/map_creator.py +0 -982
  115. boris/observation.ui +0 -814
  116. boris/param_panel.ui +0 -379
  117. boris/preferences.ui +0 -537
  118. boris/project.ui +0 -1074
  119. boris/vlc_local.py +0 -90
  120. boris_behav_obs-8.16.5.dist-info/LICENSE.TXT +0 -674
  121. boris_behav_obs-8.16.5.dist-info/METADATA +0 -134
  122. boris_behav_obs-8.16.5.dist-info/RECORD +0 -107
  123. boris_behav_obs-8.16.5.dist-info/entry_points.txt +0 -2
  124. {boris → boris_behav_obs-9.7.1.dist-info/licenses}/LICENSE.TXT +0 -0
  125. {boris_behav_obs-8.16.5.dist-info → boris_behav_obs-9.7.1.dist-info}/top_level.txt +0 -0
boris/version.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
4
+ Copyright 2012-2025 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
@@ -20,5 +20,5 @@ This file is part of BORIS.
20
20
 
21
21
  """
22
22
 
23
- __version__ = "8.16.5"
24
- __version_date__ = "2023-04-17"
23
+ __version__ = "9.7.1"
24
+ __version_date__ = "2025-10-22"
boris/video_equalizer.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
4
+ Copyright 2012-2025 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
@@ -20,8 +20,8 @@ This file is part of BORIS.
20
20
 
21
21
  """
22
22
 
23
- from PyQt5.QtWidgets import QDialog
24
- from PyQt5.QtCore import pyqtSignal, QEvent
23
+ from PySide6.QtWidgets import QDialog
24
+ from PySide6.QtCore import Signal, QEvent
25
25
  from .video_equalizer_ui import Ui_Equalizer
26
26
 
27
27
 
@@ -30,8 +30,8 @@ class Video_equalizer(QDialog, Ui_Equalizer):
30
30
  management of video equalizer: brightness, saturation, contrast, gamma and hue
31
31
  """
32
32
 
33
- sendEventSignal = pyqtSignal(int, str, int)
34
- sendKeyPressSignal = pyqtSignal(QEvent)
33
+ sendEventSignal = Signal(int, str, int)
34
+ sendKeyPressSignal = Signal(QEvent)
35
35
 
36
36
  def __init__(self, equalizer, parent=None):
37
37
  super().__init__(parent)
@@ -56,7 +56,7 @@ class Video_equalizer(QDialog, Ui_Equalizer):
56
56
 
57
57
  self.initialize(0)
58
58
 
59
- def initialize(self, n_player):
59
+ def initialize(self, n_player: int) -> None:
60
60
  if n_player not in self.equalizer:
61
61
  return
62
62
 
@@ -76,7 +76,6 @@ class Video_equalizer(QDialog, Ui_Equalizer):
76
76
  self.lb_hue.setText(str(self.equalizer[n_player]["hs_hue"]))
77
77
 
78
78
  def player_changed(self, index):
79
-
80
79
  self.initialize(index)
81
80
 
82
81
  def reset(self):
@@ -102,8 +101,11 @@ class Video_equalizer(QDialog, Ui_Equalizer):
102
101
  """
103
102
  if self.cb_player.currentIndex() not in self.equalizer:
104
103
  return
105
- self.equalizer[self.cb_player.currentIndex()][self.sender().objectName()] = self.sender().value()
106
- self.sendEventSignal.emit(self.cb_player.currentIndex(), self.sender().objectName(), self.sender().value())
104
+
105
+ print(type(self.sender().value()))
106
+
107
+ self.equalizer[self.cb_player.currentIndex()][self.sender().objectName()] = round(self.sender().value())
108
+ self.sendEventSignal.emit(self.cb_player.currentIndex(), self.sender().objectName(), round(self.sender().value()))
107
109
 
108
110
  self.initialize(self.cb_player.currentIndex())
109
111
 
@@ -142,11 +144,11 @@ def video_equalizer_show(self):
142
144
  equalizer = {}
143
145
  for n_player, _ in enumerate(self.dw_player):
144
146
  equalizer[n_player] = {
145
- "hs_brightness": self.dw_player[n_player].player.brightness,
146
- "hs_contrast": self.dw_player[n_player].player.contrast,
147
- "hs_saturation": self.dw_player[n_player].player.saturation,
148
- "hs_gamma": self.dw_player[n_player].player.gamma,
149
- "hs_hue": self.dw_player[n_player].player.hue,
147
+ "hs_brightness": round(self.dw_player[n_player].player.brightness),
148
+ "hs_contrast": round(self.dw_player[n_player].player.contrast),
149
+ "hs_saturation": round(self.dw_player[n_player].player.saturation),
150
+ "hs_gamma": round(self.dw_player[n_player].player.gamma),
151
+ "hs_hue": round(self.dw_player[n_player].player.hue),
150
152
  }
151
153
 
152
154
  self.video_equalizer_wgt = Video_equalizer(equalizer)
@@ -1,179 +1,248 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Form implementation generated from reading ui file 'boris/video_equalizer.ui'
4
- #
5
- # Created by: PyQt5 UI code generator 5.15.2
6
- #
7
- # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8
- # run again. Do not edit this file unless you know what you are doing.
9
-
10
-
11
- from PyQt5 import QtCore, QtGui, QtWidgets
3
+ ################################################################################
4
+ ## Form generated from reading UI file 'video_equalizer.ui'
5
+ ##
6
+ ## Created by: Qt User Interface Compiler version 6.8.0
7
+ ##
8
+ ## WARNING! All changes made in this file will be lost when recompiling UI file!
9
+ ################################################################################
12
10
 
11
+ from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
12
+ QMetaObject, QObject, QPoint, QRect,
13
+ QSize, QTime, QUrl, Qt)
14
+ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
15
+ QFont, QFontDatabase, QGradient, QIcon,
16
+ QImage, QKeySequence, QLinearGradient, QPainter,
17
+ QPalette, QPixmap, QRadialGradient, QTransform)
18
+ from PySide6.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QLabel,
19
+ QPushButton, QSizePolicy, QSlider, QSpacerItem,
20
+ QVBoxLayout, QWidget)
13
21
 
14
22
  class Ui_Equalizer(object):
15
23
  def setupUi(self, Equalizer):
16
- Equalizer.setObjectName("Equalizer")
24
+ if not Equalizer.objectName():
25
+ Equalizer.setObjectName(u"Equalizer")
17
26
  Equalizer.resize(388, 284)
18
- self.verticalLayout = QtWidgets.QVBoxLayout(Equalizer)
19
- self.verticalLayout.setObjectName("verticalLayout")
20
- self.label_6 = QtWidgets.QLabel(Equalizer)
21
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
27
+ self.verticalLayout = QVBoxLayout(Equalizer)
28
+ self.verticalLayout.setObjectName(u"verticalLayout")
29
+ self.label_6 = QLabel(Equalizer)
30
+ self.label_6.setObjectName(u"label_6")
31
+ sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
22
32
  sizePolicy.setHorizontalStretch(0)
23
33
  sizePolicy.setVerticalStretch(0)
24
34
  sizePolicy.setHeightForWidth(self.label_6.sizePolicy().hasHeightForWidth())
25
35
  self.label_6.setSizePolicy(sizePolicy)
26
- font = QtGui.QFont()
36
+ font = QFont()
27
37
  font.setBold(True)
28
- font.setWeight(75)
29
38
  self.label_6.setFont(font)
30
- self.label_6.setObjectName("label_6")
39
+
31
40
  self.verticalLayout.addWidget(self.label_6)
32
- self.cb_player = QtWidgets.QComboBox(Equalizer)
33
- self.cb_player.setObjectName("cb_player")
41
+
42
+ self.cb_player = QComboBox(Equalizer)
43
+ self.cb_player.setObjectName(u"cb_player")
44
+
34
45
  self.verticalLayout.addWidget(self.cb_player)
35
- self.horizontalLayout = QtWidgets.QHBoxLayout()
36
- self.horizontalLayout.setObjectName("horizontalLayout")
37
- self.label = QtWidgets.QLabel(Equalizer)
38
- self.label.setMinimumSize(QtCore.QSize(70, 0))
39
- self.label.setMaximumSize(QtCore.QSize(70, 16777215))
40
- self.label.setObjectName("label")
46
+
47
+ self.horizontalLayout = QHBoxLayout()
48
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
49
+ self.label = QLabel(Equalizer)
50
+ self.label.setObjectName(u"label")
51
+ self.label.setMinimumSize(QSize(70, 0))
52
+ self.label.setMaximumSize(QSize(70, 16777215))
53
+
41
54
  self.horizontalLayout.addWidget(self.label)
42
- self.hs_brightness = QtWidgets.QSlider(Equalizer)
43
- self.hs_brightness.setMinimumSize(QtCore.QSize(200, 0))
44
- self.hs_brightness.setMaximumSize(QtCore.QSize(200, 16777215))
55
+
56
+ self.hs_brightness = QSlider(Equalizer)
57
+ self.hs_brightness.setObjectName(u"hs_brightness")
58
+ self.hs_brightness.setMinimumSize(QSize(200, 0))
59
+ self.hs_brightness.setMaximumSize(QSize(200, 16777215))
45
60
  self.hs_brightness.setMinimum(-100)
46
- self.hs_brightness.setProperty("value", 0)
47
- self.hs_brightness.setOrientation(QtCore.Qt.Horizontal)
48
- self.hs_brightness.setObjectName("hs_brightness")
61
+ self.hs_brightness.setValue(0)
62
+ self.hs_brightness.setOrientation(Qt.Horizontal)
63
+
49
64
  self.horizontalLayout.addWidget(self.hs_brightness)
50
- self.lb_brightness = QtWidgets.QLabel(Equalizer)
51
- self.lb_brightness.setMinimumSize(QtCore.QSize(25, 0))
52
- self.lb_brightness.setMaximumSize(QtCore.QSize(25, 16777215))
53
- self.lb_brightness.setObjectName("lb_brightness")
65
+
66
+ self.lb_brightness = QLabel(Equalizer)
67
+ self.lb_brightness.setObjectName(u"lb_brightness")
68
+ self.lb_brightness.setMinimumSize(QSize(25, 0))
69
+ self.lb_brightness.setMaximumSize(QSize(25, 16777215))
70
+
54
71
  self.horizontalLayout.addWidget(self.lb_brightness)
72
+
73
+
55
74
  self.verticalLayout.addLayout(self.horizontalLayout)
56
- self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
57
- self.horizontalLayout_2.setObjectName("horizontalLayout_2")
58
- self.label_2 = QtWidgets.QLabel(Equalizer)
59
- self.label_2.setMinimumSize(QtCore.QSize(70, 0))
60
- self.label_2.setMaximumSize(QtCore.QSize(70, 16777215))
61
- self.label_2.setObjectName("label_2")
75
+
76
+ self.horizontalLayout_2 = QHBoxLayout()
77
+ self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
78
+ self.label_2 = QLabel(Equalizer)
79
+ self.label_2.setObjectName(u"label_2")
80
+ self.label_2.setMinimumSize(QSize(70, 0))
81
+ self.label_2.setMaximumSize(QSize(70, 16777215))
82
+
62
83
  self.horizontalLayout_2.addWidget(self.label_2)
63
- self.hs_contrast = QtWidgets.QSlider(Equalizer)
64
- self.hs_contrast.setMinimumSize(QtCore.QSize(200, 0))
65
- self.hs_contrast.setMaximumSize(QtCore.QSize(200, 16777215))
84
+
85
+ self.hs_contrast = QSlider(Equalizer)
86
+ self.hs_contrast.setObjectName(u"hs_contrast")
87
+ self.hs_contrast.setMinimumSize(QSize(200, 0))
88
+ self.hs_contrast.setMaximumSize(QSize(200, 16777215))
66
89
  self.hs_contrast.setMinimum(-100)
67
- self.hs_contrast.setProperty("value", 0)
68
- self.hs_contrast.setOrientation(QtCore.Qt.Horizontal)
69
- self.hs_contrast.setObjectName("hs_contrast")
90
+ self.hs_contrast.setValue(0)
91
+ self.hs_contrast.setOrientation(Qt.Horizontal)
92
+
70
93
  self.horizontalLayout_2.addWidget(self.hs_contrast)
71
- self.lb_contrast = QtWidgets.QLabel(Equalizer)
72
- self.lb_contrast.setMinimumSize(QtCore.QSize(25, 0))
73
- self.lb_contrast.setMaximumSize(QtCore.QSize(25, 16777215))
74
- self.lb_contrast.setObjectName("lb_contrast")
94
+
95
+ self.lb_contrast = QLabel(Equalizer)
96
+ self.lb_contrast.setObjectName(u"lb_contrast")
97
+ self.lb_contrast.setMinimumSize(QSize(25, 0))
98
+ self.lb_contrast.setMaximumSize(QSize(25, 16777215))
99
+
75
100
  self.horizontalLayout_2.addWidget(self.lb_contrast)
101
+
102
+
76
103
  self.verticalLayout.addLayout(self.horizontalLayout_2)
77
- self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
78
- self.horizontalLayout_3.setObjectName("horizontalLayout_3")
79
- self.label_3 = QtWidgets.QLabel(Equalizer)
80
- self.label_3.setMinimumSize(QtCore.QSize(70, 0))
81
- self.label_3.setMaximumSize(QtCore.QSize(70, 16777215))
82
- self.label_3.setObjectName("label_3")
104
+
105
+ self.horizontalLayout_3 = QHBoxLayout()
106
+ self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
107
+ self.label_3 = QLabel(Equalizer)
108
+ self.label_3.setObjectName(u"label_3")
109
+ self.label_3.setMinimumSize(QSize(70, 0))
110
+ self.label_3.setMaximumSize(QSize(70, 16777215))
111
+
83
112
  self.horizontalLayout_3.addWidget(self.label_3)
84
- self.hs_saturation = QtWidgets.QSlider(Equalizer)
85
- self.hs_saturation.setMinimumSize(QtCore.QSize(200, 0))
86
- self.hs_saturation.setMaximumSize(QtCore.QSize(200, 16777215))
113
+
114
+ self.hs_saturation = QSlider(Equalizer)
115
+ self.hs_saturation.setObjectName(u"hs_saturation")
116
+ self.hs_saturation.setMinimumSize(QSize(200, 0))
117
+ self.hs_saturation.setMaximumSize(QSize(200, 16777215))
87
118
  self.hs_saturation.setMinimum(-100)
88
- self.hs_saturation.setProperty("value", 0)
89
- self.hs_saturation.setOrientation(QtCore.Qt.Horizontal)
90
- self.hs_saturation.setObjectName("hs_saturation")
119
+ self.hs_saturation.setValue(0)
120
+ self.hs_saturation.setOrientation(Qt.Horizontal)
121
+
91
122
  self.horizontalLayout_3.addWidget(self.hs_saturation)
92
- self.lb_saturation = QtWidgets.QLabel(Equalizer)
93
- self.lb_saturation.setMinimumSize(QtCore.QSize(25, 0))
94
- self.lb_saturation.setMaximumSize(QtCore.QSize(25, 16777215))
95
- self.lb_saturation.setObjectName("lb_saturation")
123
+
124
+ self.lb_saturation = QLabel(Equalizer)
125
+ self.lb_saturation.setObjectName(u"lb_saturation")
126
+ self.lb_saturation.setMinimumSize(QSize(25, 0))
127
+ self.lb_saturation.setMaximumSize(QSize(25, 16777215))
128
+
96
129
  self.horizontalLayout_3.addWidget(self.lb_saturation)
130
+
131
+
97
132
  self.verticalLayout.addLayout(self.horizontalLayout_3)
98
- self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
99
- self.horizontalLayout_4.setObjectName("horizontalLayout_4")
100
- self.label_4 = QtWidgets.QLabel(Equalizer)
101
- self.label_4.setMinimumSize(QtCore.QSize(70, 0))
102
- self.label_4.setMaximumSize(QtCore.QSize(70, 16777215))
103
- self.label_4.setObjectName("label_4")
133
+
134
+ self.horizontalLayout_4 = QHBoxLayout()
135
+ self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
136
+ self.label_4 = QLabel(Equalizer)
137
+ self.label_4.setObjectName(u"label_4")
138
+ self.label_4.setMinimumSize(QSize(70, 0))
139
+ self.label_4.setMaximumSize(QSize(70, 16777215))
140
+
104
141
  self.horizontalLayout_4.addWidget(self.label_4)
105
- self.hs_gamma = QtWidgets.QSlider(Equalizer)
106
- self.hs_gamma.setMinimumSize(QtCore.QSize(200, 0))
107
- self.hs_gamma.setMaximumSize(QtCore.QSize(200, 16777215))
142
+
143
+ self.hs_gamma = QSlider(Equalizer)
144
+ self.hs_gamma.setObjectName(u"hs_gamma")
145
+ self.hs_gamma.setMinimumSize(QSize(200, 0))
146
+ self.hs_gamma.setMaximumSize(QSize(200, 16777215))
108
147
  self.hs_gamma.setMinimum(-100)
109
- self.hs_gamma.setProperty("value", 0)
110
- self.hs_gamma.setOrientation(QtCore.Qt.Horizontal)
111
- self.hs_gamma.setObjectName("hs_gamma")
148
+ self.hs_gamma.setValue(0)
149
+ self.hs_gamma.setOrientation(Qt.Horizontal)
150
+
112
151
  self.horizontalLayout_4.addWidget(self.hs_gamma)
113
- self.lb_gamma = QtWidgets.QLabel(Equalizer)
114
- self.lb_gamma.setMinimumSize(QtCore.QSize(25, 0))
115
- self.lb_gamma.setMaximumSize(QtCore.QSize(25, 16777215))
116
- self.lb_gamma.setObjectName("lb_gamma")
152
+
153
+ self.lb_gamma = QLabel(Equalizer)
154
+ self.lb_gamma.setObjectName(u"lb_gamma")
155
+ self.lb_gamma.setMinimumSize(QSize(25, 0))
156
+ self.lb_gamma.setMaximumSize(QSize(25, 16777215))
157
+
117
158
  self.horizontalLayout_4.addWidget(self.lb_gamma)
159
+
160
+
118
161
  self.verticalLayout.addLayout(self.horizontalLayout_4)
119
- self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
120
- self.horizontalLayout_5.setObjectName("horizontalLayout_5")
121
- self.label_5 = QtWidgets.QLabel(Equalizer)
122
- self.label_5.setMinimumSize(QtCore.QSize(70, 0))
123
- self.label_5.setMaximumSize(QtCore.QSize(70, 16777215))
124
- self.label_5.setObjectName("label_5")
162
+
163
+ self.horizontalLayout_5 = QHBoxLayout()
164
+ self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
165
+ self.label_5 = QLabel(Equalizer)
166
+ self.label_5.setObjectName(u"label_5")
167
+ self.label_5.setMinimumSize(QSize(70, 0))
168
+ self.label_5.setMaximumSize(QSize(70, 16777215))
169
+
125
170
  self.horizontalLayout_5.addWidget(self.label_5)
126
- self.hs_hue = QtWidgets.QSlider(Equalizer)
127
- self.hs_hue.setMinimumSize(QtCore.QSize(200, 0))
128
- self.hs_hue.setMaximumSize(QtCore.QSize(200, 16777215))
171
+
172
+ self.hs_hue = QSlider(Equalizer)
173
+ self.hs_hue.setObjectName(u"hs_hue")
174
+ self.hs_hue.setMinimumSize(QSize(200, 0))
175
+ self.hs_hue.setMaximumSize(QSize(200, 16777215))
129
176
  self.hs_hue.setMinimum(-100)
130
- self.hs_hue.setProperty("value", 0)
131
- self.hs_hue.setOrientation(QtCore.Qt.Horizontal)
132
- self.hs_hue.setObjectName("hs_hue")
177
+ self.hs_hue.setValue(0)
178
+ self.hs_hue.setOrientation(Qt.Horizontal)
179
+
133
180
  self.horizontalLayout_5.addWidget(self.hs_hue)
134
- self.lb_hue = QtWidgets.QLabel(Equalizer)
135
- self.lb_hue.setMinimumSize(QtCore.QSize(25, 0))
136
- self.lb_hue.setMaximumSize(QtCore.QSize(25, 16777215))
137
- self.lb_hue.setObjectName("lb_hue")
181
+
182
+ self.lb_hue = QLabel(Equalizer)
183
+ self.lb_hue.setObjectName(u"lb_hue")
184
+ self.lb_hue.setMinimumSize(QSize(25, 0))
185
+ self.lb_hue.setMaximumSize(QSize(25, 16777215))
186
+
138
187
  self.horizontalLayout_5.addWidget(self.lb_hue)
188
+
189
+
139
190
  self.verticalLayout.addLayout(self.horizontalLayout_5)
140
- self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
141
- self.horizontalLayout_6.setObjectName("horizontalLayout_6")
142
- self.pb_reset_all = QtWidgets.QPushButton(Equalizer)
143
- self.pb_reset_all.setObjectName("pb_reset_all")
191
+
192
+ self.horizontalLayout_6 = QHBoxLayout()
193
+ self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
194
+ self.pb_reset_all = QPushButton(Equalizer)
195
+ self.pb_reset_all.setObjectName(u"pb_reset_all")
196
+
144
197
  self.horizontalLayout_6.addWidget(self.pb_reset_all)
145
- self.pb_reset = QtWidgets.QPushButton(Equalizer)
146
- self.pb_reset.setObjectName("pb_reset")
198
+
199
+ self.pb_reset = QPushButton(Equalizer)
200
+ self.pb_reset.setObjectName(u"pb_reset")
201
+
147
202
  self.horizontalLayout_6.addWidget(self.pb_reset)
203
+
204
+
148
205
  self.verticalLayout.addLayout(self.horizontalLayout_6)
149
- spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
150
- self.verticalLayout.addItem(spacerItem)
151
- self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
152
- self.horizontalLayout_7.setObjectName("horizontalLayout_7")
153
- spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
154
- self.horizontalLayout_7.addItem(spacerItem1)
155
- self.pb_close = QtWidgets.QPushButton(Equalizer)
156
- self.pb_close.setObjectName("pb_close")
206
+
207
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
208
+
209
+ self.verticalLayout.addItem(self.verticalSpacer)
210
+
211
+ self.horizontalLayout_7 = QHBoxLayout()
212
+ self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
213
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
214
+
215
+ self.horizontalLayout_7.addItem(self.horizontalSpacer)
216
+
217
+ self.pb_close = QPushButton(Equalizer)
218
+ self.pb_close.setObjectName(u"pb_close")
219
+
157
220
  self.horizontalLayout_7.addWidget(self.pb_close)
221
+
222
+
158
223
  self.verticalLayout.addLayout(self.horizontalLayout_7)
159
224
 
225
+
160
226
  self.retranslateUi(Equalizer)
161
- QtCore.QMetaObject.connectSlotsByName(Equalizer)
227
+
228
+ QMetaObject.connectSlotsByName(Equalizer)
229
+ # setupUi
162
230
 
163
231
  def retranslateUi(self, Equalizer):
164
- _translate = QtCore.QCoreApplication.translate
165
- Equalizer.setWindowTitle(_translate("Equalizer", "Video equalizer"))
166
- self.label_6.setText(_translate("Equalizer", "Video equalizer"))
167
- self.label.setText(_translate("Equalizer", "Brightness"))
168
- self.lb_brightness.setText(_translate("Equalizer", "0"))
169
- self.label_2.setText(_translate("Equalizer", "Contrast"))
170
- self.lb_contrast.setText(_translate("Equalizer", "0"))
171
- self.label_3.setText(_translate("Equalizer", "Saturation"))
172
- self.lb_saturation.setText(_translate("Equalizer", "0"))
173
- self.label_4.setText(_translate("Equalizer", "Gamma"))
174
- self.lb_gamma.setText(_translate("Equalizer", "0"))
175
- self.label_5.setText(_translate("Equalizer", "Hue"))
176
- self.lb_hue.setText(_translate("Equalizer", "0"))
177
- self.pb_reset_all.setText(_translate("Equalizer", "Reset all players"))
178
- self.pb_reset.setText(_translate("Equalizer", "Reset current player"))
179
- self.pb_close.setText(_translate("Equalizer", "Close"))
232
+ Equalizer.setWindowTitle(QCoreApplication.translate("Equalizer", u"Video equalizer", None))
233
+ self.label_6.setText(QCoreApplication.translate("Equalizer", u"Video equalizer", None))
234
+ self.label.setText(QCoreApplication.translate("Equalizer", u"Brightness", None))
235
+ self.lb_brightness.setText(QCoreApplication.translate("Equalizer", u"0", None))
236
+ self.label_2.setText(QCoreApplication.translate("Equalizer", u"Contrast", None))
237
+ self.lb_contrast.setText(QCoreApplication.translate("Equalizer", u"0", None))
238
+ self.label_3.setText(QCoreApplication.translate("Equalizer", u"Saturation", None))
239
+ self.lb_saturation.setText(QCoreApplication.translate("Equalizer", u"0", None))
240
+ self.label_4.setText(QCoreApplication.translate("Equalizer", u"Gamma", None))
241
+ self.lb_gamma.setText(QCoreApplication.translate("Equalizer", u"0", None))
242
+ self.label_5.setText(QCoreApplication.translate("Equalizer", u"Hue", None))
243
+ self.lb_hue.setText(QCoreApplication.translate("Equalizer", u"0", None))
244
+ self.pb_reset_all.setText(QCoreApplication.translate("Equalizer", u"Reset all players", None))
245
+ self.pb_reset.setText(QCoreApplication.translate("Equalizer", u"Reset current player", None))
246
+ self.pb_close.setText(QCoreApplication.translate("Equalizer", u"Close", None))
247
+ # retranslateUi
248
+
boris/video_operations.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
4
+ Copyright 2012-2025 Olivier Friard
5
5
 
6
6
 
7
7
  This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@ import pathlib as pl
26
26
  import shutil
27
27
  from math import log2
28
28
 
29
- from PyQt5.QtWidgets import QFileDialog
29
+ from PySide6.QtWidgets import QFileDialog
30
30
 
31
31
  from . import config as cfg
32
32
  from . import dialog
@@ -79,20 +79,15 @@ def snapshot(self):
79
79
 
80
80
  def zoom_level(self):
81
81
  """
82
- display dialog for zoom level
82
+ display dialog box for setting the zoom level
83
83
  """
84
84
  logging.info("change zoom level of player")
85
85
 
86
86
  players_list: list = []
87
87
  for idx, dw in enumerate(self.dw_player):
88
- zoom_levels: list = []
89
- for choice in (2, 1, 0.5, 0.25):
90
- zoom_levels.append((str(choice), "selected" if log2(choice) == dw.player.video_zoom else ""))
91
- players_list.append(("il", f"Player #{idx + 1}", zoom_levels))
92
-
93
- zl = dialog.Input_dialog(
94
- label_caption="Select the zoom level", elements_list=players_list, title="Video zoom level"
95
- )
88
+ players_list.append(("dsb", f"Player #{idx + 1}", 0.1, 12, 0.1, 2**dw.player.video_zoom, 1))
89
+
90
+ zl = dialog.Input_dialog(label_caption="Select the zoom level", elements_list=players_list, title="Video zoom level")
96
91
  if not zl.exec_():
97
92
  return
98
93
 
@@ -100,21 +95,64 @@ def zoom_level(self):
100
95
  self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.ZOOM_LEVEL] = {}
101
96
 
102
97
  for idx, dw in enumerate(self.dw_player):
103
- if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.ZOOM_LEVEL].get(
104
- str(idx + 1), dw.player.video_zoom
105
- ) != float(zl.elements[f"Player #{idx + 1}"].currentText()):
106
- dw.player.video_zoom = log2(float(zl.elements[f"Player #{idx + 1}"].currentText()))
107
-
108
- """
109
- dw.player.video_pan_x = 0.25
110
- dw.player.video_pan_x = 0.25
111
- """
98
+ if (
99
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.ZOOM_LEVEL].get(str(idx + 1), dw.player.video_zoom)
100
+ != zl.elements[f"Player #{idx + 1}"].value()
101
+ ):
102
+ dw.player.video_zoom = log2(float(zl.elements[f"Player #{idx + 1}"].value()))
112
103
 
113
104
  logging.debug(f"video zoom changed in {dw.player.video_zoom} for player {idx + 1}")
114
105
 
115
106
  self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.ZOOM_LEVEL][str(idx + 1)] = float(
116
- zl.elements[f"Player #{idx + 1}"].currentText()
107
+ zl.elements[f"Player #{idx + 1}"].value()
117
108
  )
109
+ display_zoom_level(self)
110
+ self.project_changed()
111
+
112
+
113
+ def change_player_offset(self):
114
+ """
115
+ display dialog box for setting the player time offset
116
+ """
117
+ logging.info("change the player time offset")
118
+
119
+ if cfg.OFFSET not in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]:
120
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET] = {}
121
+
122
+ players_list: list = []
123
+
124
+ for idx, dw in enumerate(self.dw_player):
125
+ players_list.append(
126
+ (
127
+ "dsb",
128
+ f"Player #{idx + 1}",
129
+ -100000,
130
+ 100000,
131
+ 0.001,
132
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(idx + 1)],
133
+ 3,
134
+ )
135
+ )
136
+
137
+ zl = dialog.Input_dialog(label_caption="Select the time offset", elements_list=players_list, title="Time offset")
138
+ if not zl.exec_():
139
+ return
140
+
141
+ for idx, dw in enumerate(self.dw_player):
142
+ if (
143
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET].get(str(idx + 1), 0)
144
+ != zl.elements[f"Player #{idx + 1}"].value()
145
+ ):
146
+ logging.debug(f"time offset of player changed in {zl.elements[f'Player #{idx + 1}'].value()} for player {idx + 1}")
147
+
148
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(idx + 1)] = float(
149
+ zl.elements[f"Player #{idx + 1}"].value()
150
+ )
151
+
152
+ if self.dw_player[0].player.time_pos is not None:
153
+ cumulative_time_pos = self.getLaps() # for player 1
154
+ self.sync_time(idx, cumulative_time_pos)
155
+
118
156
  self.project_changed()
119
157
 
120
158
 
@@ -129,9 +167,7 @@ def rotate_displayed_video(self):
129
167
  rotation_angles.append((str(choice), "selected" if choice == dw.player.video_rotate else ""))
130
168
  players_list.append(("il", f"Player #{idx + 1}", rotation_angles))
131
169
 
132
- w = dialog.Input_dialog(
133
- label_caption="Select the rotation angle", elements_list=players_list, title="Video rotation angle"
134
- )
170
+ w = dialog.Input_dialog(label_caption="Select the rotation angle", elements_list=players_list, title="Video rotation angle")
135
171
  if not w.exec_():
136
172
  return
137
173
  if cfg.ROTATION_ANGLE not in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]:
@@ -183,17 +219,30 @@ def display_subtitles(self):
183
219
 
184
220
  logging.debug(f"subtitle visibility for player {idx + 1}: {dw.player.sub_visibility}")
185
221
 
186
- self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.DISPLAY_MEDIA_SUBTITLES][
187
- str(idx + 1)
188
- ] = st.elements[f"Player #{idx + 1}"].isChecked()
222
+ self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.DISPLAY_MEDIA_SUBTITLES][str(idx + 1)] = st.elements[
223
+ f"Player #{idx + 1}"
224
+ ].isChecked()
189
225
  self.project_changed()
190
226
 
191
227
 
228
+ def display_zoom_level(self) -> None:
229
+ """
230
+ display the zoom level
231
+ """
232
+ msg: str = "Zoom level: <b>"
233
+ for player in self.dw_player:
234
+ msg += f"{2**player.player.video_zoom:.1f} "
235
+ msg += "</b>"
236
+ self.lb_zoom_level.setText(msg)
237
+
238
+
192
239
  def display_play_rate(self) -> None:
193
240
  """
194
241
  display current play rate in status bar widget
195
242
  """
196
- self.lbSpeed.setText(f"Play rate: <b>x{self.play_rate:.3f}</b>")
243
+
244
+ self.lb_video_info.setText(f"Play rate: <b>x{self.play_rate:.3f}</b>")
245
+
197
246
  logging.debug(f"play rate: {self.play_rate:.3f}")
198
247
 
199
248
 
@@ -232,6 +281,7 @@ def video_faster_activated(self):
232
281
  and self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][str(i + 1)]
233
282
  ):
234
283
  player.player.speed = self.play_rate
284
+ print("speed")
235
285
 
236
286
  display_play_rate(self)
237
287