boris-behav-obs 9.7.1__tar.gz → 9.7.2__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 (126) hide show
  1. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/PKG-INFO +1 -1
  2. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/config.py +7 -0
  3. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/config_file.py +3 -3
  4. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/core.py +12 -16
  5. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/preferences.py +6 -0
  6. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/preferences_ui.py +46 -28
  7. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/project_functions.py +8 -0
  8. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/version.py +2 -2
  9. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris_behav_obs.egg-info/PKG-INFO +1 -1
  10. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/pyproject.toml +1 -1
  11. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/LICENSE.TXT +0 -0
  12. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/MANIFEST.in +0 -0
  13. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/README.TXT +0 -0
  14. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/README.md +0 -0
  15. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/__init__.py +0 -0
  16. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/__main__.py +0 -0
  17. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/about.py +0 -0
  18. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/add_modifier.py +0 -0
  19. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/add_modifier_ui.py +0 -0
  20. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/advanced_event_filtering.py +0 -0
  21. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/__init__.py +0 -0
  22. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/_latency.py +0 -0
  23. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/irr_cohen_kappa.py +0 -0
  24. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +0 -0
  25. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/irr_weighted_cohen_kappa.py +0 -0
  26. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +0 -0
  27. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/list_of_dataframe_columns.py +0 -0
  28. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/number_of_occurences.py +0 -0
  29. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
  30. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/analysis_plugins/time_budget.py +0 -0
  31. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/behav_coding_map_creator.py +0 -0
  32. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/behavior_binary_table.py +0 -0
  33. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/behaviors_coding_map.py +0 -0
  34. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/boris_cli.py +0 -0
  35. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/cmd_arguments.py +0 -0
  36. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/coding_pad.py +0 -0
  37. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/connections.py +0 -0
  38. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/converters.py +0 -0
  39. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/converters_ui.py +0 -0
  40. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/cooccurence.py +0 -0
  41. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/core_qrc.py +0 -0
  42. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/core_ui.py +0 -0
  43. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/db_functions.py +0 -0
  44. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/dev.py +0 -0
  45. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/dialog.py +0 -0
  46. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/duration_widget.py +0 -0
  47. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/edit_event.py +0 -0
  48. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/edit_event_ui.py +0 -0
  49. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/event_operations.py +0 -0
  50. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/events_cursor.py +0 -0
  51. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/events_snapshots.py +0 -0
  52. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/exclusion_matrix.py +0 -0
  53. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/export_events.py +0 -0
  54. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/export_observation.py +0 -0
  55. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/external_processes.py +0 -0
  56. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/geometric_measurement.py +0 -0
  57. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/gui_utilities.py +0 -0
  58. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/image_overlay.py +0 -0
  59. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/import_observations.py +0 -0
  60. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/ipc_mpv.py +0 -0
  61. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/irr.py +0 -0
  62. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/latency.py +0 -0
  63. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/measurement_widget.py +0 -0
  64. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/media_file.py +0 -0
  65. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/menu_options.py +0 -0
  66. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/modifier_coding_map_creator.py +0 -0
  67. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/modifiers_coding_map.py +0 -0
  68. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/mpv.py +0 -0
  69. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/mpv2.py +0 -0
  70. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/observation.py +0 -0
  71. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/observation_operations.py +0 -0
  72. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/observation_ui.py +0 -0
  73. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/observations_list.py +0 -0
  74. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/otx_parser.py +0 -0
  75. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/param_panel.py +0 -0
  76. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/param_panel_ui.py +0 -0
  77. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/player_dock_widget.py +0 -0
  78. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/plot_data_module.py +0 -0
  79. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/plot_events.py +0 -0
  80. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/plot_events_rt.py +0 -0
  81. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/plot_spectrogram_rt.py +0 -0
  82. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/plot_waveform_rt.py +0 -0
  83. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/plugins.py +0 -0
  84. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/portion/__init__.py +0 -0
  85. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/portion/const.py +0 -0
  86. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/portion/dict.py +0 -0
  87. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/portion/func.py +0 -0
  88. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/portion/interval.py +0 -0
  89. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/portion/io.py +0 -0
  90. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/project.py +0 -0
  91. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/project_import_export.py +0 -0
  92. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/project_ui.py +0 -0
  93. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/qrc_boris.py +0 -0
  94. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/qrc_boris5.py +0 -0
  95. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/select_modifiers.py +0 -0
  96. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/select_observations.py +0 -0
  97. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/select_subj_behav.py +0 -0
  98. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/state_events.py +0 -0
  99. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/subjects_pad.py +0 -0
  100. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/synthetic_time_budget.py +0 -0
  101. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/time_budget_functions.py +0 -0
  102. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/time_budget_widget.py +0 -0
  103. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/transitions.py +0 -0
  104. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/utilities.py +0 -0
  105. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/video_equalizer.py +0 -0
  106. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/video_equalizer_ui.py +0 -0
  107. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/video_operations.py +0 -0
  108. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/view_df.py +0 -0
  109. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/view_df_ui.py +0 -0
  110. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris/write_event.py +0 -0
  111. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris_behav_obs.egg-info/SOURCES.txt +0 -0
  112. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
  113. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris_behav_obs.egg-info/entry_points.txt +0 -0
  114. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris_behav_obs.egg-info/requires.txt +0 -0
  115. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/boris_behav_obs.egg-info/top_level.txt +0 -0
  116. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/setup.cfg +0 -0
  117. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_db_functions.py +0 -0
  118. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_export_observation.py +0 -0
  119. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_irr.py +0 -0
  120. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_observation_gui.py +0 -0
  121. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_otx_parser.py +0 -0
  122. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_preferences_gui.py +0 -0
  123. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_project_functions.py +0 -0
  124. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_time_budget.py +0 -0
  125. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_utilities.py +0 -0
  126. {boris_behav_obs-9.7.1 → boris_behav_obs-9.7.2}/tests/test_utilities2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boris-behav-obs
