boris-behav-obs 9.6.6__tar.gz → 9.7__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.
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/PKG-INFO +3 -5
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/README.md +2 -4
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/connections.py +3 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/core.py +84 -77
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/core_ui.py +6 -2
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/event_operations.py +55 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/observation_operations.py +0 -4
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/utilities.py +6 -5
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/version.py +2 -2
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris_behav_obs.egg-info/PKG-INFO +3 -5
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris_behav_obs.egg-info/SOURCES.txt +0 -1
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/pyproject.toml +1 -1
- boris_behav_obs-9.6.6/boris/1.py +0 -45
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/LICENSE.TXT +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/MANIFEST.in +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/README.TXT +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/__init__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/__main__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/about.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/add_modifier.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/add_modifier_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/advanced_event_filtering.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/__init__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/_latency.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/irr_cohen_kappa.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/irr_weighted_cohen_kappa.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/list_of_dataframe_columns.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/number_of_occurences.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/time_budget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/behav_coding_map_creator.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/behavior_binary_table.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/behaviors_coding_map.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/boris_cli.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/cmd_arguments.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/coding_pad.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/config.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/config_file.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/converters.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/converters_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/cooccurence.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/core_qrc.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/db_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/dev.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/dialog.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/duration_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/edit_event.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/edit_event_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/events_cursor.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/events_snapshots.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/exclusion_matrix.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/export_events.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/export_observation.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/external_processes.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/geometric_measurement.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/gui_utilities.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/image_overlay.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/import_observations.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/irr.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/latency.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/measurement_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/media_file.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/menu_options.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/modifier_coding_map_creator.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/modifiers_coding_map.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/mpv-1.0.3.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/mpv.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/mpv2.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/observation.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/observation_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/observations_list.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/otx_parser.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/param_panel.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/param_panel_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/player_dock_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/plot_data_module.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/plot_events.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/plot_events_rt.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/plot_spectrogram_rt.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/plot_waveform_rt.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/plugins.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/portion/__init__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/portion/const.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/portion/dict.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/portion/func.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/portion/interval.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/portion/io.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/preferences.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/preferences_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/project.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/project_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/project_import_export.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/project_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/qrc_boris.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/qrc_boris5.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/select_modifiers.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/select_observations.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/select_subj_behav.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/state_events.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/subjects_pad.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/synthetic_time_budget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/time_budget_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/time_budget_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/transitions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/video_equalizer.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/video_equalizer_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/video_operations.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/view_df.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/view_df_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/write_event.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris_behav_obs.egg-info/entry_points.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris_behav_obs.egg-info/requires.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris_behav_obs.egg-info/top_level.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/setup.cfg +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_db_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_export_observation.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_irr.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_observation_gui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_otx_parser.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_preferences_gui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_project_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_time_budget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/tests/test_utilities.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/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.
|
|
3
|
+
Version: 9.7
|
|
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
|
|
@@ -59,6 +59,8 @@ The BORIS paper has more than 2337 citations in peer-reviewed scientific publica
|
|
|
59
59
|
|
|
60
60
|
See the official [BORIS web site](https://www.boris.unito.it).
|
|
61
61
|
|
|
62
|
+
<a href="https://www.boris.unito.it" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fwww.boris.unito.it"></a>
|
|
63
|
+
<a href="https://www.boris.unito.it/user_guide/" target="_blank"><img alt="User guide" src="https://img.shields.io/badge/Documentation-orange"></a>
|
|
62
64
|
[](https://www.python.org)
|
|
63
65
|

|
|
64
66
|

|
|
@@ -136,7 +138,3 @@ GNU General Public License for more details.
|
|
|
136
138
|
Distributed with a [GPL v.3 license](LICENSE.TXT).
|
|
137
139
|
|
|
138
140
|
Copyright (C) 2012-2025 Olivier Friard
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
@@ -21,6 +21,8 @@ The BORIS paper has more than 2337 citations in peer-reviewed scientific publica
|
|
|
21
21
|
|
|
22
22
|
See the official [BORIS web site](https://www.boris.unito.it).
|
|
23
23
|
|
|
24
|
+
<a href="https://www.boris.unito.it" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fwww.boris.unito.it"></a>
|
|
25
|
+
<a href="https://www.boris.unito.it/user_guide/" target="_blank"><img alt="User guide" src="https://img.shields.io/badge/Documentation-orange"></a>
|
|
24
26
|
[](https://www.python.org)
|
|
25
27
|

|
|
26
28
|

|
|
@@ -98,7 +100,3 @@ GNU General Public License for more details.
|
|
|
98
100
|
Distributed with a [GPL v.3 license](LICENSE.TXT).
|
|
99
101
|
|
|
100
102
|
Copyright (C) 2012-2025 Olivier Friard
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
@@ -120,6 +120,7 @@ def connections(self):
|
|
|
120
120
|
self.actionSelect_observations.triggered.connect(lambda: event_operations.select_events_between_activated(self))
|
|
121
121
|
|
|
122
122
|
self.actionEdit_selected_events.triggered.connect(lambda: event_operations.edit_selected_events(self))
|
|
123
|
+
self.action_add_comment.triggered.connect(lambda: event_operations.add_comment(self))
|
|
123
124
|
self.actionEdit_event_time.triggered.connect(lambda: event_operations.edit_time_selected_events(self))
|
|
124
125
|
|
|
125
126
|
self.actionCopy_events.triggered.connect(lambda: event_operations.copy_selected_events(self))
|
|
@@ -343,6 +344,8 @@ def connections(self):
|
|
|
343
344
|
|
|
344
345
|
self.tv_events.addAction(self.actionAdd_event)
|
|
345
346
|
self.tv_events.addAction(self.actionEdit_selected_events)
|
|
347
|
+
self.tv_events.addAction(self.action_add_comment)
|
|
348
|
+
|
|
346
349
|
self.tv_events.addAction(self.actionEdit_event_time)
|
|
347
350
|
|
|
348
351
|
self.tv_events.addAction(self.actionCopy_events)
|
|
@@ -236,8 +236,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
236
236
|
processes: list = [] # list of QProcess processes
|
|
237
237
|
overlays: dict = {} # dict for storing video overlays
|
|
238
238
|
|
|
239
|
-
undo_queue = deque()
|
|
240
|
-
undo_description = deque()
|
|
239
|
+
undo_queue = deque() # queue for undoing event operations
|
|
240
|
+
undo_description = deque() # queue for description of event operations
|
|
241
241
|
|
|
242
242
|
current_player: int = 0 # id of the selected (left click) video player
|
|
243
243
|
|
|
@@ -3728,77 +3728,78 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3728
3728
|
QMessageBox.warning(self, cfg.programName, "Function not yet implemented")
|
|
3729
3729
|
return
|
|
3730
3730
|
|
|
3731
|
-
if not self.observationId:
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
if self.twEvents.selectedItems():
|
|
3736
|
-
row_s = self.twEvents.selectedItems()[0].row()
|
|
3737
|
-
row_e = self.twEvents.selectedItems()[-1].row()
|
|
3738
|
-
eventtime_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_s][0]
|
|
3739
|
-
eventtime_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_e][0]
|
|
3740
|
-
|
|
3741
|
-
durations = [] # in seconds
|
|
3742
|
-
|
|
3743
|
-
# TODO: check for 2nd player
|
|
3744
|
-
for mediaFile in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1]:
|
|
3745
|
-
durations.append(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]["length"][mediaFile])
|
|
3746
|
-
|
|
3747
|
-
mediaFileIdx_s = [idx1 for idx1, x in enumerate(durations) if eventtime_s >= sum(durations[0:idx1])][-1]
|
|
3748
|
-
media_path_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_s]
|
|
3749
|
-
|
|
3750
|
-
mediaFileIdx_e = [idx1 for idx1, x in enumerate(durations) if eventtime_e >= sum(durations[0:idx1])][-1]
|
|
3751
|
-
media_path_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_e]
|
|
3752
|
-
|
|
3753
|
-
# calculate time for current media file in case of many queued media files
|
|
3754
|
-
|
|
3755
|
-
eventtime_onmedia_s = round(eventtime_s - util.float2decimal(sum(durations[0:mediaFileIdx_s])), 3)
|
|
3756
|
-
eventtime_onmedia_e = round(eventtime_e - util.float2decimal(sum(durations[0:mediaFileIdx_e])), 3)
|
|
3757
|
-
|
|
3758
|
-
if media_path_s != media_path_e:
|
|
3759
|
-
return
|
|
3731
|
+
# if not self.observationId:
|
|
3732
|
+
# self.no_observation()
|
|
3733
|
+
# return
|
|
3760
3734
|
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3735
|
+
#
|
|
3736
|
+
# if self.twEvents.selectedItems():
|
|
3737
|
+
# row_s = self.twEvents.selectedItems()[0].row()
|
|
3738
|
+
# row_e = self.twEvents.selectedItems()[-1].row()
|
|
3739
|
+
# eventtime_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_s][0]
|
|
3740
|
+
# eventtime_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_e][0]
|
|
3741
|
+
#
|
|
3742
|
+
# durations = [] # in seconds
|
|
3743
|
+
#
|
|
3744
|
+
# # TODO: check for 2nd player
|
|
3745
|
+
# for mediaFile in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1]:
|
|
3746
|
+
# durations.append(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]["length"][mediaFile])
|
|
3747
|
+
#
|
|
3748
|
+
# mediaFileIdx_s = [idx1 for idx1, x in enumerate(durations) if eventtime_s >= sum(durations[0:idx1])][-1]
|
|
3749
|
+
# media_path_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_s]
|
|
3750
|
+
#
|
|
3751
|
+
# mediaFileIdx_e = [idx1 for idx1, x in enumerate(durations) if eventtime_e >= sum(durations[0:idx1])][-1]
|
|
3752
|
+
# media_path_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_e]
|
|
3753
|
+
#
|
|
3754
|
+
# # calculate time for current media file in case of many queued media files
|
|
3755
|
+
#
|
|
3756
|
+
# eventtime_onmedia_s = round(eventtime_s - util.float2decimal(sum(durations[0:mediaFileIdx_s])), 3)
|
|
3757
|
+
# eventtime_onmedia_e = round(eventtime_e - util.float2decimal(sum(durations[0:mediaFileIdx_e])), 3)
|
|
3758
|
+
#
|
|
3759
|
+
# if media_path_s != media_path_e:
|
|
3760
|
+
# return
|
|
3761
|
+
#
|
|
3762
|
+
# media_path = media_path_s
|
|
3763
|
+
#
|
|
3764
|
+
# # example of external command defined in environment:
|
|
3765
|
+
# # export BORISEXTERNAL="myprog -i {MEDIA_PATH} -s {START_S} -e {END_S} {DURATION_MS} --other"
|
|
3766
|
+
#
|
|
3767
|
+
# if "BORISEXTERNAL" in os.environ:
|
|
3768
|
+
# external_command_template = os.environ["BORISEXTERNAL"]
|
|
3769
|
+
# else:
|
|
3770
|
+
# return
|
|
3771
|
+
#
|
|
3772
|
+
# external_command = external_command_template.format(
|
|
3773
|
+
# OBS_ID=self.observationId,
|
|
3774
|
+
# MEDIA_PATH=f'"{media_path}"',
|
|
3775
|
+
# MEDIA_BASENAME=f'"{os.path.basename(media_path)}"',
|
|
3776
|
+
# START_S=eventtime_onmedia_s,
|
|
3777
|
+
# END_S=eventtime_onmedia_e,
|
|
3778
|
+
# START_MS=eventtime_onmedia_s * 1000,
|
|
3779
|
+
# END_MS=eventtime_onmedia_e * 1000,
|
|
3780
|
+
# DURATION_S=eventtime_onmedia_e - eventtime_onmedia_s,
|
|
3781
|
+
# DURATION_MS=(eventtime_onmedia_e - eventtime_onmedia_s) * 1000,
|
|
3782
|
+
# )
|
|
3783
|
+
#
|
|
3784
|
+
# print(external_command)
|
|
3785
|
+
# """
|
|
3786
|
+
# p = subprocess.Popen(external_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
3787
|
+
# """
|
|
3788
|
+
# """
|
|
3789
|
+
# if eventtimeS == eventtimeE:
|
|
3790
|
+
# q = []
|
|
3791
|
+
# else:
|
|
3792
|
+
# durationsec = eventtimeE-eventtimeS
|
|
3793
|
+
# q = ["--durationmsec",str(int(durationsec*1000))]
|
|
3794
|
+
# args = [ex, "-f",os.path.abspath(fn),"--seekmsec",str(int(eventtimeS*1000)),*q,*("--size 1 --track 1 --redetect 100")
|
|
3795
|
+
# .split(" ")]
|
|
3796
|
+
# if os.path.split(fn)[1].split("_")[0] in set(["A1","A2","A3","A4","A5","A6","A7","A8","A9","A10"]):
|
|
3797
|
+
# args.append("--flip")
|
|
3798
|
+
# args.append("2")
|
|
3799
|
+
# print (os.path.split(fn)[1].split("_")[0])
|
|
3800
|
+
# print ("running",ex,"with",args,"in",os.path.split(ex)[0])
|
|
3801
|
+
# #pid = subprocess.Popen(args,executable=ex,cwd=os.path.split(ex)[0])
|
|
3802
|
+
# """
|
|
3802
3803
|
|
|
3803
3804
|
def no_media(self):
|
|
3804
3805
|
QMessageBox.warning(self, cfg.programName, "There is no media available")
|
|
@@ -5666,12 +5667,18 @@ def main():
|
|
|
5666
5667
|
ret, msg = util.check_ffmpeg_path()
|
|
5667
5668
|
if not ret:
|
|
5668
5669
|
if sys.platform.startswith("win"):
|
|
5669
|
-
|
|
5670
5670
|
import ctypes
|
|
5671
|
+
|
|
5671
5672
|
MessageBoxTimeoutW = ctypes.windll.user32.MessageBoxTimeoutW
|
|
5672
|
-
MessageBoxTimeoutW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p,
|
|
5673
|
-
|
|
5674
|
-
|
|
5673
|
+
MessageBoxTimeoutW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint]
|
|
5674
|
+
ctypes.windll.user32.MessageBoxTimeoutW(
|
|
5675
|
+
None,
|
|
5676
|
+
"The FFmpeg framework is not available.\nIt will be downloaded from the BORIS GitHub repository.",
|
|
5677
|
+
"FFmpeg",
|
|
5678
|
+
0,
|
|
5679
|
+
0,
|
|
5680
|
+
10000,
|
|
5681
|
+
) # time out
|
|
5675
5682
|
|
|
5676
5683
|
# if (not options.nosplashscreen):
|
|
5677
5684
|
# QMessageBox.warning(
|
|
@@ -5684,7 +5691,7 @@ def main():
|
|
|
5684
5691
|
logging.info("FFmpeg is not available. It will be downloaded from the BORIS GitHub repository")
|
|
5685
5692
|
|
|
5686
5693
|
# download ffmpeg and ffprobe from https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/
|
|
5687
|
-
url:str = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
|
|
5694
|
+
url: str = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
|
|
5688
5695
|
|
|
5689
5696
|
# search where to download ffmpeg
|
|
5690
5697
|
ffmpeg_dir = Path(__file__).parent / "misc"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
################################################################################
|
|
4
4
|
## Form generated from reading UI file 'core.ui'
|
|
5
5
|
##
|
|
6
|
-
## Created by: Qt User Interface Compiler version 6.
|
|
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
|
################################################################################
|
|
@@ -382,6 +382,9 @@ class Ui_MainWindow(object):
|
|
|
382
382
|
self.actionCreate_video_spectrogram.setObjectName(u"actionCreate_video_spectrogram")
|
|
383
383
|
self.action_change_time_offset_of_players = QAction(MainWindow)
|
|
384
384
|
self.action_change_time_offset_of_players.setObjectName(u"action_change_time_offset_of_players")
|
|
385
|
+
self.action_add_comment = QAction(MainWindow)
|
|
386
|
+
self.action_add_comment.setObjectName(u"action_add_comment")
|
|
387
|
+
self.action_add_comment.setMenuRole(QAction.MenuRole.NoRole)
|
|
385
388
|
self.centralwidget = QWidget(MainWindow)
|
|
386
389
|
self.centralwidget.setObjectName(u"centralwidget")
|
|
387
390
|
self.horizontalLayout_2 = QHBoxLayout(self.centralwidget)
|
|
@@ -488,7 +491,7 @@ class Ui_MainWindow(object):
|
|
|
488
491
|
MainWindow.setCentralWidget(self.centralwidget)
|
|
489
492
|
self.menubar = QMenuBar(MainWindow)
|
|
490
493
|
self.menubar.setObjectName(u"menubar")
|
|
491
|
-
self.menubar.setGeometry(QRect(0, 0, 1509,
|
|
494
|
+
self.menubar.setGeometry(QRect(0, 0, 1509, 20))
|
|
492
495
|
self.menuHelp = QMenu(self.menubar)
|
|
493
496
|
self.menuHelp.setObjectName(u"menuHelp")
|
|
494
497
|
self.menuFile = QMenu(self.menubar)
|
|
@@ -1037,6 +1040,7 @@ class Ui_MainWindow(object):
|
|
|
1037
1040
|
self.action_load_plugins.setText(QCoreApplication.translate("MainWindow", u"Load plugins", None))
|
|
1038
1041
|
self.actionCreate_video_spectrogram.setText(QCoreApplication.translate("MainWindow", u"Create video spectrogram", None))
|
|
1039
1042
|
self.action_change_time_offset_of_players.setText(QCoreApplication.translate("MainWindow", u"Change time offset of players", None))
|
|
1043
|
+
self.action_add_comment.setText(QCoreApplication.translate("MainWindow", u"Add/Edit comment", None))
|
|
1040
1044
|
self.lbLogoBoris.setText("")
|
|
1041
1045
|
self.lbLogoUnito.setText("")
|
|
1042
1046
|
self.lb_player_status.setText(QCoreApplication.translate("MainWindow", u"lb_player_status", None))
|
|
@@ -454,6 +454,61 @@ def select_events_between_activated(self):
|
|
|
454
454
|
self.tv_events.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
|
455
455
|
|
|
456
456
|
|
|
457
|
+
def add_comment(self):
|
|
458
|
+
"""
|
|
459
|
+
add a comment to the selected events
|
|
460
|
+
operation can be undone with Undo
|
|
461
|
+
"""
|
|
462
|
+
tvevents_rows_to_edit = set([index.row() for index in self.tv_events.selectionModel().selectedIndexes()])
|
|
463
|
+
if not len(tvevents_rows_to_edit):
|
|
464
|
+
QMessageBox.warning(self, cfg.programName, "No event selected!")
|
|
465
|
+
return
|
|
466
|
+
|
|
467
|
+
comment_str: str = ""
|
|
468
|
+
if len(tvevents_rows_to_edit) == 1:
|
|
469
|
+
pj_event_idx = self.tv_idx2events_idx[self.tv_events.selectionModel().selectedIndexes()[0].row()]
|
|
470
|
+
comment_str = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][pj_event_idx][
|
|
471
|
+
cfg.PJ_OBS_FIELDS[self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE]][cfg.COMMENT]
|
|
472
|
+
]
|
|
473
|
+
else:
|
|
474
|
+
# check if comment is the same in all selected events
|
|
475
|
+
|
|
476
|
+
if (
|
|
477
|
+
len(
|
|
478
|
+
set(
|
|
479
|
+
[
|
|
480
|
+
self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][self.tv_idx2events_idx[tvevents_row]][
|
|
481
|
+
cfg.PJ_OBS_FIELDS[self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE]][cfg.COMMENT]
|
|
482
|
+
]
|
|
483
|
+
for tvevents_row in tvevents_rows_to_edit
|
|
484
|
+
]
|
|
485
|
+
)
|
|
486
|
+
)
|
|
487
|
+
== 1
|
|
488
|
+
):
|
|
489
|
+
pj_event_idx = self.tv_idx2events_idx[self.tv_events.selectionModel().selectedIndexes()[0].row()]
|
|
490
|
+
comment_str = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][pj_event_idx][
|
|
491
|
+
cfg.PJ_OBS_FIELDS[self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE]][cfg.COMMENT]
|
|
492
|
+
]
|
|
493
|
+
|
|
494
|
+
new_comment, ok = QInputDialog.getText(self, "Add/Edit a comment", "Comment:", text=comment_str)
|
|
495
|
+
if not ok:
|
|
496
|
+
return
|
|
497
|
+
|
|
498
|
+
# fill the undo list
|
|
499
|
+
fill_events_undo_list(self, "Undo last comment operation")
|
|
500
|
+
|
|
501
|
+
for tvevents_row in tvevents_rows_to_edit:
|
|
502
|
+
pj_event_idx = self.tv_idx2events_idx[tvevents_row]
|
|
503
|
+
|
|
504
|
+
self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][pj_event_idx][
|
|
505
|
+
cfg.PJ_OBS_FIELDS[self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE]][cfg.COMMENT]
|
|
506
|
+
] = new_comment
|
|
507
|
+
|
|
508
|
+
# reload all events in tw
|
|
509
|
+
self.load_tw_events(self.observationId)
|
|
510
|
+
|
|
511
|
+
|
|
457
512
|
def edit_selected_events(self):
|
|
458
513
|
"""
|
|
459
514
|
edit one or more selected events for subject, behavior and/or comment
|
|
@@ -19,7 +19,6 @@ Copyright 2012-2025 Olivier Friard
|
|
|
19
19
|
MA 02110-1301, USA.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
import logging
|
|
24
23
|
from collections import deque
|
|
25
24
|
import datetime as dt
|
|
@@ -36,8 +35,6 @@ import time
|
|
|
36
35
|
from typing import List, Tuple, Optional
|
|
37
36
|
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
38
|
from PySide6.QtWidgets import (
|
|
42
39
|
QMessageBox,
|
|
43
40
|
QFileDialog,
|
|
@@ -1191,7 +1188,6 @@ def close_observation(self):
|
|
|
1191
1188
|
self.undo_queue = deque()
|
|
1192
1189
|
self.undo_description = deque()
|
|
1193
1190
|
|
|
1194
|
-
|
|
1195
1191
|
if self.playerType in (cfg.MEDIA, cfg.IMAGES):
|
|
1196
1192
|
"""
|
|
1197
1193
|
for idx, _ in enumerate(self.dw_player):
|
|
@@ -63,17 +63,18 @@ except Exception:
|
|
|
63
63
|
import ctypes
|
|
64
64
|
|
|
65
65
|
logger.info("The MPV library was not found!\nIt will be downloaded from the BORIS GitHub repository")
|
|
66
|
-
#ctypes.windll.user32.MessageBoxW(0, "The MPV library was not found!\nIt will be downloaded.", "BORIS", 0)
|
|
66
|
+
# ctypes.windll.user32.MessageBoxW(0, "The MPV library was not found!\nIt will be downloaded.", "BORIS", 0)
|
|
67
67
|
|
|
68
68
|
# test if following function works on windows
|
|
69
69
|
MessageBoxTimeoutW = ctypes.windll.user32.MessageBoxTimeoutW
|
|
70
|
-
MessageBoxTimeoutW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p,
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
MessageBoxTimeoutW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint]
|
|
71
|
+
ctypes.windll.user32.MessageBoxTimeoutW(
|
|
72
|
+
None, "The MPV library was not found.\nIt will be downloaded from the BORIS GitHub repository.", "MPV library", 0, 0, 10000
|
|
73
|
+
) # time out
|
|
73
74
|
|
|
74
75
|
# download libmpv2.dll from https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/
|
|
75
76
|
|
|
76
|
-
url:str = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
|
|
77
|
+
url: str = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
|
|
77
78
|
|
|
78
79
|
external_files_dir = ""
|
|
79
80
|
# search where to download libmpv-2.dll
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boris-behav-obs
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.7
|
|
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
|
|
@@ -59,6 +59,8 @@ The BORIS paper has more than 2337 citations in peer-reviewed scientific publica
|
|
|
59
59
|
|
|
60
60
|
See the official [BORIS web site](https://www.boris.unito.it).
|
|
61
61
|
|
|
62
|
+
<a href="https://www.boris.unito.it" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fwww.boris.unito.it"></a>
|
|
63
|
+
<a href="https://www.boris.unito.it/user_guide/" target="_blank"><img alt="User guide" src="https://img.shields.io/badge/Documentation-orange"></a>
|
|
62
64
|
[](https://www.python.org)
|
|
63
65
|

|
|
64
66
|

|
|
@@ -136,7 +138,3 @@ GNU General Public License for more details.
|
|
|
136
138
|
Distributed with a [GPL v.3 license](LICENSE.TXT).
|
|
137
139
|
|
|
138
140
|
Copyright (C) 2012-2025 Olivier Friard
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
boris_behav_obs-9.6.6/boris/1.py
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from PIL import Image, ImageDraw, ImageFont
|
|
3
|
-
import mpv
|
|
4
|
-
|
|
5
|
-
player = mpv.MPV()
|
|
6
|
-
|
|
7
|
-
player.loop = True
|
|
8
|
-
player.play('/home/olivier/gdrive_sync/src/python/generate_video_test/video1.mp4')
|
|
9
|
-
player.wait_until_playing()
|
|
10
|
-
|
|
11
|
-
font = ImageFont.truetype('DejaVuSans.ttf', 40)
|
|
12
|
-
|
|
13
|
-
overlay = player.create_image_overlay()
|
|
14
|
-
|
|
15
|
-
img = Image.new('RGBA', (400, 150), (255, 255, 255, 0))
|
|
16
|
-
d = ImageDraw.Draw(img)
|
|
17
|
-
d.text((10, 10), 'Hello World', font=font, fill=(0, 255, 255, 128))
|
|
18
|
-
#d.text((10, 60), f't={ts:.3f}', font=font, fill=(255, 0, 255, 255))
|
|
19
|
-
|
|
20
|
-
pos = 100
|
|
21
|
-
|
|
22
|
-
overlay.update(img, pos=(2*pos, pos))
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
while not player.core_idle:
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'''
|
|
30
|
-
for pos in range(0, 500, 5):
|
|
31
|
-
ts = player.time_pos
|
|
32
|
-
if ts is None:
|
|
33
|
-
break
|
|
34
|
-
|
|
35
|
-
img = Image.new('RGBA', (400, 150), (255, 255, 255, 0))
|
|
36
|
-
d = ImageDraw.Draw(img)
|
|
37
|
-
d.text((10, 10), 'Hello World', font=font, fill=(0, 255, 255, 128))
|
|
38
|
-
d.text((10, 60), f't={ts:.3f}', font=font, fill=(255, 0, 255, 255))
|
|
39
|
-
|
|
40
|
-
overlay.update(img, pos=(2*pos, pos))
|
|
41
|
-
time.sleep(0.05)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
overlay.remove()
|
|
45
|
-
'''
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/irr_weighted_cohen_kappa.py
RENAMED
|
File without changes
|
|
File without changes
|
{boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/list_of_dataframe_columns.py
RENAMED
|
File without changes
|
{boris_behav_obs-9.6.6 → boris_behav_obs-9.7}/boris/analysis_plugins/number_of_occurences.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|