boris-behav-obs 9.7.12__py3-none-any.whl → 9.8.2__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 (84) hide show
  1. boris/__init__.py +1 -1
  2. boris/__main__.py +1 -1
  3. boris/about.py +4 -3
  4. boris/add_modifier.py +1 -1
  5. boris/advanced_event_filtering.py +1 -1
  6. boris/analysis_plugins/export_to_feral.py +336 -0
  7. boris/analysis_plugins/irr_weighted_cohen_kappa.py +2 -2
  8. boris/behav_coding_map_creator.py +1 -1
  9. boris/behavior_binary_table.py +1 -1
  10. boris/behaviors_coding_map.py +1 -1
  11. boris/boris_cli.py +1 -1
  12. boris/cmd_arguments.py +1 -1
  13. boris/coding_pad.py +1 -1
  14. boris/config.py +15 -3
  15. boris/config_file.py +18 -19
  16. boris/connections.py +12 -13
  17. boris/converters.py +1 -1
  18. boris/converters_ui.py +2 -3
  19. boris/cooccurence.py +1 -1
  20. boris/core.py +168 -166
  21. boris/core_qrc.py +1830 -1967
  22. boris/core_ui.py +1 -1
  23. boris/db_functions.py +5 -14
  24. boris/dialog.py +24 -24
  25. boris/edit_event.py +1 -1
  26. boris/event_operations.py +1 -1
  27. boris/events_cursor.py +1 -1
  28. boris/events_snapshots.py +133 -78
  29. boris/exclusion_matrix.py +1 -1
  30. boris/export_events.py +49 -43
  31. boris/export_observation.py +1 -1
  32. boris/external_processes.py +1 -1
  33. boris/geometric_measurement.py +1 -1
  34. boris/gui_utilities.py +1 -1
  35. boris/image_overlay.py +1 -1
  36. boris/import_observations.py +1 -1
  37. boris/ipc_mpv.py +1 -1
  38. boris/irr.py +1 -1
  39. boris/latency.py +1 -1
  40. boris/measurement_widget.py +1 -1
  41. boris/media_file.py +1 -1
  42. boris/menu_options.py +14 -12
  43. boris/modifier_coding_map_creator.py +1 -1
  44. boris/modifiers_coding_map.py +1 -1
  45. boris/observation.py +13 -14
  46. boris/observation_operations.py +1 -1
  47. boris/observations_list.py +1 -1
  48. boris/otx_parser.py +1 -1
  49. boris/param_panel.py +1 -1
  50. boris/player_dock_widget.py +1 -1
  51. boris/plot_data_module.py +1 -1
  52. boris/plot_events.py +1 -1
  53. boris/plot_events_rt.py +1 -1
  54. boris/plot_spectrogram_rt.py +42 -73
  55. boris/plot_waveform_rt.py +1 -1
  56. boris/plugins.py +1 -1
  57. boris/preferences.py +35 -4
  58. boris/preferences_ui.py +48 -18
  59. boris/project.py +1 -1
  60. boris/project_functions.py +19 -22
  61. boris/project_import_export.py +1 -1
  62. boris/select_modifiers.py +1 -1
  63. boris/select_observations.py +22 -23
  64. boris/select_subj_behav.py +4 -4
  65. boris/state_events.py +1 -1
  66. boris/subjects_pad.py +1 -1
  67. boris/synthetic_time_budget.py +1 -1
  68. boris/time_budget_functions.py +1 -1
  69. boris/time_budget_widget.py +1 -1
  70. boris/transitions.py +1 -1
  71. boris/utilities.py +1 -1
  72. boris/version.py +3 -3
  73. boris/video_equalizer.py +1 -1
  74. boris/video_operations.py +1 -1
  75. boris/view_df.py +28 -4
  76. boris/write_event.py +1 -1
  77. {boris_behav_obs-9.7.12.dist-info → boris_behav_obs-9.8.2.dist-info}/METADATA +2 -2
  78. boris_behav_obs-9.8.2.dist-info/RECORD +110 -0
  79. {boris_behav_obs-9.7.12.dist-info → boris_behav_obs-9.8.2.dist-info}/WHEEL +1 -1
  80. boris/analysis_plugins/_export_to_feral.py +0 -225
  81. boris_behav_obs-9.7.12.dist-info/RECORD +0 -110
  82. {boris_behav_obs-9.7.12.dist-info → boris_behav_obs-9.8.2.dist-info}/entry_points.txt +0 -0
  83. {boris_behav_obs-9.7.12.dist-info → boris_behav_obs-9.8.2.dist-info}/licenses/LICENSE.TXT +0 -0
  84. {boris_behav_obs-9.7.12.dist-info → boris_behav_obs-9.8.2.dist-info}/top_level.txt +0 -0
@@ -1,28 +1,26 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
+ This file is part of BORIS.
6
7
 
