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/add_modifier_ui.py CHANGED
@@ -1,181 +1,285 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Form implementation generated from reading ui file 'add_modifier.ui'
4
- #
5
- # Created by: PyQt5 UI code generator 5.15.7
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 'add_modifier.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, QCheckBox, QComboBox, QDialog,
19
+ QHBoxLayout, QLabel, QLineEdit, QListWidget,
20
+ QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem,
21
+ QTabWidget, QVBoxLayout, QWidget)
13
22
 
14
23
  class Ui_Dialog(object):
15
24
  def setupUi(self, Dialog):
16
- Dialog.setObjectName("Dialog")
17
- Dialog.resize(638, 636)
18
- self.verticalLayout_5 = QtWidgets.QVBoxLayout(Dialog)
19
- self.verticalLayout_5.setObjectName("verticalLayout_5")
20
- self.verticalLayout_4 = QtWidgets.QVBoxLayout()
21
- self.verticalLayout_4.setObjectName("verticalLayout_4")
22
- self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
23
- self.horizontalLayout_5.setObjectName("horizontalLayout_5")
24
- self.verticalLayout_2 = QtWidgets.QVBoxLayout()
25
- self.verticalLayout_2.setObjectName("verticalLayout_2")
26
- self.lbModifier = QtWidgets.QLabel(Dialog)
27
- self.lbModifier.setObjectName("lbModifier")
25
+ if not Dialog.objectName():
26
+ Dialog.setObjectName(u"Dialog")
27
+ Dialog.resize(1088, 654)
28
+ self.verticalLayout_5 = QVBoxLayout(Dialog)
29
+ self.verticalLayout_5.setObjectName(u"verticalLayout_5")
30
+ self.cb_ask_at_stop = QCheckBox(Dialog)
31
+ self.cb_ask_at_stop.setObjectName(u"cb_ask_at_stop")
32
+
33
+ self.verticalLayout_5.addWidget(self.cb_ask_at_stop)
34
+
35
+ self.verticalLayout_4 = QVBoxLayout()
36
+ self.verticalLayout_4.setObjectName(u"verticalLayout_4")
37
+ self.horizontalLayout_5 = QHBoxLayout()
38
+ self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
39
+ self.verticalLayout_2 = QVBoxLayout()
40
+ self.verticalLayout_2.setObjectName(u"verticalLayout_2")
41
+ self.lbModifier = QLabel(Dialog)
42
+ self.lbModifier.setObjectName(u"lbModifier")
43
+
28
44
  self.verticalLayout_2.addWidget(self.lbModifier)
29
- self.leModifier = QtWidgets.QLineEdit(Dialog)
30
- self.leModifier.setObjectName("leModifier")
45
+
46
+ self.leModifier = QLineEdit(Dialog)
47
+ self.leModifier.setObjectName(u"leModifier")
48
+
31
49
  self.verticalLayout_2.addWidget(self.leModifier)
32
- self.lbCode = QtWidgets.QLabel(Dialog)
33
- self.lbCode.setObjectName("lbCode")
50
+
51
+ self.lbCode = QLabel(Dialog)
52
+ self.lbCode.setObjectName(u"lbCode")
53
+
34
54
  self.verticalLayout_2.addWidget(self.lbCode)
35
- self.leCode = QtWidgets.QLineEdit(Dialog)
36
- self.leCode.setObjectName("leCode")
55
+
56
+ self.leCode = QLineEdit(Dialog)
57
+ self.leCode.setObjectName(u"leCode")
58
+
37
59
  self.verticalLayout_2.addWidget(self.leCode)
38
- self.lbCodeHelp = QtWidgets.QLabel(Dialog)
60
+
61
+ self.lbCodeHelp = QLabel(Dialog)
62
+ self.lbCodeHelp.setObjectName(u"lbCodeHelp")
39
63
  self.lbCodeHelp.setWordWrap(True)
40
- self.lbCodeHelp.setObjectName("lbCodeHelp")
64
+
41
65
  self.verticalLayout_2.addWidget(self.lbCodeHelp)
