boris-behav-obs 8.27.10__tar.gz → 9.0.1__tar.gz

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 (148) hide show
  1. {boris_behav_obs-8.27.10/boris_behav_obs.egg-info → boris_behav_obs-9.0.1}/PKG-INFO +4 -3
  2. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/about.py +7 -5
  3. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/add_modifier.py +35 -35
  4. boris_behav_obs-9.0.1/boris/add_modifier_ui.py +285 -0
  5. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/advanced_event_filtering.py +3 -3
  6. boris_behav_obs-9.0.1/boris/analysis_plugins/__init__.py +0 -0
  7. boris_behav_obs-9.0.1/boris/analysis_plugins/number_of_occurences.py +60 -0
  8. boris_behav_obs-9.0.1/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +72 -0
  9. boris_behav_obs-9.0.1/boris/analysis_plugins/time_budget.py +95 -0
  10. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/behav_coding_map_creator.py +103 -108
  11. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/behavior_binary_table.py +1 -1
  12. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/behaviors_coding_map.py +8 -8
  13. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/coding_pad.py +6 -6
  14. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/config.py +6 -0
  15. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/config_file.py +1 -1
  16. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/connections.py +4 -2
  17. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/converters.py +2 -3
  18. boris_behav_obs-9.0.1/boris/converters_ui.py +225 -0
  19. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/cooccurence.py +2 -2
  20. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/core.py +340 -94
  21. boris_behav_obs-9.0.1/boris/core_qrc.py +16159 -0
  22. boris_behav_obs-9.0.1/boris/core_ui.py +1095 -0
  23. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/dialog.py +14 -13
  24. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/duration_widget.py +5 -5
  25. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/edit_event.py +1 -1
  26. boris_behav_obs-9.0.1/boris/edit_event_ui.py +200 -0
  27. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/event_operations.py +4 -25
  28. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/events_cursor.py +17 -9
  29. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/events_snapshots.py +5 -5
  30. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/exclusion_matrix.py +1 -1
  31. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/export_events.py +38 -28
  32. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/export_observation.py +1 -1
  33. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/external_processes.py +3 -5
  34. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/geometric_measurement.py +49 -26
  35. boris_behav_obs-9.0.1/boris/gui_utilities.py +102 -0
  36. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/import_observations.py +2 -4
  37. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/irr.py +1 -1
  38. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/latency.py +1 -1
  39. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/map_creator.py +77 -89
  40. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/measurement_widget.py +4 -4
  41. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/media_file.py +2 -4
  42. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/menu_options.py +1 -3
  43. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/modifiers_coding_map.py +4 -4
  44. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/mpv2.py +0 -2
  45. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/observation.py +124 -29
  46. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/observation_operations.py +18 -40
  47. boris_behav_obs-9.0.1/boris/observation_ui.py +679 -0
  48. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/observations_list.py +6 -6
  49. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/param_panel.py +2 -2
  50. boris_behav_obs-9.0.1/boris/param_panel_ui.py +299 -0
  51. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/player_dock_widget.py +16 -21
  52. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/plot_data_module.py +6 -6
  53. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/plot_events_rt.py +7 -8
  54. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/plot_spectrogram_rt.py +7 -8
  55. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/plot_waveform_rt.py +6 -7
  56. boris_behav_obs-9.0.1/boris/plugins.py +79 -0
  57. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/preferences.py +127 -17
  58. boris_behav_obs-9.0.1/boris/preferences_ui.py +562 -0
  59. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/project.py +69 -72
  60. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/project_functions.py +233 -31
  61. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/project_import_export.py +59 -67
  62. boris_behav_obs-9.0.1/boris/project_ui.py +794 -0
  63. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/qrc_boris.py +6 -3
  64. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/qrc_boris5.py +6 -3
  65. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/select_modifiers.py +2 -2
  66. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/select_observations.py +2 -2
  67. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/select_subj_behav.py +3 -3
  68. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/state_events.py +1 -1
  69. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/subjects_pad.py +5 -5
  70. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/synthetic_time_budget.py +2 -2
  71. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/time_budget_functions.py +15 -0
  72. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/time_budget_widget.py +4 -4
  73. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/transitions.py +34 -25
  74. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/utilities.py +95 -2
  75. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/version.py +2 -2
  76. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/video_equalizer.py +4 -4
  77. boris_behav_obs-9.0.1/boris/video_equalizer_ui.py +248 -0
  78. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/video_operations.py +1 -1
  79. boris_behav_obs-9.0.1/boris/view_df.py +106 -0
  80. boris_behav_obs-9.0.1/boris/view_df_ui.py +75 -0
  81. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/write_event.py +9 -1
  82. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1/boris_behav_obs.egg-info}/PKG-INFO +4 -3
  83. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris_behav_obs.egg-info/SOURCES.txt +7 -18
  84. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris_behav_obs.egg-info/requires.txt +2 -1
  85. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/pyproject.toml +4 -3
  86. boris_behav_obs-8.27.10/boris/add_modifier_ui.py +0 -185
  87. boris_behav_obs-8.27.10/boris/converters_ui.py +0 -148
  88. boris_behav_obs-8.27.10/boris/core_qrc.py +0 -13317
  89. boris_behav_obs-8.27.10/boris/core_ui.py +0 -985
  90. boris_behav_obs-8.27.10/boris/edit_event_ui.py +0 -126
  91. boris_behav_obs-8.27.10/boris/gui_utilities.py +0 -101
  92. boris_behav_obs-8.27.10/boris/observation_ui.py +0 -487
  93. boris_behav_obs-8.27.10/boris/param_panel_ui.py +0 -194
  94. boris_behav_obs-8.27.10/boris/preferences_ui.py +0 -338
  95. boris_behav_obs-8.27.10/boris/project_ui.py +0 -562
  96. boris_behav_obs-8.27.10/boris/qdarkstyle/__init__.py +0 -479
  97. boris_behav_obs-8.27.10/boris/qdarkstyle/__main__.py +0 -66
  98. boris_behav_obs-8.27.10/boris/qdarkstyle/colorsystem.py +0 -38
  99. boris_behav_obs-8.27.10/boris/qdarkstyle/dark/__init__.py +0 -1
  100. boris_behav_obs-8.27.10/boris/qdarkstyle/dark/darkstyle_rc.py +0 -11379
  101. boris_behav_obs-8.27.10/boris/qdarkstyle/dark/palette.py +0 -38
  102. boris_behav_obs-8.27.10/boris/qdarkstyle/example/__init__.py +0 -4
  103. boris_behav_obs-8.27.10/boris/qdarkstyle/example/__main__.py +0 -386
  104. boris_behav_obs-8.27.10/boris/qdarkstyle/example/ui/__init__.py +0 -4
  105. boris_behav_obs-8.27.10/boris/qdarkstyle/light/__init__.py +0 -1
  106. boris_behav_obs-8.27.10/boris/qdarkstyle/light/lightstyle_rc.py +0 -11305
  107. boris_behav_obs-8.27.10/boris/qdarkstyle/light/palette.py +0 -37
  108. boris_behav_obs-8.27.10/boris/qdarkstyle/palette.py +0 -102
  109. boris_behav_obs-8.27.10/boris/qdarkstyle/utils/__init__.py +0 -73
  110. boris_behav_obs-8.27.10/boris/qdarkstyle/utils/__main__.py +0 -96
  111. boris_behav_obs-8.27.10/boris/qdarkstyle/utils/images.py +0 -449
  112. boris_behav_obs-8.27.10/boris/qdarkstyle/utils/scss.py +0 -318
  113. boris_behav_obs-8.27.10/boris/video_equalizer_ui.py +0 -179
  114. boris_behav_obs-8.27.10/boris/vlc_local.py +0 -83
  115. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/LICENSE.TXT +0 -0
  116. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/MANIFEST.in +0 -0
  117. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/README.TXT +0 -0
  118. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/README.md +0 -0
  119. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/__init__.py +0 -0
  120. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/__main__.py +0 -0
  121. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/boris_cli.py +0 -0
  122. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/cmd_arguments.py +0 -0
  123. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/db_functions.py +0 -0
  124. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/dev.py +0 -0
  125. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/image_overlay.py +0 -0
  126. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/mpv-1.0.3.py +0 -0
  127. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/mpv.py +0 -0
  128. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/otx_parser.py +0 -0
  129. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/plot_events.py +0 -0
  130. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/portion/__init__.py +0 -0
  131. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/portion/const.py +0 -0
  132. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/portion/dict.py +0 -0
  133. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/portion/func.py +0 -0
  134. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/portion/interval.py +0 -0
  135. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris/portion/io.py +0 -0
  136. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
  137. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris_behav_obs.egg-info/entry_points.txt +0 -0
  138. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/boris_behav_obs.egg-info/top_level.txt +0 -0
  139. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/setup.cfg +0 -0
  140. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_db_functions.py +0 -0
  141. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_export_observation.py +0 -0
  142. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_irr.py +0 -0
  143. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_observation_gui.py +0 -0
  144. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_otx_parser.py +0 -0
  145. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_preferences_gui.py +0 -0
  146. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_project_functions.py +0 -0
  147. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_time_budget.py +0 -0
  148. {boris_behav_obs-8.27.10 → boris_behav_obs-9.0.1}/tests/test_utilities.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: boris-behav-obs