3
- Version: 9.7.1
3
+ Version: 9.7.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
@@ -132,6 +132,8 @@ POINT_EVENT_PLOT_COLOR = "black"
132
132
 
133
133
  CHAR_FORBIDDEN_IN_MODIFIERS = "(|),`~"
134
134
 
135
+ FAST_FORWARD_DEFAULT_VALUE:float = 10.0
136
+
135
137
  ADAPT_FAST_JUMP = "adapt_fast_jump"
136
138
  ADAPT_FAST_JUMP_DEFAULT = False
137
139
 
@@ -419,6 +421,10 @@ MPV_HWDEC_AUTOSAFE = "auto-safe"
419
421
  MPV_HWDEC_OPTIONS = (MPV_HWDEC_AUTO, MPV_HWDEC_AUTOSAFE, MPV_HWDEC_NO)
420
422
  MPV_HWDEC_DEFAULT_VALUE = MPV_HWDEC_AUTO
421
423
 
424
+ # frame step size (disabled)
425
+ # FRAME_STEP_SIZE: str = "frame_step_size"
426
+ # FRAME_STEP_SIZE_DEFAULT_VALUE: int = 1
427
+
422
428
  ANALYSIS_PLUGINS = "analysis_plugins"
423
429
  EXCLUDED_PLUGINS = "excluded_plugins"
424
430
  PERSONAL_PLUGINS_DIR = "personal_plugins_dir"
@@ -730,6 +736,7 @@ INIT_PARAM = {
730
736
  MPV_HWDEC: MPV_HWDEC_DEFAULT_VALUE,
731
737
  PROJECT_FILE_INDENTATION: PROJECT_FILE_INDENTATION_DEFAULT_VALUE,
732
738
  f"{MEDIA} tw fields": MEDIA_TW_EVENTS_FIELDS_DEFAULT,
739
+ # FRAME_STEP_SIZE: FRAME_STEP_SIZE_DEFAULT_VALUE,
733
740
  }
734
741
 
735
742
  SDIS_EXT = "sds"
@@ -82,11 +82,11 @@ def read(self):
82
82
 