42
- spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
43
- self.verticalLayout_2.addItem(spacerItem)
66
+
67
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
68
+
69
+ self.verticalLayout_2.addItem(self.verticalSpacer)
70
+
71
+
44
72
  self.horizontalLayout_5.addLayout(self.verticalLayout_2)
45
- self.verticalLayout_3 = QtWidgets.QVBoxLayout()
46
- self.verticalLayout_3.setObjectName("verticalLayout_3")
47
- self.pbAddModifier = QtWidgets.QPushButton(Dialog)
48
- self.pbAddModifier.setText("")
49
- self.pbAddModifier.setObjectName("pbAddModifier")
73
+
74
+ self.verticalLayout_3 = QVBoxLayout()
75
+ self.verticalLayout_3.setObjectName(u"verticalLayout_3")
76
+ self.pbAddModifier = QPushButton(Dialog)
77
+ self.pbAddModifier.setObjectName(u"pbAddModifier")
78
+
50
79
  self.verticalLayout_3.addWidget(self.pbAddModifier)
51
- self.pbModifyModifier = QtWidgets.QPushButton(Dialog)
52
- self.pbModifyModifier.setText("")
53
- self.pbModifyModifier.setObjectName("pbModifyModifier")
80
+
81
+ self.pbModifyModifier = QPushButton(Dialog)
82
+ self.pbModifyModifier.setObjectName(u"pbModifyModifier")
83
+
54
84
  self.verticalLayout_3.addWidget(self.pbModifyModifier)
55
- spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
56
- self.verticalLayout_3.addItem(spacerItem1)
85
+
86
+ self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
87
+
88
+ self.verticalLayout_3.addItem(self.verticalSpacer_2)
89
+
90
+
57
91
  self.horizontalLayout_5.addLayout(self.verticalLayout_3)
58
- self.verticalLayout = QtWidgets.QVBoxLayout()
59
- self.verticalLayout.setObjectName("verticalLayout")
60
- self.tabWidgetModifiersSets = QtWidgets.QTabWidget(Dialog)
61
- self.tabWidgetModifiersSets.setMaximumSize(QtCore.QSize(16777215, 30))
62
- self.tabWidgetModifiersSets.setTabPosition(QtWidgets.QTabWidget.North)
63
- self.tabWidgetModifiersSets.setTabShape(QtWidgets.QTabWidget.Rounded)
64
- self.tabWidgetModifiersSets.setElideMode(QtCore.Qt.ElideNone)
92
+
93
+ self.verticalLayout = QVBoxLayout()
94
+ self.verticalLayout.setObjectName(u"verticalLayout")
95
+ self.tabWidgetModifiersSets = QTabWidget(Dialog)
96
+ self.tabWidgetModifiersSets.setObjectName(u"tabWidgetModifiersSets")
97
+ self.tabWidgetModifiersSets.setMaximumSize(QSize(16777215, 30))
98
+ self.tabWidgetModifiersSets.setTabPosition(QTabWidget.TabPosition.North)
99
+ self.tabWidgetModifiersSets.setTabShape(QTabWidget.TabShape.Rounded)
100
+ self.tabWidgetModifiersSets.setElideMode(Qt.TextElideMode.ElideNone)
65
101
  self.tabWidgetModifiersSets.setDocumentMode(True)
66
- self.tabWidgetModifiersSets.setObjectName("tabWidgetModifiersSets")
102
+
67
103
  self.verticalLayout.addWidget(self.tabWidgetModifiersSets)
68
- self.lb_name = QtWidgets.QLabel(Dialog)
69
- self.lb_name.setObjectName("lb_name")
104
+
105
+ self.lb_name = QLabel(Dialog)
106
+ self.lb_name.setObjectName(u"lb_name")
107
+
70
108
  self.verticalLayout.addWidget(self.lb_name)
71
- self.le_name = QtWidgets.QLineEdit(Dialog)
72
- self.le_name.setObjectName("le_name")
109
+
110
+ self.le_name = QLineEdit(Dialog)
111
+ self.le_name.setObjectName(u"le_name")
112
+
73
113
  self.verticalLayout.addWidget(self.le_name)
74
- self.lb_description = QtWidgets.QLabel(Dialog)
75
- self.lb_description.setObjectName("lb_description")
114
+
115
+ self.lb_description = QLabel(Dialog)
116
+ self.lb_description.setObjectName(u"lb_description")
117
+
76
118
  self.verticalLayout.addWidget(self.lb_description)
