boris-behav-obs 9.2.1__py2.py3-none-any.whl → 9.2.3__py2.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/behavior_binary_table.py +4 -6
- boris/connections.py +3 -1
- boris/core.py +21 -24
- boris/export_events.py +1 -1
- boris/export_observation.py +4 -1
- boris/observation_operations.py +16 -9
- boris/player_dock_widget.py +19 -4
- boris/plot_events.py +1 -1
- boris/plugins.py +31 -4
- boris/project_functions.py +6 -14
- boris/synthetic_time_budget.py +2 -2
- boris/time_budget_functions.py +1 -1
- boris/time_budget_widget.py +1 -1
- boris/utilities.py +0 -2
- boris/version.py +2 -2
- boris_behav_obs-9.2.3.dist-info/METADATA +33 -0
- {boris_behav_obs-9.2.1.dist-info → boris_behav_obs-9.2.3.dist-info}/RECORD +21 -21
- {boris_behav_obs-9.2.1.dist-info → boris_behav_obs-9.2.3.dist-info}/WHEEL +1 -1
- boris_behav_obs-9.2.3.dist-info/entry_points.txt +2 -0
- boris_behav_obs-9.2.1.dist-info/METADATA +0 -711
- boris_behav_obs-9.2.1.dist-info/entry_points.txt +0 -2
- {boris_behav_obs-9.2.1.dist-info → boris_behav_obs-9.2.3.dist-info/licenses}/LICENSE.TXT +0 -0
- {boris_behav_obs-9.2.1.dist-info → boris_behav_obs-9.2.3.dist-info}/top_level.txt +0 -0
boris/behavior_binary_table.py
CHANGED
|
@@ -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,
|
boris/connections.py
CHANGED
|
@@ -271,7 +271,9 @@ def connections(self):
|
|
|
271
271
|
self.actionViewBehavior.triggered.connect(self.view_behavior)
|
|
272
272
|
self.twEthogram.addAction(self.actionViewBehavior)
|
|
273
273
|
|
|
274
|
-
self.actionFilterBehaviors.triggered.connect(
|
|
274
|
+
self.actionFilterBehaviors.triggered.connect(
|
|
275
|
+
lambda: self.filter_behaviors(table=cfg.ETHOGRAM, behavior_type=cfg.STATE_EVENT_TYPES + cfg.POINT_EVENT_TYPES)
|
|
276
|
+
)
|
|
275
277
|
self.twEthogram.addAction(self.actionFilterBehaviors)
|
|
276
278
|
|
|
277
279
|
self.actionShowAllBehaviors.triggered.connect(self.show_all_behaviors)
|
boris/core.py
CHANGED
|
@@ -794,10 +794,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
794
794
|
|
|
795
795
|
def filter_behaviors(
|
|
796
796
|
self,
|
|
797
|
-
title="Select the behaviors to show in the ethogram table",
|
|
798
|
-
text="Behaviors to show in ethogram list",
|
|
799
|
-
table=cfg.ETHOGRAM,
|
|
800
|
-
behavior_type=cfg.STATE_EVENT_TYPES,
|
|
797
|
+
title: str = "Select the behaviors to show in the ethogram table",
|
|
798
|
+
text: str = "Behaviors to show in ethogram list",
|
|
799
|
+
table: str = cfg.ETHOGRAM,
|
|
800
|
+
behavior_type: list = cfg.STATE_EVENT_TYPES,
|
|
801
801
|
) -> Tuple[bool, list]:
|
|
802
802
|
"""
|
|
803
803
|
allow user to:
|
|
@@ -809,6 +809,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
809
809
|
title (str): title of dialog box
|
|
810
810
|
text (str): text of dialog box
|
|
811
811
|
table (str): table where behaviors will be filtered
|
|
812
|
+
behavior_type
|
|
812
813
|
|
|
813
814
|
Returns:
|
|
814
815
|
(None if table = ETHOGRAM)
|
|
@@ -858,21 +859,22 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
858
859
|
categories = ["###no category###"]
|
|
859
860
|
|
|
860
861
|
for category in categories:
|
|
861
|
-
if category
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
862
|
+
if category == "###no category###":
|
|
863
|
+
continue
|
|
864
|
+
if category == "":
|
|
865
|
+
paramPanelWindow.item = QListWidgetItem("No category")
|
|
866
|
+
paramPanelWindow.item.setData(34, "No category")
|
|
867
|
+
else:
|
|
868
|
+
paramPanelWindow.item = QListWidgetItem(category)
|
|
869
|
+
paramPanelWindow.item.setData(34, category)
|
|
868
870
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
871
|
+
font = QFont()
|
|
872
|
+
font.setBold(True)
|
|
873
|
+
paramPanelWindow.item.setFont(font)
|
|
874
|
+
paramPanelWindow.item.setData(33, "category")
|
|
875
|
+
paramPanelWindow.item.setData(35, False)
|
|
874
876
|
|
|
875
|
-
|
|
877
|
+
paramPanelWindow.lwBehaviors.addItem(paramPanelWindow.item)
|
|
876
878
|
|
|
877
879
|
# check if behavior type must be shown
|
|
878
880
|
for behavior in [self.pj[cfg.ETHOGRAM][x][cfg.BEHAVIOR_CODE] for x in util.sorted_keys(self.pj[cfg.ETHOGRAM])]:
|
|
@@ -3639,10 +3641,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3639
3641
|
self.liveTimer.stop()
|
|
3640
3642
|
self.liveObservationStarted = False
|
|
3641
3643
|
# 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])
|
|
3644
|
+
current_time = dec(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.OBSERVATION_TIME_INTERVAL, [None, None])[1])
|
|
3643
3645
|
self.pb_live_obs.setText("Live observation finished")
|
|
3644
3646
|
|
|
3645
|
-
|
|
3646
3647
|
self.lb_current_media_time.setText(util.convertTime(self.timeFormat, current_time))
|
|
3647
3648
|
|
|
3648
3649
|
# extract State events
|
|
@@ -3672,7 +3673,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3672
3673
|
self.liveTimer.stop()
|
|
3673
3674
|
self.pb_live_obs.setText("Live observation stopped (scan sampling)")
|
|
3674
3675
|
|
|
3675
|
-
|
|
3676
3676
|
def start_live_observation(self):
|
|
3677
3677
|
"""
|
|
3678
3678
|
activate the live observation mode
|
|
@@ -5754,10 +5754,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5754
5754
|
if self.playerType == cfg.MEDIA:
|
|
5755
5755
|
self.pause_video()
|
|
5756
5756
|
|
|
5757
|
-
|
|
5758
|
-
self.seek_mediaplayer(int(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.OBSERVATION_TIME_INTERVAL][0]))
|
|
5759
|
-
else:
|
|
5760
|
-
self.seek_mediaplayer(0)
|
|
5757
|
+
self.seek_mediaplayer(int(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.OBSERVATION_TIME_INTERVAL, [0, 0])[0]))
|
|
5761
5758
|
|
|
5762
5759
|
self.update_visualizations()
|
|
5763
5760
|
|
boris/export_events.py
CHANGED
|
@@ -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)
|
boris/export_observation.py
CHANGED
|
@@ -121,7 +121,10 @@ def export_events_jwatcher(
|
|
|
121
121
|
except Exception:
|
|
122
122
|
# coded behavior not defined in ethogram
|
|
123
123
|
continue
|
|
124
|
-
if [ethogram[k][cfg.TYPE] for k in ethogram if ethogram[k][cfg.BEHAVIOR_CODE] == behav_code]
|
|
124
|
+
if [ethogram[k][cfg.TYPE] for k in ethogram if ethogram[k][cfg.BEHAVIOR_CODE] == behav_code] in [
|
|
125
|
+
[cfg.STATE_EVENT],
|
|
126
|
+
[cfg.STATE_EVENT_WITH_CODING_MAP],
|
|
127
|
+
]:
|
|
125
128
|
if behav_code in mem_number_of_state_events:
|
|
126
129
|
mem_number_of_state_events[behav_code] += 1
|
|
127
130
|
else:
|
boris/observation_operations.py
CHANGED
|
@@ -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]:
|
boris/player_dock_widget.py
CHANGED
|
@@ -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):
|
boris/plot_events.py
CHANGED
|
@@ -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)
|
boris/plugins.py
CHANGED
|
@@ -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
|
boris/project_functions.py
CHANGED
|
@@ -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"])
|
boris/synthetic_time_budget.py
CHANGED
|
@@ -95,7 +95,7 @@ def synthetic_time_budget(self) -> None:
|
|
|
95
95
|
title="Select behaviors to exclude from the total time",
|
|
96
96
|
text="The duration of the selected behaviors will be subtracted from the total time",
|
|
97
97
|
table="",
|
|
98
|
-
behavior_type=
|
|
98
|
+
behavior_type=cfg.STATE_EVENT_TYPES,
|
|
99
99
|
)
|
|
100
100
|
if cancel_pressed:
|
|
101
101
|
return
|
|
@@ -227,7 +227,7 @@ def synthetic_binned_time_budget(self) -> None:
|
|
|
227
227
|
title="Select behaviors to exclude",
|
|
228
228
|
text=("The duration of the selected behaviors will be subtracted from the total time"),
|
|
229
229
|
table="",
|
|
230
|
-
behavior_type=
|
|
230
|
+
behavior_type=cfg.STATE_EVENT_TYPES,
|
|
231
231
|
)
|
|
232
232
|
if cancel_pressed:
|
|
233
233
|
return
|
boris/time_budget_functions.py
CHANGED
|
@@ -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)
|
boris/time_budget_widget.py
CHANGED
|
@@ -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)
|
boris/utilities.py
CHANGED
|
@@ -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
|
|
boris/version.py
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: boris-behav-obs
|
|
3
|
+
Version: 9.2.3
|
|
4
|
+
Summary: BORIS - Behavioral Observation Research Interactive Software
|
|
5
|
+
Author-email: Olivier Friard <olivier.friard@unito.it>
|
|
6
|
+
License-Expression: GPL-3.0-only
|
|
7
|
+
Project-URL: Homepage, http://www.boris.unito.it
|
|
8
|
+
Project-URL: Documentation, https://boris.readthedocs.io/en/latest/
|
|
9
|
+
Project-URL: Change_log, https://github.com/olivierfriard/BORIS/wiki/BORIS-change-log-v.8
|
|
10
|
+
Project-URL: Source_code, https://github.com/olivierfriard/BORIS
|
|
11
|
+
Project-URL: Issues, https://github.com/olivierfriard/BORIS/issues
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Description-Content-Type: text/x-rst
|
|
20
|
+
License-File: LICENSE.TXT
|
|
21
|
+
Requires-Dist: exifread>=3.0.0
|
|
22
|
+
Requires-Dist: numpy>=1.26.4
|
|
23
|
+
Requires-Dist: matplotlib>=3.3.3
|
|
24
|
+
Requires-Dist: pandas>=2.2.2
|
|
25
|
+
Requires-Dist: tablib[cli,html,ods,pandas,xls,xlsx]>=3
|
|
26
|
+
Requires-Dist: pyreadr
|
|
27
|
+
Requires-Dist: pyside6==6.8.0.2
|
|
28
|
+
Requires-Dist: hachoir>=3.3.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: ruff; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
@@ -5,18 +5,18 @@ boris/add_modifier.py,sha256=DWqxkKDBm21QH_kPvhpnltwLtFvPxne0VmZ1SY26hj8,26340
|
|
|
5
5
|
boris/add_modifier_ui.py,sha256=Y7TLO5uS6zW7zpjXmjA4V_VIp_bFDNtjOTbJ9Q6m-mQ,11601
|
|
6
6
|
boris/advanced_event_filtering.py,sha256=VlvU12mL6xYacZOvJAi5uLpHMcmAw5Pvuvmka-PN29c,15469
|
|
7
7
|
boris/behav_coding_map_creator.py,sha256=PSEYMLvOwt0HR7H4kQZl6dli3q89wezWMv-Ri3EZWWc,37443
|
|
8
|
-
boris/behavior_binary_table.py,sha256=
|
|
8
|
+
boris/behavior_binary_table.py,sha256=bpmRDpEjq0rw3YOCoN_He3kfUe8A_R6E48kQR7KnkH8,12453
|
|
9
9
|
boris/behaviors_coding_map.py,sha256=Pat6U2JHxH8epWH42ZlwzZJ0Rmgl-BKQ5KARjp3GbNg,7291
|
|
10
10
|
boris/boris_cli.py,sha256=n0OiVvZM1gM6E7yKaff9wlgmpAGK4TK052VRi8AabJo,13196
|
|
11
11
|
boris/cmd_arguments.py,sha256=oWb-FvhKLbKJhATlTHy9muWu8XnnUfOZ-3Fmz2M8Yzc,1848
|
|
12
12
|
boris/coding_pad.py,sha256=fBKdp7DDyupySJosIYtqNd8s2E-GruzCgVhDFsoVWKE,10986
|
|
13
13
|
boris/config.py,sha256=cy4MSVFMHYaEHpHdncljuiaMSTpV6rFNm1OyVYF28Bc,17295
|
|
14
14
|
boris/config_file.py,sha256=1-2ZmTvKET57rwrLR1dXblt0AxMpGB1LAiHxu-Sy8es,13543
|
|
15
|
-
boris/connections.py,sha256=
|
|
15
|
+
boris/connections.py,sha256=UflmxTLTAeJgtu2C8nMv37erVYWftZQULqwZ6RkD9WA,19396
|
|
16
16
|
boris/converters.py,sha256=c1Jps-URoglY5ILQHz-pCCf6-4DFUHZLtqr_ofsrFg0,11722
|
|
17
17
|
boris/converters_ui.py,sha256=uu7LOBV_fKv2DBdOqsqPwjGsjgONr5ODBoscAA-EP48,9900
|
|
18
18
|
boris/cooccurence.py,sha256=tVERC-V8MWjWHlGEfDuu08iS94qjt4do-38jwI62QaY,10367
|
|
19
|
-
boris/core.py,sha256=
|
|
19
|
+
boris/core.py,sha256=HWJVt1MHRjlMgsyz044tCCtT3c8F47n2kGSH_HGtDFw,234686
|
|
20
20
|
boris/core_qrc.py,sha256=T3ki5e2Pj0I0QBGz63MPUgZzl8F_VHZwSq074mRNBDU,650669
|
|
21
21
|
boris/core_ui.py,sha256=SeC26uveDCjrCBLsRPuQ6FaapKfON_HIRcQStEDLhl4,76384
|
|
22
22
|
boris/db_functions.py,sha256=Uw9wWH_Pe-qNzpV1k21YG_jKsoOmfY_iiK_7ARZHGDc,13352
|
|
@@ -29,8 +29,8 @@ boris/event_operations.py,sha256=ys1DxZ6iooMvvq_hzpPVZSW0dF9Trbx921XV3jeKOxw,382
|
|
|
29
29
|
boris/events_cursor.py,sha256=VPY_ygD0fxE5lp25mcd2l00XQXurCR6hprffF4tKRbU,2078
|
|
30
30
|
boris/events_snapshots.py,sha256=PjWzQvUGQtIcEc_7FDsRphf7fAhhTccQgYc2eQSA65g,27621
|
|
31
31
|
boris/exclusion_matrix.py,sha256=ff88xD6aqc8bpIuj9ZCz9ju_HeqqgibQwoaJrIOJ6RI,5272
|
|
32
|
-
boris/export_events.py,sha256=
|
|
33
|
-
boris/export_observation.py,sha256=
|
|
32
|
+
boris/export_events.py,sha256=3B336WEA0g_8oW3VDo_kfq5D0ISu-e7z2f-_ROUvU9c,39756
|
|
33
|
+
boris/export_observation.py,sha256=SvKhuGa-Ag_kK3igL9DFdJ0TKoQLDneu54R_uiSHUyo,50813
|
|
34
34
|
boris/external_processes.py,sha256=vpmhA4Lj2GblBIrDD0YjesB8HPOgx4K9gSWVhTop4Cg,11927
|
|
35
35
|
boris/geometric_measurement.py,sha256=4pI-AYpBSFlJBqS-f8dnkgLtj_Z2E5kwwAdh6WwZ4kk,35049
|
|
36
36
|
boris/gui_utilities.py,sha256=5vjIWbUOHFbqKSti-kT0GoteBBEQ5fUYdNGdMxcg_0A,4607
|
|
@@ -47,23 +47,23 @@ boris/mpv-1.0.3.py,sha256=EXRtzQqFjOn4wMC6482Ilq3fNQ9N1GRP1VxwLzdeaBY,88077
|
|
|
47
47
|
boris/mpv.py,sha256=EfzIHjPbgewG4w3smEtqEUPZoVwYmMQkL4Q8ZyW-a58,76410
|
|
48
48
|
boris/mpv2.py,sha256=IUI4t4r9GYX7G5OXTjd3RhMMOkDdfal_15buBgksLsk,92152
|
|
49
49
|
boris/observation.py,sha256=oop08nflDLZAgDbIB8GOiVdTgLhppJ_ODH0Z24cyqvE,57176
|
|
50
|
-
boris/observation_operations.py,sha256=
|
|
50
|
+
boris/observation_operations.py,sha256=j7TSGzWSRmAdmD7vdrfvEBFtCfM0HXbo9VeIHNew2PY,105748
|
|
51
51
|
boris/observation_ui.py,sha256=DAnU94QBNvkLuHT6AxTwqSk_D_n6VUhSl8PexZv_dUk,33309
|
|
52
52
|
boris/observations_list.py,sha256=NqwECGHtHYmKhSe-qCfqPmJ24SSfzlXvIXS2i3op_zE,10591
|
|
53
53
|
boris/otx_parser.py,sha256=70QvilzFHXbjAHR88YH0aEXJ3xxheLS5fZGgHFHGpNE,16367
|
|
54
54
|
boris/param_panel.py,sha256=G0XzNmJIX89-n2OQTDccuY_wWMhr3p7GB4ZorbU6EWc,8786
|
|
55
55
|
boris/param_panel_ui.py,sha256=4emQDFmuL4_R7bKxosLjdUb-VSPWkDm7suy38F5EKcA,13260
|
|
56
|
-
boris/player_dock_widget.py,sha256=
|
|
56
|
+
boris/player_dock_widget.py,sha256=aDC6a7JEEY64TWMDU_jBBaavN-Z-fd9JQo9BnnNI4_M,6303
|
|
57
57
|
boris/plot_data_module.py,sha256=6QbLKfyGp4TYRyHnB9G45y5XrpeXLytcorltEAWfYak,16562
|
|
58
|
-
boris/plot_events.py,sha256=
|
|
58
|
+
boris/plot_events.py,sha256=CF6gnsTeaPG-P1USwh4An2s31NoMJ1roHDImcQrQj3c,24060
|
|
59
59
|
boris/plot_events_rt.py,sha256=xig__Uea3mQqO5raMBVB3pm3vuQkjAbJpwSS7AwIob8,8327
|
|
60
60
|
boris/plot_spectrogram_rt.py,sha256=JV8N7T8133wGVhlPxmgOb426u1g1p21-LbTqgaeddkk,8361
|
|
61
61
|
boris/plot_waveform_rt.py,sha256=05JN_6HCq674ROore_6PNw93GQNZJQDlDxp2ODAFkkA,7474
|
|
62
|
-
boris/plugins.py,sha256=
|
|
62
|
+
boris/plugins.py,sha256=FSeZdbGFPGfi5TDM3RQG6mEVwsp1cGKhJIZs-H0BMy4,9901
|
|
63
63
|
boris/preferences.py,sha256=qPfd9Tyg7u30kXwVqMOgkdy2RXri9bItRa5U2-ZVQmg,16847
|
|
64
64
|
boris/preferences_ui.py,sha256=D2bFLb3E0m6IwSeqKoItRDiqvPmJGoeXLHF2K02n1Zo,26293
|
|
65
65
|
boris/project.py,sha256=hAeAb5pD0u_l0bezU9ePvbTOYQKfxrFGvYB2NAqSDHg,84377
|
|
66
|
-
boris/project_functions.py,sha256=
|
|
66
|
+
boris/project_functions.py,sha256=mPaKTjcegsC6n-J8ZsOhWh_4TepJ3Y-vwXiIgl9nij0,79702
|
|
67
67
|
boris/project_import_export.py,sha256=1FdsYFzZ_jrhPRaH7xEkcPnh-hQXN4HFz1PhsIsSoL8,38361
|
|
68
68
|
boris/project_ui.py,sha256=yB-ewhHt8S8DTTRIk-dNK2tPMNU24lNji9fDW_Xazu8,38805
|
|
69
69
|
boris/qrc_boris.py,sha256=aH-qUirYY1CGxmTK1SFCPvuZfazIHX4DdUKF1gxZeYM,675008
|
|
@@ -73,12 +73,12 @@ boris/select_observations.py,sha256=HM0suMes1YxVwQ-Xakw7ROaxbN0EyeSiZFZNrTQIHAA,
|
|
|
73
73
|
boris/select_subj_behav.py,sha256=ulXbsRY-AIyQRSwXhVlvkNRS_eqWaCvkDKTTyOLqvoE,11742
|
|
74
74
|
boris/state_events.py,sha256=R5CcT_cldnxqhQkvX_V1AMNxH0Nc6jLzMZYiWkeJwAE,7770
|
|
75
75
|
boris/subjects_pad.py,sha256=lSRRGfLfD10_YpGua8RGVdKhoXlsXawGhNibPkRhuzM,3541
|
|
76
|
-
boris/synthetic_time_budget.py,sha256=
|
|
77
|
-
boris/time_budget_functions.py,sha256=
|
|
78
|
-
boris/time_budget_widget.py,sha256=
|
|
76
|
+
boris/synthetic_time_budget.py,sha256=3Eb9onMLmgqCLd50CuxV9L8RV2ESzfaMWvPK_bXUMMk,10489
|
|
77
|
+
boris/time_budget_functions.py,sha256=y5He8crz0xsTxVfz0jATwFFQVnPAIrNHja_0sF6NtRE,52551
|
|
78
|
+
boris/time_budget_widget.py,sha256=z-tyITBtIz-KH1H2OdMB5a8x9QQLK7Wu96-zkC6NVDA,43213
|
|
79
79
|
boris/transitions.py,sha256=_aZJfJWv3EBrtmQ7qsdTCayQo6uWU7BXqtQQgflEhr4,12250
|
|
80
|
-
boris/utilities.py,sha256=
|
|
81
|
-
boris/version.py,sha256=
|
|
80
|
+
boris/utilities.py,sha256=H69vrYGkQuQJVE_ywcYC6DNYcS8VTC-GoClmVEUXacA,52748
|
|
81
|
+
boris/version.py,sha256=K9SFa-Pzo_c5MuwLfeEIpmpUpKasa-rVS6AtqazzEKg,787
|
|
82
82
|
boris/video_equalizer.py,sha256=FartoGghFK-T53zklP70rPKYqTuzL8qdvfGlsOF2wwc,5854
|
|
83
83
|
boris/video_equalizer_ui.py,sha256=1CG3s79eM4JAbaCx3i1ILZXLceb41_gGXlOLNfpBgnw,10142
|
|
84
84
|
boris/video_operations.py,sha256=mh3iR__Sm2KnV44L_sW2pOo3AgLwlM7wiTnnqQiAVs4,9381
|
|
@@ -95,9 +95,9 @@ boris/portion/dict.py,sha256=SyHxc7PfDw2ufNLFQycwJtzmRfL48rDp4UrM2KN7IWc,11282
|
|
|
95
95
|
boris/portion/func.py,sha256=3TkQtFKLfsqntwd27HSGHceFhnXHmT-EbNMqktElC5Q,2174
|
|
96
96
|
boris/portion/interval.py,sha256=bAdUiJjGeUAPgsBAImwNeviiwfQq5odfhFZccAWzOTA,20299
|
|
97
97
|
boris/portion/io.py,sha256=ppNeRpiLNrocF1yzGeuEUIhYMf2LfsR-cji3d0nmvUs,6371
|
|
98
|
-
boris_behav_obs-9.2.
|
|
99
|
-
boris_behav_obs-9.2.
|
|
100
|
-
boris_behav_obs-9.2.
|
|
101
|
-
boris_behav_obs-9.2.
|
|
102
|
-
boris_behav_obs-9.2.
|
|
103
|
-
boris_behav_obs-9.2.
|
|
98
|
+
boris_behav_obs-9.2.3.dist-info/licenses/LICENSE.TXT,sha256=WJ7YI-moTFb-uVrFjnzzhGJrnL9P2iqQe8NuED3hutI,35141
|
|
99
|
+
boris_behav_obs-9.2.3.dist-info/METADATA,sha256=-SAdQZY5G3wnHZ5O4LXQuQFEko_m4uv4aOstv1KLJHA,1342
|
|
100
|
+
boris_behav_obs-9.2.3.dist-info/WHEEL,sha256=MAQBAzGbXNI3bUmkDsiV_duv8i-gcdnLzw7cfUFwqhU,109
|
|
101
|
+
boris_behav_obs-9.2.3.dist-info/entry_points.txt,sha256=k__8XvFi4vaA4QFvQehCZjYkKmZH34HSAJI2iYCWrMs,52
|
|
102
|
+
boris_behav_obs-9.2.3.dist-info/top_level.txt,sha256=fJSgm62S7WesiwTorGbOO4nNN0yzgZ3klgfGi3Px4qI,6
|
|
103
|
+
boris_behav_obs-9.2.3.dist-info/RECORD,,
|