3
- Version: 8.27.10
3
+ Version: 9.0.1
4
4
  Summary: BORIS - Behavioral Observation Research Interactive Software
5
5
  Author-email: Olivier Friard <olivier.friard@unito.it>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -701,8 +701,9 @@ Requires-Dist: numpy>=1.26.4
701
701
  Requires-Dist: matplotlib>=3.3.3
702
702
  Requires-Dist: pandas>=2.2.2
703
703
  Requires-Dist: tablib[cli,html,ods,pandas,xls,xlsx]>=3
704
- Requires-Dist: pyqt5>=5.15
705
704
  Requires-Dist: pyreadr
705
+ Requires-Dist: pyside6==6.8.0.2
706
+ Requires-Dist: hachoir>=3.3.0
706
707
  Provides-Extra: dev
707
708
  Requires-Dist: black; extra == "dev"
708
709
  Requires-Dist: ruff; extra == "dev"
@@ -31,9 +31,9 @@ from . import config as cfg
31
31
  from . import utilities as util
32
32
 
33
33
 
34
- from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
35
- from PyQt5.QtGui import QPixmap
36
- from PyQt5.QtWidgets import QMessageBox
34
+ from PySide6.QtCore import qVersion
35
+ from PySide6.QtGui import QPixmap
36
+ from PySide6.QtWidgets import QMessageBox
37
37
 