77
- self.le_description = QtWidgets.QLineEdit(Dialog)
78
- self.le_description.setObjectName("le_description")
119
+
120
+ self.le_description = QLineEdit(Dialog)
121
+ self.le_description.setObjectName(u"le_description")
122
+
79
123
  self.verticalLayout.addWidget(self.le_description)
80
- self.lbType = QtWidgets.QLabel(Dialog)
81
- self.lbType.setObjectName("lbType")
124
+
125
+ self.lbType = QLabel(Dialog)
126
+ self.lbType.setObjectName(u"lbType")
127
+
82
128
  self.verticalLayout.addWidget(self.lbType)
83
- self.cbType = QtWidgets.QComboBox(Dialog)
84
- self.cbType.setObjectName("cbType")
129
+
130
+ self.cbType = QComboBox(Dialog)
85
131
  self.cbType.addItem("")
86
132
  self.cbType.addItem("")
87
133
  self.cbType.addItem("")
88
134
  self.cbType.addItem("")
135
+ self.cbType.setObjectName(u"cbType")
136
+
89
137
  self.verticalLayout.addWidget(self.cbType)
90
- self.lbValues = QtWidgets.QLabel(Dialog)
91
- self.lbValues.setObjectName("lbValues")
138
+
139
+ self.lbValues = QLabel(Dialog)
140
+ self.lbValues.setObjectName(u"lbValues")
141
+
92
142
  self.verticalLayout.addWidget(self.lbValues)
93
- self.lwModifiers = QtWidgets.QListWidget(Dialog)
94
- self.lwModifiers.setObjectName("lwModifiers")
143
+
144
+ self.lwModifiers = QListWidget(Dialog)
145
+ self.lwModifiers.setObjectName(u"lwModifiers")
146
+
95
147
  self.verticalLayout.addWidget(self.lwModifiers)
96
- self.horizontalLayout = QtWidgets.QHBoxLayout()
97
- self.horizontalLayout.setObjectName("horizontalLayout")
98
- self.pbMoveUp = QtWidgets.QPushButton(Dialog)
99
- self.pbMoveUp.setObjectName("pbMoveUp")
148
+
149
+ self.horizontalLayout = QHBoxLayout()
150
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
151
+ self.pbMoveUp = QPushButton(Dialog)
152
+ self.pbMoveUp.setObjectName(u"pbMoveUp")
153
+
100
154
  self.horizontalLayout.addWidget(self.pbMoveUp)
101
- self.pbMoveDown = QtWidgets.QPushButton(Dialog)
102
- self.pbMoveDown.setObjectName("pbMoveDown")
155
+
156
+ self.pbMoveDown = QPushButton(Dialog)
157
+ self.pbMoveDown.setObjectName(u"pbMoveDown")
158
+
103
159
  self.horizontalLayout.addWidget(self.pbMoveDown)
160
+
161
+ self.pb_sort_modifiers = QPushButton(Dialog)
162
+ self.pb_sort_modifiers.setObjectName(u"pb_sort_modifiers")
163
+
164
+ self.horizontalLayout.addWidget(self.pb_sort_modifiers)
165
+
166
+ self.pbRemoveModifier = QPushButton(Dialog)
167
+ self.pbRemoveModifier.setObjectName(u"pbRemoveModifier")
168
+
169
+ self.horizontalLayout.addWidget(self.pbRemoveModifier)
170
+
171
+
104
172
  self.verticalLayout.addLayout(self.horizontalLayout)
105
- self.pbRemoveModifier = QtWidgets.QPushButton(Dialog)
106
- self.pbRemoveModifier.setObjectName("pbRemoveModifier")
107
- self.verticalLayout.addWidget(self.pbRemoveModifier)
108
- self.pb_sort_modifiers = QtWidgets.QPushButton(Dialog)
109
- self.pb_sort_modifiers.setObjectName("pb_sort_modifiers")
110
- self.verticalLayout.addWidget(self.pb_sort_modifiers)
111
- self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
112
- self.horizontalLayout_3.setObjectName("horizontalLayout_3")
113
- self.pbAddSet = QtWidgets.QPushButton(Dialog)
114
- self.pbAddSet.setObjectName("pbAddSet")
173
+
174
+ self.horizontalLayout_3 = QHBoxLayout()
175
+ self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
176
+ self.pbAddSet = QPushButton(Dialog)
177
+ self.pbAddSet.setObjectName(u"pbAddSet")
178
+
115
179
  self.horizontalLayout_3.addWidget(self.pbAddSet)
