boris-behav-obs 9.7.7__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.

Potentially problematic release.


This version of boris-behav-obs might be problematic. Click here for more details.

Files changed (109) hide show
  1. boris/__init__.py +26 -0
  2. boris/__main__.py +25 -0
  3. boris/about.py +143 -0
  4. boris/add_modifier.py +635 -0
  5. boris/add_modifier_ui.py +303 -0
  6. boris/advanced_event_filtering.py +455 -0
  7. boris/analysis_plugins/__init__.py +0 -0
  8. boris/analysis_plugins/_latency.py +59 -0
  9. boris/analysis_plugins/irr_cohen_kappa.py +109 -0
  10. boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
  11. boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
  12. boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
  13. boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
  14. boris/analysis_plugins/number_of_occurences.py +22 -0
  15. boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
  16. boris/analysis_plugins/time_budget.py +61 -0
  17. boris/behav_coding_map_creator.py +1110 -0
  18. boris/behavior_binary_table.py +305 -0
  19. boris/behaviors_coding_map.py +239 -0
  20. boris/boris_cli.py +340 -0
  21. boris/cmd_arguments.py +49 -0
  22. boris/coding_pad.py +280 -0
  23. boris/config.py +785 -0
  24. boris/config_file.py +356 -0
  25. boris/connections.py +409 -0
  26. boris/converters.py +333 -0
  27. boris/converters_ui.py +225 -0
  28. boris/cooccurence.py +250 -0
  29. boris/core.py +5901 -0
  30. boris/core_qrc.py +15958 -0
  31. boris/core_ui.py +1107 -0
  32. boris/db_functions.py +324 -0
  33. boris/dev.py +134 -0
  34. boris/dialog.py +1108 -0
  35. boris/duration_widget.py +238 -0
  36. boris/edit_event.py +245 -0
  37. boris/edit_event_ui.py +233 -0
  38. boris/event_operations.py +1040 -0
  39. boris/events_cursor.py +61 -0
  40. boris/events_snapshots.py +596 -0
  41. boris/exclusion_matrix.py +141 -0
  42. boris/export_events.py +1006 -0
  43. boris/export_observation.py +1203 -0
  44. boris/external_processes.py +332 -0
  45. boris/geometric_measurement.py +941 -0
  46. boris/gui_utilities.py +135 -0
  47. boris/image_overlay.py +72 -0
  48. boris/import_observations.py +242 -0
  49. boris/ipc_mpv.py +325 -0
  50. boris/irr.py +634 -0
  51. boris/latency.py +244 -0
  52. boris/measurement_widget.py +161 -0
  53. boris/media_file.py +115 -0
  54. boris/menu_options.py +213 -0
  55. boris/modifier_coding_map_creator.py +1013 -0
  56. boris/modifiers_coding_map.py +157 -0
  57. boris/mpv.py +2016 -0
  58. boris/mpv2.py +2193 -0
  59. boris/observation.py +1453 -0
  60. boris/observation_operations.py +2538 -0
  61. boris/observation_ui.py +679 -0
  62. boris/observations_list.py +337 -0
  63. boris/otx_parser.py +442 -0
  64. boris/param_panel.py +201 -0
  65. boris/param_panel_ui.py +305 -0
  66. boris/player_dock_widget.py +198 -0
  67. boris/plot_data_module.py +536 -0
  68. boris/plot_events.py +634 -0
  69. boris/plot_events_rt.py +237 -0
  70. boris/plot_spectrogram_rt.py +316 -0
  71. boris/plot_waveform_rt.py +230 -0
  72. boris/plugins.py +431 -0
  73. boris/portion/__init__.py +31 -0
  74. boris/portion/const.py +95 -0
  75. boris/portion/dict.py +365 -0
  76. boris/portion/func.py +52 -0
  77. boris/portion/interval.py +581 -0
  78. boris/portion/io.py +181 -0
  79. boris/preferences.py +510 -0
  80. boris/preferences_ui.py +770 -0
  81. boris/project.py +2007 -0
  82. boris/project_functions.py +2041 -0
  83. boris/project_import_export.py +1096 -0
  84. boris/project_ui.py +794 -0
  85. boris/qrc_boris.py +10389 -0
  86. boris/qrc_boris5.py +2579 -0
  87. boris/select_modifiers.py +312 -0
  88. boris/select_observations.py +210 -0
  89. boris/select_subj_behav.py +286 -0
  90. boris/state_events.py +197 -0
  91. boris/subjects_pad.py +106 -0
  92. boris/synthetic_time_budget.py +290 -0
  93. boris/time_budget_functions.py +1136 -0
  94. boris/time_budget_widget.py +1039 -0
  95. boris/transitions.py +365 -0
  96. boris/utilities.py +1810 -0
  97. boris/version.py +24 -0
  98. boris/video_equalizer.py +159 -0
  99. boris/video_equalizer_ui.py +248 -0
  100. boris/video_operations.py +310 -0
  101. boris/view_df.py +104 -0
  102. boris/view_df_ui.py +75 -0
  103. boris/write_event.py +538 -0
  104. boris_behav_obs-9.7.7.dist-info/METADATA +139 -0
  105. boris_behav_obs-9.7.7.dist-info/RECORD +109 -0
  106. boris_behav_obs-9.7.7.dist-info/WHEEL +5 -0
  107. boris_behav_obs-9.7.7.dist-info/entry_points.txt +2 -0
  108. boris_behav_obs-9.7.7.dist-info/licenses/LICENSE.TXT +674 -0
  109. boris_behav_obs-9.7.7.dist-info/top_level.txt +1 -0
