boris-behav-obs 9.2.1__tar.gz → 9.2.2__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.2.1 → boris_behav_obs-9.2.2}/PKG-INFO +4 -7
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/behavior_binary_table.py +4 -6
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/core.py +2 -7
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/export_events.py +1 -1
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/observation_operations.py +16 -9
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/player_dock_widget.py +19 -4
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/plot_events.py +1 -1
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/plugins.py +31 -4
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/project_functions.py +6 -14
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/time_budget_functions.py +1 -1
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/time_budget_widget.py +1 -1
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/utilities.py +0 -2
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/version.py +2 -2
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/PKG-INFO +4 -7
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/SOURCES.txt +2 -1
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/requires.txt +0 -1
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/pyproject.toml +4 -11
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_utilities.py +7 -0
- boris_behav_obs-9.2.2/tests/test_utilities2.py +124 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/LICENSE.TXT +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/MANIFEST.in +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/README.TXT +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/README.md +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/__init__.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/__main__.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/about.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/add_modifier.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/add_modifier_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/advanced_event_filtering.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/analysis_plugins/__init__.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/analysis_plugins/number_of_occurences.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/analysis_plugins/time_budget.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/behav_coding_map_creator.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/behaviors_coding_map.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/boris_cli.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/cmd_arguments.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/coding_pad.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/config.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/config_file.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/connections.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/converters.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/converters_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/cooccurence.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/core_qrc.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/core_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/db_functions.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/dev.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/dialog.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/duration_widget.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/edit_event.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/edit_event_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/event_operations.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/events_cursor.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/events_snapshots.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/exclusion_matrix.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/export_observation.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/external_processes.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/geometric_measurement.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/gui_utilities.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/image_overlay.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/import_observations.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/irr.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/latency.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/map_creator.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/measurement_widget.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/media_file.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/menu_options.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/modifiers_coding_map.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/mpv-1.0.3.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/mpv.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/mpv2.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/observation.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/observation_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/observations_list.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/otx_parser.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/param_panel.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/param_panel_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/plot_data_module.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/plot_events_rt.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/plot_spectrogram_rt.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/plot_waveform_rt.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/portion/__init__.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/portion/const.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/portion/dict.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/portion/func.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/portion/interval.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/portion/io.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/preferences.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/preferences_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/project.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/project_import_export.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/project_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/qrc_boris.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/qrc_boris5.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/select_modifiers.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/select_observations.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/select_subj_behav.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/state_events.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/subjects_pad.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/synthetic_time_budget.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/transitions.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/video_equalizer.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/video_equalizer_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/video_operations.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/view_df.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/view_df_ui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris/write_event.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/entry_points.txt +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/top_level.txt +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/setup.cfg +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_db_functions.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_export_observation.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_irr.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_observation_gui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_otx_parser.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_preferences_gui.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_project_functions.py +0 -0
- {boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/tests/test_time_budget.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: boris-behav-obs
|
|
3
|
-
Version: 9.2.
|
|
3
|
+
Version: 9.2.2
|
|
4
4
|
Summary: BORIS - Behavioral Observation Research Interactive Software
|
|
5
5
|
Author-email: Olivier Friard <olivier.friard@unito.it>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -686,13 +686,10 @@ Project-URL: Issues, https://github.com/olivierfriard/BORIS/issues
|
|
|
686
686
|
Classifier: Topic :: Scientific/Engineering
|
|
687
687
|
Classifier: Intended Audience :: Science/Research
|
|
688
688
|
Classifier: Intended Audience :: Education
|
|
689
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
690
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
691
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
692
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
693
689
|
Classifier: Programming Language :: Python :: 3.12
|
|
694
690
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
695
691
|
Classifier: Operating System :: OS Independent
|
|
692
|
+
Classifier: Topic :: Scientific/Engineering
|
|
696
693
|
Requires-Python: >=3.12
|
|
697
694
|
Description-Content-Type: text/x-rst
|
|
698
695
|
License-File: LICENSE.TXT
|
|
@@ -705,7 +702,7 @@ Requires-Dist: pyreadr
|
|
|
705
702
|
Requires-Dist: pyside6==6.8.0.2
|
|
706
703
|
Requires-Dist: hachoir>=3.3.0
|
|
707
704
|
Provides-Extra: dev
|
|
708
|
-
Requires-Dist: black; extra == "dev"
|
|
709
705
|
Requires-Dist: ruff; extra == "dev"
|
|
710
706
|
Requires-Dist: pytest; extra == "dev"
|
|
711
707
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
708
|
+
Dynamic: license-file
|
|
@@ -80,12 +80,12 @@ def create_behavior_binary_table(pj: dict, selected_observations: list, paramete
|
|
|
80
80
|
end_time = dec(max_obs_length)
|
|
81
81
|
|
|
82
82
|
if parameters_obs["time"] == cfg.TIME_OBS_INTERVAL:
|
|
83
|
-
obs_interval = pj[cfg.OBSERVATIONS][obs_id]
|
|
83
|
+
obs_interval = pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])
|
|
84
84
|
offset = pj[cfg.OBSERVATIONS][obs_id][cfg.TIME_OFFSET]
|
|
85
85
|
start_time = dec(obs_interval[0]) + offset
|
|
86
86
|
# Use max observation length for end time if no interval is defined (=0)
|
|
87
87
|
max_obs_length, _ = observation_operations.observation_length(pj, [obs_id])
|
|
88
|
-
end_time = dec(obs_interval[1]) + offset if obs_interval[1]
|
|
88
|
+
end_time = dec(obs_interval[1]) + offset if obs_interval[1] not in (0, None) else dec(max_obs_length)
|
|
89
89
|
|
|
90
90
|
if obs_id not in results_df:
|
|
91
91
|
results_df[obs_id] = {}
|
|
@@ -166,8 +166,8 @@ def behavior_binary_table(self):
|
|
|
166
166
|
None,
|
|
167
167
|
cfg.programName,
|
|
168
168
|
(
|
|
169
|
-
"Depending
|
|
170
|
-
"the execution of this function may
|
|
169
|
+
"Depending on the length of yours observations "
|
|
170
|
+
"the execution of this function may take a long time.<br>"
|
|
171
171
|
"The program interface may freeze, be patient. <br>"
|
|
172
172
|
),
|
|
173
173
|
)
|
|
@@ -216,8 +216,6 @@ def behavior_binary_table(self):
|
|
|
216
216
|
selected_observations,
|
|
217
217
|
start_coding=start_coding,
|
|
218
218
|
end_coding=end_coding,
|
|
219
|
-
# start_interval=start_interval,
|
|
220
|
-
# end_interval=end_interval,
|
|
221
219
|
start_interval=start_interval,
|
|
222
220
|
end_interval=end_interval,
|
|
223
221
|
maxTime=max_media_duration_all_obs,
|
|
@@ -3639,10 +3639,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3639
3639
|
self.liveTimer.stop()
|
|
3640
3640
|
self.liveObservationStarted = False
|
|
3641
3641
|
# set current time to end of observation interval
|
|
3642
|
-
current_time = dec(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[1])
|
|
3642
|
+
current_time = dec(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[1])
|
|
3643
3643
|
self.pb_live_obs.setText("Live observation finished")
|
|
3644
3644
|
|
|
3645
|
-
|
|
3646
3645
|
self.lb_current_media_time.setText(util.convertTime(self.timeFormat, current_time))
|
|
3647
3646
|
|
|
3648
3647
|
# extract State events
|
|
@@ -3672,7 +3671,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3672
3671
|
self.liveTimer.stop()
|
|
3673
3672
|
self.pb_live_obs.setText("Live observation stopped (scan sampling)")
|
|
3674
3673
|
|
|
3675
|
-
|
|
3676
3674
|
def start_live_observation(self):
|
|
3677
3675
|
"""
|
|
3678
3676
|
activate the live observation mode
|
|
@@ -5754,10 +5752,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5754
5752
|
if self.playerType == cfg.MEDIA:
|
|
5755
5753
|
self.pause_video()
|
|
5756
5754
|
|
|
5757
|
-
|
|
5758
|
-
self.seek_mediaplayer(int(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.OBSERVATION_TIME_INTERVAL][0]))
|
|
5759
|
-
else:
|
|
5760
|
-
self.seek_mediaplayer(0)
|
|
5755
|
+
self.seek_mediaplayer(int(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])[0]))
|
|
5761
5756
|
|
|
5762
5757
|
self.update_visualizations()
|
|
5763
5758
|
|
|
@@ -788,7 +788,7 @@ def export_events_as_textgrid(self) -> None:
|
|
|
788
788
|
|
|
789
789
|
if parameters["time"] == cfg.TIME_OBS_INTERVAL:
|
|
790
790
|
max_media_duration, _ = observation_operations.media_duration(self.pj[cfg.OBSERVATIONS], [obs_id])
|
|
791
|
-
obs_interval = self.pj[cfg.OBSERVATIONS][obs_id]
|
|
791
|
+
obs_interval = self.pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])
|
|
792
792
|
offset = float(self.pj[cfg.OBSERVATIONS][obs_id][cfg.TIME_OFFSET])
|
|
793
793
|
min_time = float(obs_interval[0]) + offset
|
|
794
794
|
# Use max media duration for max time if no interval is defined (=0)
|
|
@@ -359,14 +359,20 @@ def time_intervals_range(observations: dict, observations_list: list) -> Tuple[O
|
|
|
359
359
|
decimal.Decimal: time of latest end interval
|
|
360
360
|
|
|
361
361
|
"""
|
|
362
|
-
start_interval_list = []
|
|
363
|
-
end_interval_list = []
|
|
362
|
+
start_interval_list: list = []
|
|
363
|
+
end_interval_list: list = []
|
|
364
364
|
for obs_id in observations_list:
|
|
365
365
|
observation = observations[obs_id]
|
|
366
366
|
offset = observation[cfg.TIME_OFFSET]
|
|
367
|
-
if
|
|
368
|
-
|
|
369
|
-
|
|
367
|
+
# check if observation interval is defined
|
|
368
|
+
if (
|
|
369
|
+
not observation.get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[0]
|
|
370
|
+
and not observation.get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[1]
|
|
371
|
+
):
|
|
372
|
+
return None, None
|
|
373
|
+
|
|
374
|
+
start_interval_list.append(dec(observation[cfg.OBSERVATION_TIME_INTERVAL][0]) + offset)
|
|
375
|
+
end_interval_list.append(dec(observation[cfg.OBSERVATION_TIME_INTERVAL][1]) + offset)
|
|
370
376
|
|
|
371
377
|
if not start_interval_list:
|
|
372
378
|
earliest_start_interval = None
|
|
@@ -872,8 +878,8 @@ def new_observation(self, mode: str = cfg.NEW, obsId: str = "") -> None:
|
|
|
872
878
|
observationWindow.cb_observation_time_interval.setText(
|
|
873
879
|
(
|
|
874
880
|
"Limit observation to a time interval: "
|
|
875
|
-
f"{self.pj[cfg.OBSERVATIONS][obsId]
|
|
876
|
-
f"{self.pj[cfg.OBSERVATIONS][obsId]
|
|
881
|
+
f"{self.pj[cfg.OBSERVATIONS][obsId].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])[0]} - "
|
|
882
|
+
f"{self.pj[cfg.OBSERVATIONS][obsId].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])[1]}"
|
|
877
883
|
)
|
|
878
884
|
)
|
|
879
885
|
|
|
@@ -1950,8 +1956,9 @@ def initialize_new_media_observation(self) -> bool:
|
|
|
1950
1956
|
)
|
|
1951
1957
|
|
|
1952
1958
|
# position media
|
|
1953
|
-
|
|
1954
|
-
|
|
1959
|
+
self.seek_mediaplayer(
|
|
1960
|
+
int(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])[0]), player=i
|
|
1961
|
+
)
|
|
1955
1962
|
|
|
1956
1963
|
# restore video zoom level
|
|
1957
1964
|
if cfg.ZOOM_LEVEL in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]:
|
|
@@ -23,7 +23,18 @@ This file is part of BORIS.
|
|
|
23
23
|
import sys
|
|
24
24
|
import logging
|
|
25
25
|
import functools
|
|
26
|
-
from PySide6.QtWidgets import
|
|
26
|
+
from PySide6.QtWidgets import (
|
|
27
|
+
QApplication,
|
|
28
|
+
QLabel,
|
|
29
|
+
QDockWidget,
|
|
30
|
+
QWidget,
|
|
31
|
+
QHBoxLayout,
|
|
32
|
+
QVBoxLayout,
|
|
33
|
+
QSlider,
|
|
34
|
+
QSizePolicy,
|
|
35
|
+
QStackedWidget,
|
|
36
|
+
QToolButton,
|
|
37
|
+
)
|
|
27
38
|
from PySide6.QtCore import Signal, QEvent, Qt
|
|
28
39
|
from PySide6.QtGui import QIcon, QAction
|
|
29
40
|
|
|
@@ -141,7 +152,10 @@ class DW_player(QDockWidget):
|
|
|
141
152
|
self.mute_button.setFocusPolicy(Qt.NoFocus)
|
|
142
153
|
self.mute_button.setAutoRaise(True)
|
|
143
154
|
self.mute_action = QAction()
|
|
144
|
-
|
|
155
|
+
|
|
156
|
+
theme_mode = "dark" if QApplication.instance().palette().window().color().value() < 128 else "light"
|
|
157
|
+
|
|
158
|
+
self.mute_action.setIcon(QIcon(f":/volume_xmark_{theme_mode}"))
|
|
145
159
|
self.mute_action.triggered.connect(self.mute_action_triggered)
|
|
146
160
|
self.mute_button.setDefaultAction(self.mute_action)
|
|
147
161
|
|
|
@@ -180,10 +194,11 @@ class DW_player(QDockWidget):
|
|
|
180
194
|
"""
|
|
181
195
|
emit signal when mute action is triggered
|
|
182
196
|
"""
|
|
197
|
+
theme_mode = "dark" if QApplication.instance().palette().window().color().value() < 128 else "light"
|
|
183
198
|
if self.player.mute:
|
|
184
|
-
self.mute_action.setIcon(QIcon(":/
|
|
199
|
+
self.mute_action.setIcon(QIcon(f":/volume_xmark_{theme_mode}"))
|
|
185
200
|
else:
|
|
186
|
-
self.mute_action.setIcon(QIcon(":/
|
|
201
|
+
self.mute_action.setIcon(QIcon(f":/volume_off_{theme_mode}"))
|
|
187
202
|
self.mute_action_triggered_signal.emit(self.id_)
|
|
188
203
|
|
|
189
204
|
def keyPressEvent(self, event):
|
|
@@ -441,7 +441,7 @@ def create_events_plot(
|
|
|
441
441
|
max_time = float(obs_length)
|
|
442
442
|
|
|
443
443
|
if interval == cfg.TIME_OBS_INTERVAL:
|
|
444
|
-
obs_interval = self.pj[cfg.OBSERVATIONS][obs_id]
|
|
444
|
+
obs_interval = self.pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])
|
|
445
445
|
offset = float(self.pj[cfg.OBSERVATIONS][obs_id][cfg.TIME_OFFSET])
|
|
446
446
|
min_time = float(obs_interval[0]) + offset
|
|
447
447
|
# Use max media duration for max time if no interval is defined (=0)
|
|
@@ -65,24 +65,44 @@ def load_plugins(self):
|
|
|
65
65
|
"""
|
|
66
66
|
load selected plugins in analysis menu
|
|
67
67
|
"""
|
|
68
|
+
|
|
69
|
+
def msg():
|
|
70
|
+
QMessageBox.warning(
|
|
71
|
+
self,
|
|
72
|
+
cfg.programName,
|
|
73
|
+
f"A plugin with the same name is already loaded ({self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name]}).\n\nThe plugin from {file_} is not loaded.",
|
|
74
|
+
QMessageBox.Ok | QMessageBox.Default,
|
|
75
|
+
QMessageBox.NoButton,
|
|
76
|
+
)
|
|
77
|
+
|
|
68
78
|
self.menu_plugins.clear()
|
|
69
79
|
self.config_param[cfg.ANALYSIS_PLUGINS] = {}
|
|
70
80
|
|
|
71
81
|
# load BORIS plugins
|
|
72
|
-
for file_ in (Path(__file__).parent / "analysis_plugins").glob("*.py"):
|
|
82
|
+
for file_ in sorted((Path(__file__).parent / "analysis_plugins").glob("*.py")):
|
|
73
83
|
if file_.name == "__init__.py":
|
|
74
84
|
continue
|
|
75
85
|
plugin_name = get_plugin_name(file_)
|
|
76
86
|
if plugin_name is not None and plugin_name not in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
87
|
+
# check if plugin with same name already loaded
|
|
88
|
+
if plugin_name in self.config_param[cfg.ANALYSIS_PLUGINS]:
|
|
89
|
+
msg()
|
|
90
|
+
continue
|
|
91
|
+
|
|
77
92
|
self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name] = str(file_)
|
|
78
93
|
|
|
79
94
|
# load personal plugins
|
|
80
95
|
if self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""):
|
|
81
|
-
for file_ in Path(self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, "")).glob("*.py"):
|
|
96
|
+
for file_ in sorted(Path(self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, "")).glob("*.py")):
|
|
82
97
|
if file_.name == "__init__.py":
|
|
83
98
|
continue
|
|
84
99
|
plugin_name = get_plugin_name(file_)
|
|
85
100
|
if plugin_name is not None and plugin_name not in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
101
|
+
# check if plugin with same name already loaded
|
|
102
|
+
if plugin_name in self.config_param[cfg.ANALYSIS_PLUGINS]:
|
|
103
|
+
msg()
|
|
104
|
+
continue
|
|
105
|
+
|
|
86
106
|
self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name] = str(file_)
|
|
87
107
|
|
|
88
108
|
logging.debug(f"{self.config_param.get(cfg.ANALYSIS_PLUGINS, {})=}")
|
|
@@ -108,7 +128,7 @@ def plugin_df_filter(df: pd.DataFrame, observations_list: list = [], parameters:
|
|
|
108
128
|
# filter selected behaviors
|
|
109
129
|
df = df[df["Behavior"].isin(parameters["selected behaviors"])]
|
|
110
130
|
|
|
111
|
-
if parameters["time"] ==
|
|
131
|
+
if parameters["time"] == cfg.TIME_OBS_INTERVAL:
|
|
112
132
|
# filter each observation with observation interval start/stop
|
|
113
133
|
|
|
114
134
|
# keep events between observation interval start time and observation interval stop/end
|
|
@@ -142,6 +162,7 @@ def plugin_df_filter(df: pd.DataFrame, observations_list: list = [], parameters:
|
|
|
142
162
|
| ((df["Start (s)"] < MIN_TIME) & (df["Stop (s)"] > MAX_TIME))
|
|
143
163
|
]
|
|
144
164
|
|
|
165
|
+
# cut state events to interval
|
|
145
166
|
df_interval.loc[df["Start (s)"] < MIN_TIME, "Start (s)"] = MIN_TIME
|
|
146
167
|
df_interval.loc[df["Stop (s)"] > MAX_TIME, "Stop (s)"] = MAX_TIME
|
|
147
168
|
|
|
@@ -152,7 +173,7 @@ def plugin_df_filter(df: pd.DataFrame, observations_list: list = [], parameters:
|
|
|
152
173
|
print("filtered")
|
|
153
174
|
print("=" * 50)
|
|
154
175
|
|
|
155
|
-
print(f"{df=}")
|
|
176
|
+
# print(f"{df=}")
|
|
156
177
|
|
|
157
178
|
return df
|
|
158
179
|
|
|
@@ -205,8 +226,12 @@ def run_plugin(self, plugin_name):
|
|
|
205
226
|
if not selected_observations:
|
|
206
227
|
return
|
|
207
228
|
|
|
229
|
+
logging.info("preparing dtaaframe for plugin")
|
|
230
|
+
|
|
208
231
|
df = project_functions.project2dataframe(self.pj, selected_observations)
|
|
209
232
|
|
|
233
|
+
logging.info("done")
|
|
234
|
+
|
|
210
235
|
"""
|
|
211
236
|
logging.debug("dataframe info")
|
|
212
237
|
logging.debug(f"{df.info()}")
|
|
@@ -214,7 +239,9 @@ def run_plugin(self, plugin_name):
|
|
|
214
239
|
"""
|
|
215
240
|
|
|
216
241
|
# filter the dataframe with parameters
|
|
242
|
+
logging.info("filtering dataframe for plugin")
|
|
217
243
|
filtered_df = plugin_df_filter(df, observations_list=selected_observations, parameters=parameters)
|
|
244
|
+
logging.info("done")
|
|
218
245
|
|
|
219
246
|
plugin_results = plugin_module.run(filtered_df)
|
|
220
247
|
# test if plugin_tests is a tuple: if not transform to tuple
|
|
@@ -1899,20 +1899,12 @@ def project2dataframe(pj: dict, observations_list: list = []) -> pd.DataFrame:
|
|
|
1899
1899
|
if idx_event in stop_event_idx:
|
|
1900
1900
|
continue
|
|
1901
1901
|
data["Observation id"].append(obs_id)
|
|
1902
|
-
data["Observation date"].append(pj[
|
|
1903
|
-
data["Description"].append(" ".join(pj[
|
|
1904
|
-
data["Observation type"].append(pj[
|
|
1905
|
-
|
|
1906
|
-
data["Observation interval start"].append(
|
|
1907
|
-
|
|
1908
|
-
if pj["observations"][obs_id]["observation time interval"][0]
|
|
1909
|
-
else None
|
|
1910
|
-
)
|
|
1911
|
-
data["Observation interval stop"].append(
|
|
1912
|
-
pj["observations"][obs_id]["observation time interval"][1]
|
|
1913
|
-
if pj["observations"][obs_id]["observation time interval"][1]
|
|
1914
|
-
else None
|
|
1915
|
-
)
|
|
1902
|
+
data["Observation date"].append(pj[cfg.OBSERVATIONS][obs_id]["date"])
|
|
1903
|
+
data["Description"].append(" ".join(pj[cfg.OBSERVATIONS][obs_id]["description"].splitlines()))
|
|
1904
|
+
data["Observation type"].append(pj[cfg.OBSERVATIONS][obs_id]["type"])
|
|
1905
|
+
|
|
1906
|
+
data["Observation interval start"].append(pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[0])
|
|
1907
|
+
data["Observation interval stop"].append(pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[1])
|
|
1916
1908
|
|
|
1917
1909
|
# data["Source"].append("")
|
|
1918
1910
|
# data["Time offset (s)"].append(pj["observations"][obs_id]["time offset"])
|
|
@@ -260,7 +260,7 @@ def synthetic_time_budget_bin(pj: dict, selected_observations: list, parameters_
|
|
|
260
260
|
max_time = dec(end_time)
|
|
261
261
|
|
|
262
262
|
if time_interval == cfg.TIME_OBS_INTERVAL:
|
|
263
|
-
obs_interval = pj[cfg.OBSERVATIONS][obs_id]
|
|
263
|
+
obs_interval = pj[cfg.OBSERVATIONS][obs_id].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])
|
|
264
264
|
offset = pj[cfg.OBSERVATIONS][obs_id][cfg.TIME_OFFSET]
|
|
265
265
|
min_time = dec(obs_interval[0]) + offset
|
|
266
266
|
# Use max media duration for max time if no interval is defined (=0)
|
|
@@ -504,7 +504,7 @@ def time_budget(self, mode: str, mode2: str = "list"):
|
|
|
504
504
|
max_time = float(obs_length)
|
|
505
505
|
|
|
506
506
|
if parameters[cfg.TIME_INTERVAL] == cfg.TIME_OBS_INTERVAL:
|
|
507
|
-
obs_interval = self.pj[cfg.OBSERVATIONS][obsId]
|
|
507
|
+
obs_interval = self.pj[cfg.OBSERVATIONS][obsId].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])
|
|
508
508
|
offset = float(self.pj[cfg.OBSERVATIONS][obsId][cfg.TIME_OFFSET])
|
|
509
509
|
min_time = float(obs_interval[0]) + offset
|
|
510
510
|
# Use max media duration for max time if no interval is defined (=0)
|
|
@@ -1456,8 +1456,6 @@ def accurate_media_analysis(ffmpeg_bin: str, file_name: str) -> dict:
|
|
|
1456
1456
|
|
|
1457
1457
|
ffprobe_results = ffprobe_media_analysis(ffmpeg_bin, file_name)
|
|
1458
1458
|
|
|
1459
|
-
print(f"{ffprobe_results=}")
|
|
1460
|
-
|
|
1461
1459
|
logging.debug(f"file_name: {file_name}")
|
|
1462
1460
|
logging.debug(f"ffprobe_results: {ffprobe_results}")
|
|
1463
1461
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: boris-behav-obs
|
|
3
|
-
Version: 9.2.
|
|
3
|
+
Version: 9.2.2
|
|
4
4
|
Summary: BORIS - Behavioral Observation Research Interactive Software
|
|
5
5
|
Author-email: Olivier Friard <olivier.friard@unito.it>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -686,13 +686,10 @@ Project-URL: Issues, https://github.com/olivierfriard/BORIS/issues
|
|
|
686
686
|
Classifier: Topic :: Scientific/Engineering
|
|
687
687
|
Classifier: Intended Audience :: Science/Research
|
|
688
688
|
Classifier: Intended Audience :: Education
|
|
689
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
690
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
691
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
692
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
693
689
|
Classifier: Programming Language :: Python :: 3.12
|
|
694
690
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
695
691
|
Classifier: Operating System :: OS Independent
|
|
692
|
+
Classifier: Topic :: Scientific/Engineering
|
|
696
693
|
Requires-Python: >=3.12
|
|
697
694
|
Description-Content-Type: text/x-rst
|
|
698
695
|
License-File: LICENSE.TXT
|
|
@@ -705,7 +702,7 @@ Requires-Dist: pyreadr
|
|
|
705
702
|
Requires-Dist: pyside6==6.8.0.2
|
|
706
703
|
Requires-Dist: hachoir>=3.3.0
|
|
707
704
|
Provides-Extra: dev
|
|
708
|
-
Requires-Dist: black; extra == "dev"
|
|
709
705
|
Requires-Dist: ruff; extra == "dev"
|
|
710
706
|
Requires-Dist: pytest; extra == "dev"
|
|
711
707
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
708
|
+
Dynamic: license-file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "boris-behav-obs"
|
|
3
|
-
version = "9.2.
|
|
3
|
+
version = "9.2.2"
|
|
4
4
|
description = "BORIS - Behavioral Observation Research Interactive Software"
|
|
5
5
|
authors = [{ name="Olivier Friard", email="olivier.friard@unito.it" }]
|
|
6
6
|
readme = "README.rst"
|
|
@@ -10,13 +10,10 @@ classifiers=[
|
|
|
10
10
|
"Topic :: Scientific/Engineering",
|
|
11
11
|
"Intended Audience :: Science/Research",
|
|
12
12
|
"Intended Audience :: Education",
|
|
13
|
-
"Programming Language :: Python :: 3.8",
|
|
14
|
-
"Programming Language :: Python :: 3.9",
|
|
15
|
-
"Programming Language :: Python :: 3.10",
|
|
16
|
-
"Programming Language :: Python :: 3.11",
|
|
17
13
|
"Programming Language :: Python :: 3.12",
|
|
18
14
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
19
15
|
"Operating System :: OS Independent",
|
|
16
|
+
"Topic :: Scientific/Engineering",
|
|
20
17
|
]
|
|
21
18
|
dependencies = [
|
|
22
19
|
"exifread>=3.0.0",
|
|
@@ -30,7 +27,7 @@ dependencies = [
|
|
|
30
27
|
]
|
|
31
28
|
|
|
32
29
|
[project.optional-dependencies]
|
|
33
|
-
dev = ["
|
|
30
|
+
dev = ["ruff", "pytest", "pytest-cov"]
|
|
34
31
|
|
|
35
32
|
[project.urls]
|
|
36
33
|
Homepage = "http://www.boris.unito.it"
|
|
@@ -42,10 +39,6 @@ Issues = "https://github.com/olivierfriard/BORIS/issues"
|
|
|
42
39
|
[project.scripts]
|
|
43
40
|
boris-behav-obs = "boris:main"
|
|
44
41
|
|
|
45
|
-
[build-system]
|
|
46
|
-
requires = ["setuptools", "wheel"]
|
|
47
|
-
build-backend = "setuptools.build_meta"
|
|
48
|
-
|
|
49
42
|
|
|
50
43
|
[tool.distutils.bdist_wheel]
|
|
51
44
|
universal = true
|
|
@@ -55,7 +48,7 @@ line-length = 140
|
|
|
55
48
|
exclude = ["*_ui.py", "mpv*"]
|
|
56
49
|
|
|
57
50
|
[tool.bumpver]
|
|
58
|
-
current_version = "9.2.
|
|
51
|
+
current_version = "9.2.2"
|
|
59
52
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
60
53
|
|
|
61
54
|
|
|
@@ -44,6 +44,8 @@ class Test_accurate_media_analysis(object):
|
|
|
44
44
|
"resolution": "640x480",
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
|
|
48
|
+
"""
|
|
47
49
|
def test_no_media(self):
|
|
48
50
|
r = utilities.accurate_media_analysis("ffmpeg", "files/test.boris")
|
|
49
51
|
assert "error" in r
|
|
@@ -358,10 +360,14 @@ class Test_get_current_states_by_subject(object):
|
|
|
358
360
|
|
|
359
361
|
|
|
360
362
|
"""
|
|
363
|
+
|
|
364
|
+
|
|
361
365
|
class Test_get_ip_address(object):
|
|
362
366
|
def test_1(self):
|
|
363
367
|
print(utilities.get_ip_address())
|
|
364
368
|
assert False
|
|
369
|
+
|
|
370
|
+
|
|
365
371
|
"""
|
|
366
372
|
|
|
367
373
|
|
|
@@ -587,3 +593,4 @@ class Test_versiontuple(object):
|
|
|
587
593
|
def test_4(self):
|
|
588
594
|
r = utilities.versiontuple("")
|
|
589
595
|
assert r == ("00000000",)
|
|
596
|
+
"""
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import pytest
|
|
4
|
+
import subprocess
|
|
5
|
+
from unittest.mock import patch, MagicMock
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
# Assuming the function is imported from a module named `media_analysis`
|
|
9
|
+
# from media_analysis import accurate_media_analysis
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from boris import utilities
|
|
15
|
+
from boris import config
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Mocking the ffprobe_media_analysis function
|
|
19
|
+
def mock_ffprobe_media_analysis(ffmpeg_bin, file_name):
|
|
20
|
+
return {
|
|
21
|
+
"duration": 120,
|
|
22
|
+
"duration_ms": 120000,
|
|
23
|
+
"bitrate": 5000,
|
|
24
|
+
"frames_number": 3000,
|
|
25
|
+
"fps": 25,
|
|
26
|
+
"has_video": True,
|
|
27
|
+
"has_audio": True,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Mocking the time2seconds function
|
|
32
|
+
def mock_time2seconds(time_str):
|
|
33
|
+
return 120
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Mocking the dec function
|
|
37
|
+
def mock_dec(value):
|
|
38
|
+
return float(value)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@patch("utilities.ffprobe_media_analysis", side_effect=mock_ffprobe_media_analysis)
|
|
42
|
+
@patch("utilities.time2seconds", side_effect=mock_time2seconds)
|
|
43
|
+
@patch("utilities.dec", side_effect=mock_dec)
|
|
44
|
+
def test_accurate_media_analysis_success(mock_dec, mock_time2seconds, mock_ffprobe_media_analysis):
|
|
45
|
+
ffmpeg_bin = "/path/to/ffmpeg"
|
|
46
|
+
file_name = "test_video.mp4"
|
|
47
|
+
|
|
48
|
+
result = utilities.accurate_media_analysis(ffmpeg_bin, file_name)
|
|
49
|
+
|
|
50
|
+
assert result["duration"] == 120
|
|
51
|
+
assert result["duration_ms"] == 120000
|
|
52
|
+
assert result["bitrate"] == 5000
|
|
53
|
+
assert result["frames_number"] == 3000
|
|
54
|
+
assert result["fps"] == 25
|
|
55
|
+
assert result["has_video"] is True
|
|
56
|
+
assert result["has_audio"] is True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
@patch("utilities.ffprobe_media_analysis", return_value={"error": "ffprobe failed"})
|
|
62
|
+
@patch("utilities.time2seconds", side_effect=mock_time2seconds)
|
|
63
|
+
@patch("utilities.dec", side_effect=mock_dec)
|
|
64
|
+
@patch("subprocess.Popen")
|
|
65
|
+
def test_accurate_media_analysis_fallback(mock_popen, mock_dec, mock_time2seconds, mock_ffprobe_media_analysis):
|
|
66
|
+
ffmpeg_bin = "/path/to/ffmpeg"
|
|
67
|
+
file_name = "test_video.mp4"
|
|
68
|
+
|
|
69
|
+
# Mocking the subprocess.Popen behavior
|
|
70
|
+
mock_process = MagicMock()
|
|
71
|
+
mock_process.communicate.return_value = (
|
|
72
|
+
b"",
|
|
73
|
+
b"Duration: 00:02:00.00, bitrate: 5000 kb/s\nStream #0:0: Video: h264, 1920x1080, 25 fps\nStream #0:1: Audio: aac",
|
|
74
|
+
)
|
|
75
|
+
mock_popen.return_value = mock_process
|
|
76
|
+
|
|
77
|
+
result = utilities.accurate_media_analysis(ffmpeg_bin, file_name)
|
|
78
|
+
|
|
79
|
+
assert result["duration"] == 120
|
|
80
|
+
assert result["duration_ms"] == 120000
|
|
81
|
+
assert result["bitrate"] == 5000000
|
|
82
|
+
assert result["frames_number"] == 3000
|
|
83
|
+
assert result["fps"] == 25
|
|
84
|
+
assert result["has_video"] is True
|
|
85
|
+
assert result["has_audio"] is True
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@patch("utilities.ffprobe_media_analysis", return_value={"error": "ffprobe failed"})
|
|
89
|
+
@patch("utilities.time2seconds", side_effect=mock_time2seconds)
|
|
90
|
+
@patch("utilities.dec", side_effect=mock_dec)
|
|
91
|
+
@patch("subprocess.Popen")
|
|
92
|
+
def test_accurate_media_analysis_file_not_found(mock_popen, mock_dec, mock_time2seconds, mock_ffprobe_media_analysis):
|
|
93
|
+
ffmpeg_bin = "/path/to/ffmpeg"
|
|
94
|
+
file_name = "nonexistent_video.mp4"
|
|
95
|
+
|
|
96
|
+
# Mocking the subprocess.Popen behavior
|
|
97
|
+
mock_process = MagicMock()
|
|
98
|
+
mock_process.communicate.return_value = (b"", b"No such file or directory")
|
|
99
|
+
mock_popen.return_value = mock_process
|
|
100
|
+
|
|
101
|
+
result = utilities.accurate_media_analysis(ffmpeg_bin, file_name)
|
|
102
|
+
|
|
103
|
+
assert result["error"] == "No such file or directory"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@patch("utilities.ffprobe_media_analysis", return_value={"error": "ffprobe failed"})
|
|
107
|
+
@patch("utilities.time2seconds", side_effect=mock_time2seconds)
|
|
108
|
+
@patch("utilities.dec", side_effect=mock_dec)
|
|
109
|
+
@patch("subprocess.Popen")
|
|
110
|
+
def test_accurate_media_analysis_invalid_media(mock_popen, mock_dec, mock_time2seconds, mock_ffprobe_media_analysis):
|
|
111
|
+
ffmpeg_bin = "/path/to/ffmpeg"
|
|
112
|
+
file_name = "invalid_media.mp4"
|
|
113
|
+
|
|
114
|
+
# Mocking the subprocess.Popen behavior
|
|
115
|
+
mock_process = MagicMock()
|
|
116
|
+
mock_process.communicate.return_value = (b"", b"Invalid data found when processing input")
|
|
117
|
+
mock_popen.return_value = mock_process
|
|
118
|
+
|
|
119
|
+
result = utilities.accurate_media_analysis(ffmpeg_bin, file_name)
|
|
120
|
+
|
|
121
|
+
assert result["error"] == "This file does not seem to be a media file"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
"""
|
|
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.2.1 → boris_behav_obs-9.2.2}/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
|
{boris_behav_obs-9.2.1 → boris_behav_obs-9.2.2}/boris_behav_obs.egg-info/dependency_links.txt
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
|