116
- self.pbRemoveSet = QtWidgets.QPushButton(Dialog)
117
- self.pbRemoveSet.setObjectName("pbRemoveSet")
180
+
181
+ self.pbMoveSetLeft = QPushButton(Dialog)
182
+ self.pbMoveSetLeft.setObjectName(u"pbMoveSetLeft")
183
+
184
+ self.horizontalLayout_3.addWidget(self.pbMoveSetLeft)
185
+
186
+ self.pbMoveSetRight = QPushButton(Dialog)
187
+ self.pbMoveSetRight.setObjectName(u"pbMoveSetRight")
188
+
189
+ self.horizontalLayout_3.addWidget(self.pbMoveSetRight)
190
+
191
+ self.pbRemoveSet = QPushButton(Dialog)
192
+ self.pbRemoveSet.setObjectName(u"pbRemoveSet")
193
+
118
194
  self.horizontalLayout_3.addWidget(self.pbRemoveSet)
195
+
196
+
119
197
  self.verticalLayout.addLayout(self.horizontalLayout_3)
120
- self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
121
- self.horizontalLayout_4.setObjectName("horizontalLayout_4")
122
- self.pbMoveSetLeft = QtWidgets.QPushButton(Dialog)
123
- self.pbMoveSetLeft.setObjectName("pbMoveSetLeft")
124
- self.horizontalLayout_4.addWidget(self.pbMoveSetLeft)
125
- self.pbMoveSetRight = QtWidgets.QPushButton(Dialog)
126
- self.pbMoveSetRight.setObjectName("pbMoveSetRight")
127
- self.horizontalLayout_4.addWidget(self.pbMoveSetRight)
198
+
199
+ self.horizontalLayout_4 = QHBoxLayout()
200
+ self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
201
+
128
202
  self.verticalLayout.addLayout(self.horizontalLayout_4)
129
- self.pb_add_subjects = QtWidgets.QPushButton(Dialog)
130
- self.pb_add_subjects.setObjectName("pb_add_subjects")
203
+
204
+ self.pb_add_subjects = QPushButton(Dialog)
205
+ self.pb_add_subjects.setObjectName(u"pb_add_subjects")
206
+
131
207
  self.verticalLayout.addWidget(self.pb_add_subjects)
132
- self.pb_load_file = QtWidgets.QPushButton(Dialog)
133
- self.pb_load_file.setObjectName("pb_load_file")
208
+
209
+ self.pb_load_file = QPushButton(Dialog)
210
+ self.pb_load_file.setObjectName(u"pb_load_file")
211
+
134
212
  self.verticalLayout.addWidget(self.pb_load_file)
135
- spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
136
- self.verticalLayout.addItem(spacerItem2)
213
+
214
+ self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
215
+
216
+ self.verticalLayout.addItem(self.verticalSpacer_3)
217
+
218
+
137
219
  self.horizontalLayout_5.addLayout(self.verticalLayout)
220
+
221
+
138
222
  self.verticalLayout_4.addLayout(self.horizontalLayout_5)
139
- self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
140
- self.horizontalLayout_2.setObjectName("horizontalLayout_2")
141
- spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
142
- self.horizontalLayout_2.addItem(spacerItem3)
143
- self.pbCancel = QtWidgets.QPushButton(Dialog)
144
- self.pbCancel.setObjectName("pbCancel")
223
+
224
+ self.horizontalLayout_2 = QHBoxLayout()
225
+ self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
226
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
227
+
228
+ self.horizontalLayout_2.addItem(self.horizontalSpacer)
229
+
230
+ self.pbCancel = QPushButton(Dialog)
231
+ self.pbCancel.setObjectName(u"pbCancel")
232
+
145
233
  self.horizontalLayout_2.addWidget(self.pbCancel)