boris/ipc_mpv.py ADDED
@@ -0,0 +1,325 @@
1
+ """
2
+ BORIS
3
+ Behavioral Observation Research Interactive Software
4
+ Copyright 2012-2025 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
+ """
22
+
23
+ import socket
24
+ import json
25
+ import subprocess
26
+
27
+ import logging
28
+ import config as cfg
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ class IPC_MPV:
34
+ """
35
+ class for managing mpv through Inter Process Communication (IPC)
36
+ """
37
+
38
+ media_durations: list = []
39
+ cumul_media_durations: list = []
40
+ fps: list = []
41
+ _pause: bool = False
42
+
43
+ def __init__(self, socket_path: str = cfg.MPV_SOCKET, parent=None):
44
+ # print(f"{parent=}")
45
+ self.socket_path = socket_path
46
+ self.process = None
47
+ # self.sock = None
48
+ self.init_mpv()
49
+ # self.init_socket()
50
+
51
+ def init_mpv(self):
52
+ """
53
+ Start mpv process and embed it in the PySide6 application.
54
+ """
55
+ logger.info("Start mpv ipc process")
56
+ # print(f"{self.winId()=}")
57
+ self.process = subprocess.Popen(
58
+ [
59
+ "mpv",
60
+ "--ontop",
61
+ "--no-border",
62
+ "--osc=no", # no on screen commands
63
+ "--input-ipc-server=" + self.socket_path,
64
+ # "--wid=" + str(int(self.winId())), # Embed in the widget
65
+ "--idle=yes", # Keeps mpv running with no video
66
+ "--keep-open=always",
67
+ "--input-default-bindings=no",
68
+ "--input-vo-keyboard=no",
69
+ ],
70
+ stdout=subprocess.PIPE,
71
+ stderr=subprocess.PIPE,
72
+ )
73
+
74
+ def send_command(self, command):
75
+ """
76
+ Send a JSON command to the mpv IPC server.
77
+ """
78
+ # print(f"send command: {command}")
79
+ try:
80
+ # Create a Unix socket
81
+ with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
82
+ # Connect to the MPV IPC server
83
+ client.connect(self.socket_path)
84
+ # Send the JSON command
85
+ # print(f"{json.dumps(command).encode('utf-8')=}")
86
+ client.sendall(json.dumps(command).encode("utf-8") + b"\n")
87
+ # Receive the response
88
+ response = client.recv(2000)
89
+
90
+ # print(f"{response=}")
91
+ # Parse the response as JSON
92
+ response_data = json.loads(response.decode("utf-8"))
93
+ if response_data["error"] != "success":
94
+ logging.warning(f"send command: {command} response data: {response_data}")
95
+ # Return the 'data' field which contains the playback position
96
+ return response_data.get("data")
97
+ except FileNotFoundError:
98
+ logger.critical("Error: Socket file not found.")
99
+ except Exception as e:
100
+ logger.critical(f"An error occurred: {e}")
101
+ return None
102
+
103
+ @property
104
+ def time_pos(self):
105
+ time_pos = self.send_command({"command": ["get_property", "time-pos"]})
106
+ return time_pos
107
+
108
+ @property
109
+ def duration(self):
110
+ duration_ = self.send_command({"command": ["get_property", "duration"]})
111
+ return duration_
112
+
113
+ @property
114
+ def video_zoom(self):
115
+ return self.send_command({"command": ["get_property", "video-zoom"]})
116
+
117
+ @video_zoom.setter
118
+ def video_zoom(self, value):
119
+ self.send_command({"command": ["set_property", "video-zoom", value]})
120
+ return
121
+
122
+ @property
123
+ def pause(self):
124
+ return self.send_command({"command": ["get_property", "pause"]})
125
+
126
+ @pause.setter
127
+ def pause(self, value):
128
+ return self.send_command({"command": ["set_property", "pause", value]})
129
+
130
+ @property
131
+ def estimated_frame_number(self):
132
+ return self.send_command({"command": ["get_property", "estimated-frame-number"]})
133
+
134
+ def stop(self):
135
+ self.send_command({"command": ["stop"]})
136
+ return
137
+
138
+ @property
139
+ def playlist(self):
140
+ return self.send_command({"command": ["get_property", "playlist"]})
141
+
142
+ def playlist_next(self):
143
+ self.send_command({"command": ["playlist-next"]})
144
+ return
145
+
146
+ def playlist_prev(self):
147
+ self.send_command({"command": ["playlist-prev"]})
148
+ return
149
+
150
+ @property
151
+ def playlist_pos(self):
152
+ return self.send_command({"command": ["get_property", "playlist-pos"]})
153
+
154
+ @playlist_pos.setter
155
+ def playlist_pos(self, value):
156
+ return self.send_command({"command": ["set_property", "playlist-pos", value]})
157
+
158
+ @property
159
+ def playlist_count(self):
160
+ return self.send_command({"command": ["get_property", "playlist-count"]})
161
+
162
+ def playlist_append(self, media):
163
+ return self.send_command({"command": ["loadfile", media, "append"]})
164
+
165
+ def wait_until_playing(self):
166
+ return
167
+
168
+ def seek(self, value, mode: str):
169
+ self.send_command({"command": ["seek", value, mode]})
170
+ return
171
+
172
+ @property
173
+ def playback_time(self):
174
+ playback_time_ = self.send_command({"command": ["get_property", "playback-time"]})
175
+ return playback_time_
176
+
177
+ def frame_step(self):
178
+ self.send_command({"command": ["frame-step"]})
179
+ return
180
+
181
+ def frame_back_step(self):
182
+ self.send_command({"command": ["frame-back-step"]})
183
+ return
184
+
185
+ def screenshot_to_file(self, value):
186
+ self.send_command({"command": ["screenshot-to-file", value, "video"]})
187
+ return
188
+
189
+ @property
190
+ def speed(self):
191
+ return self.send_command({"command": ["get_property", "speed"]})
192
+
193
+ @speed.setter
194
+ def speed(self, value):
195
+ self.send_command({"command": ["set_property", "speed", value]})
196
+ return
197
+
198
+ @property
199
+ def video_rotate(self):
200
+ return self.send_command({"command": ["get_property", "video-rotate"]})
201
+
202
+ @video_rotate.setter
203
+ def video_rotate(self, value):
204
+ self.send_command({"command": ["set_property", "video-rotate", value]})
205
+ return
206
+
207
+ @property
208
+ def sub_visibility(self):
209
+ return self.send_command({"command": ["get_property", "sub-visibility"]})
210
+
211
+ @sub_visibility.setter
212
+ def sub_visibility(self, value):
213
+ self.send_command({"command": ["set_property", "sub-visibility", value]})
214
+ return
215
+
216
+ @property
217
+ def brightness(self):
218
+ return self.send_command({"command": ["get_property", "brightness"]})
219
+
220
+ @brightness.setter
221
+ def brightness(self, value):
222
+ self.send_command({"command": ["set_property", "brightness", value]})
223
+ return
224
+
225
+ @property
226
+ def contrast(self):
227
+ return self.send_command({"command": ["get_property", "contrast"]})
228
+
229
+ @contrast.setter
230
+ def contrast(self, value):
231
+ self.send_command({"command": ["set_property", "contrast", value]})
232
+ return
233
+
234
+ @property
235
+ def saturation(self):
236
+ return self.send_command({"command": ["get_property", "saturation"]})
237
+
238
+ @saturation.setter
239
+ def saturation(self, value):
240
+ self.send_command({"command": ["set_property", "saturation", value]})
241
+ return
242
+
243
+ @property
244
+ def gamma(self):
245
+ return self.send_command({"command": ["get_property", "gamma"]})
246
+
247
+ @gamma.setter
248
+ def gamma(self, value):
249
+ self.send_command({"command": ["set_property", "gamma", value]})
250
+ return
251
+
252
+ @property
253
+ def hue(self):
254
+ return self.send_command({"command": ["get_property", "hue"]})
255
+
256
+ @hue.setter
257
+ def hue(self, value):
258
+ self.send_command({"command": ["set_property", "hue", value]})
259
+ return
260
+
261
+ @property
262
+ def container_fps(self):
263
+ return self.send_command({"command": ["get_property", "container-fps"]})
264
+
265
+ @property
266
+ def width(self):
267
+ return self.send_command({"command": ["get_property", "width"]})
268
+
269
+ @property
270
+ def height(self):
271
+ return self.send_command({"command": ["get_property", "height"]})
272
+
273
+ @property
274
+ def video_format(self):
275
+ return self.send_command({"command": ["get_property", "video-format"]})
276
+
277
+ @property
278
+ def deinterlace(self):
279
+ return self.send_command({"command": ["get_property", "deinterlace"]})
280
+
281
+ @deinterlace.setter
282
+ def deinterlace(self, value):
283
+ self.send_command({"command": ["set_property", "deinterlace", value]})
284
+ return
285
+
286
+ @property
287
+ def audio_bitrate(self):
288
+ return self.send_command({"command": ["get_property", "audio-bitrate"]})
289
+
290
+ @property
291
+ def eof_reached(self):
292
+ return self.send_command({"command": ["get_property", "eof-reached"]})
293
+
294
+ @property
295
+ def core_idle(self):
296
+ return self.send_command({"command": ["get_property", "core-idle"]})
297
+
298
+ @property
299
+ def video_pan_x(self):
300
+ return self.send_command({"command": ["get_property", "video-pan-x"]})
301
+
302
+ @video_pan_x.setter
303
+ def video_pan_x(self, value):
304
+ self.send_command({"command": ["set_property", "video-pan-x", value]})
305
+ return
306
+
307
+ @property
308
+ def video_pan_y(self):
309
+ return self.send_command({"command": ["get_property", "video-pan-y"]})
310
+
311
+ @video_pan_y.setter
312
+ def video_pan_y(self, value):
313
+ self.send_command({"command": ["set_property", "video-pan-y", value]})
314
+ return
315
+
316
+ """
317
+ @property
318
+ def xxx(self):
319
+ return self.send_command({"command": ["get_property", "xxx"]})
320
+
321
+ @xxx.setter
322
+ def xxx(self, value):
323
+ self.send_command({"command": ["set_property", "xxx", value]})
324
+ return
325
+ """