boris-behav-obs 8.9.16__py3-none-any.whl → 9.7.6__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 (129) hide show
  1. boris/__init__.py +1 -1
  2. boris/__main__.py +1 -1
  3. boris/about.py +36 -39
  4. boris/add_modifier.py +122 -109
  5. boris/add_modifier_ui.py +239 -135
  6. boris/advanced_event_filtering.py +81 -45
  7. boris/analysis_plugins/__init__.py +0 -0
  8. boris/analysis_plugins/_latency.py +59 -0
  9. boris/analysis_plugins/irr_cohen_kappa.py +109 -0
  10. boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
  11. boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
  12. boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
  13. boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
  14. boris/analysis_plugins/number_of_occurences.py +22 -0
  15. boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
  16. boris/analysis_plugins/time_budget.py +61 -0
  17. boris/behav_coding_map_creator.py +228 -229
  18. boris/behavior_binary_table.py +33 -50
  19. boris/behaviors_coding_map.py +17 -18
  20. boris/boris_cli.py +6 -25
  21. boris/cmd_arguments.py +12 -1
  22. boris/coding_pad.py +42 -49
  23. boris/config.py +161 -77
  24. boris/config_file.py +63 -83
  25. boris/connections.py +112 -57
  26. boris/converters.py +13 -37
  27. boris/converters_ui.py +187 -110
  28. boris/cooccurence.py +250 -0
  29. boris/core.py +2511 -1824
  30. boris/core_qrc.py +15895 -10185
  31. boris/core_ui.py +946 -792
  32. boris/db_functions.py +21 -41
  33. boris/dev.py +134 -0
  34. boris/dialog.py +505 -244
  35. boris/duration_widget.py +15 -20
  36. boris/edit_event.py +84 -28
  37. boris/edit_event_ui.py +214 -78
  38. boris/event_operations.py +517 -415
  39. boris/events_cursor.py +25 -17
  40. boris/events_snapshots.py +36 -82
  41. boris/exclusion_matrix.py +4 -9
  42. boris/export_events.py +213 -583
  43. boris/export_observation.py +98 -611
  44. boris/external_processes.py +156 -97
  45. boris/geometric_measurement.py +652 -287
  46. boris/gui_utilities.py +91 -14
  47. boris/image_overlay.py +9 -9
  48. boris/import_observations.py +190 -98
  49. boris/ipc_mpv.py +325 -0
  50. boris/irr.py +26 -63
  51. boris/latency.py +34 -25
  52. boris/measurement_widget.py +14 -18
  53. boris/media_file.py +52 -84
  54. boris/menu_options.py +17 -6
  55. boris/modifier_coding_map_creator.py +1013 -0
  56. boris/modifiers_coding_map.py +7 -9
  57. boris/mpv.py +1 -0
  58. boris/mpv2.py +732 -705
  59. boris/observation.py +655 -310
  60. boris/observation_operations.py +1036 -404
  61. boris/observation_ui.py +584 -356
  62. boris/observations_list.py +71 -53
  63. boris/otx_parser.py +74 -80
  64. boris/param_panel.py +31 -16
  65. boris/param_panel_ui.py +254 -138
  66. boris/player_dock_widget.py +90 -60
  67. boris/plot_data_module.py +43 -46
  68. boris/plot_events.py +127 -90
  69. boris/plot_events_rt.py +17 -31
  70. boris/plot_spectrogram_rt.py +95 -30
  71. boris/plot_waveform_rt.py +32 -21
  72. boris/plugins.py +431 -0
  73. boris/portion/__init__.py +18 -8
  74. boris/portion/const.py +35 -18
  75. boris/portion/dict.py +5 -5
  76. boris/portion/func.py +2 -2
  77. boris/portion/interval.py +21 -41
  78. boris/portion/io.py +41 -32
  79. boris/preferences.py +306 -83
  80. boris/preferences_ui.py +685 -228
  81. boris/project.py +448 -293
  82. boris/project_functions.py +689 -254
  83. boris/project_import_export.py +213 -222
  84. boris/project_ui.py +674 -438
  85. boris/qrc_boris.py +6 -3
  86. boris/qrc_boris5.py +6 -3
  87. boris/select_modifiers.py +74 -48
  88. boris/select_observations.py +20 -199
  89. boris/select_subj_behav.py +67 -39
  90. boris/state_events.py +53 -37
  91. boris/subjects_pad.py +6 -9
  92. boris/synthetic_time_budget.py +45 -28
  93. boris/time_budget_functions.py +171 -171
  94. boris/time_budget_widget.py +84 -114
  95. boris/transitions.py +41 -47
  96. boris/utilities.py +766 -266
  97. boris/version.py +3 -3
  98. boris/video_equalizer.py +16 -14
  99. boris/video_equalizer_ui.py +199 -130
  100. boris/video_operations.py +125 -28
  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.6.dist-info/METADATA +139 -0
  105. boris_behav_obs-9.7.6.dist-info/RECORD +109 -0
  106. {boris_behav_obs-8.9.16.dist-info → boris_behav_obs-9.7.6.dist-info}/WHEEL +1 -1
  107. boris_behav_obs-9.7.6.dist-info/entry_points.txt +2 -0
  108. boris/README.TXT +0 -22
  109. boris/add_modifier.ui +0 -323
  110. boris/boris_ui.py +0 -886
  111. boris/converters.ui +0 -289
  112. boris/core.qrc +0 -35
  113. boris/core.ui +0 -1543
  114. boris/edit_event.ui +0 -175
  115. boris/icons/logo_eye.ico +0 -0
  116. boris/map_creator.py +0 -850
  117. boris/observation.ui +0 -773
  118. boris/param_panel.ui +0 -379
  119. boris/preferences.ui +0 -537
  120. boris/project.ui +0 -1069
  121. boris/project_server.py +0 -236
  122. boris/vlc.py +0 -10343
  123. boris/vlc_local.py +0 -90
  124. boris_behav_obs-8.9.16.dist-info/LICENSE.TXT +0 -674
  125. boris_behav_obs-8.9.16.dist-info/METADATA +0 -129
  126. boris_behav_obs-8.9.16.dist-info/RECORD +0 -108
  127. boris_behav_obs-8.9.16.dist-info/entry_points.txt +0 -2
  128. {boris → boris_behav_obs-9.7.6.dist-info/licenses}/LICENSE.TXT +0 -0
  129. {boris_behav_obs-8.9.16.dist-info → boris_behav_obs-9.7.6.dist-info}/top_level.txt +0 -0