146
- self.pbOK = QtWidgets.QPushButton(Dialog)
147
- self.pbOK.setObjectName("pbOK")
234
+
235
+ self.pbOK = QPushButton(Dialog)
236
+ self.pbOK.setObjectName(u"pbOK")
237
+
148
238
  self.horizontalLayout_2.addWidget(self.pbOK)
239
+
240
+
149
241
  self.verticalLayout_4.addLayout(self.horizontalLayout_2)
242
+
243
+
150
244
  self.verticalLayout_5.addLayout(self.verticalLayout_4)
151
245
 
246
+
152
247
  self.retranslateUi(Dialog)
248
+
153
249
  self.tabWidgetModifiersSets.setCurrentIndex(-1)
154
- QtCore.QMetaObject.connectSlotsByName(Dialog)
250
+
251
+
252
+ QMetaObject.connectSlotsByName(Dialog)
253
+ # setupUi
155
254
 
156
255
  def retranslateUi(self, Dialog):
157
- _translate = QtCore.QCoreApplication.translate
158
- Dialog.setWindowTitle(_translate("Dialog", "Set modifiers"))
159
- self.lbModifier.setText(_translate("Dialog", "Modifier"))
160
- self.lbCode.setText(_translate("Dialog", "Key code"))
161
- self.lbCodeHelp.setText(_translate("Dialog", "Key code is case sensitive. Type one character or a function key (F1, F2... F12)"))
162
- self.lb_name.setText(_translate("Dialog", "Set name"))
163
- self.lb_description.setText(_translate("Dialog", "Description"))
164
- self.lbType.setText(_translate("Dialog", "Modifier type"))
165
- self.cbType.setItemText(0, _translate("Dialog", "Single selection"))
166
- self.cbType.setItemText(1, _translate("Dialog", "Multiple selection"))
167
- self.cbType.setItemText(2, _translate("Dialog", "Numeric"))
168
- self.cbType.setItemText(3, _translate("Dialog", "Value from external data file"))
169
- self.lbValues.setText(_translate("Dialog", "Values"))
170
- self.pbMoveUp.setText(_translate("Dialog", "Move modifier up"))
171
- self.pbMoveDown.setText(_translate("Dialog", "Move modifier down"))
172
- self.pbRemoveModifier.setText(_translate("Dialog", "Remove modifier"))
173
- self.pb_sort_modifiers.setText(_translate("Dialog", "Sort modifiers"))
174
- self.pbAddSet.setText(_translate("Dialog", "Add set of modifiers"))
175
- self.pbRemoveSet.setText(_translate("Dialog", "Remove set of modifiers"))
176
- self.pbMoveSetLeft.setText(_translate("Dialog", "Move set left"))
177
- self.pbMoveSetRight.setText(_translate("Dialog", "Move set right"))
178
- self.pb_add_subjects.setText(_translate("Dialog", "Add subjects as modifiers"))
179
- self.pb_load_file.setText(_translate("Dialog", "Load modifiers from file"))
180
- self.pbCancel.setText(_translate("Dialog", "Cancel"))
181
- self.pbOK.setText(_translate("Dialog", "OK"))
256
+ Dialog.setWindowTitle(QCoreApplication.translate("Dialog", u"Set modifiers", None))
257
+ self.cb_ask_at_stop.setText(QCoreApplication.translate("Dialog", u"Ask for modifier(s) when behavior stops", None))
258
+ self.lbModifier.setText(QCoreApplication.translate("Dialog", u"Modifier", None))
259
+ self.lbCode.setText(QCoreApplication.translate("Dialog", u"Key code", None))
260
+ self.lbCodeHelp.setText(QCoreApplication.translate("Dialog", u"Key code is case sensitive. Type one character or a function key (F1, F2... F12)", None))
261
+ self.pbAddModifier.setText(QCoreApplication.translate("Dialog", u"->", None))
262
+ self.pbModifyModifier.setText(QCoreApplication.translate("Dialog", u"<-", None))
263
+ self.lb_name.setText(QCoreApplication.translate("Dialog", u"Set name", None))
264
+ self.lb_description.setText(QCoreApplication.translate("Dialog", u"Description", None))
265
+ self.lbType.setText(QCoreApplication.translate("Dialog", u"Modifier type", None))
266
+ self.cbType.setItemText(0, QCoreApplication.translate("Dialog", u"Single selection", None))
267
+ self.cbType.setItemText(1, QCoreApplication.translate("Dialog", u"Multiple selection", None))
268
+ self.cbType.setItemText(2, QCoreApplication.translate("Dialog", u"Numeric", None))
269
+ self.cbType.setItemText(3, QCoreApplication.translate("Dialog", u"Value from external data file", None))
270
+
271
+ self.lbValues.setText(QCoreApplication.translate("Dialog", u"Values", None))
272
+ self.pbMoveUp.setText(QCoreApplication.translate("Dialog", u"Move modifier up", None))
273
+ self.pbMoveDown.setText(QCoreApplication.translate("Dialog", u"Move modifier down", None))
274
+ self.pb_sort_modifiers.setText(QCoreApplication.translate("Dialog", u"Sort modifiers", None))
275
+ self.pbRemoveModifier.setText(QCoreApplication.translate("Dialog", u"Remove modifier", None))
276
+ self.pbAddSet.setText(QCoreApplication.translate("Dialog", u"Add set of modifiers", None))
277
+ self.pbMoveSetLeft.setText(QCoreApplication.translate("Dialog", u"Move set left", None))
278
+ self.pbMoveSetRight.setText(QCoreApplication.translate("Dialog", u"Move set right", None))
279
+ self.pbRemoveSet.setText(QCoreApplication.translate("Dialog", u"Remove set of modifiers", None))
280
+ self.pb_add_subjects.setText(QCoreApplication.translate("Dialog", u"Add subjects as modifiers", None))
281
+ self.pb_load_file.setText(QCoreApplication.translate("Dialog", u"Load modifiers from file", None))
282
+ self.pbCancel.setText(QCoreApplication.translate("Dialog", u"Cancel", None))
283
+ self.pbOK.setText(QCoreApplication.translate("Dialog", u"OK", None))
284
+ # retranslateUi
285
+
@@ -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 program is free software; you can redistribute it and/or modify
7
7
  it under the terms of the GNU General Public License as published by