83
83
  logging.debug(f"time format: {self.timeFormat}")
84
84
 
85
- self.fast = 10
85
+ self.fast = cfg.FAST_FORWARD_DEFAULT_VALUE
86
86
  try:
87
- self.fast = int(settings.value("Time/fast_forward_speed"))
87
+ self.fast = float(settings.value("Time/fast_forward_speed"))
88
88
  except Exception:
89
- self.fast = 10
89
+ self.fast = cfg.FAST_FORWARD_DEFAULT_VALUE
90
90
 
91
91
  logging.debug(f"Time/fast_forward_speed: {self.fast}")
92
92
 
@@ -43,7 +43,6 @@ import locale
43
43
  import tempfile
44
44
  import time
45
45
  import urllib.request
46
- from typing import Union, Tuple
47
46
  from decimal import Decimal as dec
48
47
  from decimal import ROUND_DOWN
49
48
  import gzip
@@ -242,7 +241,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
242
241
  current_player: int = 0 # id of the selected (left click) video player
243
242
 
244
243
  mem_media_name: str = "" # record current media name. Use to check if media changed
245
- mem_playlist_index: Union[int, None] = None
244
+ mem_playlist_index: int | None = None
246
245
  saved_state = None
247
246
  user_move_slider: bool = False
248
247
  observationId: str = "" # current observation id
@@ -739,7 +738,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
739
738
  text: str = "Behaviors to show in ethogram list",
740
739
  table: str = cfg.ETHOGRAM,
741
740
  behavior_type: list = cfg.STATE_EVENT_TYPES,
742
- ) -> Tuple[bool, list]:
741
+ ) -> tuple[bool, list]:
743
742
  """
744
743
  allow user to:
745
744
  filter behaviors in ethogram widget
@@ -3682,14 +3681,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3682
3681
  """
3683
3682
  show next frame
3684
3683
  """
3684
+ # frame_step_size = self.config_param.get(cfg.FRAME_STEP_SIZE, cfg.FRAME_STEP_SIZE_DEFAULT_VALUE)
3685
+
3685
3686
  if self.playerType == cfg.IMAGES:
3686
3687
  if self.image_idx < len(self.images_list) - 1:
3687
- self.image_idx += 1
3688
+ self.image_idx += 1 # frame_step_size
3688
3689
  self.extract_frame(self.dw_player[0])
3689
3690
 
3690
3691
  if self.playerType == cfg.MEDIA:
3691
3692
  for dw in self.dw_player:
3693
+ # for _ in range(frame_step_size):
3692
3694
  dw.player.frame_step()
3695
+ # time.sleep(0.5)
3693
3696
 
3694
3697
  if self.geometric_measurements_mode:
3695
3698
  self.extract_frame(dw)
@@ -3866,7 +3869,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3866
3869
  write_event.write_event(self, event, cumulative_time)
3867
3870
  # write_event.write_event(self, event, self.getLaps())
3868
3871
 
3869
- def get_frame_index(self, player_idx: int = 0) -> Union[int, str]:
3872
+ def get_frame_index(self, player_idx: int = 0) -> int | str:
3870
3873
  """
3871
3874
  returns frame index for player player_idx
3872
3875
  """
@@ -4142,7 +4145,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4142
4145
  self.dw_player[n_player].player.playlist_pos = self.dw_player[n_player].player.playlist_count - 1
4143
4146
  self.seek_mediaplayer(self.dw_player[n_player].media_durations[-1], player=n_player)
4144
4147
 
4145
- def mpv_timer_out(self, value: Union[float, None] = None, scroll_slider=True):
4148
+ def mpv_timer_out(self, value: float | None = None, scroll_slider=True):
4146
4149
  """
4147
4150
  print the media current position and total length for MPV player
4148
4151
  scroll video slider to video position
@@ -4152,13 +4155,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4152
4155
  if not self.observationId:
4153
4156
  return
4154
4157
 
4155
- print("mpv timer out")
4156
-
4157
4158
  cumulative_time_pos = self.getLaps()