7
- This program is free software; you can redistribute it and/or modify
8
+ BORIS is free software; you can redistribute it and/or modify
8
9
  it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation; either version 2 of the License, or
10
- (at your option) any later version.
10
+ the Free Software Foundation; either version 3 of the License, or
11
+ any later version.
11
12
 
12
- This program is distributed in the hope that it will be useful,
13
+ BORIS is distributed in the hope that it will be useful,
13
14
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
15
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
16
  GNU General Public License for more details.
16
17
 
17
18
  You should have received a copy of the GNU General Public License
18
- along with this program; if not, write to the Free Software
19
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
- MA 02110-1301, USA.
19
+ along with this program; if not see <http://www.gnu.org/licenses/>.
21
20
 
22
21
  """
23
22
 
24
23
  import logging
25
- from typing import Tuple
26
24
 
27
25
  from PySide6.QtCore import Qt
28
26
  from PySide6.QtWidgets import QAbstractItemView
@@ -32,7 +30,7 @@ from . import gui_utilities, observations_list, project_functions
32
30
  from . import utilities as util
33
31
 
34
32
 
35
- def select_observations2(self, mode: str, windows_title: str = "") -> Tuple[str, list]:
33
+ def select_observations2(self, mode: str, windows_title: str = "") -> tuple[str, list[str]]:
36
34
  """
37
35
  allow user to select observations
38
36
  mode: accepted values: OPEN, EDIT, SINGLE, MULTIPLE, SELECT1
@@ -149,37 +147,37 @@ def select_observations2(self, mode: str, windows_title: str = "") -> Tuple[str,
149
147
  obsList.mode = mode
150
148
 
151
149
  if mode == cfg.OPEN:
152
- obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
150
+ obsList.view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
153
151
  obsList.pbOpen.setVisible(True)
154
152
 
155
153
  if mode == cfg.VIEW:
156
- obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
154
+ obsList.view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
157
155
  obsList.pbView.setVisible(True)
158
156
 
159
157
  if mode == cfg.EDIT:
160
- obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
158
+ obsList.view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
161
159
  obsList.pbEdit.setVisible(True)
162
160
 
163
161
  if mode == cfg.SINGLE:
164
- obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
162
+ obsList.view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
165
163
  obsList.pbOpen.setVisible(True)
166
164
  obsList.pbView.setVisible(True)
167
165
  obsList.pbEdit.setVisible(True)
168
166
 
169
167
  if mode == cfg.MULTIPLE:
170
- obsList.view.setSelectionMode(QAbstractItemView.MultiSelection)
168
+ obsList.view.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)
171
169
  obsList.pbOk.setVisible(True)
172
170
  obsList.pbSelectAll.setVisible(True)
173
171
  obsList.pbUnSelectAll.setVisible(True)
174
172
 
175
173
  if mode == cfg.SELECT1:
176
- obsList.view.setSelectionMode(QAbstractItemView.SingleSelection)
174
+ obsList.view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
177
175
  obsList.pbOk.setVisible(True)
178
176
 
179
177
  # restore window geometry
180
178
  gui_utilities.restore_geometry(obsList, "observations list", (900, 600))
181
179
 
182
- obsList.view.sortItems(0, Qt.AscendingOrder)
180
+ obsList.view.sortItems(0, Qt.SortOrder.AscendingOrder)
183
181
  for row in range(obsList.view.rowCount()):
184
182
  obsList.view.resizeRowToContents(row)
185
183
 