@@ -19,16 +19,15 @@ Copyright 2012-2023 Olivier Friard
19
19
  MA 02110-1301, USA.
20
20
  """
21
21
 
22
- from decimal import Decimal as dec
23
22
  import pathlib
24
23
  import re
25
24
  import statistics
26
25
  import sys
27
26
 
28
27
  import tablib
29
- from PyQt5.QtCore import Qt
30
- from PyQt5.QtGui import QIcon
31
- from PyQt5.QtWidgets import (
28
+ from PySide6.QtCore import Qt
29
+ from PySide6.QtGui import QIcon
30
+ from PySide6.QtWidgets import (
32
31
  QDialog,
33
32
  QFileDialog,
34
33
  QHBoxLayout,
@@ -156,7 +155,7 @@ class Advanced_event_filtering_dialog(QDialog):
156
155
  hbox.addItem(QSpacerItem(241, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
157
156
  self.pb_save = QPushButton("Save results", clicked=self.save_results)
158
157
  hbox.addWidget(self.pb_save)
159
- self.pb_close = QPushButton("Close", clicked=self.close)
158
+ self.pb_close = QPushButton(cfg.CLOSE, clicked=self.close)
160
159
  hbox.addWidget(self.pb_close)
161
160
  vbox.addLayout(hbox)
162
161
 
@@ -190,7 +189,6 @@ class Advanced_event_filtering_dialog(QDialog):
190
189
  add selected logic operaton to lineedit
191
190
  """
192
191
  if self.lw3.currentItem():
193
-
194
192
  text = ""
195
193
  if self.lw3.currentItem().text() == "AND":
196
194
  text = " & "
@@ -208,7 +206,7 @@ class Advanced_event_filtering_dialog(QDialog):
208
206
  if not self.logic.text():
209
207
  return
210
208
  if self.logic.text().count('"') % 2:
211
- QMessageBox.warning(self, cfg.programName, f'Wrong number of double quotes (")')
209
+ QMessageBox.warning(self, cfg.programName, 'Wrong number of double quotes (")')
212
210
  return
213
211
 
214
212
  sb_list = re.findall('"([^"]*)"', self.logic.text())
@@ -237,15 +235,13 @@ class Advanced_event_filtering_dialog(QDialog):
237
235
  self.tw.clear()
238
236
 
239
237
  if flag_error or self.rb_details.isChecked():
240
-
241
- self.lb_results.setText(f"Results ({len(self.out)} event{'s'*(len(self.out) > 1)})")
238
+ self.lb_results.setText(f"Results ({len(self.out)} event{'s' * (len(self.out) > 1)})")
242
239
 
243
240
  self.tw.setRowCount(len(self.out))
244
241
  self.tw.setColumnCount(len(self.details_header)) # obs_id, comment, start, stop, duration
245
242
  self.tw.setHorizontalHeaderLabels(self.details_header)
246
243
 
247
244
  if not flag_error and self.rb_summary.isChecked():
248
-
249
245
  summary = {}
250
246
  for row in self.out:
251
247
  obs_id, _, start, stop, duration = row
@@ -255,7 +251,6 @@ class Advanced_event_filtering_dialog(QDialog):
255
251
 
256
252
  self.out = []
257
253
  for obs_id in summary:
258
-
259
254
  self.out.append(
260
255
  [
261
256
  obs_id,
@@ -266,7 +261,7 @@ class Advanced_event_filtering_dialog(QDialog):
266
261
  ]
267
262
  )
268
263
 
269
- self.lb_results.setText(f"Results ({len(summary)} observation{'s'*(len(summary) > 1)})")
264
+ self.lb_results.setText(f"Results ({len(summary)} observation{'s' * (len(summary) > 1)})")
270
265
  self.tw.setRowCount(len(summary))
271
266
  self.tw.setColumnCount(len(self.summary_header)) # obs_id, mean, stdev
272
267
  self.tw.setHorizontalHeaderLabels(self.summary_header)
@@ -303,9 +298,7 @@ class Advanced_event_filtering_dialog(QDialog):
303
298
  # check if file with new extension already exists
304
299
  if pathlib.Path(file_name).is_file():
305
300
  if (
306
- dialog.MessageDialog(
307
- cfg.programName, f"The file {file_name} already exists.", [cfg.CANCEL, cfg.OVERWRITE]
308
- )
301
+ dialog.MessageDialog(cfg.programName, f"The file {file_name} already exists.", [cfg.CANCEL, cfg.OVERWRITE])
309
302
  == cfg.CANCEL
310
303
  ):
311
304
  return
@@ -357,22 +350,27 @@ def event_filtering(self):
357
350
  )
358
351
  return
359
352
 
360
- max_media_duration_all_obs, _ = observation_operations.media_duration(
361
- self.pj[cfg.OBSERVATIONS], selected_observations
362
- )
353
+ max_media_duration_all_obs, _ = observation_operations.media_duration(self.pj[cfg.OBSERVATIONS], selected_observations)
354
+
355
+ start_interval, end_interval = observation_operations.time_intervals_range(self.pj[cfg.OBSERVATIONS], selected_observations)
363
356
 
364
357
  parameters = select_subj_behav.choose_obs_subj_behav_category(
365
358
  self,
366
359
  selected_observations,
367
360
  start_coding=start_coding,
368
361
  end_coding=end_coding,
362
+ # start_interval=start_interval,
363
+ # end_interval=end_interval,
364
+ start_interval=None,
365
+ end_interval=None,
369
366
  maxTime=max_media_duration_all_obs,
370
- flagShowIncludeModifiers=False,
371
- flagShowExcludeBehaviorsWoEvents=False,
367
+ show_include_modifiers=False,
368
+ show_exclude_non_coded_behaviors=False,
372
369
  by_category=False,
373
370
  n_observations=len(selected_observations),
374
371
  )
375
- if parameters == {}:
372
+
373
+ if not parameters:
376
374
  return
377
375
 
378
376
  if not parameters[cfg.SELECTED_SUBJECTS] or not parameters[cfg.SELECTED_BEHAVIORS]:
@@ -389,7 +387,7 @@ def event_filtering(self):
389
387
  cursor.execute("SELECT MIN(start), MAX(stop) FROM aggregated_events")
390
388
  min_time, max_time = cursor.fetchone()
391
389
 
392
- if parameters[cfg.TIME_INTERVAL] == cfg.TIME_ARBITRARY_INTERVAL:
390
+ if parameters[cfg.TIME_INTERVAL] in (cfg.TIME_ARBITRARY_INTERVAL, cfg.TIME_OBS_INTERVAL):
393
391
  min_time = float(parameters[cfg.START_TIME])
394
392
  max_time = float(parameters[cfg.END_TIME])
395
393
 
@@ -438,7 +436,7 @@ def event_filtering(self):
438
436
  for row in cursor.fetchall():
439
437
  obs, subj, behav, start, stop = row
440
438
  if obs not in events:
441
- events[obs]: dict = {}
439
+ events[obs] = {}
442
440
 
443
441
  # use function in base at event (state or point)
444
442
  interval_func = icc if start == stop else ico
@@ -452,10 +450,6 @@ def event_filtering(self):
452
450
 
453
451
  w = Advanced_event_filtering_dialog(events)
454
452
  w.lb_time_interval.setText(
455
- (
456
- f"Time interval: "
457
- f"{util.dynamic_time_format(min_time, cfg.DYNAMIC_TIME_CUTOFF_DEFAULT, self.timeFormat)} - "
458
- f"{util.dynamic_time_format(max_time, cfg.DYNAMIC_TIME_CUTOFF_DEFAULT, self.timeFormat)}"
459
- )
453
+ (f"Time interval: {util.smart_time_format(min_time, self.timeFormat)} - {util.smart_time_format(max_time, self.timeFormat)}")
460
454
  )
461
455
  w.exec_()
File without changes
@@ -0,0 +1,59 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ number of occurences of behaviors
5
+ """
6
+
7
+ import pandas as pd
8
+
9
+ __version__ = "0.0.1"
10
+ __version_date__ = "2025-04-10"
11
+ __plugin_name__ = "Behavior latencyxxx"
12
+ __author__ = "Olivier Friard - University of Torino - Italy"
13
+
14
+
15
+ import itertools
16
+
17
+
18
+ def run(df: pd.DataFrame):
19
+ """
20
+ Latency of a behavior after another.
21
+ """
22
+
23
+ df["start_time"] = pd.to_datetime(df["Start (s)"])
24
+ df["end_time"] = pd.to_datetime(df["Stop (s)"])
25
+
26
+ latency_by_subject: dict = {}
27
+
28
+ for subject, group in df.groupby("subject"):
29
+ behaviors = group["behavior"].tolist()
30
+ # combinations = []
31
+ # Utiliser itertools pour créer des combinaisons 2 à 2 des comportements
32
+ for comb in itertools.combinations(behaviors, 2):
33
+ # combinations.append(comb)
34
+
35
+ last_A_end_time = None
36
+
37
+ # Liste pour stocker les latences de chaque sujet
38
+ subject_latency = []
39
+
40
+ for index, row in group.iterrows():
41
+ if row["behavior"] == comb[0]:
42
+ # Si on rencontre un comportement A, on réinitialise le temps de fin du comportement A
43
+ last_A_end_time = row["end_time"]
44
+ subject_latency.append(None) # Pas de latence pour A
45
+ elif row["behavior"] == comb[1] and last_A_end_time is not None:
46
+ # Si on rencontre un comportement B et qu'on a déjà vu un A avant
47
+ latency_time = row["start_time"] - last_A_end_time
48
+ subject_latency.append(latency_time)
49
+ else:
50
+ # Si on rencontre un B mais sans A avant
51
+ subject_latency.append(None)
52
+
53
+ # Ajout des latences calculées au DataFrame
54
+ df.loc[group.index, f"latency {comb[1]} after {comb[0]}"] = subject_latency
55
+
56
+ # Calcul de la latence totale ou moyenne par sujet
57
+ latency_by_subject[(subject, comb)] = df.groupby("subject")["latency"].agg(["sum", "mean"])
58
+
59
+ return str(latency_by_subject)