4158
- print(f"{cumulative_time_pos=}")
4159
4159
  # get frame index
4160
4160
  frame_idx = self.get_frame_index()
4161
- print(f"{frame_idx=}")
4162
4161
  # frame_idx = 0
4163
4162
 
4164
4163
  if value is None: # ipc mpv
@@ -4237,9 +4236,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4237
4236
  self.show_current_states_in_subjects_table()
4238
4237
 
4239
4238
  # current media name
4240
- print(f"{self.dw_player[0].player.playlist_pos=}")
4241
- print(f"{self.dw_player[0].player.playlist=}")
4242
-
4243
4239
  if self.dw_player[0].player.playlist_pos is not None:
4244
4240
  current_media_name = Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"]).name
4245
4241
  current_playlist_index = self.dw_player[0].player.playlist_pos
@@ -4488,7 +4484,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4488
4484
  for x in self.pj[cfg.OBSERVATIONS][obs_id][cfg.EVENTS]
4489
4485
  )
4490
4486
 
4491
- def choose_behavior(self, obs_key) -> Union[None, str]:
4487
+ def choose_behavior(self, obs_key) -> None | str:
4492
4488
  """
4493
4489
  fill listwidget with all behaviors coded by key
4494
4490
 
@@ -4520,7 +4516,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4520
4516
  else:
4521
4517
  return None
4522
4518
 
4523
- def choose_subject(self, subject_key) -> Union[None, str]:
4519
+ def choose_subject(self, subject_key) -> None | str:
4524
4520
  """
4525
4521
  fill listwidget with all subjects coded by key
4526
4522
 
@@ -4608,7 +4604,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4608
4604
 
4609
4605
  return dec(str(round(mem_laps / 1000, 3)))
4610
4606
 
