boris-behav-obs 8.12__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.
- boris/__init__.py +1 -1
- boris/__main__.py +1 -1
- boris/about.py +28 -39
- boris/add_modifier.py +122 -109
- boris/add_modifier_ui.py +239 -135
- boris/advanced_event_filtering.py +81 -45
- boris/analysis_plugins/__init__.py +0 -0
- boris/analysis_plugins/_latency.py +59 -0
- boris/analysis_plugins/irr_cohen_kappa.py +109 -0
- boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
- boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
- boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
- boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
- boris/analysis_plugins/number_of_occurences.py +22 -0
- boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
- boris/analysis_plugins/time_budget.py +61 -0
- boris/behav_coding_map_creator.py +228 -229
- boris/behavior_binary_table.py +33 -50
- boris/behaviors_coding_map.py +17 -18
- boris/boris_cli.py +6 -25
- boris/cmd_arguments.py +12 -1
- boris/coding_pad.py +42 -49
- boris/config.py +141 -65
- boris/config_file.py +58 -67
- boris/connections.py +107 -61
- boris/converters.py +13 -37
- boris/converters_ui.py +187 -110
- boris/cooccurence.py +250 -0
- boris/core.py +2373 -1786
- boris/core_qrc.py +15895 -10743
- boris/core_ui.py +943 -798
- boris/db_functions.py +17 -42
- boris/dev.py +109 -8
- boris/dialog.py +482 -236
- boris/duration_widget.py +9 -14
- boris/edit_event.py +61 -31
- boris/edit_event_ui.py +208 -97
- boris/event_operations.py +408 -293
- boris/events_cursor.py +25 -17
- boris/events_snapshots.py +36 -82
- boris/exclusion_matrix.py +4 -9
- boris/export_events.py +184 -223
- boris/export_observation.py +74 -100
- boris/external_processes.py +123 -98
- boris/geometric_measurement.py +644 -290
- boris/gui_utilities.py +91 -14
- boris/image_overlay.py +4 -4
- boris/import_observations.py +190 -98
- boris/ipc_mpv.py +325 -0
- boris/irr.py +20 -57
- boris/latency.py +31 -24
- boris/measurement_widget.py +14 -18
- boris/media_file.py +17 -19
- boris/menu_options.py +17 -6
- boris/modifier_coding_map_creator.py +1013 -0
- boris/modifiers_coding_map.py +7 -9
- boris/mpv.py +1 -0
- boris/mpv2.py +732 -705
- boris/observation.py +533 -221
- boris/observation_operations.py +1025 -390
- boris/observation_ui.py +572 -362
- boris/observations_list.py +71 -53
- boris/otx_parser.py +74 -68
- boris/param_panel.py +31 -16
- boris/param_panel_ui.py +254 -138
- boris/player_dock_widget.py +90 -60
- boris/plot_data_module.py +25 -33
- boris/plot_events.py +127 -90
- boris/plot_events_rt.py +17 -31
- boris/plot_spectrogram_rt.py +95 -30
- boris/plot_waveform_rt.py +32 -21
- boris/plugins.py +431 -0
- boris/portion/__init__.py +18 -8
- boris/portion/const.py +35 -18
- boris/portion/dict.py +5 -5
- boris/portion/func.py +2 -2
- boris/portion/interval.py +21 -41
- boris/portion/io.py +41 -32
- boris/preferences.py +306 -83
- boris/preferences_ui.py +684 -227
- boris/project.py +448 -293
- boris/project_functions.py +671 -238
- boris/project_import_export.py +213 -222
- boris/project_ui.py +674 -438
- boris/qrc_boris.py +6 -3
- boris/qrc_boris5.py +6 -3
- boris/select_modifiers.py +74 -48
- boris/select_observations.py +20 -198
- boris/select_subj_behav.py +67 -39
- boris/state_events.py +52 -35
- boris/subjects_pad.py +6 -9
- boris/synthetic_time_budget.py +45 -28
- boris/time_budget_functions.py +171 -171
- boris/time_budget_widget.py +84 -114
- boris/transitions.py +41 -47
- boris/utilities.py +627 -236
- boris/version.py +3 -3
- boris/video_equalizer.py +16 -14
- boris/video_equalizer_ui.py +199 -130
- boris/video_operations.py +95 -29
- boris/view_df.py +104 -0
- boris/view_df_ui.py +75 -0
- boris/write_event.py +538 -0
- boris_behav_obs-9.7.6.dist-info/METADATA +139 -0
- boris_behav_obs-9.7.6.dist-info/RECORD +109 -0
- {boris_behav_obs-8.12.dist-info → boris_behav_obs-9.7.6.dist-info}/WHEEL +1 -1
- boris_behav_obs-9.7.6.dist-info/entry_points.txt +2 -0
- boris/README.TXT +0 -22
- boris/add_modifier.ui +0 -323
- boris/converters.ui +0 -289
- boris/core.qrc +0 -36
- boris/core.ui +0 -1556
- boris/edit_event.ui +0 -233
- boris/icons/logo_eye.ico +0 -0
- boris/map_creator.py +0 -850
- boris/observation.ui +0 -814
- boris/param_panel.ui +0 -379
- boris/preferences.ui +0 -537
- boris/project.ui +0 -1069
- boris/project_server.py +0 -236
- boris/vlc.py +0 -10343
- boris/vlc_local.py +0 -90
- boris_behav_obs-8.12.dist-info/LICENSE.TXT +0 -674
- boris_behav_obs-8.12.dist-info/METADATA +0 -128
- boris_behav_obs-8.12.dist-info/RECORD +0 -108
- boris_behav_obs-8.12.dist-info/entry_points.txt +0 -3
- {boris → boris_behav_obs-9.7.6.dist-info/licenses}/LICENSE.TXT +0 -0
- {boris_behav_obs-8.12.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
|