38
38
 
39
39
  def actionAbout_activated(self):
@@ -41,6 +41,8 @@ def actionAbout_activated(self):
41
41
  About dialog
42
42
  """
43
43
 
44
+ import PySide6
45
+
44
46
  programs_versions: list = ["MPV media player"]
45
47
 
46
48
  mpv_lib_version, mpv_lib_file_path, mpv_api_version = util.mpv_lib_version()
@@ -112,7 +114,7 @@ def actionAbout_activated(self):
112
114
  f"Operating system: {current_system.system} {current_system.release} {current_system.version} \n"
113
115
  f"CPU: {current_system.machine} {current_system.processor}\n\n"
114
116
  f"Python {platform.python_version()} ({'64-bit' if sys.maxsize > 2**32 else '32-bit'})"
115
- f" - Qt {QT_VERSION_STR} - PyQt {PYQT_VERSION_STR}\n\n"
117
+ f"Qt {qVersion()} - PySide {PySide6.__version__}\n"
116
118
  )
117
119
 
118
120
  r, memory = util.mem_info()
@@ -137,4 +139,4 @@ def actionAbout_activated(self):
137
139
 
138
140
  about_dialog.setDetailedText(details)
139
141
 
140
- _ = about_dialog.exec_()
142
+ _ = about_dialog.exec()
@@ -16,15 +16,15 @@ This file is part of BORIS.
16
16
  GNU General Public License for more details.
17
17
 
18
18
  You should have received a copy of the GNU General Public License
19
- along with this program; if not see <http://www.gnu.org/licenses/>.
19
+ along with this program; if not see <http://www.gnu.org/licPbehav_enses/>.
20
20
 
21
21
  """
22
22
 
23
23
  import logging
24
24
  import json
25
25
 
26
- from PyQt5.QtGui import QIcon
27
- from PyQt5.QtWidgets import QDialog, QWidget, QFileDialog, QMessageBox
26
+ from PySide6.QtGui import QIcon
27
+ from PySide6.QtWidgets import QDialog, QWidget, QFileDialog, QMessageBox
28
28
 
29
29
  from . import dialog
30
30
  from .add_modifier_ui import Ui_Dialog
@@ -158,38 +158,38 @@ class addModifierDialog(QDialog, Ui_Dialog):
158
158
  add modifiers from file
