boris-behav-obs 9.6.2__py2.py3-none-any.whl → 9.6.4__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/1.py +45 -0
- boris/analysis_plugins/irr_cohen_kappa.py +42 -17
- boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +40 -16
- boris/analysis_plugins/irr_weighted_cohen_kappa.py +36 -10
- boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +36 -10
- boris/analysis_plugins/time_budget.py +0 -4
- boris/behav_coding_map_creator.py +0 -1
- boris/coding_pad.py +0 -2
- boris/config_file.py +0 -2
- boris/core.py +9 -24
- boris/db_functions.py +4 -4
- boris/edit_event.py +0 -9
- boris/export_events.py +68 -76
- boris/gui_utilities.py +0 -1
- boris/modifier_coding_map_creator.py +0 -2
- boris/observation_operations.py +2 -4
- boris/param_panel.py +0 -4
- boris/plot_spectrogram_rt.py +2 -1
- boris/plot_waveform_rt.py +2 -1
- boris/plugins.py +41 -3
- boris/preferences.py +23 -7
- boris/time_budget_functions.py +0 -9
- boris/version.py +2 -2
- boris/video_equalizer.py +0 -2
- boris/view_df.py +0 -2
- boris/write_event.py +0 -9
- {boris_behav_obs-9.6.2.dist-info → boris_behav_obs-9.6.4.dist-info}/METADATA +22 -16
- {boris_behav_obs-9.6.2.dist-info → boris_behav_obs-9.6.4.dist-info}/RECORD +32 -31
- {boris_behav_obs-9.6.2.dist-info → boris_behav_obs-9.6.4.dist-info}/WHEEL +0 -0
- {boris_behav_obs-9.6.2.dist-info → boris_behav_obs-9.6.4.dist-info}/entry_points.txt +0 -0
- {boris_behav_obs-9.6.2.dist-info → boris_behav_obs-9.6.4.dist-info}/licenses/LICENSE.TXT +0 -0
- {boris_behav_obs-9.6.2.dist-info → boris_behav_obs-9.6.4.dist-info}/top_level.txt +0 -0
boris/1.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
'''
|
|
@@ -1,35 +1,59 @@
|
|
|
1
1
|
"""
|
|
2
2
|
BORIS plugin
|
|
3
3
|
|
|
4
|
-
Inter Rater Reliability (IRR) Unweighted Cohen Kappa
|
|
4
|
+
Inter Rater Reliability (IRR) Unweighted Cohen's Kappa
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from sklearn.metrics import cohen_kappa_score
|
|
9
|
+
from typing import Dict, Tuple
|
|
9
10
|
|
|
10
|
-
__version__ = "0.0.
|
|
11
|
-
__version_date__ = "2025-08-
|
|
12
|
-
__plugin_name__ = "Inter Rater Reliability - Unweighted Cohen Kappa"
|
|
11
|
+
__version__ = "0.0.2"
|
|
12
|
+
__version_date__ = "2025-08-29"
|
|
13
|
+
__plugin_name__ = "Inter Rater Reliability - Unweighted Cohen's Kappa"
|
|
13
14
|
__author__ = "Olivier Friard - University of Torino - Italy"
|
|
15
|
+
__description__ = """
|
|
16
|
+
This plugin calculates Cohen's Kappa to measure inter-rater reliability between two observers who code categorical behaviors over time intervals.
|
|
17
|
+
Unlike the weighted version, this approach does not take into account the duration of the intervals.
|
|
18
|
+
Each segment of time is treated equally, regardless of how long it lasts.
|
|
19
|
+
This plugin does not take into account the modifiers.
|
|
14
20
|
|
|
21
|
+
How it works:
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
Time segmentation
|
|
24
|
+
The program identifies all the time boundaries (start and end points) used by both observers.
|
|
25
|
+
These boundaries are merged into a common timeline, which is then divided into a set of non-overlapping elementary intervals.
|
|
26
|
+
|
|
27
|
+
Assigning codes
|
|
28
|
+
For each elementary interval, the program determines which behavior was coded by each observer.
|
|
29
|
+
|
|
30
|
+
Comparison of codes
|
|
31
|
+
The program builds two parallel lists of behavior codes, one for each observer.
|
|
32
|
+
Each elementary interval is counted as one unit of observation, no matter how long the interval actually lasts.
|
|
33
|
+
|
|
34
|
+
Cohen's Kappa calculation
|
|
35
|
+
Using these two lists, the program computes Cohen's Kappa using the cohen_kappa_score function of the sklearn package.
|
|
36
|
+
(see https://scikit-learn.org/stable/modules/generated/sklearn.metrics.cohen_kappa_score.html for details)
|
|
37
|
+
This coefficient measures how much the observers agree on their coding, adjusted for the amount of agreement that would be expected by chance.
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def run(df: pd.DataFrame) -> pd.DataFrame:
|
|
17
43
|
"""
|
|
18
|
-
Calculate the Inter Rater Reliability - Unweighted Cohen Kappa
|
|
44
|
+
Calculate the Inter Rater Reliability - Unweighted Cohen's Kappa
|
|
19
45
|
"""
|
|
20
46
|
|
|
21
|
-
#
|
|
47
|
+
# Attribute all active codes for each interval
|
|
22
48
|
def get_code(t_start, obs):
|
|
23
|
-
for seg in obs
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# Get unique values as a numpy array
|
|
29
|
-
unique_obs = df["Observation id"].unique()
|
|
49
|
+
active_codes = [seg[2] for seg in obs if seg[0] <= t_start < seg[1]]
|
|
50
|
+
if not active_codes:
|
|
51
|
+
return ""
|
|
52
|
+
# Sort to ensure deterministic representation (e.g., "A+B" instead of "B+A")
|
|
53
|
+
return "+".join(sorted(active_codes))
|
|
30
54
|
|
|
31
|
-
#
|
|
32
|
-
unique_obs_list =
|
|
55
|
+
# Get unique values
|
|
56
|
+
unique_obs_list = df["Observation id"].unique().tolist()
|
|
33
57
|
|
|
34
58
|
# Convert to tuples grouped by observation
|
|
35
59
|
grouped = {
|
|
@@ -40,10 +64,11 @@ def run(df: pd.DataFrame):
|
|
|
40
64
|
for obs, group in df.groupby("Observation id")
|
|
41
65
|
}
|
|
42
66
|
|
|
43
|
-
ck_results:
|
|
67
|
+
ck_results: Dict[Tuple[str, str], str] = {}
|
|
44
68
|
for idx1, obs_id1 in enumerate(unique_obs_list):
|
|
45
69
|
obs1 = grouped[obs_id1]
|
|
46
70
|
|
|
71
|
+
# Perfect agreement with itself
|
|
47
72
|
ck_results[(obs_id1, obs_id1)] = "1.000"
|
|
48
73
|
|
|
49
74
|
for obs_id2 in unique_obs_list[idx1 + 1 :]:
|
|
@@ -1,35 +1,59 @@
|
|
|
1
1
|
"""
|
|
2
2
|
BORIS plugin
|
|
3
3
|
|
|
4
|
-
Inter Rater Reliability (IRR) Unweighted Cohen Kappa with modifiers
|
|
4
|
+
Inter Rater Reliability (IRR) Unweighted Cohen's Kappa with modifiers
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from sklearn.metrics import cohen_kappa_score
|
|
9
9
|
|
|
10
|
-
__version__ = "0.0.
|
|
11
|
-
__version_date__ = "2025-08-
|
|
12
|
-
__plugin_name__ = "Inter Rater Reliability - Unweighted Cohen Kappa with modifiers"
|
|
10
|
+
__version__ = "0.0.2"
|
|
11
|
+
__version_date__ = "2025-08-29"
|
|
12
|
+
__plugin_name__ = "Inter Rater Reliability - Unweighted Cohen's Kappa with modifiers"
|
|
13
13
|
__author__ = "Olivier Friard - University of Torino - Italy"
|
|
14
|
+
__description__ = """
|
|
15
|
+
This plugin calculates Cohen's Kappa to measure inter-rater reliability between two observers who code categorical behaviors over time intervals.
|
|
16
|
+
Unlike the weighted version, this approach does not take into account the duration of the intervals.
|
|
17
|
+
Each segment of time is treated equally, regardless of how long it lasts.
|
|
18
|
+
This plugin takes into account the modifiers.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
How it works:
|
|
22
|
+
|
|
23
|
+
Time segmentation
|
|
24
|
+
The program identifies all the time boundaries (start and end points) used by both observers.
|
|
25
|
+
These boundaries are merged into a common timeline, which is then divided into a set of non-overlapping elementary intervals.
|
|
26
|
+
|
|
27
|
+
Assigning codes
|
|
28
|
+
For each elementary interval, the program determines which behavior was coded by each observer.
|
|
29
|
+
|
|
30
|
+
Comparison of codes
|
|
31
|
+
The program builds two parallel lists of behavior codes, one for each observer.
|
|
32
|
+
Each elementary interval is counted as one unit of observation, no matter how long the interval actually lasts.
|
|
33
|
+
|
|
34
|
+
Cohen's Kappa calculation
|
|
35
|
+
Using these two lists, the program computes Cohen's Kappa using the cohen_kappa_score function of the sklearn package.
|
|
36
|
+
(see https://scikit-learn.org/stable/modules/generated/sklearn.metrics.cohen_kappa_score.html for details)
|
|
37
|
+
This coefficient measures how much the observers agree on their coding, adjusted for the amount of agreement that would be expected by chance.
|
|
38
|
+
|
|
39
|
+
"""
|
|
14
40
|
|
|
15
41
|
|
|
16
42
|
def run(df: pd.DataFrame):
|
|
17
43
|
"""
|
|
18
|
-
Calculate the Inter Rater Reliability - Unweighted Cohen Kappa with modifiers
|
|
44
|
+
Calculate the Inter Rater Reliability - Unweighted Cohen's Kappa with modifiers
|
|
19
45
|
"""
|
|
20
46
|
|
|
21
|
-
#
|
|
47
|
+
# Attribute all active codes for each interval
|
|
22
48
|
def get_code(t_start, obs):
|
|
23
|
-
for seg in obs
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# Convert to a list
|
|
32
|
-
unique_obs_list = unique_obs.tolist()
|
|
49
|
+
active_codes = [seg[2] for seg in obs if seg[0] <= t_start < seg[1]]
|
|
50
|
+
if not active_codes:
|
|
51
|
+
return ""
|
|
52
|
+
# Sort to ensure deterministic representation (e.g., "A+B" instead of "B+A")
|
|
53
|
+
return "+".join(sorted(active_codes))
|
|
54
|
+
|
|
55
|
+
# Get unique values
|
|
56
|
+
unique_obs_list = df["Observation id"].unique().tolist()
|
|
33
57
|
|
|
34
58
|
# Convert to tuples grouped by observation
|
|
35
59
|
grouped: dict = {}
|
|
@@ -1,21 +1,47 @@
|
|
|
1
1
|
"""
|
|
2
2
|
BORIS plugin
|
|
3
3
|
|
|
4
|
-
Inter Rater Reliability (IRR) Weighted Cohen Kappa
|
|
4
|
+
Inter Rater Reliability (IRR) Weighted Cohen's Kappa
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from typing import List, Tuple, Dict, Optional
|
|
9
9
|
|
|
10
|
-
__version__ = "0.0.
|
|
11
|
-
__version_date__ = "2025-08-
|
|
12
|
-
__plugin_name__ = "Inter Rater Reliability - Weighted Cohen Kappa"
|
|
10
|
+
__version__ = "0.0.2"
|
|
11
|
+
__version_date__ = "2025-08-29"
|
|
12
|
+
__plugin_name__ = "Inter Rater Reliability - Weighted Cohen's Kappa"
|
|
13
13
|
__author__ = "Olivier Friard - University of Torino - Italy"
|
|
14
|
+
__description__ = """
|
|
15
|
+
This plugin calculates Cohen's Kappa to measure inter-rater reliability between two observers who code categorical behaviors over time intervals.
|
|
16
|
+
Unlike the unweighted version, this approach takes into account the duration of each coded interval, giving more weight to longer intervals in the agreement calculation.
|
|
17
|
+
This plugin does not take into account the modifiers.
|
|
18
|
+
|
|
19
|
+
How it works:
|
|
20
|
+
|
|
21
|
+
Time segmentation
|
|
22
|
+
The program collects all the time boundaries from both observers and merges them into a unified set of time points.
|
|
23
|
+
These define a set of non-overlapping elementary intervals covering the entire observed period.
|
|
24
|
+
|
|
25
|
+
Assigning codes
|
|
26
|
+
For each elementary interval, the program identifies the behavior category assigned by each observer.
|
|
27
|
+
|
|
28
|
+
Weighted contingency table
|
|
29
|
+
Instead of treating each interval equally, the program assigns a weight equal to the duration of the interval.
|
|
30
|
+
These durations are accumulated in a contingency table that records how much time was spent in each combination of categories across the two observers.
|
|
31
|
+
|
|
32
|
+
Agreement calculation
|
|
33
|
+
|
|
34
|
+
Observed agreement (po): The proportion of total time where both observers assigned the same category.
|
|
35
|
+
|
|
36
|
+
Expected agreement (pe): The proportion of agreement expected by chance, based on the time-weighted marginal distributions of each observer's coding.
|
|
37
|
+
|
|
38
|
+
Cohen's Kappa (κ): Computed from the weighted observed and expected agreements.
|
|
39
|
+
"""
|
|
14
40
|
|
|
15
41
|
|
|
16
42
|
def run(df: pd.DataFrame):
|
|
17
43
|
"""
|
|
18
|
-
Calculate the Inter Rater Reliability - Weighted Cohen Kappa
|
|
44
|
+
Calculate the Inter Rater Reliability - Weighted Cohen's Kappa
|
|
19
45
|
"""
|
|
20
46
|
|
|
21
47
|
def cohen_kappa_weighted_by_time(
|
|
@@ -41,12 +67,12 @@ def run(df: pd.DataFrame):
|
|
|
41
67
|
# 2. Build elementary intervals (non-overlapping time bins)
|
|
42
68
|
elementary_intervals = [(time_points[i], time_points[i + 1]) for i in range(len(time_points) - 1)]
|
|
43
69
|
|
|
44
|
-
# 3.
|
|
70
|
+
# 3. # Attribute all active codes for each interval
|
|
45
71
|
def get_code(t: float, obs: List[Tuple[float, float, str]]) -> Optional[str]:
|
|
46
|
-
for seg in obs
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return
|
|
72
|
+
active_codes = [seg[2] for seg in obs if seg[0] <= t < seg[1]]
|
|
73
|
+
if not active_codes:
|
|
74
|
+
return None
|
|
75
|
+
return "+".join(sorted(active_codes)) # rappresentazione deterministica
|
|
50
76
|
|
|
51
77
|
# 4. Build weighted contingency table (durations instead of counts)
|
|
52
78
|
contingency: Dict[Tuple[Optional[str], Optional[str]], float] = {}
|
|
@@ -1,21 +1,47 @@
|
|
|
1
1
|
"""
|
|
2
2
|
BORIS plugin
|
|
3
3
|
|
|
4
|
-
Inter Rater Reliability (IRR) Weighted Cohen Kappa with modifiers
|
|
4
|
+
Inter Rater Reliability (IRR) Weighted Cohen's Kappa with modifiers
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from typing import List, Tuple, Dict, Optional
|
|
9
9
|
|
|
10
|
-
__version__ = "0.0.
|
|
11
|
-
__version_date__ = "2025-08-
|
|
12
|
-
__plugin_name__ = "Inter Rater Reliability - Weighted Cohen Kappa with modifiers"
|
|
10
|
+
__version__ = "0.0.2"
|
|
11
|
+
__version_date__ = "2025-08-29"
|
|
12
|
+
__plugin_name__ = "Inter Rater Reliability - Weighted Cohen's Kappa with modifiers"
|
|
13
13
|
__author__ = "Olivier Friard - University of Torino - Italy"
|
|
14
|
+
__description__ = """
|
|
15
|
+
This plugin calculates Cohen's Kappa to measure inter-rater reliability between two observers who code categorical behaviors over time intervals.
|
|
16
|
+
Unlike the unweighted version, this approach takes into account the duration of each coded interval, giving more weight to longer intervals in the agreement calculation.
|
|
17
|
+
This plugin takes into account the modifiers.
|
|
18
|
+
|
|
19
|
+
How it works:
|
|
20
|
+
|
|
21
|
+
Time segmentation
|
|
22
|
+
The program collects all the time boundaries from both observers and merges them into a unified set of time points.
|
|
23
|
+
These define a set of non-overlapping elementary intervals covering the entire observed period.
|
|
24
|
+
|
|
25
|
+
Assigning codes
|
|
26
|
+
For each elementary interval, the program identifies the behavior category assigned by each observer.
|
|
27
|
+
|
|
28
|
+
Weighted contingency table
|
|
29
|
+
Instead of treating each interval equally, the program assigns a weight equal to the duration of the interval.
|
|
30
|
+
These durations are accumulated in a contingency table that records how much time was spent in each combination of categories across the two observers.
|
|
31
|
+
|
|
32
|
+
Agreement calculation
|
|
33
|
+
|
|
34
|
+
Observed agreement (po): The proportion of total time where both observers assigned the same category.
|
|
35
|
+
|
|
36
|
+
Expected agreement (pe): The proportion of agreement expected by chance, based on the time-weighted marginal distributions of each observer's coding.
|
|
37
|
+
|
|
38
|
+
Cohen's Kappa (κ): Computed from the weighted observed and expected agreements.
|
|
39
|
+
"""
|
|
14
40
|
|
|
15
41
|
|
|
16
42
|
def run(df: pd.DataFrame):
|
|
17
43
|
"""
|
|
18
|
-
Calculate the Inter Rater Reliability - Weighted Cohen Kappa with modifiers
|
|
44
|
+
Calculate the Inter Rater Reliability - Weighted Cohen's Kappa with modifiers
|
|
19
45
|
"""
|
|
20
46
|
|
|
21
47
|
def cohen_kappa_weighted_by_time(
|
|
@@ -41,12 +67,12 @@ def run(df: pd.DataFrame):
|
|
|
41
67
|
# 2. Build elementary intervals (non-overlapping time bins)
|
|
42
68
|
elementary_intervals = [(time_points[i], time_points[i + 1]) for i in range(len(time_points) - 1)]
|
|
43
69
|
|
|
44
|
-
# 3.
|
|
70
|
+
# 3. Attribute all active codes for each interval
|
|
45
71
|
def get_code(t: float, obs: List[Tuple[float, float, str]]) -> Optional[str]:
|
|
46
|
-
for seg in obs
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return
|
|
72
|
+
active_codes = [seg[2] for seg in obs if seg[0] <= t < seg[1]]
|
|
73
|
+
if not active_codes:
|
|
74
|
+
return None
|
|
75
|
+
return "+".join(sorted(active_codes)) # rappresentazione deterministica
|
|
50
76
|
|
|
51
77
|
# 4. Build weighted contingency table (durations instead of counts)
|
|
52
78
|
contingency: Dict[Tuple[Optional[str], Optional[str]], float] = {}
|
boris/coding_pad.py
CHANGED
|
@@ -261,8 +261,6 @@ def show_coding_pad(self):
|
|
|
261
261
|
self.codingpad.setWindowFlags(Qt.WindowStaysOnTopHint)
|
|
262
262
|
self.codingpad.sendEventSignal.connect(self.signal_from_widget)
|
|
263
263
|
|
|
264
|
-
print(f"{self.signal_from_widget=}")
|
|
265
|
-
|
|
266
264
|
self.codingpad.clickSignal.connect(self.click_signal_from_coding_pad)
|
|
267
265
|
self.codingpad.close_signal.connect(self.close_signal_from_coding_pad)
|
|
268
266
|
self.codingpad.show()
|
boris/config_file.py
CHANGED
boris/core.py
CHANGED
|
@@ -205,7 +205,6 @@ class TableModel(QAbstractTableModel):
|
|
|
205
205
|
if 0 <= row < self.rowCount():
|
|
206
206
|
column = index.column()
|
|
207
207
|
|
|
208
|
-
# print(self._data[:3])
|
|
209
208
|
if cfg.TW_EVENTS_FIELDS[self.observation_type][column] == "type":
|
|
210
209
|
return self._data[row][-1]
|
|
211
210
|
else:
|
|
@@ -2137,39 +2136,47 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
2137
2136
|
set_and_update_pan_and_zoom(new_pan_x, new_pan_y, new_zoom)
|
|
2138
2137
|
|
|
2139
2138
|
if cmd == "MBTN_LEFT_DBL":
|
|
2140
|
-
|
|
2139
|
+
logging.debug("MBTN_LEFT_DBL")
|
|
2141
2140
|
# ZOOM IN x2
|
|
2142
2141
|
do_zoom_in_clicked_coords(zoom_increment=1)
|
|
2143
2142
|
return
|
|
2144
2143
|
if cmd == "MBTN_RIGHT_DBL":
|
|
2144
|
+
logging.debug("MBTN_RIGHT_DBL")
|
|
2145
2145
|
# ZOOM OUT x2
|
|
2146
2146
|
do_zoom_in_clicked_coords(zoom_increment=-1)
|
|
2147
2147
|
return
|
|
2148
2148
|
if cmd == "Ctrl+WHEEL_UP":
|
|
2149
|
+
logging.debug("Ctrl+WHEEL_UP")
|
|
2149
2150
|
# ZOOM IN (3 wheel steps to zoom X2)
|
|
2150
2151
|
do_zoom_in_clicked_coords(zoom_increment=1.0 / 3.0)
|
|
2151
2152
|
return
|
|
2152
2153
|
if cmd == "Ctrl+WHEEL_DOWN":
|
|
2154
|
+
logging.debug("Ctrl+WHEEL_DOWN")
|
|
2153
2155
|
# ZOOM OUT (3 wheel steps to zoom X2)
|
|
2154
2156
|
do_zoom_in_clicked_coords(zoom_increment=-1.0 / 3.0)
|
|
2155
2157
|
return
|
|
2156
2158
|
if cmd == "WHEEL_UP":
|
|
2159
|
+
logging.debug("WHEEL_UP")
|
|
2157
2160
|
# PAN UP (VIDEO MOVES DOWN)
|
|
2158
2161
|
do_pan_in_clicked_coords(pan_x_increment=0, pan_y_increment=+0.01)
|
|
2159
2162
|
return
|
|
2160
2163
|
if cmd == "WHEEL_DOWN":
|
|
2164
|
+
logging.debug("WHEEL_DOWN")
|
|
2161
2165
|
# PAN DOWN (VIDEO MOVES UP)
|
|
2162
2166
|
do_pan_in_clicked_coords(pan_x_increment=0, pan_y_increment=-0.01)
|
|
2163
2167
|
return
|
|
2164
2168
|
if cmd == "Shift+WHEEL_UP":
|
|
2169
|
+
logging.debug("Shift+WHEEL_UP")
|
|
2165
2170
|
# PAN LEFT (VIDEO MOVES TO THE RIGHT)
|
|
2166
2171
|
do_pan_in_clicked_coords(pan_x_increment=+0.01, pan_y_increment=0)
|
|
2167
2172
|
return
|
|
2168
2173
|
if cmd == "Shift+WHEEL_DOWN":
|
|
2174
|
+
logging.debug("Shift+WHEEL_DOWN")
|
|
2169
2175
|
# PAN RIGHT (VIDEO MOVES TO THE LEFT)
|
|
2170
2176
|
do_pan_in_clicked_coords(pan_x_increment=-0.01, pan_y_increment=0)
|
|
2171
2177
|
return
|
|
2172
2178
|
if cmd == "Shift+MBTN_LEFT":
|
|
2179
|
+
logging.debug("Shift+MBTN_LEFT")
|
|
2173
2180
|
# RESET PAN AND ZOOM TO DEFAULT
|
|
2174
2181
|
set_and_update_pan_and_zoom(pan_x=0, pan_y=0, zoom=0)
|
|
2175
2182
|
return
|
|
@@ -3745,21 +3752,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3745
3752
|
|
|
3746
3753
|
# calculate time for current media file in case of many queued media files
|
|
3747
3754
|
|
|
3748
|
-
print(mediaFileIdx_s)
|
|
3749
|
-
print(type(eventtime_s))
|
|
3750
|
-
print(durations)
|
|
3751
|
-
|
|
3752
3755
|
eventtime_onmedia_s = round(eventtime_s - util.float2decimal(sum(durations[0:mediaFileIdx_s])), 3)
|
|
3753
3756
|
eventtime_onmedia_e = round(eventtime_e - util.float2decimal(sum(durations[0:mediaFileIdx_e])), 3)
|
|
3754
3757
|
|
|
3755
|
-
print(row_s, media_path_s, eventtime_s, eventtime_onmedia_s)
|
|
3756
|
-
print(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_s])
|
|
3757
|
-
|
|
3758
|
-
print(row_e, media_path_e, eventtime_e, eventtime_onmedia_e)
|
|
3759
|
-
print(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_e])
|
|
3760
|
-
|
|
3761
3758
|
if media_path_s != media_path_e:
|
|
3762
|
-
print("events are located on 2 different media files")
|
|
3763
3759
|
return
|
|
3764
3760
|
|
|
3765
3761
|
media_path = media_path_s
|
|
@@ -3770,7 +3766,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3770
3766
|
if "BORISEXTERNAL" in os.environ:
|
|
3771
3767
|
external_command_template = os.environ["BORISEXTERNAL"]
|
|
3772
3768
|
else:
|
|
3773
|
-
print("BORISEXTERNAL env var not defined")
|
|
3774
3769
|
return
|
|
3775
3770
|
|
|
3776
3771
|
external_command = external_command_template.format(
|
|
@@ -3853,11 +3848,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3853
3848
|
|
|
3854
3849
|
time_, cumulative_time = self.get_obs_time()
|
|
3855
3850
|
|
|
3856
|
-
"""
|
|
3857
|
-
print(time_)
|
|
3858
|
-
print(cumulative_time)
|
|
3859
|
-
"""
|
|
3860
|
-
|
|
3861
3851
|
if self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.MEDIA_CREATION_DATE_AS_OFFSET, False):
|
|
3862
3852
|
write_event.write_event(self, event, time_)
|
|
3863
3853
|
else:
|
|
@@ -5222,25 +5212,20 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5222
5212
|
if (not self.find_dialog.cbFindInSelectedEvents.isChecked()) or (
|
|
5223
5213
|
self.find_dialog.cbFindInSelectedEvents.isChecked() and event_idx in self.find_dialog.rowsToFind
|
|
5224
5214
|
):
|
|
5225
|
-
print(f"{event=}")
|
|
5226
|
-
|
|
5227
5215
|
# search only on filtered events
|
|
5228
5216
|
if event_idx not in self.tv_idx2events_idx:
|
|
5229
5217
|
continue
|
|
5230
5218
|
|
|
5231
5219
|
for idx in fields_list:
|
|
5232
|
-
print(f"{idx=}")
|
|
5233
5220
|
if (self.find_dialog.cb_case_sensitive.isChecked() and self.find_dialog.findText.text() in event[idx]) or (
|
|
5234
5221
|
not self.find_dialog.cb_case_sensitive.isChecked()
|
|
5235
5222
|
and self.find_dialog.findText.text().upper() in event[idx].upper()
|
|
5236
5223
|
):
|
|
5237
5224
|
self.find_dialog.currentIdx = event_idx
|
|
5238
5225
|
|
|
5239
|
-
# self.twEvents.scrollToItem(self.twEvents.item(event_idx, 0))
|
|
5240
5226
|
index = self.tv_events.model().index(event_idx, 0)
|
|
5241
5227
|
self.tv_events.scrollTo(index, QAbstractItemView.EnsureVisible)
|
|
5242
5228
|
self.tv_events.selectRow(event_idx)
|
|
5243
|
-
# self.twEvents.selectRow(event_idx)
|
|
5244
5229
|
return
|
|
5245
5230
|
|
|
5246
5231
|
if msg != "FIND_FROM_BEGINING":
|
boris/db_functions.py
CHANGED
|
@@ -188,7 +188,7 @@ def load_aggregated_events_in_db(
|
|
|
188
188
|
selected_behaviors = sorted([pj[cfg.ETHOGRAM][x][cfg.BEHAVIOR_CODE] for x in pj[cfg.ETHOGRAM]])
|
|
189
189
|
|
|
190
190
|
# check if state events are paired
|
|
191
|
-
out = ""
|
|
191
|
+
out: str = ""
|
|
192
192
|
for obs_id in selected_observations:
|
|
193
193
|
r, msg = project_functions.check_state_events_obs(obs_id, pj[cfg.ETHOGRAM], pj[cfg.OBSERVATIONS][obs_id], cfg.HHMMSS)
|
|
194
194
|
if not r:
|
|
@@ -212,11 +212,11 @@ def load_aggregated_events_in_db(
|
|
|
212
212
|
|
|
213
213
|
db = sqlite3.connect(":memory:")
|
|
214
214
|
|
|
215
|
-
"""
|
|
216
215
|
# only for debugging
|
|
216
|
+
"""
|
|
217
217
|
import os
|
|
218
|
-
os.system("rm /tmp/ramdisk/
|
|
219
|
-
db = sqlite3.connect("/tmp/ramdisk/
|
|
218
|
+
os.system("rm /tmp/ramdisk/aggregated_events.sqlite")
|
|
219
|
+
db = sqlite3.connect("/tmp/ramdisk/aggregated_events.sqlite", isolation_level=None)
|
|
220
220
|
"""
|
|
221
221
|
|
|
222
222
|
db.row_factory = sqlite3.Row
|
boris/edit_event.py
CHANGED
|
@@ -128,8 +128,6 @@ class DlgEditEvent(QDialog, Ui_Form):
|
|
|
128
128
|
set time to current media time
|
|
129
129
|
"""
|
|
130
130
|
|
|
131
|
-
print(f"{self.current_time=}")
|
|
132
|
-
|
|
133
131
|
if self.observation_type in (cfg.LIVE, cfg.MEDIA):
|
|
134
132
|
self.time_widget.set_time(dec(float(self.current_time)))
|
|
135
133
|
|
|
@@ -137,13 +135,6 @@ class DlgEditEvent(QDialog, Ui_Form):
|
|
|
137
135
|
if self.exif_date_time is not None:
|
|
138
136
|
self.time_widget.set_time(dec(self.exif_date_time))
|
|
139
137
|
|
|
140
|
-
# def frame_idx_na(self):
|
|
141
|
-
# """
|
|
142
|
-
# set/unset frame index NA
|
|
143
|
-
# """
|
|
144
|
-
# self.lb_frame_idx.setEnabled(not self.cb_set_frame_idx_na.isChecked())
|
|
145
|
-
# self.sb_frame_idx.setEnabled(not self.cb_set_frame_idx_na.isChecked())
|
|
146
|
-
|
|
147
138
|
def time_na(self):
|
|
148
139
|
"""
|
|
149
140
|
set/unset time to NA
|