boris/project_server.py DELETED
@@ -1,236 +0,0 @@
1
- """
2
- BORIS
3
- Behavioral Observation Research Interactive Software
4
- Copyright 2012-2023 Olivier Friard
5
-
6
-
7
- This program is free software; you can redistribute it and/or modify
8
- 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.
11
-
12
- This program is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- 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.
21
-
22
- """
23
-
24
- import datetime
25
- import json
26
- import logging
27
- import socket
28
-
29
- from PyQt5.QtCore import Qt, QThread, pyqtSignal
30
- from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit, QListWidgetItem
31
-
32
- from . import config as cfg
33
- from . import dialog
34
- from . import utilities as util
35
-
36
-
37
- class ProjectServerThread(QThread):
38
- """
39
- thread for serving project to BORIS mobile app
40
- """
41
-
42
- signal = pyqtSignal(dict)
43
-
44
- def __init__(self, message):
45
- QThread.__init__(self)
46
- self.message = message
47
-
48
- def __del__(self):
49
- self.wait()
50
-
51
- def run(self):
52
-
53
- BUFFER_SIZE = 1024
54
-
55
- s = socket.socket()
56
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
57
- s.settimeout(1800)
58
-
59
- s.bind((util.get_ip_address(), 0))
60
- self.signal.emit({"URL": f"{s.getsockname()[0]}:{s.getsockname()[1]}"})
61
-
62
- s.listen(5)
63
- while 1:
64
- try:
65
- c, addr = s.accept()
66
-
67
- logging.debug(f"Got connection from {addr}")
68
-
69
- except socket.timeout:
70
- s.close()
71
-
72
- logging.debug("Project server timeout")
73
-
74
- self.signal.emit({"MESSAGE": "Project server timeout"})
75
- return
76
-
77
- rq = c.recv(BUFFER_SIZE)
78
-
79
- logging.debug(f"request: {rq}")
80
-
81
- if rq == b"get":
82
- msg = self.message
83
- while msg:
84
- c.send(msg[0:BUFFER_SIZE])
85
- msg = msg[BUFFER_SIZE:]
86
- c.close()
87
-
88
- logging.debug("Project sent")
89
-
90
- self.signal.emit({"MESSAGE": f"Project sent to {addr[0]}"})
91
-
92
- if rq == b"stop":
93
- c.close()
94
-
95
- logging.debug("server stopped")
96
-
97
- self.signal.emit({"MESSAGE": "The server is now stopped"})
98
- return
99
-
100
- # receive an observation
101
- if rq == b"put":
102
- c.send(b"SEND")
103
- c.close()
104
- c2, addr = s.accept()
105
- rq2 = b""
106
- while 1:
107
- d = c2.recv(BUFFER_SIZE)
108
- if d:
109
- rq2 += d
110
- if rq2.endswith(b"#####"):
111
- break
112
- else:
113
- break
114
- c2.close()
115
- self.signal.emit({"RECEIVED": f"{rq2.decode('utf-8')}", "SENDER": addr})
116
-
117
-
118
- def send_project_via_socket(self):
119
- """
120
- send project to a device via socket
121
- """
122
-
123
- def receive_signal(msg_dict):
124
-
125
- if "RECEIVED" in msg_dict:
126
- try:
127
- sent_obs = json.loads(msg_dict["RECEIVED"][:-5]) # cut final
128
- except Exception:
129
- logging.debug("error receiving observation")
130
- del self.w
131
- self.actionSend_project.setText("Project server")
132
- return
133
-
134
- logging.debug(f"decoded {type(sent_obs)} length: {len(sent_obs)}")
135
-
136
- flag_msg = False
137
- mem_obsid = ""
138
- for obsId in sent_obs:
139
-
140
- self.w.lwi.addItem(
141
- QListWidgetItem(f"{datetime.datetime.now().isoformat()}: Observation {obsId} received")
142
- )
143
- self.w.lwi.scrollToBottom()
144
-
145
- if obsId in self.pj[cfg.OBSERVATIONS]:
146
- flag_msg = True
147
- response = dialog.MessageDialog(
148
- cfg.programName,
149
- (
150
- f"An observation with the same id<br><b>{obsId}</b><br>"
151
- f"received from<br><b>{msg_dict['SENDER'][0]}</b><br>"
152
- "already exists in the current project."
153
- ),
154
- [cfg.OVERWRITE, "Rename received observation", cfg.CANCEL],
155
- )
156
-
157
- if response == cfg.CANCEL:
158
- return
159
- self.project_changed()
160
- if response == cfg.OVERWRITE:
161
- self.pj[cfg.OBSERVATIONS][obsId] = dict(sent_obs[obsId])
162
-
163
- if response == "Rename received observation":
164
- new_id = obsId
165
- while new_id in self.pj[cfg.OBSERVATIONS]:
166
- new_id, ok = QInputDialog.getText(
167
- self,
168
- f"Rename observation received from {msg_dict['SENDER'][0]}",
169
- "New observation id:",
170
- QLineEdit.Normal,
171
- new_id,
172
- )
173
-
174
- self.pj[cfg.OBSERVATIONS][new_id] = dict(sent_obs[obsId])
175
-
176
- else:
177
- self.pj[cfg.OBSERVATIONS][obsId] = dict(sent_obs[obsId])
178
- self.project_changed()
179
- mem_obsid = obsId
180
-
181
- elif "URL" in msg_dict:
182
- self.tcp_port = int(msg_dict["URL"].split(":")[-1])
183
- self.w.label.setText(f"Project server URL:<br><b>{msg_dict['URL']}</b><br><br>Timeout: 30 minutes")
184
-
185
- else:
186
- if "stopped" in msg_dict["MESSAGE"] or "timeout" in msg_dict["MESSAGE"]:
187
- del self.w
188
- self.actionSend_project.setText("Project server")
189
- else:
190
- self.w.lwi.addItem(QListWidgetItem(f"{datetime.datetime.now().isoformat()}: {msg_dict['MESSAGE']}"))
191
- self.w.lwi.scrollToBottom()
192
-
193
- if "server" in self.actionSend_project.text():
194
-
195
- include_obs = cfg.NO
196
- if self.pj[cfg.OBSERVATIONS]:
197
- include_obs = dialog.MessageDialog(cfg.programName, "Include observations?", [cfg.YES, cfg.NO, cfg.CANCEL])
198
- if include_obs == cfg.CANCEL:
199
- return
200
-
201
- self.w = dialog.Info_widget()
202
- self.w.resize(450, 100)
203
- self.w.setWindowFlags(Qt.WindowStaysOnTopHint)
204
- self.w.setWindowTitle("Project server")
205
- self.w.label.setText("")
206
- self.w.show()
207
- QApplication.processEvents()
208
-
209
- cp_project = dict(self.pj)
210
- if include_obs == cfg.NO:
211
- cp_project[cfg.OBSERVATIONS] = {}
212
-
213
- self.server_thread = ProjectServerThread(
214
- message=str.encode(
215
- str(json.dumps(cp_project, indent=None, separators=(",", ":"), default=util.decimal_default))
216
- )
217
- )
218
- self.server_thread.signal.connect(receive_signal)
219
-
220
- self.server_thread.start()
221
-
222
- self.actionSend_project.setText("Stop serving project")
223
-
224
- # send stop msg to project server
225
- elif "serving" in self.actionSend_project.text():
226
-
227
- s = socket.socket()
228
- s.connect((util.get_ip_address(), self.tcp_port))
229
- s.send(str.encode("stop"))
230
- received = ""
231
- while 1:
232
- data = s.recv(20) # BUFFER_SIZE = 20
233
- if not data:
234
- break
235
- received += data
236
- s.close