159
159
  """
160
160
 
161
- fn = QFileDialog().getOpenFileName(self, "Load modifiers from file", "", "All files (*)")
162
- file_name = fn[0] if type(fn) is tuple else fn
163
- if file_name:
164
- try:
165
- with open(file_name) as f_in:
166
- for line in f_in:
167
- if line.strip():
168
- for c in cfg.CHAR_FORBIDDEN_IN_MODIFIERS:
169
- if c in line.strip():
170
- QMessageBox.critical(
171
- self,
172
- cfg.programName,
173
- (
174
- f"The character <b>{c}</b> is not allowed.<br>"
175
- "The following characters are not allowed in modifiers:<br>"
176
- f"<b>{cfg.CHAR_FORBIDDEN_IN_MODIFIERS}</b>"
177
- ),
178
- )
179
- break
180
- else:
181
- if line.strip() not in [self.lwModifiers.item(x).text() for x in range(self.lwModifiers.count())]:
182
- if self.itemPositionMem != -1:
183
- self.lwModifiers.insertItem(self.itemPositionMem, line.strip())
184
- else:
185
- self.lwModifiers.addItem(line.strip())
186
-
187
- self.modifiers_sets_dict[str(self.tabWidgetModifiersSets.currentIndex())]["values"] = [
188
- self.lwModifiers.item(x).text() for x in range(self.lwModifiers.count())
189
- ]
190
- except Exception:
191
- QMessageBox.warning(self, cfg.programName, f"Error reading modifiers from file:<br>{file_name}")
192
- logging.warning(f"Error reading modifiers from file<br>{file_name}")
161
+ file_name, _ = QFileDialog.getOpenFileName(self, "Load modifiers from file", "", "All files (*)")
162
+ if not file_name:
163
+ return
164
+ try:
165
+ with open(file_name) as f_in:
166
+ for line in f_in:
167
+ if line.strip():
168
+ for c in cfg.CHAR_FORBIDDEN_IN_MODIFIERS:
169
+ if c in line.strip():
170
+ QMessageBox.critical(
171
+ self,
172
+ cfg.programName,
173
+ (
174
+ f"The character <b>{c}</b> is not allowed.<br>"
175
+ "The following characters are not allowed in modifiers:<br>"
176
+ f"<b>{cfg.CHAR_FORBIDDEN_IN_MODIFIERS}</b>"
177
+ ),
178
+ )
179
+ break
180
+ else:
181
+ if line.strip() not in [self.lwModifiers.item(x).text() for x in range(self.lwModifiers.count())]:
182
+ if self.itemPositionMem != -1:
183
+ self.lwModifiers.insertItem(self.itemPositionMem, line.strip())
184
+ else:
185
+ self.lwModifiers.addItem(line.strip())
186
+
187
+ self.modifiers_sets_dict[str(self.tabWidgetModifiersSets.currentIndex())]["values"] = [
188
+ self.lwModifiers.item(x).text() for x in range(self.lwModifiers.count())
189
+ ]
190
+ except Exception:
191
+ QMessageBox.warning(self, cfg.programName, f"Error reading modifiers from file:<br>{file_name}")
192
+ logging.warning(f"Error reading modifiers from file<br>{file_name}")
193
193
 
194
194
  def sort_modifiers(self):
195
195
  """