@@ -196,15 +194,16 @@ def select_observations2(self, mode: str, windows_title: str = "") -> Tuple[str,
196
194
  if idx.column() == 0: # first column
197
195
  selected_observations.append(idx.data())
198
196
 
197
+ result_str: str = ""
199
198
  if result == 0: # cancel
200
- resultStr = ""
199
+ result_str = ""
201
200
  if result == 1: # select
202
- resultStr = "ok"
201
+ result_str = "ok"
203
202
  if result == 2: # open
204
- resultStr = cfg.OPEN
203
+ result_str = cfg.OPEN
205
204
  if result == 3: # edit
206
- resultStr = cfg.EDIT
205
+ result_str = cfg.EDIT
207
206
  if result == 4: # view
208
- resultStr = cfg.VIEW
207
+ result_str = cfg.VIEW
209
208
 
210
- return resultStr, selected_observations
209
+ return result_str, selected_observations
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
@@ -35,7 +35,7 @@ from . import utilities as util
35
35
 
36
36
  def choose_obs_subj_behav_category(
37
37
  self,
38
- selected_observations: list,
38
+ selected_observations: list[str],
39
39
  start_coding: Optional[dec] = dec("NaN"), # Union[..., None]
40
40
  end_coding: Optional[dec] = dec("NaN"),
41
41
  start_interval: Optional[dec] = dec("NaN"),
@@ -246,8 +246,8 @@ def choose_obs_subj_behav_category(
246
246
  None,
247
247
  cfg.programName,
248
248
  "The start time is after the end time",
249
- QMessageBox.Ok | QMessageBox.Default,
250
- QMessageBox.NoButton,
249
+ QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Default,
250
+ QMessageBox.StandardButton.NoButton,
251
251
  )
252
252
  return {cfg.SELECTED_SUBJECTS: [], cfg.SELECTED_BEHAVIORS: []}
253
253
 
boris/state_events.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 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
boris/subjects_pad.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 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
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 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
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
boris/transitions.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
boris/utilities.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 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
boris/version.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 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__ = "9.7.12"
24
- __version_date__ = "2025-12-05"
23
+ __version__ = "9.8.2a1"
24
+ __version_date__ = "2026-01-26"
boris/video_equalizer.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
  This file is part of BORIS.
7
7
 
boris/video_operations.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
 
7
7
  This program is free software; you can redistribute it and/or modify
boris/view_df.py CHANGED
@@ -1,11 +1,35 @@
1
- from .view_df_ui import Ui_Form
2
- from PySide6.QtWidgets import QWidget, QFileDialog
3
- from PySide6.QtCore import Qt, QAbstractTableModel
1
+ """
2
+ BORIS
3
+ Behavioral Observation Research Interactive Software
4
+ Copyright 2012-2026 Olivier Friard
5
+
6
+ This file is part of BORIS.
7
+
8
+ BORIS is free software; you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation; either version 3 of the License, or
11
+ any later version.
12
+
13
+ BORIS is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
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/>.
20
+
21
+ """
4
22
 
5
- from . import config as cfg
6
23
  from pathlib import Path
24
+
25
+ from PySide6.QtCore import QAbstractTableModel, Qt
26
+ from PySide6.QtWidgets import QFileDialog, QWidget
27
+
28
+ from . import config as cfg
7
29
  from . import dialog
30
+ from .view_df_ui import Ui_Form
8
31
 
32
+ flag_pyreadr_loaded: bool = False
9
33
  try:
10
34
  import pyreadr
11
35
 
boris/write_event.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  BORIS
3
3
  Behavioral Observation Research Interactive Software
4
- Copyright 2012-2025 Olivier Friard
4
+ Copyright 2012-2026 Olivier Friard
5
5
 
6
6
 
7
7
  This program is free software; you can redistribute it and/or modify
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boris-behav-obs
3
- Version: 9.7.12
3
+ Version: 9.8.2
4
4
  Summary: BORIS - Behavioral Observation Research Interactive Software
5
5
  Author-email: Olivier Friard <olivier.friard@unito.it>
6
6
  License-Expression: GPL-3.0-only
@@ -51,7 +51,7 @@ It provides also some analysis tools like time budget and some plotting function
51
51
  <!-- The BO-RIS paper has more than [![BORIS citations counter](https://penelope.unito.it/friard/boris_scopus_citations.png) citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications. -->
52
52
 
53
53
 
54
- The BORIS paper has more than 2472 citations in peer-reviewed scientific publications.
54
+ The BORIS paper has more than 2491 citations in peer-reviewed scientific publications.
55
55
 
56
56
 
57
57
 
@@ -0,0 +1,110 @@
1
+ boris/__init__.py,sha256=Gl4_cpvnp6b34syaGntl7mX1lbgMbMwoiFh-vx6JfbI,773
2
+ boris/__main__.py,sha256=TOrVDXimU9zCidmkyDJhceI-6r-CSRZ3J6PhvxjgE5k,764
3
+ boris/about.py,sha256=U8PgEPQwybWhGrmyWJtpjCM2xnsc9rVfUGcIHIhzrFQ,5460
4
+ boris/add_modifier.py,sha256=N5OujNy8UuKjDw0OVvaFG0qvj2qoo8BhlxHdYV4SRvc,26240
5
+ boris/add_modifier_ui.py,sha256=5PbyQKCrMhLXYkOqOvqis1E_oCYQI_994-uofIIIb0k,12366
6
+ boris/advanced_event_filtering.py,sha256=53rBYeycrDjiVLivtG3Y1Vbs5Q2Sd0JKnPwk92rfje4,15469
7
+ boris/behav_coding_map_creator.py,sha256=eJ3Lhf1r7x_Blkt7FK6dLMv_U9xcWb3oPsHWaRcVbbE,38797
8
+ boris/behavior_binary_table.py,sha256=tmk-4dzkTai9DMf70WenRnEtaUhpa1CeNiFnUNseVnI,12453
9
+ boris/behaviors_coding_map.py,sha256=HPo9onT7n12Qz8asEEfvDkwamI77RiQ_CZC1Ey384P8,7302
10
+ boris/boris_cli.py,sha256=Sc3B6FPRYJ93RGHr_dFQfqLiRR2mqh9qMYyyN226DvQ,13193
11
+ boris/cmd_arguments.py,sha256=es6AAL2JYXNt1pv6ygLtg5WzvfLix_zsJOQCMZ4WWYM,2065
12
+ boris/coding_pad.py,sha256=OaZmoHwkPy9uHmE0hkNOBJF8x3qRrM4trGr7v-zCN18,10978
13
+ boris/config.py,sha256=gKCg80wEuj6Y8P8ygXgDgJO-C-Lg-MBNBmyOpc7kaXc,18349
14
+ boris/config_file.py,sha256=j9NaoYfPKp6N3YqgFUWhc15QNkXlAWP8HUWh8XiRrcE,13534
15
+ boris/connections.py,sha256=kuZIEUjHaESbaNk-YD0ND_472gQM8Q85nId_NOU37As,19875
16
+ boris/converters.py,sha256=x094f5xdxkS0rrX6b5raYYAgEbvT-MZ6bdDnB2voDcI,11678
17
+ boris/converters_ui.py,sha256=Azd7DGDFVcpYD5zheHcYPIFTggUV2exNfw6LN0AXN4A,9925
18
+ boris/cooccurence.py,sha256=wBdjmiZWD_K06cp7bvTSdb5ZP5vbzj_88RzRbmBT_Lc,10367
19
+ boris/core.py,sha256=819EdvR-V-wWwQINVEC5qEYIt53blgEuK5Rwbb8igJ4,235104
20
+ boris/core_qrc.py,sha256=2vAMpM8WDUT5ZVTdrQ9DAN-ttdP5jiM9Cboqw48fNUk,638909
21
+ boris/core_ui.py,sha256=HgX2I2RB_8Mhk_6aW3fHvw29zo4gJQKbhDDsYi2zqiQ,77441
22
+ boris/db_functions.py,sha256=z1WIYrdutfInGFRnxTiEWVs8rOzSHB8K3u7VK-crusQ,13072
23
+ boris/dev.py,sha256=9pUElbjl9g17rFUJXX5aVSu55_iIKIuDxNdrB0DI_d0,3671
24
+ boris/dialog.py,sha256=pPbkJ49wNj5llhkWavQN7Noo6PQYg_xc-3tM-3glptQ,34154
25
+ boris/duration_widget.py,sha256=GjZgCAMGOcsNjoPiRImEVe6yMkH2vuNoh44ulpd5nlg,6924
26
+ boris/edit_event.py,sha256=ftzOpkGspbXM1yguayNseCuTZZx0rS-dWg_bb4FeqX4,7705
27
+ boris/edit_event_ui.py,sha256=qFgt00cejGB6UGC1mFkyZcsIAdvMeYMK0WYjZtJl1T0,9207
28
+ boris/event_operations.py,sha256=JpdbnR4lt-OGa8QGDM8lHly73b5hj5RrEi6V1IhitoU,40743
29
+ boris/events_cursor.py,sha256=IMG9NpF3Av-whgt5qSc4SzKZumvnuUTMZNtgHhL2Vw4,2078
30
+ boris/events_snapshots.py,sha256=dUMTfNkCcQ48xVTADCDPY_3iOI0CgVFvDkio-ISIEcI,30056
31
+ boris/exclusion_matrix.py,sha256=foT0P8E9lX1F8hk2BE7ZLoL0vi9tXIAsUxAbLMpAEBY,5269
32
+ boris/export_events.py,sha256=fjeA0P4vA8abK-rYetSmLymHI2kAzqFerDbQw6fBxqo,40113
33
+ boris/export_observation.py,sha256=vPUjiKrBcOr48LSAd_VR27q6FONbHAMZ3zT7dqtPvcA,50764
34
+ boris/external_processes.py,sha256=EPeoZXFLpMYNK-NA45QR3e8g1qFbii8wzE2KzJvmsPo,13607
35
+ boris/geometric_measurement.py,sha256=3q4bxuvvYG51WP33MEoJum1ecUVGmkNDiyZo1T85j3c,35049
36
+ boris/gui_utilities.py,sha256=TGx2nx3xzL8ZV9fhE0-728EK4HGRbtrCCnXNHqgL-MI,5458
37
+ boris/image_overlay.py,sha256=Qa_x9AZ4yeMiOUbtx6HTpyIIzcaSlOaviomm5TkgMFM,2527
38
+ boris/import_observations.py,sha256=Bxl5KgF2QulsOF53SUSx65rm5UTQFhejUn_vu-cVfKg,9074
39
+ boris/ipc_mpv.py,sha256=tJWdpd5_3wvyjnOiNihyhAaVTn_--Vsq7vo4XOQzWk8,9925
40
+ boris/irr.py,sha256=g4CGewXpDn8zIyChT34GSOTi1VNJPXHkwEw43crayWs,22335
41
+ boris/latency.py,sha256=tcgPPgWZpPWt6iAusiozB4QJwh0KJ2lfuRxnY_rK8Hw,9739
42
+ boris/measurement_widget.py,sha256=74GG-SVDQlnx2OhTtqiCq5AA1Xjfste_ghAN1rPmjJ0,4480
43
+ boris/media_file.py,sha256=rGMYYbVgShqHHSYZgtafJaavyFnfKha8lKn5_30nWFM,4818
44
+ boris/menu_options.py,sha256=mo1d_3IvOhT7yGsCdmNmIweOwY41kGkPplTospwCn4Q,7036
45
+ boris/modifier_coding_map_creator.py,sha256=8qOCrA3p4JFFdWYOPzeJ6IIb4h5cpgdypXwU2tzRLZc,33243
46
+ boris/modifiers_coding_map.py,sha256=oqOhqYaVQf_6pxU6xGD-JtbXjV-i1v5VlbxP51t9-nk,4554
47
+ boris/mpv.py,sha256=EfzIHjPbgewG4w3smEtqEUPZoVwYmMQkL4Q8ZyW-a58,76410
48
+ boris/mpv2.py,sha256=IUI4t4r9GYX7G5OXTjd3RhMMOkDdfal_15buBgksLsk,92152
49
+ boris/observation.py,sha256=UijD_ay6bYX7Y6YaA4n-J4QWslHTxyvg5XQ_Y-WnvBc,57535
50
+ boris/observation_operations.py,sha256=lZt5G9_TXCdI9qGaeT9tr2vWbLRfuPUi5rGjMBnUNtU,106581
51
+ boris/observation_ui.py,sha256=DAnU94QBNvkLuHT6AxTwqSk_D_n6VUhSl8PexZv_dUk,33309
52
+ boris/observations_list.py,sha256=xmkr_EKzj7izWjp06zS2speknS12AbVavxxpI-IAS4c,10591
53
+ boris/otx_parser.py,sha256=i7M0A5a0uoo6YTcTvlmnWxw9dh69GNc5Cfv0wce9UAg,16367
54
+ boris/param_panel.py,sha256=2RuxzfUw6MOqME-slrEEpv0xsm8JAMtasRY0KuoGnn0,8695
55
+ boris/param_panel_ui.py,sha256=4emQDFmuL4_R7bKxosLjdUb-VSPWkDm7suy38F5EKcA,13260
56
+ boris/player_dock_widget.py,sha256=X4sZwAdZ2WzAh8VfHLMGripl9k53g1qIw7koa4OlYk4,5880
57
+ boris/plot_data_module.py,sha256=a7XclqFWNzThFUQr3mGkG5iCvAL0TcoaRVUPRvELmvo,16594
58
+ boris/plot_events.py,sha256=FN9a0b2PhGJiEIxY-NEa75O9kQMtZsAviJVMOAw4BNs,24059
59
+ boris/plot_events_rt.py,sha256=7SISR0id3M-FtBngWnskUHUkj1nck7I6LRZqjGVZ6VQ,8326
60
+ boris/plot_spectrogram_rt.py,sha256=AFJS4NDoWLdZNKdNF-EfDSP6Ur_LY3tlms2q459yGsY,9611
61
+ boris/plot_waveform_rt.py,sha256=VbZBSTKMPIrTJM6Pb2PjOPZJBUFAlmX48Ru3M9odabE,7595
62
+ boris/plugins.py,sha256=SsTCOVnv83GhmUqwe-01dNCeyElnHSF8-a44TtoZO3w,17234
63
+ boris/preferences.py,sha256=fwqlZjx6hx6EfQW16sBg2VmklnS3BSUTLOGzsQK0M50,23451
64
+ boris/preferences_ui.py,sha256=gy0Ilxzlexdz9A6CSNto9uYdUrzNzNZ8RK-534cnfBA,36620
65
+ boris/project.py,sha256=IA-vfCF2StUBFoz7y1QSVI4AZFhtmp_rQAcg-0t2Bo4,86438
66
+ boris/project_functions.py,sha256=71vBM1LIBD3nZWiTSoBxSnIu4PtshPJyGDdNWUNhbXs,83549
67
+ boris/project_import_export.py,sha256=GtgGFzE7-RBXwFgtmL7bEzMqjcj6GorVtDNyO_ETFxs,38560
68
+ boris/project_ui.py,sha256=yB-ewhHt8S8DTTRIk-dNK2tPMNU24lNji9fDW_Xazu8,38805
69
+ boris/qrc_boris.py,sha256=aH-qUirYY1CGxmTK1SFCPvuZfazIHX4DdUKF1gxZeYM,675008
70
+ boris/qrc_boris5.py,sha256=prnOw7VGXWXRuVCYp_yIrmWhrlG1F9rx-3BQvkPenjY,161608
71
+ boris/select_modifiers.py,sha256=TdhOpnbp8Vpgkmhc-17C0eV7HG6Cf9oEubwMq6tq-oM,13319
72
+ boris/select_observations.py,sha256=NhJmzCtYV3ay7sB0NeDTHX6frOutgUDuyDAY9T6Tq0o,8054
73
+ boris/select_subj_behav.py,sha256=Y49lCXidxQ1SWzTQfvsr1xgMzJiq_7OisPLE2V5bpQM,11792
74
+ boris/state_events.py,sha256=XXF-v9re7wJZ6gVyI0GmYkd9hbtmunuQAydVL4QcJPU,7790
75
+ boris/subjects_pad.py,sha256=7VBrvmBvcL9iH_5ECmht0aR3iKUvKuOAa3EcX8_IHNU,3543
76
+ boris/synthetic_time_budget.py,sha256=K5HIo7IMJZ5g3WrTY3ugYRAM3dDCE_i1mqutfgnB9Jk,10489
77
+ boris/time_budget_functions.py,sha256=fK5VSlrfAR7eBTD690IBZiJ8p5Xq3rbu-3V1R6So69o,52186
78
+ boris/time_budget_widget.py,sha256=BxG0tnRPQV8QI-r3W5JhmcdiwzxtXJOdUURjdV_Ba0E,43213
79
+ boris/transitions.py,sha256=A7JQq8vB2u4GrZjt1hGD0EHmk1fn4ynx3HGNMHZQ7hU,12246
80
+ boris/utilities.py,sha256=sRBy1pTopG42nhdcsRCvioOpCp-KyfjOnkOwlUXSnB0,58805
81
+ boris/version.py,sha256=G5zqSSz0KwLrHT3UiLe2bIGMJch6IsOGLaO8EiD0Zqk,789
82
+ boris/video_equalizer.py,sha256=l4SrrfZT65IN0yLKHnHLe48PLtn0yS_1q-mgFZr1mak,5823
83
+ boris/video_equalizer_ui.py,sha256=1CG3s79eM4JAbaCx3i1ILZXLceb41_gGXlOLNfpBgnw,10142
84
+ boris/video_operations.py,sha256=G2fz9JijuebM5LYx4e9YmR-kb05w3-2DKoIZoE2iZbs,11054
85
+ boris/view_df.py,sha256=ddbpLV3sjIjBB8pCM94D5I2hdjlLeaN6c5AnNLoUp6w,4106
86
+ boris/view_df_ui.py,sha256=CaMeRH_vQ00CTDDFQn73ZZaS-r8BSTWpL-dMCFqzJ_Q,2775
87
+ boris/write_event.py,sha256=JaOkH9ZVSilDX8PACJB-dkLjmEIi6zm_05C9wRKEdlc,23817
88
+ boris/analysis_plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
+ boris/analysis_plugins/_latency.py,sha256=9kCdFDtb5Zdao1xFpioi_exm_IxyGm6RlY3Opn6GUFo,2030
90
+ boris/analysis_plugins/export_to_feral.py,sha256=Icho_3e-2Y9Z1i_56TxnYigxsoWcRHm14XzE55p3nNM,11428
91
+ boris/analysis_plugins/irr_cohen_kappa.py,sha256=OqmivIE6i1hTcFVMp0EtY0Sr7C1Jm9t0D4IKbDfTJ7U,4268
92
+ boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py,sha256=DtzFLRToR9GdkmWYDcCmpSvxHGpguVp-_n8F-t7ND7c,4461
93
+ boris/analysis_plugins/irr_weighted_cohen_kappa.py,sha256=RX2jI4hgLU1aBkzIWqY3owZcqpMzX8DpOsrRvaIFARg,6435
94
+ boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py,sha256=DXrvac4p3_jzakHi_hTW8ZG9rniGo4YCyUH_jJ7fz8c,6744
95
+ boris/analysis_plugins/list_of_dataframe_columns.py,sha256=VEiVhxADtyaIKN4JrfFV02TuTAfWhQ60bf1mHVQp27I,437
96
+ boris/analysis_plugins/number_of_occurences.py,sha256=IDyDrdezqvSKT3BlD8QWpSYk8X9nnBBLI80OUnFJ3bY,509
97
+ boris/analysis_plugins/number_of_occurences_by_independent_variable.py,sha256=_7HTKXsyxNfyO69tP8zkQEHzT0C7qHdL1sqBjnUfRQY,1459
98
+ boris/analysis_plugins/time_budget.py,sha256=bzOS0FUJ7P2kQ9d-TxXq2_OCpo-MngGDFeU5aKsniDQ,2188
99
+ boris/portion/__init__.py,sha256=KmMu4q-iIFO5nrVRIP340mEzxzOlZQqaRupiDmS70es,642
100
+ boris/portion/const.py,sha256=JSYZUktIPCekB6qSom1FPfASn-X7w0G5-aNNHKhIZnw,1715
101
+ boris/portion/dict.py,sha256=uNM-LEY52CZ2VNMMW_C9QukoyTvPlQf8vcbGa1lQBHI,11281
102
+ boris/portion/func.py,sha256=mSQr20YS1ug7R1fRqBg8LifjtXDRvJ6Kjc3WOeL9P34,2172
103
+ boris/portion/interval.py,sha256=sOlj3MAGGaB-JxCkigS-n3qw0fY7TANAsXv1pavr8J4,19931
104
+ boris/portion/io.py,sha256=kpq44pw3xnIyAlPwaR5qRHKRdZ72f8HS9YVIWs5k2pk,6367
105
+ boris_behav_obs-9.8.2.dist-info/licenses/LICENSE.TXT,sha256=WJ7YI-moTFb-uVrFjnzzhGJrnL9P2iqQe8NuED3hutI,35141
106
+ boris_behav_obs-9.8.2.dist-info/METADATA,sha256=q_scBBgdc6GEQy6iNiM7iNBdu9bjwpumjUH1BK127Tk,5203
107
+ boris_behav_obs-9.8.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
108
+ boris_behav_obs-9.8.2.dist-info/entry_points.txt,sha256=k__8XvFi4vaA4QFvQehCZjYkKmZH34HSAJI2iYCWrMs,52
109
+ boris_behav_obs-9.8.2.dist-info/top_level.txt,sha256=fJSgm62S7WesiwTorGbOO4nNN0yzgZ3klgfGi3Px4qI,6
110
+ boris_behav_obs-9.8.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,225 +0,0 @@
1
- """
2
- BORIS plugin
3
-
4
- Export to FERAL (getferal.ai)
5
- """
6
-
7
- import pandas as pd
8
- import json
9
- from pathlib import Path
10
-
11
- from PySide6.QtWidgets import QFileDialog
12
-
13
- # dependencies for CategoryDialog
14
- from PySide6.QtWidgets import QListWidget, QListWidgetItem, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QDialog
15
- from PySide6.QtCore import Qt
16
-
17
-
18
- __version__ = "0.1.1"
19
- __version_date__ = "2025-11-28"
20
- __plugin_name__ = "Export observations to FERAL"
21
- __author__ = "Olivier Friard - University of Torino - Italy"
22
-
23
-
24
- class CategoryDialog(QDialog):
25
- def __init__(self, items, parent=None):
26
- super().__init__(parent)
27
-
28
- self.setWindowTitle("Organize the videos in categories")
29
-
30
- self.setModal(True)
31
-
32
- # Main layout
33
- main_layout = QVBoxLayout(self)
34
- lists_layout = QHBoxLayout()
35
-
36
- # All videos
37
- self.list_unclassified = self._create_list_widget()
38
- self.label_unclassified = QLabel("All videos")
39
- col0_layout = QVBoxLayout()
40
- col0_layout.addWidget(self.label_unclassified)
41
- col0_layout.addWidget(self.list_unclassified)
42
-
43
- self.list_cat1 = self._create_list_widget()
44
- self.label_cat1 = QLabel("train")
45
- col1_layout = QVBoxLayout()
46
- col1_layout.addWidget(self.label_cat1)
47
- col1_layout.addWidget(self.list_cat1)
48
-
49
- self.list_cat2 = self._create_list_widget()
50
- self.label_cat2 = QLabel("val")
51
- col2_layout = QVBoxLayout()
52
- col2_layout.addWidget(self.label_cat2)
53
- col2_layout.addWidget(self.list_cat2)
54
-
55
- self.list_cat3 = self._create_list_widget()
56
- self.label_cat3 = QLabel("test")
57
- col3_layout = QVBoxLayout()
58
- col3_layout.addWidget(self.label_cat3)
59
- col3_layout.addWidget(self.list_cat3)
60
-
61
- self.list_cat4 = self._create_list_widget()
62
- self.label_cat4 = QLabel("inference")
63
- col4_layout = QVBoxLayout()
64
- col4_layout.addWidget(self.label_cat4)
65
- col4_layout.addWidget(self.list_cat4)
66
-
67
- # Add all columns to the horizontal layout
68
- lists_layout.addLayout(col0_layout)
69
- lists_layout.addLayout(col1_layout)
70
- lists_layout.addLayout(col2_layout)
71
- lists_layout.addLayout(col3_layout)
72
- lists_layout.addLayout(col4_layout)
73
-
74
- main_layout.addLayout(lists_layout)
75
-
76
- buttons_layout = QHBoxLayout()
77
- self.btn_ok = QPushButton("OK")
78
- self.btn_cancel = QPushButton("Cancel")
79
-
80
- self.btn_ok.clicked.connect(self.accept)
81
- self.btn_cancel.clicked.connect(self.reject)
82
-
83
- buttons_layout.addStretch()
84
- buttons_layout.addWidget(self.btn_ok)
85
- buttons_layout.addWidget(self.btn_cancel)
86
-
87
- main_layout.addLayout(buttons_layout)
88
-
89
- # Populate "Unclassified" with input items
90
- for text in items:
91
- QListWidgetItem(text, self.list_unclassified)
92
-
93
- def _create_list_widget(self):
94
- """
95
- Create a QListWidget ready for drag & drop.
96
- """
97
- lw = QListWidget()
98
- lw.setSelectionMode(QListWidget.ExtendedSelection)
99
- lw.setDragEnabled(True)
100
- lw.setAcceptDrops(True)
101
- lw.setDropIndicatorShown(True)
102
- lw.setDragDropMode(QListWidget.DragDrop)
103
- lw.setDefaultDropAction(Qt.MoveAction)
104
- return lw
105
-
106
- def get_categories(self):
107
- """
108
- Return the content of all categories as a dictionary of lists.
109
- """
110
-
111
- def collect(widget):
112
- return [widget.item(i).text().rstrip("*") for i in range(widget.count())]
113
-
114
- return {
115
- "unclassified": collect(self.list_unclassified),
116
- "train": collect(self.list_cat1),
117
- "val": collect(self.list_cat2),
118
- "test": collect(self.list_cat3),
119
- "inference": collect(self.list_cat4),
120
- }
121
-
122
-
123
- def run(df: pd.DataFrame, project: dict):
124
- """
125
- Export observations to FERAL
126
- See https://www.getferal.ai/ > Label Preparation
127
- """
128
-
129
- out: dict = {
130
- "is_multilabel": False,
131
- "splits": {
132
- "train": [],
133
- "val": [],
134
- "test": [],
135
- "inference": [],
136
- },
137
- }
138
-
139
- log: list = []
140
-
141
- # class names
142
- class_names = {x: project["behaviors_conf"][x]["code"] for x in project["behaviors_conf"]}
143
- out["class_names"] = class_names
144
- reversed_class_names = {project["behaviors_conf"][x]["code"]: int(x) for x in project["behaviors_conf"]}
145
- log.append(f"{class_names=}")
146
-
147
- observations: list = sorted([x for x in project["observations"]])
148
- log.append(f"Selected observation: {observations}")
149
-
150
- labels: dict = {}
151
- video_list: list = []
152
- for observation_id in observations:
153
- log.append("---")
154
- log.append(observation_id)
155
-
156
- # check number of media file in player #1
157
- if len(project["observations"][observation_id]["file"]["1"]) != 1:
158
- log.append(f"The observation {observation_id} contains more than one video")
159
- continue
160
-
161
- # check number of coded subjects
162
- if len(set([x[1] for x in project["observations"][observation_id]["events"]])) > 1:
163
- log.append(f"The observation {observation_id} contains more than one subject")
164
- continue
165
-
166
- media_file_path: str = project["observations"][observation_id]["file"]["1"][0]
167
- media_file_name = str(Path(media_file_path).name)
168
-
169
- # skip if no events
170
- if not project["observations"][observation_id]["events"]:
171
- video_list.append(media_file_name)
172
- log.append(f"No events for observation {observation_id}")
173
- continue
174
- else:
175
- video_list.append(media_file_name + "*")
176
-
177
- # extract FPS
178
- FPS = project["observations"][observation_id]["media_info"]["fps"][media_file_path]
179
- log.append(f"{media_file_name} {FPS=}")
180
- # extract media duration
181
- duration = project["observations"][observation_id]["media_info"]["length"][media_file_path]
182
- log.append(f"{media_file_name} {duration=}")
183
-
184
- number_of_frames = int(duration / (1 / FPS))
185
- log.append(f"{number_of_frames=}")
186
-
187
- labels[media_file_name] = [0] * number_of_frames
188
-
189
- for idx in range(number_of_frames):
190
- t = idx * (1 / FPS)
191
- behaviors = (
192
- df[(df["Observation id"] == observation_id) & (df["Start (s)"] <= t) & (df["Stop (s)"] >= t)]["Behavior"].unique().tolist()
193
- )
194
- if len(behaviors) > 1:
195
- log.append(f"The observation {observation_id} contains more than one behavior for frame {idx}")
196
- del labels[media_file_name]
197
- break
198
- if behaviors:
199
- behaviors_idx = reversed_class_names[behaviors[0]]
200
- labels[media_file_name][idx] = behaviors_idx
201
-
202
- out["labels"] = labels
203
-
204
- # splits
205
- dlg = CategoryDialog(video_list)
206
-
207
- if dlg.exec(): # Dialog accepted
208
- result = dlg.get_categories()
209
- del result["unclassified"]
210
- out["splits"] = result
211
-
212
- filename, _ = QFileDialog.getSaveFileName(
213
- None,
214
- "Choose a file to save",
215
- "", # start directory
216
- "JSON files (*.json);;All files (*.*)",
217
- )
218
- if filename:
219
- with open(filename, "w") as f_out:
220
- f_out.write(json.dumps(out, separators=(",", ": "), indent=1))
221
-
222
- else:
223
- log.append("splits section missing")
224
-
225
- return "\n".join(log)