4611
- def get_obs_time(self, n_player: int = 0) -> Tuple[dec, dec | None]:
4607
+ def get_obs_time(self, n_player: int = 0) -> tuple[dec, dec | None]:
4612
4608
  """
4613
4609
  returns time in current media and cumulative time from begining of observation
4614
4610
  do not add time offset
@@ -221,6 +221,9 @@ def preferences(self):
221
221
  preferencesWindow.cbConfirmSound.setChecked(self.confirmSound)
222
222
  # beep every
223
223
  preferencesWindow.sbBeepEvery.setValue(self.beep_every)
224
+ # frame step size
225
+ #preferencesWindow.sb_frame_step_size.setValue(self.config_param.get(cfg.FRAME_STEP_SIZE, cfg.FRAME_STEP_SIZE_DEFAULT_VALUE))
226
+
224
227
  # alert no focal subject
225
228
  preferencesWindow.cbAlertNoFocalSubject.setChecked(self.alertNoFocalSubject)
226
229
  # tracking cursor above event
@@ -418,6 +421,9 @@ def preferences(self):
418
421
 
419
422
  self.beep_every = preferencesWindow.sbBeepEvery.value()
420
423
 
424
+ # frame step size
425
+ #self.config_param[cfg.FRAME_STEP_SIZE] = preferencesWindow.sb_frame_step_size.value()
426
+
421
427
  self.alertNoFocalSubject = preferencesWindow.cbAlertNoFocalSubject.isChecked()
422
428
 
423
429
  self.trackingCursorAboveEvent = preferencesWindow.cbTrackingCursorAboveEvent.isChecked()
@@ -3,7 +3,7 @@
3
3
  ################################################################################
4
4
  ## Form generated from reading UI file 'preferences.ui'
5
5
  ##
6
- ## Created by: Qt User Interface Compiler version 6.9.0
6
+ ## Created by: Qt User Interface Compiler version 6.10.0
7
7
  ##
8
8
  ## WARNING! All changes made in this file will be lost when recompiling UI file!
9
9
  ################################################################################
@@ -145,11 +145,8 @@ class Ui_prefDialog(object):
145
145
 
146
146
  self.horizontalLayout_4.addWidget(self.label_4)
147
147
 
148
- self.sbffSpeed = QSpinBox(self.tab_observations)
148
+ self.sbffSpeed = QDoubleSpinBox(self.tab_observations)
149
149
  self.sbffSpeed.setObjectName(u"sbffSpeed")
150
- self.sbffSpeed.setMinimum(0)
151
- self.sbffSpeed.setMaximum(10000)
152
- self.sbffSpeed.setValue(10)
153
150
 
154
151
  self.horizontalLayout_4.addWidget(self.sbffSpeed)
155
152
 
@@ -244,6 +241,26 @@ class Ui_prefDialog(object):
244
241
 
245
242
  self.verticalLayout.addWidget(self.cb_pause_before_addevent)
246
243
 
244
+ self.horizontalLayout_23 = QHBoxLayout()
245
+ self.horizontalLayout_23.setObjectName(u"horizontalLayout_23")
246
+ self.label_24 = QLabel(self.tab_observations)
247
+ self.label_24.setObjectName(u"label_24")
248
+ self.label_24.setEnabled(False)
249
+
250
+ self.horizontalLayout_23.addWidget(self.label_24)
251
+
252
+ self.sb_frame_step_size = QSpinBox(self.tab_observations)
253
+ self.sb_frame_step_size.setObjectName(u"sb_frame_step_size")
254
+ self.sb_frame_step_size.setEnabled(False)
255
+ self.sb_frame_step_size.setMinimum(1)
256
+ self.sb_frame_step_size.setMaximum(1000)
257
+ self.sb_frame_step_size.setValue(1)
258
+
259
+ self.horizontalLayout_23.addWidget(self.sb_frame_step_size)
260
+
261
+
262
+ self.verticalLayout.addLayout(self.horizontalLayout_23)
263
+
247
264
  self.verticalSpacer_4 = QSpacerItem(20, 391, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
248
265
 
249
266
  self.verticalLayout.addItem(self.verticalSpacer_4)
@@ -256,35 +273,35 @@ class Ui_prefDialog(object):
256
273
  self.splitter_2 = QSplitter(self.tab_analysis_plugins)
257
274
  self.splitter_2.setObjectName(u"splitter_2")
258
275
  self.splitter_2.setOrientation(Qt.Orientation.Horizontal)
259
- self.widget = QWidget(self.splitter_2)
260
- self.widget.setObjectName(u"widget")
261
- self.verticalLayout_11 = QVBoxLayout(self.widget)
276
+ self.layoutWidget = QWidget(self.splitter_2)
277
+ self.layoutWidget.setObjectName(u"layoutWidget")
278
+ self.verticalLayout_11 = QVBoxLayout(self.layoutWidget)
262
279
  self.verticalLayout_11.setObjectName(u"verticalLayout_11")
263
280
  self.verticalLayout_11.setContentsMargins(0, 0, 0, 0)
264
- self.label_13 = QLabel(self.widget)
281
+ self.label_13 = QLabel(self.layoutWidget)
265
282
  self.label_13.setObjectName(u"label_13")
266
283
 
267
284
  self.verticalLayout_11.addWidget(self.label_13)
268
285
 
269
- self.lv_all_plugins = QListWidget(self.widget)
286
+ self.lv_all_plugins = QListWidget(self.layoutWidget)
270
287
  self.lv_all_plugins.setObjectName(u"lv_all_plugins")
271
288
 
272
289
  self.verticalLayout_11.addWidget(self.lv_all_plugins)
273
290
 
274
- self.label_15 = QLabel(self.widget)
291
+ self.label_15 = QLabel(self.layoutWidget)
275
292
  self.label_15.setObjectName(u"label_15")
276
293
 
277
294
  self.verticalLayout_11.addWidget(self.label_15)
278
295
 
279
296
  self.horizontalLayout_16 = QHBoxLayout()
280
297
  self.horizontalLayout_16.setObjectName(u"horizontalLayout_16")
281
- self.le_personal_plugins_dir = QLineEdit(self.widget)
298
+ self.le_personal_plugins_dir = QLineEdit(self.layoutWidget)
282
299
  self.le_personal_plugins_dir.setObjectName(u"le_personal_plugins_dir")
283
300
  self.le_personal_plugins_dir.setReadOnly(True)
284
301
 
285
302
  self.horizontalLayout_16.addWidget(self.le_personal_plugins_dir)
286
303
 
287
- self.pb_browse_plugins_dir = QPushButton(self.widget)
304
+ self.pb_browse_plugins_dir = QPushButton(self.layoutWidget)
288
305
  self.pb_browse_plugins_dir.setObjectName(u"pb_browse_plugins_dir")
289
306
 
290
307
  self.horizontalLayout_16.addWidget(self.pb_browse_plugins_dir)
@@ -292,49 +309,49 @@ class Ui_prefDialog(object):
292
309
 
293
310
  self.verticalLayout_11.addLayout(self.horizontalLayout_16)
294
311
 
295
- self.lw_personal_plugins = QListWidget(self.widget)
312
+ self.lw_personal_plugins = QListWidget(self.layoutWidget)
296
313
  self.lw_personal_plugins.setObjectName(u"lw_personal_plugins")
297
314
 
298
315
  self.verticalLayout_11.addWidget(self.lw_personal_plugins)
299
316
 
300
- self.splitter_2.addWidget(self.widget)
317
+ self.splitter_2.addWidget(self.layoutWidget)
301
318
  self.splitter = QSplitter(self.splitter_2)
302
319
  self.splitter.setObjectName(u"splitter")
303
320
  self.splitter.setOrientation(Qt.Orientation.Vertical)
304
- self.widget1 = QWidget(self.splitter)
305
- self.widget1.setObjectName(u"widget1")
306
- self.verticalLayout_12 = QVBoxLayout(self.widget1)
321
+ self.layoutWidget1 = QWidget(self.splitter)
322
+ self.layoutWidget1.setObjectName(u"layoutWidget1")
323
+ self.verticalLayout_12 = QVBoxLayout(self.layoutWidget1)
307
324
  self.verticalLayout_12.setObjectName(u"verticalLayout_12")
308
325
  self.verticalLayout_12.setContentsMargins(0, 0, 0, 0)
309
- self.label_14 = QLabel(self.widget1)
326
+ self.label_14 = QLabel(self.layoutWidget1)
310
327
  self.label_14.setObjectName(u"label_14")
311
328
 
312
329
  self.verticalLayout_12.addWidget(self.label_14)
313
330
 
314
- self.pte_plugin_description = QPlainTextEdit(self.widget1)
331
+ self.pte_plugin_description = QPlainTextEdit(self.layoutWidget1)
315
332
  self.pte_plugin_description.setObjectName(u"pte_plugin_description")
316
333
  self.pte_plugin_description.setReadOnly(True)
317
334
 
318
335
  self.verticalLayout_12.addWidget(self.pte_plugin_description)
319
336
 
320
- self.splitter.addWidget(self.widget1)
321
- self.widget2 = QWidget(self.splitter)
322
- self.widget2.setObjectName(u"widget2")
323
- self.verticalLayout_14 = QVBoxLayout(self.widget2)
337
+ self.splitter.addWidget(self.layoutWidget1)
338
+ self.layoutWidget2 = QWidget(self.splitter)
339
+ self.layoutWidget2.setObjectName(u"layoutWidget2")
340
+ self.verticalLayout_14 = QVBoxLayout(self.layoutWidget2)
324
341
  self.verticalLayout_14.setObjectName(u"verticalLayout_14")
325
342
  self.verticalLayout_14.setContentsMargins(0, 0, 0, 0)
326
- self.label_23 = QLabel(self.widget2)
343
+ self.label_23 = QLabel(self.layoutWidget2)
327
344
  self.label_23.setObjectName(u"label_23")
328
345
 
329
346
  self.verticalLayout_14.addWidget(self.label_23)
330
347
 
331
- self.pte_plugin_code = QPlainTextEdit(self.widget2)
348
+ self.pte_plugin_code = QPlainTextEdit(self.layoutWidget2)
332
349
  self.pte_plugin_code.setObjectName(u"pte_plugin_code")
333
350
  self.pte_plugin_code.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
334
351
 
335
352
  self.verticalLayout_14.addWidget(self.pte_plugin_code)
336
353
 
337
- self.splitter.addWidget(self.widget2)
354
+ self.splitter.addWidget(self.layoutWidget2)
338
355
  self.splitter_2.addWidget(self.splitter)
339
356
 
340
357
  self.verticalLayout_15.addWidget(self.splitter_2)
@@ -676,7 +693,7 @@ class Ui_prefDialog(object):
676
693
 
677
694
  self.retranslateUi(prefDialog)
678
695
 
679
- self.tabWidget.setCurrentIndex(2)
696
+ self.tabWidget.setCurrentIndex(1)
680
697
 
681
698
 
682
699
  QMetaObject.connectSlotsByName(prefDialog)
@@ -707,6 +724,7 @@ class Ui_prefDialog(object):
707
724
  self.cbTrackingCursorAboveEvent.setText(QCoreApplication.translate("prefDialog", u"Tracking cursor above current event", None))
708
725
  self.cbAlertNoFocalSubject.setText(QCoreApplication.translate("prefDialog", u"Alert if focal subject is not set", None))
709
726
  self.cb_pause_before_addevent.setText(QCoreApplication.translate("prefDialog", u"Pause media before \"Add event\" command", None))
727
+ self.label_24.setText(QCoreApplication.translate("prefDialog", u"Frame step size", None))
710
728
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_observations), QCoreApplication.translate("prefDialog", u"Observations", None))
711
729
  self.label_13.setText(QCoreApplication.translate("prefDialog", u"BORIS plugins", None))
712
730
  self.label_15.setText(QCoreApplication.translate("prefDialog", u"Personal plugins", None))
@@ -1425,6 +1425,7 @@ def open_project_json(project_file_name: str) -> tuple:
1425
1425
  pj[cfg.OBSERVATIONS][obs][cfg.TYPE] = cfg.MEDIA
1426
1426
 
1427
1427
  # convert old media list in new one
1428
+ d1: dict = {}
1428
1429
  if len(pj[cfg.OBSERVATIONS][obs][cfg.FILE]):
1429
1430
  d1 = {cfg.PLAYER1: [pj[cfg.OBSERVATIONS][obs][cfg.FILE][0]]}
1430
1431
 
@@ -1470,6 +1471,13 @@ def open_project_json(project_file_name: str) -> tuple:
1470
1471
  pj[cfg.PROJECT_VERSION] = cfg.project_format_version
1471
1472
  projectChanged = True
1472
1473
 
1474
+ # check if behavioral categories are stored as a list
1475
+ if isinstance(pj[cfg.BEHAVIORAL_CATEGORIES_CONF], list):
1476
+ # convert to dict
1477
+ pj[cfg.BEHAVIORAL_CATEGORIES_CONF] = {str(idx): {"name": bc} for idx, bc in enumerate(pj[cfg.BEHAVIORAL_CATEGORIES_CONF])}
1478
+ logging.info("Behavioral categories was converted from a list to a dictionary")
1479
+ projectChanged = True
1480
+
1473
1481
  # add category key if not found
1474
1482
  for idx in pj[cfg.ETHOGRAM]:
1475
1483
  if cfg.BEHAVIOR_CATEGORY not in pj[cfg.ETHOGRAM][idx]:
@@ -20,5 +20,5 @@ This file is part of BORIS.
20
20
 
21
21
  """
22
22
 
23
- __version__ = "9.7.1"
24
- __version_date__ = "2025-10-22"
23
+ __version__ = "9.7.2"
24
+ __version_date__ = "2025-10-24"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boris-behav-obs
3
- Version: 9.7.1
3
+ Version: 9.7.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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "boris-behav-obs"
3
- version = "9.7.1"
3
+ version = "9.7.2"
4
4
  description = "BORIS - Behavioral Observation Research Interactive Software"
5
5
  authors = [{ name="Olivier Friard", email="olivier.friard@unito.it" }]
6
6
  readme = "README.md"