boris-behav-obs 8.16.6__py3-none-any.whl → 9.7.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.
- boris/__init__.py +1 -1
- boris/__main__.py +1 -1
- boris/about.py +24 -40
- boris/add_modifier.py +88 -80
- boris/add_modifier_ui.py +235 -131
- boris/advanced_event_filtering.py +23 -29
- 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 +16 -34
- boris/config.py +108 -49
- boris/config_file.py +58 -67
- boris/connections.py +105 -58
- boris/converters.py +13 -37
- boris/converters_ui.py +187 -110
- boris/cooccurence.py +250 -0
- boris/core.py +2106 -1277
- boris/core_qrc.py +15892 -10829
- boris/core_ui.py +941 -806
- boris/db_functions.py +17 -42
- boris/dev.py +134 -0
- boris/dialog.py +461 -242
- boris/duration_widget.py +9 -14
- boris/edit_event.py +61 -31
- boris/edit_event_ui.py +208 -97
- boris/event_operations.py +405 -281
- boris/events_cursor.py +25 -17
- boris/events_snapshots.py +36 -82
- boris/exclusion_matrix.py +4 -9
- boris/export_events.py +180 -203
- boris/export_observation.py +60 -73
- boris/external_processes.py +123 -98
- boris/geometric_measurement.py +427 -218
- boris/gui_utilities.py +91 -14
- boris/image_overlay.py +4 -4
- boris/import_observations.py +190 -98
- boris/ipc_mpv.py +304 -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 +16 -6
- boris/modifier_coding_map_creator.py +1013 -0
- boris/modifiers_coding_map.py +7 -9
- boris/mpv2.py +127 -36
- boris/observation.py +493 -210
- boris/observation_operations.py +1010 -391
- boris/observation_ui.py +573 -363
- boris/observations_list.py +51 -58
- boris/otx_parser.py +74 -68
- boris/param_panel.py +45 -59
- boris/param_panel_ui.py +254 -138
- boris/player_dock_widget.py +91 -56
- boris/plot_data_module.py +18 -53
- boris/plot_events.py +56 -153
- boris/plot_events_rt.py +16 -30
- boris/plot_spectrogram_rt.py +80 -56
- boris/plot_waveform_rt.py +23 -48
- 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 +304 -123
- boris/preferences_ui.py +684 -227
- boris/project.py +293 -270
- boris/project_functions.py +618 -537
- boris/project_import_export.py +204 -213
- boris/project_ui.py +673 -441
- boris/qrc_boris.py +6 -3
- boris/qrc_boris5.py +6 -3
- boris/select_modifiers.py +62 -90
- boris/select_observations.py +19 -197
- boris/select_subj_behav.py +67 -39
- boris/state_events.py +51 -33
- boris/subjects_pad.py +6 -8
- boris/synthetic_time_budget.py +25 -17
- boris/time_budget_functions.py +169 -169
- boris/time_budget_widget.py +71 -86
- boris/transitions.py +41 -41
- boris/utilities.py +562 -222
- boris/version.py +3 -3
- boris/video_equalizer.py +16 -14
- boris/video_equalizer_ui.py +199 -130
- boris/video_operations.py +78 -28
- boris/view_df.py +104 -0
- boris/view_df_ui.py +75 -0
- boris/write_event.py +240 -136
- boris_behav_obs-9.7.2.dist-info/METADATA +140 -0
- boris_behav_obs-9.7.2.dist-info/RECORD +109 -0
- {boris_behav_obs-8.16.6.dist-info → boris_behav_obs-9.7.2.dist-info}/WHEEL +1 -1
- boris_behav_obs-9.7.2.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 -37
- boris/core.ui +0 -1571
- boris/edit_event.ui +0 -233
- boris/icons/logo_eye.ico +0 -0
- boris/map_creator.py +0 -982
- boris/observation.ui +0 -814
- boris/param_panel.ui +0 -379
- boris/preferences.ui +0 -537
- boris/project.ui +0 -1074
- boris/vlc_local.py +0 -90
- boris_behav_obs-8.16.6.dist-info/LICENSE.TXT +0 -674
- boris_behav_obs-8.16.6.dist-info/METADATA +0 -134
- boris_behav_obs-8.16.6.dist-info/RECORD +0 -106
- boris_behav_obs-8.16.6.dist-info/entry_points.txt +0 -2
- {boris → boris_behav_obs-9.7.2.dist-info/licenses}/LICENSE.TXT +0 -0
- {boris_behav_obs-8.16.6.dist-info → boris_behav_obs-9.7.2.dist-info}/top_level.txt +0 -0
boris/time_budget_functions.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
BORIS
|
|
3
3
|
Behavioral Observation Research Interactive Software
|
|
4
|
-
Copyright 2012-
|
|
4
|
+
Copyright 2012-2025 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
|
|
@@ -24,6 +24,9 @@ import statistics
|
|
|
24
24
|
from decimal import Decimal as dec
|
|
25
25
|
from typing import Tuple
|
|
26
26
|
import tablib
|
|
27
|
+
import logging
|
|
28
|
+
import itertools
|
|
29
|
+
import re
|
|
27
30
|
|
|
28
31
|
from . import config as cfg
|
|
29
32
|
from . import db_functions
|
|
@@ -32,14 +35,14 @@ from . import project_functions
|
|
|
32
35
|
from . import observation_operations
|
|
33
36
|
|
|
34
37
|
|
|
35
|
-
def default_value(ethogram: dict,
|
|
38
|
+
def default_value(ethogram: dict, behavior_code: str, param):
|
|
36
39
|
"""
|
|
37
40
|
return value for duration in case of point event
|
|
38
41
|
"""
|
|
39
42
|
default_value_ = 0.0
|
|
40
|
-
|
|
43
|
+
behavior_type = project_functions.event_type(behavior_code, ethogram)
|
|
41
44
|
|
|
42
|
-
if
|
|
45
|
+
if behavior_type in cfg.POINT_EVENT_TYPES and param in (
|
|
43
46
|
"duration",
|
|
44
47
|
"duration mean",
|
|
45
48
|
"duration stdev",
|
|
@@ -47,7 +50,7 @@ def default_value(ethogram: dict, behav: str, param):
|
|
|
47
50
|
):
|
|
48
51
|
default_value_ = cfg.NA
|
|
49
52
|
|
|
50
|
-
if
|
|
53
|
+
if behavior_type in cfg.STATE_EVENT_TYPES and param in (
|
|
51
54
|
"duration mean",
|
|
52
55
|
"duration stdev",
|
|
53
56
|
):
|
|
@@ -64,7 +67,6 @@ def init_behav_modif(ethogram: dict, selected_subjects: list, distinct_behav_mod
|
|
|
64
67
|
for subj in selected_subjects:
|
|
65
68
|
behaviors[subj] = {}
|
|
66
69
|
for behav_modif in distinct_behav_modif:
|
|
67
|
-
|
|
68
70
|
behav, modif = behav_modif
|
|
69
71
|
behav_modif_str = "|".join(behav_modif) if modif else behav
|
|
70
72
|
|
|
@@ -85,7 +87,6 @@ def init_behav_modif_bin(ethogram: dict, selected_subjects: list, distinct_behav
|
|
|
85
87
|
for subj in selected_subjects:
|
|
86
88
|
behaviors[subj] = {}
|
|
87
89
|
for behav_modif in distinct_behav_modif:
|
|
88
|
-
|
|
89
90
|
if behav_modif not in behaviors[subj]:
|
|
90
91
|
behaviors[subj][behav_modif] = {}
|
|
91
92
|
|
|
@@ -135,35 +136,24 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
135
136
|
"""
|
|
136
137
|
|
|
137
138
|
def interval_len(interval):
|
|
138
|
-
if interval.empty
|
|
139
|
-
return dec(0)
|
|
140
|
-
else:
|
|
141
|
-
return sum([x.upper - x.lower for x in interval])
|
|
139
|
+
return dec(0) if interval.empty else sum([x.upper - x.lower for x in interval])
|
|
142
140
|
|
|
143
141
|
def interval_number(interval):
|
|
144
|
-
if interval.empty
|
|
145
|
-
return dec(0)
|
|
146
|
-
else:
|
|
147
|
-
return len(interval)
|
|
142
|
+
return dec(0) if interval.empty else len(interval)
|
|
148
143
|
|
|
149
144
|
def interval_mean(interval):
|
|
150
|
-
if interval.empty
|
|
151
|
-
return dec(0)
|
|
152
|
-
else:
|
|
153
|
-
return sum([x.upper - x.lower for x in interval]) / len(interval)
|
|
145
|
+
return dec(0) if interval.empty else sum([x.upper - x.lower for x in interval]) / len(interval)
|
|
154
146
|
|
|
155
147
|
def interval_std_dev(interval) -> str:
|
|
156
148
|
if interval.empty:
|
|
157
|
-
return
|
|
149
|
+
return cfg.NA
|
|
158
150
|
else:
|
|
159
151
|
try:
|
|
160
152
|
return f"{statistics.stdev([x.upper - x.lower for x in interval]):.3f}"
|
|
161
153
|
except Exception:
|
|
162
154
|
return cfg.NA
|
|
163
155
|
|
|
164
|
-
selected_subjects = parameters_obs[cfg.SELECTED_SUBJECTS]
|
|
165
156
|
selected_behaviors = parameters_obs[cfg.SELECTED_BEHAVIORS]
|
|
166
|
-
include_modifiers = parameters_obs[cfg.INCLUDE_MODIFIERS]
|
|
167
157
|
time_interval = parameters_obs["time"]
|
|
168
158
|
start_time = parameters_obs[cfg.START_TIME]
|
|
169
159
|
end_time = parameters_obs[cfg.END_TIME]
|
|
@@ -183,14 +173,26 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
183
173
|
distinct_behav_modif = []
|
|
184
174
|
for obs_id in selected_observations:
|
|
185
175
|
for event in pj[cfg.OBSERVATIONS][obs_id][cfg.EVENTS]:
|
|
186
|
-
if
|
|
187
|
-
if
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
176
|
+
if parameters_obs[cfg.INCLUDE_MODIFIERS]:
|
|
177
|
+
if parameters_obs[cfg.EXCLUDE_NON_CODED_MODIFIERS]:
|
|
178
|
+
# get coded modifiers
|
|
179
|
+
if (
|
|
180
|
+
event[cfg.EVENT_BEHAVIOR_FIELD_IDX],
|
|
181
|
+
event[cfg.EVENT_MODIFIER_FIELD_IDX],
|
|
182
|
+
) not in distinct_behav_modif:
|
|
183
|
+
distinct_behav_modif.append((event[cfg.EVENT_BEHAVIOR_FIELD_IDX], event[cfg.EVENT_MODIFIER_FIELD_IDX]))
|
|
184
|
+
else:
|
|
185
|
+
# get all modifiers combination
|
|
186
|
+
ms: list = []
|
|
187
|
+
modifiers_list = project_functions.get_modifiers_of_behavior(pj[cfg.ETHOGRAM], event[cfg.EVENT_BEHAVIOR_FIELD_IDX])
|
|
188
|
+
if modifiers_list:
|
|
189
|
+
for modif_set in modifiers_list[0]:
|
|
190
|
+
modif_set.append("None")
|
|
191
|
+
ms.append([re.sub(r" \(.*\)", "", x) for x in modif_set])
|
|
192
|
+
distinct_modifiers = ["|".join(x) for x in itertools.product(*ms)]
|
|
193
|
+
for modifier in distinct_modifiers:
|
|
194
|
+
distinct_behav_modif.append((event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modifier))
|
|
195
|
+
|
|
194
196
|
else:
|
|
195
197
|
if (event[cfg.EVENT_BEHAVIOR_FIELD_IDX], "") not in distinct_behav_modif:
|
|
196
198
|
distinct_behav_modif.append((event[cfg.EVENT_BEHAVIOR_FIELD_IDX], ""))
|
|
@@ -212,7 +214,7 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
212
214
|
behav_header[1] = "Behaviors:"
|
|
213
215
|
modif_header[1] = "Modifiers:"
|
|
214
216
|
|
|
215
|
-
for subj in
|
|
217
|
+
for subj in parameters_obs[cfg.SELECTED_SUBJECTS]:
|
|
216
218
|
for behavior_modifiers in distinct_behav_modif:
|
|
217
219
|
behavior, modifiers = behavior_modifiers
|
|
218
220
|
behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior
|
|
@@ -224,19 +226,16 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
224
226
|
|
|
225
227
|
data_report.append(subj_header)
|
|
226
228
|
data_report.append(behav_header)
|
|
227
|
-
if
|
|
229
|
+
if parameters_obs[cfg.INCLUDE_MODIFIERS]:
|
|
228
230
|
data_report.append(modif_header)
|
|
229
231
|
data_report.append(param_header)
|
|
230
232
|
|
|
231
233
|
state_events_list = [
|
|
232
|
-
pj[cfg.ETHOGRAM][x][cfg.BEHAVIOR_CODE]
|
|
233
|
-
for x in pj[cfg.ETHOGRAM]
|
|
234
|
-
if cfg.STATE in pj[cfg.ETHOGRAM][x][cfg.TYPE].upper()
|
|
234
|
+
pj[cfg.ETHOGRAM][x][cfg.BEHAVIOR_CODE] for x in pj[cfg.ETHOGRAM] if cfg.STATE in pj[cfg.ETHOGRAM][x][cfg.TYPE].upper()
|
|
235
235
|
]
|
|
236
236
|
# select time interval
|
|
237
237
|
for obs_id in selected_observations:
|
|
238
|
-
|
|
239
|
-
behaviors = init_behav_modif_bin(pj[cfg.ETHOGRAM], selected_subjects, distinct_behav_modif, parameters)
|
|
238
|
+
behaviors = init_behav_modif_bin(pj[cfg.ETHOGRAM], parameters_obs[cfg.SELECTED_SUBJECTS], distinct_behav_modif, parameters)
|
|
240
239
|
|
|
241
240
|
obs_length = observation_operations.observation_total_length(pj[cfg.OBSERVATIONS][obs_id])
|
|
242
241
|
|
|
@@ -260,6 +259,13 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
260
259
|
min_time = dec(start_time)
|
|
261
260
|
max_time = dec(end_time)
|
|
262
261
|
|
|
262
|
+
if time_interval == cfg.TIME_OBS_INTERVAL:
|
|
263
|
+
obs_interval = pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])
|
|
264
|
+
offset = pj[cfg.OBSERVATIONS][obs_id][cfg.TIME_OFFSET]
|
|
265
|
+
min_time = dec(obs_interval[0]) + offset
|
|
266
|
+
# Use max media duration for max time if no interval is defined (=0)
|
|
267
|
+
max_time = dec(obs_interval[1]) + offset if obs_interval[1] != 0 else dec(obs_length)
|
|
268
|
+
|
|
263
269
|
events_interval = {}
|
|
264
270
|
mem_events_interval = {}
|
|
265
271
|
|
|
@@ -269,13 +275,13 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
269
275
|
else:
|
|
270
276
|
current_subject = event[cfg.EVENT_SUBJECT_FIELD_IDX]
|
|
271
277
|
|
|
272
|
-
if current_subject not in
|
|
278
|
+
if current_subject not in parameters_obs[cfg.SELECTED_SUBJECTS]:
|
|
273
279
|
continue
|
|
274
280
|
if current_subject not in events_interval:
|
|
275
281
|
events_interval[current_subject] = {}
|
|
276
282
|
mem_events_interval[current_subject] = {}
|
|
277
283
|
|
|
278
|
-
if
|
|
284
|
+
if parameters_obs[cfg.INCLUDE_MODIFIERS]:
|
|
279
285
|
modif = event[cfg.EVENT_MODIFIER_FIELD_IDX]
|
|
280
286
|
else:
|
|
281
287
|
modif = ""
|
|
@@ -287,9 +293,7 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
287
293
|
mem_events_interval[current_subject][(event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modif)] = []
|
|
288
294
|
|
|
289
295
|
if event[cfg.EVENT_BEHAVIOR_FIELD_IDX] in state_events_list:
|
|
290
|
-
mem_events_interval[current_subject][(event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modif)].append(
|
|
291
|
-
event[cfg.EVENT_TIME_FIELD_IDX]
|
|
292
|
-
)
|
|
296
|
+
mem_events_interval[current_subject][(event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modif)].append(event[cfg.EVENT_TIME_FIELD_IDX])
|
|
293
297
|
if len(mem_events_interval[current_subject][(event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modif)]) == 2:
|
|
294
298
|
events_interval[current_subject][(event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modif)] |= I.closedopen(
|
|
295
299
|
mem_events_interval[current_subject][(event[cfg.EVENT_BEHAVIOR_FIELD_IDX], modif)][0],
|
|
@@ -311,9 +315,7 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
311
315
|
time_bin_end = max_time
|
|
312
316
|
|
|
313
317
|
while True:
|
|
314
|
-
|
|
315
318
|
for subject in events_interval:
|
|
316
|
-
|
|
317
319
|
# check behavior to exclude from total time
|
|
318
320
|
time_to_subtract = 0
|
|
319
321
|
if cfg.EXCLUDED_BEHAVIORS in parameters_obs:
|
|
@@ -323,33 +325,32 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
323
325
|
time_to_subtract += interval_len(interval_intersec)
|
|
324
326
|
|
|
325
327
|
for behav in events_interval[subject]:
|
|
326
|
-
|
|
327
328
|
interval_intersec = events_interval[subject][behav] & I.closed(time_bin_start, time_bin_end)
|
|
328
329
|
|
|
329
330
|
nocc = interval_number(interval_intersec)
|
|
330
331
|
behaviors[subject][behav]["number"] = nocc
|
|
331
332
|
|
|
332
333
|
behav_type = project_functions.event_type(behav[0], pj[cfg.ETHOGRAM])
|
|
333
|
-
if behav_type
|
|
334
|
+
if behav_type in cfg.STATE_EVENT_TYPES:
|
|
334
335
|
dur = interval_len(interval_intersec)
|
|
335
336
|
behaviors[subject][behav]["duration"] = f"{dur:.3f}"
|
|
336
337
|
behaviors[subject][behav]["duration mean"] = f"{interval_mean(interval_intersec):.3f}"
|
|
337
338
|
behaviors[subject][behav]["duration stdev"] = interval_std_dev(interval_intersec)
|
|
338
339
|
|
|
339
340
|
if behav[0] in parameters_obs.get(cfg.EXCLUDED_BEHAVIORS, []):
|
|
340
|
-
proportion = dur / (
|
|
341
|
+
proportion = dur / (time_bin_end - time_bin_start)
|
|
341
342
|
else:
|
|
342
343
|
proportion = dur / ((time_bin_end - time_bin_start) - time_to_subtract)
|
|
343
344
|
behaviors[subject][behav]["proportion of time"] = f"{proportion:.3f}"
|
|
344
345
|
|
|
345
|
-
if behav_type
|
|
346
|
+
if behav_type in cfg.POINT_EVENT_TYPES:
|
|
346
347
|
behaviors[subject][behav]["duration"] = cfg.NA
|
|
347
348
|
behaviors[subject][behav]["duration mean"] = cfg.NA
|
|
348
349
|
behaviors[subject][behav]["duration stdev"] = cfg.NA
|
|
349
350
|
behaviors[subject][behav]["proportion of time"] = cfg.NA
|
|
350
351
|
|
|
351
352
|
columns = [obs_id, f"{max_time - min_time:.3f}", f"{time_bin_start:.3f}-{time_bin_end:.3f}"]
|
|
352
|
-
for subject in
|
|
353
|
+
for subject in parameters_obs[cfg.SELECTED_SUBJECTS]:
|
|
353
354
|
for behavior_modifiers in distinct_behav_modif:
|
|
354
355
|
behavior, modifiers = behavior_modifiers
|
|
355
356
|
behavior_modifiers_str = behavior_modifiers
|
|
@@ -385,12 +386,9 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
385
386
|
tablib.Dataset: dataset containing synthetic time budget data
|
|
386
387
|
"""
|
|
387
388
|
|
|
388
|
-
selected_subjects = parameters_obs[cfg.SELECTED_SUBJECTS]
|
|
389
|
-
selected_behaviors = parameters_obs[cfg.SELECTED_BEHAVIORS]
|
|
390
|
-
include_modifiers = parameters_obs[cfg.INCLUDE_MODIFIERS]
|
|
391
389
|
interval = parameters_obs["time"]
|
|
392
|
-
start_time = parameters_obs[
|
|
393
|
-
end_time = parameters_obs[
|
|
390
|
+
start_time = parameters_obs[cfg.START_TIME]
|
|
391
|
+
end_time = parameters_obs[cfg.END_TIME]
|
|
394
392
|
|
|
395
393
|
parameters = [
|
|
396
394
|
["duration", "Total duration"],
|
|
@@ -404,7 +402,7 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
404
402
|
data_report.title = "Synthetic time budget"
|
|
405
403
|
|
|
406
404
|
ok, msg, db_connector = db_functions.load_aggregated_events_in_db(
|
|
407
|
-
pj,
|
|
405
|
+
pj, parameters_obs[cfg.SELECTED_SUBJECTS], selected_observations, parameters_obs[cfg.SELECTED_BEHAVIORS]
|
|
408
406
|
)
|
|
409
407
|
|
|
410
408
|
if not ok:
|
|
@@ -413,20 +411,32 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
413
411
|
db_connector.create_aggregate("stdev", 1, StdevFunc)
|
|
414
412
|
cursor = db_connector.cursor()
|
|
415
413
|
|
|
416
|
-
# modifiers
|
|
417
|
-
if include_modifiers:
|
|
418
|
-
cursor.execute("SELECT distinct behavior, modifiers FROM aggregated_events")
|
|
419
|
-
distinct_behav_modif = [[rows["behavior"], rows["modifiers"]] for rows in cursor.fetchall()]
|
|
420
|
-
else:
|
|
421
|
-
cursor.execute("SELECT distinct behavior FROM aggregated_events")
|
|
422
|
-
distinct_behav_modif = [[rows["behavior"], ""] for rows in cursor.fetchall()]
|
|
423
|
-
|
|
424
414
|
# add selected behaviors that are not observed
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
415
|
+
distinct_behav_modif: list = []
|
|
416
|
+
for behavior in parameters_obs[cfg.SELECTED_BEHAVIORS]:
|
|
417
|
+
# modifiers
|
|
418
|
+
if parameters_obs[cfg.INCLUDE_MODIFIERS]:
|
|
419
|
+
if parameters_obs[cfg.EXCLUDE_NON_CODED_MODIFIERS]:
|
|
420
|
+
# get coded modifiers
|
|
421
|
+
cursor.execute("SELECT DISTINCT modifiers FROM aggregated_events WHERE behavior = ?", (behavior,))
|
|
422
|
+
for row in cursor.fetchall():
|
|
423
|
+
distinct_behav_modif.append((behavior, row["modifiers"]))
|
|
424
|
+
else:
|
|
425
|
+
# get all modifiers combination
|
|
426
|
+
ms: list = []
|
|
427
|
+
modifiers_list = project_functions.get_modifiers_of_behavior(pj[cfg.ETHOGRAM], behavior)
|
|
428
|
+
if modifiers_list:
|
|
429
|
+
for modif_set in modifiers_list[0]:
|
|
430
|
+
modif_set.append("None")
|
|
431
|
+
ms.append([re.sub(r" \(.*\)", "", x) for x in modif_set])
|
|
432
|
+
distinct_modifiers = ["|".join(x) for x in itertools.product(*ms)]
|
|
433
|
+
for modifier in distinct_modifiers:
|
|
434
|
+
distinct_behav_modif.append((behavior, modifier))
|
|
435
|
+
|
|
436
|
+
else:
|
|
437
|
+
distinct_behav_modif.append((behavior, ""))
|
|
428
438
|
|
|
429
|
-
|
|
439
|
+
# print(f"{distinct_behav_modif=}")
|
|
430
440
|
|
|
431
441
|
param_header = ["Observations id", "Total length (s)"]
|
|
432
442
|
subj_header, behav_header, modif_header = (
|
|
@@ -438,10 +448,10 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
438
448
|
behav_header[1] = "Behaviors:"
|
|
439
449
|
modif_header[1] = "Modifiers:"
|
|
440
450
|
|
|
441
|
-
for subj in
|
|
442
|
-
for
|
|
443
|
-
behavior, modifiers = behavior_modifiers
|
|
444
|
-
behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior
|
|
451
|
+
for subj in parameters_obs[cfg.SELECTED_SUBJECTS]:
|
|
452
|
+
for behavior, modifiers in distinct_behav_modif:
|
|
453
|
+
"""behavior, modifiers = behavior_modifiers"""
|
|
454
|
+
"""behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior"""
|
|
445
455
|
for param in parameters:
|
|
446
456
|
subj_header.append(subj)
|
|
447
457
|
behav_header.append(behavior)
|
|
@@ -450,17 +460,16 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
450
460
|
|
|
451
461
|
data_report.append(subj_header)
|
|
452
462
|
data_report.append(behav_header)
|
|
453
|
-
if
|
|
463
|
+
if parameters_obs[cfg.INCLUDE_MODIFIERS]:
|
|
454
464
|
data_report.append(modif_header)
|
|
455
465
|
data_report.append(param_header)
|
|
456
466
|
|
|
457
467
|
# select time interval
|
|
458
468
|
for obs_id in selected_observations:
|
|
459
|
-
|
|
460
|
-
behaviors = init_behav_modif(pj[cfg.ETHOGRAM], selected_subjects, distinct_behav_modif, parameters)
|
|
469
|
+
behaviors = init_behav_modif(pj[cfg.ETHOGRAM], parameters_obs[cfg.SELECTED_SUBJECTS], distinct_behav_modif, parameters)
|
|
461
470
|
|
|
462
471
|
ok, msg, db_connector = db_functions.load_aggregated_events_in_db(
|
|
463
|
-
pj,
|
|
472
|
+
pj, parameters_obs[cfg.SELECTED_SUBJECTS], [obs_id], parameters_obs[cfg.SELECTED_BEHAVIORS]
|
|
464
473
|
)
|
|
465
474
|
|
|
466
475
|
if not ok:
|
|
@@ -469,7 +478,7 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
469
478
|
db_connector.create_aggregate("stdev", 1, StdevFunc)
|
|
470
479
|
cursor = db_connector.cursor()
|
|
471
480
|
# if modifiers not to be included set modifiers to ""
|
|
472
|
-
if not
|
|
481
|
+
if not parameters_obs[cfg.INCLUDE_MODIFIERS]:
|
|
473
482
|
cursor.execute("UPDATE aggregated_events SET modifiers = ''")
|
|
474
483
|
|
|
475
484
|
# time
|
|
@@ -544,19 +553,14 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
544
553
|
),
|
|
545
554
|
)
|
|
546
555
|
|
|
547
|
-
for subject in
|
|
548
|
-
|
|
556
|
+
for subject in parameters_obs[cfg.SELECTED_SUBJECTS]:
|
|
549
557
|
# check if behaviors are to exclude from total time
|
|
550
558
|
time_to_subtract = 0
|
|
551
559
|
if obs_length != dec(-2): # obs not an images obs without time
|
|
552
560
|
if cfg.EXCLUDED_BEHAVIORS in parameters_obs:
|
|
553
561
|
for excluded_behav in parameters_obs[cfg.EXCLUDED_BEHAVIORS]:
|
|
554
562
|
cursor.execute(
|
|
555
|
-
(
|
|
556
|
-
"SELECT SUM(stop-start) "
|
|
557
|
-
"FROM aggregated_events "
|
|
558
|
-
"WHERE observation = ? AND subject = ? AND behavior = ? "
|
|
559
|
-
),
|
|
563
|
+
("SELECT SUM(stop-start) FROM aggregated_events WHERE observation = ? AND subject = ? AND behavior = ? "),
|
|
560
564
|
(
|
|
561
565
|
obs_id,
|
|
562
566
|
subject,
|
|
@@ -589,20 +593,15 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
589
593
|
)
|
|
590
594
|
|
|
591
595
|
for row in cursor.fetchall():
|
|
592
|
-
|
|
593
|
-
behaviors[subject][behavior_modifiers_str]["number"] = (
|
|
594
|
-
0 if row["n_occurences"] is None else row["n_occurences"]
|
|
595
|
-
)
|
|
596
|
+
behaviors[subject][behavior_modifiers_str]["number"] = 0 if row["n_occurences"] is None else row["n_occurences"]
|
|
596
597
|
|
|
597
598
|
if obs_length == dec(-2): # images obs without time
|
|
598
|
-
|
|
599
599
|
behaviors[subject][behavior_modifiers_str]["duration"] = cfg.NA
|
|
600
600
|
behaviors[subject][behavior_modifiers_str]["duration mean"] = cfg.NA
|
|
601
601
|
behaviors[subject][behavior_modifiers_str]["duration stdev"] = cfg.NA
|
|
602
602
|
behaviors[subject][behavior_modifiers_str]["proportion of time"] = cfg.NA
|
|
603
603
|
|
|
604
604
|
else:
|
|
605
|
-
|
|
606
605
|
if row["type"] == cfg.POINT:
|
|
607
606
|
behaviors[subject][behavior_modifiers_str]["duration"] = cfg.NA
|
|
608
607
|
behaviors[subject][behavior_modifiers_str]["duration mean"] = cfg.NA
|
|
@@ -632,16 +631,14 @@ def synthetic_time_budget(pj: dict, selected_observations: list, parameters_obs:
|
|
|
632
631
|
else:
|
|
633
632
|
# behavior subtracted
|
|
634
633
|
behaviors[subject][behavior_modifiers_str]["proportion of time"] = (
|
|
635
|
-
cfg.NA
|
|
636
|
-
if row["duration"] is None
|
|
637
|
-
else f"{row['duration'] / (max_time - min_time):.3f}"
|
|
634
|
+
cfg.NA if row["duration"] is None else f"{row['duration'] / (max_time - min_time):.3f}"
|
|
638
635
|
)
|
|
639
636
|
|
|
640
637
|
if obs_length == dec(-2):
|
|
641
638
|
columns = [obs_id, cfg.NA]
|
|
642
639
|
else:
|
|
643
640
|
columns = [obs_id, f"{max_time - min_time:0.3f}"]
|
|
644
|
-
for subj in
|
|
641
|
+
for subj in parameters_obs[cfg.SELECTED_SUBJECTS]:
|
|
645
642
|
for behavior_modifiers in distinct_behav_modif:
|
|
646
643
|
behavior, modifiers = behavior_modifiers
|
|
647
644
|
behavior_modifiers_str = "|".join(behavior_modifiers) if modifiers else behavior
|
|
@@ -666,39 +663,54 @@ def time_budget_analysis(
|
|
|
666
663
|
cursor: cursor on temporary database
|
|
667
664
|
selected_observations (list): selected observations
|
|
668
665
|
parameters (dict): parameters for analysis
|
|
669
|
-
by_category (bool): True for grouping in category else False
|
|
666
|
+
by_category (bool): True for grouping in behavioral category else False
|
|
670
667
|
|
|
671
668
|
Returns:
|
|
672
669
|
list: results
|
|
673
670
|
dict:
|
|
674
671
|
"""
|
|
675
672
|
|
|
673
|
+
logging.debug("time_budget_analysis function")
|
|
674
|
+
|
|
675
|
+
logging.debug(f"{selected_observations=}")
|
|
676
|
+
logging.debug(f"{parameters=}")
|
|
677
|
+
|
|
676
678
|
categories: dict = {}
|
|
677
679
|
out: list = []
|
|
678
680
|
for subject in parameters[cfg.SELECTED_SUBJECTS]:
|
|
679
|
-
|
|
681
|
+
logging.debug(f"{subject=}")
|
|
682
|
+
|
|
683
|
+
out_cat: list = []
|
|
684
|
+
categories[subject] = {}
|
|
680
685
|
|
|
681
686
|
for behavior in parameters[cfg.SELECTED_BEHAVIORS]:
|
|
687
|
+
logging.debug(f"{behavior=}")
|
|
682
688
|
|
|
683
689
|
if parameters[cfg.INCLUDE_MODIFIERS]: # with modifiers
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
"SELECT DISTINCT modifiers FROM events WHERE subject = ? AND code = ?", (subject, behavior)
|
|
687
|
-
|
|
688
|
-
|
|
690
|
+
if parameters[cfg.EXCLUDE_NON_CODED_MODIFIERS]:
|
|
691
|
+
# get coded modifiers
|
|
692
|
+
cursor.execute("SELECT DISTINCT modifiers FROM events WHERE subject = ? AND code = ?", (subject, behavior))
|
|
693
|
+
distinct_modifiers = [x[0] for x in cursor.fetchall()]
|
|
694
|
+
else:
|
|
695
|
+
# get all modifiers combinations
|
|
696
|
+
ms: list = []
|
|
697
|
+
modifiers_list = project_functions.get_modifiers_of_behavior(ethogram, behavior)
|
|
698
|
+
if modifiers_list:
|
|
699
|
+
for modif_set in modifiers_list[0]:
|
|
700
|
+
modif_set.append("None")
|
|
701
|
+
ms.append([re.sub(r" \(.*\)", "", x) for x in modif_set])
|
|
702
|
+
distinct_modifiers = ["|".join(x) for x in itertools.product(*ms)]
|
|
689
703
|
|
|
690
704
|
if not distinct_modifiers:
|
|
691
705
|
if not parameters[cfg.EXCLUDE_BEHAVIORS]:
|
|
692
|
-
|
|
693
|
-
if cfg.STATE in project_functions.event_type(behavior, ethogram):
|
|
694
|
-
|
|
706
|
+
if project_functions.event_type(behavior, ethogram) in cfg.STATE_EVENT_TYPES:
|
|
695
707
|
# check if observation from pictures
|
|
696
708
|
if parameters["start time"] == dec("0.000") and parameters["end time"] == dec("0.000"):
|
|
697
709
|
duration = cfg.NA
|
|
698
710
|
else:
|
|
699
711
|
duration = 0.000
|
|
700
712
|
|
|
701
|
-
|
|
713
|
+
out_cat.append(
|
|
702
714
|
{
|
|
703
715
|
"subject": subject,
|
|
704
716
|
"behavior": behavior,
|
|
@@ -712,7 +724,7 @@ def time_budget_analysis(
|
|
|
712
724
|
}
|
|
713
725
|
)
|
|
714
726
|
else: # point
|
|
715
|
-
|
|
727
|
+
out_cat.append(
|
|
716
728
|
{
|
|
717
729
|
"subject": subject,
|
|
718
730
|
"behavior": behavior,
|
|
@@ -727,8 +739,7 @@ def time_budget_analysis(
|
|
|
727
739
|
)
|
|
728
740
|
continue
|
|
729
741
|
|
|
730
|
-
if
|
|
731
|
-
|
|
742
|
+
if project_functions.event_type(behavior, ethogram) in cfg.POINT_EVENT_TYPES:
|
|
732
743
|
for modifier in distinct_modifiers:
|
|
733
744
|
cursor.execute(
|
|
734
745
|
(
|
|
@@ -738,26 +749,24 @@ def time_budget_analysis(
|
|
|
738
749
|
"AND modifiers = ? "
|
|
739
750
|
"ORDER BY observation, occurence"
|
|
740
751
|
),
|
|
741
|
-
(subject, behavior, modifier
|
|
752
|
+
(subject, behavior, modifier),
|
|
742
753
|
)
|
|
743
754
|
|
|
744
755
|
rows = cursor.fetchall()
|
|
745
756
|
|
|
746
757
|
if len(selected_observations) == 1:
|
|
747
|
-
new_rows = []
|
|
758
|
+
new_rows: list = []
|
|
748
759
|
for occurence, observation in rows:
|
|
749
|
-
if occurence is
|
|
750
|
-
|
|
751
|
-
new_occurence = min(new_occurence, float(parameters["end time"]))
|
|
760
|
+
if occurence is None:
|
|
761
|
+
new_rows.append([float("NaN"), observation])
|
|
752
762
|
else:
|
|
753
|
-
|
|
754
|
-
new_rows.append([new_occurence, observation])
|
|
763
|
+
new_rows.append([occurence, observation])
|
|
755
764
|
rows = list(new_rows)
|
|
756
765
|
|
|
757
766
|
# include behaviors without events
|
|
758
767
|
if len(rows) == 0:
|
|
759
768
|
if not parameters[cfg.EXCLUDE_BEHAVIORS]:
|
|
760
|
-
|
|
769
|
+
out_cat.append(
|
|
761
770
|
{
|
|
762
771
|
"subject": subject,
|
|
763
772
|
"behavior": behavior,
|
|
@@ -792,7 +801,7 @@ def time_budget_analysis(
|
|
|
792
801
|
{
|
|
793
802
|
"subject": subject,
|
|
794
803
|
"behavior": behavior,
|
|
795
|
-
"modifiers": modifier
|
|
804
|
+
"modifiers": modifier,
|
|
796
805
|
"duration": cfg.NA,
|
|
797
806
|
"duration_mean": cfg.NA,
|
|
798
807
|
"duration_stdev": cfg.NA,
|
|
@@ -802,8 +811,7 @@ def time_budget_analysis(
|
|
|
802
811
|
}
|
|
803
812
|
)
|
|
804
813
|
|
|
805
|
-
if
|
|
806
|
-
|
|
814
|
+
if project_functions.event_type(behavior, ethogram) in cfg.STATE_EVENT_TYPES:
|
|
807
815
|
for modifier in distinct_modifiers:
|
|
808
816
|
cursor.execute(
|
|
809
817
|
(
|
|
@@ -813,24 +821,23 @@ def time_budget_analysis(
|
|
|
813
821
|
"AND modifiers = ? "
|
|
814
822
|
"ORDER BY observation, occurence"
|
|
815
823
|
),
|
|
816
|
-
(subject, behavior, modifier
|
|
824
|
+
(subject, behavior, modifier),
|
|
817
825
|
)
|
|
818
826
|
|
|
819
827
|
rows = list(cursor.fetchall())
|
|
820
828
|
|
|
821
829
|
if len(rows) == 0:
|
|
822
|
-
|
|
823
830
|
if not parameters[cfg.EXCLUDE_BEHAVIORS]: # include behaviors without events
|
|
824
831
|
# check if observation from pictures
|
|
825
832
|
if parameters["start time"] == dec("0.000") and parameters["end time"] == dec("0.000"):
|
|
826
833
|
duration = cfg.NA
|
|
827
834
|
else:
|
|
828
|
-
duration = 0.000
|
|
829
|
-
|
|
835
|
+
duration: float = 0.000
|
|
836
|
+
out_cat.append(
|
|
830
837
|
{
|
|
831
838
|
"subject": subject,
|
|
832
839
|
"behavior": behavior,
|
|
833
|
-
"modifiers": modifier
|
|
840
|
+
"modifiers": modifier,
|
|
834
841
|
"duration": duration,
|
|
835
842
|
"duration_mean": cfg.NA,
|
|
836
843
|
"duration_stdev": cfg.NA,
|
|
@@ -842,11 +849,11 @@ def time_budget_analysis(
|
|
|
842
849
|
continue
|
|
843
850
|
|
|
844
851
|
if len(rows) % 2:
|
|
845
|
-
|
|
852
|
+
out_cat.append(
|
|
846
853
|
{
|
|
847
854
|
"subject": subject,
|
|
848
855
|
"behavior": behavior,
|
|
849
|
-
"modifiers": modifier
|
|
856
|
+
"modifiers": modifier,
|
|
850
857
|
"duration": cfg.UNPAIRED,
|
|
851
858
|
"duration_mean": cfg.UNPAIRED,
|
|
852
859
|
"duration_stdev": cfg.UNPAIRED,
|
|
@@ -856,7 +863,8 @@ def time_budget_analysis(
|
|
|
856
863
|
}
|
|
857
864
|
)
|
|
858
865
|
else:
|
|
859
|
-
all_event_durations
|
|
866
|
+
all_event_durations: list = []
|
|
867
|
+
all_event_interdurations: list = []
|
|
860
868
|
for idx, row in enumerate(rows):
|
|
861
869
|
# event
|
|
862
870
|
if idx % 2 == 0:
|
|
@@ -868,10 +876,11 @@ def time_budget_analysis(
|
|
|
868
876
|
|
|
869
877
|
# inter event if same observation
|
|
870
878
|
if idx % 2 and idx != len(rows) - 1 and row[1] == rows[idx + 1][1]:
|
|
871
|
-
if
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
879
|
+
if row[0] is not None and rows[idx + 1][0] is not None:
|
|
880
|
+
# and (
|
|
881
|
+
# parameters["start time"] <= row[0] <= parameters["end time"]
|
|
882
|
+
# and parameters["start time"] <= rows[idx + 1][0] <= parameters["end time"]
|
|
883
|
+
# ):
|
|
875
884
|
all_event_interdurations.append(float(rows[idx + 1][0]) - float(row[0]))
|
|
876
885
|
else:
|
|
877
886
|
all_event_interdurations.append(float("NaN"))
|
|
@@ -891,9 +900,7 @@ def time_budget_analysis(
|
|
|
891
900
|
else:
|
|
892
901
|
duration_stdev = cfg.NA
|
|
893
902
|
# interduration
|
|
894
|
-
if [x for x in all_event_interdurations if math.isnan(x)] or len(
|
|
895
|
-
all_event_interdurations
|
|
896
|
-
) == 0:
|
|
903
|
+
if [x for x in all_event_interdurations if math.isnan(x)] or len(all_event_interdurations) == 0:
|
|
897
904
|
inter_duration_mean = cfg.NA
|
|
898
905
|
inter_duration_stdev = cfg.NA
|
|
899
906
|
else:
|
|
@@ -907,7 +914,7 @@ def time_budget_analysis(
|
|
|
907
914
|
{
|
|
908
915
|
"subject": subject,
|
|
909
916
|
"behavior": behavior,
|
|
910
|
-
"modifiers": modifier
|
|
917
|
+
"modifiers": modifier,
|
|
911
918
|
"duration": total_duration,
|
|
912
919
|
"duration_mean": duration_mean,
|
|
913
920
|
"duration_stdev": duration_stdev,
|
|
@@ -918,34 +925,27 @@ def time_budget_analysis(
|
|
|
918
925
|
)
|
|
919
926
|
|
|
920
927
|
else: # no modifiers
|
|
921
|
-
|
|
922
|
-
if cfg.POINT in project_functions.event_type(behavior, ethogram):
|
|
923
|
-
|
|
928
|
+
if project_functions.event_type(behavior, ethogram) in cfg.POINT_EVENT_TYPES:
|
|
924
929
|
cursor.execute(
|
|
925
|
-
(
|
|
926
|
-
"SELECT occurence,observation FROM events "
|
|
927
|
-
"WHERE subject = ? AND code = ? ORDER BY observation, occurence"
|
|
928
|
-
),
|
|
930
|
+
("SELECT occurence, observation FROM events WHERE subject = ? AND code = ? ORDER BY observation, occurence"),
|
|
929
931
|
(subject, behavior),
|
|
930
932
|
)
|
|
931
933
|
|
|
932
934
|
rows = list(cursor.fetchall())
|
|
933
935
|
|
|
934
936
|
if len(selected_observations) == 1:
|
|
935
|
-
new_rows = []
|
|
937
|
+
new_rows: list = []
|
|
936
938
|
for occurence, observation in rows:
|
|
937
|
-
if occurence is
|
|
938
|
-
|
|
939
|
-
new_occurence = min(new_occurence, float(parameters["end time"]))
|
|
939
|
+
if occurence is None:
|
|
940
|
+
new_rows.append([float("NaN"), observation])
|
|
940
941
|
else:
|
|
941
|
-
|
|
942
|
-
new_rows.append([new_occurence, observation])
|
|
942
|
+
new_rows.append([occurence, observation])
|
|
943
943
|
rows = list(new_rows)
|
|
944
944
|
|
|
945
945
|
# include behaviors without events
|
|
946
946
|
if len(rows) == 0:
|
|
947
947
|
if not parameters[cfg.EXCLUDE_BEHAVIORS]:
|
|
948
|
-
|
|
948
|
+
out_cat.append(
|
|
949
949
|
{
|
|
950
950
|
"subject": subject,
|
|
951
951
|
"behavior": behavior,
|
|
@@ -990,13 +990,9 @@ def time_budget_analysis(
|
|
|
990
990
|
}
|
|
991
991
|
)
|
|
992
992
|
|
|
993
|
-
if
|
|
994
|
-
|
|
993
|
+
if project_functions.event_type(behavior, ethogram) in cfg.STATE_EVENT_TYPES:
|
|
995
994
|
cursor.execute(
|
|
996
|
-
(
|
|
997
|
-
"SELECT occurence, observation FROM events "
|
|
998
|
-
"WHERE subject = ? AND code = ? ORDER BY observation, occurence"
|
|
999
|
-
),
|
|
995
|
+
("SELECT occurence, observation FROM events WHERE subject = ? AND code = ? ORDER BY observation, occurence"),
|
|
1000
996
|
(subject, behavior),
|
|
1001
997
|
)
|
|
1002
998
|
|
|
@@ -1009,7 +1005,7 @@ def time_budget_analysis(
|
|
|
1009
1005
|
duration = cfg.NA
|
|
1010
1006
|
else:
|
|
1011
1007
|
duration = 0.000
|
|
1012
|
-
|
|
1008
|
+
out_cat.append(
|
|
1013
1009
|
{
|
|
1014
1010
|
"subject": subject,
|
|
1015
1011
|
"behavior": behavior,
|
|
@@ -1024,8 +1020,8 @@ def time_budget_analysis(
|
|
|
1024
1020
|
)
|
|
1025
1021
|
continue
|
|
1026
1022
|
|
|
1027
|
-
if len(rows) % 2:
|
|
1028
|
-
|
|
1023
|
+
if len(rows) % 2: # unpaired events
|
|
1024
|
+
out_cat.append(
|
|
1029
1025
|
{
|
|
1030
1026
|
"subject": subject,
|
|
1031
1027
|
"behavior": behavior,
|
|
@@ -1039,7 +1035,8 @@ def time_budget_analysis(
|
|
|
1039
1035
|
}
|
|
1040
1036
|
)
|
|
1041
1037
|
else:
|
|
1042
|
-
all_event_durations
|
|
1038
|
+
all_event_durations: list = []
|
|
1039
|
+
all_event_interdurations: list = []
|
|
1043
1040
|
for idx, row in enumerate(rows):
|
|
1044
1041
|
# event
|
|
1045
1042
|
if idx % 2 == 0:
|
|
@@ -1051,10 +1048,11 @@ def time_budget_analysis(
|
|
|
1051
1048
|
|
|
1052
1049
|
# inter event if same observation
|
|
1053
1050
|
if idx % 2 and idx != len(rows) - 1 and row[1] == rows[idx + 1][1]:
|
|
1054
|
-
if
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1051
|
+
if row[0] is not None and rows[idx + 1][0] is not None:
|
|
1052
|
+
# and (
|
|
1053
|
+
# parameters["start time"] <= row[0] <= parameters["end time"]
|
|
1054
|
+
# and parameters["start time"] <= rows[idx + 1][0] <= parameters["end time"]
|
|
1055
|
+
# ):
|
|
1058
1056
|
all_event_interdurations.append(float(rows[idx + 1][0]) - float(row[0]))
|
|
1059
1057
|
else:
|
|
1060
1058
|
all_event_interdurations.append(float("NaN"))
|
|
@@ -1101,9 +1099,7 @@ def time_budget_analysis(
|
|
|
1101
1099
|
out += out_cat
|
|
1102
1100
|
|
|
1103
1101
|
if by_category: # and flagCategories:
|
|
1104
|
-
|
|
1105
1102
|
for behav in out_cat:
|
|
1106
|
-
|
|
1107
1103
|
try:
|
|
1108
1104
|
category = [
|
|
1109
1105
|
ethogram[x][cfg.BEHAVIOR_CATEGORY]
|
|
@@ -1113,19 +1109,23 @@ def time_budget_analysis(
|
|
|
1113
1109
|
except Exception:
|
|
1114
1110
|
category = ""
|
|
1115
1111
|
|
|
1116
|
-
if category in categories[subject]:
|
|
1112
|
+
if category not in categories[subject]:
|
|
1113
|
+
categories[subject][category] = {"duration": 0, "number": 0}
|
|
1114
|
+
|
|
1115
|
+
if project_functions.event_type(behav["behavior"], ethogram) in cfg.STATE_EVENT_TYPES:
|
|
1117
1116
|
if behav["duration"] not in ("-", cfg.NA) and categories[subject][category]["duration"] not in (
|
|
1118
1117
|
"-",
|
|
1119
1118
|
cfg.NA,
|
|
1120
1119
|
):
|
|
1120
|
+
# print(f"{categories[subject][category]["duration"]=}")
|
|
1121
|
+
# print(f"{behav["duration"]=}")
|
|
1121
1122
|
categories[subject][category]["duration"] += behav["duration"]
|
|
1122
1123
|
else:
|
|
1123
1124
|
categories[subject][category]["duration"] = cfg.NA
|
|
1124
|
-
categories[subject][category]["number"] += behav["number"]
|
|
1125
|
-
else:
|
|
1126
|
-
categories[subject][category] = {"duration": behav["duration"], "number": behav["number"]}
|
|
1127
1125
|
|
|
1128
|
-
|
|
1126
|
+
categories[subject][category]["number"] += behav["number"]
|
|
1127
|
+
|
|
1128
|
+
out_sorted: list = []
|
|
1129
1129
|
for subject in parameters[cfg.SELECTED_SUBJECTS]:
|
|
1130
1130
|
for behavior in parameters[cfg.SELECTED_BEHAVIORS]:
|
|
1131
1131
|
for row in out:
|