@@ -0,0 +1,285 @@
1
+ # -*- coding: utf-8 -*-
2
+
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
+ ################################################################################
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)
22
+
23
+ class Ui_Dialog(object):
24
+ def setupUi(self, Dialog):
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
+
44
+ self.verticalLayout_2.addWidget(self.lbModifier)
45
+
46
+ self.leModifier = QLineEdit(Dialog)
47
+ self.leModifier.setObjectName(u"leModifier")
48
+
49
+ self.verticalLayout_2.addWidget(self.leModifier)
50
+
51
+ self.lbCode = QLabel(Dialog)
52
+ self.lbCode.setObjectName(u"lbCode")
53
+
54
+ self.verticalLayout_2.addWidget(self.lbCode)
55
+
56
+ self.leCode = QLineEdit(Dialog)
57
+ self.leCode.setObjectName(u"leCode")
58
+
59
+ self.verticalLayout_2.addWidget(self.leCode)
60
+
61
+ self.lbCodeHelp = QLabel(Dialog)
62
+ self.lbCodeHelp.setObjectName(u"lbCodeHelp")
63
+ self.lbCodeHelp.setWordWrap(True)
64
+
65
+ self.verticalLayout_2.addWidget(self.lbCodeHelp)
66
+
67
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
68
+
69
+ self.verticalLayout_2.addItem(self.verticalSpacer)
70
+
71
+
72
+ self.horizontalLayout_5.addLayout(self.verticalLayout_2)
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
+
79
+ self.verticalLayout_3.addWidget(self.pbAddModifier)
80
+
81
+ self.pbModifyModifier = QPushButton(Dialog)
82
+ self.pbModifyModifier.setObjectName(u"pbModifyModifier")
83
+
84
+ self.verticalLayout_3.addWidget(self.pbModifyModifier)
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
+
91
+ self.horizontalLayout_5.addLayout(self.verticalLayout_3)
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.North)
99
+ self.tabWidgetModifiersSets.setTabShape(QTabWidget.Rounded)
100
+ self.tabWidgetModifiersSets.setElideMode(Qt.ElideNone)
101
+ self.tabWidgetModifiersSets.setDocumentMode(True)
102
+
103
+ self.verticalLayout.addWidget(self.tabWidgetModifiersSets)
104
+
105
+ self.lb_name = QLabel(Dialog)
106
+ self.lb_name.setObjectName(u"lb_name")
107
+
108
+ self.verticalLayout.addWidget(self.lb_name)
109
+
110
+ self.le_name = QLineEdit(Dialog)
111
+ self.le_name.setObjectName(u"le_name")
112
+
113
+ self.verticalLayout.addWidget(self.le_name)
114
+
115
+ self.lb_description = QLabel(Dialog)
116
+ self.lb_description.setObjectName(u"lb_description")
117
+
118
+ self.verticalLayout.addWidget(self.lb_description)
119
+
120
+ self.le_description = QLineEdit(Dialog)
121
+ self.le_description.setObjectName(u"le_description")
122
+
123
+ self.verticalLayout.addWidget(self.le_description)
124
+
125
+ self.lbType = QLabel(Dialog)
126
+ self.lbType.setObjectName(u"lbType")
127
+
128
+ self.verticalLayout.addWidget(self.lbType)
129
+
130
+ self.cbType = QComboBox(Dialog)
131
+ self.cbType.addItem("")
132
+ self.cbType.addItem("")
133
+ self.cbType.addItem("")
134
+ self.cbType.addItem("")
135
+ self.cbType.setObjectName(u"cbType")
136
+
137
+ self.verticalLayout.addWidget(self.cbType)
138
+
139
+ self.lbValues = QLabel(Dialog)
140
+ self.lbValues.setObjectName(u"lbValues")
141
+
142
+ self.verticalLayout.addWidget(self.lbValues)
143
+
144
+ self.lwModifiers = QListWidget(Dialog)
145
+ self.lwModifiers.setObjectName(u"lwModifiers")
146
+
147
+ self.verticalLayout.addWidget(self.lwModifiers)
148
+
149
+ self.horizontalLayout = QHBoxLayout()
150
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
151
+ self.pbMoveUp = QPushButton(Dialog)
152
+ self.pbMoveUp.setObjectName(u"pbMoveUp")
153
+
154
+ self.horizontalLayout.addWidget(self.pbMoveUp)
155
+
156
+ self.pbMoveDown = QPushButton(Dialog)
157
+ self.pbMoveDown.setObjectName(u"pbMoveDown")
158
+
159
+ self.horizontalLayout.addWidget(self.pbMoveDown)
160
+
161
+ self.pbRemoveModifier = QPushButton(Dialog)
162
+ self.pbRemoveModifier.setObjectName(u"pbRemoveModifier")
163
+
164
+ self.horizontalLayout.addWidget(self.pbRemoveModifier)
165
+
166
+
167
+ self.verticalLayout.addLayout(self.horizontalLayout)
168
+
169
+ self.pb_sort_modifiers = QPushButton(Dialog)
170
+ self.pb_sort_modifiers.setObjectName(u"pb_sort_modifiers")
171
+
172
+ self.verticalLayout.addWidget(self.pb_sort_modifiers)
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
+
179
+ self.horizontalLayout_3.addWidget(self.pbAddSet)
180
+
181
+ self.pbRemoveSet = QPushButton(Dialog)
182
+ self.pbRemoveSet.setObjectName(u"pbRemoveSet")
183
+
184
+ self.horizontalLayout_3.addWidget(self.pbRemoveSet)
185
+
186
+
187
+ self.verticalLayout.addLayout(self.horizontalLayout_3)
188
+
189
+ self.horizontalLayout_4 = QHBoxLayout()
190
+ self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
191
+ self.pbMoveSetLeft = QPushButton(Dialog)
192
+ self.pbMoveSetLeft.setObjectName(u"pbMoveSetLeft")
193
+
194
+ self.horizontalLayout_4.addWidget(self.pbMoveSetLeft)
195
+
196
+ self.pbMoveSetRight = QPushButton(Dialog)
197
+ self.pbMoveSetRight.setObjectName(u"pbMoveSetRight")
198
+
199
+ self.horizontalLayout_4.addWidget(self.pbMoveSetRight)
200
+
201
+
202
+ self.verticalLayout.addLayout(self.horizontalLayout_4)
203
+
204
+ self.pb_add_subjects = QPushButton(Dialog)
205
+ self.pb_add_subjects.setObjectName(u"pb_add_subjects")
206
+
207
+ self.verticalLayout.addWidget(self.pb_add_subjects)
208
+
209
+ self.pb_load_file = QPushButton(Dialog)
210
+ self.pb_load_file.setObjectName(u"pb_load_file")
211
+
212
+ self.verticalLayout.addWidget(self.pb_load_file)
213
+
214
+ self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
215
+
216
+ self.verticalLayout.addItem(self.verticalSpacer_3)
217
+
218
+
219
+ self.horizontalLayout_5.addLayout(self.verticalLayout)
220
+
221
+
222
+ self.verticalLayout_4.addLayout(self.horizontalLayout_5)
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
+
233
+ self.horizontalLayout_2.addWidget(self.pbCancel)
234
+
235
+ self.pbOK = QPushButton(Dialog)
236
+ self.pbOK.setObjectName(u"pbOK")
237
+
238
+ self.horizontalLayout_2.addWidget(self.pbOK)
239
+
240
+
241
+ self.verticalLayout_4.addLayout(self.horizontalLayout_2)
242
+
243
+
244
+ self.verticalLayout_5.addLayout(self.verticalLayout_4)
245
+
246
+
247
+ self.retranslateUi(Dialog)
248
+
249
+ self.tabWidgetModifiersSets.setCurrentIndex(-1)
250
+
251
+
252
+ QMetaObject.connectSlotsByName(Dialog)
253
+ # setupUi
254
+
255
+ def retranslateUi(self, Dialog):
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("")
262
+ self.pbModifyModifier.setText("")
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.pbRemoveModifier.setText(QCoreApplication.translate("Dialog", u"Remove modifier", None))
275
+ self.pb_sort_modifiers.setText(QCoreApplication.translate("Dialog", u"Sort modifiers", None))
276
+ self.pbAddSet.setText(QCoreApplication.translate("Dialog", u"Add set of modifiers", None))
277
+ self.pbRemoveSet.setText(QCoreApplication.translate("Dialog", u"Remove set of modifiers", None))
278
+ self.pbMoveSetLeft.setText(QCoreApplication.translate("Dialog", u"Move set left", None))
279
+ self.pbMoveSetRight.setText(QCoreApplication.translate("Dialog", u"Move set right", 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
+
@@ -25,9 +25,9 @@ import statistics
25
25
  import sys
26
26
 
27
27
  import tablib
28
- from PyQt5.QtCore import Qt
29
- from PyQt5.QtGui import QIcon
30
- from PyQt5.QtWidgets import (
28
+ from PySide6.QtCore import Qt
29
+ from PySide6.QtGui import QIcon
30
+ from PySide6.QtWidgets import (
31
31
  QDialog,
32
32
  QFileDialog,
33
33
  QHBoxLayout,
@@ -0,0 +1,60 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ number of occurences of behaviors
5
+ """
6
+
7
+ import pandas as pd
8
+
9
+ __version__ = "0.1.0"
10
+ __version_date__ = "2024-11-14"
11
+ __plugin_name__ = "Number of occurences of behaviors"
12
+ __author__ = "Olivier Friard - University of Torino - Italy"
13
+
14
+
15
+ def run(df: pd.DataFrame):
16
+ """
17
+ Calculate the number of occurrences of behaviors by subject.
18
+ """
19
+
20
+ return df.groupby(["Subject", "Behavior"])["Behavior"].count().reset_index(name="number of occurences")
21
+
22
+
23
+ def main(df: pd.DataFrame, observations_list: list = [], parameters: dict = {}) -> pd.DataFrame:
24
+ """
25
+ filter by selected observations.
26
+ filter by selected subjects.
27
+ filter by selected behaviors.
28
+ filter by time interval.
29
+ """
30
+
31
+ # filter selected observations
32
+ if observations_list:
33
+ df = df[df["Observation id"].isin(observations_list)]
34
+
35
+ if parameters:
36
+ # filter selected subjects
37
+ df = df[df["Subject"].isin(parameters["selected subjects"])]
38
+
39
+ # filter selected behaviors
40
+ df = df[df["Behavior"].isin(parameters["selected behaviors"])]
41
+
42
+ # filter selected time interval
43
+ if parameters["start time"] is not None and parameters["end time"] is not None:
44
+ MIN_TIME = parameters["start time"]
45
+ MAX_TIME = parameters["end time"]
46
+ df_interval = df[
47
+ (
48
+ ((df["Start (s)"] >= MIN_TIME) & (df["Start (s)"] <= MAX_TIME))
49
+ | ((df["Stop (s)"] >= MIN_TIME) & (df["Stop (s)"] <= MAX_TIME))
50
+ )
51
+ | ((df["Start (s)"] < MIN_TIME) & (df["Stop (s)"] > MAX_TIME))
52
+ ]
53
+ df_interval.loc[df["Start (s)"] < MIN_TIME, "Start (s)"] = MIN_TIME
54
+ df_interval.loc[df["Stop (s)"] > MAX_TIME, "Stop (s)"] = MAX_TIME
55
+
56
+ df_interval.loc[:, "Duration (s)"] = df_interval["Stop (s)"] - df_interval["Start (s)"]
57
+
58
+ df = df_interval
59
+
60
+ return run(df)
@@ -0,0 +1,72 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ number of occurences of behaviors by independent_variable
5
+ """
6
+
7
+ import pandas as pd
8
+
9
+ __version__ = "0.1.0"
10
+ __version_date__ = "2024-11-14"
11
+ __plugin_name__ = "Number of occurences of behaviors by subject by independent_variable"
12
+ __author__ = "Olivier Friard - University of Torino - Italy"
13
+
14
+
15
+ def run(df: pd.DataFrame):
16
+ """
17
+ Calculate the number of occurrences of behaviors by subject and by independent_variable.
18
+ """
19
+
20
+ results = (
21
+ df.groupby(
22
+ [
23
+ "independent variable 'Weather'",
24
+ "Subject",
25
+ "Behavior",
26
+ ]
27
+ )["Behavior"]
28
+ .count()
29
+ .reset_index(name="number of occurences")
30
+ )
31
+
32
+ return results
33
+
34
+
35
+ def main(df: pd.DataFrame, observations_list: list = [], parameters: dict = {}) -> pd.DataFrame:
36
+ """
37
+ filter by selected observations.
38
+ filter by selected subjects.
39
+ filter by selected behaviors.
40
+ filter by time interval.
41
+ """
42
+
43
+ # filter selected observations
44
+ if observations_list:
45
+ df = df[df["Observation id"].isin(observations_list)]
46
+
47
+ if parameters:
48
+ # filter selected subjects
49
+ df = df[df["Subject"].isin(parameters["selected subjects"])]
50
+
51
+ # filter selected behaviors
52
+ df = df[df["Behavior"].isin(parameters["selected behaviors"])]
53
+
54
+ # filter selected time interval
55
+ if parameters["start time"] is not None and parameters["end time"] is not None:
56
+ MIN_TIME = parameters["start time"]
57
+ MAX_TIME = parameters["end time"]
58
+ df_interval = df[
59
+ (
60
+ ((df["Start (s)"] >= MIN_TIME) & (df["Start (s)"] <= MAX_TIME))
61
+ | ((df["Stop (s)"] >= MIN_TIME) & (df["Stop (s)"] <= MAX_TIME))
62
+ )
63
+ | ((df["Start (s)"] < MIN_TIME) & (df["Stop (s)"] > MAX_TIME))
64
+ ]
65
+ df_interval.loc[df["Start (s)"] < MIN_TIME, "Start (s)"] = MIN_TIME
66
+ df_interval.loc[df["Stop (s)"] > MAX_TIME, "Stop (s)"] = MAX_TIME
67
+
68
+ df_interval.loc[:, "Duration (s)"] = df_interval["Stop (s)"] - df_interval["Start (s)"]
69
+
70
+ df = df_interval
71
+
72
+ return run(df)
@@ -0,0 +1,95 @@
1
+ """
2
+ BORIS plugin
3
+ """
4
+
5
+ import pandas as pd
6
+
7
+ __version__ = "0.1.0"
8
+ __version_date__ = "2024-11-14"
9
+ __plugin_name__ = "Time budget"
10
+ __author__ = "Olivier Friard - University of Torino - Italy"
11
+
12
+
13
+ def run(df: pd.DataFrame):
14
+ """
15
+ Calculate the following values:
16
+
17
+ - Total number of occurences of behavior
18
+ - Total duration of behavior (in seconds)
19
+ - Duration mean of behavior (in seconds)
20
+ - Standard deviation of behavior duration (in seconds)
21
+ - Inter-event intervals mean (in seconds)
22
+ - Inter-event intervals standard deviation (in seconds)
23
+ - % of total duration
24
+ """
25
+
26
+ dfs = [
27
+ df.groupby(["Subject", "Behavior"])["Behavior"].count().reset_index(name="number of occurences"),
28
+ df.groupby(["Subject", "Behavior"])["Duration (s)"].sum().reset_index(name="total duration"),
29
+ df.groupby(["Subject", "Behavior"])["Duration (s)"].mean().astype(float).round(3).reset_index(name="duration mean"),
30
+ df.groupby(["Subject", "Behavior"])["Duration (s)"].std().astype(float).round(3).reset_index(name="duration std dev"),
31
+ ]
32
+
33
+ # inter events
34
+ df2 = df.sort_values(by=["Observation id", "Subject", "Behavior", "Start (s)"])
35
+ df2["diff"] = df2.groupby(["Observation id", "Subject", "Behavior"])["Start (s)"].shift(periods=-1) - df2["Stop (s)"]
36
+
37
+ dfs.append(df2.groupby(["Subject", "Behavior"])["diff"].mean().astype(float).round(3).reset_index(name="inter-event intervals mean"))
38
+
39
+ dfs.append(df2.groupby(["Subject", "Behavior"])["diff"].std().astype(float).round(3).reset_index(name="inter-event intervals std dev"))
40
+
41
+ # % of time
42
+ dfs.append(
43
+ (100 * df.groupby(["Subject", "Behavior"])["Duration (s)"].sum() / df.groupby(["Subject"])["Duration (s)"].sum())
44
+ .astype(float)
45
+ .round(3)
46
+ .reset_index(name="% of total duration")
47
+ )
48
+
49
+ merged_df = dfs[0]
50
+ for df in dfs[1:]:
51
+ merged_df = pd.merge(merged_df, df, on=["Subject", "Behavior"])
52
+
53
+ return merged_df
54
+
55
+
56
+ def main(df: pd.DataFrame, observations_list: list = [], parameters: dict = {}) -> pd.DataFrame:
57
+ """
58
+ filter by selected observations.
59
+ filter by selected subjects.
60
+ filter by selected behaviors.
61
+ filter by time interval.
62
+ """
63
+
64
+ # filter selected observations
65
+ if observations_list:
66
+ df = df[df["Observation id"].isin(observations_list)]
67
+
68
+ if parameters:
69
+ # filter selected subjects
70
+ df = df[df["Subject"].isin(parameters["selected subjects"])]
71
+
72
+ # filter selected behaviors
73
+ df = df[df["Behavior"].isin(parameters["selected behaviors"])]
74
+
75
+ # filter selected time interval
76
+ if parameters["start time"] is not None and parameters["end time"] is not None:
77
+ MIN_TIME = parameters["start time"]
78
+ MAX_TIME = parameters["end time"]
79
+
80
+ df_interval = df[
81
+ (
82
+ ((df["Start (s)"] >= MIN_TIME) & (df["Start (s)"] <= MAX_TIME))
83
+ | ((df["Stop (s)"] >= MIN_TIME) & (df["Stop (s)"] <= MAX_TIME))
84
+ )
85
+ | ((df["Start (s)"] < MIN_TIME) & (df["Stop (s)"] > MAX_TIME))
86
+ ]
87
+
88
+ df_interval.loc[df["Start (s)"] < MIN_TIME, "Start (s)"] = MIN_TIME
89
+ df_interval.loc[df["Stop (s)"] > MAX_TIME, "Stop (s)"] = MAX_TIME
90
+
91
+ df_interval.loc[:, "Duration (s)"] = df_interval["Stop (s)"] - df_interval["Start (s)"]
92
+
93
+ df = df_interval
94
+
95
+ return run(df)